Path: blob/main/tools/contributed/sumopy/agilepy/lib_wx/wxmisc.py
169689 views
# Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo1# Copyright (C) 2016-2025 German Aerospace Center (DLR) and others.2# SUMOPy module3# Copyright (C) 2012-2021 University of Bologna - DICAM4# This program and the accompanying materials are made available under the5# terms of the Eclipse Public License 2.0 which is available at6# https://www.eclipse.org/legal/epl-2.0/7# This Source Code may also be made available under the following Secondary8# Licenses when the conditions for such availability set forth in the Eclipse9# Public License 2.0 are satisfied: GNU General Public License, version 210# or later which is available at11# https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html12# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later1314# @file wxmisc.py15# @author Joerg Schweizer16# @date 2012171819import zlib20import cPickle21import sys22import os23import types24#AGILEDIR = os.path.join(os.path.dirname(__file__),"..")25# sys.path.append(os.path.join(AGILEDIR,"lib_base"))26#IMAGEDIR = os.path.join(os.path.dirname(__file__),"images")272829import wx3031import time32import string3334# def OnOpen(self,e):35## """ Open a file"""36## self.dirname = ''37## dlg = wx.FileDialog(self, "Choose a file", self.dirname, "", "*.*", wx.OPEN)38# if dlg.ShowModal() == wx.ID_OK:39## self.filename = dlg.GetFilename()40## self.dirname = dlg.GetDirectory()41## f = open(os.path.join(self.dirname, self.filename), 'r')42# self.control.SetValue(f.read())43# f.close()44# dlg.Destroy()4546# alternating colors in tables "light blue" 'WHEAT'47#TABLECOLORS=[wx.NamedColour('grey85'),wx.NamedColour("light blue")]484950def get_tablecolors():51cs = [wx.NamedColour('grey85'), wx.NamedColour("light blue")]52# cs = [wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOW ) ,\53# wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNHIGHLIGHT)]54# print 'resources.get_tablecolors',cs55return cs565758class AgileToolbarMixin:59"""60Easy to use toolbar where strings can be used to identify tools.61Mixin for frames.62"""6364def init_toolbar(self, orientation='horizontal', size=(16, 16), separation=5):65"""66This initialization works for panels and windows.67For frames use the AgileToolbar frames mixin class68"""69if orientation == 'horizontal':70self.toolbar = wx.ToolBar(self, -1, style=wx.TB_HORIZONTAL | wx.TB_NODIVIDER71| wx.NO_BORDER72| wx.TB_FLAT73| wx.TB_TEXT74)75else:76self.toolbar = wx.ToolBar(self, -1, style=wx.TB_VERTICAL | wx.TB_NODIVIDER77| wx.NO_BORDER78| wx.TB_FLAT79| wx.TB_TEXT80)8182self.toolbar.SetToolBitmapSize(size)83self.toolbar.SetToolSeparation(separation)8485self._tools = {}86self.toolbar.Realize()87S = self.toolbar.GetSize()88self.toolbar.SetSizeHints(S[0], S[1])8990def get_size_toolbaricons(self):91"""92Returns tuple with width and height of toolbar icons.93This is required to create them.94"""95return self.toolbar.GetToolBitmapSize()9697def disable_tools(self):98pass99# GetToolEnabled100101def restore_tools(self):102pass103# GetToolEnabled104105def add_tool(self, key, func=None, bitmap=None, info='', widget=None, **args):106"""107Add a tool to the tool bar108"""109# print 'add_tool',self,key,func110111id = wx.NewId()112if not args.has_key('name'):113name = string.capitalize(key)114else:115name = args['name']116117if widget is not None:118# tool is a widget119self.toolbar.AddControl(widget)120else:121# tools is a simple button122if not bitmap:123bitmap = wx.NullBitmap124125# print 'bitmap=',name,bitmap126self.toolbar.AddSimpleTool(id, bitmap, name, info)127#self.toolbar.AddTool(id,name, bitmap, shortHelpString=info)128129wx.EVT_TOOL(self, id, func)130# if args.has_key('func_rclick'):131# wx.EVT_TOOL_RCLICKED(self.parent, id, args['func_rclick'])132133self._tools[key] = id134# Final thing to do for a toolbar is call the Realize() method. This135# causes it to render (more or less, that is).136self.toolbar.Realize()137S = self.toolbar.GetSize()138self.toolbar.SetSizeHints(S[0], S[1])139return id140141def enable_tool(self, key, enable=True):142if self._tools.has_key(key):143# self._tools[key].Show(False)144self.toolbar.EnableTool(self._tools[key], enable)145146else:147print 'enable_tool: no tool named:', key148149def del_tool(self, key):150if self._tools.has_key(key):151# self._tools[key].Show(False)152self.toolbar.RemoveTool(self._tools[key])153del self._tools[key]154155# Final thing to do for a toolbar is call the Realize() method. This156# causes it to render (more or less, that is).157self.toolbar.Realize()158else:159print 'del_tool: no tool named:', key160161162class AgileToolbarFrameMixin(AgileToolbarMixin):163"""164Easy to use toolbar where strings can be used to identify tools.165Mixin for frames only.166"""167168def init_toolbar(self, orientation='horizontal', size=(16, 16), separation=5):169"""170Only this initialization is specific to frames.171"""172# Use the wxFrame internals to create the toolbar and associate it all173# in one tidy method call.174if orientation == 'horizontal':175self.toolbar = self.CreateToolBar(wx.TB_HORIZONTAL176| wx.NO_BORDER177| wx.TB_FLAT178| wx.TB_TEXT179)180else:181self.toolbar = self.CreateToolBar(wx.TB_VERTICAL182| wx.NO_BORDER183| wx.TB_FLAT184| wx.TB_TEXT185)186187self.toolbar.SetToolBitmapSize(size)188self.toolbar.SetToolSeparation(separation)189190self._tools = {}191192193class AgileMenuMixin:194"""195Easy to use menue mixin for main menu and popup196"""197198def init_menu(self, parent):199"""200Initialize internal variables.201"""202self.parent = parent203self.__tree = {}204205def get_menu(self, path):206items = self.__tree207val = (None, None, -1)208# print 'get_menu',path209for key in path:210# print ' ',key,items211if items.has_key(key):212val = items[key]213# print val214if len(val) == 3:215items = val[1]216else:217return None, None, -1218else:219print 'WARNING in get_menu: invalid menu key', key, 'in path'220return None, None, -1221222return val[0], val[1], val[2]223224def get_menuitem(self, path):225menupath = string.split(path, '/')[:-1]226key = string.split(path, '/')[-1]227228# print '\nget_menuitem',self.__tree229if len(menupath) == 0:230# print " *create toplevel menu",key231menuitem, id = self.__tree[key]232233else:234# print " *create submenu",key235menu, tree, id = self.get_menu(menupath)236menuitem, id = tree[key]237238# print ' menuitem,id',menuitem,id239return menuitem240241def append_menu(self, path, **args):242"""243"""244# print 'append_menu',path,args245if path == '.':246# print " use '.' as root for popups"247# create an entry for database but do not append a menue248249key = '.'250# create special menu as direct root251id = wx.NewId()252self.__tree[key] = (self, {}, id)253# print ' ROOTMENU ATTRS: self,dir(self)',self,dir(self)254255else:256# print " normal menu"257menupath = string.split(path, '/')[:-1]258key = string.split(path, '/')[-1]259260if len(menupath) == 0:261# print " *create toplevel menu",key262menu, id = self._create_menu(self, key, **args)263self.__tree[key] = (menu, {}, id)264265else:266# print " *create submenu",key267parentmenu, parentmenu_dict, parentid = self.get_menu(menupath)268# print ' PARENTMENU ATTRS: self,dir(parentmenu)',parentmenu,dir(parentmenu)269# print ' parentmenu,key,parentmenu_dict,parentid',parentmenu,key,parentmenu_dict,parentid270menu, id = self._create_menu(parentmenu, key, **args)271parentmenu_dict[key] = (menu, {}, id)272273def _create_menu(self, parentmenu, key, menu=None, **args):274# print '\n\n_create_menu key',key275# default menu/submenu item276data = {'alt': True}277# print ' PARENTMENU ATTRS: self,dir(parentmenu)',parentmenu,dir(parentmenu)278# overwrite with args279data.update(args)280281if not data.has_key('name'):282data['name'] = string.capitalize(key)283284if data['alt']:285alt = '&'286else:287alt = ''288289id = wx.NewId()290if menu is None:291menu = wx.Menu()292293if parentmenu == self:294id = -1295if data.get('popup', False):296297# !! this is the way to append a menue to toplevel298# popup menu which is a menu itself299self.AppendMenu(id, data['name'], menu)300301else:302# !! this is the way to append a menue to toplevel303# which is a menubar !!304self.Append(menu, alt+data['name'])305306else:307# attach menu to a submenu308# print ' make submenu'309310item, id = self._create_item(key, parentmenu, function=None, **args)311item.SetSubMenu(menu)312parentmenu.AppendItem(item)313# parentmenu.AppendMenu(id,alt+data['name'],menu)314315return menu, id316317def append_item(self, path, function, **args):318319# print 'append_item',path,function320menupath = string.split(path, '/')[:-1]321key = string.split(path, '/')[-1]322323menu, menu_dict, menuid = self.get_menu(menupath)324325# print ' key=',key326327if menu:328# create item and append to menu instance329item, id = self._create_item(key, menu, function, **args)330331# append item332# print ' menu',menu,type(menu),dir(menu)333menu.AppendItem(item)334if args.has_key('check'):335menu.Check(item.GetId(), args['check'])336# if (args.has_key('check'))&(args.has_key('checked')):337# menu.Check(item.GetId(), args['checked'])338339menu_dict[key] = (item, id)340return item, id341else:342print 'WARNING: in append_item: invalid menu path', menupath343return None, None344345def _create_item(self, key, menu, function=None, **args):346# default item347data = {'alt': True,348'shortkey': '',349# 'info':'',350}351352# overwrite with args353data.update(args)354355if not data.has_key('name'):356data['name'] = string.capitalize(key)357358if not data.has_key('info'):359if function.__doc__ is not None:360data['info'] = function.__doc__.replace('\n', ' ').strip()361else:362data['info'] = data['name']363364# print '_create_item',data365366# create item367id = wx.NewId()368if data['alt']:369alt = '&'370else:371alt = ''372itemtext = alt+data['name']373if data['shortkey'] != '':374itemtext += '\t'+data['shortkey']375376if data.has_key('radio'):377378item = wx.MenuItem(menu, id, itemtext, data['info'], wx.ITEM_RADIO)379# print ' radio item'380381elif data.has_key('check'):382item = wx.MenuItem(menu, id, itemtext, data['info'], wx.ITEM_CHECK)383# check boxes AFTER append384385else:386item = wx.MenuItem(menu, id, itemtext, data['info'], wx.ITEM_NORMAL)387# print ' normal item'388389if data.has_key('bitmap'):390# print '_create_item bitmap',data['bitmap']391# TODO: allow more image formats in menuitem392# item.SetBitmap(images.getSmilesBitmap())393item.SetBitmap(data['bitmap'])394395# define callback function396if function is not None: # None for submenueitem397# wx.EVT_MENU(self.parent,id,function)398self.parent.Bind(wx.EVT_MENU, function, id=id)399400return item, id401402def del_item(self, path):403menupath = string.split(path, '/')[:-1]404key = string.split(path, '/')[-1]405406menu, menu_dict, menuid = self.get_menu(menupath)407if menu:408if menu_dict.has_key(key):409menu.RemoveItem(menu_dict[key][0])410# menu_dict[key][0].Remove()411del menu_dict[key]412413def del_menu(self, path):414menupath = string.split(path, '/')[:-1]415key = string.split(path, '/')[-1]416allpath = string.split(path, '/')417parentmenu, parentmenu_dict, parentmenuid = self.get_menu(menupath)418menu, menu_dict, menuid = self.get_menu(allpath)419420if menu:421if menuid > -1:422parentmenu.Remove(menuid) # works423del parentmenu_dict[key]424else:425self.Remove(menu)426del parentmenu_dict[key]427428def __setitem__(self, menupath, **data):429# print 'set menue',menupath,'to',data430431if type(name) != types.TupleType:432# create main menue entry, if necessary433if not self.menus.has_key(name):434newmenue = wx.Menu()435self.Append(newmenue, '&'+name)436self.menus[name] = (-1, {})437438elif len(name) == 2:439# create submenu entry, if necessary440name1, name2 = name441if not self.menus.has_key(name1):442newmenue = wx.Menu()443self.Append(newmenue, '&'+name1)444self.menus[name] = (-1, {})445446menuid, submenus = self.menus[name1]447448if not submenus.has_key(name2):449id = wx.NewId()450get_menu_item()451newmenue = wx.Menu()452self.Append(newmenue, '&'+name1)453self.menus[name] = {}454455submenu = self.menus456parentmenu = None457for m in menu:458if not submenu.has_key(m):459newmenue = wx.Menu()460461def get_menu_item(self, id):462item = self.FindItemById(id)463menu = item.GetMenu()464return menu, item465466def get_menuitem_from_id(self, id):467menu, item = self.get_menu_item(id)468return item469470471class AgilePopupMenu(wx.Menu, AgileMenuMixin):472"""473Easy to use popup474"""475476def __init__(self, parent):477wx.Menu.__init__(self)478self.init_menu(parent)479480# append special root menu481AgileMenuMixin.append_menu(self, '.')482483def append_menu(self, path, **args):484AgileMenuMixin.append_menu(self, './'+path, popup=True, **args)485486def append_item(self, path, function, **args):487return AgileMenuMixin.append_item(self, './'+path, function, **args)488489def get_menuitem(self, path):490return AgileMenuMixin.get_menuitem(self, './'+path)491492# -------------------------------------------------------------------------------493# the folling methods are used with contect<sebitive menus494# on a grid based widget.495# When initializing the menu the row and column of its location can496# be stored for later retrival during an event:497# event.GetEventObject().get_row() event.GetEventObject().get_row()498499def set_row(self, row):500self.row = row501502def set_col(self, col):503self.col = col504505def get_row(self):506return self.row507508def get_col(self):509return self.col510511512KEYMAP = {513wx.WXK_BACK: "BACK",514wx.WXK_TAB: "TAB",515wx.WXK_RETURN: "RETURN",516wx.WXK_ESCAPE: "ESCAPE",517wx.WXK_SPACE: "SPACE",518wx.WXK_DELETE: "DELETE",519wx.WXK_START: "START",520wx.WXK_LBUTTON: "LBUTTON",521wx.WXK_RBUTTON: "RBUTTON",522wx.WXK_CANCEL: "CANCEL",523wx.WXK_MBUTTON: "MBUTTON",524wx.WXK_CLEAR: "CLEAR",525wx.WXK_SHIFT: "SHIFT",526wx.WXK_ALT: "ALT",527wx.WXK_CONTROL: "CONTROL",528wx.WXK_MENU: "MENU",529wx.WXK_PAUSE: "PAUSE",530wx.WXK_CAPITAL: "CAPITAL",531wx.WXK_PRIOR: "PRIOR",532wx.WXK_NEXT: "NEXT",533wx.WXK_END: "END",534wx.WXK_HOME: "HOME",535wx.WXK_LEFT: "LEFT",536wx.WXK_UP: "UP",537wx.WXK_RIGHT: "RIGHT",538wx.WXK_DOWN: "DOWN",539wx.WXK_SELECT: "SELECT",540wx.WXK_PRINT: "PRINT",541wx.WXK_EXECUTE: "EXECUTE",542wx.WXK_SNAPSHOT: "SNAPSHOT",543wx.WXK_INSERT: "INSERT",544wx.WXK_HELP: "HELP",545wx.WXK_NUMPAD0: "NUMPAD0",546wx.WXK_NUMPAD1: "NUMPAD1",547wx.WXK_NUMPAD2: "NUMPAD2",548wx.WXK_NUMPAD3: "NUMPAD3",549wx.WXK_NUMPAD4: "NUMPAD4",550wx.WXK_NUMPAD5: "NUMPAD5",551wx.WXK_NUMPAD6: "NUMPAD6",552wx.WXK_NUMPAD7: "NUMPAD7",553wx.WXK_NUMPAD8: "NUMPAD8",554wx.WXK_NUMPAD9: "NUMPAD9",555wx.WXK_MULTIPLY: "MULTIPLY",556wx.WXK_ADD: "ADD",557wx.WXK_SEPARATOR: "SEPARATOR",558wx.WXK_SUBTRACT: "SUBTRACT",559wx.WXK_DECIMAL: "DECIMAL",560wx.WXK_DIVIDE: "DIVIDE",561wx.WXK_F1: "F1",562wx.WXK_F2: "F2",563wx.WXK_F3: "F3",564wx.WXK_F4: "F4",565wx.WXK_F5: "F5",566wx.WXK_F6: "F6",567wx.WXK_F7: "F7",568wx.WXK_F8: "F8",569wx.WXK_F9: "F9",570wx.WXK_F10: "F10",571wx.WXK_F11: "F11",572wx.WXK_F12: "F12",573wx.WXK_F13: "F13",574wx.WXK_F14: "F14",575wx.WXK_F15: "F15",576wx.WXK_F16: "F16",577wx.WXK_F17: "F17",578wx.WXK_F18: "F18",579wx.WXK_F19: "F19",580wx.WXK_F20: "F20",581wx.WXK_F21: "F21",582wx.WXK_F22: "F22",583wx.WXK_F23: "F23",584wx.WXK_F24: "F24",585wx.WXK_NUMLOCK: "NUMLOCK",586wx.WXK_SCROLL: "SCROLL",587wx.WXK_PAGEUP: "PAGEUP",588wx.WXK_PAGEDOWN: "PAGEDOWN",589wx.WXK_NUMPAD_SPACE: "NUMPAD_SPACE",590wx.WXK_NUMPAD_TAB: "NUMPAD_TAB",591wx.WXK_NUMPAD_ENTER: "NUMPAD_ENTER",592wx.WXK_NUMPAD_F1: "NUMPAD_F1",593wx.WXK_NUMPAD_F2: "NUMPAD_F2",594wx.WXK_NUMPAD_F3: "NUMPAD_F3",595wx.WXK_NUMPAD_F4: "NUMPAD_F4",596wx.WXK_NUMPAD_HOME: "NUMPAD_HOME",597wx.WXK_NUMPAD_LEFT: "NUMPAD_LEFT",598wx.WXK_NUMPAD_UP: "NUMPAD_UP",599wx.WXK_NUMPAD_RIGHT: "NUMPAD_RIGHT",600wx.WXK_NUMPAD_DOWN: "NUMPAD_DOWN",601wx.WXK_NUMPAD_PRIOR: "NUMPAD_PRIOR",602wx.WXK_NUMPAD_PAGEUP: "NUMPAD_PAGEUP",603wx.WXK_NUMPAD_NEXT: "NUMPAD_NEXT",604wx.WXK_NUMPAD_PAGEDOWN: "NUMPAD_PAGEDOWN",605wx.WXK_NUMPAD_END: "NUMPAD_END",606wx.WXK_NUMPAD_BEGIN: "NUMPAD_BEGIN",607wx.WXK_NUMPAD_INSERT: "NUMPAD_INSERT",608wx.WXK_NUMPAD_DELETE: "NUMPAD_DELETE",609wx.WXK_NUMPAD_EQUAL: "NUMPAD_EQUAL",610wx.WXK_NUMPAD_MULTIPLY: "NUMPAD_MULTIPLY",611wx.WXK_NUMPAD_ADD: "NUMPAD_ADD",612wx.WXK_NUMPAD_SEPARATOR: "NUMPAD_SEPARATOR",613wx.WXK_NUMPAD_SUBTRACT: "NUMPAD_SUBTRACT",614wx.WXK_NUMPAD_DECIMAL: "NUMPAD_DECIMAL",615wx.WXK_NUMPAD_DIVIDE: "NUMPAD_DIVIDE",616}617618619class KeyHandler:620"""621Mixin for handling key events in wx622"""623624def init_keys(self, parent=None):625"""626Sets events and variables for parent.627If no parent is defined then self is assumed to be parent.628"""629if parent is None:630parent = self631632self.key_pressed = '' # string code of currently pressed key633wx.EVT_ENTER_WINDOW(self, self.on_enter_window)634wx.EVT_KEY_DOWN(self, self.on_key_down)635wx.EVT_KEY_UP(self, self.on_key_up)636637def on_enter_window(self, evt):638# print 'on_enter_window'639self.SetFocus()640#self.haveFocus = False641# self.Refresh()642643def on_key_down(self, event):644"""645A key has been pressed down...646"""647if self.GUIMode is None:648# try custom tool of metacanvas649input = self.set_keypress(event)650# print 'on_key_down',input651self.metacanvas.make_transition(input, self)652653def on_key_up(self, event):654"""655A key has been pressed down...656"""657# print 'on_key_up'658self.del_keypress()659print ' key_pressed', self.key_pressed660661def del_keypress(self):662"""663Empties self.key_pressed string664"""665self.key_pressed = ''666667def set_keypress(self, evt, ignore_specials=False):668"""669This method analyses the event and sets the self.key_pressed string.670Method returns a string with the key.671672673"""674keycode = evt.GetKeyCode()675keyname = KEYMAP.get(keycode, None)676if keyname is None:677# regular character key678if keycode < 256:679if keycode == 0:680keyname = "NUL"681elif (keycode < 27) & (not ignore_specials):682# keycode is a special control key683keyname = "Ctrl-%s" % chr(ord('A') + keycode-1)684elif (keycode < 27):685keyname = ''686else:687keyname = "\"%s\"" % chr(keycode)688else:689keyname = '' # ignore690691elif ignore_specials: # keycode is a special key692keyname = '' # ignore693694self.key_pressed = keyname695696return keyname697698def get_code_special_keys(self, event, sep='+'):699"""700This method analyses the special keypress and returns a string701that codes SHIFT, ALT, CONTROL702"""703code = ''704705if event.ControlDown():706code += 'CONTROL'+sep707708if event.ShiftDown():709code += 'SHIFT'+sep710711if event.AltDown():712code += 'ALT'+sep713714return code715716# class ToolMixin(AgileToolbarMixin):717718719class OptionsFrame(wx.Frame):720"""721Simple wx frame with some special features.722"""723724def __init__(self, parent, mainframe=None, id=-1, title='testframe', pos=wx.DefaultPosition,725size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE,726name='frame'):727728if mainframe is None:729self._mainframe = parent730else:731self._mainframe = mainframe732733# Forcing a specific style on the window.734# Should this include styles passed?735style = wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE736wx.Frame.__init__(self, parent, id, title, pos, size, style, name)737#super(GLFrame, self).__init__(parent, id, title, pos, size, style, name)738739def get_metacanvas(self):740return metacanvas741742743class OptionsPanel(AgileToolbarMixin, wx.Panel):744"""745UNUSED746Simple wx panele with some special features.747"""748749def __init__(self, parent, mainframe=None):750751wx.Panel.__init__(self, parent, -1, wx.DefaultPosition,752wx.DefaultSize, wx.SUNKEN_BORDER | wx.WANTS_CHARS)753if mainframe is None:754self._mainframe = parent755else:756self._mainframe = mainframe757758def get_metacanvas(self):759return metacanvas760761762class AgileStatusbar(wx.StatusBar):763def __init__(self, parent, fields=[('action', -4),764('message', -4),765# ('coords',-1),766# ('zoom',-1),767('progress', -1),768('status', -1),769# ('coords',-1),770]):771772wx.StatusBar.__init__(self, parent, -1, wx.ST_SIZEGRIP)773774self.set_fields(fields)775776self.sizeChanged = False777self.Bind(wx.EVT_SIZE, self.OnSize)778#self.Bind(wx.EVT_IDLE, self.OnIdle)779780# Field 0 ... just text781# self['message']=""782783# create a progrss bar784self.progressbar = wx.Gauge(self, -1, 100)785self.progressbar.SetBezelFace(4)786self.progressbar.SetShadowWidth(4)787# self.progressbar.SetValue(50)788789# put into position all status bar fields and elements790self.Reposition()791792def write_action(self, text):793self['action'] = text794795def write_message(self, text):796self['message'] = text797798# def write_coords(self,text):799# self['coords'] = text800801def set_progress(self, percent):802"""803Set bar of progressbar in percent804"""805# print 'set_progress',percent806self.progressbar.SetValue(int(percent))807self.Update()808809def set_fields(self, fields):810"""811Sets basic data of fields in status bar.812Argument field is a list with the following format:813[(name1,width1),(name2,width2),...]814"""815self._ind_fields = {}816widths = []817ind = 0818for name, width in fields:819widths.append(width)820self._ind_fields[name] = ind821ind += 1822self.SetFieldsCount(ind)823self.SetStatusWidths(widths)824825def __setitem__(self, key, message):826827ind_field = self._ind_fields[key]828# print 'AgileStatusbar.__setitem__',key,ind_field829self.SetStatusText(message, ind_field)830self.Update()831832def has_key(self, key):833return self._ind_fields.has_key(key)834835def OnSize(self, evt):836self.Reposition() # for normal size events837838# Set a flag so the idle time handler will also do the repositioning.839# It is done this way to get around a buglet where GetFieldRect is not840# accurate during the EVT_SIZE resulting from a frame maximize.841self.sizeChanged = True842843def OnIdle(self, evt):844if self.sizeChanged:845self.Reposition()846847# reposition the checkbox848849def Reposition(self):850# print 1,rect851rect = self.GetFieldRect(self._ind_fields['progress'])852self.progressbar.SetPosition(rect.GetPosition())853self.progressbar.SetSize(rect.GetSize())854855self.sizeChanged = False856857858class AgileMenubar(AgileMenuMixin, wx.MenuBar):859"""860Easy to use main menu bar861"""862863def __init__(self, parent):864wx.MenuBar.__init__(self)865self.init_menu(parent)866867868def get_bitmap(name, size=22):869"""Return bitmap of right size from imgImages library"""870name = name + "_"+str(size)871try:872return imgImages.catalog[name].getBitmap()873except:874print 'WARNING in get_bitmap: failed to return image', name875return wx.NullBitmap876877878# These are some functions for bitmaps of icons.879880881def GetHandData():882return cPickle.loads(zlib.decompress(883'x\xda\xd3\xc8)0\xe4\nV72T\x00!\x05Cu\xae\xc4`u=\x85d\x05\xa7\x9c\xc4\xe4l0O\884\x01\xc8S\xb6t\x06A(\x1f\x0b\xa0\xa9\x8c\x9e\x1e6\x19\xa0\xa8\x1e\x88\xd4C\885\x97\xd1\x83\xe8\x80 \x9c2zh\xa6\xc1\x11X\n\xab\x8c\x02\x8a\x0cD!\x92\x12\886\x98\x8c\x1e\x8a\x8b\xd1d\x14\xf4\x90%\x90LC\xf6\xbf\x1e\xba\xab\x91%\xd0\887\xdc\x86C\x06\xd9m\xe8!\xaa\x87S\x86\x1a1\xa7\x07\x00v\x0f[\x17'))888889890def GetHandBitmap():891return wx.BitmapFromXPMData(GetHandData())892893# ----------------------------------------------------------------------894895896def GetPlusData():897return cPickle.loads(zlib.decompress(898'x\xda\xd3\xc8)0\xe4\nV72T\x00!\x05Cu\xae\xc4`u=\x85d\x05\xa7\x9c\xc4\xe4l0O\899\x01\xc8S\xb6t\x06A(\x1f\x0b RF\x0f\x08\xb0\xc9@D\xe1r\x08\x19\xb8j=l2`\r\900\xe82HF\xe9a\xc8\xe8\xe9A\x9c@\x8a\x0c\x0e\xd3p\xbb\x00\x8f\xab\xe1>\xd5\xd3\901\xc3\x15:P)l!\n\x91\xc2\x1a\xd6`)\xec\xb1\x00\x92\xc2\x11?\xb8e\x88\x8fSt\902\x19=\x00\x82\x16[\xf7'))903904905def GetPlusBitmap():906return wx.BitmapFromXPMData(GetPlusData())907908# ----------------------------------------------------------------------909910911def GetMinusData():912return cPickle.loads(zlib.decompress(913'x\xda\xd3\xc8)0\xe4\nV72T\x00!\x05Cu\xae\xc4`u=\x85d\x05\xa7\x9c\xc4\xe4l0O\914\x01\xc8S\xb6t\x06A(\x1f\x0b RF\x0f\x08\xb0\xc9@D\xe1r\x08\x19\xb8j=\xa2e\915\x10\x16@\x99\xc82zz\x10\'\x90"\x83\xc34r\xdc\x86\xf0\xa9\x9e\x1e\xae\xd0\916\x81Ja\x0bQ\x88\x14\xd6\xb0\x06Ka\x8f\x05\x90\x14\x8e\xf8\xc1-C|\x9c\xa2\xcb\917\xe8\x01\x00\xed\x0f[\x87'))918919920def GetMinusBitmap():921return wx.BitmapFromXPMData(GetMinusData())922923924