7

I have a series of complicated content I'm trying to present using TikZ. The code is highly regular, so I wanted to write a simple command to handle everything. In the following code, \aelabelA and \aelabelC are not working properly at all and I don't understand why. However, \aelabelB does work. Could someone explain why the content of the boxes for scenario A and C is not visible?

\documentclass{standalone}
\usepackage{xparse}
\usepackage{tikz}

\ExplSyntaxOn
\newsavebox\aebox
\NewDocumentCommand\aelabelA{ mu{~located~at~(}u{);} }
  {
    \begin{lrbox}{\aebox}
      \begin{minipage}{1in}
        \Large\ttfamily\bfseries
        \centering\makebox[0pt]{#1}
      \end{minipage}
    \end{lrbox}
    \node[draw] ~ at~  (#3)  ~ {\usebox{\aebox}};
  }

\NewDocumentCommand\aelabelB{ m }
  {
    \begin{lrbox}{\aebox}
      \begin{minipage}{1in}
        \Large\ttfamily\bfseries
        \centering\makebox[0pt]{#1}
      \end{minipage}
    \end{lrbox}
    \usebox{\aebox}
  }

\ExplSyntaxOff

\def\aelabelC#1 located at (#2);{%%
    \begin{lrbox}{\aebox}
      \begin{minipage}{1in}
        \Large\ttfamily\bfseries
        \centering\makebox[0pt]{#1}
      \end{minipage}
    \end{lrbox}%%
    \node[draw] at (#2) {\usebox{\aebox}};
  }

\begin{document}

\begin{tikzpicture}

  \coordinate (AA) at (0,0);
  \coordinate (BB) at (2,2);
  \coordinate (CC) at (4,4);

  \aelabelA {Keys} located at (AA);

  \node[draw] at (BB) {\aelabelB{Keys}};

  \aelabelC{Keys} located at (CC);

\end{tikzpicture}

\end{document}

enter image description here

2
  • 1
    That's indeed a bit curious. (+1) However, if you put something in your tikzpicture (but not in a node), this will be gobbled. Isn't that just what happens to the contents of the lrboxes? As you see in your example B, if you do the lrbox inside a node, it won't be gobbled. If you could explain what you really want to do, perhaps there is a way with the usual TikZ/pgf methods.
    – user121799
    Commented Aug 30, 2018 at 21:24
  • @marmot omg. that's probably the problem. thank you. write up your comment as an answer and i'll accept later when i get back to my computer and test everything out.
    – A.Ellett
    Commented Aug 30, 2018 at 21:36

1 Answer 1

5

TikZ is known to gobble ordinary stuff inside tikzpicture environments unless this stuff is in a node. You can interrupt the tikzpicture in order to evade from getting ignored, and you need a bit globalization to make it work. I fixed your first command in this fashion but left the last one as it was for pedagogical purposes.

\documentclass{standalone}
\usepackage{xparse}
\usepackage{tikz}

\ExplSyntaxOn
\newsavebox\aebox
\NewDocumentCommand\aelabelA{ mu{~located~at~(}u{);} }
  {\begin{pgfinterruptpicture}
    \begin{lrbox}{0\null\global\setbox\aebox} % from https://tex.stackexchange.com/questions/49129/lrbox-in-newenvironment/49136#49136
      \begin{minipage}{1in}
        \Large\ttfamily\bfseries
        \centering\makebox[0pt]{#1}
      \end{minipage}
    \end{lrbox}
    \end{pgfinterruptpicture}
    \node[draw] ~ at~  (#3)  ~ {\usebox{\aebox}};
  }

\NewDocumentCommand\aelabelB{ m }
  {
    \begin{lrbox}{\aebox}
      \begin{minipage}{1in}
        \Large\ttfamily\bfseries
        \centering\makebox[0pt]{#1}
      \end{minipage}
    \end{lrbox}
    \usebox{\aebox}
  }

\ExplSyntaxOff

\def\aelabelC#1 located at (#2);{%%
    \begin{lrbox}{\aebox}
      \begin{minipage}{1in}
        \Large\ttfamily\bfseries
        \centering\makebox[0pt]{#1}
      \end{minipage}
    \end{lrbox}%%
    \node[draw] at (#2) {\usebox{\aebox}};
  }

\begin{document}

\begin{tikzpicture}

  \coordinate (AA) at (0,0);
  \coordinate (BB) at (2,2);
  \coordinate (CC) at (4,4);

  \aelabelA {Keys} located at (AA);

  \node[draw] at (BB) {\aelabelB{Keys}};

  \aelabelC{Keys} located at (CC);

\end{tikzpicture}

\end{document}

enter image description here

EDIT: A somewhat cleaner alternative due to @egreg (mille grazie!) with the same output.

\documentclass{standalone}
\usepackage{xparse}
\usepackage{tikz}

\ExplSyntaxOn
\newsavebox\aebox
\NewDocumentCommand\aelabelA{ mu{~located~at~(}u{);} }
  {\begin{pgfinterruptpicture}
    \begin{lrbox}{0}%
      \begin{minipage}{1in}%
        \Large\ttfamily\bfseries
        \centering\makebox[0pt]{#1}%
      \end{minipage}%
    \end{lrbox}%
    \global\setbox\aebox=\box0
    \end{pgfinterruptpicture}
    \node[draw] ~ at~  (#3)  ~ {\usebox{\aebox}};
  }

\NewDocumentCommand\aelabelB{ m }
  {
    \begin{lrbox}{\aebox}
      \begin{minipage}{1in}
        \Large\ttfamily\bfseries
        \centering\makebox[0pt]{#1}
      \end{minipage}
    \end{lrbox}
    \usebox{\aebox}
  }

\ExplSyntaxOff

\def\aelabelC#1 located at (#2);{%%
    \begin{lrbox}{\aebox}
      \begin{minipage}{1in}
        \Large\ttfamily\bfseries
        \centering\makebox[0pt]{#1}
      \end{minipage}
    \end{lrbox}%%
    \node[draw] at (#2) {\usebox{\aebox}};
  }

\begin{document}

\begin{tikzpicture}

  \coordinate (AA) at (0,0);
  \coordinate (BB) at (2,2);
  \coordinate (CC) at (4,4);

  \aelabelA {Keys} located at (AA);

  \node[draw] at (BB) {\aelabelB{Keys}};

  \aelabelC{Keys} located at (CC);

\end{tikzpicture}

\end{document}

A macro for creating \saveboxes inside a tikzpicture has been created in this question.

1
  • 2
    I suggest the cleaner \begin{lrbox}{0}...\end{lrbox}\global\setbox\aebox=\box0
    – egreg
    Commented Sep 3, 2018 at 21:10

You must log in to answer this question.

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