2 # Purpose:      Classes for parameter introduction 
   3 # Author:       Roman Rolinsky <rolinsky@mema.ucl.ac.be> 
  11 from wxPython
.xrc 
import * 
  21     'wxTRANSPARENT_WINDOW', 
  23     'wxNO_FULL_REPAINT_ON_RESIZE', 
  24     'wxFULL_REPAINT_ON_RESIZE', 
  25     'wxWS_EX_BLOCK_EVENTS', 
  28 buttonSize 
= (35,-1)    # in dialog units, transformed to pixels in panel ctor 
  30 # Class that can properly disable children 
  31 class PPanel(wxPanel
): 
  32     def __init__(self
, parent
, name
): 
  33         wxPanel
.__init
__(self
, parent
, -1, name
=name
) 
  34         self
.SetBackgroundColour(parent
.GetBackgroundColour()) 
  35         self
.SetForegroundColour(parent
.GetForegroundColour()) 
  36         self
.modified 
= self
.freeze 
= False 
  37     def Enable(self
, value
): 
  38         # Something strange is going on with enable so we make sure... 
  39         for w 
in self
.GetChildren(): 
  41         wxPanel
.Enable(self
, value
) 
  42     def SetModified(self
): 
  44         g
.panel
.SetModified(True) 
  45     # Common method to set modified state 
  46     def OnChange(self
, evt
): 
  47         if self
.freeze
: return 
  51 class ParamBinaryOr(PPanel
): 
  52     def __init__(self
, parent
, name
): 
  53         PPanel
.__init
__(self
, parent
, name
) 
  54         self
.ID_TEXT_CTRL 
= wxNewId() 
  55         self
.ID_BUTTON_CHOICES 
= wxNewId() 
  57         self
.text 
= wxTextCtrl(self
, self
.ID_TEXT_CTRL
, size
=wxSize(200,-1)) 
  58         sizer
.Add(self
.text
, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL
, 5) 
  59         self
.button 
= wxButton(self
, self
.ID_BUTTON_CHOICES
, 'Edit...', size
=buttonSize
) 
  60         sizer
.Add(self
.button
, 0, wxALIGN_CENTER_VERTICAL
) 
  61         self
.SetAutoLayout(True) 
  64         EVT_BUTTON(self
, self
.ID_BUTTON_CHOICES
, self
.OnButtonChoices
) 
  65         EVT_TEXT(self
, self
.ID_TEXT_CTRL
, self
.OnChange
) 
  67         return self
.text
.GetValue() 
  68     def SetValue(self
, value
): 
  70         self
.text
.SetValue(value
) 
  72     def OnButtonChoices(self
, evt
): 
  73         dlg 
= g
.frame
.res
.LoadDialog(self
, 'DIALOG_CHOICES') 
  74         listBox 
= XRCCTRL(dlg
, 'CHECK_LIST') 
  75         listBox
.InsertItems(self
.values
, 0) 
  76         value 
= map(string
.strip
, self
.text
.GetValue().split('|')) 
  77         if value 
== ['']: value 
= [] 
  81                 listBox
.Check(self
.values
.index(i
)) 
  84                 if self
.equal
.has_key(i
): 
  85                     listBox
.Check(self
.values
.index(self
.equal
[i
])) 
  87                     print 'WARNING: unknown flag: %s: ignored.' % i
 
  89         if dlg
.ShowModal() == wxID_OK
: 
  91             for i 
in range(listBox
.GetCount()): 
  92                 if listBox
.IsChecked(i
): 
  93                     value
.append(self
.values
[i
]) 
  97                 self
.SetValue(reduce(lambda a
,b
: a
+'|'+b
, value
)) 
 103 class ParamFlag(ParamBinaryOr
): 
 104     values 
= ['wxTOP', 'wxBOTTOM', 'wxLEFT', 'wxRIGHT', 'wxALL', 
 105               'wxEXPAND', 'wxGROW', 'wxSHAPED', 'wxALIGN_CENTRE', 'wxALIGN_RIGHT', 
 107               'wxALIGN_BOTTOM', 'wxALIGN_CENTRE_VERTICAL', 
 108               'wxALIGN_CENTRE_HORIZONTAL', 
 110     equal 
= {'wxALIGN_CENTER': 'wxALIGN_CENTRE', 
 111              'wxALIGN_CENTER_VERTICAL': 'wxALIGN_CENTRE_VERTICAL', 
 112              'wxALIGN_CENTER_HORIZONTAL': 'wxALIGN_CENTRE_HORIZONTAL'} 
 113     def __init__(self
, parent
, name
): 
 114         ParamBinaryOr
.__init
__(self
, parent
, name
) 
 116 class ParamStyle(ParamBinaryOr
): 
 117     equal 
= {'wxALIGN_CENTER': 'wxALIGN_CENTRE'}
 
 118     def __init__(self
, parent
, name
): 
 119         self
.values 
= g
.currentXXX
.winStyles 
+ genericStyles
 
 120         ParamBinaryOr
.__init
__(self
, parent
, name
) 
 122 class ParamNonGenericStyle(ParamBinaryOr
): 
 123     def __init__(self
, parent
, name
): 
 124         self
.values 
= g
.currentXXX
.winStyles
 
 125         ParamBinaryOr
.__init
__(self
, parent
, name
) 
 127 class ParamExStyle(ParamBinaryOr
): 
 128     def __init__(self
, parent
, name
): 
 130             self
.values 
= g
.currentXXX
.exStyles 
# constant at the moment 
 133         ParamBinaryOr
.__init
__(self
, parent
, name
) 
 135 class ParamColour(PPanel
): 
 136     def __init__(self
, parent
, name
): 
 137         PPanel
.__init
__(self
, parent
, name
) 
 138         self
.ID_TEXT_CTRL 
= wxNewId() 
 139         self
.ID_BUTTON 
= wxNewId() 
 141         self
.text 
= wxTextCtrl(self
, self
.ID_TEXT_CTRL
, size
=(65,-1)) 
 142         sizer
.Add(self
.text
, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL
, 5) 
 143         self
.button 
= wxPanel(self
, self
.ID_BUTTON
, wxDefaultPosition
, wxSize(20, 1)) 
 144         sizer
.Add(self
.button
, 0, wxGROW | wxALIGN_CENTER_VERTICAL
) 
 145         self
.SetAutoLayout(True) 
 148         self
.textModified 
= False 
 149         EVT_PAINT(self
.button
, self
.OnPaintButton
) 
 150         EVT_TEXT(self
, self
.ID_TEXT_CTRL
, self
.OnChange
) 
 151         EVT_LEFT_DOWN(self
.button
, self
.OnLeftDown
) 
 153         return self
.text
.GetValue() 
 154     def SetValue(self
, value
): 
 156         if not value
: value 
= '#FFFFFF' 
 157         self
.text
.SetValue(str(value
))  # update text ctrl 
 158         colour 
= wxColour(int(value
[1:3], 16), int(value
[3:5], 16), int(value
[5:7], 16)) 
 159         self
.button
.SetBackgroundColour(colour
) 
 160         self
.button
.Refresh() 
 162     def OnPaintButton(self
, evt
): 
 163         dc 
= wxPaintDC(self
.button
) 
 164         dc
.SetBrush(wxTRANSPARENT_BRUSH
) 
 165         if self
.IsEnabled(): dc
.SetPen(wxBLACK_PEN
) 
 166         else: dc
.SetPen(wxGREY_PEN
) 
 167         size 
= self
.button
.GetSize() 
 168         dc
.DrawRectangle(0, 0, size
.width
, size
.height
) 
 169     def OnLeftDown(self
, evt
): 
 170         data 
= wxColourData() 
 171         data
.SetColour(self
.GetValue()) 
 172         dlg 
= wxColourDialog(self
, data
) 
 173         if dlg
.ShowModal() == wxID_OK
: 
 174             self
.SetValue('#%02X%02X%02X' % dlg
.GetColourData().GetColour().Get()) 
 178 ################################################################################ 
 180 # Mapping from wx constants ro XML strings 
 181 fontFamiliesWx2Xml 
= {wxDEFAULT
: 'default', wxDECORATIVE
: 'decorative', 
 182                 wxROMAN
: 'roman', wxSCRIPT
: 'script', wxSWISS
: 'swiss', 
 184 fontStylesWx2Xml 
= {wxNORMAL: 'normal', wxSLANT: 'slant', wxITALIC: 'italic'}
 
 185 fontWeightsWx2Xml 
= {wxNORMAL: 'normal', wxLIGHT: 'light', wxBOLD: 'bold'}
 
 188     for k
,v 
in m
.items(): rm
[v
] = k
 
 190 fontFamiliesXml2wx 
= ReverseMap(fontFamiliesWx2Xml
) 
 191 fontStylesXml2wx 
= ReverseMap(fontStylesWx2Xml
) 
 192 fontWeightsXml2wx 
= ReverseMap(fontWeightsWx2Xml
) 
 194 class ParamFont(PPanel
): 
 195     def __init__(self
, parent
, name
): 
 196         PPanel
.__init
__(self
, parent
, name
) 
 197         self
.ID_TEXT_CTRL 
= wxNewId() 
 198         self
.ID_BUTTON_SELECT 
= wxNewId() 
 200         self
.text 
= wxTextCtrl(self
, self
.ID_TEXT_CTRL
, size
=(200,-1)) 
 201         sizer
.Add(self
.text
, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL
, 5) 
 202         self
.button 
= wxButton(self
, self
.ID_BUTTON_SELECT
, 'Select...', size
=buttonSize
) 
 203         sizer
.Add(self
.button
, 0, wxALIGN_CENTER_VERTICAL
) 
 204         self
.SetAutoLayout(True) 
 207         self
.textModified 
= False 
 208         EVT_BUTTON(self
, self
.ID_BUTTON_SELECT
, self
.OnButtonSelect
) 
 209         EVT_TEXT(self
, self
.ID_TEXT_CTRL
, self
.OnChange
) 
 210     def OnChange(self
, evt
): 
 211         PPanel
.OnChange(self
, evt
) 
 212         self
.textModified 
= True 
 213     def _defaultValue(self
): 
 214         return ['12', 'default', 'normal', 'normal', '0', '', ''] 
 216         if self
.textModified
:           # text has newer value 
 218                 return eval(self
.text
.GetValue()) 
 220                 wxLogError('Syntax error in parameter value: ' + self
.GetName()) 
 221                 return self
._defaultValue
() 
 223     def SetValue(self
, value
): 
 224         self
.freeze 
= True              # disable other handlers 
 225         if not value
: value 
= self
._defaultValue
() 
 227         self
.text
.SetValue(str(value
))  # update text ctrl 
 229     def OnButtonSelect(self
, evt
): 
 230         if self
.textModified
:           # text has newer value 
 232                 self
.value 
= eval(self
.text
.GetValue()) 
 234                 wxLogError('Syntax error in parameter value: ' + self
.GetName()) 
 235                 self
.value 
= self
._defaultValue
() 
 240         style 
= weight 
= wxNORMAL
 
 243         enc 
= wxFONTENCODING_DEFAULT
 
 244         # Fall back to default if exceptions 
 247             try: size 
= int(self
.value
[0]) 
 248             except ValueError: error 
= True 
 249             try: family 
= fontFamiliesXml2wx
[self
.value
[1]] 
 250             except KeyError: error 
= True 
 251             try: style 
= fontStylesXml2wx
[self
.value
[2]] 
 252             except KeyError: error 
= True 
 253             try: weight 
= fontWeightsXml2wx
[self
.value
[3]] 
 254             except KeyError: error 
= True 
 255             try: underlined 
= int(self
.value
[4]) 
 256             except ValueError: error 
= True 
 258             mapper 
= wxFontMapper() 
 259             if not self
.value
[6]: enc 
= mapper
.CharsetToEncoding(self
.value
[6]) 
 262         if error
: wxLogError('Invalid font specification') 
 263         if enc 
== wxFONTENCODING_DEFAULT
: enc 
= wxFONTENCODING_SYSTEM
 
 264         font 
= wxFont(size
, family
, style
, weight
, underlined
, face
, enc
) 
 266         data
.SetInitialFont(font
) 
 267         dlg 
= wxFontDialog(self
, data
) 
 268         if dlg
.ShowModal() == wxID_OK
: 
 269             font 
= dlg
.GetFontData().GetChosenFont() 
 270             value 
= [str(font
.GetPointSize()), 
 271                      fontFamiliesWx2Xml
.get(font
.GetFamily(), "default"), 
 272                      fontStylesWx2Xml
.get(font
.GetStyle(), "normal"), 
 273                      fontWeightsWx2Xml
.get(font
.GetWeight(), "normal"), 
 274                      str(font
.GetUnderlined()), 
 275                      font
.GetFaceName().encode(), 
 276                      wxFontMapper_GetEncodingName(font
.GetEncoding()).encode() 
 281             self
.textModified 
= False 
 284 ################################################################################ 
 286 class ParamInt(PPanel
): 
 287     def __init__(self
, parent
, name
): 
 288         PPanel
.__init
__(self
, parent
, name
) 
 289         self
.ID_SPIN_CTRL 
= wxNewId() 
 291         self
.spin 
= wxSpinCtrl(self
, self
.ID_SPIN_CTRL
, size
=(50,-1)) 
 293         self
.SetAutoLayout(True) 
 296         EVT_SPINCTRL(self
, self
.ID_SPIN_CTRL
, self
.OnChange
) 
 298         return str(self
.spin
.GetValue()) 
 299     def SetValue(self
, value
): 
 301         if not value
: value 
= 0 
 302         self
.spin
.SetValue(int(value
)) 
 305 # Same as int but allows dialog units (XXXd) 
 306 class ParamUnit(PPanel
): 
 307     def __init__(self
, parent
, name
): 
 308         PPanel
.__init
__(self
, parent
, name
) 
 309         self
.ID_TEXT_CTRL 
= wxNewId() 
 310         self
.ID_SPIN_BUTTON 
= wxNewId() 
 312         self
.text 
= wxTextCtrl(self
, self
.ID_TEXT_CTRL
, size
=(35,-1)) 
 313         self
.spin 
= wxSpinButton(self
, self
.ID_SPIN_BUTTON
, style 
= wxSP_VERTICAL
, size
=(-1,1)) 
 314         self
.spin
.SetRange(-10000, 10000) 
 315         sizer
.Add(self
.text
, 0, wxEXPAND | wxRIGHT
, 2) 
 316         sizer
.Add(self
.spin
, 0, wxEXPAND
) 
 317         self
.SetAutoLayout(True) 
 320         EVT_SPIN_UP(self
, self
.ID_SPIN_BUTTON
, self
.OnSpinUp
) 
 321         EVT_SPIN_DOWN(self
, self
.ID_SPIN_BUTTON
, self
.OnSpinDown
) 
 323         return self
.text
.GetValue() 
 324     def SetValue(self
, value
): 
 326         if not value
: value 
= '0' 
 327         self
.text
.SetValue(value
) 
 330         # Check if we are working with dialog units 
 331         value 
= self
.text
.GetValue() 
 333         if value
[-1].upper() == 'D': 
 337             intValue 
= int(value
) + x
 
 338             self
.spin
.SetValue(intValue
) 
 339             self
.text
.SetValue(str(intValue
) + units
) 
 342             # !!! Strange, if I use wxLogWarning, event is re-generated 
 343             print 'incorrect unit format' 
 344     def OnSpinUp(self
, evt
): 
 346     def OnSpinDown(self
, evt
): 
 349 class ParamMultilineText(PPanel
): 
 350     def __init__(self
, parent
, name
, textWidth
=-1): 
 351         PPanel
.__init
__(self
, parent
, name
) 
 352         self
.ID_TEXT_CTRL 
= wxNewId() 
 353         self
.ID_BUTTON_EDIT 
= wxNewId() 
 355         self
.text 
= wxTextCtrl(self
, self
.ID_TEXT_CTRL
, size
=wxSize(200,-1)) 
 356         sizer
.Add(self
.text
, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL
, 5) 
 357         self
.button 
= wxButton(self
, self
.ID_BUTTON_EDIT
, 'Edit...', size
=buttonSize
) 
 358         sizer
.Add(self
.button
, 0, wxALIGN_CENTER_VERTICAL
) 
 359         self
.SetAutoLayout(True) 
 362         EVT_BUTTON(self
, self
.ID_BUTTON_EDIT
, self
.OnButtonEdit
) 
 363         EVT_TEXT(self
, self
.ID_TEXT_CTRL
, self
.OnChange
) 
 365         return self
.text
.GetValue() 
 366     def SetValue(self
, value
): 
 367         self
.freeze 
= True              # disable other handlers 
 368         self
.text
.SetValue(value
) 
 369         self
.freeze 
= False             # disable other handlers 
 370     def OnButtonEdit(self
, evt
): 
 371         dlg 
= g
.frame
.res
.LoadDialog(self
, 'DIALOG_TEXT') 
 372         textCtrl 
= XRCCTRL(dlg
, 'TEXT') 
 373         textCtrl
.SetValue(self
.text
.GetValue()) 
 374         if dlg
.ShowModal() == wxID_OK
: 
 375             self
.text
.SetValue(textCtrl
.GetValue()) 
 379 class ParamText(PPanel
): 
 380     def __init__(self
, parent
, name
, textWidth
=-1): 
 381         PPanel
.__init
__(self
, parent
, name
) 
 382         self
.ID_TEXT_CTRL 
= wxNewId() 
 383         # We use sizer even here to have the same size of text control 
 385         self
.text 
= wxTextCtrl(self
, self
.ID_TEXT_CTRL
, size
=wxSize(textWidth
,-1)) 
 386         if textWidth 
== -1: option 
= 1 
 388         sizer
.Add(self
.text
, option
, wxALIGN_CENTER_VERTICAL
) 
 389         self
.SetAutoLayout(True) 
 392         EVT_TEXT(self
, self
.ID_TEXT_CTRL
, self
.OnChange
) 
 394         return self
.text
.GetValue() 
 395     def SetValue(self
, value
): 
 396         self
.freeze 
= True              # disable other handlers 
 397         self
.text
.SetValue(value
) 
 398         self
.freeze 
= False             # disable other handlers 
 400 class ParamAccel(ParamText
): 
 401     def __init__(self
, parent
, name
): 
 402         ParamText
.__init
__(self
, parent
, name
, 100) 
 404 class ParamPosSize(ParamText
): 
 405     def __init__(self
, parent
, name
): 
 406         ParamText
.__init
__(self
, parent
, name
, 80) 
 408 class ParamLabel(ParamText
): 
 409     def __init__(self
, parent
, name
): 
 410         ParamText
.__init
__(self
, parent
, name
, 200) 
 412 class ParamEncoding(ParamText
): 
 413     def __init__(self
, parent
, name
): 
 414         ParamText
.__init
__(self
, parent
, name
, 100) 
 416 class ContentDialog(wxDialog
): 
 417     def __init__(self
, parent
, value
): 
 420         g
.frame
.res
.LoadOnDialog(pre
, parent
, 'DIALOG_CONTENT') 
 422         self
._setOORInfo
(self
) 
 423         self
.list = XRCCTRL(self
, 'LIST') 
 427         self
.SetAutoLayout(True) 
 428         self
.GetSizer().Fit(self
) 
 430         self
.ID_BUTTON_APPEND 
= XRCID('BUTTON_APPEND') 
 431         self
.ID_BUTTON_REMOVE 
= XRCID('BUTTON_REMOVE') 
 432         self
.ID_BUTTON_UP 
= XRCID('BUTTON_UP') 
 433         self
.ID_BUTTON_DOWN 
= XRCID('BUTTON_DOWN') 
 434         EVT_BUTTON(self
, self
.ID_BUTTON_UP
, self
.OnButtonUp
) 
 435         EVT_BUTTON(self
, self
.ID_BUTTON_DOWN
, self
.OnButtonDown
) 
 436         EVT_BUTTON(self
, self
.ID_BUTTON_APPEND
, self
.OnButtonAppend
) 
 437         EVT_BUTTON(self
, self
.ID_BUTTON_REMOVE
, self
.OnButtonRemove
) 
 438         EVT_UPDATE_UI(self
, self
.ID_BUTTON_UP
, self
.OnUpdateUI
) 
 439         EVT_UPDATE_UI(self
, self
.ID_BUTTON_DOWN
, self
.OnUpdateUI
) 
 440         EVT_UPDATE_UI(self
, self
.ID_BUTTON_REMOVE
, self
.OnUpdateUI
) 
 441     def OnButtonUp(self
, evt
): 
 442         i 
= self
.list.GetSelection() 
 443         str = self
.list.GetString(i
) 
 445         self
.list.InsertItems([str], i
-1) 
 446         self
.list.SetSelection(i
-1) 
 447     def OnButtonDown(self
, evt
): 
 448         i 
= self
.list.GetSelection() 
 449         str = self
.list.GetString(i
) 
 451         self
.list.InsertItems([str], i
+1) 
 452         self
.list.SetSelection(i
+1) 
 453     def OnButtonAppend(self
, evt
): 
 454         str = wxGetTextFromUser('Enter new item:', 'Append', '', self
) 
 455         self
.list.Append(str) 
 456     def OnButtonRemove(self
, evt
): 
 457         self
.list.Delete(self
.list.GetSelection()) 
 458     def OnUpdateUI(self
, evt
): 
 459         if evt
.GetId() == self
.ID_BUTTON_REMOVE
: 
 460             evt
.Enable(self
.list.GetSelection() != -1) 
 461         elif evt
.GetId() == self
.ID_BUTTON_UP
: 
 462             evt
.Enable(self
.list.GetSelection() > 0) 
 463         elif evt
.GetId() == self
.ID_BUTTON_DOWN
: 
 464             evt
.Enable(self
.list.GetSelection() != -1 and \
 
 465                        self
.list.GetSelection() < self
.list.GetCount() - 1) 
 467 class ContentCheckListDialog(wxDialog
): 
 468     def __init__(self
, parent
, value
): 
 470         g
.frame
.res
.LoadOnDialog(pre
, parent
, 'DIALOG_CONTENT_CHECK_LIST') 
 472         self
._setOORInfo
(self
) 
 473         self
.list = XRCCTRL(self
, 'CHECK_LIST') 
 478             self
.list.Check(i
, ch
) 
 480         self
.SetAutoLayout(True) 
 481         self
.GetSizer().Fit(self
) 
 483         self
.ID_BUTTON_APPEND 
= XRCID('BUTTON_APPEND') 
 484         self
.ID_BUTTON_REMOVE 
= XRCID('BUTTON_REMOVE') 
 485         self
.ID_BUTTON_UP 
= XRCID('BUTTON_UP') 
 486         self
.ID_BUTTON_DOWN 
= XRCID('BUTTON_DOWN') 
 487         EVT_CHECKLISTBOX(self
, self
.list.GetId(), self
.OnCheck
) 
 488         EVT_BUTTON(self
, self
.ID_BUTTON_UP
, self
.OnButtonUp
) 
 489         EVT_BUTTON(self
, self
.ID_BUTTON_DOWN
, self
.OnButtonDown
) 
 490         EVT_BUTTON(self
, self
.ID_BUTTON_APPEND
, self
.OnButtonAppend
) 
 491         EVT_BUTTON(self
, self
.ID_BUTTON_REMOVE
, self
.OnButtonRemove
) 
 492         EVT_UPDATE_UI(self
, self
.ID_BUTTON_UP
, self
.OnUpdateUI
) 
 493         EVT_UPDATE_UI(self
, self
.ID_BUTTON_DOWN
, self
.OnUpdateUI
) 
 494         EVT_UPDATE_UI(self
, self
.ID_BUTTON_REMOVE
, self
.OnUpdateUI
) 
 495     def OnCheck(self
, evt
): 
 496         # !!! Wrong wxGTK (wxMSW?) behavior: toggling selection if checking 
 497         self
.list.Deselect(evt
.GetSelection()) 
 498     def OnButtonUp(self
, evt
): 
 499         i 
= self
.list.GetSelection() 
 500         str, ch 
= self
.list.GetString(i
), self
.list.IsChecked(i
) 
 502         self
.list.InsertItems([str], i
-1) 
 503         self
.list.Check(i
-1, ch
) 
 504         self
.list.SetSelection(i
-1) 
 505     def OnButtonDown(self
, evt
): 
 506         i 
= self
.list.GetSelection() 
 507         str, ch 
= self
.list.GetString(i
), self
.list.IsChecked(i
) 
 509         self
.list.InsertItems([str], i
+1) 
 510         self
.list.Check(i
+1, ch
) 
 511         self
.list.SetSelection(i
+1) 
 512     def OnButtonAppend(self
, evt
): 
 513         str = wxGetTextFromUser('Enter new item:', 'Append', '', self
) 
 514         self
.list.Append(str) 
 515     def OnButtonRemove(self
, evt
): 
 516         self
.list.Delete(self
.list.GetSelection()) 
 517     def OnUpdateUI(self
, evt
): 
 518         if evt
.GetId() == self
.ID_BUTTON_REMOVE
: 
 519             evt
.Enable(self
.list.GetSelection() != -1) 
 520         elif evt
.GetId() == self
.ID_BUTTON_UP
: 
 521             evt
.Enable(self
.list.GetSelection() > 0) 
 522         elif evt
.GetId() == self
.ID_BUTTON_DOWN
: 
 523             evt
.Enable(self
.list.GetSelection() != -1 and \
 
 524                        self
.list.GetSelection() < self
.list.GetCount() - 1) 
 526 class ParamContent(PPanel
): 
 527     def __init__(self
, parent
, name
): 
 528         PPanel
.__init
__(self
, parent
, name
) 
 529         self
.ID_TEXT_CTRL 
= wxNewId() 
 530         self
.ID_BUTTON_EDIT 
= wxNewId() 
 532         self
.text 
= wxTextCtrl(self
, self
.ID_TEXT_CTRL
, size
=wxSize(200,-1)) 
 533         sizer
.Add(self
.text
, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL
, 5) 
 534         self
.button 
= wxButton(self
, self
.ID_BUTTON_EDIT
, 'Edit...', size
=buttonSize
) 
 535         sizer
.Add(self
.button
, 0, wxALIGN_CENTER_VERTICAL
) 
 536         self
.SetAutoLayout(True) 
 539         self
.textModified 
= False 
 540         EVT_BUTTON(self
, self
.ID_BUTTON_EDIT
, self
.OnButtonEdit
) 
 541         EVT_TEXT(self
, self
.ID_TEXT_CTRL
, self
.OnChange
) 
 542     def OnChange(self
, evt
): 
 543         PPanel
.OnChange(self
, evt
) 
 544         self
.textModified 
= True 
 546         if self
.textModified
:           # text has newer value 
 548                 return eval(self
.text
.GetValue()) 
 550                 wxLogError('Syntax error in parameter value: ' + self
.GetName()) 
 553     def SetValue(self
, value
): 
 555         if not value
: value 
= [] 
 557         self
.text
.SetValue(str(value
))  # update text ctrl 
 559     def OnButtonEdit(self
, evt
): 
 560         if self
.textModified
:           # text has newer value 
 562                 self
.value 
= eval(self
.text
.GetValue()) 
 564                 wxLogError('Syntax error in parameter value: ' + self
.GetName()) 
 566         dlg 
= ContentDialog(self
, self
.value
) 
 567         if dlg
.ShowModal() == wxID_OK
: 
 569             for i 
in range(dlg
.list.GetCount()): 
 570                 value
.append(dlg
.list.GetString(i
)) 
 574             self
.textModified 
= False 
 578 class ParamContentCheckList(ParamContent
): 
 579     def __init__(self
, parent
, name
): 
 580         ParamContent
.__init
__(self
, parent
, name
) 
 581     def OnButtonEdit(self
, evt
): 
 582         if self
.textModified
:           # text has newer value 
 584                 self
.value 
= eval(self
.text
.GetValue()) 
 586                 wxLogError('Syntax error in parameter value: ' + self
.GetName()) 
 588         dlg 
= ContentCheckListDialog(self
, self
.value
) 
 589         if dlg
.ShowModal() == wxID_OK
: 
 591             for i 
in range(dlg
.list.GetCount()): 
 592                 value
.append((dlg
.list.GetString(i
), dlg
.list.IsChecked(i
))) 
 596             self
.textModified 
= False 
 599 class IntListDialog(wxDialog
): 
 600     def __init__(self
, parent
, value
): 
 602         g
.frame
.res
.LoadOnDialog(pre
, parent
, 'DIALOG_INTLIST') 
 604         self
._setOORInfo
(self
) 
 605         self
.list = XRCCTRL(self
, 'LIST') 
 609             if type(v
) != IntType
: 
 610                 wxLogError('Invalid item type') 
 612                 self
.list.Append(str(v
)) 
 613         self
.SetAutoLayout(True) 
 614         self
.GetSizer().Fit(self
) 
 616         self
.ID_BUTTON_ADD 
= XRCID('BUTTON_ADD') 
 617         self
.ID_BUTTON_REMOVE 
= XRCID('BUTTON_REMOVE') 
 618         EVT_BUTTON(self
, self
.ID_BUTTON_ADD
, self
.OnButtonAppend
) 
 619         EVT_BUTTON(self
, self
.ID_BUTTON_REMOVE
, self
.OnButtonRemove
) 
 620         EVT_UPDATE_UI(self
, self
.ID_BUTTON_REMOVE
, self
.OnUpdateUI
) 
 621     def OnButtonAppend(self
, evt
): 
 622         s 
= wxGetTextFromUser('Enter new number:', 'Add', '', self
) 
 624         # Check that it's unique 
 627             s 
= str(v
)                  # to be sure 
 628             i 
= self
.list.FindString(s
) 
 629             if i 
== -1:                 # ignore non-unique 
 630                 # Find place to insert 
 632                 for i 
in range(self
.list.GetCount()): 
 633                     if int(self
.list.GetString(i
)) > v
: 
 636                 if found
: self
.list.InsertItems([s
], i
) 
 637                 else: self
.list.Append(s
) 
 639             wxLogError('List item is not an int!') 
 640     def OnButtonRemove(self
, evt
): 
 641         self
.list.Delete(self
.list.GetSelection()) 
 642     def OnUpdateUI(self
, evt
): 
 643         if evt
.GetId() == self
.ID_BUTTON_REMOVE
: 
 644             evt
.Enable(self
.list.GetSelection() != -1) 
 647 class ParamIntList(ParamContent
): 
 648     def __init__(self
, parent
, name
): 
 649         ParamContent
.__init
__(self
, parent
, name
) 
 650     def OnButtonEdit(self
, evt
): 
 651         if self
.textModified
:           # text has newer value 
 653                 self
.value 
= eval(self
.text
.GetValue()) 
 655                 wxLogError('Syntax error in parameter value: ' + self
.GetName()) 
 657         dlg 
= IntListDialog(self
, self
.value
) 
 658         if dlg
.ShowModal() == wxID_OK
: 
 660             for i 
in range(dlg
.list.GetCount()): 
 661                 value
.append(int(dlg
.list.GetString(i
))) 
 665             self
.textModified 
= False 
 669 class RadioBox(PPanel
): 
 670     def __init__(self
, parent
, id, choices
, 
 671                  pos
=wxDefaultPosition
, name
='radiobox'): 
 672         PPanel
.__init
__(self
, parent
, name
) 
 673         self
.choices 
= choices
 
 674         topSizer 
= wxBoxSizer() 
 676             button 
= wxRadioButton(self
, -1, i
, size
=(-1,buttonSize
[1]), name
=i
) 
 677             topSizer
.Add(button
, 0, wxRIGHT
, 5) 
 678             EVT_RADIOBUTTON(self
, button
.GetId(), self
.OnRadioChoice
) 
 679         self
.SetAutoLayout(True) 
 680         self
.SetSizer(topSizer
) 
 682     def SetStringSelection(self
, value
): 
 684         for i 
in self
.choices
: 
 685             self
.FindWindowByName(i
).SetValue(i 
== value
) 
 688     def OnRadioChoice(self
, evt
): 
 689         if self
.freeze
: return 
 690         if evt
.GetSelection(): 
 691             self
.value 
= evt
.GetEventObject().GetName() 
 693     def GetStringSelection(self
): 
 696 class ParamBool(RadioBox
): 
 697     values 
= {'yes': '1', 'no': '0'}
 
 698     seulav 
= {'1': 'yes', '0': 'no'}
 
 699     def __init__(self
, parent
, name
): 
 700         RadioBox
.__init
__(self
, parent
, -1, choices
=self
.values
.keys(), name
=name
) 
 702         return self
.values
[self
.GetStringSelection()] 
 703     def SetValue(self
, value
): 
 704         if not value
: value 
= '1' 
 705         self
.SetStringSelection(self
.seulav
[value
]) 
 707 class ParamOrient(RadioBox
): 
 708     values 
= {'horizontal': 'wxHORIZONTAL', 'vertical': 'wxVERTICAL'}
 
 709     seulav 
= {'wxHORIZONTAL': 'horizontal', 'wxVERTICAL': 'vertical'}
 
 710     def __init__(self
, parent
, name
): 
 711         RadioBox
.__init
__(self
, parent
, -1, choices
=self
.values
.keys(), name
=name
) 
 713         return self
.values
[self
.GetStringSelection()] 
 714     def SetValue(self
, value
): 
 715         if not value
: value 
= 'wxHORIZONTAL' 
 716         self
.SetStringSelection(self
.seulav
[value
]) 
 718 class ParamOrientation(RadioBox
): 
 719     values 
= {'horizontal': 'horizontal', 'vertical': 'vertical'}
 
 720     seulav 
= {'horizontal': 'horizontal', 'vertical': 'vertical'}
 
 721     def __init__(self
, parent
, name
): 
 722         RadioBox
.__init
__(self
, parent
, -1, choices
=self
.values
.keys(), name
=name
) 
 724         return self
.values
[self
.GetStringSelection()] 
 725     def SetValue(self
, value
): 
 726         if not value
: value 
= 'vertical' 
 727         self
.SetStringSelection(self
.seulav
[value
]) 
 729 class ParamFile(PPanel
): 
 730     def __init__(self
, parent
, name
): 
 731         PPanel
.__init
__(self
, parent
, name
) 
 732         self
.ID_TEXT_CTRL 
= wxNewId() 
 733         self
.ID_BUTTON_BROWSE 
= wxNewId() 
 735         self
.text 
= wxTextCtrl(self
, self
.ID_TEXT_CTRL
, size
=wxSize(200,-1)) 
 736         sizer
.Add(self
.text
, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL
, 5) 
 737         self
.button 
= wxButton(self
, self
.ID_BUTTON_BROWSE
, 'Browse...',size
=buttonSize
) 
 738         sizer
.Add(self
.button
, 0, wxALIGN_CENTER_VERTICAL
) 
 739         self
.SetAutoLayout(True) 
 742         self
.textModified 
= False 
 743         EVT_BUTTON(self
, self
.ID_BUTTON_BROWSE
, self
.OnButtonBrowse
) 
 744         EVT_TEXT(self
, self
.ID_TEXT_CTRL
, self
.OnChange
) 
 745     def OnChange(self
, evt
): 
 746         PPanel
.OnChange(self
, evt
) 
 747         self
.textModified 
= True 
 749         if self
.textModified
:           # text has newer value 
 750             return self
.text
.GetValue() 
 752     def SetValue(self
, value
): 
 755         self
.text
.SetValue(value
)  # update text ctrl 
 757     def OnButtonBrowse(self
, evt
): 
 758         if self
.textModified
:           # text has newer value 
 759             self
.value 
= self
.text
.GetValue() 
 760         dlg 
= wxFileDialog(self
, 
 761                            defaultDir 
= os
.path
.abspath(os
.path
.dirname(self
.value
)), 
 762                            defaultFile 
= os
.path
.basename(self
.value
)) 
 763         if dlg
.ShowModal() == wxID_OK
: 
 764             # Get common part of selected path and current 
 766                 curpath 
= os
.path
.abspath(g
.frame
.dataFile
) 
 768                 curpath 
= os
.path
.join(os
.getcwd(), '') 
 769             common 
= os
.path
.commonprefix([curpath
, dlg
.GetPath()]) 
 770             self
.SetValue(dlg
.GetPath()[len(common
):]) 
 772             self
.textModified 
= False 
 775 class ParamBitmap(PPanel
): 
 776     def __init__(self
, parent
, name
): 
 778         g
.frame
.res
.LoadOnPanel(pre
, parent
, 'PANEL_BITMAP') 
 780         self
._setOORInfo
(self
) 
 781         self
.SetBackgroundColour(parent
.GetBackgroundColour()) 
 782         self
.SetForegroundColour(parent
.GetForegroundColour()) 
 783         self
.modified 
= self
.freeze 
= False 
 784         self
.radio_std 
= XRCCTRL(self
, 'RADIO_STD') 
 785         self
.radio_std
.SetBackgroundColour(parent
.GetBackgroundColour()) 
 786         self
.radio_std
.SetForegroundColour(parent
.GetForegroundColour()) 
 787         self
.radio_file 
= XRCCTRL(self
, 'RADIO_FILE') 
 788         self
.radio_file
.SetBackgroundColour(parent
.GetBackgroundColour()) 
 789         self
.radio_file
.SetForegroundColour(parent
.GetForegroundColour()) 
 790         self
.combo 
= XRCCTRL(self
, 'COMBO_STD') 
 791         self
.text 
= XRCCTRL(self
, 'TEXT_FILE') 
 792         self
.button 
= XRCCTRL(self
, 'BUTTON_BROWSE') 
 793         self
.textModified 
= False 
 794         self
.SetAutoLayout(True) 
 795         self
.GetSizer().SetMinSize((260, -1)) 
 796         self
.GetSizer().Fit(self
) 
 797         EVT_RADIOBUTTON(self
, XRCID('RADIO_STD'), self
.OnRadioStd
) 
 798         EVT_RADIOBUTTON(self
, XRCID('RADIO_FILE'), self
.OnRadioFile
) 
 799         EVT_BUTTON(self
, XRCID('BUTTON_BROWSE'), self
.OnButtonBrowse
) 
 800         EVT_COMBOBOX(self
, XRCID('COMBO_STD'), self
.OnCombo
) 
 801         EVT_TEXT(self
, XRCID('COMBO_STD'), self
.OnChange
) 
 802         EVT_TEXT(self
, XRCID('TEXT_FILE'), self
.OnChange
) 
 803     def OnRadioStd(self
, evt
): 
 805         self
.SetValue(['wxART_MISSING_IMAGE','']) 
 806     def OnRadioFile(self
, evt
): 
 808         self
.SetValue(['','']) 
 809     def updateRadios(self
): 
 811             self
.radio_std
.SetValue(True) 
 812             self
.radio_file
.SetValue(False) 
 813             self
.text
.Enable(False) 
 814             self
.button
.Enable(False) 
 815             self
.combo
.Enable(True) 
 817             self
.radio_std
.SetValue(False) 
 818             self
.radio_file
.SetValue(True) 
 819             self
.text
.Enable(True) 
 820             self
.button
.Enable(True) 
 821             self
.combo
.Enable(False) 
 822     def OnChange(self
, evt
): 
 823         PPanel
.OnChange(self
, evt
) 
 824         self
.textModified 
= True 
 825     def OnCombo(self
, evt
): 
 826         PPanel
.OnChange(self
, evt
) 
 827         self
.value
[0] = self
.combo
.GetValue() 
 829         if self
.textModified
:           # text has newer value 
 830             return [self
.combo
.GetValue(), self
.text
.GetValue()] 
 832     def SetValue(self
, value
): 
 835             self
.value 
= ['', ''] 
 838         self
.combo
.SetValue(self
.value
[0]) 
 839         self
.text
.SetValue(self
.value
[1])  # update text ctrl 
 842     def OnButtonBrowse(self
, evt
): 
 843         if self
.textModified
:           # text has newer value 
 844             self
.value
[1] = self
.text
.GetValue() 
 845         dlg 
= wxFileDialog(self
, 
 846                            defaultDir 
= os
.path
.abspath(os
.path
.dirname(self
.value
[1])), 
 847                            defaultFile 
= os
.path
.basename(self
.value
[1])) 
 848         if dlg
.ShowModal() == wxID_OK
: 
 849             # Get common part of selected path and current 
 851                 curpath 
= os
.path
.abspath(g
.frame
.dataFile
) 
 853                 curpath 
= os
.path
.join(os
.getcwd(), '') 
 854             common 
= os
.path
.commonprefix([curpath
, dlg
.GetPath()]) 
 855             self
.SetValue(['', dlg
.GetPath()[len(common
):]]) 
 857             self
.textModified 
= False 
 862     'style': ParamStyle
, 'exstyle': ParamExStyle
, 
 863     'pos': ParamPosSize
, 'size': ParamPosSize
, 
 864     'cellpos': ParamPosSize
, 'cellspan': ParamPosSize
, 
 865     'border': ParamUnit
, 'cols': ParamInt
, 'rows': ParamInt
, 
 866     'vgap': ParamUnit
, 'hgap': ParamUnit
, 
 867     'checkable': ParamBool
, 'checked': ParamBool
, 'radio': ParamBool
, 
 869     'label': ParamMultilineText
, 'title': ParamText
, 'value': ParamText
, 
 870     'content': ParamContent
, 'selection': ParamInt
, 
 871     'min': ParamInt
, 'max': ParamInt
, 
 872     'fg': ParamColour
, 'bg': ParamColour
, 'font': ParamFont
, 
 873     'enabled': ParamBool
, 'focused': ParamBool
, 'hidden': ParamBool
, 
 874     'tooltip': ParamText
, 'bitmap': ParamBitmap
, 'icon': ParamBitmap
, 
 875     'encoding': ParamEncoding