7

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).

1
  • 4
    TikZ v3 has a key node content
    – percusse
    Jan 6, 2016 at 16:22

2 Answers 2

8

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}

enter image description here

5
  • Nice! (+1) Just add align=left to the style to allow the linebreak to work properly. Jan 6, 2016 at 16:48
  • @PaulGessler Unfortunately, my solution breaks align=left. I don't know why, yet. I have to explicitely put text width=…. Jan 6, 2016 at 16:50
  • @HenriMenke Thanks, this looks like a good solution for me… If we manage to solve the align problem! Jan 7, 2016 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… Jan 7, 2016 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. Feb 8, 2016 at 10:21
8

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}

enter image description here

3
  • 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. Jan 7, 2016 at 9:41
  • For other readers: Note that if you use node contents, then you must specify your node as \node[styles];, and cannot use \node[styles] (label); or \node[styles] (label) {contents};.
    – FWDekker
    Feb 28 at 9:56
  • 1
    @FWDekker yes, this is because using node contents causes the parsing of the node to stop after the close of the options block. If you want to add a node name you can use the alternate syntax using options for that: \node[/uml/interface=MyInterface,name=label];. If you want to inherit the style but override the node contents, you can add another node contents option after the style: \node[/uml/interface,name=anotherlabel,node contents={Overridden contents}];. Feb 28 at 14:20

You must log in to answer this question.

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