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

Generated by: LCOV version 1.16