4

I would like to make use of some shorthand for drawing boxes in Tikz.

A minimal working example:

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{tikz}
\usepackage{xstring} 

\newcommand\makeButton[3]{
    \node (rect) at #1 [fill=magenta] {#3};
}

\begin{document}

\begin{tikzpicture}[overlay]
\makeButton{(1,1)}{1}{Click here.}
\end{tikzpicture}

\end{document}

I would like the second argument of \makeButton to set the color of the button. (The button should be magenta if #2==1, and cyan otherwise.) So I replaced the \newcommand in the example above by

\newcommand\makeButton[3]{
    \node (rect) at #1 [fill=\ifthenelse{\equal{#2}{1}}{magenta}{cyan}] {#3};
}

This return the following error:

! Undefined control sequence.
<argument> \equal 
                  {1}{1}
l.15 \makeButton{(1,1)}{1}{Click here.}

If I replace \equal{#2}{1} with some dummy condition for now,

\newcommand\makeButton[3]{
    \node (rect) at #1 [fill=\ifthenelse{15>10}{magenta}{cyan}] {#3};
}

... I still get an error:

! Argument of \@tempc has an extra }.
<inserted text> 
                \par 
l.15 \makeButton{(1,1)}{1}{Click here.}

How can I fix this?

4

\ifnum of Werner's answer is expandable and can be used in the value part for key fill. This is shown in the definition of \makeButtonA.

\ifcase is also expandable and expects an integer. It is useful for consecutive numbers as shown in \makeButtonB. Although \ifcase can be used inside the value for fill, the color is defined outside as macro to get a clearer source code.

Also \ifthenelse can be used (for the fans of ifthen). But then the color must be defined outside in a non-expandable context. This is shown in the definition of \makeButtonC.

Full example:

\documentclass{article}

\usepackage{tikz}% also loads xcolor
\usepackage{ifthen}

% Expandable \ifnum
\newcommand{\makeButtonA}[3]{%
  \node at #1 [fill={\ifnum#2=1 magenta\else cyan\fi}] {#3};
}

% Present \ifcase
\newcommand*{\makeButtonB}[3]{%
  \edef\ButtonFillColor{%
    \ifcase\numexpr(#2)\relax
      black% 0
    \or magenta% 1
    \or cyan% 2
    \or red% 3
    \or green% 4
    \or blue% 5
    \else black%
    \fi
  }
  \node at #1 [fill=\ButtonFillColor] {#3};
}

% A variant with \ifthenelse
\newcommand*{\makeButtonC}[3]{%
  \ifthenelse{\equal{#2}{1}}{%
    \colorlet{ButtonFillColor}{magenta}%
  }{%
    \colorlet{ButtonFillColor}{cyan}%
  }%
  \node at #1 [fill=ButtonFillColor] {#3};
}

\begin{document}

\begin{tikzpicture}[y=-8mm]
  \makeButtonA{(1,1)}{1}{Click here A1.}
  \makeButtonA{(1,2)}{15}{Click here A2.}
  \makeButtonB{(1,3)}{1}{Click here B1.}
  \makeButtonB{(1,4)}{2}{Click here B2.}
  \makeButtonB{(1,5)}{3}{Click here B3.}
  \makeButtonC{(1,6)}{1}{Click here C1.}
  \makeButtonC{(1,7)}{15}{Click here C2.}
\end{tikzpicture}

\end{document}

Result

1
  • Thank you, Heiko! I ended up using your solution for my work. I am using \makeButton to place a lot of buttons using a for loop. For that application, a command that accepts numbers as colour specifiers is easier to work with than a command that requires string inputs. For ''manual use'', I think Werner's \NewDocumentCommandis the most intuitive. Mar 4 '18 at 1:56
4

Your setting of the colour should be expandable. Here's a way to do it:

enter image description here

\documentclass{article}

\usepackage{tikz,xparse}

\newcommand{\makeButtonA}[3]{%
  \ifnum#2=1
    \node at #1 [fill=magenta] {#3};
  \else % #2 != 1
    \node at #1 [fill = cyan] {#3};
  \fi
}
\NewDocumentCommand{\makeButtonB}{m O{magenta} m}{%
  \node at #1 [fill = #2] {#3};
}

\begin{document}

\begin{tikzpicture}
  \makeButtonA{(1,1)}{1}{Click here A1.}
  \makeButtonA{(1,2)}{15}{Click here A2.}
  \makeButtonB{(1,3)}{Click here B1.}
  \makeButtonB{(1,4)}[cyan]{Click here B2.}
\end{tikzpicture}

\end{document}

I've also included an xparse option that provides an optional second argument \makeButtonB{<coord>}[<colour>]{<text>}, where the default is magenta, unless specified otherwise. It might be a more intuitive interface rather than specifying a "colour" using a "number".

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.