Is there a general way to disable preactions/postactions in TikZ on which effects such as shadows depend?
If not, is there a straightforward way to enable users to add options to an existing style so that they can neutralise their effects e.g. by setting a shadow's opacity to 0 as in https://tex.stackexchange.com/a/354728/?
First some code which works (I think) as I want it to:
\documentclass[tikz,border=10pt]{standalone}
\usetikzlibrary{shadows,positioning}
\newif\ifshowplaceholders
\showplaceholdersfalse
\tikzset{%
my node/.style={fill=gray,draw=black},
placeholders/.is choice,
placeholders/off/.code={%
\showplaceholdersfalse\let\myphantom\phantom
\pgfqkeys{/tikz}{placeholder/.style={my node,fill=none, draw=none}}%
},
placeholders/on/.code={%
\showplaceholderstrue\def\myphantom##1{##1}%
\pgfqkeys{/tikz}{placeholder/.style={my node,opacity=.25,text opacity=.5}}%
},
placeholders/.default=on,
placeholders=off,
}
\begin{document}
\begin{tikzpicture}
\node (n) [my node] {My Node};
\node (p) [above=10pt of n,placeholder] {\myphantom{Placeholder}};
\end{tikzpicture}
\end{document}
The basic idea is that placeholder nodes can be created to help with the placement of 'real' nodes. Under normal circumstances, these are invisible, but they can still be used for placement.
If desired, they can be rendered visible for debugging purposes.
placeholders=on,
Now suppose somebody wants to add a drop shadow to the 'real nodes'
my node/.style={fill=gray,drop shadow,draw=black},
% placeholders=on,
Now the placeholder is invisible, as it should be, but its shadow is not.
Ideally, I would like to disable preactions and postactions for placeholder nodes, but, not knowing how to do that, I tried to at least enable users to add neutralising code, but I can't get it to work. I suspect this has something to do with expansion, but I've not found a way which doesn't yield either an error or visibility.
I wouldn't expect the following to work, so I'm not surprised it doesn't, but I'm including it because it represents a schematic of how I was thinking the problem might be handled.
\documentclass[tikz,border=10pt]{standalone}
\usetikzlibrary{shadows,positioning}
\newif\ifshowplaceholders
\showplaceholdersfalse
\tikzset{%
my node/.style={fill=gray,draw=black},
placeholders/.is choice,
placeholders/off/.code={%
\showplaceholdersfalse\let\myphantom\phantom
\pgfqkeys{/tikz}{placeholder/.style={my node,fill=none, draw=none}}%
},
placeholders/on/.code={%
\showplaceholderstrue\def\myphantom##1{##1}%
\pgfqkeys{/tikz}{placeholder/.style={my node,opacity=.25,text opacity=.5}}%
},
placeholders/.default=on,
placeholders=off,
placeholders/when off/.code={%
% \edef\tempa{#1}%
\pgfqkeys{/tikz}{%
placeholders/off/.append code={%
\pgfqkeys{/tikz}{placeholder/.append code={\pgfqkeys{/tikz}{#1}}}%
},
}%
\ifshowplaceholders
\else
\pgfqkeys{/tikz}{placeholder/.append code={\pgfqkeys{/tikz}{#1}}}%
\fi
},
placeholders/when on/.code={%
% \edef\tempa{#1}%
\pgfqkeys{/tikz}{%
placeholders/on/.append code={%
\pgfqkeys{/tikz}{placeholder/.append code={\pgfqkeys{/tikz}{#1}}}%
}%
}%
\ifshowplaceholders
\pgfqkeys{/tikz}{placeholder/.append code={\pgfqkeys{/tikz}{#1}}}%
\fi
},
my node/.style={fill=gray,drop shadow,draw=black},
placeholders/when off={drop shadow={fill=none}},
% placeholders=on,
}
\begin{document}
\begin{tikzpicture}
\node (n) [my node] {My Node};
\node (p) [above=10pt of n,placeholder] {\myphantom{Placeholder}};
\end{tikzpicture}
\end{document}
I actually began by trying with .append style, but that didn't work either. As a last resort, I can use expl3, but I'd rather not do that for what seems as if it should be a relatively simple problem.
I should mention some options I'm not considering which might seem good approaches from the MWE above:
- not using
my nodein the placeholder style at all (I don't know what the style will be and I need the placeholders to be standardised relative to that style); - eliminating placeholders for the final run (then placing things relative to them wouldn't work - these are not being used like the temporary grids used for placement).
Things I could do:
- declare the package incompatible with
shadowsand similar things when applied to elements of this type, unless placeholders are disabled (tempting, but somewhat nuclear, and people will want to do it anyway); - introducing (yet another) layer (or two), filling it with white and creating the placeholders behind it when
off(but the package already creates a lot of layers and this seems a lot of infrastructure just to disable shadows - and it won't work if users use pre/postaction-involving things which draw on different layers).
My default is to just document the incompatibility or to do something with expl3, but I'm hoping there's some better solution.



drop shadow/.style={}? You might have to find a hook that is executed before theevery nodestyle, or perhaps define\placeholderas\path[disable stuff] node[placeholder]. – Andrew Stacey Aug 31 '23 at 06:54\tikz@preactionsand\tikz@postactions. It should be possible to def them to{}or let them to any of the defined empty macros. You should be able to usephantom nodeas defined in A688111 to avoid the\myphanntomkey. – Qrrbrbirlbel Aug 31 '23 at 07:57\placeholdermacro that deals with everything is a better aproach. But at the end of the day, a user could do anything withevery nodeandmy nodeyou can't account for. – Qrrbrbirlbel Aug 31 '23 at 08:34{}. – cfr Aug 31 '23 at 13:36spyare also incompatible, as far as I can tell, butshadowsstrike me as a simpler desideratum.) – cfr Aug 31 '23 at 13:39\letting those to\@emptyseems to work well. I've also switched to yourphantom node. I'm not sure it matters much in this case as there's no possibility of a line break in the content (even though the nodes are multiline), but perhaps it's neater and I'm committed to internals by zapping pre/post actions anyway. Do you want to answer? – cfr Aug 31 '23 at 14:49phantom node/.code=\tikz@addoption{% <ref> \expandafter\let\csname pgf@sh@boxes@\tikz@shape\endcsname\pgfutil@empty}, % <ref> zap preactions/.code=\let\tikz@preactions\@empty, zap postactions/.code=\let\tikz@postactions\@empty, placeholders/off/.code={% \chronos@placeholdersfalse \pgfqkeys{/chronos}{placeholder/.style={fill=none, draw=none,/chronos/.cd,phantom node,zap preactions,zap postactions}}% },– cfr Aug 31 '23 at 14:51placeholders/on/.code={% \pgfqkeys{/chronos}{placeholder/.style={on chronos middle ground layer,fill opacity=.1,draw opacity=.25,text opacity=.5,/chronos/.cd,zap preactions,zap postactions}}% },– cfr Aug 31 '23 at 14:52