Disclaimer: I have decided to award a bounty on this question, because the solution suggested by Christian Hupfer works but is not fully satisfactory. In doing so, I rephrased this question so that potential answers might have a broader applicability. The fundamental issue remains however unchanged.
Context: I want to create hierarchically dependent PGF keys: e.g. keys sub1
and sub2
equals key main
, unless they have been explicitely defined.
I'm looking for this because I want in my future package to have a key that sets characteristics (e.g. the color, or font) of each elements, but to be also able to locally define the characteristics of a single element.
Let's take an example to make things more intelligible. Say I have a macro that draws a tikzpicture
constituted of three elements (A
, B
and C
). I want to give the user full control for what regards colors.
The idea is that I have a global color, namely main color
, that is applied to each element of the tikzpicture
; here A
, B
, and C
. main color
has a default value (here, black) that can be overridden if the user specifies its value explicitly (e.g. main color = {150,150,150}
).
However the user could also specify the color of each element x separately (e.g. color A = {255,0,0}
). This local definition would then override any other set color for element x only.
The color of element x is thus determined as following:
color X = default main color / unless local main color is specified / unless local color X is specified.
I use PGF keys for that (since my project heavily rely on TikZ). This makes keys kind of "hierarchically dependent", as shown in following pattern:
main color <--- color A
|
|- color B
|
-- color C
(Note that I have several hierarchical levels in my real case.)
Question: How to manage this hierarchical keys system?
Below are information constituting the initial version of this question. I have updated answers based on Christian's comment.
Initial problem: My idea for implementing this behavior is the following pseudo-code:
main color/.default = {<value arbitraty defined by developer>}
main color/.code = {\setTheColor'main color'='#1'}
color A/.default = {\valueof{main color}}
color A/.code = {\setTheColor'color A'='#1'}
color B/.default = {\valueof{main color}}
color B/.code = {\setTheColor'color B'='#1'}
main color, color A, color B,
My issue is regarding how to define color A/.default
: I've tried both color a/.default={\pgfvalueof{main color}},
and color b/.link={main color},
but it is not working as shown in the MWE below.
Updated problem: The solution suggested in comments by Christian Hupfer is to use /.forward to =
. I have successfully implemented this solution in the answer I posted below. However, since I use main/.forward to=color x
, this behavior override a local definition of color x
that occured before defining main color
. As I want to implement this hierarchical keys in a package, with several nesting levels, it would be definitively too restrictive to expect the user to give key=value
pairs in the right order.
MWE: (implementing Christian's solution. Issue is on the penultimate line: B
should be blue.)
\documentclass{article}
\usepackage{xcolor}
\usepackage{tikz}
\pgfkeys{
/example/.is family, /example,
main color/.default={0,0,0},
main color/.code={\definecolor{mymaincolor}{RGB}{#1}},
main color/.forward to = /example/color a,
main color/.forward to = /example/color b,
main color/.forward to = /example/color c,
color a/.code={\definecolor{mysubcolora}{RGB}{#1}},
color b/.code={\definecolor{mysubcolorb}{RGB}{#1}},
color c/.code={\definecolor{mysubcolorc}{RGB}{#1}},
}
\newcommand{\test}[1][]{%
\pgfkeys{/example,
main color,
#1,
}%
\par
\begin{tikzpicture}
\node[fill = mysubcolora, circle, minimum height = 1cm, text= white, font=\Large\sffamily\bfseries] at (0,0) {A};
\node[fill = mysubcolorb, circle, minimum height = 1cm, text= white, font=\Large\sffamily\bfseries] at (1,0) {B};
\node[fill = mysubcolorc, circle, minimum height = 1cm, text= white, font=\Large\sffamily\bfseries] at (2,0) {C};
\end{tikzpicture}
\par
}
\begin{document}
\begin{description}
\item[\textbackslash test] no argument: circle A, B and C take default color = \emph{default} \texttt{main color} (black).
\test
\item[\textbackslash test[color a=\{255,0,0\}{]} ] circle A: \emph{local} \texttt{color A} (red), circle B and C: no definition, so \emph{default} \texttt{main color}.
\test[color a={255,0,0}]
\item[\textbackslash test[main color=\{200,200,200\}{]}] circles A, B, and C's colors are overridden by \emph{local} \texttt{main color} (grey).
\test[main color={200,200,200}]
\item[\textbackslash test[main color=\{200,200,200\}, color b =\{0,0,255\}{]}] circles A, B, and C's colors are overridden by \emph{local} \texttt{main color} (i.e. the same than above), but circle's B color is ``over-overridden'' by \emph{local} \texttt{color B} definition (blue).
\test[main color={200,200,200}, color b ={0,0,255}]
\item[\textbackslash test[color b =\{0,0,255\}, main color=\{200,200,200\}{]}] Same behavior than above. However, the \emph{local} definition of \texttt{color B} is specified \emph{before} the \emph{local} definition of \texttt{main color}. In this case, suggested solution doesn't work. (circle B should be blue.)
\test[color b ={0,0,255}, main color={200,200,200}]
\item[\textbackslash test] no argument: circle A, B and C take default color = \emph{default} \texttt{main color} (black). (Testing if local color definition are really local.)
\test
\end{description}
\end{document}
.forward to=
?every xxx
. For example\zooset{every mammal/.try, every dog/.try, every golden retriever/.try}
. Also, PGFplots will manually check/tikz/husky
while/pgfplots/hulsky
is undefined.