Files
wxWidgets/wxPython/wx/tools/XRCed/tools.py
Robin Dunn 30d91f9ebc Preferences for default "sizeritem" parameters for new panels and
controls can be configured ("File">"Preferences...").

Implemented comment object for including simple one-line comments and
comment directives as tree nodes. No validation is performed for a
valid XML string so comments must not contain "-->". Comment directive
is a special comment starting with '%' character, followed by a line
of python code. It is executed using 'exec' when the resource file is
opened. This is useful to import plugin modules containing custom
handlers which are specific to the resource file, hovewer this is of
course a security hole if you use foreign XRC files. A warning is
displayed if the preference option 'ask' is selected (by default).

Added support for custom controls and plugin modules. Refer to this
wxPythonWiki for the details:
        http://wiki.wxpython.org/index.cgi/XRCed#custom

Tool panel sections can be collapsed/expanded by clicking on the
label of a tool group.

Some undo/redo and other fixes.

Fixes for wxMSW (notebook highlighting, control sizes, tree Unselect).

Notebook page highlighting fix. Highlight resizes when the window
is resized. ParamUnit spin button detects event handler re-entry
(wxGTK probably has a bug in wxSpinButton with repeated events).

Fix for dealing with empty 'growable' property, using MiniFrame
for properties panel, the panel is restored together with the
main window.


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/branches/WX_2_8_BRANCH@44949 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
2007-03-19 17:55:26 +00:00

312 lines
13 KiB
Python

# Name: tools.py
# Purpose: XRC editor, toolbar
# Author: Roman Rolinsky <rolinsky@mema.ucl.ac.be>
# Created: 19.03.2003
# RCS-ID: $Id$
from xxx import * # xxx imports globals and params
from tree import ID_NEW
# Icons
import images
# Groups of controls
GROUPNUM = 4
GROUP_WINDOWS, GROUP_MENUS, GROUP_SIZERS, GROUP_CONTROLS = range(GROUPNUM)
# States depending on current selection and Control/Shift keys
STATE_ROOT, STATE_MENUBAR, STATE_TOOLBAR, STATE_MENU, STATE_STDDLGBTN, STATE_ELSE = range(6)
# Left toolbar for GUI elements
class Tools(wx.Panel):
TOOL_SIZE = (30, 30)
def __init__(self, parent):
if wx.Platform == '__WXGTK__':
wx.Panel.__init__(self, parent, -1,
style=wx.RAISED_BORDER|wx.WANTS_CHARS)
else:
wx.Panel.__init__(self, parent, -1, style=wx.WANTS_CHARS)
# Create sizer for groups
self.sizer = wx.BoxSizer(wx.VERTICAL)
# Data to create buttons
pullDownMenu = g.pullDownMenu
self.groups = []
self.ctrl = self.shift = False
# Current state (what to enable/disable)
self.state = None
groups = [
["Windows",
(ID_NEW.FRAME, images.getToolFrameBitmap()),
(ID_NEW.DIALOG, images.getToolDialogBitmap()),
(ID_NEW.PANEL, images.getToolPanelBitmap())],
["Menus",
(ID_NEW.TOOL_BAR, images.getToolToolBarBitmap()),
(ID_NEW.MENU_BAR, images.getToolMenuBarBitmap()),
(ID_NEW.MENU, images.getToolMenuBitmap()),
(ID_NEW.TOOL, images.getToolToolBitmap()),
(ID_NEW.MENU_ITEM, images.getToolMenuItemBitmap()),
(ID_NEW.SEPARATOR, images.getToolSeparatorBitmap())],
["Sizers",
(ID_NEW.BOX_SIZER, images.getToolBoxSizerBitmap()),
(ID_NEW.STATIC_BOX_SIZER, images.getToolStaticBoxSizerBitmap()),
(ID_NEW.GRID_SIZER, images.getToolGridSizerBitmap()),
(ID_NEW.FLEX_GRID_SIZER, images.getToolFlexGridSizerBitmap()),
(ID_NEW.GRID_BAG_SIZER, images.getToolGridBagSizerBitmap()),
(ID_NEW.SPACER, images.getToolSpacerBitmap())],
["Controls",
(ID_NEW.STATIC_TEXT, images.getToolStaticTextBitmap()),
(ID_NEW.STATIC_BITMAP, images.getToolStaticBitmapBitmap()),
(ID_NEW.STATIC_LINE, images.getToolStaticLineBitmap()),
(ID_NEW.BUTTON, images.getToolButtonBitmap()),
(ID_NEW.BITMAP_BUTTON, images.getToolBitmapButtonBitmap()),
(ID_NEW.STATIC_BOX, images.getToolStaticBoxBitmap()),
(ID_NEW.TEXT_CTRL, images.getToolTextCtrlBitmap()),
(ID_NEW.COMBO_BOX, images.getToolComboBoxBitmap()),
(ID_NEW.CHOICE, images.getToolChoiceBitmap()),
(ID_NEW.RADIO_BUTTON, images.getToolRadioButtonBitmap()),
(ID_NEW.CHECK_BOX, images.getToolCheckBoxBitmap()),
(ID_NEW.RADIO_BOX, images.getToolRadioBoxBitmap()),
(ID_NEW.SPIN_CTRL, images.getToolSpinCtrlBitmap()),
(ID_NEW.SPIN_BUTTON, images.getToolSpinButtonBitmap()),
(ID_NEW.SCROLL_BAR, images.getToolScrollBarBitmap()),
(ID_NEW.SLIDER, images.getToolSliderBitmap()),
(ID_NEW.GAUGE, images.getToolGaugeBitmap()),
(ID_NEW.TREE_CTRL, images.getToolTreeCtrlBitmap()),
(ID_NEW.LIST_BOX, images.getToolListBoxBitmap()),
(ID_NEW.CHECK_LIST, images.getToolCheckListBitmap()),
(ID_NEW.LIST_CTRL, images.getToolListCtrlBitmap()),
(ID_NEW.NOTEBOOK, images.getToolNotebookBitmap()),
(ID_NEW.SPLITTER_WINDOW, images.getToolSplitterWindowBitmap()),
(ID_NEW.UNKNOWN, images.getToolUnknownBitmap())]
]
self.boxes = {}
for grp in groups:
self.AddGroup(grp[0])
for b in grp[1:]:
self.AddButton(b[0], b[1], g.pullDownMenu.createMap[b[0]])
self.SetSizerAndFit(self.sizer)
# Allow to be resized in vertical direction only
self.SetSizeHints(self.GetSize()[0], -1)
# Events
wx.EVT_COMMAND_RANGE(self, ID_NEW.PANEL, ID_NEW.LAST,
wx.wxEVT_COMMAND_BUTTON_CLICKED, g.frame.OnCreate)
wx.EVT_KEY_DOWN(self, self.OnKeyDown)
wx.EVT_KEY_UP(self, self.OnKeyUp)
def AddButton(self, id, image, text):
from wx.lib import buttons
button = buttons.GenBitmapButton(self, id, image, size=self.TOOL_SIZE,
style=wx.NO_BORDER|wx.WANTS_CHARS)
button.SetBezelWidth(0)
wx.EVT_KEY_DOWN(button, self.OnKeyDown)
wx.EVT_KEY_UP(button, self.OnKeyUp)
button.SetToolTipString(text)
self.curSizer.Add(button)
self.groups[-1][1][id] = button
def AddGroup(self, name):
# Each group is inside box
id = wx.NewId()
box = wx.StaticBox(self, id, '[+] '+name, style=wx.WANTS_CHARS)
box.show = True
box.name = name
box.gnum = len(self.groups)
box.SetFont(g.smallerFont())
box.Bind(wx.EVT_LEFT_DOWN, self.OnClickBox)
boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
boxSizer.Add((0, 4))
self.boxes[id] = box
self.curSizer = wx.GridSizer(0, 3)
boxSizer.Add(self.curSizer)
self.sizer.Add(boxSizer, 0, wx.TOP | wx.LEFT | wx.RIGHT | wx.EXPAND, 4)
self.groups.append((box,{}))
# Enable/disable group
def EnableGroup(self, gnum, enable = True):
grp = self.groups[gnum]
grp[0].Enable(enable)
for b in grp[1].values(): b.Enable(enable)
# Show/hide group
def ShowGroup(self, gnum, show = True):
grp = self.groups[gnum]
grp[0].show = show
for b in grp[1].values(): b.Show(show)
# Enable/disable group item
def EnableGroupItem(self, gnum, id, enable = True):
grp = self.groups[gnum]
grp[1][id].Enable(enable)
# Enable/disable group items
def EnableGroupItems(self, gnum, ids, enable = True):
grp = self.groups[gnum]
for id in ids:
grp[1][id].Enable(enable)
def OnClickBox(self, evt):
box = self.boxes[evt.GetId()]
# Collapse/restore static box, change label
self.ShowGroup(box.gnum, not box.show)
if box.show: box.SetLabel('[+] ' + box.name)
else: box.SetLabel('[-] ' + box.name)
self.Layout()
# Process key events
def OnKeyDown(self, evt):
if evt.GetKeyCode() == wx.WXK_CONTROL:
g.tree.ctrl = True
elif evt.GetKeyCode() == wx.WXK_SHIFT:
g.tree.shift = True
self.UpdateIfNeeded()
evt.Skip()
def OnKeyUp(self, evt):
if evt.GetKeyCode() == wx.WXK_CONTROL:
g.tree.ctrl = False
elif evt.GetKeyCode() == wx.WXK_SHIFT:
g.tree.shift = False
self.UpdateIfNeeded()
evt.Skip()
def OnMouse(self, evt):
# Update control and shift states
g.tree.ctrl = evt.ControlDown()
g.tree.shift = evt.ShiftDown()
self.UpdateIfNeeded()
evt.Skip()
# Update UI after key presses, if necessary
def UpdateIfNeeded(self):
tree = g.tree
if self.ctrl != tree.ctrl or self.shift != tree.shift:
# Enabling is needed only for ctrl
if self.ctrl != tree.ctrl: self.UpdateUI()
self.ctrl = tree.ctrl
self.shift = tree.shift
if tree.ctrl:
status = 'SBL'
elif tree.shift:
status = 'INS'
else:
status = ''
g.frame.SetStatusText(status, 1)
# Update interface
def UpdateUI(self):
if not self.IsShown(): return
# Update status bar
pullDownMenu = g.pullDownMenu
tree = g.tree
item = tree.selection
# If nothing selected, disable everything and return
if not item:
# Disable everything
for grp in range(GROUPNUM):
self.EnableGroup(grp, False)
self.state = None
return
if tree.ctrl: needInsert = True
else: needInsert = tree.NeedInsert(item)
# Enable depending on selection
if item == tree.root or needInsert and tree.GetItemParent(item) == tree.root:
state = STATE_ROOT
else:
xxx = tree.GetPyData(item).treeObject()
# Check parent for possible child nodes if inserting sibling
if needInsert: xxx = xxx.parent
if xxx.__class__ == xxxMenuBar:
state = STATE_MENUBAR
elif xxx.__class__ in [xxxToolBar, xxxTool] or \
xxx.__class__ == xxxSeparator and xxx.parent.__class__ == xxxToolBar:
state = STATE_TOOLBAR
elif xxx.__class__ in [xxxMenu, xxxMenuItem]:
state = STATE_MENU
elif xxx.__class__ == xxxStdDialogButtonSizer:
state = STATE_STDDLGBTN
else:
state = STATE_ELSE
# Enable depending on selection
if state != self.state:
# Disable everything
for grp in range(GROUPNUM):
self.EnableGroup(grp, False)
# Enable some
if state == STATE_ROOT:
self.EnableGroup(GROUP_WINDOWS, True)
self.EnableGroup(GROUP_MENUS, True)
# But disable items
self.EnableGroupItems(GROUP_MENUS,
[ ID_NEW.TOOL,
ID_NEW.MENU_ITEM,
ID_NEW.SEPARATOR ],
False)
elif state == STATE_STDDLGBTN:
pass # nothing can be added from toolbar
elif state == STATE_MENUBAR:
self.EnableGroup(GROUP_MENUS)
self.EnableGroupItems(GROUP_MENUS,
[ ID_NEW.TOOL_BAR,
ID_NEW.MENU_BAR,
ID_NEW.TOOL ],
False)
elif state == STATE_TOOLBAR:
self.EnableGroup(GROUP_MENUS)
self.EnableGroupItems(GROUP_MENUS,
[ ID_NEW.TOOL_BAR,
ID_NEW.MENU,
ID_NEW.MENU_BAR,
ID_NEW.MENU_ITEM ],
False)
self.EnableGroup(GROUP_CONTROLS)
self.EnableGroupItems(GROUP_CONTROLS,
[ ID_NEW.TREE_CTRL,
ID_NEW.NOTEBOOK,
ID_NEW.SPLITTER_WINDOW ],
False)
elif state == STATE_MENU:
self.EnableGroup(GROUP_MENUS)
self.EnableGroupItems(GROUP_MENUS,
[ ID_NEW.TOOL_BAR,
ID_NEW.MENU_BAR,
ID_NEW.TOOL ],
False)
else:
self.EnableGroup(GROUP_WINDOWS)
self.EnableGroupItems(GROUP_WINDOWS,
[ ID_NEW.FRAME,
ID_NEW.DIALOG ],
False)
self.EnableGroup(GROUP_MENUS)
self.EnableGroupItems(GROUP_MENUS,
[ ID_NEW.MENU_BAR,
ID_NEW.MENU_BAR,
ID_NEW.MENU,
ID_NEW.MENU_ITEM,
ID_NEW.TOOL,
ID_NEW.SEPARATOR ],
False)
self.EnableGroup(GROUP_SIZERS)
self.EnableGroup(GROUP_CONTROLS)
# Special case for *book (always executed)
if state == STATE_ELSE:
if xxx.__class__ in [xxxNotebook, xxxChoicebook, xxxListbook]:
self.EnableGroup(GROUP_SIZERS, False)
else:
self.EnableGroup(GROUP_SIZERS)
if not (xxx.isSizer or xxx.parent and xxx.parent.isSizer):
self.EnableGroupItem(GROUP_SIZERS, ID_NEW.SPACER, False)
if xxx.__class__ == xxxFrame:
self.EnableGroupItem(GROUP_MENUS, ID_NEW.MENU_BAR)
# Save state
self.state = state