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