One of my publishing products involves creating a fairly large number (21,000) of diagrams, consisting of about 14,000 unique nodes. This is all machine-generated, drawing dependency graphs of game objects.
I want to favor nodes with a text width of 21mm, but allow nodes a few millimetres wider if it means reducing the height of nodes that are more than two rows of text. If a node would have two lines of text, I don't feel the need to tweak it to be made one row of text.
I prefer the second node shown here. The third is wider than it needs to be.
Until now, I've been manually adjusting the node widths to do this. As might be understandable, I want to minimize manual intervention. I was looking for a way to automate these tweaks.
@Qrrbrbirlbel gave me the hint I needed to build the full solution I was looking for, varwidth. My MWE below is a minimally-working solution (not ready for packaging, but enough to show how to do what I needed).
\documentclass{article}
\usepackage{calc}
\usepackage{tikz}
\usepackage{varwidth}
\usetikzlibrary{calc,graphs,fit,matrix}
\newcommand{\tn}[2][]{\node[,align=left,anchor=west,#1] {#2};}
\tikzset{
n/.style={draw,align=flush center,inner sep=1mm},
n21/.style={n,text width=21mm},
nvw/.style={n,minimum width=23mm},
}
\newlength{\nntw}
\newcommand{\nnvw}[3][]{\node[nvw,#1] (#2) {\begin{varwidth}{25mm}\centering #3\end{varwidth}};}
\newcommand{\nnif}[3][]{%
\setlength{\nntw}{\widthof{#3}}%
\ifdim\nntw < 25mm
\node[n21,#1](#2){#3};
\else
\nnvw[#1]{#2}{#3}
\fi
}
\begin{document}
\begin{tikzpicture}
\matrix [row sep=4mm,column sep=4mm,every node/.style={font=\sffamily},] {
\node{1}; & \node[n,text width=21mm]{Improved Unarmed Strike}; & \tn{text width = 21mm} \\
\node{2}; & \node[n,text width=23mm]{Improved Unarmed Strike}; & \tn{text width = 23mm} \\
\node{3}; & \node[n,text width=25mm]{Improved Unarmed Strike}; & \tn{text width = 25mm} \\
\node{4}; & \nnvw{}{Improved Unarmed Strike} & \tn{varwidth 25mm} \\
\node{5}; & \nnvw{}{Unarmed Strike} & \tn{varwidth 25mm} \\
\node{6}; & \nnif{}{Unarmed Strike} & \tn{varwidth if 25mm} \\
};
\end{tikzpicture}
\end{document}
The \nnwe command creates a node with a minimum width of 23mm (21mm+2*inner sep), and populates the node with a varwidth environment that can be up to 23mm wide (but will be narrower if the 'natural width' of the content can be). This functionally gives me a node that can have a text width of 21mm-23mm. Node 4 in my output was generated with the \nnvw command.
The final piece above is to handle where the node could be reduced to a single line, but I don't need it to be. I have lots of two-line nodes, so single-line nodes actually tend to stand out. If I use \nnvw, a node of 'Unarmed Strike' is reduced to a single line... but I don't need that. I added another command, \nnif, that first checks the text width it see if it would even get close to being three lines, before deciding to use \nnvw. I found that I needed to create a length to compare using \ifdim, I couldn't directly use \widthof{#3} with \ifdim.
This isn't my final solution that'll make it into my class file. I certainly want better names for the commands and whatnot, and I'd like to see if I can build the varwidth decision into a style definition... but for simple "how to get a node that can grow a bit when needed", I think this'll work.



l3espis probably still some way off ...