5

I would like to write a command which allows the user to change tikz styles. My code goes like this:

\documentclass{article}
\usepackage{tikz,xkeyval}

\makeatletter
\def\DEFstyle{}
\define@key{styles}{styleA}{\def\DEFstyle{#1}}
\newcommand{\setstyles}[1]{%
  \setkeys{styles}{styleA={}} 
  \setkeys{styles}{#1}
  \tikzstyle{TIKZSTYLE}=[\DEFstyle]
}
\makeatother

\begin{document}
\setstyles{styleA={top color=green,bottom color=red}}
\end{document}

However, I always get an error message:

! Package pgfkeys Error: I do not know the key '/tikz/top color=green,bottom color=red' and I am going to ignore it. Perhaps you misspelled it.

But the content of \DEFstyle is definitely top color=green,bottom color=red and when I directly write \tikzstyle{TIKZSTYLE}=[top color=green,bottom color=red] then everything works fine. Where does the bug hide?

3
  • Welcome to TeX.SX. Mar 5, 2013 at 18:28
  • The exact option is not important as long as it works. \tikzset{TIKZSTYLE/.style/.expand once=\DEFstyle} seems to work! Thanks a lot! May you consider to explain your solution? Otherwise I can answer this question myself. Also: thanks for the link. Mar 5, 2013 at 18:42
  • I cant answer my own question yet due to stackexchange spam limits. Mar 5, 2013 at 19:04

2 Answers 2

6

First of all,

\tikzstyle{<key>}=[<value>]

is the same as

\tikzset{<key>/.style={<value>}}

From this point I will only use the \tikzset syntax (→ Should \tikzset or \tikzstyle be used to define TikZ styles?). But you would've had the same problem with \tikzset.

The assignment is not a problem, the style TIKZStyle contains simply your argment to styleA. But when TikZ executes this style (say when \draw[TIKZSTYLE]) it sees firstly \DEFstyle and its definition and tries it as a key, but a key named top color=green,bottom color=red (for TikZ this is just one “string” at this moment) does not exist.

Even top color=green won’t work because, again, TikZ does not see the = hidden in \DEFstyle.
The only thing that would work is is a style without a parameter, say

\setstyles{styleA={rounded corners}}%
\tikz \draw[TIKZSTYLE] (0,0) rectangle (1em,2ex);

which results in rounded rectangle. But even that is not safe enough:

\setstyles{styleA={rounded corners}}%
\def\DEFstyle{fill}%
\tikz \draw[TIKZSTYLE] (0,0) rectangle (1em,2ex);

(But then again, throw some @ in the \DEFstyle macro’s name …).

These are the reasons we need to expand \DEFstyle before assigning it to the TIKZSTYLE style:

\tikzset{TIKZSTYLE/.style/.expand once=\DEFstyle}%

In your definition of the \setstyles macro are some spurious spaces:


I do not know much about your project, but as a reminder, you can do this all with PGF keys. See the second Code block.

Code

\documentclass[tikz]{standalone}
\usepackage{xkeyval}

\makeatletter
\def\DEFstyle{}
\define@key{styles}{styleA}{\def\DEFstyle{#1}}
\newcommand{\setstyles}[1]{%
  \setkeys{styles}{styleA={}}%
  \setkeys{styles}{#1}%
  \tikzset{TIKZSTYLE/.style/.expand once=\DEFstyle}%
}
\makeatother

\begin{document}
\setstyles{styleA={top color=green,bottom color=red}}
\tikz \draw[TIKZSTYLE] (0,0) rectangle (1em,2ex);
\end{document}

Code (sans-xkeyval)

\documentclass[tikz]{standalone}

\pgfkeys{
    /no xkeyval/styleA/.style={
        /tikz/TIKZSTYLE/.style={#1}
    }
}
\newcommand*{\setstyles}[1]{%
    \pgfqkeys{/no xkeyval}{#1}%
}
\begin{document}%
\setstyles{styleA={top color=green,bottom color=red}}%
\tikz \draw[TIKZSTYLE] (0,0) rectangle (1em,2ex);
\end{document}
3

One use of xkeyval package might be to preset some keys, so that their preset values can be used when no user value is provided for them.

\documentclass{article}
\usepackage{tikz,xkeyval}

\makeatletter
\define@key{styles}{color set}{\def\rectstyle{#1}}
\define@key{styles}{rect size}{\def\rectsize{#1}}
\presetkeys{styles}{color set={top color=white,bottom color=gray},rect size={5em,5em}}{}
\newcommand*{\setstyles}[1][]{%
  \setkeys{styles}{#1}%
  \edef\tempa{\unexpanded{\tikz\draw}[\rectstyle](0,0)rectangle(\rectsize)}\tempa;
}
\makeatother

\begin{document}
\begin{tikzpicture}
\setstyles
\hspace{1cm}
\setstyles[color set={top color=green,bottom color=red},rect size={5ex,6ex}]
\hspace{1cm}
\setstyles[rect size={10ex,8ex}]
\end{tikzpicture}
\end{document}

enter image description here

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .