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:
@@ -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
|
||||
-------
|
||||
|
||||
|
@@ -15,7 +15,7 @@ import sys
|
||||
# Global constants
|
||||
|
||||
progname = 'XRCed'
|
||||
version = '0.1.8-1'
|
||||
version = '0.1.8-5'
|
||||
# Minimal wxWidgets version
|
||||
MinWxVersion = (2,6,0)
|
||||
if wx.VERSION[:3] < MinWxVersion:
|
||||
@@ -48,6 +48,7 @@ class Globals:
|
||||
testWinPos = wx.DefaultPosition
|
||||
currentXXX = None
|
||||
currentEncoding = defaultEncoding
|
||||
conf = None
|
||||
|
||||
def _makeFonts(self):
|
||||
self._sysFont = wx.SystemSettings.GetFont(wx.SYS_SYSTEM_FONT)
|
||||
|
@@ -470,11 +470,10 @@ def getToolGaugeData():
|
||||
return \
|
||||
'\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\
|
||||
\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"\
|
||||
\x0cX\x909\xa4\xc6\x14\x16\x83\x18\x19\x19)r\x0f\xdc \xe2S0>\x83\xfe\xff\xff\
|
||||
O\xa1)\x0c\x0c\x0c\x00U\xa6\x18\xb48\xff\xd0\x00\x00\x00\x00\x00IEND\xaeB`\
|
||||
\x82'
|
||||
\x0cX\x909\xa4\xc6\x14\x16\x83\x18\x19\x19)r\x0f\xdc \xe2S0>\x83\xb0\xe6\x0f\
|
||||
R\x01\x00U\xa6\x18\xb4\x82\x95pI\x00\x00\x00\x00IEND\xaeB`\x82'
|
||||
|
||||
def getToolGaugeBitmap():
|
||||
return BitmapFromImage(getToolGaugeImage())
|
||||
@@ -842,13 +841,13 @@ def getToolRadioButtonData():
|
||||
return \
|
||||
'\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\x98IDAT\x18\x95m\x8f\xc1\r\xc20\x0cE\x9f\x1d\x06\xe8\x81)\xe8\x06\x91:V\
|
||||
\xc5\x08P\xb2\x15\xa8\xdd\xa0L\xd1C\x06\x00\xc2\xa1\xa4J\x83\xbfd\xc5N\xde\
|
||||
\xb7~\x10u\xd4\x15\x86\x90\xac{\xa5\xd2\xedrM\xe5YJ-\xb0?\xf7X\x06\xb5\xc0\
|
||||
\xf99\x9b\x06\xb5@\xc04H\x18\xc2\x1fX\xaa=\xb5\x84!\x00 \xa2\x8e\xcf\xfb\x95\
|
||||
\x00\xa6\xc7Dsl60.\x11\xdf\xf95\x82;\x88\xe6\x06\xc0w\x9e\xb8D\x13\\W\xab\
|
||||
\xdb*\xfd4\xde\xc7\xdc\xa6\xf2]D\xdd.c\x8e\xb4\xdb\x98\xe7\xfaC\x19\xa8A\x80\
|
||||
/\x17\xa5W:\x12\xac\xa3\xbe\x00\x00\x00\x00IEND\xaeB`\x82'
|
||||
\x00\x96IDAT\x18\x95m\x90\xc1\r\xc20\x10\x04\xc7g\n\xc8\x83*H\x07\x96RVD\t`\
|
||||
\xdc\x15(\xe9 T\x91\x87\x0b\x00\xcc#1\xb2\xcd\xadd\xf9t\x9a=\xad\x16#\x96\
|
||||
\xf6\x05\x1f\x92\xb6\x17\x1a\xdd.\xd7T\xfe\xa5D\x03\xc7\xf3\x88f\x10\r\\\x9e\
|
||||
\x8bj\x10\r\x04T\x83\t>\xfc\x81\xa5\xfaSO\xf0\x01\x00c\xc4\xf2y\xbf\x12\xc0\
|
||||
\xfc\x98\xe9\x8e\xdd\x0f\x8ck\xc4\rn\x8b`\x0fF\xf2\x00\xe0\x06G\\\xa3\nn\xa7\
|
||||
\x8b\x1e\xd3\xae\xe9>\xe5\xb1\xee\xdb\x88\xad2\xe6H\xd5E\xad\xe7\x12hA\x80/\
|
||||
\x17\xa5W:+\xbbb\xd2\x00\x00\x00\x00IEND\xaeB`\x82'
|
||||
|
||||
def getToolRadioButtonBitmap():
|
||||
return BitmapFromImage(getToolRadioButtonImage())
|
||||
@@ -865,13 +864,13 @@ def getToolRadioButtonIcon():
|
||||
#----------------------------------------------------------------------
|
||||
def getToolRootData():
|
||||
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\
|
||||
\x00cIDAT(\x91\xed\x90\xc1\x0e\x800\x08C[\xf0\x97T\xfe\xff\xa6~\x93n\xb7e.`\
|
||||
\xa6\xbb\xda\x84\x03\xa4m\xf2 E1\xa2\xc9;\xa6\xebL\xf5NQ\x86\x05\xeb2\xdf\
|
||||
\xcc\xdb~\x84fW\x14\x85\x99%\x8a\xe2\xcb\xb8\x08\x1eF\x84T\nj\x947\x18\xa5\
|
||||
\xa0\r==\xce-h\xf5#\xf4#\x90\xa2\xbd^W2\x94\x06\x90\x01\x0f\xb3'\x06\xe8\x11\
|
||||
R\xf1\x00\x00\x00\x00IEND\xaeB`\x82"
|
||||
\x00aIDAT(\x91\xed\x93\xc1\n\x80@\x08Dg\xb4_\xaa\xfc\xff[\xf5M\xb5\xdd\x96m\
|
||||
\xd1\xa8\xbc6\xe0A\x19\x07\x9e )\x8a\x8c\x06oX\x8e\xbd\xb4=E\x19\x06\xcc\xd3\
|
||||
x1/\xeb\x16\x9a]Q\x14fV(\x8a/\xe5"x\x18\x11R\rhQ\xde`\xd4\x80~\xe9\xeepn@\
|
||||
\xaf\x1f\xe19\x02\xb3\xbf \xa9m\x00\'\x0f\xb3\'\x06(\x95\x90F\x00\x00\x00\
|
||||
\x00IEND\xaeB`\x82'
|
||||
|
||||
def getToolRootBitmap():
|
||||
return BitmapFromImage(getToolRootImage())
|
||||
@@ -917,8 +916,8 @@ def getToolSeparatorData():
|
||||
return \
|
||||
'\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\x17IDAT\x18\x95c\x9c2u\n\x03\x11 ;+\x9b\x05B\x11\xa3\x1a\x00\xfb\
|
||||
\x1c\x04C\xb1\x8cE\xa0\x00\x00\x00\x00IEND\xaeB`\x82'
|
||||
\x00\x00\x17IDAT\x08\x99c\x9c2u\n\x03\x11 ;+\x9b\x05B\x11\xa3\x1a\x00\xfb\
|
||||
\x1c\x04CU\x1cv\xec\x00\x00\x00\x00IEND\xaeB`\x82'
|
||||
|
||||
def getToolSeparatorBitmap():
|
||||
return BitmapFromImage(getToolSeparatorImage())
|
||||
@@ -1052,28 +1051,28 @@ def getToolSplitterWindowIcon():
|
||||
#----------------------------------------------------------------------
|
||||
def getToolStaticBitmapData():
|
||||
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\x01\xf7IDAT(\x91\x85\x921h\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\
|
||||
\x0ejq\x10\xb2\x08\xe9Rt\xd0:\xf6:\x14\x13P\x92.\xd6\x82C\xb3\x14\x92A\x92S\
|
||||
\x03\xf7\xc0k?\x87pgC\xab\xfdO\xef}\xef\xfd\xbe\xef}\xff\xefY\x96\xedpT\x87\
|
||||
\x07\xa9p\x82lGYc\xfb\xa3@\x06%\xbf\x12\xda\x9f\xdb\x0c\x06\x83\x7f&\xb4,\
|
||||
\xdb\xc9\x83\x8d\xad\x06o\xd7j,-\x9eG\xab\x02f\x98\xd0\xf8\x12\xb3\xfa~\x9b\
|
||||
\xfa\xeb\x0fc\x95s\xb0\xb1\xd5\xa0\xe4k\\"<\xff2\xe0\x82i\x92\xa4\x86\xf8\
|
||||
\xfb\x80{\x8fv\xa9\xaf\xd6s\xd8\xce\xaa-\xbfX\xc6W\x11^\xf1*\xa8\tP\x1e\x9c\
|
||||
\xa9PP\x1a\xd7\xf5X\x9a+1;=\x9b?Ue\x8bp\xae\x02\x1a\xd0\xa5Q 5\x00$\xa9\xa6\
|
||||
\xa0\x0c^Q\xe3z:\xef77\xc7\x18\x93_\x06\r\xca%1#s\x124(M\xc9\xcd\xce\xc1\xce\
|
||||
\x9a\xad>\x7f\x03i\x02\x18Hc0\x1dH\xbb\xa3d\xa9\xc1\xc41\xf5\xb5\xe8\xf88j\
|
||||
\xafj\x98\x94\x11\xac4\x89\xe9\x001\xa4\x86^\xafKg\x7f@\xf5\xf1JnN\xde\xa3\
|
||||
\xd6\x1am\x0cP \x19v \x8d1f@\xb7\xd7\xc3\x0c\x13\xaa/w\x896k\xe3\xe6\xd8\x8e\
|
||||
\xb2\xee\xdc\xbd-\xdb\xcd\x88\x89sMV\x1e\x06\xc4qLg\xbf\xcb\x83\'\x11^\xf1\
|
||||
\x02\xd1fcl\x8eX\xb6\x83e;\xa0\x90\x99\x9b\x15\xd9\xf9\xba#\xadO\x1f\xa5r=\
|
||||
\x90p\xe1\x96\xec}\xdb\x93L\xd9]\xcbv\xfe\x8237*""\xd2j\xb7$\x98\n$\xbc\x1fJ\
|
||||
\xbf\xdf?\x06\x8c\x81\xbe\xef\xcbF\xb4!\x95k\x81\xac<{*\xf3\x0b\xf3\xe2\x16\
|
||||
\xdd\x13\x811\x10\x90`jR\xd6\xdf\xad\x8f*^\t\xa4|\xb6|:\x98\xc1\xe5\xb2/\x93\
|
||||
\x97.J\xb8\x18\xfe\x17\xb2lg\xf4\xc9\x01\xe4\xf0@|\xdf\xc5\x18\xc3\x8f\x9f\
|
||||
\xbf-N\xd1\x1f(\xba\xfe\xd4\xf5\xbb\xa30\x00\x00\x00\x00IEND\xaeB`\x82'
|
||||
\x00\x00\x01\xf9IDAT(\x91\x85\x931h\x13Q\x18\xc7\x7fw\xf7\x86\x17p\xb8\x83\
|
||||
\x0c\x97-\x05\x1dts\xb3N\x9et\x90\xe0\xa0-..N\x1d\xact(\xd1\xa9\xba\x05D\xa5\
|
||||
\x83Z\x1c\x84,B\xba\x14\x1d\xb4\x8e\xbd\x0e\xc5\x04\x94\xa4\x8b\xb5\xe0\xd0,\
|
||||
\x85d\x90\xe4\xd4\xc0=\xf0\xda\xcf!\xdc\xd9\xa3Q\xbf\xe9\xbd\xef}\xbf\xef{\
|
||||
\xdf\xff{\xcf\xb2l\x87\xe3vt\x98\x08\x13\xccv\x94\x95\xdb\x1f\x07R(\xfe\x19\
|
||||
\xd3\xf9\xd4a8\x1c\xfe5\xa1e\xd9N\xe6ln7y\xb3^gy\xe9,Z\x150\xa3\x98\xe6\xe7\
|
||||
\x88\xb5w;4^\xbd\xcfU\xce\xc0\xe6v\x93\x92\xafq\t\xf1\xfc\x8b\x80\x0b\xa6E\
|
||||
\x9c\x18\xa2oC\xee>\xdc\xa3\xb1\xd6\xc8`;\xad\xb6\xf2|\x05_\x85x\xc5\xcb\xa0\
|
||||
\xa6@yp\xaaBAi\\\xd7cy\xbe\xc4\xdc\xf5\xb9\xec\xaa*]T\xe7+\xa0\x01]\x1a;\x12\
|
||||
\x03@\x9ch\n\xca\xe0\x155\xae\xa7\xb3~3q\x8c1Y0hP.\xb1\x19\x8b\x13\xa3AiJnz\
|
||||
\x0ev\xdal\xed\xd9kHb\xc0@\x12\x81\xe9B\xd2\x1b'K\x0c&\x8ah\xac\x87'\xc7Q\
|
||||
\x7fY\xc7$\x8ca\xa5\x89M\x17\x88 1\xf4\xfb=\xba\x07Cj\x8fV3q\xb2\x1e\xb5\xd6\
|
||||
hc\x80\x02\xf1\xa8\x0bI\x841Cz\xfd>f\x14S{\xb1G\xb8U\xcf\x8bc;\xca\xba}\xe7\
|
||||
\x96\xec\xb4B\xa6\xce\xb4X}\x10\x10E\x11\xdd\x83\x1e\xf7\x1f\x87x\xc5s\x84[\
|
||||
\xcd\xdc\x1c\xb1l\x07\xcbv@!\xb37*\xb2\xfbeW\xda\x1f?H\xe5j \xd5\xc5\x9b\xb2\
|
||||
\xffu_RKc-\xdb\xf9\x03\xce^\xab\x88\x88H\xbb\xd3\x96`&\x90\xea\xbd\xaa\x0c\
|
||||
\x06\x83\x13@\x0e\xf4}_6\xc3M\xa9\\\td\xf5\xe9\x13YX\\\x10\xb7\xe8N\x04r \
|
||||
\xc1\xcc\xb4l\xbc\xdd\x18W\xbc\x14H\xf9t\xf9\xff`\n\x97\xcb\xbeL_8/\xd5\xa5\
|
||||
\xea?!\xcbv\xc6\x8f\x1c@\x8e\x0e\xc5\xf7]\x8c1|\xff\xf1+\xf7\xf7&\xd9o(\xba\
|
||||
\xfe\xd4S\x004\x8f\x00\x00\x00\x00IEND\xaeB`\x82"
|
||||
|
||||
def getToolStaticBitmapBitmap():
|
||||
return BitmapFromImage(getToolStaticBitmapImage())
|
||||
@@ -1140,8 +1139,8 @@ def getToolStaticLineData():
|
||||
return \
|
||||
'\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\x17IDAT\x18\x95c\x9c2u\n\x03Y ;+\x9b\x05B\x91\xa7\x1f\x00gO\x04C\xda+\
|
||||
\x0c\xd5\x00\x00\x00\x00IEND\xaeB`\x82'
|
||||
\x00\x17IDAT\x08\x99c\x9c2u\n\x03Y ;+\x9b\x05B\x91\xa7\x1f\x00gO\x04C>\xbb?\
|
||||
\x99\x00\x00\x00\x00IEND\xaeB`\x82'
|
||||
|
||||
def getToolStaticLineBitmap():
|
||||
return BitmapFromImage(getToolStaticLineImage())
|
||||
@@ -1204,9 +1203,9 @@ def getToolToolData():
|
||||
return \
|
||||
'\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>\
|
||||
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\
|
||||
\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'
|
||||
|
||||
def getToolToolBitmap():
|
||||
@@ -1248,13 +1247,13 @@ def getToolToolBarIcon():
|
||||
#----------------------------------------------------------------------
|
||||
def getToolTreeCtrlData():
|
||||
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\
|
||||
\x00cIDAT(\x91\xed\x90\xc1\x0e\x800\x08C[\xf0\x97T\xfe\xff\xa6~\x93n\xb7e.`\
|
||||
\xa6\xbb\xda\x84\x03\xa4m\xf2 E1\xa2\xc9;\xa6\xebL\xf5NQ\x86\x05\xeb2\xdf\
|
||||
\xcc\xdb~\x84fW\x14\x85\x99%\x8a\xe2\xcb\xb8\x08\x1eF\x84T\nj\x947\x18\xa5\
|
||||
\xa0\r==\xce-h\xf5#\xf4#\x90\xa2\xbd^W2\x94\x06\x90\x01\x0f\xb3'\x06\xe8\x11\
|
||||
R\xf1\x00\x00\x00\x00IEND\xaeB`\x82"
|
||||
\x00aIDAT(\x91\xed\x93\xc1\n\x80@\x08Dg\xb4_\xaa\xfc\xff[\xf5M\xb5\xdd\x96m\
|
||||
\xd1\xa8\xbc6\xe0A\x19\x07\x9e )\x8a\x8c\x06oX\x8e\xbd\xb4=E\x19\x06\xcc\xd3\
|
||||
x1/\xeb\x16\x9a]Q\x14fV(\x8a/\xe5"x\x18\x11R\rhQ\xde`\xd4\x80~\xe9\xeepn@\
|
||||
\xaf\x1f\xe19\x02\xb3\xbf \xa9m\x00\'\x0f\xb3\'\x06(\x95\x90F\x00\x00\x00\
|
||||
\x00IEND\xaeB`\x82'
|
||||
|
||||
def getToolTreeCtrlBitmap():
|
||||
return BitmapFromImage(getToolTreeCtrlImage())
|
||||
@@ -1290,6 +1289,27 @@ def getToolUnknownIcon():
|
||||
icon.CopyFromBitmap(getToolUnknownBitmap())
|
||||
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():
|
||||
return \
|
||||
@@ -1449,13 +1469,13 @@ def getTreePanelIcon():
|
||||
#----------------------------------------------------------------------
|
||||
def getTreeRootData():
|
||||
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\
|
||||
\x00cIDAT(\x91\xed\x90\xc1\x0e\x800\x08C[\xf0\x97T\xfe\xff\xa6~\x93n\xb7e.`\
|
||||
\xa6\xbb\xda\x84\x03\xa4m\xf2 E1\xa2\xc9;\xa6\xebL\xf5NQ\x86\x05\xeb2\xdf\
|
||||
\xcc\xdb~\x84fW\x14\x85\x99%\x8a\xe2\xcb\xb8\x08\x1eF\x84T\nj\x947\x18\xa5\
|
||||
\xa0\r==\xce-h\xf5#\xf4#\x90\xa2\xbd^W2\x94\x06\x90\x01\x0f\xb3'\x06\xe8\x11\
|
||||
R\xf1\x00\x00\x00\x00IEND\xaeB`\x82"
|
||||
\x00aIDAT(\x91\xed\x93\xc1\n\x80@\x08Dg\xb4_\xaa\xfc\xff[\xf5M\xb5\xdd\x96m\
|
||||
\xd1\xa8\xbc6\xe0A\x19\x07\x9e )\x8a\x8c\x06oX\x8e\xbd\xb4=E\x19\x06\xcc\xd3\
|
||||
x1/\xeb\x16\x9a]Q\x14fV(\x8a/\xe5"x\x18\x11R\rhQ\xde`\xd4\x80~\xe9\xeepn@\
|
||||
\xaf\x1f\xe19\x02\xb3\xbf \xa9m\x00\'\x0f\xb3\'\x06(\x95\x90F\x00\x00\x00\
|
||||
\x00IEND\xaeB`\x82'
|
||||
|
||||
def getTreeRootBitmap():
|
||||
return BitmapFromImage(getTreeRootImage())
|
||||
|
@@ -22,7 +22,7 @@ class Panel(wx.Notebook):
|
||||
# Set common button size for parameter buttons
|
||||
bTmp = wx.Button(self, -1, '')
|
||||
import params
|
||||
params.buttonSize = (self.DLG_SZE(buttonSize)[0], bTmp.GetSize()[1])
|
||||
params.buttonSize = (self.DLG_SZE(buttonSizeD)[0], bTmp.GetSize()[1])
|
||||
bTmp.Destroy()
|
||||
del bTmp
|
||||
|
||||
@@ -160,6 +160,7 @@ class Panel(wx.Notebook):
|
||||
# Register undo object when modifying first time
|
||||
if not self.modified and value:
|
||||
g.undoMan.RegisterUndo(UndoEdit())
|
||||
g.frame.SetModified()
|
||||
self.modified = value
|
||||
|
||||
def Apply(self):
|
||||
@@ -184,7 +185,7 @@ class ParamPage(wx.Panel):
|
||||
param = evt.GetEventObject().GetName()
|
||||
w = self.controls[param]
|
||||
w.Enable(True)
|
||||
objElem = xxx.element
|
||||
objElem = xxx.node
|
||||
if evt.IsChecked():
|
||||
# Ad new text node in order of allParams
|
||||
w.SetValue('') # set empty (default) value
|
||||
@@ -192,7 +193,7 @@ class ParamPage(wx.Panel):
|
||||
elem = g.tree.dom.createElement(param)
|
||||
# Some classes are special
|
||||
if param == 'font':
|
||||
xxx.params[param] = xxxParamFont(xxx.element, elem)
|
||||
xxx.params[param] = xxxParamFont(xxx.node, elem)
|
||||
elif param in xxxObject.bitmapTags:
|
||||
xxx.params[param] = xxxParamBitmap(elem)
|
||||
else:
|
||||
@@ -218,7 +219,7 @@ class ParamPage(wx.Panel):
|
||||
xxx.params[param].remove()
|
||||
del xxx.params[param]
|
||||
w.SetValue('')
|
||||
w.modified = False # mark as not changed
|
||||
w.SetModified(False) # mark as not changed
|
||||
w.Enable(False)
|
||||
# Set modified flag (provokes undo storing is necessary)
|
||||
panel.SetModified(True)
|
||||
@@ -228,7 +229,7 @@ class ParamPage(wx.Panel):
|
||||
name = self.controlName.GetValue()
|
||||
if xxx.name != name:
|
||||
xxx.name = name
|
||||
xxx.element.setAttribute('name', name)
|
||||
xxx.node.setAttribute('name', name)
|
||||
for param, w in self.controls.items():
|
||||
if w.modified:
|
||||
paramObj = xxx.params[param]
|
||||
@@ -237,10 +238,11 @@ class ParamPage(wx.Panel):
|
||||
xxx.setSpecial(param, value)
|
||||
else:
|
||||
paramObj.update(value)
|
||||
|
||||
# Save current state
|
||||
def SaveState(self):
|
||||
self.origChecks = map(lambda i: (i[0], i[1].GetValue()), self.checks.items())
|
||||
self.origControls = map(lambda i: (i[0], i[1].GetValue(), i[1].IsEnabled()),
|
||||
self.origControls = map(lambda i: (i[0], i[1].GetValue(), i[1].enabled),
|
||||
self.controls.items())
|
||||
if self.controlName:
|
||||
self.origName = self.controlName.GetValue()
|
||||
@@ -257,7 +259,8 @@ class ParamPage(wx.Panel):
|
||||
for k,v,e in state[1]:
|
||||
self.controls[k].SetValue(v)
|
||||
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:
|
||||
self.controlName.SetValue(state[2])
|
||||
|
||||
@@ -283,11 +286,15 @@ class PropPage(ParamPage):
|
||||
for param in xxx.allParams:
|
||||
present = xxx.params.has_key(param)
|
||||
if param in xxx.required:
|
||||
if isinstance(xxx, xxxComment):
|
||||
label = None
|
||||
else:
|
||||
label = wx.StaticText(self, paramIDs[param], param + ':',
|
||||
size = (LABEL_WIDTH,-1), name = param)
|
||||
else:
|
||||
# Notebook has one very loooooong parameter
|
||||
# Rename some parameters
|
||||
if param == 'usenotebooksizer': sParam = 'usesizer:'
|
||||
elif param == 'option': sParam = 'proportion'
|
||||
else: sParam = param + ':'
|
||||
label = wx.CheckBox(self, paramIDs[param], sParam,
|
||||
size = (LABEL_WIDTH,-1), name = param)
|
||||
@@ -303,13 +310,19 @@ class PropPage(ParamPage):
|
||||
typeClass = ParamText
|
||||
control = typeClass(self, param)
|
||||
control.Enable(present)
|
||||
# Comment has only one parameter
|
||||
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
|
||||
topSizer.Add(sizer, 1, wx.ALL | wx.EXPAND, 3)
|
||||
self.SetAutoLayout(True)
|
||||
self.SetSizer(topSizer)
|
||||
topSizer.Fit(self)
|
||||
|
||||
def SetValues(self, xxx):
|
||||
self.xxx = xxx
|
||||
self.origChecks = []
|
||||
@@ -336,6 +349,13 @@ class PropPage(ParamPage):
|
||||
self.origChecks.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
|
||||
@@ -362,6 +382,7 @@ class StylePage(ParamPage):
|
||||
self.SetAutoLayout(True)
|
||||
self.SetSizer(topSizer)
|
||||
topSizer.Fit(self)
|
||||
|
||||
# Set data for a cahced page
|
||||
def SetValues(self, xxx):
|
||||
self.xxx = xxx
|
||||
|
@@ -25,7 +25,10 @@ genericExStyles = [
|
||||
'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 PPanel(wx.Panel):
|
||||
@@ -33,13 +36,14 @@ class PPanel(wx.Panel):
|
||||
wx.Panel.__init__(self, parent, -1, name=name)
|
||||
self.modified = self.freeze = False
|
||||
def Enable(self, value):
|
||||
self.enabled = value
|
||||
# Something strange is going on with enable so we make sure...
|
||||
for w in self.GetChildren():
|
||||
w.Enable(value)
|
||||
#wx.Panel.Enable(self, value)
|
||||
def SetModified(self):
|
||||
self.modified = True
|
||||
g.panel.SetModified(True)
|
||||
def SetModified(self, state=True):
|
||||
self.modified = state
|
||||
if state: g.panel.SetModified(True)
|
||||
# Common method to set modified state
|
||||
def OnChange(self, evt):
|
||||
if self.freeze: return
|
||||
@@ -56,9 +60,7 @@ class ParamBinaryOr(PPanel):
|
||||
sizer.Add(self.text, 0, wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 5)
|
||||
self.button = wx.Button(self, self.ID_BUTTON_CHOICES, 'Edit...', size=buttonSize)
|
||||
sizer.Add(self.button, 0, wx.ALIGN_CENTER_VERTICAL)
|
||||
self.SetAutoLayout(True)
|
||||
self.SetSizer(sizer)
|
||||
sizer.Fit(self)
|
||||
wx.EVT_BUTTON(self, self.ID_BUTTON_CHOICES, self.OnButtonChoices)
|
||||
wx.EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange)
|
||||
def GetValue(self):
|
||||
@@ -191,9 +193,7 @@ class ParamColour(PPanel):
|
||||
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))
|
||||
sizer.Add(self.button, 0, wx.ALIGN_CENTER_VERTICAL | wx.LEFT, 5)
|
||||
self.SetAutoLayout(True)
|
||||
self.SetSizer(sizer)
|
||||
sizer.Fit(self)
|
||||
self.textModified = False
|
||||
wx.EVT_PAINT(self.button, self.OnPaintButton)
|
||||
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)
|
||||
self.button = wx.Button(self, self.ID_BUTTON_SELECT, 'Select...', size=buttonSize)
|
||||
sizer.Add(self.button, 0, wx.ALIGN_CENTER_VERTICAL)
|
||||
self.SetAutoLayout(True)
|
||||
self.SetSizer(sizer)
|
||||
sizer.Fit(self)
|
||||
self.textModified = False
|
||||
wx.EVT_BUTTON(self, self.ID_BUTTON_SELECT, self.OnButtonSelect)
|
||||
wx.EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange)
|
||||
@@ -320,7 +318,6 @@ class ParamFont(PPanel):
|
||||
dlg = wx.FontDialog(self, data)
|
||||
if dlg.ShowModal() == wx.ID_OK:
|
||||
font = dlg.GetFontData().GetChosenFont()
|
||||
print font.GetEncoding()
|
||||
if font.GetEncoding() == wx.FONTENCODING_SYSTEM:
|
||||
encName = ''
|
||||
else:
|
||||
@@ -348,9 +345,7 @@ class ParamInt(PPanel):
|
||||
self.spin = wx.SpinCtrl(self, self.ID_SPIN_CTRL, size=(60,-1))
|
||||
self.spin.SetRange(-2147483648, 2147483647) # min/max integers
|
||||
sizer.Add(self.spin)
|
||||
self.SetAutoLayout(True)
|
||||
self.SetSizer(sizer)
|
||||
sizer.Fit(self)
|
||||
wx.EVT_SPINCTRL(self, self.ID_SPIN_CTRL, self.OnChange)
|
||||
def GetValue(self):
|
||||
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.SetRange(0, 10000) # min/max integers
|
||||
sizer.Add(self.spin)
|
||||
self.SetAutoLayout(True)
|
||||
self.SetSizer(sizer)
|
||||
sizer.Fit(self)
|
||||
wx.EVT_SPINCTRL(self, self.ID_SPIN_CTRL, self.OnChange)
|
||||
def GetValue(self):
|
||||
return str(self.spin.GetValue())
|
||||
@@ -388,26 +381,23 @@ class ParamUnit(PPanel):
|
||||
self.ID_TEXT_CTRL = wx.NewId()
|
||||
self.ID_SPIN_BUTTON = wx.NewId()
|
||||
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]
|
||||
self.text = wx.TextCtrl(self, self.ID_TEXT_CTRL, size=(textW,-1))
|
||||
self.spin.SetRange(-10000, 10000)
|
||||
sizer.Add(self.text, 0, wx.EXPAND)
|
||||
sizer.Add(self.spin, 0, wx.EXPAND)
|
||||
#sizer.SetMinSize((50,-1))
|
||||
self.SetAutoLayout(True)
|
||||
self.SetSizer(sizer)
|
||||
sizer.Fit(self)
|
||||
wx.EVT_SPIN_UP(self, self.ID_SPIN_BUTTON, self.OnSpinUp)
|
||||
wx.EVT_SPIN_DOWN(self, self.ID_SPIN_BUTTON, self.OnSpinDown)
|
||||
self.spin.Bind(wx.EVT_SPIN_UP, self.OnSpinUp)
|
||||
self.spin.Bind(wx.EVT_SPIN_DOWN, self.OnSpinDown)
|
||||
def GetValue(self):
|
||||
return self.text.GetValue()
|
||||
def SetValue(self, value):
|
||||
self.freeze = True
|
||||
if not value: value = '0'
|
||||
self.text.SetValue(value)
|
||||
self.freeze = False
|
||||
self.Change(0)
|
||||
def Change(self, x):
|
||||
self.freeze = True
|
||||
# Check if we are working with dialog units
|
||||
value = self.text.GetValue()
|
||||
units = ''
|
||||
@@ -417,14 +407,19 @@ class ParamUnit(PPanel):
|
||||
try:
|
||||
intValue = int(value) + x
|
||||
self.spin.SetValue(intValue)
|
||||
if x: # 0 can be passed to update spin value only
|
||||
self.text.SetValue(str(intValue) + units)
|
||||
self.SetModified()
|
||||
except:
|
||||
# !!! 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):
|
||||
self.freeze = True
|
||||
self.Change(1)
|
||||
def OnSpinDown(self, evt):
|
||||
if self.freeze: return
|
||||
self.freeze = True
|
||||
self.Change(-1)
|
||||
|
||||
class ParamMultilineText(PPanel):
|
||||
@@ -437,9 +432,7 @@ class ParamMultilineText(PPanel):
|
||||
sizer.Add(self.text, 0, wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 5)
|
||||
self.button = wx.Button(self, self.ID_BUTTON_EDIT, 'Edit...', size=buttonSize)
|
||||
sizer.Add(self.button, 0, wx.ALIGN_CENTER_VERTICAL)
|
||||
self.SetAutoLayout(True)
|
||||
self.SetSizer(sizer)
|
||||
sizer.Fit(self)
|
||||
self.SetSizerAndFit(sizer)
|
||||
wx.EVT_BUTTON(self, self.ID_BUTTON_EDIT, self.OnButtonEdit)
|
||||
wx.EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange)
|
||||
def GetValue(self):
|
||||
@@ -458,18 +451,16 @@ class ParamMultilineText(PPanel):
|
||||
dlg.Destroy()
|
||||
|
||||
class ParamText(PPanel):
|
||||
def __init__(self, parent, name, textWidth=-1):
|
||||
def __init__(self, parent, name, textWidth=-1, style=0):
|
||||
PPanel.__init__(self, parent, name)
|
||||
self.ID_TEXT_CTRL = wx.NewId()
|
||||
# We use sizer even here to have the same size of text control
|
||||
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
|
||||
else: option = 0
|
||||
sizer.Add(self.text, option, wx.ALIGN_CENTER_VERTICAL | wx.TOP | wx.BOTTOM, 2)
|
||||
self.SetAutoLayout(True)
|
||||
self.SetSizer(sizer)
|
||||
sizer.Fit(self)
|
||||
wx.EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange)
|
||||
def GetValue(self):
|
||||
return self.text.GetValue()
|
||||
@@ -494,6 +485,11 @@ class ParamEncoding(ParamText):
|
||||
def __init__(self, parent, name):
|
||||
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):
|
||||
def __init__(self, parent, value):
|
||||
# Load from resource
|
||||
@@ -612,9 +608,7 @@ class ParamContent(PPanel):
|
||||
sizer.Add(self.text, 0, wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 5)
|
||||
self.button = wx.Button(self, self.ID_BUTTON_EDIT, 'Edit...', size=buttonSize)
|
||||
sizer.Add(self.button, 0, wx.ALIGN_CENTER_VERTICAL)
|
||||
self.SetAutoLayout(True)
|
||||
self.SetSizer(sizer)
|
||||
sizer.Fit(self)
|
||||
self.textModified = False
|
||||
wx.EVT_BUTTON(self, self.ID_BUTTON_EDIT, self.OnButtonEdit)
|
||||
wx.EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange)
|
||||
@@ -625,8 +619,7 @@ class ParamContent(PPanel):
|
||||
if self.textModified: # text has newer value
|
||||
try:
|
||||
return self.text.GetValue().split('|')
|
||||
except SyntaxError:
|
||||
wx.LogError('Syntax error in parameter value: ' + self.GetName())
|
||||
except ValueError:
|
||||
return []
|
||||
return self.value
|
||||
def SetValue(self, value):
|
||||
@@ -648,6 +641,9 @@ class ParamContent(PPanel):
|
||||
self.SetModified()
|
||||
self.textModified = False
|
||||
dlg.Destroy()
|
||||
def SetModified(self, state=True):
|
||||
PPanel.SetModified(self, state)
|
||||
self.textModified = False
|
||||
|
||||
# CheckList content
|
||||
class ParamContentCheckList(ParamContent):
|
||||
@@ -728,8 +724,7 @@ class ParamIntList(ParamContent):
|
||||
if self.textModified: # text has newer value
|
||||
try:
|
||||
self.value = map(int, self.text.GetValue().split('|'))
|
||||
except SyntaxError:
|
||||
wx.LogError('Syntax error in parameter value: ' + self.GetName())
|
||||
except ValueError:
|
||||
self.value = []
|
||||
dlg = IntListDialog(self, self.value)
|
||||
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)
|
||||
topSizer.Add(button, 0, wx.RIGHT, 5)
|
||||
wx.EVT_RADIOBUTTON(self, button.GetId(), self.OnRadioChoice)
|
||||
self.SetAutoLayout(True)
|
||||
self.SetSizer(topSizer)
|
||||
topSizer.Fit(self)
|
||||
def SetStringSelection(self, value):
|
||||
self.freeze = True
|
||||
for i in self.choices:
|
||||
@@ -812,9 +805,7 @@ class ParamFile(PPanel):
|
||||
sizer.Add(self.text, 0, wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 5)
|
||||
self.button = wx.Button(self, self.ID_BUTTON_BROWSE, 'Browse...',size=buttonSize)
|
||||
sizer.Add(self.button, 0, wx.ALIGN_CENTER_VERTICAL)
|
||||
self.SetAutoLayout(True)
|
||||
self.SetSizer(sizer)
|
||||
sizer.Fit(self)
|
||||
self.textModified = False
|
||||
wx.EVT_BUTTON(self, self.ID_BUTTON_BROWSE, self.OnButtonBrowse)
|
||||
wx.EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange)
|
||||
@@ -941,5 +932,6 @@ paramDict = {
|
||||
'fg': ParamColour, 'bg': ParamColour, 'font': ParamFont,
|
||||
'enabled': ParamBool, 'focused': ParamBool, 'hidden': ParamBool,
|
||||
'tooltip': ParamText, 'bitmap': ParamBitmap, 'icon': ParamBitmap,
|
||||
'encoding': ParamEncoding, 'borders': ParamUnit
|
||||
'encoding': ParamEncoding, 'borders': ParamUnit,
|
||||
'comment': ParamComment
|
||||
}
|
||||
|
@@ -87,11 +87,11 @@ class Tools(wx.Panel):
|
||||
|
||||
(ID_NEW.UNKNOWN, images.getToolUnknownBitmap())]
|
||||
]
|
||||
self.boxes = {}
|
||||
for grp in groups:
|
||||
self.AddGroup(grp[0])
|
||||
for b in grp[1:]:
|
||||
self.AddButton(b[0], b[1], g.pullDownMenu.createMap[b[0]])
|
||||
self.SetAutoLayout(True)
|
||||
self.SetSizerAndFit(self.sizer)
|
||||
# Allow to be resized in vertical direction only
|
||||
self.SetSizeHints(self.GetSize()[0], -1)
|
||||
@@ -114,13 +114,19 @@ class Tools(wx.Panel):
|
||||
|
||||
def AddGroup(self, name):
|
||||
# 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.Bind(wx.EVT_LEFT_DOWN, self.OnClickBox)
|
||||
boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
|
||||
boxSizer.Add((0, 4))
|
||||
self.boxes[id] = box
|
||||
self.curSizer = wx.GridSizer(0, 3)
|
||||
boxSizer.Add(self.curSizer)
|
||||
self.sizer.Add(boxSizer, 0, wx.TOP | wx.LEFT | wx.RIGHT, 4)
|
||||
self.sizer.Add(boxSizer, 0, wx.TOP | wx.LEFT | wx.RIGHT | wx.EXPAND, 4)
|
||||
self.groups.append((box,{}))
|
||||
|
||||
# Enable/disable group
|
||||
@@ -129,6 +135,12 @@ class Tools(wx.Panel):
|
||||
grp[0].Enable(enable)
|
||||
for b in grp[1].values(): b.Enable(enable)
|
||||
|
||||
# Show/hide group
|
||||
def ShowGroup(self, gnum, show = True):
|
||||
grp = self.groups[gnum]
|
||||
grp[0].show = show
|
||||
for b in grp[1].values(): b.Show(show)
|
||||
|
||||
# Enable/disable group item
|
||||
def EnableGroupItem(self, gnum, id, enable = True):
|
||||
grp = self.groups[gnum]
|
||||
@@ -140,6 +152,14 @@ class Tools(wx.Panel):
|
||||
for id in ids:
|
||||
grp[1][id].Enable(enable)
|
||||
|
||||
def OnClickBox(self, evt):
|
||||
box = self.boxes[evt.GetId()]
|
||||
# Collapse/restore static box, change label
|
||||
self.ShowGroup(box.gnum, not box.show)
|
||||
if box.show: box.SetLabel('[+] ' + box.name)
|
||||
else: box.SetLabel('[-] ' + box.name)
|
||||
self.Layout()
|
||||
|
||||
# Process key events
|
||||
def OnKeyDown(self, evt):
|
||||
if evt.GetKeyCode() == wx.WXK_CONTROL:
|
||||
|
@@ -86,10 +86,12 @@ class ID_NEW:
|
||||
CHOICEBOOK = wx.NewId()
|
||||
LISTBOOK = wx.NewId()
|
||||
SPLITTER_WINDOW = wx.NewId()
|
||||
GRID = wx.NewId()
|
||||
SCROLLED_WINDOW = wx.NewId()
|
||||
HTML_WINDOW = wx.NewId()
|
||||
CALENDAR_CTRL = wx.NewId()
|
||||
DATE_CTRL = wx.NewId()
|
||||
FILE_PICKER_CTRL = wx.NewId()
|
||||
GENERIC_DIR_CTRL = wx.NewId()
|
||||
SPIN_CTRL = wx.NewId()
|
||||
UNKNOWN = wx.NewId()
|
||||
@@ -124,6 +126,10 @@ class ID_NEW:
|
||||
CONTEXT_HELP_BUTTON = 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()
|
||||
|
||||
@@ -193,10 +199,12 @@ class PullDownMenu:
|
||||
ID_NEW.CHOICEBOOK: 'wxChoicebook',
|
||||
ID_NEW.LISTBOOK: 'wxListbook',
|
||||
ID_NEW.SPLITTER_WINDOW: 'wxSplitterWindow',
|
||||
ID_NEW.GRID: 'wxGrid',
|
||||
ID_NEW.SCROLLED_WINDOW: 'wxScrolledWindow',
|
||||
ID_NEW.HTML_WINDOW: 'wxHtmlWindow',
|
||||
ID_NEW.CALENDAR_CTRL: 'wxCalendarCtrl',
|
||||
ID_NEW.DATE_CTRL: 'wxDatePickerCtrl',
|
||||
ID_NEW.FILE_PICKER_CTRL: 'wxFilePickerCtrl',
|
||||
ID_NEW.GENERIC_DIR_CTRL: 'wxGenericDirCtrl',
|
||||
ID_NEW.SPIN_CTRL: 'wxSpinCtrl',
|
||||
|
||||
@@ -268,10 +276,12 @@ class PullDownMenu:
|
||||
(ID_NEW.SCROLL_BAR, 'ScrollBar', 'Create scroll bar'),
|
||||
(ID_NEW.TREE_CTRL, 'TreeCtrl', 'Create tree'),
|
||||
(ID_NEW.LIST_CTRL, 'ListCtrl', 'Create list'),
|
||||
# (ID_NEW.GRID, 'Grid', 'Create grid'),
|
||||
(ID_NEW.SCROLLED_WINDOW, 'ScrolledWindow', 'Create scrolled window'),
|
||||
(ID_NEW.HTML_WINDOW, 'HtmlWindow', 'Create HTML window'),
|
||||
(ID_NEW.CALENDAR_CTRL, 'CalendarCtrl', 'Create calendar 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.UNKNOWN, 'Unknown', 'Create custom control placeholder'),
|
||||
],
|
||||
@@ -370,7 +380,13 @@ class PullDownMenu:
|
||||
ID_NEW.HELP_BUTTON: ('wxID_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.SetBackgroundColour(wx.RED)
|
||||
self.lines = [l1, l2, l3, l4]
|
||||
self.size = size
|
||||
# Move highlight to a new position
|
||||
def Replace(self, pos, size):
|
||||
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[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.size = size
|
||||
# Remove it
|
||||
def Remove(self):
|
||||
map(wx.Window.Destroy, self.lines)
|
||||
@@ -428,8 +446,12 @@ class HighLightBox:
|
||||
|
||||
class XML_Tree(wx.TreeCtrl):
|
||||
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.fontComment = wx.FFont(self.GetFont().GetPointSize(),
|
||||
self.GetFont().GetFamily(),
|
||||
wx.FONTFLAG_ITALIC)
|
||||
# Register events
|
||||
wx.EVT_TREE_SEL_CHANGED(self, self.GetId(), self.OnSelChanged)
|
||||
# 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_TREE_ITEM_EXPANDED(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.selectionChanging = False
|
||||
@@ -450,6 +474,7 @@ class XML_Tree(wx.TreeCtrl):
|
||||
# Create image list
|
||||
il = wx.ImageList(16, 16, True)
|
||||
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())
|
||||
xxxPanel.image = il.Add(images.getTreePanelImage().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(),
|
||||
image=treeObj.treeImage(),
|
||||
data=wx.TreeItemData(xxx))
|
||||
# Different color for references
|
||||
if treeObj.ref:
|
||||
# Different color for comments and references
|
||||
if xxx.className == 'comment':
|
||||
self.SetItemTextColour(item, 'Blue')
|
||||
self.SetItemFont(item, self.fontComment)
|
||||
elif treeObj.ref:
|
||||
self.SetItemTextColour(item, 'DarkGreen')
|
||||
elif treeObj.hasStyle and treeObj.params.get('hidden', False):
|
||||
self.SetItemTextColour(item, 'Grey')
|
||||
# Try to find children objects
|
||||
if treeObj.hasChildren:
|
||||
nodes = treeObj.element.childNodes[:]
|
||||
nodes = treeObj.node.childNodes[:]
|
||||
for n in nodes:
|
||||
if IsObject(n):
|
||||
self.AddNode(item, treeObj, n)
|
||||
elif n.nodeType != minidom.Node.ELEMENT_NODE:
|
||||
treeObj.element.removeChild(n)
|
||||
treeObj.node.removeChild(n)
|
||||
n.unlink()
|
||||
|
||||
# Insert new item at specific position
|
||||
@@ -581,23 +609,30 @@ class XML_Tree(wx.TreeCtrl):
|
||||
xxx = MakeXXXFromDOM(parent, elem)
|
||||
# If nextItem is None, we append to parent, otherwise insert before it
|
||||
if nextItem.IsOk():
|
||||
node = self.GetPyData(nextItem).element
|
||||
parent.element.insertBefore(elem, node)
|
||||
node = self.GetPyData(nextItem).node
|
||||
parent.node.insertBefore(elem, node)
|
||||
# Inserting before is difficult, se we insert after or first child
|
||||
index = self.ItemIndex(nextItem)
|
||||
newItem = self.InsertItemBefore(itemParent, index,
|
||||
xxx.treeName(), image=xxx.treeImage())
|
||||
self.SetPyData(newItem, xxx)
|
||||
else:
|
||||
parent.element.appendChild(elem)
|
||||
parent.node.appendChild(elem)
|
||||
newItem = self.AppendItem(itemParent, xxx.treeName(), image=xxx.treeImage(),
|
||||
data=wx.TreeItemData(xxx))
|
||||
# Different color for references
|
||||
if xxx.treeObject().ref: self.SetItemTextColour(newItem, 'DarkGreen')
|
||||
treeObj = xxx.treeObject()
|
||||
# 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
|
||||
if xxx.hasChildren:
|
||||
treeObj = xxx.treeObject()
|
||||
for n in treeObj.element.childNodes:
|
||||
for n in treeObj.node.childNodes:
|
||||
if IsObject(n):
|
||||
self.AddNode(newItem, treeObj, n)
|
||||
return newItem
|
||||
@@ -605,13 +640,14 @@ class XML_Tree(wx.TreeCtrl):
|
||||
# Remove leaf of tree, return it's data object
|
||||
def RemoveLeaf(self, leaf):
|
||||
xxx = self.GetPyData(leaf)
|
||||
node = xxx.element
|
||||
node = xxx.node
|
||||
parent = node.parentNode
|
||||
parent.removeChild(node)
|
||||
self.Delete(leaf)
|
||||
# Reset selection object
|
||||
self.selection = None
|
||||
return node
|
||||
|
||||
# Find position relative to the top-level window
|
||||
def FindNodePos(self, item, obj=None):
|
||||
# Root at (0,0)
|
||||
@@ -631,17 +667,18 @@ class XML_Tree(wx.TreeCtrl):
|
||||
if g.testWin.highLight:
|
||||
g.testWin.highLight.Remove()
|
||||
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
|
||||
while self.GetPyData(winParent).isSizer:
|
||||
winParent = self.GetItemParent(winParent)
|
||||
# Notebook children are layed out in a little strange way
|
||||
# wxGTK places NB panels relative to the NB parent
|
||||
if wx.Platform == '__WXGTK__':
|
||||
if self.GetPyData(itemParent).treeObject().__class__ == xxxNotebook:
|
||||
parentPos = wx.Point(0,0)
|
||||
else:
|
||||
winParent = self.GetItemParent(winParent)
|
||||
parentPos = self.FindNodePos(winParent)
|
||||
# Position (-1,-1) is really (0,0)
|
||||
pos = obj.GetPosition()
|
||||
# Position (-1,-1) is really (0,0)
|
||||
if pos == (-1,-1): pos = (0,0)
|
||||
return parentPos + pos
|
||||
|
||||
@@ -700,7 +737,6 @@ class XML_Tree(wx.TreeCtrl):
|
||||
# If some data was modified, apply changes
|
||||
if g.panel.IsModified():
|
||||
self.Apply(xxx, oldItem)
|
||||
#if conf.autoRefresh:
|
||||
if g.testWin:
|
||||
if g.testWin.highLight:
|
||||
g.testWin.highLight.Remove()
|
||||
@@ -751,12 +787,18 @@ class XML_Tree(wx.TreeCtrl):
|
||||
size = obj.GetSize()
|
||||
# Highlight
|
||||
# Negative positions are not working quite well
|
||||
if g.testWin.highLight:
|
||||
g.testWin.highLight.Replace(pos, size)
|
||||
hl = g.testWin.highLight
|
||||
# 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:
|
||||
g.testWin.highLight = HighLightBox(pos, size)
|
||||
g.testWin.highLight.Refresh()
|
||||
g.testWin.highLight.item = item
|
||||
g.testWin.highLight = hl = HighLightBox(pos, size)
|
||||
hl.Refresh()
|
||||
hl.item = item
|
||||
|
||||
def ShowTestWindow(self, item):
|
||||
xxx = self.GetPyData(item)
|
||||
@@ -774,7 +816,7 @@ class XML_Tree(wx.TreeCtrl):
|
||||
return
|
||||
# Show item in bold
|
||||
if g.testWin: # Reset old
|
||||
self.Unselect()
|
||||
self.UnselectAll()
|
||||
self.SetItemBold(g.testWin.item, False)
|
||||
try:
|
||||
wx.BeginBusyCursor()
|
||||
@@ -810,19 +852,6 @@ class XML_Tree(wx.TreeCtrl):
|
||||
testWin = g.testWin
|
||||
# Create a window with this resource
|
||||
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
|
||||
highLight = None
|
||||
if testWin:
|
||||
@@ -848,7 +877,7 @@ class XML_Tree(wx.TreeCtrl):
|
||||
# Save in memory FS
|
||||
memFile = MemoryFile('xxx.xrc')
|
||||
# Create memory XML file
|
||||
elem = xxx.element.cloneNode(True)
|
||||
elem = xxx.node.cloneNode(True)
|
||||
if not xxx.name:
|
||||
name = 'noname'
|
||||
else:
|
||||
@@ -877,6 +906,10 @@ class XML_Tree(wx.TreeCtrl):
|
||||
if not g.currentEncoding:
|
||||
xmlFlags != xrc.XRC_USE_LOCALE
|
||||
res = xrc.XmlResource('', xmlFlags)
|
||||
xrc.XmlResource.Set(res) # set as global
|
||||
# Register handlers
|
||||
addHandlers()
|
||||
# Same module list
|
||||
res.Load('memory:xxx.xrc')
|
||||
try:
|
||||
if xxx.__class__ == xxxFrame:
|
||||
@@ -907,7 +940,7 @@ class XML_Tree(wx.TreeCtrl):
|
||||
testWin.SetClientSize(testWin.GetBestSize())
|
||||
testWin.Show(True)
|
||||
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.Layout()
|
||||
testWin.SetPosition(pos)
|
||||
@@ -917,7 +950,7 @@ class XML_Tree(wx.TreeCtrl):
|
||||
wx.EVT_BUTTON(testWin, wx.ID_CANCEL, self.OnCloseTestWin)
|
||||
elif xxx.__class__ == xxxWizard:
|
||||
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)
|
||||
firstPage = None
|
||||
for w in wiz.GetChildren():
|
||||
@@ -959,9 +992,11 @@ class XML_Tree(wx.TreeCtrl):
|
||||
testWin.toolBar = res.LoadToolBar(testWin, STD_NAME)
|
||||
testWin.SetToolBar(testWin.toolBar)
|
||||
testWin.Show(True)
|
||||
# Catch some events, set highlight
|
||||
if testWin:
|
||||
testWin.item = item
|
||||
wx.EVT_CLOSE(testWin, self.OnCloseTestWin)
|
||||
wx.EVT_SIZE(testWin, self.OnSizeTestWin)
|
||||
testWin.highLight = None
|
||||
if highLight and not self.pendingHighLight:
|
||||
self.HighLight(highLight)
|
||||
@@ -974,6 +1009,9 @@ class XML_Tree(wx.TreeCtrl):
|
||||
inf = sys.exc_info()
|
||||
wx.LogError(traceback.format_exception(inf[0], inf[1], None)[-1])
|
||||
wx.LogError('Error loading resource')
|
||||
# Cleanup
|
||||
res.Unload('xxx.xrc')
|
||||
xrc.XmlResource.Set(None)
|
||||
wx.MemoryFSHandler.RemoveFile('xxx.xrc')
|
||||
|
||||
def CloseTestWindow(self):
|
||||
@@ -987,6 +1025,11 @@ class XML_Tree(wx.TreeCtrl):
|
||||
def OnCloseTestWin(self, evt):
|
||||
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
|
||||
def WindowIndex(self, item):
|
||||
n = 0 # index of sibling
|
||||
@@ -1068,6 +1111,7 @@ class XML_Tree(wx.TreeCtrl):
|
||||
SetMenu(m, pullDownMenu.topLevel)
|
||||
m.AppendSeparator()
|
||||
m.Append(ID_NEW.REF, 'reference...', 'Create object_ref node')
|
||||
m.Append(ID_NEW.COMMENT, 'comment', 'Create comment node')
|
||||
else:
|
||||
xxx = self.GetPyData(item).treeObject()
|
||||
# Check parent for possible child nodes if inserting sibling
|
||||
@@ -1089,8 +1133,12 @@ class XML_Tree(wx.TreeCtrl):
|
||||
m.Enable(ID_NEW.SPACER, False)
|
||||
if xxx.__class__ is not xxxFrame:
|
||||
m.Enable(ID_NEW.MENU_BAR, False)
|
||||
# Add custom controls menu
|
||||
if len(pullDownMenu.custom) > 2:
|
||||
SetMenu(m, [pullDownMenu.custom])
|
||||
m.AppendSeparator()
|
||||
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
|
||||
if not needInsert:
|
||||
if self.shift:
|
||||
@@ -1126,6 +1174,7 @@ class XML_Tree(wx.TreeCtrl):
|
||||
SetMenu(m, pullDownMenu.sizers, shift=True)
|
||||
else:
|
||||
SetMenu(m, pullDownMenu.controls, shift=True)
|
||||
if xxx.isElement:
|
||||
id = wx.NewId()
|
||||
menu.AppendMenu(id, 'Replace With', m)
|
||||
if not m.GetMenuItemCount(): menu.Enable(id, False)
|
||||
@@ -1165,9 +1214,25 @@ class XML_Tree(wx.TreeCtrl):
|
||||
# Item width may have changed
|
||||
# !!! Tric to update tree width (wxGTK, ??)
|
||||
self.SetIndent(self.GetIndent())
|
||||
elif xxx.className == 'comment':
|
||||
self.SetItemText(item, xxx.treeName())
|
||||
# Change tree icon for sizers
|
||||
if isinstance(xxx, xxxBoxSizer):
|
||||
self.SetItemImage(item, xxx.treeImage())
|
||||
# Set global modified state
|
||||
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()
|
||||
|
@@ -134,11 +134,11 @@ class UndoReplace:
|
||||
item = g.tree.ItemAtFullIndex(self.itemIndex)
|
||||
xxx = g.tree.GetPyData(item)
|
||||
# Replace with old element
|
||||
parent = xxx.parent.element
|
||||
parent = xxx.parent.node
|
||||
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:
|
||||
parent.replaceChild(self.xxx.element, xxx.element)
|
||||
parent.replaceChild(self.xxx.node, xxx.node)
|
||||
self.xxx.parent = xxx.parent
|
||||
xxx = self.xxx
|
||||
g.tree.SetPyData(item, xxx)
|
||||
@@ -191,9 +191,9 @@ class UndoMove:
|
||||
((parent.isSizer and not isinstance(xxx, xxxSizerItem)) or \
|
||||
(isinstance(parent, xxxNotebook) and not isinstance(xxx, xxxNotebookPage)) or \
|
||||
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 = xxx.child.element # replace
|
||||
elem = xxx.child.node # replace
|
||||
# This may help garbage collection
|
||||
xxx.child.parent = None
|
||||
isChildContainer = False
|
||||
@@ -227,9 +227,9 @@ class UndoMove:
|
||||
((parent.isSizer and not isinstance(xxx, xxxSizerItem)) or \
|
||||
(isinstance(parent, xxxNotebook) and not isinstance(xxx, xxxNotebookPage)) or \
|
||||
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 = xxx.child.element # replace
|
||||
elem = xxx.child.node # replace
|
||||
# This may help garbage collection
|
||||
xxx.child.parent = None
|
||||
isChildContainer = False
|
||||
|
@@ -40,9 +40,14 @@ if __name__ == '__main__':
|
||||
else:
|
||||
basePath = os.path.dirname(__file__)
|
||||
|
||||
# Remember system path
|
||||
sys_path = sys.path
|
||||
|
||||
# 1 adds CMD command to Help menu
|
||||
debug = 0
|
||||
|
||||
import xxx
|
||||
|
||||
g.helpText = """\
|
||||
<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>
|
||||
@@ -51,7 +56,7 @@ select "Append Child", and then any command.<P>
|
||||
Or just press one of the buttons on the tools palette.<P>
|
||||
Enter XML ID, change properties, create children.<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',
|
||||
@@ -71,13 +76,13 @@ class ScrolledMessageDialog(wx.Dialog):
|
||||
wx.DefaultSize, wx.TE_MULTILINE | wx.TE_READONLY)
|
||||
text.SetFont(g.modernFont())
|
||||
dc = wx.WindowDC(text)
|
||||
# !!! possible bug - GetTextExtent without font returns sysfont dims
|
||||
w, h = dc.GetFullTextExtent(' ', g.modernFont())[:2]
|
||||
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.SetSize((w * 80 + 30, h * 40))
|
||||
text.ShowPosition(1)
|
||||
ok.SetConstraints(Layoutf('b=b5#1;x%w50#1;w!80;h!25', (self,)))
|
||||
text.ShowPosition(1) # scroll to the first line
|
||||
ok.SetConstraints(Layoutf('b=b5#1;x%w50#1;w!80;h!35', (self,)))
|
||||
self.SetAutoLayout(True)
|
||||
self.Fit()
|
||||
self.CenterOnScreen(wx.BOTH)
|
||||
@@ -102,7 +107,7 @@ class Frame(wx.Frame):
|
||||
self.inIdle = False
|
||||
|
||||
# Load our own resources
|
||||
self.res = xrc.XmlResource('')
|
||||
self.res = xrc.EmptyXmlResource()
|
||||
# !!! Blocking of assert failure occurring in older unicode builds
|
||||
try:
|
||||
quietlog = wx.LogNull()
|
||||
@@ -127,6 +132,9 @@ class Frame(wx.Frame):
|
||||
menu.Append(self.ID_GENERATE_PYTHON, '&Generate Python...',
|
||||
'Generate a Python module that uses this XRC')
|
||||
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')
|
||||
|
||||
menuBar.Append(menu, '&File')
|
||||
@@ -161,11 +169,11 @@ class Frame(wx.Frame):
|
||||
self.ID_REFRESH = wx.NewId()
|
||||
menu.Append(self.ID_REFRESH, '&Refresh\tCtrl-R', 'Refresh test window')
|
||||
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)
|
||||
menu.Check(self.ID_AUTO_REFRESH, conf.autoRefresh)
|
||||
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')
|
||||
|
||||
menu = wx.Menu()
|
||||
@@ -182,7 +190,7 @@ class Frame(wx.Frame):
|
||||
menu = wx.Menu()
|
||||
menu.Append(wx.ID_ABOUT, '&About...', 'About XCRed')
|
||||
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:
|
||||
self.ID_DEBUG_CMD = wx.NewId()
|
||||
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_SAVEAS, self.OnSaveOrSaveAs)
|
||||
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)
|
||||
# Edit
|
||||
wx.EVT_MENU(self, wx.ID_UNDO, self.OnUndo)
|
||||
@@ -311,9 +320,8 @@ class Frame(wx.Frame):
|
||||
|
||||
tree.RegisterKeyEvents()
|
||||
|
||||
# !!! frame styles are broken
|
||||
# Miniframe for not embedded mode
|
||||
miniFrame = wx.Frame(self, -1, 'Properties & Style',
|
||||
# Miniframe for split mode
|
||||
miniFrame = wx.MiniFrame(self, -1, 'Properties & Style',
|
||||
(conf.panelX, conf.panelY),
|
||||
(conf.panelWidth, conf.panelHeight))
|
||||
self.miniFrame = miniFrame
|
||||
@@ -337,9 +345,6 @@ class Frame(wx.Frame):
|
||||
self.SetAutoLayout(True)
|
||||
self.SetSizer(sizer)
|
||||
|
||||
# Initialize
|
||||
self.Clear()
|
||||
|
||||
# Other events
|
||||
wx.EVT_IDLE(self, self.OnIdle)
|
||||
wx.EVT_CLOSE(self, self.OnCloseWindow)
|
||||
@@ -472,6 +477,17 @@ class Frame(wx.Frame):
|
||||
dlg.ShowModal()
|
||||
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):
|
||||
self.Close()
|
||||
@@ -480,20 +496,28 @@ class Frame(wx.Frame):
|
||||
# Extra check to not mess with idle updating
|
||||
if undoMan.CanUndo():
|
||||
undoMan.Undo()
|
||||
g.panel.SetModified(False)
|
||||
if not undoMan.CanUndo():
|
||||
self.SetModified(False)
|
||||
|
||||
def OnRedo(self, evt):
|
||||
if undoMan.CanRedo():
|
||||
undoMan.Redo()
|
||||
self.SetModified(True)
|
||||
|
||||
def OnCopy(self, evt):
|
||||
selected = tree.selection
|
||||
if not selected: return # key pressed event
|
||||
xxx = tree.GetPyData(selected)
|
||||
if wx.TheClipboard.Open():
|
||||
if xxx.isElement:
|
||||
data = wx.CustomDataObject('XRCED')
|
||||
# Set encoding in header
|
||||
# (False,True)
|
||||
s = xxx.element.toxml(encoding=expat.native_encoding)
|
||||
s = xxx.node.toxml(encoding=expat.native_encoding)
|
||||
else:
|
||||
data = wx.CustomDataObject('XRCED_node')
|
||||
s = xxx.node.data
|
||||
data.SetData(cPickle.dumps(s))
|
||||
wx.TheClipboard.SetData(data)
|
||||
wx.TheClipboard.Close()
|
||||
@@ -528,21 +552,35 @@ class Frame(wx.Frame):
|
||||
parent = tree.GetPyData(parentLeaf).treeObject()
|
||||
|
||||
# Create a copy of clipboard pickled element
|
||||
success = False
|
||||
success = success_node = False
|
||||
if wx.TheClipboard.Open():
|
||||
try:
|
||||
data = wx.CustomDataObject('XRCED')
|
||||
if wx.TheClipboard.IsSupported(data.GetFormat()):
|
||||
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(
|
||||
"There is no data in the clipboard in the required format",
|
||||
"Error")
|
||||
return
|
||||
|
||||
xml = cPickle.loads(data.GetData()) # xml representation of element
|
||||
if success:
|
||||
elem = minidom.parseString(xml).childNodes[0]
|
||||
else:
|
||||
elem = g.tree.dom.createComment(xml)
|
||||
|
||||
# Tempopary xxx object to test things
|
||||
xxx = MakeXXXFromDOM(parent, elem)
|
||||
@@ -559,9 +597,9 @@ class Frame(wx.Frame):
|
||||
((parent.isSizer and not isinstance(xxx, xxxSizerItem)) or \
|
||||
(parentIsBook and not isinstance(xxx, xxxPage)) or \
|
||||
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 = xxx.child.element # replace
|
||||
elem = xxx.child.node # replace
|
||||
# This may help garbage collection
|
||||
xxx.child.parent = None
|
||||
isChildContainer = False
|
||||
@@ -606,6 +644,9 @@ class Frame(wx.Frame):
|
||||
def ItemsAreCompatible(self, parent, child):
|
||||
# Check compatibility
|
||||
error = False
|
||||
# Comments are always compatible
|
||||
if child.__class__ == xxxComment:
|
||||
return True
|
||||
# Top-level
|
||||
if child.__class__ in [xxxDialog, xxxFrame, xxxWizard]:
|
||||
# Top-level classes
|
||||
@@ -733,9 +774,9 @@ class Frame(wx.Frame):
|
||||
((parent.isSizer and not isinstance(xxx, xxxSizerItem)) or \
|
||||
(isinstance(parent, xxxNotebook) and not isinstance(xxx, xxxNotebookPage)) or \
|
||||
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 = xxx.child.element # replace
|
||||
elem = xxx.child.node # replace
|
||||
# This may help garbage collection
|
||||
xxx.child.parent = None
|
||||
isChildContainer = False
|
||||
@@ -790,9 +831,9 @@ class Frame(wx.Frame):
|
||||
((parent.isSizer and not isinstance(xxx, xxxSizerItem)) or \
|
||||
(isinstance(parent, xxxNotebook) and not isinstance(xxx, xxxNotebookPage)) or \
|
||||
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 = xxx.child.element # replace
|
||||
elem = xxx.child.node # replace
|
||||
# This may help garbage collection
|
||||
xxx.child.parent = None
|
||||
isChildContainer = False
|
||||
@@ -842,14 +883,19 @@ class Frame(wx.Frame):
|
||||
# Prepare undo data
|
||||
panel.Apply()
|
||||
index = tree.ItemFullIndex(selected)
|
||||
xxx = tree.GetPyData(selected)
|
||||
parent = tree.GetPyData(tree.GetItemParent(selected)).treeObject()
|
||||
elem = tree.RemoveLeaf(selected)
|
||||
undoMan.RegisterUndo(UndoCutDelete(index, parent, elem))
|
||||
if evt.GetId() == wx.ID_CUT:
|
||||
if wx.TheClipboard.Open():
|
||||
if xxx.isElement:
|
||||
data = wx.CustomDataObject('XRCED')
|
||||
# (False, True)
|
||||
s = elem.toxml(encoding=expat.native_encoding)
|
||||
else:
|
||||
data = wx.CustomDataObject('XRCED_node')
|
||||
s = xxx.node.data
|
||||
data.SetData(cPickle.dumps(s))
|
||||
wx.TheClipboard.SetData(data)
|
||||
wx.TheClipboard.Close()
|
||||
@@ -867,7 +913,7 @@ class Frame(wx.Frame):
|
||||
def OnSubclass(self, evt):
|
||||
selected = tree.selection
|
||||
xxx = tree.GetPyData(selected).treeObject()
|
||||
elem = xxx.element
|
||||
elem = xxx.node
|
||||
subclass = xxx.subclass
|
||||
dlg = wx.TextEntryDialog(self, 'Subclass:', defaultValue=subclass)
|
||||
if dlg.ShowModal() == wx.ID_OK:
|
||||
@@ -910,6 +956,7 @@ class Frame(wx.Frame):
|
||||
self.miniFrame.Show(True)
|
||||
self.miniFrame.SetDimensions(conf.panelX, conf.panelY,
|
||||
conf.panelWidth, conf.panelHeight)
|
||||
self.miniFrame.Layout()
|
||||
# Reduce width
|
||||
self.SetDimensions(pos.x, pos.y,
|
||||
max(size.width - sizePanel.width, self.minWidth), size.height)
|
||||
@@ -1063,11 +1110,18 @@ Homepage: http://xrced.sourceforge.net\
|
||||
ref = wx.GetTextFromUser('Create reference to:', 'Create reference')
|
||||
if not ref: return
|
||||
xxx = MakeEmptyRefXXX(parent, ref)
|
||||
elif evt.GetId() == ID_NEW.COMMENT:
|
||||
xxx = MakeEmptyCommentXXX(parent)
|
||||
else:
|
||||
# Create empty element
|
||||
if evt.GetId() >= ID_NEW.CUSTOM:
|
||||
className = pullDownMenu.customMap[evt.GetId()]
|
||||
else:
|
||||
className = pullDownMenu.createMap[evt.GetId()]
|
||||
xxx = MakeEmptyXXX(parent, className)
|
||||
|
||||
# Insert new node, register undo
|
||||
if xxx.isElement: # true object
|
||||
# Set default name for top-level windows
|
||||
if parent.__class__ == xxxMainNode:
|
||||
cl = xxx.treeObject().__class__
|
||||
@@ -1081,11 +1135,11 @@ Homepage: http://xrced.sourceforge.net\
|
||||
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)
|
||||
xxx.treeObject().node.appendChild(elem)
|
||||
|
||||
# Insert new node, register undo
|
||||
elem = xxx.element
|
||||
newItem = tree.InsertNode(parentLeaf, parent, elem, nextItem)
|
||||
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))
|
||||
tree.EnsureVisible(newItem)
|
||||
tree.SelectItem(newItem)
|
||||
@@ -1093,20 +1147,22 @@ Homepage: http://xrced.sourceforge.net\
|
||||
tree.ScrollTo(newItem)
|
||||
tree.Refresh()
|
||||
# Update view?
|
||||
if g.testWin and tree.IsHighlatable(newItem):
|
||||
if xxx.isElement and g.testWin and tree.IsHighlatable(newItem):
|
||||
if conf.autoRefresh:
|
||||
tree.needUpdate = True
|
||||
tree.pendingHighLight = newItem
|
||||
else:
|
||||
tree.pendingHighLight = None
|
||||
tree.SetFocus()
|
||||
if not xxx.isElement:
|
||||
tree.EditLabel(newItem)
|
||||
self.SetModified()
|
||||
|
||||
# Replace one object with another
|
||||
def OnReplace(self, evt):
|
||||
selected = tree.selection
|
||||
xxx = tree.GetPyData(selected).treeObject()
|
||||
elem = xxx.element
|
||||
elem = xxx.node
|
||||
parent = elem.parentNode
|
||||
undoMan.RegisterUndo(UndoReplace(selected))
|
||||
# New class
|
||||
@@ -1285,6 +1341,7 @@ Homepage: http://xrced.sourceforge.net\
|
||||
return
|
||||
|
||||
def OnIconize(self, evt):
|
||||
if evt.Iconized():
|
||||
conf.x, conf.y = self.GetPosition()
|
||||
conf.width, conf.height = self.GetSize()
|
||||
if conf.embedPanel:
|
||||
@@ -1293,6 +1350,9 @@ Homepage: http://xrced.sourceforge.net\
|
||||
conf.panelX, conf.panelY = self.miniFrame.GetPosition()
|
||||
conf.panelWidth, conf.panelHeight = self.miniFrame.GetSize()
|
||||
self.miniFrame.Iconize()
|
||||
else:
|
||||
if not conf.embedPanel:
|
||||
self.miniFrame.Iconize(False)
|
||||
evt.Skip()
|
||||
|
||||
def OnCloseWindow(self, evt):
|
||||
@@ -1313,13 +1373,11 @@ Homepage: http://xrced.sourceforge.net\
|
||||
conf.panelWidth, conf.panelHeight = self.miniFrame.GetSize()
|
||||
evt.Skip()
|
||||
|
||||
|
||||
def CreateLocalConf(self, path):
|
||||
name = os.path.splitext(path)[0]
|
||||
name += '.xcfg'
|
||||
return wx.FileConfig(localFilename=name)
|
||||
|
||||
|
||||
def Clear(self):
|
||||
self.dataFile = ''
|
||||
conf.localconf = None
|
||||
@@ -1336,6 +1394,13 @@ Homepage: http://xrced.sourceforge.net\
|
||||
xxxMenuBar, xxxMenu, xxxToolBar,
|
||||
xxxWizard, xxxBitmap, xxxIcon]:
|
||||
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):
|
||||
self.modified = state
|
||||
@@ -1366,6 +1431,8 @@ Homepage: http://xrced.sourceforge.net\
|
||||
self.dataFile = path = os.path.abspath(path)
|
||||
dir = os.path.dirname(path)
|
||||
if dir: os.chdir(dir)
|
||||
# Allow importing modules from the same directory
|
||||
sys.path = sys_path + [dir]
|
||||
tree.SetData(dom)
|
||||
self.SetTitle(progname + ': ' + os.path.basename(path))
|
||||
conf.localconf = self.CreateLocalConf(self.dataFile)
|
||||
@@ -1379,6 +1446,10 @@ Homepage: http://xrced.sourceforge.net\
|
||||
return True
|
||||
|
||||
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
|
||||
children = node.childNodes[:]
|
||||
# Main node doesn't need to be indented
|
||||
@@ -1392,7 +1463,8 @@ Homepage: http://xrced.sourceforge.net\
|
||||
node.appendChild(text)
|
||||
# Indent children which are elements
|
||||
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)
|
||||
|
||||
def Save(self, path):
|
||||
@@ -1446,9 +1518,6 @@ Homepage: http://xrced.sourceforge.net\
|
||||
return True
|
||||
return False
|
||||
|
||||
def SaveUndo(self):
|
||||
pass # !!!
|
||||
|
||||
################################################################################
|
||||
|
||||
class PythonOptions(wx.Dialog):
|
||||
@@ -1515,14 +1584,88 @@ class PythonOptions(wx.Dialog):
|
||||
|
||||
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():
|
||||
print >> sys.stderr, 'usage: xrced [-dhiv] [file]'
|
||||
|
||||
class App(wx.App):
|
||||
from wx.lib.mixins.inspection import InspectableApp
|
||||
class App(InspectableApp):
|
||||
def OnInit(self):
|
||||
self.Init()
|
||||
# Check version
|
||||
if wx.VERSION[:3] < MinWxVersion:
|
||||
wx.LogWarning('''\
|
||||
@@ -1574,12 +1717,47 @@ Please upgrade wxWidgets to %d.%d.%d or higher.''' % MinWxVersion)
|
||||
conf.panelWidth = conf.ReadInt('panelWidth', 200)
|
||||
conf.panelHeight = conf.ReadInt('panelHeight', 200)
|
||||
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
|
||||
wx.FileSystem.AddHandler(wx.MemoryFSHandler())
|
||||
# Create main frame
|
||||
frame = Frame(pos, size)
|
||||
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
|
||||
if args:
|
||||
conf.panic = False
|
||||
@@ -1604,8 +1782,16 @@ Please upgrade wxWidgets to %d.%d.%d or higher.''' % MinWxVersion)
|
||||
wc.WriteInt('sashPos', conf.sashPos)
|
||||
wc.WriteInt('panelWidth', conf.panelWidth)
|
||||
wc.WriteInt('panelHeight', conf.panelHeight)
|
||||
wc.WriteInt('nopanic', True)
|
||||
wc.WriteInt('nopanic', 1)
|
||||
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()
|
||||
|
||||
def main():
|
||||
|
@@ -10,6 +10,7 @@
|
||||
<orient>wxHORIZONTAL</orient>
|
||||
<object class="sizeritem">
|
||||
<object class="wxTextCtrl" name="TEXT">
|
||||
<value></value>
|
||||
<size>250,100</size>
|
||||
<style>wxTE_MULTILINE</style>
|
||||
</object>
|
||||
@@ -22,23 +23,17 @@
|
||||
<flag>wxEXPAND</flag>
|
||||
</object>
|
||||
<object class="sizeritem">
|
||||
<object class="wxStaticLine"/>
|
||||
<flag>wxEXPAND</flag>
|
||||
</object>
|
||||
<object class="sizeritem">
|
||||
<object class="wxBoxSizer">
|
||||
<orient>wxHORIZONTAL</orient>
|
||||
<object class="sizeritem">
|
||||
<object class="wxStdDialogButtonSizer">
|
||||
<object class="button">
|
||||
<object class="wxButton" name="wxID_OK">
|
||||
<label>OK</label>
|
||||
<default>1</default>
|
||||
<label></label>
|
||||
<label>&Ok</label>
|
||||
</object>
|
||||
<flag>wxRIGHT</flag>
|
||||
<border>10</border>
|
||||
</object>
|
||||
<object class="sizeritem">
|
||||
<object class="button">
|
||||
<object class="wxButton" name="wxID_CANCEL">
|
||||
<label>Cancel</label>
|
||||
<label></label>
|
||||
<label>&Cancel</label>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
@@ -191,24 +186,21 @@
|
||||
<option>1</option>
|
||||
<flag>wxEXPAND</flag>
|
||||
</object>
|
||||
<object class="sizeritem">
|
||||
<object class="wxStaticLine"/>
|
||||
<flag>wxEXPAND</flag>
|
||||
<object class="spacer">
|
||||
<size>0,10</size>
|
||||
</object>
|
||||
<object class="sizeritem">
|
||||
<object class="wxBoxSizer">
|
||||
<orient>wxHORIZONTAL</orient>
|
||||
<object class="sizeritem">
|
||||
<object class="wxStdDialogButtonSizer">
|
||||
<object class="button">
|
||||
<object class="wxButton" name="wxID_OK">
|
||||
<label>OK</label>
|
||||
<default>1</default>
|
||||
<label></label>
|
||||
<label>&Ok</label>
|
||||
</object>
|
||||
<flag>wxRIGHT</flag>
|
||||
<border>10</border>
|
||||
</object>
|
||||
<object class="sizeritem">
|
||||
<object class="button">
|
||||
<object class="wxButton" name="wxID_CANCEL">
|
||||
<label>Cancel</label>
|
||||
<label></label>
|
||||
<label>&Cancel</label>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
@@ -233,24 +225,21 @@
|
||||
<flag>wxALL|wxEXPAND</flag>
|
||||
<border>5</border>
|
||||
</object>
|
||||
<object class="sizeritem">
|
||||
<object class="wxStaticLine"/>
|
||||
<flag>wxEXPAND</flag>
|
||||
<object class="spacer">
|
||||
<size>0,10</size>
|
||||
</object>
|
||||
<object class="sizeritem">
|
||||
<object class="wxBoxSizer">
|
||||
<orient>wxHORIZONTAL</orient>
|
||||
<object class="sizeritem">
|
||||
<object class="wxStdDialogButtonSizer">
|
||||
<object class="button">
|
||||
<object class="wxButton" name="wxID_OK">
|
||||
<label>OK</label>
|
||||
<default>1</default>
|
||||
<label></label>
|
||||
<label>&Ok</label>
|
||||
</object>
|
||||
<flag>wxRIGHT</flag>
|
||||
<border>10</border>
|
||||
</object>
|
||||
<object class="sizeritem">
|
||||
<object class="button">
|
||||
<object class="wxButton" name="wxID_CANCEL">
|
||||
<label>Cancel</label>
|
||||
<label></label>
|
||||
<label>&Cancel</label>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
@@ -261,7 +250,7 @@
|
||||
<style>wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER</style>
|
||||
</object>
|
||||
<object class="wxDialog" name="DIALOG_STYLES">
|
||||
<title>Window styles</title>
|
||||
<title>Window Styles</title>
|
||||
<centered>1</centered>
|
||||
<object class="wxBoxSizer">
|
||||
<orient>wxVERTICAL</orient>
|
||||
@@ -299,24 +288,21 @@
|
||||
<flag>wxBOTTOM|wxLEFT|wxRIGHT|wxEXPAND</flag>
|
||||
<border>5</border>
|
||||
</object>
|
||||
<object class="sizeritem">
|
||||
<object class="wxStaticLine"/>
|
||||
<flag>wxEXPAND</flag>
|
||||
<object class="spacer">
|
||||
<size>0,10</size>
|
||||
</object>
|
||||
<object class="sizeritem">
|
||||
<object class="wxBoxSizer">
|
||||
<orient>wxHORIZONTAL</orient>
|
||||
<object class="sizeritem">
|
||||
<object class="wxStdDialogButtonSizer">
|
||||
<object class="button">
|
||||
<object class="wxButton" name="wxID_OK">
|
||||
<label>OK</label>
|
||||
<default>1</default>
|
||||
<label></label>
|
||||
<label>&Ok</label>
|
||||
</object>
|
||||
<flag>wxRIGHT</flag>
|
||||
<border>10</border>
|
||||
</object>
|
||||
<object class="sizeritem">
|
||||
<object class="button">
|
||||
<object class="wxButton" name="wxID_CANCEL">
|
||||
<label>Cancel</label>
|
||||
<label></label>
|
||||
<label>&Cancel</label>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
@@ -350,7 +336,7 @@
|
||||
<orient>wxVERTICAL</orient>
|
||||
<object class="sizeritem">
|
||||
<object class="wxSpinCtrl" name="SPIN">
|
||||
<size>20,-1d</size>
|
||||
<size>60,-1</size>
|
||||
</object>
|
||||
<flag>wxBOTTOM</flag>
|
||||
<border>5</border>
|
||||
@@ -381,25 +367,23 @@
|
||||
</object>
|
||||
<option>1</option>
|
||||
<flag>wxEXPAND</flag>
|
||||
<border>0</border>
|
||||
</object>
|
||||
<object class="spacer">
|
||||
<size>0,10</size>
|
||||
</object>
|
||||
<object class="sizeritem">
|
||||
<object class="wxStaticLine"/>
|
||||
<flag>wxEXPAND</flag>
|
||||
</object>
|
||||
<object class="sizeritem">
|
||||
<object class="wxBoxSizer">
|
||||
<orient>wxHORIZONTAL</orient>
|
||||
<object class="sizeritem">
|
||||
<object class="wxStdDialogButtonSizer">
|
||||
<object class="button">
|
||||
<object class="wxButton" name="wxID_OK">
|
||||
<label>OK</label>
|
||||
<default>1</default>
|
||||
<label></label>
|
||||
<label>&Ok</label>
|
||||
</object>
|
||||
<flag>wxRIGHT</flag>
|
||||
<border>10</border>
|
||||
</object>
|
||||
<object class="sizeritem">
|
||||
<object class="button">
|
||||
<object class="wxButton" name="wxID_CANCEL">
|
||||
<label>Cancel</label>
|
||||
<label></label>
|
||||
<label>&Cancel</label>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
@@ -619,4 +603,113 @@
|
||||
</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>&Ok</label>
|
||||
</object>
|
||||
</object>
|
||||
<object class="button">
|
||||
<object class="wxButton" name="wxID_CANCEL">
|
||||
<label></label>
|
||||
<label>&Cancel</label>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
<flag>wxALL|wxALIGN_CENTRE_HORIZONTAL</flag>
|
||||
<border>10</border>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</resource>
|
@@ -7,6 +7,7 @@
|
||||
from xml.dom import minidom
|
||||
from globals import *
|
||||
from params import *
|
||||
import traceback, types
|
||||
|
||||
# Base class for interface parameter classes
|
||||
class xxxNode:
|
||||
@@ -189,6 +190,7 @@ class xxxObject:
|
||||
hasStyle = True # almost everyone
|
||||
hasName = True # has name attribute?
|
||||
isSizer = hasChild = False
|
||||
isElement = True
|
||||
allParams = None # Some nodes have no parameters
|
||||
# Style parameters (all optional)
|
||||
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
|
||||
def __init__(self, parent, element, refElem=None):
|
||||
self.parent = parent
|
||||
self.element = element
|
||||
self.node = element
|
||||
self.refElem = refElem
|
||||
self.undo = None
|
||||
# Reference are dereferenced
|
||||
@@ -230,33 +232,32 @@ class xxxObject:
|
||||
if self.hasName: self.name = element.getAttribute('name')
|
||||
# Set parameters (text element children)
|
||||
self.params = {}
|
||||
nodes = element.childNodes[:]
|
||||
for node in nodes:
|
||||
if node.nodeType == minidom.Node.ELEMENT_NODE:
|
||||
tag = node.tagName
|
||||
for n in element.childNodes[:]:
|
||||
if n.nodeType == minidom.Node.ELEMENT_NODE:
|
||||
tag = n.tagName
|
||||
if tag in ['object', 'object_ref']:
|
||||
continue # do nothing for object children here
|
||||
elif tag not in self.allParams and tag not in self.styles:
|
||||
print 'WARNING: unknown parameter for %s: %s' % \
|
||||
(self.className, tag)
|
||||
elif tag in self.specials:
|
||||
self.special(tag, node)
|
||||
self.special(tag, n)
|
||||
elif tag == 'content':
|
||||
if self.className == 'wxCheckListBox':
|
||||
self.params[tag] = xxxParamContentCheckList(node)
|
||||
self.params[tag] = xxxParamContentCheckList(n)
|
||||
else:
|
||||
self.params[tag] = xxxParamContent(node)
|
||||
self.params[tag] = xxxParamContent(n)
|
||||
elif tag == 'font': # has children
|
||||
self.params[tag] = xxxParamFont(element, node)
|
||||
self.params[tag] = xxxParamFont(element, n)
|
||||
elif tag in self.bitmapTags:
|
||||
# Can have attributes
|
||||
self.params[tag] = xxxParamBitmap(node)
|
||||
self.params[tag] = xxxParamBitmap(n)
|
||||
else: # simple parameter
|
||||
self.params[tag] = xxxParam(node)
|
||||
elif node.nodeType == minidom.Node.TEXT_NODE and node.data.isspace():
|
||||
self.params[tag] = xxxParam(n)
|
||||
elif n.nodeType == minidom.Node.TEXT_NODE and n.data.isspace():
|
||||
# Remove empty text nodes
|
||||
element.removeChild(node)
|
||||
node.unlink()
|
||||
element.removeChild(n)
|
||||
n.unlink()
|
||||
|
||||
# Check that all required params are set
|
||||
for param in self.required:
|
||||
@@ -281,9 +282,9 @@ class xxxObject:
|
||||
break
|
||||
if found:
|
||||
nextTextElem = self.params[p].node
|
||||
self.element.insertBefore(elem, nextTextElem)
|
||||
self.node.insertBefore(elem, nextTextElem)
|
||||
else:
|
||||
self.element.appendChild(elem)
|
||||
self.node.appendChild(elem)
|
||||
else:
|
||||
wx.LogWarning('Required parameter %s of %s missing' %
|
||||
(param, self.className))
|
||||
@@ -313,7 +314,34 @@ class xxxObject:
|
||||
if self.hasChild: obj = self.child
|
||||
else: obj = self
|
||||
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
|
||||
def DoFindResource(parent, name, classname, recursive):
|
||||
@@ -360,7 +388,7 @@ class xxxParamFont(xxxObject, xxxNode):
|
||||
self.data = v
|
||||
def update(self, value):
|
||||
# `value' is a list of strings corresponding to all parameters
|
||||
elem = self.element
|
||||
elem = self.node
|
||||
# Remove old elements first
|
||||
childNodes = elem.childNodes[:]
|
||||
for node in childNodes: elem.removeChild(node)
|
||||
@@ -638,6 +666,16 @@ class xxxDateCtrl(xxxObject):
|
||||
winStyles = ['wxDP_DEFAULT', 'wxDP_SPIN', 'wxDP_DROPDOWN',
|
||||
'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
|
||||
|
||||
@@ -771,45 +809,11 @@ class xxxFlexGridSizer(xxxGridSizer):
|
||||
specials = ['growablecols', 'growablerows']
|
||||
allParams = ['cols', 'rows', 'vgap', 'hgap'] + specials
|
||||
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):
|
||||
specials = ['growablecols', 'growablerows']
|
||||
allParams = ['vgap', 'hgap'] + specials
|
||||
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.
|
||||
# Not shown in tree.
|
||||
@@ -843,7 +847,8 @@ class xxxChildContainer(xxxObject):
|
||||
class xxxSizerItem(xxxChildContainer):
|
||||
allParams = ['option', 'flag', 'border', 'minsize', 'ratio']
|
||||
paramDict = {'option': ParamInt, 'minsize': ParamPosSize, 'ratio': ParamPosSize}
|
||||
#default = {'cellspan': '1,1'}
|
||||
defaults_panel = {}
|
||||
defaults_control = {}
|
||||
def __init__(self, parent, element, refElem=None):
|
||||
# For GridBag sizer items, extra parameters added
|
||||
if isinstance(parent, xxxGridBagSizer):
|
||||
@@ -923,7 +928,143 @@ class xxxUnknown(xxxObject):
|
||||
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 = {
|
||||
'wxPanel': xxxPanel,
|
||||
'wxDialog': xxxDialog,
|
||||
@@ -973,6 +1114,8 @@ xxxDict = {
|
||||
'wxGenericDirCtrl': xxxGenericDirCtrl,
|
||||
'wxSpinCtrl': xxxSpinCtrl,
|
||||
'wxScrolledWindow': xxxScrolledWindow,
|
||||
'wxGrid': xxxGrid,
|
||||
'wxFilePickerCtrl': xxxFilePickerCtrl,
|
||||
'wxDatePickerCtrl': xxxDateCtrl,
|
||||
|
||||
'wxBoxSizer': xxxBoxSizer,
|
||||
@@ -990,13 +1133,15 @@ xxxDict = {
|
||||
'separator': xxxSeparator,
|
||||
|
||||
'unknown': xxxUnknown,
|
||||
'comment': xxxComment,
|
||||
}
|
||||
|
||||
# Create IDs for all parameters of all classes
|
||||
paramIDs = {'fg': wx.NewId(), 'bg': wx.NewId(), 'exstyle': wx.NewId(), 'font': wx.NewId(),
|
||||
'enabled': wx.NewId(), 'focused': wx.NewId(), 'hidden': 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():
|
||||
if cl.allParams:
|
||||
@@ -1009,25 +1154,29 @@ for cl in xxxDict.values():
|
||||
|
||||
# Test for object elements
|
||||
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
|
||||
def MakeXXXFromDOM(parent, element):
|
||||
if element.tagName == 'object_ref':
|
||||
ref = element.getAttribute('ref')
|
||||
def MakeXXXFromDOM(parent, node):
|
||||
if node.nodeType == minidom.Node.COMMENT_NODE:
|
||||
return xxxComment(parent, node)
|
||||
if node.tagName == 'object_ref':
|
||||
ref = node.getAttribute('ref')
|
||||
refElem = FindResource(ref)
|
||||
if refElem: cls = refElem.getAttribute('class')
|
||||
else: return xxxUnknown(parent, element)
|
||||
else: return xxxUnknown(parent, node)
|
||||
else:
|
||||
refElem = None
|
||||
cls = element.getAttribute('class')
|
||||
cls = node.getAttribute('class')
|
||||
try:
|
||||
klass = xxxDict[cls]
|
||||
except KeyError:
|
||||
# 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
|
||||
return klass(parent, element, refElem)
|
||||
return klass(parent, node, refElem)
|
||||
|
||||
# Make empty DOM element
|
||||
def MakeEmptyDOM(className):
|
||||
@@ -1051,7 +1200,8 @@ def MakeEmptyDOM(className):
|
||||
def MakeEmptyXXX(parent, className):
|
||||
# Make corresponding DOM object first
|
||||
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.isSizer and className != 'spacer':
|
||||
sizerItemElem = MakeEmptyDOM(parent.itemTag)
|
||||
@@ -1070,7 +1220,16 @@ def MakeEmptyXXX(parent, className):
|
||||
pageElem.appendChild(elem)
|
||||
elem = pageElem
|
||||
# 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
|
||||
def MakeEmptyRefDOM(ref):
|
||||
@@ -1107,3 +1266,15 @@ def MakeEmptyRefXXX(parent, ref):
|
||||
#xxx.allParams.remove('label')
|
||||
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
|
||||
|
||||
|
Reference in New Issue
Block a user