15

I would like to delay the output of some parts of a breakable tcolorbox (I want to use them in a "notes column" and try to implement a way to split them if they get too long for a page). Has someone an idea how I could e.g. store the four parts of the following tcolorbox and then output them on a 2x2 grid on one page in the order 3,2,1,4?

\documentclass[]{article}

\usepackage[many]{tcolorbox}
\usepackage{lipsum}

\begin{document}

\begin{tcolorbox}[
title=breakable,
watermark text=\arabic{tcbbreakpart},
enhanced jigsaw,
text width=4cm,
breakable,
break at=5cm/5cm/5cm/8cm]
\lipsum[1]
\end{tcolorbox}    
\end{document}
2
  • 2
    (+1) I think that is a good question. I had the same thing in mind for quite a long time. I even have a name for a library providing that feature (the magazine library), but I had no time yet to follow that thought. Maybe, someone has a clever idea to answer this question more easily. Jun 8, 2015 at 13:16
  • I've wrote something similar, but not really the same, only for two parts, but it uses breakable tcolorboxes: the jumplines package. I thought about extending it, but I had no time so far.
    – user31729
    Jun 8, 2015 at 20:04

2 Answers 2

8

NEW ANSWER (needs tcolorbox version 3.70 (2015/07/16) or newer:

Starting from version 3.70 (2015/07/16), the tcolorbox package provides a new magazine library. The main purpose of this library is to store a tcolorbox into an array of box registers for later usage.

The store to box array option stores all parts of a break sequence of a tcolorbox into a box array. This is a sequence of box registers which can be inserted later with \useboxarray{1}, \useboxarray{2}, etc.

\documentclass{article}
\usepackage[many,magazine]{tcolorbox}
\usepackage{lipsum}

\begin{document}

\begin{tcolorbox}[
  title=breakable,
  height fixed for=first and middle,
  watermark text=\arabic{tcbbreakpart},
  enhanced jigsaw,
  text width=4cm,
  breakable,
  break at=5cm/5cm/5cm/8cm,
  reset and store to box array
  ]
\lipsum[1]
\end{tcolorbox}

\tabcolsep=1pt\relax
\begin{tabular}{cc}
\useboxarray{3} & \useboxarray{2}\\
\useboxarray{1} & \useboxarray{4}
\end{tabular}

\end{document}

enter image description here

OLD ANSWER (useful for tcolorbox versions before 3.70):

This was the base for the magazine library.

The core of the solution is to capture the broken box parts into boxes automatically. Therefore, a series of boxes is needed, called a box set in the following. A default box set is created by the following code, but there could be more than one box set.

The capture operation is done using the new store to box set options. All box parts are appended to an existing box set. To clear the set from possible previous storage operation reset box set is used.

After saving, the boxes from the box set can be addressed as \tcbuseboxset{1}, \tcbuseboxset{2}, etc.

\documentclass{article}
\usepackage[many]{tcolorbox}
\usepackage{lipsum}

\makeatletter

\def\newtcbboxset#1{%
  \global\csdef{tcb@boxset@#1@size}{0}%
  \global\csdef{tcb@boxset@#1@allocated}{0}%
}

\newtcbboxset{default}

\def\tcbstoretoboxset#1{%
  \tcbletboxsetsize[#1]\tcb@boxset@size%
  \numdef\tcb@boxset@size{\tcb@boxset@size+1}%
  \global\cslet{tcb@boxset@#1@size}{\tcb@boxset@size}%
  \letcs\tcb@boxset@allocated{tcb@boxset@#1@allocated}%
  \ifnum\tcb@boxset@allocated<\tcb@boxset@size\relax%
    \newbox\tcb@boxset@box\csxdef{tcb@boxset@#1@\tcb@boxset@size @box}{\the\tcb@boxset@box}%
    \global\cslet{tcb@boxset@#1@allocated}{\tcb@boxset@size}%
  \else%
    \letcs\tcb@boxset@box{tcb@boxset@#1@\tcb@boxset@size @box}%
  \fi%
  \edef\reserved@a{%
    \endgroup
    \global\setbox\tcb@boxset@box\hbox{%
      \begingroup\aftergroup}%
        \def\noexpand\@currenvir{\@currenvir}%
        \def\noexpand\@currenvline{\on@line}}%
  \reserved@a
    \@endpefalse
    \color@setgroup
      \ignorespaces}

\def\endtcbstoretoboxset{\unskip\color@endgroup}

\def\tcb@storetoboxset@begin#1#2[#3]{\begin{tcbstoretoboxset}{#1}}
\def\tcb@storetoboxset@end{\end{tcbstoretoboxset}}

\tcbset{
  store to box set/.code={%
    \def\kvtcb@float{S}\def\tcb@float@env@begin{\tcb@storetoboxset@begin{#1}}\def\tcb@float@env@end{\tcb@storetoboxset@end}},
  store to box set/.default=default,
  reset box set/.code={\tcbresetboxset[#1]},
  reset box set/.default=default,
  do not store to box set/.style={nofloat},
}

\newrobustcmd*{\tcbletboxsetsize}[2][default]{%
  \letcs#2{tcb@boxset@#1@size}%
  \ifdef{#2}{}{%
    \tcb@error{undefined box set '#1'}%
    {You have to say \string\newtcbboxset{#1}, before '#1' can be used as box set.}%
  }%
}

\newrobustcmd*{\tcbresetboxset}[1][default]{%
  \tcbletboxsetsize[#1]\tcb@boxset@size%
  \global\csdef{tcb@boxset@#1@size}{0}%
}

\newrobustcmd*{\tcbuseboxset}[2][default]{%
  \tcbletboxsetsize[#1]\tcb@boxset@size%
  \ifnum\numexpr#2>0\relax%
    \ifnum\numexpr#2>\tcb@boxset@size\relax%
    \else%
      \global\letcs\tcb@boxset@box{tcb@boxset@#1@#2@box}%
      \usebox{\tcb@boxset@box}%
    \fi%
  \fi%
}

\makeatother


\begin{document}

\begin{tcolorbox}[
  title=breakable,
  height fixed for=first and middle,
  watermark text=\arabic{tcbbreakpart},
  enhanced jigsaw,
  text width=4cm,
  breakable,
  break at=5cm/5cm/5cm/8cm,
  reset box set,
  store to box set,
  ]
\lipsum[1]
\end{tcolorbox}

\tabcolsep=1pt\relax
\begin{tabular}{cc}
\tcbuseboxset{3} & \tcbuseboxset{2}\\
\tcbuseboxset{1} & \tcbuseboxset{4}
\end{tabular}

\end{document}

Note that the boxes are saved with the \global modifier and will survive the current TeX group. This could cause memory problems if used extensively.

The current number of boxes stored inside the box set can be questioned by \tcbletboxsetsize{\mysize}. Afterwards, \mysize contains the current size.

9
  • It is pretty hard competing with the package developer, but I'll take credit for egging you on to provide an elegant solution. Jul 10, 2015 at 14:45
  • @StevenB.Segletes Sorry for that ;-) I was aware that I should find a hook to answer this question. As I wrote to Ulrike, I wanted to have such a thing for a long time. Funnily, I found the core of the the solution two or three days ago, but had no time to elaborate it properly for an answer. Your answer pushed me into stealing some time to do it ;-) Jul 11, 2015 at 9:03
  • Yes, your comment to the OP on 8 June indicated you had something in mind. It's a nice feature to add. Best wishes. Jul 11, 2015 at 13:06
  • This works very fine (and also if one doesn't break the box manually). Jul 12, 2015 at 21:35
  • Could the unbroken box be stored in the same run too (to get the size)? Jul 13, 2015 at 8:00
7

Here, I set the broken \tcolorbox into a \vbox. THat has the effect of leaving it as one vertical box, but it places the sectioning numbers properly (if you use an \hbox, you only get a large page "1"). Then, I \clipbox the saved page at regular intervals.

I first clipped 3pt off the bottom and 1pt off the top of the saved \vbox (i.e., blank space, maybe a tcolorbox setting). Then, the vertical clip interval was 5pt less than the nominal 5cm height (I don't know why) and, being a \vbox, I had to trim from the right hand margin as well, in this case, 32pt less than \textwidth-4cm, to allow for the blank border on the sides.

I used stackengine to save the clips into boxes, but a simple \savebox \usebox would be equally suitable.

\documentclass[]{article}
\usepackage[many]{tcolorbox}
\usepackage{trimclip,stackengine}
\usepackage{lipsum}
\newsavebox\breakbox
\newlength\cliptop
\newlength\clipbot
\begin{document}

\setbox0=\vbox{%
\begin{tcolorbox}[
title=breakable,
watermark text=\arabic{tcbbreakpart},
enhanced jigsaw,
text width=4cm,
breakable,
break at=5cm/5cm/5cm/8cm]
\lipsum[1]
\end{tcolorbox}%
}
\savebox\breakbox{\clipbox{0pt 3pt 0pt 1pt}{\box0}}
\edef\dellength{\dimexpr5cm-5pt}
\def\rightclip{\dimexpr\textwidth-4cm-32pt}
%#1
\setlength\cliptop{0pt}
\setlength\clipbot{\dimexpr\ht\breakbox-\dellength\relax}
\savestack{\BoxA}{\clipbox{0pt {\clipbot} {\rightclip} {\cliptop}}{\usebox{\breakbox}}}
%#2
\addtolength\cliptop{\dellength}
\addtolength\clipbot{-\dellength}
\savestack{\BoxB}{\clipbox{0pt {\clipbot} {\rightclip} {\cliptop}}{\usebox{\breakbox}}}
%#3
\addtolength\cliptop{\dellength}
\addtolength\clipbot{-\dellength}
\savestack{\BoxC}{\clipbox{0pt {\clipbot} {\rightclip} {\cliptop}}{\usebox{\breakbox}}}
%#4
\addtolength\cliptop{\dellength}
\addtolength\clipbot{-\dellength}
\ifdim\clipbot<0pt\relax\setlength\clipbot{0pt}\fi
\savestack{\BoxD}{\clipbox{0pt {\clipbot} {\rightclip} {\cliptop}}{\usebox{\breakbox}}}
%
\tabcolsep=1pt\relax
\begin{tabular}{cc}
\BoxC & \BoxB\\
\BoxA & \BoxD
\end{tabular}
\end{document}

enter image description here

0

You must log in to answer this question.

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