Merged wxPython 2.4.x to the 2.5 branch (Finally!!!)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@19793 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
162
wxPython/wxPython/tools/XRCed/CHANGES.txt
Normal file
@@ -0,0 +1,162 @@
|
||||
0.1.0
|
||||
-----
|
||||
|
||||
Finally implemented tools panel for almost all controls (except
|
||||
wxHtmlWindow, wxCalendarCtrl and wxGenericDirCtrl - they are too
|
||||
rarely used).
|
||||
|
||||
Changed some sizes in panel to better work with different fonts.
|
||||
|
||||
Fixed double-refreshing after Ctrl+R.
|
||||
|
||||
Maybe something else that I've forgot. It's been a looong day... :)
|
||||
|
||||
0.0.9-6
|
||||
-------
|
||||
|
||||
Added dialog unit support.
|
||||
|
||||
Dealing with non-specified required values (set to defaults, if exist).
|
||||
|
||||
Added 'minsize' parameter of sizeritem.
|
||||
|
||||
Added '-i' option to turn off translations and use international characters.
|
||||
|
||||
0.0.9-5
|
||||
-------
|
||||
|
||||
Mac platform-specific checks.
|
||||
|
||||
0.0.9-4
|
||||
-------
|
||||
|
||||
Implemented standard bitmap selection.
|
||||
|
||||
Fixed a bug in FlexGridSizer code.
|
||||
|
||||
0.0.9-3
|
||||
-------
|
||||
|
||||
File browsing (for bitmaps/icons, etc.) had a small problem when current
|
||||
file was not saved yet.
|
||||
|
||||
0.0.9-2
|
||||
-------
|
||||
|
||||
Small bug fix for initial don't panic message.
|
||||
|
||||
0.0.9-1
|
||||
-------
|
||||
|
||||
Changed program structure, reduced use of global variables (grouped in
|
||||
module 'globals', which creates an instanse 'g' of class Globals.
|
||||
|
||||
First version of undo/redo working!
|
||||
|
||||
Support for toolbars inside panels and frames.
|
||||
|
||||
Added 'container' submenu for creating Panel, Notebook and ToolBar objects.
|
||||
|
||||
wxMSW-only: added code to switch focus back to main window when test
|
||||
window is updated.
|
||||
|
||||
0.0.8-2
|
||||
-------
|
||||
|
||||
Fixed unicode problem for unicode build.
|
||||
|
||||
0.0.8-1
|
||||
-------
|
||||
|
||||
Using WX_2_4_BRANCH.
|
||||
|
||||
Added new controls: wxSpinCtrl, wxGenericDirCtrl, unknown (custom
|
||||
control), improved wxXRC format suppor (menu styles, etc.).
|
||||
|
||||
Some I18N support: parsing "encoding" attribute in XML header, later
|
||||
it can be modified in "properties" panel for "XML tree".
|
||||
|
||||
UNIX note: currently XML writing for non-ascii chars works only if
|
||||
sys.getdefaultencoding() returns good value. To do this, one has to
|
||||
put following lines to "sitecustomize.py" file:
|
||||
|
||||
# Start code segment
|
||||
import sys
|
||||
sys.setdefaultencoding('iso-8859-1') # or whatever
|
||||
# End code segment
|
||||
|
||||
0.0.7
|
||||
-----
|
||||
|
||||
Some command-line arguments.
|
||||
|
||||
"Test window" command and toolbar button.
|
||||
|
||||
New panel interphace (wxHTMLWindow is not used anymore).
|
||||
|
||||
Toggling between embedded and detached panel.
|
||||
|
||||
Cache for already used windows.
|
||||
|
||||
Current top-level control is bold, if test window shown.
|
||||
|
||||
Undo/redo broken.
|
||||
|
||||
CheckListBox does not work unless wxXRC source fixed (in both wxPytnon and
|
||||
wxWin):
|
||||
|
||||
contrib/src/xrc/xmlrsall.cpp
|
||||
45,46c45,46
|
||||
< AddHandler(new wxListCtrlXmlHandler);
|
||||
< #if CHECKLISTBOX
|
||||
---
|
||||
> AddHandler(new wxListCtrlXmlHandler);
|
||||
> #if wxUSE_CHECKLISTBOX
|
||||
|
||||
This is fixed in CVS.
|
||||
|
||||
0.0.6
|
||||
-----
|
||||
|
||||
Toolbar, bitmap, icon support (no display yet).
|
||||
|
||||
Changed parameter objects, added support for multiple parameters (like
|
||||
`growablecols').
|
||||
|
||||
Fixed double-clicking problem with tree control on Windows.
|
||||
|
||||
Some performance improovements.
|
||||
|
||||
|
||||
0.0.5
|
||||
-----
|
||||
|
||||
Added notebook with properties page and style page. Fixed some problems
|
||||
on Windows.
|
||||
|
||||
|
||||
0.0.4
|
||||
-----
|
||||
|
||||
Some fixes suggested by RD
|
||||
|
||||
|
||||
0.0.3
|
||||
-----
|
||||
|
||||
Faster preview window refresh.
|
||||
|
||||
Cut/Paste works better.
|
||||
|
||||
Some tree icons.
|
||||
|
||||
Tree item names.
|
||||
|
||||
Bugfixes.
|
||||
|
||||
|
||||
0.0.2
|
||||
-----
|
||||
|
||||
The first release.
|
||||
|
@@ -7,10 +7,11 @@
|
||||
Installation on UNIX
|
||||
--------------------
|
||||
|
||||
XRCed requires wxGTK and wxPython greater than 2.3.2, and Python 2.2 (it may
|
||||
work with earlier version, but was not tested).
|
||||
XRCed requires wxGTK and wxPython greater or equal to 2.3.3, and Python 2.2
|
||||
(it may work with earlier version, but was not tested).
|
||||
|
||||
Of course wxGTK's XRC library (libwxxrc) must be installed.
|
||||
Of course wxGTK's XRC library (libwxxrc) and it's python module must
|
||||
be installed.
|
||||
|
||||
Installation on Windows
|
||||
-----------------------
|
@@ -1,9 +1,9 @@
|
||||
TODO for XRCed
|
||||
==============
|
||||
|
||||
- Undo/Redo
|
||||
- better help
|
||||
|
||||
- menu - accel not displayed in preview
|
||||
+ undo/redo
|
||||
|
||||
+ tree icons
|
||||
|
||||
@@ -13,7 +13,7 @@ TODO for XRCed
|
||||
|
||||
+ XML indents
|
||||
|
||||
? select same notebook pages after update
|
||||
+ select same notebook pages after update
|
||||
|
||||
- put some default values in tree ctrl etc.
|
||||
|
||||
@@ -26,4 +26,4 @@ TODO for XRCed
|
||||
|
||||
+ disable some window creation when it's not valid
|
||||
|
||||
- check for memory leaks from wx objects
|
||||
- selecting object by clicking in test window
|
27
wxPython/wxPython/tools/XRCed/encode_bitmaps.py
Normal file
@@ -0,0 +1,27 @@
|
||||
|
||||
import sys, os, glob
|
||||
from wxPython.tools import img2py
|
||||
|
||||
output = 'images.py'
|
||||
|
||||
# get the list of PNG files
|
||||
files = glob.glob('src-images/*.png')
|
||||
|
||||
# Truncate the inages module
|
||||
open(output, 'w')
|
||||
|
||||
# call img2py on each file
|
||||
for file in files:
|
||||
|
||||
# extract the basename to be used as the image name
|
||||
name = os.path.splitext(os.path.basename(file))[0]
|
||||
|
||||
# encode it
|
||||
if file == files[0]:
|
||||
cmd = "-u -i -n %s %s %s" % (name, file, output)
|
||||
else:
|
||||
cmd = "-a -u -i -n %s %s %s" % (name, file, output)
|
||||
img2py.main(cmd.split())
|
||||
|
||||
|
||||
|
39
wxPython/wxPython/tools/XRCed/globals.py
Normal file
@@ -0,0 +1,39 @@
|
||||
# Name: globals.py
|
||||
# Purpose: XRC editor, global variables
|
||||
# Author: Roman Rolinsky <rolinsky@mema.ucl.ac.be>
|
||||
# Created: 02.12.2002
|
||||
# RCS-ID: $Id$
|
||||
|
||||
from wxPython.wx import *
|
||||
from wxPython.xrc import *
|
||||
|
||||
# Global constants
|
||||
|
||||
sysFont = wxSystemSettings_GetFont(wxSYS_SYSTEM_FONT)
|
||||
labelFont = wxFont(sysFont.GetPointSize(), wxDEFAULT, wxNORMAL, wxBOLD)
|
||||
modernFont = wxFont(sysFont.GetPointSize(), wxMODERN, wxNORMAL, wxNORMAL)
|
||||
smallerFont = wxFont(sysFont.GetPointSize()-2, wxDEFAULT, wxNORMAL, wxNORMAL)
|
||||
|
||||
progname = 'XRCed'
|
||||
version = '0.1.0'
|
||||
|
||||
try:
|
||||
True
|
||||
except NameError:
|
||||
True = 1==1
|
||||
False = 1==0
|
||||
|
||||
# Global variables
|
||||
|
||||
class Globals:
|
||||
panel = None
|
||||
tree = None
|
||||
frame = None
|
||||
tools = None
|
||||
undoMan = None
|
||||
testWin = None
|
||||
testWinPos = wxDefaultPosition
|
||||
currentXXX = None
|
||||
xmlFlags = wxXRC_USE_LOCALE | wxXRC_NO_SUBCLASSING
|
||||
|
||||
g = Globals()
|
23
wxPython/wxPython/tools/XRCed/license.txt
Normal file
@@ -0,0 +1,23 @@
|
||||
Copyright (c) 2002, Roman Rolinsky <rollrom@users.sourceforge.net>
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
365
wxPython/wxPython/tools/XRCed/panel.py
Normal file
@@ -0,0 +1,365 @@
|
||||
# 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
|
||||
import params
|
||||
params.buttonSize = self.DLG_SZE(buttonSize)
|
||||
|
||||
# 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()
|
||||
try:
|
||||
page = self.pageCache[xxx.__class__]
|
||||
page.Reparent(self.page1)
|
||||
except KeyError:
|
||||
page = PropPage(self.page1, xxx.className, xxx)
|
||||
self.pageCache[xxx.__class__] = 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.Reparent(self.page1)
|
||||
except KeyError:
|
||||
page = PropPage(self.page1, xxx.child.className, 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.x, size.y, 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.x, size.y, 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.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)
|
||||
box = wxStaticBox(self, -1, label)
|
||||
box.SetFont(labelFont)
|
||||
topSizer = wxStaticBoxSizer(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))
|
||||
|
@@ -4,17 +4,11 @@
|
||||
# Created: 22.08.2001
|
||||
# RCS-ID: $Id$
|
||||
|
||||
from wxPython.wx import *
|
||||
from wxPython.xrc import *
|
||||
import string
|
||||
import os.path
|
||||
from globals import *
|
||||
from types import *
|
||||
|
||||
# Object which is currently processed
|
||||
currentXXX = None
|
||||
def SetCurrentXXX(xxx):
|
||||
global currentXXX
|
||||
currentXXX = xxx
|
||||
from wxPython.xrc import *
|
||||
|
||||
genericStyles = ['wxSIMPLE_BORDER', 'wxDOUBLE_BORDER',
|
||||
'wxSUNKEN_BORDER', 'wxRAISED_BORDER',
|
||||
@@ -22,53 +16,54 @@ genericStyles = ['wxSIMPLE_BORDER', 'wxDOUBLE_BORDER',
|
||||
'wxTRANSPARENT_WINDOW', 'wxWANTS_CHARS',
|
||||
'wxNO_FULL_REPAINT_ON_RESIZE']
|
||||
|
||||
buttonSize = (55,-1)
|
||||
buttonSize = (30,-1) # in dialog units, transformed to pixels in panel ctor
|
||||
|
||||
# Class that can properly disable children
|
||||
class PPanel(wxPanel):
|
||||
def __init__(self, parent, name):
|
||||
wxPanel.__init__(self, parent, -1, name=name)
|
||||
self.modified = self.freeze = false
|
||||
self.modified = self.freeze = False
|
||||
def Enable(self, value):
|
||||
# Something strange is going on with enable so we make sure...
|
||||
for w in self.GetChildren():
|
||||
w.Enable(value)
|
||||
wxPanel.Enable(self, value)
|
||||
def SetModified(self):
|
||||
self.modified = true
|
||||
panel.SetModified(true)
|
||||
self.modified = True
|
||||
g.panel.SetModified(True)
|
||||
# Common method to set modified state
|
||||
def OnChange(self, evt):
|
||||
if self.freeze: return
|
||||
self.SetModified()
|
||||
evt.Skip()
|
||||
|
||||
class ParamBinaryOr(PPanel):
|
||||
def __init__(self, parent, name):
|
||||
PPanel.__init__(self, parent, name)
|
||||
self.ID_TEXT_CTRL = wxNewId()
|
||||
self.ID_BUTTON_CHOICES = wxNewId()
|
||||
self.SetBackgroundColour(panel.GetBackgroundColour())
|
||||
self.SetBackgroundColour(g.panel.GetBackgroundColour())
|
||||
sizer = wxBoxSizer()
|
||||
self.text = wxTextCtrl(self, self.ID_TEXT_CTRL, size=wxSize(200,-1))
|
||||
sizer.Add(self.text, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5)
|
||||
self.button = wxButton(self, self.ID_BUTTON_CHOICES, 'Edit...', size=buttonSize)
|
||||
sizer.Add(self.button, 0, wxALIGN_CENTER_VERTICAL)
|
||||
self.SetAutoLayout(true)
|
||||
self.SetAutoLayout(True)
|
||||
self.SetSizer(sizer)
|
||||
sizer.Fit(self)
|
||||
EVT_BUTTON(self, self.ID_BUTTON_CHOICES, self.OnButtonChoices)
|
||||
EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange)
|
||||
def OnChange(self, evt):
|
||||
if self.freeze: return
|
||||
self.SetModified()
|
||||
evt.Skip()
|
||||
def GetValue(self):
|
||||
return self.text.GetValue()
|
||||
def SetValue(self, value):
|
||||
self.freeze = true
|
||||
self.freeze = True
|
||||
self.text.SetValue(value)
|
||||
self.freeze = false
|
||||
self.freeze = False
|
||||
def OnButtonChoices(self, evt):
|
||||
dlg = wxDialog(self, -1, 'Choices')
|
||||
topSizer = wxBoxSizer(wxVERTICAL)
|
||||
listBox = wxCheckListBox(dlg, -1, choices=self.values, size=(250,200))
|
||||
value = map(string.strip, string.split(self.text.GetValue(), '|'))
|
||||
value = map(string.strip, self.text.GetValue().split('|'))
|
||||
if value == ['']: value = []
|
||||
ignored = []
|
||||
for i in value:
|
||||
@@ -89,7 +84,7 @@ class ParamBinaryOr(PPanel):
|
||||
sizer.Add(0, 0, 1)
|
||||
sizer.Add(wxButton(dlg, wxID_CANCEL, 'Cancel'))
|
||||
topSizer.Add(sizer, 0, wxALL | wxEXPAND, 10)
|
||||
dlg.SetAutoLayout(true)
|
||||
dlg.SetAutoLayout(True)
|
||||
dlg.SetSizer(topSizer)
|
||||
topSizer.Fit(dlg)
|
||||
dlg.Center()
|
||||
@@ -109,7 +104,7 @@ class ParamBinaryOr(PPanel):
|
||||
|
||||
class ParamFlag(ParamBinaryOr):
|
||||
values = ['wxTOP', 'wxBOTTOM', 'wxLEFT', 'wxRIGHT', 'wxALL',
|
||||
'wxEXPAND', 'wxSHAPED', 'wxALIGN_CENTRE', 'wxALIGN_RIGHT',
|
||||
'wxEXPAND', 'wxGROW', 'wxSHAPED', 'wxALIGN_CENTRE', 'wxALIGN_RIGHT',
|
||||
'wxALIGN_BOTTOM', 'wxALIGN_CENTRE_VERTICAL',
|
||||
'wxALIGN_CENTRE_HORIZONTAL']
|
||||
equal = {'wxALIGN_CENTER': 'wxALIGN_CENTRE',
|
||||
@@ -121,18 +116,18 @@ class ParamFlag(ParamBinaryOr):
|
||||
class ParamStyle(ParamBinaryOr):
|
||||
equal = {'wxALIGN_CENTER': 'wxALIGN_CENTRE'}
|
||||
def __init__(self, parent, name):
|
||||
self.values = currentXXX.winStyles + genericStyles
|
||||
self.values = g.currentXXX.winStyles + genericStyles
|
||||
ParamBinaryOr.__init__(self, parent, name)
|
||||
|
||||
class ParamNonGenericStyle(ParamBinaryOr):
|
||||
def __init__(self, parent, name):
|
||||
self.values = currentXXX.winStyles
|
||||
self.values = g.currentXXX.winStyles
|
||||
ParamBinaryOr.__init__(self, parent, name)
|
||||
|
||||
class ParamExStyle(ParamBinaryOr):
|
||||
def __init__(self, parent, name):
|
||||
if currentXXX:
|
||||
self.values = currentXXX.exStyles # constant at the moment
|
||||
if g.currentXXX:
|
||||
self.values = g.currentXXX.exStyles # constant at the moment
|
||||
else:
|
||||
self.values = []
|
||||
ParamBinaryOr.__init__(self, parent, name)
|
||||
@@ -142,33 +137,29 @@ class ParamColour(PPanel):
|
||||
PPanel.__init__(self, parent, name)
|
||||
self.ID_TEXT_CTRL = wxNewId()
|
||||
self.ID_BUTTON = wxNewId()
|
||||
self.SetBackgroundColour(panel.GetBackgroundColour())
|
||||
self.SetBackgroundColour(g.panel.GetBackgroundColour())
|
||||
sizer = wxBoxSizer()
|
||||
self.text = wxTextCtrl(self, self.ID_TEXT_CTRL, size=(65,-1))
|
||||
sizer.Add(self.text, 0, wxRIGHT, 5)
|
||||
self.button = wxPanel(self, self.ID_BUTTON, wxDefaultPosition, wxSize(20, 20))
|
||||
sizer.Add(self.button, 0, wxGROW)
|
||||
self.SetAutoLayout(true)
|
||||
self.SetAutoLayout(True)
|
||||
self.SetSizer(sizer)
|
||||
sizer.Fit(self)
|
||||
self.textModified = false
|
||||
self.textModified = False
|
||||
EVT_PAINT(self.button, self.OnPaintButton)
|
||||
EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange)
|
||||
EVT_LEFT_DOWN(self.button, self.OnLeftDown)
|
||||
def GetValue(self):
|
||||
return self.text.GetValue()
|
||||
def SetValue(self, value):
|
||||
self.freeze = true
|
||||
self.freeze = True
|
||||
if not value: value = '#FFFFFF'
|
||||
self.text.SetValue(str(value)) # update text ctrl
|
||||
colour = wxColour(int(value[1:3], 16), int(value[3:5], 16), int(value[5:7], 16))
|
||||
self.button.SetBackgroundColour(colour)
|
||||
self.button.Refresh()
|
||||
self.freeze = false
|
||||
def OnChange(self, evt):
|
||||
if self.freeze: return
|
||||
self.SetModified()
|
||||
evt.Skip()
|
||||
self.freeze = False
|
||||
def OnPaintButton(self, evt):
|
||||
dc = wxPaintDC(self.button)
|
||||
dc.SetBrush(wxTRANSPARENT_BRUSH)
|
||||
@@ -206,23 +197,21 @@ class ParamFont(PPanel):
|
||||
PPanel.__init__(self, parent, name)
|
||||
self.ID_TEXT_CTRL = wxNewId()
|
||||
self.ID_BUTTON_SELECT = wxNewId()
|
||||
self.SetBackgroundColour(panel.GetBackgroundColour())
|
||||
self.SetBackgroundColour(g.panel.GetBackgroundColour())
|
||||
sizer = wxBoxSizer()
|
||||
self.text = wxTextCtrl(self, self.ID_TEXT_CTRL, size=wxSize(200,-1))
|
||||
sizer.Add(self.text, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5)
|
||||
self.button = wxButton(self, self.ID_BUTTON_SELECT, 'Select...', size=buttonSize)
|
||||
sizer.Add(self.button, 0, wxALIGN_CENTER_VERTICAL)
|
||||
self.SetAutoLayout(true)
|
||||
self.SetAutoLayout(True)
|
||||
self.SetSizer(sizer)
|
||||
sizer.Fit(self)
|
||||
self.textModified = false
|
||||
self.textModified = False
|
||||
EVT_BUTTON(self, self.ID_BUTTON_SELECT, self.OnButtonSelect)
|
||||
EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange)
|
||||
def OnChange(self, evt):
|
||||
if self.freeze: return
|
||||
self.SetModified()
|
||||
self.textModified = true
|
||||
evt.Skip()
|
||||
PPanel.OnChange(self, evt)
|
||||
self.textModified = True
|
||||
def _defaultValue(self):
|
||||
return ['12', 'default', 'normal', 'normal', '0', '', '']
|
||||
def GetValue(self):
|
||||
@@ -234,11 +223,11 @@ class ParamFont(PPanel):
|
||||
return self._defaultValue()
|
||||
return self.value
|
||||
def SetValue(self, value):
|
||||
self.freeze = true # disable other handlers
|
||||
self.freeze = True # disable other handlers
|
||||
if not value: value = self._defaultValue()
|
||||
self.value = value
|
||||
self.text.SetValue(str(value)) # update text ctrl
|
||||
self.freeze = false
|
||||
self.freeze = False
|
||||
def OnButtonSelect(self, evt):
|
||||
if self.textModified: # text has newer value
|
||||
try:
|
||||
@@ -255,23 +244,23 @@ class ParamFont(PPanel):
|
||||
face = ''
|
||||
enc = wxFONTENCODING_DEFAULT
|
||||
# Fall back to default if exceptions
|
||||
error = false
|
||||
error = False
|
||||
try:
|
||||
try: size = int(self.value[0])
|
||||
except ValueError: error = true
|
||||
except ValueError: error = True
|
||||
try: family = fontFamiliesXml2wx[self.value[1]]
|
||||
except KeyError: error = true
|
||||
except KeyError: error = True
|
||||
try: style = fontStylesXml2wx[self.value[2]]
|
||||
except KeyError: error = true
|
||||
except KeyError: error = True
|
||||
try: weight = fontWeightsXml2wx[self.value[3]]
|
||||
except KeyError: error = true
|
||||
except KeyError: error = True
|
||||
try: underlined = int(self.value[4])
|
||||
except ValueError: error = true
|
||||
except ValueError: error = True
|
||||
face = self.value[5]
|
||||
mapper = wxFontMapper()
|
||||
if not self.value[6]: enc = mapper.CharsetToEncoding(self.value[6])
|
||||
except IndexError:
|
||||
error = true
|
||||
error = True
|
||||
if error: wxLogError('Invalid font specification')
|
||||
if enc == wxFONTENCODING_DEFAULT: enc = wxFONTENCODING_SYSTEM
|
||||
font = wxFont(size, family, style, weight, underlined, face, enc)
|
||||
@@ -291,7 +280,7 @@ class ParamFont(PPanel):
|
||||
# Add ignored flags
|
||||
self.SetValue(value)
|
||||
self.SetModified()
|
||||
self.textModified = false
|
||||
self.textModified = False
|
||||
dlg.Destroy()
|
||||
|
||||
################################################################################
|
||||
@@ -302,60 +291,108 @@ class ParamInt(PPanel):
|
||||
self.ID_SPIN_CTRL = wxNewId()
|
||||
sizer = wxBoxSizer()
|
||||
self.spin = wxSpinCtrl(self, self.ID_SPIN_CTRL, size=wxSize(50,-1))
|
||||
self.SetBackgroundColour(panel.GetBackgroundColour())
|
||||
self.SetBackgroundColour(g.panel.GetBackgroundColour())
|
||||
sizer.Add(self.spin)
|
||||
self.SetAutoLayout(true)
|
||||
self.SetAutoLayout(True)
|
||||
self.SetSizer(sizer)
|
||||
sizer.Fit(self)
|
||||
EVT_SPINCTRL(self, self.ID_SPIN_CTRL, self.OnChange)
|
||||
def GetValue(self):
|
||||
return str(self.spin.GetValue())
|
||||
def SetValue(self, value):
|
||||
self.freeze = true
|
||||
self.freeze = True
|
||||
if not value: value = 0
|
||||
self.spin.SetValue(int(value))
|
||||
self.freeze = false
|
||||
def OnChange(self, evt):
|
||||
if self.freeze: return
|
||||
self.SetModified()
|
||||
evt.Skip()
|
||||
self.freeze = False
|
||||
|
||||
# Same as int but allows dialog units (XXXd)
|
||||
class ParamUnit(PPanel):
|
||||
def __init__(self, parent, name):
|
||||
PPanel.__init__(self, parent, name)
|
||||
self.ID_TEXT_CTRL = wxNewId()
|
||||
self.ID_SPIN_BUTTON = wxNewId()
|
||||
sizer = wxBoxSizer()
|
||||
self.text = wxTextCtrl(self, self.ID_TEXT_CTRL, size=wxSize(35,-1))
|
||||
self.spin = wxSpinButton(self, self.ID_SPIN_BUTTON, style = wxSP_VERTICAL)
|
||||
self.spin.SetRange(-10000, 10000)
|
||||
self.SetBackgroundColour(g.panel.GetBackgroundColour())
|
||||
sizer.Add(self.text, 0, wxEXPAND | wxRIGHT, 2)
|
||||
sizer.Add(self.spin)
|
||||
self.SetAutoLayout(True)
|
||||
self.SetSizer(sizer)
|
||||
sizer.Fit(self)
|
||||
EVT_SPIN_UP(self, self.ID_SPIN_BUTTON, self.OnSpinUp)
|
||||
EVT_SPIN_DOWN(self, self.ID_SPIN_BUTTON, self.OnSpinDown)
|
||||
def GetValue(self):
|
||||
return self.text.GetValue()
|
||||
def SetValue(self, value):
|
||||
self.freeze = True
|
||||
if not value: value = '0'
|
||||
self.text.SetValue(value)
|
||||
self.freeze = False
|
||||
def Change(self, x):
|
||||
# Check if we are working with dialog units
|
||||
value = self.text.GetValue()
|
||||
units = ''
|
||||
if value[-1].upper() == 'D':
|
||||
units = value[-1]
|
||||
value = value[:-1]
|
||||
try:
|
||||
intValue = int(value) + x
|
||||
self.spin.SetValue(intValue)
|
||||
self.text.SetValue(str(intValue) + units)
|
||||
self.SetModified()
|
||||
except:
|
||||
# !!! Strange, if I use wxLogWarning, event is re-generated
|
||||
print 'incorrect unit format'
|
||||
def OnSpinUp(self, evt):
|
||||
self.Change(1)
|
||||
def OnSpinDown(self, evt):
|
||||
self.Change(-1)
|
||||
|
||||
class ParamText(PPanel):
|
||||
def __init__(self, parent, name, textWidth=200):
|
||||
def __init__(self, parent, name, textWidth=-1):
|
||||
PPanel.__init__(self, parent, name)
|
||||
self.ID_TEXT_CTRL = wxNewId()
|
||||
# We use sizer even here to have the same size of text control
|
||||
sizer = wxBoxSizer()
|
||||
self.SetBackgroundColour(panel.GetBackgroundColour())
|
||||
self.SetBackgroundColour(g.panel.GetBackgroundColour())
|
||||
self.text = wxTextCtrl(self, self.ID_TEXT_CTRL, size=wxSize(textWidth,-1))
|
||||
sizer.Add(self.text, 0, wxALIGN_CENTER_VERTICAL)
|
||||
self.SetAutoLayout(true)
|
||||
if textWidth == -1: option = 1
|
||||
else: option = 0
|
||||
sizer.Add(self.text, option, wxALIGN_CENTER_VERTICAL)
|
||||
self.SetAutoLayout(True)
|
||||
self.SetSizer(sizer)
|
||||
sizer.Fit(self)
|
||||
EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange)
|
||||
def GetValue(self):
|
||||
return self.text.GetValue()
|
||||
def SetValue(self, value):
|
||||
self.freeze = true # disable other handlers
|
||||
self.freeze = True # disable other handlers
|
||||
self.text.SetValue(value)
|
||||
self.freeze = false # disable other handlers
|
||||
def OnChange(self, evt):
|
||||
if self.freeze: return
|
||||
self.SetModified()
|
||||
evt.Skip()
|
||||
self.freeze = False # disable other handlers
|
||||
|
||||
class ParamAccel(ParamText):
|
||||
def __init__(self, parent, name):
|
||||
ParamText.__init__(self, parent, name, 50)
|
||||
ParamText.__init__(self, parent, name, 100)
|
||||
|
||||
class ParamPosSize(ParamText):
|
||||
def __init__(self, parent, name):
|
||||
ParamText.__init__(self, parent, name, 80)
|
||||
|
||||
class ParamLabel(ParamText):
|
||||
def __init__(self, parent, name):
|
||||
ParamText.__init__(self, parent, name, 200)
|
||||
|
||||
class ParamEncoding(ParamText):
|
||||
def __init__(self, parent, name):
|
||||
ParamText.__init__(self, parent, name, 100)
|
||||
|
||||
class ContentDialog(wxDialogPtr):
|
||||
def __init__(self, parent, value):
|
||||
# Is this normal???
|
||||
w = frame.res.LoadDialog(parent, 'DIALOG_CONTENT')
|
||||
# Load from resource
|
||||
w = g.frame.res.LoadDialog(parent, 'DIALOG_CONTENT')
|
||||
# Perform initialization with class pointer
|
||||
wxDialogPtr.__init__(self, w.this)
|
||||
self.thisown = 1
|
||||
self.Center()
|
||||
@@ -363,7 +400,7 @@ class ContentDialog(wxDialogPtr):
|
||||
# Set list items
|
||||
for v in value:
|
||||
self.list.Append(v)
|
||||
self.SetAutoLayout(true)
|
||||
self.SetAutoLayout(True)
|
||||
self.GetSizer().Fit(self)
|
||||
# Callbacks
|
||||
self.ID_BUTTON_APPEND = XMLID('BUTTON_APPEND')
|
||||
@@ -405,8 +442,7 @@ class ContentDialog(wxDialogPtr):
|
||||
|
||||
class ContentCheckListDialog(wxDialogPtr):
|
||||
def __init__(self, parent, value):
|
||||
# Is this normal???
|
||||
w = frame.res.LoadDialog(parent, 'DIALOG_CONTENT_CHECK_LIST')
|
||||
w = g.frame.res.LoadDialog(parent, 'DIALOG_CONTENT_CHECK_LIST')
|
||||
wxDialogPtr.__init__(self, w.this)
|
||||
self.thisown = 1
|
||||
self.Center()
|
||||
@@ -417,7 +453,7 @@ class ContentCheckListDialog(wxDialogPtr):
|
||||
self.list.Append(v)
|
||||
self.list.Check(i, ch)
|
||||
i += 1
|
||||
self.SetAutoLayout(true)
|
||||
self.SetAutoLayout(True)
|
||||
self.GetSizer().Fit(self)
|
||||
# Callbacks
|
||||
self.ID_BUTTON_APPEND = XMLID('BUTTON_APPEND')
|
||||
@@ -468,23 +504,21 @@ class ParamContent(PPanel):
|
||||
PPanel.__init__(self, parent, name)
|
||||
self.ID_TEXT_CTRL = wxNewId()
|
||||
self.ID_BUTTON_EDIT = wxNewId()
|
||||
self.SetBackgroundColour(panel.GetBackgroundColour())
|
||||
self.SetBackgroundColour(g.panel.GetBackgroundColour())
|
||||
sizer = wxBoxSizer()
|
||||
self.text = wxTextCtrl(self, self.ID_TEXT_CTRL, size=wxSize(200,-1))
|
||||
sizer.Add(self.text, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5)
|
||||
self.button = wxButton(self, self.ID_BUTTON_EDIT, 'Edit...', size=buttonSize)
|
||||
sizer.Add(self.button, 0, wxALIGN_CENTER_VERTICAL)
|
||||
self.SetAutoLayout(true)
|
||||
self.SetAutoLayout(True)
|
||||
self.SetSizer(sizer)
|
||||
sizer.Fit(self)
|
||||
self.textModified = false
|
||||
self.textModified = False
|
||||
EVT_BUTTON(self, self.ID_BUTTON_EDIT, self.OnButtonEdit)
|
||||
EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange)
|
||||
def OnChange(self, evt):
|
||||
if self.freeze: return
|
||||
self.SetModified()
|
||||
self.textModified = true
|
||||
evt.Skip()
|
||||
PPanel.OnChange(self, evt)
|
||||
self.textModified = True
|
||||
def GetValue(self):
|
||||
if self.textModified: # text has newer value
|
||||
try:
|
||||
@@ -494,11 +528,11 @@ class ParamContent(PPanel):
|
||||
return []
|
||||
return self.value
|
||||
def SetValue(self, value):
|
||||
self.freeze = true
|
||||
self.freeze = True
|
||||
if not value: value = []
|
||||
self.value = value
|
||||
self.text.SetValue(str(value)) # update text ctrl
|
||||
self.freeze = false
|
||||
self.freeze = False
|
||||
def OnButtonEdit(self, evt):
|
||||
if self.textModified: # text has newer value
|
||||
try:
|
||||
@@ -514,7 +548,7 @@ class ParamContent(PPanel):
|
||||
# Add ignored flags
|
||||
self.SetValue(value)
|
||||
self.SetModified()
|
||||
self.textModified = false
|
||||
self.textModified = False
|
||||
dlg.Destroy()
|
||||
|
||||
# CheckList content
|
||||
@@ -536,13 +570,13 @@ class ParamContentCheckList(ParamContent):
|
||||
# Add ignored flags
|
||||
self.SetValue(value)
|
||||
self.SetModified()
|
||||
self.textModified = false
|
||||
self.textModified = False
|
||||
dlg.Destroy()
|
||||
|
||||
class IntListDialog(wxDialogPtr):
|
||||
def __init__(self, parent, value):
|
||||
# Is this normal???
|
||||
w = frame.res.LoadDialog(parent, 'DIALOG_INTLIST')
|
||||
w = g.frame.res.LoadDialog(parent, 'DIALOG_INTLIST')
|
||||
wxDialogPtr.__init__(self, w.this)
|
||||
self.thisown = 1
|
||||
self.Center()
|
||||
@@ -554,7 +588,7 @@ class IntListDialog(wxDialogPtr):
|
||||
wxLogError('Invalid item type')
|
||||
else:
|
||||
self.list.Append(str(v))
|
||||
self.SetAutoLayout(true)
|
||||
self.SetAutoLayout(True)
|
||||
self.GetSizer().Fit(self)
|
||||
# Callbacks
|
||||
self.ID_BUTTON_ADD = XMLID('BUTTON_ADD')
|
||||
@@ -571,10 +605,10 @@ class IntListDialog(wxDialogPtr):
|
||||
i = self.list.FindString(s)
|
||||
if i == -1: # ignore non-unique
|
||||
# Find place to insert
|
||||
found = false
|
||||
found = False
|
||||
for i in range(self.list.Number()):
|
||||
if int(self.list.GetString(i)) > v:
|
||||
found = true
|
||||
found = True
|
||||
break
|
||||
if found: self.list.InsertItems([s], i)
|
||||
else: self.list.Append(s)
|
||||
@@ -605,7 +639,7 @@ class ParamIntList(ParamContent):
|
||||
# Add ignored flags
|
||||
self.SetValue(value)
|
||||
self.SetModified()
|
||||
self.textModified = false
|
||||
self.textModified = False
|
||||
dlg.Destroy()
|
||||
|
||||
# Boxless radiobox
|
||||
@@ -613,22 +647,22 @@ class RadioBox(PPanel):
|
||||
def __init__(self, parent, id, choices,
|
||||
pos=wxDefaultPosition, name='radiobox'):
|
||||
PPanel.__init__(self, parent, name)
|
||||
self.SetBackgroundColour(panel.GetBackgroundColour())
|
||||
self.SetBackgroundColour(g.panel.GetBackgroundColour())
|
||||
self.choices = choices
|
||||
topSizer = wxBoxSizer()
|
||||
for i in choices:
|
||||
button = wxRadioButton(self, -1, i, name=i)
|
||||
topSizer.Add(button)
|
||||
EVT_RADIOBUTTON(self, button.GetId(), self.OnRadioChoice)
|
||||
self.SetAutoLayout(true)
|
||||
self.SetAutoLayout(True)
|
||||
self.SetSizer(topSizer)
|
||||
topSizer.Fit(self)
|
||||
def SetStringSelection(self, value):
|
||||
self.freeze = true
|
||||
self.freeze = True
|
||||
for i in self.choices:
|
||||
self.FindWindowByName(i).SetValue(i == value)
|
||||
self.value = value
|
||||
self.freeze = false
|
||||
self.freeze = False
|
||||
def OnRadioChoice(self, evt):
|
||||
if self.freeze: return
|
||||
if evt.GetSelection():
|
||||
@@ -664,59 +698,140 @@ class ParamFile(PPanel):
|
||||
PPanel.__init__(self, parent, name)
|
||||
self.ID_TEXT_CTRL = wxNewId()
|
||||
self.ID_BUTTON_BROWSE = wxNewId()
|
||||
self.SetBackgroundColour(panel.GetBackgroundColour())
|
||||
self.SetBackgroundColour(g.panel.GetBackgroundColour())
|
||||
sizer = wxBoxSizer()
|
||||
self.text = wxTextCtrl(self, self.ID_TEXT_CTRL, size=wxSize(200,-1))
|
||||
sizer.Add(self.text, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5)
|
||||
self.button = wxButton(self, self.ID_BUTTON_BROWSE, 'Browse...',size=buttonSize)
|
||||
sizer.Add(self.button, 0, wxALIGN_CENTER_VERTICAL)
|
||||
self.SetAutoLayout(true)
|
||||
self.SetAutoLayout(True)
|
||||
self.SetSizer(sizer)
|
||||
sizer.Fit(self)
|
||||
self.textModified = false
|
||||
self.textModified = False
|
||||
EVT_BUTTON(self, self.ID_BUTTON_BROWSE, self.OnButtonBrowse)
|
||||
EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange)
|
||||
def OnChange(self, evt):
|
||||
if self.freeze: return
|
||||
self.SetModified()
|
||||
self.textModified = true
|
||||
evt.Skip()
|
||||
PPanel.OnChange(self, evt)
|
||||
self.textModified = True
|
||||
def GetValue(self):
|
||||
if self.textModified: # text has newer value
|
||||
return self.text.GetValue()
|
||||
return self.value
|
||||
def SetValue(self, value):
|
||||
self.freeze = true
|
||||
self.freeze = True
|
||||
self.value = value
|
||||
self.text.SetValue(value) # update text ctrl
|
||||
self.freeze = false
|
||||
self.freeze = False
|
||||
def OnButtonBrowse(self, evt):
|
||||
if self.textModified: # text has newer value
|
||||
self.value = self.text.GetValue()
|
||||
dlg = wxFileDialog(self,
|
||||
defaultDir = os.path.dirname(self.value),
|
||||
defaultDir = os.path.abspath(os.path.dirname(self.value)),
|
||||
defaultFile = os.path.basename(self.value))
|
||||
if dlg.ShowModal() == wxID_OK:
|
||||
# Make relative
|
||||
common = os.path.commonprefix([os.path.abspath(frame.dataFile),
|
||||
dlg.GetPath()])
|
||||
# Get common part of selected path and current
|
||||
if g.frame.dataFile:
|
||||
curpath = os.path.abspath(g.frame.dataFile)
|
||||
else:
|
||||
curpath = os.path.join(os.getcwd(), '')
|
||||
common = os.path.commonprefix([curpath, dlg.GetPath()])
|
||||
self.SetValue(dlg.GetPath()[len(common):])
|
||||
self.SetModified()
|
||||
self.textModified = false
|
||||
self.textModified = False
|
||||
dlg.Destroy()
|
||||
|
||||
class ParamBitmap(PPanel):
|
||||
def __init__(self, parent, name):
|
||||
# Load from resource
|
||||
w = g.frame.res.LoadPanel(parent, 'PANEL_BITMAP')
|
||||
# Perform initialization with class pointer
|
||||
wxPanelPtr.__init__(self, w.this)
|
||||
self.thisown = 1
|
||||
self.modified = self.freeze = False
|
||||
self.SetBackgroundColour(g.panel.GetBackgroundColour())
|
||||
self.radio_std = self.FindWindowByName('RADIO_STD')
|
||||
self.radio_file = self.FindWindowByName('RADIO_FILE')
|
||||
self.combo = self.FindWindowByName('COMBO_STD')
|
||||
self.text = self.FindWindowByName('TEXT_FILE')
|
||||
self.button = self.FindWindowByName('BUTTON_BROWSE')
|
||||
self.textModified = False
|
||||
self.SetAutoLayout(True)
|
||||
self.GetSizer().SetMinSize((260, -1))
|
||||
self.GetSizer().Fit(self)
|
||||
EVT_RADIOBUTTON(self, XMLID('RADIO_STD'), self.OnRadioStd)
|
||||
EVT_RADIOBUTTON(self, XMLID('RADIO_FILE'), self.OnRadioFile)
|
||||
EVT_BUTTON(self, XMLID('BUTTON_BROWSE'), self.OnButtonBrowse)
|
||||
EVT_COMBOBOX(self, XMLID('COMBO_STD'), self.OnCombo)
|
||||
EVT_TEXT(self, XMLID('COMBO_STD'), self.OnChange)
|
||||
EVT_TEXT(self, XMLID('TEXT_FILE'), self.OnChange)
|
||||
def OnRadioStd(self, evt):
|
||||
self.SetModified()
|
||||
self.SetValue(['wxART_MISSING_IMAGE',''])
|
||||
def OnRadioFile(self, evt):
|
||||
self.SetModified()
|
||||
self.SetValue(['',''])
|
||||
def updateRadios(self):
|
||||
if self.value[0]:
|
||||
self.radio_std.SetValue(True)
|
||||
self.text.Enable(False)
|
||||
self.button.Enable(False)
|
||||
self.combo.Enable(True)
|
||||
else:
|
||||
self.radio_file.SetValue(True)
|
||||
self.text.Enable(True)
|
||||
self.button.Enable(True)
|
||||
self.combo.Enable(False)
|
||||
def OnChange(self, evt):
|
||||
PPanel.OnChange(self, evt)
|
||||
self.textModified = True
|
||||
def OnCombo(self, evt):
|
||||
PPanel.OnChange(self, evt)
|
||||
self.value[0] = self.combo.GetValue()
|
||||
def GetValue(self):
|
||||
if self.textModified: # text has newer value
|
||||
return [self.combo.GetValue(), self.text.GetValue()]
|
||||
return self.value
|
||||
def SetValue(self, value):
|
||||
self.freeze = True
|
||||
if not value:
|
||||
self.value = ['', '']
|
||||
else:
|
||||
self.value = value
|
||||
self.combo.SetValue(self.value[0])
|
||||
self.text.SetValue(self.value[1]) # update text ctrl
|
||||
self.updateRadios()
|
||||
self.freeze = False
|
||||
def OnButtonBrowse(self, evt):
|
||||
if self.textModified: # text has newer value
|
||||
self.value[1] = self.text.GetValue()
|
||||
dlg = wxFileDialog(self,
|
||||
defaultDir = os.path.abspath(os.path.dirname(self.value[1])),
|
||||
defaultFile = os.path.basename(self.value[1]))
|
||||
if dlg.ShowModal() == wxID_OK:
|
||||
# Get common part of selected path and current
|
||||
if g.frame.dataFile:
|
||||
curpath = os.path.abspath(g.frame.dataFile)
|
||||
else:
|
||||
curpath = os.path.join(os.getcwd(), '')
|
||||
common = os.path.commonprefix([curpath, dlg.GetPath()])
|
||||
self.SetValue(['', dlg.GetPath()[len(common):]])
|
||||
self.SetModified()
|
||||
self.textModified = False
|
||||
dlg.Destroy()
|
||||
|
||||
paramDict = {
|
||||
'flag': ParamFlag,
|
||||
'style': ParamStyle, 'exstyle': ParamExStyle,
|
||||
'pos': ParamPosSize, 'size': ParamPosSize,
|
||||
'border': ParamInt, 'cols': ParamInt, 'rows': ParamInt,
|
||||
'vgap': ParamInt, 'hgap': ParamInt,
|
||||
'checkable': ParamBool, 'accel': ParamAccel,
|
||||
'border': ParamUnit, 'cols': ParamInt, 'rows': ParamInt,
|
||||
'vgap': ParamUnit, 'hgap': ParamUnit,
|
||||
'checkable': ParamBool, 'checked': ParamBool, 'radio': ParamBool,
|
||||
'accel': ParamAccel,
|
||||
'label': ParamText, 'title': ParamText, 'value': ParamText,
|
||||
'content': ParamContent, 'selection': ParamInt,
|
||||
'min': ParamInt, 'max': ParamInt,
|
||||
'fg': ParamColour, 'bg': ParamColour, 'font': ParamFont,
|
||||
'enabled': ParamBool, 'focused': ParamBool, 'hidden': ParamBool,
|
||||
'tooltip': ParamText, 'bitmap': ParamFile, 'icon': ParamFile,
|
||||
'tooltip': ParamText, 'bitmap': ParamBitmap, 'icon': ParamBitmap,
|
||||
'label': ParamLabel, 'encoding': ParamEncoding
|
||||
}
|
||||
|
||||
|
24
wxPython/wxPython/tools/XRCed/sawfishrc
Normal file
@@ -0,0 +1,24 @@
|
||||
(require 'sawmill-defaults)
|
||||
|
||||
;;; Define two hooks to reset focus behavior while mapping test window
|
||||
|
||||
(define (xrced-match-window-before w)
|
||||
(setq prop (aref (get-x-text-property w 'WM_CLASS) 0))
|
||||
(cond ((equal prop "_XRCED_T_W")
|
||||
(setq transients-get-focus-b transients-get-focus)
|
||||
(setq transients-get-focus nil)
|
||||
(setq focus-windows-when-mapped-b focus-windows-when-mapped)
|
||||
(setq focus-windows-when-mapped nil)
|
||||
)
|
||||
)
|
||||
)
|
||||
(define (xrced-match-window-after w)
|
||||
(setq prop (aref (get-x-text-property w 'WM_CLASS) 0))
|
||||
(cond ((equal prop "_XRCED_T_W")
|
||||
(setq transients-get-focus-b transients-get-focus-b)
|
||||
(setq focus-windows-when-mapped focus-windows-when-mapped-b)
|
||||
)
|
||||
)
|
||||
)
|
||||
(add-hook 'map-notify-hook xrced-match-window-before)
|
||||
(add-hook 'map-notify-hook xrced-match-window-after 't)
|
BIN
wxPython/wxPython/tools/XRCed/src-images/AutoRefresh.png
Normal file
After Width: | Height: | Size: 316 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/Copy.png
Normal file
After Width: | Height: | Size: 273 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/Cut.png
Normal file
After Width: | Height: | Size: 255 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/Icon.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
wxPython/wxPython/tools/XRCed/src-images/New.png
Normal file
After Width: | Height: | Size: 190 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/Open.png
Normal file
After Width: | Height: | Size: 274 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/Paste.png
Normal file
After Width: | Height: | Size: 280 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/Redo.png
Normal file
After Width: | Height: | Size: 252 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/Refresh.png
Normal file
After Width: | Height: | Size: 275 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/Save.png
Normal file
After Width: | Height: | Size: 207 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/Test.png
Normal file
After Width: | Height: | Size: 350 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/ToolBitmapButton.png
Normal file
After Width: | Height: | Size: 616 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/ToolBoxSizer.png
Normal file
After Width: | Height: | Size: 141 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/ToolButton.png
Normal file
After Width: | Height: | Size: 182 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/ToolCheckBox.png
Normal file
After Width: | Height: | Size: 117 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/ToolCheckList.png
Normal file
After Width: | Height: | Size: 233 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/ToolChoice.png
Normal file
After Width: | Height: | Size: 193 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/ToolComboBox.png
Normal file
After Width: | Height: | Size: 233 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/ToolDefault.png
Normal file
After Width: | Height: | Size: 154 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/ToolDialog.png
Normal file
After Width: | Height: | Size: 146 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/ToolFlexGridSizer.png
Normal file
After Width: | Height: | Size: 139 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/ToolFrame.png
Normal file
After Width: | Height: | Size: 131 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/ToolGauge.png
Normal file
After Width: | Height: | Size: 141 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/ToolGridSizer.png
Normal file
After Width: | Height: | Size: 133 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/ToolListBox.png
Normal file
After Width: | Height: | Size: 184 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/ToolListCtrl.png
Normal file
After Width: | Height: | Size: 167 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/ToolMenu.png
Normal file
After Width: | Height: | Size: 166 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/ToolMenuBar.png
Normal file
After Width: | Height: | Size: 171 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/ToolMenuItem.png
Normal file
After Width: | Height: | Size: 135 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/ToolNotebook.png
Normal file
After Width: | Height: | Size: 253 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/ToolPanel.png
Normal file
After Width: | Height: | Size: 140 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/ToolRadioBox.png
Normal file
After Width: | Height: | Size: 296 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/ToolRadioButton.png
Normal file
After Width: | Height: | Size: 200 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/ToolRoot.png
Normal file
After Width: | Height: | Size: 170 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/ToolScrollBar.png
Normal file
After Width: | Height: | Size: 254 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/ToolSeparator.png
Normal file
After Width: | Height: | Size: 80 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/ToolSlider.png
Normal file
After Width: | Height: | Size: 185 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/ToolSpacer.png
Normal file
After Width: | Height: | Size: 229 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/ToolSpinButton.png
Normal file
After Width: | Height: | Size: 161 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/ToolSpinCtrl.png
Normal file
After Width: | Height: | Size: 308 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/ToolStaticBitmap.png
Normal file
After Width: | Height: | Size: 576 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/ToolStaticBox.png
Normal file
After Width: | Height: | Size: 189 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/ToolStaticBoxSizer.png
Normal file
After Width: | Height: | Size: 173 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/ToolStaticLine.png
Normal file
After Width: | Height: | Size: 82 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/ToolStaticText.png
Normal file
After Width: | Height: | Size: 166 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/ToolTextCtrl.png
Normal file
After Width: | Height: | Size: 129 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/ToolTool.png
Normal file
After Width: | Height: | Size: 119 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/ToolToolBar.png
Normal file
After Width: | Height: | Size: 165 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/ToolTreeCtrl.png
Normal file
After Width: | Height: | Size: 154 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/ToolUnknown.png
Normal file
After Width: | Height: | Size: 145 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/TreeDefault.png
Normal file
After Width: | Height: | Size: 154 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/TreeDialog.png
Normal file
After Width: | Height: | Size: 146 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/TreeFrame.png
Normal file
After Width: | Height: | Size: 131 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/TreeMenu.png
Normal file
After Width: | Height: | Size: 166 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/TreeMenuBar.png
Normal file
After Width: | Height: | Size: 171 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/TreeMenuItem.png
Normal file
After Width: | Height: | Size: 139 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/TreePanel.png
Normal file
After Width: | Height: | Size: 140 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/TreeRoot.png
Normal file
After Width: | Height: | Size: 170 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/TreeSeparator.png
Normal file
After Width: | Height: | Size: 103 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/TreeSizerFlexGrid.png
Normal file
After Width: | Height: | Size: 139 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/TreeSizerGrid.png
Normal file
After Width: | Height: | Size: 133 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/TreeSizerH.png
Normal file
After Width: | Height: | Size: 141 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/TreeSizerV.png
Normal file
After Width: | Height: | Size: 136 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/TreeStaticBoxSizerH.png
Normal file
After Width: | Height: | Size: 173 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/TreeStaticBoxSizerV.png
Normal file
After Width: | Height: | Size: 177 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/TreeTool.png
Normal file
After Width: | Height: | Size: 141 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/TreeToolBar.png
Normal file
After Width: | Height: | Size: 194 B |
BIN
wxPython/wxPython/tools/XRCed/src-images/Undo.png
Normal file
After Width: | Height: | Size: 240 B |
279
wxPython/wxPython/tools/XRCed/tools.py
Normal file
@@ -0,0 +1,279 @@
|
||||
# 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_ELSE = range(5)
|
||||
|
||||
# Left toolbar for GUI elements
|
||||
class Tools(wxPanel):
|
||||
TOOL_SIZE = (30, 30)
|
||||
def __init__(self, parent):
|
||||
if wxPlatform == '__WXGTK__':
|
||||
wxPanel.__init__(self, parent, -1,
|
||||
style=wxRAISED_BORDER|wxWANTS_CHARS)
|
||||
else:
|
||||
wxPanel.__init__(self, parent, -1, style=wxWANTS_CHARS)
|
||||
# Create sizer for groups
|
||||
self.sizer = wxBoxSizer(wxVERTICAL)
|
||||
# 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.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.UNKNOWN, images.getToolUnknownBitmap())]
|
||||
]
|
||||
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.SetAutoLayout(True)
|
||||
self.SetSizerAndFit(self.sizer)
|
||||
# Allow to be resized in vertical direction only
|
||||
self.SetSizeHints(self.GetSize()[0], -1)
|
||||
# Events
|
||||
EVT_COMMAND_RANGE(self, ID_NEW.PANEL, ID_NEW.LAST,
|
||||
wxEVT_COMMAND_BUTTON_CLICKED, g.frame.OnCreate)
|
||||
EVT_KEY_DOWN(self, self.OnKeyDown)
|
||||
EVT_KEY_UP(self, self.OnKeyUp)
|
||||
|
||||
def AddButton(self, id, image, text):
|
||||
button = wxBitmapButton(self, id, image, size=self.TOOL_SIZE,
|
||||
style=wxBU_AUTODRAW|wxNO_BORDER|wxWANTS_CHARS)
|
||||
EVT_KEY_DOWN(button, self.OnKeyDown)
|
||||
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
|
||||
box = wxStaticBox(self, -1, name, style=wxWANTS_CHARS)
|
||||
box.SetFont(smallerFont)
|
||||
boxSizer = wxStaticBoxSizer(box, wxVERTICAL)
|
||||
boxSizer.Add(0, 4)
|
||||
self.curSizer = wxGridSizer(0, 3)
|
||||
boxSizer.Add(self.curSizer)
|
||||
self.sizer.Add(boxSizer, 0, wxTOP | wxLEFT | wxRIGHT, 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)
|
||||
|
||||
# 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)
|
||||
|
||||
# Process key events
|
||||
def OnKeyDown(self, evt):
|
||||
if evt.GetKeyCode() == WXK_CONTROL:
|
||||
g.tree.ctrl = True
|
||||
elif evt.GetKeyCode() == WXK_SHIFT:
|
||||
g.tree.shift = True
|
||||
self.UpdateIfNeeded()
|
||||
evt.Skip()
|
||||
|
||||
def OnKeyUp(self, evt):
|
||||
if evt.GetKeyCode() == WXK_CONTROL:
|
||||
g.tree.ctrl = False
|
||||
elif evt.GetKeyCode() == 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):
|
||||
# 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
|
||||
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_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 ],
|
||||
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 notebook (always executed)
|
||||
if state == STATE_ELSE:
|
||||
if xxx.__class__ == xxxNotebook:
|
||||
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)
|
||||
# Save state
|
||||
self.state = state
|
839
wxPython/wxPython/tools/XRCed/tree.py
Normal file
@@ -0,0 +1,839 @@
|
||||
# Name: tree.py
|
||||
# Purpose: XRC editor, XML_tree class
|
||||
# Author: Roman Rolinsky <rolinsky@mema.ucl.ac.be>
|
||||
# Created: 02.12.2002
|
||||
# RCS-ID: $Id$
|
||||
|
||||
from xxx import * # xxx imports globals and params
|
||||
|
||||
# Icons
|
||||
import images
|
||||
|
||||
class MemoryFile:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.buffer = ''
|
||||
def write(self, data):
|
||||
self.buffer += data.encode()
|
||||
def close(self):
|
||||
wxMemoryFSHandler_AddFile(self.name, self.buffer)
|
||||
|
||||
################################################################################
|
||||
|
||||
# Redefine writing to include encoding
|
||||
class MyDocument(minidom.Document):
|
||||
def __init__(self):
|
||||
minidom.Document.__init__(self)
|
||||
self.encoding = ''
|
||||
def writexml(self, writer, indent="", addindent="", newl="", encoding=""):
|
||||
if encoding: encdstr = 'encoding="%s"' % encoding
|
||||
else: encdstr = ''
|
||||
writer.write('<?xml version="1.0" %s?>\n' % encdstr)
|
||||
for node in self.childNodes:
|
||||
node.writexml(writer, indent, addindent, newl)
|
||||
|
||||
################################################################################
|
||||
|
||||
# Ids for menu commands
|
||||
class ID_NEW:
|
||||
PANEL = wxNewId()
|
||||
DIALOG = wxNewId()
|
||||
FRAME = wxNewId()
|
||||
TOOL_BAR = wxNewId()
|
||||
TOOL = wxNewId()
|
||||
MENU_BAR = wxNewId()
|
||||
MENU = wxNewId()
|
||||
|
||||
STATIC_TEXT = wxNewId()
|
||||
TEXT_CTRL = wxNewId()
|
||||
|
||||
BUTTON = wxNewId()
|
||||
BITMAP_BUTTON = wxNewId()
|
||||
RADIO_BUTTON = wxNewId()
|
||||
SPIN_BUTTON = wxNewId()
|
||||
|
||||
STATIC_BOX = wxNewId()
|
||||
CHECK_BOX = wxNewId()
|
||||
RADIO_BOX = wxNewId()
|
||||
COMBO_BOX = wxNewId()
|
||||
LIST_BOX = wxNewId()
|
||||
|
||||
STATIC_LINE = wxNewId()
|
||||
STATIC_BITMAP = wxNewId()
|
||||
CHOICE = wxNewId()
|
||||
SLIDER = wxNewId()
|
||||
GAUGE = wxNewId()
|
||||
SCROLL_BAR = wxNewId()
|
||||
TREE_CTRL = wxNewId()
|
||||
LIST_CTRL = wxNewId()
|
||||
CHECK_LIST = wxNewId()
|
||||
NOTEBOOK = wxNewId()
|
||||
HTML_WINDOW = wxNewId()
|
||||
CALENDAR_CTRL = wxNewId()
|
||||
GENERIC_DIR_CTRL = wxNewId()
|
||||
SPIN_CTRL = wxNewId()
|
||||
UNKNOWN = wxNewId()
|
||||
|
||||
BOX_SIZER = wxNewId()
|
||||
STATIC_BOX_SIZER = wxNewId()
|
||||
GRID_SIZER = wxNewId()
|
||||
FLEX_GRID_SIZER = wxNewId()
|
||||
SPACER = wxNewId()
|
||||
TOOL_BAR = wxNewId()
|
||||
TOOL = wxNewId()
|
||||
MENU = wxNewId()
|
||||
MENU_ITEM = wxNewId()
|
||||
SEPARATOR = wxNewId()
|
||||
LAST = wxNewId()
|
||||
|
||||
class PullDownMenu:
|
||||
ID_EXPAND = wxNewId()
|
||||
ID_COLLAPSE = wxNewId()
|
||||
ID_PASTE_SIBLING = wxNewId()
|
||||
|
||||
def __init__(self, parent):
|
||||
self.ID_DELETE = parent.ID_DELETE
|
||||
EVT_MENU_RANGE(parent, ID_NEW.PANEL, ID_NEW.LAST, parent.OnCreate)
|
||||
EVT_MENU(parent, self.ID_COLLAPSE, parent.OnCollapse)
|
||||
EVT_MENU(parent, self.ID_EXPAND, parent.OnExpand)
|
||||
EVT_MENU(parent, self.ID_PASTE_SIBLING, parent.OnPaste)
|
||||
# We connect to tree, but process in frame
|
||||
EVT_MENU_HIGHLIGHT_ALL(g.tree, parent.OnPullDownHighlight)
|
||||
|
||||
# Mapping from IDs to element names
|
||||
self.createMap = {
|
||||
ID_NEW.PANEL: 'wxPanel',
|
||||
ID_NEW.DIALOG: 'wxDialog',
|
||||
ID_NEW.FRAME: 'wxFrame',
|
||||
ID_NEW.TOOL_BAR: 'wxToolBar',
|
||||
ID_NEW.TOOL: 'tool',
|
||||
ID_NEW.MENU_BAR: 'wxMenuBar',
|
||||
ID_NEW.MENU: 'wxMenu',
|
||||
ID_NEW.MENU_ITEM: 'wxMenuItem',
|
||||
ID_NEW.SEPARATOR: 'separator',
|
||||
|
||||
ID_NEW.STATIC_TEXT: 'wxStaticText',
|
||||
ID_NEW.TEXT_CTRL: 'wxTextCtrl',
|
||||
|
||||
ID_NEW.BUTTON: 'wxButton',
|
||||
ID_NEW.BITMAP_BUTTON: 'wxBitmapButton',
|
||||
ID_NEW.RADIO_BUTTON: 'wxRadioButton',
|
||||
ID_NEW.SPIN_BUTTON: 'wxSpinButton',
|
||||
|
||||
ID_NEW.STATIC_BOX: 'wxStaticBox',
|
||||
ID_NEW.CHECK_BOX: 'wxCheckBox',
|
||||
ID_NEW.RADIO_BOX: 'wxRadioBox',
|
||||
ID_NEW.COMBO_BOX: 'wxComboBox',
|
||||
ID_NEW.LIST_BOX: 'wxListBox',
|
||||
|
||||
ID_NEW.STATIC_LINE: 'wxStaticLine',
|
||||
ID_NEW.STATIC_BITMAP: 'wxStaticBitmap',
|
||||
ID_NEW.CHOICE: 'wxChoice',
|
||||
ID_NEW.SLIDER: 'wxSlider',
|
||||
ID_NEW.GAUGE: 'wxGauge',
|
||||
ID_NEW.SCROLL_BAR: 'wxScrollBar',
|
||||
ID_NEW.TREE_CTRL: 'wxTreeCtrl',
|
||||
ID_NEW.LIST_CTRL: 'wxListCtrl',
|
||||
ID_NEW.CHECK_LIST: 'wxCheckList',
|
||||
ID_NEW.NOTEBOOK: 'wxNotebook',
|
||||
ID_NEW.HTML_WINDOW: 'wxHtmlWindow',
|
||||
ID_NEW.CALENDAR_CTRL: 'wxCalendarCtrl',
|
||||
ID_NEW.GENERIC_DIR_CTRL: 'wxGenericDirCtrl',
|
||||
ID_NEW.SPIN_CTRL: 'wxSpinCtrl',
|
||||
|
||||
ID_NEW.BOX_SIZER: 'wxBoxSizer',
|
||||
ID_NEW.STATIC_BOX_SIZER: 'wxStaticBoxSizer',
|
||||
ID_NEW.GRID_SIZER: 'wxGridSizer',
|
||||
ID_NEW.FLEX_GRID_SIZER: 'wxFlexGridSizer',
|
||||
ID_NEW.SPACER: 'spacer',
|
||||
ID_NEW.UNKNOWN: 'unknown',
|
||||
}
|
||||
self.controls = [
|
||||
['control', 'Various controls',
|
||||
(ID_NEW.STATIC_TEXT, 'Label', 'Create label'),
|
||||
(ID_NEW.STATIC_BITMAP, 'Bitmap', 'Create bitmap'),
|
||||
(ID_NEW.STATIC_LINE, 'Line', 'Create line'),
|
||||
(ID_NEW.TEXT_CTRL, 'TextBox', 'Create text box'),
|
||||
(ID_NEW.CHOICE, 'Choice', 'Create choice'),
|
||||
(ID_NEW.SLIDER, 'Slider', 'Create slider'),
|
||||
(ID_NEW.GAUGE, 'Gauge', 'Create gauge'),
|
||||
(ID_NEW.SPIN_CTRL, 'SpinCtrl', 'Create spin'),
|
||||
(ID_NEW.SCROLL_BAR, 'ScrollBar', 'Create scroll bar'),
|
||||
(ID_NEW.TREE_CTRL, 'TreeCtrl', 'Create tree'),
|
||||
(ID_NEW.LIST_CTRL, 'ListCtrl', 'Create list'),
|
||||
(ID_NEW.CHECK_LIST, 'CheckList', 'Create check list'),
|
||||
(ID_NEW.HTML_WINDOW, 'HtmlWindow', 'Create HTML window'),
|
||||
(ID_NEW.CALENDAR_CTRL, 'CalendarCtrl', 'Create calendar control'),
|
||||
(ID_NEW.GENERIC_DIR_CTRL, 'GenericDirCtrl', 'Create generic dir control'),
|
||||
(ID_NEW.UNKNOWN, 'Unknown', 'Create custom control placeholder'),
|
||||
],
|
||||
['button', 'Buttons',
|
||||
(ID_NEW.BUTTON, 'Button', 'Create button'),
|
||||
(ID_NEW.BITMAP_BUTTON, 'BitmapButton', 'Create bitmap button'),
|
||||
(ID_NEW.RADIO_BUTTON, 'RadioButton', 'Create radio button'),
|
||||
(ID_NEW.SPIN_BUTTON, 'SpinButton', 'Create spin button'),
|
||||
],
|
||||
['box', 'Boxes',
|
||||
(ID_NEW.STATIC_BOX, 'StaticBox', 'Create static box'),
|
||||
(ID_NEW.CHECK_BOX, 'CheckBox', 'Create check box'),
|
||||
(ID_NEW.RADIO_BOX, 'RadioBox', 'Create radio box'),
|
||||
(ID_NEW.COMBO_BOX, 'ComboBox', 'Create combo box'),
|
||||
(ID_NEW.LIST_BOX, 'ListBox', 'Create list box'),
|
||||
],
|
||||
['container', 'Containers',
|
||||
(ID_NEW.PANEL, 'Panel', 'Create panel'),
|
||||
(ID_NEW.NOTEBOOK, 'Notebook', 'Create notebook control'),
|
||||
(ID_NEW.TOOL_BAR, 'ToolBar', 'Create toolbar'),
|
||||
],
|
||||
['sizer', 'Sizers',
|
||||
(ID_NEW.BOX_SIZER, 'BoxSizer', 'Create box sizer'),
|
||||
(ID_NEW.STATIC_BOX_SIZER, 'StaticBoxSizer',
|
||||
'Create static box sizer'),
|
||||
(ID_NEW.GRID_SIZER, 'GridSizer', 'Create grid sizer'),
|
||||
(ID_NEW.FLEX_GRID_SIZER, 'FlexGridSizer',
|
||||
'Create flexgrid sizer'),
|
||||
(ID_NEW.SPACER, 'Spacer', 'Create spacer'),
|
||||
]
|
||||
]
|
||||
self.menuControls = [
|
||||
(ID_NEW.MENU, 'Menu', 'Create menu'),
|
||||
(ID_NEW.MENU_ITEM, 'MenuItem', 'Create menu item'),
|
||||
(ID_NEW.SEPARATOR, 'Separator', 'Create separator'),
|
||||
]
|
||||
self.toolBarControls = [
|
||||
(ID_NEW.TOOL, 'Tool', 'Create tool'),
|
||||
(ID_NEW.SEPARATOR, 'Separator', 'Create separator'),
|
||||
['control', 'Various controls',
|
||||
(ID_NEW.STATIC_TEXT, 'Label', 'Create label'),
|
||||
(ID_NEW.STATIC_BITMAP, 'Bitmap', 'Create bitmap'),
|
||||
(ID_NEW.STATIC_LINE, 'Line', 'Create line'),
|
||||
(ID_NEW.TEXT_CTRL, 'TextBox', 'Create text box'),
|
||||
(ID_NEW.CHOICE, 'Choice', 'Create choice'),
|
||||
(ID_NEW.SLIDER, 'Slider', 'Create slider'),
|
||||
(ID_NEW.GAUGE, 'Gauge', 'Create gauge'),
|
||||
(ID_NEW.SCROLL_BAR, 'ScrollBar', 'Create scroll bar'),
|
||||
(ID_NEW.LIST_CTRL, 'ListCtrl', 'Create list control'),
|
||||
(ID_NEW.CHECK_LIST, 'CheckList', 'Create check list'),
|
||||
],
|
||||
['button', 'Buttons',
|
||||
(ID_NEW.BUTTON, 'Button', 'Create button'),
|
||||
(ID_NEW.BITMAP_BUTTON, 'BitmapButton', 'Create bitmap button'),
|
||||
(ID_NEW.RADIO_BUTTON, 'RadioButton', 'Create radio button'),
|
||||
(ID_NEW.SPIN_BUTTON, 'SpinButton', 'Create spin button'),
|
||||
],
|
||||
['box', 'Boxes',
|
||||
(ID_NEW.STATIC_BOX, 'StaticBox', 'Create static box'),
|
||||
(ID_NEW.CHECK_BOX, 'CheckBox', 'Create check box'),
|
||||
(ID_NEW.RADIO_BOX, 'RadioBox', 'Create radio box'),
|
||||
(ID_NEW.COMBO_BOX, 'ComboBox', 'Create combo box'),
|
||||
(ID_NEW.LIST_BOX, 'ListBox', 'Create list box'),
|
||||
],
|
||||
]
|
||||
|
||||
################################################################################
|
||||
|
||||
# Set menu to list items.
|
||||
# Each menu command is a tuple (id, label, help)
|
||||
# submenus are lists [id, label, help, submenu]
|
||||
# and separators are any other type
|
||||
def SetMenu(m, list):
|
||||
for l in list:
|
||||
if type(l) == types.TupleType:
|
||||
apply(m.Append, l)
|
||||
elif type(l) == types.ListType:
|
||||
subMenu = wxMenu()
|
||||
SetMenu(subMenu, l[2:])
|
||||
m.AppendMenu(wxNewId(), l[0], subMenu, l[1])
|
||||
else: # separator
|
||||
m.AppendSeparator()
|
||||
|
||||
################################################################################
|
||||
|
||||
class HighLightBox:
|
||||
def __init__(self, pos, size):
|
||||
if size.x == -1: size.x = 0
|
||||
if size.y == -1: size.y = 0
|
||||
w = g.testWin.panel
|
||||
l1 = wxWindow(w, -1, pos, wxSize(size.x, 2))
|
||||
l1.SetBackgroundColour(wxRED)
|
||||
l2 = wxWindow(w, -1, pos, wxSize(2, size.y))
|
||||
l2.SetBackgroundColour(wxRED)
|
||||
l3 = wxWindow(w, -1, wxPoint(pos.x + size.x - 2, pos.y), wxSize(2, size.y))
|
||||
l3.SetBackgroundColour(wxRED)
|
||||
l4 = wxWindow(w, -1, wxPoint(pos.x, pos.y + size.y - 2), wxSize(size.x, 2))
|
||||
l4.SetBackgroundColour(wxRED)
|
||||
self.lines = [l1, l2, l3, l4]
|
||||
# Move highlight to a new position
|
||||
def Replace(self, pos, size):
|
||||
if size.x == -1: size.x = 0
|
||||
if size.y == -1: size.y = 0
|
||||
self.lines[0].SetDimensions(pos.x, pos.y, size.x, 2)
|
||||
self.lines[1].SetDimensions(pos.x, pos.y, 2, size.y)
|
||||
self.lines[2].SetDimensions(pos.x + size.x - 2, pos.y, 2, size.y)
|
||||
self.lines[3].SetDimensions(pos.x, pos.y + size.y - 2, size.x, 2)
|
||||
# Remove it
|
||||
def Remove(self):
|
||||
map(wxWindow.Destroy, self.lines)
|
||||
g.testWin.highLight = None
|
||||
|
||||
################################################################################
|
||||
|
||||
class XML_Tree(wxTreeCtrl):
|
||||
# Constant to define standart window name
|
||||
stdName = '_XRCED_T_W'
|
||||
def __init__(self, parent, id):
|
||||
wxTreeCtrl.__init__(self, parent, id, style = wxTR_HAS_BUTTONS)
|
||||
self.SetBackgroundColour(wxColour(224, 248, 224))
|
||||
EVT_TREE_SEL_CHANGED(self, self.GetId(), self.OnSelChanged)
|
||||
# One works on Linux, another on Windows
|
||||
if wxPlatform == '__WXGTK__':
|
||||
EVT_TREE_ITEM_ACTIVATED(self, self.GetId(), self.OnItemActivated)
|
||||
else:
|
||||
EVT_LEFT_DCLICK(self, self.OnDClick)
|
||||
EVT_RIGHT_DOWN(self, self.OnRightDown)
|
||||
|
||||
self.needUpdate = False
|
||||
self.pendingHighLight = None
|
||||
self.ctrl = self.shift = False
|
||||
self.dom = None
|
||||
# Create image list
|
||||
il = wxImageList(16, 16, True)
|
||||
self.rootImage = il.AddIcon(images.getTreeRootIcon())
|
||||
xxxObject.image = il.AddIcon(images.getTreeDefaultIcon())
|
||||
xxxPanel.image = il.AddIcon(images.getTreePanelIcon())
|
||||
xxxDialog.image = il.AddIcon(images.getTreeDialogIcon())
|
||||
xxxFrame.image = il.AddIcon(images.getTreeFrameIcon())
|
||||
xxxMenuBar.image = il.AddIcon(images.getTreeMenuBarIcon())
|
||||
xxxMenu.image = il.AddIcon(images.getTreeMenuIcon())
|
||||
xxxMenuItem.image = il.AddIcon(images.getTreeMenuItemIcon())
|
||||
xxxToolBar.image = il.AddIcon(images.getTreeToolBarIcon())
|
||||
xxxTool.image = il.AddIcon(images.getTreeToolIcon())
|
||||
xxxSeparator.image = il.AddIcon(images.getTreeSeparatorIcon())
|
||||
xxxSizer.imageH = il.AddIcon(images.getTreeSizerHIcon())
|
||||
xxxSizer.imageV = il.AddIcon(images.getTreeSizerVIcon())
|
||||
xxxStaticBoxSizer.imageH = il.AddIcon(images.getTreeStaticBoxSizerHIcon())
|
||||
xxxStaticBoxSizer.imageV = il.AddIcon(images.getTreeStaticBoxSizerVIcon())
|
||||
xxxGridSizer.image = il.AddIcon(images.getTreeSizerGridIcon())
|
||||
xxxFlexGridSizer.image = il.AddIcon(images.getTreeSizerFlexGridIcon())
|
||||
self.il = il
|
||||
self.SetImageList(il)
|
||||
|
||||
def RegisterKeyEvents(self):
|
||||
EVT_KEY_DOWN(self, g.tools.OnKeyDown)
|
||||
EVT_KEY_UP(self, g.tools.OnKeyUp)
|
||||
EVT_ENTER_WINDOW(self, g.tools.OnMouse)
|
||||
EVT_LEAVE_WINDOW(self, g.tools.OnMouse)
|
||||
|
||||
def Unselect(self):
|
||||
self.selection = None
|
||||
wxTreeCtrl.Unselect(self)
|
||||
g.tools.UpdateUI()
|
||||
|
||||
def ExpandAll(self, item):
|
||||
if self.ItemHasChildren(item):
|
||||
self.Expand(item)
|
||||
i, cookie = self.GetFirstChild(item, 0)
|
||||
children = []
|
||||
while i.IsOk():
|
||||
children.append(i)
|
||||
i, cookie = self.GetNextChild(item, cookie)
|
||||
for i in children:
|
||||
self.ExpandAll(i)
|
||||
def CollapseAll(self, item):
|
||||
if self.ItemHasChildren(item):
|
||||
i, cookie = self.GetFirstChild(item, 0)
|
||||
children = []
|
||||
while i.IsOk():
|
||||
children.append(i)
|
||||
i, cookie = self.GetNextChild(item, cookie)
|
||||
for i in children:
|
||||
self.CollapseAll(i)
|
||||
self.Collapse(item)
|
||||
|
||||
# Clear tree
|
||||
def Clear(self):
|
||||
self.DeleteAllItems()
|
||||
# Add minimal structure
|
||||
if self.dom: self.dom.unlink()
|
||||
self.dom = MyDocument()
|
||||
self.dummyNode = self.dom.createComment('dummy node')
|
||||
# Create main node
|
||||
self.mainNode = self.dom.createElement('resource')
|
||||
self.dom.appendChild(self.mainNode)
|
||||
self.rootObj = xxxMainNode(self.dom)
|
||||
self.root = self.AddRoot('XML tree', self.rootImage,
|
||||
data=wxTreeItemData(self.rootObj))
|
||||
self.SetItemHasChildren(self.root)
|
||||
self.Expand(self.root)
|
||||
self.Unselect()
|
||||
|
||||
# Clear old data and set new
|
||||
def SetData(self, dom):
|
||||
self.DeleteAllItems()
|
||||
# Add minimal structure
|
||||
if self.dom: self.dom.unlink()
|
||||
self.dom = dom
|
||||
self.dummyNode = self.dom.createComment('dummy node')
|
||||
# Find 'resource' child, add it's children
|
||||
self.mainNode = dom.documentElement
|
||||
self.rootObj = xxxMainNode(self.dom)
|
||||
self.root = self.AddRoot('XML tree', self.rootImage,
|
||||
data=wxTreeItemData(self.rootObj))
|
||||
self.SetItemHasChildren(self.root)
|
||||
nodes = self.mainNode.childNodes[:]
|
||||
for node in nodes:
|
||||
if IsObject(node):
|
||||
self.AddNode(self.root, None, node)
|
||||
else:
|
||||
self.mainNode.removeChild(node)
|
||||
node.unlink()
|
||||
self.Expand(self.root)
|
||||
self.Unselect()
|
||||
|
||||
# Add tree item for given parent item if node is DOM element node with
|
||||
# 'object' tag. xxxParent is parent xxx object
|
||||
def AddNode(self, itemParent, xxxParent, node):
|
||||
# Set item data to current node
|
||||
try:
|
||||
xxx = MakeXXXFromDOM(xxxParent, node)
|
||||
except:
|
||||
print 'ERROR: MakeXXXFromDom(%s, %s)' % (xxxParent, node)
|
||||
raise
|
||||
treeObj = xxx.treeObject()
|
||||
# Append tree item
|
||||
item = self.AppendItem(itemParent, treeObj.treeName(),
|
||||
image=treeObj.treeImage(),
|
||||
data=wxTreeItemData(xxx))
|
||||
# Try to find children objects
|
||||
if treeObj.hasChildren:
|
||||
nodes = treeObj.element.childNodes[:]
|
||||
for n in nodes:
|
||||
if IsObject(n):
|
||||
self.AddNode(item, treeObj, n)
|
||||
elif n.nodeType != minidom.Node.ELEMENT_NODE:
|
||||
treeObj.element.removeChild(n)
|
||||
n.unlink()
|
||||
# Insert new item at specific position
|
||||
def InsertNode(self, itemParent, parent, elem, nextItem):
|
||||
# Insert in XML tree and wxWin
|
||||
xxx = MakeXXXFromDOM(parent, elem)
|
||||
# If nextItem is None, we append to parent, otherwise insert before it
|
||||
if nextItem.IsOk():
|
||||
node = self.GetPyData(nextItem).element
|
||||
parent.element.insertBefore(elem, node)
|
||||
# Inserting before is difficult, se we insert after or first child
|
||||
index = self.ItemIndex(nextItem)
|
||||
newItem = self.InsertItemBefore(itemParent, index,
|
||||
xxx.treeName(), image=xxx.treeImage())
|
||||
self.SetPyData(newItem, xxx)
|
||||
else:
|
||||
parent.element.appendChild(elem)
|
||||
newItem = self.AppendItem(itemParent, xxx.treeName(), image=xxx.treeImage(),
|
||||
data=wxTreeItemData(xxx))
|
||||
# Add children items
|
||||
if xxx.hasChildren:
|
||||
treeObj = xxx.treeObject()
|
||||
for n in treeObj.element.childNodes:
|
||||
if IsObject(n):
|
||||
self.AddNode(newItem, treeObj, n)
|
||||
return newItem
|
||||
|
||||
# Remove leaf of tree, return it's data object
|
||||
def RemoveLeaf(self, leaf):
|
||||
xxx = self.GetPyData(leaf)
|
||||
node = xxx.element
|
||||
parent = node.parentNode
|
||||
parent.removeChild(node)
|
||||
self.Delete(leaf)
|
||||
# Reset selection object
|
||||
self.selection = None
|
||||
return node
|
||||
# Find position relative to the top-level window
|
||||
def FindNodePos(self, item):
|
||||
# Root at (0,0)
|
||||
if item == g.testWin.item: return wxPoint(0, 0)
|
||||
itemParent = self.GetItemParent(item)
|
||||
# Select NB page
|
||||
obj = self.FindNodeObject(item)
|
||||
if self.GetPyData(itemParent).treeObject().__class__ == xxxNotebook:
|
||||
notebook = self.FindNodeObject(itemParent)
|
||||
# Find position
|
||||
for i in range(notebook.GetPageCount()):
|
||||
if notebook.GetPage(i) == obj:
|
||||
if notebook.GetSelection() != i: notebook.SetSelection(i)
|
||||
break
|
||||
# Find first ancestor which is a wxWindow (not a sizer)
|
||||
winParent = itemParent
|
||||
while self.GetPyData(winParent).isSizer:
|
||||
winParent = self.GetItemParent(winParent)
|
||||
parentPos = self.FindNodePos(winParent)
|
||||
# Position (-1,-1) is really (0,0)
|
||||
pos = obj.GetPosition()
|
||||
if pos == (-1,-1): pos = (0,0)
|
||||
return parentPos + pos
|
||||
# Find window (or sizer) corresponding to a tree item.
|
||||
def FindNodeObject(self, item):
|
||||
testWin = g.testWin
|
||||
# If top-level, return testWin (or panel its panel)
|
||||
if item == testWin.item: return testWin.panel
|
||||
itemParent = self.GetItemParent(item)
|
||||
xxx = self.GetPyData(item).treeObject()
|
||||
parentWin = self.FindNodeObject(itemParent)
|
||||
# Top-level sizer? return window's sizer
|
||||
if xxx.isSizer and isinstance(parentWin, wxWindowPtr):
|
||||
return parentWin.GetSizer()
|
||||
# Otherwise get parent's object and it's child
|
||||
child = parentWin.GetChildren()[self.ItemIndex(item)]
|
||||
# Return window or sizer for sizer items
|
||||
if child.GetClassName() == 'wxSizerItem':
|
||||
if child.IsWindow(): child = child.GetWindow()
|
||||
elif child.IsSizer():
|
||||
child = child.GetSizer()
|
||||
# Test for notebook sizers
|
||||
if isinstance(child, wxNotebookSizerPtr):
|
||||
child = child.GetNotebook()
|
||||
return child
|
||||
def OnSelChanged(self, evt):
|
||||
# Apply changes
|
||||
# !!! problem with wxGTK - GetOldItem is Ok if nothing selected
|
||||
#oldItem = evt.GetOldItem()
|
||||
status = ''
|
||||
oldItem = self.selection
|
||||
if oldItem:
|
||||
xxx = self.GetPyData(oldItem)
|
||||
# If some data was modified, apply changes
|
||||
if g.panel.IsModified():
|
||||
self.Apply(xxx, oldItem)
|
||||
#if conf.autoRefresh:
|
||||
if g.testWin:
|
||||
if g.testWin.highLight:
|
||||
g.testWin.highLight.Remove()
|
||||
self.needUpdate = True
|
||||
status = 'Changes were applied'
|
||||
g.frame.SetStatusText(status)
|
||||
# Generate view
|
||||
self.selection = evt.GetItem()
|
||||
if not self.selection.IsOk():
|
||||
self.selection = None
|
||||
return
|
||||
xxx = self.GetPyData(self.selection)
|
||||
# Update panel
|
||||
g.panel.SetData(xxx)
|
||||
# Update tools
|
||||
g.tools.UpdateUI()
|
||||
# Hightlighting is done in OnIdle
|
||||
self.pendingHighLight = self.selection
|
||||
# Check if item is in testWin subtree
|
||||
def IsHighlatable(self, item):
|
||||
if item == g.testWin.item: return False
|
||||
while item != self.root:
|
||||
item = self.GetItemParent(item)
|
||||
if item == g.testWin.item: return True
|
||||
return False
|
||||
# Highlight selected item
|
||||
def HighLight(self, item):
|
||||
self.pendingHighLight = None
|
||||
# Can highlight only with some top-level windows
|
||||
if not g.testWin or self.GetPyData(g.testWin.item).treeObject().__class__ \
|
||||
not in [xxxDialog, xxxPanel, xxxFrame]:
|
||||
return
|
||||
# If a control from another window is selected, remove highlight
|
||||
if not self.IsHighlatable(item):
|
||||
if g.testWin.highLight: g.testWin.highLight.Remove()
|
||||
return
|
||||
# Get window/sizer object
|
||||
obj, pos = self.FindNodeObject(item), self.FindNodePos(item)
|
||||
size = obj.GetSize()
|
||||
# Highlight
|
||||
# Nagative positions are not working wuite well
|
||||
if g.testWin.highLight:
|
||||
g.testWin.highLight.Replace(pos, size)
|
||||
else:
|
||||
g.testWin.highLight = HighLightBox(pos, size)
|
||||
g.testWin.highLight.item = item
|
||||
def ShowTestWindow(self, item):
|
||||
xxx = self.GetPyData(item)
|
||||
if g.panel.IsModified():
|
||||
self.Apply(xxx, item) # apply changes
|
||||
treeObj = xxx.treeObject()
|
||||
if treeObj.className not in ['wxFrame', 'wxPanel', 'wxDialog',
|
||||
'wxMenuBar', 'wxToolBar']:
|
||||
wxLogMessage('No view for this element (yet)')
|
||||
return
|
||||
# Show item in bold
|
||||
if g.testWin: # Reset old
|
||||
self.SetItemBold(g.testWin.item, False)
|
||||
self.CreateTestWin(item)
|
||||
# Maybe an error occured, so we need to test
|
||||
if g.testWin: self.SetItemBold(g.testWin.item)
|
||||
# Double-click on Linux
|
||||
def OnItemActivated(self, evt):
|
||||
if evt.GetItem() != self.root:
|
||||
self.ShowTestWindow(evt.GetItem())
|
||||
# Double-click on Windows
|
||||
def OnDClick(self, evt):
|
||||
item, flags = self.HitTest(evt.GetPosition())
|
||||
if flags in [wxTREE_HITTEST_ONITEMBUTTON, wxTREE_HITTEST_ONITEMLABEL]:
|
||||
if item != self.root: self.ShowTestWindow(item)
|
||||
else:
|
||||
evt.Skip()
|
||||
# (re)create test window
|
||||
def CreateTestWin(self, item):
|
||||
testWin = g.testWin
|
||||
wxBeginBusyCursor()
|
||||
wxYield()
|
||||
# Create a window with this resource
|
||||
xxx = self.GetPyData(item).treeObject()
|
||||
# Close old window, remember where it was
|
||||
highLight = None
|
||||
if testWin:
|
||||
pos = testWin.GetPosition()
|
||||
if item == testWin.item:
|
||||
# Remember highlight if same top-level window
|
||||
if testWin.highLight:
|
||||
highLight = testWin.highLight.item
|
||||
if xxx.className == 'wxPanel':
|
||||
if testWin.highLight:
|
||||
testWin.pendingHighLight = highLight
|
||||
testWin.highLight.Remove()
|
||||
testWin.panel.Destroy()
|
||||
testWin.panel = None
|
||||
else:
|
||||
testWin.Destroy()
|
||||
testWin = g.testWin = None
|
||||
else:
|
||||
testWin.Destroy()
|
||||
testWin = g.testWin = None
|
||||
else:
|
||||
pos = g.testWinPos
|
||||
# Save in memory FS
|
||||
memFile = MemoryFile('xxx.xrc')
|
||||
# Create partial XML file - faster for big files
|
||||
|
||||
dom = MyDocument()
|
||||
mainNode = dom.createElement('resource')
|
||||
dom.appendChild(mainNode)
|
||||
|
||||
# Remove temporarily from old parent
|
||||
elem = xxx.element
|
||||
# Change window id to _XRCED_T_W. This gives some name for
|
||||
# unnamed windows, and for named gives the possibility to
|
||||
# write sawfish scripts.
|
||||
if not xxx.name:
|
||||
name = 'noname'
|
||||
else:
|
||||
name = xxx.name
|
||||
elem.setAttribute('name', self.stdName)
|
||||
parent = elem.parentNode
|
||||
next = elem.nextSibling
|
||||
parent.replaceChild(self.dummyNode, elem)
|
||||
# Append to new DOM, write it
|
||||
mainNode.appendChild(elem)
|
||||
dom.writexml(memFile, encoding=self.rootObj.params['encoding'].value())
|
||||
# Put back in place
|
||||
mainNode.removeChild(elem)
|
||||
dom.unlink()
|
||||
parent.replaceChild(elem, self.dummyNode)
|
||||
# Remove temporary name or restore changed
|
||||
if not xxx.name:
|
||||
elem.removeAttribute('name')
|
||||
else:
|
||||
elem.setAttribute('name', xxx.name)
|
||||
memFile.close() # write to wxMemoryFS
|
||||
res = wxXmlResource('', g.xmlFlags)
|
||||
res.Load('memory:xxx.xrc')
|
||||
if xxx.__class__ == xxxFrame:
|
||||
# Frame can't have many children,
|
||||
# but it's first child possibly can...
|
||||
child = self.GetFirstChild(item, 0)[0]
|
||||
if child.IsOk() and self.GetPyData(child).__class__ == xxxPanel:
|
||||
# Clean-up before recursive call or error
|
||||
wxMemoryFSHandler_RemoveFile('xxx.xrc')
|
||||
wxEndBusyCursor()
|
||||
self.CreateTestWin(child)
|
||||
return
|
||||
# This currently works under GTK, but not under MSW
|
||||
testWin = g.testWin = wxPreFrame()
|
||||
res.LoadOnFrame(testWin, g.frame, self.stdName)
|
||||
# Create status bar
|
||||
testWin.CreateStatusBar()
|
||||
testWin.panel = testWin
|
||||
testWin.SetPosition(pos)
|
||||
testWin.Show(True)
|
||||
elif xxx.__class__ == xxxPanel:
|
||||
# Create new frame
|
||||
if not testWin:
|
||||
testWin = g.testWin = wxFrame(g.frame, -1, 'Panel: ' + name, pos=pos)
|
||||
testWin.panel = res.LoadPanel(testWin, self.stdName)
|
||||
testWin.SetClientSize(testWin.panel.GetSize())
|
||||
testWin.Show(True)
|
||||
elif xxx.__class__ == xxxDialog:
|
||||
testWin = g.testWin = res.LoadDialog(None, self.stdName)
|
||||
testWin.panel = testWin
|
||||
testWin.Layout()
|
||||
testWin.SetPosition(pos)
|
||||
testWin.Show(True)
|
||||
elif xxx.__class__ == xxxMenuBar:
|
||||
testWin = g.testWin = wxFrame(g.frame, -1, 'MenuBar: ' + name, pos=pos)
|
||||
testWin.panel = None
|
||||
# Set status bar to display help
|
||||
testWin.CreateStatusBar()
|
||||
testWin.menuBar = res.LoadMenuBar(self.stdName)
|
||||
testWin.SetMenuBar(testWin.menuBar)
|
||||
testWin.Show(True)
|
||||
elif xxx.__class__ == xxxToolBar:
|
||||
testWin = g.testWin = wxFrame(g.frame, -1, 'ToolBar: ' + name, pos=pos)
|
||||
testWin.panel = None
|
||||
# Set status bar to display help
|
||||
testWin.CreateStatusBar()
|
||||
testWin.toolBar = res.LoadToolBar(testWin, self.stdName)
|
||||
testWin.SetToolBar(testWin.toolBar)
|
||||
testWin.Show(True)
|
||||
wxMemoryFSHandler_RemoveFile('xxx.xrc')
|
||||
testWin.item = item
|
||||
EVT_CLOSE(testWin, self.OnCloseTestWin)
|
||||
EVT_BUTTON(testWin, wxID_OK, self.OnCloseTestWin)
|
||||
EVT_BUTTON(testWin, wxID_CANCEL, self.OnCloseTestWin)
|
||||
testWin.highLight = None
|
||||
if highLight and not self.pendingHighLight:
|
||||
self.HighLight(highLight)
|
||||
wxEndBusyCursor()
|
||||
|
||||
def OnCloseTestWin(self, evt):
|
||||
self.SetItemBold(g.testWin.item, False)
|
||||
g.testWinPos = g.testWin.GetPosition()
|
||||
g.testWin.Destroy()
|
||||
g.testWin = None
|
||||
|
||||
# Return item index in parent
|
||||
def ItemIndex(self, item):
|
||||
n = 0 # index of sibling
|
||||
prev = self.GetPrevSibling(item)
|
||||
while prev.IsOk():
|
||||
prev = self.GetPrevSibling(prev)
|
||||
n += 1
|
||||
return n
|
||||
|
||||
# Full tree index of an item - list of positions
|
||||
def ItemFullIndex(self, item):
|
||||
if not item.IsOk(): return None
|
||||
l = []
|
||||
while item != self.root:
|
||||
l.insert(0, self.ItemIndex(item))
|
||||
item = self.GetItemParent(item)
|
||||
return l
|
||||
# Get item position from full index
|
||||
def ItemAtFullIndex(self, index):
|
||||
if index is None: return wxTreeItemId()
|
||||
item = self.root
|
||||
for i in index:
|
||||
item = self.GetFirstChild(item, 0)[0]
|
||||
for k in range(i): item = self.GetNextSibling(item)
|
||||
return item
|
||||
|
||||
# True if next item should be inserted after current (vs. appended to it)
|
||||
def NeedInsert(self, item):
|
||||
xxx = self.GetPyData(item)
|
||||
if item == self.root: return False # root item
|
||||
if xxx.hasChildren and not self.GetChildrenCount(item, False):
|
||||
return False
|
||||
return not (self.IsExpanded(item) and self.GetChildrenCount(item, False))
|
||||
|
||||
# Pull-down
|
||||
def OnRightDown(self, evt):
|
||||
pullDownMenu = g.pullDownMenu
|
||||
# select this item
|
||||
pt = evt.GetPosition();
|
||||
item, flags = self.HitTest(pt)
|
||||
if item.Ok() and flags & wxTREE_HITTEST_ONITEM:
|
||||
self.SelectItem(item)
|
||||
|
||||
# Setup menu
|
||||
menu = wxMenu()
|
||||
|
||||
item = self.selection
|
||||
if not item:
|
||||
menu.Append(g.pullDownMenu.ID_EXPAND, 'Expand', 'Expand tree')
|
||||
menu.Append(g.pullDownMenu.ID_COLLAPSE, 'Collapse', 'Collapse tree')
|
||||
else:
|
||||
# self.ctrl = evt.ControlDown() # save Ctrl state
|
||||
# self.shift = evt.ShiftDown() # and Shift too
|
||||
m = wxMenu() # create menu
|
||||
if self.ctrl:
|
||||
needInsert = True
|
||||
else:
|
||||
needInsert = self.NeedInsert(item)
|
||||
if item == self.root or needInsert and self.GetItemParent(item) == self.root:
|
||||
m.Append(ID_NEW.PANEL, 'Panel', 'Create panel')
|
||||
m.Append(ID_NEW.DIALOG, 'Dialog', 'Create dialog')
|
||||
m.Append(ID_NEW.FRAME, 'Frame', 'Create frame')
|
||||
m.AppendSeparator()
|
||||
m.Append(ID_NEW.TOOL_BAR, 'ToolBar', 'Create toolbar')
|
||||
m.Append(ID_NEW.MENU_BAR, 'MenuBar', 'Create menubar')
|
||||
m.Append(ID_NEW.MENU, 'Menu', 'Create menu')
|
||||
else:
|
||||
xxx = self.GetPyData(item).treeObject()
|
||||
# Check parent for possible child nodes if inserting sibling
|
||||
if needInsert: xxx = xxx.parent
|
||||
if xxx.__class__ == xxxMenuBar:
|
||||
m.Append(ID_NEW.MENU, 'Menu', 'Create menu')
|
||||
elif xxx.__class__ in [xxxToolBar, xxxTool] or \
|
||||
xxx.__class__ == xxxSeparator and xxx.parent.__class__ == xxxToolBar:
|
||||
SetMenu(m, pullDownMenu.toolBarControls)
|
||||
elif xxx.__class__ in [xxxMenu, xxxMenuItem]:
|
||||
SetMenu(m, pullDownMenu.menuControls)
|
||||
else:
|
||||
SetMenu(m, pullDownMenu.controls)
|
||||
if xxx.__class__ == xxxNotebook:
|
||||
m.Enable(m.FindItem('sizer'), False)
|
||||
elif not (xxx.isSizer or xxx.parent and xxx.parent.isSizer):
|
||||
m.Enable(ID_NEW.SPACER, False)
|
||||
# Select correct label for create menu
|
||||
if not needInsert:
|
||||
if self.shift:
|
||||
menu.AppendMenu(wxNewId(), 'Insert Child', m,
|
||||
'Create child object as the first child')
|
||||
else:
|
||||
menu.AppendMenu(wxNewId(), 'Append Child', m,
|
||||
'Create child object as the last child')
|
||||
else:
|
||||
if self.shift:
|
||||
menu.AppendMenu(wxNewId(), 'Create Sibling', m,
|
||||
'Create sibling before selected object')
|
||||
else:
|
||||
menu.AppendMenu(wxNewId(), 'Create Sibling', m,
|
||||
'Create sibling after selected object')
|
||||
menu.AppendSeparator()
|
||||
# Not using standart IDs because we don't want to show shortcuts
|
||||
menu.Append(wxID_CUT, 'Cut', 'Cut to the clipboard')
|
||||
menu.Append(wxID_COPY, 'Copy', 'Copy to the clipboard')
|
||||
if self.ctrl and item != self.root:
|
||||
menu.Append(pullDownMenu.ID_PASTE_SIBLING, 'Paste Sibling',
|
||||
'Paste from the clipboard as a sibling')
|
||||
else:
|
||||
menu.Append(wxID_PASTE, 'Paste', 'Paste from the clipboard')
|
||||
menu.Append(pullDownMenu.ID_DELETE,
|
||||
'Delete', 'Delete object')
|
||||
if self.ItemHasChildren(item):
|
||||
menu.AppendSeparator()
|
||||
menu.Append(pullDownMenu.ID_EXPAND, 'Expand', 'Expand subtree')
|
||||
menu.Append(pullDownMenu.ID_COLLAPSE, 'Collapse', 'Collapse subtree')
|
||||
self.PopupMenu(menu, evt.GetPosition())
|
||||
menu.Destroy()
|
||||
|
||||
# Apply changes
|
||||
def Apply(self, xxx, item):
|
||||
g.panel.Apply()
|
||||
# Update tree view
|
||||
xxx = xxx.treeObject()
|
||||
if xxx.hasName and self.GetItemText(item) != xxx.name:
|
||||
self.SetItemText(item, xxx.treeName())
|
||||
# Item width may have changed
|
||||
# !!! Tric to update tree width (wxGTK, ??)
|
||||
self.SetIndent(self.GetIndent())
|
||||
# Change tree icon for sizers
|
||||
if isinstance(xxx, xxxBoxSizer):
|
||||
self.SetItemImage(item, xxx.treeImage())
|
||||
# Set global modified state
|
||||
g.frame.modified = True
|
||||
|
151
wxPython/wxPython/tools/XRCed/undo.py
Normal file
@@ -0,0 +1,151 @@
|
||||
# Name: undo.py
|
||||
# Purpose: XRC editor, undo/redo module
|
||||
# Author: Roman Rolinsky <rolinsky@mema.ucl.ac.be>
|
||||
# Created: 01.12.2002
|
||||
# RCS-ID: $Id$
|
||||
|
||||
from globals import *
|
||||
#from panel import *
|
||||
|
||||
# Undo/redo classes
|
||||
class UndoManager:
|
||||
# Undo/redo stacks
|
||||
undo = []
|
||||
redo = []
|
||||
def RegisterUndo(self, undoObj):
|
||||
self.undo.append(undoObj)
|
||||
for i in self.redo: i.destroy()
|
||||
self.redo = []
|
||||
def Undo(self):
|
||||
undoObj = self.undo.pop()
|
||||
undoObj.undo()
|
||||
self.redo.append(undoObj)
|
||||
g.frame.modified = True
|
||||
g.frame.SetStatusText('Undone')
|
||||
def Redo(self):
|
||||
undoObj = self.redo.pop()
|
||||
undoObj.redo()
|
||||
self.undo.append(undoObj)
|
||||
g.frame.modified = True
|
||||
g.frame.SetStatusText('Redone')
|
||||
def Clear(self):
|
||||
for i in self.undo: i.destroy()
|
||||
self.undo = []
|
||||
for i in self.redo: i.destroy()
|
||||
self.redo = []
|
||||
def CanUndo(self):
|
||||
return not not self.undo
|
||||
def CanRedo(self):
|
||||
return not not self.redo
|
||||
|
||||
class UndoCutDelete:
|
||||
def __init__(self, itemIndex, parent, elem):
|
||||
self.itemIndex = itemIndex
|
||||
self.parent = parent
|
||||
self.elem = elem
|
||||
def destroy(self):
|
||||
if self.elem: self.elem.unlink()
|
||||
def undo(self):
|
||||
item = g.tree.InsertNode(g.tree.ItemAtFullIndex(self.itemIndex[:-1]),
|
||||
self.parent, self.elem,
|
||||
g.tree.ItemAtFullIndex(self.itemIndex))
|
||||
# Scroll to show new item (!!! redundant?)
|
||||
g.tree.EnsureVisible(item)
|
||||
g.tree.SelectItem(item)
|
||||
self.elem = None
|
||||
# Update testWin if needed
|
||||
if g.testWin and g.tree.IsHighlatable(item):
|
||||
if g.conf.autoRefresh:
|
||||
g.tree.needUpdate = True
|
||||
g.tree.pendingHighLight = item
|
||||
else:
|
||||
g.tree.pendingHighLight = None
|
||||
def redo(self):
|
||||
item = g.tree.ItemAtFullIndex(self.itemIndex)
|
||||
# Delete testWin?
|
||||
if g.testWin:
|
||||
# If deleting top-level item, delete testWin
|
||||
if item == g.testWin.item:
|
||||
g.testWin.Destroy()
|
||||
g.testWin = None
|
||||
else:
|
||||
# Remove highlight, update testWin
|
||||
if g.testWin.highLight:
|
||||
g.testWin.highLight.Remove()
|
||||
g.tree.needUpdate = True
|
||||
self.elem = g.tree.RemoveLeaf(item)
|
||||
g.tree.Unselect()
|
||||
g.panel.Clear()
|
||||
|
||||
class UndoPasteCreate:
|
||||
def __init__(self, itemParent, parent, item, selected):
|
||||
self.itemParentIndex = g.tree.ItemFullIndex(itemParent)
|
||||
self.parent = parent
|
||||
self.itemIndex = g.tree.ItemFullIndex(item) # pasted item
|
||||
self.selectedIndex = g.tree.ItemFullIndex(selected) # maybe different from item
|
||||
self.elem = None
|
||||
def destroy(self):
|
||||
if self.elem: self.elem.unlink()
|
||||
def undo(self):
|
||||
self.elem = g.tree.RemoveLeaf(g.tree.ItemAtFullIndex(self.itemIndex))
|
||||
# Restore old selection
|
||||
selected = g.tree.ItemAtFullIndex(self.selectedIndex)
|
||||
g.tree.EnsureVisible(selected)
|
||||
g.tree.SelectItem(selected)
|
||||
# Delete testWin?
|
||||
if g.testWin:
|
||||
# If deleting top-level item, delete testWin
|
||||
if selected == g.testWin.item:
|
||||
g.testWin.Destroy()
|
||||
g.testWin = None
|
||||
else:
|
||||
# Remove highlight, update testWin
|
||||
if g.testWin.highLight:
|
||||
g.testWin.highLight.Remove()
|
||||
g.tree.needUpdate = True
|
||||
def redo(self):
|
||||
item = g.tree.InsertNode(g.tree.ItemAtFullIndex(self.itemParentIndex),
|
||||
self.parent, self.elem,
|
||||
g.tree.ItemAtFullIndex(self.itemIndex))
|
||||
# Scroll to show new item
|
||||
g.tree.EnsureVisible(item)
|
||||
g.tree.SelectItem(item)
|
||||
self.elem = None
|
||||
# Update testWin if needed
|
||||
if g.testWin and g.tree.IsHighlatable(item):
|
||||
if g.conf.autoRefresh:
|
||||
g.tree.needUpdate = True
|
||||
g.tree.pendingHighLight = item
|
||||
else:
|
||||
g.tree.pendingHighLight = None
|
||||
|
||||
class UndoEdit:
|
||||
def __init__(self):
|
||||
self.pages = map(ParamPage.GetState, g.panel.pages)
|
||||
self.selectedIndex = g.tree.ItemFullIndex(g.tree.GetSelection())
|
||||
def destroy(self):
|
||||
pass
|
||||
# Update test view
|
||||
def update(self, selected):
|
||||
g.tree.Apply(g.tree.GetPyData(selected), selected)
|
||||
# Update view
|
||||
if g.testWin:
|
||||
if g.testWin.highLight:
|
||||
g.testWin.highLight.Remove()
|
||||
g.tree.pendingHighLight = selected
|
||||
if g.testWin:
|
||||
g.tree.needUpdate = True
|
||||
def undo(self):
|
||||
# Restore selection
|
||||
selected = g.tree.ItemAtFullIndex(self.selectedIndex)
|
||||
if selected != g.tree.GetSelection():
|
||||
g.tree.SelectItem(selected)
|
||||
# Save current state for redo
|
||||
map(ParamPage.SaveState, g.panel.pages)
|
||||
pages = map(ParamPage.GetState, g.panel.pages)
|
||||
map(ParamPage.SetState, g.panel.pages, self.pages)
|
||||
self.pages = pages
|
||||
self.update(selected)
|
||||
def redo(self):
|
||||
self.undo()
|
||||
self.update(g.tree.GetSelection())
|
@@ -23,13 +23,14 @@
|
||||
<object class="wxButton" name="BUTTON_UP">
|
||||
<label>Move Up</label>
|
||||
</object>
|
||||
<flag>wxBOTTOM</flag>
|
||||
<flag>wxBOTTOM|wxEXPAND</flag>
|
||||
<border>5</border>
|
||||
</object>
|
||||
<object class="sizeritem">
|
||||
<object class="wxButton" name="BUTTON_DOWN">
|
||||
<label>Move Down</label>
|
||||
</object>
|
||||
<flag>wxEXPAND</flag>
|
||||
</object>
|
||||
<object class="spacer">
|
||||
<size>10,20</size>
|
||||
@@ -39,13 +40,14 @@
|
||||
<object class="wxButton" name="BUTTON_APPEND">
|
||||
<label>Append...</label>
|
||||
</object>
|
||||
<flag>wxBOTTOM</flag>
|
||||
<flag>wxBOTTOM|wxEXPAND</flag>
|
||||
<border>5</border>
|
||||
</object>
|
||||
<object class="sizeritem">
|
||||
<object class="wxButton" name="BUTTON_REMOVE">
|
||||
<label>Remove</label>
|
||||
</object>
|
||||
<flag>wxEXPAND</flag>
|
||||
</object>
|
||||
</object>
|
||||
<flag>wxALL|wxEXPAND</flag>
|
||||
@@ -80,7 +82,7 @@
|
||||
<border>10</border>
|
||||
</object>
|
||||
</object>
|
||||
<style>wxRESIZE_BORDER</style>
|
||||
<style>wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER</style>
|
||||
</object>
|
||||
<object class="wxDialog" name="DIALOG_CONTENT_CHECK_LIST">
|
||||
<title>Content</title>
|
||||
@@ -105,13 +107,14 @@
|
||||
<object class="wxButton" name="BUTTON_UP">
|
||||
<label>Move Up</label>
|
||||
</object>
|
||||
<flag>wxBOTTOM</flag>
|
||||
<flag>wxBOTTOM|wxEXPAND</flag>
|
||||
<border>5</border>
|
||||
</object>
|
||||
<object class="sizeritem">
|
||||
<object class="wxButton" name="BUTTON_DOWN">
|
||||
<label>Move Down</label>
|
||||
</object>
|
||||
<flag>wxEXPAND</flag>
|
||||
</object>
|
||||
<object class="spacer">
|
||||
<size>10,20</size>
|
||||
@@ -121,13 +124,14 @@
|
||||
<object class="wxButton" name="BUTTON_APPEND">
|
||||
<label>Append...</label>
|
||||
</object>
|
||||
<flag>wxBOTTOM</flag>
|
||||
<flag>wxBOTTOM|wxEXPAND</flag>
|
||||
<border>5</border>
|
||||
</object>
|
||||
<object class="sizeritem">
|
||||
<object class="wxButton" name="BUTTON_REMOVE">
|
||||
<label>Remove</label>
|
||||
</object>
|
||||
<flag>wxEXPAND</flag>
|
||||
</object>
|
||||
</object>
|
||||
<flag>wxALL|wxEXPAND</flag>
|
||||
@@ -162,7 +166,7 @@
|
||||
<border>10</border>
|
||||
</object>
|
||||
</object>
|
||||
<style>wxRESIZE_BORDER</style>
|
||||
<style>wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER</style>
|
||||
</object>
|
||||
<object class="wxDialog" name="DIALOG_INTLIST">
|
||||
<title>Numbers</title>
|
||||
@@ -230,6 +234,89 @@
|
||||
<border>10</border>
|
||||
</object>
|
||||
</object>
|
||||
<style>wxRESIZE_BORDER</style>
|
||||
<style>wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER</style>
|
||||
</object>
|
||||
<object class="wxPanel" name="PANEL_BITMAP">
|
||||
<object class="wxStaticBoxSizer">
|
||||
<label></label>
|
||||
<orient>wxVERTICAL</orient>
|
||||
<object class="sizeritem">
|
||||
<object class="wxFlexGridSizer">
|
||||
<cols>2</cols>
|
||||
<rows>2</rows>
|
||||
<object class="sizeritem">
|
||||
<object class="wxRadioButton" name="RADIO_STD">
|
||||
<label>art:</label>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem">
|
||||
<object class="wxComboBox" name="COMBO_STD">
|
||||
<content>
|
||||
<item>wxART_ADD_BOOKMARK</item>
|
||||
<item>wxART_DEL_BOOKMARK</item>
|
||||
<item>wxART_HELP_SIDE_PANEL</item>
|
||||
<item>wxART_HELP_SETTINGS</item>
|
||||
<item>wxART_HELP_BOOK</item>
|
||||
<item>wxART_HELP_FOLDER</item>
|
||||
<item>wxART_HELP_PAGE</item>
|
||||
<item>wxART_GO_BACK</item>
|
||||
<item>wxART_GO_FORWARD</item>
|
||||
<item>wxART_GO_UP</item>
|
||||
<item>wxART_GO_DOWN</item>
|
||||
<item>wxART_GO_TO_PARENT</item>
|
||||
<item>wxART_GO_HOME</item>
|
||||
<item>wxART_FILE_OPEN</item>
|
||||
<item>wxART_PRINT</item>
|
||||
<item>wxART_HELP</item>
|
||||
<item>wxART_TIP</item>
|
||||
<item>wxART_REPORT_VIEW</item>
|
||||
<item>wxART_LIST_VIEW</item>
|
||||
<item>wxART_NEW_DIR</item>
|
||||
<item>wxART_FOLDER</item>
|
||||
<item>wxART_GO_DIR_UP</item>
|
||||
<item>wxART_EXECUTABLE_FILE</item>
|
||||
<item>wxART_NORMAL_FILE</item>
|
||||
<item>wxART_TICK_MARK</item>
|
||||
<item>wxART_CROSS_MARK</item>
|
||||
<item>wxART_ERROR</item>
|
||||
<item>wxART_QUESTION</item>
|
||||
<item>wxART_WARNING</item>
|
||||
<item>wxART_INFORMATION</item>
|
||||
<item>wxART_MISSING_IMAGE</item>
|
||||
</content>
|
||||
</object>
|
||||
<flag>wxRIGHT|wxEXPAND</flag>
|
||||
<border>5</border>
|
||||
</object>
|
||||
<object class="sizeritem">
|
||||
<object class="wxRadioButton" name="RADIO_FILE">
|
||||
<label>file:</label>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem">
|
||||
<object class="wxBoxSizer">
|
||||
<orient>wxHORIZONTAL</orient>
|
||||
<object class="sizeritem">
|
||||
<object class="wxTextCtrl" name="TEXT_FILE"/>
|
||||
<option>1</option>
|
||||
<flag>wxRIGHT|wxEXPAND</flag>
|
||||
<border>5</border>
|
||||
</object>
|
||||
<object class="sizeritem">
|
||||
<object class="wxButton" name="BUTTON_BROWSE">
|
||||
<label>Browse...</label>
|
||||
<size>30,-1d</size>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
<flag>wxRIGHT|wxEXPAND</flag>
|
||||
<border>5</border>
|
||||
</object>
|
||||
<vgap>2</vgap>
|
||||
<growablecols>1</growablecols>
|
||||
</object>
|
||||
<flag>wxEXPAND</flag>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</resource>
|
@@ -4,13 +4,14 @@
|
||||
# Created: 22.08.2001
|
||||
# RCS-ID: $Id$
|
||||
|
||||
from wxPython.wx import *
|
||||
from wxPython.xrc import *
|
||||
from xml.dom import minidom
|
||||
import wxPython.lib.wxpTag
|
||||
|
||||
from globals import *
|
||||
from params import *
|
||||
|
||||
currentEncoding = wxLocale_GetSystemEncodingName()
|
||||
if not currentEncoding:
|
||||
currentEncoding = 'ascii'
|
||||
|
||||
# Base class for interface parameter classes
|
||||
class xxxNode:
|
||||
def __init__(self, node):
|
||||
@@ -26,17 +27,24 @@ class xxxParam(xxxNode):
|
||||
xxxNode.__init__(self, node)
|
||||
if not node.hasChildNodes():
|
||||
# If does not have child nodes, create empty text node
|
||||
text = tree.dom.createTextNode('')
|
||||
text = g.tree.dom.createTextNode('')
|
||||
node.appendChild(text)
|
||||
else:
|
||||
text = node.childNodes[0] # first child must be text node
|
||||
assert text.nodeType == minidom.Node.TEXT_NODE
|
||||
# Use convertion from unicode to current encoding
|
||||
self.textNode = text
|
||||
# Value returns string
|
||||
def value(self):
|
||||
return self.textNode.data
|
||||
def update(self, value):
|
||||
self.textNode.data = value
|
||||
if wxUSE_UNICODE: # no conversion is needed
|
||||
def value(self):
|
||||
return self.textNode.data
|
||||
def update(self, value):
|
||||
self.textNode.data = value
|
||||
else:
|
||||
def value(self):
|
||||
return self.textNode.data.encode(currentEncoding)
|
||||
def update(self, value):
|
||||
self.textNode.data = unicode(value, currentEncoding)
|
||||
|
||||
# Integer parameter
|
||||
class xxxParamInt(xxxParam):
|
||||
@@ -63,7 +71,7 @@ class xxxParamContent(xxxNode):
|
||||
assert n.tagName == 'item', 'bad content content'
|
||||
if not n.hasChildNodes():
|
||||
# If does not have child nodes, create empty text node
|
||||
text = tree.dom.createTextNode('')
|
||||
text = g.tree.dom.createTextNode('')
|
||||
node.appendChild(text)
|
||||
else:
|
||||
# !!! normalize?
|
||||
@@ -85,8 +93,8 @@ class xxxParamContent(xxxNode):
|
||||
self.node.removeChild(n)
|
||||
l = []
|
||||
for str in value:
|
||||
itemElem = tree.dom.createElement('item')
|
||||
itemText = tree.dom.createTextNode(str)
|
||||
itemElem = g.tree.dom.createElement('item')
|
||||
itemText = g.tree.dom.createTextNode(str)
|
||||
itemElem.appendChild(itemText)
|
||||
self.node.appendChild(itemElem)
|
||||
l.append(itemText)
|
||||
@@ -106,9 +114,10 @@ class xxxParamContentCheckList(xxxNode):
|
||||
if n.nodeType == minidom.Node.ELEMENT_NODE:
|
||||
assert n.tagName == 'item', 'bad content content'
|
||||
checked = n.getAttribute('checked')
|
||||
if not checked: checked = 0
|
||||
if not n.hasChildNodes():
|
||||
# If does not have child nodes, create empty text node
|
||||
text = tree.dom.createTextNode('')
|
||||
text = g.tree.dom.createTextNode('')
|
||||
node.appendChild(text)
|
||||
else:
|
||||
# !!! normalize?
|
||||
@@ -129,10 +138,11 @@ class xxxParamContentCheckList(xxxNode):
|
||||
for n in childNodes:
|
||||
self.node.removeChild(n)
|
||||
l = []
|
||||
for (s,ch) in value:
|
||||
itemElem = tree.dom.createElement('item')
|
||||
itemElem.setAttribute('checked', str(ch))
|
||||
itemText = tree.dom.createTextNode(s)
|
||||
for s,ch in value:
|
||||
itemElem = g.tree.dom.createElement('item')
|
||||
# Add checked only if True
|
||||
if ch: itemElem.setAttribute('checked', '1')
|
||||
itemText = g.tree.dom.createTextNode(s)
|
||||
itemElem.appendChild(itemText)
|
||||
self.node.appendChild(itemElem)
|
||||
l.append((itemText, itemElem))
|
||||
@@ -143,20 +153,37 @@ class xxxParamContentCheckList(xxxNode):
|
||||
self.l[i][1].setAttribute('checked', str(value[i][1]))
|
||||
self.data = value
|
||||
|
||||
# Bitmap parameter
|
||||
class xxxParamBitmap(xxxParam):
|
||||
def __init__(self, node):
|
||||
xxxParam.__init__(self, node)
|
||||
self.stock_id = node.getAttribute('stock_id')
|
||||
def value(self):
|
||||
return [self.stock_id, xxxParam.value(self)]
|
||||
def update(self, value):
|
||||
self.stock_id = value[0]
|
||||
if self.stock_id:
|
||||
self.node.setAttribute('stock_id', self.stock_id)
|
||||
else:
|
||||
self.node.removeAttribute('stock_id')
|
||||
xxxParam.update(self, value[1])
|
||||
|
||||
################################################################################
|
||||
|
||||
# Classes to interface DOM objects
|
||||
class xxxObject:
|
||||
# Default behavior
|
||||
hasChildren = false # has children elements?
|
||||
hasStyle = true # almost everyone
|
||||
hasName = true # has name attribute?
|
||||
isSizer = hasChild = false
|
||||
hasChildren = False # has children elements?
|
||||
hasStyle = True # almost everyone
|
||||
hasName = True # has name attribute?
|
||||
isSizer = hasChild = False
|
||||
allParams = None # Some nodes have no parameters
|
||||
# Style parameters (all optional)
|
||||
styles = ['fg', 'bg', 'font', 'enabled', 'focused', 'hidden', 'tooltip']
|
||||
# Special parameters
|
||||
specials = []
|
||||
# Bitmap tags
|
||||
bitmapTags = ['bitmap', 'bitmap2', 'icon']
|
||||
# Required paremeters: none by default
|
||||
required = []
|
||||
# Default parameters with default values
|
||||
@@ -184,7 +211,7 @@ class xxxObject:
|
||||
tag = node.tagName
|
||||
if tag == 'object':
|
||||
continue # do nothing for object children here
|
||||
if not tag in self.allParams and not tag in self.styles:
|
||||
if tag not in self.allParams and tag not in self.styles:
|
||||
print 'WARNING: unknown parameter for %s: %s' % \
|
||||
(self.className, tag)
|
||||
elif tag in self.specials:
|
||||
@@ -196,12 +223,38 @@ class xxxObject:
|
||||
self.params[tag] = xxxParamContent(node)
|
||||
elif tag == 'font': # has children
|
||||
self.params[tag] = xxxParamFont(element, node)
|
||||
elif tag in self.bitmapTags:
|
||||
# Can have attributes
|
||||
self.params[tag] = xxxParamBitmap(node)
|
||||
else: # simple parameter
|
||||
self.params[tag] = xxxParam(node)
|
||||
else:
|
||||
# Remove all other nodes
|
||||
element.removeChild(node)
|
||||
node.unlink()
|
||||
# Check that all required params are set
|
||||
for param in self.required:
|
||||
if not self.params.has_key(param):
|
||||
# If default is specified, set it
|
||||
if self.default.has_key(param):
|
||||
elem = g.tree.dom.createElement(param)
|
||||
self.params[param] = xxxParam(elem)
|
||||
# Find place to put new element: first present element after param
|
||||
found = False
|
||||
paramStyles = self.allParams + self.styles
|
||||
for p in paramStyles[paramStyles.index(param) + 1:]:
|
||||
# Content params don't have same type
|
||||
if self.params.has_key(p) and p != 'content':
|
||||
found = True
|
||||
break
|
||||
if found:
|
||||
nextTextElem = self.params[p].node
|
||||
self.element.insertBefore(elem, nextTextElem)
|
||||
else:
|
||||
self.element.appendChild(elem)
|
||||
else:
|
||||
wxLogWarning('Required parameter %s of %s missing' %
|
||||
(param, self.className))
|
||||
# Returns real tree object
|
||||
def treeObject(self):
|
||||
if self.hasChild: return self.child
|
||||
@@ -244,8 +297,8 @@ class xxxParamFont(xxxObject, xxxNode):
|
||||
v = []
|
||||
for param in self.allParams:
|
||||
if value[i]:
|
||||
fontElem = tree.dom.createElement(param)
|
||||
textNode = tree.dom.createTextNode(value[i])
|
||||
fontElem = g.tree.dom.createElement(param)
|
||||
textNode = g.tree.dom.createTextNode(value[i])
|
||||
self.params[param] = textNode
|
||||
fontElem.appendChild(textNode)
|
||||
elem.appendChild(fontElem)
|
||||
@@ -258,11 +311,27 @@ class xxxParamFont(xxxObject, xxxNode):
|
||||
################################################################################
|
||||
|
||||
class xxxContainer(xxxObject):
|
||||
hasChildren = true
|
||||
hasChildren = True
|
||||
|
||||
# Simulate normal parameter for encoding
|
||||
class xxxEncoding:
|
||||
def __init__(self, val):
|
||||
self.encd = val
|
||||
def value(self):
|
||||
return self.encd
|
||||
def update(self, val):
|
||||
self.encd = val
|
||||
|
||||
# Special class for root node
|
||||
class xxxMainNode(xxxContainer):
|
||||
hasStyle = hasName = false
|
||||
allParams = ['encoding']
|
||||
required = ['encoding']
|
||||
default = {'encoding': ''}
|
||||
hasStyle = hasName = False
|
||||
def __init__(self, dom):
|
||||
xxxContainer.__init__(self, None, dom.documentElement)
|
||||
self.className = 'XML tree'
|
||||
self.params['encoding'] = xxxEncoding(dom.encoding)
|
||||
|
||||
################################################################################
|
||||
# Top-level windwows
|
||||
@@ -275,12 +344,13 @@ class xxxPanel(xxxContainer):
|
||||
exStyles = ['wxWS_EX_VALIDATE_RECURSIVELY']
|
||||
|
||||
class xxxDialog(xxxContainer):
|
||||
allParams = ['title', 'pos', 'size', 'style']
|
||||
allParams = ['title', 'centered', 'pos', 'size', 'style']
|
||||
paramDict = {'centered': ParamBool}
|
||||
required = ['title']
|
||||
winStyles = ['wxDEFAULT_DIALOG_STYLE', 'wxSTAY_ON_TOP',
|
||||
'wxDIALOG_MODAL', 'wxDIALOG_MODELESS',
|
||||
'wxCAPTION', 'wxSYSTEM_MENU', 'wxRESIZE_BORDER', 'wxRESIZE_BOX',
|
||||
'wxTHICK_FRAME',
|
||||
'wxTHICK_FRAME',
|
||||
'wxNO_3D', 'wxTAB_TRAVERSAL', 'wxCLIP_CHILDREN']
|
||||
styles = ['fg', 'bg', 'font', 'enabled', 'focused', 'hidden', 'exstyle',
|
||||
'tooltip']
|
||||
@@ -291,7 +361,7 @@ class xxxFrame(xxxContainer):
|
||||
paramDict = {'centered': ParamBool}
|
||||
required = ['title']
|
||||
winStyles = ['wxDEFAULT_FRAME_STYLE', 'wxDEFAULT_DIALOG_STYLE',
|
||||
'wxSTAY_ON_TOP',
|
||||
'wxSTAY_ON_TOP',
|
||||
'wxCAPTION', 'wxSYSTEM_MENU', 'wxRESIZE_BORDER',
|
||||
'wxRESIZE_BOX', 'wxMINIMIZE_BOX', 'wxMAXIMIZE_BOX',
|
||||
'wxFRAME_FLOAT_ON_PARENT', 'wxFRAME_TOOL_WINDOW',
|
||||
@@ -302,13 +372,14 @@ class xxxFrame(xxxContainer):
|
||||
|
||||
class xxxTool(xxxObject):
|
||||
allParams = ['bitmap', 'bitmap2', 'toggle', 'tooltip', 'longhelp']
|
||||
paramDict = {'bitmap2': ParamFile}
|
||||
hasStyle = false
|
||||
required = ['bitmap']
|
||||
paramDict = {'bitmap2': ParamBitmap, 'toggle': ParamBool}
|
||||
hasStyle = False
|
||||
|
||||
class xxxToolBar(xxxContainer):
|
||||
allParams = ['bitmapsize', 'margins', 'packing', 'separation',
|
||||
allParams = ['bitmapsize', 'margins', 'packing', 'separation',
|
||||
'pos', 'size', 'style']
|
||||
hasStyle = false
|
||||
hasStyle = False
|
||||
paramDict = {'bitmapsize': ParamPosSize, 'margins': ParamPosSize,
|
||||
'packing': ParamInt, 'separation': ParamInt,
|
||||
'style': ParamNonGenericStyle}
|
||||
@@ -321,6 +392,7 @@ class xxxBitmap(xxxObject):
|
||||
allParams = ['bitmap']
|
||||
required = ['bitmap']
|
||||
|
||||
# Just like bitmap
|
||||
class xxxIcon(xxxObject):
|
||||
allParams = ['icon']
|
||||
required = ['icon']
|
||||
@@ -331,6 +403,7 @@ class xxxIcon(xxxObject):
|
||||
class xxxStaticText(xxxObject):
|
||||
allParams = ['label', 'pos', 'size', 'style']
|
||||
required = ['label']
|
||||
default = {'label': ''}
|
||||
winStyles = ['wxALIGN_LEFT', 'wxALIGN_RIGHT', 'wxALIGN_CENTRE', 'wxST_NO_AUTORESIZE']
|
||||
|
||||
class xxxStaticLine(xxxObject):
|
||||
@@ -392,7 +465,7 @@ class xxxHtmlWindow(xxxObject):
|
||||
paramDict = {'borders': ParamInt}
|
||||
winStyles = ['wxHW_SCROLLBAR_NEVER', 'wxHW_SCROLLBAR_AUTO']
|
||||
|
||||
class xxxCalendar(xxxObject):
|
||||
class xxxCalendarCtrl(xxxObject):
|
||||
allParams = ['pos', 'size', 'style']
|
||||
|
||||
class xxxNotebook(xxxContainer):
|
||||
@@ -400,6 +473,12 @@ class xxxNotebook(xxxContainer):
|
||||
paramDict = {'usenotebooksizer': ParamBool}
|
||||
winStyles = ['wxNB_FIXEDWIDTH', 'wxNB_LEFT', 'wxNB_RIGHT', 'wxNB_BOTTOM']
|
||||
|
||||
class xxxGenericDirCtrl(xxxObject):
|
||||
allParams = ['defaultfolder', 'filter', 'defaultfilter', 'pos', 'size', 'style']
|
||||
paramDict = {'defaultfilter': ParamInt}
|
||||
winStyles = ['wxDIRCTRL_DIR_ONLY', 'wxDIRCTRL_3D_INTERNAL', 'wxDIRCTRL_SELECT_FIRST',
|
||||
'wxDIRCTRL_SHOW_FILTERS', 'wxDIRCTRL_EDIT_LABELS']
|
||||
|
||||
################################################################################
|
||||
# Buttons
|
||||
|
||||
@@ -423,7 +502,13 @@ class xxxRadioButton(xxxObject):
|
||||
winStyles = ['wxRB_GROUP']
|
||||
|
||||
class xxxSpinButton(xxxObject):
|
||||
allParams = ['pos', 'size', 'style']
|
||||
allParams = ['value', 'min', 'max', 'pos', 'size', 'style']
|
||||
paramDict = {'value': ParamInt}
|
||||
winStyles = ['wxSP_HORIZONTAL', 'wxSP_VERTICAL', 'wxSP_ARROW_KEYS', 'wxSP_WRAP']
|
||||
|
||||
class xxxSpinCtrl(xxxObject):
|
||||
allParams = ['value', 'min', 'max', 'pos', 'size', 'style']
|
||||
paramDict = {'value': ParamInt}
|
||||
winStyles = ['wxSP_HORIZONTAL', 'wxSP_VERTICAL', 'wxSP_ARROW_KEYS', 'wxSP_WRAP']
|
||||
|
||||
################################################################################
|
||||
@@ -440,7 +525,8 @@ class xxxRadioBox(xxxObject):
|
||||
winStyles = ['wxRA_SPECIFY_ROWS', 'wxRA_SPECIFY_COLS']
|
||||
|
||||
class xxxCheckBox(xxxObject):
|
||||
allParams = ['label', 'pos', 'size', 'style']
|
||||
allParams = ['label', 'checked', 'pos', 'size', 'style']
|
||||
paramDict = {'checked': ParamBool}
|
||||
required = ['label']
|
||||
|
||||
class xxxComboBox(xxxObject):
|
||||
@@ -462,14 +548,14 @@ class xxxCheckList(xxxObject):
|
||||
'wxLC_USER_TEXT', 'wxLC_EDIT_LABELS', 'wxLC_NO_HEADER',
|
||||
'wxLC_SINGLE_SEL', 'wxLC_SORT_ASCENDING', 'wxLC_SORT_DESCENDING']
|
||||
paramDict = {'content': ParamContentCheckList}
|
||||
|
||||
|
||||
################################################################################
|
||||
# Sizers
|
||||
|
||||
class xxxSizer(xxxContainer):
|
||||
hasName = hasStyle = false
|
||||
hasName = hasStyle = False
|
||||
paramDict = {'orient': ParamOrient}
|
||||
isSizer = true
|
||||
isSizer = True
|
||||
|
||||
class xxxBoxSizer(xxxSizer):
|
||||
allParams = ['orient']
|
||||
@@ -483,7 +569,6 @@ class xxxBoxSizer(xxxSizer):
|
||||
class xxxStaticBoxSizer(xxxBoxSizer):
|
||||
allParams = ['label', 'orient']
|
||||
required = ['label', 'orient']
|
||||
default = {'orient': 'wxVERTICAL'}
|
||||
|
||||
class xxxGridSizer(xxxSizer):
|
||||
allParams = ['cols', 'rows', 'vgap', 'hgap']
|
||||
@@ -492,7 +577,8 @@ class xxxGridSizer(xxxSizer):
|
||||
|
||||
# For repeated parameters
|
||||
class xxxParamMulti:
|
||||
def __init__(self):
|
||||
def __init__(self, node):
|
||||
self.node = node
|
||||
self.l, self.data = [], []
|
||||
def append(self, param):
|
||||
self.l.append(param)
|
||||
@@ -511,16 +597,17 @@ class xxxFlexGridSizer(xxxGridSizer):
|
||||
# Special processing for growable* parameters
|
||||
# (they are represented by several nodes)
|
||||
def special(self, tag, node):
|
||||
if tag not in self.params:
|
||||
self.params[tag] = xxxParamMulti()
|
||||
if not self.params.has_key(tag):
|
||||
# Create new multi-group
|
||||
self.params[tag] = xxxParamMulti(node)
|
||||
self.params[tag].append(xxxParamInt(node))
|
||||
def setSpecial(self, param, value):
|
||||
# Straightforward implementation: remove, add again
|
||||
self.params[param].remove()
|
||||
del self.params[param]
|
||||
for i in value:
|
||||
node = tree.dom.createElement(param)
|
||||
text = tree.dom.createTextNode(str(i))
|
||||
node = g.tree.dom.createElement(param)
|
||||
text = g.tree.dom.createTextNode(str(i))
|
||||
node.appendChild(text)
|
||||
self.element.appendChild(node)
|
||||
self.special(param, node)
|
||||
@@ -528,8 +615,8 @@ class xxxFlexGridSizer(xxxGridSizer):
|
||||
# Container with only one child.
|
||||
# Not shown in tree.
|
||||
class xxxChildContainer(xxxObject):
|
||||
hasName = hasStyle = false
|
||||
hasChild = true
|
||||
hasName = hasStyle = False
|
||||
hasChild = True
|
||||
def __init__(self, parent, element):
|
||||
xxxObject.__init__(self, parent, element)
|
||||
# Must have one child with 'object' tag, but we don't check it
|
||||
@@ -550,8 +637,8 @@ class xxxChildContainer(xxxObject):
|
||||
assert 0, 'no child found'
|
||||
|
||||
class xxxSizerItem(xxxChildContainer):
|
||||
allParams = ['option', 'flag', 'border']
|
||||
paramDict = {'option': ParamInt}
|
||||
allParams = ['option', 'flag', 'border', 'minsize']
|
||||
paramDict = {'option': ParamInt, 'minsize': ParamPosSize}
|
||||
def __init__(self, parent, element):
|
||||
xxxChildContainer.__init__(self, parent, element)
|
||||
# Remove pos parameter - not needed for sizeritems
|
||||
@@ -574,26 +661,37 @@ class xxxNotebookPage(xxxChildContainer):
|
||||
self.child.allParams.remove('size')
|
||||
|
||||
class xxxSpacer(xxxObject):
|
||||
hasName = hasStyle = false
|
||||
hasName = hasStyle = False
|
||||
allParams = ['size', 'option', 'flag', 'border']
|
||||
paramDict = {'option': ParamInt}
|
||||
default = {'size': '0,0'}
|
||||
|
||||
class xxxMenuBar(xxxContainer):
|
||||
allParams = []
|
||||
allParams = ['style']
|
||||
paramDict = {'style': ParamNonGenericStyle} # no generic styles
|
||||
winStyles = ['wxMB_DOCKABLE']
|
||||
|
||||
class xxxMenu(xxxContainer):
|
||||
allParams = ['label']
|
||||
allParams = ['label', 'help', 'style']
|
||||
default = {'label': ''}
|
||||
paramDict = {'style': ParamNonGenericStyle} # no generic styles
|
||||
winStyles = ['wxMENU_TEAROFF']
|
||||
|
||||
class xxxMenuItem(xxxObject):
|
||||
allParams = ['checkable', 'label', 'accel', 'help']
|
||||
allParams = ['label', 'bitmap', 'accel', 'help',
|
||||
'checkable', 'radio', 'enabled', 'checked']
|
||||
default = {'label': ''}
|
||||
hasStyle = False
|
||||
|
||||
class xxxSeparator(xxxObject):
|
||||
hasName = hasStyle = false
|
||||
hasName = hasStyle = False
|
||||
|
||||
################################################################################
|
||||
# Unknown control
|
||||
|
||||
class xxxUnknown(xxxObject):
|
||||
allParams = ['pos', 'size', 'style']
|
||||
paramDict = {'style': ParamNonGenericStyle} # no generic styles
|
||||
|
||||
################################################################################
|
||||
|
||||
@@ -603,7 +701,7 @@ xxxDict = {
|
||||
'wxFrame': xxxFrame,
|
||||
'tool': xxxTool,
|
||||
'wxToolBar': xxxToolBar,
|
||||
|
||||
|
||||
'wxBitmap': xxxBitmap,
|
||||
'wxIcon': xxxIcon,
|
||||
|
||||
@@ -632,8 +730,10 @@ xxxDict = {
|
||||
'wxNotebook': xxxNotebook,
|
||||
'notebookpage': xxxNotebookPage,
|
||||
'wxHtmlWindow': xxxHtmlWindow,
|
||||
'wxCalendar': xxxCalendar,
|
||||
|
||||
'wxCalendarCtrl': xxxCalendarCtrl,
|
||||
'wxGenericDirCtrl': xxxGenericDirCtrl,
|
||||
'wxSpinCtrl': xxxSpinCtrl,
|
||||
|
||||
'wxBoxSizer': xxxBoxSizer,
|
||||
'wxStaticBoxSizer': xxxStaticBoxSizer,
|
||||
'wxGridSizer': xxxGridSizer,
|
||||
@@ -645,12 +745,14 @@ xxxDict = {
|
||||
'wxMenu': xxxMenu,
|
||||
'wxMenuItem': xxxMenuItem,
|
||||
'separator': xxxSeparator,
|
||||
|
||||
'unknown': xxxUnknown,
|
||||
}
|
||||
|
||||
# Create IDs for all parameters of all classes
|
||||
paramIDs = {'fg': wxNewId(), 'bg': wxNewId(), 'exstyle': wxNewId(), 'font': wxNewId(),
|
||||
'enabled': wxNewId(), 'focused': wxNewId(), 'hidden': wxNewId(),
|
||||
'tooltip': wxNewId()
|
||||
'tooltip': wxNewId(), 'encoding': wxNewId()
|
||||
}
|
||||
for cl in xxxDict.values():
|
||||
if cl.allParams:
|
||||
@@ -668,27 +770,27 @@ def IsObject(node):
|
||||
# Make XXX object from some DOM object, selecting correct class
|
||||
def MakeXXXFromDOM(parent, element):
|
||||
try:
|
||||
return xxxDict[element.getAttribute('class')](parent, element)
|
||||
klass = xxxDict[element.getAttribute('class')]
|
||||
except KeyError:
|
||||
# Verify that it's not recursive exception
|
||||
if element.getAttribute('class') not in xxxDict:
|
||||
print 'ERROR: unknown class:', element.getAttribute('class')
|
||||
print 'ERROR: unknown class:', element.getAttribute('class')
|
||||
raise
|
||||
return klass(parent, element)
|
||||
|
||||
# Make empty DOM element
|
||||
def MakeEmptyDOM(className):
|
||||
elem = tree.dom.createElement('object')
|
||||
def MakeEmptyDOM(className):
|
||||
elem = g.tree.dom.createElement('object')
|
||||
elem.setAttribute('class', className)
|
||||
# Set required and default parameters
|
||||
xxxClass = xxxDict[className]
|
||||
defaultNotRequired = filter(lambda x, l=xxxClass.required: x not in l,
|
||||
xxxClass.default.keys())
|
||||
for param in xxxClass.required + defaultNotRequired:
|
||||
textElem = tree.dom.createElement(param)
|
||||
textElem = g.tree.dom.createElement(param)
|
||||
try:
|
||||
textNode = tree.dom.createTextNode(xxxClass.default[param])
|
||||
textNode = g.tree.dom.createTextNode(xxxClass.default[param])
|
||||
except KeyError:
|
||||
textNode = tree.dom.createTextNode('')
|
||||
textNode = g.tree.dom.createTextNode('')
|
||||
textElem.appendChild(textNode)
|
||||
elem.appendChild(textElem)
|
||||
return elem
|
||||
|
256
wxPython/wxPython/tools/dbg.py
Normal file
@@ -0,0 +1,256 @@
|
||||
#----------------------------------------------------------------------------
|
||||
# Name: dbg.py
|
||||
# RCS-ID: $Id$
|
||||
# Author: Will Sadkin
|
||||
# Email: wsadkin@nameconnector.com
|
||||
# Created: 07/11/2002
|
||||
# Copyright: (c) 2002 by Will Sadkin, 2002
|
||||
# License: wxWindows license
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
"""
|
||||
This module provides a useful debugging framework that supports
|
||||
showing nesting of function calls and allows a program to contain
|
||||
lots of debugging print statements that can easily be turned on
|
||||
or off to debug the code. It also supports the ability to
|
||||
have each function indent the debugging statements contained
|
||||
within it, including those of any other function called within
|
||||
its scope, thus allowing you to see in what order functions are
|
||||
being called, and from where.
|
||||
|
||||
This capability is particularly useful in wxPython applications,
|
||||
where exactly events occur that cause functions to be called is
|
||||
not entirely clear, and because wxPython programs can't be run
|
||||
from inside other debugging environments that have their own
|
||||
message loops.
|
||||
|
||||
This module defines a Logger class, responsible for managing
|
||||
debugging output. Each Logger instance can be given a name
|
||||
at construction; if this is done, '<name>:' will precede each
|
||||
logging output made by that Logger instance.
|
||||
|
||||
The log() function this class provides takes a set of positional
|
||||
arguments that are printed in order if debugging is enabled
|
||||
(just like print does), followed by a set of keyword arguments
|
||||
that control the behavior of the log() function itself on subsequent
|
||||
calls. The current keyword arguments are:
|
||||
|
||||
indent
|
||||
When set to a value of 1, this increments the current
|
||||
indentation level, causing all subsequent dbg() outputs to be
|
||||
indented by 3 more spaces. When set to a value of 0,
|
||||
this process is reversed, causing the indent to decrease by
|
||||
3 spaces. The default indentation level is 0.
|
||||
|
||||
enable
|
||||
When set to a value of 1, this turns on dbg() output for
|
||||
for program importing this module, until told to do otherwise.
|
||||
When set to a value of 0, dbg output is turned off. (dbg
|
||||
output is off by default.)
|
||||
|
||||
suspend
|
||||
When set to a value of 1, this increments the current
|
||||
"suspension" level. This makes it possible for a function
|
||||
to temporarily suspend its and any of its dependents'
|
||||
potential outputs that use the same Logger instance.
|
||||
When set to a value of 0, the suspension level is
|
||||
decremented. When the value goes back to 0, potential
|
||||
logging is resumed (actual output depends on the
|
||||
"enable" status of the Logger instance in question.)
|
||||
|
||||
wxlog
|
||||
When set to a value of 1, the output will be sent to the
|
||||
active wxLog target.
|
||||
|
||||
stream
|
||||
When set to a non-None value, the current output stream
|
||||
(default of sys.stdout) is pushed onto a stack of streams,
|
||||
and is replaced in the dbg system with the specified stream.
|
||||
When called with a value of None, the previous stream will
|
||||
be restored (if stacked.) If set to None without previously
|
||||
changing it will result in no action being taken.
|
||||
|
||||
You can also call the log function implicitly on the Logger
|
||||
instance, ie. you can type:
|
||||
from wxPython.tools.dbg import Logger
|
||||
dbg = Logger()
|
||||
dbg('something to print')
|
||||
|
||||
Using this fairly simple mechanism, it is possible to get fairly
|
||||
useful debugging output in a program. Consider the following
|
||||
code example:
|
||||
|
||||
>>> d = {1:'a', 2:'dictionary', 3:'of', 4:'words'}
|
||||
>>> dbg = dbg.Logger('module')
|
||||
>>> dbg(enable=1)
|
||||
module: dbg enabled
|
||||
>>> def foo(d):
|
||||
... dbg('foo', indent=1)
|
||||
... bar(d)
|
||||
... dbg('end of foo', indent=0)
|
||||
...
|
||||
>>> def bar(d):
|
||||
... dbg('bar', indent=1)
|
||||
... dbg('contents of d:', indent=1)
|
||||
... l = d.items()
|
||||
... l.sort()
|
||||
... for key, value in l:
|
||||
... dbg('%d =' % key, value)
|
||||
... dbg(indent=0)
|
||||
... dbg('end of bar', indent=0)
|
||||
...
|
||||
>>> foo(d)
|
||||
module: foo
|
||||
module: bar
|
||||
module: contents of d:
|
||||
module: 1 = a
|
||||
module: 2 = dictionary
|
||||
module: 3 = of
|
||||
module: 4 = words
|
||||
module: end of bar
|
||||
module: end of foo
|
||||
>>>
|
||||
|
||||
"""
|
||||
|
||||
|
||||
class Logger:
|
||||
def __init__(self, name=None):
|
||||
import sys
|
||||
self.name = name
|
||||
self._indent = 0 # current number of indentations
|
||||
self._dbg = 0 # enable/disable flag
|
||||
self._suspend = 0 # allows code to "suspend/resume" potential dbg output
|
||||
self._wxLog = 0 # use wxLogMessage for debug output
|
||||
self._outstream = sys.stdout # default output stream
|
||||
self._outstream_stack = [] # for restoration of streams as necessary
|
||||
|
||||
|
||||
def IsEnabled():
|
||||
return self._dbg
|
||||
|
||||
def IsSuspended():
|
||||
return _suspend
|
||||
|
||||
|
||||
def log(self, *args, **kwargs):
|
||||
"""
|
||||
This function provides a useful framework for generating
|
||||
optional debugging output that can be displayed at an
|
||||
arbitrary level of indentation.
|
||||
"""
|
||||
if not self._dbg and not 'enable' in kwargs.keys():
|
||||
return
|
||||
|
||||
if self._dbg and len(args) and not self._suspend:
|
||||
# (emulate print functionality)
|
||||
strs = [str(arg) for arg in args]
|
||||
output = ' '.join(strs)
|
||||
if self.name: output = self.name+': ' + output
|
||||
output = ' ' * 3 * self._indent + output
|
||||
|
||||
if self._wxLog:
|
||||
from wxPython.wx import wxLogMessage # (if not already imported)
|
||||
wxLogMessage(output)
|
||||
else:
|
||||
self._outstream.write(output + '\n')
|
||||
self._outstream.flush()
|
||||
# else do nothing
|
||||
|
||||
# post process args:
|
||||
for kwarg, value in kwargs.items():
|
||||
if kwarg == 'indent':
|
||||
self.SetIndent(value)
|
||||
elif kwarg == 'enable':
|
||||
self.SetEnabled(value)
|
||||
elif kwarg == 'suspend':
|
||||
self.SetSuspend(value)
|
||||
elif kwarg == 'wxlog':
|
||||
self.SetWxLog(value)
|
||||
elif kwarg == 'stream':
|
||||
self.SetStream(value)
|
||||
|
||||
# aliases for the log function
|
||||
dbg = log # backwards compatible
|
||||
msg = log #
|
||||
__call__ = log # this one lets you 'call' the instance directly
|
||||
|
||||
|
||||
def SetEnabled(self, value):
|
||||
if value:
|
||||
old_dbg = self._dbg
|
||||
self._dbg = 1
|
||||
if not old_dbg:
|
||||
self.dbg('dbg enabled')
|
||||
else:
|
||||
if self._dbg:
|
||||
self.dbg('dbg disabled')
|
||||
self._dbg = 0
|
||||
|
||||
|
||||
def SetSuspend(self, value):
|
||||
if value:
|
||||
self._suspend += 1
|
||||
elif self._suspend > 0:
|
||||
self._suspend -= 1
|
||||
|
||||
|
||||
def SetIndent(self, value):
|
||||
if value:
|
||||
self._indent += 1
|
||||
elif self._indent > 0:
|
||||
self._indent -= 1
|
||||
|
||||
|
||||
def SetWxLog(self, value):
|
||||
self._wxLog = value
|
||||
|
||||
|
||||
def SetStream(self, value):
|
||||
if value:
|
||||
self._outstream_stack.append( self._outstream )
|
||||
self._outstream = value
|
||||
elif value is None and len(self._outstream_stack) > 0:
|
||||
self._outstream = self._outstream_stack.pop(-1)
|
||||
|
||||
|
||||
#------------------------------------------------------------
|
||||
|
||||
if __name__ == "__main__":
|
||||
from wxPython.wx import *
|
||||
wxLog_SetActiveTarget( wxLogStderr() )
|
||||
logger = Logger('module')
|
||||
dbg = logger.dbg
|
||||
dbg(enable=1)
|
||||
logger('test __call__ interface')
|
||||
dbg('testing wxLog output to stderr:', wxlog=1, indent=1)
|
||||
dbg('1,2,3...')
|
||||
dbg('testing wxLogNull:')
|
||||
devnull = wxLogNull()
|
||||
dbg('4,5,6...') # shouldn't print, according to doc...
|
||||
del devnull
|
||||
dbg('(resuming to wxLogStdErr)', '7,8,9...', indent=0)
|
||||
dbg('disabling wxLog output, switching to stderr:')
|
||||
dbg(wxlog=0, stream=sys.stderr)
|
||||
dbg(logger._outstream, 'switching back to stdout:')
|
||||
dbg(stream=None)
|
||||
dbg(logger._outstream )
|
||||
def foo(str):
|
||||
dbg('foo:', indent=1)
|
||||
dbg(str, indent=0)
|
||||
foo('testing dbg inside function')
|
||||
class bar(Logger):
|
||||
def __init__(self, name):
|
||||
Logger.__init__(self, name)
|
||||
def enable(self, value):
|
||||
self.dbg(enable=value)
|
||||
def foo(self, str):
|
||||
self.dbg('foo:', indent=1)
|
||||
self.dbg(str, indent=0)
|
||||
f = bar('class mixin')
|
||||
f.foo("shouldn't print")
|
||||
f.enable(1)
|
||||
f.foo("should print")
|
||||
dbg('test completed.', enable=0)
|
||||
dbg('(double-checking ;-)')
|
||||
|
80
wxPython/wxPython/tools/helpviewer.py
Normal file
@@ -0,0 +1,80 @@
|
||||
#----------------------------------------------------------------------
|
||||
# Name: wxPython.tools.helpviewer
|
||||
# Purpose: HTML Help viewer
|
||||
#
|
||||
# Author: Robin Dunn
|
||||
#
|
||||
# Created: 11-Dec-2002
|
||||
# RCS-ID: $Id$
|
||||
# Copyright: (c) 2002 by Total Control Software
|
||||
# Licence: wxWindows license
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
"""
|
||||
helpviewer.py -- Displays HTML Help in a wxHtmlHelpController window.
|
||||
|
||||
Usage:
|
||||
helpviewer [--cache=path] helpfile [helpfile(s)...]
|
||||
|
||||
Where helpfile is the path to either a .hhp file or a .zip file
|
||||
which contians a .hhp file. The .hhp files are the same as those
|
||||
used by Microsoft's HTML Help Workshop for creating CHM files.
|
||||
"""
|
||||
|
||||
|
||||
import sys, os
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
def main(args=sys.argv):
|
||||
if len(args) < 2:
|
||||
print __doc__
|
||||
return
|
||||
|
||||
args = args[1:]
|
||||
cachedir = None
|
||||
if args[0][:7] == '--cache':
|
||||
cachedir = os.path.expanduser(args[0].split('=')[1])
|
||||
args = args[1:]
|
||||
|
||||
if len(args) == 0:
|
||||
print __doc__
|
||||
return
|
||||
|
||||
from wxPython.wx import wxPySimpleApp, wxConfigBase_Get, \
|
||||
wxLog_SetActiveTarget, wxLogStderr, \
|
||||
wxLog_SetLogLevel, wxLOG_Error, \
|
||||
wxFileSystem_AddHandler, wxZipFSHandler
|
||||
import wxPython.html
|
||||
from wxPython.htmlhelp import wxHtmlHelpController
|
||||
|
||||
|
||||
app = wxPySimpleApp()
|
||||
#wxLog_SetActiveTarget(wxLogStderr())
|
||||
wxLog_SetLogLevel(wxLOG_Error)
|
||||
|
||||
# Set up the default config so the htmlhelp frame can save its preferences
|
||||
app.SetVendorName('wxWindows')
|
||||
app.SetAppName('helpviewer')
|
||||
cfg = wxConfigBase_Get()
|
||||
|
||||
# Add the Zip filesystem
|
||||
wxFileSystem_AddHandler(wxZipFSHandler())
|
||||
|
||||
# Create the viewer
|
||||
helpctrl = wxHtmlHelpController()
|
||||
if cachedir:
|
||||
helpctrl.SetTempDir(cachedir)
|
||||
|
||||
# and add the books
|
||||
for helpfile in args:
|
||||
print "Adding %s..." % helpfile
|
||||
helpctrl.AddBook(helpfile, 1)
|
||||
|
||||
# start it up!
|
||||
helpctrl.DisplayContents()
|
||||
app.MainLoop()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
@@ -1,7 +1,16 @@
|
||||
"""
|
||||
Common routines for the image converter utilities.
|
||||
"""
|
||||
import sys, os, glob, getopt, string
|
||||
#----------------------------------------------------------------------
|
||||
# Name: wxPython.tools.img2img
|
||||
# Purpose: Common routines for the image converter utilities.
|
||||
#
|
||||
# Author: Robin Dunn
|
||||
#
|
||||
# RCS-ID: $Id$
|
||||
# Copyright: (c) 2002 by Total Control Software
|
||||
# Licence: wxWindows license
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
|
||||
import sys, os, glob, getopt
|
||||
from wxPython.wx import *
|
||||
|
||||
if wxPlatform == "__WXGTK__":
|
||||
@@ -11,7 +20,7 @@ if wxPlatform == "__WXGTK__":
|
||||
wxInitAllImageHandlers()
|
||||
|
||||
def convert(file, maskClr, outputDir, outputName, outType, outExt):
|
||||
if string.lower(os.path.splitext(file)[1]) == ".ico":
|
||||
if os.path.splitext(file)[1].lower() == ".ico":
|
||||
icon = wxIcon(file, wxBITMAP_TYPE_ICO)
|
||||
img = wxBitmapFromIcon(icon)
|
||||
else:
|
||||
|
@@ -1,4 +1,14 @@
|
||||
#!/usr/bin/env python
|
||||
#----------------------------------------------------------------------
|
||||
# Name: wxPython.tools.img2png
|
||||
# Purpose: Convert an image to PNG format
|
||||
#
|
||||
# Author: Robin Dunn
|
||||
#
|
||||
# RCS-ID: $Id$
|
||||
# Copyright: (c) 2002 by Total Control Software
|
||||
# Licence: wxWindows license
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
"""
|
||||
img2png.py -- convert several image formats to PNG format
|
||||
|
||||
|
@@ -1,4 +1,15 @@
|
||||
#!/usr/bin/env python
|
||||
#----------------------------------------------------------------------
|
||||
# Name: wxPython.tools.img2py
|
||||
# Purpose: Convert an image to Python code.
|
||||
#
|
||||
# Author: Robin Dunn
|
||||
#
|
||||
# RCS-ID: $Id$
|
||||
# Copyright: (c) 2002 by Total Control Software
|
||||
# Licence: wxWindows license
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
|
||||
"""
|
||||
img2py.py -- Convert an image to PNG format and embed it in a Python
|
||||
module with appropriate code so it can be loaded into
|
||||
@@ -22,6 +33,12 @@ Options:
|
||||
specify a name that should be used to customize the access
|
||||
fucntions, (getNameBitmap, etc.)
|
||||
|
||||
-c Maintain a catalog of names that can be used to reference
|
||||
images. Catalog can be accessed via catalog and index attributes
|
||||
of the module. If the -n <name> option is specified then <name>
|
||||
is used for the catalog key and index value, otherwise
|
||||
the filename without any path or extension is used as the key.
|
||||
|
||||
-a This flag specifies that the python_file should be appended
|
||||
to instead of overwritten. This in combination with -n will
|
||||
allow you to put multiple images in one Python source file.
|
||||
@@ -32,9 +49,14 @@ Options:
|
||||
|
||||
"""
|
||||
|
||||
#
|
||||
# Changes:
|
||||
# - Cliff Wells <LogiplexSoftware@earthlink.net>
|
||||
# 20021206: Added catalog (-c) option.
|
||||
#
|
||||
|
||||
|
||||
import sys, os, glob, getopt, tempfile, string
|
||||
import sys, os, glob, getopt, tempfile
|
||||
import cPickle, cStringIO, zlib
|
||||
import img2img
|
||||
from wxPython import wx
|
||||
@@ -98,9 +120,10 @@ def main(args):
|
||||
maskClr = None
|
||||
imgName = ""
|
||||
icon = 0
|
||||
catalog = 0
|
||||
|
||||
try:
|
||||
opts, fileArgs = getopt.getopt(args, "auin:m:")
|
||||
opts, fileArgs = getopt.getopt(args, "auicn:m:")
|
||||
except getopt.GetoptError:
|
||||
print __doc__
|
||||
return
|
||||
@@ -116,6 +139,8 @@ def main(args):
|
||||
maskClr = val
|
||||
elif opt == "-i":
|
||||
icon = 1
|
||||
elif opt == "-c":
|
||||
catalog = 1
|
||||
|
||||
if len(fileArgs) != 2:
|
||||
print __doc__
|
||||
@@ -139,6 +164,33 @@ def main(args):
|
||||
else:
|
||||
out = open(python_file, "w")
|
||||
|
||||
if catalog:
|
||||
pyPath, pyFile = os.path.split(python_file)
|
||||
imgPath, imgFile = os.path.split(image_file)
|
||||
|
||||
if not imgName:
|
||||
imgName = os.path.splitext(imgFile)[0]
|
||||
print "\nWarning: -n not specified. Using filename (%s) for catalog entry." % imgName
|
||||
|
||||
old_index = []
|
||||
if append:
|
||||
# check to see if catalog exists already (file may have been created
|
||||
# with an earlier version of img2py or without -c option)
|
||||
oldSysPath = sys.path[:]
|
||||
sys.path = [pyPath] # make sure we don't import something else by accident
|
||||
mod = __import__(os.path.splitext(pyFile)[0])
|
||||
if 'index' not in dir(mod):
|
||||
print "\nWarning: %s was originally created without catalog." % python_file
|
||||
print " Any images already in file will not be cataloged.\n"
|
||||
out.write("\n# ***************** Catalog starts here *******************")
|
||||
out.write("\n\ncatalog = {}\n")
|
||||
out.write("index = []\n\n")
|
||||
out.write("class ImageClass: pass\n\n")
|
||||
else: # save a copy of the old index so we can warn about duplicate names
|
||||
old_index[:] = mod.index[:]
|
||||
del mod
|
||||
sys.path = oldSysPath[:]
|
||||
|
||||
out.write("#" + "-" * 70 + "\n")
|
||||
if not append:
|
||||
out.write("# This file was generated by %s\n#\n" % sys.argv[0])
|
||||
@@ -150,6 +202,11 @@ def main(args):
|
||||
else:
|
||||
out.write("import cStringIO\n\n\n")
|
||||
|
||||
if catalog:
|
||||
out.write("catalog = {}\n")
|
||||
out.write("index = []\n\n")
|
||||
out.write("class ImageClass: pass\n\n")
|
||||
|
||||
if compressed:
|
||||
out.write("def get%sData():\n"
|
||||
" return zlib.decompress(\n%s)\n\n"
|
||||
@@ -173,6 +230,19 @@ def main(args):
|
||||
" return icon\n\n"
|
||||
% tuple([imgName] * 2))
|
||||
|
||||
if catalog:
|
||||
if imgName in old_index:
|
||||
print "Warning: %s already in catalog." % imgName
|
||||
print " Only the last entry will be accessible.\n"
|
||||
old_index.append(imgName)
|
||||
out.write("index.append('%s')\n" % imgName)
|
||||
out.write("catalog['%s'] = ImageClass()\n" % imgName)
|
||||
out.write("catalog['%s'].getData = get%sData\n" % tuple([imgName] * 2))
|
||||
out.write("catalog['%s'].getImage = get%sImage\n" % tuple([imgName] * 2))
|
||||
out.write("catalog['%s'].getBitmap = get%sBitmap\n" % tuple([imgName] * 2))
|
||||
if icon:
|
||||
out.write("catalog['%s'].getIcon = get%sIcon\n" % tuple([imgName] * 2))
|
||||
out.write("\n\n")
|
||||
|
||||
if imgName:
|
||||
n_msg = ' using "%s"' % imgName
|
||||
|
@@ -1,4 +1,14 @@
|
||||
#!/usr/bin/env python
|
||||
#----------------------------------------------------------------------
|
||||
# Name: wxPython.tools.img2xpm
|
||||
# Purpose: Convert an image to XPM format
|
||||
#
|
||||
# Author: Robin Dunn
|
||||
#
|
||||
# RCS-ID: $Id$
|
||||
# Copyright: (c) 2002 by Total Control Software
|
||||
# Licence: wxWindows license
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
"""
|
||||
img2xpm.py -- convert several image formats to XPM
|
||||
|
||||
|