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