Line data Source code
1 : /* File: pencil_diagram_maker.c; Copyright and License: see below */
2 :
3 : #include "pencil_diagram_maker.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_diagram_maker_draw_rects_callback ( void *data,
11 : const geometry_rectangle_t *rect_a,
12 : const geometry_rectangle_t *rect_b )
13 : {
14 0 : assert( NULL != data );
15 0 : assert( NULL != rect_a );
16 0 : assert( NULL != rect_b );
17 0 : cairo_t *cr = data;
18 0 : cairo_set_source_rgba( cr, 1.0, 0.8, 0.8, 1.0 );
19 0 : cairo_rectangle ( cr,
20 : geometry_rectangle_get_left ( rect_a ),
21 : geometry_rectangle_get_top ( rect_a ),
22 : geometry_rectangle_get_width ( rect_a ),
23 : geometry_rectangle_get_height ( rect_a )
24 : );
25 0 : cairo_rectangle ( cr,
26 : geometry_rectangle_get_left ( rect_b ),
27 : geometry_rectangle_get_top ( rect_b ),
28 : geometry_rectangle_get_width ( rect_b ),
29 : geometry_rectangle_get_height ( rect_b )
30 : );
31 0 : cairo_stroke (cr);
32 :
33 : geometry_rectangle_t isect;
34 0 : const int err_no_intersect = geometry_rectangle_init_by_intersect( &isect, rect_a, rect_b );
35 0 : if ( err_no_intersect == 0 )
36 : {
37 0 : cairo_rectangle ( cr,
38 : geometry_rectangle_get_left ( &isect ),
39 : geometry_rectangle_get_top ( &isect ),
40 : geometry_rectangle_get_width ( &isect ),
41 : geometry_rectangle_get_height ( &isect )
42 : );
43 0 : cairo_fill (cr);
44 0 : geometry_rectangle_destroy( &isect );
45 : }
46 0 : }
47 :
48 0 : void pencil_diagram_maker_show_overlaps ( pencil_diagram_maker_t *this_,
49 : data_stat_t *io_layout_stat,
50 : cairo_t *cr )
51 : {
52 : data_stat_t dummy_layout_stats;
53 0 : data_stat_init( &dummy_layout_stats );
54 0 : pencil_layout_data_analyze( pencil_layouter_get_layout_data_const( &((*this_).layouter) ),
55 : (io_layout_stat == NULL) ? &dummy_layout_stats : io_layout_stat,
56 : pencil_diagram_maker_draw_rects_callback,
57 : cr
58 : );
59 0 : data_stat_destroy( &dummy_layout_stats );
60 0 : }
61 :
62 0 : void pencil_diagram_maker_draw ( pencil_diagram_maker_t *this_,
63 : data_id_t mark_focused,
64 : data_id_t mark_highlighted,
65 : const data_small_set_t *mark_selected,
66 : cairo_t *cr )
67 : {
68 0 : U8_TRACE_BEGIN();
69 0 : assert( NULL != mark_selected );
70 0 : assert( NULL != cr );
71 :
72 : PangoLayout *layout;
73 0 : layout = pango_cairo_create_layout (cr);
74 :
75 : /* get layout data object */
76 0 : const pencil_layout_data_t *const layout_data = pencil_layouter_get_layout_data_const ( &((*this_).layouter) );
77 :
78 : /* get diagram bounds */
79 0 : const layout_diagram_t *const diagram_layout = pencil_layout_data_get_diagram_const( layout_data );
80 0 : const geometry_rectangle_t *const diagram_bounds = layout_diagram_get_bounds_const ( diagram_layout );
81 0 : double width = geometry_rectangle_get_width ( diagram_bounds );
82 0 : double height = geometry_rectangle_get_height ( diagram_bounds );
83 :
84 0 : const pencil_size_t *const pencil_size = pencil_layouter_get_pencil_size_const( &((*this_).layouter) );
85 :
86 : /* draw diagram */
87 0 : const data_diagram_t *diag = data_visible_set_get_diagram_const( (*this_).input_data );
88 0 : pencil_diagram_painter_draw ( &((*this_).diagram_painter),
89 : diagram_layout,
90 : data_id_equals_id( &mark_focused, DATA_TABLE_DIAGRAM, data_diagram_get_row_id(diag) ),
91 : data_id_equals_id( &mark_highlighted, DATA_TABLE_DIAGRAM, data_diagram_get_row_id(diag) ),
92 : data_small_set_contains_row_id( mark_selected, DATA_TABLE_DIAGRAM, data_diagram_get_row_id(diag) ),
93 : (*this_).profile,
94 : pencil_size,
95 : layout,
96 : cr
97 : );
98 :
99 0 : if (( width > 20.0 ) && ( height > 20.0 ))
100 : {
101 : /* draw all contained classifiers */
102 0 : pencil_diagram_maker_private_draw_classifiers ( this_,
103 : mark_focused,
104 : mark_highlighted,
105 : mark_selected,
106 : layout,
107 : cr
108 : );
109 :
110 : /* draw all contained features */
111 0 : pencil_diagram_maker_private_draw_features ( this_,
112 : mark_focused,
113 : mark_highlighted,
114 : mark_selected,
115 : layout,
116 : cr
117 : );
118 :
119 : /* draw all contained relationships */
120 0 : pencil_diagram_maker_private_draw_relationships ( this_,
121 : mark_focused,
122 : mark_highlighted,
123 : mark_selected,
124 : layout,
125 : cr
126 : );
127 : }
128 :
129 0 : g_object_unref (layout);
130 :
131 0 : U8_TRACE_END();
132 0 : }
133 :
134 0 : void pencil_diagram_maker_private_draw_classifiers ( pencil_diagram_maker_t *this_,
135 : data_id_t mark_focused,
136 : data_id_t mark_highlighted,
137 : const data_small_set_t *mark_selected,
138 : PangoLayout *layout,
139 : cairo_t *cr )
140 : {
141 0 : U8_TRACE_BEGIN();
142 0 : assert( NULL != mark_selected );
143 0 : assert( NULL != cr );
144 :
145 0 : const pencil_layout_data_t *const layout_data = pencil_layouter_get_layout_data_const ( &((*this_).layouter) );
146 :
147 : /* iterate over all classifiers */
148 0 : const uint32_t count = pencil_layout_data_get_visible_classifier_count ( layout_data );
149 0 : for ( uint32_t index = 0; index < count; index ++ )
150 : {
151 0 : const layout_visible_classifier_t *const classifier_layout = pencil_layout_data_get_visible_classifier_const( layout_data, index );
152 :
153 0 : const pencil_size_t *const pencil_size = pencil_layouter_get_pencil_size_const( &((*this_).layouter) );
154 :
155 0 : pencil_classifier_composer_draw( &((*this_).classifier_painter),
156 : classifier_layout,
157 : mark_focused,
158 : mark_highlighted,
159 : mark_selected,
160 : layout_data,
161 : (*this_).profile,
162 : pencil_size,
163 : layout,
164 : cr
165 : );
166 : }
167 :
168 0 : U8_TRACE_END();
169 0 : }
170 :
171 0 : void pencil_diagram_maker_private_draw_features ( pencil_diagram_maker_t *this_,
172 : data_id_t mark_focused,
173 : data_id_t mark_highlighted,
174 : const data_small_set_t *mark_selected,
175 : PangoLayout *layout,
176 : cairo_t *cr )
177 : {
178 0 : U8_TRACE_BEGIN();
179 0 : assert( NULL != mark_selected );
180 0 : assert( NULL != cr );
181 :
182 0 : const pencil_layout_data_t *const layout_data = pencil_layouter_get_layout_data_const ( &((*this_).layouter) );
183 :
184 : /* iterate over all features */
185 0 : const uint32_t count = pencil_layout_data_get_feature_count ( layout_data );
186 0 : for ( uint32_t f_idx = 0; f_idx < count; f_idx ++ )
187 : {
188 : /* get feature */
189 0 : const layout_feature_t *const the_feature = pencil_layout_data_get_feature_const( layout_data, f_idx );
190 :
191 : /* determine display flags of diagramelement */
192 0 : const layout_visible_classifier_t *const classifier_layout = layout_feature_get_classifier_const ( the_feature );
193 0 : const data_diagramelement_t *const diagramelement = layout_visible_classifier_get_diagramelement_const( classifier_layout );
194 0 : const data_diagramelement_flag_t display_flags = data_diagramelement_get_display_flags( diagramelement );
195 :
196 : /* draw features */
197 0 : pencil_feature_painter_draw ( &((*this_).feature_painter),
198 : the_feature,
199 : data_id_equals_id( &mark_focused, DATA_TABLE_FEATURE, layout_feature_get_feature_id(the_feature) ),
200 : data_id_equals_id( &mark_highlighted, DATA_TABLE_FEATURE, layout_feature_get_feature_id( the_feature ) ),
201 : data_small_set_contains_row_id( mark_selected, DATA_TABLE_FEATURE, layout_feature_get_feature_id(the_feature) ),
202 0 : (0 != ( display_flags & DATA_DIAGRAMELEMENT_FLAG_GRAY_OUT )),
203 : (*this_).profile,
204 : pencil_layouter_get_pencil_size_const( &((*this_).layouter) ),
205 : layout,
206 : cr
207 : );
208 : }
209 :
210 0 : U8_TRACE_END();
211 0 : }
212 :
213 0 : void pencil_diagram_maker_private_draw_relationships ( pencil_diagram_maker_t *this_,
214 : data_id_t mark_focused,
215 : data_id_t mark_highlighted,
216 : const data_small_set_t *mark_selected,
217 : PangoLayout *layout,
218 : cairo_t *cr )
219 : {
220 0 : U8_TRACE_BEGIN();
221 0 : assert( NULL != mark_selected );
222 0 : assert( NULL != cr );
223 :
224 0 : const pencil_layout_data_t *const layout_data = pencil_layouter_get_layout_data_const ( &((*this_).layouter) );
225 :
226 0 : const uint32_t rel_count = pencil_layout_data_get_relationship_count ( layout_data );
227 0 : for ( uint32_t index = 0; index < rel_count; index ++ )
228 : {
229 : pencil_visibility_t show_relation;
230 0 : const layout_relationship_t *const relationship_layout = pencil_layout_data_get_relationship_const ( layout_data, index );
231 0 : const data_relationship_t *const the_relationship = layout_relationship_get_data_const ( relationship_layout );
232 0 : show_relation = layout_relationship_get_visibility ( relationship_layout );
233 0 : if ( PENCIL_VISIBILITY_IMPLICIT == show_relation )
234 : {
235 0 : if ( data_id_equals_id( &mark_focused, DATA_TABLE_RELATIONSHIP, data_relationship_get_row_id(the_relationship) )
236 0 : || data_id_equals_id( &mark_highlighted, DATA_TABLE_RELATIONSHIP, data_relationship_get_row_id(the_relationship) )
237 0 : || data_small_set_contains_row_id( mark_selected, DATA_TABLE_RELATIONSHIP, data_relationship_get_row_id(the_relationship) ) )
238 : {
239 : /* the implicit relationship is focused or marked or highlighted */
240 0 : show_relation = PENCIL_VISIBILITY_SHOW;
241 : }
242 : else
243 : {
244 0 : if ( DATA_TABLE_DIAGRAMELEMENT == data_id_get_table( &mark_highlighted ) )
245 : {
246 0 : const data_row_id_t diagramelement_id = data_id_get_row_id( &mark_highlighted );
247 0 : const data_visible_classifier_t *visible_clsfy = data_visible_set_get_visible_classifier_by_id_const ( (*this_).input_data, diagramelement_id );
248 0 : if ( visible_clsfy != NULL )
249 : {
250 0 : if ( data_visible_classifier_is_valid( visible_clsfy ) )
251 : {
252 0 : const data_classifier_t *classifier = data_visible_classifier_get_classifier_const( visible_clsfy );
253 0 : if (( data_classifier_get_row_id( classifier ) == data_relationship_get_from_classifier_row_id( the_relationship ) )
254 0 : ||( data_classifier_get_row_id( classifier ) == data_relationship_get_to_classifier_row_id( the_relationship ) ))
255 : {
256 : /* the implicit relationship has highlighted from or to classifier */
257 0 : show_relation = PENCIL_VISIBILITY_SHOW;
258 : }
259 : }
260 : }
261 :
262 : }
263 : }
264 : }
265 0 : if (( PENCIL_VISIBILITY_SHOW == show_relation )||( PENCIL_VISIBILITY_GRAY_OUT == show_relation ))
266 : {
267 0 : const pencil_size_t *const pencil_size = pencil_layouter_get_pencil_size_const( &((*this_).layouter) );
268 0 : pencil_relationship_painter_draw ( &((*this_).relationship_painter),
269 : relationship_layout,
270 : data_id_equals_id( &mark_focused, DATA_TABLE_RELATIONSHIP, data_relationship_get_row_id(the_relationship) ),
271 : data_id_equals_id( &mark_highlighted, DATA_TABLE_RELATIONSHIP, data_relationship_get_row_id( the_relationship ) ),
272 : data_small_set_contains_row_id( mark_selected, DATA_TABLE_RELATIONSHIP, data_relationship_get_row_id(the_relationship) ),
273 : (*this_).profile,
274 : pencil_size,
275 : layout,
276 : cr
277 : );
278 : }
279 : }
280 :
281 0 : U8_TRACE_END();
282 0 : }
283 :
284 0 : pencil_error_t pencil_diagram_maker_get_order_at_pos ( const pencil_diagram_maker_t *this_,
285 : data_id_t obj_id,
286 : double x,
287 : double y,
288 : layout_order_t* out_layout_order )
289 : {
290 0 : U8_TRACE_BEGIN();
291 0 : assert( NULL != out_layout_order );
292 :
293 0 : pencil_error_t result = PENCIL_ERROR_NONE;
294 :
295 0 : const data_table_t table = data_id_get_table ( &obj_id );
296 0 : switch ( table )
297 : {
298 0 : case DATA_TABLE_CLASSIFIER:
299 : {
300 0 : const data_row_id_t classifier_id = data_id_get_row_id ( &obj_id );
301 : const data_classifier_t *const the_classifier
302 0 : = data_visible_set_get_classifier_by_id_const ( (*this_).input_data, classifier_id );
303 0 : const data_classifier_type_t c_type
304 : = (NULL == the_classifier)
305 : ? DATA_CLASSIFIER_TYPE_CLASS /* for new or unknown objects, assume class */
306 0 : : data_classifier_get_main_type( the_classifier );
307 0 : result = pencil_layouter_get_classifier_order_at_pos ( &((*this_).layouter),
308 : c_type,
309 : x,
310 : y,
311 0 : (*this_).snap_to_grid_distance,
312 : out_layout_order
313 : );
314 : }
315 0 : break;
316 :
317 0 : case DATA_TABLE_FEATURE:
318 : {
319 0 : const data_row_id_t feature_id = data_id_get_row_id ( &obj_id );
320 : const data_feature_t *const the_feature
321 0 : = data_visible_set_get_feature_by_id_const ( (*this_).input_data, feature_id );
322 0 : if( NULL != the_feature )
323 : {
324 0 : result = pencil_layouter_get_feature_order_at_pos ( &((*this_).layouter),
325 : the_feature,
326 : x,
327 : y,
328 : out_layout_order
329 : );
330 : }
331 : else
332 : {
333 0 : U8_LOG_ANOMALY( "feature to move does not exist in input_data." );
334 0 : layout_order_init_empty( out_layout_order );
335 0 : result = PENCIL_ERROR_UNKNOWN_OBJECT;
336 : }
337 : }
338 0 : break;
339 :
340 0 : case DATA_TABLE_RELATIONSHIP:
341 : {
342 0 : result = pencil_layouter_get_relationship_order_at_pos ( &((*this_).layouter),
343 : x,
344 : y,
345 : out_layout_order
346 : );
347 : }
348 0 : break;
349 :
350 0 : case DATA_TABLE_DIAGRAMELEMENT:
351 : {
352 0 : U8_LOG_WARNING( "not implemented to move diagramelements. use the classifier instead." );
353 0 : layout_order_init_empty( out_layout_order );
354 0 : result = PENCIL_ERROR_UNKNOWN_OBJECT;
355 : }
356 0 : break;
357 :
358 0 : case DATA_TABLE_DIAGRAM:
359 : {
360 : /* pencil cannot move diagrams */
361 0 : U8_LOG_WARNING( "object to be re-positioned has unexpected type: diagram" );
362 0 : layout_order_init_empty( out_layout_order );
363 0 : result = PENCIL_ERROR_UNKNOWN_OBJECT;
364 : }
365 0 : break;
366 :
367 0 : default:
368 : {
369 0 : U8_LOG_WARNING( "object to be re-positioned has illegal type" );
370 0 : layout_order_init_empty( out_layout_order );
371 0 : result = PENCIL_ERROR_UNKNOWN_OBJECT;
372 : }
373 0 : break;
374 : }
375 :
376 0 : U8_TRACE_END_ERR(result);
377 0 : return result;
378 : }
379 :
380 0 : pencil_error_t pencil_diagram_maker_get_feature_order_at_pos ( const pencil_diagram_maker_t *this_,
381 : const data_feature_t *feature_ptr,
382 : double x,
383 : double y,
384 : layout_order_t* out_layout_order )
385 : {
386 0 : U8_TRACE_BEGIN();
387 0 : assert( NULL != feature_ptr );
388 0 : assert( NULL != out_layout_order );
389 :
390 : const pencil_error_t result
391 0 : = pencil_layouter_get_feature_order_at_pos ( &((*this_).layouter),
392 : feature_ptr,
393 : x,
394 : y,
395 : out_layout_order
396 : );
397 :
398 0 : U8_TRACE_END_ERR(result);
399 0 : return result;
400 : }
401 :
402 :
403 : /*
404 : Copyright 2016-2024 Andreas Warnke
405 :
406 : Licensed under the Apache License, Version 2.0 (the "License");
407 : you may not use this file except in compliance with the License.
408 : You may obtain a copy of the License at
409 :
410 : http://www.apache.org/licenses/LICENSE-2.0
411 :
412 : Unless required by applicable law or agreed to in writing, software
413 : distributed under the License is distributed on an "AS IS" BASIS,
414 : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
415 : See the License for the specific language governing permissions and
416 : limitations under the License.
417 : */
|