Line data Source code
1 : /* File: gui_sketch_object_creator.c; Copyright and License: see below */
2 :
3 : #include "sketch/gui_sketch_object_creator.h"
4 : #include "geometry/geometry_rectangle.h"
5 : #include "ctrl_multi_step_changer.h"
6 : #include "entity/data_table.h"
7 : #include "entity/data_id.h"
8 : #include "u8/u8_trace.h"
9 : #include "u8/u8_log.h"
10 : #include <stdint.h>
11 : #include <stdbool.h>
12 :
13 0 : void gui_sketch_object_creator_init ( gui_sketch_object_creator_t *this_,
14 : ctrl_controller_t *controller,
15 : data_database_reader_t *db_reader,
16 : gui_simple_message_to_user_t *message_to_user )
17 : {
18 0 : U8_TRACE_BEGIN();
19 :
20 0 : (*this_).db_reader = db_reader;
21 0 : (*this_).controller = controller;
22 0 : gui_sketch_defaults_init ( &((*this_).defaults ) );
23 0 : data_rules_init ( &((*this_).data_rules ) );
24 0 : (*this_).message_to_user = message_to_user;
25 :
26 0 : U8_TRACE_END();
27 0 : }
28 :
29 0 : void gui_sketch_object_creator_destroy ( gui_sketch_object_creator_t *this_ )
30 : {
31 0 : U8_TRACE_BEGIN();
32 :
33 0 : (*this_).message_to_user = NULL;
34 0 : data_rules_destroy ( &((*this_).data_rules) );
35 0 : gui_sketch_defaults_destroy ( &((*this_).defaults) );
36 0 : (*this_).db_reader = NULL;
37 0 : (*this_).controller = NULL;
38 :
39 0 : U8_TRACE_END();
40 0 : }
41 :
42 0 : u8_error_t gui_sketch_object_creator_create_classifier ( gui_sketch_object_creator_t *this_,
43 : data_row_t diagram_id,
44 : int32_t x_order,
45 : int32_t y_order,
46 : data_row_t *out_diagramelement_id,
47 : data_row_t *out_classifier_id )
48 : {
49 0 : U8_TRACE_BEGIN();
50 0 : assert ( NULL != out_classifier_id );
51 0 : assert ( NULL != out_diagramelement_id );
52 0 : assert ( DATA_ROW_VOID != diagram_id );
53 :
54 : u8_error_t c_result;
55 :
56 : /* get type of diagram */
57 0 : data_diagram_type_t diag_type = DATA_DIAGRAM_TYPE_LIST;
58 : {
59 : const u8_error_t diag_err
60 0 : = data_database_reader_get_diagram_by_id( (*this_).db_reader,
61 : diagram_id,
62 : &((*this_).private_temp_diagram)
63 : );
64 0 : if ( U8_ERROR_NONE == diag_err )
65 : {
66 0 : diag_type = data_diagram_get_diagram_type( &((*this_).private_temp_diagram) );
67 0 : data_diagram_destroy ( &((*this_).private_temp_diagram) );
68 : }
69 : else
70 : {
71 0 : U8_LOG_ERROR_INT( "gui_sketch_object_creator_create_classifier cannot find diagram:", diagram_id );
72 : }
73 : }
74 :
75 : /* determine type of new classifier */
76 : data_classifier_type_t type_of_new_classifier;
77 0 : type_of_new_classifier = gui_sketch_defaults_get_classifier_type( &((*this_).defaults), diag_type );
78 :
79 : /* define classifier */
80 : const u8_error_t d_err
81 0 : = data_classifier_init_new ( &((*this_).private_temp_classifier),
82 : type_of_new_classifier,
83 : "", /* stereotype */
84 : "New Element", /* name */
85 : "", /* description */
86 : x_order,
87 : y_order,
88 : y_order /* y_order used also as list_order */
89 : );
90 0 : if ( d_err != U8_ERROR_NONE )
91 : {
92 0 : U8_LOG_ERROR_HEX("data_classifier_init_new failed in gui_sketch_object_creator_create_classifier:",d_err);
93 : }
94 :
95 : /* create classifier, adapt name if necessary: */
96 : {
97 : ctrl_multi_step_changer_t multi_stepper;
98 0 : ctrl_multi_step_changer_init( &multi_stepper, (*this_).controller, (*this_).db_reader );
99 : u8_error_t out_info;
100 0 : c_result = ctrl_multi_step_changer_create_classifier( &multi_stepper,
101 : &((*this_).private_temp_classifier),
102 : &out_info
103 : );
104 0 : *out_classifier_id = data_classifier_get_row_id( &((*this_).private_temp_classifier) );
105 0 : ctrl_multi_step_changer_destroy( &multi_stepper );
106 : }
107 :
108 0 : if ( U8_ERROR_NONE == c_result )
109 : {
110 : /* get diagram controller */
111 0 : ctrl_diagram_controller_t *const diagram_control = ctrl_controller_get_diagram_control_ptr( (*this_).controller );
112 :
113 : data_diagramelement_t new_diagele;
114 0 : data_diagramelement_init_new ( &new_diagele,
115 : diagram_id,
116 : *out_classifier_id,
117 : DATA_DIAGRAMELEMENT_FLAG_NONE,
118 : DATA_ROW_VOID
119 : );
120 :
121 0 : c_result = ctrl_diagram_controller_create_diagramelement ( diagram_control,
122 : &new_diagele,
123 : CTRL_UNDO_REDO_ACTION_BOUNDARY_APPEND,
124 : out_diagramelement_id
125 : );
126 :
127 : /* cleanup */
128 0 : data_diagramelement_destroy ( &new_diagele );
129 : }
130 0 : else if ( U8_ERROR_READ_ONLY_DB == c_result )
131 : {
132 : /* notify read-only warning to user */
133 0 : gui_simple_message_to_user_show_message( (*this_).message_to_user,
134 : GUI_SIMPLE_MESSAGE_TYPE_WARNING,
135 : GUI_SIMPLE_MESSAGE_CONTENT_DB_IS_READ_ONLY
136 : );
137 : }
138 :
139 : /* cleanup */
140 0 : data_classifier_destroy ( &((*this_).private_temp_classifier) );
141 :
142 0 : U8_TRACE_END_ERR( c_result );
143 0 : return c_result;
144 : }
145 :
146 0 : u8_error_t gui_sketch_object_creator_create_classifier_as_child ( gui_sketch_object_creator_t *this_,
147 : data_row_t diagram_id,
148 : data_row_t parent_classifier_id,
149 : int32_t x_order,
150 : int32_t y_order,
151 : data_row_t *out_diagramelement_id,
152 : data_row_t *out_classifier_id,
153 : data_row_t *out_relationship_id )
154 : {
155 0 : U8_TRACE_BEGIN();
156 0 : assert ( NULL != out_classifier_id );
157 0 : assert ( NULL != out_diagramelement_id );
158 0 : assert ( NULL != out_relationship_id );
159 0 : assert ( DATA_ROW_VOID != parent_classifier_id );
160 0 : assert ( DATA_ROW_VOID != diagram_id );
161 :
162 : u8_error_t c_result;
163 :
164 0 : c_result = gui_sketch_object_creator_create_classifier( this_,
165 : diagram_id,
166 : x_order,
167 : y_order,
168 : out_diagramelement_id,
169 : out_classifier_id
170 : );
171 :
172 0 : if ( U8_ERROR_NONE == c_result )
173 : {
174 : /* get classifier controller */
175 : ctrl_classifier_controller_t *classifier_control;
176 0 : classifier_control = ctrl_controller_get_classifier_control_ptr ( (*this_).controller );
177 :
178 : /* define relationship */
179 : const u8_error_t d_err
180 0 : = data_relationship_init_new( &((*this_).private_temp_relationship),
181 : parent_classifier_id,
182 : DATA_ROW_VOID,
183 : *out_classifier_id,
184 : DATA_ROW_VOID,
185 : DATA_RELATIONSHIP_TYPE_UML_CONTAINMENT,
186 : "", /* =stereotype */
187 : "", /* =name */
188 : "", /* =description */
189 : y_order /* =list_order */
190 : );
191 0 : if ( d_err != U8_ERROR_NONE )
192 : {
193 0 : U8_LOG_ERROR_HEX("data_relationship_init failed in gui_sketch_object_creator_create_classifier_as_child:",d_err);
194 : }
195 :
196 : /* create relationship */
197 0 : c_result = ctrl_classifier_controller_create_relationship( classifier_control,
198 0 : &((*this_).private_temp_relationship),
199 : CTRL_UNDO_REDO_ACTION_BOUNDARY_APPEND,
200 : out_relationship_id
201 : );
202 :
203 : /* cleanup */
204 0 : data_relationship_destroy( &((*this_).private_temp_relationship) );
205 : }
206 :
207 0 : U8_TRACE_END_ERR( c_result );
208 0 : return c_result;
209 : }
210 :
211 0 : u8_error_t gui_sketch_object_creator_create_diagram ( gui_sketch_object_creator_t *this_,
212 : data_row_t parent_diagram_id,
213 : int32_t list_order,
214 : data_row_t *out_diagram_id )
215 : {
216 0 : U8_TRACE_BEGIN();
217 0 : assert ( NULL != out_diagram_id );
218 :
219 : u8_error_t c_result;
220 :
221 : ctrl_diagram_controller_t *diag_control;
222 0 : diag_control = ctrl_controller_get_diagram_control_ptr ( (*this_).controller );
223 :
224 : /* create the diagram */
225 : const u8_error_t d_err
226 0 : = data_diagram_init_new( &((*this_).private_temp_diagram),
227 : parent_diagram_id,
228 : DATA_DIAGRAM_TYPE_UML_COMPONENT_DIAGRAM,
229 : "",
230 : "New Diagram",
231 : "",
232 : list_order,
233 : DATA_DIAGRAM_FLAG_NONE
234 : );
235 0 : if ( d_err != U8_ERROR_NONE )
236 : {
237 0 : U8_LOG_ERROR_HEX("data_diagram_init_new failed in gui_sketch_object_creator_create_diagram:",d_err);
238 : }
239 :
240 0 : c_result = ctrl_diagram_controller_create_diagram( diag_control,
241 0 : &((*this_).private_temp_diagram),
242 : CTRL_UNDO_REDO_ACTION_BOUNDARY_START_NEW,
243 : out_diagram_id
244 : );
245 0 : if ( U8_ERROR_READ_ONLY_DB == c_result )
246 : {
247 : /* notify read-only warning to user */
248 0 : gui_simple_message_to_user_show_message( (*this_).message_to_user,
249 : GUI_SIMPLE_MESSAGE_TYPE_WARNING,
250 : GUI_SIMPLE_MESSAGE_CONTENT_DB_IS_READ_ONLY
251 : );
252 : }
253 :
254 : /* cleanup */
255 0 : if ( d_err == U8_ERROR_NONE )
256 : {
257 0 : data_diagram_destroy ( &((*this_).private_temp_diagram) );
258 : }
259 :
260 0 : U8_TRACE_END_ERR( c_result );
261 0 : return c_result;
262 : }
263 :
264 0 : u8_error_t gui_sketch_object_creator_create_relationship ( gui_sketch_object_creator_t *this_,
265 : data_diagram_type_t diag_type,
266 : data_row_t from_classifier_id,
267 : data_row_t from_feature_id,
268 : data_row_t to_classifier_id,
269 : data_row_t to_feature_id,
270 : int32_t list_order,
271 : data_row_t *out_relationship_id )
272 : {
273 0 : U8_TRACE_BEGIN();
274 0 : assert ( NULL != out_relationship_id );
275 0 : assert ( DATA_ROW_VOID != from_classifier_id );
276 0 : assert ( DATA_ROW_VOID != to_classifier_id );
277 :
278 : u8_error_t c_result;
279 :
280 : /* get classifier controller */
281 : ctrl_classifier_controller_t *classifier_control;
282 0 : classifier_control = ctrl_controller_get_classifier_control_ptr( (*this_).controller );
283 :
284 : /* propose a type for the relationship */
285 0 : data_relationship_type_t new_rel_type = DATA_RELATIONSHIP_TYPE_UML_DEPENDENCY;
286 : {
287 : /* get type of from_classifier */
288 0 : data_classifier_type_t from_class_type = DATA_CLASSIFIER_TYPE_CLASS;
289 : {
290 : const u8_error_t clsfy_err
291 0 : = data_database_reader_get_classifier_by_id( (*this_).db_reader,
292 : from_classifier_id,
293 : &((*this_).private_temp_classifier)
294 : );
295 0 : if ( U8_ERROR_NONE == clsfy_err )
296 : {
297 0 : from_class_type = data_classifier_get_main_type( &((*this_).private_temp_classifier) );
298 0 : data_classifier_destroy ( &((*this_).private_temp_classifier) );
299 : }
300 : else
301 : {
302 0 : U8_LOG_ERROR_INT( "gui_sketch_object_creator_create_relationship cannot find classifier:", from_classifier_id );
303 : }
304 : }
305 :
306 : /* get type of from_feature */
307 0 : data_feature_type_t from_feature_type = DATA_FEATURE_TYPE_VOID;
308 0 : if ( from_feature_id != DATA_ROW_VOID )
309 : {
310 : const u8_error_t feat_err
311 0 : = data_database_reader_get_feature_by_id( (*this_).db_reader,
312 : from_feature_id,
313 : &((*this_).private_temp_feature)
314 : );
315 0 : if ( U8_ERROR_NONE == feat_err )
316 : {
317 0 : from_feature_type = data_feature_get_main_type( &((*this_).private_temp_feature) );
318 0 : data_feature_destroy ( &((*this_).private_temp_feature) );
319 : }
320 : else
321 : {
322 0 : U8_LOG_ERROR_INT( "gui_sketch_object_creator_create_relationship cannot find feature:", from_feature_id );
323 : }
324 : }
325 0 : new_rel_type = gui_sketch_defaults_get_relationship_type( &((*this_).defaults), from_class_type, from_feature_type );
326 : }
327 :
328 : /* define relationship struct */
329 : const u8_error_t d_err
330 0 : = data_relationship_init_new( &((*this_).private_temp_relationship),
331 : from_classifier_id,
332 : from_feature_id,
333 : to_classifier_id,
334 : to_feature_id,
335 : new_rel_type,
336 : "", /* =stereotype */
337 : "", /* =name */
338 : "", /* =description */
339 : list_order
340 : );
341 0 : if ( d_err != U8_ERROR_NONE )
342 : {
343 0 : U8_LOG_ERROR_HEX("data_relationship_init failed in gui_sketch_object_creator_create_relationship:",d_err);
344 : }
345 :
346 : /* check preconditions */
347 0 : const bool is_scenario = data_rules_diagram_is_scenario ( &((*this_).data_rules), diag_type )
348 0 : && (( from_feature_id != DATA_ROW_VOID )||( to_feature_id != DATA_ROW_VOID ));
349 0 : const bool diagram_ok = is_scenario
350 0 : ? data_rules_diagram_shows_scenario_relationships ( &((*this_).data_rules), diag_type )
351 0 : : data_rules_diagram_shows_uncond_relationships ( &((*this_).data_rules), diag_type );
352 :
353 0 : if ( diagram_ok ) {
354 : /* create relationship */
355 0 : c_result = ctrl_classifier_controller_create_relationship( classifier_control,
356 0 : &((*this_).private_temp_relationship),
357 : CTRL_UNDO_REDO_ACTION_BOUNDARY_START_NEW,
358 : out_relationship_id
359 : );
360 0 : if ( U8_ERROR_READ_ONLY_DB == c_result )
361 : {
362 : /* notify read-only warning to user */
363 0 : gui_simple_message_to_user_show_message( (*this_).message_to_user,
364 : GUI_SIMPLE_MESSAGE_TYPE_WARNING,
365 : GUI_SIMPLE_MESSAGE_CONTENT_DB_IS_READ_ONLY
366 : );
367 : }
368 : }
369 : else
370 : {
371 : /* notify error to user */
372 0 : gui_simple_message_to_user_show_message( (*this_).message_to_user,
373 : GUI_SIMPLE_MESSAGE_TYPE_ERROR,
374 : GUI_SIMPLE_MESSAGE_CONTENT_NO_RELATIONSHIPS
375 : );
376 0 : c_result = U8_ERROR_DIAGRAM_HIDES_RELATIONSHIPS;
377 : }
378 :
379 : /* cleanup */
380 0 : data_relationship_destroy( &((*this_).private_temp_relationship) );
381 :
382 0 : U8_TRACE_END_ERR( c_result );
383 0 : return c_result;
384 : }
385 :
386 0 : u8_error_t gui_sketch_object_creator_create_feature ( gui_sketch_object_creator_t *this_,
387 : data_diagram_type_t diag_type,
388 : data_row_t parent_classifier_id,
389 : int32_t std_list_order,
390 : int32_t port_list_order,
391 : data_row_t *out_feature_id )
392 : {
393 0 : U8_TRACE_BEGIN();
394 0 : assert ( NULL != out_feature_id );
395 0 : assert ( DATA_ROW_VOID != parent_classifier_id );
396 :
397 : u8_error_t c_result;
398 :
399 : /* get classifier controller */
400 : ctrl_classifier_controller_t *classifier_control;
401 0 : classifier_control = ctrl_controller_get_classifier_control_ptr( (*this_).controller );
402 :
403 : /* get type of parent classifier */
404 0 : data_classifier_type_t parent_class_type = DATA_CLASSIFIER_TYPE_CLASS;
405 : {
406 : const u8_error_t clsfy_err
407 0 : = data_database_reader_get_classifier_by_id( (*this_).db_reader,
408 : parent_classifier_id,
409 : &((*this_).private_temp_classifier)
410 : );
411 0 : if ( U8_ERROR_NONE == clsfy_err )
412 : {
413 0 : parent_class_type = data_classifier_get_main_type( &((*this_).private_temp_classifier) );
414 0 : data_classifier_destroy( &((*this_).private_temp_classifier) );
415 : }
416 : else
417 : {
418 0 : U8_LOG_ERROR_INT( "gui_sketch_object_creator_create_feature cannot find classifier:", parent_classifier_id );
419 : }
420 : }
421 :
422 : /* propose a type for the feature */
423 : data_feature_type_t new_feature_type;
424 0 : new_feature_type = gui_sketch_defaults_get_feature_type( &((*this_).defaults), parent_class_type );
425 :
426 : /* select the right list_order */
427 : int32_t list_order;
428 0 : if ( ( DATA_FEATURE_TYPE_PROVIDED_INTERFACE == new_feature_type )
429 0 : || ( DATA_FEATURE_TYPE_REQUIRED_INTERFACE == new_feature_type )
430 0 : || ( DATA_FEATURE_TYPE_PORT == new_feature_type )
431 0 : || ( DATA_FEATURE_TYPE_IN_PORT_PIN == new_feature_type )
432 0 : || ( DATA_FEATURE_TYPE_OUT_PORT_PIN == new_feature_type )
433 0 : || ( DATA_FEATURE_TYPE_ENTRY == new_feature_type )
434 0 : || ( DATA_FEATURE_TYPE_EXIT == new_feature_type ) )
435 : {
436 0 : list_order = port_list_order;
437 : }
438 : else /* DATA_FEATURE_TYPE_PROPERTY or DATA_FEATURE_TYPE_OPERATION or DATA_FEATURE_TYPE_TAGGED_VALUE */
439 : {
440 0 : list_order = std_list_order;
441 : }
442 :
443 : /* define feature struct */
444 : const u8_error_t data_err
445 0 : = data_feature_init_new( &((*this_).private_temp_feature),
446 : new_feature_type,
447 : parent_classifier_id,
448 : "New Feature", /* name */
449 : "", /* type/value */
450 : "",
451 : list_order
452 : );
453 0 : if ( data_err != U8_ERROR_NONE )
454 : {
455 0 : U8_LOG_ERROR_HEX("data_feature_init failed in gui_sketch_object_creator_create_feature:",data_err);
456 : }
457 :
458 : /* check preconditions */
459 0 : const bool classifier_ok = data_rules_classifier_has_uncond_features ( &((*this_).data_rules), parent_class_type );
460 0 : const bool is_scenario = data_rules_feature_is_scenario_cond ( &((*this_).data_rules), new_feature_type );
461 0 : assert ( ! is_scenario ); /* lifelines should not be created by this function */
462 0 : const bool diagram_ok = is_scenario
463 0 : ? data_rules_diagram_shows_scenario_features ( &((*this_).data_rules), diag_type )
464 0 : : data_rules_diagram_shows_uncond_features ( &((*this_).data_rules), diag_type );
465 :
466 0 : if ( diagram_ok && classifier_ok )
467 : {
468 : /* create feature */
469 0 : c_result = ctrl_classifier_controller_create_feature( classifier_control,
470 0 : &((*this_).private_temp_feature),
471 : CTRL_UNDO_REDO_ACTION_BOUNDARY_START_NEW,
472 : out_feature_id
473 : );
474 0 : if ( U8_ERROR_READ_ONLY_DB == c_result )
475 : {
476 : /* notify read-only warning to user */
477 0 : gui_simple_message_to_user_show_message( (*this_).message_to_user,
478 : GUI_SIMPLE_MESSAGE_TYPE_WARNING,
479 : GUI_SIMPLE_MESSAGE_CONTENT_DB_IS_READ_ONLY
480 : );
481 : }
482 : }
483 0 : else if ( ! classifier_ok )
484 : {
485 : /* notify error to user */
486 0 : gui_simple_message_to_user_show_message( (*this_).message_to_user,
487 : GUI_SIMPLE_MESSAGE_TYPE_ERROR,
488 : GUI_SIMPLE_MESSAGE_CONTENT_FEATURELESS_CLASSIFIER
489 : );
490 0 : c_result = U8_ERROR_CLASSIFIER_REFUSES_FEATURE;
491 : }
492 : else
493 : {
494 : /* notify error to user */
495 0 : gui_simple_message_to_user_show_message( (*this_).message_to_user,
496 : GUI_SIMPLE_MESSAGE_TYPE_ERROR,
497 : GUI_SIMPLE_MESSAGE_CONTENT_NO_FEATURES
498 : );
499 0 : c_result = U8_ERROR_DIAGRAM_HIDES_FEATURES;
500 : }
501 :
502 : /* cleanup */
503 0 : data_feature_destroy( &((*this_).private_temp_feature) );
504 :
505 0 : U8_TRACE_END_ERR( c_result );
506 0 : return c_result;
507 : }
508 :
509 :
510 : /*
511 : Copyright 2017-2025 Andreas Warnke
512 :
513 : Licensed under the Apache License, Version 2.0 (the "License");
514 : you may not use this file except in compliance with the License.
515 : You may obtain a copy of the License at
516 :
517 : http://www.apache.org/licenses/LICENSE-2.0
518 :
519 : Unless required by applicable law or agreed to in writing, software
520 : distributed under the License is distributed on an "AS IS" BASIS,
521 : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
522 : See the License for the specific language governing permissions and
523 : limitations under the License.
524 : */
|