Line data Source code
1 : /* File: pencil_classifier_1d_layouter.c; Copyright and License: see below */
2 :
3 : #include "pencil_classifier_1d_layouter.h"
4 : #include "layout/layout_visible_classifier_iter.h"
5 : #include "u8/u8_trace.h"
6 : #include <pango/pangocairo.h>
7 : #include <stdio.h>
8 : #include <stdlib.h>
9 : #include <math.h>
10 :
11 0 : void pencil_classifier_1d_layouter_init( pencil_classifier_1d_layouter_t *this_,
12 : layout_visible_set_t *layout_data,
13 : const data_profile_part_t *profile,
14 : const pencil_size_t *pencil_size )
15 : {
16 0 : U8_TRACE_BEGIN();
17 0 : assert( NULL != layout_data );
18 0 : assert( NULL != profile );
19 0 : assert( NULL != pencil_size );
20 :
21 0 : (*this_).layout_data = layout_data;
22 0 : (*this_).profile = profile;
23 0 : (*this_).pencil_size = pencil_size;
24 0 : pencil_classifier_composer_init( &((*this_).classifier_composer) );
25 0 : data_guidelines_init( &((*this_).guidelines) );
26 :
27 : /* get draw area */
28 : {
29 : const layout_diagram_t *const diagram_layout
30 0 : = layout_visible_set_get_diagram_ptr( (*this_).layout_data );
31 0 : (*this_).diagram_draw_area = layout_diagram_get_draw_area_const( diagram_layout );
32 : }
33 :
34 0 : U8_TRACE_END();
35 0 : }
36 :
37 0 : void pencil_classifier_1d_layouter_destroy( pencil_classifier_1d_layouter_t *this_ )
38 : {
39 0 : U8_TRACE_BEGIN();
40 :
41 0 : data_guidelines_destroy( &((*this_).guidelines) );
42 0 : pencil_classifier_composer_destroy( &((*this_).classifier_composer) );
43 :
44 0 : U8_TRACE_END();
45 0 : }
46 :
47 0 : void pencil_classifier_1d_layouter_layout_for_list( pencil_classifier_1d_layouter_t *this_, PangoLayout *font_layout )
48 : {
49 0 : U8_TRACE_BEGIN();
50 :
51 : /* get preferred object distance */
52 0 : const double obj_dist = pencil_size_get_preferred_object_distance( (*this_).pencil_size );
53 : /* const double gap = pencil_size_get_standard_object_border( (*this_).pencil_size ); */
54 :
55 : /* get the draw coordinates */
56 : geometry_rectangle_t draw_area;
57 0 : geometry_rectangle_copy( &draw_area, (*this_).diagram_draw_area );
58 0 : geometry_rectangle_enlarge( &draw_area, 0.0, (- obj_dist) );
59 0 : double diag_w = geometry_rectangle_get_width( &draw_area );
60 0 : double diag_h = geometry_rectangle_get_height( &draw_area );
61 :
62 0 : const double phi = 1.6180339; /* minor=0.618, major=1.0, sum=1.618 => (sum/major)==(major/minor) */
63 0 : const double golden_ratio_width = diag_w/phi;
64 0 : const double golden_ratio_height = diag_h/phi;
65 :
66 : /* sort the classifiers according to their list_order */
67 : universal_array_index_sorter_t sorted_classifiers;
68 0 : universal_array_index_sorter_init( &sorted_classifiers );
69 :
70 : /* calculate preferred classifier bounds/envelopes */
71 0 : const uint_fast32_t c_count = layout_visible_set_get_visible_classifier_count( (*this_).layout_data );
72 0 : for ( uint_fast32_t plain_idx = 0; plain_idx < c_count; plain_idx ++ )
73 : {
74 : layout_visible_classifier_t *const visible_classifier1
75 0 : = layout_visible_set_get_visible_classifier_ptr( (*this_).layout_data, plain_idx );
76 : const data_visible_classifier_t *const visible_classifier_data
77 0 : = layout_visible_classifier_get_data_const ( visible_classifier1 );
78 0 : const data_classifier_t *const classifier1 = data_visible_classifier_get_classifier_const( visible_classifier_data );
79 :
80 : /* sort the classifiers according to their list_order */
81 : {
82 0 : const double weight = (const double) data_classifier_get_list_order( classifier1 );
83 0 : const int insert_err = universal_array_index_sorter_insert( &sorted_classifiers, plain_idx, weight );
84 0 : if ( 0 != insert_err )
85 : {
86 0 : U8_LOG_ERROR ( "universal_array_index_sorter_t list is full." );
87 : }
88 : }
89 :
90 : /* set the preferred bounds, space and label_box of the classifier layout */
91 : {
92 : geometry_rectangle_t envelope_box;
93 0 : geometry_rectangle_init( &envelope_box, 0.0, 0.0, golden_ratio_width, (golden_ratio_height/c_count) );
94 0 : const geometry_compartments_t no_features = geometry_compartments_new_empty();
95 :
96 0 : const bool has_contained_children = false; /* this diagram type does not embrace children */
97 0 : pencil_classifier_composer_set_envelope_box( &((*this_).classifier_composer),
98 : &envelope_box,
99 : has_contained_children,
100 : &no_features,
101 : (*this_).profile,
102 : (*this_).pencil_size,
103 : font_layout,
104 : visible_classifier1
105 : );
106 :
107 0 : geometry_rectangle_destroy( &envelope_box );
108 : }
109 : }
110 :
111 : /* layout list */
112 0 : pencil_classifier_1d_layouter_private_layout_vertical( this_,
113 : &sorted_classifiers,
114 : &draw_area,
115 : GEOMETRY_H_ALIGN_CENTER
116 : );
117 :
118 : /* cleanup sorted array indices and area-rectangles */
119 0 : universal_array_index_sorter_destroy( &sorted_classifiers );
120 0 : geometry_rectangle_destroy( &draw_area );
121 :
122 0 : U8_TRACE_END();
123 0 : }
124 :
125 0 : void pencil_classifier_1d_layouter_layout_for_sequence( pencil_classifier_1d_layouter_t *this_, PangoLayout *font_layout )
126 : {
127 0 : U8_TRACE_BEGIN();
128 :
129 : /* get preferred object distance */
130 0 : const double obj_dist = pencil_size_get_preferred_object_distance( (*this_).pencil_size );
131 : /* const double gap = pencil_size_get_standard_object_border( (*this_).pencil_size ); */
132 :
133 : /* get the diagram coordinates */
134 : geometry_rectangle_t draw_area;
135 0 : geometry_rectangle_copy( &draw_area, (*this_).diagram_draw_area );
136 0 : geometry_rectangle_shift( &draw_area, obj_dist, 0.0 );
137 0 : geometry_rectangle_enlarge( &draw_area, (-2.0 * obj_dist), (- obj_dist) );
138 0 : double diag_w = geometry_rectangle_get_width( &draw_area );
139 0 : double diag_h = geometry_rectangle_get_height( &draw_area );
140 :
141 0 : const double phi = 1.6180339; /* minor=0.618, major=1.0, sum=1.618 => (sum/major)==(major/minor) */
142 0 : const double minor_ratio = (1.0 - 0.6180339);
143 0 : const double golden_ratio_width = diag_w/phi;
144 0 : const double minor_minor_height = diag_h * minor_ratio * minor_ratio;
145 0 : const double half_minor_width = diag_w * minor_ratio * 0.5;
146 :
147 : geometry_rectangle_t left_area;
148 0 : geometry_rectangle_copy( &left_area, &draw_area );
149 0 : geometry_rectangle_enlarge( &left_area, (- half_minor_width), 0.0 );
150 :
151 : geometry_rectangle_t right_column;
152 0 : geometry_rectangle_copy( &right_column, &draw_area );
153 0 : geometry_rectangle_shift( &right_column, (diag_w-half_minor_width), minor_minor_height );
154 0 : geometry_rectangle_enlarge( &right_column, (half_minor_width-diag_w), (- minor_minor_height) );
155 :
156 : /* sort the classifiers according to their list_order */
157 : universal_array_index_sorter_t sorted_notes_reqs;
158 0 : universal_array_index_sorter_init( &sorted_notes_reqs );
159 : universal_array_index_sorter_t sorted_diag_refs;
160 0 : universal_array_index_sorter_init( &sorted_diag_refs );
161 : universal_array_index_sorter_t sorted_acting_classifiers;
162 0 : universal_array_index_sorter_init( &sorted_acting_classifiers );
163 :
164 : /* calculate preferred classifier bounds */
165 0 : const uint_fast32_t c_count = layout_visible_set_get_visible_classifier_count( (*this_).layout_data );
166 0 : for ( uint_fast32_t plain_idx = 0; plain_idx < c_count; plain_idx ++ )
167 : {
168 : layout_visible_classifier_t *const visible_classifier1
169 0 : = layout_visible_set_get_visible_classifier_ptr( (*this_).layout_data, plain_idx );
170 : const data_visible_classifier_t *const visible_classifier_data
171 0 : = layout_visible_classifier_get_data_const ( visible_classifier1 );
172 0 : const data_classifier_t *const classifier1 = data_visible_classifier_get_classifier_const( visible_classifier_data );
173 0 : const data_classifier_type_t c1_type = data_classifier_get_main_type ( classifier1 );
174 :
175 : /* check classifier type and sort into corresponding list */
176 : {
177 0 : int insert_err = 0;
178 0 : const double weight = (const double) data_classifier_get_list_order( classifier1 );
179 : const bool c1_type_is_scenario
180 0 : = data_guidelines_classifier_has_scenario_semantics( &((*this_).guidelines),
181 : DATA_DIAGRAM_TYPE_UML_SEQUENCE_DIAGRAM,
182 : c1_type
183 : );
184 0 : if ( c1_type == DATA_CLASSIFIER_TYPE_INTERACTION_USE )
185 : {
186 0 : insert_err = universal_array_index_sorter_insert( &sorted_diag_refs, plain_idx, weight );
187 : }
188 0 : else if ( ! c1_type_is_scenario )
189 : {
190 0 : insert_err = universal_array_index_sorter_insert( &sorted_notes_reqs, plain_idx, weight );
191 : }
192 : else
193 : {
194 0 : insert_err = universal_array_index_sorter_insert( &sorted_acting_classifiers, plain_idx, weight );
195 : }
196 0 : if ( 0 != insert_err )
197 : {
198 0 : U8_LOG_ERROR ( "universal_array_index_sorter_t list is full." );
199 : }
200 : }
201 :
202 : /* set the preferred bounds, space and label_box of the classifier layout */
203 : {
204 : geometry_rectangle_t envelope_box;
205 0 : if ( c1_type == DATA_CLASSIFIER_TYPE_INTERACTION_USE )
206 : {
207 0 : geometry_rectangle_init( &envelope_box, 0.0, 0.0, (diag_w-half_minor_width), (minor_minor_height/2.0) );
208 : }
209 : else
210 : {
211 0 : geometry_rectangle_init( &envelope_box, 0.0, 0.0, (golden_ratio_width/c_count), minor_minor_height );
212 : }
213 0 : const geometry_compartments_t no_features = geometry_compartments_new_empty();
214 :
215 0 : const bool has_contained_children = false; /* this diagram type does not embrace children */
216 0 : pencil_classifier_composer_set_envelope_box( &((*this_).classifier_composer),
217 : &envelope_box,
218 : has_contained_children,
219 : &no_features,
220 : (*this_).profile,
221 : (*this_).pencil_size,
222 : font_layout,
223 : visible_classifier1
224 : );
225 :
226 0 : geometry_rectangle_destroy( &envelope_box );
227 : }
228 : }
229 0 : assert( c_count
230 : == universal_array_index_sorter_get_count( &sorted_notes_reqs )
231 : + universal_array_index_sorter_get_count( &sorted_diag_refs )
232 : + universal_array_index_sorter_get_count( &sorted_acting_classifiers )
233 : );
234 :
235 : /* layout acting classifiers */
236 0 : pencil_classifier_1d_layouter_private_layout_horizontal( this_,
237 : &sorted_acting_classifiers,
238 : &left_area,
239 : GEOMETRY_V_ALIGN_TOP
240 : );
241 : /* layout digram references */
242 0 : pencil_classifier_1d_layouter_private_linear_vertical( this_,
243 : &sorted_diag_refs,
244 : &left_area,
245 : GEOMETRY_H_ALIGN_LEFT
246 : );
247 : /* layout notes/comments and requirements */
248 0 : pencil_classifier_1d_layouter_private_linear_vertical( this_,
249 : &sorted_notes_reqs,
250 : &right_column,
251 : GEOMETRY_H_ALIGN_RIGHT
252 : );
253 :
254 : /* cleanup sorted array indices and area-rectangles */
255 0 : universal_array_index_sorter_destroy( &sorted_acting_classifiers );
256 0 : universal_array_index_sorter_destroy( &sorted_diag_refs );
257 0 : universal_array_index_sorter_destroy( &sorted_notes_reqs );
258 0 : geometry_rectangle_destroy( &right_column );
259 0 : geometry_rectangle_destroy( &left_area );
260 0 : geometry_rectangle_destroy( &draw_area );
261 :
262 0 : U8_TRACE_END();
263 0 : }
264 :
265 0 : void pencil_classifier_1d_layouter_layout_for_timing( pencil_classifier_1d_layouter_t *this_, PangoLayout *font_layout )
266 : {
267 0 : U8_TRACE_BEGIN();
268 :
269 : /* get preferred object distance */
270 0 : const double obj_dist = pencil_size_get_preferred_object_distance( (*this_).pencil_size );
271 : /* const double gap = pencil_size_get_standard_object_border( (*this_).pencil_size ); */
272 :
273 : /* get the diagram coordinates */
274 : geometry_rectangle_t draw_area;
275 0 : geometry_rectangle_copy( &draw_area, (*this_).diagram_draw_area );
276 0 : geometry_rectangle_shift( &draw_area, obj_dist, 0.0 );
277 0 : geometry_rectangle_enlarge( &draw_area, (-2.0 * obj_dist), (- obj_dist) );
278 0 : const double diag_w = geometry_rectangle_get_width( &draw_area );
279 0 : const double diag_h = geometry_rectangle_get_height( &draw_area );
280 :
281 0 : const double phi = 1.6180339; /* minor=0.618, major=1.0, sum=1.618 => (sum/major)==(major/minor) */
282 0 : const double minor_ratio = (1.0 - 0.6180339);
283 0 : const double golden_ratio_width = diag_w/phi;
284 0 : const double golden_ratio_height = diag_h/phi;
285 0 : const double minor_minor_width = diag_w * minor_ratio * minor_ratio;
286 0 : const double minor_minor_height = diag_h * minor_ratio * minor_ratio;
287 :
288 : geometry_rectangle_t top_row;
289 0 : geometry_rectangle_copy( &top_row, &draw_area );
290 0 : geometry_rectangle_shift( &top_row, minor_minor_width, 0.0 );
291 0 : geometry_rectangle_enlarge( &top_row, (- minor_minor_width), (minor_minor_width-diag_h) );
292 :
293 : geometry_rectangle_t center_area;
294 0 : geometry_rectangle_copy( ¢er_area, &draw_area );
295 0 : geometry_rectangle_shift( ¢er_area, 0.0, minor_minor_height );
296 0 : geometry_rectangle_enlarge( ¢er_area, 0.0, (- minor_minor_height) );
297 :
298 : /* sort the classifiers according to their list_order */
299 : universal_array_index_sorter_t sorted_notes_reqs;
300 0 : universal_array_index_sorter_init( &sorted_notes_reqs );
301 : universal_array_index_sorter_t sorted_acting_classifiers;
302 0 : universal_array_index_sorter_init( &sorted_acting_classifiers );
303 :
304 : /* calculate preferred classifier bounds */
305 0 : const uint_fast32_t c_count = layout_visible_set_get_visible_classifier_count( (*this_).layout_data );
306 0 : for ( uint_fast32_t plain_idx = 0; plain_idx < c_count; plain_idx ++ )
307 : {
308 : layout_visible_classifier_t *const visible_classifier1
309 0 : = layout_visible_set_get_visible_classifier_ptr( (*this_).layout_data, plain_idx );
310 : const data_visible_classifier_t *const visible_classifier_data
311 0 : = layout_visible_classifier_get_data_const ( visible_classifier1 );
312 0 : const data_classifier_t *const classifier1 = data_visible_classifier_get_classifier_const( visible_classifier_data );
313 0 : const data_classifier_type_t c1_type = data_classifier_get_main_type ( classifier1 );
314 :
315 : /* check classifier type and sort into corresponding list */
316 : {
317 0 : int insert_err = 0;
318 0 : const double weight = (const double) data_classifier_get_list_order( classifier1 );
319 : const bool c1_type_is_scenario
320 0 : = data_guidelines_classifier_has_scenario_semantics( &((*this_).guidelines),
321 : DATA_DIAGRAM_TYPE_UML_TIMING_DIAGRAM,
322 : c1_type
323 : );
324 0 : if ( ! c1_type_is_scenario )
325 : {
326 0 : insert_err = universal_array_index_sorter_insert( &sorted_notes_reqs, plain_idx, weight );
327 : }
328 : else
329 : {
330 0 : insert_err = universal_array_index_sorter_insert( &sorted_acting_classifiers, plain_idx, weight );
331 : }
332 0 : if ( 0 != insert_err )
333 : {
334 0 : U8_LOG_ERROR ( "universal_array_index_sorter_t list is full." );
335 : }
336 : }
337 :
338 : /* set the preferred bounds, space and label_box of the classifier layout */
339 : {
340 : geometry_rectangle_t envelope_box;
341 0 : geometry_rectangle_init( &envelope_box, 0.0, 0.0, ((diag_w-golden_ratio_width)/2.0), (golden_ratio_height/c_count) );
342 0 : const geometry_compartments_t no_features = geometry_compartments_new_empty();
343 :
344 0 : const bool has_contained_children = false; /* this diagram type does not embrace children */
345 0 : pencil_classifier_composer_set_envelope_box( &((*this_).classifier_composer),
346 : &envelope_box,
347 : has_contained_children,
348 : &no_features,
349 : (*this_).profile,
350 : (*this_).pencil_size,
351 : font_layout,
352 : visible_classifier1
353 : );
354 :
355 0 : geometry_rectangle_destroy( &envelope_box );
356 : }
357 : }
358 0 : assert( c_count
359 : == universal_array_index_sorter_get_count( &sorted_notes_reqs )
360 : + universal_array_index_sorter_get_count( &sorted_acting_classifiers )
361 : );
362 :
363 : /* layout acting classifiers */
364 0 : pencil_classifier_1d_layouter_private_layout_vertical( this_,
365 : &sorted_acting_classifiers,
366 : ¢er_area,
367 : GEOMETRY_H_ALIGN_LEFT
368 : );
369 : /* layout notes/comments and requirements */
370 0 : pencil_classifier_1d_layouter_private_linear_horizontal( this_,
371 : &sorted_notes_reqs,
372 : &top_row,
373 : GEOMETRY_V_ALIGN_TOP
374 : );
375 :
376 : /* cleanup sorted array indices and area-rectangles */
377 0 : universal_array_index_sorter_destroy( &sorted_acting_classifiers );
378 0 : universal_array_index_sorter_destroy( &sorted_notes_reqs );
379 0 : geometry_rectangle_destroy( ¢er_area );
380 0 : geometry_rectangle_destroy( &top_row );
381 0 : geometry_rectangle_destroy( &draw_area );
382 :
383 0 : U8_TRACE_END();
384 0 : }
385 :
386 0 : void pencil_classifier_1d_layouter_private_layout_horizontal( const pencil_classifier_1d_layouter_t *this_,
387 : const universal_array_index_sorter_t *classifier_list,
388 : const geometry_rectangle_t *dest_rect,
389 : geometry_v_align_t v_alignment )
390 : {
391 0 : U8_TRACE_BEGIN();
392 :
393 : /* get the destination rectangle coordinates */
394 0 : const double diag_x = geometry_rectangle_get_left( dest_rect );
395 0 : const double diag_w = geometry_rectangle_get_width( dest_rect );
396 :
397 : /* calculate sum of wished envelope widths */
398 0 : double total_wish_width = 0.0;
399 : layout_visible_classifier_iter_t classifer_iterator;
400 0 : layout_visible_classifier_iter_init( &classifer_iterator, (*this_).layout_data, classifier_list );
401 0 : while( layout_visible_classifier_iter_has_next( &classifer_iterator ) )
402 : {
403 : const layout_visible_classifier_t *const visible_classifier1
404 0 : = layout_visible_classifier_iter_next_ptr( &classifer_iterator );
405 :
406 : /* update sum of wished envelope widths */
407 : const geometry_rectangle_t envelope
408 0 : = layout_visible_classifier_get_envelope_box( visible_classifier1 );
409 0 : total_wish_width += geometry_rectangle_get_width( &envelope );
410 : }
411 0 : layout_visible_classifier_iter_destroy( &classifer_iterator );
412 0 : const uint_fast32_t count_classifiers = universal_array_index_sorter_get_count ( classifier_list );
413 0 : const double dx_spaces = (count_classifiers==0) ? diag_w : ((diag_w - total_wish_width)/count_classifiers);
414 :
415 : /* update the classifier coordinates */
416 0 : double current_x = diag_x;
417 0 : layout_visible_classifier_iter_init( &classifer_iterator, (*this_).layout_data, classifier_list );
418 0 : while( layout_visible_classifier_iter_has_next( &classifer_iterator ) )
419 : {
420 : layout_visible_classifier_t *const visible_classifier2
421 0 : = layout_visible_classifier_iter_next_ptr( &classifer_iterator );
422 :
423 : const geometry_rectangle_t envelope
424 0 : = layout_visible_classifier_get_envelope_box( visible_classifier2 );
425 0 : const double envelope_top = geometry_rectangle_get_top( &envelope );
426 0 : const double envelope_height = geometry_rectangle_get_height( &envelope );
427 0 : const double envelope_left = geometry_rectangle_get_left( &envelope );
428 0 : const double envelope_width = geometry_rectangle_get_width( &envelope );
429 :
430 0 : const double dest_top = geometry_v_align_get_top( &v_alignment,
431 : envelope_height,
432 : geometry_rectangle_get_top( dest_rect ),
433 : geometry_rectangle_get_height( dest_rect )
434 : );
435 0 : const double delta_y = dest_top - envelope_top;
436 :
437 0 : if ( dx_spaces > 0.0 )
438 : {
439 : /* equal spaces if there are spaces */
440 0 : const double delta_x = current_x + (dx_spaces/2.0) - envelope_left;
441 0 : const geometry_offset_t offset = geometry_offset_new( delta_x, delta_y );
442 :
443 0 : layout_visible_classifier_shift( visible_classifier2, &offset );
444 :
445 0 : current_x += dx_spaces + envelope_width;
446 : }
447 : else
448 : {
449 : /* const double wish2avail_ratio = (diag_h == 0.0) ? 1.0 : (total_wish_width/diag_h); */
450 0 : const double avail2wish_ratio = (total_wish_width == 0.0) ? 1.0 : (diag_w/total_wish_width);
451 0 : const double available_width = envelope_width * avail2wish_ratio;
452 0 : const uint32_t position = layout_visible_classifier_iter_count_processed( &classifer_iterator ) - 1;
453 0 : const double x_align_ratio = (count_classifiers==1) ? 0.5 : position / ( count_classifiers - 1.0 );
454 0 : const double x_align_envelope = envelope_width * x_align_ratio;
455 0 : const double x_align_available = available_width * x_align_ratio;
456 :
457 0 : const double delta_x = (current_x+x_align_available) - (envelope_left+x_align_envelope);
458 0 : const geometry_offset_t offset = geometry_offset_new( delta_x, delta_y );
459 :
460 0 : layout_visible_classifier_shift( visible_classifier2, &offset );
461 :
462 0 : current_x += available_width;
463 : }
464 : }
465 0 : layout_visible_classifier_iter_destroy( &classifer_iterator );
466 :
467 0 : U8_TRACE_END();
468 0 : }
469 :
470 0 : void pencil_classifier_1d_layouter_private_layout_vertical( const pencil_classifier_1d_layouter_t *this_,
471 : const universal_array_index_sorter_t *classifier_list,
472 : const geometry_rectangle_t *dest_rect,
473 : geometry_h_align_t h_alignment )
474 : {
475 0 : U8_TRACE_BEGIN();
476 :
477 : /* get the destination rectangle coordinates */
478 0 : const double diag_y = geometry_rectangle_get_top( dest_rect );
479 0 : const double diag_h = geometry_rectangle_get_height( dest_rect );
480 :
481 : /* calculate sum of wished envelope heights */
482 0 : double total_wish_height = 0.0;
483 : layout_visible_classifier_iter_t classifer_iterator;
484 0 : layout_visible_classifier_iter_init( &classifer_iterator, (*this_).layout_data, classifier_list );
485 0 : while( layout_visible_classifier_iter_has_next( &classifer_iterator ) )
486 : {
487 : const layout_visible_classifier_t *const visible_classifier1
488 0 : = layout_visible_classifier_iter_next_ptr( &classifer_iterator );
489 :
490 : /* update sum of wished envelope heights */
491 : const geometry_rectangle_t envelope
492 0 : = layout_visible_classifier_get_envelope_box( visible_classifier1 );
493 0 : total_wish_height += geometry_rectangle_get_height( &envelope );
494 : }
495 0 : layout_visible_classifier_iter_destroy( &classifer_iterator );
496 0 : const uint_fast32_t count_classifiers = universal_array_index_sorter_get_count ( classifier_list );
497 0 : const double dy_spaces = (count_classifiers==0) ? diag_h : ((diag_h - total_wish_height)/count_classifiers);
498 :
499 : /* update the classifier coordinates */
500 0 : double current_y = diag_y;
501 0 : layout_visible_classifier_iter_init( &classifer_iterator, (*this_).layout_data, classifier_list );
502 0 : while( layout_visible_classifier_iter_has_next( &classifer_iterator ) )
503 : {
504 : layout_visible_classifier_t *const visible_classifier2
505 0 : = layout_visible_classifier_iter_next_ptr( &classifer_iterator );
506 :
507 : const geometry_rectangle_t envelope
508 0 : = layout_visible_classifier_get_envelope_box( visible_classifier2 );
509 0 : const double envelope_top = geometry_rectangle_get_top( &envelope );
510 0 : const double envelope_height = geometry_rectangle_get_height( &envelope );
511 0 : const double envelope_left = geometry_rectangle_get_left( &envelope );
512 0 : const double envelope_width = geometry_rectangle_get_width( &envelope );
513 :
514 0 : const double dest_left = geometry_h_align_get_left( &h_alignment,
515 : envelope_width,
516 : geometry_rectangle_get_left( dest_rect ),
517 : geometry_rectangle_get_width( dest_rect )
518 : );
519 0 : const double delta_x = dest_left - envelope_left;
520 :
521 0 : if ( dy_spaces > 0.0 )
522 : {
523 : /* equal spaces if there are spaces */
524 0 : const double delta_y = current_y + (dy_spaces/2.0) - envelope_top;
525 0 : const geometry_offset_t offset = geometry_offset_new( delta_x, delta_y );
526 :
527 0 : layout_visible_classifier_shift( visible_classifier2, &offset );
528 :
529 0 : current_y += dy_spaces + envelope_height;
530 : }
531 : else
532 : {
533 : /* keep available-to-wish ratio if classifiers overlap */
534 : /* const double wish2avail_ratio = (diag_h == 0.0) ? 1.0 : (total_wish_height/diag_h); */
535 0 : const double avail2wish_ratio = (total_wish_height == 0.0) ? 1.0 : (diag_h/total_wish_height);
536 0 : const double available_height = envelope_height * avail2wish_ratio;
537 0 : const uint32_t position = layout_visible_classifier_iter_count_processed( &classifer_iterator ) - 1;
538 0 : const double y_align_ratio = (count_classifiers==1) ? 0.5 : position / ( count_classifiers - 1.0 );
539 0 : const double y_align_envelope = envelope_height * y_align_ratio;
540 0 : const double y_align_available = available_height * y_align_ratio;
541 :
542 0 : const double delta_y = (current_y+y_align_available) - (envelope_top+y_align_envelope);
543 0 : const geometry_offset_t offset = geometry_offset_new( delta_x, delta_y );
544 :
545 0 : layout_visible_classifier_shift( visible_classifier2, &offset );
546 :
547 0 : current_y += available_height;
548 : }
549 : }
550 0 : layout_visible_classifier_iter_destroy( &classifer_iterator );
551 :
552 0 : U8_TRACE_END();
553 0 : }
554 :
555 0 : void pencil_classifier_1d_layouter_private_linear_horizontal( const pencil_classifier_1d_layouter_t *this_,
556 : const universal_array_index_sorter_t *classifier_list,
557 : const geometry_rectangle_t *dest_rect,
558 : geometry_v_align_t v_alignment )
559 : {
560 0 : U8_TRACE_BEGIN();
561 :
562 : /* get the destination rectangle coordinates */
563 0 : const double diag_x = geometry_rectangle_get_left( (*this_).diagram_draw_area );
564 0 : const double diag_w = geometry_rectangle_get_width( (*this_).diagram_draw_area );
565 0 : const double dest_left = geometry_rectangle_get_left( dest_rect );
566 0 : const double dest_right = geometry_rectangle_get_right( dest_rect );
567 :
568 : /* update the classifier coordinates */
569 : layout_visible_classifier_iter_t classifer_iterator;
570 0 : layout_visible_classifier_iter_init( &classifer_iterator, (*this_).layout_data, classifier_list );
571 0 : while( layout_visible_classifier_iter_has_next( &classifer_iterator ) )
572 : {
573 : layout_visible_classifier_t *const visible_classifier2
574 0 : = layout_visible_classifier_iter_next_ptr( &classifer_iterator );
575 :
576 : /* get envelope */
577 : const geometry_rectangle_t envelope
578 0 : = layout_visible_classifier_get_envelope_box( visible_classifier2 );
579 0 : const double envelope_top = geometry_rectangle_get_top( &envelope );
580 0 : const double envelope_height = geometry_rectangle_get_height( &envelope );
581 0 : const double envelope_left = geometry_rectangle_get_left( &envelope );
582 0 : const double envelope_width = geometry_rectangle_get_width( &envelope );
583 :
584 : /* calc x */
585 : const data_visible_classifier_t *const visible_classifier_data
586 0 : = layout_visible_classifier_get_data_const ( visible_classifier2 );
587 0 : const data_classifier_t *const classifier2 = data_visible_classifier_get_classifier_const( visible_classifier_data );
588 0 : const int32_t list_order = data_classifier_get_list_order( classifier2 );
589 0 : const double x_value_rel = (list_order/((double)UINT32_MAX))+0.5;
590 0 : double new_left = diag_x + (diag_w-envelope_width)*x_value_rel;
591 0 : if ( (new_left+envelope_width) > dest_right )
592 : {
593 0 : new_left = dest_right - envelope_width;
594 : }
595 0 : if ( new_left < dest_left )
596 : {
597 0 : new_left = dest_left;
598 : }
599 0 : const double delta_x = new_left - envelope_left;
600 :
601 : /* calc y */
602 0 : const double dest_top = geometry_v_align_get_top( &v_alignment,
603 : envelope_height,
604 : geometry_rectangle_get_top( dest_rect ),
605 : geometry_rectangle_get_height( dest_rect )
606 : );
607 0 : const double delta_y = dest_top - envelope_top;
608 0 : const geometry_offset_t offset = geometry_offset_new( delta_x, delta_y );
609 :
610 0 : layout_visible_classifier_shift( visible_classifier2, &offset );
611 : }
612 0 : layout_visible_classifier_iter_destroy( &classifer_iterator );
613 :
614 0 : U8_TRACE_END();
615 0 : }
616 :
617 0 : void pencil_classifier_1d_layouter_private_linear_vertical( const pencil_classifier_1d_layouter_t *this_,
618 : const universal_array_index_sorter_t *classifier_list,
619 : const geometry_rectangle_t *dest_rect,
620 : geometry_h_align_t h_alignment )
621 : {
622 0 : U8_TRACE_BEGIN();
623 :
624 : /* get the destination rectangle coordinates */
625 0 : const double diag_y = geometry_rectangle_get_top( (*this_).diagram_draw_area );
626 0 : const double diag_h = geometry_rectangle_get_height( (*this_).diagram_draw_area );
627 0 : const double dest_top = geometry_rectangle_get_top( dest_rect );
628 0 : const double dest_bottom = geometry_rectangle_get_bottom( dest_rect );
629 :
630 : /* update the classifier coordinates */
631 : layout_visible_classifier_iter_t classifer_iterator;
632 0 : layout_visible_classifier_iter_init( &classifer_iterator, (*this_).layout_data, classifier_list );
633 0 : while( layout_visible_classifier_iter_has_next( &classifer_iterator ) )
634 : {
635 : layout_visible_classifier_t *const visible_classifier2
636 0 : = layout_visible_classifier_iter_next_ptr( &classifer_iterator );
637 :
638 : /* get envelope */
639 : const geometry_rectangle_t envelope
640 0 : = layout_visible_classifier_get_envelope_box( visible_classifier2 );
641 0 : const double envelope_top = geometry_rectangle_get_top( &envelope );
642 0 : const double envelope_height = geometry_rectangle_get_height( &envelope );
643 0 : const double envelope_left = geometry_rectangle_get_left( &envelope );
644 0 : const double envelope_width = geometry_rectangle_get_width( &envelope );
645 :
646 : /* calc x */
647 0 : const double dest_left = geometry_h_align_get_left( &h_alignment,
648 : envelope_width,
649 : geometry_rectangle_get_left( dest_rect ),
650 : geometry_rectangle_get_width( dest_rect )
651 : );
652 0 : const double delta_x = dest_left - envelope_left;
653 :
654 : /* calc y */
655 : const data_visible_classifier_t *const visible_classifier_data
656 0 : = layout_visible_classifier_get_data_const ( visible_classifier2 );
657 0 : const data_classifier_t *const classifier2 = data_visible_classifier_get_classifier_const( visible_classifier_data );
658 0 : const int32_t list_order = data_classifier_get_list_order( classifier2 );
659 0 : const double y_value_rel = (list_order/((double)UINT32_MAX))+0.5;
660 0 : double new_top = diag_y + (diag_h-envelope_height)*y_value_rel;
661 0 : if ( (new_top+envelope_height) > dest_bottom )
662 : {
663 0 : new_top = dest_bottom - envelope_height;
664 : }
665 0 : if ( new_top < dest_top )
666 : {
667 0 : new_top = dest_top;
668 : }
669 0 : const double delta_y = new_top - envelope_top;
670 0 : const geometry_offset_t offset = geometry_offset_new( delta_x, delta_y );
671 :
672 0 : layout_visible_classifier_shift( visible_classifier2, &offset );
673 :
674 : }
675 0 : layout_visible_classifier_iter_destroy( &classifer_iterator );
676 :
677 0 : U8_TRACE_END();
678 0 : }
679 :
680 :
681 : /*
682 : Copyright 2017-2026 Andreas Warnke
683 :
684 : Licensed under the Apache License, Version 2.0 (the "License");
685 : you may not use this file except in compliance with the License.
686 : You may obtain a copy of the License at
687 :
688 : http://www.apache.org/licenses/LICENSE-2.0
689 :
690 : Unless required by applicable law or agreed to in writing, software
691 : distributed under the License is distributed on an "AS IS" BASIS,
692 : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
693 : See the License for the specific language governing permissions and
694 : limitations under the License.
695 : */
|