diff options
Diffstat (limited to 'macros/latex/contrib/familytree/ft-gens.dtx')
-rw-r--r-- | macros/latex/contrib/familytree/ft-gens.dtx | 365 |
1 files changed, 365 insertions, 0 deletions
diff --git a/macros/latex/contrib/familytree/ft-gens.dtx b/macros/latex/contrib/familytree/ft-gens.dtx new file mode 100644 index 0000000000..f179f060ec --- /dev/null +++ b/macros/latex/contrib/familytree/ft-gens.dtx @@ -0,0 +1,365 @@ +% \iffalse +% Copyright 2022 Jiro Senju +% +% This package is free software; you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation; either version 2 of the License, or +% any later version. +% +% This package is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this package. If not, see <http://www.gnu.org/licenses/>. +% \fi +% +% \newcommand{\tOne}{Parent-child Relationship Box or Generations Box} +% \newcommand{\tTwo}{(\texttt{ft-gens.dtx})} +% \section[\tOne{} \tTwo]{\tOne\\\tTwo} +% +% \DescribeMacro{\pcdef} +% \cmd{\pcdef +% \marg{new box name} +% \marg{parent box name} +% \marg{child box name} +% } +% \medskip +% +% Defines a parent-child relationship box. +% Connects the given \meta{parent box} and \meta{child box} by a line, +% and creates a new box \meta{new box name}. +% +% \meta{parent box} is a box who has only one line from an individual +% name to one's child. For example, the box created by |\indvdldef| with +% |\maleline| attribute (and equivalent) is specified. +% Obviously, \meta{child box} is a box who has a line to one's parent. +% For example, the box created by |\indvdldef| with |\biological| or +% |\adopted| is specified as a child mark. +% +% |\pcdef| is a simplified version of |\gensdef|, which is discussed next. +% \bigskip +% +% \noindent +% \DescribeMacro{\gensdef} +% \cmd{\gensdef +% \marg{new box name} +% \marg{parent box name} +% \marg{list of connection-pair} +% } +% +% \begin{tabbing} +% \hspace{4em} \=\kill +% \texttt{connection-pair :=}\\ +% \> \marg{individual box name in the parent box}\\ +% \> \marg{child box name} +% \end{tabbing} +% \medskip +% +% Defines a two-generations box. +% Same to |\pcdef|, \meta{child box} is a box who has only one line to +% the parent, but \meta{parent box} can have multiple lines to one's child. +% It is \meta{connection-pair} that makes it clear which parent connects +% to which child box. +% +% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% \subsection{Example} +% +% \begin{enumerate} +% \item +% |\sblngdef| for daughters, |\pcdef|, and then |\sblngdef| for their +% parent generation. +% \srcfig{fig3Robert1} +% +% \needspace{2\baselineskip} +% \item +% two |\sblngdef|, and then |\gensdef|. The result is essentially same. +% One difference is the space between the siblings which was +% automatically adjusted in previous example. +% \srcfig{fig3Robert2} +% \end{enumerate} +% +% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% \subsection{The order of connecting multiple boxes} +% \label{sec:Lily1} +% +% If we get |\sblngdef| as a tool to align the individual boxes in +% column, then |\pcdef| and |\gensdef| are the tool to align the boxes +% in row. +% When the siblings have their child for each, then there are multiple +% parent-child relationships, so it is better to call it generations box +% rather than parent-child box. +% +% There are two ways to draw such tree. One is to define parent-child +% first and then define the siblings of the parent generation. The other +% is in the reverse order, eg. to define the siblings of the parent +% generation first and then define the parent-child relationship for each. +% +% Let's consider about these two ways. +% +% \begin{enumerate} +% \needspace{2\baselineskip} +% \item +% define two parent-child relationships, and then define the siblings. +% +% \srcfig{fig3Lily1} +% +% \needspace{3\baselineskip} +% \item +% define the sisters, and then define the parent-child for each. +% +% \srcfig{fig3Lily2} +% \end{enumerate} +% +% As you see, by the 1st method the length of two lines to their child +% differs and the positions (in horizontal) of the child generation are +% not equal. That makes the tree uneasy to understand straightforward. +% It is because that the feature of |\sblngdef| to set the line length +% to the longest one didn't work. +% The argument passed to |\sblngdef| were already connected to the child, +% so if |\sblngdef| extended the line it would be much worse result. +% +% On the other hand, by the 2nd method, the argument passed to +% |\sblngdef| were not connected to the child. So it is harmless if +% |\sblngdef| extends the line. +% \smallskip +% +% Even if you took the 1st method, there still exists to make the line +% length equal. +% Using |\indvdldef| feature to adjust the line length, set the length +% of Lily's |\femaleline| (|\matrilineal|) to the one of Petunia's. +% To achieve this, calculate the difference of the name length of these +% sisters and give an optional argument of |\indvdldef|. +% The result should be same to above. +% \medskip +% +% \srcfig{fig3Lily3} +% \medskip +% +% You can get the same result if you use |\nameboxcfg| since it has a +% feature to set the length of a line to child. +% But it is not a good idea to use |\nameboxcfg| every time when you +% |\indvdldef|. The value set by |\nameboxcfg| should be applied wider, +% and it is not supposed to use for a single |\indvdldef|. It is better +% to append an optional argument to |\indvdldef|. +% \smallskip +% +% There is one more option. It is to set the length of Lily's name to Petunia's. +% By this method, the space between Lily's name and the line to child +% becomes wider and the length of lines become equal. +% \medskip +% +% \srcfig{fig3Lily4} +% \medskip +% +% The sequence or the order to define and connect the boxes is important. +% In connecting the boxes, this package considers the size of the +% being connected individual boxes. For example, the sibling box +% considers the height of the +% individual box and makes the boxes to be never overlapped. +% But in connecting a child to the already defined sibling box, this +% feature doesn't work. So the children of the siblings may be +% overlapped. In this case, you need to insert the interval box between +% the siblings manually. +% +% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% \subsectImpl +% +% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% \subsubsection{Generations box --- core} +% +% \iffalse +% \parag{Customization} +% +% \DescribeMacro{\ftgenscfg} +% \NoDescription +% \begin{macrocode} +% \newcommand{\ftgenscfg}[1]{% +% } +% \end{macrocode} +% \fi +% +% \parag{Connection pair} +% +% \DescribeMacro{\ft@getpair} +% Extracts a connection-pair from the given list, +% defines the connection-point in the parent box (the former of the pair) +% as |\ft@cpoint|, and defines the child box name (the latter of the +% pair) as |\ft@kids|. +% \smallskip +% +% \begin{macrocode} +\def\ft@getpair#1#2#3{% connection-pair parent-box-name + \ft@dbgmsg{args #1, #2, #3}% + \@ifundefined{#3#1nameCY}{% + \@ifundefined{#3#1mrrgCY}{% + \xdef\ft@cpoint{#1nameCY}% + }{% + \xdef\ft@cpoint{#3#1mrrgCY}% + }% + }{% + \xdef\ft@cpoint{#3#1nameCY}% + }% + \xdef\ft@kids{#2}% +} +% \end{macrocode} +% +% \parag{Top margin} +% +% \DescribeMacro{\def@calc@xtop} +% +% \begin{macrocode} +\newcommand{\ft@calc@xtop}[4]{% name parent cpoint kids + % top half of kids + \ft@len=\dimexpr\ht\@nameuse{#4} - \@nameuse{#4nameCY}pt\relax\relax% + % top half of parent cpoint + \@tempskipa=\dimexpr\ht\@nameuse{#2} - \@nameuse{#3}pt\relax\relax% + % + \ifdim\ft@len<\@tempskipa% + \ft@len=0pt% + \else% + \advance\ft@len -\@tempskipa% + \fi% + \global#1=\ft@len% +} +% \end{macrocode} +% +% \parag{Bottom margin} +% +% \DescribeMacro{\ft@calc@xbottom} +% +% \begin{macrocode} +\newcommand{\ft@calc@xbottom}[4]{% name parent cpoint kids + % bottom half of kids + \ft@len=\@nameuse{#4nameCY}pt\relax% + % bottom half of parent cpoint + \@tempskipa=\@nameuse{#3}pt\relax% + % + \ifdim\ft@len=\@tempskipa% + \ft@len=0pt% + \global\setlength{\ft@depth}{\dp\@nameuse{#2}}% + \ifdim\ft@depth<\dp\@nameuse{#4}% + \global\setlength{\ft@depth}{\dp\@nameuse{#4}}% + \fi% + \else% + \ifdim\ft@len<\@tempskipa% + \ft@len=0pt% + \global\setlength{\ft@depth}{\dp\@nameuse{#2}}% + \else% + \advance\ft@len -\@tempskipa% + \global\setlength{\ft@depth}{\dp\@nameuse{#4}}% + \fi% + \fi% + \global#1=\ft@len% +} +% \end{macrocode} +% +% \parag{Calculate the box size} +% +% \DescribeMacro{\ft@gens@size} +% +% \begin{macrocode} +\newlength{\ft@xtop} +\newlength{\ft@xbottom} +\newcommand{\ft@gens@size}[2]{% parent-box connect-pair-list + \@tempswatrue% + \ft@width=0pt% + \@for\@temptokena:=#2\do{% + \expandafter\ft@getpair\@temptokena{#1}% + \ft@dbgmsg{\ft@cpoint and \ft@kids}% + \if@tempswa% + \ft@calc@xtop{\ft@xtop}{#1}{\ft@cpoint}{\ft@kids}% + \@tempswafalse% + \fi% + \setlength{\ft@len}{\wd\@nameuse{\ft@kids}}% + \ifdim\ft@width<\ft@len% + \global\ft@width=\ft@len% + \fi% + }% + \ft@calc@xbottom{\ft@xbottom}{#1}{\ft@cpoint}{\ft@kids}% + \ft@dbgmsg{xtop \the\ft@xtop, xbottom \the\ft@xbottom}% + % + \ft@x=\dimexpr\wd\@nameuse{#1}% - \ft@cmarkbox@length\relax% + \ft@dbgmsg{x \the\ft@x}% + \advance\ft@width \ft@x% + \ft@dbgmsg{w \the\ft@width}% + \ft@height=\dimexpr\ht\@nameuse{#1} + \ft@xtop + \ft@xbottom\relax% + \ft@dbgmsg{kids H \the\ht\@nameuse{\ft@kids}}% + \ft@dbgmsg{H \strip@pt\ft@height, D \strip@pt\ft@depth}% +} +% \end{macrocode} +% +% \parag{Layout} +% +% \DescribeMacro{\ft@gens@layout} +% +% \begin{macrocode} +\newcommand{\ft@gens@layout}[3]{% + % box-name parent-box-name {{parent-name} {child-name}, ...} + \ft@newnamebox{#1}{% + \edef\@w{\strip@pt\ft@width}% + \edef\@h{\strip@pt\ft@height}% + \begin{picture}(\@w,\@h)% + \ft@dbgframe{\@w,\@h}% + % + \ft@y=\ft@xbottom% + \ft@dbgplot{0,\strip@pt\ft@y}% + \put(0,\strip@pt\ft@y){\usebox{\@nameuse{#2}}}% + \advance\ft@y \@nameuse{#2nameCY}pt% + \ft@namexdefstrip{#1nameCY}{\ft@y}% + %\ft@namexdefstrip{#1#2nameCY}{\ft@y}% + % + \@for\@temptokena:=#3\do{%% + \expandafter\ft@getpair\@temptokena{#2}% + \ft@dbgmsg{\ft@cpoint and \ft@kids}% + % + \ft@y=\dimexpr\ft@xbottom + \@nameuse{\ft@cpoint}pt\relax% + \ft@dbgmsg{parent cpoint \the\ft@y}% + \ft@dbgplot{\strip@pt\ft@x,\strip@pt\ft@y}% + % + \advance\ft@y -\@nameuse{\ft@kids nameCY}pt% + \ft@dbgmsg{final child y \the\ft@y}% + \put(\strip@pt\ft@x,\strip@pt\ft@y){% + \usebox{\@nameuse{\ft@kids}}}% + \ft@namexdefstrip{#1\ft@kids Y}{\ft@y}% + }% + \end{picture}% + }% +} +% \end{macrocode} +% +% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% \subsubsection{Generations box --- interface} +% +% \DescribeMacro{\ftgensdef} +% +% \begin{macrocode} +\newcommand{\ftgensdef}[3]{% + % box-name parent-box-name {{parent-name} {child-name}, ...} + % + % calculate the size of the new box + \ft@gens@size{#2}{#3}% + % + % draw them all + \ft@gens@layout{#1}{#2}{#3}% + % + \@ifundefined{#2hascmark}{}{% + \ft@namexdef{#1hascmark}{\@nameuse{#2hascmark}}% + }% + \ft@nameboxsz{#1}{\ft@height}{\ft@depth}% +} +\ft@alias{gensdef} +% \end{macrocode} +% +% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% \subsubsection{Parent-child box --- interface} +% +% \DescribeMacro{\ftpcdef} +% +% \begin{macrocode} +\newcommand{\ftpcdef}[3]{% box-name parent-box-name child-box-name + \ftgensdef{#1}{#2}{{#2}{#3}}% +} +\ft@alias{pcdef} +% \end{macrocode} |