wxWidgets/wxPython/wx/tools/XRCed/panel.py
Robin Dunn b09afc93f5 ON XP when pages are added to a Notebook their colours (and their
children's) are modified to match the theme colours for notebook pages
rather than normal panel colours.  When items are added dynamically
after the fact to the notebook pages then we need to fiddle with the
colours ourself.

Also, since xrced is importing from wxPython.wx then DC.Draw methods
now need to use the old parameter syntax.


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@25197 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
2004-01-15 22:44:52 +00:00

376 lines
15 KiB
Python

# Name: panel.py
# Purpose: XRC editor, Panel class and related
# Author: Roman Rolinsky <rolinsky@mema.ucl.ac.be>
# Created: 02.12.2002
# RCS-ID: $Id$
from xxx import * # xxx imports globals and params
from undo import *
from wxPython.html import wxHtmlWindow
# Properties panel containing notebook
class Panel(wxNotebook):
def __init__(self, parent, id = -1):
if wxPlatform != '__WXMAC__': # some problems with this style on macs
wxNotebook.__init__(self, parent, id, style=wxNB_BOTTOM)
else:
wxNotebook.__init__(self, parent, id)
global panel
g.panel = panel = self
self.modified = False
# Set common button size for parameter buttons
bTmp = wxButton(self, -1, '')
import params
params.buttonSize = (self.DLG_SZE(buttonSize)[0], bTmp.GetSize()[1])
bTmp.Destroy()
del bTmp
# List of child windows
self.pages = []
# Create scrolled windows for pages
self.page1 = wxScrolledWindow(self, -1)
sizer = wxBoxSizer()
sizer.Add(wxBoxSizer()) # dummy sizer
self.page1.SetAutoLayout(True)
self.page1.SetSizer(sizer)
self.AddPage(self.page1, 'Properties')
# Second page
self.page2 = wxScrolledWindow(self, -1)
sizer = wxBoxSizer()
sizer.Add(wxBoxSizer()) # dummy sizer
self.page2.SetAutoLayout(True)
self.page2.SetSizer(sizer)
# Cache for already used panels
self.pageCache = {} # cached property panels
self.stylePageCache = {} # cached style panels
# Dummy parent window for cache pages
self.cacheParent = wxFrame(None, -1, 'i am invisible')
# Delete child windows and recreate page sizer
def ResetPage(self, page):
topSizer = page.GetSizer()
sizer = topSizer.GetChildren()[0].GetSizer()
for w in page.GetChildren():
sizer.RemoveWindow(w)
if isinstance(w, ParamPage):
# With SetParent, we wouldn't need this
w.Reparent(self.cacheParent)
else:
w.Destroy()
topSizer.RemoveSizer(sizer)
# Create new windows
sizer = wxBoxSizer(wxVERTICAL)
# Special case - resize html window
if g.conf.panic:
topSizer.Add(sizer, 1, wxEXPAND)
else:
topSizer.Add(sizer, 0, wxALL, 5)
return sizer
def SetData(self, xxx):
self.pages = []
# First page
# Set cached or new page
# Remove current objects and sizer
sizer = self.ResetPage(self.page1)
if not xxx or (not xxx.allParams and not xxx.hasName):
if g.tree.selection:
sizer.Add(wxStaticText(self.page1, -1, 'This item has no properties.'))
else: # nothing selected
# If first time, show some help
if g.conf.panic:
html = wxHtmlWindow(self.page1, -1, wxDefaultPosition,
wxDefaultSize, wxSUNKEN_BORDER)
html.SetPage(g.helpText)
sizer.Add(html, 1, wxEXPAND)
g.conf.panic = False
else:
sizer.Add(wxStaticText(self.page1, -1, 'Select a tree item.'))
else:
g.currentXXX = xxx.treeObject()
# Normal or SizerItem page
isGBSizerItem = isinstance(xxx.parent, xxxGridBagSizer)
cacheID = (xxx.__class__, isGBSizerItem)
try:
page = self.pageCache[cacheID]
page.box.SetLabel(xxx.panelName())
page.Reparent(self.page1)
except KeyError:
page = PropPage(self.page1, xxx.panelName(), xxx)
self.pageCache[cacheID] = page
page.SetValues(xxx)
self.pages.append(page)
sizer.Add(page, 1, wxEXPAND)
if xxx.hasChild:
# Special label for child objects - they may have different GUI
cacheID = (xxx.child.__class__, xxx.__class__)
try:
page = self.pageCache[cacheID]
page.box.SetLabel(xxx.child.panelName())
page.Reparent(self.page1)
except KeyError:
page = PropPage(self.page1, xxx.child.panelName(), xxx.child)
self.pageCache[cacheID] = page
page.SetValues(xxx.child)
self.pages.append(page)
sizer.Add(page, 0, wxEXPAND | wxTOP, 5)
self.page1.Layout()
size = self.page1.GetSizer().GetMinSize()
self.page1.SetScrollbars(1, 1, size.width, size.height, 0, 0, True)
# Second page
# Create if does not exist
if xxx and xxx.treeObject().hasStyle:
xxx = xxx.treeObject()
# Simplest case: set data if class is the same
sizer = self.ResetPage(self.page2)
try:
page = self.stylePageCache[xxx.__class__]
page.Reparent(self.page2)
except KeyError:
page = StylePage(self.page2, xxx.className + ' style', xxx)
self.stylePageCache[xxx.__class__] = page
page.SetValues(xxx)
self.pages.append(page)
sizer.Add(page, 0, wxEXPAND)
# Add page if not exists
if not self.GetPageCount() == 2:
self.AddPage(self.page2, 'Style')
self.page2.Layout()
size = self.page2.GetSizer().GetMinSize()
self.page2.SetScrollbars(1, 1, size.width, size.height, 0, 0, True)
else:
# Remove page if exists
if self.GetPageCount() == 2:
self.SetSelection(0)
self.page1.Refresh()
self.RemovePage(1)
self.modified = False
def Clear(self):
self.SetData(None)
self.modified = False
# If some parameter has changed
def IsModified(self):
return self.modified
def SetModified(self, value):
# Register undo object when modifying first time
if not self.modified and value:
g.undoMan.RegisterUndo(UndoEdit())
self.modified = value
def Apply(self):
for p in self.pages: p.Apply()
################################################################################
# General class for notebook pages
class ParamPage(wxPanel):
def __init__(self, parent, xxx):
wxPanel.__init__(self, parent, -1)
self.SetBackgroundColour(parent.GetBackgroundColour())
self.SetForegroundColour(parent.GetForegroundColour())
self.xxx = xxx
# Register event handlers
for id in paramIDs.values():
EVT_CHECKBOX(self, id, self.OnCheckParams)
self.checks = {}
self.controls = {} # save python objects
self.controlName = None
def OnCheckParams(self, evt):
xxx = self.xxx
param = evt.GetEventObject().GetName()
w = self.controls[param]
w.Enable(True)
objElem = xxx.element
if evt.IsChecked():
# Ad new text node in order of allParams
w.SetValue('') # set empty (default) value
w.SetModified() # mark as changed
elem = g.tree.dom.createElement(param)
# Some classes are special
if param == 'font':
xxx.params[param] = xxxParamFont(xxx.element, elem)
elif param in xxxObject.bitmapTags:
xxx.params[param] = xxxParamBitmap(elem)
else:
xxx.params[param] = xxxParam(elem)
# Find place to put new element: first present element after param
found = False
paramStyles = xxx.allParams + xxx.styles
for p in paramStyles[paramStyles.index(param) + 1:]:
# Content params don't have same type
if xxx.params.has_key(p) and p != 'content':
found = True
break
if found:
nextTextElem = xxx.params[p].node
objElem.insertBefore(elem, nextTextElem)
else:
objElem.appendChild(elem)
else:
# Remove parameter
xxx.params[param].remove()
del xxx.params[param]
w.SetValue('')
w.modified = False # mark as not changed
w.Enable(False)
# Set modified flag (provokes undo storing is necessary)
panel.SetModified(True)
def Apply(self):
xxx = self.xxx
if self.controlName:
name = self.controlName.GetValue()
if xxx.name != name:
xxx.name = name
xxx.element.setAttribute('name', name)
for param, w in self.controls.items():
if w.modified:
paramObj = xxx.params[param]
value = w.GetValue()
if param in xxx.specials:
xxx.setSpecial(param, value)
else:
paramObj.update(value)
# Save current state
def SaveState(self):
self.origChecks = map(lambda i: (i[0], i[1].GetValue()), self.checks.items())
self.origControls = map(lambda i: (i[0], i[1].GetValue(), i[1].IsEnabled()),
self.controls.items())
if self.controlName:
self.origName = self.controlName.GetValue()
# Return original values
def GetState(self):
if self.controlName:
return (self.origChecks, self.origControls, self.origName)
else:
return (self.origChecks, self.origControls)
# Set values from undo data
def SetState(self, state):
for k,v in state[0]:
self.checks[k].SetValue(v)
for k,v,e in state[1]:
self.controls[k].SetValue(v)
self.controls[k].Enable(e)
if e: self.controls[k].modified = True
if self.controlName:
self.controlName.SetValue(state[2])
################################################################################
# Panel for displaying properties
class PropPage(ParamPage):
def __init__(self, parent, label, xxx):
ParamPage.__init__(self, parent, xxx)
self.box = wxStaticBox(self, -1, label)
self.box.SetFont(labelFont)
topSizer = wxStaticBoxSizer(self.box, wxVERTICAL)
sizer = wxFlexGridSizer(len(xxx.allParams), 2, 1, 1)
sizer.AddGrowableCol(1)
if xxx.hasName:
label = wxStaticText(self, -1, 'XML ID:', size=(100,-1))
control = ParamText(self, 'XML_name', 200)
sizer.AddMany([ (label, 0, wxALIGN_CENTER_VERTICAL),
(control, 0, wxALIGN_CENTER_VERTICAL | wxBOTTOM | wxGROW, 5) ])
self.controlName = control
for param in xxx.allParams:
present = xxx.params.has_key(param)
if param in xxx.required:
label = wxStaticText(self, paramIDs[param], param + ':',
size = (100,-1), name = param)
else:
# Notebook has one very loooooong parameter
if param == 'usenotebooksizer': sParam = 'usesizer:'
else: sParam = param + ':'
label = wxCheckBox(self, paramIDs[param], sParam,
size = (100,-1), name = param)
self.checks[param] = label
try:
typeClass = xxx.paramDict[param]
except KeyError:
try:
# Standart type
typeClass = paramDict[param]
except KeyError:
# Default
typeClass = ParamText
control = typeClass(self, param)
control.Enable(present)
sizer.AddMany([ (label, 0, wxALIGN_CENTER_VERTICAL),
(control, 0, wxALIGN_CENTER_VERTICAL | wxGROW) ])
self.controls[param] = control
topSizer.Add(sizer, 1, wxALL | wxEXPAND, 3)
self.SetAutoLayout(True)
self.SetSizer(topSizer)
topSizer.Fit(self)
def SetValues(self, xxx):
self.xxx = xxx
self.origChecks = []
self.origControls = []
# Set values, checkboxes to False, disable defaults
if xxx.hasName:
self.controlName.SetValue(xxx.name)
self.origName = xxx.name
for param in xxx.allParams:
w = self.controls[param]
w.modified = False
try:
value = xxx.params[param].value()
w.Enable(True)
w.SetValue(value)
if not param in xxx.required:
self.checks[param].SetValue(True)
self.origChecks.append((param, True))
self.origControls.append((param, value, True))
except KeyError:
self.checks[param].SetValue(False)
w.SetValue('')
w.Enable(False)
self.origChecks.append((param, False))
self.origControls.append((param, '', False))
################################################################################
# Style notebook page
class StylePage(ParamPage):
def __init__(self, parent, label, xxx):
ParamPage.__init__(self, parent, xxx)
box = wxStaticBox(self, -1, label)
box.SetFont(labelFont)
topSizer = wxStaticBoxSizer(box, wxVERTICAL)
sizer = wxFlexGridSizer(len(xxx.styles), 2, 1, 1)
sizer.AddGrowableCol(1)
for param in xxx.styles:
present = xxx.params.has_key(param)
check = wxCheckBox(self, paramIDs[param],
param + ':', size = (100,-1), name = param)
check.SetValue(present)
control = paramDict[param](self, name = param)
control.Enable(present)
sizer.AddMany([ (check, 0, wxALIGN_CENTER_VERTICAL),
(control, 0, wxALIGN_CENTER_VERTICAL | wxGROW) ])
self.checks[param] = check
self.controls[param] = control
topSizer.Add(sizer, 1, wxALL | wxEXPAND, 3)
self.SetAutoLayout(True)
self.SetSizer(topSizer)
topSizer.Fit(self)
# Set data for a cahced page
def SetValues(self, xxx):
self.xxx = xxx
self.origChecks = []
self.origControls = []
for param in xxx.styles:
present = xxx.params.has_key(param)
check = self.checks[param]
check.SetValue(present)
w = self.controls[param]
w.modified = False
if present:
value = xxx.params[param].value()
else:
value = ''
w.SetValue(value)
w.Enable(present)
self.origChecks.append((param, present))
self.origControls.append((param, value, present))