Problem
I would like to create several nodes whose text is a placeholder for an image, i.e., \phantom{\pgfuseimage{mypicture}}. This is easily done as, for example:
\matrix {
\node {\phantom{\pgfuseimage{firstpicture}}}; & \node {\phantom{\pgfuseimage{secondpicture}}}; \\
\node {\phantom{\pgfuseimage{thirdpicture}}}; & \node {\phantom{\pgfuseimage{fourthpicture}}}; \\
% etc.
};
The problem is that this is quite verbose. I would like to avoid having to type \phantom{\pgfuseimage{...}} in each node. Besides saving keystrokes, it would make the code much cleaner and easier to read.
Attempted solutions
Defining a macro to abbreviate
Of course, I could define a command \pgfimageplaceholder to be \phantom{\pgfuseimage{...}}. But I would still need to write \pgfimageplaceholder in each node, so the macro doesn't help save many keystrokes or improve readability much at all.
Using the execute at begin/end node keys
After seeing how matrix of nodes is defined (page 207 of the PGF/TikZ 2.10 manual), I thought that I might be able to use the execute at begin node and execute at end node options in TikZ to factor out \phantom{\pgfuseimage{...}}. Following the definition of matrix of nodes, I tried:
\matrix [every node/.append style={execute at begin node=\phantom\bgroup\pgfuseimage\bgroup,
execute at end node=\egroup\egroup}]
{
\node {firstpicture}; & \node {secondpicture}; \\
\node {thirdpicture}; & \node {fourthpicture}; \\
% etc.
};
Unfortunately, this gives the error Missing } inserted. I've never done any plain TeX coding, so I'm not familiar with \bgroup and \egroup. Am I using them correctly? If so, why does this error occur? (Interestingly, I do not get an error if I replace \phantom\bgroup\pgfuseimage\bgroup with \textit\bgroup and \egroup\egroup with \egroup.)
Using a PGF key
In response to an earlier version of this question, @AndrewStacey suggested using a key to pass the picture name to the node, rather than relying on the node text. I've never created PGF keys before, but, if I understand them correctly, then the code would be something like the following. (Please correct me if I am misinterpreting your suggestion, @AndrewStacey.)
\pgfkeyssetvalue{/picture name}{}
\matrix [every node/.append style={execute at begin node=\phantom{\pgfuseimage{\pgfkeysvalueof{/picture name}}}}]
{
\node[/picture name=firstpicture] {}; & \node[/picture name=secondpicture] {}; \\
\node[/picture name=thirdpicture] {}; & \node[/picture name=fourthpicture] {}; \\
% etc.
};
Is this the correct way to create and use a key? If so, this approach is more readable, but doesn't save very many keystrokes.
Using a \foreach construction
I thought about using \foreach, but I do not see how to combine it with the \matrix structure that I want.
A minimal working example
For completeness, here is a MWE.
\documentclass{minimal}
\usepackage{tikz}
\usetikzlibrary{positioning}
\begin{document}
\pgfdeclareimage{firstpicture}{pic1.pdf}
\pgfdeclareimage{secondpicture}{pic2.pdf}
\pgfdeclareimage{thirdpicture}{pic3.pdf}
\pgfdeclareimage{fourthpicture}{pic4.pdf}
% etc.
\newcommand{\pgfimageplaceholder}[1]{\phantom{\pgfuseimage{#1}}}
\begin{tikzpicture}[every node/.style={draw=black},
every matrix/.style={draw=red}]
% Here is a working example of what I need to do,
% but it is rather verbose. I would rather not
% have to type \phantom{\pgfuseimage{ each time.
\matrix (part1)
{
\node {\phantom{\pgfuseimage{firstpicture}}}; & \node {\phantom{\pgfuseimage{secondpicture}}}; \\
\node {\phantom{\pgfuseimage{thirdpicture}}}; & \node {\phantom{\pgfuseimage{fourthpicture}}}; \\
% etc.
};
% I could replace \phantom{\pgfuseimage{ with a
% macro, but that doesn't save many keystrokes
% or improve readability much.
\matrix (part2)
[right=of part1]
{
\node {\pgfimageplaceholder{firstpicture}}; & \node {\pgfimageplaceholder{secondpicture}}; \\
\node {\pgfimageplaceholder{thirdpicture}}; & \node {\pgfimageplaceholder{fourthpicture}}; \\
% etc.
};
% I was hoping to be able to somehow use the hooks
% execute at begin/end node to factor out the
% repeated \phantom{\pgfuseimage{.
\matrix (part3)
[right=of part2
% When the following two lines are uncommented,
% the error is ``Missing } inserted.''
% , every node/.append style={execute at begin node=\phantom\bgroup\pgfuseimage\bgroup,
% execute at end node=\egroup\egroup}
]
{
\node {firstpicture}; & \node {secondpicture}; \\
\node {thirdpicture}; & \node {fourthpicture}; \\
% etc.
};
% Andrew Stacey suggested using a key to specify
% the picture, rather than putting it in the node
% text. Here is my attempt at doing that.
\pgfkeyssetvalue{/picture name}{}
\matrix (part4)
[right=of part3,
every node/.append style={%
execute at begin node=\phantom{\pgfuseimage{\pgfkeysvalueof{/picture name}}}}]
{
\node[/picture name=firstpicture] {}; & \node[/picture name=secondpicture] {}; \\
\node[/picture name=thirdpicture] {}; & \node[/picture name=fourthpicture] {}; \\
% etc.
};
\end{tikzpicture}
\end{document}
fontoption doesn't quite do what I want. – Henry DeYoung Jun 13 '12 at 20:48\node[execute at begin node=\begingroup\textit, execute at end node=\endgroup] {mypicture};– Alain Matthes Jun 13 '12 at 20:48\textitplays a role here? Also with the same ignorance this looks like an XY problem. Can you give a concrete example about the task at hand? Maybe we can look at it together and find a way that doesn't involve a lot of customization. – percusse Jun 13 '12 at 22:15\begingroupin that way.\textit\begingroup...is\textit{\begingroup}...so the argument to\textitis an unmatched\begingroupand things fall over. Same with any macro such as\pgfuseimageor\phantom. – David Carlisle Jun 13 '12 at 22:24\pgfuseimage\bgroupand\egroupis not\pgfuseimage\bgroup{node text}\egroupbut actually a lot more goes in between. So I think your best bet is to put the whole code in one of these hooks and use a pgfkey to set the image name. That would actually be quite straightforward, would it be an acceptable solution? – Andrew Stacey Jun 14 '12 at 08:56\textitbut not for\phantom{\pgfuseimage{...}}. – Henry DeYoung Jun 14 '12 at 20:27\newcommand\imgnode[1]{\node {\phantom{\pgfuseimage{#1}}}? Then then you could type\imgnode{firstpicture};, which saves plenty of keystrokes but is still reasonably readable. – Jake Jun 14 '12 at 20:46\imgnodecommand would be slightly more complicated than what you wrote, but not much more complicated. So far, IMO yours is the best solution--I don't know why I didn't think of that! For its own sake, I'm still interested in understanding what goes wrong withexecute at begin node=\phantom\bgroup\pgfuseimage\bgroup, however. – Henry DeYoung Jun 14 '12 at 20:59\textitthat doesn't matter but for\pgfuseimagethen it does as it wants just a file name. Your attempt with pgfkeys is pretty much what I was thinking. To save key strokes, you could make the key name considerably shorter. But Jake's suggestion of a wrapper macro is probably best:\newcommand\imgnode[2][]{\node[#1] {\phantom{\pgfuseimage{#2}};}. – Andrew Stacey Jun 14 '12 at 21:08\pgfuseimageis treated verbatim, but this is not the case for\textit. So, in principle, if one could redefine\pgfuseimageto not treat its argument verbatim, then the hook-based approach might work. Is that right? Of course, redefining\pgfuseimagewould be much, much more complicated than just using Jake's suggestion. – Henry DeYoung Jun 14 '12 at 21:20