From a28b531d84231f6b15da482470c30e610330a68e Mon Sep 17 00:00:00 2001 From: Garux Date: Wed, 2 Aug 2017 09:54:33 +0300 Subject: [PATCH] Radiant: misc... * entity inspector, entity list->'autofocus on selection' buttons: also do FocusAllViews() on clicking them * focus on preferences treeview on 2nd+ call to make text search to work * fixed WindowPositionTracker globally: minus many particular hacks, plus correct wnds positioning in Floating viewports layout * fixed ToggleShown functionality: shown/hidden wnds states are saved and loaded correctly in Floating viewports layout * also save/load XY and Cam viewports visibility states * new preferences->layout icons * fix: stop chaseMouseMotion on mouse button release --- libs/gtkutil/widget.h | 35 +++++++++++++++++++++++---- libs/gtkutil/window.h | 29 +++++++++++++++++++++- radiant/camwindow.cpp | 1 + radiant/entityinspector.cpp | 5 ++++ radiant/entitylist.cpp | 5 ++++ radiant/findtexturedialog.cpp | 2 -- radiant/groupdialog.cpp | 4 --- radiant/mainframe.cpp | 8 +++--- radiant/patchdialog.cpp | 2 -- radiant/preferences.cpp | 3 +++ radiant/preferences.h | 3 +-- radiant/xywindow.cpp | 17 +++---------- setup/data/tools-src/window1.png | Bin 0 -> 388 bytes setup/data/tools-src/window2.png | Bin 0 -> 406 bytes setup/data/tools-src/window3.png | Bin 0 -> 395 bytes setup/data/tools-src/window4.png | Bin 0 -> 387 bytes setup/data/tools/bitmaps/window1.png | Bin 388 -> 875 bytes setup/data/tools/bitmaps/window2.png | Bin 406 -> 883 bytes setup/data/tools/bitmaps/window3.png | Bin 395 -> 738 bytes setup/data/tools/bitmaps/window4.png | Bin 387 -> 873 bytes 20 files changed, 82 insertions(+), 32 deletions(-) create mode 100644 setup/data/tools-src/window1.png create mode 100644 setup/data/tools-src/window2.png create mode 100644 setup/data/tools-src/window3.png create mode 100644 setup/data/tools-src/window4.png diff --git a/libs/gtkutil/widget.h b/libs/gtkutil/widget.h index f4bc3267..0ee5465e 100644 --- a/libs/gtkutil/widget.h +++ b/libs/gtkutil/widget.h @@ -28,8 +28,11 @@ #include "warnings.h" #include "debugging/debugging.h" +#include + inline bool widget_is_visible( GtkWidget* widget ){ - return GTK_WIDGET_VISIBLE( widget ) != FALSE; + //return GTK_WIDGET_VISIBLE( widget ) != FALSE; + return gtk_widget_get_visible( widget ) != FALSE; } inline void widget_set_visible( GtkWidget* widget, bool show ){ @@ -37,8 +40,6 @@ inline void widget_set_visible( GtkWidget* widget, bool show ){ /* workaround for gtk 2.24 issue: not displayed glwidget after toggle */ GtkWidget* glwidget = GTK_WIDGET( g_object_get_data( G_OBJECT( widget ), "glwidget" ) ); if ( glwidget ){ - //if ( widget_is_visible( glwidget ) ) - //globalOutputStream() << "glwidget have been already visible :0\n"; /* is not hidden aswell, according to this */ gtk_widget_hide( glwidget ); gtk_widget_show( glwidget ); } @@ -86,11 +87,17 @@ ToggleShown( const ToggleShown& other ); // NOT COPYABLE ToggleShown& operator=( const ToggleShown& other ); // NOT ASSIGNABLE static gboolean notify_visible( GtkWidget* widget, gpointer dummy, ToggleShown* self ){ + /* destroy = notify::visible with visible = 0, thus let's filter it out */ + if( gtk_main_level() > 0 ){ //== 0 at destroy time + self->m_shownDeferred = widget_is_visible( self->m_widget ); + } +//globalOutputStream() << "ToggleShown::notify_visible time " << gtk_get_current_event_time() << " visible " << self->m_shownDeferred << "\n"; self->update(); return FALSE; } static gboolean destroy( GtkWidget* widget, ToggleShown* self ){ - self->m_shownDeferred = GTK_WIDGET_VISIBLE( self->m_widget ) != FALSE; +//globalOutputStream() << "ToggleShown::destroy time " << gtk_get_current_event_time() << " visible " << self->m_shownDeferred << "\n"; + //self->m_shownDeferred = widget_is_visible( self->m_widget ); //always 0 at destroy time self->m_widget = 0; return FALSE; } @@ -102,22 +109,26 @@ ToggleShown( bool shown ) : m_shownDeferred( shown ), m_widget( 0 ), m_item( ActiveCaller( *this ) ){ } void update(){ +//globalOutputStream() << "ToggleShown::update\n"; m_item.update(); } bool active() const { +//globalOutputStream() << "ToggleShown::active\n"; if ( m_widget == 0 ) { return m_shownDeferred; } else { - return GTK_WIDGET_VISIBLE( m_widget ) != FALSE; + return widget_is_visible( m_widget ); } } void exportActive( const BoolImportCallback& importCallback ){ +//globalOutputStream() << "ToggleShown::exportActive\n"; importCallback( active() ); } typedef MemberCaller1 ActiveCaller; void set( bool shown ){ +//globalOutputStream() << "ToggleShown::set\n"; if ( m_widget == 0 ) { m_shownDeferred = shown; } @@ -127,10 +138,12 @@ void set( bool shown ){ } } void toggle(){ +//globalOutputStream() << "ToggleShown::toggle\n"; widget_toggle_visible( m_widget ); } typedef MemberCaller ToggleCaller; void connect( GtkWidget* widget ){ +//globalOutputStream() << "ToggleShown::connect\n"; m_widget = widget; widget_set_visible( m_widget, m_shownDeferred ); g_signal_connect( G_OBJECT( m_widget ), "notify::visible", G_CALLBACK( notify_visible ), this ); @@ -139,6 +152,18 @@ void connect( GtkWidget* widget ){ } }; +namespace{ + +void ToggleShown_importBool( ToggleShown& self, bool value ){ + self.set( value ); +} +typedef ReferenceCaller1 ToggleShownImportBoolCaller; +void ToggleShown_exportBool( const ToggleShown& self, const BoolImportCallback& importer ){ + importer( self.active() ); +} +typedef ConstReferenceCaller1 ToggleShownExportBoolCaller; + +} inline void widget_queue_draw( GtkWidget& widget ){ gtk_widget_queue_draw( &widget ); diff --git a/libs/gtkutil/window.h b/libs/gtkutil/window.h index 1a7161e6..cd597c86 100644 --- a/libs/gtkutil/window.h +++ b/libs/gtkutil/window.h @@ -108,32 +108,59 @@ typedef ConstReferenceCaller1m_position = WindowPosition( event->x, event->y, event->width, event->height ); return FALSE; } public: WindowPositionTracker() - : m_position( c_default_window_pos ){ + : m_position( c_default_window_pos ), m_window( 0 ){ } void sync( GtkWindow* window ){ +//globalOutputStream() << "WindowPositionTracker::sync\n"; window_set_position( window, m_position ); } +void sync(){ + if( m_window ) + sync( m_window ); +} + +/** need to reapply pos on every hiding to keep wnd pos after hide+show (flickering between two positions, if doing on showing) +this stuff is weird: some wnds, like entity list, keep pos on hide/show... untill you resize them -) +some, like floating xy/cam/groupdialog do not; if you remove glwidget from floating xy - it does xD +if you gtk_window_set_position( window, GTK_WIN_POS_CENTER_ALWAYS ), they do keep it, except of random centering after resizing (ms windows) +but this option doesn't sound healthy; +gtk_window_set_transient_for seems to do some gtk_window_set_position also +old questionable comment on this issue: +workaround for strange gtk behaviour - modifying the contents of a window while it is not visible causes the window position to change without sending a configure_event */ +static gboolean notify_visible( GtkWidget* widget, gpointer dummy, WindowPositionTracker* self ){ + if( !widget_is_visible( GTK_WIDGET( self->m_window ) ) ) + self->sync(); + return FALSE; +} + void connect( GtkWindow* window ){ +//globalOutputStream() << "WindowPositionTracker::connect\n"; + m_window = window; sync( window ); g_signal_connect( G_OBJECT( window ), "configure_event", G_CALLBACK( configure ), this ); + g_signal_connect( G_OBJECT( window ), "notify::visible", G_CALLBACK( notify_visible ), this ); } const WindowPosition& getPosition() const { +//globalOutputStream() << "WindowPositionTracker::getPosition\n"; return m_position; } //hack void setPosition( const WindowPosition& position ){ +//globalOutputStream() << "WindowPositionTracker::setPosition\n"; m_position = position; } }; diff --git a/radiant/camwindow.cpp b/radiant/camwindow.cpp index 0beb2ed7..f6b6270a 100644 --- a/radiant/camwindow.cpp +++ b/radiant/camwindow.cpp @@ -2308,6 +2308,7 @@ void CamWnd_Construct(){ GlobalPreferenceSystem().registerPreference( "CameraFaceWire", BoolImportStringCaller( g_camwindow_globals_private.m_bFaceWire ), BoolExportStringCaller( g_camwindow_globals_private.m_bFaceWire ) ); GlobalPreferenceSystem().registerPreference( "3DZoomInToPointer", BoolImportStringCaller( g_camwindow_globals.m_bZoomInToPointer ), BoolExportStringCaller( g_camwindow_globals.m_bZoomInToPointer ) ); GlobalPreferenceSystem().registerPreference( "fieldOfView", FloatImportStringCaller( camera_t::fieldOfView ), FloatExportStringCaller( camera_t::fieldOfView ) ); + GlobalPreferenceSystem().registerPreference( "CamVIS", makeBoolStringImportCallback( ToggleShownImportBoolCaller( g_camera_shown ) ), makeBoolStringExportCallback( ToggleShownExportBoolCaller( g_camera_shown ) ) ); CamWnd_constructStatic(); diff --git a/radiant/entityinspector.cpp b/radiant/entityinspector.cpp index 2040ffd7..9d3967f1 100644 --- a/radiant/entityinspector.cpp +++ b/radiant/entityinspector.cpp @@ -1429,6 +1429,10 @@ void EntityInspector_selectConnected( GtkButton *button, gpointer user_data ){ Select_ConnectedEntities( true, true, focus ); } +void EntityInspector_focusSelected( GtkButton *button, gpointer user_data ){ + FocusAllViews(); +} + GtkWidget* EntityInspector_constructWindow( GtkWindow* toplevel ){ GtkWidget* vbox = gtk_vbox_new( FALSE, 2 ); gtk_widget_show( vbox ); @@ -1690,6 +1694,7 @@ GtkWidget* EntityInspector_constructWindow( GtkWindow* toplevel ){ gtk_widget_set_tooltip_text( button, "AutoFocus on Selection" ); gtk_widget_show( button ); g_focusToggleButton = GTK_TOGGLE_BUTTON( button ); + g_signal_connect( G_OBJECT( button ), "clicked", G_CALLBACK( EntityInspector_focusSelected ), 0 ); } } } diff --git a/radiant/entitylist.cpp b/radiant/entitylist.cpp index d08414e5..eca344f4 100644 --- a/radiant/entitylist.cpp +++ b/radiant/entitylist.cpp @@ -142,6 +142,10 @@ void entitylist_treeviewcolumn_celldatafunc( GtkTreeViewColumn* column, GtkCellR } } +void entitylist_focusSelected( GtkButton *button, gpointer user_data ){ + FocusAllViews(); +} + static gboolean entitylist_tree_select( GtkTreeSelection *selection, GtkTreeModel *model, GtkTreePath *path, gboolean path_currently_selected, gpointer data ){ GtkTreeIter iter; gtk_tree_model_get_iter( model, &iter, path ); @@ -339,6 +343,7 @@ void EntityList_constructWindow( GtkWindow* main_window ){ gtk_widget_show( check ); gtk_box_pack_start( GTK_BOX( vbox ), check, FALSE, FALSE, 0 ); getEntityList().m_check = check; + g_signal_connect( G_OBJECT( check ), "clicked", G_CALLBACK( entitylist_focusSelected ), 0 ); } } diff --git a/radiant/findtexturedialog.cpp b/radiant/findtexturedialog.cpp index 14998574..5bea3f7e 100644 --- a/radiant/findtexturedialog.cpp +++ b/radiant/findtexturedialog.cpp @@ -253,8 +253,6 @@ void FindTextureDialog::setReplaceStr( const char* name ){ } void FindTextureDialog::show(){ - // workaround for strange gtk behaviour - modifying the contents of a window while it is not visible causes the window position to change without sending a configure_event - g_FindTextureDialog.m_position_tracker.sync( g_FindTextureDialog.GetWidget() ); g_FindTextureDialog.ShowDlg(); gtk_window_present( g_FindTextureDialog.GetWidget() ); } diff --git a/radiant/groupdialog.cpp b/radiant/groupdialog.cpp index dc94603b..8eafa1df 100644 --- a/radiant/groupdialog.cpp +++ b/radiant/groupdialog.cpp @@ -59,13 +59,9 @@ GroupDlg(); void Create( GtkWindow* parent ); void Show(){ - // workaround for strange gtk behaviour - modifying the contents of a window while it is not visible causes the window position to change without sending a configure_event - m_position_tracker.sync( m_window ); /* workaround for gtk 2.24 issue: not displayed glwidget after toggle */ GtkWidget* glwidget = GTK_WIDGET( g_object_get_data( G_OBJECT( m_window ), "glwidget" ) ); if ( glwidget ){ - //if ( widget_is_visible( glwidget ) ) - //globalOutputStream() << "glwidget have been already visible :0\n"; /* is not hidden aswell, according to this */ gtk_widget_hide( glwidget ); gtk_widget_show( glwidget ); } diff --git a/radiant/mainframe.cpp b/radiant/mainframe.cpp index 80187727..2ad56036 100644 --- a/radiant/mainframe.cpp +++ b/radiant/mainframe.cpp @@ -1772,10 +1772,12 @@ bool MainFrame_isActiveApp(){ //globalOutputStream() << "toplevel.. "; if ( gtk_window_is_active( GTK_WINDOW( i->data ) ) ) { //globalOutputStream() << "is active\n"; + g_list_free( list ); return true; } //globalOutputStream() << "not active\n"; } + g_list_free( list ); return false; } @@ -2967,6 +2969,7 @@ gboolean toolbar_redirect_scroll( GtkWidget* widget, GdkEventScroll* event, gpoi return FALSE; } + void MainFrame::Create(){ GtkWindow* window = GTK_WINDOW( gtk_window_new( GTK_WINDOW_TOPLEVEL ) ); @@ -3157,8 +3160,6 @@ void MainFrame::Create(){ global_accel_connect_window( window ); g_posCamWnd.connect( window ); - gtk_widget_show( GTK_WIDGET( window ) ); - m_pCamWnd = NewCamWnd(); GlobalCamera_setCamWnd( *m_pCamWnd ); @@ -3166,6 +3167,7 @@ void MainFrame::Create(){ GtkFrame* frame = create_framed_widget( CamWnd_getWidget( *m_pCamWnd ) ); gtk_container_add( GTK_CONTAINER( window ), GTK_WIDGET( frame ) ); } + CamWnd_setParent( *m_pCamWnd, window ); /* workaround for gtk 2.24 issue: not displayed glwidget after toggle */ g_object_set_data( G_OBJECT( window ), "glwidget", CamWnd_getWidget( *m_pCamWnd ) ); @@ -3182,11 +3184,11 @@ void MainFrame::Create(){ m_pXYWnd->m_parent = window; m_pXYWnd->SetViewType( XY ); - { GtkFrame* frame = create_framed_widget( m_pXYWnd->GetWidget() ); gtk_container_add( GTK_CONTAINER( window ), GTK_WIDGET( frame ) ); } + XY_Top_Shown_Construct( window ); /* workaround for gtk 2.24 issue: not displayed glwidget after toggle */ g_object_set_data( G_OBJECT( window ), "glwidget", m_pXYWnd->GetWidget() ); diff --git a/radiant/patchdialog.cpp b/radiant/patchdialog.cpp index 7ce797e7..ef6728a3 100644 --- a/radiant/patchdialog.cpp +++ b/radiant/patchdialog.cpp @@ -301,8 +301,6 @@ void PatchInspector_queueDraw(){ void DoPatchInspector(){ g_PatchInspector.GetPatchInfo(); if ( !g_PatchInspector.visible() ) { - // workaround for strange gtk behaviour - modifying the contents of a window while it is not visible causes the window position to change without sending a configure_event - g_PatchInspector.m_position_tracker.sync( g_PatchInspector.GetWidget() ); g_PatchInspector.ShowDlg(); } } diff --git a/radiant/preferences.cpp b/radiant/preferences.cpp index e838ab8a..1c8b7e45 100644 --- a/radiant/preferences.cpp +++ b/radiant/preferences.cpp @@ -753,6 +753,7 @@ GtkWindow* PrefsDlg::BuildDialog(){ GtkTreeStore* store = gtk_tree_store_new( 2, G_TYPE_STRING, G_TYPE_POINTER ); GtkWidget* view = gtk_tree_view_new_with_model( GTK_TREE_MODEL( store ) ); + m_treeview = view; gtk_tree_view_set_headers_visible( GTK_TREE_VIEW( view ), FALSE ); { @@ -932,6 +933,8 @@ void PreferencesDialog_restartRequired( const char* staticName ){ void PreferencesDialog_showDialog(){ //if ( ConfirmModified( "Edit Preferences" ) && g_Preferences.DoModal() == eIDOK ) { + if( gtk_widget_get_realized( g_Preferences.m_treeview ) == TRUE ) + gtk_widget_grab_focus( g_Preferences.m_treeview ); if ( g_Preferences.DoModal() == eIDOK ) { if ( !g_restart_required.empty() ) { StringOutputStream message( 256 ); diff --git a/radiant/preferences.h b/radiant/preferences.h index 4b44f97f..e6d36898 100644 --- a/radiant/preferences.h +++ b/radiant/preferences.h @@ -321,8 +321,6 @@ CGameDescription *GameDescriptionForComboItem(); extern CGameDialog g_GamesDialog; -class texdef_t; - class PrefsDlg : public Dialog { public: @@ -332,6 +330,7 @@ std::list mGames; public: GtkWidget *m_notebook; +GtkWidget *m_treeview; virtual ~PrefsDlg(){ g_string_free( m_rc_path, true ); diff --git a/radiant/xywindow.cpp b/radiant/xywindow.cpp index 0a0f412c..db1cef55 100644 --- a/radiant/xywindow.cpp +++ b/radiant/xywindow.cpp @@ -809,6 +809,8 @@ gboolean xywnd_button_release( GtkWidget* widget, GdkEventButton* event, XYWnd* xywnd->XY_MouseUp( static_cast( event->x ), static_cast( event->y ), buttons_for_event_button( event ) ); xywnd->ButtonState_onMouseUp( buttons_for_event_button( event ) ); + + xywnd->chaseMouseMotion( static_cast( event->x ), static_cast( event->y ) ); /* stop chaseMouseMotion this way */ } return FALSE; } @@ -3391,24 +3393,12 @@ void Clipper_registerPreferencesPage(){ #include "stringio.h" - - -void ToggleShown_importBool( ToggleShown& self, bool value ){ - self.set( value ); -} -typedef ReferenceCaller1 ToggleShownImportBoolCaller; -void ToggleShown_exportBool( const ToggleShown& self, const BoolImportCallback& importer ){ - importer( self.active() ); -} -typedef ConstReferenceCaller1 ToggleShownExportBoolCaller; - - void XYWindow_Construct(){ // GlobalCommands_insert( "ToggleCrosshairs", FreeCaller(), Accelerator( 'X', (GdkModifierType)GDK_SHIFT_MASK ) ); // GlobalCommands_insert( "ToggleSizePaint", FreeCaller(), Accelerator( 'J' ) ); // GlobalCommands_insert( "ToggleGrid", FreeCaller(), Accelerator( '0' ) ); - GlobalToggles_insert( "ToggleView", ToggleShown::ToggleCaller( g_xy_top_shown ), ToggleItem::AddCallbackCaller( g_xy_top_shown.m_item ), Accelerator( 'V', (GdkModifierType)( GDK_SHIFT_MASK | GDK_CONTROL_MASK ) ) ); + GlobalToggles_insert( "ToggleView", ToggleShown::ToggleCaller( g_xy_top_shown ), ToggleItem::AddCallbackCaller( g_xy_top_shown.m_item ) ); GlobalToggles_insert( "ToggleSideView", ToggleShown::ToggleCaller( g_yz_side_shown ), ToggleItem::AddCallbackCaller( g_yz_side_shown.m_item ) ); GlobalToggles_insert( "ToggleFrontView", ToggleShown::ToggleCaller( g_xz_front_shown ), ToggleItem::AddCallbackCaller( g_xz_front_shown.m_item ) ); GlobalCommands_insert( "NextView", FreeCaller(), Accelerator( GDK_Tab, (GdkModifierType)GDK_CONTROL_MASK ) ); @@ -3450,6 +3440,7 @@ void XYWindow_Construct(){ GlobalPreferenceSystem().registerPreference( "SI_Colors11", Vector3ImportStringCaller( g_xywindow_globals.color_selbrushes ), Vector3ExportStringCaller( g_xywindow_globals.color_selbrushes ) ); + GlobalPreferenceSystem().registerPreference( "XYVIS", makeBoolStringImportCallback( ToggleShownImportBoolCaller( g_xy_top_shown ) ), makeBoolStringExportCallback( ToggleShownExportBoolCaller( g_xy_top_shown ) ) ); GlobalPreferenceSystem().registerPreference( "XZVIS", makeBoolStringImportCallback( ToggleShownImportBoolCaller( g_xz_front_shown ) ), makeBoolStringExportCallback( ToggleShownExportBoolCaller( g_xz_front_shown ) ) ); GlobalPreferenceSystem().registerPreference( "YZVIS", makeBoolStringImportCallback( ToggleShownImportBoolCaller( g_yz_side_shown ) ), makeBoolStringExportCallback( ToggleShownExportBoolCaller( g_yz_side_shown ) ) ); diff --git a/setup/data/tools-src/window1.png b/setup/data/tools-src/window1.png new file mode 100644 index 0000000000000000000000000000000000000000..c880b89d9e3e49ad5e9a527fe5544b750b569397 GIT binary patch literal 388 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnF3?v&v(vJfvmUKs7M+SzC{oH>NSwWJ?9znhg z3{`3j3=J&|48MRv4KElNN(~qoUL`OvSj}Ky5HFasE6@fg!5`og;>y5q0Lc9R|Nj9X zU|`sAWNs^v&zR)x?!uJDU6TUja29w(7Bet#3xP1>rMq>1fPw{{E{-7@=jTp1&3izB z$60dWd`_-NhK-I>{-$R!E!B7yAnN|;L&_X~4*6SYB}d#>?z`@<@P={WV&-c_4IIW2 zyH*^|VmSNZz!4sY;$Xv6)M$ok!<7u1+)!v63Vcf!LHqH~UF^1C0=mwmH9 zx~9eM&r;@wWT4%uC9V-ADTyViR>?)FK#IZ0z|dINz)aW3JjBS*%Fx2f&`8_B$jZRr xMe8X(6b-rgDVb@NPz|QKh87`)##Sa~R)%H}4GBUIt^+kNc)I$ztaD0e0st=Mc%%RT literal 0 HcmV?d00001 diff --git a/setup/data/tools-src/window2.png b/setup/data/tools-src/window2.png new file mode 100644 index 0000000000000000000000000000000000000000..94e936c5ce9ef0544b6cc8b38524ab12fac3c539 GIT binary patch literal 406 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnH3?%tPCZz)@mUKs7M+SzC{oH>NSwWJ?9znhg z3{`3j3=J&|48MRv4KElNN(~qoUL`OvSj}Ky5HFasE6@fg!4u#U;>y5q0Lc9R|38q@ zi8*=<$YD(Kc6VV)cDEZ1+F zHSbA~kqe_#MUgE}pv$fK=Z%$oKkYONSwWJ?9znhg z3{`3j3=J&|48MRv4KElNN(~qoUL`OvSj}Ky5HFasE6@fg!5`og;>y5q0Lc9R|Nj9X zU|`sAWNs^v&zR)x?!uJDU6TUja29w(7Bet#3xP1>rMq>1fP&?oE{-7@=jTqm%iEy9 z(;|6rKBrFXfgJ~1|E6!cut>}|q>uf?@u#O+1>#KZTy${_G>_WX*utaW&A7UGrj3SJ zMSG*MbA&PL|AUXcpP$Wqo3&b3KUdr0)+t5RDcd$Z=P}%1xkcvF(zF8%w?)<^n>J^; zo!?(!V0Mdf<8Q}E^EjnSpc7O}Tq8@X{p@o&9 zk+y-6m4U&F)>C{a8glbfGSe!d8ccN!EkX>9txU|U49y@K5`-RH2WnvOboFyt=akR{ E06&F&4*&oF literal 0 HcmV?d00001 diff --git a/setup/data/tools-src/window4.png b/setup/data/tools-src/window4.png new file mode 100644 index 0000000000000000000000000000000000000000..891ca415ef532e887275adef080bd6bf71f4b17c GIT binary patch literal 387 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnF3?v&v(vJfvmUKs7M+SzC{oH>NSwWJ?9znhg z3{`3j3=J&|48MRv4KElNN(~qoUL`OvSj}Ky5HFasE6@fg!5`og;>y5q0Lc9R|Nj9X zU|`sAWNs^v&zR)x?!uJDU6TUja29w(7Bet#3xP1>rMq>1fP(p+E{-7@=ci7%&D)?L zz@mB3oi%P9gNR~(m$Kg^!E=?$w>#lqdI9D6jTzMOo)h3S)T!tL00Eq}(& zIU7p5?p)+zK9LmDqjaTwNlVxb&-`Oi7G1lZC%?~VDR>n4=YNXO(?a%QUyk^~Me1Qo z);UVVU9b5Lv|6>qHKHUXu_V85q21 vJ;jHjAvZrIGp!P;!Bp4KBE-LFmDCpaup{S3j3^P6x`kj(%=;uYdf{Z5%nGwWB>uidhC!GZ-*QBiQG4}f#~ z`}?PEo|?EIktLS}?n(%QF`H4dNi%&(di$>SwnJ@Eo1-S3nv|21Gmy@8e{*x2vTBM# zfBpet4CRgxAab?oZsINTAxHC}0s5rXXVAnz=d=rP1TaZVSvW;FOnC8;#c<~`^)n@I zOI);eQE+fDX3;w^X&3GecX#(0%VxAKZ_{3&4Ro>bV&jGT79y8if7nBJ04rfnPtRTZ zcXb@==s3{P-P4VhSO=YRfe!NV@tHAWMnFIS!M4yqrd@)L8Y{%Uvovm(~T@sB>xAwS*^DFarUgX%{KIBB$d4 zOuLBeMFr>5KJAV=e|N|Xi%_eQ#A*(>B49uuq>FQ|Np;o{`~dZ zcTXHU4rJp3mrkF7OPxD)_S~6kcoajVAYDr;JNLpdkUN$ySqZV@*r5|Z^4gW_XAhkR z`Q+&7t2b{08GE+v0g{(4oC1=U&)y{HR$4iC2#uEl0C;Q65gDR^lI8#a002ovPDHLk FV1g0wYgYgO delta 336 zcmaFO*21jV8Q|y6%O%Cdz`(%k>ERLtq!mDzg&9aThNK^#sAyl$AK(+>%D`{{DD?mT z{{uk4z_8)S+*Tl;G0EHAg(;1@CI!ghEbxddW?(M zk(GhLi`G+oC>nC}Q!>*kK^oM6I!tv9EkX>9txU|U49y@q5`-RH2kKz(boFyt=akR{ E0Ag8f&;S4c diff --git a/setup/data/tools/bitmaps/window2.png b/setup/data/tools/bitmaps/window2.png index 94e936c5ce9ef0544b6cc8b38524ab12fac3c539..67da22ab7bad26e5401aea758ee4e745ed9efe0b 100644 GIT binary patch delta 835 zcmV-J1HAl}1M>zUiBL{Q4GJ0x0000DNk~Le0000w0000W2m$~A0L+y9f{`IVe+h6% zS#tmY3l0DP3l0H5zTrUt000_vMObuGZ)S9NVRB^vP+@6qbS_RsR3LUUE;TMOFfjCT zp#T5^!%0LzR9Hu2teSS8VF&@BbB7QD1?>CR&xZtpCIX;a=^wyk1kjLmF3{mejvRUX z_%V=#0GhJNOM!^crMh#ep1OdEe+R|6z~H1Jpt*CYn*e|z;XpkANjx-63=rp{)<6Fl z7@!E^k^c?<5s2ace;C5_=FoR86%#JdC_05MRkFy?buJ>kBBx_$+C@sQ$my7bv`cx8 z2AY5rx-@exB<&6v=R(R|H0L@xItB#=rKhLY)YMFvFk#}XiQV(N`=<3Ze>F9wrlxv$ zcwmh*C_lv9JT^Tp(I`e`F=g1Qs-hLb%ae zqVx0fF`Y}@4lDL14qC|oECJM#)qu{;otkUA+!m{IryQQ*?Cgx@T>Q;^Dm2frmb<_d zIbqHO(Fjrbc=`6D?P$&wnkv+Ou)U?V1vzs-5(9of1?OTdcY*EzCW$EvrwE4$FFvvu z?p&sRro?TDi`Fg*e+~{t%g7Mt(mZr=ITz>}cX#(0%VxAKZ_{3&4Ro>bV&jGT7Q#!e zfpIQ8XJ9ScJv}{l?cddLtfS*VM|V#*a$?1FE-{&mqK-RUGoChskB`rc88ZR`0`S*W z^Q0V{v z|3FG7=IAjXhcU_9-GwQQyCwz5;VkfoEM{Qf76M_$OLy!300mn;T^vIsF6W*%s_wI&%Kgq958u7ghW1wWqLDz5dIx zT)%DByeIWRMlOs}6-Bl@fiAb^pEp+W{j}5ckbvmrq=qBewa2$G#Mk8-%TD}Pr|=}$ z;7psyyN`)-Y0oz3&WP4X2)l7ACz7%8SW`bw+>$t~ W5FH6Z53U1sFnGH9xvX1R9Hu2teSS8VF&@BbB7QD1*`)NKwn?qkt0VQKYk1(A%Jo=G!f9iwGQ-l zu7`(5YHDgzQ&ZoxzV7+m6K74Fe=uP}O-)UDdU{Y$kfWm`eoq3O3k*)`0`$<0ii%pW zV8PlgYwK6kXD-cj>UR>a5NF6{fFRa9R_Q8f<91`ODPD1N<0_X_ZrrpHm!s(sx;Z&H zlTJ;F+8ot(sI7fhd-{@e%_dF8Y(}_?Aqs?4>hsi7cckvQu_w4Wn8A}lJ6*fIqa9E3rAOKYTA!bvAH5|S&AAXR%LJB{M^*ye z3Pc?XJ6v2`@H>|(g%@%me~6_Zb9Q!~a(D_>=h`l}&7GPHbgNpj8nDD5STfMVxj;v> zw6?S#Y!{j;gy!h>qwVtX@}d!<6Xr|+rt-n!T%bFGgM$~XU6i;jk*S{v?&!rw77K?7 zPgytxe=>l0gHCA|In03N+QNMcjTajOU97!8yKQ;fjAb+2-Q9_)e+B7L?qa$Fn3TJF zx;qYZbR6s0wSSkVrzbIPg@i7h(k`Zh0s;bN%$VWh<3prdY3p2INDK)8Ey$?Vz(Y2N zhKXT_IhVT4JcwyDEXamf=#Dz~2o1B^XxgP^=#HjcT88du+NEXaj;38&hVBp=F9iT& X2TgZfp!2!_0000<2SrXqu0mjfzERLtq!mDzg&9aThNK^#sAyl$AK(+>%D`{{DD?mT z{{uk4z_8)S+*Tl;G0EHAg(;1@CI!ghEbxddW?LUowx8d`)H8e5r|Ss9u^bR-BpxDM38;OXk; Jvd$@?2>>U2az6k7 diff --git a/setup/data/tools/bitmaps/window4.png b/setup/data/tools/bitmaps/window4.png index 891ca415ef532e887275adef080bd6bf71f4b17c..ac6df1c1c4ef84ee0ac5a8b2d7f9c45f4d00622a 100644 GIT binary patch delta 825 zcmV-91IGM=1L+1KiBL{Q4GJ0x0000DNk~Le0000w0000W2m$~A0L+y9f{`IVe+h6% zS#tmY3l0DP3l0H5zTrUt000_vMObuGZ)S9NVRB^vP+@6qbS_RsR3LUUE;TMOFfjCT zp#T5^xk*GpR9Hu2teSS8VF&@BbB7QD1*`-0Kwn?qxqho;Yjbgb5RBe`;#d)6;{3f*c(kv3e5XTp9uN(2a_UTCiZj+AVAA zSJY=N&2;K_60Z|g2bttr}p>v52SOQoSZhC-N4Yte*i&BbClw@ z#&;a<=-Abfv@l7fUIpk@i!O`Cm5mAs3R6~1adUGUNaq6WUa@k8=yXxIiy;igK1TI< z>Zv$HER5 z7Z+U4rC&kj?Cd<{@D!}hf3;n1n>#fZ=vK94HDHN>r(~d?bAgU%X>Dmg*e*0x2+h&$ zN89D&$RGcH8o{8Ovt4ySwA51?gJuV!8vEl)HPne>)CzbR6s0wSSkV zrzidzdw`t_aa=$^z>FC)e0+Qewk`&Ra|yZyff-i7BF3Y|N|LYMB&MM|&8Aq`8r$US{T zIv%*ROPO=&o^~m7f9_~v7*5p$az)V4@E?vKSq-_8_}{<)N06*WJAktiro_4b34wEG zuAMt|7Ov{j=`(nAoH%y;`t7?{&YuUW85rjRExvsACXl>z;S`YEvuzKMyn6HYm7}MD zjI)Q%U%PT0$T)WB1jHN5m#hSm7ml47LIb5xrvd;C0n8cy4`l delta 335 zcmaFK*37Kf8Q|y6%O%Cdz`(%k>ERLtq!mDzg&9aThNK^#sAyl$AK(+>%D`{{DD?mT z{{uk4z_8)S+*Tl;G0EHAg(;1@CI!ghEbxddW?!978nDPn~d^ zw?RRGMf0FLYuq}=F*39=w6HQX(l#)% zGB9}2dWsK4LvDUbW?Cg!gQ~89sji_#h@r8SiJ6t58AL~d(1Yth9SokXelF{r5}E*J C8gLQ-