7

I'm trying to create elements grouping .pic:

  1. have children of unknown layout (doesn't even has to be node structure, it could even be plot, or tree )
  2. act like a node - anchor it as one element, doesn't matter what it's contents are
  3. auxiliary inner contents
    1. title element
    2. connectors on left and right side (not shown, but will be made in similar way as title), thats position/marks can be accesed from both inner elements and outer elements
  4. access to inner marks of nodes
  5. I want it to be able to be nested

Connectors will serve as I/O ports of system, so they will be used inside a system for internal logic circuit, and outer usage - for using of (sub)system. These subsystems can be nested, it will create complete schema.

I've created native solution using matrix style:

\documentclass[tikz,border=3mm]{standalone}

\usetikzlibrary{fit,positioning,matrix}
\tikzset {
    element/.style={draw=black, fill=yellow, rounded corners},
}

\begin{document}
\begin{tikzpicture}[
        pics/group/.style args={#1#2}{
            code = {
                \node(-main) [matrix of nodes]{
                    \node[minimum height=1cm]{};\\
                    #2; \\
                };
                \coordinate (data-center east) at (-main.west -| -main.east);
                \coordinate[shift={(0,-1cm)}] (aaa) at (-main.north west);
                \coordinate[shift={(0,-1cm)}] (title-coord) at (-main.north);
                \node(-title) at (title-coord) [draw,anchor=south,fill=white] {{\scriptsize{Group:}} #1};
                % just helper points of matrix node coords
                \begin{scope}[radius=2pt,fill=gray]
                    \fill(-main.north west) circle[radius=2pt];
                    \fill(-main.north east) circle[radius=2pt];
                    \fill(-main.north) circle[radius=2pt];
                    \fill(-main.south west) circle[radius=2pt];
                    \fill(-main.south east) circle[radius=2pt];
                \end{scope}
            },
            background code={
                \node[fit=(-main)(-title),draw,dashed,color=gray,fill=red!10] (-ccont) {};
                \draw[draw,fill=blue!75!green!25] (aaa) rectangle (-main.south east);
            }
        }
    ]
    \pic(gmain) {group={Main}{
        \node(b)[element]{b - middle};
        \node(c)[element, left=10pt of b]{c - left};
        \node(a)[element, right=10pt of b]{a - right};
    }};

     \pic(gleft)[left=of gmain-ccont] {group={Left}{
            \node(l){\#};
            \node(ltext)[right=of l]{just random element};
            \node(ltext2)[below=1pt of ltext]{with unknown alignemnt};
            \node(ltext3)[below=1pt of ltext2]{min/max of x/y};
            \node(l2t)[above=0.1cm of l]{\#};
            \node(l3t)[above=0.1cm of l2t]{\#};
            \node(l2)[below=0.1cm of l]{\#};
            \node(l3)[below=0.1cm of l2]{\#};
            \node(l4)[below=0.1cm of l3]{\#};
            \node(l5)[right=0.1cm of l4]{\#};
            \node(l6)[right=0.1cm of l5]{\#};
            \node(l7)[right=0.1cm of l6]{\#};
    }};

    \pic(group_d)[right=of gmain-ccont] {group={Group D - very long name}{
        \node(b)[element]{bb};
        \node(c)[element, left=of b]{ccc - left};
    }};

    \pic(group_below)[below=of gmain-ccont] {group={Below}{
        \node(b)[element]{bb};
        \node(c)[element, left=of b]{ccc - left};
    }};

    \pic[above=of gmain-ccont] {group={Group D}{
        \node(b)[element]{bb};
        \node(c)[element, left=of b]{ccc - left};
    }};

    \path (group_belowb.east) edge[<->] (group_d-ccont.south west);
\end{tikzpicture}


\end{document}

It has three big issues:

  1. If group name is bigger than contents, alignment bugs - I want group contents block to expand
  2. I used matrix, therefore I can't nest these beautiful nodes inside of them - I would like to not use matrix layout at all, just somehow create inner elements of node (it will be done recursively)
  3. can't set opional! - key=value styles for elements - title(background,font,border,...) and block(background, border,...)

And one lesser issue:

  1. Did I create solution with tikz drawing principles in mind? or did I do it with dirty hacks? I know, that nesting of tikzpicture-s goes against tikz principles, so I avoided using that. I still I don't feel, that it is a clean solution and don't know how to make it cleaner.

Here is build screenshoot: enter image description here

Disclaimer: I spent many hours of studying TeX and Tikz library, but couldn't find a better solution for nodes grouping problem.

5

I hope next code is a little bit cleaner but there are some remaining problems.

  1. it uses matrix node to draw blue background rectangle.
  2. Using a matrix of nodes, there's no need for \node ... in each element, just contents.

problems:

  1. Group placement is not completely solved.
  2. No access to inner matrix nodes (still working on it)
  3. Problem with long label names. What do you want to do with them?

The code looks like

\documentclass[tikz,border=3mm]{standalone}
\usetikzlibrary{fit,positioning,matrix,backgrounds}

\begin{document}
\tikzset{element/.style={draw=black, fill=yellow, rounded corners, minimum height=1cm},
         dot/.style={circle, minimum size=4pt, inner sep=0pt, outer sep=0pt, fill=gray},
         pics/group/.style 2 args={
            code = {
              \node(-main)[matrix of nodes, nodes={element}, draw, 
                   fill=blue!75!green!25, column sep=5mm, ampersand replacement=\&]
            {#2\\};
              \node[above=-\pgflinewidth of -main.north,draw, fill=white] (-title) 
                  {{\scriptsize Group:} #1};
              % just helper points of matrix node coords
              \foreach \i in {north west, north, north east}
                 \node[dot, above=1cm of -main.\i] (p-\i) {};
            },
            background code={
                \node[fit=(p-north west)(-main.south east), draw, dashed, 
                    color=gray, fill=red!10] (-ccont) {};
                }
            }
}

\begin{tikzpicture}
\pic(gmain) {group={Main}{c-left \& b-middle \& a-right}};

\pic(gleft)[left=of gmain-ccont] {group={Left}%
      {\begin{tabular}{l}
         \#\#\#\#\#\#\\
         \#  just random element\\
         \#  with unknowm alignement \\ 
         \# min/max of x/y \end{tabular}
      }};

\pic (group_d) [right = of gmain-ccont] {group={Group D - very long name}{ccc-left \& bb}};

\pic (group_below) [below= 2cm of gmain-ccont] {group={Below}{ccc-left \& bb}};

\pic(groupd) [above=of gmain-ccont] {group={Group D}{bb \& ccc-left}};

%\draw[<->] (group_below-main-1-1.east) -- (group_d-ccont.south west);

\end{tikzpicture}
\end{document}

enter image description here

  • Well, exactly what I didn't want to do - matrix Layout. I wanted any layout to be put as "sub-picture" inside group. – kravemir Feb 9 '15 at 16:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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