2 # Purpose:      Classes for parameter introduction 
   3 # Author:       Roman Rolinsky <rolinsky@mema.ucl.ac.be> 
  11 from wxPython
.xrc 
import * 
  14     'wxSIMPLE_BORDER', 'wxSUNKEN_BORDER', 'wxDOUBLE_BORDER', 
  15     'wxRAISED_BORDER', 'wxSTATIC_BORDER', 'wxNO_BORDER', 
  16     'wxCLIP_CHILDREN', 'wxTRANSPARENT_WINDOW', 'wxWANTS_CHARS', 
  17     'wxNO_FULL_REPAINT_ON_RESIZE', 'wxFULL_REPAINT_ON_RESIZE' 
  21     'wxWS_EX_VALIDATE_RECURSIVELY', 
  22     'wxWS_EX_BLOCK_EVENTS', 
  24     'wxFRAME_EX_CONTEXTHELP', 
  25     'wxWS_EX_PROCESS_IDLE', 
  26     'wxWS_EX_PROCESS_UI_UPDATES' 
  29 buttonSize 
= (35,-1)    # in dialog units, transformed to pixels in panel ctor 
  31 # Class that can properly disable children 
  32 class PPanel(wxPanel
): 
  33     def __init__(self
, parent
, name
): 
  34         wxPanel
.__init
__(self
, parent
, -1, name
=name
) 
  35         self
.modified 
= self
.freeze 
= False 
  36     def Enable(self
, value
): 
  37         # Something strange is going on with enable so we make sure... 
  38         for w 
in self
.GetChildren(): 
  40         #wxPanel.Enable(self, value) 
  41     def SetModified(self
): 
  43         g
.panel
.SetModified(True) 
  44     # Common method to set modified state 
  45     def OnChange(self
, evt
): 
  46         if self
.freeze
: return 
  50 class ParamBinaryOr(PPanel
): 
  51     def __init__(self
, parent
, name
): 
  52         PPanel
.__init
__(self
, parent
, name
) 
  53         self
.ID_TEXT_CTRL 
= wxNewId() 
  54         self
.ID_BUTTON_CHOICES 
= wxNewId() 
  56         self
.text 
= wxTextCtrl(self
, self
.ID_TEXT_CTRL
, size
=wxSize(200,-1)) 
  57         sizer
.Add(self
.text
, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL
, 5) 
  58         self
.button 
= wxButton(self
, self
.ID_BUTTON_CHOICES
, 'Edit...', size
=buttonSize
) 
  59         sizer
.Add(self
.button
, 0, wxALIGN_CENTER_VERTICAL
) 
  60         self
.SetAutoLayout(True) 
  63         EVT_BUTTON(self
, self
.ID_BUTTON_CHOICES
, self
.OnButtonChoices
) 
  64         EVT_TEXT(self
, self
.ID_TEXT_CTRL
, self
.OnChange
) 
  66         return self
.text
.GetValue() 
  67     def SetValue(self
, value
): 
  69         self
.text
.SetValue(value
) 
  71     def OnButtonChoices(self
, evt
): 
  72         dlg 
= g
.frame
.res
.LoadDialog(self
, 'DIALOG_CHOICES') 
  73         if self
.GetName() == 'flag':  dlg
.SetTitle('Sizer item flags') 
  74         elif self
.GetName() == 'style':  dlg
.SetTitle('Window styles') 
  75         elif self
.GetName() == 'exstyle':  dlg
.SetTitle('Extended window styles') 
  76         listBox 
= XRCCTRL(dlg
, 'CHECKLIST') 
  77         listBox
.InsertItems(self
.values
, 0) 
  78         value 
= map(string
.strip
, self
.text
.GetValue().split('|')) 
  79         if value 
== ['']: value 
= [] 
  83                 listBox
.Check(self
.values
.index(i
)) 
  86                 if self
.equal
.has_key(i
): 
  87                     listBox
.Check(self
.values
.index(self
.equal
[i
])) 
  89                     print 'WARNING: unknown flag: %s: ignored.' % i
 
  91         if dlg
.ShowModal() == wxID_OK
: 
  93             for i 
in range(listBox
.GetCount()): 
  94                 if listBox
.IsChecked(i
): 
  95                     value
.append(self
.values
[i
]) 
  99                 self
.SetValue(reduce(lambda a
,b
: a
+'|'+b
, 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             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 
= XRCCTRL(dlg
, 'CHECKLIST_SPECIFIC') 
 141         listBoxSpecific
.InsertItems(self
.valuesSpecific
, 0) 
 142         listBoxGeneric 
= 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() == wxID_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
 
 177                 self
.SetValue(reduce(lambda a
,b
: a
+'|'+b
, value
)) 
 183 class ParamExStyle(ParamBinaryOr
): 
 184     def __init__(self
, parent
, name
): 
 186             self
.values 
= g
.currentXXX
.exStyles 
+ genericExStyles
 
 189         ParamBinaryOr
.__init
__(self
, parent
, name
) 
 190         self
.SetTitle('Extended window styles') 
 192 class ParamColour(PPanel
): 
 193     def __init__(self
, parent
, name
): 
 194         PPanel
.__init
__(self
, parent
, name
) 
 195         self
.ID_TEXT_CTRL 
= wxNewId() 
 196         self
.ID_BUTTON 
= wxNewId() 
 198         self
.text 
= wxTextCtrl(self
, self
.ID_TEXT_CTRL
, size
=(80,-1)) 
 199         sizer
.Add(self
.text
, 0, wxALIGN_CENTER_VERTICAL | wxTOP | wxBOTTOM
, 2) 
 200         self
.button 
= wxPanel(self
, self
.ID_BUTTON
, wxDefaultPosition
, wxSize(20, 20)) 
 201         sizer
.Add(self
.button
, 0, wxALIGN_CENTER_VERTICAL | wxLEFT
, 5) 
 202         self
.SetAutoLayout(True) 
 205         self
.textModified 
= False 
 206         EVT_PAINT(self
.button
, self
.OnPaintButton
) 
 207         EVT_TEXT(self
, self
.ID_TEXT_CTRL
, self
.OnChange
) 
 208         EVT_LEFT_DOWN(self
.button
, self
.OnLeftDown
) 
 210         return self
.text
.GetValue() 
 211     def SetValue(self
, value
): 
 213         if not value
: value 
= '#FFFFFF' 
 214         self
.text
.SetValue(str(value
))  # update text ctrl 
 215         colour 
= wxColour(int(value
[1:3], 16), int(value
[3:5], 16), int(value
[5:7], 16)) 
 216         self
.button
.SetBackgroundColour(colour
) 
 217         self
.button
.Refresh() 
 219     def OnPaintButton(self
, evt
): 
 220         dc 
= wxPaintDC(self
.button
) 
 221         dc
.SetBrush(wxTRANSPARENT_BRUSH
) 
 222         if self
.IsEnabled(): dc
.SetPen(wxBLACK_PEN
) 
 223         else: dc
.SetPen(wxGREY_PEN
) 
 224         size 
= self
.button
.GetSize() 
 225         dc
.DrawRectangle(0, 0, size
.width
, size
.height
) 
 226     def OnLeftDown(self
, evt
): 
 227         data 
= wxColourData() 
 228         data
.SetColour(self
.GetValue()) 
 229         dlg 
= wxColourDialog(self
, data
) 
 230         if dlg
.ShowModal() == wxID_OK
: 
 231             self
.SetValue('#%02X%02X%02X' % dlg
.GetColourData().GetColour().Get()) 
 235 ################################################################################ 
 237 # Mapping from wx constants ro XML strings 
 238 fontFamiliesWx2Xml 
= {wxDEFAULT
: 'default', wxDECORATIVE
: 'decorative', 
 239                 wxROMAN
: 'roman', wxSCRIPT
: 'script', wxSWISS
: 'swiss', 
 241 fontStylesWx2Xml 
= {wxNORMAL: 'normal', wxSLANT: 'slant', wxITALIC: 'italic'}
 
 242 fontWeightsWx2Xml 
= {wxNORMAL: 'normal', wxLIGHT: 'light', wxBOLD: 'bold'}
 
 245     for k
,v 
in m
.items(): rm
[v
] = k
 
 247 fontFamiliesXml2wx 
= ReverseMap(fontFamiliesWx2Xml
) 
 248 fontStylesXml2wx 
= ReverseMap(fontStylesWx2Xml
) 
 249 fontWeightsXml2wx 
= ReverseMap(fontWeightsWx2Xml
) 
 251 class ParamFont(PPanel
): 
 252     def __init__(self
, parent
, name
): 
 253         PPanel
.__init
__(self
, parent
, name
) 
 254         self
.ID_TEXT_CTRL 
= wxNewId() 
 255         self
.ID_BUTTON_SELECT 
= wxNewId() 
 257         self
.text 
= wxTextCtrl(self
, self
.ID_TEXT_CTRL
, size
=(200,-1)) 
 258         sizer
.Add(self
.text
, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL
, 5) 
 259         self
.button 
= wxButton(self
, self
.ID_BUTTON_SELECT
, 'Select...', size
=buttonSize
) 
 260         sizer
.Add(self
.button
, 0, wxALIGN_CENTER_VERTICAL
) 
 261         self
.SetAutoLayout(True) 
 264         self
.textModified 
= False 
 265         EVT_BUTTON(self
, self
.ID_BUTTON_SELECT
, self
.OnButtonSelect
) 
 266         EVT_TEXT(self
, self
.ID_TEXT_CTRL
, self
.OnChange
) 
 267     def OnChange(self
, evt
): 
 268         PPanel
.OnChange(self
, evt
) 
 269         self
.textModified 
= True 
 270     def _defaultValue(self
): 
 271         return [`g
._sysFont
.GetPointSize()`
, 'default', 'normal', 'normal', '0', '', ''] 
 273         if self
.textModified
:           # text has newer value 
 275                 return eval(self
.text
.GetValue()) 
 277                 wxLogError('Syntax error in parameter value: ' + self
.GetName()) 
 278                 return self
._defaultValue
() 
 280     def SetValue(self
, value
): 
 281         self
.freeze 
= True              # disable other handlers 
 282         if not value
: value 
= self
._defaultValue
() 
 284         self
.text
.SetValue(str(value
))  # update text ctrl 
 286     def OnButtonSelect(self
, evt
): 
 287         if self
.textModified
:           # text has newer value 
 289                 self
.value 
= eval(self
.text
.GetValue()) 
 291                 wxLogError('Syntax error in parameter value: ' + self
.GetName()) 
 292                 self
.value 
= self
._defaultValue
() 
 295         size 
= g
._sysFont
.GetPointSize() 
 297         style 
= weight 
= wxNORMAL
 
 300         enc 
= wxFONTENCODING_DEFAULT
 
 301         # Fall back to default if exceptions 
 304             try: size 
= int(self
.value
[0]) 
 305             except ValueError: error 
= True; wxLogError('Invalid size specification') 
 306             try: family 
= fontFamiliesXml2wx
[self
.value
[1]] 
 307             except KeyError: error 
= True; wxLogError('Invalid family specification') 
 308             try: style 
= fontStylesXml2wx
[self
.value
[2]] 
 309             except KeyError: error 
= True; wxLogError('Invalid style specification') 
 310             try: weight 
= fontWeightsXml2wx
[self
.value
[3]] 
 311             except KeyError: error 
= True; wxLogError('Invalid weight specification') 
 312             try: underlined 
= bool(self
.value
[4]) 
 313             except ValueError: error 
= True; wxLogError('Invalid underlined flag specification') 
 317         mapper 
= wxFontMapper() 
 318         if not self
.value
[6]: enc 
= mapper
.CharsetToEncoding(self
.value
[6]) 
 320         if error
: wxLogError('Invalid font specification') 
 321         if enc 
== wxFONTENCODING_DEFAULT
: enc 
= wxFONTENCODING_SYSTEM
 
 322         font 
= wxFont(size
, family
, style
, weight
, underlined
, face
, enc
) 
 324         data
.SetInitialFont(font
) 
 325         dlg 
= wxFontDialog(self
, data
) 
 326         if dlg
.ShowModal() == wxID_OK
: 
 327             font 
= dlg
.GetFontData().GetChosenFont() 
 328             print font
.GetEncoding() 
 329             if font
.GetEncoding() == wxFONTENCODING_SYSTEM
: 
 332                 encName 
= wxFontMapper_GetEncodingName(font
.GetEncoding()).encode() 
 333             value 
= [str(font
.GetPointSize()), 
 334                      fontFamiliesWx2Xml
.get(font
.GetFamily(), "default"), 
 335                      fontStylesWx2Xml
.get(font
.GetStyle(), "normal"), 
 336                      fontWeightsWx2Xml
.get(font
.GetWeight(), "normal"), 
 337                      str(int(font
.GetUnderlined())), 
 338                      font
.GetFaceName().encode(), 
 343             self
.textModified 
= False 
 346 ################################################################################ 
 348 class ParamInt(PPanel
): 
 349     def __init__(self
, parent
, name
): 
 350         PPanel
.__init
__(self
, parent
, name
) 
 351         self
.ID_SPIN_CTRL 
= wxNewId() 
 353         self
.spin 
= wxSpinCtrl(self
, self
.ID_SPIN_CTRL
, size
=(60,-1)) 
 354         self
.spin
.SetRange(-2147483648, 2147483647) # min/max integers 
 356         self
.SetAutoLayout(True) 
 359         EVT_SPINCTRL(self
, self
.ID_SPIN_CTRL
, self
.OnChange
) 
 361         return str(self
.spin
.GetValue()) 
 362     def SetValue(self
, value
): 
 364         if not value
: value 
= 0 
 365         self
.spin
.SetValue(int(value
)) 
 368 # Non-negative number 
 369 class ParamIntNN(PPanel
): 
 370     def __init__(self
, parent
, name
): 
 371         PPanel
.__init
__(self
, parent
, name
) 
 372         self
.ID_SPIN_CTRL 
= wxNewId() 
 374         self
.spin 
= wxSpinCtrl(self
, self
.ID_SPIN_CTRL
, size
=(60,-1)) 
 375         self
.spin
.SetRange(0, 10000) # min/max integers 
 377         self
.SetAutoLayout(True) 
 380         EVT_SPINCTRL(self
, self
.ID_SPIN_CTRL
, self
.OnChange
) 
 382         return str(self
.spin
.GetValue()) 
 383     def SetValue(self
, value
): 
 385         if not value
: value 
= 0 
 386         self
.spin
.SetValue(int(value
)) 
 389 # Same as int but allows dialog units (XXXd) 
 390 class ParamUnit(PPanel
): 
 391     def __init__(self
, parent
, name
): 
 392         PPanel
.__init
__(self
, parent
, name
) 
 393         self
.ID_TEXT_CTRL 
= wxNewId() 
 394         self
.ID_SPIN_BUTTON 
= wxNewId() 
 395         sizer 
= wxBoxSizer(wxHORIZONTAL
) 
 396         self
.spin 
= wxSpinButton(self
, self
.ID_SPIN_BUTTON
, style 
= wxSP_VERTICAL
, size
=(-1,1)) 
 397         textW 
= 60 - self
.spin
.GetSize()[0] 
 398         self
.text 
= wxTextCtrl(self
, self
.ID_TEXT_CTRL
, size
=(textW
,-1)) 
 399         self
.spin
.SetRange(-10000, 10000) 
 400         sizer
.Add(self
.text
, 0, wxEXPAND
) 
 401         sizer
.Add(self
.spin
, 0, wxEXPAND
) 
 402         #sizer.SetMinSize((50,-1)) 
 403         self
.SetAutoLayout(True) 
 406         EVT_SPIN_UP(self
, self
.ID_SPIN_BUTTON
, self
.OnSpinUp
) 
 407         EVT_SPIN_DOWN(self
, self
.ID_SPIN_BUTTON
, self
.OnSpinDown
) 
 409         return self
.text
.GetValue() 
 410     def SetValue(self
, value
): 
 412         if not value
: value 
= '0' 
 413         self
.text
.SetValue(value
) 
 416         # Check if we are working with dialog units 
 417         value 
= self
.text
.GetValue() 
 419         if value
[-1].upper() == 'D': 
 423             intValue 
= int(value
) + x
 
 424             self
.spin
.SetValue(intValue
) 
 425             self
.text
.SetValue(str(intValue
) + units
) 
 428             # !!! Strange, if I use wxLogWarning, event is re-generated 
 429             print 'incorrect unit format' 
 430     def OnSpinUp(self
, evt
): 
 432     def OnSpinDown(self
, evt
): 
 435 class ParamMultilineText(PPanel
): 
 436     def __init__(self
, parent
, name
, textWidth
=-1): 
 437         PPanel
.__init
__(self
, parent
, name
) 
 438         self
.ID_TEXT_CTRL 
= wxNewId() 
 439         self
.ID_BUTTON_EDIT 
= wxNewId() 
 441         self
.text 
= wxTextCtrl(self
, self
.ID_TEXT_CTRL
, size
=wxSize(200,-1)) 
 442         sizer
.Add(self
.text
, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL
, 5) 
 443         self
.button 
= wxButton(self
, self
.ID_BUTTON_EDIT
, 'Edit...', size
=buttonSize
) 
 444         sizer
.Add(self
.button
, 0, wxALIGN_CENTER_VERTICAL
) 
 445         self
.SetAutoLayout(True) 
 448         EVT_BUTTON(self
, self
.ID_BUTTON_EDIT
, self
.OnButtonEdit
) 
 449         EVT_TEXT(self
, self
.ID_TEXT_CTRL
, self
.OnChange
) 
 451         return self
.text
.GetValue() 
 452     def SetValue(self
, value
): 
 453         self
.freeze 
= True              # disable other handlers 
 454         self
.text
.SetValue(value
) 
 455         self
.freeze 
= False             # disable other handlers 
 456     def OnButtonEdit(self
, evt
): 
 457         dlg 
= g
.frame
.res
.LoadDialog(self
, 'DIALOG_TEXT') 
 458         textCtrl 
= XRCCTRL(dlg
, 'TEXT') 
 459         textCtrl
.SetValue(self
.text
.GetValue()) 
 460         if dlg
.ShowModal() == wxID_OK
: 
 461             self
.text
.SetValue(textCtrl
.GetValue()) 
 465 class ParamText(PPanel
): 
 466     def __init__(self
, parent
, name
, textWidth
=-1): 
 467         PPanel
.__init
__(self
, parent
, name
) 
 468         self
.ID_TEXT_CTRL 
= wxNewId() 
 469         # We use sizer even here to have the same size of text control 
 471         self
.text 
= wxTextCtrl(self
, self
.ID_TEXT_CTRL
, size
=wxSize(textWidth
,-1)) 
 472         if textWidth 
== -1: option 
= 1 
 474         sizer
.Add(self
.text
, option
, wxALIGN_CENTER_VERTICAL | wxTOP | wxBOTTOM
, 2) 
 475         self
.SetAutoLayout(True) 
 478         EVT_TEXT(self
, self
.ID_TEXT_CTRL
, self
.OnChange
) 
 480         return self
.text
.GetValue() 
 481     def SetValue(self
, value
): 
 482         self
.freeze 
= True              # disable other handlers 
 483         self
.text
.SetValue(value
) 
 484         self
.freeze 
= False             # disable other handlers 
 486 class ParamAccel(ParamText
): 
 487     def __init__(self
, parent
, name
): 
 488         ParamText
.__init
__(self
, parent
, name
, 100) 
 490 class ParamPosSize(ParamText
): 
 491     def __init__(self
, parent
, name
): 
 492         ParamText
.__init
__(self
, parent
, name
, 80) 
 494 class ParamLabel(ParamText
): 
 495     def __init__(self
, parent
, name
): 
 496         ParamText
.__init
__(self
, parent
, name
, 200) 
 498 class ParamEncoding(ParamText
): 
 499     def __init__(self
, parent
, name
): 
 500         ParamText
.__init
__(self
, parent
, name
, 100) 
 502 class ContentDialog(wxDialog
): 
 503     def __init__(self
, parent
, value
): 
 506         g
.frame
.res
.LoadOnDialog(pre
, parent
, 'DIALOG_CONTENT') 
 508         self
._setOORInfo
(self
) 
 509         self
.list = XRCCTRL(self
, 'LIST') 
 513         self
.SetAutoLayout(True) 
 514         self
.GetSizer().Fit(self
) 
 516         self
.ID_BUTTON_APPEND 
= XRCID('BUTTON_APPEND') 
 517         self
.ID_BUTTON_REMOVE 
= XRCID('BUTTON_REMOVE') 
 518         self
.ID_BUTTON_UP 
= XRCID('BUTTON_UP') 
 519         self
.ID_BUTTON_DOWN 
= XRCID('BUTTON_DOWN') 
 520         EVT_BUTTON(self
, self
.ID_BUTTON_UP
, self
.OnButtonUp
) 
 521         EVT_BUTTON(self
, self
.ID_BUTTON_DOWN
, self
.OnButtonDown
) 
 522         EVT_BUTTON(self
, self
.ID_BUTTON_APPEND
, self
.OnButtonAppend
) 
 523         EVT_BUTTON(self
, self
.ID_BUTTON_REMOVE
, self
.OnButtonRemove
) 
 524         EVT_UPDATE_UI(self
, self
.ID_BUTTON_UP
, self
.OnUpdateUI
) 
 525         EVT_UPDATE_UI(self
, self
.ID_BUTTON_DOWN
, self
.OnUpdateUI
) 
 526         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 = wxGetTextFromUser('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(wxDialog
): 
 554     def __init__(self
, parent
, value
): 
 556         g
.frame
.res
.LoadOnDialog(pre
, parent
, 'DIALOG_CONTENT_CHECKLIST') 
 558         self
._setOORInfo
(self
) 
 559         self
.list = XRCCTRL(self
, 'CHECKLIST') 
 564             self
.list.Check(i
, ch
) 
 566         self
.SetAutoLayout(True) 
 567         self
.GetSizer().Fit(self
) 
 569         self
.ID_BUTTON_APPEND 
= XRCID('BUTTON_APPEND') 
 570         self
.ID_BUTTON_REMOVE 
= XRCID('BUTTON_REMOVE') 
 571         self
.ID_BUTTON_UP 
= XRCID('BUTTON_UP') 
 572         self
.ID_BUTTON_DOWN 
= XRCID('BUTTON_DOWN') 
 573         EVT_CHECKLISTBOX(self
, self
.list.GetId(), self
.OnCheck
) 
 574         EVT_BUTTON(self
, self
.ID_BUTTON_UP
, self
.OnButtonUp
) 
 575         EVT_BUTTON(self
, self
.ID_BUTTON_DOWN
, self
.OnButtonDown
) 
 576         EVT_BUTTON(self
, self
.ID_BUTTON_APPEND
, self
.OnButtonAppend
) 
 577         EVT_BUTTON(self
, self
.ID_BUTTON_REMOVE
, self
.OnButtonRemove
) 
 578         EVT_UPDATE_UI(self
, self
.ID_BUTTON_UP
, self
.OnUpdateUI
) 
 579         EVT_UPDATE_UI(self
, self
.ID_BUTTON_DOWN
, self
.OnUpdateUI
) 
 580         EVT_UPDATE_UI(self
, self
.ID_BUTTON_REMOVE
, self
.OnUpdateUI
) 
 581     def OnCheck(self
, evt
): 
 582         # !!! Wrong wxGTK (wxMSW?) behavior: toggling selection if checking 
 583         self
.list.Deselect(evt
.GetSelection()) 
 584     def OnButtonUp(self
, evt
): 
 585         i 
= self
.list.GetSelection() 
 586         str, ch 
= self
.list.GetString(i
), self
.list.IsChecked(i
) 
 588         self
.list.InsertItems([str], i
-1) 
 589         self
.list.Check(i
-1, ch
) 
 590         self
.list.SetSelection(i
-1) 
 591     def OnButtonDown(self
, evt
): 
 592         i 
= self
.list.GetSelection() 
 593         str, ch 
= self
.list.GetString(i
), self
.list.IsChecked(i
) 
 595         self
.list.InsertItems([str], i
+1) 
 596         self
.list.Check(i
+1, ch
) 
 597         self
.list.SetSelection(i
+1) 
 598     def OnButtonAppend(self
, evt
): 
 599         str = wxGetTextFromUser('Enter new item:', 'Append', '', self
) 
 600         self
.list.Append(str) 
 601     def OnButtonRemove(self
, evt
): 
 602         self
.list.Delete(self
.list.GetSelection()) 
 603     def OnUpdateUI(self
, evt
): 
 604         if evt
.GetId() == self
.ID_BUTTON_REMOVE
: 
 605             evt
.Enable(self
.list.GetSelection() != -1) 
 606         elif evt
.GetId() == self
.ID_BUTTON_UP
: 
 607             evt
.Enable(self
.list.GetSelection() > 0) 
 608         elif evt
.GetId() == self
.ID_BUTTON_DOWN
: 
 609             evt
.Enable(self
.list.GetSelection() != -1 and \
 
 610                        self
.list.GetSelection() < self
.list.GetCount() - 1) 
 612 class ParamContent(PPanel
): 
 613     def __init__(self
, parent
, name
): 
 614         PPanel
.__init
__(self
, parent
, name
) 
 615         self
.ID_TEXT_CTRL 
= wxNewId() 
 616         self
.ID_BUTTON_EDIT 
= wxNewId() 
 618         self
.text 
= wxTextCtrl(self
, self
.ID_TEXT_CTRL
, size
=wxSize(200,-1)) 
 619         sizer
.Add(self
.text
, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL
, 5) 
 620         self
.button 
= wxButton(self
, self
.ID_BUTTON_EDIT
, 'Edit...', size
=buttonSize
) 
 621         sizer
.Add(self
.button
, 0, wxALIGN_CENTER_VERTICAL
) 
 622         self
.SetAutoLayout(True) 
 625         self
.textModified 
= False 
 626         EVT_BUTTON(self
, self
.ID_BUTTON_EDIT
, self
.OnButtonEdit
) 
 627         EVT_TEXT(self
, self
.ID_TEXT_CTRL
, self
.OnChange
) 
 628     def OnChange(self
, evt
): 
 629         PPanel
.OnChange(self
, evt
) 
 630         self
.textModified 
= True 
 632         if self
.textModified
:           # text has newer value 
 634                 return eval(self
.text
.GetValue()) 
 636                 wxLogError('Syntax error in parameter value: ' + self
.GetName()) 
 639     def SetValue(self
, value
): 
 641         if not value
: value 
= [] 
 643         self
.text
.SetValue(str(value
))  # update text ctrl 
 645     def OnButtonEdit(self
, evt
): 
 646         if self
.textModified
:           # text has newer value 
 648                 self
.value 
= eval(self
.text
.GetValue()) 
 650                 wxLogError('Syntax error in parameter value: ' + self
.GetName()) 
 652         dlg 
= ContentDialog(self
, self
.value
) 
 653         if dlg
.ShowModal() == wxID_OK
: 
 655             for i 
in range(dlg
.list.GetCount()): 
 656                 value
.append(dlg
.list.GetString(i
)) 
 659             self
.textModified 
= False 
 663 class ParamContentCheckList(ParamContent
): 
 664     def __init__(self
, parent
, name
): 
 665         ParamContent
.__init
__(self
, parent
, name
) 
 666     def OnButtonEdit(self
, evt
): 
 667         if self
.textModified
:           # text has newer value 
 669                 self
.value 
= eval(self
.text
.GetValue()) 
 671                 wxLogError('Syntax error in parameter value: ' + self
.GetName()) 
 673         dlg 
= ContentCheckListDialog(self
, self
.value
) 
 674         if dlg
.ShowModal() == wxID_OK
: 
 676             for i 
in range(dlg
.list.GetCount()): 
 677                 value
.append((dlg
.list.GetString(i
), int(dlg
.list.IsChecked(i
)))) 
 680             self
.textModified 
= False 
 683 class IntListDialog(wxDialog
): 
 684     def __init__(self
, parent
, value
): 
 686         g
.frame
.res
.LoadOnDialog(pre
, parent
, 'DIALOG_INTLIST') 
 688         self
._setOORInfo
(self
) 
 689         self
.list = XRCCTRL(self
, 'LIST') 
 693             if type(v
) != IntType
: 
 694                 wxLogError('Invalid item type') 
 696                 self
.list.Append(str(v
)) 
 697         self
.SetAutoLayout(True) 
 698         self
.GetSizer().Fit(self
) 
 700         self
.spinCtrl 
= XRCCTRL(self
, 'SPIN') 
 701         EVT_BUTTON(self
, XRCID('BUTTON_ADD'), self
.OnButtonAdd
) 
 702         self
.ID_BUTTON_REMOVE 
= XRCID('BUTTON_REMOVE') 
 703         EVT_BUTTON(self
, self
.ID_BUTTON_REMOVE
, self
.OnButtonRemove
) 
 704         EVT_BUTTON(self
, XRCID('BUTTON_CLEAR'), self
.OnButtonClear
) 
 705         EVT_UPDATE_UI(self
, self
.ID_BUTTON_REMOVE
, self
.OnUpdateUI
) 
 706     def OnButtonAdd(self
, evt
): 
 707         # Check that it's unique 
 709             v 
= self
.spinCtrl
.GetValue() 
 710             s 
= str(v
)                  # to be sure 
 711             i 
= self
.list.FindString(s
) 
 712             if i 
== -1:                 # ignore non-unique 
 713                 # Find place to insert 
 715                 for i 
in range(self
.list.GetCount()): 
 716                     if int(self
.list.GetString(i
)) > v
: 
 719                 if found
: self
.list.InsertItems([s
], i
) 
 720                 else: self
.list.Append(s
) 
 722             wxLogError('List item is not an int!') 
 723     def OnButtonRemove(self
, evt
): 
 724         self
.list.Delete(self
.list.GetSelection()) 
 725     def OnButtonClear(self
, evt
): 
 727     def OnUpdateUI(self
, evt
): 
 728         if evt
.GetId() == self
.ID_BUTTON_REMOVE
: 
 729             evt
.Enable(self
.list.GetSelection() != -1) 
 732 class ParamIntList(ParamContent
): 
 733     def __init__(self
, parent
, name
): 
 734         ParamContent
.__init
__(self
, parent
, name
) 
 735     def OnButtonEdit(self
, evt
): 
 736         if self
.textModified
:           # text has newer value 
 738                 self
.value 
= eval(self
.text
.GetValue()) 
 740                 wxLogError('Syntax error in parameter value: ' + self
.GetName()) 
 742         dlg 
= IntListDialog(self
, self
.value
) 
 743         if dlg
.ShowModal() == wxID_OK
: 
 745             for i 
in range(dlg
.list.GetCount()): 
 746                 value
.append(int(dlg
.list.GetString(i
))) 
 749             self
.textModified 
= False 
 753 class RadioBox(PPanel
): 
 754     def __init__(self
, parent
, id, choices
, 
 755                  pos
=wxDefaultPosition
, name
='radiobox'): 
 756         PPanel
.__init
__(self
, parent
, name
) 
 757         self
.choices 
= choices
 
 758         topSizer 
= wxBoxSizer() 
 760             button 
= wxRadioButton(self
, -1, i
, size
=(-1,buttonSize
[1]), name
=i
) 
 761             topSizer
.Add(button
, 0, wxRIGHT
, 5) 
 762             EVT_RADIOBUTTON(self
, button
.GetId(), self
.OnRadioChoice
) 
 763         self
.SetAutoLayout(True) 
 764         self
.SetSizer(topSizer
) 
 766     def SetStringSelection(self
, value
): 
 768         for i 
in self
.choices
: 
 769             self
.FindWindowByName(i
).SetValue(i 
== value
) 
 772     def OnRadioChoice(self
, evt
): 
 773         if self
.freeze
: return 
 774         if evt
.GetSelection(): 
 775             self
.value 
= evt
.GetEventObject().GetName() 
 777     def GetStringSelection(self
): 
 780 class ParamBool(RadioBox
): 
 781     values 
= {'yes': '1', 'no': '0'}
 
 782     seulav 
= {'1': 'yes', '0': 'no'}
 
 783     def __init__(self
, parent
, name
): 
 784         RadioBox
.__init
__(self
, parent
, -1, choices
=self
.values
.keys(), name
=name
) 
 786         return self
.values
[self
.GetStringSelection()] 
 787     def SetValue(self
, value
): 
 788         if not value
: value 
= '1' 
 789         self
.SetStringSelection(self
.seulav
[value
]) 
 791 class ParamOrient(RadioBox
): 
 792     values 
= {'horizontal': 'wxHORIZONTAL', 'vertical': 'wxVERTICAL'}
 
 793     seulav 
= {'wxHORIZONTAL': 'horizontal', 'wxVERTICAL': 'vertical'}
 
 794     def __init__(self
, parent
, name
): 
 795         RadioBox
.__init
__(self
, parent
, -1, choices
=self
.values
.keys(), name
=name
) 
 797         return self
.values
[self
.GetStringSelection()] 
 798     def SetValue(self
, value
): 
 799         if not value
: value 
= 'wxHORIZONTAL' 
 800         self
.SetStringSelection(self
.seulav
[value
]) 
 802 class ParamOrientation(RadioBox
): 
 803     values 
= {'horizontal': 'horizontal', 'vertical': 'vertical'}
 
 804     seulav 
= {'horizontal': 'horizontal', 'vertical': 'vertical'}
 
 805     def __init__(self
, parent
, name
): 
 806         RadioBox
.__init
__(self
, parent
, -1, choices
=self
.values
.keys(), name
=name
) 
 808         return self
.values
[self
.GetStringSelection()] 
 809     def SetValue(self
, value
): 
 810         if not value
: value 
= 'vertical' 
 811         self
.SetStringSelection(self
.seulav
[value
]) 
 813 class ParamFile(PPanel
): 
 814     def __init__(self
, parent
, name
): 
 815         PPanel
.__init
__(self
, parent
, name
) 
 816         self
.ID_TEXT_CTRL 
= wxNewId() 
 817         self
.ID_BUTTON_BROWSE 
= wxNewId() 
 819         self
.text 
= wxTextCtrl(self
, self
.ID_TEXT_CTRL
, size
=wxSize(200,-1)) 
 820         sizer
.Add(self
.text
, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL
, 5) 
 821         self
.button 
= wxButton(self
, self
.ID_BUTTON_BROWSE
, 'Browse...',size
=buttonSize
) 
 822         sizer
.Add(self
.button
, 0, wxALIGN_CENTER_VERTICAL
) 
 823         self
.SetAutoLayout(True) 
 826         self
.textModified 
= False 
 827         EVT_BUTTON(self
, self
.ID_BUTTON_BROWSE
, self
.OnButtonBrowse
) 
 828         EVT_TEXT(self
, self
.ID_TEXT_CTRL
, self
.OnChange
) 
 829     def OnChange(self
, evt
): 
 830         PPanel
.OnChange(self
, evt
) 
 831         self
.textModified 
= True 
 833         if self
.textModified
:           # text has newer value 
 834             return self
.text
.GetValue() 
 836     def SetValue(self
, value
): 
 839         self
.text
.SetValue(value
)  # update text ctrl 
 841     def OnButtonBrowse(self
, evt
): 
 842         if self
.textModified
:           # text has newer value 
 843             self
.value 
= self
.text
.GetValue() 
 844         dlg 
= wxFileDialog(self
, 
 845                            defaultDir 
= os
.path
.abspath(os
.path
.dirname(self
.value
)), 
 846                            defaultFile 
= os
.path
.basename(self
.value
)) 
 847         if dlg
.ShowModal() == wxID_OK
: 
 848             # Get common part of selected path and current 
 850                 curpath 
= os
.path
.abspath(g
.frame
.dataFile
) 
 852                 curpath 
= os
.path
.join(os
.getcwd(), '') 
 853             common 
= os
.path
.commonprefix([curpath
, dlg
.GetPath()]) 
 854             self
.SetValue(dlg
.GetPath()[len(common
):]) 
 856             self
.textModified 
= False 
 859 class ParamBitmap(PPanel
): 
 860     def __init__(self
, parent
, name
): 
 862         g
.frame
.res
.LoadOnPanel(pre
, parent
, 'PANEL_BITMAP') 
 864         self
._setOORInfo
(self
) 
 865         self
.modified 
= self
.freeze 
= False 
 866         self
.radio_std 
= XRCCTRL(self
, 'RADIO_STD') 
 867         self
.radio_file 
= XRCCTRL(self
, 'RADIO_FILE') 
 868         self
.combo 
= XRCCTRL(self
, 'COMBO_STD') 
 869         self
.text 
= XRCCTRL(self
, 'TEXT_FILE') 
 870         self
.button 
= XRCCTRL(self
, 'BUTTON_BROWSE') 
 871         self
.textModified 
= False 
 872         self
.SetAutoLayout(True) 
 873         self
.GetSizer().SetMinSize((260, -1)) 
 874         self
.GetSizer().Fit(self
) 
 875         EVT_RADIOBUTTON(self
, XRCID('RADIO_STD'), self
.OnRadioStd
) 
 876         EVT_RADIOBUTTON(self
, XRCID('RADIO_FILE'), self
.OnRadioFile
) 
 877         EVT_BUTTON(self
, XRCID('BUTTON_BROWSE'), self
.OnButtonBrowse
) 
 878         EVT_COMBOBOX(self
, XRCID('COMBO_STD'), self
.OnCombo
) 
 879         EVT_TEXT(self
, XRCID('COMBO_STD'), self
.OnChange
) 
 880         EVT_TEXT(self
, XRCID('TEXT_FILE'), self
.OnChange
) 
 881     def OnRadioStd(self
, evt
): 
 883         self
.SetValue(['wxART_MISSING_IMAGE','']) 
 884     def OnRadioFile(self
, evt
): 
 886         self
.SetValue(['','']) 
 887     def updateRadios(self
): 
 889             self
.radio_std
.SetValue(True) 
 890             self
.radio_file
.SetValue(False) 
 891             self
.text
.Enable(False) 
 892             self
.button
.Enable(False) 
 893             self
.combo
.Enable(True) 
 895             self
.radio_std
.SetValue(False) 
 896             self
.radio_file
.SetValue(True) 
 897             self
.text
.Enable(True) 
 898             self
.button
.Enable(True) 
 899             self
.combo
.Enable(False) 
 900     def OnChange(self
, evt
): 
 901         PPanel
.OnChange(self
, evt
) 
 902         self
.textModified 
= True 
 903     def OnCombo(self
, evt
): 
 904         PPanel
.OnChange(self
, evt
) 
 905         self
.value
[0] = self
.combo
.GetValue() 
 907         if self
.textModified
:           # text has newer value 
 908             return [self
.combo
.GetValue(), self
.text
.GetValue()] 
 910     def SetValue(self
, value
): 
 913             self
.value 
= ['', ''] 
 916         self
.combo
.SetValue(self
.value
[0]) 
 917         self
.text
.SetValue(self
.value
[1])  # update text ctrl 
 920     def OnButtonBrowse(self
, evt
): 
 921         if self
.textModified
:           # text has newer value 
 922             self
.value
[1] = self
.text
.GetValue() 
 923         dlg 
= wxFileDialog(self
, 
 924                            defaultDir 
= os
.path
.abspath(os
.path
.dirname(self
.value
[1])), 
 925                            defaultFile 
= os
.path
.basename(self
.value
[1])) 
 926         if dlg
.ShowModal() == wxID_OK
: 
 927             # Get common part of selected path and current 
 929                 curpath 
= os
.path
.abspath(g
.frame
.dataFile
) 
 931                 curpath 
= os
.path
.join(os
.getcwd(), '') 
 932             common 
= os
.path
.commonprefix([curpath
, dlg
.GetPath()]) 
 933             self
.SetValue(['', dlg
.GetPath()[len(common
):]]) 
 935             self
.textModified 
= False 
 940     'style': ParamStyle
, 'exstyle': ParamExStyle
, 
 941     'pos': ParamPosSize
, 'size': ParamPosSize
, 
 942     'cellpos': ParamPosSize
, 'cellspan': ParamPosSize
, 
 943     'border': ParamUnit
, 'cols': ParamIntNN
, 'rows': ParamIntNN
, 
 944     'vgap': ParamUnit
, 'hgap': ParamUnit
, 
 945     'checkable': ParamBool
, 'checked': ParamBool
, 'radio': ParamBool
, 
 947     'label': ParamMultilineText
, 'title': ParamText
, 'value': ParamText
, 
 948     'content': ParamContent
, 'selection': ParamIntNN
, 
 949     'min': ParamInt
, 'max': ParamInt
, 
 950     'fg': ParamColour
, 'bg': ParamColour
, 'font': ParamFont
, 
 951     'enabled': ParamBool
, 'focused': ParamBool
, 'hidden': ParamBool
, 
 952     'tooltip': ParamText
, 'bitmap': ParamBitmap
, 'icon': ParamBitmap
, 
 953     'encoding': ParamEncoding
, 'borders': ParamUnit