LCOV - code coverage report
Current view: top level - gui/source - gui_main_window.c (source / functions) Hit Total Coverage
Test: crystal-facet-uml_v1.62.0_covts Lines: 0 599 0.0 %
Date: 2024-12-21 18:34:41 Functions: 0 18 0.0 %

          Line data    Source code
       1             : /* File: gui_main_window.c; Copyright and License: see below */
       2             : 
       3             : #include "gui_main_window.h"
       4             : #include "gui_clipboard.h"
       5             : #include "gui_type_resource.h"
       6             : #include "u8/u8_trace.h"
       7             : #include "entity/data_diagram_type.h"
       8             : #include "entity/data_classifier_type.h"
       9             : #include "entity/data_feature_type.h"
      10             : #include "entity/data_relationship_type.h"
      11             : #include "storage/data_database.h"
      12             : #include "storage/data_change_notifier.h"
      13             : #include "meta/meta_info.h"
      14             : #include <gdk/gdk.h>
      15             : #include <gtk/gtk.h>
      16             : #include <stdio.h>
      17             : #include <stdbool.h>
      18             : 
      19           0 : void gui_main_window_init( gui_main_window_t *this_,
      20             :                            ctrl_controller_t *controller,
      21             :                            io_data_file_t *data_file,
      22             :                            data_database_reader_t *db_reader,
      23             :                            gui_resources_t *resources,
      24             :                            GtkApplication *gtk_app,
      25             :                            observer_t *window_close_observer,
      26             :                            observer_t *window_open_observer )
      27             : {
      28           0 :     U8_TRACE_BEGIN();
      29           0 :     assert( gtk_app != NULL );
      30             : 
      31             :     /* init own attributes */
      32           0 :     (*this_).window_close_observer = window_close_observer;
      33           0 :     (*this_).window_open_observer = window_open_observer;
      34           0 :     (*this_).data_file = data_file;
      35           0 :     (*this_).resources = resources;
      36             : 
      37             :     /* init window */
      38             :     {
      39           0 :         (*this_).window = gtk_application_window_new( gtk_app );
      40             :         const char *window_title;
      41           0 :         window_title = io_data_file_get_filename_const( data_file );
      42           0 :         gtk_window_set_title(GTK_WINDOW( (*this_).window ), ( window_title == NULL ) ? META_INFO_PROGRAM_NAME_STR : window_title );
      43           0 :         gtk_widget_set_size_request( (*this_).window, 800, 400 );
      44           0 :         gtk_window_set_default_size( GTK_WINDOW( (*this_).window ), 16*70, 9*70 );
      45             :     }
      46             : 
      47             :     /* init the message widgets */
      48           0 :     gui_main_window_private_init_simple_message_to_user( this_ );
      49           0 :     gui_simple_message_to_user_init( &((*this_).message_to_user), (*this_).message_text_label, (*this_).message_icon_image, resources );
      50             : 
      51             :     /* init the keyboard shortcuts */
      52             :     {
      53           0 :         (*this_).keyboard_shortcut_ctrl = GTK_SHORTCUT_CONTROLLER(gtk_shortcut_controller_new());
      54           0 :         gtk_widget_add_controller( (*this_).window, GTK_EVENT_CONTROLLER((*this_).keyboard_shortcut_ctrl) );
      55             :     }
      56             : 
      57             :     /* init tools */
      58           0 :     gui_main_window_private_init_toolbox( this_ );
      59             : 
      60             :     /* determine the current/main clipboard */
      61           0 :     GdkClipboard *current_clipboard = NULL;
      62             :     {
      63           0 :         current_clipboard = gtk_widget_get_clipboard( GTK_WIDGET((*this_).window) );  /* idea taken from gtk demo */
      64             :     }
      65             : 
      66           0 :     gui_marked_set_init( &((*this_).marker_data),
      67           0 :                          G_OBJECT((*this_).window),
      68             :                          &gui_sketch_area_show_diagram,
      69           0 :                          &((*this_).sketcharea_data)
      70             :                        );
      71           0 :     gui_toolbox_init( &((*this_).tools_data),
      72           0 :                       GTK_WIDGET( (*this_).tool_row ),
      73           0 :                       gui_button_get_widget_ptr( &((*this_).view_navigate) ),
      74           0 :                       gui_button_get_widget_ptr( &((*this_).view_edit) ),
      75           0 :                       gui_button_get_widget_ptr( &((*this_).view_create) ),
      76           0 :                       gui_button_get_widget_ptr( &((*this_).view_search) ),
      77             :                       current_clipboard,
      78             :                       &((*this_).marker_data),
      79             :                       &((*this_).message_to_user),
      80             :                       db_reader,
      81             :                       controller
      82             :                     );
      83             : 
      84             :     /* init search widgets and sketch area */
      85           0 :     gui_main_window_private_init_search_and_sketch_area( this_ );
      86           0 :     gui_search_runner_init( &((*this_).search_runner),
      87             :                             &((*this_).message_to_user),
      88             :                             db_reader,
      89             :                             io_data_file_get_database_ptr( data_file ),
      90             :                             &((*this_).sketcharea_data)
      91             :                           );
      92           0 :     gui_search_request_init( &((*this_).search_request),
      93             :                              (*this_).search_label,
      94             :                              (*this_).search_entry,
      95             :                              (*this_).search_button,
      96             :                              &((*this_).marker_data),
      97             :                              &((*this_).search_runner)
      98             :                            );
      99           0 :     gui_sketch_area_init( &((*this_).sketcharea_data),
     100             :                           (*this_).sketcharea,
     101             :                           &((*this_).marker_data),
     102             :                           &((*this_).tools_data),
     103             :                           &((*this_).message_to_user),
     104             :                           resources,
     105             :                           controller,
     106             :                           db_reader
     107             :                         );
     108             : 
     109             :     /* init attribute editor widgets */
     110           0 :     gui_main_window_private_init_attributes_editor( this_ );
     111             : 
     112           0 :     gui_attributes_editor_init( &((*this_).attributes_editor),
     113           0 :                                 GTK_LABEL( (*this_).id_label ),
     114           0 :                                 GTK_ENTRY( (*this_).name_entry ),
     115           0 :                                 GTK_ENTRY( (*this_).stereotype_entry ),
     116             :                                 (*this_).type_dropdown,
     117           0 :                                 GTK_WIDGET( (*this_).type_diag_grid ),
     118           0 :                                 GTK_WIDGET( (*this_).type_clas_grid ),
     119           0 :                                 GTK_WIDGET( (*this_).type_feat_grid ),
     120           0 :                                 GTK_WIDGET( (*this_).type_rel_grid ),
     121           0 :                                 GTK_TEXT_VIEW( (*this_).description_text_view ),
     122           0 :                                 gui_button_get_button_ptr( &((*this_).file_save ) ),
     123             :                                 resources,
     124             :                                 controller,
     125             :                                 db_reader,
     126             :                                 io_data_file_get_database_ptr( data_file ),
     127             :                                 &((*this_).message_to_user)
     128             :                               );
     129             : 
     130             :     /* init the file choosers */
     131           0 :     gui_file_action_init( &((*this_).file_action),
     132             :                           controller,
     133             :                           data_file,
     134             :                           &((*this_).message_to_user)
     135             :                         );
     136           0 :     gui_file_use_db_dialog_init( &((*this_).file_use_db_dialog),
     137           0 :                                  GTK_WINDOW( (*this_).window ),
     138             :                                  &((*this_).file_action)
     139             :                                );
     140           0 :     gui_file_export_dialog_init( &((*this_).file_export_dialog),
     141             :                                  io_data_file_get_database_ptr( data_file ),
     142             :                                  db_reader,
     143           0 :                                  GTK_WINDOW( (*this_).window ),
     144             :                                  &((*this_).message_to_user)
     145             :                                );
     146             : 
     147           0 :     U8_TRACE_INFO("GTK+ Widgets are created.");
     148             : 
     149           0 :     (*this_).two_panes = gtk_paned_new( GTK_ORIENTATION_HORIZONTAL );
     150           0 :     gtk_paned_set_start_child( GTK_PANED((*this_).two_panes), (*this_).sketch_stack_column );
     151           0 :     gtk_paned_set_resize_start_child( GTK_PANED((*this_).two_panes), true );
     152           0 :     gtk_paned_set_shrink_start_child( GTK_PANED((*this_).two_panes), false );
     153           0 :     gtk_paned_set_end_child( GTK_PANED((*this_).two_panes), (*this_).attr_edit_column );
     154           0 :     gtk_paned_set_resize_end_child( GTK_PANED((*this_).two_panes), false );
     155           0 :     gtk_paned_set_shrink_end_child( GTK_PANED((*this_).two_panes), true );
     156           0 :     gtk_widget_set_vexpand( GTK_WIDGET( (*this_).sketch_stack_column ), true );
     157           0 :     gtk_widget_set_hexpand( GTK_WIDGET( (*this_).sketch_stack_column ), true );
     158           0 :     gtk_widget_set_vexpand( GTK_WIDGET( (*this_).attr_edit_column ), true );
     159           0 :     gtk_widget_set_hexpand( GTK_WIDGET( (*this_).attr_edit_column ), false );
     160           0 :     gtk_paned_set_position( GTK_PANED((*this_).two_panes), 11*70 );
     161             : 
     162           0 :     (*this_).main_stack_column = gtk_box_new( GTK_ORIENTATION_VERTICAL, /*spacing:*/ 0 );
     163           0 :     gtk_box_append( GTK_BOX((*this_).main_stack_column), GTK_WIDGET((*this_).tool_row) );
     164           0 :     (*this_).options_layout = gui_file_export_dialog_get_options( &((*this_).file_export_dialog) );
     165           0 :     gtk_box_append( GTK_BOX((*this_).main_stack_column), (*this_).options_layout );
     166           0 :     gtk_box_append( GTK_BOX((*this_).main_stack_column), GTK_WIDGET((*this_).two_panes) );
     167           0 :     gtk_box_append( GTK_BOX((*this_).main_stack_column), GTK_WIDGET((*this_).message_row) );
     168           0 :     gtk_widget_set_vexpand( GTK_WIDGET( (*this_).tool_row ), false );
     169           0 :     gtk_widget_set_hexpand( GTK_WIDGET( (*this_).tool_row ), true );
     170           0 :     gtk_widget_set_vexpand( GTK_WIDGET( (*this_).two_panes ), true );
     171           0 :     gtk_widget_set_hexpand( GTK_WIDGET( (*this_).two_panes ), true );
     172           0 :     gtk_widget_set_vexpand( GTK_WIDGET( (*this_).message_row ), false );
     173           0 :     gtk_widget_set_hexpand( GTK_WIDGET( (*this_).message_row ), true );
     174             : 
     175           0 :     gtk_window_set_child( GTK_WINDOW((*this_).window), (*this_).main_stack_column );
     176           0 :     gtk_window_set_resizable( GTK_WINDOW((*this_).window), true );
     177             : 
     178           0 :     U8_TRACE_INFO("GTK+ Widgets are added to containers.");
     179             : 
     180             :     /* inject dependencies by signals */
     181             :     /* parameter info: g_signal_connect( instance-that-emits-the-signal, signal-name, callback-handler, data-to-be-passed-to-callback-handler) */
     182           0 :     g_signal_connect( G_OBJECT((*this_).window), "close-request", G_CALLBACK(gui_main_window_delete_event_callback), this_ );
     183           0 :     g_signal_connect( G_OBJECT((*this_).window), "destroy", G_CALLBACK(gui_main_window_destroy_event_callback), this_ );
     184           0 :     g_signal_connect( G_OBJECT((*this_).window), "state-flags-changed", G_CALLBACK( gui_main_window_state_callback ), this_ );
     185           0 :     g_signal_connect( G_OBJECT((*this_).window), DATA_CHANGE_NOTIFIER_GLIB_SIGNAL_NAME, G_CALLBACK(gui_main_window_data_changed_callback), this_ );
     186           0 :     g_signal_connect( G_OBJECT((*this_).sketcharea), DATA_CHANGE_NOTIFIER_GLIB_SIGNAL_NAME, G_CALLBACK(gui_sketch_area_data_changed_callback), &((*this_).sketcharea_data) );
     187           0 :     g_signal_connect( G_OBJECT((*this_).tool_row), GUI_TOOLBOX_GLIB_SIGNAL_NAME, G_CALLBACK(gui_sketch_area_tool_changed_callback), &((*this_).sketcharea_data) );
     188           0 :     g_signal_connect( gui_button_get_widget_ptr( &((*this_).file_new) ), "clicked", G_CALLBACK(gui_main_window_new_db_btn_callback), this_ );
     189           0 :     g_signal_connect( gui_button_get_widget_ptr( &((*this_).file_open) ), "clicked", G_CALLBACK(gui_main_window_open_db_btn_callback), this_ );
     190           0 :     g_signal_connect( gui_button_get_widget_ptr( &((*this_).file_save) ), "clicked", G_CALLBACK(gui_main_window_save_btn_callback), this_ );
     191           0 :     g_signal_connect( gui_button_get_widget_ptr( &((*this_).file_export) ), "clicked", G_CALLBACK(gui_main_window_export_btn_callback), this_ );
     192             : 
     193           0 :     g_signal_connect( gui_button_get_widget_ptr( &((*this_).view_new_window) ), "clicked", G_CALLBACK(gui_main_window_new_window_btn_callback), this_ );
     194             : 
     195           0 :     gui_toolbox_t *const tools = &((*this_).tools_data);
     196           0 :     g_signal_connect( gui_button_get_widget_ptr( &((*this_).view_navigate) ), "clicked", G_CALLBACK(gui_toolbox_navigate_btn_callback), tools );
     197           0 :     g_signal_connect( gui_button_get_widget_ptr( &((*this_).view_edit) ), "clicked", G_CALLBACK(gui_toolbox_edit_btn_callback), tools );
     198           0 :     g_signal_connect( gui_button_get_widget_ptr( &((*this_).view_create) ), "clicked", G_CALLBACK(gui_toolbox_create_btn_callback), tools );
     199           0 :     g_signal_connect( gui_button_get_widget_ptr( &((*this_).view_search) ), "clicked", G_CALLBACK(gui_toolbox_search_btn_callback), tools );
     200             : 
     201             :     /* The search id button is connected to two callback functions: one to switch to search mode, one to perform a search: */
     202           0 :     g_signal_connect( G_OBJECT((*this_).id_search_btn),
     203             :                       "clicked",
     204             :                       G_CALLBACK(gui_toolbox_search_id_btn_callback),
     205             :                       tools
     206             :                     );
     207           0 :     g_signal_connect( G_OBJECT((*this_).id_search_btn),
     208             :                       "clicked",
     209             :                       G_CALLBACK(gui_search_request_id_search_callback),
     210             :                       &((*this_).search_request)
     211             :                     );
     212             : 
     213           0 :     g_signal_connect( G_OBJECT((*this_).tool_row), GUI_TOOLBOX_GLIB_SIGNAL_NAME, G_CALLBACK(gui_search_request_tool_changed_callback), &((*this_).search_request) );
     214           0 :     g_signal_connect( G_OBJECT((*this_).search_entry), DATA_CHANGE_NOTIFIER_GLIB_SIGNAL_NAME, G_CALLBACK(gui_search_request_data_changed_callback), &((*this_).search_request) );
     215           0 :     g_signal_connect( G_OBJECT((*this_).search_entry), "activate", G_CALLBACK(gui_search_request_search_start_callback), &((*this_).search_request) );
     216           0 :     g_signal_connect( G_OBJECT((*this_).search_button), "clicked", G_CALLBACK(gui_search_request_search_start_callback), &((*this_).search_request) );
     217             : 
     218           0 :     g_signal_connect( gui_button_get_widget_ptr( &((*this_).edit_undo) ), "clicked", G_CALLBACK(gui_toolbox_undo_btn_callback), tools );
     219           0 :     g_signal_connect( gui_button_get_widget_ptr( &((*this_).edit_redo) ), "clicked", G_CALLBACK(gui_toolbox_redo_btn_callback), tools );
     220           0 :     g_signal_connect( gui_button_get_widget_ptr( &((*this_).edit_cut) ), "clicked", G_CALLBACK(gui_toolbox_cut_btn_callback), tools );
     221           0 :     g_signal_connect( gui_button_get_widget_ptr( &((*this_).edit_copy) ), "clicked", G_CALLBACK(gui_toolbox_copy_btn_callback), tools );
     222           0 :     g_signal_connect( gui_button_get_widget_ptr( &((*this_).edit_paste) ), "clicked", G_CALLBACK(gui_toolbox_paste_btn_callback), tools );
     223           0 :     g_signal_connect( gui_button_get_widget_ptr( &((*this_).edit_delete) ), "clicked", G_CALLBACK(gui_toolbox_delete_btn_callback), tools );
     224           0 :     g_signal_connect( gui_button_get_widget_ptr( &((*this_).edit_instantiate) ), "clicked", G_CALLBACK(gui_toolbox_instantiate_btn_callback), tools );
     225           0 :     g_signal_connect( gui_button_get_widget_ptr( &((*this_).edit_highlight) ), "clicked", G_CALLBACK(gui_toolbox_highlight_btn_callback), tools );
     226           0 :     g_signal_connect( gui_button_get_widget_ptr( &((*this_).edit_reset) ), "clicked", G_CALLBACK(gui_toolbox_reset_btn_callback), tools );
     227             : 
     228           0 :     g_signal_connect( G_OBJECT((*this_).name_entry),
     229             :                       "activate",
     230             :                       G_CALLBACK(gui_attributes_editor_name_enter_callback),
     231             :                       &((*this_).attributes_editor)
     232             :                     );
     233             :     {
     234           0 :         GtkEventControllerFocus *evt_focus_n = GTK_EVENT_CONTROLLER_FOCUS(gtk_event_controller_focus_new());
     235           0 :         g_signal_connect( evt_focus_n,
     236             :                           "leave",
     237             :                           G_CALLBACK(gui_attributes_editor_name_focus_left_callback),
     238             :                           &((*this_).attributes_editor)
     239             :                         );
     240           0 :         gtk_widget_add_controller( (*this_).name_entry, GTK_EVENT_CONTROLLER(evt_focus_n) );
     241             :     }
     242             :     {
     243           0 :         GtkEventControllerFocus *evt_focus_s = GTK_EVENT_CONTROLLER_FOCUS(gtk_event_controller_focus_new());
     244           0 :         g_signal_connect( evt_focus_s,
     245             :                           "leave",
     246             :                           G_CALLBACK(gui_attributes_editor_stereotype_focus_left_callback),
     247             :                           &((*this_).attributes_editor)
     248             :                         );
     249           0 :         gtk_widget_add_controller( (*this_).stereotype_entry, GTK_EVENT_CONTROLLER(evt_focus_s) );
     250             :     }
     251             :     {
     252           0 :         GtkEventControllerFocus *evt_focus_d = GTK_EVENT_CONTROLLER_FOCUS(gtk_event_controller_focus_new());
     253           0 :         g_signal_connect( evt_focus_d,
     254             :                           "leave",
     255             :                           G_CALLBACK(gui_attributes_editor_description_focus_left_callback),
     256             :                           &((*this_).attributes_editor)
     257             :                         );
     258           0 :         gtk_widget_add_controller( (*this_).description_text_view, GTK_EVENT_CONTROLLER(evt_focus_d) );
     259             :     }
     260           0 :     g_signal_connect( G_OBJECT((*this_).stereotype_entry), "activate", G_CALLBACK(gui_attributes_editor_stereotype_enter_callback), &((*this_).attributes_editor) );
     261           0 :     g_signal_connect_after( G_OBJECT((*this_).type_dropdown), "notify::selected", G_CALLBACK(gui_attributes_editor_type_changed_callback), &((*this_).attributes_editor));
     262           0 :     for( int_fast32_t diag_idx = 0; diag_idx < GUI_TYPE_RESOURCE_LIST_DIAGRAMS; diag_idx ++ )
     263             :     {
     264           0 :         g_signal_connect( G_OBJECT((*this_).type_diag_btn[ diag_idx ]),
     265             :                           "clicked",
     266             :                           G_CALLBACK( gui_attributes_editor_type_of_diagram_btn_callback ),
     267             :                           &((*this_).type_diag_data[diag_idx])
     268             :                         );
     269             :     }
     270           0 :     for( int_fast32_t clas_idx = 0; clas_idx < GUI_TYPE_RESOURCE_LIST_CLASSIFIERS; clas_idx ++ )
     271             :     {
     272           0 :         g_signal_connect( G_OBJECT((*this_).type_clas_btn[ clas_idx ]),
     273             :                           "clicked",
     274             :                           G_CALLBACK( gui_attributes_editor_type_of_classifier_btn_callback ),
     275             :                           &((*this_).type_clas_data[clas_idx])
     276             :                         );
     277             :     }
     278           0 :     for( int_fast32_t feat_idx = 0; feat_idx < GUI_TYPE_RESOURCE_LIST_INV_FEATURES; feat_idx ++ )
     279             :     {
     280           0 :         g_signal_connect( G_OBJECT((*this_).type_feat_btn[ feat_idx ]),
     281             :                           "clicked",
     282             :                           G_CALLBACK( gui_attributes_editor_type_of_feature_btn_callback ),
     283             :                           &((*this_).type_feat_data[feat_idx])
     284             :                         );
     285             :     }
     286           0 :     for( int_fast32_t rel_idx = 0; rel_idx < GUI_TYPE_RESOURCE_LIST_RELATIONS; rel_idx ++ )
     287             :     {
     288           0 :         g_signal_connect( G_OBJECT((*this_).type_rel_btn[ rel_idx ]),
     289             :                           "clicked",
     290             :                           G_CALLBACK( gui_attributes_editor_type_of_relationship_btn_callback ),
     291             :                           &((*this_).type_rel_data[rel_idx])
     292             :                         );
     293             :     }
     294           0 :     g_signal_connect( G_OBJECT((*this_).window), GUI_MARKED_SET_GLIB_SIGNAL_NAME, G_CALLBACK(gui_attributes_editor_focused_object_changed_callback), &((*this_).attributes_editor) );
     295           0 :     g_signal_connect( G_OBJECT((*this_).name_entry), DATA_CHANGE_NOTIFIER_GLIB_SIGNAL_NAME, G_CALLBACK(gui_attributes_editor_data_changed_callback), &((*this_).attributes_editor) );
     296             :         /* ^-- name_entry is the  proxy for all widgets of attributes_editor */
     297             : 
     298           0 :     g_signal_connect( gui_button_get_widget_ptr( &((*this_).help_about) ), "clicked", G_CALLBACK(gui_main_window_about_btn_callback), this_ );
     299             : 
     300           0 :     U8_TRACE_INFO("GTK+ Callbacks are connected to widget events.");
     301             : 
     302             :     /* register observers */
     303             : 
     304           0 :     (*this_).data_notifier = data_database_get_notifier_ptr( io_data_file_get_database_ptr( data_file ) );
     305           0 :     data_change_notifier_add_listener( (*this_).data_notifier, G_OBJECT((*this_).window) );
     306           0 :     data_change_notifier_add_listener( (*this_).data_notifier, G_OBJECT((*this_).sketcharea) );
     307           0 :     data_change_notifier_add_listener( (*this_).data_notifier, G_OBJECT((*this_).name_entry) );
     308             :         /* ^-- name_entry is the  proxy for all widgets of attributes_editor */
     309           0 :     data_change_notifier_add_listener( (*this_).data_notifier, G_OBJECT((*this_).search_entry) );
     310             : 
     311           0 :     U8_TRACE_INFO("GTK+ Widgets are registered as listeners at signal emitter.");
     312             : 
     313           0 :     gtk_widget_set_visible( (*this_).window, TRUE );
     314           0 :     gtk_widget_set_sensitive( GTK_WIDGET((*this_).window), TRUE );  /* idea taken from gtk demo */
     315             : 
     316           0 :     GdkSurface *surface = gtk_native_get_surface( GTK_NATIVE((*this_).window) );
     317           0 :     gdk_surface_set_cursor( surface, NULL );  /* idea taken from gtk3->4 guide */
     318             : 
     319           0 :     gui_attributes_editor_update_widgets( &((*this_).attributes_editor) );  /* hide some widgets again */
     320             : #ifdef NDEBUG
     321             :     gui_simple_message_to_user_hide( &((*this_).message_to_user) );
     322             : #else
     323           0 :     gui_simple_message_to_user_show_message ( &((*this_).message_to_user), GUI_SIMPLE_MESSAGE_TYPE_INFO, GUI_SIMPLE_MESSAGE_CONTENT_DEBUG_MODE );
     324             : #endif
     325           0 :     gui_search_request_hide( &((*this_).search_request) );
     326           0 :     U8_TRACE_INFO("GTK+ Widgets are shown.");
     327           0 :     U8_TRACE_END();
     328           0 : }
     329             : 
     330           0 : void gui_main_window_destroy( gui_main_window_t *this_ )
     331             : {
     332           0 :     U8_TRACE_BEGIN();
     333             : 
     334             :     /* Note: The widgets may be destroyed already. A cast by G_OBJECT is therefore illegal. */
     335           0 :     data_change_notifier_remove_listener( (*this_).data_notifier, (GObject*)(*this_).window );
     336           0 :     data_change_notifier_remove_listener( (*this_).data_notifier, (GObject*)(*this_).name_entry );
     337           0 :     data_change_notifier_remove_listener( (*this_).data_notifier, (GObject*)(*this_).sketcharea );
     338           0 :     data_change_notifier_remove_listener( (*this_).data_notifier, (GObject*)(*this_).search_entry );
     339             : 
     340           0 :     U8_TRACE_INFO("GTK+ Widgets are unregistered as listeners from data module.");
     341           0 :     gui_file_export_dialog_destroy ( &((*this_).file_export_dialog) );
     342           0 :     gui_file_use_db_dialog_destroy ( &((*this_).file_use_db_dialog) );
     343           0 :     U8_TRACE_INFO("GTK+ hidden windows are destroyed.");
     344           0 :     gui_file_action_destroy( &((*this_).file_action) );
     345             : 
     346           0 :     gui_search_request_destroy( &((*this_).search_request) );
     347           0 :     gui_search_runner_destroy( &((*this_).search_runner) );
     348           0 :     gui_sketch_area_destroy( &((*this_).sketcharea_data) );
     349           0 :     gui_toolbox_destroy( &((*this_).tools_data) );
     350           0 :     gui_marked_set_destroy( &((*this_).marker_data) );
     351           0 :     gui_attributes_editor_destroy( &((*this_).attributes_editor) );
     352           0 :     gui_simple_message_to_user_destroy( &((*this_).message_to_user) );
     353           0 :     (*this_).data_file = NULL;
     354           0 :     (*this_).resources = NULL;
     355             : 
     356           0 :     gui_button_destroy( &((*this_).file_new) );
     357           0 :     gui_button_destroy( &((*this_).file_open) );
     358           0 :     gui_button_destroy( &((*this_).file_save) );
     359           0 :     gui_button_destroy( &((*this_).file_export) );
     360           0 :     gui_button_destroy( &((*this_).view_new_window) );
     361           0 :     gui_button_destroy( &((*this_).view_navigate) );
     362           0 :     gui_button_destroy( &((*this_).view_edit) );
     363           0 :     gui_button_destroy( &((*this_).view_create) );
     364           0 :     gui_button_destroy( &((*this_).view_search) );
     365           0 :     gui_button_destroy( &((*this_).edit_undo) );
     366           0 :     gui_button_destroy( &((*this_).edit_redo) );
     367           0 :     gui_button_destroy( &((*this_).edit_cut) );
     368           0 :     gui_button_destroy( &((*this_).edit_copy) );
     369           0 :     gui_button_destroy( &((*this_).edit_paste) );
     370           0 :     gui_button_destroy( &((*this_).edit_delete) );
     371           0 :     gui_button_destroy( &((*this_).edit_instantiate) );
     372           0 :     gui_button_destroy( &((*this_).edit_highlight) );
     373           0 :     gui_button_destroy( &((*this_).edit_reset) );
     374           0 :     gui_button_destroy( &((*this_).help_about) );
     375             : 
     376           0 :     U8_TRACE_END();
     377           0 : }
     378             : 
     379           0 : static inline void gtk_button_set_image( GtkButton *btn, GtkWidget *icon )
     380             : {
     381           0 :     gtk_button_set_child( btn, icon );
     382           0 : }
     383             : 
     384           0 : void gui_main_window_private_init_toolbox( gui_main_window_t *this_ )
     385             : {
     386           0 :     U8_TRACE_BEGIN();
     387           0 :     const gui_resources_t *const res = (*this_).resources;
     388             : 
     389           0 :     gui_button_init( &((*this_).file_new),
     390           0 :                      GDK_PAINTABLE( gui_resources_get_file_new( res ) ),
     391             :                      "new",
     392             :                      "New"
     393             :                     );
     394             : 
     395           0 :     gui_button_init( &((*this_).file_open),
     396           0 :                      GDK_PAINTABLE( gui_resources_get_file_open( res ) ),
     397             :                      "open",
     398             :                      "Open"
     399             :                     );
     400             : 
     401             :     /* save icon depends if latest changes are already saved */
     402           0 :     const bool is_saved = io_data_file_is_in_sync( (*this_).data_file );
     403           0 :     gui_button_init( &((*this_).file_save),
     404             :                      is_saved
     405           0 :                      ? GDK_PAINTABLE( gui_resources_get_file_saved( res ) )
     406           0 :                      : GDK_PAINTABLE( gui_resources_get_file_save( res ) ),
     407             :                      "save",
     408             :                      "Save (Ctrl-S)"
     409             :                     );
     410           0 :     GtkShortcutTrigger *commit_trig = gtk_shortcut_trigger_parse_string( "<Control>S" );
     411           0 :     GtkShortcutAction *commit_act = gtk_callback_action_new( &gui_main_window_save_shortcut_callback,
     412             :                                                              this_,
     413             :                                                              NULL
     414             :                                                            );
     415           0 :     GtkShortcut* ctrl_s = gtk_shortcut_new_with_arguments( commit_trig,
     416             :                                                            commit_act,
     417             :                                                            NULL /* = format_string */
     418             :                                                          );
     419           0 :     gtk_shortcut_controller_add_shortcut( (*this_).keyboard_shortcut_ctrl, ctrl_s );
     420             : 
     421           0 :     gui_button_init( &((*this_).file_export),
     422           0 :                      GDK_PAINTABLE( gui_resources_get_file_export( res ) ),
     423             :                      "export",
     424             :                      "Export"
     425             :                     );
     426             : 
     427           0 :     (*this_).tool_sect_1_icon = gtk_image_new_from_paintable( GDK_PAINTABLE ( gui_resources_get_tool_sect( res ) ) );
     428           0 :     gtk_widget_set_size_request( GTK_WIDGET((*this_).tool_sect_1_icon), 12 /*=w*/ , 32 /*=h*/ );
     429           0 :     gtk_image_set_pixel_size( GTK_IMAGE((*this_).tool_sect_1_icon), 32 );
     430           0 :     gtk_widget_set_halign( (*this_).tool_sect_1_icon, GTK_ALIGN_START );
     431             : 
     432           0 :     gui_button_init( &((*this_).view_new_window),
     433           0 :                      GDK_PAINTABLE( gui_resources_get_view_new_window( res ) ),
     434             :                      "win",
     435             :                      "New Window"
     436             :                     );
     437             : 
     438           0 :     gui_button_init_toggle( &((*this_).view_navigate),
     439           0 :                             GDK_PAINTABLE( gui_resources_get_view_navigate( res ) ),
     440             :                             "nav",
     441             :                             "Navigate"
     442             :                            );
     443             : 
     444           0 :     gui_button_init_toggle( &((*this_).view_edit),
     445           0 :                             GDK_PAINTABLE( gui_resources_get_view_edit( res ) ),
     446             :                             "edit",
     447             :                             "Edit"
     448             :                            );
     449           0 :     gtk_toggle_button_set_group( GTK_TOGGLE_BUTTON( gui_button_get_widget_ptr( &((*this_).view_edit) ) ),
     450           0 :                                  GTK_TOGGLE_BUTTON( gui_button_get_widget_ptr( &((*this_).view_navigate) ) )
     451             :                                );
     452             : 
     453           0 :     gui_button_init_toggle( &((*this_).view_create),
     454           0 :                             GDK_PAINTABLE( gui_resources_get_view_create( res ) ),
     455             :                             "create",
     456             :                             "Create"
     457             :                            );
     458           0 :     gtk_toggle_button_set_group( GTK_TOGGLE_BUTTON( gui_button_get_widget_ptr( &((*this_).view_create) ) ),
     459           0 :                                  GTK_TOGGLE_BUTTON( gui_button_get_widget_ptr( &((*this_).view_edit) ) )
     460             :                                );
     461             : 
     462           0 :     gui_button_init_toggle( &((*this_).view_search),
     463           0 :                             GDK_PAINTABLE( gui_resources_get_view_search( res ) ),
     464             :                             "search",
     465             :                             "Search"
     466             :                            );
     467           0 :     gtk_toggle_button_set_group( GTK_TOGGLE_BUTTON( gui_button_get_widget_ptr( &((*this_).view_search) ) ),
     468           0 :                                  GTK_TOGGLE_BUTTON( gui_button_get_widget_ptr( &((*this_).view_create) ) )
     469             :                                );
     470             : 
     471           0 :     (*this_).tool_sect_2_icon = gtk_image_new_from_paintable( GDK_PAINTABLE ( gui_resources_get_tool_sect( res ) ) );
     472           0 :     gtk_widget_set_size_request( GTK_WIDGET((*this_).tool_sect_2_icon), 12 /*=w*/ , 32 /*=h*/ );
     473           0 :     gtk_image_set_pixel_size( GTK_IMAGE((*this_).tool_sect_2_icon), 32 );
     474           0 :     gtk_widget_set_halign( (*this_).tool_sect_2_icon, GTK_ALIGN_START );
     475             : 
     476           0 :     gui_button_init( &((*this_).edit_undo),
     477           0 :                      GDK_PAINTABLE( gui_resources_get_edit_undo( res ) ),
     478             :                      "undo",
     479             :                      "Undo (Ctrl-Z)"
     480             :                     );
     481           0 :     GtkShortcutTrigger *undo_trig = gtk_shortcut_trigger_parse_string( "<Control>Z" );
     482           0 :     GtkShortcutAction *undo_act = gtk_callback_action_new( &gui_toolbox_undo_shortcut_callback,
     483           0 :                                                            &((*this_).tools_data),
     484             :                                                            NULL
     485             :                                                          );
     486           0 :     GtkShortcut* ctrl_z = gtk_shortcut_new_with_arguments( undo_trig,
     487             :                                                            undo_act,
     488             :                                                            NULL /* = format_string */
     489             :                                                          );
     490           0 :     gtk_shortcut_controller_add_shortcut( (*this_).keyboard_shortcut_ctrl, ctrl_z );
     491             : 
     492           0 :     gui_button_init( &((*this_).edit_redo),
     493           0 :                      GDK_PAINTABLE( gui_resources_get_edit_redo( res ) ),
     494             :                      "redo",
     495             :                      "Redo (Ctrl-Y)"
     496             :                    );
     497           0 :     GtkShortcutTrigger *redo_trig = gtk_shortcut_trigger_parse_string( "<Control>Y" );
     498           0 :     GtkShortcutAction *redo_act = gtk_callback_action_new( &gui_toolbox_redo_shortcut_callback,
     499           0 :                                                            &((*this_).tools_data),
     500             :                                                            NULL
     501             :                                                          );
     502           0 :     GtkShortcut* ctrl_y = gtk_shortcut_new_with_arguments( redo_trig,
     503             :                                                            redo_act,
     504             :                                                            NULL /* = format_string */
     505             :                                                          );
     506           0 :     gtk_shortcut_controller_add_shortcut( (*this_).keyboard_shortcut_ctrl, ctrl_y );
     507             : 
     508           0 :     gui_button_init( &((*this_).edit_cut),
     509           0 :                      GDK_PAINTABLE( gui_resources_get_edit_cut( res ) ),
     510             :                      "cut",
     511             :                      "Cut (Ctrl-X)"
     512             :                    );
     513             :     /*
     514             :     GDK_KEY_x + GDK_CONTROL_MASK handling see gui_sketch_area_key_press_callback();
     515             :     moved there to not interfere with text input fields
     516             :     */
     517             : 
     518           0 :     gui_button_init( &((*this_).edit_copy),
     519           0 :                      GDK_PAINTABLE( gui_resources_get_edit_copy( res ) ),
     520             :                      "copy",
     521             :                      "Copy (Ctrl-C)"
     522             :                    );
     523             :     /*
     524             :     GDK_KEY_c + GDK_CONTROL_MASK handling see gui_sketch_area_key_press_callback();
     525             :     moved there to not interfere with text input fields
     526             :     */
     527             : 
     528           0 :     gui_button_init( &((*this_).edit_paste),
     529           0 :                      GDK_PAINTABLE( gui_resources_get_edit_paste( res ) ),
     530             :                      "paste",
     531             :                      "Paste (Ctrl-V)"
     532             :                    );
     533             :     /*
     534             :     GK_KEY_v + GDK_CONTROL_MASK handling see gui_sketch_area_key_press_callback();
     535             :     moved there to not interfere with text input fields
     536             :     */
     537             : 
     538           0 :     gui_button_init( &((*this_).edit_delete),
     539           0 :                      GDK_PAINTABLE( gui_resources_get_edit_delete( res ) ),
     540             :                      "del",
     541             :                      "Delete (DEL)"
     542             :                    );
     543             :     /*
     544             :     GDK_KEY_Delete handling see gui_sketch_area_key_press_callback();
     545             :     moved there to not interfere with text input fields
     546             :     */
     547             : 
     548           0 :     gui_button_init( &((*this_).edit_instantiate),
     549           0 :                      GDK_PAINTABLE( gui_resources_get_edit_instantiate( res ) ),
     550             :                      "inst",
     551             :                      "Instantiate"
     552             :                    );
     553             : 
     554           0 :     gui_button_init( &((*this_).edit_highlight),
     555           0 :                      GDK_PAINTABLE( gui_resources_get_edit_highlight( res ) ),
     556             :                      "mark",
     557             :                      "Highlight"
     558             :                    );
     559             : 
     560           0 :     gui_button_init( &((*this_).edit_reset),
     561           0 :                      GDK_PAINTABLE( gui_resources_get_edit_reset( res ) ),
     562             :                      "zero",
     563             :                      "Reset Selection"
     564             :                    );
     565             : 
     566           0 :     gui_button_init( &((*this_).help_about),
     567           0 :                      GDK_PAINTABLE( gui_resources_get_crystal_facet_uml( res ) ),
     568             :                      "info",
     569             :                      "About"
     570             :                    );
     571             : 
     572             :     /* insert widgets to box container */
     573             :     {
     574           0 :         (*this_).tool_row = gtk_box_new( GTK_ORIENTATION_HORIZONTAL, /*spacing:*/ 4 );
     575           0 :         gtk_box_append( GTK_BOX((*this_).tool_row), gui_button_get_widget_ptr( &((*this_).file_new) ) );
     576           0 :         gtk_box_append( GTK_BOX((*this_).tool_row), gui_button_get_widget_ptr( &((*this_).file_open) ) );
     577           0 :         gtk_box_append( GTK_BOX((*this_).tool_row), gui_button_get_widget_ptr( &((*this_).file_save) ) );
     578           0 :         gtk_box_append( GTK_BOX((*this_).tool_row), gui_button_get_widget_ptr( &((*this_).file_export) ) );
     579           0 :         gtk_box_append( GTK_BOX((*this_).tool_row), GTK_WIDGET((*this_).tool_sect_1_icon) );
     580           0 :         gtk_box_append( GTK_BOX((*this_).tool_row), gui_button_get_widget_ptr( &((*this_).view_new_window) ) );
     581           0 :         gtk_box_append( GTK_BOX((*this_).tool_row), gui_button_get_widget_ptr( &((*this_).view_search) ) );
     582           0 :         gtk_box_append( GTK_BOX((*this_).tool_row), gui_button_get_widget_ptr( &((*this_).view_navigate) ) );
     583           0 :         gtk_box_append( GTK_BOX((*this_).tool_row), gui_button_get_widget_ptr( &((*this_).view_edit) ) );
     584           0 :         gtk_box_append( GTK_BOX((*this_).tool_row), gui_button_get_widget_ptr( &((*this_).view_create) ) );
     585           0 :         gtk_box_append( GTK_BOX((*this_).tool_row), GTK_WIDGET((*this_).tool_sect_2_icon) );
     586           0 :         gtk_box_append( GTK_BOX((*this_).tool_row), gui_button_get_widget_ptr( &((*this_).edit_undo) ) );
     587           0 :         gtk_box_append( GTK_BOX((*this_).tool_row), gui_button_get_widget_ptr( &((*this_).edit_redo) ) );
     588           0 :         gtk_box_append( GTK_BOX((*this_).tool_row), gui_button_get_widget_ptr( &((*this_).edit_cut) ) );
     589           0 :         gtk_box_append( GTK_BOX((*this_).tool_row), gui_button_get_widget_ptr( &((*this_).edit_copy) ) );
     590           0 :         gtk_box_append( GTK_BOX((*this_).tool_row), gui_button_get_widget_ptr( &((*this_).edit_paste) ) );
     591           0 :         gtk_box_append( GTK_BOX((*this_).tool_row), gui_button_get_widget_ptr( &((*this_).edit_delete) ) );
     592           0 :         gtk_box_append( GTK_BOX((*this_).tool_row), gui_button_get_widget_ptr( &((*this_).edit_instantiate) ) );
     593           0 :         gtk_box_append( GTK_BOX((*this_).tool_row), gui_button_get_widget_ptr( &((*this_).edit_highlight) ) );
     594           0 :         gtk_box_append( GTK_BOX((*this_).tool_row), gui_button_get_widget_ptr( &((*this_).edit_reset) ) );
     595           0 :         gtk_box_append( GTK_BOX((*this_).tool_row), gui_button_get_widget_ptr( &((*this_).help_about) ) );
     596             :     }
     597             : 
     598           0 :     U8_TRACE_END();
     599           0 : }
     600             : 
     601           0 : void gui_main_window_private_init_attributes_editor( gui_main_window_t *this_ )
     602             : {
     603           0 :     U8_TRACE_BEGIN();
     604           0 :     const gui_resources_t *const res = (*this_).resources;
     605             : 
     606           0 :     (*this_).attr_section_icon = gtk_image_new_from_paintable( GDK_PAINTABLE ( gui_resources_get_edit_attributes_sect( res ) ) );
     607           0 :     gtk_widget_set_size_request( GTK_WIDGET((*this_).attr_section_icon), 48 /*=w*/ , 12 /*=h*/ );
     608           0 :     gtk_image_set_pixel_size( GTK_IMAGE((*this_).attr_section_icon), 48 );
     609           0 :     gtk_widget_set_halign( (*this_).attr_section_icon, GTK_ALIGN_START );
     610             : 
     611           0 :     (*this_).id_label = gtk_label_new( "" );
     612           0 :     gtk_label_set_selectable( GTK_LABEL( (*this_).id_label ), true );
     613           0 :     (*this_).name_label = gtk_label_new( "Name:" );
     614           0 :     (*this_).description_label = gtk_label_new( "Description:" );
     615           0 :     (*this_).stereotype_label = gtk_label_new( "Stereotype:" );
     616           0 :     (*this_).type_label = gtk_label_new( "Type:" );
     617           0 :     gtk_label_set_xalign( GTK_LABEL( (*this_).id_label ), 1.0 ); /* align right */
     618           0 :     gtk_label_set_xalign( GTK_LABEL( (*this_).name_label ), 0.0 );
     619           0 :     gtk_label_set_xalign( GTK_LABEL( (*this_).description_label ), 0.0 );
     620           0 :     gtk_label_set_xalign( GTK_LABEL( (*this_).stereotype_label ), 0.0 );
     621           0 :     gtk_label_set_xalign( GTK_LABEL( (*this_).type_label ), 0.0 );
     622             : 
     623           0 :     (*this_).id_search_btn = gtk_button_new();
     624           0 :     (*this_).id_search_btn_icon = gtk_image_new_from_paintable( GDK_PAINTABLE( gui_resources_get_search_search( res ) ) );
     625           0 :     gtk_button_set_image( GTK_BUTTON((*this_).id_search_btn), (*this_).id_search_btn_icon );
     626           0 :     gtk_widget_set_tooltip_text( GTK_WIDGET((*this_).id_search_btn), "Find Occurrences" );
     627           0 :     gtk_widget_set_size_request( GTK_WIDGET((*this_).id_search_btn_icon), 32 /*=w*/ , 32 /*=h*/ );
     628             : 
     629             :     /* insert widgets to box container */
     630             :     {
     631           0 :         (*this_).id_row = gtk_box_new( GTK_ORIENTATION_HORIZONTAL, /*spacing:*/ 8 );
     632           0 :         gtk_box_append( GTK_BOX((*this_).id_row), GTK_WIDGET((*this_).attr_section_icon) );
     633           0 :         gtk_box_append( GTK_BOX((*this_).id_row), GTK_WIDGET((*this_).id_label) );
     634           0 :         gtk_box_append( GTK_BOX((*this_).id_row), GTK_WIDGET((*this_).id_search_btn) );
     635             : 
     636           0 :         gtk_widget_set_vexpand ( GTK_WIDGET( (*this_).attr_section_icon ), false );
     637           0 :         gtk_widget_set_hexpand ( GTK_WIDGET( (*this_).attr_section_icon ), false );
     638           0 :         gtk_widget_set_vexpand ( GTK_WIDGET( (*this_).id_label ), false );
     639           0 :         gtk_widget_set_hexpand ( GTK_WIDGET( (*this_).id_label ), true );
     640           0 :         gtk_widget_set_vexpand ( GTK_WIDGET( (*this_).id_search_btn ), false );
     641           0 :         gtk_widget_set_hexpand ( GTK_WIDGET( (*this_).id_search_btn ), false );
     642             :     }
     643             : 
     644           0 :     (*this_).name_entry = gtk_entry_new();
     645             : 
     646           0 :     (*this_).stereotype_entry = gtk_entry_new();
     647             : 
     648           0 :     (*this_).description_text_view = gtk_text_view_new();
     649           0 :     gtk_text_view_set_wrap_mode( GTK_TEXT_VIEW( (*this_).description_text_view ),
     650             :                                  GTK_WRAP_WORD_CHAR
     651             :                                );
     652           0 :     gtk_widget_set_vexpand( GTK_WIDGET( (*this_).description_text_view ), true );
     653           0 :     gtk_widget_set_hexpand( GTK_WIDGET( (*this_).description_text_view ), false );
     654             :     //gtk_widget_set_size_request( GTK_WIDGET((*this_).description_text_view), 128 /*=w*/ , 48 /*=h*/ );
     655             :     /* need own scroll window container */
     656           0 :     gtk_text_view_set_bottom_margin( GTK_TEXT_VIEW( (*this_).description_text_view ), 12 );
     657           0 :     gtk_text_view_set_left_margin( GTK_TEXT_VIEW( (*this_).description_text_view ), 12 );
     658           0 :     gtk_text_view_set_right_margin( GTK_TEXT_VIEW( (*this_).description_text_view ), 12 );
     659           0 :     gtk_text_view_set_top_margin( GTK_TEXT_VIEW( (*this_).description_text_view ), 12 );
     660           0 :     (*this_).description_scroll_win = gtk_scrolled_window_new();
     661           0 :     gtk_scrolled_window_set_child( GTK_SCROLLED_WINDOW((*this_).description_scroll_win), (*this_).description_text_view );
     662           0 :     gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( (*this_).description_scroll_win ),
     663             :                                     GTK_POLICY_AUTOMATIC,
     664             :                                     GTK_POLICY_AUTOMATIC
     665             :                                   );
     666             : 
     667           0 :     GListStore *model = NULL;  /* the model is set later */
     668           0 :     GtkExpression *expression = NULL;  /* not needed: there is no search entry that could find list elements */
     669           0 :     (*this_).type_dropdown = GTK_DROP_DOWN( gtk_drop_down_new ( G_LIST_MODEL( model ), expression ) );
     670           0 :     GtkBuilderScope *scope = gtk_builder_cscope_new();
     671             :     static const char bytes[] =
     672             :     "<interface>\n"
     673             :     "<template class=\"GtkListItem\">\n"
     674             :     "  <property name=\"child\">\n"
     675             :     "    <object class=\"GtkPaned\">\n"
     676             :     "      <property name=\"start-child\">\n"
     677             :     "        <object class=\"GtkImage\">\n"
     678             :     "          <property name=\"width-request\">32</property>\n"
     679             :     "          <property name=\"height-request\">24</property>\n"
     680             :     "          <binding name=\"paintable\">\n"
     681             :     "            <lookup name=\"icon\" type=\"GuiTypeResource\">\n"
     682             :     "              <lookup name=\"item\">GtkListItem</lookup>\n"
     683             :     "            </lookup>\n"
     684             :     "          </binding>\n"
     685             :     "        </object>\n"
     686             :     "      </property>\n"
     687             :     "      <property name=\"end-child\">\n"
     688             :     "        <object class=\"GtkLabel\">\n"
     689             :     "          <property name=\"xalign\">0</property>\n"
     690             :     "          <binding name=\"label\">\n"
     691             :     "            <lookup name=\"name\" type=\"GuiTypeResource\">\n"
     692             :     "              <lookup name=\"item\">GtkListItem</lookup>\n"
     693             :     "            </lookup>\n"
     694             :     "          </binding>\n"
     695             :     "        </object>\n"
     696             :     "      </property>\n"
     697             :     "      <property name=\"position\">48</property>\n"
     698             :     "    </object>\n"
     699             :     "  </property>\n"
     700             :     "</template>\n"
     701             :     "</interface>\n";
     702           0 :     GBytes *byteptr = g_bytes_new( &bytes, sizeof(bytes)-sizeof(char) );
     703           0 :     GtkListItemFactory *factory = gtk_builder_list_item_factory_new_from_bytes( scope, byteptr );
     704           0 :     gtk_drop_down_set_factory( (*this_).type_dropdown, factory );
     705           0 :     g_object_unref( scope );
     706           0 :     g_object_unref( factory );
     707           0 :     g_bytes_unref( byteptr );
     708             : 
     709             :     static gui_type_resource_list_t res_select;
     710           0 :     gui_type_resource_list_init( &res_select, res );
     711             :     {
     712           0 :         (*this_).type_diag_grid = GTK_GRID( gtk_grid_new() );
     713           0 :         gtk_widget_set_halign( GTK_WIDGET( (*this_).type_diag_grid ), GTK_ALIGN_END );
     714             :         const gui_type_resource_t (*diag_data)[];
     715             :         unsigned int diag_data_length;
     716           0 :         gui_type_resource_list_get_all_diagram_types( &res_select, &diag_data, &diag_data_length );
     717           0 :         assert( diag_data_length == GUI_TYPE_RESOURCE_LIST_DIAGRAMS );
     718           0 :         for( int_fast32_t diag_idx = 0; diag_idx < GUI_TYPE_RESOURCE_LIST_DIAGRAMS; diag_idx ++ )
     719             :         {
     720           0 :             const gui_type_resource_t *const type_data = &((*diag_data)[diag_idx]);
     721           0 :             const data_diagram_type_t diag_type = data_type_get_diagram_type( gui_type_resource_get_type_id( type_data ) );
     722           0 :             GdkTexture *const diag_icon = gui_type_resource_get_icon( type_data );
     723           0 :             const char *const diag_name = gui_type_resource_get_name( type_data );
     724             : 
     725           0 :             gui_attribute_type_of_diagram_init( &((*this_).type_diag_data[diag_idx]), diag_type, &((*this_).attributes_editor) );
     726           0 :             (*this_).type_diag_img[ diag_idx ] = GTK_IMAGE( gtk_image_new_from_paintable( GDK_PAINTABLE( diag_icon ) ) );
     727           0 :             gtk_widget_set_size_request( GTK_WIDGET( (*this_).type_diag_img[ diag_idx ] ), 32 /*=w*/ , 24 /*=h*/ );
     728           0 :             (*this_).type_diag_btn[ diag_idx ] = GTK_BUTTON( gtk_button_new() );
     729           0 :             gtk_button_set_image( (*this_).type_diag_btn[ diag_idx ], GTK_WIDGET( (*this_).type_diag_img[ diag_idx ] ) );
     730           0 :             gtk_widget_set_tooltip_text( GTK_WIDGET( (*this_).type_diag_btn[ diag_idx ] ), diag_name );
     731           0 :             gtk_grid_attach( (*this_).type_diag_grid, GTK_WIDGET( (*this_).type_diag_btn[ diag_idx ] ), diag_idx%7, diag_idx/7, 1, 1 );
     732             :         }
     733             : 
     734           0 :         (*this_).type_clas_grid = GTK_GRID( gtk_grid_new() );
     735           0 :         gtk_widget_set_halign( GTK_WIDGET( (*this_).type_clas_grid ), GTK_ALIGN_END );
     736             :         const gui_type_resource_t (*clas_data)[];
     737             :         unsigned int clas_data_length;
     738           0 :         gui_type_resource_list_get_all_classifier_types( &res_select, &clas_data, &clas_data_length );
     739           0 :         assert( clas_data_length == GUI_TYPE_RESOURCE_LIST_CLASSIFIERS );
     740           0 :         for( int_fast32_t clas_idx = 0; clas_idx < GUI_TYPE_RESOURCE_LIST_CLASSIFIERS; clas_idx ++ )
     741             :         {
     742           0 :             const gui_type_resource_t *const type_data = &((*clas_data)[clas_idx]);
     743           0 :             const data_classifier_type_t clas_type = data_type_get_classifier_type( gui_type_resource_get_type_id( type_data ) );
     744           0 :             GdkTexture *const clas_icon = gui_type_resource_get_icon( type_data );
     745           0 :             const char *const clas_name = gui_type_resource_get_name( type_data );
     746             : 
     747           0 :             gui_attribute_type_of_classifier_init( &((*this_).type_clas_data[clas_idx]), clas_type, &((*this_).attributes_editor) );
     748           0 :             (*this_).type_clas_img[ clas_idx ] = GTK_IMAGE( gtk_image_new_from_paintable( GDK_PAINTABLE( clas_icon ) ) );
     749           0 :             gtk_widget_set_size_request( GTK_WIDGET( (*this_).type_clas_img[ clas_idx ] ), 32 /*=w*/ , 24 /*=h*/ );
     750           0 :             (*this_).type_clas_btn[ clas_idx ] = GTK_BUTTON( gtk_button_new() );
     751           0 :             gtk_button_set_image( (*this_).type_clas_btn[ clas_idx ], GTK_WIDGET( (*this_).type_clas_img[ clas_idx ] ) );
     752           0 :             gtk_widget_set_tooltip_text( GTK_WIDGET( (*this_).type_clas_btn[ clas_idx ] ), clas_name );
     753           0 :             gtk_grid_attach( (*this_).type_clas_grid, GTK_WIDGET( (*this_).type_clas_btn[ clas_idx ] ), clas_idx%7, clas_idx/7, 1, 1 );
     754             :         }
     755             : 
     756           0 :         (*this_).type_feat_grid = GTK_GRID( gtk_grid_new() );
     757           0 :         gtk_widget_set_halign( GTK_WIDGET( (*this_).type_feat_grid ), GTK_ALIGN_END );
     758             :         const gui_type_resource_t (*feat_data)[];
     759             :         unsigned int feat_data_length;
     760           0 :         gui_type_resource_list_get_invariant_feature_types( &res_select, &feat_data, &feat_data_length );
     761           0 :         assert( feat_data_length == GUI_TYPE_RESOURCE_LIST_INV_FEATURES );
     762           0 :         for( int_fast32_t feat_idx = 0; feat_idx < GUI_TYPE_RESOURCE_LIST_INV_FEATURES; feat_idx ++ )  /* ignore the lifeline */
     763             :         {
     764           0 :             const gui_type_resource_t *const type_data = &((*feat_data)[feat_idx]);
     765           0 :             const data_feature_type_t feat_type = data_type_get_feature_type( gui_type_resource_get_type_id( type_data ) );
     766           0 :             GdkTexture *const feat_icon = gui_type_resource_get_icon( type_data );
     767           0 :             const char *const feat_name = gui_type_resource_get_name( type_data );
     768             : 
     769           0 :             gui_attribute_type_of_feature_init( &((*this_).type_feat_data[feat_idx]), feat_type, &((*this_).attributes_editor) );
     770           0 :             (*this_).type_feat_img[ feat_idx ] = GTK_IMAGE( gtk_image_new_from_paintable( GDK_PAINTABLE( feat_icon ) ) );
     771           0 :             gtk_widget_set_size_request( GTK_WIDGET( (*this_).type_feat_img[ feat_idx ] ), 32 /*=w*/ , 24 /*=h*/ );
     772           0 :             (*this_).type_feat_btn[ feat_idx ] = GTK_BUTTON( gtk_button_new() );
     773           0 :             gtk_button_set_image( (*this_).type_feat_btn[ feat_idx ], GTK_WIDGET( (*this_).type_feat_img[ feat_idx ] ) );
     774           0 :             gtk_widget_set_tooltip_text( GTK_WIDGET( (*this_).type_feat_btn[ feat_idx ] ), feat_name );
     775           0 :             gtk_grid_attach( (*this_).type_feat_grid, GTK_WIDGET( (*this_).type_feat_btn[ feat_idx ] ), feat_idx%7, feat_idx/7, 1, 1 );
     776             :         }
     777             : 
     778           0 :         (*this_).type_rel_grid = GTK_GRID( gtk_grid_new() );
     779           0 :         gtk_widget_set_halign( GTK_WIDGET( (*this_).type_rel_grid ), GTK_ALIGN_END );
     780             :         const gui_type_resource_t (*rel_data)[];
     781             :         unsigned int rel_data_length;
     782           0 :         gui_type_resource_list_get_all_relationship_types( &res_select, &rel_data, &rel_data_length );
     783           0 :         assert( rel_data_length == GUI_TYPE_RESOURCE_LIST_RELATIONS );
     784           0 :         for( int_fast32_t rel_idx = 0; rel_idx < GUI_TYPE_RESOURCE_LIST_RELATIONS; rel_idx ++ )
     785             :         {
     786           0 :             const gui_type_resource_t *const type_data = &((*rel_data)[rel_idx]);
     787           0 :             const data_relationship_type_t rel_type = data_type_get_relationship_type( gui_type_resource_get_type_id( type_data ) );
     788           0 :             GdkTexture *const rel_icon = gui_type_resource_get_icon( type_data );
     789           0 :             const char *const rel_name = gui_type_resource_get_name( type_data );
     790             : 
     791           0 :             gui_attribute_type_of_relationship_init( &((*this_).type_rel_data[rel_idx]), rel_type, &((*this_).attributes_editor) );
     792           0 :             (*this_).type_rel_img[ rel_idx ] = GTK_IMAGE( gtk_image_new_from_paintable( GDK_PAINTABLE( rel_icon ) ) );
     793           0 :             gtk_widget_set_size_request( GTK_WIDGET( (*this_).type_rel_img[ rel_idx ] ), 32 /*=w*/ , 24 /*=h*/ );
     794           0 :             (*this_).type_rel_btn[ rel_idx ] = GTK_BUTTON( gtk_button_new() );
     795           0 :             gtk_button_set_image( (*this_).type_rel_btn[ rel_idx ], GTK_WIDGET( (*this_).type_rel_img[ rel_idx ] ) );
     796           0 :             gtk_widget_set_tooltip_text( GTK_WIDGET( (*this_).type_rel_btn[ rel_idx ] ), rel_name );
     797           0 :             gtk_grid_attach( (*this_).type_rel_grid, GTK_WIDGET( (*this_).type_rel_btn[ rel_idx ] ), rel_idx%7, rel_idx/7, 1, 1 );
     798             :         }
     799             :     }
     800           0 :     gui_type_resource_list_destroy( &res_select );
     801             : 
     802             :     /* insert widgets to box container */
     803             :     {
     804           0 :         (*this_).attr_edit_column = gtk_box_new( GTK_ORIENTATION_VERTICAL, /*spacing:*/ 4 );
     805           0 :         gtk_box_append( GTK_BOX((*this_).attr_edit_column), GTK_WIDGET((*this_).id_row) );
     806           0 :         gtk_box_append( GTK_BOX((*this_).attr_edit_column), GTK_WIDGET((*this_).name_label) );
     807           0 :         gtk_box_append( GTK_BOX((*this_).attr_edit_column), GTK_WIDGET((*this_).name_entry) );
     808           0 :         gtk_box_append( GTK_BOX((*this_).attr_edit_column), GTK_WIDGET((*this_).stereotype_label) );
     809           0 :         gtk_box_append( GTK_BOX((*this_).attr_edit_column), GTK_WIDGET((*this_).stereotype_entry) );
     810           0 :         gtk_box_append( GTK_BOX((*this_).attr_edit_column), GTK_WIDGET((*this_).type_label) );
     811           0 :         gtk_box_append( GTK_BOX((*this_).attr_edit_column), GTK_WIDGET((*this_).type_dropdown) );
     812           0 :         gtk_box_append( GTK_BOX((*this_).attr_edit_column), GTK_WIDGET((*this_).type_diag_grid) );
     813           0 :         gtk_box_append( GTK_BOX((*this_).attr_edit_column), GTK_WIDGET((*this_).type_clas_grid) );
     814           0 :         gtk_box_append( GTK_BOX((*this_).attr_edit_column), GTK_WIDGET((*this_).type_feat_grid) );
     815           0 :         gtk_box_append( GTK_BOX((*this_).attr_edit_column), GTK_WIDGET((*this_).type_rel_grid) );
     816           0 :         gtk_box_append( GTK_BOX((*this_).attr_edit_column), GTK_WIDGET((*this_).description_label) );
     817           0 :         gtk_box_append( GTK_BOX((*this_).attr_edit_column), GTK_WIDGET((*this_).description_scroll_win) );
     818             : 
     819           0 :         gtk_widget_set_vexpand( GTK_WIDGET( (*this_).description_scroll_win ), true );
     820           0 :         gtk_widget_set_hexpand( GTK_WIDGET( (*this_).description_scroll_win ), true );
     821             :     }
     822             : 
     823           0 :     U8_TRACE_END();
     824           0 : }
     825             : 
     826           0 : void gui_main_window_private_init_simple_message_to_user( gui_main_window_t *this_ )
     827             : {
     828           0 :     U8_TRACE_BEGIN();
     829           0 :     const gui_resources_t *const res = (*this_).resources;
     830             : 
     831           0 :     (*this_).message_text_label = gtk_label_new( "" );
     832           0 :     gtk_label_set_xalign(GTK_LABEL( (*this_).message_text_label ), 0.0 );
     833             : 
     834           0 :     (*this_).message_icon_image = gtk_image_new_from_paintable( GDK_PAINTABLE ( gui_resources_get_crystal_facet_uml( res ) ) );    gtk_widget_set_size_request( GTK_WIDGET((*this_).message_icon_image), 32 /*=w*/ , 32 /*=h*/ );
     835             : 
     836             :     /* insert widgets to box container */
     837             :     {
     838           0 :         (*this_).message_row = gtk_box_new( GTK_ORIENTATION_HORIZONTAL, /*spacing:*/ 20 );
     839           0 :         gtk_box_append( GTK_BOX((*this_).message_row), GTK_WIDGET((*this_).message_icon_image) );
     840           0 :         gtk_box_append( GTK_BOX((*this_).message_row), GTK_WIDGET((*this_).message_text_label) );
     841             : 
     842           0 :         gtk_widget_set_vexpand( GTK_WIDGET( (*this_).message_icon_image ), false );
     843           0 :         gtk_widget_set_hexpand( GTK_WIDGET( (*this_).message_icon_image ), false );
     844           0 :         gtk_widget_set_vexpand( GTK_WIDGET( (*this_).message_text_label ), false );
     845           0 :         gtk_widget_set_hexpand( GTK_WIDGET( (*this_).message_text_label ), true );
     846             :     }
     847             : 
     848           0 :     U8_TRACE_END();
     849           0 : }
     850             : 
     851           0 : void gui_main_window_private_init_search_and_sketch_area( gui_main_window_t *this_ )
     852             : {
     853           0 :     U8_TRACE_BEGIN();
     854           0 :     const gui_resources_t *const res = (*this_).resources;
     855             : 
     856             :     /* init search widgets */
     857             :     {
     858           0 :         (*this_).search_label = gtk_label_new ( "Search:" );
     859           0 :         gtk_label_set_xalign( GTK_LABEL( (*this_).search_label ), 1.0 ); /* align right */
     860           0 :         gtk_label_set_yalign( GTK_LABEL( (*this_).search_label ), 0.5 ); /* align middle-height */
     861             : 
     862           0 :         (*this_).search_entry = gtk_entry_new();
     863             : 
     864           0 :         (*this_).search_button = gtk_button_new();
     865           0 :         (*this_).search_btn_icon = gtk_image_new_from_paintable( GDK_PAINTABLE( gui_resources_get_search_search( res ) ) );
     866           0 :         gtk_button_set_image( GTK_BUTTON((*this_).search_button), (*this_).search_btn_icon );
     867           0 :         gtk_widget_set_tooltip_text( GTK_WIDGET((*this_).search_button), "Search" );
     868           0 :         gtk_widget_set_size_request( GTK_WIDGET((*this_).search_btn_icon), 32 /*=w*/ , 32 /*=h*/ );
     869             :     }
     870             : 
     871             :     /* insert widgets to box container */
     872             :     {
     873           0 :         (*this_).search_row = gtk_box_new( GTK_ORIENTATION_HORIZONTAL, /*spacing:*/ 4 );
     874           0 :         gtk_box_append( GTK_BOX((*this_).search_row), GTK_WIDGET((*this_).search_label) );
     875           0 :         gtk_box_append( GTK_BOX((*this_).search_row), GTK_WIDGET((*this_).search_entry) );
     876           0 :         gtk_box_append( GTK_BOX((*this_).search_row), GTK_WIDGET((*this_).search_button) );
     877             : 
     878           0 :         gtk_widget_set_vexpand ( GTK_WIDGET( (*this_).search_label ), false );
     879           0 :         gtk_widget_set_hexpand ( GTK_WIDGET( (*this_).search_label ), false );
     880           0 :         gtk_widget_set_vexpand ( GTK_WIDGET( (*this_).search_entry ), false );
     881           0 :         gtk_widget_set_hexpand ( GTK_WIDGET( (*this_).search_entry ), true );
     882           0 :         gtk_widget_set_vexpand ( GTK_WIDGET( (*this_).search_button ), false );
     883           0 :         gtk_widget_set_hexpand ( GTK_WIDGET( (*this_).search_button ), false );
     884             :     }
     885             : 
     886             :     /* init sketch area */
     887             :     {
     888           0 :         (*this_).sketcharea = gtk_drawing_area_new();
     889           0 :         gtk_widget_set_can_focus( GTK_WIDGET( (*this_).sketcharea ), TRUE );  /* this allows the text entry widgets to lose the focus */
     890           0 :         gtk_widget_set_size_request( GTK_WIDGET( (*this_).sketcharea ), 600, 360);  /* set a minimum initial size */
     891             :         /*gtk_widget_set_focus_on_click( GTK_WIDGET( (*this_).sketcharea ), TRUE ); not yet existing: since GTK 3.2 */
     892             :     }
     893             : 
     894             :     /* insert widgets to box container */
     895             :     {
     896           0 :         (*this_).sketch_stack_column = gtk_box_new( GTK_ORIENTATION_VERTICAL, /*spacing:*/ 0 );
     897           0 :         gtk_box_append( GTK_BOX((*this_).sketch_stack_column), GTK_WIDGET((*this_).search_row) );
     898           0 :         gtk_box_append( GTK_BOX((*this_).sketch_stack_column), GTK_WIDGET((*this_).sketcharea) );
     899             : 
     900           0 :         gtk_widget_set_vexpand ( GTK_WIDGET( (*this_).search_row ), false );
     901           0 :         gtk_widget_set_hexpand ( GTK_WIDGET( (*this_).search_row ), true );
     902           0 :         gtk_widget_set_vexpand ( GTK_WIDGET( (*this_).sketcharea ), true );
     903           0 :         gtk_widget_set_hexpand ( GTK_WIDGET( (*this_).sketcharea ), true );
     904             :     }
     905             : 
     906           0 :     U8_TRACE_END();
     907           0 : }
     908             : 
     909           0 : void gui_main_window_destroy_event_callback( GtkWidget *widget, gpointer data )
     910             : {
     911           0 :     U8_TRACE_BEGIN();
     912           0 :     gui_main_window_t *this_ = data;
     913           0 :     assert( (*this_).window == (void*)widget );
     914             : 
     915             :     /* forward destroy request to gui_window_manager: */
     916           0 :     observer_notify( (*this_).window_close_observer, this_ );
     917             : 
     918           0 :     U8_TRACE_TIMESTAMP();
     919           0 :     U8_TRACE_END();
     920           0 : }
     921             : 
     922           0 : gboolean gui_main_window_delete_event_callback( GtkWindow *widget, gpointer data )
     923             : {
     924           0 :     U8_TRACE_BEGIN();
     925           0 :     gui_main_window_t *this_ = data;
     926           0 :     assert( (*this_).window == (void*)widget );
     927             :     (void) this_;  /* unused in case of NDEBUG */
     928             : 
     929           0 :     U8_TRACE_TIMESTAMP();
     930           0 :     U8_TRACE_END();
     931           0 :     return false;  /* return false to trigger destroy event */
     932             : }
     933             : 
     934           0 : void gui_main_window_new_db_btn_callback( GtkWidget* button, gpointer data )
     935             : {
     936           0 :     U8_TRACE_BEGIN();
     937           0 :     gui_main_window_t *this_ = data;
     938             : 
     939           0 :     gui_simple_message_to_user_hide( &((*this_).message_to_user) );
     940             : 
     941           0 :     gui_file_use_db_dialog_show( &((*this_).file_use_db_dialog), false /* open_existing*/ );
     942             : 
     943           0 :     U8_TRACE_TIMESTAMP();
     944           0 :     U8_TRACE_END();
     945           0 : }
     946             : 
     947           0 : void gui_main_window_open_db_btn_callback( GtkWidget* button, gpointer data )
     948             : {
     949           0 :     U8_TRACE_BEGIN();
     950           0 :     gui_main_window_t *this_ = data;
     951             : 
     952           0 :     gui_simple_message_to_user_hide( &((*this_).message_to_user) );
     953             : 
     954           0 :     gui_file_use_db_dialog_show( &((*this_).file_use_db_dialog), true /* open_existing*/ );
     955             : 
     956           0 :     U8_TRACE_TIMESTAMP();
     957           0 :     U8_TRACE_END();
     958           0 : }
     959             : 
     960           0 : void gui_main_window_save_btn_callback( GtkButton *button, gpointer user_data )
     961             : {
     962           0 :     U8_TRACE_BEGIN();
     963             :     gui_main_window_t *this_;
     964           0 :     this_ = (gui_main_window_t*) user_data;
     965           0 :     assert( this_ != NULL );
     966             : 
     967           0 :     gui_simple_message_to_user_hide( &((*this_).message_to_user) );
     968             : 
     969           0 :     gui_attributes_editor_commit_changes ( &((*this_).attributes_editor) );
     970             : 
     971           0 :     const u8_error_t err = gui_file_action_save( &((*this_).file_action) );
     972           0 :     if ( err == U8_ERROR_NONE )
     973             :     {
     974           0 :         GtkImage *const save_image = gui_button_get_icon_ptr( &((*this_).file_save) );
     975           0 :         const GdkPaintable *const shown_icon = gtk_image_get_paintable( save_image );
     976           0 :         GdkPaintable *const saved_icon = GDK_PAINTABLE( gui_resources_get_file_saved( (*this_).resources ) );
     977           0 :         if ( shown_icon != saved_icon )
     978             :         {
     979           0 :             gtk_image_set_from_paintable( save_image, saved_icon );
     980           0 :             U8_TRACE_INFO("icon of save button set to SAVED(/)");
     981             :         }
     982             :     }
     983             : 
     984           0 :     U8_TRACE_TIMESTAMP();
     985           0 :     U8_TRACE_END();
     986           0 : }
     987             : 
     988           0 : gboolean gui_main_window_save_shortcut_callback( GtkWidget* widget, GVariant* args, gpointer user_data )
     989             : {
     990           0 :     gui_main_window_save_btn_callback( (GtkButton*)widget, user_data );
     991           0 :     return TRUE;
     992             : }
     993             : 
     994           0 : void gui_main_window_export_btn_callback( GtkWidget* button, gpointer data )
     995             : {
     996           0 :     U8_TRACE_BEGIN();
     997           0 :     gui_main_window_t *this_ = data;
     998             : 
     999           0 :     gui_simple_message_to_user_hide( &((*this_).message_to_user) );
    1000             : 
    1001           0 :     const bool was_visible = gtk_widget_get_visible( (*this_).options_layout );
    1002           0 :     gtk_widget_set_visible( (*this_).options_layout, ! was_visible );
    1003             : 
    1004           0 :     U8_TRACE_TIMESTAMP();
    1005           0 :     U8_TRACE_END();
    1006           0 : }
    1007             : 
    1008           0 : void gui_main_window_new_window_btn_callback( GtkWidget* button, gpointer data )
    1009             : {
    1010           0 :     U8_TRACE_BEGIN();
    1011           0 :     gui_main_window_t *this_ = data;
    1012             : 
    1013             :     /* hide last message */
    1014           0 :     gui_simple_message_to_user_hide( &((*this_).message_to_user) );
    1015             : 
    1016             :     /* forward new window request to gui_window_manager: */
    1017           0 :     observer_notify( (*this_).window_open_observer, &((*this_).message_to_user) );
    1018             : 
    1019           0 :     U8_TRACE_TIMESTAMP();
    1020           0 :     U8_TRACE_END();
    1021           0 : }
    1022             : 
    1023           0 : void gui_main_window_about_btn_callback( GtkWidget* button, gpointer data )
    1024             : {
    1025           0 :     U8_TRACE_BEGIN();
    1026           0 :     gui_main_window_t *this_ = data;
    1027             : 
    1028           0 :     if ( GUI_SIMPLE_MESSAGE_TYPE_ABOUT == gui_simple_message_to_user_get_type_id( &((*this_).message_to_user) ) )
    1029             :     {
    1030             :         /* hide the already visible about message */
    1031           0 :         gui_simple_message_to_user_hide( &((*this_).message_to_user) );
    1032             :     }
    1033             :     else
    1034             :     {
    1035           0 :         gui_simple_message_to_user_show_message( &((*this_).message_to_user),
    1036             :                                                  GUI_SIMPLE_MESSAGE_TYPE_ABOUT,
    1037             :                                                  GUI_SIMPLE_MESSAGE_CONTENT_ABOUT
    1038             :                                                );
    1039             :     }
    1040             : 
    1041           0 :     U8_TRACE_TIMESTAMP();
    1042           0 :     U8_TRACE_END();
    1043           0 : }
    1044             : 
    1045           0 : void gui_main_window_data_changed_callback( GtkWidget *window, data_change_message_t *msg, gpointer user_data )
    1046             : {
    1047           0 :     U8_TRACE_BEGIN();
    1048           0 :     gui_main_window_t *this_ = user_data;
    1049             : 
    1050             :     /* update the window title */
    1051           0 :     if (( DATA_CHANGE_EVENT_TYPE_DB_OPENED == data_change_message_get_event( msg ) )
    1052           0 :         || ( DATA_CHANGE_EVENT_TYPE_DB_CLOSED == data_change_message_get_event( msg ) ))
    1053             :     {
    1054             :         /* the database has changed */
    1055           0 :         const char *filename = io_data_file_get_filename_const( (*this_).data_file );
    1056           0 :         if ( NULL == filename )
    1057             :         {
    1058           0 :             gtk_window_set_title(GTK_WINDOW((*this_).window), META_INFO_PROGRAM_NAME_STR );
    1059             :         }
    1060             :         else
    1061             :         {
    1062           0 :             gtk_window_set_title(GTK_WINDOW((*this_).window), filename );
    1063             :         }
    1064             :     }
    1065             : 
    1066             :     /* update the save button status indicator */
    1067           0 :     GtkImage *const save_image = gui_button_get_icon_ptr( &((*this_).file_save) );
    1068           0 :     const GdkPaintable *const shown_icon = gtk_image_get_paintable( save_image );
    1069             : 
    1070           0 :     if (( DATA_CHANGE_EVENT_TYPE_DB_OPENED == data_change_message_get_event( msg ) )
    1071           0 :         || ( DATA_CHANGE_EVENT_TYPE_DB_CLOSED == data_change_message_get_event( msg ) ))
    1072           0 :     {
    1073           0 :         GdkPaintable *const saved_icon = GDK_PAINTABLE( gui_resources_get_file_saved( (*this_).resources ) );
    1074           0 :         if ( shown_icon != saved_icon )
    1075             :         {
    1076           0 :             gtk_image_set_from_paintable( save_image, saved_icon );
    1077           0 :             U8_TRACE_INFO("icon of save button set to SAVED(/)");
    1078             :         }
    1079             :     }
    1080           0 :     else if ( DATA_CHANGE_EVENT_TYPE_DB_PREPARE_CLOSE != data_change_message_get_event( msg ) )
    1081             :     {
    1082           0 :         GdkPaintable *const save_icon = GDK_PAINTABLE( gui_resources_get_file_save( (*this_).resources ) );
    1083           0 :         if ( shown_icon != save_icon )
    1084             :         {
    1085           0 :             gtk_image_set_from_paintable( save_image, save_icon );
    1086           0 :             U8_TRACE_INFO("icon of save button set to NOT-SAVED(*)");
    1087             :         }
    1088             :     }
    1089             : 
    1090           0 :     U8_TRACE_TIMESTAMP();
    1091           0 :     U8_TRACE_END();
    1092           0 : }
    1093             : 
    1094           0 : void gui_main_window_state_callback( GtkWidget* window, GtkStateFlags old_flags, gpointer user_data )
    1095             : {
    1096           0 :     U8_TRACE_BEGIN();
    1097           0 :     gui_main_window_t *this_ = user_data;
    1098             : 
    1099             :     /* GTK_STATE_FLAG_ACTIVE is close to what is needed */
    1100             :     /* but it is sometimes not called when window loses focus */
    1101             :     /* and it is sometimes activated multiple times when window gains focus */
    1102             : 
    1103           0 :     GtkStateFlags new_flags = gtk_widget_get_state_flags ( window );
    1104           0 :     GtkStateFlags changed = old_flags ^ new_flags;
    1105             : 
    1106           0 :     if ( 0 != ( changed & GTK_STATE_FLAG_BACKDROP ) )
    1107             :     {
    1108           0 :         U8_TRACE_INFO_INT("GTK_STATE_FLAGS & GTK_STATE_FLAG_BACKDROP:", changed & GTK_STATE_FLAG_BACKDROP );
    1109             : 
    1110             :         /* check if latest changes are already saved */
    1111           0 :         const bool is_saved = io_data_file_is_in_sync( (*this_).data_file );
    1112             : 
    1113             :         /* update the icon of the save button */
    1114           0 :         GtkImage *const save_image = gui_button_get_icon_ptr( &((*this_).file_save) );
    1115           0 :         const GdkPaintable *const shown_icon = gtk_image_get_paintable( save_image );
    1116             : 
    1117           0 :         GdkPaintable *const current_icon
    1118             :             = is_saved
    1119           0 :             ? GDK_PAINTABLE( gui_resources_get_file_saved( (*this_).resources ) )
    1120           0 :             : ( 0 != ( new_flags & GTK_STATE_FLAG_BACKDROP ) )
    1121           0 :             ? GDK_PAINTABLE( gui_resources_get_file_unsaved( (*this_).resources ) )
    1122           0 :             : GDK_PAINTABLE( gui_resources_get_file_save( (*this_).resources ) );
    1123             : 
    1124             :         /* update the save button status indicator */
    1125           0 :         if ( shown_icon != current_icon )
    1126             :         {
    1127           0 :             gtk_image_set_from_paintable( save_image, current_icon );
    1128           0 :             U8_TRACE_INFO("icon of save button updated");
    1129             :         }
    1130             :         // U8_TRACE_FLUSH();
    1131             :     }
    1132             : 
    1133           0 :     U8_TRACE_TIMESTAMP();
    1134           0 :     U8_TRACE_END();
    1135           0 : }
    1136             : 
    1137             : 
    1138             : /*
    1139             : Copyright 2016-2024 Andreas Warnke
    1140             : 
    1141             : Licensed under the Apache License, Version 2.0 (the "License");
    1142             : you may not use this file except in compliance with the License.
    1143             : You may obtain a copy of the License at
    1144             : 
    1145             :     http://www.apache.org/licenses/LICENSE-2.0
    1146             : 
    1147             : Unless required by applicable law or agreed to in writing, software
    1148             : distributed under the License is distributed on an "AS IS" BASIS,
    1149             : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    1150             : See the License for the specific language governing permissions and
    1151             : limitations under the License.
    1152             : */

Generated by: LCOV version 1.16