]> git.saurik.com Git - wxWidgets.git/commitdiff
New XRCed from Roman Rolinsky
authorRobin Dunn <robin@alldunn.com>
Wed, 7 Nov 2001 16:13:35 +0000 (16:13 +0000)
committerRobin Dunn <robin@alldunn.com>
Wed, 7 Nov 2001 16:13:35 +0000 (16:13 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@12350 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

wxPython/tools/XRCed/CHANGES
wxPython/tools/XRCed/images.py
wxPython/tools/XRCed/params.py
wxPython/tools/XRCed/xrced.py
wxPython/tools/XRCed/xxx.py

index 2b2dbef1e59bbe13bc0ae43ee1a4b3bcdf203fd8..28061d36fe6d3531e65b2b4a3af9894752c48690 100644 (file)
@@ -1,3 +1,15 @@
+0.0.6
+-----
+
+Toolbar, bitmap, icon support (no display yet).
+
+Changed parameter objects, added support for multiple parameters (like 
+`growablecols').
+
+Fixed double-clicking problem with tree control on Windows.
+
+Some performance improovements.
+
 0.0.5
 -----
 
 0.0.5
 -----
 
index 668186f52c39439ab1559f0bf34e7a9cc67f5691..f2957d15a9ec0cb6242153fcbc9a1ce42bb4749a 100644 (file)
@@ -237,6 +237,22 @@ def getTreeMenuBarBitmap():
 def getTreeMenuBarImage():
     return wxImageFromBitmap(getTreeMenuBarBitmap())
 
 def getTreeMenuBarImage():
     return wxImageFromBitmap(getTreeMenuBarBitmap())
 
+#----------------------------------------------------------------------
+def getTreeToolBarData():
+    return cPickle.loads(zlib.decompress(
+'x\xda\xd3\xc8)0\xe4\nV74S\x00"\x0b\x05Cu\xae\xc4`\xf5\x08\x85d\x05\xa7\x9c\
+\xc4\xe4l0\xcf\x1f\xc8S\xb64\xb04\xb14\x00\xf3\x1d@|7\x0b7g\x03\x08_\x19\xc4\
+70\x80\xf3\x15\x80|\xbf\xfc\xbcT0G\x0f\xa6\xd8\xcd\x02\xcc\xd7\x86\xf0\r\x0c\
+\xa0\x8a\xf3A|\x17\x03\x17\x13\x17\x98fT@\rA=T\x10\x01\x11\xccG\x06\xfe0Am\
+\xed\x88|\x07\x87\x88|e\xe5\x08\x02\x82\x11\x11\x11p\xec\x8f\xc7L\x7fT\x00\
+\x11\x8c@\x034\xf2\xbb\x1e\x00\x1c\x05j\x12' ))
+
+def getTreeToolBarBitmap():
+    return wxBitmapFromXPMData(getTreeToolBarData())
+
+def getTreeToolBarImage():
+    return wxImageFromBitmap(getTreeToolBarBitmap())
+
 #----------------------------------------------------------------------
 def getTreeMenuData():
     return cPickle.loads(zlib.decompress(
 #----------------------------------------------------------------------
 def getTreeMenuData():
     return cPickle.loads(zlib.decompress(
index 770ae2e0f904af55f8c30a76e66aafe496bff363..4e0982abee824ee12204a17085924307b0120b72 100644 (file)
@@ -7,6 +7,7 @@
 from wxPython.wx import *
 from wxPython.xrc import *
 import string
 from wxPython.wx import *
 from wxPython.xrc import *
 import string
+import os.path
 
 # Object which is currently processed
 currentXXX = None
 
 # Object which is currently processed
 currentXXX = None
@@ -14,40 +15,52 @@ def SetCurrentXXX(xxx):
     global currentXXX
     currentXXX = xxx
 
     global currentXXX
     currentXXX = xxx
 
-genericStyles = ['wxSIMPLE_BORDER', 'wxSUNKEN_BORDER', 'wxRAISED_BORDER',
-                 'wxTAB_TRAVERSAL', 'wxWANTS_CHARS', 'wxVSCROLL', 'wxHSCROLL']
+genericStyles = ['wxSIMPLE_BORDER', 'wxDOUBLE_BORDER',
+                 'wxSUNKEN_BORDER', 'wxRAISED_BORDER',
+                 'wxSTATIC_BORDER', 'wxNO_BORDER',
+                 'wxTRANSPARENT_WINDOW', 'wxWANTS_CHARS',
+                 'wxNO_FULL_REPAINT_ON_RESIZE']
 
 # Class that can properly disable children
 class PPanel(wxPanel):
     def __init__(self, parent, id, name):
         wxPanel.__init__(self, parent, id, name=name)
 
 # Class that can properly disable children
 class PPanel(wxPanel):
     def __init__(self, parent, id, name):
         wxPanel.__init__(self, parent, id, name=name)
+        self.modified = self.freeze = false
     def Enable(self, value):
     def Enable(self, value):
+        # Something strange is going on with enable so we make sure...
         for w in self.GetChildren():
             w.Enable(value)
         for w in self.GetChildren():
             w.Enable(value)
+        wxPanel.Enable(self, value)
+    def SetModified(self):
+        self.modified = true
+        panel.SetModified(true)        
 
 class ParamBinaryOr(PPanel):
 
 class ParamBinaryOr(PPanel):
-    def __init__(self, parent, id, value, size, name):
+    def __init__(self, parent, id, size, name):
         PPanel.__init__(self, parent, id, name)
         self.ID_TEXT_CTRL = wxNewId()
         self.ID_BUTTON_CHOICES = wxNewId()
         self.SetBackgroundColour(panel.GetBackgroundColour())
         sizer = wxBoxSizer()
         PPanel.__init__(self, parent, id, name)
         self.ID_TEXT_CTRL = wxNewId()
         self.ID_BUTTON_CHOICES = wxNewId()
         self.SetBackgroundColour(panel.GetBackgroundColour())
         sizer = wxBoxSizer()
-        self.text = wxTextCtrl(self, self.ID_TEXT_CTRL, value, size=wxSize(200,-1))
-        sizer.Add(self.text, 0, wxRIGHT, 10)
+        self.text = wxTextCtrl(self, self.ID_TEXT_CTRL, size=wxSize(200,-1))
+        sizer.Add(self.text, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 10)
         self.button = wxButton(self, self.ID_BUTTON_CHOICES, 'Edit...')
         self.button = wxButton(self, self.ID_BUTTON_CHOICES, 'Edit...')
-        sizer.Add(self.button)
+        sizer.Add(self.button, 0, wxALIGN_CENTER_VERTICAL)
         self.SetAutoLayout(true)
         self.SetSizer(sizer)
         sizer.Fit(self)
         EVT_BUTTON(self, self.ID_BUTTON_CHOICES, self.OnButtonChoices)
         EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange)
     def OnChange(self, evt):
         self.SetAutoLayout(true)
         self.SetSizer(sizer)
         sizer.Fit(self)
         EVT_BUTTON(self, self.ID_BUTTON_CHOICES, self.OnButtonChoices)
         EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange)
     def OnChange(self, evt):
-        panel.SetModified(true)
+        if self.freeze: return
+        self.SetModified()
         evt.Skip()
     def GetValue(self):
         return self.text.GetValue()
     def SetValue(self, value):
         evt.Skip()
     def GetValue(self):
         return self.text.GetValue()
     def SetValue(self, value):
+        self.freeze = true
         self.text.SetValue(value)
         self.text.SetValue(value)
+        self.freeze = false
     def OnButtonChoices(self, evt):
         dlg = wxDialog(self, -1, 'Choices')
         topSizer = wxBoxSizer(wxVERTICAL)
     def OnButtonChoices(self, evt):
         dlg = wxDialog(self, -1, 'Choices')
         topSizer = wxBoxSizer(wxVERTICAL)
@@ -63,7 +76,7 @@ class ParamBinaryOr(PPanel):
                 if self.equal.has_key(i):
                     listBox.Check(self.values.index(self.equal[i]))
                 else:
                 if self.equal.has_key(i):
                     listBox.Check(self.values.index(self.equal[i]))
                 else:
-                    print 'Unknown flag: %s: ignored.' % i
+                    print 'WARNING: unknown flag: %s: ignored.' % i
                     ignored.append(i)
         topSizer.Add(listBox, 1, wxEXPAND)
         sizer = wxBoxSizer()
                     ignored.append(i)
         topSizer.Add(listBox, 1, wxEXPAND)
         sizer = wxBoxSizer()
@@ -77,15 +90,16 @@ class ParamBinaryOr(PPanel):
         dlg.SetSizer(topSizer)
         topSizer.Fit(dlg)
         dlg.Center()
         dlg.SetSizer(topSizer)
         topSizer.Fit(dlg)
         dlg.Center()
-        if dlg.ShowModal() != wxID_OK: return
-        value = []
-        for i in range(listBox.Number()):
-            if listBox.IsChecked(i):
-                value.append(self.values[i])
-        # Add ignored flags
-        value.extend(ignored)
-        self.SetValue(reduce(lambda a,b: a+'|'+b, value))
-        panel.SetModified(true)
+        if dlg.ShowModal() == wxID_OK: 
+            value = []
+            for i in range(listBox.Number()):
+                if listBox.IsChecked(i):
+                    value.append(self.values[i])
+            # Add ignored flags
+            value.extend(ignored)
+            self.SetValue(reduce(lambda a,b: a+'|'+b, value))
+            self.SetModified()
+        dlg.Destroy()
 
 class ParamFlag(ParamBinaryOr):
     values = ['wxTOP', 'wxBOTTOM', 'wxLEFT', 'wxRIGHT', 'wxALL',
 
 class ParamFlag(ParamBinaryOr):
     values = ['wxTOP', 'wxBOTTOM', 'wxLEFT', 'wxRIGHT', 'wxALL',
@@ -95,58 +109,66 @@ class ParamFlag(ParamBinaryOr):
     equal = {'wxALIGN_CENTER': 'wxALIGN_CENTRE',
              'wxALIGN_CENTER_VERTICAL': 'wxALIGN_CENTRE_VERTICAL',
              'wxALIGN_CENTER_HORIZONTAL': 'wxALIGN_CENTRE_HORIZONTAL'}
     equal = {'wxALIGN_CENTER': 'wxALIGN_CENTRE',
              'wxALIGN_CENTER_VERTICAL': 'wxALIGN_CENTRE_VERTICAL',
              'wxALIGN_CENTER_HORIZONTAL': 'wxALIGN_CENTRE_HORIZONTAL'}
-    def __init__(self, parent, id, value, size, name):
-        ParamBinaryOr.__init__(self, parent, id, value, size, name)
+    def __init__(self, parent, id, size, name):
+        ParamBinaryOr.__init__(self, parent, id, size, name)
 
 class ParamStyle(ParamBinaryOr):
     equal = {'wxALIGN_CENTER': 'wxALIGN_CENTRE'}
 
 class ParamStyle(ParamBinaryOr):
     equal = {'wxALIGN_CENTER': 'wxALIGN_CENTRE'}
-    def __init__(self, parent, id, value, size, name):
+    def __init__(self, parent, id = -1, size = wxDefaultSize, name = ''):
         self.values = currentXXX.winStyles + genericStyles
         self.values = currentXXX.winStyles + genericStyles
-        ParamBinaryOr.__init__(self, parent, id, value, size, name)
+        ParamBinaryOr.__init__(self, parent, id, size, name)
+
+class ParamNonGenericStyle(ParamBinaryOr):
+    def __init__(self, parent, id = -1, size = wxDefaultSize, name = ''):
+        self.values = currentXXX.winStyles
+        ParamBinaryOr.__init__(self, parent, id, size, name)
 
 class ParamExStyle(ParamBinaryOr):
 
 class ParamExStyle(ParamBinaryOr):
-    def __init__(self, parent, id, value, size, name):
+    def __init__(self, parent, id = -1, size = wxDefaultSize, name = ''):
         if currentXXX:
             self.values = currentXXX.exStyles # constant at the moment
         else:
             self.values = []
         if currentXXX:
             self.values = currentXXX.exStyles # constant at the moment
         else:
             self.values = []
-        ParamBinaryOr.__init__(self, parent, id, value, size, name)
+        ParamBinaryOr.__init__(self, parent, id, size, name)
 
 class ParamColour(PPanel):
 
 class ParamColour(PPanel):
-    def __init__(self, parent, id, value, size, name):
+    def __init__(self, parent, id = -1, size = wxDefaultSize, name = ''):
         PPanel.__init__(self, parent, id, name)
         self.ID_TEXT_CTRL = wxNewId()
         self.ID_BUTTON = wxNewId()
         self.SetBackgroundColour(panel.GetBackgroundColour())
         sizer = wxBoxSizer()
         PPanel.__init__(self, parent, id, name)
         self.ID_TEXT_CTRL = wxNewId()
         self.ID_BUTTON = wxNewId()
         self.SetBackgroundColour(panel.GetBackgroundColour())
         sizer = wxBoxSizer()
-        self.text = wxTextCtrl(self, self.ID_TEXT_CTRL, str(value), size=wxSize(60,-1))
-        sizer.Add(self.text, 0, wxGROW | wxRIGHT, 10)
+        self.text = wxTextCtrl(self, self.ID_TEXT_CTRL, size=wxSize(60,-1))
+        sizer.Add(self.text, 0, wxRIGHT, 10)
         self.button = wxPanel(self, self.ID_BUTTON, wxDefaultPosition, wxSize(40, -1))
         sizer.Add(self.button, 0, wxGROW)
         self.SetAutoLayout(true)
         self.SetSizer(sizer)
         sizer.Fit(self)
         self.textModified = false
         self.button = wxPanel(self, self.ID_BUTTON, wxDefaultPosition, wxSize(40, -1))
         sizer.Add(self.button, 0, wxGROW)
         self.SetAutoLayout(true)
         self.SetSizer(sizer)
         sizer.Fit(self)
         self.textModified = false
-        self.SetValue(value)
         EVT_PAINT(self.button, self.OnPaintButton)
         EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange)
         EVT_LEFT_DOWN(self.button, self.OnLeftDown)
     def GetValue(self):
         return self.value
     def SetValue(self, value):
         EVT_PAINT(self.button, self.OnPaintButton)
         EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange)
         EVT_LEFT_DOWN(self.button, self.OnLeftDown)
     def GetValue(self):
         return self.value
     def SetValue(self, value):
+        self.freeze = true
         if not value: value = '#FFFFFF'
         self.value = value
         self.text.SetValue(str(value))  # update text ctrl
         if not value: value = '#FFFFFF'
         self.value = value
         self.text.SetValue(str(value))  # update text ctrl
-        self.button.SetBackgroundColour(wxNamedColour(value))
+        colour = wxColour(int(value[1:3], 16), int(value[3:5], 16), int(value[5:7], 16))
+        self.button.SetBackgroundColour(colour)
         self.button.Refresh()
         self.button.Refresh()
+        self.freeze = false
     def OnChange(self, evt):
     def OnChange(self, evt):
-        panel.SetModified(true)
+        if self.freeze: return
+        self.SetModified()
         self.textModified = true
         evt.Skip()
     def OnPaintButton(self, evt):
         dc = wxPaintDC(self.button)
         dc.SetBrush(wxTRANSPARENT_BRUSH)
         self.textModified = true
         evt.Skip()
     def OnPaintButton(self, evt):
         dc = wxPaintDC(self.button)
         dc.SetBrush(wxTRANSPARENT_BRUSH)
-        if panel.page2.IsEnabled() and self.IsEnabled(): dc.SetPen(wxBLACK_PEN)
+        if self.IsEnabled(): dc.SetPen(wxBLACK_PEN)
         else: dc.SetPen(wxGREY_PEN)
         size = self.button.GetSize()
         dc.DrawRectangle(0, 0, size.x, size.y)
         else: dc.SetPen(wxGREY_PEN)
         size = self.button.GetSize()
         dc.DrawRectangle(0, 0, size.x, size.y)
@@ -154,7 +176,9 @@ class ParamColour(PPanel):
         dlg = wxColourDialog(self)
         if dlg.ShowModal() == wxID_OK:
             self.SetValue('#%02X%02X%02X' % dlg.GetColourData().GetColour().Get())
         dlg = wxColourDialog(self)
         if dlg.ShowModal() == wxID_OK:
             self.SetValue('#%02X%02X%02X' % dlg.GetColourData().GetColour().Get())
-            panel.SetModified(true)
+            self.SetModified()
+            self.textModified = false
+        dlg.Destroy()
 
 ################################################################################
 
 
 ################################################################################
 
@@ -173,16 +197,16 @@ fontStylesXml2wx = ReverseMap(fontStylesWx2Xml)
 fontWeightsXml2wx = ReverseMap(fontWeightsWx2Xml)
 
 class ParamFont(PPanel):
 fontWeightsXml2wx = ReverseMap(fontWeightsWx2Xml)
 
 class ParamFont(PPanel):
-    def __init__(self, parent, id, value, size, name):
+    def __init__(self, parent, id = -1, size = wxDefaultSize, name = ''):
         PPanel.__init__(self, parent, id, name)
         self.ID_TEXT_CTRL = wxNewId()
         self.ID_BUTTON_SELECT = wxNewId()
         self.SetBackgroundColour(panel.GetBackgroundColour())
         sizer = wxBoxSizer()
         PPanel.__init__(self, parent, id, name)
         self.ID_TEXT_CTRL = wxNewId()
         self.ID_BUTTON_SELECT = wxNewId()
         self.SetBackgroundColour(panel.GetBackgroundColour())
         sizer = wxBoxSizer()
-        self.text = wxTextCtrl(self, self.ID_TEXT_CTRL, str(value), size=wxSize(200,-1))
-        sizer.Add(self.text, 0, wxRIGHT, 10)
+        self.text = wxTextCtrl(self, self.ID_TEXT_CTRL, size=wxSize(200,-1))
+        sizer.Add(self.text, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 10)
         self.button = wxButton(self, self.ID_BUTTON_SELECT, 'Select...')
         self.button = wxButton(self, self.ID_BUTTON_SELECT, 'Select...')
-        sizer.Add(self.button)
+        sizer.Add(self.button, 0, wxALIGN_CENTER_VERTICAL)
         self.SetAutoLayout(true)
         self.SetSizer(sizer)
         sizer.Fit(self)
         self.SetAutoLayout(true)
         self.SetSizer(sizer)
         sizer.Fit(self)
@@ -190,7 +214,8 @@ class ParamFont(PPanel):
         EVT_BUTTON(self, self.ID_BUTTON_SELECT, self.OnButtonSelect)
         EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange)
     def OnChange(self, evt):
         EVT_BUTTON(self, self.ID_BUTTON_SELECT, self.OnButtonSelect)
         EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange)
     def OnChange(self, evt):
-        panel.SetModified(true)
+        if self.freeze: return
+        self.SetModified()
         self.textModified = true
         evt.Skip()
     def GetValue(self):
         self.textModified = true
         evt.Skip()
     def GetValue(self):
@@ -198,9 +223,11 @@ class ParamFont(PPanel):
             return eval(self.text.GetValue())
         return self.value
     def SetValue(self, value):
             return eval(self.text.GetValue())
         return self.value
     def SetValue(self, value):
+        self.freeze = true              # disable other handlers
         if not value: value = [''] * 7
         self.value = value
         self.text.SetValue(str(value))  # update text ctrl
         if not value: value = [''] * 7
         self.value = value
         self.text.SetValue(str(value))  # update text ctrl
+        self.freeze = false
     def OnButtonSelect(self, evt):
         if self.textModified:           # text has newer value
             self.value = eval(self.text.GetValue())
     def OnButtonSelect(self, evt):
         if self.textModified:           # text has newer value
             self.value = eval(self.text.GetValue())
@@ -224,26 +251,27 @@ class ParamFont(PPanel):
         data = wxFontData()
         data.SetInitialFont(font)
         dlg = wxFontDialog(self, data)
         data = wxFontData()
         data.SetInitialFont(font)
         dlg = wxFontDialog(self, data)
-        if dlg.ShowModal() != wxID_OK: return
-        font = dlg.GetFontData().GetChosenFont()
-        value = [str(font.GetPointSize()), fontFamiliesWx2Xml[font.GetFamily()],
-                 fontStylesWx2Xml[font.GetStyle()],
-                 fontWeightsWx2Xml[font.GetWeight()],
-                 str(font.GetUnderlined()), font.GetFaceName(),
-                 wxFontMapper_GetEncodingName(font.GetEncoding())]
-        # Add ignored flags
-        self.SetValue(value)
-        panel.SetModified(true)
-        self.textModified = false
+        if dlg.ShowModal() == wxID_OK:
+            font = dlg.GetFontData().GetChosenFont()
+            value = [str(font.GetPointSize()), fontFamiliesWx2Xml[font.GetFamily()],
+                     fontStylesWx2Xml[font.GetStyle()],
+                     fontWeightsWx2Xml[font.GetWeight()],
+                     str(font.GetUnderlined()), font.GetFaceName(),
+                     wxFontMapper_GetEncodingName(font.GetEncoding())]
+            # Add ignored flags
+            self.SetValue(value)
+            self.SetModified()
+            self.textModified = false
+        dlg.Destroy()
 
 ################################################################################
 
 class ParamInt(PPanel):
 
 ################################################################################
 
 class ParamInt(PPanel):
-    def __init__(self, parent, id, value, size, name):
+    def __init__(self, parent, id = -1, size = wxDefaultSize, name = ''):
         PPanel.__init__(self, parent, id, name)
         self.ID_SPIN_CTRL = wxNewId()
         sizer = wxBoxSizer()
         PPanel.__init__(self, parent, id, name)
         self.ID_SPIN_CTRL = wxNewId()
         sizer = wxBoxSizer()
-        self.spin = wxSpinCtrl(self, self.ID_SPIN_CTRL, value, size=wxSize(50,-1))
+        self.spin = wxSpinCtrl(self, self.ID_SPIN_CTRL, size=wxSize(50,-1))
         self.SetBackgroundColour(panel.GetBackgroundColour())
         sizer.Add(self.spin)
         self.SetAutoLayout(true)
         self.SetBackgroundColour(panel.GetBackgroundColour())
         sizer.Add(self.spin)
         self.SetAutoLayout(true)
@@ -253,35 +281,46 @@ class ParamInt(PPanel):
     def GetValue(self):
         return str(self.spin.GetValue())
     def SetValue(self, value):
     def GetValue(self):
         return str(self.spin.GetValue())
     def SetValue(self, value):
+        self.freeze = true
         if not value: value = 0
         self.spin.SetValue(int(value))
         if not value: value = 0
         self.spin.SetValue(int(value))
+        self.freeze = false
     def OnChange(self, evt):
     def OnChange(self, evt):
-        panel.SetModified(true)
+        if self.freeze: return
+        self.SetModified()
         evt.Skip()
 
         evt.Skip()
 
-class ParamText(wxTextCtrl):
-    def __init__(self, parent, id, value, size, name):
-        wxTextCtrl.__init__(self, parent, id, value, size=wxSize(200,-1), name=name)
-        EVT_TEXT(self, id, self.OnChange)
+class ParamText(PPanel):
+    def __init__(self, parent, id = -1, size = wxDefaultSize, name = '', textWidth=200):
+        PPanel.__init__(self, parent, id, name)
+        self.ID_TEXT_CTRL = wxNewId()
+        # We use sizer even here to have the same size of text control
+        sizer = wxBoxSizer()
+        self.SetBackgroundColour(panel.GetBackgroundColour())
+        self.text = wxTextCtrl(self, self.ID_TEXT_CTRL, size=wxSize(textWidth,-1))
+        sizer.Add(self.text, 0, wxALIGN_CENTER_VERTICAL)
+        self.SetAutoLayout(true)
+        self.SetSizer(sizer)
+        sizer.Fit(self)
+        EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange)
+    def GetValue(self):
+        return self.text.GetValue()
+    def SetValue(self, value):
+        self.freeze = true              # disable other handlers
+        self.text.SetValue(value)
+        self.freeze = false             # disable other handlers
     def OnChange(self, evt):
     def OnChange(self, evt):
-        panel.SetModified(true)
+        if self.freeze: return
+        self.SetModified()
         evt.Skip()
 
         evt.Skip()
 
-class ParamAccel(wxTextCtrl):
-    def __init__(self, parent, id, value, size, name):
-        wxTextCtrl.__init__(self, parent, id, value, size=wxSize(50,-1), name=name)
-        EVT_TEXT(self, id, self.OnChange)
-    def OnChange(self, evt):
-        panel.SetModified(true)
-        evt.Skip()
+class ParamAccel(ParamText):
+    def __init__(self, parent, id = -1, size = wxDefaultSize, name = ''):
+        ParamText.__init__(self, parent, id, size, name, 50)
 
 
-class ParamPosSize(wxTextCtrl):
-    def __init__(self, parent, id, value, size, name):
-        wxTextCtrl.__init__(self, parent, id, value, size=wxSize(80,-1), name=name)
-        EVT_TEXT(self, id, self.OnChange)
-    def OnChange(self, evt):
-        panel.SetModified(true)
-        evt.Skip()
+class ParamPosSize(ParamText):
+    def __init__(self, parent, id = -1, size = wxDefaultSize, name = ''):
+        ParamText.__init__(self, parent, id, size, name, 80)
 
 class ContentDialog(wxDialog):
     def __init__(self, parent, value):
 
 class ContentDialog(wxDialog):
     def __init__(self, parent, value):
@@ -339,16 +378,16 @@ class ContentDialog(wxDialog):
                        self.list.GetSelection() < self.list.Number() - 1)
 
 class ParamContent(PPanel):
                        self.list.GetSelection() < self.list.Number() - 1)
 
 class ParamContent(PPanel):
-    def __init__(self, parent, id, value, size, name):
+    def __init__(self, parent, id = -1, size = wxDefaultSize, name = ''):
         PPanel.__init__(self, parent, id, name)
         self.ID_TEXT_CTRL = wxNewId()
         self.ID_BUTTON_EDIT = wxNewId()
         self.SetBackgroundColour(panel.GetBackgroundColour())
         sizer = wxBoxSizer()
         PPanel.__init__(self, parent, id, name)
         self.ID_TEXT_CTRL = wxNewId()
         self.ID_BUTTON_EDIT = wxNewId()
         self.SetBackgroundColour(panel.GetBackgroundColour())
         sizer = wxBoxSizer()
-        self.text = wxTextCtrl(self, self.ID_TEXT_CTRL, str(value), size=wxSize(200,-1))
-        sizer.Add(self.text, 0, wxRIGHT, 10)
+        self.text = wxTextCtrl(self, self.ID_TEXT_CTRL, size=wxSize(200,-1))
+        sizer.Add(self.text, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 10)
         self.button = wxButton(self, self.ID_BUTTON_EDIT, 'Edit...')
         self.button = wxButton(self, self.ID_BUTTON_EDIT, 'Edit...')
-        sizer.Add(self.button)
+        sizer.Add(self.button, 0, wxALIGN_CENTER_VERTICAL)
         self.SetAutoLayout(true)
         self.SetSizer(sizer)
         sizer.Fit(self)
         self.SetAutoLayout(true)
         self.SetSizer(sizer)
         sizer.Fit(self)
@@ -356,7 +395,8 @@ class ParamContent(PPanel):
         EVT_BUTTON(self, self.ID_BUTTON_EDIT, self.OnButtonEdit)
         EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange)
     def OnChange(self, evt):
         EVT_BUTTON(self, self.ID_BUTTON_EDIT, self.OnButtonEdit)
         EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange)
     def OnChange(self, evt):
-        panel.SetModified(true)
+        if self.freeze: return        
+        self.SetModified()
         self.textModified = true
         evt.Skip()
     def GetValue(self):
         self.textModified = true
         evt.Skip()
     def GetValue(self):
@@ -364,58 +404,58 @@ class ParamContent(PPanel):
             return eval(self.text.GetValue())
         return self.value
     def SetValue(self, value):
             return eval(self.text.GetValue())
         return self.value
     def SetValue(self, value):
+        self.freeze = true
         self.value = value
         self.text.SetValue(str(value))  # update text ctrl
         self.value = value
         self.text.SetValue(str(value))  # update text ctrl
+        self.freeze = false
     def OnButtonEdit(self, evt):
         if self.textModified:           # text has newer value
             self.value = eval(self.text.GetValue())
         dlg = ContentDialog(self, self.value)
     def OnButtonEdit(self, evt):
         if self.textModified:           # text has newer value
             self.value = eval(self.text.GetValue())
         dlg = ContentDialog(self, self.value)
-        if dlg.ShowModal() != wxID_OK: return
-        value = []
-        for i in range(dlg.list.Number()):
-            value.append(dlg.list.GetString(i))
-        # Add ignored flags
-        self.SetValue(value)
-        panel.SetModified(true)
-        self.textModified = false
+        if dlg.ShowModal() == wxID_OK:
+            value = []
+            for i in range(dlg.list.Number()):
+                value.append(dlg.list.GetString(i))
+            # Add ignored flags
+            self.SetValue(value)
+            self.SetModified()
+            self.textModified = false
+        dlg.Destroy()
 
 # Boxless radiobox 
 class RadioBox(PPanel):
     def __init__(self, parent, id, choices,
                  pos=wxDefaultPosition, size=wxDefaultSize, name='radiobox'):
         PPanel.__init__(self, parent, id, name)
 
 # Boxless radiobox 
 class RadioBox(PPanel):
     def __init__(self, parent, id, choices,
                  pos=wxDefaultPosition, size=wxDefaultSize, name='radiobox'):
         PPanel.__init__(self, parent, id, name)
-        self.ID_RADIO_CHOICE = wxNewId()         # economize on IDs, use names
         self.SetBackgroundColour(panel.GetBackgroundColour())
         self.choices = choices
         topSizer = wxBoxSizer()
         for i in choices:
         self.SetBackgroundColour(panel.GetBackgroundColour())
         self.choices = choices
         topSizer = wxBoxSizer()
         for i in choices:
-            topSizer.Add(wxRadioButton(self, self.ID_RADIO_CHOICE, i, name=i))
+            button = wxRadioButton(self, -1, i, name=i)
+            topSizer.Add(button)
+            EVT_RADIOBUTTON(self, button.GetId(), self.OnRadioChoice)
         self.SetAutoLayout(true)
         self.SetSizer(topSizer)
         topSizer.Fit(self)
         self.SetAutoLayout(true)
         self.SetSizer(topSizer)
         topSizer.Fit(self)
-        EVT_RADIOBUTTON(self, self.ID_RADIO_CHOICE, self.OnRadioChoice)
     def SetStringSelection(self, value):
     def SetStringSelection(self, value):
-        self.value = None
+        self.freeze = true
         for i in self.choices:
         for i in self.choices:
-            w = self.FindWindowByName(i)
-            w.SetValue(i == value)
+            self.FindWindowByName(i).SetValue(i == value)
         self.value = value
         self.value = value
+        self.freeze = false
     def OnRadioChoice(self, evt):
     def OnRadioChoice(self, evt):
-        if not self.value:              # procedure call
-            evt.Skip()
-            return
-        self.FindWindowByName(self.value).SetValue(false)
-        self.value = evt.GetEventObject().GetName()
-        panel.SetModified(true)
+        if self.freeze: return
+        if evt.GetSelection():
+            self.value = evt.GetEventObject().GetName()
+            self.SetModified()
     def GetStringSelection(self):
         return self.value
 
 class ParamBool(RadioBox):
     values = {'yes': '1', 'no': '0'}
     seulav = {'1': 'yes', '0': 'no'}
     def GetStringSelection(self):
         return self.value
 
 class ParamBool(RadioBox):
     values = {'yes': '1', 'no': '0'}
     seulav = {'1': 'yes', '0': 'no'}
-    def __init__(self, parent, id, value, size, name):
+    def __init__(self, parent, id = -1, size = wxDefaultSize, name = ''):
         RadioBox.__init__(self, parent, id, choices = self.values.keys(), name=name)
         RadioBox.__init__(self, parent, id, choices = self.values.keys(), name=name)
-        self.SetValue(value)
     def GetValue(self):
         return self.values[self.GetStringSelection()]
     def SetValue(self, value):
     def GetValue(self):
         return self.values[self.GetStringSelection()]
     def SetValue(self, value):
@@ -425,15 +465,59 @@ class ParamBool(RadioBox):
 class ParamOrient(RadioBox):
     values = {'horizontal': 'wxHORIZONTAL', 'vertical': 'wxVERTICAL'}
     seulav = {'wxHORIZONTAL': 'horizontal', 'wxVERTICAL': 'vertical'}
 class ParamOrient(RadioBox):
     values = {'horizontal': 'wxHORIZONTAL', 'vertical': 'wxVERTICAL'}
     seulav = {'wxHORIZONTAL': 'horizontal', 'wxVERTICAL': 'vertical'}
-    def __init__(self, parent, id, value, size, name):
+    def __init__(self, parent, id = -1, size = wxDefaultSize, name = ''):
         RadioBox.__init__(self, parent, id, choices = self.values.keys(), name=name)
         RadioBox.__init__(self, parent, id, choices = self.values.keys(), name=name)
-        self.SetValue(value)
     def GetValue(self):
         return self.values[self.GetStringSelection()]
     def SetValue(self, value):
         if not value: value = 'wxHORIZONTAL'
         self.SetStringSelection(self.seulav[value])
 
     def GetValue(self):
         return self.values[self.GetStringSelection()]
     def SetValue(self, value):
         if not value: value = 'wxHORIZONTAL'
         self.SetStringSelection(self.seulav[value])
 
+class ParamFile(PPanel):
+    def __init__(self, parent, id = -1, size = wxDefaultSize, name = ''):    
+        PPanel.__init__(self, parent, id, name)
+        self.ID_TEXT_CTRL = wxNewId()
+        self.ID_BUTTON_BROWSE = wxNewId()
+        self.SetBackgroundColour(panel.GetBackgroundColour())
+        sizer = wxBoxSizer()
+        self.text = wxTextCtrl(self, self.ID_TEXT_CTRL, size=wxSize(200,-1))
+        sizer.Add(self.text, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 10)
+        self.button = wxButton(self, self.ID_BUTTON_BROWSE, 'Browse...')
+        sizer.Add(self.button, 0, wxALIGN_CENTER_VERTICAL)
+        self.SetAutoLayout(true)
+        self.SetSizer(sizer)
+        sizer.Fit(self)
+        self.textModified = false
+        EVT_BUTTON(self, self.ID_BUTTON_BROWSE, self.OnButtonBrowse)
+        EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange)
+    def OnChange(self, evt):
+        if self.freeze: return        
+        self.SetModified()
+        self.textModified = true
+        evt.Skip()
+    def GetValue(self):
+        if self.textModified:           # text has newer value
+            return eval(self.text.GetValue())
+        return self.value
+    def SetValue(self, value):
+        self.freeze = true
+        self.value = value
+        self.text.SetValue(value)  # update text ctrl
+        self.freeze = false
+    def OnButtonBrowse(self, evt):
+        if self.textModified:           # text has newer value
+            self.value = self.text.GetValue()
+        dlg = wxFileDialog(self,
+                           defaultDir = os.path.abspath(os.path.dirname(self.value)),
+                           defaultFile = os.path.basename(self.value))
+        if dlg.ShowModal() == wxID_OK:
+            # Make relative
+            common = os.path.commonprefix([frame.dataFile, dlg.GetPath()])
+            self.SetValue(dlg.GetPath()[len(common):])
+            self.SetModified()
+            self.textModified = false
+        dlg.Destroy()
+
 paramDict = {
     'flag': ParamFlag,
     'style': ParamStyle, 'exstyle': ParamExStyle,
 paramDict = {
     'flag': ParamFlag,
     'style': ParamStyle, 'exstyle': ParamExStyle,
@@ -446,6 +530,6 @@ paramDict = {
     'min': ParamInt, 'max': ParamInt,
     'fg': ParamColour, 'bg': ParamColour, 'font': ParamFont,
     'enabled': ParamBool, 'focused': ParamBool, 'hidden': ParamBool,
     'min': ParamInt, 'max': ParamInt,
     'fg': ParamColour, 'bg': ParamColour, 'font': ParamFont,
     'enabled': ParamBool, 'focused': ParamBool, 'hidden': ParamBool,
-    'tooltip': ParamText
+    'tooltip': ParamText, 'bitmap': ParamFile, 'icon': ParamFile,
     }
 
     }
 
index 2378d1661bbd7338af6feff0817fbd06a2ce9b8a..5540a3d9217432773ce0a24b6d3c8f6179128849 100644 (file)
@@ -17,12 +17,15 @@ import images
 # String constants
 
 faceColour = wxSystemSettings_GetSystemColour(wxSYS_COLOUR_3DFACE)
 # String constants
 
 faceColour = wxSystemSettings_GetSystemColour(wxSYS_COLOUR_3DFACE)
-# Stange wxHtmlWindow behavior: when bgcolor is exact, it turns white
-bgcolor = (faceColour.Red()-1, faceColour.Green()-1, faceColour.Blue()-1)
+# Background colour problem on wxGTK
+if wxGetOsVersion()[1] == 1:
+    bgcolor = (faceColour.Red()-1, faceColour.Green()-1, faceColour.Blue()-1)
+else:
+    bgcolor = (faceColour.Red(), faceColour.Green(), faceColour.Blue())
 htmlHeader = '<html><body bgcolor="#%02x%02x%02x">\n' % bgcolor
 htmlFooter = '</body></html>\n'
 progname = 'XRCed'
 htmlHeader = '<html><body bgcolor="#%02x%02x%02x">\n' % bgcolor
 htmlFooter = '</body></html>\n'
 progname = 'XRCed'
-version = '0.0.5'
+version = '0.0.6'
 
 # Local modules
 from xxx import *
 
 # Local modules
 from xxx import *
@@ -59,22 +62,41 @@ def SetMenu(m, list):
 class Panel(wxNotebook):
     def __init__(self, parent, id = -1):
         wxNotebook.__init__(self, parent, id, style=wxNB_BOTTOM)
 class Panel(wxNotebook):
     def __init__(self, parent, id = -1):
         wxNotebook.__init__(self, parent, id, style=wxNB_BOTTOM)
-        #self.SetBackgroundColour(wxColour(bgcolor))
         sys.modules['params'].panel = self
         self.page1 = HtmlPage(self)
         self.AddPage(self.page1, 'Properties')
         self.page2 = None
         sys.modules['params'].panel = self
         self.page1 = HtmlPage(self)
         self.AddPage(self.page1, 'Properties')
         self.page2 = None
+        # Cache for already used panels
+        self.styleCache = {}
     def SetData(self, xxx):
     def SetData(self, xxx):
+        # First page
         self.page1.SetPageData(xxx)
         # Replace/remove style page
         self.page1.SetPageData(xxx)
         # Replace/remove style page
+        curPage = self.GetSelection()
         if self.page2:
         if self.page2:
+            # If style page for a same class, don't need to recreate
+            if xxx and self.page2.cacheId == xxx.treeObject().__class__:
+                self.page2.SetData(xxx.treeObject())
+                return
+            # Else remove and then add if needed
             self.RemovePage(1)
             self.RemovePage(1)
-            self.page2.Destroy()
+            if not self.styleCache.has_key(self.page2.cacheId):
+                self.styleCache[self.page2.cacheId] = self.page2
+        self.Freeze()
         if xxx and xxx.treeObject().hasStyle:
         if xxx and xxx.treeObject().hasStyle:
-            self.page2 = StylePage(self, xxx.treeObject())
+            cacheId = xxx.treeObject().__class__
+            if self.styleCache.has_key(cacheId):
+                self.page2 = self.styleCache[cacheId]
+                self.page2.SetData(xxx.treeObject())
+            else:
+                self.page2 = StylePage(self, xxx.treeObject())
             self.AddPage(self.page2, 'Style')
         else:
             self.page2 = None
             self.AddPage(self.page2, 'Style')
         else:
             self.page2 = None
+        # Keep page selected
+        if self.page2 and curPage == 1:
+            self.SetSelection(curPage)
+        self.Thaw()
     def Clear(self):
         self.page1.Clear()
         if self.page2:
     def Clear(self):
         self.page1.Clear()
         if self.page2:
@@ -113,21 +135,13 @@ class ParamPage:
             w = self.FindWindowByName('_data_' + param)
         else:
             w = self.FindWindowByName('data_' + param)
             w = self.FindWindowByName('_data_' + param)
         else:
             w = self.FindWindowByName('data_' + param)
-        elem = xxx.element
+        objElem = xxx.element
         if evt.IsChecked():
             # Ad  new text node in order of allParams
             w.SetValue('')              # set empty (default) value
         if evt.IsChecked():
             # Ad  new text node in order of allParams
             w.SetValue('')              # set empty (default) value
-            # For font element, we have to create another object
-            if param == 'font':
-                # Make XXX object
-                textElem = tree.dom.createElement('font')
-                font = xxxFont(xxx, textElem)
-                xxx.params['font'] = font
-            else:
-                textElem = tree.dom.createElement(param)
-                textNode = tree.dom.createTextNode('')
-                textElem.appendChild(textNode)
-                xxx.params[param] = textNode
+            w.SetModified()             # mark as changed
+            elem = tree.dom.createElement(param)
+            xxx.params[param] = xxxParam(elem)
             # Find place to put new element: first present element after param
             found = false
             paramStyles = xxx.allParams + xxx.styles
             # Find place to put new element: first present element after param
             found = false
             paramStyles = xxx.allParams + xxx.styles
@@ -137,22 +151,18 @@ class ParamPage:
                     found = true
                     break
             if found:
                     found = true
                     break
             if found:
-                nextTextElem = xxx.params[p].parentNode
-                elem.insertBefore(textElem, nextTextElem)
+                nextTextElem = xxx.params[p].node
+                objElem.insertBefore(elem, nextTextElem)
             else:
             else:
-                elem.appendChild(textElem)
+                objElem.appendChild(elem)
         else:
         else:
-            # Remove parameter element and following text node
-            textElem = xxx.params[param].parentNode
-            newline = textElem.nextSibling
-            if newline and newline.nodeType == minidom.Node.TEXT_NODE:
-                elem.removeChild(newline)
-            elem.removeChild(textElem)
+            # Remove parameter 
+            xxx.params[param].remove()
             del xxx.params[param]
             w.SetValue('')
             del xxx.params[param]
             w.SetValue('')
+            # Set modified flas
+            self.SetModified(true)
         w.Enable(evt.IsChecked())
         w.Enable(evt.IsChecked())
-        # Set modified flas
-        self.SetModified(true)
 
 
 ################################################################################
 
 
 ################################################################################
@@ -168,45 +178,44 @@ class HtmlPage(wxHtmlWindow, ParamPage):
         else:
             self.SetFonts("", "", [7, 8, 10, 12, 16, 22, 30])
         self.modified = false
         else:
             self.SetFonts("", "", [7, 8, 10, 12, 16, 22, 30])
         self.modified = false
+        # Previous type
+        self.xxxClass = self.xxxChildClass = None
     def Clear(self):
         self.SetPage(htmlHeader + 'select a tree item on the left' + htmlFooter)
     def SetPageData(self, xxx):
         if not xxx:
             self.SetPage(htmlHeader + 'this item has no properties' + htmlFooter)
             return
     def Clear(self):
         self.SetPage(htmlHeader + 'select a tree item on the left' + htmlFooter)
     def SetPageData(self, xxx):
         if not xxx:
             self.SetPage(htmlHeader + 'this item has no properties' + htmlFooter)
             return
-        self.SetPage(htmlHeader + xxx.generateHtml() + htmlFooter)
+        self.Freeze()                   # doesn't seem to help
+        # Don't change interface if same class
+        compare = false
+        if self.xxxClass and self.xxxClass == xxx.__class__:
+            compare = true              # a little weird code
+            if xxx.hasChild:
+                if self.xxxChildClass != xxx.child.__class__:
+                    compare = false
+        if not compare:                 # not same
+            self.SetPage(htmlHeader + xxx.generateHtml() + htmlFooter)
+            self.xxxClass = xxx.__class__
+            if xxx.hasChild: self.xxxChildClass = xxx.child.__class__
+        self.SetValues(xxx)
+        if xxx.hasChild:
+            self.SetValues(xxx.child)
+        self.Thaw()
+    def SetValues(self, xxx):
         # Set values, checkboxes to false, disable defaults
         if xxx.hasChild: prefix = '_'
         else: prefix = ''
         # Set values, checkboxes to false, disable defaults
         if xxx.hasChild: prefix = '_'
         else: prefix = ''
+        if xxx.hasName:
+            self.FindWindowByName('data_name').SetValue(xxx.name)
         for param in xxx.allParams:
         for param in xxx.allParams:
-            if xxx.params.has_key(param):
-                if param == 'content':
-                    value = []
-                    for text in xxx.params[param]:
-                        value.append(str(text.data)) # convert from unicode
-                else:
-                    value = xxx.params[param].data
+            try:
+                value = xxx.params[param].value()
                 self.FindWindowByName(prefix + 'data_' + param).SetValue(value)
                 if not param in xxx.required:
                     self.FindWindowByName(prefix + 'check_' + param).SetValue(true)
                 self.FindWindowByName(prefix + 'data_' + param).SetValue(value)
                 if not param in xxx.required:
                     self.FindWindowByName(prefix + 'check_' + param).SetValue(true)
-            else:
+            except KeyError:
                 self.FindWindowByName(prefix + 'data_' + param).Enable(false)
                 self.FindWindowByName(prefix + 'data_' + param).Enable(false)
-        # Same for the child of sizeritem
-        if xxx.hasChild:
-            xxx = xxx.child
-            for param in xxx.allParams:
-                if xxx.params.has_key(param):
-                    if param == 'content':
-                        value = []
-                        for text in xxx.params[param]:
-                            value.append(str(text.data)) # convert from unicode
-                    else:
-                        value = xxx.params[param].data
-                    self.FindWindowByName('data_' + param).SetValue(value)
-                    if not param in xxx.required:
-                        self.FindWindowByName('check_' + param).SetValue(true)
-                else:
-                    self.FindWindowByName('data_' + param).Enable(false)
     # If some parameter has changed
     def IsModified(self):
         return self.modified
     # If some parameter has changed
     def IsModified(self):
         return self.modified
@@ -220,27 +229,27 @@ class StylePage(wxPanel, ParamPage):
     def __init__(self, parent, xxx):
         wxPanel.__init__(self, parent, -1)
         ParamPage.__init__(self)
     def __init__(self, parent, xxx):
         wxPanel.__init__(self, parent, -1)
         ParamPage.__init__(self)
+        self.cacheId = xxx.__class__
         if wxGetOsVersion()[1] == 1:
             self.SetFont(wxFont(12, wxDEFAULT, wxNORMAL, wxNORMAL))
         else:
             self.SetFont(wxFont(10, wxDEFAULT, wxNORMAL, wxNORMAL))
         topSizer = wxBoxSizer(wxVERTICAL)
         if wxGetOsVersion()[1] == 1:
             self.SetFont(wxFont(12, wxDEFAULT, wxNORMAL, wxNORMAL))
         else:
             self.SetFont(wxFont(10, wxDEFAULT, wxNORMAL, wxNORMAL))
         topSizer = wxBoxSizer(wxVERTICAL)
-        sizer = wxFlexGridSizer(len(xxx.styles), 2, 0, 1)
+        sizer = wxFlexGridSizer(len(xxx.styles), 2, 1, 1)
         self.controls = {}              # save python objects
         for param in xxx.styles:
             present = param in xxx.params.keys()
             check = wxCheckBox(self, paramIDs[param],
                                param + ':', name = 'check_' + param)
             check.SetValue(present)
         self.controls = {}              # save python objects
         for param in xxx.styles:
             present = param in xxx.params.keys()
             check = wxCheckBox(self, paramIDs[param],
                                param + ':', name = 'check_' + param)
             check.SetValue(present)
-            control = paramDict[param](self, -1, '', (-1, -1),
-                                       'data_' + param)
+            control = paramDict[param](self, name = 'data_' + param)
             if present:
             if present:
-                control.SetValue(xxx.params[param].data)
+                control.SetValue(xxx.params[param].value())
             else:
                 control.SetValue('')
             control.Enable(present)
             else:
                 control.SetValue('')
             control.Enable(present)
-            sizer.AddMany([ (check, 0, 0),
-                            (control, 0, 0) ])
+            sizer.AddMany([ (check, 0, wxALIGN_CENTER_VERTICAL),
+                            (control, 0, wxALIGN_CENTER_VERTICAL) ])
             self.controls[param] = control
         topSizer.Add(sizer, 1, wxALL, 5)
         self.SetAutoLayout(true)
             self.controls[param] = control
         topSizer.Add(sizer, 1, wxALL, 5)
         self.SetAutoLayout(true)
@@ -248,6 +257,20 @@ class StylePage(wxPanel, ParamPage):
         
         self.modified = false
 
         
         self.modified = false
 
+    # Set data for a cahced page
+    def SetData(self, xxx):
+        for param in xxx.styles:
+            present = param in xxx.params.keys()
+            check = self.FindWindowByName('check_' + param)
+            check.SetValue(present)
+            control = self.controls[param]
+            if present:
+                control.SetValue(xxx.params[param].value())
+            else:
+                control.SetValue('')
+            control.Enable(present)
+        self.modified = false
+
     # If some parameter has changed
     def IsModified(self):
         return self.modified
     # If some parameter has changed
     def IsModified(self):
         return self.modified
@@ -302,7 +325,9 @@ class XML_Tree(wxTreeCtrl):
                             style=wxTR_HAS_BUTTONS | wxTR_LINES_AT_ROOT)
         self.SetBackgroundColour(wxColour(224, 248, 224))
         EVT_TREE_SEL_CHANGED(self, self.GetId(), self.OnSelChanged)
                             style=wxTR_HAS_BUTTONS | wxTR_LINES_AT_ROOT)
         self.SetBackgroundColour(wxColour(224, 248, 224))
         EVT_TREE_SEL_CHANGED(self, self.GetId(), self.OnSelChanged)
+        # One works on Linux, another on Windows
         EVT_TREE_ITEM_ACTIVATED(self, self.GetId(), self.OnItemActivated)
         EVT_TREE_ITEM_ACTIVATED(self, self.GetId(), self.OnItemActivated)
+        EVT_LEFT_DCLICK(self, self.OnDClick) 
         EVT_RIGHT_DOWN(self, self.OnRightDown)
         self.needUpdate = false
         self.pendingHighLight = None
         EVT_RIGHT_DOWN(self, self.OnRightDown)
         self.needUpdate = false
         self.pendingHighLight = None
@@ -316,6 +341,7 @@ class XML_Tree(wxTreeCtrl):
         xxxDialog.image = il.AddIcon(wxIconFromXPMData(images.getTreeDialogData()))
         xxxFrame.image = il.AddIcon(wxIconFromXPMData(images.getTreeFrameData()))
         xxxMenuBar.image = il.AddIcon(wxIconFromXPMData(images.getTreeMenuBarData()))
         xxxDialog.image = il.AddIcon(wxIconFromXPMData(images.getTreeDialogData()))
         xxxFrame.image = il.AddIcon(wxIconFromXPMData(images.getTreeFrameData()))
         xxxMenuBar.image = il.AddIcon(wxIconFromXPMData(images.getTreeMenuBarData()))
+        xxxToolBar.image = il.AddIcon(wxIconFromXPMData(images.getTreeToolBarData()))
         xxxMenu.image = il.AddIcon(wxIconFromXPMData(images.getTreeMenuData()))
         xxxSizer.imageH = il.AddIcon(wxIconFromXPMData(images.getTreeSizerHData()))
         xxxSizer.imageV = il.AddIcon(wxIconFromXPMData(images.getTreeSizerVData()))
         xxxMenu.image = il.AddIcon(wxIconFromXPMData(images.getTreeMenuData()))
         xxxSizer.imageH = il.AddIcon(wxIconFromXPMData(images.getTreeSizerHData()))
         xxxSizer.imageV = il.AddIcon(wxIconFromXPMData(images.getTreeSizerVData()))
@@ -361,7 +387,10 @@ class XML_Tree(wxTreeCtrl):
     # 'object' tag. xxxParent is parent xxx object
     def AddNode(self, itemParent, xxxParent, node):
         # Set item data to current node
     # 'object' tag. xxxParent is parent xxx object
     def AddNode(self, itemParent, xxxParent, node):
         # Set item data to current node
-        xxx = MakeXXXFromDOM(xxxParent, node)
+        try:
+            xxx = MakeXXXFromDOM(xxxParent, node)
+        except:
+            return
         treeObj = xxx.treeObject()
         # Append tree item
         item = self.AppendItem(itemParent, treeObj.treeName(),
         treeObj = xxx.treeObject()
         # Append tree item
         item = self.AppendItem(itemParent, treeObj.treeName(),
@@ -474,7 +503,7 @@ class XML_Tree(wxTreeCtrl):
             not in ['wxDialog', 'wxPanel', 'wxFrame']:
             return
         # Top-level does not have highlight
             not in ['wxDialog', 'wxPanel', 'wxFrame']:
             return
         # Top-level does not have highlight
-        if item == testWin.item:
+        if item == testWin.item or item == tree.GetRootItem():
             if testWin.highLight: testWin.highLight.Remove()
             return
         # If a control from another window is selected, remove highlight
             if testWin.highLight: testWin.highLight.Remove()
             return
         # If a control from another window is selected, remove highlight
@@ -502,7 +531,7 @@ class XML_Tree(wxTreeCtrl):
             testWin.highLight = HightLightBox(pos, size)
         testWin.highLight.item = item
                 
             testWin.highLight = HightLightBox(pos, size)
         testWin.highLight.item = item
                 
-    # Double-click
+    # Double-click on Linux
     def OnItemActivated(self, evt):
         item = evt.GetItem()
         xxx = self.GetPyData(item)
     def OnItemActivated(self, evt):
         item = evt.GetItem()
         xxx = self.GetPyData(item)
@@ -511,6 +540,20 @@ class XML_Tree(wxTreeCtrl):
             self.Apply(xxx, item)       # apply changes
         self.CreateTestWin(item)
         
             self.Apply(xxx, item)       # apply changes
         self.CreateTestWin(item)
         
+    # Double-click on Windows
+    def OnDClick(self, evt):
+        id, flags = self.HitTest(evt.GetPosition())
+        if flags in [wxTREE_HITTEST_ONITEMBUTTON, wxTREE_HITTEST_ONITEMLABEL]:
+            # !!! can't create a wxTreeItemId from int
+            item = self.selection           # assume item already selected
+            xxx = self.GetPyData(item)
+            if not xxx: return              # if root selected, do nothing
+            if panel.IsModified():
+                self.Apply(xxx, item)       # apply changes
+            self.CreateTestWin(item)
+        else:
+            evt.Skip()
+        
     # (re)create test window
     def CreateTestWin(self, node):
         global testWin
     # (re)create test window
     def CreateTestWin(self, node):
         global testWin
@@ -621,7 +664,7 @@ class XML_Tree(wxTreeCtrl):
         if xxx.hasChildren and not self.ItemHasChildren(item):
             return false
         return not (self.IsExpanded(item) and self.ItemHasChildren(item))
         if xxx.hasChildren and not self.ItemHasChildren(item):
             return false
         return not (self.IsExpanded(item) and self.ItemHasChildren(item))
-        
+
     # Pull-down
     def OnRightDown(self, evt):
         # Setup menu
     # Pull-down
     def OnRightDown(self, evt):
         # Setup menu
@@ -632,7 +675,9 @@ class XML_Tree(wxTreeCtrl):
             menu.Append(pullDownMenu.ID_EXPAND, 'Expand', 'Expand tree')
         else:
             self.ctrl = evt.ControlDown() # save Ctrl state
             menu.Append(pullDownMenu.ID_EXPAND, 'Expand', 'Expand tree')
         else:
             self.ctrl = evt.ControlDown() # save Ctrl state
-            m = wxMenu()                # create menu
+            self.shift = evt.ShiftDown()  # and Shift too
+            m = wxMenu()                  # create menu
+            needInsert = false
             if item != self.GetRootItem(): needInsert = self.NeedInsert(item)
             if item == self.GetRootItem() or \
                self.GetItemParent(item) == self.GetRootItem() and needInsert:
             if item != self.GetRootItem(): needInsert = self.NeedInsert(item)
             if item == self.GetRootItem() or \
                self.GetItemParent(item) == self.GetRootItem() and needInsert:
@@ -640,12 +685,15 @@ class XML_Tree(wxTreeCtrl):
                 m.Append(pullDownMenu.ID_NEW_DIALOG, 'Dialog', 'Create dialog')
                 m.Append(pullDownMenu.ID_NEW_FRAME, 'Frame', 'Create frame')
                 m.AppendSeparator()
                 m.Append(pullDownMenu.ID_NEW_DIALOG, 'Dialog', 'Create dialog')
                 m.Append(pullDownMenu.ID_NEW_FRAME, 'Frame', 'Create frame')
                 m.AppendSeparator()
-                m.Append(pullDownMenu.ID_NEW_MENU_BAR, 'MenuBar', 'Create menu bar')
+                m.Append(pullDownMenu.ID_NEW_TOOL_BAR, 'ToolBar', 'Create toolbar')
+                m.Append(pullDownMenu.ID_NEW_MENU_BAR, 'MenuBar', 'Create menubar')
                 m.Append(pullDownMenu.ID_NEW_MENU, 'Menu', 'Create menu')
             else:
                 xxx = self.GetPyData(item)
                 if xxx.__class__ == xxxMenuBar:
                     m.Append(pullDownMenu.ID_NEW_MENU, 'Menu', 'Create menu')
                 m.Append(pullDownMenu.ID_NEW_MENU, 'Menu', 'Create menu')
             else:
                 xxx = self.GetPyData(item)
                 if xxx.__class__ == xxxMenuBar:
                     m.Append(pullDownMenu.ID_NEW_MENU, 'Menu', 'Create menu')
+                elif xxx.__class__ in [xxxToolBar, xxxTool]:
+                    SetMenu(m, pullDownMenu.toolBarControls)
                 elif xxx.__class__ in [xxxMenu, xxxMenuItem]:
                     SetMenu(m, pullDownMenu.menuControls)
                 else:
                 elif xxx.__class__ in [xxxMenu, xxxMenuItem]:
                     SetMenu(m, pullDownMenu.menuControls)
                 else:
@@ -654,15 +702,20 @@ class XML_Tree(wxTreeCtrl):
                             xxx.parent and xxx.parent.isSizer):
                         m.Enable(pullDownMenu.ID_NEW_SPACER, false)
             # Select correct label for create menu
                             xxx.parent and xxx.parent.isSizer):
                         m.Enable(pullDownMenu.ID_NEW_SPACER, false)
             # Select correct label for create menu
-            if item == self.GetRootItem():
-                menu.AppendMenu(wxNewId(), 'Create', m, 'Create top-level object')
+            if not needInsert:
+                if self.shift:
+                    menu.AppendMenu(wxNewId(), 'Insert Child', m,
+                                    'Create child object as the first child')
+                else:
+                    menu.AppendMenu(wxNewId(), 'Append Child', m,
+                                    'Create child object as the last child')
             else:
             else:
-                if not needInsert:
-                    menu.AppendMenu(wxNewId(), 'Create child', m,
-                                            'Create child object')
+                if self.shift:
+                    menu.AppendMenu(wxNewId(), 'Create Sibling', m,
+                                    'Create sibling before selected object')
                 else:
                     menu.AppendMenu(wxNewId(), 'Create Sibling', m,
                 else:
                     menu.AppendMenu(wxNewId(), 'Create Sibling', m,
-                                            'Create sibling of selected object')
+                                    'Create sibling after selected object')
             menu.AppendSeparator()
             menu.Append(wxID_CUT, 'Cut', 'Cut to the clipboard')
             menu.Append(wxID_COPY, 'Copy', 'Copy to the clipboard')
             menu.AppendSeparator()
             menu.Append(wxID_CUT, 'Cut', 'Cut to the clipboard')
             menu.Append(wxID_COPY, 'Copy', 'Copy to the clipboard')
@@ -702,29 +755,14 @@ class XML_Tree(wxTreeCtrl):
                 self.SetItemText(item, xxx.treeName())
         if xxx.hasChild: prefix = '_'
         else: prefix = ''
                 self.SetItemText(item, xxx.treeName())
         if xxx.hasChild: prefix = '_'
         else: prefix = ''
-        for param, data in xxx.params.items():
-            value = panel.FindWindowByName(prefix + 'data_' + param).GetValue()
-            if param == 'content':
-                # If number if items is not the same, recreate children
-                if len(value) != len(data):
-                    elem = xxx.element.getElementsByTagName('content')[0]
-                    for n in elem.childNodes:
-                        elem.removeChild(n)
-                    data = []
-                    for str in value:
-                        itemElem = tree.dom.createElement('item')
-                        itemText = tree.dom.createTextNode(str)
-                        itemElem.appendChild(itemText)
-                        elem.appendChild(itemElem)
-                        data.append(itemText)
-                    xxx.params[param] = data
-                else:
-                    for i in range(len(value)):
-                        data[i].data = value[i]
-            elif param == 'font':
-                data.updateXML(value)
+        for param, paramObj in xxx.params.items():
+            paramWin = panel.FindWindowByName(prefix + 'data_' + param)
+            if not paramWin.modified: continue
+            value = paramWin.GetValue()
+            if param in xxx.specials:
+                xxx.setSpecial(param, value)
             else:
             else:
-                data.data = value
+                paramObj.update(value)
         if xxx.hasChild:
             self.Apply(xxx.child, item)
         else:
         if xxx.hasChild:
             self.Apply(xxx.child, item)
         else:
@@ -738,6 +776,8 @@ class PullDownMenu:
     ID_NEW_PANEL = wxNewId()
     ID_NEW_DIALOG = wxNewId()
     ID_NEW_FRAME = wxNewId()
     ID_NEW_PANEL = wxNewId()
     ID_NEW_DIALOG = wxNewId()
     ID_NEW_FRAME = wxNewId()
+    ID_NEW_TOOL_BAR = wxNewId()
+    ID_NEW_TOOL = wxNewId()
     ID_NEW_MENU_BAR = wxNewId()
     ID_NEW_MENU = wxNewId()
 
     ID_NEW_MENU_BAR = wxNewId()
     ID_NEW_MENU = wxNewId()
 
@@ -756,6 +796,7 @@ class PullDownMenu:
     ID_NEW_LIST_BOX = wxNewId()
         
     ID_NEW_STATIC_LINE = wxNewId()
     ID_NEW_LIST_BOX = wxNewId()
         
     ID_NEW_STATIC_LINE = wxNewId()
+    ID_NEW_STATIC_BITMAP = wxNewId()
     ID_NEW_CHOICE = wxNewId()
     ID_NEW_SLIDER = wxNewId()
     ID_NEW_GAUGE = wxNewId()
     ID_NEW_CHOICE = wxNewId()
     ID_NEW_SLIDER = wxNewId()
     ID_NEW_GAUGE = wxNewId()
@@ -772,6 +813,8 @@ class PullDownMenu:
     ID_NEW_GRID_SIZER = wxNewId()
     ID_NEW_FLEX_GRID_SIZER = wxNewId()
     ID_NEW_SPACER = wxNewId()
     ID_NEW_GRID_SIZER = wxNewId()
     ID_NEW_FLEX_GRID_SIZER = wxNewId()
     ID_NEW_SPACER = wxNewId()
+    ID_NEW_TOOL_BAR = wxNewId()
+    ID_NEW_TOOL = wxNewId()
     ID_NEW_MENU = wxNewId()
     ID_NEW_MENU_ITEM = wxNewId()
     ID_NEW_SEPARATOR = wxNewId()
     ID_NEW_MENU = wxNewId()
     ID_NEW_MENU_ITEM = wxNewId()
     ID_NEW_SEPARATOR = wxNewId()
@@ -786,6 +829,8 @@ class PullDownMenu:
         # We connect to tree, but process in frame
         EVT_MENU_HIGHLIGHT_ALL(tree, parent.OnPullDownHighlight)
 
         # We connect to tree, but process in frame
         EVT_MENU_HIGHLIGHT_ALL(tree, parent.OnPullDownHighlight)
 
+################################################################################
+
 class Frame(wxFrame):
     def __init__(self, size):
         wxFrame.__init__(self, None, -1, '', size=size)
 class Frame(wxFrame):
     def __init__(self, size):
         wxFrame.__init__(self, None, -1, '', size=size)
@@ -883,6 +928,7 @@ class Frame(wxFrame):
         sizer = wxBoxSizer(wxVERTICAL)
         sizer.Add(wxStaticLine(self, -1), 0, wxEXPAND)
         splitter = wxSplitterWindow(self, -1, style=wxSP_3DSASH)
         sizer = wxBoxSizer(wxVERTICAL)
         sizer.Add(wxStaticLine(self, -1), 0, wxEXPAND)
         splitter = wxSplitterWindow(self, -1, style=wxSP_3DSASH)
+        self.splitter = splitter
         splitter.SetMinimumPaneSize(100)
         # Create tree
         global tree
         splitter.SetMinimumPaneSize(100)
         # Create tree
         global tree
@@ -892,7 +938,7 @@ class Frame(wxFrame):
         global panel
         panel = Panel(splitter)
         # Set plitter windows
         global panel
         panel = Panel(splitter)
         # Set plitter windows
-        splitter.SplitVertically(tree, panel, 200)
+        splitter.SplitVertically(tree, panel, conf.sashPos)
         sizer.Add(splitter, 1, wxEXPAND)
         self.SetAutoLayout(true)
         self.SetSizer(sizer)
         sizer.Add(splitter, 1, wxEXPAND)
         self.SetAutoLayout(true)
         self.SetSizer(sizer)
@@ -905,8 +951,12 @@ class Frame(wxFrame):
             pullDownMenu.ID_NEW_PANEL: 'wxPanel',
             pullDownMenu.ID_NEW_DIALOG: 'wxDialog',
             pullDownMenu.ID_NEW_FRAME: 'wxFrame',
             pullDownMenu.ID_NEW_PANEL: 'wxPanel',
             pullDownMenu.ID_NEW_DIALOG: 'wxDialog',
             pullDownMenu.ID_NEW_FRAME: 'wxFrame',
+            pullDownMenu.ID_NEW_TOOL_BAR: 'wxToolBar',
+            pullDownMenu.ID_NEW_TOOL: 'tool',
             pullDownMenu.ID_NEW_MENU_BAR: 'wxMenuBar',
             pullDownMenu.ID_NEW_MENU: 'wxMenu',
             pullDownMenu.ID_NEW_MENU_BAR: 'wxMenuBar',
             pullDownMenu.ID_NEW_MENU: 'wxMenu',
+            pullDownMenu.ID_NEW_MENU_ITEM: 'wxMenuItem',
+            pullDownMenu.ID_NEW_SEPARATOR: 'separator',
 
             pullDownMenu.ID_NEW_STATIC_TEXT: 'wxStaticText',
             pullDownMenu.ID_NEW_TEXT_CTRL: 'wxTextCtrl',
 
             pullDownMenu.ID_NEW_STATIC_TEXT: 'wxStaticText',
             pullDownMenu.ID_NEW_TEXT_CTRL: 'wxTextCtrl',
@@ -923,6 +973,7 @@ class Frame(wxFrame):
             pullDownMenu.ID_NEW_LIST_BOX: 'wxListBox',
             
             pullDownMenu.ID_NEW_STATIC_LINE: 'wxStaticLine',
             pullDownMenu.ID_NEW_LIST_BOX: 'wxListBox',
             
             pullDownMenu.ID_NEW_STATIC_LINE: 'wxStaticLine',
+            pullDownMenu.ID_NEW_STATIC_BITMAP: 'wxStaticBitmap',
             pullDownMenu.ID_NEW_CHOICE: 'wxChoice',
             pullDownMenu.ID_NEW_SLIDER: 'wxSlider',
             pullDownMenu.ID_NEW_GAUGE: 'wxGauge',
             pullDownMenu.ID_NEW_CHOICE: 'wxChoice',
             pullDownMenu.ID_NEW_SLIDER: 'wxSlider',
             pullDownMenu.ID_NEW_GAUGE: 'wxGauge',
@@ -939,9 +990,6 @@ class Frame(wxFrame):
             pullDownMenu.ID_NEW_GRID_SIZER: 'wxGridSizer',
             pullDownMenu.ID_NEW_FLEX_GRID_SIZER: 'wxFlexGridSizer',
             pullDownMenu.ID_NEW_SPACER: 'spacer',
             pullDownMenu.ID_NEW_GRID_SIZER: 'wxGridSizer',
             pullDownMenu.ID_NEW_FLEX_GRID_SIZER: 'wxFlexGridSizer',
             pullDownMenu.ID_NEW_SPACER: 'spacer',
-            pullDownMenu.ID_NEW_MENU: 'wxMenu',
-            pullDownMenu.ID_NEW_MENU_ITEM: 'wxMenuItem',
-            pullDownMenu.ID_NEW_SEPARATOR: 'separator',
             }
         pullDownMenu.controls = [
             ['control', 'Various controls',
             }
         pullDownMenu.controls = [
             ['control', 'Various controls',
@@ -988,6 +1036,10 @@ class Frame(wxFrame):
             (pullDownMenu.ID_NEW_MENU_ITEM, 'MenuItem', 'Create menu item'),
             (pullDownMenu.ID_NEW_SEPARATOR, 'Separator', 'Create separator'),
             ]
             (pullDownMenu.ID_NEW_MENU_ITEM, 'MenuItem', 'Create menu item'),
             (pullDownMenu.ID_NEW_SEPARATOR, 'Separator', 'Create separator'),
             ]
+        pullDownMenu.toolBarControls = [
+            (pullDownMenu.ID_NEW_TOOL, 'Tool', 'Create tool'),
+            (pullDownMenu.ID_NEW_SEPARATOR, 'Separator', 'Create separator'),
+            ]
         
         # Initialize
         self.Clear()
         
         # Initialize
         self.Clear()
@@ -1220,9 +1272,11 @@ class Frame(wxFrame):
         self.tb.ToggleTool(self.ID_AUTO_REFRESH, conf.autoRefresh)
 
     def OnAbout(self, evt):
         self.tb.ToggleTool(self.ID_AUTO_REFRESH, conf.autoRefresh)
 
     def OnAbout(self, evt):
-        wxMessageDialog(self, '%s %s\n\nRoman Rolinsky <rolinsky@mema.ucl.ac.be>' % \
-                        (progname, version),
-                        'About %s' % progname, wxOK | wxCENTRE).ShowModal()
+        str = '%s %s\n\nRoman Rolinsky <rolinsky@mema.ucl.ac.be>' % \
+              (progname, version)
+        dlg = wxMessageDialog(self, str, 'About ' + progname, wxOK | wxCENTRE)
+        dlg.ShowModal()
+        dlg.Destroy()
 
     # Simple emulation of python command line
     def OnDebugCMD(self, evt):
 
     # Simple emulation of python command line
     def OnDebugCMD(self, evt):
@@ -1323,7 +1377,9 @@ class Frame(wxFrame):
                         tree.GetSelection() != tree.GetRootItem()
             evt.Enable(enable)
         elif evt.GetId() == wxID_PASTE:
                         tree.GetSelection() != tree.GetRootItem()
             evt.Enable(enable)
         elif evt.GetId() == wxID_PASTE:
-            enable = self.clipboard != None
+            enable = tree.GetSelection().IsOk() and \
+                     tree.GetSelection() != tree.GetRootItem() and \
+                     self.clipboard != None
             evt.Enable(enable)
 
     def OnIdle(self, evt):
             evt.Enable(enable)
 
     def OnIdle(self, evt):
@@ -1335,12 +1391,16 @@ class Frame(wxFrame):
                 tree.needUpdate = false
         elif tree.pendingHighLight:
             tree.HighLight(tree.pendingHighLight)
                 tree.needUpdate = false
         elif tree.pendingHighLight:
             tree.HighLight(tree.pendingHighLight)
-        evt.Skip()
+        else:
+            evt.Skip()
 
     def OnCloseWindow(self, evt):
         if not self.AskSave(): return
         if testWin: testWin.Destroy()
 
     def OnCloseWindow(self, evt):
         if not self.AskSave(): return
         if testWin: testWin.Destroy()
+        # Destroy cached windows
+        for w in panel.styleCache.values(): w.Destroy()
         conf.width, conf.height = self.GetSize()
         conf.width, conf.height = self.GetSize()
+        conf.sashPos = self.splitter.GetSashPosition()
         evt.Skip()
 
     def Clear(self):
         evt.Skip()
 
     def Clear(self):
@@ -1385,8 +1445,10 @@ class Frame(wxFrame):
     def AskSave(self):
         if not (self.modified or panel.IsModified()): return true
         flags = wxICON_EXCLAMATION | wxYES_NO | wxCANCEL | wxCENTRE
     def AskSave(self):
         if not (self.modified or panel.IsModified()): return true
         flags = wxICON_EXCLAMATION | wxYES_NO | wxCANCEL | wxCENTRE
-        say = wxMessageDialog( self, 'File is modified. Save before exit?',
-                               'Save before too late?', flags ).ShowModal()
+        dlg = wxMessageDialog( self, 'File is modified. Save before exit?',
+                               'Save before too late?', flags )
+        say = dlg.ShowModal()
+        dlg.Destroy()
         if say == wxID_YES:
             self.OnSaveOrSaveAs(wxCommandEvent(wxID_SAVE))
             # If save was successful, modified flag is unset
         if say == wxID_YES:
             self.OnSaveOrSaveAs(wxCommandEvent(wxID_SAVE))
             # If save was successful, modified flag is unset
@@ -1408,6 +1470,7 @@ class App(wxApp):
         conf = wxConfig(style=wxCONFIG_USE_LOCAL_FILE)
         conf.autoRefresh = conf.ReadInt('autorefresh', true)
         size = conf.ReadInt('width', 800), conf.ReadInt('height', 600)
         conf = wxConfig(style=wxCONFIG_USE_LOCAL_FILE)
         conf.autoRefresh = conf.ReadInt('autorefresh', true)
         size = conf.ReadInt('width', 800), conf.ReadInt('height', 600)
+        conf.sashPos = conf.ReadInt('sashPos', 200)
         # Add handlers
         wxFileSystem_AddHandler(wxMemoryFSHandler())
         wxInitAllImageHandlers()
         # Add handlers
         wxFileSystem_AddHandler(wxMemoryFSHandler())
         wxInitAllImageHandlers()
@@ -1415,7 +1478,7 @@ class App(wxApp):
         global frame
         frame = self.frame = Frame(size)
         self.frame.Show(true)
         global frame
         frame = self.frame = Frame(size)
         self.frame.Show(true)
-        # Load resources from XRC file (!!! should be transformed to .py later)
+        # Load resources from XRC file (!!! should be transformed to .py later?)
         sys.modules['params'].frame = frame
         frame.res = wxXmlResource('')
         frame.res.Load(os.path.join(sys.path[0], 'xrced.xrc'))
         sys.modules['params'].frame = frame
         frame.res = wxXmlResource('')
         frame.res.Load(os.path.join(sys.path[0], 'xrced.xrc'))
@@ -1427,6 +1490,7 @@ class App(wxApp):
         wc.WriteInt('autorefresh', conf.autoRefresh)
         wc.WriteInt('width', conf.width)
         wc.WriteInt('height', conf.height)
         wc.WriteInt('autorefresh', conf.autoRefresh)
         wc.WriteInt('width', conf.width)
         wc.WriteInt('height', conf.height)
+        wc.WriteInt('sashPos', conf.sashPos)
         wc.Flush()
 
 def main():
         wc.Flush()
 
 def main():
index 3187456095cb9573326969a80a0ceda50dba721f..47d8b0a03f66c766b693209711a25446fb731a2b 100644 (file)
@@ -11,6 +11,72 @@ import wxPython.lib.wxpTag
 
 from params import *
 
 
 from params import *
 
+# Parameter value class
+class xxxParam:
+    # Standard use: for text nodes
+    def __init__(self, node):
+        self.node = node
+        if not node.hasChildNodes():
+            # If does not have child nodes, create empty text node
+            text = tree.dom.createTextNode('')
+            node.appendChild(text)
+        else:
+            text = node.childNodes[0] # first child must be text node
+            assert text.nodeType == minidom.Node.TEXT_NODE
+        self.textNode = text
+    # Value returns string
+    def value(self):
+        return str(self.textNode.data)
+    def update(self, value):
+        self.textNode.data = value
+    def remove(self):
+        self.node.parentNode.removeChild(self.node)
+        self.node.unlink()
+
+# Content parameter
+class xxxParamContent:
+    def __init__(self, node):
+        self.node = node
+        data, l = [], []                # data is needed to quicker value retrieval
+        nodes = node.childNodes[:]      # make a copy of the child list
+        for n in nodes:
+            if n.nodeType == minidom.Node.ELEMENT_NODE:
+                assert n.tagName == 'item', 'bad content content'
+                if not n.hasChildNodes():
+                    # If does not have child nodes, create empty text node
+                    text = tree.dom.createTextNode('')
+                    node.appendChild(text)
+                else:
+                    # !!! normalize?
+                    text = n.childNodes[0] # first child must be text node
+                    assert text.nodeType == minidom.Node.TEXT_NODE
+                l.append(text)
+                data.append(text.data)
+            else:                       # remove other
+                node.removeChild(n)
+                n.unlink()
+        self.l, self.data = l, data
+    def value(self):
+        return self.data
+    def update(self, value):
+        # If number if items is not the same, recreate children
+        if len(value) != len(self.l):   # remove first if number of items has changed
+            for n in self.node.childNodes:
+                self.node.removeChild(n)
+            l = []
+            for str in value:
+                itemElem = tree.dom.createElement('item')
+                itemText = tree.dom.createTextNode(str)
+                itemElem.appendChild(itemText)
+                self.node.appendChild(itemElem)
+                l.append(itemText)
+        else:
+            for i in range(len(value)):
+                self.l[i].data = value[i]
+        self.data = value
+
+################################################################################
+
 # Classes to interface DOM objects
 class xxxObject:
     # Default behavior
 # Classes to interface DOM objects
 class xxxObject:
     # Default behavior
@@ -20,6 +86,8 @@ class xxxObject:
     isSizer = hasChild = false
     # Style parameters (all optional)
     styles = ['fg', 'bg', 'font', 'enabled', 'focused', 'hidden', 'tooltip']
     isSizer = hasChild = false
     # Style parameters (all optional)
     styles = ['fg', 'bg', 'font', 'enabled', 'focused', 'hidden', 'tooltip']
+    # Special parameters
+    specials = []
     # Required paremeters: none by default
     required = []
     # Default parameters with default values
     # Required paremeters: none by default
     required = []
     # Default parameters with default values
@@ -44,44 +112,20 @@ class xxxObject:
         nodes = element.childNodes[:]
         for node in nodes:
             if node.nodeType == minidom.Node.ELEMENT_NODE:
         nodes = element.childNodes[:]
         for node in nodes:
             if node.nodeType == minidom.Node.ELEMENT_NODE:
-                if node.tagName == 'object':
+                tag = node.tagName
+                if tag == 'object':
                     continue            # do nothing for object children here
                     continue            # do nothing for object children here
-                if not node.tagName in self.allParams and not node.tagName in self.styles:
+                if not tag in self.allParams and not tag in self.styles:
                     print 'WARNING: unknown parameter for %s: %s' % \
                     print 'WARNING: unknown parameter for %s: %s' % \
-                          (self.className, node.tagName)
-                    continue
-                if node.tagName == 'content': # has items
-                    # Param value is a list of text nodes
-                    l = []
-                    nodes = node.childNodes[:]
-                    for n in nodes:
-                        if n.nodeType == minidom.Node.ELEMENT_NODE:
-                            assert n.tagName == 'item', 'bad content content'
-                            if not n.hasChildNodes():
-                                # If does not have child nodes, create empty text node
-                                text = tree.dom.createTextNode('')
-                                node.appendChild(text)
-                            else:
-                                # !!! normalize?
-                                text = n.childNodes[0] # first child must be text node
-                                assert text.nodeType == minidom.Node.TEXT_NODE
-                            l.append(text)
-                        else:
-                            node.removeChild(n)
-                            n.unlink()
-                    self.params[node.tagName] = l
-                elif node.tagName == 'font': # has children
-                    # we read and write all font parameters at once
-                    self.params[node.tagName] = xxxFont(self, node)
+                          (self.className, tag)
+                elif tag in self.specials:
+                    self.special(tag, node)
+                elif tag == 'content':
+                    self.params[tag] = xxxParamContent(node)
+                elif tag == 'font': # has children
+                    self.params[tag] = xxxParamFont(self, node)
                 else:                   # simple parameter
                 else:                   # simple parameter
-                    if not node.hasChildNodes():
-                        # If does not have child nodes, create empty text node
-                        text = tree.dom.createTextNode('')
-                        node.appendChild(text)
-                    else:
-                        text = node.childNodes[0] # first child must be text node
-                        assert text.nodeType == minidom.Node.TEXT_NODE
-                    self.params[node.tagName] = text
+                    self.params[tag] = xxxParam(node)
             else:
                 # Remove all other nodes
                 element.removeChild(node)
             else:
                 # Remove all other nodes
                 element.removeChild(node)
@@ -95,10 +139,8 @@ class xxxObject:
         if self.hasName:
             html += """\
 <td><wxp module="xxx" class="ParamText" width=150>
         if self.hasName:
             html += """\
 <td><wxp module="xxx" class="ParamText" width=150>
-<param name="id" value="%d">
 <param name="name" value="data_name">
 <param name="name" value="data_name">
-<param name="value" value='("%s")'>
-</wxp></td>""" % (-1, self.name)
+</wxp></td>"""
         html += '</table><p>'
         html += '<table cellspacing=0 cellpadding=0>\n'
         # Add required parameters
         html += '</table><p>'
         html += '<table cellspacing=0 cellpadding=0>\n'
         # Add required parameters
@@ -115,17 +157,6 @@ class xxxObject:
 <param name="label" value=("")>
 </wxp></td><td width=100>%s: </td>
 """ % (paramIDs[param], prefix + 'check_' + param, param)
 <param name="label" value=("")>
 </wxp></td><td width=100>%s: </td>
 """ % (paramIDs[param], prefix + 'check_' + param, param)
-            # Add value part
-            if self.params.has_key(param):
-                if param == 'content':
-                    l = []
-                    for text in self.params[param]:
-                        l.append(str(text.data)) # convert from unicode
-                    value = str(l)
-                else:
-                    value = "('" + self.params[param].data + "')"
-            else:
-                value = "('')"
             # Get parameter type
             try:
                 # Local or overriden type
             # Get parameter type
             try:
                 # Local or overriden type
@@ -141,9 +172,8 @@ class xxxObject:
 <td><wxp module="xxx" class="%s">
 <param name="id" value="%d">
 <param name="name" value="%s">
 <td><wxp module="xxx" class="%s">
 <param name="id" value="%d">
 <param name="name" value="%s">
-<param name="value" value="%s">
 </wxp></td>
 </wxp></td>
-""" % (typeClass, -1, prefix + 'data_' + param, value)
+""" % (typeClass, -1, prefix + 'data_' + param)
         html += '</table>\n'
         return html
     # Returns real tree object
         html += '</table>\n'
         return html
     # Returns real tree object
@@ -162,20 +192,27 @@ class xxxObject:
 
 ################################################################################
 
 
 ################################################################################
 
-class xxxFont(xxxObject):
+class xxxParamFont(xxxParam):
     allParams = ['size', 'style', 'weight', 'family', 'underlined',
                  'face', 'encoding']
     def __init__(self, parent, element):
         xxxObject.__init__(self, parent, element)
         self.parentNode = element       # required to behave similar to DOM node
     allParams = ['size', 'style', 'weight', 'family', 'underlined',
                  'face', 'encoding']
     def __init__(self, parent, element):
         xxxObject.__init__(self, parent, element)
         self.parentNode = element       # required to behave similar to DOM node
-        self.data = self.value()
-    def updateXML(self, value):
+        v = []
+        for p in self.allParams:
+            try:
+                v.append(str(self.params[p].data))
+            except KeyError:
+                v.append('')
+        self.data = v
+    def update(self, value):
         # `value' is a list of strings corresponding to all parameters
         elem = self.element
         for node in elem.childNodes:
             elem.removeChild(node)
         i = 0
         self.params.clear()
         # `value' is a list of strings corresponding to all parameters
         elem = self.element
         for node in elem.childNodes:
             elem.removeChild(node)
         i = 0
         self.params.clear()
+        v = []
         for param in self.allParams:
             if value[i]:
                 fontElem = tree.dom.createElement(param)
         for param in self.allParams:
             if value[i]:
                 fontElem = tree.dom.createElement(param)
@@ -183,17 +220,9 @@ class xxxFont(xxxObject):
                 self.params[param] = textNode
                 fontElem.appendChild(textNode)
                 elem.appendChild(fontElem)
                 self.params[param] = textNode
                 fontElem.appendChild(textNode)
                 elem.appendChild(fontElem)
+            v.append(value[i])
             i += 1
             i += 1
-        # Update data
-        self.data = self.value()
-    def value(self):
-        v = []
-        for p in self.allParams:
-            try:
-                v.append(str(self.params[p].data))
-            except KeyError:
-                v.append('')
-        return v
+        self.data = v
 
 ################################################################################
 
 
 ################################################################################
 
@@ -207,13 +236,17 @@ class xxxPanel(xxxContainer):
     allParams = ['pos', 'size', 'style']
     styles = ['fg', 'bg', 'font', 'enabled', 'focused', 'hidden', 'exstyle',
               'tooltip']
     allParams = ['pos', 'size', 'style']
     styles = ['fg', 'bg', 'font', 'enabled', 'focused', 'hidden', 'exstyle',
               'tooltip']
+    winStyles = ['wxNO_3D', 'wxTAB_TRAVERSAL', 'wxCLIP_CHILDREN']
     exStyles = ['wxWS_EX_VALIDATE_RECURSIVELY']
 
 class xxxDialog(xxxContainer):
     allParams = ['title', 'pos', 'size', 'style']
     required = ['title']
     exStyles = ['wxWS_EX_VALIDATE_RECURSIVELY']
 
 class xxxDialog(xxxContainer):
     allParams = ['title', 'pos', 'size', 'style']
     required = ['title']
-    winStyles = ['wxDIALOG_MODAL', 'wxCAPTION', 'wxDEFAULT_DIALOG_STYLE',
-              'wxRESIZE_BORDER', 'wxSYSTEM_MENU',  'wxTHICK_FRAME', 'wxSTAY_ON_TOP']
+    winStyles = ['wxDEFAULT_DIALOG_STYLE', 'wxSTAY_ON_TOP',
+                 'wxDIALOG_MODAL', 'wxDIALOG_MODELESS',
+                 'wxCAPTION', 'wxSYSTEM_MENU', 'wxRESIZE_BORDER', 'wxRESIZE_BOX',
+                 'wxTHICK_FRAME', 
+                 'wxNO_3D', 'wxTAB_TRAVERSAL', 'wxCLIP_CHILDREN']
     styles = ['fg', 'bg', 'font', 'enabled', 'focused', 'hidden', 'exstyle',
               'tooltip']
     exStyles = ['wxWS_EX_VALIDATE_RECURSIVELY']
     styles = ['fg', 'bg', 'font', 'enabled', 'focused', 'hidden', 'exstyle',
               'tooltip']
     exStyles = ['wxWS_EX_VALIDATE_RECURSIVELY']
@@ -222,14 +255,41 @@ class xxxFrame(xxxContainer):
     allParams = ['title', 'centered', 'pos', 'size', 'style']
     paramDict = {'centered': ParamBool}
     required = ['title']
     allParams = ['title', 'centered', 'pos', 'size', 'style']
     paramDict = {'centered': ParamBool}
     required = ['title']
-    winStyles = ['wxDEFAULT_FRAME_STYLE', 'wxICONIZE', 'wxCAPTION', 'wxMINIMIZE',
-              'wxICONIZE', 'wxMINIMIZE_BOX', 'wxMAXIMIZE', 'wxMAXIMIZE_BOX',
-              'wxSTAY_ON_TOP', 'wxSYSTEM_MENU', 'wxRESIZE_BORDER',
-              'wxFRAME_FLOAT_ON_PARENT', 'wxFRAME_TOOL_WINDOW']
+    winStyles = ['wxDEFAULT_FRAME_STYLE', 'wxDEFAULT_DIALOG_STYLE',
+                 'wxSTAY_ON_TOP', 
+                 'wxCAPTION', 'wxSYSTEM_MENU', 'wxRESIZE_BORDER',
+                 'wxRESIZE_BOX', 'wxMINIMIZE_BOX', 'wxMAXIMIZE_BOX',
+                 'wxFRAME_FLOAT_ON_PARENT', 'wxFRAME_TOOL_WINDOW',
+                 'wxNO_3D', 'wxTAB_TRAVERSAL', 'wxCLIP_CHILDREN']
     styles = ['fg', 'bg', 'font', 'enabled', 'focused', 'hidden', 'exstyle',
               'tooltip']
     exStyles = ['wxWS_EX_VALIDATE_RECURSIVELY']
 
     styles = ['fg', 'bg', 'font', 'enabled', 'focused', 'hidden', 'exstyle',
               'tooltip']
     exStyles = ['wxWS_EX_VALIDATE_RECURSIVELY']
 
+class xxxTool(xxxObject):
+    allParams = ['bitmap', 'bitmap2', 'toggle', 'tooltip', 'longhelp']
+    paramDict = {'bitmap2': ParamFile}
+    hasStyle = false
+
+class xxxToolBar(xxxContainer):
+    allParams = ['bitmapsize', 'margins', 'packing', 'separation', 
+                 'pos', 'size', 'style']
+    hasStyle = false
+    paramDict = {'bitmapsize': ParamPosSize, 'margins': ParamPosSize,
+                 'packing': ParamInt, 'separation': ParamInt,
+                 'style': ParamNonGenericStyle}
+    winStyles = ['wxTB_FLAT', 'wxTB_DOCKABLE', 'wxTB_VERTICAL', 'wxTB_HORIZONTAL']
+
+################################################################################
+# Bitmap, Icon
+
+class xxxBitmap(xxxObject):
+    allParams = ['bitmap']
+    required = ['bitmap']
+
+class xxxIcon(xxxObject):
+    allParams = ['icon']
+    required = ['icon']
+
 ################################################################################
 # Controls
 
 ################################################################################
 # Controls
 
@@ -242,14 +302,19 @@ class xxxStaticLine(xxxObject):
     allParams = ['pos', 'size', 'style']
     winStyles = ['wxLI_HORIZONTAL', 'wxLI_VERTICAL']
 
     allParams = ['pos', 'size', 'style']
     winStyles = ['wxLI_HORIZONTAL', 'wxLI_VERTICAL']
 
+class xxxStaticBitmap(xxxObject):
+    allParams = ['bitmap', 'pos', 'size', 'style']
+    required = ['bitmap']
+
 class xxxTextCtrl(xxxObject):
     allParams = ['value', 'pos', 'size', 'style']
     winStyles = ['wxTE_PROCESS_ENTER', 'wxTE_PROCESS_TAB', 'wxTE_MULTILINE',
 class xxxTextCtrl(xxxObject):
     allParams = ['value', 'pos', 'size', 'style']
     winStyles = ['wxTE_PROCESS_ENTER', 'wxTE_PROCESS_TAB', 'wxTE_MULTILINE',
-              'wxTE_PASSWORD', 'wxTE_READONLY']
+              'wxTE_PASSWORD', 'wxTE_READONLY', 'wxHSCROLL']
 
 class xxxChoice(xxxObject):
     allParams = ['content', 'selection', 'pos', 'size', 'style']
     required = ['content']
 
 class xxxChoice(xxxObject):
     allParams = ['content', 'selection', 'pos', 'size', 'style']
     required = ['content']
+    winStyles = ['wxCB_SORT']
 
 class xxxSlider(xxxObject):
     allParams = ['value', 'min', 'max', 'pos', 'size', 'style',
 
 class xxxSlider(xxxObject):
     allParams = ['value', 'min', 'max', 'pos', 'size', 'style',
@@ -260,7 +325,8 @@ class xxxSlider(xxxObject):
                  'tick': ParamInt, 'selmin': ParamInt, 'selmax': ParamInt}
     required = ['value', 'min', 'max']
     winStyles = ['wxSL_HORIZONTAL', 'wxSL_VERTICAL', 'wxSL_AUTOTICKS', 'wxSL_LABELS',
                  'tick': ParamInt, 'selmin': ParamInt, 'selmax': ParamInt}
     required = ['value', 'min', 'max']
     winStyles = ['wxSL_HORIZONTAL', 'wxSL_VERTICAL', 'wxSL_AUTOTICKS', 'wxSL_LABELS',
-              'wxSL_LEFT', 'wxSL_RIGHT', 'wxSL_TOP', 'wxSL_SELRANGE']
+                 'wxSL_LEFT', 'wxSL_RIGHT', 'wxSL_TOP', 'wxSL_BOTTOM',
+                 'wxSL_BOTH', 'wxSL_SELRANGE']
 
 class xxxGauge(xxxObject):
     allParams = ['range', 'pos', 'size', 'style', 'value', 'shadow', 'bezel']
 
 class xxxGauge(xxxObject):
     allParams = ['range', 'pos', 'size', 'style', 'value', 'shadow', 'bezel']
@@ -315,7 +381,8 @@ class xxxBitmapButton(xxxObject):
     allParams = ['bitmap', 'selected', 'focus', 'disabled', 'default',
                  'pos', 'size', 'style']
     required = ['bitmap']
     allParams = ['bitmap', 'selected', 'focus', 'disabled', 'default',
                  'pos', 'size', 'style']
     required = ['bitmap']
-    winStyles = ['wxBU_LEFT', 'wxBU_TOP', 'wxBU_RIGHT', 'wxBU_BOTTOM']
+    winStyles = ['wxBU_AUTODRAW', 'wxBU_LEFT', 'wxBU_TOP',
+                 'wxBU_RIGHT', 'wxBU_BOTTOM']
 
 class xxxRadioButton(xxxObject):
     allParams = ['label', 'value', 'pos', 'size', 'style']
 
 class xxxRadioButton(xxxObject):
     allParams = ['label', 'value', 'pos', 'size', 'style']
@@ -347,8 +414,7 @@ class xxxCheckBox(xxxObject):
 class xxxComboBox(xxxObject):
     allParams = ['content', 'selection', 'value', 'pos', 'size', 'style']
     required = ['content']
 class xxxComboBox(xxxObject):
     allParams = ['content', 'selection', 'value', 'pos', 'size', 'style']
     required = ['content']
-    winStyles = ['wxCB_SIMPLE', 'wxCB_DROPDOWN', 'wxCB_READONLY', 'wxCB_DROPDOWN',
-              'wxCB_SORT']
+    winStyles = ['wxCB_SIMPLE', 'wxCB_SORT', 'wxCB_READONLY', 'wxCB_DROPDOWN']
 
 class xxxListBox(xxxObject):
     allParams = ['content', 'selection', 'pos', 'size', 'style']
 
 class xxxListBox(xxxObject):
     allParams = ['content', 'selection', 'pos', 'size', 'style']
@@ -370,7 +436,7 @@ class xxxBoxSizer(xxxSizer):
     default = {'orient': 'wxVERTICAL'}
     # Tree icon depends on orientation
     def treeImage(self):
     default = {'orient': 'wxVERTICAL'}
     # Tree icon depends on orientation
     def treeImage(self):
-        if self.params['orient'].data == 'wxHORIZONTAL': return self.imageH
+        if self.params['orient'].value() == 'wxHORIZONTAL': return self.imageH
         else: return self.imageV
 
 class xxxStaticBoxSizer(xxxBoxSizer):
         else: return self.imageV
 
 class xxxStaticBoxSizer(xxxBoxSizer):
@@ -383,8 +449,40 @@ class xxxGridSizer(xxxSizer):
     required = ['cols']
     default = {'cols': '2', 'rows': '2'}
 
     required = ['cols']
     default = {'cols': '2', 'rows': '2'}
 
+# For repeated parameters
+class xxxParamMulti:
+    def __init__(self):
+        self.l, self.data = [], []
+    def append(self, param):
+        self.l.append(param)
+        self.data.append(param.value())
+    def value(self):
+        return self.data
+    def remove(self):
+        for param in self.l:
+            param.remove()
+        self.l, self.data = [], []
+
 class xxxFlexGridSizer(xxxGridSizer):
 class xxxFlexGridSizer(xxxGridSizer):
-    pass
+    specials = ['growablecols', 'growablerows']
+    allParams = ['cols', 'rows', 'vgap', 'hgap'] + specials
+    paramDict = {'growablecols':ParamContent, 'growablerows':ParamContent}
+    # Special processing for growable* parameters
+    # (they are represented by several nodes)
+    def special(self, tag, node):
+        if tag not in self.params.keys():
+            self.params[tag] = xxxParamMulti()
+        self.params[tag].append(xxxParam(node))
+    def setSpecial(self, param, value):
+        # Straightforward implementation: remove, add again
+        self.params[param].remove()
+        del self.params[param]
+        for str in value:
+            node = tree.dom.createElement(param)
+            text = tree.dom.createTextNode(str)
+            node.appendChild(text)
+            self.element.appendChild(node)
+            self.special(param, node)
 
 # Container with only one child.
 # Not shown in tree.
 
 # Container with only one child.
 # Not shown in tree.
@@ -449,6 +547,8 @@ class xxxMenuBar(xxxContainer):
 class xxxMenu(xxxContainer):
     allParams = ['label']
     default = {'label': ''}
 class xxxMenu(xxxContainer):
     allParams = ['label']
     default = {'label': ''}
+    paramDict = {'style': ParamNonGenericStyle}    # no generic styles
+    winStyles = ['wxMENU_TEAROFF']
 
 class xxxMenuItem(xxxObject):
     allParams = ['checkable', 'label', 'accel', 'help']
 
 class xxxMenuItem(xxxObject):
     allParams = ['checkable', 'label', 'accel', 'help']
@@ -464,13 +564,19 @@ xxxDict = {
     'wxPanel': xxxPanel,
     'wxDialog': xxxDialog,
     'wxFrame': xxxFrame,
     'wxPanel': xxxPanel,
     'wxDialog': xxxDialog,
     'wxFrame': xxxFrame,
+    'tool': xxxTool,
+    'wxToolBar': xxxToolBar,
     
     
+    'wxBitmap': xxxBitmap,
+    'wxIcon': xxxIcon,
+
     'wxButton': xxxButton,
     'wxBitmapButton': xxxBitmapButton,
     'wxRadioButton': xxxRadioButton,
     'wxSpinButton': xxxSpinButton,
 
     'wxStaticBox': xxxStaticBox,
     'wxButton': xxxButton,
     'wxBitmapButton': xxxBitmapButton,
     'wxRadioButton': xxxRadioButton,
     'wxSpinButton': xxxSpinButton,
 
     'wxStaticBox': xxxStaticBox,
+    'wxStaticBitmap': xxxStaticBitmap,
     'wxRadioBox': xxxRadioBox,
     'wxComboBox': xxxComboBox,
     'wxCheckBox': xxxCheckBox,
     'wxRadioBox': xxxRadioBox,
     'wxComboBox': xxxComboBox,
     'wxCheckBox': xxxCheckBox,
@@ -523,7 +629,13 @@ def IsObject(node):
 
 # Make XXX object from some DOM object, selecting correct class
 def MakeXXXFromDOM(parent, element):
 
 # Make XXX object from some DOM object, selecting correct class
 def MakeXXXFromDOM(parent, element):
-    return xxxDict[element.getAttribute('class')](parent, element)
+    try:
+        return xxxDict[element.getAttribute('class')](parent, element)
+    except KeyError:
+        # Verify that it's not recursive exception
+        if element.getAttribute('class') not in xxxDict.keys():
+            print 'ERROR: unknown class:', element.getAttribute('class')
+        raise
 
 # Make empty DOM element
 def MakeEmptyDOM(className): 
 
 # Make empty DOM element
 def MakeEmptyDOM(className):