2 # Purpose:      XRC editor, toolbar 
   3 # Author:       Roman Rolinsky <rolinsky@mema.ucl.ac.be> 
   7 from xxx 
import *                       # xxx imports globals and params 
   8 from tree 
import ID_NEW
 
  15 GROUP_WINDOWS
, GROUP_MENUS
, GROUP_SIZERS
, GROUP_CONTROLS 
= range(GROUPNUM
) 
  17 # States depending on current selection and Control/Shift keys 
  18 STATE_ROOT
, STATE_MENUBAR
, STATE_TOOLBAR
, STATE_MENU
, STATE_STDDLGBTN
, STATE_ELSE 
= range(6) 
  19 # Left toolbar for GUI elements 
  20 class Tools(wx
.Panel
): 
  22     def __init__(self
, parent
): 
  23         if wx
.Platform 
== '__WXGTK__': 
  24             wx
.Panel
.__init
__(self
, parent
, -1, 
  25                              style
=wx
.RAISED_BORDER|wx
.WANTS_CHARS
) 
  27             wx
.Panel
.__init
__(self
, parent
, -1, style
=wx
.WANTS_CHARS
) 
  28         # Create sizer for groups 
  29         self
.sizer 
= wx
.BoxSizer(wx
.VERTICAL
) 
  30         # Data to create buttons 
  31         pullDownMenu 
= g
.pullDownMenu
 
  33         self
.ctrl 
= self
.shift 
= False 
  34         # Current state (what to enable/disable) 
  38              (ID_NEW
.FRAME
, images
.getToolFrameBitmap()), 
  39              (ID_NEW
.DIALOG
, images
.getToolDialogBitmap()), 
  40              (ID_NEW
.PANEL
, images
.getToolPanelBitmap())], 
  42              (ID_NEW
.TOOL_BAR
, images
.getToolToolBarBitmap()), 
  43              (ID_NEW
.MENU_BAR
, images
.getToolMenuBarBitmap()), 
  44              (ID_NEW
.MENU
, images
.getToolMenuBitmap()), 
  45              (ID_NEW
.TOOL
, images
.getToolToolBitmap()), 
  46              (ID_NEW
.MENU_ITEM
, images
.getToolMenuItemBitmap()), 
  47              (ID_NEW
.SEPARATOR
, images
.getToolSeparatorBitmap())], 
  49              (ID_NEW
.BOX_SIZER
, images
.getToolBoxSizerBitmap()), 
  50              (ID_NEW
.STATIC_BOX_SIZER
, images
.getToolStaticBoxSizerBitmap()), 
  51              (ID_NEW
.GRID_SIZER
, images
.getToolGridSizerBitmap()), 
  52              (ID_NEW
.FLEX_GRID_SIZER
, images
.getToolFlexGridSizerBitmap()), 
  53              (ID_NEW
.GRID_BAG_SIZER
, images
.getToolGridBagSizerBitmap()), 
  54              (ID_NEW
.SPACER
, images
.getToolSpacerBitmap())], 
  56              (ID_NEW
.STATIC_TEXT
, images
.getToolStaticTextBitmap()), 
  57              (ID_NEW
.STATIC_BITMAP
, images
.getToolStaticBitmapBitmap()), 
  58              (ID_NEW
.STATIC_LINE
, images
.getToolStaticLineBitmap()), 
  59              (ID_NEW
.BUTTON
, images
.getToolButtonBitmap()), 
  60              (ID_NEW
.BITMAP_BUTTON
, images
.getToolBitmapButtonBitmap()), 
  61              (ID_NEW
.STATIC_BOX
, images
.getToolStaticBoxBitmap()), 
  63              (ID_NEW
.TEXT_CTRL
, images
.getToolTextCtrlBitmap()), 
  64              (ID_NEW
.COMBO_BOX
, images
.getToolComboBoxBitmap()), 
  65              (ID_NEW
.CHOICE
, images
.getToolChoiceBitmap()), 
  67              (ID_NEW
.RADIO_BUTTON
, images
.getToolRadioButtonBitmap()), 
  68              (ID_NEW
.CHECK_BOX
, images
.getToolCheckBoxBitmap()), 
  69              (ID_NEW
.RADIO_BOX
, images
.getToolRadioBoxBitmap()), 
  71              (ID_NEW
.SPIN_CTRL
, images
.getToolSpinCtrlBitmap()), 
  72              (ID_NEW
.SPIN_BUTTON
, images
.getToolSpinButtonBitmap()), 
  73              (ID_NEW
.SCROLL_BAR
, images
.getToolScrollBarBitmap()), 
  75              (ID_NEW
.SLIDER
, images
.getToolSliderBitmap()), 
  76              (ID_NEW
.GAUGE
, images
.getToolGaugeBitmap()), 
  77              (ID_NEW
.TREE_CTRL
, images
.getToolTreeCtrlBitmap()), 
  79              (ID_NEW
.LIST_BOX
, images
.getToolListBoxBitmap()), 
  80              (ID_NEW
.CHECK_LIST
, images
.getToolCheckListBitmap()), 
  81              (ID_NEW
.LIST_CTRL
, images
.getToolListCtrlBitmap()), 
  83              (ID_NEW
.NOTEBOOK
, images
.getToolNotebookBitmap()), 
  84              (ID_NEW
.SPLITTER_WINDOW
, images
.getToolSplitterWindowBitmap()), 
  86              (ID_NEW
.UNKNOWN
, images
.getToolUnknownBitmap())] 
  92                 self
.AddButton(b
[0], b
[1], g
.pullDownMenu
.createMap
[b
[0]]) 
  93         self
.SetSizerAndFit(self
.sizer
) 
  94         # Allow to be resized in vertical direction only 
  95         self
.SetSizeHints(self
.GetSize()[0], -1) 
  97         wx
.EVT_COMMAND_RANGE(self
, ID_NEW
.PANEL
, ID_NEW
.LAST
, 
  98                              wx
.wxEVT_COMMAND_BUTTON_CLICKED
, g
.frame
.OnCreate
) 
  99         wx
.EVT_KEY_DOWN(self
, self
.OnKeyDown
) 
 100         wx
.EVT_KEY_UP(self
, self
.OnKeyUp
) 
 101         # wxMSW does not generate click events for StaticBox 
 102         if wx
.Platform 
== '__WXMSW__': 
 103             self
.Bind(wx
.EVT_LEFT_DOWN
, self
.OnClickBox
) 
 106     def AddButton(self
, id, image
, text
): 
 107         from wx
.lib 
import buttons
 
 108         button 
= buttons
.GenBitmapButton(self
, id, image
, size
=self
.TOOL_SIZE
, 
 109                                          style
=wx
.NO_BORDER|wx
.WANTS_CHARS
) 
 110         button
.SetBezelWidth(0) 
 111         wx
.EVT_KEY_DOWN(button
, self
.OnKeyDown
) 
 112         wx
.EVT_KEY_UP(button
, self
.OnKeyUp
) 
 113         wx
.EVT_LEFT_DOWN(button
, self
.OnLeftDownOnButton
) 
 114         wx
.EVT_MOTION(button
, self
.OnMotionOnButton
) 
 115         button
.SetToolTipString(text
) 
 116         self
.curSizer
.Add(button
) 
 117         self
.groups
[-1][1][id] = button
 
 119     def AddGroup(self
, name
): 
 120         # Each group is inside box 
 122         box 
= wx
.StaticBox(self
, id, '[+] '+name
, style
=wx
.WANTS_CHARS
) 
 123         box
.SetForegroundColour(wx
.Colour(64, 64, 64)) 
 124 #        box.SetFont(g.smallerFont()) 
 127         box
.gnum 
= len(self
.groups
) 
 128         box
.Bind(wx
.EVT_LEFT_DOWN
, self
.OnClickBox
) 
 129         boxSizer 
= wx
.StaticBoxSizer(box
, wx
.VERTICAL
) 
 132         self
.curSizer 
= wx
.GridSizer(0, 3, 3, 3) 
 133         boxSizer
.Add(self
.curSizer
) 
 134         self
.sizer
.Add(boxSizer
, 0, wx
.TOP | wx
.LEFT | wx
.RIGHT | wx
.EXPAND
, 4) 
 135         self
.groups
.append((box
,{})) 
 137     # Enable/disable group 
 138     def EnableGroup(self
, gnum
, enable 
= True): 
 139         grp 
= self
.groups
[gnum
] 
 140         for b 
in grp
[1].values(): b
.Enable(enable
) 
 143     def ShowGroup(self
, gnum
, show 
= True): 
 144         grp 
= self
.groups
[gnum
] 
 146         for b 
in grp
[1].values(): b
.Show(show
) 
 148     # Enable/disable group item 
 149     def EnableGroupItem(self
, gnum
, id, enable 
= True): 
 150         grp 
= self
.groups
[gnum
] 
 151         grp
[1][id].Enable(enable
) 
 153     # Enable/disable group items 
 154     def EnableGroupItems(self
, gnum
, ids
, enable 
= True): 
 155         grp 
= self
.groups
[gnum
] 
 157             grp
[1][id].Enable(enable
) 
 159     def OnClickBox(self
, evt
): 
 160         if wx
.Platform 
== '__WXMSW__': 
 162             for id,b 
in self
.boxes
.items(): 
 163                 # How to detect a click on a label? 
 164                 if b
.GetRect().Inside(evt
.GetPosition()): 
 171             box 
= self
.boxes
[evt
.GetId()] 
 172         # Collapse/restore static box, change label 
 173         self
.ShowGroup(box
.gnum
, not box
.show
) 
 174         if box
.show
: box
.SetLabel('[+] ' + box
.name
) 
 175         else: box
.SetLabel('[-] ' + box
.name
) 
 178         #for b in self.boxes.items(): 
 181     def OnLeftDownOnButton(self
, evt
): 
 182         self
.posDown 
= evt
.GetPosition() 
 183         self
.idDown 
= evt
.GetId() 
 184         self
.btnDown 
= evt
.GetEventObject() 
 187     def OnMotionOnButton(self
, evt
): 
 189         if evt
.Dragging() and evt
.LeftIsDown(): 
 190             d 
= evt
.GetPosition() - self
.posDown
 
 191             if max(abs(d
[0]), abs(d
[1])) >= 5: 
 192                 if self
.btnDown
.HasCapture():  
 193                     # Generate up event to release mouse 
 194                     evt 
= wx
.MouseEvent(wx
.EVT_LEFT_UP
.typeId
) 
 195                     evt
.SetId(self
.idDown
) 
 196                     # Set flag to prevent normal button operation this time 
 198                     self
.btnDown
.ProcessEvent(evt
) 
 204         do
.SetData(str(self
.idDown
)) 
 205         bm 
= self
.btnDown
.GetBitmapLabel() 
 206         # wxGTK requires wxIcon cursor, wxWIN and wxMAC require wxCursor 
 207         if wx
.Platform 
== '__WXGTK__': 
 208             icon 
= wx
.EmptyIcon() 
 209             icon
.CopyFromBitmap(bm
) 
 210             dragSource 
= wx
.DropSource(self
, icon
) 
 212             curs 
= wx
.CursorFromImage(wx
.ImageFromBitmap(bm
)) 
 213             dragSource 
= wx
.DropSource(self
, curs
) 
 214         dragSource
.SetData(do
) 
 215         g
.frame
.SetStatusText('Release the mouse button over the test window') 
 216         dragSource
.DoDragDrop() 
 219     def OnKeyDown(self
, evt
): 
 220         if evt
.GetKeyCode() == wx
.WXK_CONTROL
: 
 222         elif evt
.GetKeyCode() == wx
.WXK_SHIFT
: 
 224         self
.UpdateIfNeeded() 
 227     def OnKeyUp(self
, evt
): 
 228         if evt
.GetKeyCode() == wx
.WXK_CONTROL
: 
 230         elif evt
.GetKeyCode() == wx
.WXK_SHIFT
: 
 232         self
.UpdateIfNeeded() 
 235     def OnMouse(self
, evt
): 
 236         # Update control and shift states 
 237         g
.tree
.ctrl 
= evt
.ControlDown() 
 238         g
.tree
.shift 
= evt
.ShiftDown() 
 239         self
.UpdateIfNeeded() 
 242     # Update UI after key presses, if necessary 
 243     def UpdateIfNeeded(self
): 
 245         if self
.ctrl 
!= tree
.ctrl 
or self
.shift 
!= tree
.shift
: 
 246             # Enabling is needed only for ctrl 
 247             if self
.ctrl 
!= tree
.ctrl
: self
.UpdateUI() 
 248             self
.ctrl 
= tree
.ctrl
 
 249             self
.shift 
= tree
.shift
 
 256             g
.frame
.SetStatusText(status
, 1) 
 260         if not self
.IsShown(): return 
 262         pullDownMenu 
= g
.pullDownMenu
 
 264         item 
= tree
.selection
 
 265         # If nothing selected, disable everything and return 
 268             for grp 
in range(GROUPNUM
): 
 269                 self
.EnableGroup(grp
, False) 
 272         if tree
.ctrl
: needInsert 
= True 
 273         else: needInsert 
= tree
.NeedInsert(item
) 
 274         # Enable depending on selection 
 275         if item 
== tree
.root 
or needInsert 
and tree
.GetItemParent(item
) == tree
.root
: 
 278             xxx 
= tree
.GetPyData(item
).treeObject() 
 279             # Check parent for possible child nodes if inserting sibling 
 280             if needInsert
: xxx 
= xxx
.parent
 
 281             if xxx
.__class
__ == xxxMenuBar
: 
 282                 state 
= STATE_MENUBAR
 
 283             elif xxx
.__class
__ in [xxxToolBar
, xxxTool
] or \
 
 284                  xxx
.__class
__ == xxxSeparator 
and xxx
.parent
.__class
__ == xxxToolBar
: 
 285                 state 
= STATE_TOOLBAR
 
 286             elif xxx
.__class
__ in [xxxMenu
, xxxMenuItem
]: 
 288             elif xxx
.__class
__ == xxxStdDialogButtonSizer
: 
 289                 state 
= STATE_STDDLGBTN
 
 293         # Enable depending on selection 
 294         if state 
!= self
.state
: 
 296             for grp 
in range(GROUPNUM
): 
 297                 self
.EnableGroup(grp
, False) 
 299             if state 
== STATE_ROOT
: 
 300                 self
.EnableGroup(GROUP_WINDOWS
, True) 
 301                 self
.EnableGroup(GROUP_MENUS
, True) 
 303                 self
.EnableGroupItems(GROUP_MENUS
, 
 308             elif state 
== STATE_STDDLGBTN
: 
 309                 pass                    # nothing can be added from toolbar 
 310             elif state 
== STATE_MENUBAR
: 
 311                 self
.EnableGroup(GROUP_MENUS
) 
 312                 self
.EnableGroupItems(GROUP_MENUS
, 
 317             elif state 
== STATE_TOOLBAR
: 
 318                 self
.EnableGroup(GROUP_MENUS
) 
 319                 self
.EnableGroupItems(GROUP_MENUS
, 
 325                 self
.EnableGroup(GROUP_CONTROLS
) 
 326                 self
.EnableGroupItems(GROUP_CONTROLS
, 
 329                                         ID_NEW
.SPLITTER_WINDOW 
], 
 331             elif state 
== STATE_MENU
: 
 332                 self
.EnableGroup(GROUP_MENUS
) 
 333                 self
.EnableGroupItems(GROUP_MENUS
, 
 339                 self
.EnableGroup(GROUP_WINDOWS
) 
 340                 self
.EnableGroupItems(GROUP_WINDOWS
, 
 344                 self
.EnableGroup(GROUP_MENUS
) 
 345                 self
.EnableGroupItems(GROUP_MENUS
, 
 353                 self
.EnableGroup(GROUP_SIZERS
) 
 354                 self
.EnableGroup(GROUP_CONTROLS
) 
 355         # Special case for *book (always executed) 
 356         if state 
== STATE_ELSE
: 
 357             if xxx
.__class
__ in [xxxNotebook
, xxxChoicebook
, xxxListbook
]: 
 358                 self
.EnableGroup(GROUP_SIZERS
, False) 
 360                 self
.EnableGroup(GROUP_SIZERS
) 
 361                 if not (xxx
.isSizer 
or xxx
.parent 
and xxx
.parent
.isSizer
): 
 362                     self
.EnableGroupItem(GROUP_SIZERS
, ID_NEW
.SPACER
, False) 
 363             if xxx
.__class
__ == xxxFrame
: 
 364                 self
.EnableGroupItem(GROUP_MENUS
, ID_NEW
.MENU_BAR
)