2016-07-13 17:37:44 +00:00
import ClientCaches
import ClientConstants as CC
2018-01-17 22:52:10 +00:00
import ClientGUIMenus
2018-05-16 20:09:50 +00:00
import ClientGUIShortcuts
2016-07-13 17:37:44 +00:00
import HydrusConstants as HC
import HydrusData
2017-03-02 02:14:56 +00:00
import HydrusExceptions
2017-05-10 21:33:58 +00:00
import HydrusGlobals as HG
2016-07-13 17:37:44 +00:00
import os
import wx
2018-01-31 22:58:15 +00:00
( OKEvent , EVT_OK ) = wx . lib . newevent . NewCommandEvent ( )
2018-02-21 21:59:37 +00:00
CHILD_POSITION_PADDING = 24
2017-04-05 21:16:40 +00:00
FUZZY_PADDING = 15
2016-07-13 17:37:44 +00:00
2016-12-21 22:30:54 +00:00
def GetDisplayPosition ( window ) :
display_index = wx . Display . GetFromWindow ( window )
if display_index == wx . NOT_FOUND :
display_index = 0 # default to primary
display = wx . Display ( display_index )
rect = display . GetClientArea ( )
2018-01-03 22:37:30 +00:00
return tuple ( rect . GetPosition ( ) )
2016-12-21 22:30:54 +00:00
def GetDisplaySize ( window ) :
display_index = wx . Display . GetFromWindow ( window )
if display_index == wx . NOT_FOUND :
display_index = 0 # default to primary
display = wx . Display ( display_index )
rect = display . GetClientArea ( )
2018-01-03 22:37:30 +00:00
return tuple ( rect . GetSize ( ) )
2016-12-21 22:30:54 +00:00
2016-07-13 17:37:44 +00:00
def GetSafePosition ( position ) :
( p_x , p_y ) = position
# some window managers size the windows just off screen to cut off borders
# so choose a test position that's a little more lenient
( test_x , test_y ) = ( p_x + FUZZY_PADDING , p_y + FUZZY_PADDING )
display_index = wx . Display . GetFromPoint ( ( test_x , test_y ) )
if display_index == wx . NOT_FOUND :
return wx . DefaultPosition
else :
return position
def GetSafeSize ( tlw , min_size , gravity ) :
( min_width , min_height ) = min_size
parent = tlw . GetParent ( )
if parent is None :
width = min_width
height = min_height
else :
( parent_window_width , parent_window_height ) = parent . GetTopLevelParent ( ) . GetSize ( )
( width_gravity , height_gravity ) = gravity
if width_gravity == - 1 :
width = min_width
else :
2017-08-02 21:32:54 +00:00
max_width = parent_window_width - 2 * CHILD_POSITION_PADDING
2016-07-13 17:37:44 +00:00
width = int ( width_gravity * max_width )
if height_gravity == - 1 :
height = min_height
else :
2017-08-02 21:32:54 +00:00
max_height = parent_window_height - 2 * CHILD_POSITION_PADDING
2016-07-13 17:37:44 +00:00
height = int ( height_gravity * max_height )
2016-12-21 22:30:54 +00:00
( display_width , display_height ) = GetDisplaySize ( tlw )
2016-07-13 17:37:44 +00:00
width = min ( display_width , width )
height = min ( display_height , height )
return ( width , height )
def ExpandTLWIfPossible ( tlw , frame_key , desired_size_delta ) :
2017-12-06 22:06:56 +00:00
new_options = HG . client_controller . new_options
2016-07-13 17:37:44 +00:00
( remember_size , remember_position , last_size , last_position , default_gravity , default_position , maximised , fullscreen ) = new_options . GetFrameLocation ( frame_key )
if not tlw . IsMaximized ( ) and not tlw . IsFullScreen ( ) :
( current_width , current_height ) = tlw . GetSize ( )
( desired_delta_width , desired_delta_height ) = desired_size_delta
2016-12-21 22:30:54 +00:00
desired_width = current_width + desired_delta_width + FUZZY_PADDING
desired_height = current_height + desired_delta_height + FUZZY_PADDING
2016-07-13 17:37:44 +00:00
2016-12-21 22:30:54 +00:00
( width , height ) = GetSafeSize ( tlw , ( desired_width , desired_height ) , default_gravity )
2016-07-13 17:37:44 +00:00
if width > current_width or height > current_height :
tlw . SetSize ( ( width , height ) )
2016-12-21 22:30:54 +00:00
SlideOffScreenTLWUpAndLeft ( tlw )
2017-11-08 22:07:12 +00:00
2016-07-13 17:37:44 +00:00
2017-09-06 20:18:20 +00:00
def MouseIsOnMyDisplay ( window ) :
window_display_index = wx . Display . GetFromWindow ( window )
mouse_display_index = wx . Display . GetFromPoint ( wx . GetMousePosition ( ) )
return window_display_index == mouse_display_index
2017-05-24 20:28:24 +00:00
def PostSizeChangedEvent ( window ) :
event = CC . SizeChangedEvent ( - 1 )
2018-02-21 21:59:37 +00:00
wx . QueueEvent ( window . GetEventHandler ( ) , event )
2017-05-24 20:28:24 +00:00
2016-07-13 17:37:44 +00:00
def SaveTLWSizeAndPosition ( tlw , frame_key ) :
2017-12-06 22:06:56 +00:00
new_options = HG . client_controller . new_options
2016-07-13 17:37:44 +00:00
( remember_size , remember_position , last_size , last_position , default_gravity , default_position , maximised , fullscreen ) = new_options . GetFrameLocation ( frame_key )
maximised = tlw . IsMaximized ( )
fullscreen = tlw . IsFullScreen ( )
if not ( maximised or fullscreen ) :
2018-01-03 22:37:30 +00:00
safe_position = GetSafePosition ( tuple ( tlw . GetPosition ( ) ) )
2016-07-13 17:37:44 +00:00
if safe_position != wx . DefaultPosition :
2018-01-03 22:37:30 +00:00
last_size = tuple ( tlw . GetSize ( ) )
2016-07-13 17:37:44 +00:00
last_position = safe_position
new_options . SetFrameLocation ( frame_key , remember_size , remember_position , last_size , last_position , default_gravity , default_position , maximised , fullscreen )
2018-02-14 21:47:18 +00:00
def SetInitialTLWSizeAndPosition ( tlw , frame_key ) :
2016-07-13 17:37:44 +00:00
2017-12-06 22:06:56 +00:00
new_options = HG . client_controller . new_options
2016-07-13 17:37:44 +00:00
( remember_size , remember_position , last_size , last_position , default_gravity , default_position , maximised , fullscreen ) = new_options . GetFrameLocation ( frame_key )
parent = tlw . GetParent ( )
if remember_size and last_size is not None :
( width , height ) = last_size
else :
( min_width , min_height ) = tlw . GetEffectiveMinSize ( )
min_width + = FUZZY_PADDING
min_height + = FUZZY_PADDING
( width , height ) = GetSafeSize ( tlw , ( min_width , min_height ) , default_gravity )
tlw . SetInitialSize ( ( width , height ) )
min_width = min ( 240 , width )
min_height = min ( 240 , height )
tlw . SetMinSize ( ( min_width , min_height ) )
#
if remember_position and last_position is not None :
safe_position = GetSafePosition ( last_position )
tlw . SetPosition ( safe_position )
elif default_position == ' topleft ' :
if parent is not None :
if isinstance ( parent , wx . TopLevelWindow ) :
parent_tlp = parent
else :
parent_tlp = parent . GetTopLevelParent ( )
2018-01-03 22:37:30 +00:00
( parent_x , parent_y ) = parent_tlp . GetPosition ( )
2016-07-13 17:37:44 +00:00
tlw . SetPosition ( ( parent_x + CHILD_POSITION_PADDING , parent_y + CHILD_POSITION_PADDING ) )
else :
safe_position = GetSafePosition ( ( 0 + CHILD_POSITION_PADDING , 0 + CHILD_POSITION_PADDING ) )
tlw . SetPosition ( safe_position )
2017-11-08 22:07:12 +00:00
SlideOffScreenTLWUpAndLeft ( tlw )
2016-07-13 17:37:44 +00:00
elif default_position == ' center ' :
wx . CallAfter ( tlw . Center )
# if these aren't callafter, the size and pos calls don't stick if a restore event happens
if maximised :
wx . CallAfter ( tlw . Maximize )
if fullscreen :
wx . CallAfter ( tlw . ShowFullScreen , True , wx . FULLSCREEN_ALL )
2016-12-21 22:30:54 +00:00
def SlideOffScreenTLWUpAndLeft ( tlw ) :
( tlw_width , tlw_height ) = tlw . GetSize ( )
( tlw_x , tlw_y ) = tlw . GetPosition ( )
tlw_right = tlw_x + tlw_width
tlw_bottom = tlw_y + tlw_height
( display_width , display_height ) = GetDisplaySize ( tlw )
( display_x , display_y ) = GetDisplayPosition ( tlw )
display_right = display_x + display_width
display_bottom = display_y + display_height
move_x = tlw_right > display_right
move_y = tlw_bottom > display_bottom
if move_x or move_y :
delta_x = min ( display_right - tlw_right , 0 )
delta_y = min ( display_bottom - tlw_bottom , 0 )
tlw . SetPosition ( ( tlw_x + delta_x , tlw_y + delta_y ) )
2016-07-13 17:37:44 +00:00
class NewDialog ( wx . Dialog ) :
2017-08-02 21:32:54 +00:00
def __init__ ( self , parent , title , style_override = None ) :
2016-07-13 17:37:44 +00:00
2017-08-02 21:32:54 +00:00
if style_override is None :
style = wx . DEFAULT_DIALOG_STYLE | wx . RESIZE_BORDER
if not HC . PLATFORM_LINUX and parent is not None :
style | = wx . FRAME_FLOAT_ON_PARENT
else :
2016-07-13 17:37:44 +00:00
2017-08-02 21:32:54 +00:00
style = style_override
2016-07-13 17:37:44 +00:00
wx . Dialog . __init__ ( self , parent , title = title , style = style )
2017-12-06 22:06:56 +00:00
self . _new_options = HG . client_controller . new_options
2016-07-13 17:37:44 +00:00
2016-08-10 19:04:08 +00:00
self . SetBackgroundColour ( wx . SystemSettings . GetColour ( wx . SYS_COLOUR_FRAMEBK ) )
2016-07-13 17:37:44 +00:00
2017-11-15 22:35:49 +00:00
self . SetIcon ( HG . client_controller . frame_icon )
2016-07-13 17:37:44 +00:00
self . Bind ( wx . EVT_BUTTON , self . EventDialogButton )
2017-01-25 22:56:55 +00:00
self . Bind ( wx . EVT_MENU_CLOSE , self . EventMenuClose )
self . Bind ( wx . EVT_MENU_HIGHLIGHT_ALL , self . EventMenuHighlight )
self . Bind ( wx . EVT_MENU_OPEN , self . EventMenuOpen )
self . _menu_stack = [ ]
self . _menu_text_stack = [ ]
2017-05-10 21:33:58 +00:00
HG . client_controller . ResetIdleTimer ( )
2016-07-13 17:37:44 +00:00
2017-10-18 19:41:25 +00:00
def _CanCancel ( self ) :
return True
2017-01-25 22:56:55 +00:00
def EventMenuClose ( self , event ) :
menu = event . GetMenu ( )
if menu is not None and menu in self . _menu_stack :
index = self . _menu_stack . index ( menu )
del self . _menu_stack [ index ]
previous_text = self . _menu_text_stack . pop ( )
2017-05-10 21:33:58 +00:00
status_bar = HG . client_controller . GetGUI ( ) . GetStatusBar ( )
2017-01-25 22:56:55 +00:00
status_bar . SetStatusText ( previous_text )
def EventMenuHighlight ( self , event ) :
if len ( self . _menu_stack ) > 0 :
text = ' '
menu = self . _menu_stack [ - 1 ]
2018-01-17 22:52:10 +00:00
while ClientGUIMenus . MenuIsDead ( menu ) :
2018-01-10 22:41:51 +00:00
2018-01-17 22:52:10 +00:00
if len ( self . _menu_stack ) == 0 :
return
2018-01-10 22:41:51 +00:00
2018-01-17 22:52:10 +00:00
del self . _menu_stack [ - 1 ]
2017-01-25 22:56:55 +00:00
2018-01-17 22:52:10 +00:00
menu = self . _menu_stack [ - 1 ]
2017-01-25 22:56:55 +00:00
2018-01-17 22:52:10 +00:00
menu_item = menu . FindItemById ( event . GetMenuId ( ) )
if menu_item is not None :
text = menu_item . GetHelp ( )
2017-01-25 22:56:55 +00:00
2018-01-10 22:41:51 +00:00
status_bar = HG . client_controller . GetGUI ( ) . GetStatusBar ( )
2017-01-25 22:56:55 +00:00
status_bar . SetStatusText ( text )
def EventMenuOpen ( self , event ) :
menu = event . GetMenu ( )
if menu is not None :
2017-05-10 21:33:58 +00:00
status_bar = HG . client_controller . GetGUI ( ) . GetStatusBar ( )
2017-01-25 22:56:55 +00:00
previous_text = status_bar . GetStatusText ( )
self . _menu_stack . append ( menu )
self . _menu_text_stack . append ( previous_text )
2017-04-05 21:16:40 +00:00
def EventDialogButton ( self , event ) :
2017-10-18 19:41:25 +00:00
event_id = event . GetId ( )
if event_id == wx . ID_CANCEL :
if not self . _CanCancel ( ) :
return
2018-04-11 22:30:40 +00:00
if not self . IsModal ( ) : # in some rare cases (including spammy AutoHotkey, looks like), this can be fired before the dialog can clean itself up
return
2017-10-18 19:41:25 +00:00
self . EndModal ( event_id )
2017-04-05 21:16:40 +00:00
2016-07-13 17:37:44 +00:00
class DialogThatResizes ( NewDialog ) :
2017-08-02 21:32:54 +00:00
def __init__ ( self , parent , title , frame_key , style_override = None ) :
2016-07-13 17:37:44 +00:00
self . _frame_key = frame_key
2017-08-02 21:32:54 +00:00
NewDialog . __init__ ( self , parent , title , style_override = style_override )
2016-07-13 17:37:44 +00:00
class DialogThatTakesScrollablePanel ( DialogThatResizes ) :
2017-08-02 21:32:54 +00:00
def __init__ ( self , parent , title , frame_key = ' regular_dialog ' , style_override = None ) :
2016-07-13 17:37:44 +00:00
self . _panel = None
2017-08-02 21:32:54 +00:00
DialogThatResizes . __init__ ( self , parent , title , frame_key , style_override = style_override )
2016-07-13 17:37:44 +00:00
2016-11-16 20:21:43 +00:00
self . _InitialiseButtons ( )
2016-07-13 17:37:44 +00:00
2018-01-31 22:58:15 +00:00
self . Bind ( EVT_OK , self . EventOK )
2016-07-13 17:37:44 +00:00
self . Bind ( CC . EVT_SIZE_CHANGED , self . EventChildSizeChanged )
2017-10-18 19:41:25 +00:00
def _CanCancel ( self ) :
return self . _panel . CanCancel ( )
2016-11-16 20:21:43 +00:00
def _GetButtonBox ( self ) :
raise NotImplementedError ( )
def _InitialiseButtons ( self ) :
raise NotImplementedError ( )
2018-11-07 23:09:40 +00:00
def _TryEndModal ( self , value ) :
try :
self . EndModal ( value )
except Exception as e :
HydrusData . ShowText ( ' This dialog seems to have been unable to close for some reason. I am printing the stack to the log. The dialog may have already closed, or may attempt to close now. Please inform hydrus dev of this situation. I recommend you restart the client if you can. If the UI is locked, you will have to kill it via task manager. ' )
HydrusData . PrintException ( e )
import traceback
HydrusData . DebugPrint ( ' ' . join ( traceback . format_stack ( ) ) )
try :
self . Close ( )
except :
HydrusData . ShowText ( ' The dialog would not close on command. ' )
try :
self . Destroy ( )
except :
HydrusData . ShowText ( ' The dialog would not destroy on command. ' )
2017-06-21 21:15:59 +00:00
def DoOK ( self ) :
raise NotImplementedError ( )
2016-07-13 17:37:44 +00:00
def EventChildSizeChanged ( self , event ) :
if self . _panel is not None :
# the min size here is to compensate for wx.Notebook and anything else that don't update virtualsize on page change
( current_panel_width , current_panel_height ) = self . _panel . GetSize ( )
( desired_panel_width , desired_panel_height ) = self . _panel . GetVirtualSize ( )
( min_panel_width , min_panel_height ) = self . _panel . GetEffectiveMinSize ( )
desired_delta_width = max ( 0 , desired_panel_width - current_panel_width , min_panel_width - current_panel_width )
desired_delta_height = max ( 0 , desired_panel_height - current_panel_height , min_panel_height - current_panel_height )
if desired_delta_width > 0 or desired_delta_height > 0 :
ExpandTLWIfPossible ( self , self . _frame_key , ( desired_delta_width , desired_delta_height ) )
2017-06-07 22:05:15 +00:00
def EventOK ( self , event ) :
2016-07-13 17:37:44 +00:00
2018-05-30 20:13:21 +00:00
if not self :
return
2017-06-21 21:15:59 +00:00
self . DoOK ( )
2016-07-13 17:37:44 +00:00
def SetPanel ( self , panel ) :
self . _panel = panel
2016-11-16 20:21:43 +00:00
buttonbox = self . _GetButtonBox ( )
2016-07-13 17:37:44 +00:00
vbox = wx . BoxSizer ( wx . VERTICAL )
2018-01-03 22:37:30 +00:00
vbox . Add ( self . _panel , CC . FLAGS_EXPAND_BOTH_WAYS )
vbox . Add ( buttonbox , CC . FLAGS_BUTTON_SIZER )
2016-07-13 17:37:44 +00:00
self . SetSizer ( vbox )
2018-02-14 21:47:18 +00:00
SetInitialTLWSizeAndPosition ( self , self . _frame_key )
2016-07-13 17:37:44 +00:00
2018-08-01 20:44:57 +00:00
self . _panel . SetupScrolling ( scrollIntoView = False ) # this changes geteffectiveminsize calc, so it needs to be below settlwsizeandpos
2017-08-02 21:32:54 +00:00
2018-08-01 20:44:57 +00:00
PostSizeChangedEvent ( self ) # helps deal with some Linux/otherscrollbar weirdness where setupscrolling changes inherent virtual size
2016-07-13 17:37:44 +00:00
2016-11-16 20:21:43 +00:00
class DialogThatTakesScrollablePanelClose ( DialogThatTakesScrollablePanel ) :
def _GetButtonBox ( self ) :
buttonbox = wx . BoxSizer ( wx . HORIZONTAL )
2018-01-03 22:37:30 +00:00
buttonbox . Add ( self . _close , CC . FLAGS_VCENTER )
2016-11-16 20:21:43 +00:00
return buttonbox
def _InitialiseButtons ( self ) :
self . _close = wx . Button ( self , id = wx . ID_OK , label = ' close ' )
2017-06-07 22:05:15 +00:00
self . _close . Bind ( wx . EVT_BUTTON , self . EventOK )
2016-11-16 20:21:43 +00:00
self . _cancel = wx . Button ( self , id = wx . ID_CANCEL )
self . _cancel . Hide ( )
class DialogNullipotent ( DialogThatTakesScrollablePanelClose ) :
def __init__ ( self , parent , title ) :
2017-04-19 20:58:30 +00:00
DialogThatTakesScrollablePanelClose . __init__ ( self , parent , title )
2016-11-16 20:21:43 +00:00
2017-06-21 21:15:59 +00:00
def DoOK ( self ) :
2016-11-16 20:21:43 +00:00
2017-12-20 22:55:48 +00:00
if not self . IsModal ( ) :
return
2016-11-16 20:21:43 +00:00
SaveTLWSizeAndPosition ( self , self . _frame_key )
2018-11-07 23:09:40 +00:00
self . _TryEndModal ( wx . ID_OK )
2016-11-16 20:21:43 +00:00
2017-07-27 00:47:13 +00:00
class DialogNullipotentVetoable ( DialogThatTakesScrollablePanelClose ) :
2018-02-21 21:59:37 +00:00
def __init__ ( self , parent , title , style_override = None , hide_close_button = False ) :
2017-07-27 00:47:13 +00:00
2017-08-02 21:32:54 +00:00
DialogThatTakesScrollablePanelClose . __init__ ( self , parent , title , style_override = style_override )
2018-02-21 21:59:37 +00:00
if hide_close_button :
self . _close . Hide ( )
self . Bind ( wx . EVT_CLOSE , self . EventOK ) # the close event no longer goes to the default button, since it is hidden, wew
2017-07-27 00:47:13 +00:00
def DoOK ( self ) :
2017-12-20 22:55:48 +00:00
if not self . IsModal ( ) :
2017-08-02 21:32:54 +00:00
return
2017-07-27 00:47:13 +00:00
try :
self . _panel . TryToClose ( )
2017-12-13 22:33:07 +00:00
except HydrusExceptions . VetoException as e :
2018-03-14 21:01:02 +00:00
message = HydrusData . ToUnicode ( e )
2017-12-13 22:33:07 +00:00
if len ( message ) > 0 :
wx . MessageBox ( message )
2017-07-27 00:47:13 +00:00
return
SaveTLWSizeAndPosition ( self , self . _frame_key )
2018-11-07 23:09:40 +00:00
self . _TryEndModal ( wx . ID_OK )
2017-07-27 00:47:13 +00:00
2016-11-16 20:21:43 +00:00
class DialogThatTakesScrollablePanelApplyCancel ( DialogThatTakesScrollablePanel ) :
def _GetButtonBox ( self ) :
buttonbox = wx . BoxSizer ( wx . HORIZONTAL )
2018-01-03 22:37:30 +00:00
buttonbox . Add ( self . _apply , CC . FLAGS_VCENTER )
buttonbox . Add ( self . _cancel , CC . FLAGS_VCENTER )
2016-11-16 20:21:43 +00:00
return buttonbox
def _InitialiseButtons ( self ) :
self . _apply = wx . Button ( self , id = wx . ID_OK , label = ' apply ' )
2017-06-07 22:05:15 +00:00
self . _apply . Bind ( wx . EVT_BUTTON , self . EventOK )
2016-11-16 20:21:43 +00:00
self . _apply . SetForegroundColour ( ( 0 , 128 , 0 ) )
self . _cancel = wx . Button ( self , id = wx . ID_CANCEL , label = ' cancel ' )
self . _cancel . SetForegroundColour ( ( 128 , 0 , 0 ) )
class DialogEdit ( DialogThatTakesScrollablePanelApplyCancel ) :
2016-07-13 17:37:44 +00:00
2017-11-22 21:03:07 +00:00
def __init__ ( self , parent , title , frame_key = ' regular_dialog ' ) :
2016-07-13 17:37:44 +00:00
2017-11-22 21:03:07 +00:00
DialogThatTakesScrollablePanelApplyCancel . __init__ ( self , parent , title , frame_key = frame_key )
2016-07-13 17:37:44 +00:00
2017-06-21 21:15:59 +00:00
def DoOK ( self ) :
2016-07-13 17:37:44 +00:00
2017-12-20 22:55:48 +00:00
if not self . IsModal ( ) :
return
2017-03-02 02:14:56 +00:00
try :
value = self . _panel . GetValue ( )
2017-12-13 22:33:07 +00:00
except HydrusExceptions . VetoException as e :
2018-03-14 21:01:02 +00:00
message = HydrusData . ToUnicode ( e )
2017-12-13 22:33:07 +00:00
if len ( message ) > 0 :
wx . MessageBox ( message )
2017-03-02 02:14:56 +00:00
return
2016-07-13 17:37:44 +00:00
SaveTLWSizeAndPosition ( self , self . _frame_key )
2018-11-07 23:09:40 +00:00
self . _TryEndModal ( wx . ID_OK )
2016-07-13 17:37:44 +00:00
2016-11-16 20:21:43 +00:00
class DialogManage ( DialogThatTakesScrollablePanelApplyCancel ) :
2016-07-13 17:37:44 +00:00
2017-06-21 21:15:59 +00:00
def DoOK ( self ) :
2016-07-13 17:37:44 +00:00
2017-12-20 22:55:48 +00:00
if not self . IsModal ( ) :
return
2017-04-05 21:16:40 +00:00
try :
self . _panel . CommitChanges ( )
2017-12-13 22:33:07 +00:00
except HydrusExceptions . VetoException as e :
2018-03-14 21:01:02 +00:00
message = HydrusData . ToUnicode ( e )
2017-12-13 22:33:07 +00:00
if len ( message ) > 0 :
wx . MessageBox ( message )
2017-04-05 21:16:40 +00:00
return
2016-07-13 17:37:44 +00:00
SaveTLWSizeAndPosition ( self , self . _frame_key )
2018-11-07 23:09:40 +00:00
self . _TryEndModal ( wx . ID_OK )
2016-07-13 17:37:44 +00:00
class Frame ( wx . Frame ) :
def __init__ ( self , parent , title , float_on_parent = True ) :
style = wx . DEFAULT_FRAME_STYLE
if float_on_parent :
style | = wx . FRAME_FLOAT_ON_PARENT
wx . Frame . __init__ ( self , parent , title = title , style = style )
2017-12-06 22:06:56 +00:00
self . _new_options = HG . client_controller . new_options
2016-07-13 17:37:44 +00:00
2016-08-10 19:04:08 +00:00
self . SetBackgroundColour ( wx . SystemSettings . GetColour ( wx . SYS_COLOUR_FRAMEBK ) )
2016-07-13 17:37:44 +00:00
2017-11-15 22:35:49 +00:00
self . SetIcon ( HG . client_controller . frame_icon )
2016-07-13 17:37:44 +00:00
2017-01-25 22:56:55 +00:00
self . Bind ( wx . EVT_MENU_CLOSE , self . EventMenuClose )
self . Bind ( wx . EVT_MENU_HIGHLIGHT_ALL , self . EventMenuHighlight )
self . Bind ( wx . EVT_MENU_OPEN , self . EventMenuOpen )
self . _menu_stack = [ ]
self . _menu_text_stack = [ ]
2017-05-10 21:33:58 +00:00
HG . client_controller . ResetIdleTimer ( )
2016-07-13 17:37:44 +00:00
2017-01-25 22:56:55 +00:00
def EventMenuClose ( self , event ) :
menu = event . GetMenu ( )
if menu is not None and menu in self . _menu_stack :
index = self . _menu_stack . index ( menu )
del self . _menu_stack [ index ]
previous_text = self . _menu_text_stack . pop ( )
2017-05-10 21:33:58 +00:00
status_bar = HG . client_controller . GetGUI ( ) . GetStatusBar ( )
2017-01-25 22:56:55 +00:00
status_bar . SetStatusText ( previous_text )
def EventMenuHighlight ( self , event ) :
if len ( self . _menu_stack ) > 0 :
text = ' '
menu = self . _menu_stack [ - 1 ]
2018-01-17 22:52:10 +00:00
while ClientGUIMenus . MenuIsDead ( menu ) :
2018-01-10 22:41:51 +00:00
2018-01-17 22:52:10 +00:00
del self . _menu_stack [ - 1 ]
2017-01-25 22:56:55 +00:00
2018-01-17 22:52:10 +00:00
if len ( self . _menu_stack ) == 0 :
2017-01-25 22:56:55 +00:00
2018-01-17 22:52:10 +00:00
return
2017-01-25 22:56:55 +00:00
2018-01-17 22:52:10 +00:00
menu = self . _menu_stack [ - 1 ]
menu_item = menu . FindItemById ( event . GetMenuId ( ) )
if menu_item is not None :
text = menu_item . GetHelp ( )
2017-01-25 22:56:55 +00:00
2018-01-10 22:41:51 +00:00
status_bar = HG . client_controller . GetGUI ( ) . GetStatusBar ( )
2017-01-25 22:56:55 +00:00
status_bar . SetStatusText ( text )
def EventMenuOpen ( self , event ) :
menu = event . GetMenu ( )
if menu is not None :
2017-05-10 21:33:58 +00:00
status_bar = HG . client_controller . GetGUI ( ) . GetStatusBar ( )
2017-01-25 22:56:55 +00:00
previous_text = status_bar . GetStatusText ( )
self . _menu_stack . append ( menu )
self . _menu_text_stack . append ( previous_text )
2016-07-13 17:37:44 +00:00
class FrameThatResizes ( Frame ) :
def __init__ ( self , parent , title , frame_key , float_on_parent = True ) :
self . _frame_key = frame_key
Frame . __init__ ( self , parent , title , float_on_parent )
self . Bind ( wx . EVT_SIZE , self . EventSizeAndPositionChanged )
self . Bind ( wx . EVT_MOVE_END , self . EventSizeAndPositionChanged )
self . Bind ( wx . EVT_CLOSE , self . EventSizeAndPositionChanged )
self . Bind ( wx . EVT_MAXIMIZE , self . EventSizeAndPositionChanged )
def EventSizeAndPositionChanged ( self , event ) :
SaveTLWSizeAndPosition ( self , self . _frame_key )
event . Skip ( )
class FrameThatTakesScrollablePanel ( FrameThatResizes ) :
2017-07-12 20:03:45 +00:00
def __init__ ( self , parent , title , frame_key = ' regular_dialog ' , float_on_parent = True ) :
2016-07-13 17:37:44 +00:00
self . _panel = None
FrameThatResizes . __init__ ( self , parent , title , frame_key , float_on_parent )
2016-07-27 21:53:34 +00:00
self . _ok = wx . Button ( self , id = wx . ID_OK , label = ' close ' )
2018-01-31 22:58:15 +00:00
self . _ok . Bind ( wx . EVT_BUTTON , self . EventClose )
2016-07-13 17:37:44 +00:00
2018-01-31 22:58:15 +00:00
self . Bind ( EVT_OK , self . EventClose )
2016-07-13 17:37:44 +00:00
self . Bind ( CC . EVT_SIZE_CHANGED , self . EventChildSizeChanged )
2016-11-30 20:24:17 +00:00
self . Bind ( wx . EVT_CHAR_HOOK , self . EventCharHook )
def EventCharHook ( self , event ) :
2018-05-16 20:09:50 +00:00
( modifier , key ) = ClientGUIShortcuts . ConvertKeyEventToSimpleTuple ( event )
2017-04-05 21:16:40 +00:00
if key == wx . WXK_ESCAPE :
2016-11-30 20:24:17 +00:00
self . Close ( )
2016-12-07 22:12:52 +00:00
else :
event . Skip ( )
2016-11-30 20:24:17 +00:00
2016-07-13 17:37:44 +00:00
2018-01-31 22:58:15 +00:00
def EventClose ( self , event ) :
2016-07-13 17:37:44 +00:00
self . Close ( )
def EventChildSizeChanged ( self , event ) :
if self . _panel is not None :
# the min size here is to compensate for wx.Notebook and anything else that don't update virtualsize on page change
( current_panel_width , current_panel_height ) = self . _panel . GetSize ( )
( desired_panel_width , desired_panel_height ) = self . _panel . GetVirtualSize ( )
( min_panel_width , min_panel_height ) = self . _panel . GetEffectiveMinSize ( )
desired_delta_width = max ( 0 , desired_panel_width - current_panel_width , min_panel_width - current_panel_width )
desired_delta_height = max ( 0 , desired_panel_height - current_panel_height , min_panel_height - current_panel_height )
if desired_delta_width > 0 or desired_delta_height > 0 :
ExpandTLWIfPossible ( self , self . _frame_key , ( desired_delta_width , desired_delta_height ) )
def SetPanel ( self , panel ) :
self . _panel = panel
vbox = wx . BoxSizer ( wx . VERTICAL )
2018-01-03 22:37:30 +00:00
vbox . Add ( self . _panel , CC . FLAGS_EXPAND_BOTH_WAYS )
vbox . Add ( self . _ok , CC . FLAGS_LONE_BUTTON )
2016-07-13 17:37:44 +00:00
self . SetSizer ( vbox )
2018-02-14 21:47:18 +00:00
SetInitialTLWSizeAndPosition ( self , self . _frame_key )
2016-07-13 17:37:44 +00:00
self . Show ( True )
2018-08-01 20:44:57 +00:00
self . _panel . SetupScrolling ( scrollIntoView = False ) # this changes geteffectiveminsize calc, so it needs to be below settlwsizeandpos
2016-07-13 17:37:44 +00:00
2018-08-01 20:44:57 +00:00
PostSizeChangedEvent ( self ) # helps deal with some Linux/otherscrollbar weirdness where setupscrolling changes inherent virtual size
2018-02-14 21:47:18 +00:00
2016-12-07 22:12:52 +00:00