% Copyright (c) 2015-2019 Robert Ryszard Paciorek % % MIT License % % Permission is hereby granted, free of charge, to any person obtaining a copy % of this software and associated documentation files (the "Software"), to deal % in the Software without restriction, including without limitation the rights % to use, copy, modify, merge, publish, distribute, sublicense, and/or sell % copies of the Software, and to permit persons to whom the Software is % furnished to do so, subject to the following conditions: % % The above copyright notice and this permission notice shall be included in all % copies or substantial portions of the Software. % % THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR % IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, % FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE % AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER % LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, % OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE % SOFTWARE. % Version 1.0 (2019-05-13): first public release \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{vtable} \RequirePackage{array,varwidth} \RequirePackage{dashrule,graphicx} % for I type \RequirePackage{xparse,etoolbox,calc,forloop,alphalph} \newlength {\vtable@RowHeight} % current height of row (can be increase in next cells) \newlength {\vtable@RowInitHeight} % init height of row (loaded from aux file) \newlength {\vtable@RowForceHeight} % enforced value of row height \newlength {\vtable@RowTmpHeight} \newcounter{vtable@CurrRow} % current row number (file global value) \newcounter{vtable@CurrColumn} % current column number (reset on each new row) \newcounter{vtable@State} % set to 1 when finish / start new row \newcounter{vtable@LastRow} % set to non zero on last row of multirow cell in \vtable@PreRow, clear in \vtable@PostRow \newcounter{vtable@RowIter} % temporary counter used in \vtable@PostRow \newsavebox{\vtable@CellBox} \newsavebox{\vtable@CellVBox} \setcounter{vtable@State}{1} \newcommand{\vtable@PreRow}{% \stepcounter{vtable@CurrRow}% \setcounter{vtable@CurrColumn}{1}% \setcounter{vtable@State}{0}% \typeout{BEGIN ROW : \the\value{vtable@CurrRow}}% \global\vtable@RowHeight=0pt% \global\vtable@RowForceHeight=0pt% \ifcsname tabRowHeight@\AlphAlph{\value{vtable@CurrRow}}\endcsname% \global\vtable@RowInitHeight=\csname tabRowHeight@\AlphAlph{\value{vtable@CurrRow}}\endcsname% \else% \global\vtable@RowInitHeight=0pt% \fi% } \newcommand{\vtable@PostRow}{ \typeout{ do post row stuff } \ifdim\vtable@RowForceHeight=0pt\else\vtable@RowHeight=\vtable@RowForceHeight\fi% \csdimgdef{tabRowHeight@\AlphAlph{\value{vtable@CurrRow}}}{\vtable@RowHeight}% \immediate\write\@auxout{% \string\newdimen\string\tabRowHeight@\AlphAlph{\value{vtable@CurrRow}}% \string\global\string\tabRowHeight@\AlphAlph{\value{vtable@CurrRow}}=\the\vtable@RowHeight% }% } % START TABLE CELL % \vtable@PreCell{max width}{min width}{hmode}{col num}{vmode} % hmode = l (left) c (center) r (right) j (justify) % vmode = t (top) m (middle) b (bottom) \DeclareDocumentCommand{\vtable@PreCell}{m m m m m}{% % if starting first cell in do pre row stuff \ifnumcomp{\value{vtable@State}}{=}{1}{ \vtable@PreRow }{}% \typeout{CELL(\the\value{vtable@CurrRow},\the\value{vtable@CurrColumn}):} % start "varwidth" box in "lrbox" enviroment \begin{lrbox}{\vtable@CellBox}\begin{varwidth}[b]{#1}% % \\ will be always \nextRow \let\\\nextRow% \newcommand{\nextRow}{\typeout{ finish row}\setcounter{vtable@State}{1}\tabularnewline} % \lb can be used for line break \let\lb\linebreak% % if provide minimal width \ifstrequal{#2}{}{}{% % add space (with this width) in hidden row \settototalheight{\vtable@RowTmpHeight}{A}\hspace*{#2}\vspace{-\vtable@RowTmpHeight}\linebreak{}% }% % set ragged of varwidth content and vertical space before and after varwidth \ifstrequal{#3}{l}{ \raggedright \gdef\vtableCell@HPre{0} \gdef\vtableCell@HPost{1}}{% \ifstrequal{#3}{c}{ \centering \gdef\vtableCell@HPre{1} \gdef\vtableCell@HPost{1}}{% \ifstrequal{#3}{r}{ \raggedleft \gdef\vtableCell@HPre{1} \gdef\vtableCell@HPost{0}}{% \ifstrequal{#3}{j}{ \gdef\vtableCell@HPre{0} \gdef\vtableCell@HPost{1}}{% }}}}% \gdef\vtable@CellVMode{#5} % % if this is multirow cell \ifcsname tabMultirowFirst@\the\value{vtable@CurrColumn}\endcsname% % if it's last row of multirow \typeout{ in multi row mode, end at \csname tabMultirowLast@\the\value{vtable@CurrColumn}\endcsname row } \ifnumcomp{\value{vtable@CurrRow}}{=}{\csname tabMultirowLast@\the\value{vtable@CurrColumn}\endcsname}{% \typeout{ last row of multirow cell} \setcounter{vtable@LastRow}{\csname tabMultirowLast@\the\value{vtable@CurrColumn}\endcsname} % print content in current cell and forgot it \csname tabMultirowText@\the\value{vtable@CurrColumn}\endcsname% \csundef{tabMultirowText@\the\value{vtable@CurrColumn}}% }{}% \csnumgdef{vtable@ColSpan@\the\value{vtable@CurrColumn}}{\csname tabMultirowColSpan@\the\value{vtable@CurrColumn}\endcsname}% \else % set colspan value for tablePostCell macro \csnumgdef{vtable@ColSpan@\the\value{vtable@CurrColumn}}{#4} \fi% \typeout{ colspan: \csname vtable@ColSpan@\the\value{vtable@CurrColumn}\endcsname } } % FINISH TABLE CELL \DeclareDocumentCommand{\vtable@PostCell}{}{% \@finalstrut\@arstrutbox\end{varwidth}\end{lrbox}% % get height of current cell \settototalheight{\vtable@RowTmpHeight}{\usebox{\vtable@CellBox}}% \dimdef{\multirowHeight}{0pt}% % % if it's last row of multirow \ifnumcomp{\value{vtable@LastRow}}{=}{0}{}{% % calculate \multirowHeight \forloop{vtable@RowIter}{\csname tabMultirowFirst@\the\value{vtable@CurrColumn}\endcsname}{\value{vtable@RowIter} < \value{vtable@LastRow}}{% \dimdef{\multirowHeight}{\multirowHeight + \csname tabRowHeight@\AlphAlph{\value{vtable@RowIter}}\endcsname + 5pt}% TODO }% % remove declare of multirow \csundef{tabMultirowFirst@\the\value{vtable@CurrColumn}}% \csundef{tabMultirowLast@\the\value{vtable@CurrColumn}}% \csundef{tabMultirowForceHeight@\the\value{vtable@CurrColumn}}% \setcounter{vtable@LastRow}{0}% }% % % calculate max height of cell in current row \setlength{\vtable@RowHeight}{\maxof{\vtable@RowHeight}{\vtable@RowTmpHeight - \multirowHeight}}% % this must be global \global\vtable@RowHeight=\vtable@RowHeight% % calculate height of placeholders in current run \typeout{ max(\the\vtable@RowHeight, \the\vtable@RowInitHeight) + \multirowHeight{} - \the\vtable@RowTmpHeight}% \setlength{\vtable@RowTmpHeight}{\maxof{\vtable@RowHeight}{\vtable@RowInitHeight} + \multirowHeight - \vtable@RowTmpHeight}% % if vertical centering we need 1/2 \vtable@RowTmpHeight \ifdefstring{\vtable@CellVMode}{m}{\setlength{\vtable@RowTmpHeight}{0.5\vtable@RowTmpHeight}}{}% % % prepare vbox with (erlier prepared) varwidth and vertical placeholder \begin{lrbox}{\vtable@CellVBox}\vbox{% % in b and c (but not t) mode add vspce before content \ifdefstring{\vtable@CellVMode}{t}{}{\vspace*{\vtable@RowTmpHeight}}\vspace*{4pt}% TODO \hbox{\usebox{\vtable@CellBox}}% % in t and c (but not b) mode add vspce after content, \vspace*{0pt} is important \ifdefstring{\vtable@CellVMode}{b}{\vspace*{0pt}}{\vspace*{\vtable@RowTmpHeight}}\vspace*{-4pt}% TODO }\end{lrbox}% % if this is multirow cell, update saved height of content \ifdim\multirowHeight=0pt\else \ht\vtable@CellVBox=0pt \dp\vtable@CellVBox=0pt \fi % % filling space on left (varwidth alignment) \hspace{\stretch{\vtableCell@HPre}}% % print prepared vbox \usebox{\vtable@CellVBox} % filling space on right (varwidth alignment) \hspace{\stretch{\vtableCell@HPost}}% % % increase column counter \addtocounter{vtable@CurrColumn}{\csname vtable@ColSpan@\the\value{vtable@CurrColumn}\endcsname} % if finishing last cell in row do post row stuff \ifnumcomp{\value{vtable@State}}{=}{1}{ \vtable@PostRow }{}% } % we need j type for using as base column in Z-type, this is placeholder \newcolumntype{j}{l} % Z{max width}{min width}{hmode}{col num}{vmode}{rown num} % hmode = l (left) c (center) r (right) j (justify) % vmode = t (top) m (middle) b (bottom) % use hmode as base columnt type for correct working in multicolumn \newcolumntype{Z}[6]{>{\vtable@PreCell{#1}{#2}{#3}{#4}{#5}}#3<{\vtable@PostCell}} \newcolumntype{L}[3]{Z{#1}{#2}{l}{1}{#3}{1}} \newcolumntype{C}[3]{Z{#1}{#2}{c}{1}{#3}{1}} \newcolumntype{R}[3]{Z{#1}{#2}{r}{1}{#3}{1}} \newcolumntype{J}[3]{Z{#1}{#2}{j}{1}{#3}{1}} % force current row height \newcommand{\forceRowHeight}[1]{\global\vtable@RowForceHeight=#1} % \tableFormatedCell{max width}[min width]{hmode}{vmode} % hmode = l (left) c (center) r (right) j (justify) % vmode = t (top) m (middle) b (bottom) \DeclareDocumentCommand{\tableFormatedCell}{m O{} m m}{ \@finalstrut\@arstrutbox\end{varwidth}\end{lrbox}% \vtable@PreCell{#1}{#2}{#3}{1}{#4}% } % \setMultiColumn{col num}{max width}{min width}{hmode}{vmode}{left sep}{right sep}{text} % hmode = l (left) c (center) r (right) j (justify) % vmode = t (top) m (middle) b (bottom) \newcommand{\setMultiColumn}[8]{\multicolumn{#1}{#6Z{#2}{#3}{#4}{#1}{#5}{1}#7}{#8}} % \setMultiRow{col num}[minimal height]{text} \DeclareDocumentCommand{\setMultiRow}{m O{0pt} m O{1}}{% \typeout{multi row: #1 #2 #4 in column \the\value{vtable@CurrColumn} row \the\value{vtable@CurrRow}}% \csnumgdef{tabMultirowFirst@\the\value{vtable@CurrColumn}}{\value{vtable@CurrRow}}% \csnumgdef{tabMultirowLast@\the\value{vtable@CurrColumn}}{\value{vtable@CurrRow} + #1 - 1}% \csdimgdef{tabMultirowForceHeight@\the\value{vtable@CurrColumn}}{#2}% \csnumgdef{tabMultirowColSpan@\the\value{vtable@CurrColumn}}{#4}% \csnumgdef{vtable@ColSpan@\the\value{vtable@CurrColumn}}{#4}% \csgdef{tabMultirowText@\the\value{vtable@CurrColumn}}{#3}% } % \setMultiColRow{col num}{row num}{max width}{min width}{hmode}{vmode}{left sep}{right sep}{text} % hmode = l (left) c (center) r (right) j (justify) % vmode = t (top) m (middle) b (bottom) \newcommand{\setMultiColRow}[9]{ \multicolumn{#1}{#7Z{#3}{#4}{#5}{#1}{#6}{#2}#8}{% \ifstrequal{#9}{}{}{\setMultiRow{#2}{#9}[#1]}% } } % I-type column put vertical frame line using hdashrule \newcolumntype{I}[3]{!{% \setlength{\vtable@RowTmpHeight}{\vtable@RowInitHeight + 5pt}% TODO \begin{lrbox}{\vtable@CellVBox}% \rotatebox{90}{\hspace*{-4pt}#1\hdashrule{\vtable@RowTmpHeight}{#2}{#3}}% TODO \end{lrbox}% \ht\vtable@CellVBox=0pt% \dp\vtable@CellVBox=0pt% \usebox{\vtable@CellVBox}% }}