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 buttonSize 
= (35,-1)    # in dialog units, transformed to pixels in panel ctor 
  30 # Class that can properly disable children 
  31 class PPanel(wx
.Panel
): 
  32     def __init__(self
, parent
, name
): 
  33         wx
.Panel
.__init
__(self
, parent
, -1, name
=name
) 
  34         self
.modified 
= self
.freeze 
= False 
  35     def Enable(self
, value
): 
  36         # Something strange is going on with enable so we make sure... 
  37         for w 
in self
.GetChildren(): 
  39         #wx.Panel.Enable(self, value) 
  40     def SetModified(self
): 
  42         g
.panel
.SetModified(True) 
  43     # Common method to set modified state 
  44     def OnChange(self
, evt
): 
  45         if self
.freeze
: return 
  49 class ParamBinaryOr(PPanel
): 
  50     def __init__(self
, parent
, name
): 
  51         PPanel
.__init
__(self
, parent
, name
) 
  52         self
.ID_TEXT_CTRL 
= wx
.NewId() 
  53         self
.ID_BUTTON_CHOICES 
= wx
.NewId() 
  55         self
.text 
= wx
.TextCtrl(self
, self
.ID_TEXT_CTRL
, size
=wx
.Size(200,-1)) 
  56         sizer
.Add(self
.text
, 0, wx
.RIGHT | wx
.ALIGN_CENTER_VERTICAL
, 5) 
  57         self
.button 
= wx
.Button(self
, self
.ID_BUTTON_CHOICES
, 'Edit...', size
=buttonSize
) 
  58         sizer
.Add(self
.button
, 0, wx
.ALIGN_CENTER_VERTICAL
) 
  59         self
.SetAutoLayout(True) 
  62         wx
.EVT_BUTTON(self
, self
.ID_BUTTON_CHOICES
, self
.OnButtonChoices
) 
  63         wx
.EVT_TEXT(self
, self
.ID_TEXT_CTRL
, self
.OnChange
) 
  65         return self
.text
.GetValue() 
  66     def SetValue(self
, value
): 
  68         self
.text
.SetValue(value
) 
  70     def OnButtonChoices(self
, evt
): 
  71         dlg 
= g
.frame
.res
.LoadDialog(self
, 'DIALOG_CHOICES') 
  72         if self
.GetName() == 'flag':  dlg
.SetTitle('Sizer item flags') 
  73         elif self
.GetName() == 'style':  dlg
.SetTitle('Window styles') 
  74         elif self
.GetName() == 'exstyle':  dlg
.SetTitle('Extended window styles') 
  75         listBox 
= xrc
.XRCCTRL(dlg
, 'CHECKLIST') 
  76         listBox
.InsertItems(self
.values
, 0) 
  77         value 
= map(string
.strip
, self
.text
.GetValue().split('|')) 
  78         if value 
== ['']: value 
= [] 
  82                 listBox
.Check(self
.values
.index(i
)) 
  85                 if self
.equal
.has_key(i
): 
  86                     listBox
.Check(self
.values
.index(self
.equal
[i
])) 
  88                     print 'WARNING: unknown flag: %s: ignored.' % i
 
  90         if dlg
.ShowModal() == wx
.ID_OK
: 
  92             for i 
in range(listBox
.GetCount()): 
  93                 if listBox
.IsChecked(i
): 
  94                     value
.append(self
.values
[i
]) 
  98                 self
.SetValue(reduce(lambda a
,b
: a
+'|'+b
, value
)) 
 104 class ParamFlag(ParamBinaryOr
): 
 105     values 
= ['wxTOP', 'wxBOTTOM', 'wxLEFT', 'wxRIGHT', 'wxALL', 
 106               'wxEXPAND', 'wxGROW', 'wxSHAPED', 'wxSTRETCH_NOT', 
 107               'wxALIGN_CENTRE', 'wxALIGN_LEFT', 'wxALIGN_RIGHT', 
 108               'wxALIGN_TOP', 'wxALIGN_BOTTOM',  
 109               'wxALIGN_CENTRE_VERTICAL', 'wxALIGN_CENTRE_HORIZONTAL',  
 110               'wxADJUST_MINSIZE', 'wxFIXED_MINSIZE' 
 112     equal 
= {'wxALIGN_CENTER': 'wxALIGN_CENTRE', 
 113              'wxALIGN_CENTER_VERTICAL': 'wxALIGN_CENTRE_VERTICAL', 
 114              'wxALIGN_CENTER_HORIZONTAL': 'wxALIGN_CENTRE_HORIZONTAL', 
 115              'wxUP': 'wxTOP', 'wxDOWN': 'wxBOTTOM', 'wxNORTH': 'wxTOP', 
 116              'wxSOUTH': 'wxBOTTOM', 'wxWEST': 'wxLEFT', 'wxEAST': 'wxRIGHT'} 
 117     def __init__(self
, parent
, name
): 
 118         ParamBinaryOr
.__init
__(self
, parent
, name
) 
 120 class ParamNonGenericStyle(ParamBinaryOr
): 
 121     def __init__(self
, parent
, name
): 
 122         self
.values 
= g
.currentXXX
.winStyles
 
 123         ParamBinaryOr
.__init
__(self
, parent
, name
) 
 125 class ParamStyle(ParamBinaryOr
): 
 126     equal 
= {'wxALIGN_CENTER': 'wxALIGN_CENTRE'}
 
 127     def __init__(self
, parent
, name
): 
 128         ParamBinaryOr
.__init
__(self
, parent
, name
) 
 129         self
.valuesSpecific 
= g
.currentXXX
.winStyles
 
 130         if self
.valuesSpecific
:         # override if using specific styles 
 132             self
.valuesGeneric 
= [s 
for s 
in genericStyles
 
 133                                   if s 
not in self
.valuesSpecific
] 
 134             wx
.EVT_BUTTON(self
, self
.ID_BUTTON_CHOICES
, self
.OnButtonChoicesBoth
) 
 136             self
.values 
= genericStyles
 
 137     def OnButtonChoicesBoth(self
, evt
): 
 138         dlg 
= g
.frame
.res
.LoadDialog(self
, 'DIALOG_STYLES') 
 139         listBoxSpecific 
= xrc
.XRCCTRL(dlg
, 'CHECKLIST_SPECIFIC') 
 140         listBoxSpecific
.InsertItems(self
.valuesSpecific
, 0) 
 141         listBoxGeneric 
= xrc
.XRCCTRL(dlg
, 'CHECKLIST_GENERIC') 
 142         listBoxGeneric
.InsertItems(self
.valuesGeneric
, 0) 
 143         value 
= map(string
.strip
, self
.text
.GetValue().split('|')) 
 144         if value 
== ['']: value 
= [] 
 145         # Set specific styles 
 146         value2 
= []                     # collect generic and ignored here 
 149                 listBoxSpecific
.Check(self
.valuesSpecific
.index(i
)) 
 152                 if self
.equal
.has_key(i
): 
 153                     listBoxSpecific
.Check(self
.valuesSpecific
.index(self
.equal
[i
])) 
 157         # Set generic styles, collect non-standart values 
 160                 listBoxGeneric
.Check(self
.valuesGeneric
.index(i
)) 
 163                 if self
.equal
.has_key(i
): 
 164                     listBoxGeneric
.Check(self
.valuesGeneric
.index(self
.equal
[i
])) 
 166                     print 'WARNING: unknown flag: %s: ignored.' % i
 
 168         if dlg
.ShowModal() == wx
.ID_OK
: 
 169             value 
= [self
.valuesSpecific
[i
] 
 170                      for i 
in range(listBoxSpecific
.GetCount()) 
 171                      if listBoxSpecific
.IsChecked(i
)] + \
 
 172                      [self
.valuesGeneric
[i
] 
 173                       for i 
in range(listBoxGeneric
.GetCount()) 
 174                       if listBoxGeneric
.IsChecked(i
)] + ignored
 
 176                 self
.SetValue(reduce(lambda a
,b
: a
+'|'+b
, value
)) 
 182 class ParamExStyle(ParamBinaryOr
): 
 183     def __init__(self
, parent
, name
): 
 185             self
.values 
= g
.currentXXX
.exStyles 
+ genericExStyles
 
 188         ParamBinaryOr
.__init
__(self
, parent
, name
) 
 190 class ParamColour(PPanel
): 
 191     def __init__(self
, parent
, name
): 
 192         PPanel
.__init
__(self
, parent
, name
) 
 193         self
.ID_TEXT_CTRL 
= wx
.NewId() 
 194         self
.ID_BUTTON 
= wx
.NewId() 
 195         sizer 
= wx
.BoxSizer() 
 196         self
.text 
= wx
.TextCtrl(self
, self
.ID_TEXT_CTRL
, size
=(80,-1)) 
 197         sizer
.Add(self
.text
, 0, wx
.ALIGN_CENTER_VERTICAL | wx
.TOP | wx
.BOTTOM
, 2) 
 198         self
.button 
= wx
.Panel(self
, self
.ID_BUTTON
, wx
.DefaultPosition
, wx
.Size(20, 20)) 
 199         sizer
.Add(self
.button
, 0, wx
.ALIGN_CENTER_VERTICAL | wx
.LEFT
, 5) 
 200         self
.SetAutoLayout(True) 
 203         self
.textModified 
= False 
 204         wx
.EVT_PAINT(self
.button
, self
.OnPaintButton
) 
 205         wx
.EVT_TEXT(self
, self
.ID_TEXT_CTRL
, self
.OnChange
) 
 206         wx
.EVT_LEFT_DOWN(self
.button
, self
.OnLeftDown
) 
 208         return self
.text
.GetValue() 
 209     def SetValue(self
, value
): 
 211         if not value
: value 
= '#FFFFFF' 
 212         self
.text
.SetValue(str(value
))  # update text ctrl 
 214             colour 
= wx
.Colour(int(value
[1:3], 16), int(value
[3:5], 16), int(value
[5:7], 16)) 
 215             self
.button
.SetBackgroundColour(colour
) 
 216         except:                         # ignore errors 
 218         self
.button
.Refresh() 
 220     def OnPaintButton(self
, evt
): 
 221         dc 
= wx
.PaintDC(self
.button
) 
 222         dc
.SetBrush(wx
.TRANSPARENT_BRUSH
) 
 223         if self
.IsEnabled(): dc
.SetPen(wx
.BLACK_PEN
) 
 224         else: dc
.SetPen(wx
.GREY_PEN
) 
 225         size 
= self
.button
.GetSize() 
 226         dc
.DrawRectangle(0, 0, size
.width
, size
.height
) 
 227     def OnLeftDown(self
, evt
): 
 228         data 
= wx
.ColourData() 
 229         data
.SetColour(self
.GetValue()) 
 230         dlg 
= wx
.ColourDialog(self
, data
) 
 231         if dlg
.ShowModal() == wx
.ID_OK
: 
 232             self
.SetValue('#%02X%02X%02X' % dlg
.GetColourData().GetColour().Get()) 
 236 ################################################################################ 
 238 # Mapping from wx constants to XML strings 
 239 fontFamiliesWx2Xml 
= {wx
.DEFAULT
: 'default', wx
.DECORATIVE
: 'decorative', 
 240                 wx
.ROMAN
: 'roman', wx
.SCRIPT
: 'script', wx
.SWISS
: 'swiss', 
 242 fontStylesWx2Xml 
= {wx.NORMAL: 'normal', wx.SLANT: 'slant', wx.ITALIC: 'italic'}
 
 243 fontWeightsWx2Xml 
= {wx.NORMAL: 'normal', wx.LIGHT: 'light', wx.BOLD: 'bold'}
 
 246     for k
,v 
in m
.items(): rm
[v
] = k
 
 248 fontFamiliesXml2wx 
= ReverseMap(fontFamiliesWx2Xml
) 
 249 fontStylesXml2wx 
= ReverseMap(fontStylesWx2Xml
) 
 250 fontWeightsXml2wx 
= ReverseMap(fontWeightsWx2Xml
) 
 252 class ParamFont(PPanel
): 
 253     def __init__(self
, parent
, name
): 
 254         PPanel
.__init
__(self
, parent
, name
) 
 255         self
.ID_TEXT_CTRL 
= wx
.NewId() 
 256         self
.ID_BUTTON_SELECT 
= wx
.NewId() 
 257         sizer 
= wx
.BoxSizer() 
 258         self
.text 
= wx
.TextCtrl(self
, self
.ID_TEXT_CTRL
, size
=(200,-1)) 
 259         sizer
.Add(self
.text
, 0, wx
.RIGHT | wx
.ALIGN_CENTER_VERTICAL
, 5) 
 260         self
.button 
= wx
.Button(self
, self
.ID_BUTTON_SELECT
, 'Select...', size
=buttonSize
) 
 261         sizer
.Add(self
.button
, 0, wx
.ALIGN_CENTER_VERTICAL
) 
 262         self
.SetAutoLayout(True) 
 265         self
.textModified 
= False 
 266         wx
.EVT_BUTTON(self
, self
.ID_BUTTON_SELECT
, self
.OnButtonSelect
) 
 267         wx
.EVT_TEXT(self
, self
.ID_TEXT_CTRL
, self
.OnChange
) 
 268     def OnChange(self
, evt
): 
 269         PPanel
.OnChange(self
, evt
) 
 270         self
.textModified 
= True 
 271     def _defaultValue(self
): 
 272         return [`g
._sysFont
.GetPointSize()`
, 'default', 'normal', 'normal', '0', '', ''] 
 274         if self
.textModified
:           # text has newer value 
 276                 return eval(self
.text
.GetValue()) 
 278                 wx
.LogError('Syntax error in parameter value: ' + self
.GetName()) 
 279                 return self
._defaultValue
() 
 281     def SetValue(self
, value
): 
 282         self
.freeze 
= True              # disable other handlers 
 283         if not value
: value 
= self
._defaultValue
() 
 285         self
.text
.SetValue(str(value
))  # update text ctrl 
 287     def OnButtonSelect(self
, evt
): 
 288         if self
.textModified
:           # text has newer value 
 290                 self
.value 
= eval(self
.text
.GetValue()) 
 292                 wx
.LogError('Syntax error in parameter value: ' + self
.GetName()) 
 293                 self
.value 
= self
._defaultValue
() 
 296         size 
= g
._sysFont
.GetPointSize() 
 298         style 
= weight 
= wx
.NORMAL
 
 301         enc 
= wx
.FONTENCODING_DEFAULT
 
 302         # Fall back to default if exceptions 
 305             try: size 
= int(self
.value
[0]) 
 306             except ValueError: error 
= True; wx
.LogError('Invalid size specification') 
 307             try: family 
= fontFamiliesXml2wx
[self
.value
[1]] 
 308             except KeyError: error 
= True; wx
.LogError('Invalid family specification') 
 309             try: style 
= fontStylesXml2wx
[self
.value
[2]] 
 310             except KeyError: error 
= True; wx
.LogError('Invalid style specification') 
 311             try: weight 
= fontWeightsXml2wx
[self
.value
[3]] 
 312             except KeyError: error 
= True; wx
.LogError('Invalid weight specification') 
 313             try: underlined 
= bool(self
.value
[4]) 
 314             except ValueError: error 
= True; wx
.LogError('Invalid underlined flag specification') 
 318         mapper 
= wx
.FontMapper() 
 319         if not self
.value
[6]: enc 
= mapper
.CharsetToEncoding(self
.value
[6]) 
 321         if error
: wx
.LogError('Invalid font specification') 
 322         if enc 
== wx
.FONTENCODING_DEFAULT
: enc 
= wx
.FONTENCODING_SYSTEM
 
 323         font 
= wx
.Font(size
, family
, style
, weight
, underlined
, face
, enc
) 
 325         data
.SetInitialFont(font
) 
 326         dlg 
= wx
.FontDialog(self
, data
) 
 327         if dlg
.ShowModal() == wx
.ID_OK
: 
 328             font 
= dlg
.GetFontData().GetChosenFont() 
 329             print font
.GetEncoding() 
 330             if font
.GetEncoding() == wx
.FONTENCODING_SYSTEM
: 
 333                 encName 
= wx
.FontMapper
.GetEncodingName(font
.GetEncoding()).encode() 
 334             value 
= [str(font
.GetPointSize()), 
 335                      fontFamiliesWx2Xml
.get(font
.GetFamily(), "default"), 
 336                      fontStylesWx2Xml
.get(font
.GetStyle(), "normal"), 
 337                      fontWeightsWx2Xml
.get(font
.GetWeight(), "normal"), 
 338                      str(int(font
.GetUnderlined())), 
 339                      font
.GetFaceName().encode(), 
 344             self
.textModified 
= False 
 347 ################################################################################ 
 349 class ParamInt(PPanel
): 
 350     def __init__(self
, parent
, name
): 
 351         PPanel
.__init
__(self
, parent
, name
) 
 352         self
.ID_SPIN_CTRL 
= wx
.NewId() 
 353         sizer 
= wx
.BoxSizer() 
 354         self
.spin 
= wx
.SpinCtrl(self
, self
.ID_SPIN_CTRL
, size
=(60,-1)) 
 355         self
.spin
.SetRange(-2147483648, 2147483647) # min/max integers 
 357         self
.SetAutoLayout(True) 
 360         wx
.EVT_SPINCTRL(self
, self
.ID_SPIN_CTRL
, self
.OnChange
) 
 362         return str(self
.spin
.GetValue()) 
 363     def SetValue(self
, value
): 
 365         if not value
: value 
= 0 
 366         self
.spin
.SetValue(int(value
)) 
 369 # Non-negative number 
 370 class ParamIntNN(PPanel
): 
 371     def __init__(self
, parent
, name
): 
 372         PPanel
.__init
__(self
, parent
, name
) 
 373         self
.ID_SPIN_CTRL 
= wx
.NewId() 
 374         sizer 
= wx
.BoxSizer() 
 375         self
.spin 
= wx
.SpinCtrl(self
, self
.ID_SPIN_CTRL
, size
=(60,-1)) 
 376         self
.spin
.SetRange(0, 10000) # min/max integers 
 378         self
.SetAutoLayout(True) 
 381         wx
.EVT_SPINCTRL(self
, self
.ID_SPIN_CTRL
, self
.OnChange
) 
 383         return str(self
.spin
.GetValue()) 
 384     def SetValue(self
, value
): 
 386         if not value
: value 
= 0 
 387         self
.spin
.SetValue(int(value
)) 
 390 # Same as int but allows dialog units (XXXd) 
 391 class ParamUnit(PPanel
): 
 392     def __init__(self
, parent
, name
): 
 393         PPanel
.__init
__(self
, parent
, name
) 
 394         self
.ID_TEXT_CTRL 
= wx
.NewId() 
 395         self
.ID_SPIN_BUTTON 
= wx
.NewId() 
 396         sizer 
= wx
.BoxSizer(wx
.HORIZONTAL
) 
 397         self
.spin 
= wx
.SpinButton(self
, self
.ID_SPIN_BUTTON
, style 
= wx
.SP_VERTICAL
, size
=(-1,1)) 
 398         textW 
= 60 - self
.spin
.GetSize()[0] 
 399         self
.text 
= wx
.TextCtrl(self
, self
.ID_TEXT_CTRL
, size
=(textW
,-1)) 
 400         self
.spin
.SetRange(-10000, 10000) 
 401         sizer
.Add(self
.text
, 0, wx
.EXPAND
) 
 402         sizer
.Add(self
.spin
, 0, wx
.EXPAND
) 
 403         #sizer.SetMinSize((50,-1)) 
 404         self
.SetAutoLayout(True) 
 407         wx
.EVT_SPIN_UP(self
, self
.ID_SPIN_BUTTON
, self
.OnSpinUp
) 
 408         wx
.EVT_SPIN_DOWN(self
, self
.ID_SPIN_BUTTON
, self
.OnSpinDown
) 
 410         return self
.text
.GetValue() 
 411     def SetValue(self
, value
): 
 413         if not value
: value 
= '0' 
 414         self
.text
.SetValue(value
) 
 417         # Check if we are working with dialog units 
 418         value 
= self
.text
.GetValue() 
 420         if value
[-1].upper() == 'D': 
 424             intValue 
= int(value
) + x
 
 425             self
.spin
.SetValue(intValue
) 
 426             self
.text
.SetValue(str(intValue
) + units
) 
 429             # !!! Strange, if I use wx.LogWarning, event is re-generated 
 430             print 'incorrect unit format' 
 431     def OnSpinUp(self
, evt
): 
 433     def OnSpinDown(self
, evt
): 
 436 class ParamMultilineText(PPanel
): 
 437     def __init__(self
, parent
, name
, textWidth
=-1): 
 438         PPanel
.__init
__(self
, parent
, name
) 
 439         self
.ID_TEXT_CTRL 
= wx
.NewId() 
 440         self
.ID_BUTTON_EDIT 
= wx
.NewId() 
 441         sizer 
= wx
.BoxSizer() 
 442         self
.text 
= wx
.TextCtrl(self
, self
.ID_TEXT_CTRL
, size
=wx
.Size(200,-1)) 
 443         sizer
.Add(self
.text
, 0, wx
.RIGHT | wx
.ALIGN_CENTER_VERTICAL
, 5) 
 444         self
.button 
= wx
.Button(self
, self
.ID_BUTTON_EDIT
, 'Edit...', size
=buttonSize
) 
 445         sizer
.Add(self
.button
, 0, wx
.ALIGN_CENTER_VERTICAL
) 
 446         self
.SetAutoLayout(True) 
 449         wx
.EVT_BUTTON(self
, self
.ID_BUTTON_EDIT
, self
.OnButtonEdit
) 
 450         wx
.EVT_TEXT(self
, self
.ID_TEXT_CTRL
, self
.OnChange
) 
 452         return self
.text
.GetValue() 
 453     def SetValue(self
, value
): 
 454         self
.freeze 
= True              # disable other handlers 
 455         self
.text
.SetValue(value
) 
 456         self
.freeze 
= False             # disable other handlers 
 457     def OnButtonEdit(self
, evt
): 
 458         dlg 
= g
.frame
.res
.LoadDialog(self
, 'DIALOG_TEXT') 
 459         textCtrl 
= xrc
.XRCCTRL(dlg
, 'TEXT') 
 460         textCtrl
.SetValue(self
.text
.GetValue()) 
 461         if dlg
.ShowModal() == wx
.ID_OK
: 
 462             self
.text
.SetValue(textCtrl
.GetValue()) 
 466 class ParamText(PPanel
): 
 467     def __init__(self
, parent
, name
, textWidth
=-1): 
 468         PPanel
.__init
__(self
, parent
, name
) 
 469         self
.ID_TEXT_CTRL 
= wx
.NewId() 
 470         # We use sizer even here to have the same size of text control 
 471         sizer 
= wx
.BoxSizer() 
 472         self
.text 
= wx
.TextCtrl(self
, self
.ID_TEXT_CTRL
, size
=wx
.Size(textWidth
,-1)) 
 473         if textWidth 
== -1: option 
= 1 
 475         sizer
.Add(self
.text
, option
, wx
.ALIGN_CENTER_VERTICAL | wx
.TOP | wx
.BOTTOM
, 2) 
 476         self
.SetAutoLayout(True) 
 479         wx
.EVT_TEXT(self
, self
.ID_TEXT_CTRL
, self
.OnChange
) 
 481         return self
.text
.GetValue() 
 482     def SetValue(self
, value
): 
 483         self
.freeze 
= True              # disable other handlers 
 484         self
.text
.SetValue(value
) 
 485         self
.freeze 
= False             # disable other handlers 
 487 class ParamAccel(ParamText
): 
 488     def __init__(self
, parent
, name
): 
 489         ParamText
.__init
__(self
, parent
, name
, 100) 
 491 class ParamPosSize(ParamText
): 
 492     def __init__(self
, parent
, name
): 
 493         ParamText
.__init
__(self
, parent
, name
, 80) 
 495 class ParamLabel(ParamText
): 
 496     def __init__(self
, parent
, name
): 
 497         ParamText
.__init
__(self
, parent
, name
, 200) 
 499 class ParamEncoding(ParamText
): 
 500     def __init__(self
, parent
, name
): 
 501         ParamText
.__init
__(self
, parent
, name
, 100) 
 503 class ContentDialog(wx
.Dialog
): 
 504     def __init__(self
, parent
, value
): 
 507         g
.frame
.res
.LoadOnDialog(pre
, parent
, 'DIALOG_CONTENT') 
 509         self
.list = xrc
.XRCCTRL(self
, 'LIST') 
 513         self
.SetAutoLayout(True) 
 514         self
.GetSizer().Fit(self
) 
 516         self
.ID_BUTTON_APPEND 
= xrc
.XRCID('BUTTON_APPEND') 
 517         self
.ID_BUTTON_REMOVE 
= xrc
.XRCID('BUTTON_REMOVE') 
 518         self
.ID_BUTTON_UP 
= xrc
.XRCID('BUTTON_UP') 
 519         self
.ID_BUTTON_DOWN 
= xrc
.XRCID('BUTTON_DOWN') 
 520         wx
.EVT_BUTTON(self
, self
.ID_BUTTON_UP
, self
.OnButtonUp
) 
 521         wx
.EVT_BUTTON(self
, self
.ID_BUTTON_DOWN
, self
.OnButtonDown
) 
 522         wx
.EVT_BUTTON(self
, self
.ID_BUTTON_APPEND
, self
.OnButtonAppend
) 
 523         wx
.EVT_BUTTON(self
, self
.ID_BUTTON_REMOVE
, self
.OnButtonRemove
) 
 524         wx
.EVT_UPDATE_UI(self
, self
.ID_BUTTON_UP
, self
.OnUpdateUI
) 
 525         wx
.EVT_UPDATE_UI(self
, self
.ID_BUTTON_DOWN
, self
.OnUpdateUI
) 
 526         wx
.EVT_UPDATE_UI(self
, self
.ID_BUTTON_REMOVE
, self
.OnUpdateUI
) 
 527     def OnButtonUp(self
, evt
): 
 528         i 
= self
.list.GetSelection() 
 529         str = self
.list.GetString(i
) 
 531         self
.list.InsertItems([str], i
-1) 
 532         self
.list.SetSelection(i
-1) 
 533     def OnButtonDown(self
, evt
): 
 534         i 
= self
.list.GetSelection() 
 535         str = self
.list.GetString(i
) 
 537         self
.list.InsertItems([str], i
+1) 
 538         self
.list.SetSelection(i
+1) 
 539     def OnButtonAppend(self
, evt
): 
 540         str = wx
.GetTextFromUser('Enter new item:', 'Append', '', self
) 
 541         self
.list.Append(str) 
 542     def OnButtonRemove(self
, evt
): 
 543         self
.list.Delete(self
.list.GetSelection()) 
 544     def OnUpdateUI(self
, evt
): 
 545         if evt
.GetId() == self
.ID_BUTTON_REMOVE
: 
 546             evt
.Enable(self
.list.GetSelection() != -1) 
 547         elif evt
.GetId() == self
.ID_BUTTON_UP
: 
 548             evt
.Enable(self
.list.GetSelection() > 0) 
 549         elif evt
.GetId() == self
.ID_BUTTON_DOWN
: 
 550             evt
.Enable(self
.list.GetSelection() != -1 and \
 
 551                        self
.list.GetSelection() < self
.list.GetCount() - 1) 
 553 class ContentCheckListDialog(wx
.Dialog
): 
 554     def __init__(self
, parent
, value
): 
 556         g
.frame
.res
.LoadOnDialog(pre
, parent
, 'DIALOG_CONTENT_CHECKLIST') 
 558         self
.list = xrc
.XRCCTRL(self
, 'CHECKLIST') 
 563             self
.list.Check(i
, ch
) 
 565         self
.SetAutoLayout(True) 
 566         self
.GetSizer().Fit(self
) 
 568         self
.ID_BUTTON_APPEND 
= xrc
.XRCID('BUTTON_APPEND') 
 569         self
.ID_BUTTON_REMOVE 
= xrc
.XRCID('BUTTON_REMOVE') 
 570         self
.ID_BUTTON_UP 
= xrc
.XRCID('BUTTON_UP') 
 571         self
.ID_BUTTON_DOWN 
= xrc
.XRCID('BUTTON_DOWN') 
 572         wx
.EVT_CHECKLISTBOX(self
, self
.list.GetId(), self
.OnCheck
) 
 573         wx
.EVT_BUTTON(self
, self
.ID_BUTTON_UP
, self
.OnButtonUp
) 
 574         wx
.EVT_BUTTON(self
, self
.ID_BUTTON_DOWN
, self
.OnButtonDown
) 
 575         wx
.EVT_BUTTON(self
, self
.ID_BUTTON_APPEND
, self
.OnButtonAppend
) 
 576         wx
.EVT_BUTTON(self
, self
.ID_BUTTON_REMOVE
, self
.OnButtonRemove
) 
 577         wx
.EVT_UPDATE_UI(self
, self
.ID_BUTTON_UP
, self
.OnUpdateUI
) 
 578         wx
.EVT_UPDATE_UI(self
, self
.ID_BUTTON_DOWN
, self
.OnUpdateUI
) 
 579         wx
.EVT_UPDATE_UI(self
, self
.ID_BUTTON_REMOVE
, self
.OnUpdateUI
) 
 580     def OnCheck(self
, evt
): 
 581         # !!! Wrong wxGTK (wxMSW?) behavior: toggling selection if checking 
 582         self
.list.Deselect(evt
.GetSelection()) 
 583     def OnButtonUp(self
, evt
): 
 584         i 
= self
.list.GetSelection() 
 585         str, ch 
= self
.list.GetString(i
), self
.list.IsChecked(i
) 
 587         self
.list.InsertItems([str], i
-1) 
 588         self
.list.Check(i
-1, ch
) 
 589         self
.list.SetSelection(i
-1) 
 590     def OnButtonDown(self
, evt
): 
 591         i 
= self
.list.GetSelection() 
 592         str, ch 
= self
.list.GetString(i
), self
.list.IsChecked(i
) 
 594         self
.list.InsertItems([str], i
+1) 
 595         self
.list.Check(i
+1, ch
) 
 596         self
.list.SetSelection(i
+1) 
 597     def OnButtonAppend(self
, evt
): 
 598         str = wx
.GetTextFromUser('Enter new item:', 'Append', '', self
) 
 599         self
.list.Append(str) 
 600     def OnButtonRemove(self
, evt
): 
 601         self
.list.Delete(self
.list.GetSelection()) 
 602     def OnUpdateUI(self
, evt
): 
 603         if evt
.GetId() == self
.ID_BUTTON_REMOVE
: 
 604             evt
.Enable(self
.list.GetSelection() != -1) 
 605         elif evt
.GetId() == self
.ID_BUTTON_UP
: 
 606             evt
.Enable(self
.list.GetSelection() > 0) 
 607         elif evt
.GetId() == self
.ID_BUTTON_DOWN
: 
 608             evt
.Enable(self
.list.GetSelection() != -1 and \
 
 609                        self
.list.GetSelection() < self
.list.GetCount() - 1) 
 611 class ParamContent(PPanel
): 
 612     def __init__(self
, parent
, name
): 
 613         PPanel
.__init
__(self
, parent
, name
) 
 614         self
.ID_TEXT_CTRL 
= wx
.NewId() 
 615         self
.ID_BUTTON_EDIT 
= wx
.NewId() 
 616         sizer 
= wx
.BoxSizer() 
 617         self
.text 
= wx
.TextCtrl(self
, self
.ID_TEXT_CTRL
, size
=wx
.Size(200,-1)) 
 618         sizer
.Add(self
.text
, 0, wx
.RIGHT | wx
.ALIGN_CENTER_VERTICAL
, 5) 
 619         self
.button 
= wx
.Button(self
, self
.ID_BUTTON_EDIT
, 'Edit...', size
=buttonSize
) 
 620         sizer
.Add(self
.button
, 0, wx
.ALIGN_CENTER_VERTICAL
) 
 621         self
.SetAutoLayout(True) 
 624         self
.textModified 
= False 
 625         wx
.EVT_BUTTON(self
, self
.ID_BUTTON_EDIT
, self
.OnButtonEdit
) 
 626         wx
.EVT_TEXT(self
, self
.ID_TEXT_CTRL
, self
.OnChange
) 
 627     def OnChange(self
, evt
): 
 628         PPanel
.OnChange(self
, evt
) 
 629         self
.textModified 
= True 
 631         if self
.textModified
:           # text has newer value 
 633                 return self
.text
.GetValue().split('|') 
 635                 wx
.LogError('Syntax error in parameter value: ' + self
.GetName()) 
 638     def SetValue(self
, value
): 
 640         if not value
: value 
= [] 
 643             repr_ 
= reduce(lambda a
,b
: '%s|%s' % (a
,b
), value
) 
 646         self
.text
.SetValue(repr_
)  # update text ctrl 
 648     def OnButtonEdit(self
, evt
): 
 649         if self
.textModified
:           # text has newer value 
 650             self
.value 
= self
.GetValue() 
 651         dlg 
= ContentDialog(self
, self
.value
) 
 652         if dlg
.ShowModal() == wx
.ID_OK
: 
 654             for i 
in range(dlg
.list.GetCount()): 
 655                 value
.append(dlg
.list.GetString(i
)) 
 658             self
.textModified 
= False 
 662 class ParamContentCheckList(ParamContent
): 
 663     def __init__(self
, parent
, name
): 
 664         ParamContent
.__init
__(self
, parent
, name
) 
 665     def OnButtonEdit(self
, evt
): 
 666         if self
.textModified
:           # text has newer value 
 667             self
.value 
= self
.GetValue() 
 668         dlg 
= ContentCheckListDialog(self
, self
.value
) 
 669         if dlg
.ShowModal() == wx
.ID_OK
: 
 671             for i 
in range(dlg
.list.GetCount()): 
 672                 value
.append((dlg
.list.GetString(i
), int(dlg
.list.IsChecked(i
)))) 
 675             self
.textModified 
= False 
 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 
= eval(self
.text
.GetValue()) 
 734                 wx
.LogError('Syntax error in parameter value: ' + self
.GetName()) 
 736         dlg 
= IntListDialog(self
, self
.value
) 
 737         if dlg
.ShowModal() == wx
.ID_OK
: 
 739             for i 
in range(dlg
.list.GetCount()): 
 740                 value
.append(int(dlg
.list.GetString(i
))) 
 743             self
.textModified 
= False 
 747 class RadioBox(PPanel
): 
 748     def __init__(self
, parent
, id, choices
, 
 749                  pos
=wx
.DefaultPosition
, name
='radiobox'): 
 750         PPanel
.__init
__(self
, parent
, name
) 
 751         self
.choices 
= choices
 
 752         topSizer 
= wx
.BoxSizer() 
 754             button 
= wx
.RadioButton(self
, -1, i
, size
=(-1,buttonSize
[1]), name
=i
) 
 755             topSizer
.Add(button
, 0, wx
.RIGHT
, 5) 
 756             wx
.EVT_RADIOBUTTON(self
, button
.GetId(), self
.OnRadioChoice
) 
 757         self
.SetAutoLayout(True) 
 758         self
.SetSizer(topSizer
) 
 760     def SetStringSelection(self
, value
): 
 762         for i 
in self
.choices
: 
 763             self
.FindWindowByName(i
).SetValue(i 
== value
) 
 766     def OnRadioChoice(self
, evt
): 
 767         if self
.freeze
: return 
 768         if evt
.GetSelection(): 
 769             self
.value 
= evt
.GetEventObject().GetName() 
 771     def GetStringSelection(self
): 
 774 class ParamBool(RadioBox
): 
 775     values 
= {'yes': '1', 'no': '0'}
 
 776     seulav 
= {'1': 'yes', '0': 'no'}
 
 777     def __init__(self
, parent
, name
): 
 778         RadioBox
.__init
__(self
, parent
, -1, choices
=self
.values
.keys(), name
=name
) 
 780         return self
.values
[self
.GetStringSelection()] 
 781     def SetValue(self
, value
): 
 782         if not value
: value 
= '1' 
 783         self
.SetStringSelection(self
.seulav
[value
]) 
 785 class ParamOrient(RadioBox
): 
 786     values 
= {'horizontal': 'wxHORIZONTAL', 'vertical': 'wxVERTICAL'}
 
 787     seulav 
= {'wxHORIZONTAL': 'horizontal', 'wxVERTICAL': 'vertical'}
 
 788     def __init__(self
, parent
, name
): 
 789         RadioBox
.__init
__(self
, parent
, -1, choices
=self
.values
.keys(), name
=name
) 
 791         return self
.values
[self
.GetStringSelection()] 
 792     def SetValue(self
, value
): 
 793         if not value
: value 
= 'wxHORIZONTAL' 
 794         self
.SetStringSelection(self
.seulav
[value
]) 
 796 class ParamOrientation(RadioBox
): 
 797     values 
= {'horizontal': 'horizontal', 'vertical': 'vertical'}
 
 798     seulav 
= {'horizontal': 'horizontal', 'vertical': 'vertical'}
 
 799     def __init__(self
, parent
, name
): 
 800         RadioBox
.__init
__(self
, parent
, -1, choices
=self
.values
.keys(), name
=name
) 
 802         return self
.values
[self
.GetStringSelection()] 
 803     def SetValue(self
, value
): 
 804         if not value
: value 
= 'vertical' 
 805         self
.SetStringSelection(self
.seulav
[value
]) 
 807 class ParamFile(PPanel
): 
 808     def __init__(self
, parent
, name
): 
 809         PPanel
.__init
__(self
, parent
, name
) 
 810         self
.ID_TEXT_CTRL 
= wx
.NewId() 
 811         self
.ID_BUTTON_BROWSE 
= wx
.NewId() 
 812         sizer 
= wx
.BoxSizer() 
 813         self
.text 
= wx
.TextCtrl(self
, self
.ID_TEXT_CTRL
, size
=wx
.Size(200,-1)) 
 814         sizer
.Add(self
.text
, 0, wx
.RIGHT | wx
.ALIGN_CENTER_VERTICAL
, 5) 
 815         self
.button 
= wx
.Button(self
, self
.ID_BUTTON_BROWSE
, 'Browse...',size
=buttonSize
) 
 816         sizer
.Add(self
.button
, 0, wx
.ALIGN_CENTER_VERTICAL
) 
 817         self
.SetAutoLayout(True) 
 820         self
.textModified 
= False 
 821         wx
.EVT_BUTTON(self
, self
.ID_BUTTON_BROWSE
, self
.OnButtonBrowse
) 
 822         wx
.EVT_TEXT(self
, self
.ID_TEXT_CTRL
, self
.OnChange
) 
 823     def OnChange(self
, evt
): 
 824         PPanel
.OnChange(self
, evt
) 
 825         self
.textModified 
= True 
 827         if self
.textModified
:           # text has newer value 
 828             return self
.text
.GetValue() 
 830     def SetValue(self
, value
): 
 833         self
.text
.SetValue(value
)  # update text ctrl 
 835     def OnButtonBrowse(self
, evt
): 
 836         if self
.textModified
:           # text has newer value 
 837             self
.value 
= self
.text
.GetValue() 
 838         dlg 
= wx
.FileDialog(self
, 
 839                            defaultDir 
= os
.path
.abspath(os
.path
.dirname(self
.value
)), 
 840                            defaultFile 
= os
.path
.basename(self
.value
)) 
 841         if dlg
.ShowModal() == wx
.ID_OK
: 
 842             # Get common part of selected path and current 
 844                 curpath 
= os
.path
.abspath(g
.frame
.dataFile
) 
 846                 curpath 
= os
.path
.join(os
.getcwd(), '') 
 847             common 
= os
.path
.commonprefix([curpath
, dlg
.GetPath()]) 
 848             self
.SetValue(dlg
.GetPath()[len(common
):]) 
 850             self
.textModified 
= False 
 853 class ParamBitmap(PPanel
): 
 854     def __init__(self
, parent
, name
): 
 856         g
.frame
.res
.LoadOnPanel(pre
, parent
, 'PANEL_BITMAP') 
 858         self
.modified 
= self
.freeze 
= False 
 859         self
.radio_std 
= xrc
.XRCCTRL(self
, 'RADIO_STD') 
 860         self
.radio_file 
= xrc
.XRCCTRL(self
, 'RADIO_FILE') 
 861         self
.combo 
= xrc
.XRCCTRL(self
, 'COMBO_STD') 
 862         self
.text 
= xrc
.XRCCTRL(self
, 'TEXT_FILE') 
 863         self
.button 
= xrc
.XRCCTRL(self
, 'BUTTON_BROWSE') 
 864         self
.textModified 
= False 
 865         self
.SetAutoLayout(True) 
 866         self
.GetSizer().SetMinSize((260, -1)) 
 867         self
.GetSizer().Fit(self
) 
 868         wx
.EVT_RADIOBUTTON(self
, xrc
.XRCID('RADIO_STD'), self
.OnRadioStd
) 
 869         wx
.EVT_RADIOBUTTON(self
, xrc
.XRCID('RADIO_FILE'), self
.OnRadioFile
) 
 870         wx
.EVT_BUTTON(self
, xrc
.XRCID('BUTTON_BROWSE'), self
.OnButtonBrowse
) 
 871         wx
.EVT_COMBOBOX(self
, xrc
.XRCID('COMBO_STD'), self
.OnCombo
) 
 872         wx
.EVT_TEXT(self
, xrc
.XRCID('COMBO_STD'), self
.OnChange
) 
 873         wx
.EVT_TEXT(self
, xrc
.XRCID('TEXT_FILE'), self
.OnChange
) 
 874     def OnRadioStd(self
, evt
): 
 876         self
.SetValue(['wxART_MISSING_IMAGE','']) 
 877     def OnRadioFile(self
, evt
): 
 879         self
.SetValue(['','']) 
 880     def updateRadios(self
): 
 882             self
.radio_std
.SetValue(True) 
 883             self
.radio_file
.SetValue(False) 
 884             self
.text
.Enable(False) 
 885             self
.button
.Enable(False) 
 886             self
.combo
.Enable(True) 
 888             self
.radio_std
.SetValue(False) 
 889             self
.radio_file
.SetValue(True) 
 890             self
.text
.Enable(True) 
 891             self
.button
.Enable(True) 
 892             self
.combo
.Enable(False) 
 893     def OnChange(self
, evt
): 
 894         PPanel
.OnChange(self
, evt
) 
 895         self
.textModified 
= True 
 896     def OnCombo(self
, evt
): 
 897         PPanel
.OnChange(self
, evt
) 
 898         self
.value
[0] = self
.combo
.GetValue() 
 900         if self
.textModified
:           # text has newer value 
 901             return [self
.combo
.GetValue(), self
.text
.GetValue()] 
 903     def SetValue(self
, value
): 
 906             self
.value 
= ['', ''] 
 909         self
.combo
.SetValue(self
.value
[0]) 
 910         self
.text
.SetValue(self
.value
[1])  # update text ctrl 
 913     def OnButtonBrowse(self
, evt
): 
 914         if self
.textModified
:           # text has newer value 
 915             self
.value
[1] = self
.text
.GetValue() 
 916         dlg 
= wx
.FileDialog(self
, 
 917                            defaultDir 
= os
.path
.abspath(os
.path
.dirname(self
.value
[1])), 
 918                            defaultFile 
= os
.path
.basename(self
.value
[1])) 
 919         if dlg
.ShowModal() == wx
.ID_OK
: 
 920             # Get common part of selected path and current 
 922                 curpath 
= os
.path
.abspath(g
.frame
.dataFile
) 
 924                 curpath 
= os
.path
.join(os
.getcwd(), '') 
 925             common 
= os
.path
.commonprefix([curpath
, dlg
.GetPath()]) 
 926             self
.SetValue(['', dlg
.GetPath()[len(common
):]]) 
 928             self
.textModified 
= False 
 933     'style': ParamStyle
, 'exstyle': ParamExStyle
, 
 934     'pos': ParamPosSize
, 'size': ParamPosSize
, 
 935     'cellpos': ParamPosSize
, 'cellspan': ParamPosSize
, 
 936     'border': ParamUnit
, 'cols': ParamIntNN
, 'rows': ParamIntNN
, 
 937     'vgap': ParamUnit
, 'hgap': ParamUnit
, 
 938     'checkable': ParamBool
, 'checked': ParamBool
, 'radio': ParamBool
, 
 940     'label': ParamMultilineText
, 'title': ParamText
, 'value': ParamText
, 
 941     'content': ParamContent
, 'selection': ParamIntNN
, 
 942     'min': ParamInt
, 'max': ParamInt
, 
 943     'fg': ParamColour
, 'bg': ParamColour
, 'font': ParamFont
, 
 944     'enabled': ParamBool
, 'focused': ParamBool
, 'hidden': ParamBool
, 
 945     'tooltip': ParamText
, 'bitmap': ParamBitmap
, 'icon': ParamBitmap
, 
 946     'encoding': ParamEncoding
, 'borders': ParamUnit