Preferences for default "sizeritem" parameters for new panels and

controls can be configured ("File">"Preferences...").

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

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

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

Some undo/redo and other fixes.

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

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

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


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/branches/WX_2_8_BRANCH@44949 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Robin Dunn
2007-03-19 17:55:26 +00:00
parent 459fbbc100
commit 30d91f9ebc
11 changed files with 989 additions and 376 deletions

View File

@@ -1,3 +1,47 @@
0.1.8-5 (under construction)
-------
Preferences for default "sizeritem" parameters for new panels and
controls can be configured ("File">"Preferences...").
Implemented comment object for including simple one-line comments and
comment directives as tree nodes. No validation is performed for a
valid XML string so comments must not contain "-->". Comment directive
is a special comment starting with '%' character, followed by a line
of python code. It is executed using 'exec' when the resource file is
opened. This is useful to import plugin modules containing custom
handlers which are specific to the resource file, hovewer this is of
course a security hole if you use foreign XRC files. A warning is
displayed if the preference option 'ask' is selected (by default).
Added support for custom controls and plugin modules. Refer to this
wxPythonWiki for the details:
http://wiki.wxpython.org/index.cgi/XRCed#custom
Tool panel sections can be collapsed/expanded by clicking on the
label of a tool group.
Some undo/redo and other fixes.
0.1.8-4
-------
Fixes for wxMSW (notebook highlighting, control sizes, tree Unselect).
0.1.8-3
-------
Notebook page highlighting fix. Highlight resizes when the window
is resized. ParamUnit spin button detects event handler re-entry
(wxGTK probably has a bug in wxSpinButton with repeated events).
0.1.8-2
-------
Fix for dealing with empty 'growable' property, using MiniFrame
for properties panel, the panel is restored together with the
main window.
0.1.8-1 0.1.8-1
------- -------

View File

@@ -15,7 +15,7 @@ import sys
# Global constants # Global constants
progname = 'XRCed' progname = 'XRCed'
version = '0.1.8-1' version = '0.1.8-5'
# Minimal wxWidgets version # Minimal wxWidgets version
MinWxVersion = (2,6,0) MinWxVersion = (2,6,0)
if wx.VERSION[:3] < MinWxVersion: if wx.VERSION[:3] < MinWxVersion:
@@ -48,6 +48,7 @@ class Globals:
testWinPos = wx.DefaultPosition testWinPos = wx.DefaultPosition
currentXXX = None currentXXX = None
currentEncoding = defaultEncoding currentEncoding = defaultEncoding
conf = None
def _makeFonts(self): def _makeFonts(self):
self._sysFont = wx.SystemSettings.GetFont(wx.SYS_SYSTEM_FONT) self._sysFont = wx.SystemSettings.GetFont(wx.SYS_SYSTEM_FONT)

View File

@@ -470,11 +470,10 @@ def getToolGaugeData():
return \ return \
'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x18\x00\x00\x00\x0e\x08\x02\ '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x18\x00\x00\x00\x0e\x08\x02\
\x00\x00\x00\xba\x9aK)\x00\x00\x00\x03sBIT\x08\x08\x08\xdb\xe1O\xe0\x00\x00\ \x00\x00\x00\xba\x9aK)\x00\x00\x00\x03sBIT\x08\x08\x08\xdb\xe1O\xe0\x00\x00\
\x00XIDAT(\x91c\x9c2u\n\x03U\x00U\x0c\xfa\xff\xff?\x0b\x9c\x85)\xcd\xc8\xc8x\ \x00TIDAT(\x91c\x9c2u\n\x03U\x00U\x0c\xfa\xff\xff?\x0b\x9c\x85)\xcd\xc8\xc8x\
\xf5\xdaU"\xcdb\x81\xb3\xde\xbf~O\x89\xa3\x98pIl\xdb\xbd\x8d:\x06\x91\nF\r"\ \xf5\xdaU"\xcdb\x81\xb3\xde\xbf~O\x89\xa3\x98pIl\xdb\xbd\x8d:\x06\x91\nF\r"\
\x0cX\x909\xa4\xc6\x14\x16\x83\x18\x19\x19)r\x0f\xdc \xe2S0>\x83\xfe\xff\xff\ \x0cX\x909\xa4\xc6\x14\x16\x83\x18\x19\x19)r\x0f\xdc \xe2S0>\x83\xb0\xe6\x0f\
O\xa1)\x0c\x0c\x0c\x00U\xa6\x18\xb48\xff\xd0\x00\x00\x00\x00\x00IEND\xaeB`\ R\x01\x00U\xa6\x18\xb4\x82\x95pI\x00\x00\x00\x00IEND\xaeB`\x82'
\x82'
def getToolGaugeBitmap(): def getToolGaugeBitmap():
return BitmapFromImage(getToolGaugeImage()) return BitmapFromImage(getToolGaugeImage())
@@ -842,13 +841,13 @@ def getToolRadioButtonData():
return \ return \
'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x0b\x00\x00\x00\x0b\x08\x06\ '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x0b\x00\x00\x00\x0b\x08\x06\
\x00\x00\x00\xa9\xacw&\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\x00\ \x00\x00\x00\xa9\xacw&\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\x00\
\x00\x98IDAT\x18\x95m\x8f\xc1\r\xc20\x0cE\x9f\x1d\x06\xe8\x81)\xe8\x06\x91:V\ \x00\x96IDAT\x18\x95m\x90\xc1\r\xc20\x10\x04\xc7g\n\xc8\x83*H\x07\x96RVD\t`\
\xc5\x08P\xb2\x15\xa8\xdd\xa0L\xd1C\x06\x00\xc2\xa1\xa4J\x83\xbfd\xc5N\xde\ \xdc\x15(\xe9 T\x91\x87\x0b\x00\xcc#1\xb2\xcd\xadd\xf9t\x9a=\xad\x16#\x96\
\xb7~\x10u\xd4\x15\x86\x90\xac{\xa5\xd2\xedrM\xe5YJ-\xb0?\xf7X\x06\xb5\xc0\ \xf6\x05\x1f\x92\xb6\x17\x1a\xdd.\xd7T\xfe\xa5D\x03\xc7\xf3\x88f\x10\r\\\x9e\
\xf99\x9b\x06\xb5@\xc04H\x18\xc2\x1fX\xaa=\xb5\x84!\x00 \xa2\x8e\xcf\xfb\x95\ \x8bj\x10\r\x04T\x83\t>\xfc\x81\xa5\xfaSO\xf0\x01\x00c\xc4\xf2y\xbf\x12\xc0\
\x00\xa6\xc7Dsl60.\x11\xdf\xf95\x82;\x88\xe6\x06\xc0w\x9e\xb8D\x13\\W\xab\ \xfc\x98\xe9\x8e\xdd\x0f\x8ck\xc4\rn\x8b`\x0fF\xf2\x00\xe0\x06G\\\xa3\nn\xa7\
\xdb*\xfd4\xde\xc7\xdc\xa6\xf2]D\xdd.c\x8e\xb4\xdb\x98\xe7\xfaC\x19\xa8A\x80\ \x8b\x1e\xd3\xae\xe9>\xe5\xb1\xee\xdb\x88\xad2\xe6H\xd5E\xad\xe7\x12hA\x80/\
/\x17\xa5W:\x12\xac\xa3\xbe\x00\x00\x00\x00IEND\xaeB`\x82' \x17\xa5W:+\xbbb\xd2\x00\x00\x00\x00IEND\xaeB`\x82'
def getToolRadioButtonBitmap(): def getToolRadioButtonBitmap():
return BitmapFromImage(getToolRadioButtonImage()) return BitmapFromImage(getToolRadioButtonImage())
@@ -865,13 +864,13 @@ def getToolRadioButtonIcon():
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def getToolRootData(): def getToolRootData():
return \ return \
"\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x0e\x08\x06\ '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x0e\x08\x06\
\x00\x00\x00&/\x9c\x8a\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\x00\ \x00\x00\x00&/\x9c\x8a\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\x00\
\x00cIDAT(\x91\xed\x90\xc1\x0e\x800\x08C[\xf0\x97T\xfe\xff\xa6~\x93n\xb7e.`\ \x00aIDAT(\x91\xed\x93\xc1\n\x80@\x08Dg\xb4_\xaa\xfc\xff[\xf5M\xb5\xdd\x96m\
\xa6\xbb\xda\x84\x03\xa4m\xf2 E1\xa2\xc9;\xa6\xebL\xf5NQ\x86\x05\xeb2\xdf\ \xd1\xa8\xbc6\xe0A\x19\x07\x9e )\x8a\x8c\x06oX\x8e\xbd\xb4=E\x19\x06\xcc\xd3\
\xcc\xdb~\x84fW\x14\x85\x99%\x8a\xe2\xcb\xb8\x08\x1eF\x84T\nj\x947\x18\xa5\ x1/\xeb\x16\x9a]Q\x14fV(\x8a/\xe5"x\x18\x11R\rhQ\xde`\xd4\x80~\xe9\xeepn@\
\xa0\r==\xce-h\xf5#\xf4#\x90\xa2\xbd^W2\x94\x06\x90\x01\x0f\xb3'\x06\xe8\x11\ \xaf\x1f\xe19\x02\xb3\xbf \xa9m\x00\'\x0f\xb3\'\x06(\x95\x90F\x00\x00\x00\
R\xf1\x00\x00\x00\x00IEND\xaeB`\x82" \x00IEND\xaeB`\x82'
def getToolRootBitmap(): def getToolRootBitmap():
return BitmapFromImage(getToolRootImage()) return BitmapFromImage(getToolRootImage())
@@ -917,8 +916,8 @@ def getToolSeparatorData():
return \ return \
'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x0e\x00\x00\x00\x02\x08\x02\ '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x0e\x00\x00\x00\x02\x08\x02\
\x00\x00\x00\xe7\xe8z\xfd\x00\x00\x00\x03sBIT\x08\x08\x08\xdb\xe1O\xe0\x00\ \x00\x00\x00\xe7\xe8z\xfd\x00\x00\x00\x03sBIT\x08\x08\x08\xdb\xe1O\xe0\x00\
\x00\x00\x17IDAT\x18\x95c\x9c2u\n\x03\x11 ;+\x9b\x05B\x11\xa3\x1a\x00\xfb\ \x00\x00\x17IDAT\x08\x99c\x9c2u\n\x03\x11 ;+\x9b\x05B\x11\xa3\x1a\x00\xfb\
\x1c\x04C\xb1\x8cE\xa0\x00\x00\x00\x00IEND\xaeB`\x82' \x1c\x04CU\x1cv\xec\x00\x00\x00\x00IEND\xaeB`\x82'
def getToolSeparatorBitmap(): def getToolSeparatorBitmap():
return BitmapFromImage(getToolSeparatorImage()) return BitmapFromImage(getToolSeparatorImage())
@@ -1052,28 +1051,28 @@ def getToolSplitterWindowIcon():
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def getToolStaticBitmapData(): def getToolStaticBitmapData():
return \ return \
'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x0e\x00\x00\x00\x11\x08\x06\ "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x0e\x00\x00\x00\x11\x08\x06\
\x00\x00\x00\xed\xc8\x9d\x9f\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\ \x00\x00\x00\xed\xc8\x9d\x9f\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\
\x00\x00\x01\xf7IDAT(\x91\x85\x921h\x13Q\x18\xc7\x7fw\xf7\x86\x17p\xb8\x83\ \x00\x00\x01\xf9IDAT(\x91\x85\x931h\x13Q\x18\xc7\x7fw\xf7\x86\x17p\xb8\x83\
\x0c\x97-\x05\x1dts\xb3N\x9et\x90\xe0`[\\\\\x9c:X\xe9PN\xa7\xea\x16\x10\x95\ \x0c\x97-\x05\x1dts\xb3N\x9et\x90\xe0\xa0-..N\x1d\xact(\xd1\xa9\xba\x05D\xa5\
\x0ejq\x10\xb2\x08\xe9Rt\xd0:\xf6:\x14\x13P\x92.\xd6\x82C\xb3\x14\x92A\x92S\ \x83Z\x1c\x84,B\xba\x14\x1d\xb4\x8e\xbd\x0e\xc5\x04\x94\xa4\x8b\xb5\xe0\xd0,\
\x03\xf7\xc0k?\x87pgC\xab\xfdO\xef}\xef\xfd\xbe\xef}\xff\xefY\x96\xedpT\x87\ \x85d\x90\xe4\xd4\xc0=\xf0\xda\xcf!\xdc\xd9\xa3Q\xbf\xe9\xbd\xef}\xbf\xef{\
\x07\xa9p\x82lGYc\xfb\xa3@\x06%\xbf\x12\xda\x9f\xdb\x0c\x06\x83\x7f&\xb4,\ \xdf\xff{\xcf\xb2l\x87\xe3vt\x98\x08\x13\xccv\x94\x95\xdb\x1f\x07R(\xfe\x19\
\xdb\xc9\x83\x8d\xad\x06o\xd7j,-\x9eG\xab\x02f\x98\xd0\xf8\x12\xb3\xfa~\x9b\ \xd3\xf9\xd4a8\x1c\xfe5\xa1e\xd9N\xe6ln7y\xb3^gy\xe9,Z\x150\xa3\x98\xe6\xe7\
\xfa\xeb\x0fc\x95s\xb0\xb1\xd5\xa0\xe4k\\"<\xff2\xe0\x82i\x92\xa4\x86\xf8\ \x88\xb5w;4^\xbd\xcfU\xce\xc0\xe6v\x93\x92\xafq\t\xf1\xfc\x8b\x80\x0b\xa6E\
\xfb\x80{\x8fv\xa9\xaf\xd6s\xd8\xce\xaa-\xbfX\xc6W\x11^\xf1*\xa8\tP\x1e\x9c\ \x9c\x18\xa2oC\xee>\xdc\xa3\xb1\xd6\xc8`;\xad\xb6\xf2|\x05_\x85x\xc5\xcb\xa0\
\xa9PP\x1a\xd7\xf5X\x9a+1;=\x9b?Ue\x8bp\xae\x02\x1a\xd0\xa5Q 5\x00$\xa9\xa6\ \xa6@yp\xaaBAi\\\xd7cy\xbe\xc4\xdc\xf5\xb9\xec\xaa*]T\xe7+\xa0\x01]\x1a;\x12\
\xa0\x0c^Q\xe3z:\xef77\xc7\x18\x93_\x06\r\xca%1#s\x124(M\xc9\xcd\xce\xc1\xce\ \x03@\x9ch\n\xca\xe0\x155\xae\xa7\xb3~3q\x8c1Y0hP.\xb1\x19\x8b\x13\xa3AiJnz\
\x9a\xad>\x7f\x03i\x02\x18Hc0\x1dH\xbb\xa3d\xa9\xc1\xc41\xf5\xb5\xe8\xf88j\ \x0ev\xdal\xed\xd9kHb\xc0@\x12\x81\xe9B\xd2\x1b'K\x0c&\x8ah\xac\x87'\xc7Q\
\xafj\x98\x94\x11\xac4\x89\xe9\x001\xa4\x86^\xafKg\x7f@\xf5\xf1JnN\xde\xa3\ \x7fY\xc7$\x8ca\xa5\x89M\x17\x88 1\xf4\xfb=\xba\x07Cj\x8fV3q\xb2\x1e\xb5\xd6\
\xd6\x1am\x0cP \x19v \x8d1f@\xb7\xd7\xc3\x0c\x13\xaa/w\x896k\xe3\xe6\xd8\x8e\ hc\x80\x02\xf1\xa8\x0bI\x841Cz\xfd>f\x14S{\xb1G\xb8U\xcf\x8bc;\xca\xba}\xe7\
\xb2\xee\xdc\xbd-\xdb\xcd\x88\x89sMV\x1e\x06\xc4qLg\xbf\xcb\x83\'\x11^\xf1\ \x96\xec\xb4B\xa6\xce\xb4X}\x10\x10E\x11\xdd\x83\x1e\xf7\x1f\x87x\xc5s\x84[\
\x02\xd1fcl\x8eX\xb6\x83e;\xa0\x90\x99\x9b\x15\xd9\xf9\xba#\xadO\x1f\xa5r=\ \xcd\xdc\x1c\xb1l\x07\xcbv@!\xb37*\xb2\xfbeW\xda\x1f?H\xe5j \xd5\xc5\x9b\xb2\
\x90p\xe1\x96\xec}\xdb\x93L\xd9]\xcbv\xfe\x8237*""\xd2j\xb7$\x98\n$\xbc\x1fJ\ \xffu_RKc-\xdb\xf9\x03\xce^\xab\x88\x88H\xbb\xd3\x96`&\x90\xea\xbd\xaa\x0c\
\xbf\xdf?\x06\x8c\x81\xbe\xef\xcbF\xb4!\x95k\x81\xac<{*\xf3\x0b\xf3\xe2\x16\ \x06\x83\x13@\x0e\xf4}_6\xc3M\xa9\\\td\xf5\xe9\x13YX\\\x10\xb7\xe8N\x04r \
\xdd\x13\x811\x10\x90`jR\xd6\xdf\xad\x8f*^\t\xa4|\xb6|:\x98\xc1\xe5\xb2/\x93\ \xc1\xcc\xb4l\xbc\xdd\x18W\xbc\x14H\xf9t\xf9\xff`\n\x97\xcb\xbeL_8/\xd5\xa5\
\x97.J\xb8\x18\xfe\x17\xb2lg\xf4\xc9\x01\xe4\xf0@|\xdf\xc5\x18\xc3\x8f\x9f\ \xea?!\xcbv\xc6\x8f\x1c@\x8e\x0e\xc5\xf7]\x8c1|\xff\xf1+\xf7\xf7&\xd9o(\xba\
\xbf-N\xd1\x1f(\xba\xfe\xd4\xf5\xbb\xa30\x00\x00\x00\x00IEND\xaeB`\x82' \xfe\xd4S\x004\x8f\x00\x00\x00\x00IEND\xaeB`\x82"
def getToolStaticBitmapBitmap(): def getToolStaticBitmapBitmap():
return BitmapFromImage(getToolStaticBitmapImage()) return BitmapFromImage(getToolStaticBitmapImage())
@@ -1140,8 +1139,8 @@ def getToolStaticLineData():
return \ return \
'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x14\x00\x00\x00\x02\x08\x02\ '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x14\x00\x00\x00\x02\x08\x02\
\x00\x00\x00\xd7dk\xdc\x00\x00\x00\x03sBIT\x08\x08\x08\xdb\xe1O\xe0\x00\x00\ \x00\x00\x00\xd7dk\xdc\x00\x00\x00\x03sBIT\x08\x08\x08\xdb\xe1O\xe0\x00\x00\
\x00\x17IDAT\x18\x95c\x9c2u\n\x03Y ;+\x9b\x05B\x91\xa7\x1f\x00gO\x04C\xda+\ \x00\x17IDAT\x08\x99c\x9c2u\n\x03Y ;+\x9b\x05B\x91\xa7\x1f\x00gO\x04C>\xbb?\
\x0c\xd5\x00\x00\x00\x00IEND\xaeB`\x82' \x99\x00\x00\x00\x00IEND\xaeB`\x82'
def getToolStaticLineBitmap(): def getToolStaticLineBitmap():
return BitmapFromImage(getToolStaticLineImage()) return BitmapFromImage(getToolStaticLineImage())
@@ -1204,9 +1203,9 @@ def getToolToolData():
return \ return \
'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\t\x00\x00\x00\t\x08\x02\x00\ '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\t\x00\x00\x00\t\x08\x02\x00\
\x00\x00o\xf3\x91G\x00\x00\x00\x03sBIT\x08\x08\x08\xdb\xe1O\xe0\x00\x00\x00>\ \x00\x00o\xf3\x91G\x00\x00\x00\x03sBIT\x08\x08\x08\xdb\xe1O\xe0\x00\x00\x00>\
IDAT\x18\x95c\xfc\xf1\xe7\x07\x036\xc0\xc1\xc2\xc1\xc2\xc0\xc0p\xe3\xc6\r4\ IDAT\x08\x99c\xfc\xf1\xe7\x07\x036\xc0\xc1\xc2\xc1\xc2\xc0\xc0p\xe3\xc6\r4\
\x89\x03\x07\x0e0000a\xd5\x04\x01,hj\x19\x18\x18\x1c\x1c\x1c \x0c|\xfa\x883\ \x89\x03\x07\x0e0000a\xd5\x04\x01,hj\x19\x18\x18\x1c\x1c\x1c \x0c|\xfa\x883\
\x13n\x14\x8a\x1c\xdc&\x12\x00\x00b\xc7\r\xe0\xb7\\uG\x00\x00\x00\x00IEND\ \x13n\x14\x8a\x1c\xdc&\x12\x00\x00b\xc7\r\xe0y\xf1\x04O\x00\x00\x00\x00IEND\
\xaeB`\x82' \xaeB`\x82'
def getToolToolBitmap(): def getToolToolBitmap():
@@ -1248,13 +1247,13 @@ def getToolToolBarIcon():
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def getToolTreeCtrlData(): def getToolTreeCtrlData():
return \ return \
"\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x0e\x08\x06\ '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x0e\x08\x06\
\x00\x00\x00&/\x9c\x8a\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\x00\ \x00\x00\x00&/\x9c\x8a\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\x00\
\x00cIDAT(\x91\xed\x90\xc1\x0e\x800\x08C[\xf0\x97T\xfe\xff\xa6~\x93n\xb7e.`\ \x00aIDAT(\x91\xed\x93\xc1\n\x80@\x08Dg\xb4_\xaa\xfc\xff[\xf5M\xb5\xdd\x96m\
\xa6\xbb\xda\x84\x03\xa4m\xf2 E1\xa2\xc9;\xa6\xebL\xf5NQ\x86\x05\xeb2\xdf\ \xd1\xa8\xbc6\xe0A\x19\x07\x9e )\x8a\x8c\x06oX\x8e\xbd\xb4=E\x19\x06\xcc\xd3\
\xcc\xdb~\x84fW\x14\x85\x99%\x8a\xe2\xcb\xb8\x08\x1eF\x84T\nj\x947\x18\xa5\ x1/\xeb\x16\x9a]Q\x14fV(\x8a/\xe5"x\x18\x11R\rhQ\xde`\xd4\x80~\xe9\xeepn@\
\xa0\r==\xce-h\xf5#\xf4#\x90\xa2\xbd^W2\x94\x06\x90\x01\x0f\xb3'\x06\xe8\x11\ \xaf\x1f\xe19\x02\xb3\xbf \xa9m\x00\'\x0f\xb3\'\x06(\x95\x90F\x00\x00\x00\
R\xf1\x00\x00\x00\x00IEND\xaeB`\x82" \x00IEND\xaeB`\x82'
def getToolTreeCtrlBitmap(): def getToolTreeCtrlBitmap():
return BitmapFromImage(getToolTreeCtrlImage()) return BitmapFromImage(getToolTreeCtrlImage())
@@ -1290,6 +1289,27 @@ def getToolUnknownIcon():
icon.CopyFromBitmap(getToolUnknownBitmap()) icon.CopyFromBitmap(getToolUnknownBitmap())
return icon return icon
#----------------------------------------------------------------------
def getTreeCommentData():
return \
'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x0e\x08\x06\
\x00\x00\x00&/\x9c\x8a\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\x00\
\x00AIDAT(\x91cddbf\xa0\x040Q\xa4\x9bf\x06\xfc\xff\xf7\xf7\xff\xff\x7f\x7f\
\xff\xa3\xb3\xe9\xe7\x02R\x00#z,\xe0s.#\x133#A\x17 +\xc2\xc5\xc6k\x00\xa9`\
\x18x\x81\xfaa@*\x00\x00\xb0\xac\x18?Q\xffAR\x00\x00\x00\x00IEND\xaeB`\x82'
def getTreeCommentBitmap():
return BitmapFromImage(getTreeCommentImage())
def getTreeCommentImage():
stream = cStringIO.StringIO(getTreeCommentData())
return ImageFromStream(stream)
def getTreeCommentIcon():
icon = EmptyIcon()
icon.CopyFromBitmap(getTreeCommentBitmap())
return icon
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def getTreeDefaultData(): def getTreeDefaultData():
return \ return \
@@ -1449,13 +1469,13 @@ def getTreePanelIcon():
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def getTreeRootData(): def getTreeRootData():
return \ return \
"\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x0e\x08\x06\ '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x0e\x08\x06\
\x00\x00\x00&/\x9c\x8a\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\x00\ \x00\x00\x00&/\x9c\x8a\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\x00\
\x00cIDAT(\x91\xed\x90\xc1\x0e\x800\x08C[\xf0\x97T\xfe\xff\xa6~\x93n\xb7e.`\ \x00aIDAT(\x91\xed\x93\xc1\n\x80@\x08Dg\xb4_\xaa\xfc\xff[\xf5M\xb5\xdd\x96m\
\xa6\xbb\xda\x84\x03\xa4m\xf2 E1\xa2\xc9;\xa6\xebL\xf5NQ\x86\x05\xeb2\xdf\ \xd1\xa8\xbc6\xe0A\x19\x07\x9e )\x8a\x8c\x06oX\x8e\xbd\xb4=E\x19\x06\xcc\xd3\
\xcc\xdb~\x84fW\x14\x85\x99%\x8a\xe2\xcb\xb8\x08\x1eF\x84T\nj\x947\x18\xa5\ x1/\xeb\x16\x9a]Q\x14fV(\x8a/\xe5"x\x18\x11R\rhQ\xde`\xd4\x80~\xe9\xeepn@\
\xa0\r==\xce-h\xf5#\xf4#\x90\xa2\xbd^W2\x94\x06\x90\x01\x0f\xb3'\x06\xe8\x11\ \xaf\x1f\xe19\x02\xb3\xbf \xa9m\x00\'\x0f\xb3\'\x06(\x95\x90F\x00\x00\x00\
R\xf1\x00\x00\x00\x00IEND\xaeB`\x82" \x00IEND\xaeB`\x82'
def getTreeRootBitmap(): def getTreeRootBitmap():
return BitmapFromImage(getTreeRootImage()) return BitmapFromImage(getTreeRootImage())

View File

@@ -22,7 +22,7 @@ class Panel(wx.Notebook):
# Set common button size for parameter buttons # Set common button size for parameter buttons
bTmp = wx.Button(self, -1, '') bTmp = wx.Button(self, -1, '')
import params import params
params.buttonSize = (self.DLG_SZE(buttonSize)[0], bTmp.GetSize()[1]) params.buttonSize = (self.DLG_SZE(buttonSizeD)[0], bTmp.GetSize()[1])
bTmp.Destroy() bTmp.Destroy()
del bTmp del bTmp
@@ -160,6 +160,7 @@ class Panel(wx.Notebook):
# Register undo object when modifying first time # Register undo object when modifying first time
if not self.modified and value: if not self.modified and value:
g.undoMan.RegisterUndo(UndoEdit()) g.undoMan.RegisterUndo(UndoEdit())
g.frame.SetModified()
self.modified = value self.modified = value
def Apply(self): def Apply(self):
@@ -184,7 +185,7 @@ class ParamPage(wx.Panel):
param = evt.GetEventObject().GetName() param = evt.GetEventObject().GetName()
w = self.controls[param] w = self.controls[param]
w.Enable(True) w.Enable(True)
objElem = xxx.element objElem = xxx.node
if evt.IsChecked(): if evt.IsChecked():
# Ad new text node in order of allParams # Ad new text node in order of allParams
w.SetValue('') # set empty (default) value w.SetValue('') # set empty (default) value
@@ -192,7 +193,7 @@ class ParamPage(wx.Panel):
elem = g.tree.dom.createElement(param) elem = g.tree.dom.createElement(param)
# Some classes are special # Some classes are special
if param == 'font': if param == 'font':
xxx.params[param] = xxxParamFont(xxx.element, elem) xxx.params[param] = xxxParamFont(xxx.node, elem)
elif param in xxxObject.bitmapTags: elif param in xxxObject.bitmapTags:
xxx.params[param] = xxxParamBitmap(elem) xxx.params[param] = xxxParamBitmap(elem)
else: else:
@@ -218,7 +219,7 @@ class ParamPage(wx.Panel):
xxx.params[param].remove() xxx.params[param].remove()
del xxx.params[param] del xxx.params[param]
w.SetValue('') w.SetValue('')
w.modified = False # mark as not changed w.SetModified(False) # mark as not changed
w.Enable(False) w.Enable(False)
# Set modified flag (provokes undo storing is necessary) # Set modified flag (provokes undo storing is necessary)
panel.SetModified(True) panel.SetModified(True)
@@ -228,7 +229,7 @@ class ParamPage(wx.Panel):
name = self.controlName.GetValue() name = self.controlName.GetValue()
if xxx.name != name: if xxx.name != name:
xxx.name = name xxx.name = name
xxx.element.setAttribute('name', name) xxx.node.setAttribute('name', name)
for param, w in self.controls.items(): for param, w in self.controls.items():
if w.modified: if w.modified:
paramObj = xxx.params[param] paramObj = xxx.params[param]
@@ -237,10 +238,11 @@ class ParamPage(wx.Panel):
xxx.setSpecial(param, value) xxx.setSpecial(param, value)
else: else:
paramObj.update(value) paramObj.update(value)
# Save current state # Save current state
def SaveState(self): def SaveState(self):
self.origChecks = map(lambda i: (i[0], i[1].GetValue()), self.checks.items()) 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.origControls = map(lambda i: (i[0], i[1].GetValue(), i[1].enabled),
self.controls.items()) self.controls.items())
if self.controlName: if self.controlName:
self.origName = self.controlName.GetValue() self.origName = self.controlName.GetValue()
@@ -257,7 +259,8 @@ class ParamPage(wx.Panel):
for k,v,e in state[1]: for k,v,e in state[1]:
self.controls[k].SetValue(v) self.controls[k].SetValue(v)
self.controls[k].Enable(e) self.controls[k].Enable(e)
if e: self.controls[k].modified = True # Set all states to modified
if e and k in self.xxx.params: self.controls[k].modified = True
if self.controlName: if self.controlName:
self.controlName.SetValue(state[2]) self.controlName.SetValue(state[2])
@@ -283,11 +286,15 @@ class PropPage(ParamPage):
for param in xxx.allParams: for param in xxx.allParams:
present = xxx.params.has_key(param) present = xxx.params.has_key(param)
if param in xxx.required: if param in xxx.required:
label = wx.StaticText(self, paramIDs[param], param + ':', if isinstance(xxx, xxxComment):
size = (LABEL_WIDTH,-1), name = param) label = None
else:
label = wx.StaticText(self, paramIDs[param], param + ':',
size = (LABEL_WIDTH,-1), name = param)
else: else:
# Notebook has one very loooooong parameter # Rename some parameters
if param == 'usenotebooksizer': sParam = 'usesizer:' if param == 'usenotebooksizer': sParam = 'usesizer:'
elif param == 'option': sParam = 'proportion'
else: sParam = param + ':' else: sParam = param + ':'
label = wx.CheckBox(self, paramIDs[param], sParam, label = wx.CheckBox(self, paramIDs[param], sParam,
size = (LABEL_WIDTH,-1), name = param) size = (LABEL_WIDTH,-1), name = param)
@@ -303,13 +310,19 @@ class PropPage(ParamPage):
typeClass = ParamText typeClass = ParamText
control = typeClass(self, param) control = typeClass(self, param)
control.Enable(present) control.Enable(present)
sizer.AddMany([ (label, 0, wx.ALIGN_CENTER_VERTICAL), # Comment has only one parameter
(control, 0, wx.ALIGN_CENTER_VERTICAL | wx.GROW) ]) if isinstance(xxx, xxxComment):
# Bind char event to check Enter key
control.text.Bind(wx.EVT_CHAR, self.OnEnter)
sizer.Add(control, 0, wx.ALIGN_CENTER_VERTICAL | wx.GROW)
else:
sizer.AddMany([ (label, 0, wx.ALIGN_CENTER_VERTICAL),
(control, 0, wx.ALIGN_CENTER_VERTICAL | wx.GROW) ])
self.controls[param] = control self.controls[param] = control
topSizer.Add(sizer, 1, wx.ALL | wx.EXPAND, 3) topSizer.Add(sizer, 1, wx.ALL | wx.EXPAND, 3)
self.SetAutoLayout(True)
self.SetSizer(topSizer) self.SetSizer(topSizer)
topSizer.Fit(self) topSizer.Fit(self)
def SetValues(self, xxx): def SetValues(self, xxx):
self.xxx = xxx self.xxx = xxx
self.origChecks = [] self.origChecks = []
@@ -336,6 +349,13 @@ class PropPage(ParamPage):
self.origChecks.append((param, False)) self.origChecks.append((param, False))
self.origControls.append((param, '', False)) self.origControls.append((param, '', False))
# This is called only for comment now
def OnEnter(self, evt):
if evt.GetKeyCode() == 13:
g.tree.Apply(self.xxx, g.tree.selection)
else:
evt.Skip()
################################################################################ ################################################################################
# Style notebook page # Style notebook page
@@ -362,6 +382,7 @@ class StylePage(ParamPage):
self.SetAutoLayout(True) self.SetAutoLayout(True)
self.SetSizer(topSizer) self.SetSizer(topSizer)
topSizer.Fit(self) topSizer.Fit(self)
# Set data for a cahced page # Set data for a cahced page
def SetValues(self, xxx): def SetValues(self, xxx):
self.xxx = xxx self.xxx = xxx

View File

@@ -25,7 +25,10 @@ genericExStyles = [
'wxWS_EX_PROCESS_UI_UPDATES' 'wxWS_EX_PROCESS_UI_UPDATES'
] ]
buttonSize = (35,-1) # in dialog units, transformed to pixels in panel ctor # Global var initialized in Panel.__init__ for button size in screen pixels
buttonSize = None
# Button size in dialog units
buttonSizeD = (35,-1)
# Class that can properly disable children # Class that can properly disable children
class PPanel(wx.Panel): class PPanel(wx.Panel):
@@ -33,13 +36,14 @@ class PPanel(wx.Panel):
wx.Panel.__init__(self, parent, -1, name=name) wx.Panel.__init__(self, parent, -1, name=name)
self.modified = self.freeze = False self.modified = self.freeze = False
def Enable(self, value): def Enable(self, value):
self.enabled = value
# Something strange is going on with enable so we make sure... # Something strange is going on with enable so we make sure...
for w in self.GetChildren(): for w in self.GetChildren():
w.Enable(value) w.Enable(value)
#wx.Panel.Enable(self, value) #wx.Panel.Enable(self, value)
def SetModified(self): def SetModified(self, state=True):
self.modified = True self.modified = state
g.panel.SetModified(True) if state: g.panel.SetModified(True)
# Common method to set modified state # Common method to set modified state
def OnChange(self, evt): def OnChange(self, evt):
if self.freeze: return if self.freeze: return
@@ -56,9 +60,7 @@ class ParamBinaryOr(PPanel):
sizer.Add(self.text, 0, wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 5) sizer.Add(self.text, 0, wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 5)
self.button = wx.Button(self, self.ID_BUTTON_CHOICES, 'Edit...', size=buttonSize) self.button = wx.Button(self, self.ID_BUTTON_CHOICES, 'Edit...', size=buttonSize)
sizer.Add(self.button, 0, wx.ALIGN_CENTER_VERTICAL) sizer.Add(self.button, 0, wx.ALIGN_CENTER_VERTICAL)
self.SetAutoLayout(True)
self.SetSizer(sizer) self.SetSizer(sizer)
sizer.Fit(self)
wx.EVT_BUTTON(self, self.ID_BUTTON_CHOICES, self.OnButtonChoices) wx.EVT_BUTTON(self, self.ID_BUTTON_CHOICES, self.OnButtonChoices)
wx.EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange) wx.EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange)
def GetValue(self): def GetValue(self):
@@ -191,9 +193,7 @@ class ParamColour(PPanel):
sizer.Add(self.text, 0, wx.ALIGN_CENTER_VERTICAL | wx.TOP | wx.BOTTOM, 2) sizer.Add(self.text, 0, wx.ALIGN_CENTER_VERTICAL | wx.TOP | wx.BOTTOM, 2)
self.button = wx.Panel(self, self.ID_BUTTON, wx.DefaultPosition, wx.Size(20, 20)) self.button = wx.Panel(self, self.ID_BUTTON, wx.DefaultPosition, wx.Size(20, 20))
sizer.Add(self.button, 0, wx.ALIGN_CENTER_VERTICAL | wx.LEFT, 5) sizer.Add(self.button, 0, wx.ALIGN_CENTER_VERTICAL | wx.LEFT, 5)
self.SetAutoLayout(True)
self.SetSizer(sizer) self.SetSizer(sizer)
sizer.Fit(self)
self.textModified = False self.textModified = False
wx.EVT_PAINT(self.button, self.OnPaintButton) wx.EVT_PAINT(self.button, self.OnPaintButton)
wx.EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange) wx.EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange)
@@ -253,9 +253,7 @@ class ParamFont(PPanel):
sizer.Add(self.text, 0, wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 5) sizer.Add(self.text, 0, wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 5)
self.button = wx.Button(self, self.ID_BUTTON_SELECT, 'Select...', size=buttonSize) self.button = wx.Button(self, self.ID_BUTTON_SELECT, 'Select...', size=buttonSize)
sizer.Add(self.button, 0, wx.ALIGN_CENTER_VERTICAL) sizer.Add(self.button, 0, wx.ALIGN_CENTER_VERTICAL)
self.SetAutoLayout(True)
self.SetSizer(sizer) self.SetSizer(sizer)
sizer.Fit(self)
self.textModified = False self.textModified = False
wx.EVT_BUTTON(self, self.ID_BUTTON_SELECT, self.OnButtonSelect) wx.EVT_BUTTON(self, self.ID_BUTTON_SELECT, self.OnButtonSelect)
wx.EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange) wx.EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange)
@@ -320,7 +318,6 @@ class ParamFont(PPanel):
dlg = wx.FontDialog(self, data) dlg = wx.FontDialog(self, data)
if dlg.ShowModal() == wx.ID_OK: if dlg.ShowModal() == wx.ID_OK:
font = dlg.GetFontData().GetChosenFont() font = dlg.GetFontData().GetChosenFont()
print font.GetEncoding()
if font.GetEncoding() == wx.FONTENCODING_SYSTEM: if font.GetEncoding() == wx.FONTENCODING_SYSTEM:
encName = '' encName = ''
else: else:
@@ -348,9 +345,7 @@ class ParamInt(PPanel):
self.spin = wx.SpinCtrl(self, self.ID_SPIN_CTRL, size=(60,-1)) self.spin = wx.SpinCtrl(self, self.ID_SPIN_CTRL, size=(60,-1))
self.spin.SetRange(-2147483648, 2147483647) # min/max integers self.spin.SetRange(-2147483648, 2147483647) # min/max integers
sizer.Add(self.spin) sizer.Add(self.spin)
self.SetAutoLayout(True)
self.SetSizer(sizer) self.SetSizer(sizer)
sizer.Fit(self)
wx.EVT_SPINCTRL(self, self.ID_SPIN_CTRL, self.OnChange) wx.EVT_SPINCTRL(self, self.ID_SPIN_CTRL, self.OnChange)
def GetValue(self): def GetValue(self):
return str(self.spin.GetValue()) return str(self.spin.GetValue())
@@ -369,9 +364,7 @@ class ParamIntNN(PPanel):
self.spin = wx.SpinCtrl(self, self.ID_SPIN_CTRL, size=(60,-1)) self.spin = wx.SpinCtrl(self, self.ID_SPIN_CTRL, size=(60,-1))
self.spin.SetRange(0, 10000) # min/max integers self.spin.SetRange(0, 10000) # min/max integers
sizer.Add(self.spin) sizer.Add(self.spin)
self.SetAutoLayout(True)
self.SetSizer(sizer) self.SetSizer(sizer)
sizer.Fit(self)
wx.EVT_SPINCTRL(self, self.ID_SPIN_CTRL, self.OnChange) wx.EVT_SPINCTRL(self, self.ID_SPIN_CTRL, self.OnChange)
def GetValue(self): def GetValue(self):
return str(self.spin.GetValue()) return str(self.spin.GetValue())
@@ -388,26 +381,23 @@ class ParamUnit(PPanel):
self.ID_TEXT_CTRL = wx.NewId() self.ID_TEXT_CTRL = wx.NewId()
self.ID_SPIN_BUTTON = wx.NewId() self.ID_SPIN_BUTTON = wx.NewId()
sizer = wx.BoxSizer(wx.HORIZONTAL) sizer = wx.BoxSizer(wx.HORIZONTAL)
self.spin = wx.SpinButton(self, self.ID_SPIN_BUTTON, style = wx.SP_VERTICAL, size=(-1,1)) self.spin = wx.SpinButton(self, self.ID_SPIN_BUTTON, style = wx.SP_VERTICAL, size=(-1,0))
textW = 60 - self.spin.GetSize()[0] textW = 60 - self.spin.GetSize()[0]
self.text = wx.TextCtrl(self, self.ID_TEXT_CTRL, size=(textW,-1)) self.text = wx.TextCtrl(self, self.ID_TEXT_CTRL, size=(textW,-1))
self.spin.SetRange(-10000, 10000) self.spin.SetRange(-10000, 10000)
sizer.Add(self.text, 0, wx.EXPAND) sizer.Add(self.text, 0, wx.EXPAND)
sizer.Add(self.spin, 0, wx.EXPAND) sizer.Add(self.spin, 0, wx.EXPAND)
#sizer.SetMinSize((50,-1))
self.SetAutoLayout(True)
self.SetSizer(sizer) self.SetSizer(sizer)
sizer.Fit(self) self.spin.Bind(wx.EVT_SPIN_UP, self.OnSpinUp)
wx.EVT_SPIN_UP(self, self.ID_SPIN_BUTTON, self.OnSpinUp) self.spin.Bind(wx.EVT_SPIN_DOWN, self.OnSpinDown)
wx.EVT_SPIN_DOWN(self, self.ID_SPIN_BUTTON, self.OnSpinDown)
def GetValue(self): def GetValue(self):
return self.text.GetValue() return self.text.GetValue()
def SetValue(self, value): def SetValue(self, value):
self.freeze = True if not value: value = '0'
if not value: value = '0'
self.text.SetValue(value) self.text.SetValue(value)
self.freeze = False self.Change(0)
def Change(self, x): def Change(self, x):
self.freeze = True
# Check if we are working with dialog units # Check if we are working with dialog units
value = self.text.GetValue() value = self.text.GetValue()
units = '' units = ''
@@ -417,14 +407,19 @@ class ParamUnit(PPanel):
try: try:
intValue = int(value) + x intValue = int(value) + x
self.spin.SetValue(intValue) self.spin.SetValue(intValue)
self.text.SetValue(str(intValue) + units) if x: # 0 can be passed to update spin value only
self.SetModified() self.text.SetValue(str(intValue) + units)
self.SetModified()
except: except:
# !!! Strange, if I use wx.LogWarning, event is re-generated # !!! Strange, if I use wx.LogWarning, event is re-generated
print 'incorrect unit format' print 'ERROR: incorrect unit format'
self.freeze = False
def OnSpinUp(self, evt): def OnSpinUp(self, evt):
self.freeze = True
self.Change(1) self.Change(1)
def OnSpinDown(self, evt): def OnSpinDown(self, evt):
if self.freeze: return
self.freeze = True
self.Change(-1) self.Change(-1)
class ParamMultilineText(PPanel): class ParamMultilineText(PPanel):
@@ -437,9 +432,7 @@ class ParamMultilineText(PPanel):
sizer.Add(self.text, 0, wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 5) sizer.Add(self.text, 0, wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 5)
self.button = wx.Button(self, self.ID_BUTTON_EDIT, 'Edit...', size=buttonSize) self.button = wx.Button(self, self.ID_BUTTON_EDIT, 'Edit...', size=buttonSize)
sizer.Add(self.button, 0, wx.ALIGN_CENTER_VERTICAL) sizer.Add(self.button, 0, wx.ALIGN_CENTER_VERTICAL)
self.SetAutoLayout(True) self.SetSizerAndFit(sizer)
self.SetSizer(sizer)
sizer.Fit(self)
wx.EVT_BUTTON(self, self.ID_BUTTON_EDIT, self.OnButtonEdit) wx.EVT_BUTTON(self, self.ID_BUTTON_EDIT, self.OnButtonEdit)
wx.EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange) wx.EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange)
def GetValue(self): def GetValue(self):
@@ -458,18 +451,16 @@ class ParamMultilineText(PPanel):
dlg.Destroy() dlg.Destroy()
class ParamText(PPanel): class ParamText(PPanel):
def __init__(self, parent, name, textWidth=-1): def __init__(self, parent, name, textWidth=-1, style=0):
PPanel.__init__(self, parent, name) PPanel.__init__(self, parent, name)
self.ID_TEXT_CTRL = wx.NewId() self.ID_TEXT_CTRL = wx.NewId()
# We use sizer even here to have the same size of text control # We use sizer even here to have the same size of text control
sizer = wx.BoxSizer() sizer = wx.BoxSizer()
self.text = wx.TextCtrl(self, self.ID_TEXT_CTRL, size=wx.Size(textWidth,-1)) self.text = wx.TextCtrl(self, self.ID_TEXT_CTRL, size=wx.Size(textWidth,-1), style=style)
if textWidth == -1: option = 1 if textWidth == -1: option = 1
else: option = 0 else: option = 0
sizer.Add(self.text, option, wx.ALIGN_CENTER_VERTICAL | wx.TOP | wx.BOTTOM, 2) sizer.Add(self.text, option, wx.ALIGN_CENTER_VERTICAL | wx.TOP | wx.BOTTOM, 2)
self.SetAutoLayout(True)
self.SetSizer(sizer) self.SetSizer(sizer)
sizer.Fit(self)
wx.EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange) wx.EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange)
def GetValue(self): def GetValue(self):
return self.text.GetValue() return self.text.GetValue()
@@ -494,6 +485,11 @@ class ParamEncoding(ParamText):
def __init__(self, parent, name): def __init__(self, parent, name):
ParamText.__init__(self, parent, name, 100) ParamText.__init__(self, parent, name, 100)
class ParamComment(ParamText):
def __init__(self, parent, name):
ParamText.__init__(self, parent, name, 330 + buttonSize[0],
style=wx.TE_PROCESS_ENTER)
class ContentDialog(wx.Dialog): class ContentDialog(wx.Dialog):
def __init__(self, parent, value): def __init__(self, parent, value):
# Load from resource # Load from resource
@@ -612,9 +608,7 @@ class ParamContent(PPanel):
sizer.Add(self.text, 0, wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 5) sizer.Add(self.text, 0, wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 5)
self.button = wx.Button(self, self.ID_BUTTON_EDIT, 'Edit...', size=buttonSize) self.button = wx.Button(self, self.ID_BUTTON_EDIT, 'Edit...', size=buttonSize)
sizer.Add(self.button, 0, wx.ALIGN_CENTER_VERTICAL) sizer.Add(self.button, 0, wx.ALIGN_CENTER_VERTICAL)
self.SetAutoLayout(True)
self.SetSizer(sizer) self.SetSizer(sizer)
sizer.Fit(self)
self.textModified = False self.textModified = False
wx.EVT_BUTTON(self, self.ID_BUTTON_EDIT, self.OnButtonEdit) wx.EVT_BUTTON(self, self.ID_BUTTON_EDIT, self.OnButtonEdit)
wx.EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange) wx.EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange)
@@ -625,8 +619,7 @@ class ParamContent(PPanel):
if self.textModified: # text has newer value if self.textModified: # text has newer value
try: try:
return self.text.GetValue().split('|') return self.text.GetValue().split('|')
except SyntaxError: except ValueError:
wx.LogError('Syntax error in parameter value: ' + self.GetName())
return [] return []
return self.value return self.value
def SetValue(self, value): def SetValue(self, value):
@@ -648,6 +641,9 @@ class ParamContent(PPanel):
self.SetModified() self.SetModified()
self.textModified = False self.textModified = False
dlg.Destroy() dlg.Destroy()
def SetModified(self, state=True):
PPanel.SetModified(self, state)
self.textModified = False
# CheckList content # CheckList content
class ParamContentCheckList(ParamContent): class ParamContentCheckList(ParamContent):
@@ -728,8 +724,7 @@ class ParamIntList(ParamContent):
if self.textModified: # text has newer value if self.textModified: # text has newer value
try: try:
self.value = map(int, self.text.GetValue().split('|')) self.value = map(int, self.text.GetValue().split('|'))
except SyntaxError: except ValueError:
wx.LogError('Syntax error in parameter value: ' + self.GetName())
self.value = [] self.value = []
dlg = IntListDialog(self, self.value) dlg = IntListDialog(self, self.value)
if dlg.ShowModal() == wx.ID_OK: if dlg.ShowModal() == wx.ID_OK:
@@ -752,9 +747,7 @@ class RadioBox(PPanel):
button = wx.RadioButton(self, -1, i, size=(-1,buttonSize[1]), name=i) button = wx.RadioButton(self, -1, i, size=(-1,buttonSize[1]), name=i)
topSizer.Add(button, 0, wx.RIGHT, 5) topSizer.Add(button, 0, wx.RIGHT, 5)
wx.EVT_RADIOBUTTON(self, button.GetId(), self.OnRadioChoice) wx.EVT_RADIOBUTTON(self, button.GetId(), self.OnRadioChoice)
self.SetAutoLayout(True)
self.SetSizer(topSizer) self.SetSizer(topSizer)
topSizer.Fit(self)
def SetStringSelection(self, value): def SetStringSelection(self, value):
self.freeze = True self.freeze = True
for i in self.choices: for i in self.choices:
@@ -812,9 +805,7 @@ class ParamFile(PPanel):
sizer.Add(self.text, 0, wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 5) sizer.Add(self.text, 0, wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 5)
self.button = wx.Button(self, self.ID_BUTTON_BROWSE, 'Browse...',size=buttonSize) self.button = wx.Button(self, self.ID_BUTTON_BROWSE, 'Browse...',size=buttonSize)
sizer.Add(self.button, 0, wx.ALIGN_CENTER_VERTICAL) sizer.Add(self.button, 0, wx.ALIGN_CENTER_VERTICAL)
self.SetAutoLayout(True)
self.SetSizer(sizer) self.SetSizer(sizer)
sizer.Fit(self)
self.textModified = False self.textModified = False
wx.EVT_BUTTON(self, self.ID_BUTTON_BROWSE, self.OnButtonBrowse) wx.EVT_BUTTON(self, self.ID_BUTTON_BROWSE, self.OnButtonBrowse)
wx.EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange) wx.EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange)
@@ -941,5 +932,6 @@ paramDict = {
'fg': ParamColour, 'bg': ParamColour, 'font': ParamFont, 'fg': ParamColour, 'bg': ParamColour, 'font': ParamFont,
'enabled': ParamBool, 'focused': ParamBool, 'hidden': ParamBool, 'enabled': ParamBool, 'focused': ParamBool, 'hidden': ParamBool,
'tooltip': ParamText, 'bitmap': ParamBitmap, 'icon': ParamBitmap, 'tooltip': ParamText, 'bitmap': ParamBitmap, 'icon': ParamBitmap,
'encoding': ParamEncoding, 'borders': ParamUnit 'encoding': ParamEncoding, 'borders': ParamUnit,
'comment': ParamComment
} }

View File

@@ -87,11 +87,11 @@ class Tools(wx.Panel):
(ID_NEW.UNKNOWN, images.getToolUnknownBitmap())] (ID_NEW.UNKNOWN, images.getToolUnknownBitmap())]
] ]
self.boxes = {}
for grp in groups: for grp in groups:
self.AddGroup(grp[0]) self.AddGroup(grp[0])
for b in grp[1:]: for b in grp[1:]:
self.AddButton(b[0], b[1], g.pullDownMenu.createMap[b[0]]) self.AddButton(b[0], b[1], g.pullDownMenu.createMap[b[0]])
self.SetAutoLayout(True)
self.SetSizerAndFit(self.sizer) self.SetSizerAndFit(self.sizer)
# Allow to be resized in vertical direction only # Allow to be resized in vertical direction only
self.SetSizeHints(self.GetSize()[0], -1) self.SetSizeHints(self.GetSize()[0], -1)
@@ -114,13 +114,19 @@ class Tools(wx.Panel):
def AddGroup(self, name): def AddGroup(self, name):
# Each group is inside box # Each group is inside box
box = wx.StaticBox(self, -1, name, style=wx.WANTS_CHARS) id = wx.NewId()
box = wx.StaticBox(self, id, '[+] '+name, style=wx.WANTS_CHARS)
box.show = True
box.name = name
box.gnum = len(self.groups)
box.SetFont(g.smallerFont()) box.SetFont(g.smallerFont())
box.Bind(wx.EVT_LEFT_DOWN, self.OnClickBox)
boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL) boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
boxSizer.Add((0, 4)) boxSizer.Add((0, 4))
self.boxes[id] = box
self.curSizer = wx.GridSizer(0, 3) self.curSizer = wx.GridSizer(0, 3)
boxSizer.Add(self.curSizer) boxSizer.Add(self.curSizer)
self.sizer.Add(boxSizer, 0, wx.TOP | wx.LEFT | wx.RIGHT, 4) self.sizer.Add(boxSizer, 0, wx.TOP | wx.LEFT | wx.RIGHT | wx.EXPAND, 4)
self.groups.append((box,{})) self.groups.append((box,{}))
# Enable/disable group # Enable/disable group
@@ -129,6 +135,12 @@ class Tools(wx.Panel):
grp[0].Enable(enable) grp[0].Enable(enable)
for b in grp[1].values(): b.Enable(enable) for b in grp[1].values(): b.Enable(enable)
# Show/hide group
def ShowGroup(self, gnum, show = True):
grp = self.groups[gnum]
grp[0].show = show
for b in grp[1].values(): b.Show(show)
# Enable/disable group item # Enable/disable group item
def EnableGroupItem(self, gnum, id, enable = True): def EnableGroupItem(self, gnum, id, enable = True):
grp = self.groups[gnum] grp = self.groups[gnum]
@@ -140,6 +152,14 @@ class Tools(wx.Panel):
for id in ids: for id in ids:
grp[1][id].Enable(enable) grp[1][id].Enable(enable)
def OnClickBox(self, evt):
box = self.boxes[evt.GetId()]
# Collapse/restore static box, change label
self.ShowGroup(box.gnum, not box.show)
if box.show: box.SetLabel('[+] ' + box.name)
else: box.SetLabel('[-] ' + box.name)
self.Layout()
# Process key events # Process key events
def OnKeyDown(self, evt): def OnKeyDown(self, evt):
if evt.GetKeyCode() == wx.WXK_CONTROL: if evt.GetKeyCode() == wx.WXK_CONTROL:

View File

@@ -86,10 +86,12 @@ class ID_NEW:
CHOICEBOOK = wx.NewId() CHOICEBOOK = wx.NewId()
LISTBOOK = wx.NewId() LISTBOOK = wx.NewId()
SPLITTER_WINDOW = wx.NewId() SPLITTER_WINDOW = wx.NewId()
GRID = wx.NewId()
SCROLLED_WINDOW = wx.NewId() SCROLLED_WINDOW = wx.NewId()
HTML_WINDOW = wx.NewId() HTML_WINDOW = wx.NewId()
CALENDAR_CTRL = wx.NewId() CALENDAR_CTRL = wx.NewId()
DATE_CTRL = wx.NewId() DATE_CTRL = wx.NewId()
FILE_PICKER_CTRL = wx.NewId()
GENERIC_DIR_CTRL = wx.NewId() GENERIC_DIR_CTRL = wx.NewId()
SPIN_CTRL = wx.NewId() SPIN_CTRL = wx.NewId()
UNKNOWN = wx.NewId() UNKNOWN = wx.NewId()
@@ -124,6 +126,10 @@ class ID_NEW:
CONTEXT_HELP_BUTTON = wx.NewId() CONTEXT_HELP_BUTTON = wx.NewId()
REF = wx.NewId() REF = wx.NewId()
COMMENT = wx.NewId()
CUSTOM = wx.NewId()
for i in range(99): wx.NewId() # reserve IDs for custom controls
LAST = wx.NewId() LAST = wx.NewId()
@@ -193,10 +199,12 @@ class PullDownMenu:
ID_NEW.CHOICEBOOK: 'wxChoicebook', ID_NEW.CHOICEBOOK: 'wxChoicebook',
ID_NEW.LISTBOOK: 'wxListbook', ID_NEW.LISTBOOK: 'wxListbook',
ID_NEW.SPLITTER_WINDOW: 'wxSplitterWindow', ID_NEW.SPLITTER_WINDOW: 'wxSplitterWindow',
ID_NEW.GRID: 'wxGrid',
ID_NEW.SCROLLED_WINDOW: 'wxScrolledWindow', ID_NEW.SCROLLED_WINDOW: 'wxScrolledWindow',
ID_NEW.HTML_WINDOW: 'wxHtmlWindow', ID_NEW.HTML_WINDOW: 'wxHtmlWindow',
ID_NEW.CALENDAR_CTRL: 'wxCalendarCtrl', ID_NEW.CALENDAR_CTRL: 'wxCalendarCtrl',
ID_NEW.DATE_CTRL: 'wxDatePickerCtrl', ID_NEW.DATE_CTRL: 'wxDatePickerCtrl',
ID_NEW.FILE_PICKER_CTRL: 'wxFilePickerCtrl',
ID_NEW.GENERIC_DIR_CTRL: 'wxGenericDirCtrl', ID_NEW.GENERIC_DIR_CTRL: 'wxGenericDirCtrl',
ID_NEW.SPIN_CTRL: 'wxSpinCtrl', ID_NEW.SPIN_CTRL: 'wxSpinCtrl',
@@ -268,10 +276,12 @@ class PullDownMenu:
(ID_NEW.SCROLL_BAR, 'ScrollBar', 'Create scroll bar'), (ID_NEW.SCROLL_BAR, 'ScrollBar', 'Create scroll bar'),
(ID_NEW.TREE_CTRL, 'TreeCtrl', 'Create tree'), (ID_NEW.TREE_CTRL, 'TreeCtrl', 'Create tree'),
(ID_NEW.LIST_CTRL, 'ListCtrl', 'Create list'), (ID_NEW.LIST_CTRL, 'ListCtrl', 'Create list'),
# (ID_NEW.GRID, 'Grid', 'Create grid'),
(ID_NEW.SCROLLED_WINDOW, 'ScrolledWindow', 'Create scrolled window'), (ID_NEW.SCROLLED_WINDOW, 'ScrolledWindow', 'Create scrolled window'),
(ID_NEW.HTML_WINDOW, 'HtmlWindow', 'Create HTML window'), (ID_NEW.HTML_WINDOW, 'HtmlWindow', 'Create HTML window'),
(ID_NEW.CALENDAR_CTRL, 'CalendarCtrl', 'Create calendar control'), (ID_NEW.CALENDAR_CTRL, 'CalendarCtrl', 'Create calendar control'),
(ID_NEW.DATE_CTRL, 'DatePickerCtrl', 'Create date picker control'), (ID_NEW.DATE_CTRL, 'DatePickerCtrl', 'Create date picker control'),
# (ID_NEW.FILE_PICKER_CTRL, 'FilePickerCtrl', 'Create file picker control'),
(ID_NEW.GENERIC_DIR_CTRL, 'GenericDirCtrl', 'Create generic dir control'), (ID_NEW.GENERIC_DIR_CTRL, 'GenericDirCtrl', 'Create generic dir control'),
(ID_NEW.UNKNOWN, 'Unknown', 'Create custom control placeholder'), (ID_NEW.UNKNOWN, 'Unknown', 'Create custom control placeholder'),
], ],
@@ -370,7 +380,13 @@ class PullDownMenu:
ID_NEW.HELP_BUTTON: ('wxID_HELP', '&Help'), ID_NEW.HELP_BUTTON: ('wxID_HELP', '&Help'),
ID_NEW.CONTEXT_HELP_BUTTON: ('wxID_CONTEXT_HELP', '&Help'), ID_NEW.CONTEXT_HELP_BUTTON: ('wxID_CONTEXT_HELP', '&Help'),
} }
self.custom = ['custom', 'User-defined controls']
self.customMap = {}
def addCustom(self, klass):
n = len(self.custom)-2
self.custom.append((ID_NEW.CUSTOM + n, klass))
self.customMap[ID_NEW.CUSTOM + n] = klass
################################################################################ ################################################################################
@@ -409,6 +425,7 @@ class HighLightBox:
l4 = wx.Window(w, -1, wx.Point(pos.x, pos.y + size.height - 2), wx.Size(size.width, 2)) l4 = wx.Window(w, -1, wx.Point(pos.x, pos.y + size.height - 2), wx.Size(size.width, 2))
l4.SetBackgroundColour(wx.RED) l4.SetBackgroundColour(wx.RED)
self.lines = [l1, l2, l3, l4] self.lines = [l1, l2, l3, l4]
self.size = size
# Move highlight to a new position # Move highlight to a new position
def Replace(self, pos, size): def Replace(self, pos, size):
if size.width == -1: size.width = 0 if size.width == -1: size.width = 0
@@ -417,6 +434,7 @@ class HighLightBox:
self.lines[1].SetDimensions(pos.x, pos.y, 2, size.height) self.lines[1].SetDimensions(pos.x, pos.y, 2, size.height)
self.lines[2].SetDimensions(pos.x + size.width - 2, pos.y, 2, size.height) self.lines[2].SetDimensions(pos.x + size.width - 2, pos.y, 2, size.height)
self.lines[3].SetDimensions(pos.x, pos.y + size.height - 2, size.width, 2) self.lines[3].SetDimensions(pos.x, pos.y + size.height - 2, size.width, 2)
self.size = size
# Remove it # Remove it
def Remove(self): def Remove(self):
map(wx.Window.Destroy, self.lines) map(wx.Window.Destroy, self.lines)
@@ -428,8 +446,12 @@ class HighLightBox:
class XML_Tree(wx.TreeCtrl): class XML_Tree(wx.TreeCtrl):
def __init__(self, parent, id): def __init__(self, parent, id):
wx.TreeCtrl.__init__(self, parent, id, style = wx.TR_HAS_BUTTONS | wx.TR_MULTIPLE) wx.TreeCtrl.__init__(self, parent, id,
style = wx.TR_HAS_BUTTONS | wx.TR_MULTIPLE | wx.TR_EDIT_LABELS)
self.SetBackgroundColour(wx.Colour(224, 248, 224)) self.SetBackgroundColour(wx.Colour(224, 248, 224))
self.fontComment = wx.FFont(self.GetFont().GetPointSize(),
self.GetFont().GetFamily(),
wx.FONTFLAG_ITALIC)
# Register events # Register events
wx.EVT_TREE_SEL_CHANGED(self, self.GetId(), self.OnSelChanged) wx.EVT_TREE_SEL_CHANGED(self, self.GetId(), self.OnSelChanged)
# One works on Linux, another on Windows # One works on Linux, another on Windows
@@ -440,6 +462,8 @@ class XML_Tree(wx.TreeCtrl):
wx.EVT_RIGHT_DOWN(self, self.OnRightDown) wx.EVT_RIGHT_DOWN(self, self.OnRightDown)
wx.EVT_TREE_ITEM_EXPANDED(self, self.GetId(), self.OnItemExpandedCollapsed) wx.EVT_TREE_ITEM_EXPANDED(self, self.GetId(), self.OnItemExpandedCollapsed)
wx.EVT_TREE_ITEM_COLLAPSED(self, self.GetId(), self.OnItemExpandedCollapsed) wx.EVT_TREE_ITEM_COLLAPSED(self, self.GetId(), self.OnItemExpandedCollapsed)
self.Bind(wx.EVT_TREE_BEGIN_LABEL_EDIT, self.OnBeginLabelEdit)
self.Bind(wx.EVT_TREE_END_LABEL_EDIT, self.OnEndLabelEdit)
self.selection = None self.selection = None
self.selectionChanging = False self.selectionChanging = False
@@ -450,6 +474,7 @@ class XML_Tree(wx.TreeCtrl):
# Create image list # Create image list
il = wx.ImageList(16, 16, True) il = wx.ImageList(16, 16, True)
self.rootImage = il.Add(images.getTreeRootImage().Scale(16,16).ConvertToBitmap()) self.rootImage = il.Add(images.getTreeRootImage().Scale(16,16).ConvertToBitmap())
xxxComment.image = il.Add(images.getTreeCommentImage().Scale(16,16).ConvertToBitmap())
xxxObject.image = il.Add(images.getTreeDefaultImage().Scale(16,16).ConvertToBitmap()) xxxObject.image = il.Add(images.getTreeDefaultImage().Scale(16,16).ConvertToBitmap())
xxxPanel.image = il.Add(images.getTreePanelImage().Scale(16,16).ConvertToBitmap()) xxxPanel.image = il.Add(images.getTreePanelImage().Scale(16,16).ConvertToBitmap())
xxxDialog.image = il.Add(images.getTreeDialogImage().Scale(16,16).ConvertToBitmap()) xxxDialog.image = il.Add(images.getTreeDialogImage().Scale(16,16).ConvertToBitmap())
@@ -560,19 +585,22 @@ class XML_Tree(wx.TreeCtrl):
item = self.AppendItem(itemParent, treeObj.treeName(), item = self.AppendItem(itemParent, treeObj.treeName(),
image=treeObj.treeImage(), image=treeObj.treeImage(),
data=wx.TreeItemData(xxx)) data=wx.TreeItemData(xxx))
# Different color for references # Different color for comments and references
if treeObj.ref: if xxx.className == 'comment':
self.SetItemTextColour(item, 'Blue')
self.SetItemFont(item, self.fontComment)
elif treeObj.ref:
self.SetItemTextColour(item, 'DarkGreen') self.SetItemTextColour(item, 'DarkGreen')
elif treeObj.hasStyle and treeObj.params.get('hidden', False): elif treeObj.hasStyle and treeObj.params.get('hidden', False):
self.SetItemTextColour(item, 'Grey') self.SetItemTextColour(item, 'Grey')
# Try to find children objects # Try to find children objects
if treeObj.hasChildren: if treeObj.hasChildren:
nodes = treeObj.element.childNodes[:] nodes = treeObj.node.childNodes[:]
for n in nodes: for n in nodes:
if IsObject(n): if IsObject(n):
self.AddNode(item, treeObj, n) self.AddNode(item, treeObj, n)
elif n.nodeType != minidom.Node.ELEMENT_NODE: elif n.nodeType != minidom.Node.ELEMENT_NODE:
treeObj.element.removeChild(n) treeObj.node.removeChild(n)
n.unlink() n.unlink()
# Insert new item at specific position # Insert new item at specific position
@@ -581,23 +609,30 @@ class XML_Tree(wx.TreeCtrl):
xxx = MakeXXXFromDOM(parent, elem) xxx = MakeXXXFromDOM(parent, elem)
# If nextItem is None, we append to parent, otherwise insert before it # If nextItem is None, we append to parent, otherwise insert before it
if nextItem.IsOk(): if nextItem.IsOk():
node = self.GetPyData(nextItem).element node = self.GetPyData(nextItem).node
parent.element.insertBefore(elem, node) parent.node.insertBefore(elem, node)
# Inserting before is difficult, se we insert after or first child # Inserting before is difficult, se we insert after or first child
index = self.ItemIndex(nextItem) index = self.ItemIndex(nextItem)
newItem = self.InsertItemBefore(itemParent, index, newItem = self.InsertItemBefore(itemParent, index,
xxx.treeName(), image=xxx.treeImage()) xxx.treeName(), image=xxx.treeImage())
self.SetPyData(newItem, xxx) self.SetPyData(newItem, xxx)
else: else:
parent.element.appendChild(elem) parent.node.appendChild(elem)
newItem = self.AppendItem(itemParent, xxx.treeName(), image=xxx.treeImage(), newItem = self.AppendItem(itemParent, xxx.treeName(), image=xxx.treeImage(),
data=wx.TreeItemData(xxx)) data=wx.TreeItemData(xxx))
# Different color for references treeObj = xxx.treeObject()
if xxx.treeObject().ref: self.SetItemTextColour(newItem, 'DarkGreen') # Different color for references and comments
if xxx.className == 'comment':
self.SetItemTextColour(newItem, 'Blue')
self.SetItemFont(newItem, self.fontComment)
elif treeObj.ref:
self.SetItemTextColour(newItem, 'DarkGreen')
elif treeObj.hasStyle and treeObj.params.get('hidden', False):
self.SetItemTextColour(newItem, 'Grey')
# Add children items # Add children items
if xxx.hasChildren: if xxx.hasChildren:
treeObj = xxx.treeObject() treeObj = xxx.treeObject()
for n in treeObj.element.childNodes: for n in treeObj.node.childNodes:
if IsObject(n): if IsObject(n):
self.AddNode(newItem, treeObj, n) self.AddNode(newItem, treeObj, n)
return newItem return newItem
@@ -605,13 +640,14 @@ class XML_Tree(wx.TreeCtrl):
# Remove leaf of tree, return it's data object # Remove leaf of tree, return it's data object
def RemoveLeaf(self, leaf): def RemoveLeaf(self, leaf):
xxx = self.GetPyData(leaf) xxx = self.GetPyData(leaf)
node = xxx.element node = xxx.node
parent = node.parentNode parent = node.parentNode
parent.removeChild(node) parent.removeChild(node)
self.Delete(leaf) self.Delete(leaf)
# Reset selection object # Reset selection object
self.selection = None self.selection = None
return node return node
# Find position relative to the top-level window # Find position relative to the top-level window
def FindNodePos(self, item, obj=None): def FindNodePos(self, item, obj=None):
# Root at (0,0) # Root at (0,0)
@@ -631,17 +667,18 @@ class XML_Tree(wx.TreeCtrl):
if g.testWin.highLight: if g.testWin.highLight:
g.testWin.highLight.Remove() g.testWin.highLight.Remove()
break break
# Find first ancestor which is a wxWindow (not a sizer) # For sizers and notebooks we must select the first window-like parent
winParent = itemParent winParent = itemParent
while self.GetPyData(winParent).isSizer: while self.GetPyData(winParent).isSizer:
winParent = self.GetItemParent(winParent) winParent = self.GetItemParent(winParent)
# Notebook children are layed out in a little strange way # Notebook children are layed out in a little strange way
if self.GetPyData(itemParent).treeObject().__class__ == xxxNotebook: # wxGTK places NB panels relative to the NB parent
parentPos = wx.Point(0,0) if wx.Platform == '__WXGTK__':
else: if self.GetPyData(itemParent).treeObject().__class__ == xxxNotebook:
parentPos = self.FindNodePos(winParent) winParent = self.GetItemParent(winParent)
# Position (-1,-1) is really (0,0) parentPos = self.FindNodePos(winParent)
pos = obj.GetPosition() pos = obj.GetPosition()
# Position (-1,-1) is really (0,0)
if pos == (-1,-1): pos = (0,0) if pos == (-1,-1): pos = (0,0)
return parentPos + pos return parentPos + pos
@@ -700,7 +737,6 @@ class XML_Tree(wx.TreeCtrl):
# If some data was modified, apply changes # If some data was modified, apply changes
if g.panel.IsModified(): if g.panel.IsModified():
self.Apply(xxx, oldItem) self.Apply(xxx, oldItem)
#if conf.autoRefresh:
if g.testWin: if g.testWin:
if g.testWin.highLight: if g.testWin.highLight:
g.testWin.highLight.Remove() g.testWin.highLight.Remove()
@@ -747,16 +783,22 @@ class XML_Tree(wx.TreeCtrl):
if not obj or xxx.hasStyle and xxx.params.get('hidden', False): if not obj or xxx.hasStyle and xxx.params.get('hidden', False):
if g.testWin.highLight: g.testWin.highLight.Remove() if g.testWin.highLight: g.testWin.highLight.Remove()
return return
pos = self.FindNodePos(item, obj) pos = self.FindNodePos(item, obj)
size = obj.GetSize() size = obj.GetSize()
# Highlight # Highlight
# Negative positions are not working quite well # Negative positions are not working quite well
if g.testWin.highLight: hl = g.testWin.highLight
g.testWin.highLight.Replace(pos, size) # If highlight object has the same size SetDimension does not repaint it
# so we must remove the old HL window
if hl and hl.size == size:
hl.Remove()
hl = None
if hl:
hl.Replace(pos, size)
else: else:
g.testWin.highLight = HighLightBox(pos, size) g.testWin.highLight = hl = HighLightBox(pos, size)
g.testWin.highLight.Refresh() hl.Refresh()
g.testWin.highLight.item = item hl.item = item
def ShowTestWindow(self, item): def ShowTestWindow(self, item):
xxx = self.GetPyData(item) xxx = self.GetPyData(item)
@@ -774,7 +816,7 @@ class XML_Tree(wx.TreeCtrl):
return return
# Show item in bold # Show item in bold
if g.testWin: # Reset old if g.testWin: # Reset old
self.Unselect() self.UnselectAll()
self.SetItemBold(g.testWin.item, False) self.SetItemBold(g.testWin.item, False)
try: try:
wx.BeginBusyCursor() wx.BeginBusyCursor()
@@ -810,19 +852,6 @@ class XML_Tree(wx.TreeCtrl):
testWin = g.testWin testWin = g.testWin
# Create a window with this resource # Create a window with this resource
xxx = self.GetPyData(item).treeObject() xxx = self.GetPyData(item).treeObject()
# If frame
# if xxx.__class__ == xxxFrame:
# Frame can't have many children,
# but it's first child possibly can...
# child = self.GetFirstChild(item)[0]
# if child.IsOk() and self.GetPyData(child).__class__ == xxxPanel:
# # Clean-up before recursive call or error
# wx.MemoryFSHandler.RemoveFile('xxx.xrc')
# wx.EndBusyCursor()
# self.CreateTestWin(child)
# return
# Close old window, remember where it was # Close old window, remember where it was
highLight = None highLight = None
if testWin: if testWin:
@@ -848,7 +877,7 @@ class XML_Tree(wx.TreeCtrl):
# Save in memory FS # Save in memory FS
memFile = MemoryFile('xxx.xrc') memFile = MemoryFile('xxx.xrc')
# Create memory XML file # Create memory XML file
elem = xxx.element.cloneNode(True) elem = xxx.node.cloneNode(True)
if not xxx.name: if not xxx.name:
name = 'noname' name = 'noname'
else: else:
@@ -877,6 +906,10 @@ class XML_Tree(wx.TreeCtrl):
if not g.currentEncoding: if not g.currentEncoding:
xmlFlags != xrc.XRC_USE_LOCALE xmlFlags != xrc.XRC_USE_LOCALE
res = xrc.XmlResource('', xmlFlags) res = xrc.XmlResource('', xmlFlags)
xrc.XmlResource.Set(res) # set as global
# Register handlers
addHandlers()
# Same module list
res.Load('memory:xxx.xrc') res.Load('memory:xxx.xrc')
try: try:
if xxx.__class__ == xxxFrame: if xxx.__class__ == xxxFrame:
@@ -907,7 +940,7 @@ class XML_Tree(wx.TreeCtrl):
testWin.SetClientSize(testWin.GetBestSize()) testWin.SetClientSize(testWin.GetBestSize())
testWin.Show(True) testWin.Show(True)
elif xxx.__class__ == xxxDialog: elif xxx.__class__ == xxxDialog:
testWin = g.testWin = res.LoadDialog(None, STD_NAME) testWin = g.testWin = res.LoadDialog(g.frame, STD_NAME)
testWin.panel = testWin testWin.panel = testWin
testWin.Layout() testWin.Layout()
testWin.SetPosition(pos) testWin.SetPosition(pos)
@@ -917,7 +950,7 @@ class XML_Tree(wx.TreeCtrl):
wx.EVT_BUTTON(testWin, wx.ID_CANCEL, self.OnCloseTestWin) wx.EVT_BUTTON(testWin, wx.ID_CANCEL, self.OnCloseTestWin)
elif xxx.__class__ == xxxWizard: elif xxx.__class__ == xxxWizard:
wiz = wx.wizard.PreWizard() wiz = wx.wizard.PreWizard()
res.LoadOnObject(wiz, None, STD_NAME, 'wxWizard') res.LoadOnObject(wiz, g.frame, STD_NAME, 'wxWizard')
# Find first page (don't know better way) # Find first page (don't know better way)
firstPage = None firstPage = None
for w in wiz.GetChildren(): for w in wiz.GetChildren():
@@ -959,9 +992,11 @@ class XML_Tree(wx.TreeCtrl):
testWin.toolBar = res.LoadToolBar(testWin, STD_NAME) testWin.toolBar = res.LoadToolBar(testWin, STD_NAME)
testWin.SetToolBar(testWin.toolBar) testWin.SetToolBar(testWin.toolBar)
testWin.Show(True) testWin.Show(True)
# Catch some events, set highlight
if testWin: if testWin:
testWin.item = item testWin.item = item
wx.EVT_CLOSE(testWin, self.OnCloseTestWin) wx.EVT_CLOSE(testWin, self.OnCloseTestWin)
wx.EVT_SIZE(testWin, self.OnSizeTestWin)
testWin.highLight = None testWin.highLight = None
if highLight and not self.pendingHighLight: if highLight and not self.pendingHighLight:
self.HighLight(highLight) self.HighLight(highLight)
@@ -974,6 +1009,9 @@ class XML_Tree(wx.TreeCtrl):
inf = sys.exc_info() inf = sys.exc_info()
wx.LogError(traceback.format_exception(inf[0], inf[1], None)[-1]) wx.LogError(traceback.format_exception(inf[0], inf[1], None)[-1])
wx.LogError('Error loading resource') wx.LogError('Error loading resource')
# Cleanup
res.Unload('xxx.xrc')
xrc.XmlResource.Set(None)
wx.MemoryFSHandler.RemoveFile('xxx.xrc') wx.MemoryFSHandler.RemoveFile('xxx.xrc')
def CloseTestWindow(self): def CloseTestWindow(self):
@@ -987,6 +1025,11 @@ class XML_Tree(wx.TreeCtrl):
def OnCloseTestWin(self, evt): def OnCloseTestWin(self, evt):
self.CloseTestWindow() self.CloseTestWindow()
def OnSizeTestWin(self, evt):
if g.testWin.highLight:
self.HighLight(g.testWin.highLight.item)
evt.Skip()
# Return index in parent, for real window children # Return index in parent, for real window children
def WindowIndex(self, item): def WindowIndex(self, item):
n = 0 # index of sibling n = 0 # index of sibling
@@ -1068,6 +1111,7 @@ class XML_Tree(wx.TreeCtrl):
SetMenu(m, pullDownMenu.topLevel) SetMenu(m, pullDownMenu.topLevel)
m.AppendSeparator() m.AppendSeparator()
m.Append(ID_NEW.REF, 'reference...', 'Create object_ref node') m.Append(ID_NEW.REF, 'reference...', 'Create object_ref node')
m.Append(ID_NEW.COMMENT, 'comment', 'Create comment node')
else: else:
xxx = self.GetPyData(item).treeObject() xxx = self.GetPyData(item).treeObject()
# Check parent for possible child nodes if inserting sibling # Check parent for possible child nodes if inserting sibling
@@ -1089,8 +1133,12 @@ class XML_Tree(wx.TreeCtrl):
m.Enable(ID_NEW.SPACER, False) m.Enable(ID_NEW.SPACER, False)
if xxx.__class__ is not xxxFrame: if xxx.__class__ is not xxxFrame:
m.Enable(ID_NEW.MENU_BAR, False) m.Enable(ID_NEW.MENU_BAR, False)
# Add custom controls menu
if len(pullDownMenu.custom) > 2:
SetMenu(m, [pullDownMenu.custom])
m.AppendSeparator() m.AppendSeparator()
m.Append(ID_NEW.REF, 'reference...', 'Create object_ref node') m.Append(ID_NEW.REF, 'reference...', 'Create object_ref node')
m.Append(ID_NEW.COMMENT, 'comment', 'Create comment node')
# Select correct label for create menu # Select correct label for create menu
if not needInsert: if not needInsert:
if self.shift: if self.shift:
@@ -1126,11 +1174,12 @@ class XML_Tree(wx.TreeCtrl):
SetMenu(m, pullDownMenu.sizers, shift=True) SetMenu(m, pullDownMenu.sizers, shift=True)
else: else:
SetMenu(m, pullDownMenu.controls, shift=True) SetMenu(m, pullDownMenu.controls, shift=True)
id = wx.NewId() if xxx.isElement:
menu.AppendMenu(id, 'Replace With', m) id = wx.NewId()
if not m.GetMenuItemCount(): menu.Enable(id, False) menu.AppendMenu(id, 'Replace With', m)
menu.Append(pullDownMenu.ID_SUBCLASS, 'Subclass...', if not m.GetMenuItemCount(): menu.Enable(id, False)
'Set "subclass" property') menu.Append(pullDownMenu.ID_SUBCLASS, 'Subclass...',
'Set "subclass" property')
menu.AppendSeparator() menu.AppendSeparator()
# Not using standart IDs because we don't want to show shortcuts # Not using standart IDs because we don't want to show shortcuts
menu.Append(wx.ID_CUT, 'Cut', 'Cut to the clipboard') menu.Append(wx.ID_CUT, 'Cut', 'Cut to the clipboard')
@@ -1165,9 +1214,25 @@ class XML_Tree(wx.TreeCtrl):
# Item width may have changed # Item width may have changed
# !!! Tric to update tree width (wxGTK, ??) # !!! Tric to update tree width (wxGTK, ??)
self.SetIndent(self.GetIndent()) self.SetIndent(self.GetIndent())
elif xxx.className == 'comment':
self.SetItemText(item, xxx.treeName())
# Change tree icon for sizers # Change tree icon for sizers
if isinstance(xxx, xxxBoxSizer): if isinstance(xxx, xxxBoxSizer):
self.SetItemImage(item, xxx.treeImage()) self.SetItemImage(item, xxx.treeImage())
# Set global modified state # Set global modified state
g.frame.SetModified() g.frame.SetModified()
def OnBeginLabelEdit(self, evt):
xxx = self.GetPyData(evt.GetItem())
if xxx.isElement:
evt.Veto()
else:
evt.Skip()
def OnEndLabelEdit(self, evt):
xxx = self.GetPyData(evt.GetItem())
node = xxx.node
if not xxx.isElement:
node.data = evt.GetLabel()
g.panel.SetData(xxx)
evt.Skip()

View File

@@ -134,11 +134,11 @@ class UndoReplace:
item = g.tree.ItemAtFullIndex(self.itemIndex) item = g.tree.ItemAtFullIndex(self.itemIndex)
xxx = g.tree.GetPyData(item) xxx = g.tree.GetPyData(item)
# Replace with old element # Replace with old element
parent = xxx.parent.element parent = xxx.parent.node
if xxx is self.xxx: # sizeritem or notebookpage - replace child if xxx is self.xxx: # sizeritem or notebookpage - replace child
parent.replaceChild(self.xxx.child.element, xxx.child.element) parent.replaceChild(self.xxx.child.node, xxx.child.node)
else: else:
parent.replaceChild(self.xxx.element, xxx.element) parent.replaceChild(self.xxx.node, xxx.node)
self.xxx.parent = xxx.parent self.xxx.parent = xxx.parent
xxx = self.xxx xxx = self.xxx
g.tree.SetPyData(item, xxx) g.tree.SetPyData(item, xxx)
@@ -191,9 +191,9 @@ class UndoMove:
((parent.isSizer and not isinstance(xxx, xxxSizerItem)) or \ ((parent.isSizer and not isinstance(xxx, xxxSizerItem)) or \
(isinstance(parent, xxxNotebook) and not isinstance(xxx, xxxNotebookPage)) or \ (isinstance(parent, xxxNotebook) and not isinstance(xxx, xxxNotebookPage)) or \
not (parent.isSizer or isinstance(parent, xxxNotebook))): not (parent.isSizer or isinstance(parent, xxxNotebook))):
elem.removeChild(xxx.child.element) # detach child elem.removeChild(xxx.child.node) # detach child
elem.unlink() # delete child container elem.unlink() # delete child container
elem = xxx.child.element # replace elem = xxx.child.node # replace
# This may help garbage collection # This may help garbage collection
xxx.child.parent = None xxx.child.parent = None
isChildContainer = False isChildContainer = False
@@ -227,9 +227,9 @@ class UndoMove:
((parent.isSizer and not isinstance(xxx, xxxSizerItem)) or \ ((parent.isSizer and not isinstance(xxx, xxxSizerItem)) or \
(isinstance(parent, xxxNotebook) and not isinstance(xxx, xxxNotebookPage)) or \ (isinstance(parent, xxxNotebook) and not isinstance(xxx, xxxNotebookPage)) or \
not (parent.isSizer or isinstance(parent, xxxNotebook))): not (parent.isSizer or isinstance(parent, xxxNotebook))):
elem.removeChild(xxx.child.element) # detach child elem.removeChild(xxx.child.node) # detach child
elem.unlink() # delete child container elem.unlink() # delete child container
elem = xxx.child.element # replace elem = xxx.child.node # replace
# This may help garbage collection # This may help garbage collection
xxx.child.parent = None xxx.child.parent = None
isChildContainer = False isChildContainer = False

View File

@@ -40,9 +40,14 @@ if __name__ == '__main__':
else: else:
basePath = os.path.dirname(__file__) basePath = os.path.dirname(__file__)
# Remember system path
sys_path = sys.path
# 1 adds CMD command to Help menu # 1 adds CMD command to Help menu
debug = 0 debug = 0
import xxx
g.helpText = """\ g.helpText = """\
<HTML><H2>Welcome to XRC<font color="blue">ed</font></H2><H3><font color="green">DON'T PANIC :)</font></H3> <HTML><H2>Welcome to XRC<font color="blue">ed</font></H2><H3><font color="green">DON'T PANIC :)</font></H3>
Read this note before clicking on anything!<P> Read this note before clicking on anything!<P>
@@ -51,7 +56,7 @@ select "Append Child", and then any command.<P>
Or just press one of the buttons on the tools palette.<P> Or just press one of the buttons on the tools palette.<P>
Enter XML ID, change properties, create children.<P> Enter XML ID, change properties, create children.<P>
To test your interface select Test command (View menu).<P> To test your interface select Test command (View menu).<P>
Consult README file for the details.</HTML> Consult README.txt file for the details.</HTML>
""" """
defaultIDs = {xxxPanel:'PANEL', xxxDialog:'DIALOG', xxxFrame:'FRAME', defaultIDs = {xxxPanel:'PANEL', xxxDialog:'DIALOG', xxxFrame:'FRAME',
@@ -71,13 +76,13 @@ class ScrolledMessageDialog(wx.Dialog):
wx.DefaultSize, wx.TE_MULTILINE | wx.TE_READONLY) wx.DefaultSize, wx.TE_MULTILINE | wx.TE_READONLY)
text.SetFont(g.modernFont()) text.SetFont(g.modernFont())
dc = wx.WindowDC(text) dc = wx.WindowDC(text)
# !!! possible bug - GetTextExtent without font returns sysfont dims
w, h = dc.GetFullTextExtent(' ', g.modernFont())[:2] w, h = dc.GetFullTextExtent(' ', g.modernFont())[:2]
ok = wx.Button(self, wx.ID_OK, "OK") ok = wx.Button(self, wx.ID_OK, "OK")
ok.SetDefault()
text.SetConstraints(Layoutf('t=t5#1;b=t5#2;l=l5#1;r=r5#1', (self,ok))) text.SetConstraints(Layoutf('t=t5#1;b=t5#2;l=l5#1;r=r5#1', (self,ok)))
text.SetSize((w * 80 + 30, h * 40)) text.SetSize((w * 80 + 30, h * 40))
text.ShowPosition(1) text.ShowPosition(1) # scroll to the first line
ok.SetConstraints(Layoutf('b=b5#1;x%w50#1;w!80;h!25', (self,))) ok.SetConstraints(Layoutf('b=b5#1;x%w50#1;w!80;h!35', (self,)))
self.SetAutoLayout(True) self.SetAutoLayout(True)
self.Fit() self.Fit()
self.CenterOnScreen(wx.BOTH) self.CenterOnScreen(wx.BOTH)
@@ -102,7 +107,7 @@ class Frame(wx.Frame):
self.inIdle = False self.inIdle = False
# Load our own resources # Load our own resources
self.res = xrc.XmlResource('') self.res = xrc.EmptyXmlResource()
# !!! Blocking of assert failure occurring in older unicode builds # !!! Blocking of assert failure occurring in older unicode builds
try: try:
quietlog = wx.LogNull() quietlog = wx.LogNull()
@@ -127,6 +132,9 @@ class Frame(wx.Frame):
menu.Append(self.ID_GENERATE_PYTHON, '&Generate Python...', menu.Append(self.ID_GENERATE_PYTHON, '&Generate Python...',
'Generate a Python module that uses this XRC') 'Generate a Python module that uses this XRC')
menu.AppendSeparator() menu.AppendSeparator()
self.ID_PREFS = wx.NewId()
menu.Append(self.ID_PREFS, 'Preferences...', 'Change XRCed settings')
menu.AppendSeparator()
menu.Append(wx.ID_EXIT, '&Quit\tCtrl-Q', 'Exit application') menu.Append(wx.ID_EXIT, '&Quit\tCtrl-Q', 'Exit application')
menuBar.Append(menu, '&File') menuBar.Append(menu, '&File')
@@ -161,11 +169,11 @@ class Frame(wx.Frame):
self.ID_REFRESH = wx.NewId() self.ID_REFRESH = wx.NewId()
menu.Append(self.ID_REFRESH, '&Refresh\tCtrl-R', 'Refresh test window') menu.Append(self.ID_REFRESH, '&Refresh\tCtrl-R', 'Refresh test window')
self.ID_AUTO_REFRESH = wx.NewId() self.ID_AUTO_REFRESH = wx.NewId()
menu.Append(self.ID_AUTO_REFRESH, '&Auto-refresh\tCtrl-A', menu.Append(self.ID_AUTO_REFRESH, '&Auto-refresh\tAlt-A',
'Toggle auto-refresh mode', True) 'Toggle auto-refresh mode', True)
menu.Check(self.ID_AUTO_REFRESH, conf.autoRefresh) menu.Check(self.ID_AUTO_REFRESH, conf.autoRefresh)
self.ID_TEST_HIDE = wx.NewId() self.ID_TEST_HIDE = wx.NewId()
menu.Append(self.ID_TEST_HIDE, '&Hide\tCtrl-H', 'Close test window') menu.Append(self.ID_TEST_HIDE, '&Hide\tF6', 'Close test window')
menuBar.Append(menu, '&View') menuBar.Append(menu, '&View')
menu = wx.Menu() menu = wx.Menu()
@@ -182,7 +190,7 @@ class Frame(wx.Frame):
menu = wx.Menu() menu = wx.Menu()
menu.Append(wx.ID_ABOUT, '&About...', 'About XCRed') menu.Append(wx.ID_ABOUT, '&About...', 'About XCRed')
self.ID_README = wx.NewId() self.ID_README = wx.NewId()
menu.Append(self.ID_README, '&Readme...', 'View the README file') menu.Append(self.ID_README, '&Readme...\tF1', 'View the README file')
if debug: if debug:
self.ID_DEBUG_CMD = wx.NewId() self.ID_DEBUG_CMD = wx.NewId()
menu.Append(self.ID_DEBUG_CMD, 'CMD', 'Python command line') menu.Append(self.ID_DEBUG_CMD, 'CMD', 'Python command line')
@@ -247,6 +255,7 @@ class Frame(wx.Frame):
wx.EVT_MENU(self, wx.ID_SAVE, self.OnSaveOrSaveAs) wx.EVT_MENU(self, wx.ID_SAVE, self.OnSaveOrSaveAs)
wx.EVT_MENU(self, wx.ID_SAVEAS, self.OnSaveOrSaveAs) wx.EVT_MENU(self, wx.ID_SAVEAS, self.OnSaveOrSaveAs)
wx.EVT_MENU(self, self.ID_GENERATE_PYTHON, self.OnGeneratePython) wx.EVT_MENU(self, self.ID_GENERATE_PYTHON, self.OnGeneratePython)
wx.EVT_MENU(self, self.ID_PREFS, self.OnPrefs)
wx.EVT_MENU(self, wx.ID_EXIT, self.OnExit) wx.EVT_MENU(self, wx.ID_EXIT, self.OnExit)
# Edit # Edit
wx.EVT_MENU(self, wx.ID_UNDO, self.OnUndo) wx.EVT_MENU(self, wx.ID_UNDO, self.OnUndo)
@@ -311,11 +320,10 @@ class Frame(wx.Frame):
tree.RegisterKeyEvents() tree.RegisterKeyEvents()
# !!! frame styles are broken # Miniframe for split mode
# Miniframe for not embedded mode miniFrame = wx.MiniFrame(self, -1, 'Properties & Style',
miniFrame = wx.Frame(self, -1, 'Properties & Style', (conf.panelX, conf.panelY),
(conf.panelX, conf.panelY), (conf.panelWidth, conf.panelHeight))
(conf.panelWidth, conf.panelHeight))
self.miniFrame = miniFrame self.miniFrame = miniFrame
sizer2 = wx.BoxSizer() sizer2 = wx.BoxSizer()
miniFrame.SetAutoLayout(True) miniFrame.SetAutoLayout(True)
@@ -337,9 +345,6 @@ class Frame(wx.Frame):
self.SetAutoLayout(True) self.SetAutoLayout(True)
self.SetSizer(sizer) self.SetSizer(sizer)
# Initialize
self.Clear()
# Other events # Other events
wx.EVT_IDLE(self, self.OnIdle) wx.EVT_IDLE(self, self.OnIdle)
wx.EVT_CLOSE(self, self.OnCloseWindow) wx.EVT_CLOSE(self, self.OnCloseWindow)
@@ -471,7 +476,18 @@ class Frame(wx.Frame):
dlg = PythonOptions(self, conf.localconf, self.dataFile) dlg = PythonOptions(self, conf.localconf, self.dataFile)
dlg.ShowModal() dlg.ShowModal()
dlg.Destroy() dlg.Destroy()
def OnPrefs(self, evt):
dlg = PrefsDialog(self)
if dlg.ShowModal() == wx.ID_OK:
# Fetch new preferences
for id,cdp in dlg.checkControls.items():
c,d,p = cdp
if dlg.FindWindowById(id).IsChecked():
d[p] = str(c.GetValue())
elif p in d: del d[p]
g.conf.allowExec = ('ask', 'yes', 'no')[dlg.radio_allow_exec.GetSelection()]
dlg.Destroy()
def OnExit(self, evt): def OnExit(self, evt):
self.Close() self.Close()
@@ -480,20 +496,28 @@ class Frame(wx.Frame):
# Extra check to not mess with idle updating # Extra check to not mess with idle updating
if undoMan.CanUndo(): if undoMan.CanUndo():
undoMan.Undo() undoMan.Undo()
g.panel.SetModified(False)
if not undoMan.CanUndo():
self.SetModified(False)
def OnRedo(self, evt): def OnRedo(self, evt):
if undoMan.CanRedo(): if undoMan.CanRedo():
undoMan.Redo() undoMan.Redo()
self.SetModified(True)
def OnCopy(self, evt): def OnCopy(self, evt):
selected = tree.selection selected = tree.selection
if not selected: return # key pressed event if not selected: return # key pressed event
xxx = tree.GetPyData(selected) xxx = tree.GetPyData(selected)
if wx.TheClipboard.Open(): if wx.TheClipboard.Open():
data = wx.CustomDataObject('XRCED') if xxx.isElement:
# Set encoding in header data = wx.CustomDataObject('XRCED')
# (False,True) # Set encoding in header
s = xxx.element.toxml(encoding=expat.native_encoding) # (False,True)
s = xxx.node.toxml(encoding=expat.native_encoding)
else:
data = wx.CustomDataObject('XRCED_node')
s = xxx.node.data
data.SetData(cPickle.dumps(s)) data.SetData(cPickle.dumps(s))
wx.TheClipboard.SetData(data) wx.TheClipboard.SetData(data)
wx.TheClipboard.Close() wx.TheClipboard.Close()
@@ -528,21 +552,35 @@ class Frame(wx.Frame):
parent = tree.GetPyData(parentLeaf).treeObject() parent = tree.GetPyData(parentLeaf).treeObject()
# Create a copy of clipboard pickled element # Create a copy of clipboard pickled element
success = False success = success_node = False
if wx.TheClipboard.Open(): if wx.TheClipboard.Open():
data = wx.CustomDataObject('XRCED') try:
if wx.TheClipboard.IsSupported(data.GetFormat()): data = wx.CustomDataObject('XRCED')
success = wx.TheClipboard.GetData(data) if wx.TheClipboard.IsSupported(data.GetFormat()):
wx.TheClipboard.Close() try:
success = wx.TheClipboard.GetData(data)
except:
# there is a problem if XRCED_node is in clipboard
# but previous SetData was for XRCED
pass
if not success: # try other format
data = wx.CustomDataObject('XRCED_node')
if wx.TheClipboard.IsSupported(data.GetFormat()):
success_node = wx.TheClipboard.GetData(data)
finally:
wx.TheClipboard.Close()
if not success: if not success and not success_node:
wx.MessageBox( wx.MessageBox(
"There is no data in the clipboard in the required format", "There is no data in the clipboard in the required format",
"Error") "Error")
return return
xml = cPickle.loads(data.GetData()) # xml representation of element xml = cPickle.loads(data.GetData()) # xml representation of element
elem = minidom.parseString(xml).childNodes[0] if success:
elem = minidom.parseString(xml).childNodes[0]
else:
elem = g.tree.dom.createComment(xml)
# Tempopary xxx object to test things # Tempopary xxx object to test things
xxx = MakeXXXFromDOM(parent, elem) xxx = MakeXXXFromDOM(parent, elem)
@@ -559,9 +597,9 @@ class Frame(wx.Frame):
((parent.isSizer and not isinstance(xxx, xxxSizerItem)) or \ ((parent.isSizer and not isinstance(xxx, xxxSizerItem)) or \
(parentIsBook and not isinstance(xxx, xxxPage)) or \ (parentIsBook and not isinstance(xxx, xxxPage)) or \
not (parent.isSizer or parentIsBook)): not (parent.isSizer or parentIsBook)):
elem.removeChild(xxx.child.element) # detach child elem.removeChild(xxx.child.node) # detach child
elem.unlink() # delete child container elem.unlink() # delete child container
elem = xxx.child.element # replace elem = xxx.child.node # replace
# This may help garbage collection # This may help garbage collection
xxx.child.parent = None xxx.child.parent = None
isChildContainer = False isChildContainer = False
@@ -606,6 +644,9 @@ class Frame(wx.Frame):
def ItemsAreCompatible(self, parent, child): def ItemsAreCompatible(self, parent, child):
# Check compatibility # Check compatibility
error = False error = False
# Comments are always compatible
if child.__class__ == xxxComment:
return True
# Top-level # Top-level
if child.__class__ in [xxxDialog, xxxFrame, xxxWizard]: if child.__class__ in [xxxDialog, xxxFrame, xxxWizard]:
# Top-level classes # Top-level classes
@@ -733,9 +774,9 @@ class Frame(wx.Frame):
((parent.isSizer and not isinstance(xxx, xxxSizerItem)) or \ ((parent.isSizer and not isinstance(xxx, xxxSizerItem)) or \
(isinstance(parent, xxxNotebook) and not isinstance(xxx, xxxNotebookPage)) or \ (isinstance(parent, xxxNotebook) and not isinstance(xxx, xxxNotebookPage)) or \
not (parent.isSizer or isinstance(parent, xxxNotebook))): not (parent.isSizer or isinstance(parent, xxxNotebook))):
elem.removeChild(xxx.child.element) # detach child elem.removeChild(xxx.child.node) # detach child
elem.unlink() # delete child container elem.unlink() # delete child container
elem = xxx.child.element # replace elem = xxx.child.node # replace
# This may help garbage collection # This may help garbage collection
xxx.child.parent = None xxx.child.parent = None
isChildContainer = False isChildContainer = False
@@ -790,9 +831,9 @@ class Frame(wx.Frame):
((parent.isSizer and not isinstance(xxx, xxxSizerItem)) or \ ((parent.isSizer and not isinstance(xxx, xxxSizerItem)) or \
(isinstance(parent, xxxNotebook) and not isinstance(xxx, xxxNotebookPage)) or \ (isinstance(parent, xxxNotebook) and not isinstance(xxx, xxxNotebookPage)) or \
not (parent.isSizer or isinstance(parent, xxxNotebook))): not (parent.isSizer or isinstance(parent, xxxNotebook))):
elem.removeChild(xxx.child.element) # detach child elem.removeChild(xxx.child.node) # detach child
elem.unlink() # delete child container elem.unlink() # delete child container
elem = xxx.child.element # replace elem = xxx.child.node # replace
# This may help garbage collection # This may help garbage collection
xxx.child.parent = None xxx.child.parent = None
isChildContainer = False isChildContainer = False
@@ -842,14 +883,19 @@ class Frame(wx.Frame):
# Prepare undo data # Prepare undo data
panel.Apply() panel.Apply()
index = tree.ItemFullIndex(selected) index = tree.ItemFullIndex(selected)
xxx = tree.GetPyData(selected)
parent = tree.GetPyData(tree.GetItemParent(selected)).treeObject() parent = tree.GetPyData(tree.GetItemParent(selected)).treeObject()
elem = tree.RemoveLeaf(selected) elem = tree.RemoveLeaf(selected)
undoMan.RegisterUndo(UndoCutDelete(index, parent, elem)) undoMan.RegisterUndo(UndoCutDelete(index, parent, elem))
if evt.GetId() == wx.ID_CUT: if evt.GetId() == wx.ID_CUT:
if wx.TheClipboard.Open(): if wx.TheClipboard.Open():
data = wx.CustomDataObject('XRCED') if xxx.isElement:
# (False, True) data = wx.CustomDataObject('XRCED')
s = elem.toxml(encoding=expat.native_encoding) # (False, True)
s = elem.toxml(encoding=expat.native_encoding)
else:
data = wx.CustomDataObject('XRCED_node')
s = xxx.node.data
data.SetData(cPickle.dumps(s)) data.SetData(cPickle.dumps(s))
wx.TheClipboard.SetData(data) wx.TheClipboard.SetData(data)
wx.TheClipboard.Close() wx.TheClipboard.Close()
@@ -867,7 +913,7 @@ class Frame(wx.Frame):
def OnSubclass(self, evt): def OnSubclass(self, evt):
selected = tree.selection selected = tree.selection
xxx = tree.GetPyData(selected).treeObject() xxx = tree.GetPyData(selected).treeObject()
elem = xxx.element elem = xxx.node
subclass = xxx.subclass subclass = xxx.subclass
dlg = wx.TextEntryDialog(self, 'Subclass:', defaultValue=subclass) dlg = wx.TextEntryDialog(self, 'Subclass:', defaultValue=subclass)
if dlg.ShowModal() == wx.ID_OK: if dlg.ShowModal() == wx.ID_OK:
@@ -910,6 +956,7 @@ class Frame(wx.Frame):
self.miniFrame.Show(True) self.miniFrame.Show(True)
self.miniFrame.SetDimensions(conf.panelX, conf.panelY, self.miniFrame.SetDimensions(conf.panelX, conf.panelY,
conf.panelWidth, conf.panelHeight) conf.panelWidth, conf.panelHeight)
self.miniFrame.Layout()
# Reduce width # Reduce width
self.SetDimensions(pos.x, pos.y, self.SetDimensions(pos.x, pos.y,
max(size.width - sizePanel.width, self.minWidth), size.height) max(size.width - sizePanel.width, self.minWidth), size.height)
@@ -1063,29 +1110,36 @@ Homepage: http://xrced.sourceforge.net\
ref = wx.GetTextFromUser('Create reference to:', 'Create reference') ref = wx.GetTextFromUser('Create reference to:', 'Create reference')
if not ref: return if not ref: return
xxx = MakeEmptyRefXXX(parent, ref) xxx = MakeEmptyRefXXX(parent, ref)
elif evt.GetId() == ID_NEW.COMMENT:
xxx = MakeEmptyCommentXXX(parent)
else: else:
# Create empty element # Create empty element
className = pullDownMenu.createMap[evt.GetId()] if evt.GetId() >= ID_NEW.CUSTOM:
className = pullDownMenu.customMap[evt.GetId()]
else:
className = pullDownMenu.createMap[evt.GetId()]
xxx = MakeEmptyXXX(parent, className) xxx = MakeEmptyXXX(parent, className)
# Set default name for top-level windows
if parent.__class__ == xxxMainNode:
cl = xxx.treeObject().__class__
frame.maxIDs[cl] += 1
xxx.setTreeName('%s%d' % (defaultIDs[cl], frame.maxIDs[cl]))
# And for some other standard controls
elif parent.__class__ == xxxStdDialogButtonSizer:
xxx.setTreeName(pullDownMenu.stdButtonIDs[evt.GetId()][0])
# We can even set label
obj = xxx.treeObject()
elem = g.tree.dom.createElement('label')
elem.appendChild(g.tree.dom.createTextNode(pullDownMenu.stdButtonIDs[evt.GetId()][1]))
obj.params['label'] = xxxParam(elem)
xxx.treeObject().element.appendChild(elem)
# Insert new node, register undo # Insert new node, register undo
elem = xxx.element if xxx.isElement: # true object
newItem = tree.InsertNode(parentLeaf, parent, elem, nextItem) # Set default name for top-level windows
if parent.__class__ == xxxMainNode:
cl = xxx.treeObject().__class__
frame.maxIDs[cl] += 1
xxx.setTreeName('%s%d' % (defaultIDs[cl], frame.maxIDs[cl]))
# And for some other standard controls
elif parent.__class__ == xxxStdDialogButtonSizer:
xxx.setTreeName(pullDownMenu.stdButtonIDs[evt.GetId()][0])
# We can even set label
obj = xxx.treeObject()
elem = g.tree.dom.createElement('label')
elem.appendChild(g.tree.dom.createTextNode(pullDownMenu.stdButtonIDs[evt.GetId()][1]))
obj.params['label'] = xxxParam(elem)
xxx.treeObject().node.appendChild(elem)
newItem = tree.InsertNode(parentLeaf, parent, xxx.node, nextItem)
else: # comment node
newItem = tree.InsertNode(parentLeaf, parent, xxx.node, nextItem)
undoMan.RegisterUndo(UndoPasteCreate(parentLeaf, parent, newItem, selected)) undoMan.RegisterUndo(UndoPasteCreate(parentLeaf, parent, newItem, selected))
tree.EnsureVisible(newItem) tree.EnsureVisible(newItem)
tree.SelectItem(newItem) tree.SelectItem(newItem)
@@ -1093,20 +1147,22 @@ Homepage: http://xrced.sourceforge.net\
tree.ScrollTo(newItem) tree.ScrollTo(newItem)
tree.Refresh() tree.Refresh()
# Update view? # Update view?
if g.testWin and tree.IsHighlatable(newItem): if xxx.isElement and g.testWin and tree.IsHighlatable(newItem):
if conf.autoRefresh: if conf.autoRefresh:
tree.needUpdate = True tree.needUpdate = True
tree.pendingHighLight = newItem tree.pendingHighLight = newItem
else: else:
tree.pendingHighLight = None tree.pendingHighLight = None
tree.SetFocus() tree.SetFocus()
if not xxx.isElement:
tree.EditLabel(newItem)
self.SetModified() self.SetModified()
# Replace one object with another # Replace one object with another
def OnReplace(self, evt): def OnReplace(self, evt):
selected = tree.selection selected = tree.selection
xxx = tree.GetPyData(selected).treeObject() xxx = tree.GetPyData(selected).treeObject()
elem = xxx.element elem = xxx.node
parent = elem.parentNode parent = elem.parentNode
undoMan.RegisterUndo(UndoReplace(selected)) undoMan.RegisterUndo(UndoReplace(selected))
# New class # New class
@@ -1285,14 +1341,18 @@ Homepage: http://xrced.sourceforge.net\
return return
def OnIconize(self, evt): def OnIconize(self, evt):
conf.x, conf.y = self.GetPosition() if evt.Iconized():
conf.width, conf.height = self.GetSize() conf.x, conf.y = self.GetPosition()
if conf.embedPanel: conf.width, conf.height = self.GetSize()
conf.sashPos = self.splitter.GetSashPosition() if conf.embedPanel:
conf.sashPos = self.splitter.GetSashPosition()
else:
conf.panelX, conf.panelY = self.miniFrame.GetPosition()
conf.panelWidth, conf.panelHeight = self.miniFrame.GetSize()
self.miniFrame.Iconize()
else: else:
conf.panelX, conf.panelY = self.miniFrame.GetPosition() if not conf.embedPanel:
conf.panelWidth, conf.panelHeight = self.miniFrame.GetSize() self.miniFrame.Iconize(False)
self.miniFrame.Iconize()
evt.Skip() evt.Skip()
def OnCloseWindow(self, evt): def OnCloseWindow(self, evt):
@@ -1313,13 +1373,11 @@ Homepage: http://xrced.sourceforge.net\
conf.panelWidth, conf.panelHeight = self.miniFrame.GetSize() conf.panelWidth, conf.panelHeight = self.miniFrame.GetSize()
evt.Skip() evt.Skip()
def CreateLocalConf(self, path): def CreateLocalConf(self, path):
name = os.path.splitext(path)[0] name = os.path.splitext(path)[0]
name += '.xcfg' name += '.xcfg'
return wx.FileConfig(localFilename=name) return wx.FileConfig(localFilename=name)
def Clear(self): def Clear(self):
self.dataFile = '' self.dataFile = ''
conf.localconf = None conf.localconf = None
@@ -1336,6 +1394,13 @@ Homepage: http://xrced.sourceforge.net\
xxxMenuBar, xxxMenu, xxxToolBar, xxxMenuBar, xxxMenu, xxxToolBar,
xxxWizard, xxxBitmap, xxxIcon]: xxxWizard, xxxBitmap, xxxIcon]:
self.maxIDs[cl] = 0 self.maxIDs[cl] = 0
# Restore handlers, menu, etc. to initial
setHandlers(self.handlers[:])
g.pullDownMenu.custom = self.custom[:]
# Remove modules imported from comment directives
map(sys.modules.pop, [m for m in sys.modules if m not in self.modules])
xxxParamComment.locals = {} # clear local namespace
xxxParamComment.allow = None # clear execution state
def SetModified(self, state=True): def SetModified(self, state=True):
self.modified = state self.modified = state
@@ -1366,6 +1431,8 @@ Homepage: http://xrced.sourceforge.net\
self.dataFile = path = os.path.abspath(path) self.dataFile = path = os.path.abspath(path)
dir = os.path.dirname(path) dir = os.path.dirname(path)
if dir: os.chdir(dir) if dir: os.chdir(dir)
# Allow importing modules from the same directory
sys.path = sys_path + [dir]
tree.SetData(dom) tree.SetData(dom)
self.SetTitle(progname + ': ' + os.path.basename(path)) self.SetTitle(progname + ': ' + os.path.basename(path))
conf.localconf = self.CreateLocalConf(self.dataFile) conf.localconf = self.CreateLocalConf(self.dataFile)
@@ -1379,6 +1446,10 @@ Homepage: http://xrced.sourceforge.net\
return True return True
def Indent(self, node, indent = 0): def Indent(self, node, indent = 0):
if node.nodeType == minidom.Node.COMMENT_NODE:
text = self.domCopy.createTextNode('\n' + ' ' * indent)
node.parentNode.insertBefore(text, node)
return # no children
# Copy child list because it will change soon # Copy child list because it will change soon
children = node.childNodes[:] children = node.childNodes[:]
# Main node doesn't need to be indented # Main node doesn't need to be indented
@@ -1392,7 +1463,8 @@ Homepage: http://xrced.sourceforge.net\
node.appendChild(text) node.appendChild(text)
# Indent children which are elements # Indent children which are elements
for n in children: for n in children:
if n.nodeType == minidom.Node.ELEMENT_NODE: if n.nodeType == minidom.Node.ELEMENT_NODE or \
n.nodeType == minidom.Node.COMMENT_NODE:
self.Indent(n, indent + 2) self.Indent(n, indent + 2)
def Save(self, path): def Save(self, path):
@@ -1446,9 +1518,6 @@ Homepage: http://xrced.sourceforge.net\
return True return True
return False return False
def SaveUndo(self):
pass # !!!
################################################################################ ################################################################################
class PythonOptions(wx.Dialog): class PythonOptions(wx.Dialog):
@@ -1515,14 +1584,88 @@ class PythonOptions(wx.Dialog):
self.EndModal(wx.ID_OK) self.EndModal(wx.ID_OK)
################################################################################ ################################################################################
class PrefsDialog(wx.Dialog):
def __init__(self, parent):
pre = wx.PreDialog()
g.frame.res.LoadOnDialog(pre, parent, "DIALOG_PREFS")
self.PostCreate(pre)
self.checkControls = {} # map of check IDs to (control,dict,param)
xxx = sys.modules['xxx']
d = xxx.xxxSizerItem.defaults_panel
self.check_proportion_panel = xrc.XRCCTRL(self, 'check_proportion_panel')
id = self.check_proportion_panel.GetId()
wx.EVT_CHECKBOX(self, id, self.OnCheck)
self.checkControls[id] = (xrc.XRCCTRL(self, 'spin_proportion_panel'),
d, 'option')
self.check_flag_panel = xrc.XRCCTRL(self, 'check_flag_panel')
id = self.check_flag_panel.GetId()
wx.EVT_CHECKBOX(self, id, self.OnCheck)
self.checkControls[id] = (xrc.XRCCTRL(self, 'text_flag_panel'),
d, 'flag')
d = xxx.xxxSizerItem.defaults_control
self.check_proportion_panel = xrc.XRCCTRL(self, 'check_proportion_control')
id = self.check_proportion_panel.GetId()
wx.EVT_CHECKBOX(self, id, self.OnCheck)
self.checkControls[id] = (xrc.XRCCTRL(self, 'spin_proportion_control'),
d, 'option')
self.check_flag_panel = xrc.XRCCTRL(self, 'check_flag_control')
id = self.check_flag_panel.GetId()
wx.EVT_CHECKBOX(self, id, self.OnCheck)
self.checkControls[id] = (xrc.XRCCTRL(self, 'text_flag_control'),
d, 'flag')
for id,cdp in self.checkControls.items():
c,d,p = cdp
try:
if isinstance(c, wx.SpinCtrl):
c.SetValue(int(d[p]))
else:
c.SetValue(d[p])
self.FindWindowById(id).SetValue(True)
except KeyError:
c.Enable(False)
self.radio_allow_exec = xrc.XRCCTRL(self, 'radio_allow_exec')
try:
radio = {'ask': 0, 'yes':1, 'no':2}[g.conf.allowExec]
except KeyError:
radio = 0
self.radio_allow_exec.SetSelection(radio)
def OnCheck(self, evt):
self.checkControls[evt.GetId()][0].Enable(evt.IsChecked())
evt.Skip()
################################################################################
# Parse string in form var1=val1[,var2=val2]* as dictionary
def ReadDictFromString(s):
d = {}
for vv in s.split(','):
var,val = vv.split(':')
d[var.strip()] = val
return d
# Transform dictionary with strings into one string
def DictToString(d):
return ','.join(map(':'.join, d.items()))
def usage(): def usage():
print >> sys.stderr, 'usage: xrced [-dhiv] [file]' print >> sys.stderr, 'usage: xrced [-dhiv] [file]'
class App(wx.App): from wx.lib.mixins.inspection import InspectableApp
class App(InspectableApp):
def OnInit(self): def OnInit(self):
self.Init()
# Check version # Check version
if wx.VERSION[:3] < MinWxVersion: if wx.VERSION[:3] < MinWxVersion:
wx.LogWarning('''\ wx.LogWarning('''\
@@ -1574,11 +1717,46 @@ Please upgrade wxWidgets to %d.%d.%d or higher.''' % MinWxVersion)
conf.panelWidth = conf.ReadInt('panelWidth', 200) conf.panelWidth = conf.ReadInt('panelWidth', 200)
conf.panelHeight = conf.ReadInt('panelHeight', 200) conf.panelHeight = conf.ReadInt('panelHeight', 200)
conf.panic = not conf.HasEntry('nopanic') conf.panic = not conf.HasEntry('nopanic')
# Preferences
conf.allowExec = conf.Read('Prefs/allowExec', 'ask')
p = 'Prefs/sizeritem_defaults_panel'
if conf.HasEntry(p):
sys.modules['xxx'].xxxSizerItem.defaults_panel = ReadDictFromString(conf.Read(p))
p = 'Prefs/sizeritem_defaults_control'
if conf.HasEntry(p):
sys.modules['xxx'].xxxSizerItem.defaults_control = ReadDictFromString(conf.Read(p))
# Add handlers # Add handlers
wx.FileSystem.AddHandler(wx.MemoryFSHandler()) wx.FileSystem.AddHandler(wx.MemoryFSHandler())
# Create main frame # Create main frame
frame = Frame(pos, size) frame = Frame(pos, size)
frame.Show(True) frame.Show(True)
# Load plugins
plugins = os.getenv('XRCEDPATH')
if plugins:
cwd = os.getcwd()
try:
for dir in plugins.split(':'):
if os.path.isdir(dir) and \
os.path.isfile(os.path.join(dir, '__init__.py')):
# Normalize
dir = os.path.abspath(os.path.normpath(dir))
sys.path = sys_path + [os.path.dirname(dir)]
try:
os.chdir(dir)
__import__(os.path.basename(dir), globals(), locals(), ['*'])
except:
print traceback.print_exc()
finally:
os.chdir(cwd)
# Store important data
frame.handlers = getHandlers()[:]
frame.custom = g.pullDownMenu.custom[:]
frame.modules = set(sys.modules.keys())
# Initialize
frame.Clear()
# Load file after showing # Load file after showing
if args: if args:
@@ -1604,8 +1782,16 @@ Please upgrade wxWidgets to %d.%d.%d or higher.''' % MinWxVersion)
wc.WriteInt('sashPos', conf.sashPos) wc.WriteInt('sashPos', conf.sashPos)
wc.WriteInt('panelWidth', conf.panelWidth) wc.WriteInt('panelWidth', conf.panelWidth)
wc.WriteInt('panelHeight', conf.panelHeight) wc.WriteInt('panelHeight', conf.panelHeight)
wc.WriteInt('nopanic', True) wc.WriteInt('nopanic', 1)
wc.Write('recentFiles', '|'.join(conf.recentfiles.values()[-5:])) wc.Write('recentFiles', '|'.join(conf.recentfiles.values()[-5:]))
# Preferences
wc.DeleteGroup('Prefs')
wc.Write('Prefs/allowExec', conf.allowExec)
v = sys.modules['xxx'].xxxSizerItem.defaults_panel
if v: wc.Write('Prefs/sizeritem_defaults_panel', DictToString(v))
v = sys.modules['xxx'].xxxSizerItem.defaults_control
if v: wc.Write('Prefs/sizeritem_defaults_control', DictToString(v))
wc.Flush() wc.Flush()
def main(): def main():

View File

@@ -10,6 +10,7 @@
<orient>wxHORIZONTAL</orient> <orient>wxHORIZONTAL</orient>
<object class="sizeritem"> <object class="sizeritem">
<object class="wxTextCtrl" name="TEXT"> <object class="wxTextCtrl" name="TEXT">
<value></value>
<size>250,100</size> <size>250,100</size>
<style>wxTE_MULTILINE</style> <style>wxTE_MULTILINE</style>
</object> </object>
@@ -22,23 +23,17 @@
<flag>wxEXPAND</flag> <flag>wxEXPAND</flag>
</object> </object>
<object class="sizeritem"> <object class="sizeritem">
<object class="wxStaticLine"/> <object class="wxStdDialogButtonSizer">
<flag>wxEXPAND</flag> <object class="button">
</object>
<object class="sizeritem">
<object class="wxBoxSizer">
<orient>wxHORIZONTAL</orient>
<object class="sizeritem">
<object class="wxButton" name="wxID_OK"> <object class="wxButton" name="wxID_OK">
<label>OK</label> <label></label>
<default>1</default> <label>&amp;Ok</label>
</object> </object>
<flag>wxRIGHT</flag>
<border>10</border>
</object> </object>
<object class="sizeritem"> <object class="button">
<object class="wxButton" name="wxID_CANCEL"> <object class="wxButton" name="wxID_CANCEL">
<label>Cancel</label> <label></label>
<label>&amp;Cancel</label>
</object> </object>
</object> </object>
</object> </object>
@@ -191,24 +186,21 @@
<option>1</option> <option>1</option>
<flag>wxEXPAND</flag> <flag>wxEXPAND</flag>
</object> </object>
<object class="sizeritem"> <object class="spacer">
<object class="wxStaticLine"/> <size>0,10</size>
<flag>wxEXPAND</flag>
</object> </object>
<object class="sizeritem"> <object class="sizeritem">
<object class="wxBoxSizer"> <object class="wxStdDialogButtonSizer">
<orient>wxHORIZONTAL</orient> <object class="button">
<object class="sizeritem">
<object class="wxButton" name="wxID_OK"> <object class="wxButton" name="wxID_OK">
<label>OK</label> <label></label>
<default>1</default> <label>&amp;Ok</label>
</object> </object>
<flag>wxRIGHT</flag>
<border>10</border>
</object> </object>
<object class="sizeritem"> <object class="button">
<object class="wxButton" name="wxID_CANCEL"> <object class="wxButton" name="wxID_CANCEL">
<label>Cancel</label> <label></label>
<label>&amp;Cancel</label>
</object> </object>
</object> </object>
</object> </object>
@@ -233,24 +225,21 @@
<flag>wxALL|wxEXPAND</flag> <flag>wxALL|wxEXPAND</flag>
<border>5</border> <border>5</border>
</object> </object>
<object class="sizeritem"> <object class="spacer">
<object class="wxStaticLine"/> <size>0,10</size>
<flag>wxEXPAND</flag>
</object> </object>
<object class="sizeritem"> <object class="sizeritem">
<object class="wxBoxSizer"> <object class="wxStdDialogButtonSizer">
<orient>wxHORIZONTAL</orient> <object class="button">
<object class="sizeritem">
<object class="wxButton" name="wxID_OK"> <object class="wxButton" name="wxID_OK">
<label>OK</label> <label></label>
<default>1</default> <label>&amp;Ok</label>
</object> </object>
<flag>wxRIGHT</flag>
<border>10</border>
</object> </object>
<object class="sizeritem"> <object class="button">
<object class="wxButton" name="wxID_CANCEL"> <object class="wxButton" name="wxID_CANCEL">
<label>Cancel</label> <label></label>
<label>&amp;Cancel</label>
</object> </object>
</object> </object>
</object> </object>
@@ -261,7 +250,7 @@
<style>wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER</style> <style>wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER</style>
</object> </object>
<object class="wxDialog" name="DIALOG_STYLES"> <object class="wxDialog" name="DIALOG_STYLES">
<title>Window styles</title> <title>Window Styles</title>
<centered>1</centered> <centered>1</centered>
<object class="wxBoxSizer"> <object class="wxBoxSizer">
<orient>wxVERTICAL</orient> <orient>wxVERTICAL</orient>
@@ -299,24 +288,21 @@
<flag>wxBOTTOM|wxLEFT|wxRIGHT|wxEXPAND</flag> <flag>wxBOTTOM|wxLEFT|wxRIGHT|wxEXPAND</flag>
<border>5</border> <border>5</border>
</object> </object>
<object class="sizeritem"> <object class="spacer">
<object class="wxStaticLine"/> <size>0,10</size>
<flag>wxEXPAND</flag>
</object> </object>
<object class="sizeritem"> <object class="sizeritem">
<object class="wxBoxSizer"> <object class="wxStdDialogButtonSizer">
<orient>wxHORIZONTAL</orient> <object class="button">
<object class="sizeritem">
<object class="wxButton" name="wxID_OK"> <object class="wxButton" name="wxID_OK">
<label>OK</label> <label></label>
<default>1</default> <label>&amp;Ok</label>
</object> </object>
<flag>wxRIGHT</flag>
<border>10</border>
</object> </object>
<object class="sizeritem"> <object class="button">
<object class="wxButton" name="wxID_CANCEL"> <object class="wxButton" name="wxID_CANCEL">
<label>Cancel</label> <label></label>
<label>&amp;Cancel</label>
</object> </object>
</object> </object>
</object> </object>
@@ -350,7 +336,7 @@
<orient>wxVERTICAL</orient> <orient>wxVERTICAL</orient>
<object class="sizeritem"> <object class="sizeritem">
<object class="wxSpinCtrl" name="SPIN"> <object class="wxSpinCtrl" name="SPIN">
<size>20,-1d</size> <size>60,-1</size>
</object> </object>
<flag>wxBOTTOM</flag> <flag>wxBOTTOM</flag>
<border>5</border> <border>5</border>
@@ -381,25 +367,23 @@
</object> </object>
<option>1</option> <option>1</option>
<flag>wxEXPAND</flag> <flag>wxEXPAND</flag>
<border>0</border>
</object>
<object class="spacer">
<size>0,10</size>
</object> </object>
<object class="sizeritem"> <object class="sizeritem">
<object class="wxStaticLine"/> <object class="wxStdDialogButtonSizer">
<flag>wxEXPAND</flag> <object class="button">
</object>
<object class="sizeritem">
<object class="wxBoxSizer">
<orient>wxHORIZONTAL</orient>
<object class="sizeritem">
<object class="wxButton" name="wxID_OK"> <object class="wxButton" name="wxID_OK">
<label>OK</label> <label></label>
<default>1</default> <label>&amp;Ok</label>
</object> </object>
<flag>wxRIGHT</flag>
<border>10</border>
</object> </object>
<object class="sizeritem"> <object class="button">
<object class="wxButton" name="wxID_CANCEL"> <object class="wxButton" name="wxID_CANCEL">
<label>Cancel</label> <label></label>
<label>&amp;Cancel</label>
</object> </object>
</object> </object>
</object> </object>
@@ -619,4 +603,113 @@
</object> </object>
</object> </object>
</object> </object>
<object class="wxDialog" name="DIALOG_PREFS">
<title>XRCed Preferences</title>
<object class="wxBoxSizer">
<orient>wxVERTICAL</orient>
<object class="sizeritem">
<object class="wxStaticBoxSizer">
<label>Defaults for new containes</label>
<orient>wxVERTICAL</orient>
<object class="sizeritem">
<object class="wxFlexGridSizer">
<cols>2</cols>
<rows>2</rows>
<object class="sizeritem">
<object class="wxCheckBox" name="check_proportion_panel">
<label>proportion</label>
</object>
</object>
<object class="sizeritem">
<object class="wxSpinCtrl" name="spin_proportion_panel">
<size>50,-1</size>
</object>
</object>
<object class="sizeritem">
<object class="wxCheckBox" name="check_flag_panel">
<label>flag</label>
</object>
</object>
<object class="sizeritem">
<object class="wxTextCtrl" name="text_flag_panel">
<size>150,-1</size>
</object>
</object>
<hgap>10</hgap>
</object>
</object>
</object>
<flag>wxALL</flag>
<border>5</border>
</object>
<object class="sizeritem">
<object class="wxStaticBoxSizer">
<label>Defaults for new controls</label>
<orient>wxVERTICAL</orient>
<object class="sizeritem">
<object class="wxFlexGridSizer">
<cols>2</cols>
<rows>2</rows>
<object class="sizeritem">
<object class="wxCheckBox" name="check_proportion_control">
<label>proportion</label>
</object>
</object>
<object class="sizeritem">
<object class="wxSpinCtrl" name="spin_proportion_control">
<size>50,-1</size>
</object>
</object>
<object class="sizeritem">
<object class="wxCheckBox" name="check_flag_control">
<label>flag</label>
</object>
</object>
<object class="sizeritem">
<object class="wxTextCtrl" name="text_flag_control">
<size>150,-1</size>
</object>
</object>
<hgap>10</hgap>
</object>
</object>
</object>
<flag>wxALL</flag>
<border>5</border>
</object>
<object class="sizeritem">
<object class="wxRadioBox" name="radio_allow_exec">
<label>Execution of comment directives</label>
<content>
<item>ask</item>
<item>always</item>
<item>never</item>
</content>
</object>
<flag>wxALL|wxALIGN_CENTRE_HORIZONTAL</flag>
<border>5</border>
</object>
<object class="spacer">
<size>0,10</size>
</object>
<object class="sizeritem">
<object class="wxStdDialogButtonSizer">
<object class="button">
<object class="wxButton" name="wxID_OK">
<label></label>
<label>&amp;Ok</label>
</object>
</object>
<object class="button">
<object class="wxButton" name="wxID_CANCEL">
<label></label>
<label>&amp;Cancel</label>
</object>
</object>
</object>
<flag>wxALL|wxALIGN_CENTRE_HORIZONTAL</flag>
<border>10</border>
</object>
</object>
</object>
</resource> </resource>

View File

@@ -7,6 +7,7 @@
from xml.dom import minidom from xml.dom import minidom
from globals import * from globals import *
from params import * from params import *
import traceback, types
# Base class for interface parameter classes # Base class for interface parameter classes
class xxxNode: class xxxNode:
@@ -189,6 +190,7 @@ class xxxObject:
hasStyle = True # almost everyone hasStyle = True # almost everyone
hasName = True # has name attribute? hasName = True # has name attribute?
isSizer = hasChild = False isSizer = hasChild = False
isElement = True
allParams = None # Some nodes have no parameters allParams = None # Some nodes have no parameters
# Style parameters (all optional) # Style parameters (all optional)
styles = ['fg', 'bg', 'font', 'enabled', 'focused', 'hidden', 'tooltip'] styles = ['fg', 'bg', 'font', 'enabled', 'focused', 'hidden', 'tooltip']
@@ -210,7 +212,7 @@ class xxxObject:
# parent is parent xxx object (or None if none), element is DOM element object # parent is parent xxx object (or None if none), element is DOM element object
def __init__(self, parent, element, refElem=None): def __init__(self, parent, element, refElem=None):
self.parent = parent self.parent = parent
self.element = element self.node = element
self.refElem = refElem self.refElem = refElem
self.undo = None self.undo = None
# Reference are dereferenced # Reference are dereferenced
@@ -230,33 +232,32 @@ class xxxObject:
if self.hasName: self.name = element.getAttribute('name') if self.hasName: self.name = element.getAttribute('name')
# Set parameters (text element children) # Set parameters (text element children)
self.params = {} self.params = {}
nodes = element.childNodes[:] for n in element.childNodes[:]:
for node in nodes: if n.nodeType == minidom.Node.ELEMENT_NODE:
if node.nodeType == minidom.Node.ELEMENT_NODE: tag = n.tagName
tag = node.tagName
if tag in ['object', 'object_ref']: if tag in ['object', 'object_ref']:
continue # do nothing for object children here continue # do nothing for object children here
elif tag not in self.allParams and tag not in self.styles: elif tag not in self.allParams and tag not in self.styles:
print 'WARNING: unknown parameter for %s: %s' % \ print 'WARNING: unknown parameter for %s: %s' % \
(self.className, tag) (self.className, tag)
elif tag in self.specials: elif tag in self.specials:
self.special(tag, node) self.special(tag, n)
elif tag == 'content': elif tag == 'content':
if self.className == 'wxCheckListBox': if self.className == 'wxCheckListBox':
self.params[tag] = xxxParamContentCheckList(node) self.params[tag] = xxxParamContentCheckList(n)
else: else:
self.params[tag] = xxxParamContent(node) self.params[tag] = xxxParamContent(n)
elif tag == 'font': # has children elif tag == 'font': # has children
self.params[tag] = xxxParamFont(element, node) self.params[tag] = xxxParamFont(element, n)
elif tag in self.bitmapTags: elif tag in self.bitmapTags:
# Can have attributes # Can have attributes
self.params[tag] = xxxParamBitmap(node) self.params[tag] = xxxParamBitmap(n)
else: # simple parameter else: # simple parameter
self.params[tag] = xxxParam(node) self.params[tag] = xxxParam(n)
elif node.nodeType == minidom.Node.TEXT_NODE and node.data.isspace(): elif n.nodeType == minidom.Node.TEXT_NODE and n.data.isspace():
# Remove empty text nodes # Remove empty text nodes
element.removeChild(node) element.removeChild(n)
node.unlink() n.unlink()
# Check that all required params are set # Check that all required params are set
for param in self.required: for param in self.required:
@@ -281,9 +282,9 @@ class xxxObject:
break break
if found: if found:
nextTextElem = self.params[p].node nextTextElem = self.params[p].node
self.element.insertBefore(elem, nextTextElem) self.node.insertBefore(elem, nextTextElem)
else: else:
self.element.appendChild(elem) self.node.appendChild(elem)
else: else:
wx.LogWarning('Required parameter %s of %s missing' % wx.LogWarning('Required parameter %s of %s missing' %
(param, self.className)) (param, self.className))
@@ -313,7 +314,34 @@ class xxxObject:
if self.hasChild: obj = self.child if self.hasChild: obj = self.child
else: obj = self else: obj = self
obj.name = name obj.name = name
obj.element.setAttribute('name', name) obj.node.setAttribute('name', name)
# Set normal (text) params
def set(self, param, value):
try:
self.params[param].update(value)
except KeyError:
elem = g.tree.dom.createElement(param)
p = xxxParam(elem)
p.update(value)
self.params[param] = p
self.node.appendChild(elem)
# Special processing for growablecols-like parameters
# represented by several nodes
def special(self, tag, node):
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 = g.tree.dom.createElement(param)
text = g.tree.dom.createTextNode(str(i))
node.appendChild(text)
self.node.appendChild(node)
self.special(param, node)
# Imitation of FindResource/DoFindResource from xmlres.cpp # Imitation of FindResource/DoFindResource from xmlres.cpp
def DoFindResource(parent, name, classname, recursive): def DoFindResource(parent, name, classname, recursive):
@@ -360,7 +388,7 @@ class xxxParamFont(xxxObject, xxxNode):
self.data = v self.data = v
def update(self, value): def update(self, value):
# `value' is a list of strings corresponding to all parameters # `value' is a list of strings corresponding to all parameters
elem = self.element elem = self.node
# Remove old elements first # Remove old elements first
childNodes = elem.childNodes[:] childNodes = elem.childNodes[:]
for node in childNodes: elem.removeChild(node) for node in childNodes: elem.removeChild(node)
@@ -638,6 +666,16 @@ class xxxDateCtrl(xxxObject):
winStyles = ['wxDP_DEFAULT', 'wxDP_SPIN', 'wxDP_DROPDOWN', winStyles = ['wxDP_DEFAULT', 'wxDP_SPIN', 'wxDP_DROPDOWN',
'wxDP_ALLOWNONE', 'wxDP_SHOWCENTURY'] 'wxDP_ALLOWNONE', 'wxDP_SHOWCENTURY']
class xxxGrid(xxxObject):
allParams = ['pos', 'size', 'style']
class xxxFilePickerCtrl(xxxObject):
allParams = ['value', 'message', 'wildcard', 'pos', 'size', 'style']
winStyles = ['wxFLP_OPEN', 'wxFLP_SAVE', 'wxFLP_OVERWRITE_PROMPT',
'wxFLP_FILE_MUST_EXIST', 'wxFLP_CHANGE_DIR',
'wxFLP_DEFAULT_STYLE']
################################################################################ ################################################################################
# Buttons # Buttons
@@ -771,45 +809,11 @@ class xxxFlexGridSizer(xxxGridSizer):
specials = ['growablecols', 'growablerows'] specials = ['growablecols', 'growablerows']
allParams = ['cols', 'rows', 'vgap', 'hgap'] + specials allParams = ['cols', 'rows', 'vgap', 'hgap'] + specials
paramDict = {'growablecols': ParamIntList, 'growablerows': ParamIntList} paramDict = {'growablecols': ParamIntList, 'growablerows': ParamIntList}
# Special processing for growable* parameters
# (they are represented by several nodes)
def special(self, tag, node):
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 = g.tree.dom.createElement(param)
text = g.tree.dom.createTextNode(str(i))
node.appendChild(text)
self.element.appendChild(node)
self.special(param, node)
class xxxGridBagSizer(xxxSizer): class xxxGridBagSizer(xxxSizer):
specials = ['growablecols', 'growablerows'] specials = ['growablecols', 'growablerows']
allParams = ['vgap', 'hgap'] + specials allParams = ['vgap', 'hgap'] + specials
paramDict = {'growablecols':ParamIntList, 'growablerows':ParamIntList} paramDict = {'growablecols': ParamIntList, 'growablerows': ParamIntList}
# Special processing for growable* parameters
# (they are represented by several nodes)
def special(self, tag, node):
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 = g.tree.dom.createElement(param)
text = g.tree.dom.createTextNode(str(i))
node.appendChild(text)
self.element.appendChild(node)
self.special(param, node)
# Container with only one child. # Container with only one child.
# Not shown in tree. # Not shown in tree.
@@ -843,7 +847,8 @@ class xxxChildContainer(xxxObject):
class xxxSizerItem(xxxChildContainer): class xxxSizerItem(xxxChildContainer):
allParams = ['option', 'flag', 'border', 'minsize', 'ratio'] allParams = ['option', 'flag', 'border', 'minsize', 'ratio']
paramDict = {'option': ParamInt, 'minsize': ParamPosSize, 'ratio': ParamPosSize} paramDict = {'option': ParamInt, 'minsize': ParamPosSize, 'ratio': ParamPosSize}
#default = {'cellspan': '1,1'} defaults_panel = {}
defaults_control = {}
def __init__(self, parent, element, refElem=None): def __init__(self, parent, element, refElem=None):
# For GridBag sizer items, extra parameters added # For GridBag sizer items, extra parameters added
if isinstance(parent, xxxGridBagSizer): if isinstance(parent, xxxGridBagSizer):
@@ -923,7 +928,143 @@ class xxxUnknown(xxxObject):
winStyles = ['wxNO_FULL_REPAINT_ON_RESIZE'] winStyles = ['wxNO_FULL_REPAINT_ON_RESIZE']
################################################################################ ################################################################################
# Comment
_handlers = [] # custom handler classes/funcs
def getHandlers():
return _handlers
def setHandlers(handlers):
global _handlers
_handlers = handlers
_CFuncPtr = None # ctypes function type
def register(hndlr):
"""Register hndlr function or XmlResourceHandler class."""
if _CFuncPtr and isinstance(hndlr, _CFuncPtr):
_handlers.append(hndlr)
return
if not isinstance(hndlr, type):
wx.LogError('handler is not a type: %s' % hndlr)
elif not issubclass(hndlr, wx.xrc.XmlResourceHandler):
wx.LogError('handler is not a XmlResourceHandler: %s' % hndlr)
else:
_handlers.append(hndlr)
def load_dl(path, localname=''):
"""Load shared/dynamic library into xxx namespace.
If path is not absolute or relative, try to find in the module's directory.
"""
if not localname:
localname = os.path.basename(os.path.splitext(path)[0])
try:
import ctypes
global _CFuncPtr
_CFuncPtr = ctypes._CFuncPtr # use as a flag of loaded ctypes
#if not os.path.dirname(path) and os.path.isfile(path):
except ImportError:
wx.LogError('ctypes module not found')
globals()[localname] = None
return
try:
dl = ctypes.CDLL(path)
globals()[localname] = dl
# Register AddXmlHandlers() if exists
try:
register(dl.AddXmlHandlers)
except:
pass
except:
wx.LogError('error loading dynamic library: %s' % path)
print traceback.print_exc()
# Called when creating test window
def addHandlers():
for h in _handlers:
if _CFuncPtr and isinstance(h, _CFuncPtr):
try:
apply(h, ())
except:
wx.LogError('error calling DL func: "%s"' % h)
print traceback.print_exc()
else:
try:
xrc.XmlResource.Get().AddHandler(apply(h, ()))
except:
wx.LogError('error adding XmlHandler: "%s"' % h)
print traceback.print_exc()
def custom(klassName, klass='unknown'):
"""Define custom control based on xrcClass.
klass: new object name
xrcClass: name of an existing XRC object class or
a class object defining class parameters.
"""
if type(klass) is str:
# Copy correct xxx class under new name
kl = xxxDict[klass]
xxxClass = types.ClassType('xxx' + klassName, kl.__bases__, kl.__dict__)
else:
xxxClass = klass
# Register param IDs
for param in klass.allParams + klass.paramDict.keys():
if not paramIDs.has_key(param):
paramIDs[param] = wx.NewId()
# Insert in dictionaty
xxxDict[klassName] = xxxClass
# Add to menu
g.pullDownMenu.addCustom(klassName)
class xxxParamComment(xxxParam):
locals = {} # namespace for comment directives
allow = None # undefined initial state for current file
def __init__(self, node):
xxxNode.__init__(self, node)
self.textNode = node
# Parse "pragma" comments if enabled
if node.data and node.data[0] == '%' and g.conf.allowExec != 'no' and \
xxxParamComment.allow is not False:
# Show warning
if g.conf.allowExec == 'ask' and xxxParamComment.allow is None:
flags = wx.ICON_EXCLAMATION | wx.YES_NO | wx.CENTRE
dlg = wx.MessageDialog(g.frame, '''
This file contains executable %comment directives. Allow to execute?''',
'Warning', flags)
say = dlg.ShowModal()
dlg.Destroy()
if say == wx.ID_YES:
xxxParamComment.allow = True
else:
xxxParamComment.allow = False
try:
code = node.data[1:]
exec code in globals(), self.locals
except:
wx.LogError('exec error: "%s"' % code)
print traceback.print_exc()
class xxxComment(xxxObject):
hasStyle = hasName = False
allParams = required = ['comment']
def __init__(self, parent, node):
self.parent = parent
self.node = node
self.isElement = False
self.undo = None
self.className = 'comment'
self.ref = self.subclass = None
self.params = {'comment': xxxParamComment(node)}
def treeName(self):
# Replace newlines by \n to avoid tree item resizing
return self.params['comment'].value().replace('\n', r'\n')
################################################################################
# Mapping of XRC names to xxx classes
xxxDict = { xxxDict = {
'wxPanel': xxxPanel, 'wxPanel': xxxPanel,
'wxDialog': xxxDialog, 'wxDialog': xxxDialog,
@@ -973,6 +1114,8 @@ xxxDict = {
'wxGenericDirCtrl': xxxGenericDirCtrl, 'wxGenericDirCtrl': xxxGenericDirCtrl,
'wxSpinCtrl': xxxSpinCtrl, 'wxSpinCtrl': xxxSpinCtrl,
'wxScrolledWindow': xxxScrolledWindow, 'wxScrolledWindow': xxxScrolledWindow,
'wxGrid': xxxGrid,
'wxFilePickerCtrl': xxxFilePickerCtrl,
'wxDatePickerCtrl': xxxDateCtrl, 'wxDatePickerCtrl': xxxDateCtrl,
'wxBoxSizer': xxxBoxSizer, 'wxBoxSizer': xxxBoxSizer,
@@ -990,13 +1133,15 @@ xxxDict = {
'separator': xxxSeparator, 'separator': xxxSeparator,
'unknown': xxxUnknown, 'unknown': xxxUnknown,
'comment': xxxComment,
} }
# Create IDs for all parameters of all classes # Create IDs for all parameters of all classes
paramIDs = {'fg': wx.NewId(), 'bg': wx.NewId(), 'exstyle': wx.NewId(), 'font': wx.NewId(), paramIDs = {'fg': wx.NewId(), 'bg': wx.NewId(), 'exstyle': wx.NewId(), 'font': wx.NewId(),
'enabled': wx.NewId(), 'focused': wx.NewId(), 'hidden': wx.NewId(), 'enabled': wx.NewId(), 'focused': wx.NewId(), 'hidden': wx.NewId(),
'tooltip': wx.NewId(), 'encoding': wx.NewId(), 'tooltip': wx.NewId(), 'encoding': wx.NewId(),
'cellpos': wx.NewId(), 'cellspan': wx.NewId() 'cellpos': wx.NewId(), 'cellspan': wx.NewId(),
'text': wx.NewId()
} }
for cl in xxxDict.values(): for cl in xxxDict.values():
if cl.allParams: if cl.allParams:
@@ -1009,25 +1154,29 @@ for cl in xxxDict.values():
# Test for object elements # Test for object elements
def IsObject(node): def IsObject(node):
return node.nodeType == minidom.Node.ELEMENT_NODE and node.tagName in ['object', 'object_ref'] return node.nodeType == minidom.Node.ELEMENT_NODE and \
node.tagName in ['object', 'object_ref'] or \
node.nodeType == minidom.Node.COMMENT_NODE
# Make XXX object from some DOM object, selecting correct class # Make XXX object from some DOM object, selecting correct class
def MakeXXXFromDOM(parent, element): def MakeXXXFromDOM(parent, node):
if element.tagName == 'object_ref': if node.nodeType == minidom.Node.COMMENT_NODE:
ref = element.getAttribute('ref') return xxxComment(parent, node)
if node.tagName == 'object_ref':
ref = node.getAttribute('ref')
refElem = FindResource(ref) refElem = FindResource(ref)
if refElem: cls = refElem.getAttribute('class') if refElem: cls = refElem.getAttribute('class')
else: return xxxUnknown(parent, element) else: return xxxUnknown(parent, node)
else: else:
refElem = None refElem = None
cls = element.getAttribute('class') cls = node.getAttribute('class')
try: try:
klass = xxxDict[cls] klass = xxxDict[cls]
except KeyError: except KeyError:
# If we encounter a weird class, use unknown template # If we encounter a weird class, use unknown template
print 'WARNING: unsupported class:', element.getAttribute('class') print 'WARNING: unsupported class:', node.getAttribute('class')
klass = xxxUnknown klass = xxxUnknown
return klass(parent, element, refElem) return klass(parent, node, refElem)
# Make empty DOM element # Make empty DOM element
def MakeEmptyDOM(className): def MakeEmptyDOM(className):
@@ -1051,7 +1200,8 @@ def MakeEmptyDOM(className):
def MakeEmptyXXX(parent, className): def MakeEmptyXXX(parent, className):
# Make corresponding DOM object first # Make corresponding DOM object first
elem = MakeEmptyDOM(className) elem = MakeEmptyDOM(className)
# If parent is a sizer, we should create sizeritem object, except for spacers # Special handling, e.g. if parent is a sizer, we should create
# sizeritem object, except for spacers, etc.
if parent: if parent:
if parent.isSizer and className != 'spacer': if parent.isSizer and className != 'spacer':
sizerItemElem = MakeEmptyDOM(parent.itemTag) sizerItemElem = MakeEmptyDOM(parent.itemTag)
@@ -1070,7 +1220,16 @@ def MakeEmptyXXX(parent, className):
pageElem.appendChild(elem) pageElem.appendChild(elem)
elem = pageElem elem = pageElem
# Now just make object # Now just make object
return MakeXXXFromDOM(parent, elem) xxx = MakeXXXFromDOM(parent, elem)
# Special defaults for new panels and controls
if isinstance(xxx, xxxSizerItem):
if isinstance(xxx.child, xxxContainer) and not xxx.child.isSizer:
for param,v in xxxSizerItem.defaults_panel.items():
xxx.set(param, v)
elif isinstance(xxx.child, xxxObject):
for param,v in xxxSizerItem.defaults_control.items():
xxx.set(param, v)
return xxx
# Make empty DOM element for reference # Make empty DOM element for reference
def MakeEmptyRefDOM(ref): def MakeEmptyRefDOM(ref):
@@ -1107,3 +1266,15 @@ def MakeEmptyRefXXX(parent, ref):
#xxx.allParams.remove('label') #xxx.allParams.remove('label')
return xxx return xxx
# Make empty comment node
def MakeEmptyCommentDOM():
node = g.tree.dom.createComment('')
return node
# Make empty xxxComment
def MakeEmptyCommentXXX(parent):
node = MakeEmptyCommentDOM()
# Now just make object
xxx = MakeXXXFromDOM(parent, node)
return xxx