2 # Purpose:      Classes for parameter introduction 
   3 # Author:       Roman Rolinsky <rolinsky@mema.ucl.ac.be> 
  13     'wxSIMPLE_BORDER', 'wxSUNKEN_BORDER', 'wxDOUBLE_BORDER', 
  14     'wxRAISED_BORDER', 'wxSTATIC_BORDER', 'wxNO_BORDER', 
  15     'wxCLIP_CHILDREN', 'wxTRANSPARENT_WINDOW', 'wxWANTS_CHARS', 
  16     'wxNO_FULL_REPAINT_ON_RESIZE', 'wxFULL_REPAINT_ON_RESIZE' 
  20     'wxWS_EX_VALIDATE_RECURSIVELY', 
  21     'wxWS_EX_BLOCK_EVENTS', 
  23     'wxFRAME_EX_CONTEXTHELP', 
  24     'wxWS_EX_PROCESS_IDLE', 
  25     'wxWS_EX_PROCESS_UI_UPDATES' 
  28 # Global vars initialized in Panel.__init__ for button and textbox size in screen pixels 
  29 buttonSize 
= textSise 
= None 
  30 # Default Button size in dialog units 
  34 # Class that can properly disable children 
  35 class PPanel(wx
.Panel
): 
  36     def __init__(self
, parent
, name
): 
  37         wx
.Panel
.__init
__(self
, parent
, -1, name
=name
) 
  38         self
.modified 
= self
.freeze 
= False 
  39     def Enable(self
, value
): 
  41         # Something strange is going on with enable so we make sure... 
  42         for w 
in self
.GetChildren(): 
  44         #wx.Panel.Enable(self, value) 
  45     def SetModified(self
, state
=True): 
  47         if state
: g
.panel
.SetModified(True) 
  48     # Common method to set modified state 
  49     def OnChange(self
, evt
): 
  50         if self
.freeze
: return 
  54 class ParamBinaryOr(PPanel
): 
  55     def __init__(self
, parent
, name
): 
  56         PPanel
.__init
__(self
, parent
, name
) 
  57         self
.ID_TEXT_CTRL 
= wx
.NewId() 
  58         self
.ID_BUTTON_CHOICES 
= wx
.NewId() 
  60         self
.text 
= wx
.TextCtrl(self
, self
.ID_TEXT_CTRL
, size
=wx
.Size(200,-1)) 
  61         sizer
.Add(self
.text
, 0, wx
.RIGHT | wx
.ALIGN_CENTER_VERTICAL
, 5) 
  62         self
.button 
= wx
.Button(self
, self
.ID_BUTTON_CHOICES
, 'Edit...',  
  63                                 size
=(buttonSize
[0], textSize
[1])) 
  64         sizer
.Add(self
.button
, 0, wx
.EXPAND
) 
  65         self
.SetSizerAndFit(sizer
) 
  66         wx
.EVT_BUTTON(self
, self
.ID_BUTTON_CHOICES
, self
.OnButtonChoices
) 
  67         wx
.EVT_TEXT(self
, self
.ID_TEXT_CTRL
, self
.OnChange
) 
  69         return self
.text
.GetValue() 
  70     def SetValue(self
, value
): 
  72         self
.text
.SetValue(value
) 
  74     def OnButtonChoices(self
, evt
): 
  75         dlg 
= g
.frame
.res
.LoadDialog(self
, 'DIALOG_CHOICES') 
  76         if self
.GetName() == 'flag':  dlg
.SetTitle('Sizer item flags') 
  77         elif self
.GetName() == 'style':  dlg
.SetTitle('Window styles') 
  78         elif self
.GetName() == 'exstyle':  dlg
.SetTitle('Extended window styles') 
  79         listBox 
= xrc
.XRCCTRL(dlg
, 'CHECKLIST') 
  80         listBox
.InsertItems(self
.values
, 0) 
  81         value 
= map(string
.strip
, self
.text
.GetValue().split('|')) 
  82         if value 
== ['']: value 
= [] 
  86                 listBox
.Check(self
.values
.index(i
)) 
  89                 if self
.equal
.has_key(i
): 
  90                     listBox
.Check(self
.values
.index(self
.equal
[i
])) 
  92                     print 'WARNING: unknown flag: %s: ignored.' % i
 
  94         if dlg
.ShowModal() == wx
.ID_OK
: 
  96             for i 
in range(listBox
.GetCount()): 
  97                 if listBox
.IsChecked(i
): 
  98                     value
.append(self
.values
[i
]) 
 100             value
.extend(ignored
) 
 101             self
.SetValue('|'.join(value
)) 
 105 class ParamFlag(ParamBinaryOr
): 
 106     values 
= ['wxTOP', 'wxBOTTOM', 'wxLEFT', 'wxRIGHT', 'wxALL', 
 107               'wxEXPAND', 'wxGROW', 'wxSHAPED', 'wxSTRETCH_NOT', 
 108               'wxALIGN_CENTRE', 'wxALIGN_LEFT', 'wxALIGN_RIGHT', 
 109               'wxALIGN_TOP', 'wxALIGN_BOTTOM',  
 110               'wxALIGN_CENTRE_VERTICAL', 'wxALIGN_CENTRE_HORIZONTAL',  
 111               'wxADJUST_MINSIZE', 'wxFIXED_MINSIZE' 
 113     equal 
= {'wxALIGN_CENTER': 'wxALIGN_CENTRE', 
 114              'wxALIGN_CENTER_VERTICAL': 'wxALIGN_CENTRE_VERTICAL', 
 115              'wxALIGN_CENTER_HORIZONTAL': 'wxALIGN_CENTRE_HORIZONTAL', 
 116              'wxUP': 'wxTOP', 'wxDOWN': 'wxBOTTOM', 'wxNORTH': 'wxTOP', 
 117              'wxSOUTH': 'wxBOTTOM', 'wxWEST': 'wxLEFT', 'wxEAST': 'wxRIGHT'} 
 118     def __init__(self
, parent
, name
): 
 119         ParamBinaryOr
.__init
__(self
, parent
, name
) 
 121 class ParamNonGenericStyle(ParamBinaryOr
): 
 122     def __init__(self
, parent
, name
): 
 123         self
.values 
= g
.currentXXX
.winStyles
 
 124         ParamBinaryOr
.__init
__(self
, parent
, name
) 
 126 class ParamStyle(ParamBinaryOr
): 
 127     equal 
= {'wxALIGN_CENTER': 'wxALIGN_CENTRE'}
 
 128     def __init__(self
, parent
, name
): 
 129         ParamBinaryOr
.__init
__(self
, parent
, name
) 
 130         self
.valuesSpecific 
= g
.currentXXX
.winStyles
 
 131         if self
.valuesSpecific
:         # override if using specific styles 
 133             self
.valuesGeneric 
= [s 
for s 
in genericStyles
 
 134                                   if s 
not in self
.valuesSpecific
] 
 135             wx
.EVT_BUTTON(self
, self
.ID_BUTTON_CHOICES
, self
.OnButtonChoicesBoth
) 
 137             self
.values 
= genericStyles
 
 138     def OnButtonChoicesBoth(self
, evt
): 
 139         dlg 
= g
.frame
.res
.LoadDialog(self
, 'DIALOG_STYLES') 
 140         listBoxSpecific 
= xrc
.XRCCTRL(dlg
, 'CHECKLIST_SPECIFIC') 
 141         listBoxSpecific
.InsertItems(self
.valuesSpecific
, 0) 
 142         listBoxGeneric 
= xrc
.XRCCTRL(dlg
, 'CHECKLIST_GENERIC') 
 143         listBoxGeneric
.InsertItems(self
.valuesGeneric
, 0) 
 144         value 
= map(string
.strip
, self
.text
.GetValue().split('|')) 
 145         if value 
== ['']: value 
= [] 
 146         # Set specific styles 
 147         value2 
= []                     # collect generic and ignored here 
 150                 listBoxSpecific
.Check(self
.valuesSpecific
.index(i
)) 
 153                 if self
.equal
.has_key(i
): 
 154                     listBoxSpecific
.Check(self
.valuesSpecific
.index(self
.equal
[i
])) 
 158         # Set generic styles, collect non-standart values 
 161                 listBoxGeneric
.Check(self
.valuesGeneric
.index(i
)) 
 164                 if self
.equal
.has_key(i
): 
 165                     listBoxGeneric
.Check(self
.valuesGeneric
.index(self
.equal
[i
])) 
 167                     print 'WARNING: unknown flag: %s: ignored.' % i
 
 169         if dlg
.ShowModal() == wx
.ID_OK
: 
 170             value 
= [self
.valuesSpecific
[i
] 
 171                      for i 
in range(listBoxSpecific
.GetCount()) 
 172                      if listBoxSpecific
.IsChecked(i
)] + \
 
 173                      [self
.valuesGeneric
[i
] 
 174                       for i 
in range(listBoxGeneric
.GetCount()) 
 175                       if listBoxGeneric
.IsChecked(i
)] + ignored
 
 176             self
.SetValue('|'.join(value
)) 
 180 class ParamExStyle(ParamBinaryOr
): 
 181     def __init__(self
, parent
, name
): 
 183             self
.values 
= g
.currentXXX
.exStyles 
+ genericExStyles
 
 186         ParamBinaryOr
.__init
__(self
, parent
, name
) 
 188 class ParamColour(PPanel
): 
 189     def __init__(self
, parent
, name
): 
 190         PPanel
.__init
__(self
, parent
, name
) 
 191         self
.ID_TEXT_CTRL 
= wx
.NewId() 
 192         self
.ID_BUTTON 
= wx
.NewId() 
 193         sizer 
= wx
.BoxSizer() 
 194         self
.text 
= wx
.TextCtrl(self
, self
.ID_TEXT_CTRL
, size
=(80,-1)) 
 195         sizer
.Add(self
.text
, 0, wx
.ALIGN_CENTER_VERTICAL | wx
.TOP | wx
.BOTTOM
, 2) 
 196         self
.button 
= wx
.Panel(self
, self
.ID_BUTTON
, wx
.DefaultPosition
, wx
.Size(20, 20)) 
 197         sizer
.Add(self
.button
, 0, wx
.ALIGN_CENTER_VERTICAL | wx
.LEFT
, 5) 
 199         self
.textModified 
= False 
 200         wx
.EVT_PAINT(self
.button
, self
.OnPaintButton
) 
 201         wx
.EVT_TEXT(self
, self
.ID_TEXT_CTRL
, self
.OnChange
) 
 202         wx
.EVT_LEFT_DOWN(self
.button
, self
.OnLeftDown
) 
 204         return self
.text
.GetValue() 
 205     def SetValue(self
, value
): 
 207         if not value
: value 
= '#FFFFFF' 
 208         self
.text
.SetValue(str(value
))  # update text ctrl 
 210             colour 
= wx
.Colour(int(value
[1:3], 16), int(value
[3:5], 16), int(value
[5:7], 16)) 
 211             self
.button
.SetBackgroundColour(colour
) 
 212         except:                         # ignore errors 
 214         self
.button
.Refresh() 
 216     def OnPaintButton(self
, evt
): 
 217         dc 
= wx
.PaintDC(self
.button
) 
 218         dc
.SetBrush(wx
.TRANSPARENT_BRUSH
) 
 219         if self
.IsEnabled(): dc
.SetPen(wx
.BLACK_PEN
) 
 220         else: dc
.SetPen(wx
.GREY_PEN
) 
 221         size 
= self
.button
.GetSize() 
 222         dc
.DrawRectangle(0, 0, size
.width
, size
.height
) 
 223     def OnLeftDown(self
, evt
): 
 224         data 
= wx
.ColourData() 
 225         data
.SetColour(self
.GetValue()) 
 226         dlg 
= wx
.ColourDialog(self
, data
) 
 227         if dlg
.ShowModal() == wx
.ID_OK
: 
 228             self
.SetValue('#%02X%02X%02X' % dlg
.GetColourData().GetColour().Get()) 
 232 ################################################################################ 
 234 # Mapping from wx constants to XML strings 
 235 fontFamiliesWx2Xml 
= {wx
.DEFAULT
: 'default', wx
.DECORATIVE
: 'decorative', 
 236                 wx
.ROMAN
: 'roman', wx
.SCRIPT
: 'script', wx
.SWISS
: 'swiss', 
 238 fontStylesWx2Xml 
= {wx.NORMAL: 'normal', wx.SLANT: 'slant', wx.ITALIC: 'italic'}
 
 239 fontWeightsWx2Xml 
= {wx.NORMAL: 'normal', wx.LIGHT: 'light', wx.BOLD: 'bold'}
 
 242     for k
,v 
in m
.items(): rm
[v
] = k
 
 244 fontFamiliesXml2wx 
= ReverseMap(fontFamiliesWx2Xml
) 
 245 fontStylesXml2wx 
= ReverseMap(fontStylesWx2Xml
) 
 246 fontWeightsXml2wx 
= ReverseMap(fontWeightsWx2Xml
) 
 248 class ParamFont(PPanel
): 
 249     def __init__(self
, parent
, name
): 
 250         PPanel
.__init
__(self
, parent
, name
) 
 251         self
.ID_TEXT_CTRL 
= wx
.NewId() 
 252         self
.ID_BUTTON_SELECT 
= wx
.NewId() 
 253         sizer 
= wx
.BoxSizer() 
 254         self
.text 
= wx
.TextCtrl(self
, self
.ID_TEXT_CTRL
, size
=(200,-1)) 
 255         sizer
.Add(self
.text
, 0, wx
.RIGHT | wx
.ALIGN_CENTER_VERTICAL
, 5) 
 256         self
.button 
= wx
.Button(self
, self
.ID_BUTTON_SELECT
, 'Select...', size
=buttonSize
) 
 257         sizer
.Add(self
.button
, 0, wx
.ALIGN_CENTER_VERTICAL
) 
 259         self
.textModified 
= False 
 260         wx
.EVT_BUTTON(self
, self
.ID_BUTTON_SELECT
, self
.OnButtonSelect
) 
 261         wx
.EVT_TEXT(self
, self
.ID_TEXT_CTRL
, self
.OnChange
) 
 262     def OnChange(self
, evt
): 
 263         PPanel
.OnChange(self
, evt
) 
 264         self
.textModified 
= True 
 265     def _defaultValue(self
): 
 266         return [`g
.sysFont().GetPointSize()`
, 'default', 'normal', 'normal', '0', '', ''] 
 268         if self
.textModified
:           # text has newer value 
 270                 return eval(self
.text
.GetValue()) 
 272                 wx
.LogError('Syntax error in parameter value: ' + self
.GetName()) 
 273                 return self
._defaultValue
() 
 275     def SetValue(self
, value
): 
 276         self
.freeze 
= True              # disable other handlers 
 277         if not value
: value 
= self
._defaultValue
() 
 279         self
.text
.SetValue(str(value
))  # update text ctrl 
 281     def OnButtonSelect(self
, evt
): 
 282         if self
.textModified
:           # text has newer value 
 284                 self
.value 
= eval(self
.text
.GetValue()) 
 286                 wx
.LogError('Syntax error in parameter value: ' + self
.GetName()) 
 287                 self
.value 
= self
._defaultValue
() 
 290         size 
= g
.sysFont().GetPointSize() 
 292         style 
= weight 
= wx
.NORMAL
 
 295         enc 
= wx
.FONTENCODING_DEFAULT
 
 296         # Fall back to default if exceptions 
 299             try: size 
= int(self
.value
[0]) 
 300             except ValueError: error 
= True; wx
.LogError('Invalid size specification') 
 301             try: family 
= fontFamiliesXml2wx
[self
.value
[1]] 
 302             except KeyError: error 
= True; wx
.LogError('Invalid family specification') 
 303             try: style 
= fontStylesXml2wx
[self
.value
[2]] 
 304             except KeyError: error 
= True; wx
.LogError('Invalid style specification') 
 305             try: weight 
= fontWeightsXml2wx
[self
.value
[3]] 
 306             except KeyError: error 
= True; wx
.LogError('Invalid weight specification') 
 307             try: underlined 
= bool(self
.value
[4]) 
 308             except ValueError: error 
= True; wx
.LogError('Invalid underlined flag specification') 
 312         mapper 
= wx
.FontMapper() 
 313         if not self
.value
[6]: enc 
= mapper
.CharsetToEncoding(self
.value
[6]) 
 315         if error
: wx
.LogError('Invalid font specification') 
 316         if enc 
== wx
.FONTENCODING_DEFAULT
: enc 
= wx
.FONTENCODING_SYSTEM
 
 317         font 
= wx
.Font(size
, family
, style
, weight
, underlined
, face
, enc
) 
 319         data
.SetInitialFont(font
) 
 320         dlg 
= wx
.FontDialog(self
, data
) 
 321         if dlg
.ShowModal() == wx
.ID_OK
: 
 322             font 
= dlg
.GetFontData().GetChosenFont() 
 323             if font
.GetEncoding() == wx
.FONTENCODING_SYSTEM
: 
 326                 encName 
= wx
.FontMapper
.GetEncodingName(font
.GetEncoding()).encode() 
 327             value 
= [str(font
.GetPointSize()), 
 328                      fontFamiliesWx2Xml
.get(font
.GetFamily(), "default"), 
 329                      fontStylesWx2Xml
.get(font
.GetStyle(), "normal"), 
 330                      fontWeightsWx2Xml
.get(font
.GetWeight(), "normal"), 
 331                      str(int(font
.GetUnderlined())), 
 332                      font
.GetFaceName().encode(), 
 337             self
.textModified 
= False 
 340 ################################################################################ 
 342 class ParamInt(PPanel
): 
 343     def __init__(self
, parent
, name
): 
 344         PPanel
.__init
__(self
, parent
, name
) 
 345         self
.ID_SPIN_CTRL 
= wx
.NewId() 
 346         sizer 
= wx
.BoxSizer() 
 347         self
.spin 
= wx
.SpinCtrl(self
, self
.ID_SPIN_CTRL
, size
=(60,-1)) 
 348         self
.spin
.SetRange(-2147483648, 2147483647) # min/max integers 
 351         wx
.EVT_SPINCTRL(self
, self
.ID_SPIN_CTRL
, self
.OnChange
) 
 353         return str(self
.spin
.GetValue()) 
 354     def SetValue(self
, value
): 
 356         if not value
: value 
= 0 
 357         self
.spin
.SetValue(int(value
)) 
 360 # Non-negative number 
 361 class ParamIntNN(PPanel
): 
 362     def __init__(self
, parent
, name
): 
 363         PPanel
.__init
__(self
, parent
, name
) 
 364         self
.ID_SPIN_CTRL 
= wx
.NewId() 
 365         sizer 
= wx
.BoxSizer() 
 366         self
.spin 
= wx
.SpinCtrl(self
, self
.ID_SPIN_CTRL
, size
=(60,-1)) 
 367         self
.spin
.SetRange(0, 10000) # min/max integers 
 370         wx
.EVT_SPINCTRL(self
, self
.ID_SPIN_CTRL
, self
.OnChange
) 
 372         return str(self
.spin
.GetValue()) 
 373     def SetValue(self
, value
): 
 375         if not value
: value 
= 0 
 376         self
.spin
.SetValue(int(value
)) 
 379 # Same as int but allows dialog units (XXXd) 
 380 class ParamUnit(PPanel
): 
 381     def __init__(self
, parent
, name
): 
 382         PPanel
.__init
__(self
, parent
, name
) 
 383         self
.ID_TEXT_CTRL 
= wx
.NewId() 
 384         self
.ID_SPIN_BUTTON 
= wx
.NewId() 
 385         sizer 
= wx
.BoxSizer(wx
.HORIZONTAL
) 
 386         self
.spin 
= wx
.SpinButton(self
, self
.ID_SPIN_BUTTON
, style 
= wx
.SP_VERTICAL
, size
=(-1,0)) 
 387         textW 
= 60 - self
.spin
.GetSize()[0] 
 388         self
.text 
= wx
.TextCtrl(self
, self
.ID_TEXT_CTRL
, size
=(textW
,-1)) 
 389         self
.spin
.SetRange(-10000, 10000) 
 390         sizer
.Add(self
.text
, 0, wx
.EXPAND
) 
 391         sizer
.Add(self
.spin
, 0, wx
.EXPAND
) 
 393         self
.spin
.Bind(wx
.EVT_SPIN_UP
, self
.OnSpinUp
) 
 394         self
.spin
.Bind(wx
.EVT_SPIN_DOWN
, self
.OnSpinDown
) 
 395         self
.text
.Bind(wx
.EVT_TEXT
, self
.OnChange
) 
 398         return self
.text
.GetValue() 
 399     def SetValue(self
, value
): 
 401         if not value
: value 
= '0'         
 402         self
.text
.SetValue(value
) 
 407         # Check if we are working with dialog units 
 408         value 
= self
.text
.GetValue() 
 410         if value
[-1].upper() == 'D': 
 414             intValue 
= int(value
) + x
 
 415             self
.spin
.SetValue(intValue
) 
 416             if x
:                       # 0 can be passed to update spin value only 
 417                 self
.text
.SetValue(str(intValue
) + units
) 
 420             # !!! Strange, if I use wx.LogWarning, event is re-generated 
 421             print 'ERROR: incorrect unit format' 
 423     def OnSpinUp(self
, evt
): 
 426     def OnSpinDown(self
, evt
): 
 427         if self
.freeze
: return 
 431 class ParamMultilineText(PPanel
): 
 432     def __init__(self
, parent
, name
, textWidth
=-1): 
 433         PPanel
.__init
__(self
, parent
, name
) 
 434         self
.ID_TEXT_CTRL 
= wx
.NewId() 
 435         self
.ID_BUTTON_EDIT 
= wx
.NewId() 
 436         sizer 
= wx
.BoxSizer() 
 437         self
.text 
= wx
.TextCtrl(self
, self
.ID_TEXT_CTRL
, size
=wx
.Size(200,-1)) 
 438         sizer
.Add(self
.text
, 0, wx
.RIGHT | wx
.ALIGN_CENTER_VERTICAL
, 5) 
 439         self
.button 
= wx
.Button(self
, self
.ID_BUTTON_EDIT
, 'Edit...', size
=buttonSize
) 
 440         sizer
.Add(self
.button
, 0, wx
.ALIGN_CENTER_VERTICAL
) 
 441         self
.SetSizerAndFit(sizer
) 
 442         wx
.EVT_BUTTON(self
, self
.ID_BUTTON_EDIT
, self
.OnButtonEdit
) 
 443         wx
.EVT_TEXT(self
, self
.ID_TEXT_CTRL
, self
.OnChange
) 
 445         return self
.text
.GetValue() 
 446     def SetValue(self
, value
): 
 447         self
.freeze 
= True              # disable other handlers 
 448         self
.text
.SetValue(value
) 
 449         self
.freeze 
= False             # disable other handlers 
 450     def OnButtonEdit(self
, evt
): 
 451         dlg 
= g
.frame
.res
.LoadDialog(self
, 'DIALOG_TEXT') 
 452         textCtrl 
= xrc
.XRCCTRL(dlg
, 'TEXT') 
 453         textCtrl
.SetValue(self
.text
.GetValue()) 
 454         if dlg
.ShowModal() == wx
.ID_OK
: 
 455             self
.text
.SetValue(textCtrl
.GetValue()) 
 459 class ParamText(PPanel
): 
 460     def __init__(self
, parent
, name
, textWidth
=-1, style
=0): 
 461         PPanel
.__init
__(self
, parent
, name
) 
 462         self
.ID_TEXT_CTRL 
= wx
.NewId() 
 463         # We use sizer even here to have the same size of text control 
 464         sizer 
= wx
.BoxSizer() 
 465         self
.text 
= wx
.TextCtrl(self
, self
.ID_TEXT_CTRL
, size
=wx
.Size(textWidth
,-1), style
=style
) 
 466         if textWidth 
== -1: option 
= 1 
 468         sizer
.Add(self
.text
, option
, wx
.ALIGN_CENTER_VERTICAL | wx
.TOP | wx
.BOTTOM
, 2) 
 470         wx
.EVT_TEXT(self
, self
.ID_TEXT_CTRL
, self
.OnChange
) 
 472         return self
.text
.GetValue() 
 473     def SetValue(self
, value
): 
 474         self
.freeze 
= True              # disable other handlers 
 475         self
.text
.SetValue(value
) 
 476         self
.freeze 
= False             # disable other handlers 
 478 class ParamAccel(ParamText
): 
 479     def __init__(self
, parent
, name
): 
 480         ParamText
.__init
__(self
, parent
, name
, 100) 
 482 class ParamPosSize(ParamText
): 
 483     def __init__(self
, parent
, name
): 
 484         ParamText
.__init
__(self
, parent
, name
, 80) 
 486 class ParamLabel(ParamText
): 
 487     def __init__(self
, parent
, name
): 
 488         ParamText
.__init
__(self
, parent
, name
, 200) 
 490 class ParamEncoding(ParamText
): 
 491     def __init__(self
, parent
, name
): 
 492         ParamText
.__init
__(self
, parent
, name
, 100) 
 494 class ParamComment(ParamText
): 
 495     def __init__(self
, parent
, name
): 
 496         ParamText
.__init
__(self
, parent
, name
, 330 + buttonSize
[0], 
 497                            style
=wx
.TE_PROCESS_ENTER
) 
 499 class ContentDialog(wx
.Dialog
): 
 500     def __init__(self
, parent
, value
): 
 503         g
.frame
.res
.LoadOnDialog(pre
, parent
, 'DIALOG_CONTENT') 
 505         self
.list = xrc
.XRCCTRL(self
, 'LIST') 
 509         self
.SetAutoLayout(True) 
 510         self
.GetSizer().Fit(self
) 
 512         self
.ID_BUTTON_APPEND 
= xrc
.XRCID('BUTTON_APPEND') 
 513         self
.ID_BUTTON_REMOVE 
= xrc
.XRCID('BUTTON_REMOVE') 
 514         self
.ID_BUTTON_UP 
= xrc
.XRCID('BUTTON_UP') 
 515         self
.ID_BUTTON_DOWN 
= xrc
.XRCID('BUTTON_DOWN') 
 516         wx
.EVT_BUTTON(self
, self
.ID_BUTTON_UP
, self
.OnButtonUp
) 
 517         wx
.EVT_BUTTON(self
, self
.ID_BUTTON_DOWN
, self
.OnButtonDown
) 
 518         wx
.EVT_BUTTON(self
, self
.ID_BUTTON_APPEND
, self
.OnButtonAppend
) 
 519         wx
.EVT_BUTTON(self
, self
.ID_BUTTON_REMOVE
, self
.OnButtonRemove
) 
 520         wx
.EVT_UPDATE_UI(self
, self
.ID_BUTTON_UP
, self
.OnUpdateUI
) 
 521         wx
.EVT_UPDATE_UI(self
, self
.ID_BUTTON_DOWN
, self
.OnUpdateUI
) 
 522         wx
.EVT_UPDATE_UI(self
, self
.ID_BUTTON_REMOVE
, self
.OnUpdateUI
) 
 523     def OnButtonUp(self
, evt
): 
 524         i 
= self
.list.GetSelection() 
 525         str = self
.list.GetString(i
) 
 527         self
.list.InsertItems([str], i
-1) 
 528         self
.list.SetSelection(i
-1) 
 529     def OnButtonDown(self
, evt
): 
 530         i 
= self
.list.GetSelection() 
 531         str = self
.list.GetString(i
) 
 533         self
.list.InsertItems([str], i
+1) 
 534         self
.list.SetSelection(i
+1) 
 535     def OnButtonAppend(self
, evt
): 
 536         str = wx
.GetTextFromUser('Enter new item:', 'Append', '', self
) 
 537         self
.list.Append(str) 
 538     def OnButtonRemove(self
, evt
): 
 539         self
.list.Delete(self
.list.GetSelection()) 
 540     def OnUpdateUI(self
, evt
): 
 541         if evt
.GetId() == self
.ID_BUTTON_REMOVE
: 
 542             evt
.Enable(self
.list.GetSelection() != -1) 
 543         elif evt
.GetId() == self
.ID_BUTTON_UP
: 
 544             evt
.Enable(self
.list.GetSelection() > 0) 
 545         elif evt
.GetId() == self
.ID_BUTTON_DOWN
: 
 546             evt
.Enable(self
.list.GetSelection() != -1 and \
 
 547                        self
.list.GetSelection() < self
.list.GetCount() - 1) 
 549 class ContentCheckListDialog(wx
.Dialog
): 
 550     def __init__(self
, parent
, value
): 
 552         g
.frame
.res
.LoadOnDialog(pre
, parent
, 'DIALOG_CONTENT_CHECKLIST') 
 554         self
.list = xrc
.XRCCTRL(self
, 'CHECK_LIST') 
 559             self
.list.Check(i
, ch
) 
 561         self
.SetAutoLayout(True) 
 562         self
.GetSizer().Fit(self
) 
 564         self
.ID_BUTTON_APPEND 
= xrc
.XRCID('BUTTON_APPEND') 
 565         self
.ID_BUTTON_REMOVE 
= xrc
.XRCID('BUTTON_REMOVE') 
 566         self
.ID_BUTTON_UP 
= xrc
.XRCID('BUTTON_UP') 
 567         self
.ID_BUTTON_DOWN 
= xrc
.XRCID('BUTTON_DOWN') 
 568         wx
.EVT_CHECKLISTBOX(self
, self
.list.GetId(), self
.OnCheck
) 
 569         wx
.EVT_BUTTON(self
, self
.ID_BUTTON_UP
, self
.OnButtonUp
) 
 570         wx
.EVT_BUTTON(self
, self
.ID_BUTTON_DOWN
, self
.OnButtonDown
) 
 571         wx
.EVT_BUTTON(self
, self
.ID_BUTTON_APPEND
, self
.OnButtonAppend
) 
 572         wx
.EVT_BUTTON(self
, self
.ID_BUTTON_REMOVE
, self
.OnButtonRemove
) 
 573         wx
.EVT_UPDATE_UI(self
, self
.ID_BUTTON_UP
, self
.OnUpdateUI
) 
 574         wx
.EVT_UPDATE_UI(self
, self
.ID_BUTTON_DOWN
, self
.OnUpdateUI
) 
 575         wx
.EVT_UPDATE_UI(self
, self
.ID_BUTTON_REMOVE
, self
.OnUpdateUI
) 
 576     def OnCheck(self
, evt
): 
 577         # !!! Wrong wxGTK (wxMSW?) behavior: toggling selection if checking 
 578         self
.list.Deselect(evt
.GetSelection()) 
 579     def OnButtonUp(self
, evt
): 
 580         i 
= self
.list.GetSelection() 
 581         str, ch 
= self
.list.GetString(i
), self
.list.IsChecked(i
) 
 583         self
.list.InsertItems([str], i
-1) 
 584         self
.list.Check(i
-1, ch
) 
 585         self
.list.SetSelection(i
-1) 
 586     def OnButtonDown(self
, evt
): 
 587         i 
= self
.list.GetSelection() 
 588         str, ch 
= self
.list.GetString(i
), self
.list.IsChecked(i
) 
 590         self
.list.InsertItems([str], i
+1) 
 591         self
.list.Check(i
+1, ch
) 
 592         self
.list.SetSelection(i
+1) 
 593     def OnButtonAppend(self
, evt
): 
 594         str = wx
.GetTextFromUser('Enter new item:', 'Append', '', self
) 
 595         self
.list.Append(str) 
 596     def OnButtonRemove(self
, evt
): 
 597         self
.list.Delete(self
.list.GetSelection()) 
 598     def OnUpdateUI(self
, evt
): 
 599         if evt
.GetId() == self
.ID_BUTTON_REMOVE
: 
 600             evt
.Enable(self
.list.GetSelection() != -1) 
 601         elif evt
.GetId() == self
.ID_BUTTON_UP
: 
 602             evt
.Enable(self
.list.GetSelection() > 0) 
 603         elif evt
.GetId() == self
.ID_BUTTON_DOWN
: 
 604             evt
.Enable(self
.list.GetSelection() != -1 and \
 
 605                        self
.list.GetSelection() < self
.list.GetCount() - 1) 
 607 class ParamContent(PPanel
): 
 608     def __init__(self
, parent
, name
): 
 609         PPanel
.__init
__(self
, parent
, name
) 
 610         self
.ID_TEXT_CTRL 
= wx
.NewId() 
 611         self
.ID_BUTTON_EDIT 
= wx
.NewId() 
 612         sizer 
= wx
.BoxSizer() 
 613         self
.text 
= wx
.TextCtrl(self
, self
.ID_TEXT_CTRL
, size
=wx
.Size(200,-1)) 
 614         sizer
.Add(self
.text
, 0, wx
.RIGHT | wx
.ALIGN_CENTER_VERTICAL
, 5) 
 615         self
.button 
= wx
.Button(self
, self
.ID_BUTTON_EDIT
, 'Edit...', size
=buttonSize
) 
 616         sizer
.Add(self
.button
, 0, wx
.ALIGN_CENTER_VERTICAL
) 
 618         self
.textModified 
= False 
 619         wx
.EVT_BUTTON(self
, self
.ID_BUTTON_EDIT
, self
.OnButtonEdit
) 
 620         wx
.EVT_TEXT(self
, self
.ID_TEXT_CTRL
, self
.OnChange
) 
 621     def OnChange(self
, evt
): 
 622         PPanel
.OnChange(self
, evt
) 
 623         self
.textModified 
= True 
 625         if self
.textModified
:           # text has newer value 
 627                 return self
.text
.GetValue().split('|') 
 631     def SetValue(self
, value
): 
 633         if not value
: value 
= [] 
 635         repr_ 
= '|'.join(map(str, value
)) 
 636         self
.text
.SetValue(repr_
)  # update text ctrl 
 638     def OnButtonEdit(self
, evt
): 
 639         if self
.textModified
:           # text has newer value 
 640             self
.value 
= self
.GetValue() 
 641         dlg 
= ContentDialog(self
, self
.value
) 
 642         if dlg
.ShowModal() == wx
.ID_OK
: 
 644             for i 
in range(dlg
.list.GetCount()): 
 645                 value
.append(dlg
.list.GetString(i
)) 
 648             self
.textModified 
= False 
 650     def SetModified(self
, state
=True): 
 651         PPanel
.SetModified(self
, state
) 
 652         self
.textModified 
= False 
 655 class ParamContentCheckList(ParamContent
): 
 656     def __init__(self
, parent
, name
): 
 657         ParamContent
.__init
__(self
, parent
, name
) 
 658     def OnButtonEdit(self
, evt
): 
 659         if self
.textModified
:           # text has newer value 
 660             self
.value 
= self
.GetValue() 
 661         dlg 
= ContentCheckListDialog(self
, self
.value
) 
 662         if dlg
.ShowModal() == wx
.ID_OK
: 
 664             for i 
in range(dlg
.list.GetCount()): 
 665                 value
.append((dlg
.list.GetString(i
), int(dlg
.list.IsChecked(i
)))) 
 668             self
.textModified 
= False 
 670     def SetValue(self
, value
): 
 672         if not value
: value 
= [] 
 674         repr_ 
= '|'.join(map(str,value
)) 
 675         self
.text
.SetValue(repr_
)  # update text ctrl 
 678 class IntListDialog(wx
.Dialog
): 
 679     def __init__(self
, parent
, value
): 
 681         g
.frame
.res
.LoadOnDialog(pre
, parent
, 'DIALOG_INTLIST') 
 683         self
.list = xrc
.XRCCTRL(self
, 'LIST') 
 687             if type(v
) != IntType
: 
 688                 wx
.LogError('Invalid item type') 
 690                 self
.list.Append(str(v
)) 
 691         self
.SetAutoLayout(True) 
 692         self
.GetSizer().Fit(self
) 
 694         self
.spinCtrl 
= xrc
.XRCCTRL(self
, 'SPIN') 
 695         wx
.EVT_BUTTON(self
, xrc
.XRCID('BUTTON_ADD'), self
.OnButtonAdd
) 
 696         self
.ID_BUTTON_REMOVE 
= xrc
.XRCID('BUTTON_REMOVE') 
 697         wx
.EVT_BUTTON(self
, self
.ID_BUTTON_REMOVE
, self
.OnButtonRemove
) 
 698         wx
.EVT_BUTTON(self
, xrc
.XRCID('BUTTON_CLEAR'), self
.OnButtonClear
) 
 699         wx
.EVT_UPDATE_UI(self
, self
.ID_BUTTON_REMOVE
, self
.OnUpdateUI
) 
 700     def OnButtonAdd(self
, evt
): 
 701         # Check that it's unique 
 703             v 
= self
.spinCtrl
.GetValue() 
 704             s 
= str(v
)                  # to be sure 
 705             i 
= self
.list.FindString(s
) 
 706             if i 
== -1:                 # ignore non-unique 
 707                 # Find place to insert 
 709                 for i 
in range(self
.list.GetCount()): 
 710                     if int(self
.list.GetString(i
)) > v
: 
 713                 if found
: self
.list.InsertItems([s
], i
) 
 714                 else: self
.list.Append(s
) 
 716             wx
.LogError('List item is not an int!') 
 717     def OnButtonRemove(self
, evt
): 
 718         self
.list.Delete(self
.list.GetSelection()) 
 719     def OnButtonClear(self
, evt
): 
 721     def OnUpdateUI(self
, evt
): 
 722         if evt
.GetId() == self
.ID_BUTTON_REMOVE
: 
 723             evt
.Enable(self
.list.GetSelection() != -1) 
 726 class ParamIntList(ParamContent
): 
 727     def __init__(self
, parent
, name
): 
 728         ParamContent
.__init
__(self
, parent
, name
) 
 729     def OnButtonEdit(self
, evt
): 
 730         if self
.textModified
:           # text has newer value 
 732                 self
.value 
= map(int, self
.text
.GetValue().split('|')) 
 735         dlg 
= IntListDialog(self
, self
.value
) 
 736         if dlg
.ShowModal() == wx
.ID_OK
: 
 738             for i 
in range(dlg
.list.GetCount()): 
 739                 value
.append(int(dlg
.list.GetString(i
))) 
 742             self
.textModified 
= False 
 746 class RadioBox(PPanel
): 
 747     def __init__(self
, parent
, id, choices
, 
 748                  pos
=wx
.DefaultPosition
, name
='radiobox'): 
 749         PPanel
.__init
__(self
, parent
, name
) 
 750         self
.choices 
= choices
 
 751         topSizer 
= wx
.BoxSizer() 
 753             button 
= wx
.RadioButton(self
, -1, i
, size
=(-1,buttonSize
[1]), name
=i
) 
 754             topSizer
.Add(button
, 0, wx
.RIGHT
, 5) 
 755             wx
.EVT_RADIOBUTTON(self
, button
.GetId(), self
.OnRadioChoice
) 
 756         self
.SetSizer(topSizer
) 
 757     def SetStringSelection(self
, value
): 
 759         for i 
in self
.choices
: 
 760             self
.FindWindowByName(i
).SetValue(i 
== value
) 
 763     def OnRadioChoice(self
, evt
): 
 764         if self
.freeze
: return 
 765         if evt
.GetSelection(): 
 766             self
.value 
= evt
.GetEventObject().GetName() 
 768     def GetStringSelection(self
): 
 771 class ParamBool(RadioBox
): 
 772     values 
= {'yes': '1', 'no': '0'}
 
 773     seulav 
= {'1': 'yes', '0': 'no'}
 
 774     def __init__(self
, parent
, name
): 
 775         RadioBox
.__init
__(self
, parent
, -1, choices
=self
.values
.keys(), name
=name
) 
 777         return self
.values
[self
.GetStringSelection()] 
 778     def SetValue(self
, value
): 
 779         if not value
: value 
= '1' 
 780         self
.SetStringSelection(self
.seulav
[value
]) 
 782 class ParamOrient(RadioBox
): 
 783     values 
= {'horizontal': 'wxHORIZONTAL', 'vertical': 'wxVERTICAL'}
 
 784     seulav 
= {'wxHORIZONTAL': 'horizontal', 'wxVERTICAL': 'vertical'}
 
 785     def __init__(self
, parent
, name
): 
 786         RadioBox
.__init
__(self
, parent
, -1, choices
=self
.values
.keys(), name
=name
) 
 788         return self
.values
[self
.GetStringSelection()] 
 789     def SetValue(self
, value
): 
 790         if not value
: value 
= 'wxHORIZONTAL' 
 791         self
.SetStringSelection(self
.seulav
[value
]) 
 793 class ParamOrientation(RadioBox
): 
 794     values 
= {'horizontal': 'horizontal', 'vertical': 'vertical'}
 
 795     seulav 
= {'horizontal': 'horizontal', 'vertical': 'vertical'}
 
 796     def __init__(self
, parent
, name
): 
 797         RadioBox
.__init
__(self
, parent
, -1, choices
=self
.values
.keys(), name
=name
) 
 799         return self
.values
[self
.GetStringSelection()] 
 800     def SetValue(self
, value
): 
 801         if not value
: value 
= 'vertical' 
 802         self
.SetStringSelection(self
.seulav
[value
]) 
 804 class ParamFile(PPanel
): 
 805     def __init__(self
, parent
, name
): 
 806         PPanel
.__init
__(self
, parent
, name
) 
 807         self
.ID_TEXT_CTRL 
= wx
.NewId() 
 808         self
.ID_BUTTON_BROWSE 
= wx
.NewId() 
 809         sizer 
= wx
.BoxSizer() 
 810         self
.text 
= wx
.TextCtrl(self
, self
.ID_TEXT_CTRL
, size
=wx
.Size(200,-1)) 
 811         sizer
.Add(self
.text
, 0, wx
.RIGHT | wx
.ALIGN_CENTER_VERTICAL
, 5) 
 812         self
.button 
= wx
.Button(self
, self
.ID_BUTTON_BROWSE
, 'Browse...',size
=buttonSize
) 
 813         sizer
.Add(self
.button
, 0, wx
.ALIGN_CENTER_VERTICAL
) 
 815         self
.textModified 
= False 
 816         wx
.EVT_BUTTON(self
, self
.ID_BUTTON_BROWSE
, self
.OnButtonBrowse
) 
 817         wx
.EVT_TEXT(self
, self
.ID_TEXT_CTRL
, self
.OnChange
) 
 818     def OnChange(self
, evt
): 
 819         PPanel
.OnChange(self
, evt
) 
 820         self
.textModified 
= True 
 822         if self
.textModified
:           # text has newer value 
 823             return self
.text
.GetValue() 
 825     def SetValue(self
, value
): 
 828         self
.text
.SetValue(value
)  # update text ctrl 
 830     def OnButtonBrowse(self
, evt
): 
 831         if self
.textModified
:           # text has newer value 
 832             self
.value 
= self
.text
.GetValue() 
 833         dlg 
= wx
.FileDialog(self
, 
 834                            defaultDir 
= os
.path
.abspath(os
.path
.dirname(self
.value
)), 
 835                            defaultFile 
= os
.path
.basename(self
.value
)) 
 836         if dlg
.ShowModal() == wx
.ID_OK
: 
 837             # Get common part of selected path and current 
 839                 curpath 
= os
.path
.abspath(g
.frame
.dataFile
) 
 841                 curpath 
= os
.path
.join(os
.getcwd(), '') 
 842             common 
= os
.path
.commonprefix([curpath
, dlg
.GetPath()]) 
 843             self
.SetValue(dlg
.GetPath()[len(common
):]) 
 845             self
.textModified 
= False 
 848 class ParamBitmap(PPanel
): 
 849     def __init__(self
, parent
, name
): 
 851         g
.frame
.res
.LoadOnPanel(pre
, parent
, 'PANEL_BITMAP') 
 853         self
.modified 
= self
.freeze 
= False 
 854         self
.radio_std 
= xrc
.XRCCTRL(self
, 'RADIO_STD') 
 855         self
.radio_file 
= xrc
.XRCCTRL(self
, 'RADIO_FILE') 
 856         self
.combo 
= xrc
.XRCCTRL(self
, 'COMBO_STD') 
 857         self
.text 
= xrc
.XRCCTRL(self
, 'TEXT_FILE') 
 858         self
.button 
= xrc
.XRCCTRL(self
, 'BUTTON_BROWSE') 
 859         self
.textModified 
= False 
 860         self
.SetAutoLayout(True) 
 861         self
.GetSizer().SetMinSize((260, -1)) 
 862         self
.GetSizer().Fit(self
) 
 863         wx
.EVT_RADIOBUTTON(self
, xrc
.XRCID('RADIO_STD'), self
.OnRadioStd
) 
 864         wx
.EVT_RADIOBUTTON(self
, xrc
.XRCID('RADIO_FILE'), self
.OnRadioFile
) 
 865         wx
.EVT_BUTTON(self
, xrc
.XRCID('BUTTON_BROWSE'), self
.OnButtonBrowse
) 
 866         wx
.EVT_COMBOBOX(self
, xrc
.XRCID('COMBO_STD'), self
.OnCombo
) 
 867         wx
.EVT_TEXT(self
, xrc
.XRCID('COMBO_STD'), self
.OnChange
) 
 868         wx
.EVT_TEXT(self
, xrc
.XRCID('TEXT_FILE'), self
.OnChange
) 
 869     def OnRadioStd(self
, evt
): 
 871         self
.SetValue(['wxART_MISSING_IMAGE','']) 
 872     def OnRadioFile(self
, evt
): 
 874         self
.SetValue(['','']) 
 875     def updateRadios(self
): 
 877             self
.radio_std
.SetValue(True) 
 878             self
.radio_file
.SetValue(False) 
 879             self
.text
.Enable(False) 
 880             self
.button
.Enable(False) 
 881             self
.combo
.Enable(True) 
 883             self
.radio_std
.SetValue(False) 
 884             self
.radio_file
.SetValue(True) 
 885             self
.text
.Enable(True) 
 886             self
.button
.Enable(True) 
 887             self
.combo
.Enable(False) 
 888     def OnChange(self
, evt
): 
 889         PPanel
.OnChange(self
, evt
) 
 890         self
.textModified 
= True 
 891     def OnCombo(self
, evt
): 
 892         PPanel
.OnChange(self
, evt
) 
 893         self
.value
[0] = self
.combo
.GetValue() 
 895         if self
.textModified
:           # text has newer value 
 896             return [self
.combo
.GetValue(), self
.text
.GetValue()] 
 898     def SetValue(self
, value
): 
 901             self
.value 
= ['', ''] 
 904         self
.combo
.SetValue(self
.value
[0]) 
 905         self
.text
.SetValue(self
.value
[1])  # update text ctrl 
 908     def OnButtonBrowse(self
, evt
): 
 909         if self
.textModified
:           # text has newer value 
 910             self
.value
[1] = self
.text
.GetValue() 
 911         dlg 
= wx
.FileDialog(self
, 
 912                            defaultDir 
= os
.path
.abspath(os
.path
.dirname(self
.value
[1])), 
 913                            defaultFile 
= os
.path
.basename(self
.value
[1])) 
 914         if dlg
.ShowModal() == wx
.ID_OK
: 
 915             # Get common part of selected path and current 
 917                 curpath 
= os
.path
.abspath(g
.frame
.dataFile
) 
 919                 curpath 
= os
.path
.join(os
.getcwd(), '') 
 920             common 
= os
.path
.commonprefix([curpath
, dlg
.GetPath()]) 
 921             self
.SetValue(['', dlg
.GetPath()[len(common
):]]) 
 923             self
.textModified 
= False 
 928     'style': ParamStyle
, 'exstyle': ParamExStyle
, 
 929     'pos': ParamPosSize
, 'size': ParamPosSize
, 
 930     'cellpos': ParamPosSize
, 'cellspan': ParamPosSize
, 
 931     'border': ParamUnit
, 'cols': ParamIntNN
, 'rows': ParamIntNN
, 
 932     'vgap': ParamUnit
, 'hgap': ParamUnit
, 
 933     'checkable': ParamBool
, 'checked': ParamBool
, 'radio': ParamBool
, 
 935     'label': ParamMultilineText
, 'title': ParamText
, 'value': ParamText
, 
 936     'content': ParamContent
, 'selection': ParamIntNN
, 
 937     'min': ParamInt
, 'max': ParamInt
, 
 938     'fg': ParamColour
, 'bg': ParamColour
, 'font': ParamFont
, 
 939     'enabled': ParamBool
, 'focused': ParamBool
, 'hidden': ParamBool
, 
 940     'tooltip': ParamText
, 'bitmap': ParamBitmap
, 'icon': ParamBitmap
, 
 941     'encoding': ParamEncoding
, 'borders': ParamUnit
, 
 942     'comment': ParamComment