1 -----------------------------------------------------------------------------
3 -- Module : Text.Html.BlockTable
4 -- Copyright : (c) Andy Gill and OGI, 1999-2001
5 -- License : BSD-style (see the file libraries/base/LICENSE)
7 -- Maintainer : Andy Gill <andy@galconn.com>
8 -- Stability : experimental
9 -- Portability : portable
11 -- An Html combinator library
13 -----------------------------------------------------------------------------
15 module Text.Html.BlockTable (
19 BlockTable, -- abstract
21 -- Contruction Functions:
27 -- Investigation Functions:
40 -- These combinators can be used to build formated 2D tables.
41 -- The specific target useage is for HTML table generation.
46 > table1 :: BlockTable String
47 > table1 = single "Hello" +-----+
49 This is a 1x1 cell +-----+
52 single :: a -> BlockTable a
54 So the cells can contain anything.
56 > table2 :: BlockTable String
57 > table2 = single "World" +-----+
62 > table3 :: BlockTable String
63 > table3 = table1 %-% table2 +-----%-----+
65 % is used to indicate +-----%-----+
69 > table4 :: BlockTable String
70 > table4 = table3 %/% table2 +-----+-----+
72 Notice the padding on the %%%%%%%%%%%%%
73 smaller (bottom) cell to |World |
74 force the table to be a +-----------+
77 > table5 :: BlockTable String
78 > table5 = table1 %-% table4 +-----%-----+-----+
80 Notice the padding on the | %-----+-----+
81 leftmost cell, again to | %World |
82 force the table to be a +-----%-----------+
85 Now the table can be rendered with processTable, for example:
86 Main> processTable table5
90 [("World",(2,1))]] :: [[([Char],(Int,Int))]]
94 -- ---------------------------------------------------------------------------
95 -- Contruction Functions
97 -- Perhaps one day I'll write the Show instance
98 -- to show boxes aka the above ascii renditions.
100 instance (Show a) => Show (BlockTable a) where
101 showsPrec p = showsTable
103 type TableI a = [[(a,(Int,Int))]] -> [[(a,(Int,Int))]]
105 data BlockTable a = Table (Int -> Int -> TableI a) Int Int
108 -- You can create a (1x1) table entry
110 single :: a -> BlockTable a
111 single a = Table (\ x y z -> [(a,(x+1,y+1))] : z) 1 1
114 -- You can compose tables, horizonally and vertically
116 above :: BlockTable a -> BlockTable a -> BlockTable a
117 beside :: BlockTable a -> BlockTable a -> BlockTable a
119 t1 `above` t2 = trans (combine (trans t1) (trans t2) (.))
121 t1 `beside` t2 = combine t1 t2 (\ lst1 lst2 r ->
123 -- Note this depends on the fact that
124 -- that the result has the same number
125 -- of lines as the y dimention; one list
126 -- per line. This is not true in general
127 -- but is always true for these combinators.
128 -- I should assert this!
129 -- I should even prove this.
130 beside (x:xs) (y:ys) = (x ++ y) : beside xs ys
131 beside (x:xs) [] = x : xs ++ r
132 beside [] (y:ys) = y : ys ++ r
135 beside (lst1 []) (lst2 []))
137 -- trans flips (transposes) over the x and y axis of
138 -- the table. It is only used internally, and typically
139 -- in pairs, ie. (flip ... munge ... (un)flip).
141 trans :: BlockTable a -> BlockTable a
142 trans (Table f1 x1 y1) = Table (flip f1) y1 x1
144 combine :: BlockTable a
146 -> (TableI a -> TableI b -> TableI c)
148 combine (Table f1 x1 y1) (Table f2 x2 y2) comb = Table new_fn (x1+x2) max_y
152 case compare y1 y2 of
153 EQ -> comb (f1 0 y) (f2 x y)
154 GT -> comb (f1 0 y) (f2 x (y + y1 - y2))
155 LT -> comb (f1 0 (y + y2 - y1)) (f2 x y)
157 -- ---------------------------------------------------------------------------
158 -- Investigation Functions
160 -- This is the other thing you can do with a Table;
161 -- turn it into a 2D list, tagged with the (x,y)
162 -- sizes of each cell in the table.
164 getMatrix :: BlockTable a -> [[(a,(Int,Int))]]
165 getMatrix (Table r _ _) = r 0 0 []
167 -- You can also look at a table
169 showsTable :: (Show a) => BlockTable a -> ShowS
170 showsTable table = shows (getMatrix table)
172 showTable :: (Show a) => BlockTable a -> String
173 showTable table = showsTable table ""