\: Introduction to Alignment. This module allows to make alignment of
tables typesetting similar to how \TeX\ does so but different.
>
> module Graphics.DVI.Alignment (
>
> DataNode(..), NoAlignNode(..), UnsetBoxNode(..), hAlign
> ) where {
> import Control.Applicative;
> import Control.Monad;
> import Control.Monad.Trans.Writer;
> import Data.List;
> import Data.Maybe;
> import Data.Monoid;
> import Data.Typeable;
> import Graphics.DVI;
> bool :: x -> x -> Bool -> x;
> bool x _ False = x;
> bool _ x True = x;
\: Alignment Nodes. Data nodes: Used in a template. It contains a column
number, and a function to convert a distance to a glue value. The distance
to be converted shall be the largest natural width (height for vertical
alignments) of the box in all records; the glue value will be used to
determine the actual width of this field. The data node is then replaced
by a horizontal box packaging the contents of this field.
> data DataNode = DataNode Int (Dimen -> Glue) deriving Typeable;
> instance NodeClass DataNode where {
> showNode (DataNode x _) = "Data " ++ show x ++ ";";
> };
No-align nodes: If this is the first node in a field data, the rest of its
contents are copied to output without using the template.
> data NoAlignNode = NoAlignNode deriving Typeable;
> instance NodeClass NoAlignNode where {
> showNode NoAlignNode = "NoAlign;";
> };
Unset box nodes: The width, height, and depth of a box might not be known
at first due to the rows varying, so the template can contain unset box
nodes, which will be packaged after the data nodes are replaced by the
boxes, allowing width and height and depth to be calculated.
> data UnsetBoxNode = UnsetBoxNode (Dimen -> Dimen) [Node]
> deriving Typeable;
> instance NodeClass UnsetBoxNode where {
> showNode (UnsetBoxNode _ x) = "UnsetBox [" ++ (x >>= showNode)
> ++ "];";
> traverseBox f (UnsetBoxNode z n) = (Node . UnsetBoxNode z <$>
> sequence (traverseBox f <$> n)) >>= f;
> };
\: Alignment.
> hAlign :: Dimen -> [Node] -> [[[Node]]] -> [Node];
> hAlign d n f = dat' where {
> f' = nna <$> f;
> fna = f' >>= either (const []) return;
> nna [x : y] | isJust (castNode x :: Maybe NoAlignNode) = Left y;
> nna x = Right x;
> awd = map (wd1 . hPack id) <$> fna;
> wd1 (x, _, _) = nodeWidth x;
> mwd = maximum <$> transpose awd;
> tg = foldl addGlue (fixedGlue 0) $ execWriter (mapM (travFunc tg') n);
> tg' z@(DataNode i x) = writer (Node z, [x (mwd !! i)]);
> gs = calcGlueSet d tg;
> dat = f' >>= either id (uncurry (++) . runWriter .
> \x -> mapM (travFunc (hp x)) n);
> dat' = travPure sb <$> dat;
> hp y (DataNode i x) = hp' $ hPack (const . round $ calcGlue gs
> (x (mwd !! i))) (y !! i);
> hp' (x, _, y) = writer (Node x, y);
> sb (UnsetBoxNode f x) = sb' $ hPack f x;
> sb' (x, _, _) = Node x;
> };
\endinput
> }