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