I would like to create a multinode shape doublecirc
with two node parts, say text
and lower
, consisting of two circles with text in each.
(There are obviously ways to do this more simply -- but this is a MWE, my intended shape is more complex.)
I would like the color of the part lower
circle to be inherited from text
, but with an optional pgfkey allowing it to be changed:
\node[name=a,shape=doublecirc,style={draw},red] % circles+text red
\node[name=b,shape=doublecirc,style={draw},draw=red]% circles red
\node[name=c,shape=doublecirc,style={draw},draw=red, /tikz/lower color = blue] % lower circle blue
I found out a way to do this based on extending
Loop Space's solution to another question.
However, it turned out to be much more complex than I expected,
essentially working around pgfkeys.
(Specifically, I used the etoolbox
package command \ifdefstring
,
and a 'dummy' initial color assignment (empty
) to my key.)
\documentclass{article}
\usepackage{etoolbox}
\usepackage{pgf,tikz}
\usetikzlibrary{arrows,shapes.arrows,shapes.geometric,
shapes.multipart,backgrounds,decorations.pathmorphing,positioning,fit,
shapes.callouts}
\makeatletter
\newbox\pgfnodepartlowerbox
\newbox\pgfnodeparttextbox
\pgfkeys{/tikz/lower color/.initial = empty}% Default value indicates undefined
\pgfdeclareshape{doublecirc}{%
\nodeparts{text,lower}%
\savedmacro\lowercolor{%
\edef\tst{\pgfkeysvalueof{/tikz/lower color}}%
\ifdefstring{\tst}{empty}% comparison command from etoolbox
{\ifx\tikz@strokecolor\pgfutil@empty%if not defined
\def\lowercolor{.}%
\else%
\def\lowercolor{\tikz@strokecolor}%
\fi}%
{\def\lowercolor{\expandafter\pgfkeysvalueof{/tikz/lower color}}}%if defined
}
\savedanchor\centerpoint{%
\pgf@x=.5\wd\pgfnodeparttextbox%
\pgf@y=.5\ht\pgfnodeparttextbox%
}
\savedanchor\lower{%
\pgf@x=.5\wd\pgfnodepartlowerbox%
\pgf@y=.5\ht\pgfnodepartlowerbox%
\advance\pgf@y by -2.0\ht\pgfnodeparttextbox%
\advance\pgf@x by 2.0\wd\pgfnodeparttextbox%
}
\anchor{center}{\centerpoint}%
\anchor{lower}{\lower}
\backgroundpath{
\pgfpathcircle{\centerpoint}{\wd\pgfnodeparttextbox}%
\pgfusepath{stroke}%
\pgfsetstrokecolor{\lowercolor}%
\pgfpathcircle{\lower}{1.5\wd\pgfnodepartlowerbox}%
\pgfusepath{stroke}%
}
\anchorborder{\centerpoint}
}
\makeatother
\begin{document}
\begin{tikzpicture}
\node[name=a,shape=doublecirc,style={draw},red] at (0,0) {A\nodepart{lower}{B}}; % Inherit color from .
\node[name=b,shape=doublecirc,style={draw},draw=red] at (2,0) {A\nodepart{lower}{B}}; % Inherit color from draw
\node[name=c,shape=doublecirc,style={draw},draw=red, /tikz/lower color = blue] at (4,0) {A\nodepart{lower}{B}}; % Specify color with parameter
\end{tikzpicture}
\end{document}
Is there a simpler way to do this with pgfkeys
?
A particular technical problem was that I did not find an elegant way
to initialize my pgfkey (lower color
), while leaving the key undefined.
At least not in a way that I could then detect with some form of \if
(but I found the TeX conditionals perplexing: I don't fully understand why I need to use \edef
in the code above)
In answering another question @percusse introduces an
.initial without value
handler
which looks promising. However, this requires redefining the \pgfkeys@notset
and \pgfkeysvalueof
which I worry would make it harder to create a self-contained package with the shape declaration (?)
I also explored trying to use macros or other handlers associated with my pgfkey, but found this confusing. (See the discussion of storing values vs. macros here and here)
I'm guessing that being able to handle colors in this way might be useful for other multi-part node shapes.
(Author's note: this is my first question posting, so apologize if I unwittingly violate protocol or if this has been answered previously.)
multipartb
. (That is my local experimental copy - which provided the motivation for the question.)