hydrus/include/ClientGUIMenus.py

177 lines
4.5 KiB
Python
Raw Normal View History

2016-11-02 21:09:14 +00:00
import collections
2018-01-03 22:37:30 +00:00
import HydrusData
2017-05-10 21:33:58 +00:00
import HydrusGlobals as HG
2018-02-21 21:59:37 +00:00
import os
2016-11-02 21:09:14 +00:00
import wx
menus_to_submenus = collections.defaultdict( set )
menus_to_menu_item_data = collections.defaultdict( set )
def AppendMenu( menu, submenu, label ):
2016-12-28 22:24:52 +00:00
label = SanitiseLabel( label )
2016-11-16 20:21:43 +00:00
2018-01-03 22:37:30 +00:00
menu.AppendSubMenu( submenu, label )
2016-11-02 21:09:14 +00:00
menus_to_submenus[ menu ].add( submenu )
2017-01-25 22:56:55 +00:00
def AppendMenuBitmapItem( event_handler, menu, label, description, bitmap, callable, *args, **kwargs ):
2016-11-02 21:09:14 +00:00
2016-12-28 22:24:52 +00:00
label = SanitiseLabel( label )
2016-11-16 20:21:43 +00:00
2016-12-28 22:24:52 +00:00
menu_item = wx.MenuItem( menu, wx.ID_ANY, label )
2016-11-02 21:09:14 +00:00
2016-12-28 22:24:52 +00:00
menu_item.SetHelp( description )
2016-11-02 21:09:14 +00:00
2016-12-28 22:24:52 +00:00
menu_item.SetBitmap( bitmap )
2016-11-02 21:09:14 +00:00
2018-01-03 22:37:30 +00:00
menu.Append( menu_item )
2016-12-28 22:24:52 +00:00
2017-01-25 22:56:55 +00:00
BindMenuItem( event_handler, menu, menu_item, callable, *args, **kwargs )
2016-11-02 21:09:14 +00:00
return menu_item
2017-01-25 22:56:55 +00:00
def AppendMenuCheckItem( event_handler, menu, label, description, initial_value, callable, *args, **kwargs ):
2016-11-02 21:09:14 +00:00
2016-12-28 22:24:52 +00:00
label = SanitiseLabel( label )
2016-11-02 21:09:14 +00:00
2016-12-28 22:24:52 +00:00
menu_item = menu.AppendCheckItem( wx.ID_ANY, label, description )
menu_item.Check( initial_value )
2017-01-25 22:56:55 +00:00
BindMenuItem( event_handler, menu, menu_item, callable, *args, **kwargs )
2016-12-28 22:24:52 +00:00
return menu_item
2017-01-25 22:56:55 +00:00
def AppendMenuItem( event_handler, menu, label, description, callable, *args, **kwargs ):
2016-12-28 22:24:52 +00:00
label = SanitiseLabel( label )
menu_item = menu.Append( wx.ID_ANY, label, description )
2017-01-25 22:56:55 +00:00
BindMenuItem( event_handler, menu, menu_item, callable, *args, **kwargs )
2016-12-28 22:24:52 +00:00
return menu_item
2017-01-04 22:48:23 +00:00
def AppendMenuLabel( menu, label, description = None ):
if description is None:
description = ''
menu_item = menu.Append( wx.ID_ANY, label, description )
return menu_item
2017-03-15 20:13:04 +00:00
def AppendSeparator( menu ):
num_items = menu.GetMenuItemCount()
if num_items > 0:
last_item = menu.FindItemByPosition( num_items - 1 )
if not last_item.IsSeparator():
menu.AppendSeparator()
2017-01-25 22:56:55 +00:00
def BindMenuItem( event_handler, menu, menu_item, callable, *args, **kwargs ):
2016-12-28 22:24:52 +00:00
2017-03-08 23:23:12 +00:00
event_callable = GetEventCallable( callable, *args, **kwargs )
2016-12-28 22:24:52 +00:00
2017-03-08 23:23:12 +00:00
event_handler.Bind( wx.EVT_MENU, event_callable, source = menu_item )
2016-12-28 22:24:52 +00:00
menus_to_menu_item_data[ menu ].add( ( menu_item, event_handler ) )
2016-11-02 21:09:14 +00:00
2018-01-17 22:52:10 +00:00
def CreateMenu():
menu = wx.Menu()
return menu
2018-01-03 22:37:30 +00:00
def UnbindMenuItems( menu ):
2017-01-25 22:56:55 +00:00
2016-11-02 21:09:14 +00:00
menu_item_data = menus_to_menu_item_data[ menu ]
del menus_to_menu_item_data[ menu ]
for ( menu_item, event_handler ) in menu_item_data:
2018-02-21 21:59:37 +00:00
if not event_handler: # under some circumstances, this has been deleted before the menu was
continue
2016-11-02 21:09:14 +00:00
event_handler.Unbind( wx.EVT_MENU, source = menu_item )
2018-01-17 22:52:10 +00:00
if menu in menus_to_submenus:
submenus = menus_to_submenus[ menu ]
for submenu in submenus:
UnbindMenuItems( submenu )
submenu.is_dead = True
2016-11-02 21:09:14 +00:00
2018-01-17 22:52:10 +00:00
del menus_to_submenus[ menu ]
2016-11-02 21:09:14 +00:00
2018-02-21 21:59:37 +00:00
def DestroyMenu( window, menu ):
2016-11-02 21:09:14 +00:00
2018-01-03 22:37:30 +00:00
UnbindMenuItems( menu )
2016-11-02 21:09:14 +00:00
2018-01-17 22:52:10 +00:00
menu.is_dead = True
2018-02-21 21:59:37 +00:00
# if the window we just popupmenu'd on is dead now (i.e. it died while the menu was open), destroying the menu will cause a crash and letting the event continue will cause a crash
if not window:
message = 'A window just died before its menu could be safely destroyed! If an exception were not raised here, the program would crash! If you know you did something tricky, please avoid this in future. If you think you did something normal, please let hydrus dev know.'
raise Exception( message )
2016-11-02 21:09:14 +00:00
menu.Destroy()
2016-12-28 22:24:52 +00:00
2017-03-08 23:23:12 +00:00
def GetEventCallable( callable, *args, **kwargs ):
2016-12-28 22:24:52 +00:00
2017-03-08 23:23:12 +00:00
def event_callable( event ):
2018-01-03 22:37:30 +00:00
if HG.menu_profile_mode:
summary = 'Profiling menu: ' + repr( callable )
HydrusData.ShowText( summary )
HydrusData.Profile( summary, 'callable( *args, **kwargs )', globals(), locals() )
else:
callable( *args, **kwargs )
2017-03-08 23:23:12 +00:00
2016-12-28 22:24:52 +00:00
2017-03-08 23:23:12 +00:00
return event_callable
2016-12-28 22:24:52 +00:00
2018-01-17 22:52:10 +00:00
def MenuIsDead( menu ):
# doing 'if menu' doesn't work for the deadobject test, wew
return hasattr( menu, 'is_dead' )
2016-12-28 22:24:52 +00:00
def SanitiseLabel( label ):
2017-11-01 20:37:39 +00:00
if label == '':
label = '-invalid label-'
2016-12-28 22:24:52 +00:00
return label.replace( '&', '&&' )