3

I'm looking after a way to create tree diagrams for file format specifications like in the Minecraft Wiki. I tried creating it with Forest and this is what I have at the moment. This solution works fine, but my large descriptions just get cut off at the right end of the document. I tried adding line breaks in Forest but haven't achieved it yet. Is there a way to make such diagrams in LaTeX (I don't care about the used packages)?

I has to be in LaTeX due do the possibility to add links and references in the text of the diagram.

3 Answers 3

3

Here's a different approach which does not rely on the use of labels. The latter will only really work properly if they are confined to a single line because Forest cannot accommodate them when packing the tree. For short labels, they are most convenient in this kind of tree, but for longer labels, they are not the best choice, in my opinion.

  • minecraft schematic styles the tree;
  • icon adds a default file icon to a node;
  • icon=<style> adds a file icon in <style> to a node.

As examples, I use a default style, which can be redefined by changing icon/style/.style, icon/main/.style, icon/dim/.style and icon/elk/.style.

you too can choose the elk blues

\documentclass[tikz,border=10pt,multi,dvipsnames,svgnames,x11names]{standalone}
\usepackage[edges]{forest}
\usepackage{calc}
\forestset{
  declare toks={my label}{},
  declare toks={my details}{},
  declare boolean={my icon}{0},
  minecraft schematic/.style={% addaswyd o ateb: http://tex.stackexchange.com/a/340354/
    for tree={% addaswyd o gôd Gonzalo Medina: http://tex.stackexchange.com/a/270761/
      folder,
      font=\sffamily,
      grow'=0,
      text width=75mm,
    },
    before typesetting nodes={
      for tree={
        split option={content}{:}{my label,my details},
        delay={
          content/.process={On=?_OOw3}{my icon}{1}{\makebox[\iconwidth+\iconmargin]{}}{}{my label}{my details}{##1\textbf{##2:} ##3},
        },
      },
    },
  },
  icon/.style={
    my icon,
    tikz+={
      \pic at ([xshift=\iconmargin,yshift=-.1*\baselineskip].north west) {my file={#1}};
    },
    edge path'/.expanded={% addaswyd o forest-lib-edges.sty
      ([xshift=\forestregister{folder indent}]!u.parent anchor) |- ([xshift=-.5*\iconmargin,yshift=-.5*\iconheight].north west)
    },
  }
}
\tikzset{
  my file/.pic={
    \draw [icon/.cd, style, #1] (0,-\iconheight) |- +([xshift=-.2*\iconwidth]\iconwidth,\iconheight) edge +([yshift=-.2*\iconwidth]\iconwidth,\iconheight) |- +([yshift=-.2*\iconwidth]\iconwidth,\iconheight) |- cycle;
  },
  icon/.search also={/tikz},
  icon/.cd,
  width/.store in=\iconwidth,
  height/.store in=\iconheight,
  margin/.store in=\iconmargin,
  style/.style={fill=gray!50!blue!25},
  width=7.5pt,
  height=10pt,
  margin=2.5pt,
  main/.style={inner color=white, outer color=red},
  dim/.style={fill=gray!25},
  elk/.style={top color=blue, bottom color=blue, middle color=cyan},
}
\begin{document}
\begin{forest}
  minecraft schematic,
  where level<=2{icon}{},
  [Schematic:Schematic data., icon=main
    [Various:Things
      [Other:Various things
        [Dimensions:{All dimensions for everything in the entire universe should be stored, one per line, here.
          Authors should ensure that dimensions are listed in ascending order.
          Partial submissions will not be accepted.}, for tree={icon=dim}
          [tex:t1.1.1.1.1]
          [tex:t1.1.1.1.2]
          [tex:t1.1.1.1.3]
        ]
      ]
      [tex:t1.1.2
        [tex:t1.1.2.1]
      ]
      [tex:t1.1.3
        [tex:t1.1.3.1]
      ]
    ]
    [Elks:Many elks are quite friendly once you get to know them., for tree={icon=elk}
      [Faint praise:Damning with]
      [Elk blues:Moose jazz]
    ]
  ]
\end{forest}
\end{document}

EDIT

Note that a proper example in the question could have clarified what you wanted and avoided a lot of wasted time and effort. You say you tried to adapt the code above and had problems, but you provide no details of what you tried and minimal additional information about your desiderata.

The following may or may not be like what you tried, may or may not be what you want, may or may not be of any use. Really, I have no idea.

We add an additional Forest style, icon square img:

  icon square img/.style={
    my icon,
    tikz+={
      \node [anchor=north west] at ([xshift=-.5*\iconmargin,yshift=.2*\iconwidth].north west) {\includegraphics[width=\iconwidth]{example-grid-100x100pt}};
    },
    edge path'/.expanded={% addaswyd o forest-lib-edges.sty
      ([xshift=\forestregister{folder indent}]!u.parent anchor) |- ([xshift=-.5*\iconmargin,yshift=-.5*\iconwidth].north west)
    },
  },

Then we can adapt the original tree to use the new style.

\begin{forest}
  minecraft schematic,
  where level<=2{icon square img}{},
  /tikz/icon/width=10pt,
  [Schematic:Schematic data.
    [Various:Things
      [Other:Various things
        [Dimensions:{All dimensions for everything in the entire universe should be stored, one per line, here.
          Authors should ensure that dimensions are listed in ascending order.
          Partial submissions will not be accepted.}
          [tex:t1.1.1.1.1]
          [tex:t1.1.1.1.2]
          [tex:t1.1.1.1.3]
        ]
      ]
      [tex:t1.1.2
        [tex:t1.1.2.1]
      ]
      [tex:t1.1.3
        [tex:t1.1.3.1]
      ]
    ]
    [Elks:Many elks are quite friendly once you get to know them.
      [Faint praise:Damning with]
      [Elk blues:Moose jazz]
    ]
  ]
\end{forest}

alternative with external images

I note that not one of the icons in the sample you linked to elsewhere was square. Every one was a standard file-shaped icon. Files in icons are never square, even though their containing icons are. Therefore, I did not even think I needed my crystal ball, which is unreliable at the best of times.

6
  • Thank you, this is what I was looking for! Can I change the icon to be an actual image?
    – piegames
    Commented Jan 6, 2017 at 15:22
  • 1
    You can use \node at ... {\includegraphics{}}; rather than \pic ...; in the definition of the icon style. Is that what you mean?
    – cfr
    Commented Jan 6, 2017 at 16:10
  • Yes, exactly. I replaced it this way and now the icon has an offset and is distorted. Can you please update you answer that it works with a (square) texture?
    – piegames
    Commented Jan 6, 2017 at 16:58
  • @piegames FWIW ^^
    – cfr
    Commented Jan 7, 2017 at 0:35
  • @piegames: if this is the solution you are looking for, please mark this answer as "Solving" by clicking on the checkmark.
    – Jan
    Commented Jan 7, 2017 at 9:09
3

If the descriptions will not take more then a few lines (such that the tree layout doesn't have to be changed) you just have to add text width=3cm (or some other width) to my label/.style.

Suppose we change the following two things in this code: we replace

  my label/.style={
    label={[font=\sffamily]right:{#1}},
  },

by

  my label/.style={
    label={[font=\sffamily,text width=3cm]right:{#1}},
  },

and we replace

      [tex:t1.1.1.1.1]

by

      [tex:t1.1.1.1.1 long long long long long text]

Then we obtain:

enter image description here

4
  • Even with only 2 lines of text this looks ugly because the lines are farther away from each other then from the text of the leaf above/below. How do I change line spacing / the distance between leaves in Forest?
    – piegames
    Commented Jan 5, 2017 at 17:55
  • In the sub-tree, where the children should have a wider distance, add for tree={s sep=1cm}; e.g., in the above sampe code, use ... [tex:t1.1.1.1, for tree={s sep=1cm} [tex:t1.1.1.1.1 long long ... . Replace 1cm by whatever distance looks reasonable.
    – gernot
    Commented Jan 5, 2017 at 18:08
  • The trouble with this solution is that you need to increase the distances manually. Also, be careful because folder modifies s after packing node. I think the change will still work, but it would be worth checking.
    – cfr
    Commented Jan 6, 2017 at 0:38
  • @piegames It depends. It would be easier to help if you'd provided a proper example, which would obviously need to include some samples of nodes with typical amounts of text in them.
    – cfr
    Commented Jan 6, 2017 at 0:39
3

You can add line break inside node's label with align=left, more detail can be found in this answer

Complete code

\documentclass[tikz,border=10pt,multi,dvipsnames,svgnames,x11names]{standalone}
\usepackage[edges]{forest}

\begin{document}
\begin{forest}
  my label/.style={
    label={[font=\sffamily,align=left]right:{#1}},% align=left added
  },
  for tree={% 
    folder,
    font=\sffamily,
    text=white,
    minimum height=0.75cm,
    if level=0{fill=ForestGreen}{fill/.wrap pgfmath arg={SlateBlue#1}{int(4-(mod((level()-1),4)))}},
    rounded corners=4pt,
    grow'=0,
    edge={ForestGreen,rounded corners,line width=1pt},
    fit=band,
  },
  before typesetting nodes={
    for tree={
      split option={content}{:}{content,my label},
    }
  }
  [tex:{t1\\ bla bla bla}
    [tex:t1.1
      [tex:t1.1.1
        [tex:t1.1.1.1
          [tex:t1.1.1.1.1]
          [tex:t1.1.1.1.2]
          [tex:t1.1.1.1.3]
        ]
      ]
      [tex:t1.1.2
        [tex:t1.1.2.1]
      ]
      [tex:t1.1.3
        [tex:t1.1.3.1]
      ]
    ]
    [tex:t1.2
      [tex:t1.2.1]
      [tex:t1.2.2]
    ]
  ]
\end{forest}
\end{document}
3
  • Why do I need the align=left? I removed it and just added \\ and still got a line break.
    – piegames
    Commented Jan 5, 2017 at 17:50
  • @piegames Then you have adulterated my code without telling people and cannot expect their solutions to constitute more than desperate whistling in the darkness of ignorance.
    – cfr
    Commented Jan 6, 2017 at 0:31
  • The trouble with this solution is that the way the tree is packed will not allow for the growing height and depth of the label. This is OK for, say, 2 lines because the boxed nodes are quite tall and deep. But it would be less good if the OP needs, say, a paragraph.
    – cfr
    Commented Jan 6, 2017 at 0:33

You must log in to answer this question.

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