[Tex/LaTex] Access mdframed node coordinates with TikZ

mdframedtikz-pgf

Is it possible to get a (breakable) frame like this with mdframed? Or as a more general question. Can one access the coordinates of the frame that is drawn with TikZ?

desired result

With a pagebreak in it:
page 1
page 2

I build this example with the following code.

\documentclass{scrartcl}

\usepackage{environ}

\usepackage{tikz}
\usetikzlibrary{calc}

\NewEnviron{excursustikz}{%
   \par
   \vspace{0.5\baselineskip}%
   \noindent
   \begin{tikzpicture}%
      \node (body) [%
         text width=\textwidth-4pt-2ex,
         inner sep=0pt,
      ] {\BODY};
      \draw [
         line width=4pt,
         blue,
         line cap=round,
         rounded corners=2ex,
         ->
      ] ($(body.south west)+(5em,-2ex)$) -| ($(body.west)+(-2ex,0)$) |- %
        ($(body.north)+(-12em,2ex)$) .. controls +(0:10em) and +(190:5em) .. ++(20em,2ex);
      \node [blue,fill=white] at ($(body.north west)+(3.5em,2.36ex)$) {\sffamily\bfseries Excursus};
   \end{tikzpicture}%^
   \par
   \vspace{0.25\baselineskip}%
}

\usepackage{lipsum}

\begin{document}
\lipsum[1]
\begin{excursustikz}
   \lipsum[2]
\end{excursustikz}
\lipsum[3]
\end{document}

The node that I imagine to use is body, but I’m not sure if mdframed uses a node internally. Furthermore one has to care about a page spanning frame. In that case the line at the right should be broken, as if you cut the path in two parts.

Best Answer

Update: To let mdframed know the right dimensions of the frame to calculate the page breaks we must give them as invisible margins (middleline) and adjust everything according to these. See the updated code below.


Marco’s comment lead me to the relevant parts in the manual. Here is my code

\documentclass{scrartcl}

\usepackage{tikz}
   \usetikzlibrary{calc,arrows}
\usepackage{etoolbox}
\usepackage[framemethod=tikz]{mdframed}

\tikzstyle{excursus arrow}=[%
   line width=4pt,
   draw=blue,
   rounded corners=2ex
]
\tikzstyle{excursus head}=[%
   fill=white,
   font={\bfseries\sffamily},
   text=blue,
   anchor=base,
]

\makeatletter
\newcommand{\drawexcursusarrow}{%
   \patchcmd{\mdf@putbox@single}{\mdfcreateextratikz}{
      \path let \p1=(P), \p2=(O) in (\x2,\y1) coordinate (Q);
      \path let \p1=(Q), \p2=(O) in (\x1,{(\y1-\y2)/2}) coordinate (M);
      \path [excursus arrow, round cap->]
         ($(O)+(5em,0ex)$) -| (M) |- %
         ($(Q)+(6em,0ex)$) .. controls +(0:16em) and +(185:6em) .. %
         ++(23em,2ex);
      \node [excursus head] at ($(Q)+(4.5em,-2pt)$) {Excursus};
   }{}{}%
   \patchcmd{\mdf@putbox@first}{\mdfcreateextratikz}{
      \path let \p1=(P), \p2=(O) in (\x2,\y1) coordinate (Q);
      \path [excursus arrow,->]
         (O) |- %
         ($(Q)+(6em,0ex)$) .. controls +(0:16em) and +(185:6em) .. %
         ++(23em,2ex);
      \node [excursus head] at ($(Q)+(4.5em,-2pt)$) {Excursus};
   }{}{}%
   \patchcmd{\mdf@putbox@second}{\mdfcreateextratikz}{
      \path let \p1=(P), \p2=(O) in (\x2,\y1) coordinate (Q);
      \path [excursus arrow,round cap-]
         ($(O)+(5em,0ex)$) -| (Q);
   }{}{}%
   \patchcmd{\mdf@putbox@middle}{\mdfcreateextratikz}{
      \path let \p1=(P), \p2=(O) in (\x2,\y1) coordinate (Q);
      \path [excursus arrow]
         (O) -- (Q);
   }{}{}%
}
\makeatother
\newmdenv[%
   middlelinewidth=24pt,
   middlelinecolor=green,
   rightline=false,
   innertopmargin=0ex,
   innerbottommargin=0ex,
   innerrightmargin=2pt,
   innerleftmargin=0ex,
   leftmargin=-11pt,
   skipabove=12pt,
   skipbelow=-1pt,%=12-24/2-2/2
   settings=\drawexcursusarrow,
]{excursus}

\usepackage{lipsum}

\begin{document}
\lipsum[3]
\begin{excursus}
   \lipsum[1]
\end{excursus}
\lipsum[3]
\end{document}

I used \pathcmd to differentiate between the broken and unbroken frames. Furthermore I draw the arrow with \drawexcursusarrow and apply this via the settings key only to the {excursus} environment, so my changes don’t effect the other frames.


Bonus question

is it possible to let mdframed ignore the descenders of the last line in the frame? Otherwise the (optical) innerbottomsep depends on these.

Related Question