How does a .style
handler work?
It is basically a .code
handler (as everything is in the end anyway), the code that is saved is \pgfkeysalso{#1}
.
The style A
expands to \pgfkeysalso{draw}
and B
to \pgfkeysalso{fill=yelow}
.
The manual says for \pgfkeysalso
:
This command has execatly the same effect as \pgfkeys
, only the default path is not modified before or after the keys are being set.
The “default path” is the one you’re on currently (with \tikzset
this is /tikz
). The .cd
handler however changes this default path to /tikz/mystyle
. A key that uses \pgfkeysalso
then tries to find draw
and fill
in this path and fails.
The rather complex handler .search also
installs a .unknown
code that tries to use unrecognized keys to apply in the given paths. (In a similar way do /pgf
keys work in /tikz
.) percusse already uses this in his solution and it is probably the most convenient approach.
The problem though is that you must use those keys only in the /tikz/mystyle
path. You can’t use them in other paths without setting the default path to /tikz
or /tikz/mystyle
. For example you can’t do \pgfkeys{/tikz/mystyle/A}
because as the key is not called from the /tikz/mystyle
path the installed .search also
won’t be checked. This may seem as an unrealistic example (and it probably is) but for other styles that do not change the properties of the whole path like for example insert path
this is important as a key containing such styles may be used anywhere to set exactly those properties.
The most robust way would be to save the styles with /tikz
(and you know they are used as /tikz
key and nothing else):
\tikzset{
mystyle/A/.style=/tikz/draw,
mystyle/B/.style={/tikz/fill=yellow}
}
If you want the styles to behave as if they would be used in the default /tikz
path you could use a .tikz
handler that saves the key as a \tikzset
(as opposed to a \pgfkeysalso
). A simple definition like
\pgfkeys{/handlers/.tikz/.code=%
\pgfkeys{\pgfkeyscurrentpath/.code=\tikzset{#1}}}
makes it possible to use it as
\tikzset{
mystyle/A/.tikz={draw},
mystyle/B/.tikz={fill=yellow}}
In a way, this is also my solution for the mystyle
switch key.
Again, a mystyle/.cd
(which also only work if the previous path was /tikz
) changes the path even for keys you would want to use after mystyle={A,B}
. While those are most likely again /tikz
keys they don’t need to be. You could have used /tikz/mystyle={A,B}
from any PGF keys path without wanting to go back to /tikz
. Similar to a .tikz
handler I would define the mystyle
key as:
\tikzset{
mystyle/A/.tikz={draw},
mystyle/B/.tikz={fill=yellow},
mystyle/.code=\pgfqkeys{/tikz/mystyle}{#1}
}
The manual even says to \pgfkeysalso
that “[c]hanging the default path inside a \pgfkeyalso
is dangerous, so use with care”.
Similar solutions are used by TikZ naturally, for example the decoration
key (which is actually a /pgf
key):
\pgfkeys{%
/pgf/decoration/.code={\pgfkeys{/pgf/decoration/.cd,#1}}}
This for example makes it possible to use decoration={<something>}
from \pgfset
(e.g. the /pgf
path) and also from \tikzset
without the restraint to go back to /pgf
or /tikz
. (It would be save though to go back to /tikz
as /pgf
is searched from there anyway but for a pure pgf
solution this would fail.)
Code
\documentclass[tikz,convert=false]{standalone}
\pgfkeys{/handlers/.tikz/.code=%
\pgfkeys{\pgfkeyscurrentpath/.code=\tikzset{#1}}}
\tikzset{
mystyle/A/.tikz={draw},
mystyle/B/.tikz={fill=yellow},
mystyle/.code=\pgfqkeys{/tikz/mystyle}{#1}
}
\begin{document}
\begin{tikzpicture}
\node [mystyle={A,B}] {Test};
\end{tikzpicture}
\end{document}
Another solution you might be interested in is the following.
This avoids changing the default path and relies on using mystyle={…}
when the default path is /tikz
. You can know say /.style={</tikz options>}
and use mystyle={…}
without using an additional handler, the need to specify /tikz
somehow and somewhere. All it needs is an auxiliary key to use with a /.list
. (Or you specify the /.list
in your code directly while using your original definition (mystyle/.style={mystyle/#1}
): mystyle/.list={A,B}
.
Though, if you know that the keys you use are TikZ keys, save them as such (with /.tikz
or /tikz/
).
Code
\documentclass[tikz,convert=false]{standalone}
\tikzset{
mystyle/A/.style={draw},
mystyle/B/.style={fill=yellow},
mystyle/.style={@mystyle/.list={#1}},
@mystyle/.style={/tikz/mystyle/#1}% auxiliary
}
\begin{document}
\begin{tikzpicture}
\node [mystyle={A,B}] {Test};
\end{tikzpicture}
\end{document}