2 # Purpose:      Classes for parameter introduction 
   3 # Author:       Roman Rolinsky <rolinsky@mema.ucl.ac.be> 
  11 from wxPython
.xrc 
import * 
  13 genericStyles 
= ['wxSIMPLE_BORDER', 'wxDOUBLE_BORDER', 
  14                  'wxSUNKEN_BORDER', 'wxRAISED_BORDER', 
  15                  'wxSTATIC_BORDER', 'wxNO_BORDER', 
  16                  'wxTRANSPARENT_WINDOW', 'wxWANTS_CHARS', 
  17                  'wxNO_FULL_REPAINT_ON_RESIZE'] 
  19 buttonSize 
= (35,-1)    # in dialog units, transformed to pixels in panel ctor 
  21 # Class that can properly disable children 
  22 class PPanel(wxPanel
): 
  23     def __init__(self
, parent
, name
): 
  24         wxPanel
.__init
__(self
, parent
, -1, name
=name
) 
  25         self
.SetBackgroundColour(parent
.GetBackgroundColour()) 
  26         self
.SetForegroundColour(parent
.GetForegroundColour()) 
  27         self
.modified 
= self
.freeze 
= False 
  28     def Enable(self
, value
): 
  29         # Something strange is going on with enable so we make sure... 
  30         for w 
in self
.GetChildren(): 
  32         wxPanel
.Enable(self
, value
) 
  33     def SetModified(self
): 
  35         g
.panel
.SetModified(True) 
  36     # Common method to set modified state 
  37     def OnChange(self
, evt
): 
  38         if self
.freeze
: return 
  42 class ParamBinaryOr(PPanel
): 
  43     def __init__(self
, parent
, name
): 
  44         PPanel
.__init
__(self
, parent
, name
) 
  45         self
.ID_TEXT_CTRL 
= wxNewId() 
  46         self
.ID_BUTTON_CHOICES 
= wxNewId() 
  48         self
.text 
= wxTextCtrl(self
, self
.ID_TEXT_CTRL
, size
=wxSize(200,-1)) 
  49         sizer
.Add(self
.text
, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL
, 5) 
  50         self
.button 
= wxButton(self
, self
.ID_BUTTON_CHOICES
, 'Edit...', size
=buttonSize
) 
  51         sizer
.Add(self
.button
, 0, wxALIGN_CENTER_VERTICAL
) 
  52         self
.SetAutoLayout(True) 
  55         EVT_BUTTON(self
, self
.ID_BUTTON_CHOICES
, self
.OnButtonChoices
) 
  56         EVT_TEXT(self
, self
.ID_TEXT_CTRL
, self
.OnChange
) 
  58         return self
.text
.GetValue() 
  59     def SetValue(self
, value
): 
  61         self
.text
.SetValue(value
) 
  63     def OnButtonChoices(self
, evt
): 
  64         dlg 
= g
.frame
.res
.LoadDialog(self
, 'DIALOG_CHOICES') 
  65         listBox 
= XRCCTRL(dlg
, 'CHECK_LIST') 
  66         listBox
.InsertItems(self
.values
, 0) 
  67         value 
= map(string
.strip
, self
.text
.GetValue().split('|')) 
  68         if value 
== ['']: value 
= [] 
  72                 listBox
.Check(self
.values
.index(i
)) 
  75                 if self
.equal
.has_key(i
): 
  76                     listBox
.Check(self
.values
.index(self
.equal
[i
])) 
  78                     print 'WARNING: unknown flag: %s: ignored.' % i
 
  80         if dlg
.ShowModal() == wxID_OK
: 
  82             for i 
in range(listBox
.GetCount()): 
  83                 if listBox
.IsChecked(i
): 
  84                     value
.append(self
.values
[i
]) 
  88                 self
.SetValue(reduce(lambda a
,b
: a
+'|'+b
, value
)) 
  94 class ParamFlag(ParamBinaryOr
): 
  95     values 
= ['wxTOP', 'wxBOTTOM', 'wxLEFT', 'wxRIGHT', 'wxALL', 
  96               'wxEXPAND', 'wxGROW', 'wxSHAPED', 'wxALIGN_CENTRE', 'wxALIGN_RIGHT', 
  98               'wxALIGN_BOTTOM', 'wxALIGN_CENTRE_VERTICAL', 
  99               'wxALIGN_CENTRE_HORIZONTAL', 
 101     equal 
= {'wxALIGN_CENTER': 'wxALIGN_CENTRE', 
 102              'wxALIGN_CENTER_VERTICAL': 'wxALIGN_CENTRE_VERTICAL', 
 103              'wxALIGN_CENTER_HORIZONTAL': 'wxALIGN_CENTRE_HORIZONTAL'} 
 104     def __init__(self
, parent
, name
): 
 105         ParamBinaryOr
.__init
__(self
, parent
, name
) 
 107 class ParamStyle(ParamBinaryOr
): 
 108     equal 
= {'wxALIGN_CENTER': 'wxALIGN_CENTRE'}
 
 109     def __init__(self
, parent
, name
): 
 110         self
.values 
= g
.currentXXX
.winStyles 
+ genericStyles
 
 111         ParamBinaryOr
.__init
__(self
, parent
, name
) 
 113 class ParamNonGenericStyle(ParamBinaryOr
): 
 114     def __init__(self
, parent
, name
): 
 115         self
.values 
= g
.currentXXX
.winStyles
 
 116         ParamBinaryOr
.__init
__(self
, parent
, name
) 
 118 class ParamExStyle(ParamBinaryOr
): 
 119     def __init__(self
, parent
, name
): 
 121             self
.values 
= g
.currentXXX
.exStyles 
# constant at the moment 
 124         ParamBinaryOr
.__init
__(self
, parent
, name
) 
 126 class ParamColour(PPanel
): 
 127     def __init__(self
, parent
, name
): 
 128         PPanel
.__init
__(self
, parent
, name
) 
 129         self
.ID_TEXT_CTRL 
= wxNewId() 
 130         self
.ID_BUTTON 
= wxNewId() 
 132         self
.text 
= wxTextCtrl(self
, self
.ID_TEXT_CTRL
, size
=(65,-1)) 
 133         sizer
.Add(self
.text
, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL
, 5) 
 134         self
.button 
= wxPanel(self
, self
.ID_BUTTON
, wxDefaultPosition
, wxSize(20, 1)) 
 135         sizer
.Add(self
.button
, 0, wxGROW | wxALIGN_CENTER_VERTICAL
) 
 136         self
.SetAutoLayout(True) 
 139         self
.textModified 
= False 
 140         EVT_PAINT(self
.button
, self
.OnPaintButton
) 
 141         EVT_TEXT(self
, self
.ID_TEXT_CTRL
, self
.OnChange
) 
 142         EVT_LEFT_DOWN(self
.button
, self
.OnLeftDown
) 
 144         return self
.text
.GetValue() 
 145     def SetValue(self
, value
): 
 147         if not value
: value 
= '#FFFFFF' 
 148         self
.text
.SetValue(str(value
))  # update text ctrl 
 149         colour 
= wxColour(int(value
[1:3], 16), int(value
[3:5], 16), int(value
[5:7], 16)) 
 150         self
.button
.SetBackgroundColour(colour
) 
 151         self
.button
.Refresh() 
 153     def OnPaintButton(self
, evt
): 
 154         dc 
= wxPaintDC(self
.button
) 
 155         dc
.SetBrush(wxTRANSPARENT_BRUSH
) 
 156         if self
.IsEnabled(): dc
.SetPen(wxBLACK_PEN
) 
 157         else: dc
.SetPen(wxGREY_PEN
) 
 158         size 
= self
.button
.GetSize() 
 159         dc
.DrawRectangle(0, 0, size
.width
, size
.height
) 
 160     def OnLeftDown(self
, evt
): 
 161         data 
= wxColourData() 
 162         data
.SetColour(self
.GetValue()) 
 163         dlg 
= wxColourDialog(self
, data
) 
 164         if dlg
.ShowModal() == wxID_OK
: 
 165             self
.SetValue('#%02X%02X%02X' % dlg
.GetColourData().GetColour().Get()) 
 169 ################################################################################ 
 171 # Mapping from wx constants ro XML strings 
 172 fontFamiliesWx2Xml 
= {wxDEFAULT
: 'default', wxDECORATIVE
: 'decorative', 
 173                 wxROMAN
: 'roman', wxSCRIPT
: 'script', wxSWISS
: 'swiss', 
 175 fontStylesWx2Xml 
= {wxNORMAL: 'normal', wxSLANT: 'slant', wxITALIC: 'italic'}
 
 176 fontWeightsWx2Xml 
= {wxNORMAL: 'normal', wxLIGHT: 'light', wxBOLD: 'bold'}
 
 179     for k
,v 
in m
.items(): rm
[v
] = k
 
 181 fontFamiliesXml2wx 
= ReverseMap(fontFamiliesWx2Xml
) 
 182 fontStylesXml2wx 
= ReverseMap(fontStylesWx2Xml
) 
 183 fontWeightsXml2wx 
= ReverseMap(fontWeightsWx2Xml
) 
 185 class ParamFont(PPanel
): 
 186     def __init__(self
, parent
, name
): 
 187         PPanel
.__init
__(self
, parent
, name
) 
 188         self
.ID_TEXT_CTRL 
= wxNewId() 
 189         self
.ID_BUTTON_SELECT 
= wxNewId() 
 191         self
.text 
= wxTextCtrl(self
, self
.ID_TEXT_CTRL
, size
=(200,-1)) 
 192         sizer
.Add(self
.text
, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL
, 5) 
 193         self
.button 
= wxButton(self
, self
.ID_BUTTON_SELECT
, 'Select...', size
=buttonSize
) 
 194         sizer
.Add(self
.button
, 0, wxALIGN_CENTER_VERTICAL
) 
 195         self
.SetAutoLayout(True) 
 198         self
.textModified 
= False 
 199         EVT_BUTTON(self
, self
.ID_BUTTON_SELECT
, self
.OnButtonSelect
) 
 200         EVT_TEXT(self
, self
.ID_TEXT_CTRL
, self
.OnChange
) 
 201     def OnChange(self
, evt
): 
 202         PPanel
.OnChange(self
, evt
) 
 203         self
.textModified 
= True 
 204     def _defaultValue(self
): 
 205         return ['12', 'default', 'normal', 'normal', '0', '', ''] 
 207         if self
.textModified
:           # text has newer value 
 209                 return eval(self
.text
.GetValue()) 
 211                 wxLogError('Syntax error in parameter value: ' + self
.GetName()) 
 212                 return self
._defaultValue
() 
 214     def SetValue(self
, value
): 
 215         self
.freeze 
= True              # disable other handlers 
 216         if not value
: value 
= self
._defaultValue
() 
 218         self
.text
.SetValue(str(value
))  # update text ctrl 
 220     def OnButtonSelect(self
, evt
): 
 221         if self
.textModified
:           # text has newer value 
 223                 self
.value 
= eval(self
.text
.GetValue()) 
 225                 wxLogError('Syntax error in parameter value: ' + self
.GetName()) 
 226                 self
.value 
= self
._defaultValue
() 
 231         style 
= weight 
= wxNORMAL
 
 234         enc 
= wxFONTENCODING_DEFAULT
 
 235         # Fall back to default if exceptions 
 238             try: size 
= int(self
.value
[0]) 
 239             except ValueError: error 
= True 
 240             try: family 
= fontFamiliesXml2wx
[self
.value
[1]] 
 241             except KeyError: error 
= True 
 242             try: style 
= fontStylesXml2wx
[self
.value
[2]] 
 243             except KeyError: error 
= True 
 244             try: weight 
= fontWeightsXml2wx
[self
.value
[3]] 
 245             except KeyError: error 
= True 
 246             try: underlined 
= int(self
.value
[4]) 
 247             except ValueError: error 
= True 
 249             mapper 
= wxFontMapper() 
 250             if not self
.value
[6]: enc 
= mapper
.CharsetToEncoding(self
.value
[6]) 
 253         if error
: wxLogError('Invalid font specification') 
 254         if enc 
== wxFONTENCODING_DEFAULT
: enc 
= wxFONTENCODING_SYSTEM
 
 255         font 
= wxFont(size
, family
, style
, weight
, underlined
, face
, enc
) 
 257         data
.SetInitialFont(font
) 
 258         dlg 
= wxFontDialog(self
, data
) 
 259         if dlg
.ShowModal() == wxID_OK
: 
 260             font 
= dlg
.GetFontData().GetChosenFont() 
 261             value 
= [str(font
.GetPointSize()), 
 262                      fontFamiliesWx2Xml
.get(font
.GetFamily(), "default"), 
 263                      fontStylesWx2Xml
.get(font
.GetStyle(), "normal"), 
 264                      fontWeightsWx2Xml
.get(font
.GetWeight(), "normal"), 
 265                      str(font
.GetUnderlined()), 
 266                      font
.GetFaceName().encode(), 
 267                      wxFontMapper_GetEncodingName(font
.GetEncoding()).encode() 
 272             self
.textModified 
= False 
 275 ################################################################################ 
 277 class ParamInt(PPanel
): 
 278     def __init__(self
, parent
, name
): 
 279         PPanel
.__init
__(self
, parent
, name
) 
 280         self
.ID_SPIN_CTRL 
= wxNewId() 
 282         self
.spin 
= wxSpinCtrl(self
, self
.ID_SPIN_CTRL
, size
=(50,-1)) 
 284         self
.SetAutoLayout(True) 
 287         EVT_SPINCTRL(self
, self
.ID_SPIN_CTRL
, self
.OnChange
) 
 289         return str(self
.spin
.GetValue()) 
 290     def SetValue(self
, value
): 
 292         if not value
: value 
= 0 
 293         self
.spin
.SetValue(int(value
)) 
 296 # Same as int but allows dialog units (XXXd) 
 297 class ParamUnit(PPanel
): 
 298     def __init__(self
, parent
, name
): 
 299         PPanel
.__init
__(self
, parent
, name
) 
 300         self
.ID_TEXT_CTRL 
= wxNewId() 
 301         self
.ID_SPIN_BUTTON 
= wxNewId() 
 303         self
.text 
= wxTextCtrl(self
, self
.ID_TEXT_CTRL
, size
=(35,-1)) 
 304         self
.spin 
= wxSpinButton(self
, self
.ID_SPIN_BUTTON
, style 
= wxSP_VERTICAL
, size
=(-1,1)) 
 305         self
.spin
.SetRange(-10000, 10000) 
 306         sizer
.Add(self
.text
, 0, wxEXPAND | wxRIGHT
, 2) 
 307         sizer
.Add(self
.spin
, 0, wxEXPAND
) 
 308         self
.SetAutoLayout(True) 
 311         EVT_SPIN_UP(self
, self
.ID_SPIN_BUTTON
, self
.OnSpinUp
) 
 312         EVT_SPIN_DOWN(self
, self
.ID_SPIN_BUTTON
, self
.OnSpinDown
) 
 314         return self
.text
.GetValue() 
 315     def SetValue(self
, value
): 
 317         if not value
: value 
= '0' 
 318         self
.text
.SetValue(value
) 
 321         # Check if we are working with dialog units 
 322         value 
= self
.text
.GetValue() 
 324         if value
[-1].upper() == 'D': 
 328             intValue 
= int(value
) + x
 
 329             self
.spin
.SetValue(intValue
) 
 330             self
.text
.SetValue(str(intValue
) + units
) 
 333             # !!! Strange, if I use wxLogWarning, event is re-generated 
 334             print 'incorrect unit format' 
 335     def OnSpinUp(self
, evt
): 
 337     def OnSpinDown(self
, evt
): 
 340 class ParamMultilineText(PPanel
): 
 341     def __init__(self
, parent
, name
, textWidth
=-1): 
 342         PPanel
.__init
__(self
, parent
, name
) 
 343         self
.ID_TEXT_CTRL 
= wxNewId() 
 344         self
.ID_BUTTON_EDIT 
= wxNewId() 
 346         self
.text 
= wxTextCtrl(self
, self
.ID_TEXT_CTRL
, size
=wxSize(200,-1)) 
 347         sizer
.Add(self
.text
, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL
, 5) 
 348         self
.button 
= wxButton(self
, self
.ID_BUTTON_EDIT
, 'Edit...', size
=buttonSize
) 
 349         sizer
.Add(self
.button
, 0, wxALIGN_CENTER_VERTICAL
) 
 350         self
.SetAutoLayout(True) 
 353         EVT_BUTTON(self
, self
.ID_BUTTON_EDIT
, self
.OnButtonEdit
) 
 354         EVT_TEXT(self
, self
.ID_TEXT_CTRL
, self
.OnChange
) 
 356         return self
.text
.GetValue() 
 357     def SetValue(self
, value
): 
 358         self
.freeze 
= True              # disable other handlers 
 359         self
.text
.SetValue(value
) 
 360         self
.freeze 
= False             # disable other handlers 
 361     def OnButtonEdit(self
, evt
): 
 362         dlg 
= g
.frame
.res
.LoadDialog(self
, 'DIALOG_TEXT') 
 363         textCtrl 
= XRCCTRL(dlg
, 'TEXT') 
 364         textCtrl
.SetValue(self
.text
.GetValue()) 
 365         if dlg
.ShowModal() == wxID_OK
: 
 366             self
.text
.SetValue(textCtrl
.GetValue()) 
 370 class ParamText(PPanel
): 
 371     def __init__(self
, parent
, name
, textWidth
=-1): 
 372         PPanel
.__init
__(self
, parent
, name
) 
 373         self
.ID_TEXT_CTRL 
= wxNewId() 
 374         # We use sizer even here to have the same size of text control 
 376         self
.text 
= wxTextCtrl(self
, self
.ID_TEXT_CTRL
, size
=wxSize(textWidth
,-1)) 
 377         if textWidth 
== -1: option 
= 1 
 379         sizer
.Add(self
.text
, option
, wxALIGN_CENTER_VERTICAL
) 
 380         self
.SetAutoLayout(True) 
 383         EVT_TEXT(self
, self
.ID_TEXT_CTRL
, self
.OnChange
) 
 385         return self
.text
.GetValue() 
 386     def SetValue(self
, value
): 
 387         self
.freeze 
= True              # disable other handlers 
 388         self
.text
.SetValue(value
) 
 389         self
.freeze 
= False             # disable other handlers 
 391 class ParamAccel(ParamText
): 
 392     def __init__(self
, parent
, name
): 
 393         ParamText
.__init
__(self
, parent
, name
, 100) 
 395 class ParamPosSize(ParamText
): 
 396     def __init__(self
, parent
, name
): 
 397         ParamText
.__init
__(self
, parent
, name
, 80) 
 399 class ParamLabel(ParamText
): 
 400     def __init__(self
, parent
, name
): 
 401         ParamText
.__init
__(self
, parent
, name
, 200) 
 403 class ParamEncoding(ParamText
): 
 404     def __init__(self
, parent
, name
): 
 405         ParamText
.__init
__(self
, parent
, name
, 100) 
 407 class ContentDialog(wxDialog
): 
 408     def __init__(self
, parent
, value
): 
 411         g
.frame
.res
.LoadOnDialog(pre
, parent
, 'DIALOG_CONTENT') 
 413         self
._setOORInfo
(self
) 
 414         self
.list = XRCCTRL(self
, 'LIST') 
 418         self
.SetAutoLayout(True) 
 419         self
.GetSizer().Fit(self
) 
 421         self
.ID_BUTTON_APPEND 
= XRCID('BUTTON_APPEND') 
 422         self
.ID_BUTTON_REMOVE 
= XRCID('BUTTON_REMOVE') 
 423         self
.ID_BUTTON_UP 
= XRCID('BUTTON_UP') 
 424         self
.ID_BUTTON_DOWN 
= XRCID('BUTTON_DOWN') 
 425         EVT_BUTTON(self
, self
.ID_BUTTON_UP
, self
.OnButtonUp
) 
 426         EVT_BUTTON(self
, self
.ID_BUTTON_DOWN
, self
.OnButtonDown
) 
 427         EVT_BUTTON(self
, self
.ID_BUTTON_APPEND
, self
.OnButtonAppend
) 
 428         EVT_BUTTON(self
, self
.ID_BUTTON_REMOVE
, self
.OnButtonRemove
) 
 429         EVT_UPDATE_UI(self
, self
.ID_BUTTON_UP
, self
.OnUpdateUI
) 
 430         EVT_UPDATE_UI(self
, self
.ID_BUTTON_DOWN
, self
.OnUpdateUI
) 
 431         EVT_UPDATE_UI(self
, self
.ID_BUTTON_REMOVE
, self
.OnUpdateUI
) 
 432     def OnButtonUp(self
, evt
): 
 433         i 
= self
.list.GetSelection() 
 434         str = self
.list.GetString(i
) 
 436         self
.list.InsertItems([str], i
-1) 
 437         self
.list.SetSelection(i
-1) 
 438     def OnButtonDown(self
, evt
): 
 439         i 
= self
.list.GetSelection() 
 440         str = self
.list.GetString(i
) 
 442         self
.list.InsertItems([str], i
+1) 
 443         self
.list.SetSelection(i
+1) 
 444     def OnButtonAppend(self
, evt
): 
 445         str = wxGetTextFromUser('Enter new item:', 'Append', '', self
) 
 446         self
.list.Append(str) 
 447     def OnButtonRemove(self
, evt
): 
 448         self
.list.Delete(self
.list.GetSelection()) 
 449     def OnUpdateUI(self
, evt
): 
 450         if evt
.GetId() == self
.ID_BUTTON_REMOVE
: 
 451             evt
.Enable(self
.list.GetSelection() != -1) 
 452         elif evt
.GetId() == self
.ID_BUTTON_UP
: 
 453             evt
.Enable(self
.list.GetSelection() > 0) 
 454         elif evt
.GetId() == self
.ID_BUTTON_DOWN
: 
 455             evt
.Enable(self
.list.GetSelection() != -1 and \
 
 456                        self
.list.GetSelection() < self
.list.GetCount() - 1) 
 458 class ContentCheckListDialog(wxDialog
): 
 459     def __init__(self
, parent
, value
): 
 461         g
.frame
.res
.LoadOnDialog(pre
, parent
, 'DIALOG_CONTENT_CHECK_LIST') 
 463         self
._setOORInfo
(self
) 
 464         self
.list = XRCCTRL(self
, 'CHECK_LIST') 
 469             self
.list.Check(i
, ch
) 
 471         self
.SetAutoLayout(True) 
 472         self
.GetSizer().Fit(self
) 
 474         self
.ID_BUTTON_APPEND 
= XRCID('BUTTON_APPEND') 
 475         self
.ID_BUTTON_REMOVE 
= XRCID('BUTTON_REMOVE') 
 476         self
.ID_BUTTON_UP 
= XRCID('BUTTON_UP') 
 477         self
.ID_BUTTON_DOWN 
= XRCID('BUTTON_DOWN') 
 478         EVT_CHECKLISTBOX(self
, self
.list.GetId(), self
.OnCheck
) 
 479         EVT_BUTTON(self
, self
.ID_BUTTON_UP
, self
.OnButtonUp
) 
 480         EVT_BUTTON(self
, self
.ID_BUTTON_DOWN
, self
.OnButtonDown
) 
 481         EVT_BUTTON(self
, self
.ID_BUTTON_APPEND
, self
.OnButtonAppend
) 
 482         EVT_BUTTON(self
, self
.ID_BUTTON_REMOVE
, self
.OnButtonRemove
) 
 483         EVT_UPDATE_UI(self
, self
.ID_BUTTON_UP
, self
.OnUpdateUI
) 
 484         EVT_UPDATE_UI(self
, self
.ID_BUTTON_DOWN
, self
.OnUpdateUI
) 
 485         EVT_UPDATE_UI(self
, self
.ID_BUTTON_REMOVE
, self
.OnUpdateUI
) 
 486     def OnCheck(self
, evt
): 
 487         # !!! Wrong wxGTK (wxMSW?) behavior: toggling selection if checking 
 488         self
.list.Deselect(evt
.GetSelection()) 
 489     def OnButtonUp(self
, evt
): 
 490         i 
= self
.list.GetSelection() 
 491         str, ch 
= self
.list.GetString(i
), self
.list.IsChecked(i
) 
 493         self
.list.InsertItems([str], i
-1) 
 494         self
.list.Check(i
-1, ch
) 
 495         self
.list.SetSelection(i
-1) 
 496     def OnButtonDown(self
, evt
): 
 497         i 
= self
.list.GetSelection() 
 498         str, ch 
= self
.list.GetString(i
), self
.list.IsChecked(i
) 
 500         self
.list.InsertItems([str], i
+1) 
 501         self
.list.Check(i
+1, ch
) 
 502         self
.list.SetSelection(i
+1) 
 503     def OnButtonAppend(self
, evt
): 
 504         str = wxGetTextFromUser('Enter new item:', 'Append', '', self
) 
 505         self
.list.Append(str) 
 506     def OnButtonRemove(self
, evt
): 
 507         self
.list.Delete(self
.list.GetSelection()) 
 508     def OnUpdateUI(self
, evt
): 
 509         if evt
.GetId() == self
.ID_BUTTON_REMOVE
: 
 510             evt
.Enable(self
.list.GetSelection() != -1) 
 511         elif evt
.GetId() == self
.ID_BUTTON_UP
: 
 512             evt
.Enable(self
.list.GetSelection() > 0) 
 513         elif evt
.GetId() == self
.ID_BUTTON_DOWN
: 
 514             evt
.Enable(self
.list.GetSelection() != -1 and \
 
 515                        self
.list.GetSelection() < self
.list.GetCount() - 1) 
 517 class ParamContent(PPanel
): 
 518     def __init__(self
, parent
, name
): 
 519         PPanel
.__init
__(self
, parent
, name
) 
 520         self
.ID_TEXT_CTRL 
= wxNewId() 
 521         self
.ID_BUTTON_EDIT 
= wxNewId() 
 523         self
.text 
= wxTextCtrl(self
, self
.ID_TEXT_CTRL
, size
=wxSize(200,-1)) 
 524         sizer
.Add(self
.text
, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL
, 5) 
 525         self
.button 
= wxButton(self
, self
.ID_BUTTON_EDIT
, 'Edit...', size
=buttonSize
) 
 526         sizer
.Add(self
.button
, 0, wxALIGN_CENTER_VERTICAL
) 
 527         self
.SetAutoLayout(True) 
 530         self
.textModified 
= False 
 531         EVT_BUTTON(self
, self
.ID_BUTTON_EDIT
, self
.OnButtonEdit
) 
 532         EVT_TEXT(self
, self
.ID_TEXT_CTRL
, self
.OnChange
) 
 533     def OnChange(self
, evt
): 
 534         PPanel
.OnChange(self
, evt
) 
 535         self
.textModified 
= True 
 537         if self
.textModified
:           # text has newer value 
 539                 return eval(self
.text
.GetValue()) 
 541                 wxLogError('Syntax error in parameter value: ' + self
.GetName()) 
 544     def SetValue(self
, value
): 
 546         if not value
: value 
= [] 
 548         self
.text
.SetValue(str(value
))  # update text ctrl 
 550     def OnButtonEdit(self
, evt
): 
 551         if self
.textModified
:           # text has newer value 
 553                 self
.value 
= eval(self
.text
.GetValue()) 
 555                 wxLogError('Syntax error in parameter value: ' + self
.GetName()) 
 557         dlg 
= ContentDialog(self
, self
.value
) 
 558         if dlg
.ShowModal() == wxID_OK
: 
 560             for i 
in range(dlg
.list.GetCount()): 
 561                 value
.append(dlg
.list.GetString(i
)) 
 565             self
.textModified 
= False 
 569 class ParamContentCheckList(ParamContent
): 
 570     def __init__(self
, parent
, name
): 
 571         ParamContent
.__init
__(self
, parent
, name
) 
 572     def OnButtonEdit(self
, evt
): 
 573         if self
.textModified
:           # text has newer value 
 575                 self
.value 
= eval(self
.text
.GetValue()) 
 577                 wxLogError('Syntax error in parameter value: ' + self
.GetName()) 
 579         dlg 
= ContentCheckListDialog(self
, self
.value
) 
 580         if dlg
.ShowModal() == wxID_OK
: 
 582             for i 
in range(dlg
.list.GetCount()): 
 583                 value
.append((dlg
.list.GetString(i
), dlg
.list.IsChecked(i
))) 
 587             self
.textModified 
= False 
 590 class IntListDialog(wxDialog
): 
 591     def __init__(self
, parent
, value
): 
 593         g
.frame
.res
.LoadOnDialog(pre
, parent
, 'DIALOG_INTLIST') 
 595         self
._setOORInfo
(self
) 
 596         self
.list = XRCCTRL(self
, 'LIST') 
 600             if type(v
) != IntType
: 
 601                 wxLogError('Invalid item type') 
 603                 self
.list.Append(str(v
)) 
 604         self
.SetAutoLayout(True) 
 605         self
.GetSizer().Fit(self
) 
 607         self
.ID_BUTTON_ADD 
= XRCID('BUTTON_ADD') 
 608         self
.ID_BUTTON_REMOVE 
= XRCID('BUTTON_REMOVE') 
 609         EVT_BUTTON(self
, self
.ID_BUTTON_ADD
, self
.OnButtonAppend
) 
 610         EVT_BUTTON(self
, self
.ID_BUTTON_REMOVE
, self
.OnButtonRemove
) 
 611         EVT_UPDATE_UI(self
, self
.ID_BUTTON_REMOVE
, self
.OnUpdateUI
) 
 612     def OnButtonAppend(self
, evt
): 
 613         s 
= wxGetTextFromUser('Enter new number:', 'Add', '', self
) 
 615         # Check that it's unique 
 618             s 
= str(v
)                  # to be sure 
 619             i 
= self
.list.FindString(s
) 
 620             if i 
== -1:                 # ignore non-unique 
 621                 # Find place to insert 
 623                 for i 
in range(self
.list.GetCount()): 
 624                     if int(self
.list.GetString(i
)) > v
: 
 627                 if found
: self
.list.InsertItems([s
], i
) 
 628                 else: self
.list.Append(s
) 
 630             wxLogError('List item is not an int!') 
 631     def OnButtonRemove(self
, evt
): 
 632         self
.list.Delete(self
.list.GetSelection()) 
 633     def OnUpdateUI(self
, evt
): 
 634         if evt
.GetId() == self
.ID_BUTTON_REMOVE
: 
 635             evt
.Enable(self
.list.GetSelection() != -1) 
 638 class ParamIntList(ParamContent
): 
 639     def __init__(self
, parent
, name
): 
 640         ParamContent
.__init
__(self
, parent
, name
) 
 641     def OnButtonEdit(self
, evt
): 
 642         if self
.textModified
:           # text has newer value 
 644                 self
.value 
= eval(self
.text
.GetValue()) 
 646                 wxLogError('Syntax error in parameter value: ' + self
.GetName()) 
 648         dlg 
= IntListDialog(self
, self
.value
) 
 649         if dlg
.ShowModal() == wxID_OK
: 
 651             for i 
in range(dlg
.list.GetCount()): 
 652                 value
.append(int(dlg
.list.GetString(i
))) 
 656             self
.textModified 
= False 
 660 class RadioBox(PPanel
): 
 661     def __init__(self
, parent
, id, choices
, 
 662                  pos
=wxDefaultPosition
, name
='radiobox'): 
 663         PPanel
.__init
__(self
, parent
, name
) 
 664         self
.choices 
= choices
 
 665         topSizer 
= wxBoxSizer() 
 667             button 
= wxRadioButton(self
, -1, i
, size
=(-1,buttonSize
[1]), name
=i
) 
 668             topSizer
.Add(button
, 0, wxRIGHT
, 5) 
 669             EVT_RADIOBUTTON(self
, button
.GetId(), self
.OnRadioChoice
) 
 670         self
.SetAutoLayout(True) 
 671         self
.SetSizer(topSizer
) 
 673     def SetStringSelection(self
, value
): 
 675         for i 
in self
.choices
: 
 676             self
.FindWindowByName(i
).SetValue(i 
== value
) 
 679     def OnRadioChoice(self
, evt
): 
 680         if self
.freeze
: return 
 681         if evt
.GetSelection(): 
 682             self
.value 
= evt
.GetEventObject().GetName() 
 684     def GetStringSelection(self
): 
 687 class ParamBool(RadioBox
): 
 688     values 
= {'yes': '1', 'no': '0'}
 
 689     seulav 
= {'1': 'yes', '0': 'no'}
 
 690     def __init__(self
, parent
, name
): 
 691         RadioBox
.__init
__(self
, parent
, -1, choices
=self
.values
.keys(), name
=name
) 
 693         return self
.values
[self
.GetStringSelection()] 
 694     def SetValue(self
, value
): 
 695         if not value
: value 
= '1' 
 696         self
.SetStringSelection(self
.seulav
[value
]) 
 698 class ParamOrient(RadioBox
): 
 699     values 
= {'horizontal': 'wxHORIZONTAL', 'vertical': 'wxVERTICAL'}
 
 700     seulav 
= {'wxHORIZONTAL': 'horizontal', 'wxVERTICAL': 'vertical'}
 
 701     def __init__(self
, parent
, name
): 
 702         RadioBox
.__init
__(self
, parent
, -1, choices
=self
.values
.keys(), name
=name
) 
 704         return self
.values
[self
.GetStringSelection()] 
 705     def SetValue(self
, value
): 
 706         if not value
: value 
= 'wxHORIZONTAL' 
 707         self
.SetStringSelection(self
.seulav
[value
]) 
 709 class ParamOrientation(RadioBox
): 
 710     values 
= {'horizontal': 'horizontal', 'vertical': 'vertical'}
 
 711     seulav 
= {'horizontal': 'horizontal', 'vertical': 'vertical'}
 
 712     def __init__(self
, parent
, name
): 
 713         RadioBox
.__init
__(self
, parent
, -1, choices
=self
.values
.keys(), name
=name
) 
 715         return self
.values
[self
.GetStringSelection()] 
 716     def SetValue(self
, value
): 
 717         if not value
: value 
= 'vertical' 
 718         self
.SetStringSelection(self
.seulav
[value
]) 
 720 class ParamFile(PPanel
): 
 721     def __init__(self
, parent
, name
): 
 722         PPanel
.__init
__(self
, parent
, name
) 
 723         self
.ID_TEXT_CTRL 
= wxNewId() 
 724         self
.ID_BUTTON_BROWSE 
= wxNewId() 
 726         self
.text 
= wxTextCtrl(self
, self
.ID_TEXT_CTRL
, size
=wxSize(200,-1)) 
 727         sizer
.Add(self
.text
, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL
, 5) 
 728         self
.button 
= wxButton(self
, self
.ID_BUTTON_BROWSE
, 'Browse...',size
=buttonSize
) 
 729         sizer
.Add(self
.button
, 0, wxALIGN_CENTER_VERTICAL
) 
 730         self
.SetAutoLayout(True) 
 733         self
.textModified 
= False 
 734         EVT_BUTTON(self
, self
.ID_BUTTON_BROWSE
, self
.OnButtonBrowse
) 
 735         EVT_TEXT(self
, self
.ID_TEXT_CTRL
, self
.OnChange
) 
 736     def OnChange(self
, evt
): 
 737         PPanel
.OnChange(self
, evt
) 
 738         self
.textModified 
= True 
 740         if self
.textModified
:           # text has newer value 
 741             return self
.text
.GetValue() 
 743     def SetValue(self
, value
): 
 746         self
.text
.SetValue(value
)  # update text ctrl 
 748     def OnButtonBrowse(self
, evt
): 
 749         if self
.textModified
:           # text has newer value 
 750             self
.value 
= self
.text
.GetValue() 
 751         dlg 
= wxFileDialog(self
, 
 752                            defaultDir 
= os
.path
.abspath(os
.path
.dirname(self
.value
)), 
 753                            defaultFile 
= os
.path
.basename(self
.value
)) 
 754         if dlg
.ShowModal() == wxID_OK
: 
 755             # Get common part of selected path and current 
 757                 curpath 
= os
.path
.abspath(g
.frame
.dataFile
) 
 759                 curpath 
= os
.path
.join(os
.getcwd(), '') 
 760             common 
= os
.path
.commonprefix([curpath
, dlg
.GetPath()]) 
 761             self
.SetValue(dlg
.GetPath()[len(common
):]) 
 763             self
.textModified 
= False 
 766 class ParamBitmap(PPanel
): 
 767     def __init__(self
, parent
, name
): 
 769         g
.frame
.res
.LoadOnPanel(pre
, parent
, 'PANEL_BITMAP') 
 771         self
._setOORInfo
(self
) 
 772         self
.SetBackgroundColour(parent
.GetBackgroundColour()) 
 773         self
.SetForegroundColour(parent
.GetForegroundColour()) 
 774         self
.modified 
= self
.freeze 
= False 
 775         self
.radio_std 
= XRCCTRL(self
, 'RADIO_STD') 
 776         self
.radio_std
.SetBackgroundColour(parent
.GetBackgroundColour()) 
 777         self
.radio_std
.SetForegroundColour(parent
.GetForegroundColour()) 
 778         self
.radio_file 
= XRCCTRL(self
, 'RADIO_FILE') 
 779         self
.radio_file
.SetBackgroundColour(parent
.GetBackgroundColour()) 
 780         self
.radio_file
.SetForegroundColour(parent
.GetForegroundColour()) 
 781         self
.combo 
= XRCCTRL(self
, 'COMBO_STD') 
 782         self
.text 
= XRCCTRL(self
, 'TEXT_FILE') 
 783         self
.button 
= XRCCTRL(self
, 'BUTTON_BROWSE') 
 784         self
.textModified 
= False 
 785         self
.SetAutoLayout(True) 
 786         self
.GetSizer().SetMinSize((260, -1)) 
 787         self
.GetSizer().Fit(self
) 
 788         EVT_RADIOBUTTON(self
, XRCID('RADIO_STD'), self
.OnRadioStd
) 
 789         EVT_RADIOBUTTON(self
, XRCID('RADIO_FILE'), self
.OnRadioFile
) 
 790         EVT_BUTTON(self
, XRCID('BUTTON_BROWSE'), self
.OnButtonBrowse
) 
 791         EVT_COMBOBOX(self
, XRCID('COMBO_STD'), self
.OnCombo
) 
 792         EVT_TEXT(self
, XRCID('COMBO_STD'), self
.OnChange
) 
 793         EVT_TEXT(self
, XRCID('TEXT_FILE'), self
.OnChange
) 
 794     def OnRadioStd(self
, evt
): 
 796         self
.SetValue(['wxART_MISSING_IMAGE','']) 
 797     def OnRadioFile(self
, evt
): 
 799         self
.SetValue(['','']) 
 800     def updateRadios(self
): 
 802             self
.radio_std
.SetValue(True) 
 803             self
.radio_file
.SetValue(False) 
 804             self
.text
.Enable(False) 
 805             self
.button
.Enable(False) 
 806             self
.combo
.Enable(True) 
 808             self
.radio_std
.SetValue(False) 
 809             self
.radio_file
.SetValue(True) 
 810             self
.text
.Enable(True) 
 811             self
.button
.Enable(True) 
 812             self
.combo
.Enable(False) 
 813     def OnChange(self
, evt
): 
 814         PPanel
.OnChange(self
, evt
) 
 815         self
.textModified 
= True 
 816     def OnCombo(self
, evt
): 
 817         PPanel
.OnChange(self
, evt
) 
 818         self
.value
[0] = self
.combo
.GetValue() 
 820         if self
.textModified
:           # text has newer value 
 821             return [self
.combo
.GetValue(), self
.text
.GetValue()] 
 823     def SetValue(self
, value
): 
 826             self
.value 
= ['', ''] 
 829         self
.combo
.SetValue(self
.value
[0]) 
 830         self
.text
.SetValue(self
.value
[1])  # update text ctrl 
 833     def OnButtonBrowse(self
, evt
): 
 834         if self
.textModified
:           # text has newer value 
 835             self
.value
[1] = self
.text
.GetValue() 
 836         dlg 
= wxFileDialog(self
, 
 837                            defaultDir 
= os
.path
.abspath(os
.path
.dirname(self
.value
[1])), 
 838                            defaultFile 
= os
.path
.basename(self
.value
[1])) 
 839         if dlg
.ShowModal() == wxID_OK
: 
 840             # Get common part of selected path and current 
 842                 curpath 
= os
.path
.abspath(g
.frame
.dataFile
) 
 844                 curpath 
= os
.path
.join(os
.getcwd(), '') 
 845             common 
= os
.path
.commonprefix([curpath
, dlg
.GetPath()]) 
 846             self
.SetValue(['', dlg
.GetPath()[len(common
):]]) 
 848             self
.textModified 
= False 
 853     'style': ParamStyle
, 'exstyle': ParamExStyle
, 
 854     'pos': ParamPosSize
, 'size': ParamPosSize
, 
 855     'border': ParamUnit
, 'cols': ParamInt
, 'rows': ParamInt
, 
 856     'vgap': ParamUnit
, 'hgap': ParamUnit
, 
 857     'checkable': ParamBool
, 'checked': ParamBool
, 'radio': ParamBool
, 
 859     'label': ParamMultilineText
, 'title': ParamText
, 'value': ParamText
, 
 860     'content': ParamContent
, 'selection': ParamInt
, 
 861     'min': ParamInt
, 'max': ParamInt
, 
 862     'fg': ParamColour
, 'bg': ParamColour
, 'font': ParamFont
, 
 863     'enabled': ParamBool
, 'focused': ParamBool
, 'hidden': ParamBool
, 
 864     'tooltip': ParamText
, 'bitmap': ParamBitmap
, 'icon': ParamBitmap
, 
 865     'encoding': ParamEncoding