Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I would like to know if there is a way to automatically resize edges when they have long labels. For example, the following code

\documentclass[10pt]{article}
\usepackage{tikz}
\usetikzlibrary{positioning}
\begin{document}

\begin{tikzpicture}
   \node (a) [draw] {a};
   \node (b) [draw, right=of a] {b};
   \node (c) [draw, below right=of b] {c};
   \draw [-stealth] (a) -- node[above]{\scriptsize very long label} (b);
   \draw [-stealth] (b) -- node[below,sloped]{\scriptsize another long label} (c);
\end{tikzpicture}

\end{document}

produces labels which are longer than the corresponding arrows:

result picture

I would like to know if there is a way to automatically resize each edge so that its label fits (not too loosely) between the endpoints of the edge. I want to do this independently of the length of the label. In particular, I do not want to manually set the separation between nodes as a specific numerical distance (e.g. 2 inches).

This question can easily be translated to other drawing packages/programs. I would also like to know whether it is possible to implement a similar mechanism in metapost.

EDIT: I have added a non-horizontal arrow to generalize the question, and better reflect my intent.

share|improve this question
2  
As the edge expands, what should happen to the nodes? Should they move apart equally? Should one be fixed and the other move further away? –  Andrew Stacey Jun 14 '11 at 10:50
    
I guess I don't particularly care either way. Does it significantly affect a solution? In either case, I would probably default to having the nodes move apart equally. –  Ricardo Andrade Jun 14 '11 at 11:20
    
Not significantly, but it helps frame the problem a bit more clearly. –  Andrew Stacey Jun 14 '11 at 12:20
    
I've updated my answer to take into account your edit. –  Andrew Stacey Jun 15 '11 at 9:39
add comment

2 Answers

up vote 7 down vote accepted

I think that this is one of those that will have many solutions, ranging from the "well, it works!" to the truly elegant. Here's one of the former type.

\documentclass{standalone}
% \url{http://tex.stackexchange.com/questions/20693}
\usepackage{tikz}
\usetikzlibrary{shapes.multipart}

\tikzset{%
  xrightarrow/.style={
    rectangle split,
    anchor=text split west,
    rectangle split parts=2,
    append after command={%
      (\tikzlastnode.text split west) edge[->] (\tikzlastnode.text split east)
    }
  }
}

\begin{document}
\begin{tikzpicture}[>=stealth]
\node[draw] (a) {a};
\node[xrightarrow] at (a.east) (c) {a very long label \nodepart{two}{and some text underneath}};
\node[draw,anchor=west] (b) at (c.text split east) {b};
\node[xrightarrow,rotate=-45] at (b.south east) (d) {a very long label \nodepart{two}{and some text underneath}};
\node[draw,anchor=north west] (e) at (d.text split east) {c};
\end{tikzpicture}
\end{document}

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{shapes.multipart}

\tikzset{%
  xrightarrow/.style={
    rectangle split,
    anchor=text split west,
    rectangle split parts=2,
    append after command={%
      (\tikzlastnode.text split west) edge[->] (\tikzlastnode.text split east)
    }
  }
}

\begin{document}
\begin{tikzpicture}
\node[draw] (a) {a};
\node[xrightarrow] at (a.east) (c) {a very long label \nodepart{two}{and some text underneath}};
\node[draw,anchor=west] (b) at (c.text split east) {b};
\end{tikzpicture}
\end{document}

Result:

xrightarrow with nodes

I use a rectangle split shape so that we can easily get text on top and below and have the text centred nicely on the arrow. Ideally, the arrow would be part of the node shape itself but that would require defining a new node shape (which I'm too lazy to do right now!). To get round that, we draw the arrow with an append after command to hide it from the "user". The reason for asking (in the comments) about what should happen on expansion is purely down to the order in which things are drawn. Here, a is first, then the edge, and finally b. To have both a and b move then draw the edge first and position a and b at its ends.

(One could also play a bit more and have the text on the arrow automatically typeset in a smaller font.)

share|improve this answer
add comment

the same without tikz

\documentclass{standalone}
\usepackage{amsmath}
\newcommand\foo[4][]{%
  $\fbox{#3}\kern-1pt{\xrightarrow[\text{#1}]{\text{#2}}}\kern-1pt\fbox{#4}$}
\begin{document}

\foo[and some text underneath]{a very long label two}{a}{b}

\end{document}

enter image description here

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.