[Tex/LaTex] Connecting nodes with brace in TikZ

nodestikz-arrowstikz-pgf

How would be possible to put a brace instead of a "line" connecting nodes and add some text above it with TikZ?

enter image description here

Best Answer

An automatic solution:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc,shapes.arrows,decorations.pathreplacing,shadows}

% list of keys
\pgfkeys{/tikz/.cd,
  arrow color/.store in=\arrowcol,
  arrow color=green!80!blue,
  items distance/.store in=\itemdistance,
  items distance=3cm,
  border color/.store in=\bordercol,
  border color=green!80!black,
  fill color/.store in=\fillcol,
  fill color=green!80!lime!20,
  brace color/.store in=\bracecol,
  brace color=green!80!blue,
  brace distance/.store in=\bracedistance,
  brace distance=5pt,
}

% list of styles
\tikzset{my arrow/.style={
    single arrow, draw, minimum height=0.5cm,
    minimum width=0.05cm,
    single arrow head extend=0.1cm
  },
  module/.style={
    rounded corners,
    draw=\bordercol,
    fill=\fillcol,
    minimum height=1cm,
    minimum width=1.5cm,
    general shadow={shadow yshift=-.4ex,opacity=.4, fill=black!50, every shadow}, 
  },
  brace/.style={
    decoration={brace,raise=\bracedistance,amplitude=0.75em},
    decorate,
    draw=\bracecol,
    very thick,    
  }
}

% code able to reproduce arrows between two modules     
\newcommand{\guparrow}{
node[my arrow,top color=\arrowcol!10,bottom color=\arrowcol,midway] {}
}

% braceddiagram:
% #1 options <optional argument>,
% #2 list of items <mandatory>,
% #3 brace comment <mandatory> 
\newcommand{\braceddiagram}[3][]{
  \begin{tikzpicture}[#1]% here we can pass the options for customization
     % counting all the items to be displayed
     \foreach \items [count=\xi] in {#2}{\global\let\maxnumitem\xi}

     % foreach item in the list we are going to compute the distance it should 
     % be placed;
     % then we put the item in a node with the module style: it also gets a 
     % name in the form <module><num-module>
     \foreach \items [count=\xi] in {#2}{%
       \path let 
         \n1={0+\xi*\itemdistance} in
         node[module] (module\xi) at +(\n1,0) {\items};
     }
     % when all items are located we can put the arrows in between: 
     % for this we draw an imaginary path and we put the arrow between nodes; 
     % the path starts from the module on the left and ends in the 
     % subsequent module: we should compute analytically the start and end modules
     \foreach \items [count=\xi] in {#2}{%
       \pgfmathtruncatemacro{\xj}{mod(\xi, \maxnumitem) + 1)}
       \ifnum\xi<\maxnumitem % to not have a path starting from the last module 
                             % directed to the first one
         \path (module\xj) -- (module\xi) \guparrow;
       \fi
     }

     % at the end we draw the brace with the comment
     \draw[brace] (module1.north west)--(module\maxnumitem.north east)
      node[above=3*\bracedistance, midway]{#3};

  \end{tikzpicture}
}


\begin{document}

\braceddiagram[brace distance=4pt]{Bla, Bla, Bla}{Some comment}

\vspace{1cm}

\tikzset{my style for the diagram/.style={
    brace distance=6pt,
    brace color=violet!60!magenta,
    fill color=violet!60!magenta!30,
    border color=violet!60!magenta,
    arrow color=violet!60!magenta,
  }
}

\braceddiagram[my style for the diagram]{Bla, Bla, Bla, Bla}{Some other comment}

\end{document}

The result:

enter image description here

Some notes on the code

The basic command to be used is:

\braceddiagram[<options>]{<list of items>}{<comment above brace>}

In the <list of items> one should insert a comma separated list: each of them will be placed in an horizontal fashion and the distance between two of them is characterized by the key items distance (initial value 3cm). Beware: too many items won't probably fit the page, so one can either reduce the distance of the items or scale the diagram.

Scaling the diagram consists of introducing the standard two options scale=<factor> and transform shape. For example:

\braceddiagram[scale=0.75,transform shape]{Bla, Bla, Bla, Bla}{Some other comment}

In the <options> argument, optional, it is possible to introduce usual TikZ options (as did before) as well as the specific keys of the diagram. When one needs to customize several keys, it is better to create a new style:

\tikzset{my style for the diagram/.style={
    brace distance=6pt,
    brace color=violet!60!magenta,
    fill color=violet!60!magenta!30,
    border color=violet!60!magenta,
    arrow color=violet!60!magenta,
  }
}

to be passed to the diagram:

\braceddiagram[my style for the diagram,thick,scale=0.75,transform shape]{Bla, Bla, Bla, Bla}{Some other comment}