Line data Source code
1 : /* File: draw_classifier_contour.c; Copyright and License: see below */
2 :
3 : #include "draw/draw_classifier_contour.h"
4 : #include "draw/draw_classifier_icon.h"
5 : #include "u8/u8_trace.h"
6 : #include <stdio.h>
7 : #include <stdlib.h>
8 : #include <assert.h>
9 : #include <math.h>
10 :
11 : /*! where to place the control points of a bezier curve to get a good approximation for a 90 degree curve */
12 : const static double BEZIER_CTRL_POINT_FOR_90_DEGREE_CIRCLE = 0.552284749831;
13 :
14 : const static double SINUS_OF_45_DEGREE = 0.707106781;
15 :
16 161 : geometry_rectangle_t draw_classifier_contour_calc_inner_area ( const draw_classifier_contour_t *this_,
17 : data_classifier_type_t classifier_type,
18 : const geometry_rectangle_t *outer_bounds,
19 : const pencil_size_t *pencil_size )
20 : {
21 161 : U8_TRACE_BEGIN();
22 161 : assert ( NULL != outer_bounds );
23 161 : assert ( NULL != pencil_size );
24 :
25 : geometry_rectangle_t result;
26 161 : geometry_rectangle_init_empty( &result );
27 :
28 161 : double gap = pencil_size_get_standard_object_border( pencil_size );
29 161 : double double_gap = 2.0 * gap; /* a line has the gap distance on both sides to the next object */
30 :
31 161 : switch ( classifier_type )
32 : {
33 6 : case DATA_CLASSIFIER_TYPE_USE_CASE:
34 : {
35 : /* within a use case, space is limited (double_gap is the border on each side): */
36 6 : double inner_x_radius = 0.5 * geometry_rectangle_get_width( outer_bounds ) - double_gap;
37 6 : double inner_y_radius = 0.5 * geometry_rectangle_get_height( outer_bounds ) - double_gap;
38 6 : double h_offset = (1.0 - SINUS_OF_45_DEGREE) * inner_x_radius;
39 6 : double v_offset = (1.0 - SINUS_OF_45_DEGREE) * inner_y_radius;
40 :
41 6 : geometry_rectangle_replace( &result, outer_bounds );
42 6 : geometry_rectangle_expand_4dir( &result, -double_gap - h_offset, -double_gap - v_offset );
43 : }
44 6 : break;
45 :
46 5 : case DATA_CLASSIFIER_TYPE_NODE:
47 : {
48 : /* the 3d border of a node shrinks the space */
49 5 : double offset_3d = double_gap;
50 :
51 5 : geometry_rectangle_replace( &result, outer_bounds );
52 5 : geometry_rectangle_enlarge( &result, -2.0 * double_gap - offset_3d, -2.0 * double_gap - offset_3d );
53 5 : geometry_rectangle_shift( &result, double_gap, double_gap + offset_3d );
54 : }
55 5 : break;
56 :
57 45 : case DATA_CLASSIFIER_TYPE_ACTOR:
58 : case DATA_CLASSIFIER_TYPE_DYN_INITIAL_NODE:
59 : case DATA_CLASSIFIER_TYPE_DYN_FINAL_NODE:
60 : case DATA_CLASSIFIER_TYPE_DYN_FORK_NODE:
61 : case DATA_CLASSIFIER_TYPE_DYN_JOIN_NODE:
62 : case DATA_CLASSIFIER_TYPE_DYN_SHALLOW_HISTORY:
63 : case DATA_CLASSIFIER_TYPE_DYN_DEEP_HISTORY:
64 : case DATA_CLASSIFIER_TYPE_DYN_ACCEPT_TIME_EVENT:
65 : case DATA_CLASSIFIER_TYPE_IMAGE:
66 : {
67 : /* the symbol icon height is part of the shape border */
68 45 : double symbol_icon_height = pencil_size_get_classifier_symbol_height( pencil_size );
69 :
70 45 : geometry_rectangle_replace( &result, outer_bounds );
71 45 : geometry_rectangle_enlarge( &result, -2.0 * double_gap, -2.0 * double_gap - symbol_icon_height );
72 45 : geometry_rectangle_shift( &result, double_gap, double_gap + symbol_icon_height );
73 : }
74 45 : break;
75 :
76 20 : case DATA_CLASSIFIER_TYPE_DIAGRAM_REFERENCE: /* and */
77 : case DATA_CLASSIFIER_TYPE_INTERACTION: /* and */
78 : case DATA_CLASSIFIER_TYPE_PACKAGE: /* and */
79 : case DATA_CLASSIFIER_TYPE_COMMENT:
80 : {
81 20 : double top_ornament_height = pencil_size_get_standard_font_size( pencil_size );
82 :
83 20 : geometry_rectangle_replace( &result, outer_bounds );
84 20 : geometry_rectangle_enlarge( &result, -2.0 * double_gap, -2.0 * double_gap - top_ornament_height );
85 20 : geometry_rectangle_shift( &result, double_gap, double_gap + top_ornament_height );
86 : }
87 20 : break;
88 :
89 70 : case DATA_CLASSIFIER_TYPE_BLOCK:
90 : case DATA_CLASSIFIER_TYPE_REQUIREMENT:
91 : case DATA_CLASSIFIER_TYPE_SUBSYSTEM:
92 : case DATA_CLASSIFIER_TYPE_ACTIVITY:
93 : case DATA_CLASSIFIER_TYPE_STATE:
94 : case DATA_CLASSIFIER_TYPE_COMPONENT:
95 : case DATA_CLASSIFIER_TYPE_PART:
96 : case DATA_CLASSIFIER_TYPE_INTERFACE:
97 : case DATA_CLASSIFIER_TYPE_CLASS:
98 : case DATA_CLASSIFIER_TYPE_OBJECT:
99 : case DATA_CLASSIFIER_TYPE_ARTIFACT:
100 : case DATA_CLASSIFIER_TYPE_CONSTRAINT_BLOCK:
101 : case DATA_CLASSIFIER_TYPE_DYN_INTERRUPTABLE_REGION:
102 : case DATA_CLASSIFIER_TYPE_STEREOTYPE:
103 : {
104 : /* standard size */
105 70 : geometry_rectangle_replace( &result, outer_bounds );
106 70 : geometry_rectangle_expand_4dir( &result, -double_gap, -double_gap );
107 : }
108 70 : break;
109 :
110 5 : case DATA_CLASSIFIER_TYPE_DYN_DECISION_NODE:
111 : {
112 : /* within a decision rhombus, space is limited by factor 2 per dimension: */
113 5 : double half_outer_width = 0.5 * geometry_rectangle_get_width( outer_bounds ) - double_gap;
114 5 : double half_outer_height = 0.5 * geometry_rectangle_get_height( outer_bounds ) - double_gap;
115 5 : double h_offset = 0.5 * half_outer_width;
116 5 : double v_offset = 0.5 * half_outer_height;
117 :
118 5 : geometry_rectangle_replace( &result, outer_bounds );
119 5 : geometry_rectangle_expand_4dir( &result, -double_gap - h_offset, -double_gap - v_offset );
120 : }
121 5 : break;
122 :
123 5 : case DATA_CLASSIFIER_TYPE_DYN_ACCEPT_EVENT :
124 : {
125 : /* within an accept event, space is limited (double_gap is the border on each side): */
126 5 : double half_outer_height = 0.5 * geometry_rectangle_get_height( outer_bounds ) - double_gap;
127 5 : double horizontal_offset = half_outer_height;
128 :
129 5 : geometry_rectangle_replace( &result, outer_bounds );
130 5 : geometry_rectangle_enlarge( &result, -2.0 * double_gap - horizontal_offset, -2.0 * double_gap );
131 5 : geometry_rectangle_shift( &result, double_gap + horizontal_offset, double_gap );
132 : }
133 5 : break;
134 :
135 5 : case DATA_CLASSIFIER_TYPE_DYN_SEND_SIGNAL:
136 : {
137 : /* within a send signal, space is limited (double_gap is the border on each side): */
138 5 : double half_outer_height = 0.5 * geometry_rectangle_get_height( outer_bounds ) - double_gap;
139 5 : double horizontal_offset = half_outer_height;
140 :
141 5 : geometry_rectangle_replace( &result, outer_bounds );
142 5 : geometry_rectangle_enlarge( &result, -2.0 * double_gap - horizontal_offset, -2.0 * double_gap );
143 5 : geometry_rectangle_shift( &result, double_gap, double_gap );
144 : }
145 5 : break;
146 :
147 0 : default:
148 : {
149 : /* this case can happen if a model file of a new cfu version is opened with an older version of cfu */
150 0 : U8_LOG_ANOMALY("unknown data_classifier_type_t in draw_classifier_contour_calc_inner_area()");
151 : /* assume standard size */
152 0 : geometry_rectangle_replace( &result, outer_bounds );
153 0 : geometry_rectangle_expand_4dir( &result, -double_gap, -double_gap );
154 : }
155 0 : break;
156 : }
157 :
158 161 : U8_TRACE_END();
159 161 : return result;
160 : }
161 :
162 128 : geometry_rectangle_t draw_classifier_contour_calc_outer_bounds ( const draw_classifier_contour_t *this_,
163 : data_classifier_type_t classifier_type,
164 : const geometry_rectangle_t *inner_area,
165 : const pencil_size_t *pencil_size )
166 : {
167 128 : U8_TRACE_BEGIN();
168 128 : assert ( NULL != inner_area );
169 128 : assert ( NULL != pencil_size );
170 :
171 : geometry_rectangle_t result;
172 128 : geometry_rectangle_init_empty( &result );
173 :
174 128 : double gap = pencil_size_get_standard_object_border( pencil_size );
175 128 : double double_gap = 2.0 * gap; /* a line has the gap distance on both sides to the next object */
176 :
177 128 : switch ( classifier_type )
178 : {
179 5 : case DATA_CLASSIFIER_TYPE_USE_CASE:
180 : {
181 : /* within a use case, space is limited (double_gap is the border on each side): */
182 5 : double half_inner_width = 0.5 * geometry_rectangle_get_width( inner_area );
183 5 : double half_inner_height = 0.5 * geometry_rectangle_get_height( inner_area );
184 5 : double h_offset = half_inner_width * ( 1.0 / SINUS_OF_45_DEGREE - 1.0 );
185 5 : double v_offset = half_inner_height * ( 1.0 / SINUS_OF_45_DEGREE - 1.0 );
186 :
187 5 : geometry_rectangle_replace( &result, inner_area );
188 5 : geometry_rectangle_expand_4dir( &result, +double_gap + h_offset, +double_gap + v_offset );
189 : }
190 5 : break;
191 :
192 5 : case DATA_CLASSIFIER_TYPE_NODE:
193 : {
194 : /* the 3d border of a node shrinks the space */
195 5 : double offset_3d = double_gap;
196 :
197 5 : geometry_rectangle_replace( &result, inner_area );
198 5 : geometry_rectangle_enlarge( &result, +2.0 * double_gap + offset_3d, +2.0 * double_gap + offset_3d );
199 5 : geometry_rectangle_shift( &result, -double_gap, -double_gap - offset_3d );
200 : }
201 5 : break;
202 :
203 9 : case DATA_CLASSIFIER_TYPE_ACTOR:
204 : case DATA_CLASSIFIER_TYPE_DYN_INITIAL_NODE:
205 : case DATA_CLASSIFIER_TYPE_DYN_FINAL_NODE:
206 : case DATA_CLASSIFIER_TYPE_DYN_FORK_NODE:
207 : case DATA_CLASSIFIER_TYPE_DYN_JOIN_NODE:
208 : case DATA_CLASSIFIER_TYPE_DYN_SHALLOW_HISTORY:
209 : case DATA_CLASSIFIER_TYPE_DYN_DEEP_HISTORY:
210 : case DATA_CLASSIFIER_TYPE_DYN_ACCEPT_TIME_EVENT:
211 : case DATA_CLASSIFIER_TYPE_IMAGE:
212 : {
213 : /* the symbol icon height is part of the shape border */
214 9 : double symbol_icon_height = pencil_size_get_classifier_symbol_height( pencil_size );
215 :
216 9 : geometry_rectangle_replace( &result, inner_area );
217 9 : geometry_rectangle_enlarge( &result, +2.0 * double_gap, +2.0 * double_gap + symbol_icon_height );
218 9 : geometry_rectangle_shift( &result, -double_gap, -double_gap - symbol_icon_height );
219 : }
220 9 : break;
221 :
222 24 : case DATA_CLASSIFIER_TYPE_DIAGRAM_REFERENCE: /* and */
223 : case DATA_CLASSIFIER_TYPE_INTERACTION: /* and */
224 : case DATA_CLASSIFIER_TYPE_PACKAGE: /* and */
225 : case DATA_CLASSIFIER_TYPE_COMMENT:
226 : {
227 24 : double top_ornament_height = pencil_size_get_standard_font_size( pencil_size );
228 :
229 24 : geometry_rectangle_replace( &result, inner_area );
230 24 : geometry_rectangle_enlarge( &result, +2.0 * double_gap, +2.0 * double_gap + top_ornament_height );
231 24 : geometry_rectangle_shift( &result, -double_gap, -double_gap - top_ornament_height );
232 : }
233 24 : break;
234 :
235 70 : case DATA_CLASSIFIER_TYPE_BLOCK:
236 : case DATA_CLASSIFIER_TYPE_REQUIREMENT:
237 : case DATA_CLASSIFIER_TYPE_SUBSYSTEM:
238 : case DATA_CLASSIFIER_TYPE_ACTIVITY:
239 : case DATA_CLASSIFIER_TYPE_STATE:
240 : case DATA_CLASSIFIER_TYPE_COMPONENT:
241 : case DATA_CLASSIFIER_TYPE_PART:
242 : case DATA_CLASSIFIER_TYPE_INTERFACE:
243 : case DATA_CLASSIFIER_TYPE_CLASS:
244 : case DATA_CLASSIFIER_TYPE_OBJECT:
245 : case DATA_CLASSIFIER_TYPE_ARTIFACT:
246 : case DATA_CLASSIFIER_TYPE_CONSTRAINT_BLOCK:
247 : case DATA_CLASSIFIER_TYPE_DYN_INTERRUPTABLE_REGION:
248 : case DATA_CLASSIFIER_TYPE_STEREOTYPE:
249 : {
250 : /* standard size */
251 70 : geometry_rectangle_replace( &result, inner_area );
252 70 : geometry_rectangle_expand_4dir( &result, +double_gap, +double_gap );
253 : }
254 70 : break;
255 :
256 5 : case DATA_CLASSIFIER_TYPE_DYN_DECISION_NODE:
257 : {
258 : /* within a decision rhombus, space is limited by factor 2 per dimension: */
259 5 : double half_inner_width = 0.5 * geometry_rectangle_get_width( inner_area );
260 5 : double half_inner_height = 0.5 * geometry_rectangle_get_height( inner_area );
261 5 : double h_offset = half_inner_width;
262 5 : double v_offset = half_inner_height;
263 :
264 5 : geometry_rectangle_replace( &result, inner_area );
265 5 : geometry_rectangle_expand_4dir( &result, +double_gap + h_offset, +double_gap + v_offset );
266 : }
267 5 : break;
268 :
269 5 : case DATA_CLASSIFIER_TYPE_DYN_ACCEPT_EVENT :
270 : {
271 : /* within an accept event, space is limited (double_gap is the border on each side): */
272 5 : double half_inner_height = 0.5 * geometry_rectangle_get_height( inner_area );
273 5 : double horizontal_offset = half_inner_height;
274 :
275 5 : geometry_rectangle_replace( &result, inner_area );
276 5 : geometry_rectangle_enlarge( &result, +2.0 * double_gap + horizontal_offset, +2.0 * double_gap );
277 5 : geometry_rectangle_shift( &result, -double_gap - horizontal_offset, -double_gap );
278 : }
279 5 : break;
280 :
281 5 : case DATA_CLASSIFIER_TYPE_DYN_SEND_SIGNAL:
282 : {
283 : /* within a send signal, space is limited (double_gap is the border on each side): */
284 5 : double half_inner_height = 0.5 * geometry_rectangle_get_height( inner_area );
285 5 : double horizontal_offset = half_inner_height;
286 :
287 5 : geometry_rectangle_replace( &result, inner_area );
288 5 : geometry_rectangle_enlarge( &result, +2.0 * double_gap + horizontal_offset, +2.0 * double_gap );
289 5 : geometry_rectangle_shift( &result, -double_gap, -double_gap );
290 : }
291 5 : break;
292 :
293 0 : default:
294 : {
295 : /* this case can happen if a model file of a new cfu version is opened with an older version of cfu */
296 0 : U8_LOG_ANOMALY("unknown data_classifier_type_t in draw_classifier_contour_calc_outer_bounds()");
297 : /* assume standard size */
298 0 : geometry_rectangle_replace( &result, inner_area );
299 0 : geometry_rectangle_expand_4dir( &result, +double_gap, +double_gap );
300 : }
301 0 : break;
302 : }
303 :
304 128 : U8_TRACE_END();
305 128 : return result;
306 : }
307 :
308 0 : void draw_classifier_contour_draw_rounded_rect ( const draw_classifier_contour_t *this_,
309 : const geometry_rectangle_t *outer_bounds,
310 : bool dashed_line,
311 : const pencil_size_t *pencil_size,
312 : cairo_t *cr )
313 : {
314 0 : U8_TRACE_BEGIN();
315 0 : assert ( NULL != outer_bounds );
316 0 : assert ( NULL != pencil_size );
317 0 : assert ( NULL != cr );
318 0 : const double gap = pencil_size_get_standard_object_border( pencil_size );
319 0 : const double border_left = geometry_rectangle_get_left ( outer_bounds ) + gap;
320 0 : const double border_top = geometry_rectangle_get_top ( outer_bounds ) + gap;
321 0 : const double border_width = geometry_rectangle_get_width ( outer_bounds ) - gap - gap;
322 0 : const double border_height = geometry_rectangle_get_height ( outer_bounds ) - gap - gap;
323 0 : const double border_bottom = border_top + border_height;
324 0 : const double border_right = border_left + border_width;
325 0 : const double corner_radius = 6.0 * gap;
326 0 : const double ctrl_offset = corner_radius * (1.0-BEZIER_CTRL_POINT_FOR_90_DEGREE_CIRCLE);
327 :
328 : /* set dashes */
329 0 : if ( dashed_line )
330 : {
331 : double dashes[2];
332 0 : dashes[0] = 2.0 * pencil_size_get_line_dash_length( pencil_size );
333 0 : dashes[1] = 1.0 * pencil_size_get_line_dash_length( pencil_size );
334 0 : cairo_set_dash ( cr, dashes, 2, 0.0 );
335 : }
336 :
337 0 : cairo_move_to ( cr, border_right - corner_radius, border_bottom );
338 0 : cairo_line_to ( cr, border_left + corner_radius, border_bottom );
339 0 : cairo_curve_to ( cr, border_left + ctrl_offset, border_bottom, border_left, border_bottom - ctrl_offset, border_left /* end point x */, border_bottom - corner_radius /* end point y */ );
340 0 : cairo_line_to ( cr, border_left, border_top + corner_radius );
341 0 : cairo_curve_to ( cr, border_left, border_top + ctrl_offset, border_left + ctrl_offset, border_top, border_left + corner_radius /* end point x */, border_top /* end point y */ );
342 0 : cairo_line_to ( cr, border_right - corner_radius, border_top );
343 0 : cairo_curve_to ( cr, border_right - ctrl_offset, border_top, border_right, border_top + ctrl_offset, border_right /* end point x */, border_top + corner_radius /* end point y */ );
344 0 : cairo_line_to ( cr, border_right, border_bottom - corner_radius );
345 0 : cairo_curve_to ( cr, border_right, border_bottom - ctrl_offset, border_right - ctrl_offset, border_bottom, border_right - corner_radius /* end point x */, border_bottom /* end point y */ );
346 0 : cairo_stroke (cr);
347 :
348 : /* reset dashes */
349 0 : if ( dashed_line )
350 : {
351 0 : cairo_set_dash ( cr, NULL, 0, 0.0 );
352 : }
353 :
354 0 : U8_TRACE_END();
355 0 : }
356 :
357 0 : void draw_classifier_contour_draw_ellipse ( const draw_classifier_contour_t *this_,
358 : const geometry_rectangle_t *outer_bounds,
359 : const pencil_size_t *pencil_size,
360 : cairo_t *cr )
361 : {
362 0 : U8_TRACE_BEGIN();
363 0 : assert ( NULL != outer_bounds );
364 0 : assert ( NULL != pencil_size );
365 0 : assert ( NULL != cr );
366 0 : const double gap = pencil_size_get_standard_object_border( pencil_size );
367 0 : const double border_left = geometry_rectangle_get_left ( outer_bounds ) + gap;
368 0 : const double border_top = geometry_rectangle_get_top ( outer_bounds ) + gap;
369 0 : const double border_width = geometry_rectangle_get_width ( outer_bounds ) - gap - gap;
370 0 : const double border_height = geometry_rectangle_get_height ( outer_bounds ) - gap - gap;
371 0 : const double border_bottom = border_top + border_height;
372 0 : const double border_right = border_left + border_width;
373 0 : const double half_width = 0.5 * border_width;
374 0 : const double half_height = 0.5 * border_height;
375 0 : const double center_x = border_left + half_width;
376 0 : const double center_y = border_top + half_height;
377 0 : const double ctrl_xoffset = half_width * (1.0-BEZIER_CTRL_POINT_FOR_90_DEGREE_CIRCLE);
378 0 : const double ctrl_yoffset = half_height * (1.0-BEZIER_CTRL_POINT_FOR_90_DEGREE_CIRCLE);
379 :
380 0 : cairo_move_to ( cr, center_x, border_bottom );
381 0 : cairo_curve_to ( cr, border_left + ctrl_xoffset, border_bottom, border_left, border_bottom - ctrl_yoffset, border_left /* end point x */, center_y /* end point y */ );
382 0 : cairo_curve_to ( cr, border_left, border_top + ctrl_yoffset, border_left + ctrl_xoffset, border_top, center_x /* end point x */, border_top /* end point y */ );
383 0 : cairo_curve_to ( cr, border_right - ctrl_xoffset, border_top, border_right, border_top + ctrl_yoffset, border_right /* end point x */, center_y /* end point y */ );
384 0 : cairo_curve_to ( cr, border_right, border_bottom - ctrl_yoffset, border_right - ctrl_xoffset, border_bottom, center_x /* end point x */, border_bottom /* end point y */ );
385 0 : cairo_stroke (cr);
386 :
387 0 : U8_TRACE_END();
388 0 : }
389 :
390 0 : void draw_classifier_contour_draw_rhombus ( const draw_classifier_contour_t *this_,
391 : const geometry_rectangle_t *outer_bounds,
392 : const pencil_size_t *pencil_size,
393 : cairo_t *cr )
394 : {
395 0 : U8_TRACE_BEGIN();
396 0 : assert ( NULL != outer_bounds );
397 0 : assert ( NULL != pencil_size );
398 0 : assert ( NULL != cr );
399 0 : const double gap = pencil_size_get_standard_object_border( pencil_size );
400 0 : const double border_left = geometry_rectangle_get_left ( outer_bounds ) + gap;
401 0 : const double border_top = geometry_rectangle_get_top ( outer_bounds ) + gap;
402 0 : const double border_width = geometry_rectangle_get_width ( outer_bounds ) - gap - gap;
403 0 : const double border_height = geometry_rectangle_get_height ( outer_bounds ) - gap - gap;
404 0 : const double border_bottom = border_top + border_height;
405 0 : const double border_right = border_left + border_width;
406 0 : const double center_x = geometry_rectangle_get_center_x ( outer_bounds );
407 0 : const double center_y = geometry_rectangle_get_center_y ( outer_bounds );
408 :
409 0 : cairo_move_to ( cr, center_x, border_bottom );
410 0 : cairo_line_to ( cr, border_left, center_y );
411 0 : cairo_line_to ( cr, center_x, border_top );
412 0 : cairo_line_to ( cr, border_right, center_y );
413 0 : cairo_line_to ( cr, center_x, border_bottom );
414 0 : cairo_stroke (cr);
415 :
416 0 : U8_TRACE_END();
417 0 : }
418 :
419 0 : void draw_classifier_contour_draw_3d_box ( const draw_classifier_contour_t *this_,
420 : const geometry_rectangle_t *outer_bounds,
421 : const pencil_size_t *pencil_size,
422 : cairo_t *cr )
423 : {
424 0 : U8_TRACE_BEGIN();
425 0 : assert ( NULL != outer_bounds );
426 0 : assert ( NULL != pencil_size );
427 0 : assert ( NULL != cr );
428 0 : const double gap = pencil_size_get_standard_object_border( pencil_size );
429 0 : const double border_left = geometry_rectangle_get_left ( outer_bounds ) + gap;
430 0 : const double border_top = geometry_rectangle_get_top ( outer_bounds ) + gap;
431 0 : const double border_width = geometry_rectangle_get_width ( outer_bounds ) - gap - gap;
432 0 : const double border_height = geometry_rectangle_get_height ( outer_bounds ) - gap - gap;
433 0 : const double border_bottom = border_top + border_height;
434 0 : const double border_right = border_left + border_width;
435 0 : const double offset_3d = 2.0*gap;
436 :
437 0 : cairo_rectangle ( cr, border_left, border_top+offset_3d, border_width-offset_3d, border_height-offset_3d );
438 0 : cairo_stroke (cr);
439 :
440 0 : cairo_move_to ( cr, border_left, border_top+offset_3d );
441 0 : cairo_line_to ( cr, border_left+offset_3d, border_top );
442 0 : cairo_line_to ( cr, border_right, border_top );
443 0 : cairo_line_to ( cr, border_right, border_bottom-offset_3d );
444 0 : cairo_line_to ( cr, border_right-offset_3d, border_bottom );
445 0 : cairo_stroke (cr);
446 0 : cairo_move_to ( cr, border_right, border_top );
447 0 : cairo_line_to ( cr, border_right-offset_3d, border_top+offset_3d );
448 0 : cairo_stroke (cr);
449 :
450 0 : U8_TRACE_END();
451 0 : }
452 :
453 0 : void draw_classifier_contour_draw_accept_event ( const draw_classifier_contour_t *this_,
454 : const geometry_rectangle_t *outer_bounds,
455 : const pencil_size_t *pencil_size,
456 : cairo_t *cr )
457 : {
458 0 : U8_TRACE_BEGIN();
459 0 : assert ( NULL != outer_bounds );
460 0 : assert ( NULL != pencil_size );
461 0 : assert ( NULL != cr );
462 0 : const double gap = pencil_size_get_standard_object_border( pencil_size );
463 0 : const double border_left = geometry_rectangle_get_left ( outer_bounds ) + gap;
464 0 : const double border_top = geometry_rectangle_get_top ( outer_bounds ) + gap;
465 0 : const double border_width = geometry_rectangle_get_width ( outer_bounds ) - gap - gap;
466 0 : const double border_height = geometry_rectangle_get_height ( outer_bounds ) - gap - gap;
467 0 : const double border_bottom = border_top + border_height;
468 0 : const double border_right = border_left + border_width;
469 0 : const double center_y = geometry_rectangle_get_center_y ( outer_bounds );
470 0 : const double x_indent = border_height / 2.0;
471 :
472 0 : cairo_move_to ( cr, border_right, border_bottom );
473 0 : cairo_line_to ( cr, border_right, border_top );
474 0 : cairo_line_to ( cr, border_left, border_top );
475 0 : cairo_line_to ( cr, border_left + x_indent, center_y );
476 0 : cairo_line_to ( cr, border_left, border_bottom );
477 0 : cairo_line_to ( cr, border_right, border_bottom );
478 0 : cairo_stroke (cr);
479 :
480 0 : U8_TRACE_END();
481 0 : }
482 :
483 0 : void draw_classifier_contour_draw_send_signal ( const draw_classifier_contour_t *this_,
484 : const geometry_rectangle_t *outer_bounds,
485 : const pencil_size_t *pencil_size,
486 : cairo_t *cr )
487 : {
488 0 : U8_TRACE_BEGIN();
489 0 : assert ( NULL != outer_bounds );
490 0 : assert ( NULL != pencil_size );
491 0 : assert ( NULL != cr );
492 0 : const double gap = pencil_size_get_standard_object_border( pencil_size );
493 0 : const double border_left = geometry_rectangle_get_left ( outer_bounds ) + gap;
494 0 : const double border_top = geometry_rectangle_get_top ( outer_bounds ) + gap;
495 0 : const double border_width = geometry_rectangle_get_width ( outer_bounds ) - gap - gap;
496 0 : const double border_height = geometry_rectangle_get_height ( outer_bounds ) - gap - gap;
497 0 : const double border_bottom = border_top + border_height;
498 0 : const double border_right = border_left + border_width;
499 0 : const double center_y = geometry_rectangle_get_center_y ( outer_bounds );
500 0 : const double x_indent = border_height / 2.0;
501 :
502 0 : cairo_move_to ( cr, border_right - x_indent, border_bottom );
503 0 : cairo_line_to ( cr, border_right, center_y );
504 0 : cairo_line_to ( cr, border_right - x_indent, border_top );
505 0 : cairo_line_to ( cr, border_left, border_top );
506 0 : cairo_line_to ( cr, border_left, border_bottom );
507 0 : cairo_line_to ( cr, border_right - x_indent, border_bottom );
508 0 : cairo_stroke (cr);
509 :
510 0 : U8_TRACE_END();
511 0 : }
512 :
513 0 : void draw_classifier_contour_draw_package ( const draw_classifier_contour_t *this_,
514 : const geometry_rectangle_t *outer_bounds,
515 : const geometry_rectangle_t *label_box,
516 : const pencil_size_t *pencil_size,
517 : cairo_t *cr )
518 : {
519 0 : U8_TRACE_BEGIN();
520 0 : assert ( NULL != outer_bounds );
521 0 : assert ( NULL != pencil_size );
522 0 : assert ( NULL != cr );
523 0 : const double gap = pencil_size_get_standard_object_border( pencil_size );
524 0 : const double border_left = geometry_rectangle_get_left ( outer_bounds ) + gap;
525 0 : const double border_top = geometry_rectangle_get_top ( outer_bounds ) + gap;
526 0 : const double border_width = geometry_rectangle_get_width ( outer_bounds ) - gap - gap;
527 0 : const double border_height = geometry_rectangle_get_height ( outer_bounds ) - gap - gap;
528 :
529 : double tab_width;
530 : double tab_height;
531 0 : const bool label_in_tab = ( geometry_rectangle_get_top( label_box ) < (border_top + gap + gap) );
532 0 : if ( label_in_tab )
533 : {
534 0 : tab_width = geometry_rectangle_get_width ( label_box ) + gap + gap;
535 0 : tab_height = geometry_rectangle_get_height ( label_box ) + gap;
536 : }
537 : else
538 : {
539 0 : tab_width = border_width/3.0;
540 0 : tab_height = pencil_size_get_standard_font_size( pencil_size );
541 : }
542 0 : cairo_rectangle ( cr, border_left, border_top, tab_width, tab_height );
543 0 : cairo_rectangle ( cr, border_left, border_top+tab_height, border_width, border_height-tab_height );
544 0 : cairo_stroke (cr);
545 :
546 0 : U8_TRACE_END();
547 0 : }
548 :
549 0 : void draw_classifier_contour_draw_diagram_ref ( const draw_classifier_contour_t *this_,
550 : const geometry_rectangle_t *outer_bounds,
551 : const pencil_size_t *pencil_size,
552 : cairo_t *cr )
553 : {
554 0 : U8_TRACE_BEGIN();
555 0 : assert ( NULL != outer_bounds );
556 0 : assert ( NULL != pencil_size );
557 0 : assert ( NULL != cr );
558 0 : const double gap = pencil_size_get_standard_object_border( pencil_size );
559 0 : const double border_left = geometry_rectangle_get_left ( outer_bounds ) + gap;
560 0 : const double border_top = geometry_rectangle_get_top ( outer_bounds ) + gap;
561 0 : const double border_width = geometry_rectangle_get_width ( outer_bounds ) - gap - gap;
562 0 : const double border_height = geometry_rectangle_get_height ( outer_bounds ) - gap - gap;
563 0 : const double title_corner_height = pencil_size_get_standard_font_size( pencil_size );
564 0 : const double title_corner_edge45 = 0.4 * title_corner_height;
565 0 : const double title_corner_width = border_width/5.0;
566 :
567 0 : cairo_rectangle ( cr, border_left, border_top, border_width, border_height );
568 0 : cairo_move_to ( cr, border_left, border_top+title_corner_height );
569 0 : cairo_line_to ( cr, border_left+title_corner_width - title_corner_edge45, border_top+title_corner_height );
570 0 : cairo_line_to ( cr, border_left+title_corner_width, border_top+title_corner_height-title_corner_edge45 );
571 0 : cairo_line_to ( cr, border_left+title_corner_width, border_top );
572 0 : cairo_stroke (cr);
573 :
574 0 : U8_TRACE_END();
575 0 : }
576 :
577 0 : void draw_classifier_contour_draw_comment ( const draw_classifier_contour_t *this_,
578 : const geometry_rectangle_t *outer_bounds,
579 : const pencil_size_t *pencil_size,
580 : cairo_t *cr )
581 : {
582 0 : U8_TRACE_BEGIN();
583 0 : assert ( NULL != outer_bounds );
584 0 : assert ( NULL != pencil_size );
585 0 : assert ( NULL != cr );
586 0 : const double gap = pencil_size_get_standard_object_border( pencil_size );
587 0 : const double border_left = geometry_rectangle_get_left ( outer_bounds ) + gap;
588 0 : const double border_top = geometry_rectangle_get_top ( outer_bounds ) + gap;
589 0 : const double border_width = geometry_rectangle_get_width ( outer_bounds ) - gap - gap;
590 0 : const double border_height = geometry_rectangle_get_height ( outer_bounds ) - gap - gap;
591 0 : const double corner_edge = pencil_size_get_standard_font_size( pencil_size );
592 0 : const double border_bottom = border_top + border_height;
593 0 : const double border_right = border_left + border_width;
594 :
595 0 : cairo_move_to ( cr, border_right, border_top + corner_edge );
596 0 : cairo_line_to ( cr, border_right - corner_edge, border_top + corner_edge );
597 0 : cairo_line_to ( cr, border_right - corner_edge, border_top );
598 0 : cairo_line_to ( cr, border_left, border_top );
599 0 : cairo_line_to ( cr, border_left, border_bottom );
600 0 : cairo_line_to ( cr, border_right, border_bottom );
601 0 : cairo_line_to ( cr, border_right, border_top + corner_edge );
602 0 : cairo_line_to ( cr, border_right - corner_edge, border_top );
603 0 : cairo_stroke (cr);
604 :
605 0 : U8_TRACE_END();
606 0 : }
607 :
608 0 : void draw_classifier_contour_draw_compartment_line ( const draw_classifier_contour_t *this_,
609 : data_classifier_type_t classifier_type,
610 : const geometry_rectangle_t *outer_bounds,
611 : double y_coordinate,
612 : const pencil_size_t *pencil_size,
613 : cairo_t *cr )
614 : {
615 0 : U8_TRACE_BEGIN();
616 0 : assert ( NULL != outer_bounds );
617 0 : assert ( NULL != pencil_size );
618 0 : assert ( NULL != cr );
619 :
620 0 : const double bounds_left = geometry_rectangle_get_left( outer_bounds );
621 0 : const double bounds_width = geometry_rectangle_get_width( outer_bounds );
622 0 : const double bounds_height = geometry_rectangle_get_height( outer_bounds );
623 0 : const double gap = pencil_size_get_standard_object_border( pencil_size );
624 :
625 0 : double left = bounds_left + gap;
626 0 : double right = bounds_left + bounds_width - gap;
627 0 : switch ( classifier_type )
628 : {
629 0 : case DATA_CLASSIFIER_TYPE_USE_CASE:
630 : {
631 0 : const double center_x = geometry_rectangle_get_center_x( outer_bounds );
632 0 : const double center_y = geometry_rectangle_get_center_y( outer_bounds );
633 0 : const double radius_x = ( bounds_width / 2.0 ) - gap; /* there is 1.0*gap around the ellipsis */
634 0 : const double radius_y = ( bounds_height / 2.0 ) - gap; /* there is 1.0*gap around the ellipsis */
635 0 : const double norm_dy = ( y_coordinate - center_y ) / radius_y;
636 0 : const double sqr_norm_dx = 1.0 - ( norm_dy * norm_dy );
637 0 : if ( sqr_norm_dx >= 0.0 )
638 : {
639 0 : const double dx = sqrt( sqr_norm_dx ) * radius_x;
640 0 : left = center_x - dx;
641 0 : right = center_x + dx;
642 : }
643 : else
644 : {
645 0 : left = bounds_left + gap;
646 0 : right = bounds_left + bounds_width - gap;
647 : }
648 : }
649 0 : break;
650 :
651 0 : case DATA_CLASSIFIER_TYPE_NODE:
652 : {
653 : /* the 3d border of a node shrinks the space */
654 0 : const double offset_3d = 2.0 * gap;
655 0 : left = bounds_left + gap;
656 0 : right = bounds_left + bounds_width - offset_3d - gap;
657 : }
658 0 : break;
659 :
660 0 : default:
661 : {
662 : /* for all other cases; this switch is not exhaustive */
663 0 : left = bounds_left + gap;
664 0 : right = bounds_left + bounds_width - gap;
665 : }
666 0 : break;
667 : }
668 :
669 0 : cairo_move_to ( cr, left, y_coordinate );
670 0 : cairo_line_to ( cr, right, y_coordinate );
671 0 : cairo_stroke (cr);
672 :
673 0 : U8_TRACE_END();
674 0 : }
675 :
676 :
677 : /*
678 : Copyright 2016-2024 Andreas Warnke
679 : http://www.apache.org/licenses/LICENSE-2.0
680 :
681 : Licensed under the Apache License, Version 2.0 (the "License");
682 : you may not use this file except in compliance with the License.
683 : You may obtain a copy of the License at
684 :
685 :
686 : Unless required by applicable law or agreed to in writing, software
687 : distributed under the License is distributed on an "AS IS" BASIS,
688 : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
689 : See the License for the specific language governing permissions and
690 : limitations under the License.
691 : */
|