LCOV - code coverage report
Current view: top level - gui/source - gui_toolbox.c (source / functions) Coverage Total Hit
Test: crystal-facet-uml_v1.70.5_covts Lines: 0.0 % 447 0
Test Date: 2026-05-28 21:31:40 Functions: 0.0 % 28 0

            Line data    Source code
       1              : /* File: gui_toolbox.c; Copyright and License: see below */
       2              : 
       3              : #include "gui_toolbox.h"
       4              : #include "ctrl_multi_step_changer.h"
       5              : #include "u8/u8_trace.h"
       6              : #include "u8/u8_error.h"
       7              : #include "utf8stringbuf/utf8string.h"
       8              : #include <assert.h>
       9              : #include "gui_gtk.h"
      10              : #include <stdbool.h>
      11              : 
      12              : static bool gui_toolbox_glib_signal_initialized = false;
      13              : static guint gui_toolbox_glib_signal_id = 0;
      14              : const char *GUI_TOOLBOX_GLIB_SIGNAL_NAME = "cfu_tool_changed";
      15              : 
      16            0 : void gui_toolbox_init( gui_toolbox_t *this_,
      17              :                        GtkWidget *toolbar,
      18              :                        GtkWidget *tool_navigate,
      19              :                        GtkWidget *tool_edit,
      20              :                        GtkWidget *tool_create,
      21              :                        GtkWidget *tool_search,
      22              :                        GdkClipboard *gtk_clipboard,
      23              :                        gui_marked_set_t *marker,
      24              :                        gui_simple_message_to_user_t *message_to_user,
      25              :                        data_database_reader_t *db_reader,
      26              :                        ctrl_controller_t *controller )
      27              : {
      28            0 :     U8_TRACE_BEGIN();
      29            0 :     assert( NULL != tool_navigate );
      30            0 :     assert( NULL != tool_edit );
      31            0 :     assert( NULL != tool_create );
      32            0 :     assert( NULL != tool_search );
      33            0 :     assert( NULL != gtk_clipboard );
      34            0 :     assert( NULL != marker );
      35            0 :     assert( NULL != message_to_user );
      36            0 :     assert( NULL != db_reader );
      37            0 :     assert( NULL != controller );
      38              : 
      39            0 :     (*this_).selected_tool = GUI_TOOL_NAVIGATE;
      40            0 :     (*this_).marker = marker;
      41            0 :     (*this_).message_to_user = message_to_user;
      42            0 :     (*this_).db_reader = db_reader;
      43            0 :     (*this_).controller = controller;
      44            0 :     (*this_).toolbar = toolbar;
      45            0 :     (*this_).tool_navigate = tool_navigate;
      46            0 :     (*this_).tool_edit = tool_edit;
      47            0 :     (*this_).tool_create = tool_create;
      48            0 :     (*this_).tool_search = tool_search;
      49              : 
      50            0 :     gui_clipboard_init( &((*this_).clipboard),
      51              :                         gtk_clipboard,
      52              :                         this_,
      53              :                         message_to_user,
      54              :                         db_reader,
      55              :                         controller
      56              :                       );
      57              : 
      58              :     /* define a new signal */
      59            0 :     if ( ! gui_toolbox_glib_signal_initialized )
      60              :     {
      61            0 :         gui_toolbox_glib_signal_id = g_signal_new(
      62              :             GUI_TOOLBOX_GLIB_SIGNAL_NAME,
      63              :             G_TYPE_OBJECT,
      64              :             G_SIGNAL_RUN_FIRST,
      65              :             0,
      66              :             NULL,
      67              :             NULL,
      68              :             g_cclosure_marshal_VOID__INT,
      69              :             G_TYPE_NONE,
      70              :             1,
      71              :             G_TYPE_INT /* gui_tool_t */
      72              :         );
      73            0 :         gui_toolbox_glib_signal_initialized = true;
      74            0 :         U8_TRACE_INFO_INT( "g_signal_new(\"cfu_tool_changed\") returned new signal id", gui_toolbox_glib_signal_id );
      75              :     }
      76              : 
      77            0 :     U8_TRACE_END();
      78            0 : }
      79              : 
      80            0 : void gui_toolbox_destroy( gui_toolbox_t *this_ )
      81              : {
      82            0 :     U8_TRACE_BEGIN();
      83              : 
      84            0 :     gui_clipboard_destroy( &((*this_).clipboard) );
      85              : 
      86            0 :     (*this_).db_reader = NULL;
      87            0 :     (*this_).controller = NULL;
      88            0 :     (*this_).marker = NULL;
      89            0 :     (*this_).message_to_user = NULL;
      90            0 :     (*this_).toolbar = NULL;
      91            0 :     (*this_).tool_navigate = NULL;
      92            0 :     (*this_).tool_edit = NULL;
      93            0 :     (*this_).tool_create = NULL;
      94            0 :     (*this_).tool_search = NULL;
      95              : 
      96            0 :     U8_TRACE_END();
      97            0 : }
      98              : 
      99            0 : void gui_toolbox_set_selected_tool( gui_toolbox_t *this_, gui_tool_t tool )
     100              : {
     101            0 :     U8_TRACE_BEGIN();
     102              : 
     103            0 :     switch ( tool )
     104              :     {
     105            0 :         case GUI_TOOL_NAVIGATE:
     106              :         {
     107            0 :             gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( (*this_).tool_navigate ), true );
     108            0 :             (*this_).selected_tool = GUI_TOOL_NAVIGATE;
     109            0 :             gui_toolbox_private_notify_listeners( this_ );
     110              :         }
     111            0 :         break;
     112              : 
     113            0 :         case GUI_TOOL_EDIT:
     114              :         {
     115            0 :             gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( (*this_).tool_edit ), true );
     116            0 :             (*this_).selected_tool = GUI_TOOL_EDIT;
     117            0 :             gui_toolbox_private_notify_listeners( this_ );
     118              :         }
     119            0 :         break;
     120              : 
     121            0 :         case GUI_TOOL_SEARCH:
     122              :         {
     123            0 :             gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( (*this_).tool_search ), true );
     124            0 :             (*this_).selected_tool = GUI_TOOL_SEARCH;
     125            0 :             gui_toolbox_private_notify_listeners( this_ );
     126              :         }
     127            0 :         break;
     128              : 
     129            0 :         case GUI_TOOL_CREATE:
     130              :         {
     131            0 :             gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( (*this_).tool_create ), true );
     132            0 :             (*this_).selected_tool = GUI_TOOL_CREATE;
     133            0 :             gui_toolbox_private_notify_listeners( this_ );
     134              :         }
     135            0 :         break;
     136              : 
     137            0 :         default:
     138              :         {
     139            0 :             U8_LOG_ERROR( "invalid enum value" );
     140              :         }
     141            0 :         break;
     142              :     }
     143              : 
     144            0 :     U8_TRACE_END();
     145            0 : }
     146              : 
     147            0 : void gui_toolbox_set_selected_tool_and_focus ( gui_toolbox_t *this_, gui_tool_t tool, data_id_t focused_diagram )
     148              : {
     149            0 :     U8_TRACE_BEGIN();
     150              : 
     151              :     /* switch tool */
     152            0 :     gui_toolbox_set_selected_tool( this_, tool );
     153              : 
     154            0 :     const data_id_t current_focus = gui_marked_set_get_focused_diagram( (*this_).marker );
     155            0 :     if ( ! data_id_equals_or_both_void( &focused_diagram, &current_focus ) )
     156              :     {
     157              :         /* clear selected set (no notification) */
     158            0 :         gui_marked_set_clear_selected_set( (*this_).marker );
     159              : 
     160              :         /* request to load the diagram to focus on */
     161            0 :         gui_marked_set_request_focused_diagram( (*this_).marker, focused_diagram );
     162              :     }
     163              : 
     164            0 :     U8_TRACE_END();
     165            0 : }
     166              : 
     167            0 : void gui_toolbox_navigate_btn_callback( GtkWidget* button, gpointer data )
     168              : {
     169            0 :     U8_TRACE_BEGIN();
     170            0 :     gui_toolbox_t *this_ = data;
     171            0 :     assert( NULL != this_ );
     172              : 
     173            0 :     gui_simple_message_to_user_hide( (*this_).message_to_user );
     174              : 
     175            0 :     (*this_).selected_tool = GUI_TOOL_NAVIGATE;
     176              : 
     177            0 :     gui_toolbox_private_notify_listeners( this_ );
     178              : 
     179            0 :     U8_TRACE_TIMESTAMP();
     180            0 :     U8_TRACE_END();
     181            0 : }
     182              : 
     183            0 : void gui_toolbox_edit_btn_callback( GtkWidget* button, gpointer data )
     184              : {
     185            0 :     U8_TRACE_BEGIN();
     186            0 :     gui_toolbox_t *this_ = data;
     187            0 :     assert( NULL != this_ );
     188              : 
     189            0 :     gui_simple_message_to_user_hide( (*this_).message_to_user );
     190              : 
     191            0 :     (*this_).selected_tool = GUI_TOOL_EDIT;
     192              : 
     193            0 :     gui_toolbox_private_notify_listeners( this_ );
     194              : 
     195            0 :     U8_TRACE_TIMESTAMP();
     196            0 :     U8_TRACE_END();
     197            0 : }
     198              : 
     199            0 : void gui_toolbox_create_btn_callback( GtkWidget* button, gpointer data )
     200              : {
     201            0 :     U8_TRACE_BEGIN();
     202            0 :     gui_toolbox_t *this_ = data;
     203            0 :     assert( NULL != this_ );
     204              : 
     205            0 :     gui_simple_message_to_user_hide( (*this_).message_to_user );
     206              : 
     207            0 :     (*this_).selected_tool = GUI_TOOL_CREATE;
     208              : 
     209            0 :     gui_toolbox_private_notify_listeners( this_ );
     210              : 
     211            0 :     U8_TRACE_TIMESTAMP();
     212            0 :     U8_TRACE_END();
     213            0 : }
     214              : 
     215            0 : void gui_toolbox_search_btn_callback( GtkWidget* button, gpointer data )
     216              : {
     217            0 :     U8_TRACE_BEGIN();
     218            0 :     gui_toolbox_t *this_ = data;
     219            0 :     assert( NULL != this_ );
     220              : 
     221            0 :     gui_simple_message_to_user_hide( (*this_).message_to_user );
     222              : 
     223            0 :     (*this_).selected_tool = GUI_TOOL_SEARCH;
     224              : 
     225            0 :     gui_toolbox_private_notify_listeners( this_ );
     226              : 
     227            0 :     U8_TRACE_TIMESTAMP();
     228            0 :     U8_TRACE_END();
     229            0 : }
     230              : 
     231            0 : void gui_toolbox_search_id_btn_callback( GtkWidget* button, gpointer data )
     232              : {
     233            0 :     U8_TRACE_BEGIN();
     234            0 :     gui_toolbox_t *this_ = data;
     235            0 :     assert( NULL != this_ );
     236              : 
     237            0 :     gui_toolbox_set_selected_tool( this_, GUI_TOOL_SEARCH );
     238              : 
     239            0 :     U8_TRACE_TIMESTAMP();
     240            0 :     U8_TRACE_END();
     241            0 : }
     242              : 
     243            0 : void gui_toolbox_cut_btn_callback( GtkWidget* button, gpointer data )
     244              : {
     245            0 :     U8_TRACE_BEGIN();
     246            0 :     gui_toolbox_t *this_ = data;
     247            0 :     assert( NULL != this_ );
     248              : 
     249            0 :     gui_toolbox_cut( this_ );
     250              : 
     251            0 :     U8_TRACE_TIMESTAMP();
     252            0 :     U8_TRACE_END();
     253            0 : }
     254              : 
     255            0 : void gui_toolbox_cut( gui_toolbox_t *this_ )
     256              : {
     257            0 :     U8_TRACE_BEGIN();
     258              :     u8_error_t ctrl_err;
     259              : 
     260            0 :     gui_simple_message_to_user_hide( (*this_).message_to_user );
     261              : 
     262              :     data_stat_t stat;
     263            0 :     data_stat_init(&stat);
     264              : 
     265            0 :     const data_small_set_t *const set_to_be_cut = gui_marked_set_get_selected_set_const( (*this_).marker );
     266              : 
     267              :     /* do not check if set is empty; gui_clipboard_copy_set_to_clipboard will do this */
     268              : 
     269            0 :     gui_clipboard_copy_set_to_clipboard( &((*this_).clipboard), set_to_be_cut, &stat );
     270              : 
     271            0 :     ctrl_err = gui_toolbox_private_delete_set( this_, set_to_be_cut, &stat );
     272              : 
     273            0 :     gui_marked_set_clear_selected_set( (*this_).marker );
     274              : 
     275            0 :     if ( U8_ERROR_INPUT_EMPTY == ctrl_err )
     276              :     {
     277            0 :         gui_simple_message_to_user_show_message( (*this_).message_to_user,
     278              :                                                  GUI_SIMPLE_MESSAGE_TYPE_WARNING,
     279              :                                                  GUI_SIMPLE_MESSAGE_CONTENT_NO_SELECTION
     280              :                                                );
     281              :     }
     282            0 :     else if ( u8_error_contains( ctrl_err, U8_ERROR_OBJECT_STILL_REFERENCED ) )
     283              :     {
     284            0 :         gui_simple_message_to_user_show_message( (*this_).message_to_user,
     285              :                                                  GUI_SIMPLE_MESSAGE_TYPE_ERROR,
     286              :                                                  GUI_SIMPLE_MESSAGE_CONTENT_DELETING_NOT_POSSIBLE
     287              :                                                );
     288              :     }
     289            0 :     else if ( U8_ERROR_NONE != ctrl_err )
     290              :     {
     291            0 :         U8_LOG_ERROR_HEX( "Error in ctrl_classifier_controller_delete_set_from_diagram", ctrl_err );
     292              :     }
     293              :     else
     294              :     {
     295            0 :         gui_simple_message_to_user_show_message_with_stat ( (*this_).message_to_user,
     296              :                                                             GUI_SIMPLE_MESSAGE_TYPE_INFO,
     297              :                                                             GUI_SIMPLE_MESSAGE_CONTENT_CUT_TO_CLIPBOARD,
     298              :                                                             &stat
     299              :                                                           );
     300              :     }
     301              : 
     302            0 :     data_stat_destroy(&stat);
     303              : 
     304            0 :     U8_TRACE_END();
     305            0 : }
     306              : 
     307            0 : void gui_toolbox_copy_btn_callback( GtkWidget* button, gpointer data )
     308              : {
     309            0 :     U8_TRACE_BEGIN();
     310            0 :     gui_toolbox_t *this_ = data;
     311            0 :     assert( NULL != this_ );
     312              : 
     313            0 :     gui_toolbox_copy( this_ );
     314              : 
     315            0 :     U8_TRACE_TIMESTAMP();
     316            0 :     U8_TRACE_END();
     317            0 : }
     318              : 
     319            0 : void gui_toolbox_copy( gui_toolbox_t *this_ )
     320              : {
     321            0 :     U8_TRACE_BEGIN();
     322              :     int out_err;
     323              : 
     324            0 :     gui_simple_message_to_user_hide( (*this_).message_to_user );
     325              : 
     326              :     data_stat_t stat;
     327            0 :     data_stat_init(&stat);
     328              : 
     329            0 :     const data_small_set_t *const set_to_be_copied = gui_marked_set_get_selected_set_const( (*this_).marker );
     330              : 
     331              :     /* even in case data_small_set_is_empty( set_to_be_copied ),
     332              :      * it is possible to copy an empty set to the clipboard
     333              :      * --> therefore simply continue... */
     334            0 :     out_err = gui_clipboard_copy_set_to_clipboard( &((*this_).clipboard), set_to_be_copied, &stat );
     335              : 
     336            0 :     if ( out_err == 0 )
     337              :     {
     338            0 :         if ( 0 == data_stat_get_total_count( &stat ) )
     339              :         {
     340            0 :             gui_simple_message_to_user_show_message( (*this_).message_to_user,
     341              :                                                      GUI_SIMPLE_MESSAGE_TYPE_WARNING,
     342              :                                                      GUI_SIMPLE_MESSAGE_CONTENT_NO_SELECTION
     343              :                                                    );
     344              :         }
     345              :         else
     346              :         {
     347            0 :             gui_simple_message_to_user_show_message_with_stat( (*this_).message_to_user,
     348              :                                                                GUI_SIMPLE_MESSAGE_TYPE_INFO,
     349              :                                                                GUI_SIMPLE_MESSAGE_CONTENT_COPY_TO_CLIPBOARD,
     350              :                                                                &stat
     351              :                                                              );
     352              :         }
     353              :     }
     354              :     else
     355              :     {
     356              :         /* error to be shown to the user */
     357            0 :         gui_simple_message_to_user_show_message( (*this_).message_to_user,
     358              :                                                  GUI_SIMPLE_MESSAGE_TYPE_ERROR,
     359              :                                                  GUI_SIMPLE_MESSAGE_CONTENT_STRING_TRUNCATED
     360              :                                                );
     361              :     }
     362              : 
     363            0 :     data_stat_destroy(&stat);
     364              : 
     365            0 :     U8_TRACE_END();
     366            0 : }
     367              : 
     368            0 : void gui_toolbox_paste_btn_callback( GtkWidget* button, gpointer data )
     369              : {
     370            0 :     U8_TRACE_BEGIN();
     371            0 :     gui_toolbox_t *this_ = data;
     372            0 :     assert( NULL != this_ );
     373              : 
     374            0 :     gui_toolbox_paste( this_ );
     375              : 
     376            0 :     U8_TRACE_TIMESTAMP();
     377            0 :     U8_TRACE_END();
     378            0 : }
     379              : 
     380            0 : void gui_toolbox_paste( gui_toolbox_t *this_ )
     381              : {
     382            0 :     U8_TRACE_BEGIN();
     383            0 :     gui_simple_message_to_user_hide( (*this_).message_to_user );
     384              : 
     385            0 :     const data_id_t destination_diagram_id = gui_marked_set_get_focused_diagram( (*this_).marker );
     386            0 :     if ( data_id_is_valid( &destination_diagram_id ) )
     387              :     {
     388            0 :         const data_row_t dest_diagram_row = data_id_get_row( &destination_diagram_id );
     389            0 :         gui_clipboard_request_clipboard_text( &((*this_).clipboard), dest_diagram_row );
     390              : 
     391              :         /* this call triggers a callback later to gui_clipboard_clipboard_text_received_callback */
     392              : 
     393              :         /* Note: (*this_).message_to_user is updated by (*this_).clipboard already - nothing to do here */
     394              :     }
     395              :     else
     396              :     {
     397              :         /* error to be shown to the user */
     398            0 :         gui_simple_message_to_user_show_message( (*this_).message_to_user,
     399              :                                                  GUI_SIMPLE_MESSAGE_TYPE_ERROR,
     400              :                                                  GUI_SIMPLE_MESSAGE_CONTENT_NO_FOCUS
     401              :                                                );
     402              :     }
     403              : 
     404            0 :     U8_TRACE_END();
     405            0 : }
     406              : 
     407            0 : void gui_toolbox_delete_btn_callback( GtkWidget* button, gpointer data )
     408              : {
     409            0 :     U8_TRACE_BEGIN();
     410            0 :     gui_toolbox_t *this_ = data;
     411            0 :     assert( NULL != this_ );
     412              : 
     413            0 :     gui_toolbox_delete( this_ );
     414              : 
     415            0 :     U8_TRACE_TIMESTAMP();
     416            0 :     U8_TRACE_END();
     417            0 : }
     418              : 
     419            0 : void gui_toolbox_delete( gui_toolbox_t *this_ )
     420              : {
     421            0 :     U8_TRACE_BEGIN();
     422              :     u8_error_t ctrl_err;
     423              : 
     424            0 :     gui_simple_message_to_user_hide( (*this_).message_to_user );
     425              : 
     426              :     data_stat_t stat;
     427            0 :     data_stat_init(&stat);
     428              : 
     429            0 :     const data_small_set_t *const set_to_be_deleted = gui_marked_set_get_selected_set_const( (*this_).marker );
     430              : 
     431              :     /* do not check if set is empty; gui_toolbox_private_delete_set will do this */
     432              : 
     433            0 :     ctrl_err = gui_toolbox_private_delete_set( this_, set_to_be_deleted, &stat );
     434              : 
     435            0 :     gui_marked_set_clear_selected_set( (*this_).marker );
     436              : 
     437            0 :     if ( U8_ERROR_INPUT_EMPTY == ctrl_err )
     438              :     {
     439            0 :         gui_simple_message_to_user_show_message( (*this_).message_to_user,
     440              :                                                  GUI_SIMPLE_MESSAGE_TYPE_WARNING,
     441              :                                                  GUI_SIMPLE_MESSAGE_CONTENT_NO_SELECTION
     442              :                                                );
     443              :     }
     444            0 :     else if ( u8_error_contains( ctrl_err, U8_ERROR_OBJECT_STILL_REFERENCED ) )
     445              :     {
     446            0 :         gui_simple_message_to_user_show_message( (*this_).message_to_user,
     447              :                                                  GUI_SIMPLE_MESSAGE_TYPE_ERROR,
     448              :                                                  GUI_SIMPLE_MESSAGE_CONTENT_DELETING_NOT_POSSIBLE
     449              :                                                );
     450              :     }
     451            0 :     else if ( U8_ERROR_NONE != ctrl_err )
     452              :     {
     453            0 :         U8_LOG_ERROR_HEX( "Error in ctrl_classifier_controller_delete_set_from_diagram", ctrl_err );
     454              :     }
     455              :     else
     456              :     {
     457            0 :         gui_simple_message_to_user_show_message_with_stat ( (*this_).message_to_user,
     458              :                                                             GUI_SIMPLE_MESSAGE_TYPE_INFO,
     459              :                                                             GUI_SIMPLE_MESSAGE_CONTENT_DELETE,
     460              :                                                             &stat
     461              :                                                           );
     462              :     }
     463              : 
     464            0 :     data_stat_destroy(&stat);
     465              : 
     466            0 :     U8_TRACE_END();
     467            0 : }
     468              : 
     469            0 : u8_error_t gui_toolbox_private_delete_set( gui_toolbox_t *this_,
     470              :                                            const data_small_set_t *set_to_be_deleted,
     471              :                                            data_stat_t *io_stat )
     472              : {
     473            0 :     U8_TRACE_BEGIN();
     474            0 :     assert( NULL != set_to_be_deleted );
     475            0 :     assert( NULL != io_stat );
     476              :     u8_error_t ctrl_err;
     477              : 
     478              :     ctrl_multi_step_changer_t multi_stepper;
     479            0 :     ctrl_multi_step_changer_init( &multi_stepper, (*this_).controller, (*this_).db_reader );
     480              : 
     481            0 :     ctrl_err = ctrl_multi_step_changer_delete_set ( &multi_stepper, set_to_be_deleted, io_stat );
     482              : 
     483            0 :     ctrl_multi_step_changer_destroy( &multi_stepper );
     484              : 
     485            0 :     U8_TRACE_END_ERR( ctrl_err );
     486            0 :     return ctrl_err;
     487              : }
     488              : 
     489            0 : void gui_toolbox_highlight_btn_callback( GtkWidget* button, gpointer data )
     490              : {
     491            0 :     U8_TRACE_BEGIN();
     492            0 :     gui_toolbox_t *this_ = data;
     493            0 :     assert( NULL != this_ );
     494              : 
     495            0 :     gui_simple_message_to_user_hide( (*this_).message_to_user );
     496              : 
     497            0 :     const data_small_set_t *const set_to_be_highlighted = gui_marked_set_get_selected_set_const( (*this_).marker );
     498              : 
     499              :     /* do not check if set is empty; gui_toolbox_private_toggle_display_flag_in_set will do this */
     500              : 
     501            0 :     gui_toolbox_private_toggle_display_flag_in_set( this_,
     502              :                                                     set_to_be_highlighted,
     503              :                                                     DATA_DIAGRAMELEMENT_FLAG_EMPHASIS | DATA_DIAGRAMELEMENT_FLAG_GRAY_OUT
     504              :                                                   );
     505              : 
     506            0 :     U8_TRACE_TIMESTAMP();
     507            0 :     U8_TRACE_END();
     508            0 : }
     509              : 
     510            0 : void gui_toolbox_instantiate_btn_callback( GtkWidget* button, gpointer data )
     511              : {
     512            0 :     U8_TRACE_BEGIN();
     513            0 :     gui_toolbox_t *this_ = data;
     514            0 :     assert( NULL != this_ );
     515              : 
     516            0 :     gui_simple_message_to_user_hide( (*this_).message_to_user );
     517              : 
     518            0 :     const data_small_set_t *const set_to_be_instantiated = gui_marked_set_get_selected_set_const( (*this_).marker );
     519              : 
     520              :     /* do not check if set is empty; gui_toolbox_private_toggle_display_flag_in_set will do this */
     521              : 
     522            0 :     gui_toolbox_private_toggle_display_flag_in_set( this_,
     523              :                                                     set_to_be_instantiated,
     524              :                                                     DATA_DIAGRAMELEMENT_FLAG_NAMED_INSTANCE | DATA_DIAGRAMELEMENT_FLAG_ANONYMOUS_INSTANCE
     525              :                                                   );
     526              : 
     527            0 :     U8_TRACE_TIMESTAMP();
     528            0 :     U8_TRACE_END();
     529            0 : }
     530              : 
     531            0 : void gui_toolbox_reset_btn_callback( GtkWidget* button, gpointer data )
     532              : {
     533            0 :     U8_TRACE_BEGIN();
     534            0 :     gui_toolbox_t *this_ = data;
     535            0 :     assert( NULL != this_ );
     536              : 
     537            0 :     gui_simple_message_to_user_hide( (*this_).message_to_user );
     538              : 
     539            0 :     gui_marked_set_clear_selected_set( (*this_).marker );
     540              :     //gui_marked_set_clear_focused( (*this_).marker );
     541              : 
     542              :     /* trigger redraw */
     543            0 :     gui_toolbox_private_notify_listeners( this_ );
     544              : 
     545            0 :     U8_TRACE_TIMESTAMP();
     546            0 :     U8_TRACE_END();
     547            0 : }
     548              : 
     549            0 : void gui_toolbox_private_toggle_display_flag_in_set( gui_toolbox_t *this_,
     550              :                                                      const data_small_set_t *set_to_be_toggled,
     551              :                                                      data_diagramelement_flag_t flag_bits_to_toggle )
     552              : {
     553            0 :     U8_TRACE_BEGIN();
     554            0 :     u8_error_t error = U8_ERROR_NONE;
     555            0 :     bool new_pattern_initialized = false;
     556            0 :     data_diagramelement_flag_t new_pattern = DATA_DIAGRAMELEMENT_FLAG_NONE;
     557            0 :     bool is_first = true;
     558              : 
     559            0 :     for ( int index = 0; index < data_small_set_get_count( set_to_be_toggled ); index ++ )
     560              :     {
     561              :         data_id_t current_id;
     562            0 :         current_id = data_small_set_get_id( set_to_be_toggled, index );
     563            0 :         switch ( data_id_get_table( &current_id ) )
     564              :         {
     565            0 :             case DATA_TABLE_CLASSIFIER:
     566              :             {
     567              :                 /* program internal error */
     568            0 :                 U8_LOG_WARNING( "gui_toolbox_private_toggle_display_flag_in_set cannot toggle display flags in non-diagramelements." );
     569            0 :                 error |= U8_ERROR_INVALID_REQUEST;
     570              :             }
     571            0 :             break;
     572              : 
     573            0 :             case DATA_TABLE_FEATURE:
     574              :             {
     575              :                 /* program internal error */
     576            0 :                 U8_LOG_WARNING( "gui_toolbox_private_toggle_display_flag_in_set cannot toggle display flags in non-diagramelements." );
     577            0 :                 error |= U8_ERROR_INVALID_REQUEST;
     578              :             }
     579            0 :             break;
     580              : 
     581            0 :             case DATA_TABLE_RELATIONSHIP:
     582              :             {
     583              :                 /* program internal error */
     584            0 :                 U8_LOG_WARNING( "gui_toolbox_private_toggle_display_flag_in_set cannot toggle display flags in non-diagramelements." );
     585            0 :                 error |= U8_ERROR_INVALID_REQUEST;
     586              :             }
     587            0 :             break;
     588              : 
     589            0 :             case DATA_TABLE_DIAGRAMELEMENT:
     590              :             {
     591              :                 data_diagramelement_t out_diagramelement;
     592            0 :                 data_row_t diag_elem_id = data_id_get_row( &current_id );
     593              :                 ctrl_diagram_controller_t *diag_ctrl;
     594            0 :                 diag_ctrl = ctrl_controller_get_diagram_control_ptr( (*this_).controller );
     595              : 
     596            0 :                 error |= (u8_error_t) data_database_reader_get_diagramelement_by_id ( (*this_).db_reader,
     597              :                                                                                         diag_elem_id,
     598              :                                                                                         &out_diagramelement
     599              :                                                                                       );
     600              :                 data_diagramelement_flag_t current_flags;
     601            0 :                 current_flags = data_diagramelement_get_display_flags( &out_diagramelement );
     602              : 
     603            0 :                 if ( ! new_pattern_initialized )
     604              :                 {
     605              :                     /* select zero or one bit to set. alg: select the next highest bit */
     606            0 :                     bool last_was_set = true;
     607            0 :                     new_pattern = DATA_DIAGRAMELEMENT_FLAG_NONE;
     608            0 :                     for ( int bit = 0; bit < 8*sizeof(data_diagramelement_flag_t); bit ++ )
     609              :                     {
     610            0 :                         data_diagramelement_flag_t probe = (1 << bit);
     611            0 :                         if ( 0 != ( probe & flag_bits_to_toggle ) )
     612              :                         {
     613              :                             /* this is a relevant bit */
     614            0 :                             if ( 0 != ( probe & current_flags ) )
     615              :                             {
     616            0 :                                 new_pattern = DATA_DIAGRAMELEMENT_FLAG_NONE;
     617            0 :                                 last_was_set = true;
     618              :                             }
     619              :                             else
     620              :                             {
     621            0 :                                 if ( last_was_set )
     622              :                                 {
     623            0 :                                     new_pattern = probe;
     624              :                                 }
     625            0 :                                 last_was_set = false;
     626              :                             }
     627              :                         }
     628              :                     }
     629            0 :                     new_pattern_initialized = true;
     630              :                 }
     631              : 
     632            0 :                 current_flags = (current_flags & (~flag_bits_to_toggle)) | new_pattern;
     633              : 
     634            0 :                 error |= ctrl_diagram_controller_update_diagramelement_display_flags( diag_ctrl,
     635              :                                                                                       diag_elem_id,
     636              :                                                                                       current_flags,
     637              :                                                                                       ( is_first
     638              :                                                                                       ? CTRL_UNDO_REDO_ACTION_BOUNDARY_START_NEW
     639            0 :                                                                                       : CTRL_UNDO_REDO_ACTION_BOUNDARY_APPEND )
     640              :                                                                                     );
     641            0 :                 is_first = false;
     642              :             }
     643            0 :             break;
     644              : 
     645            0 :             case DATA_TABLE_DIAGRAM:
     646              :             {
     647              :                 /* program internal error */
     648            0 :                 U8_LOG_WARNING( "gui_toolbox_private_toggle_display_flag_in_set cannot toggle display flags in non-diagramelements." );
     649            0 :                 error |= U8_ERROR_INVALID_REQUEST;
     650              :             }
     651            0 :             break;
     652              : 
     653            0 :             default:
     654              :             {
     655              :                 /* program internal error */
     656            0 :                 U8_LOG_ERROR( "gui_toolbox_private_toggle_display_flag_in_set fould illegal data_table_t enum value." );
     657              :             }
     658            0 :             break;
     659              :         }
     660              :     }
     661              : 
     662            0 :     if ( error != U8_ERROR_NONE )
     663              :     {
     664              :         /* error to be shown to the user */
     665            0 :         gui_simple_message_to_user_show_message( (*this_).message_to_user,
     666              :                                                  GUI_SIMPLE_MESSAGE_TYPE_WARNING,
     667              :                                                  GUI_SIMPLE_MESSAGE_CONTENT_SET_PARTLY_UNSUITABLE
     668              :                                                );
     669              :     }
     670            0 :     else if ( 0 == data_small_set_get_count( set_to_be_toggled ) )
     671              :     {
     672              :         /* error to be shown to the user */
     673            0 :         gui_simple_message_to_user_show_message( (*this_).message_to_user,
     674              :                                                  GUI_SIMPLE_MESSAGE_TYPE_WARNING,
     675              :                                                  GUI_SIMPLE_MESSAGE_CONTENT_NO_SELECTION
     676              :                                                );
     677              :     }
     678              : 
     679            0 :     U8_TRACE_END();
     680            0 : }
     681              : 
     682            0 : void gui_toolbox_undo_btn_callback( GtkWidget* button, gpointer data )
     683              : {
     684            0 :     U8_TRACE_BEGIN();
     685            0 :     gui_toolbox_t *this_ = data;
     686            0 :     assert( this_ != NULL );
     687              :     u8_error_t ctrl_err;
     688              : 
     689            0 :     gui_simple_message_to_user_hide( (*this_).message_to_user );
     690              : 
     691              :     data_stat_t stat;
     692            0 :     data_stat_init( &stat );
     693              : 
     694            0 :     ctrl_err = ctrl_controller_undo( (*this_).controller, &stat );
     695              : 
     696              :     /* find a diagram that can show the changes */
     697            0 :     if ( U8_ERROR_NONE == ctrl_err )
     698              :     {
     699              :         ctrl_undo_redo_iterator_t iter;
     700            0 :         ctrl_undo_redo_iterator_init_empty( &iter );
     701            0 :         ctrl_err |= ctrl_controller_get_redo_iterator( (*this_).controller, &iter );
     702            0 :         gui_toolbox_private_show_changes( this_, &iter );
     703            0 :         ctrl_undo_redo_iterator_destroy( &iter );
     704              :     }
     705              : 
     706              :     /* show error/success message to the user */
     707            0 :     if ( U8_ERROR_INVALID_REQUEST == ctrl_err )
     708              :     {
     709            0 :         gui_simple_message_to_user_show_message( (*this_).message_to_user,
     710              :                                                  GUI_SIMPLE_MESSAGE_TYPE_WARNING,
     711              :                                                  GUI_SIMPLE_MESSAGE_CONTENT_NO_MORE_UNDO
     712              :                                                );
     713              :     }
     714            0 :     else if ( U8_ERROR_ARRAY_BUFFER_EXCEEDED == ctrl_err )
     715              :     {
     716            0 :         gui_simple_message_to_user_show_message( (*this_).message_to_user,
     717              :                                                  GUI_SIMPLE_MESSAGE_TYPE_ERROR,
     718              :                                                  GUI_SIMPLE_MESSAGE_CONTENT_UNDO_NOT_POSSIBLE
     719              :                                                );
     720              :     }
     721              :     else
     722              :     {
     723              :         /* success */
     724            0 :         gui_simple_message_to_user_show_message_with_stat( (*this_).message_to_user,
     725              :                                                            GUI_SIMPLE_MESSAGE_TYPE_INFO,
     726              :                                                            GUI_SIMPLE_MESSAGE_CONTENT_UNDO,
     727              :                                                            &stat
     728              :                                                          );
     729              :     }
     730              : 
     731            0 :     data_stat_destroy( &stat );
     732              : 
     733            0 :     U8_TRACE_TIMESTAMP();
     734            0 :     U8_TRACE_END();
     735            0 : }
     736              : 
     737            0 : gboolean gui_toolbox_undo_shortcut_callback( GtkWidget* widget, GVariant* args, gpointer user_data )
     738              : {
     739            0 :     gui_toolbox_undo_btn_callback( widget, user_data );
     740            0 :     return TRUE;
     741              : }
     742              : 
     743            0 : void gui_toolbox_redo_btn_callback( GtkWidget* button, gpointer data )
     744              : {
     745            0 :     U8_TRACE_BEGIN();
     746            0 :     gui_toolbox_t *this_ = data;
     747            0 :     assert( this_ != NULL );
     748              :     u8_error_t ctrl_err;
     749              : 
     750            0 :     gui_simple_message_to_user_hide( (*this_).message_to_user );
     751              : 
     752              :     data_stat_t stat;
     753            0 :     data_stat_init( &stat );
     754              : 
     755            0 :     ctrl_err = ctrl_controller_redo( (*this_).controller, &stat );
     756              : 
     757              :     /* find a diagram that can show the changes */
     758            0 :     if ( U8_ERROR_NONE == ctrl_err )
     759              :     {
     760              :         ctrl_undo_redo_iterator_t iter;
     761            0 :         ctrl_undo_redo_iterator_init_empty( &iter );
     762            0 :         ctrl_err |= ctrl_controller_get_undo_iterator( (*this_).controller, &iter );
     763            0 :         gui_toolbox_private_show_changes( this_, &iter );
     764            0 :         ctrl_undo_redo_iterator_destroy( &iter );
     765              :     }
     766              : 
     767              :     /* show error/success message to the user */
     768            0 :     if ( U8_ERROR_INVALID_REQUEST == ctrl_err )
     769              :     {
     770            0 :         gui_simple_message_to_user_show_message( (*this_).message_to_user,
     771              :                                                  GUI_SIMPLE_MESSAGE_TYPE_WARNING,
     772              :                                                  GUI_SIMPLE_MESSAGE_CONTENT_NO_MORE_REDO
     773              :                                                );
     774              :     }
     775              :     else
     776              :     {
     777              :         /* success */
     778            0 :         gui_simple_message_to_user_show_message_with_stat( (*this_).message_to_user,
     779              :                                                            GUI_SIMPLE_MESSAGE_TYPE_INFO,
     780              :                                                            GUI_SIMPLE_MESSAGE_CONTENT_REDO,
     781              :                                                            &stat
     782              :                                                          );
     783              :     }
     784              : 
     785            0 :     data_stat_destroy( &stat );
     786              : 
     787            0 :     U8_TRACE_TIMESTAMP();
     788            0 :     U8_TRACE_END();
     789            0 : }
     790              : 
     791              : /*!
     792              :  *  \brief callback that informs that the redo shortcut was activated
     793              :  */
     794            0 : gboolean gui_toolbox_redo_shortcut_callback( GtkWidget* widget, GVariant* args, gpointer user_data )
     795              : {
     796            0 :     gui_toolbox_redo_btn_callback( widget, user_data );
     797            0 :     return TRUE;
     798              : }
     799              : 
     800            0 : void gui_toolbox_private_show_changes( gui_toolbox_t *this_,
     801              :                                        ctrl_undo_redo_iterator_t *action_iterator )
     802              : {
     803            0 :     U8_TRACE_BEGIN();
     804            0 :     data_id_t display_diag_nav = DATA_ID_VOID;  /* display this diagram in navigation mode, prio 1 */
     805            0 :     data_id_t display_diag_edit = DATA_ID_VOID;  /* display this diagram in edit mode, prio 2 */
     806            0 :     data_id_t display_classifier = DATA_ID_VOID;  /* display this classifier somehow, prio 3 */
     807              : 
     808            0 :     while( ctrl_undo_redo_iterator_has_next( action_iterator ) )
     809              :     {
     810            0 :         const ctrl_undo_redo_entry_t *const probe = ctrl_undo_redo_iterator_next( action_iterator );
     811              : 
     812            0 :         switch( ctrl_undo_redo_entry_get_action_type( probe ) )
     813              :         {
     814            0 :             case CTRL_UNDO_REDO_ENTRY_TYPE_DELETE_DIAGRAM:
     815              :             {
     816              :                 const data_diagram_t *const diag
     817            0 :                     = ctrl_undo_redo_entry_get_diagram_before_action_const( probe );
     818            0 :                 assert( data_diagram_is_valid( diag ) );
     819            0 :                 display_diag_nav = data_diagram_get_parent_data_id( diag );
     820              :             }
     821            0 :             break;
     822              : 
     823            0 :             case CTRL_UNDO_REDO_ENTRY_TYPE_CREATE_DIAGRAM:
     824              :             {
     825              :                 const data_diagram_t *const diag
     826            0 :                     = ctrl_undo_redo_entry_get_diagram_after_action_const( probe );
     827            0 :                 assert( data_diagram_is_valid( diag ) );
     828            0 :                 display_diag_nav = data_diagram_get_parent_data_id( diag );
     829              :             }
     830            0 :             break;
     831              : 
     832            0 :             case CTRL_UNDO_REDO_ENTRY_TYPE_UPDATE_DIAGRAM:
     833              :             {
     834              :                 const data_diagram_t *const diag
     835            0 :                     = ctrl_undo_redo_entry_get_diagram_after_action_const( probe );
     836            0 :                 assert( data_diagram_is_valid( diag ) );
     837            0 :                 display_diag_edit = data_diagram_get_data_id( diag );
     838              :             }
     839            0 :             break;
     840              : 
     841            0 :             case CTRL_UNDO_REDO_ENTRY_TYPE_DELETE_DIAGRAMELEMENT:
     842              :             {
     843              :                 const data_diagramelement_t *const diagele
     844            0 :                     = ctrl_undo_redo_entry_get_diagramelement_before_action_const( probe );
     845            0 :                 assert( data_diagramelement_is_valid( diagele ) );
     846            0 :                 display_diag_edit = data_diagramelement_get_diagram_data_id( diagele );
     847              :             }
     848            0 :             break;
     849              : 
     850            0 :             case CTRL_UNDO_REDO_ENTRY_TYPE_CREATE_DIAGRAMELEMENT:  /* ... or ... */
     851              :             case CTRL_UNDO_REDO_ENTRY_TYPE_UPDATE_DIAGRAMELEMENT:
     852              :             {
     853              :                 const data_diagramelement_t *const diagele
     854            0 :                     = ctrl_undo_redo_entry_get_diagramelement_after_action_const( probe );
     855            0 :                 assert( data_diagramelement_is_valid( diagele ) );
     856            0 :                 display_diag_edit = data_diagramelement_get_diagram_data_id( diagele );
     857              :             }
     858            0 :             break;
     859              : 
     860            0 :             case CTRL_UNDO_REDO_ENTRY_TYPE_DELETE_CLASSIFIER:  /* ... or ... */
     861              :             case CTRL_UNDO_REDO_ENTRY_TYPE_CREATE_CLASSIFIER:
     862              :             {
     863              :                 /* Nothing to do: When a classifier is created or deleted, also */
     864              :                 /* a diagramelement is created or deleted. */
     865              :             }
     866            0 :             break;
     867              : 
     868            0 :             case CTRL_UNDO_REDO_ENTRY_TYPE_UPDATE_CLASSIFIER:
     869              :             {
     870              :                 const data_classifier_t *const classifier
     871            0 :                     = ctrl_undo_redo_entry_get_classifier_after_action_const( probe );
     872            0 :                 assert( data_classifier_is_valid( classifier ) );
     873            0 :                 display_classifier = data_classifier_get_data_id( classifier );
     874              :             }
     875            0 :             break;
     876              : 
     877            0 :             case CTRL_UNDO_REDO_ENTRY_TYPE_DELETE_FEATURE:
     878              :             {
     879              :                 const data_feature_t *const feature
     880            0 :                     = ctrl_undo_redo_entry_get_feature_before_action_const( probe );
     881            0 :                 assert( data_feature_is_valid( feature ) );
     882            0 :                 display_classifier = data_feature_get_classifier_data_id( feature );
     883              :             }
     884            0 :             break;
     885              : 
     886            0 :             case CTRL_UNDO_REDO_ENTRY_TYPE_UPDATE_FEATURE:  /* ... or ... */
     887              :             case CTRL_UNDO_REDO_ENTRY_TYPE_CREATE_FEATURE:
     888              :             {
     889              :                 const data_feature_t *const feature
     890            0 :                     = ctrl_undo_redo_entry_get_feature_after_action_const( probe );
     891            0 :                 assert( data_feature_is_valid( feature ) );
     892            0 :                 display_classifier = data_feature_get_classifier_data_id( feature );
     893              :             }
     894            0 :             break;
     895              : 
     896            0 :             case CTRL_UNDO_REDO_ENTRY_TYPE_DELETE_RELATIONSHIP:
     897              :             {
     898              :                 const data_relationship_t *const relationship
     899            0 :                     = ctrl_undo_redo_entry_get_relationship_before_action_const( probe );
     900            0 :                 assert( data_relationship_is_valid( relationship ) );
     901            0 :                 display_classifier = data_relationship_get_from_classifier_data_id( relationship );
     902              :             }
     903            0 :             break;
     904              : 
     905            0 :             case CTRL_UNDO_REDO_ENTRY_TYPE_UPDATE_RELATIONSHIP:  /* ... or ... */
     906              :             case CTRL_UNDO_REDO_ENTRY_TYPE_CREATE_RELATIONSHIP:
     907              :             {
     908              :                 const data_relationship_t *const relationship
     909            0 :                     = ctrl_undo_redo_entry_get_relationship_after_action_const( probe );
     910            0 :                 assert( data_relationship_is_valid( relationship ) );
     911            0 :                 display_classifier = data_relationship_get_from_classifier_data_id( relationship );
     912              :             }
     913            0 :             break;
     914              : 
     915            0 :             default:  /* ... or ... */
     916              :             case CTRL_UNDO_REDO_ENTRY_TYPE_BOUNDARY:
     917              :             {
     918            0 :                 U8_LOG_WARNING( "gui_toolbox_private_show_changes runs into unexpected switch-case." );
     919            0 :                 assert( false );
     920              :             }
     921              :             break;
     922              :         }
     923              :     }
     924              : 
     925            0 :     if ( data_id_is_valid( &display_diag_nav ) )
     926              :     {
     927            0 :         gui_toolbox_set_selected_tool_and_focus( this_, GUI_TOOL_NAVIGATE, display_diag_nav );
     928              :     }
     929            0 :     else if ( data_id_is_valid( &display_diag_edit ) )
     930              :     {
     931            0 :         gui_toolbox_set_selected_tool_and_focus( this_, GUI_TOOL_EDIT, display_diag_edit );
     932              :     }
     933            0 :     else if ( data_id_is_valid( &display_classifier ) )
     934              :     {
     935              :         /* try to find ANY diagram that MAY show the modified object: */
     936            0 :         assert( data_id_get_table( &display_classifier ) == DATA_TABLE_CLASSIFIER );
     937              :         data_small_set_t diagram_ids;
     938            0 :         data_small_set_init( &diagram_ids );
     939              :         const u8_error_t d_err
     940            0 :             =  data_database_reader_get_diagram_ids_by_classifier_id( (*this_).db_reader,
     941              :                                                                       data_id_get_row( &display_classifier ),
     942              :                                                                       &diagram_ids
     943              :                                                                     );
     944            0 :         if (( d_err == U8_ERROR_NONE )||( d_err == U8_ERROR_ARRAY_BUFFER_EXCEEDED ))
     945              :         {
     946            0 :             if ( data_small_set_contains( &diagram_ids, gui_marked_set_get_focused_diagram( (*this_).marker ) ) )
     947              :             {
     948              :                 /* the right diagram is already shown, just update the tool */
     949            0 :                 gui_toolbox_set_selected_tool( this_, GUI_TOOL_EDIT );
     950              :             }
     951            0 :             else if ( ! data_small_set_is_empty( &diagram_ids ) )
     952              :             {
     953            0 :                 gui_toolbox_set_selected_tool_and_focus( this_, GUI_TOOL_EDIT, data_small_set_get_id( &diagram_ids, 0 ) );
     954              :             }
     955              :             else
     956              :             {
     957            0 :                 U8_LOG_ANOMALY( "gui_toolbox_private_show_changes found a classifier without a diagram." );
     958              :             }
     959              :         }
     960            0 :         data_small_set_destroy( &diagram_ids );
     961              :     }
     962              :     else
     963              :     {
     964            0 :         U8_LOG_ANOMALY( "gui_toolbox_private_show_changes did not find a diagram to show the changes." );
     965              :     }
     966              : 
     967            0 :     U8_TRACE_END();
     968            0 : }
     969              : 
     970            0 : void gui_toolbox_private_notify_listeners( gui_toolbox_t *this_ )
     971              : {
     972            0 :     U8_TRACE_BEGIN();
     973              : 
     974            0 :     U8_TRACE_INFO( "g_signal_emit to listeners" );
     975            0 :     g_signal_emit( (*this_).toolbar, gui_toolbox_glib_signal_id, 0, (*this_).selected_tool );
     976              : 
     977            0 :     U8_TRACE_END();
     978            0 : }
     979              : 
     980              : 
     981              : /*
     982              : Copyright 2016-2026 Andreas Warnke
     983              : 
     984              : Licensed under the Apache License, Version 2.0 (the "License");
     985              : you may not use this file except in compliance with the License.
     986              : You may obtain a copy of the License at
     987              : 
     988              :     http://www.apache.org/licenses/LICENSE-2.0
     989              : 
     990              : Unless required by applicable law or agreed to in writing, software
     991              : distributed under the License is distributed on an "AS IS" BASIS,
     992              : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     993              : See the License for the specific language governing permissions and
     994              : limitations under the License.
     995              : */
        

Generated by: LCOV version 2.0-1