7

I'm trying to write some conditional TikZ styles. This has been tried here before, but I think never in a completely satisfying way. My try is this:

\documentclass{article}

\usepackage{tikz}

\begin{document}
    \tikzset{drawif/.style={\ifnum 1=1 draw\else fill\fi}}
    \tikz{\node[drawif] {Test};}
\end{document}

Instead of 1=1, insert a meaningful expression. When compiling, this gives a lot of errors:

! Missing = inserted for \ifnum.
               }
l.7         \tikz{\node[drawif]
                      {Test};}
! Missing number, treated as zero.
               }
l.7         \tikz{\node[drawif]
                      {Test};}
! Argument of \pgfkeys@@normal has an extra }.
            \par 
l.7         \tikz{\node[drawif] {Test};}

Runaway argument?
\pgfkeys@mainstop \else \pgfkeys@case@two \fi \fi \fi \pgfkeys@parse \ETC.
! Paragraph ended before \pgfkeys@@normal was complete.

etc. What's going on?

Turion
  • 4,622
  • if you need to do the test at style definition time you could try by putting it outside the \tikzset command or using .estyle – Bordaigorl Dec 02 '14 at 15:55
  • Instead if you need the code to be executed every time you set the style you really need .code instead of .style. What happens here is that tikz tried to parse your code as tikz styles and gets all confused – Bordaigorl Dec 02 '14 at 15:56

2 Answers2

6

What happens is that tikz is trying to parse the style you are defining as a style and gets confused when it reads \ifnum.

What you actually want here is to run some code when setting the drawif style. This code will in turn set some styles under certain conditions. To run code when setting a style you can use the .code key instead of the .style one.

\documentclass{article}

\usepackage{tikz}

\begin{document}
    \tikzset{drawif/.code={\ifnum 1=1 \tikzset{draw}\else \tikzset{fill}\fi}}
    \tikz{\node[drawif] {Test};}
\end{document}

You can use #1 inside the .code value to refer to the argument that can be passed to the style:

\usepackage{tikz}

\begin{document}
    \tikzset{drawif/.code={\ifnum #1=1 \tikzset{draw}\else \tikzset{fill}\fi}}
    \tikz{\node[drawif=1] {Test};}
\end{document}

and with drawif/.default=1 you can set a default value used for #1 in case drawif is used without argument.

Bordaigorl
  • 15,135
3

.style tries to split the input at = to recognize key/value pairs. You need to hide the = sign in braces:

\documentclass{article}

\usepackage{tikz}

\begin{document}
\makeatletter
\tikzset{
  drawif/.style={%
    \expandafter\ifnum\@firstofone{1=\test} draw\else fill\fi
  }
}
\makeatother

\def\test{1}
\tikz{\node[drawif] {Test};}

\def\test{0}
\tikz{\node[drawif] {Test};}

\end{document}

but I think the .code route is better.

A simpler trick:

\documentclass{article}

\usepackage{tikz}

\newcommand{\equals}{=}

\begin{document}
\tikzset{
  drawif/.style={%
    \ifnum 1\equals\test draw\else fill\fi
  }
}

\def\test{1}
\tikz{\node[drawif] {Test};}

\def\test{0}
\tikz{\node[drawif] {Test};}

\end{document}

Of course \test is used just for the example. Note that < or > don't give problems.

egreg
  • 1,121,712