summaryrefslogtreecommitdiff
path: root/metapost/context/base/mpiv/mp-step.mpiv
blob: f7a7ba5debb69ac1273bd5936656dd6118d22670 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
%D \module
%D   [       file=mp-cell.mpiv, % mp-step.mpiv,
%D        version=2010.10.07,   % 2001.05.22,
%D          title=\CONTEXT\ \METAPOST\ graphics,
%D       subtitle=steps,
%D         author=Hans Hagen,
%D           date=\currentdate,
%D      copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
%C
%C This module is part of the \CONTEXT\ macro||package and is
%C therefore copyrighted by \PRAGMA. See licen-en.pdf for
%C details.

% step prefixes .. no save needed

if known context_cell : endinput ; fi ;

boolean context_cell ; context_cell := true ;

def initialize_step_variables =
    save
        text_fill_color, text_line_color, text_line_width, text_offset,
        cell_fill_color, cell_line_color, cell_line_width, cell_offset,
        line_line_color, line_line_width, line_alternative,
        line_distance, cell_distance_y, cell_distance_x,
        nofcells, chart_vertical ;

    color   text_line_color     ; text_line_color     := red ;
    color   cell_line_color     ; cell_line_color     := blue ;
    color   line_line_color     ; line_line_color     := green ;

    color   text_fill_color     ; text_fill_color     := white ;
    color   cell_fill_color     ; cell_fill_color     := white ;

    numeric text_line_width     ; text_line_width     := 2pt ;
    numeric cell_line_width     ; cell_line_width     := 2pt ;
    numeric line_line_width     ; line_line_width     := 2pt  ;

    numeric text_offset         ; text_offset         := 4pt ;
    numeric cell_offset         ; cell_offset         := 4pt ;

    numeric line_distance       ; line_distance       := 10pt ; % between line and text
    numeric line_offset         ; line_offset         :=  4pt ; % between center and start of line
    numeric line_height         ; line_height         := 20pt ;

    numeric cell_distance_y     ; cell_distance_y     := 20pt ;
    numeric cell_distance_x     ; cell_distance_x     := 20pt ;

    numeric text_distance_set   ; text_distance_set   :=  4pt ;

    boolean chart_vertical      ; chart_vertical      := false ;

    numeric nofcells            ; nofcells            := 0 ;

enddef ;

def step_cells (expr t, b) =
    nofcells := nofcells + 1 ;
    cells_t[nofcells] := textext.d(t) ;
    cells_b[nofcells] := textext.d(b) ;
    texts_t[nofcells] := nullpicture ;
    texts_m[nofcells] := nullpicture ;
    texts_b[nofcells] := nullpicture ;
enddef ;

def step_texts (expr t, b) =
    texts_t[nofcells] := textext.d(t) ;
    texts_m[nofcells] := textext.d(m) ;
    texts_b[nofcells] := textext.d(b) ;
enddef ;

def step_begin_cell =
    nofcells := nofcells + 1 ;
    cells_t[nofcells] := nullpicture ;
    cells_b[nofcells] := nullpicture ;
    texts_t[nofcells] := nullpicture ;
    texts_m[nofcells] := nullpicture ;
    texts_b[nofcells] := nullpicture ;
enddef ;

def step_end_cell =
enddef ;

def step_cell_top (expr t) = cells_t[nofcells] := textext.d(t) ; enddef ;
def step_cell_bot (expr b) = cells_b[nofcells] := textext.d(b) ; enddef ;
def step_text_top (expr t) = texts_t[nofcells] := textext.d(t) ; enddef ;
def step_text_mid (expr m) = texts_m[nofcells] := textext.d(m) ; enddef ;
def step_text_bot (expr b) = texts_b[nofcells] := textext.d(b) ; enddef ;

def step_begin_chart =
    begingroup ;
        initialize_step_variables ;
        save nofcells ; numeric nofcells ; nofcells := 0 ;
        save cells_t, cells_m, cells_b ; picture cells_t[], cells_m[], cells_b[] ;
        save texts_t, texts_m, texts_b ; picture texts_t[], texts_m[], texts_b[] ;
enddef ;

def step_end_chart =
    % we could combine some loops but this is cleaner
    save dx, delta ; numeric dx, delta ;
    save p ; path p ;
    save one_row_only ; boolean one_row_only ;
    save cell_t, next_t, text_t ; picture cell_t, next_t, text_t ;
    save cell_m, next_m, text_m ; picture cell_m, next_m, text_m ;
    save cell_b, next_b, text_b ; picture cell_b, next_b, text_b ;
    save height_t, width_t, max_height_t, max_width_t ; numeric height_t, width_t, max_height_t, max_width_t ;
    save height_m, width_m, max_height_m, max_width_m ; numeric height_m, width_m, max_height_m, max_width_m ;
    save height_b, width_b, max_height_b, max_width_b ; numeric height_b, width_b, max_height_b, max_width_b ;
    % check rows
    one_row_only := true ;
    for i=1 upto nofcells :
        if bbwidth(cells_b[i]) > 0 :
            one_row_only := false ;
        fi ;
    endfor ;
    % swap and rotate
    if chart_vertical :
        if one_row_only :
            % deal with mid_texts
            max_width_t := max_width_m := max_width_b := 0 ;
            for i=1 upto nofcells :
                width_t := bbwidth(texts_t[i]) ;
                width_m := bbwidth(texts_m[i]) ;
                width_b := bbwidth(texts_b[i]) ;
                if width_t > max_width_t : max_width_t := width_t fi ;
                if width_m > max_width_m : max_width_m := width_m fi ;
                if width_b > max_width_b : max_width_b := width_b fi ;
            endfor ;
            if max_width_m > 0 :
                for i=1 upto nofcells :
                    text_t := texts_t[i] ; width_t := bbwidth(text_t) ;
                    text_m := texts_m[i] ; width_m := bbwidth(text_m) ;
                    text_b := texts_b[i] ; width_b := bbwidth(text_b) ;
                    if width_t < max_width_t :
                        setbounds text_t to boundingbox text_t leftenlarged (max_width_t - width_t) ;
                    fi ;
                    if width_m < max_width_m :
                        setbounds text_m to boundingbox text_m leftenlarged  ((max_width_m - width_m)/2) ;
                        setbounds text_m to boundingbox text_m rightenlarged ((max_width_m - width_m)/2) ;
                    fi ;
                    if width_b < max_width_b :
                        setbounds text_b to boundingbox text_b rightenlarged (max_width_b - width_b) ;
                    fi ;
                    text_t := text_t shifted (- xpart llcorner text_t, 0) ;
                    text_m := text_m shifted (- xpart llcorner text_m, 0) ;
                    text_b := text_b shifted (- xpart llcorner text_b, 0) ;
                    texts_t[i] := image (
                        draw text_t ;
                        draw text_m shifted (max_width_t +                 text_distance_set,0) ;
                        draw text_b shifted (max_width_t + max_width_m + 2*text_distance_set,0) ;
                    ) rotated 90 ;
                    texts_m[i] := texts_b[i] := nullpicture ;
                    cells_t[i] := cells_t[i] rotated 90 ;
                endfor ;
            else :
                for i=1 upto nofcells :
                    cells_t[i] := cells_t[i] rotated 90 ;
                    texts_t[i] := texts_t[i] rotated 90 ;
                    texts_b[i] := texts_b[i] rotated 90 ;
                endfor ;
            fi ;
        else :
            for i=1 upto nofcells :
                cell_t := cells_t[i] ;
                cell_b := cells_b[i] ;
                cells_t[i] := cell_b rotated 90 ;
                cells_b[i] := cell_t rotated 90 ;
                text_t := texts_t[i] ;
                text_b := texts_b[i] ;
                texts_t[i] := text_b rotated 90 ;
                texts_b[i] := text_t rotated 90 ;
            endfor ;
        fi ;
    fi ;
    % align horizontal
    for i=1 upto nofcells :
        cell_t := cells_t[i] ;
        cell_b := cells_b[i] ;
        width_t := bbwidth(cell_t) ;
        width_b := bbwidth(cell_b) ;
        if (width_t = 0) and (width_b = 0) :
            % skip
        elseif (width_t > 0) and (width_t < width_b) :
            delta := (width_b-width_t)/2 ;
            setbounds cell_t to boundingbox cell_t leftenlarged delta rightenlarged delta ;
            cells_t[i] := cell_t ;
        elseif (width_b > 0) and (width_t > width_b) :
            delta := (width_t-width_b)/2 ;
            setbounds cell_b to boundingbox cell_b leftenlarged delta rightenlarged delta ;
            cells_b[i] := cell_b ;
        fi ;
    endfor ;
    % analyze vertical
    max_height_t := 0 ;
    max_height_b := 0 ;
    for i=1 upto nofcells :
        cell_t := cells_t[i] ;
        cell_b := cells_b[i] ;
        height_t := bbheight(cell_t) ;
        height_b := bbheight(cell_b) ;
        if height_t > 0 :
            setbounds cell_t to boundingbox cell_t enlarged cell_offset ;
            height_t := height_t + 2 * cell_offset ;
            cells_t[i] := cell_t ;
        fi ;
        if height_b > 0 :
            setbounds cell_b to boundingbox cell_b enlarged cell_offset ;
            height_b := height_b + 2 * cell_offset ;
            cells_b[i] := cell_b ;
        fi ;
        if height_t > max_height_t :
            max_height_t := height_t ;
        fi
        if height_b > max_height_b :
            max_height_b := height_b ;
        fi ;
    endfor ;
    % align vertical
    for i=1 upto nofcells :
        cell_t := cells_t[i] ;
        cell_b := cells_b[i] ;
        height_t := bbheight(cell_t) ;
        height_b := bbheight(cell_b) ;
        if height_t > 0 :
            delta := (max_height_t-height_t)/2 ;
            setbounds cell_t to boundingbox cell_t topenlarged delta bottomenlarged delta ;
        fi ;
        if height_b > 0 :
            delta := (max_height_b-height_b)/2 ;
            setbounds cell_b to boundingbox cell_b topenlarged delta bottomenlarged delta ;
        fi ;
        cells_t[i] := cell_t ;
        cells_b[i] := cell_b ;
    endfor ;
    % position
    dx := 0 ;
    for i=1 upto nofcells :
        cell_t := cells_t[i] ;
        cell_b := cells_b[i] ;
        cell_t := cell_t shifted -llcorner cell_t ;
        cell_b := cell_b shifted -llcorner cell_b ;
        cell_t := cell_t shifted (dx, 0) ;
        cell_b := cell_b shifted (dx,-cell_distance_y-max_height_b) ;
        cells_t[i] := cell_t ;
        cells_b[i] := cell_b ;
        width_t := bbwidth(cell_t) ;
        width_b := bbwidth(cell_b) ;
        if width_t > 0 :
            dx := dx + cell_distance_x + width_t ;
        elseif width_b > 0 :
            dx := dx + cell_distance_x + width_b ;
        fi ;
    endfor ;
    % flush
    for i=1 upto nofcells :
        cell_t := cells_t[i] ;
        cell_b := cells_b[i] ;
        width_t := bbwidth(cell_t) ;
        width_b := bbwidth(cell_b) ;
        if width_t > 0 :
            fill boundingbox cell_t withcolor cell_fill_color ;
            draw boundingbox cell_t withpen pencircle scaled cell_line_width withcolor cell_line_color ;
            draw cell_t ;
        fi ;
        if width_b > 0 :
            fill boundingbox cell_b withcolor cell_fill_color ;
            draw boundingbox cell_b withpen pencircle scaled cell_line_width withcolor cell_line_color ;
            draw cell_b ;
        fi ;
    endfor ;
    %
    def midtopboundary    expr p = 0.5[ulcorner boundingbox p, urcorner boundingbox p] enddef ;
    def midbottomboundary expr p = 0.5[llcorner boundingbox p, lrcorner boundingbox p] enddef ;
    % draw top and bottom text boxes
    for i=1 upto nofcells-1 :
        text_t := texts_t[i] ;
        text_b := texts_b[i] ;
        if bbwidth(text_t) > 0 :
            setbounds text_t to boundingbox text_t enlarged text_offset ;
            texts_t[i] := text_t ;
        fi ;
        if bbwidth(text_b) > 0 :
            setbounds text_b to boundingbox text_b enlarged text_offset ;
            texts_b[i] := text_b ;
        fi ;
    endfor ;
    % arrows
    for i=1 upto nofcells-1 :
        cell_t := cells_t[i] ;
        cell_b := cells_b[i] ;
        next_t := cells_t[i+1] ;
        next_b := cells_b[i+1] ;
        pair t_a, t_b, t_c, b_a, b_b, b_c ;
        t_a := midtopboundary cell_t ;
        t_b := midtopboundary next_t ;
        t_c := (xpart 0.5[t_a,t_b], ypart t_a+line_height+line_distance) ;
        if one_row_only :
            b_a := midbottomboundary cell_t ;
            b_b := midbottomboundary next_t ;
        else :
            b_a := midbottomboundary cell_b ;
            b_b := midbottomboundary next_b ;
        fi ;
        b_c := (xpart 0.5[b_a,b_b], ypart b_a-line_height-line_distance) ;
        texts_t[i] := thelabel.top(texts_t[i],t_c) ;
        texts_b[i] := thelabel.bot(texts_b[i],b_c) ;
    endfor ;
    %
    for i=1 upto nofcells-1 : % todo arrows when empty text
        cell_t := cells_t[i] ;
        cell_b := cells_b[i] ;
        next_t := cells_t[i+1] ;
        next_b := cells_b[i+1] ;
        text_t := texts_t[i] ;
        text_b := texts_b[i] ;
        if bbwidth(text_t) > 0 :
            if bbwidth(cell_t) > 0 :
                drawarrow midtopboundary cell_t
                    shifted (if i > 1 : line_offset else : 0 fi, cell_line_width) {up}  ..
                    midbottomboundary text_t shifted (0,-line_distance) ..
                    {down} midtopboundary next_t shifted(if i < nofcells - 1 : -line_offset else : 0 fi,cell_line_width)
                    withpen pencircle scaled line_line_width
                    withcolor line_line_color ;
            else :
            fi ;
        fi ;
        if bbwidth(text_b) > 0 :
            if one_row_only :
                cell_b := cell_t ;
                next_b := next_t ;
            fi ;
            if bbwidth(cell_b) > 0 :
                drawarrow midbottomboundary cell_b
                    shifted (if i > 1 : line_offset else : 0 fi, -cell_line_width) {down}  ..
                    midtopboundary text_b shifted (0, line_distance) ..
                    {up} midbottomboundary next_b shifted (if i < nofcells - 1 : -line_offset else : 0 fi,-cell_line_width)
                    withpen pencircle scaled line_line_width
                    withcolor line_line_color ;
            else :
            fi ;
        fi ;
    endfor ;
    % draw top and bottom text boxes
    for i=1 upto nofcells-1 :
        text_t := texts_t[i] ;
        text_b := texts_b[i] ;
        if bbwidth(text_t) > 0 :
            fill boundingbox text_t withcolor text_fill_color ;
            draw boundingbox text_t withpen pencircle scaled text_line_width withcolor text_line_color ;
            draw text_t ;
        fi ;
        if bbwidth(text_b) > 0 :
            fill boundingbox text_b withcolor text_fill_color ;
            draw boundingbox text_b withpen pencircle scaled text_line_width withcolor text_line_color ;
            draw text_b ;
        fi ;
    endfor ;
    if chart_vertical :
        % rotate back
        currentpicture := currentpicture rotated -90 ;
    fi ;
    endgroup ;
enddef ;

% start_begin_step ;
%     step_cells ("\strut test 0", "\strut test 0") ;
%     step_cells ("\strut test 1", "\vbox{\hsize3cm \strut oeps 1\crlf oeps 1}") ;
%     step_texts ("\strut 1",    "\strut 1") ;
%     step_cells ("\strut test 2", "\strut oeps 2 oeps 2") ;
%     step_cells ("\strut test X", "\strut test X") ;
%     step_texts ("\strut 2",    "\strut 2") ;
%     step_cells ("\strut test 3", "\strut oeps 3 oeps 3") ;
%     step_texts ("\strut 3",    "\strut 3") ;
%     step_cells ("\strut test 4", "\strut oeps 4 oeps 4") ;
%     step_texts ("\strut 4",    "\strut 4") ;
% stop_end_chart ;