# Tikz node style that will programmatically modify the node content

I’d like to set up a tikz style, say /uml/interface, that would modify the node content following some macro of my choosing. For example, it would prefix the node text with some text of my choosing. I would use it as follows.

\path node[/uml/interface] (MyInterface) {MyInterface};


And as a result of applying the /uml/interface style the node content would become <<interface>> \\ MyInterface.

I have used the font change command, as follows.

\tikzset{/uml/interface/.style={rectangle, draw, every text node/.style={font=\bfseries}}}


But I did not find in the PGF manual how to programmatically modify the node text itself.

Ideally, I would do something like this:

\tikzset{/uml/interface/.style={…, every text node/.style={applyMacro=\umlinterface}}}


and

\newcommand{\umlinterface}[1]{<<interface>> \\ \textbf{#1}}


. As a workaround I could typeset my node as follows:

\path node[/uml/interface] (MyInterface) {\umlinterface{MyInterface}};


, but I’d prefer having a clean node content part (for consistence, maintenance, readability, and avoiding refactoring all my related node commands when I decide to add a prefix).

-
TikZ v3 has a key node content – percusse Jan 6 at 16:22

You can apply a macro to the node text by injecting it with execute at begin node. This works, because in the TikZ code this key is immediately followed by \bgroup.

/uml/interface/.style={
rectangle, draw,
execute at begin node=\umlinterface
}


To be safe, I added another level of grouping.

\documentclass{article}
\usepackage[T1]{fontenc} % just for the guillemets
\usepackage{tikz}
\begin{document}
\newcommand{\umlinterface}[1]{<<interface>> \\ \textbf{#1}}
\tikzset{
/uml/interface/.style={
rectangle, draw,
execute at begin node=\umlinterface\bgroup,
execute at end node=\egroup
}
}
\begin{tikzpicture}
\path node[/uml/interface] (MyInterface) {MyInterface};
\end{tikzpicture}
\end{document}


-
Nice! (+1) Just add align=left to the style to allow the linebreak to work properly. – Paul Gessler Jan 6 at 16:48
@PaulGessler Unfortunately, my solution breaks align=left. I don't know why, yet. I have to explicitely put text width=…. – Henri Menke Jan 6 at 16:50
@HenriMenke Thanks, this looks like a good solution for me… If we manage to solve the align problem! – Olivier Cailloux Jan 7 at 9:36
Also the suggested strategy has odd behavior inside a beamer frame. It works with execute at begin node=\textbf but not with execute at begin node=\myowncommand, not sure why. I guess it is related to align-not-working anyway so I’ll wait to see if anybody better acquainted to (la)tex than me can work it out… – Olivier Cailloux Jan 7 at 13:56
Here is a patch to render execute at begin node compatible with align=. Unfortunately it involves fiddling with the inner workings of tikz. I would not go that far just to get my "prefix" functionality. I’d like to find a simpler solution, but I guess none exist currently. – Olivier Cailloux Feb 8 at 10:21

Slightly different from your expected input, but here's one approach using the node contents key mentioned by percusse.

I use the interface name as an argument to the style, and piece together the full node contents inside the definition of the style.

\documentclass[tikz]{standalone}
\usepackage[T1]{fontenc} % just for the guillemets
\tikzset{/uml/interface/.style={
% ... more style defs as needed ...
rectangle, draw, align=left,
node contents={<<interface>> \\ \textbf{#1}},
}}

\begin{document}
\tikz{\node[/uml/interface=MyInterface];}
\end{document}


-
Clever use of node contents! I’d favor Henri’s solution if we can make it work, but it is good to have a backup solution. – Olivier Cailloux Jan 7 at 9:41