1 #----------------------------------------------------------------------------- 
   2 # Name:        STCStyleEditor.py 
   3 # Purpose:     Style editor for the wxStyledTextCtrl 
   5 # Author:      Riaan Booysen 
   9 # Copyright:   (c) 2001 - 2002 Riaan Booysen 
  10 # Licence:     wxWindows license 
  11 #----------------------------------------------------------------------------- 
  12 #Boa:Dialog:STCStyleEditDlg 
  14 """ Style editor for the wxStyledTextCtrl. 
  16 Reads in property style definitions from a config file. 
  17 Modified styled can be saved (and optionally applied to a given list of STCs) 
  19 It can also maintain a Common definition dictionary of font names, colours and 
  20 sizes which can be shared across multiple language style definitions. 
  21 This is also used to store platform spesific settings as fonts and sizes 
  24 The following items are defined in the stc-styles.rc.cfg file. 
  26 common.defs.msw - Common definition dictionary used on wxMSW 
  27 common.defs.gtk - Common definition dictionary used on wxGTK 
  28 common.styleidnames - STC styles shared by all languages 
  30 Each supported language defines the following groups: 
  32 displaysrc - Example source to display in the editor 
  33 braces - Dictionary defining the (line, column) for showing 'good' and 'bad' 
  34          brace matching (both keys optional) 
  35 keywords - Space separated list of keywords 
  36 lexer - wxSTC constant for the language lexer 
  37 styleidnames - Dictionary of language spesific style numbers and names 
  39 [style.<language>] - The users current style values 
  40 [style.<language>.default] - Default style values (can be reverted from) 
  42 0 or more predefined style groups or 'themes' 
  43 [style.<language>.<predefined name>] 
  45 Currently the following languages are supported: 
  46     python, html, xml, cpp, text, props 
  47 Other languages can be added by just defining the above settings for them in 
  48 the config file (if wxSTC implements them). 
  50 Use the initSTC function to initialise your wxSTC from a config file. 
  53 import os
, sys
, string
, pprint
, copy
 
  55 from wxPython
.wx 
import * 
  56 from wxPython
.help import * 
  57 from wxPython
.lib
.anchors 
import LayoutAnchors
 
  58 from wxPython
.stc 
import * 
  60 settingsIdNames 
= {-1: 'Selection', -2: 'Caret', -3: 'Edge'}
 
  62 commonPropDefs 
= {'fore': '#888888', 'size': 8, 
  63   'face': wxSystemSettings_GetSystemFont(wxSYS_DEFAULT_GUI_FONT
).GetFaceName()} 
  65 styleCategoryDescriptions 
= { 
  66  '----Language----': 'Styles spesific to the language', 
  67  '----Standard----': 'Styles shared by all languages', 
  68  '----Settings----': 'Properties set by STC methods', 
  69  '----Common----': 'User definable values that can be shared between languages'} 
  71 [wxID_STCSTYLEEDITDLG
, wxID_STCSTYLEEDITDLGADDCOMMONITEMBTN
, 
  72  wxID_STCSTYLEEDITDLGBGCOLBTN
, wxID_STCSTYLEEDITDLGBGCOLCB
, 
  73  wxID_STCSTYLEEDITDLGBGCOLDEFCB
, wxID_STCSTYLEEDITDLGBGCOLOKBTN
, 
  74  wxID_STCSTYLEEDITDLGCANCELBTN
, wxID_STCSTYLEEDITDLGCONTEXTHELPBUTTON1
, 
  75  wxID_STCSTYLEEDITDLGELEMENTLB
, wxID_STCSTYLEEDITDLGFACECB
, 
  76  wxID_STCSTYLEEDITDLGFACEDEFCB
, wxID_STCSTYLEEDITDLGFACEOKBTN
, 
  77  wxID_STCSTYLEEDITDLGFGCOLBTN
, wxID_STCSTYLEEDITDLGFGCOLCB
, 
  78  wxID_STCSTYLEEDITDLGFGCOLDEFCB
, wxID_STCSTYLEEDITDLGFGCOLOKBTN
, 
  79  wxID_STCSTYLEEDITDLGFIXEDWIDTHCHK
, wxID_STCSTYLEEDITDLGOKBTN
, 
  80  wxID_STCSTYLEEDITDLGPANEL1
, wxID_STCSTYLEEDITDLGPANEL2
, 
  81  wxID_STCSTYLEEDITDLGPANEL3
, wxID_STCSTYLEEDITDLGPANEL4
, 
  82  wxID_STCSTYLEEDITDLGREMOVECOMMONITEMBTN
, wxID_STCSTYLEEDITDLGSIZECB
, 
  83  wxID_STCSTYLEEDITDLGSIZEOKBTN
, wxID_STCSTYLEEDITDLGSPEEDSETTINGCH
, 
  84  wxID_STCSTYLEEDITDLGSTATICBOX1
, wxID_STCSTYLEEDITDLGSTATICBOX2
, 
  85  wxID_STCSTYLEEDITDLGSTATICLINE1
, wxID_STCSTYLEEDITDLGSTATICTEXT2
, 
  86  wxID_STCSTYLEEDITDLGSTATICTEXT3
, wxID_STCSTYLEEDITDLGSTATICTEXT4
, 
  87  wxID_STCSTYLEEDITDLGSTATICTEXT6
, wxID_STCSTYLEEDITDLGSTATICTEXT7
, 
  88  wxID_STCSTYLEEDITDLGSTATICTEXT8
, wxID_STCSTYLEEDITDLGSTATICTEXT9
, 
  89  wxID_STCSTYLEEDITDLGSTC
, wxID_STCSTYLEEDITDLGSTYLEDEFST
, 
  90  wxID_STCSTYLEEDITDLGTABOLDCB
, wxID_STCSTYLEEDITDLGTABOLDDEFCB
, 
  91  wxID_STCSTYLEEDITDLGTAEOLFILLEDCB
, wxID_STCSTYLEEDITDLGTAEOLFILLEDDEFCB
, 
  92  wxID_STCSTYLEEDITDLGTAITALICCB
, wxID_STCSTYLEEDITDLGTAITALICDEFCB
, 
  93  wxID_STCSTYLEEDITDLGTASIZEDEFCB
, wxID_STCSTYLEEDITDLGTAUNDERLINEDCB
, 
  94  wxID_STCSTYLEEDITDLGTAUNDERLINEDDEFCB
, 
  95 ] = map(lambda _init_ctrls
: wxNewId(), range(47)) 
  97 class STCStyleEditDlg(wxDialog
): 
  98     """ Style editor for the wxStyledTextCtrl """ 
  99     _custom_classes 
= {'wxWindow' : ['wxStyledTextCtrl']}
 
 100     def _init_utils(self
): 
 101         # generated method, don't edit 
 104     def _init_ctrls(self
, prnt
): 
 105         # generated method, don't edit 
 106         wxDialog
.__init
__(self
, id=wxID_STCSTYLEEDITDLG
, name
='STCStyleEditDlg', 
 107               parent
=prnt
, pos
=wxPoint(583, 291), size
=wxSize(459, 482), 
 108               style
=wxWANTS_CHARS | wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER
, 
 109               title
=self
.stc_title
) 
 111         self
.SetClientSize(wxSize(451, 455)) 
 112         self
.SetAutoLayout(True) 
 113         self
.SetSizeHints(425, 400, -1, -1) 
 115         EVT_SIZE(self
, self
.OnStcstyleeditdlgSize
) 
 117         self
.speedsettingCh 
= wxChoice(choices
=[], 
 118               id=wxID_STCSTYLEEDITDLGSPEEDSETTINGCH
, name
='speedsettingCh', 
 119               parent
=self
, pos
=wxPoint(96, 28), size
=wxSize(346, 21), style
=0, 
 120               validator
=wxDefaultValidator
) 
 121         self
.speedsettingCh
.SetConstraints(LayoutAnchors(self
.speedsettingCh
, 
 122               True, True, True, False)) 
 123         self
.speedsettingCh
.SetHelpText('The speed setting allows you to revert to one of the predefined style sets. This will overwrite your current settings when tha dialog is posted.') 
 124         EVT_CHOICE(self
.speedsettingCh
, wxID_STCSTYLEEDITDLGSPEEDSETTINGCH
, 
 125               self
.OnSpeedsettingchChoice
) 
 127         self
.elementLb 
= wxListBox(choices
=[], id=wxID_STCSTYLEEDITDLGELEMENTLB
, 
 128               name
='elementLb', parent
=self
, pos
=wxPoint(8, 72), 
 129               size
=wxSize(160, 112), style
=0, validator
=wxDefaultValidator
) 
 130         self
.elementLb
.SetConstraints(LayoutAnchors(self
.elementLb
, True, True, 
 132         self
.elementLb
.SetHelpText('Select a style here to edit it. Common definitions can be added and maintained here.  A common definition is a property that can be shared between styles and special cased per platform.') 
 133         EVT_LISTBOX(self
.elementLb
, wxID_STCSTYLEEDITDLGELEMENTLB
, 
 134               self
.OnElementlbListbox
) 
 136         self
.addCommonItemBtn 
= wxButton(id=wxID_STCSTYLEEDITDLGADDCOMMONITEMBTN
, 
 137               label
='Add', name
='addCommonItemBtn', parent
=self
, pos
=wxPoint(8, 
 138               184), size
=wxSize(80, 17), style
=0) 
 139         self
.addCommonItemBtn
.SetToolTipString('Add new Common definition') 
 140         EVT_BUTTON(self
.addCommonItemBtn
, wxID_STCSTYLEEDITDLGADDCOMMONITEMBTN
, 
 141               self
.OnAddsharebtnButton
) 
 143         self
.removeCommonItemBtn 
= wxButton(id=wxID_STCSTYLEEDITDLGREMOVECOMMONITEMBTN
, 
 144               label
='Remove', name
='removeCommonItemBtn', parent
=self
, 
 145               pos
=wxPoint(88, 184), size
=wxSize(80, 17), style
=0) 
 146         self
.removeCommonItemBtn
.SetToolTipString('Remove the selected Common definition') 
 147         EVT_BUTTON(self
.removeCommonItemBtn
, 
 148               wxID_STCSTYLEEDITDLGREMOVECOMMONITEMBTN
, 
 149               self
.OnRemovesharebtnButton
) 
 151         self
.styleDefST 
= wxStaticText(id=wxID_STCSTYLEEDITDLGSTYLEDEFST
, 
 152               label
='(nothing selected)', name
='styleDefST', parent
=self
, 
 153               pos
=wxPoint(96, 8), size
=wxSize(366, 16), 
 154               style
=wxST_NO_AUTORESIZE
) 
 155         self
.styleDefST
.SetFont(wxFont(self
.style_font_size
, wxSWISS
, wxNORMAL
, 
 157         self
.styleDefST
.SetConstraints(LayoutAnchors(self
.styleDefST
, True, 
 160         self
.staticLine1 
= wxStaticLine(id=wxID_STCSTYLEEDITDLGSTATICLINE1
, 
 161               name
='staticLine1', parent
=self
, pos
=wxPoint(48, 62), 
 162               size
=wxSize(120, 2), style
=wxLI_HORIZONTAL
) 
 163         self
.staticLine1
.SetConstraints(LayoutAnchors(self
.staticLine1
, True, 
 166         self
.staticText6 
= wxStaticText(id=wxID_STCSTYLEEDITDLGSTATICTEXT6
, 
 167               label
='Style', name
='staticText6', parent
=self
, pos
=wxPoint(8, 
 168               56), size
=wxSize(40, 13), style
=0) 
 170         self
.staticText8 
= wxStaticText(id=wxID_STCSTYLEEDITDLGSTATICTEXT8
, 
 171               label
='Style def:', name
='staticText8', parent
=self
, 
 172               pos
=wxPoint(8, 8), size
=wxSize(88, 13), style
=0) 
 174         self
.staticText9 
= wxStaticText(id=wxID_STCSTYLEEDITDLGSTATICTEXT9
, 
 175               label
='SpeedSetting:', name
='staticText9', parent
=self
, 
 176               pos
=wxPoint(8, 32), size
=wxSize(88, 13), style
=0) 
 178         self
.panel3 
= wxPanel(id=wxID_STCSTYLEEDITDLGPANEL3
, name
='panel3', 
 179               parent
=self
, pos
=wxPoint(176, 56), size
=wxSize(146, 104), 
 180               style
=wxTAB_TRAVERSAL
) 
 181         self
.panel3
.SetConstraints(LayoutAnchors(self
.panel3
, False, True, True, 
 184         self
.panel4 
= wxPanel(id=wxID_STCSTYLEEDITDLGPANEL4
, name
='panel4', 
 185               parent
=self
, pos
=wxPoint(330, 56), size
=wxSize(114, 104), 
 186               style
=wxTAB_TRAVERSAL
) 
 187         self
.panel4
.SetConstraints(LayoutAnchors(self
.panel4
, False, True, True, 
 190         self
.panel1 
= wxPanel(id=wxID_STCSTYLEEDITDLGPANEL1
, name
='panel1', 
 191               parent
=self
, pos
=wxPoint(176, 161), size
=wxSize(143, 40), 
 192               style
=wxTAB_TRAVERSAL
) 
 193         self
.panel1
.SetConstraints(LayoutAnchors(self
.panel1
, False, True, True, 
 196         self
.panel2 
= wxPanel(id=wxID_STCSTYLEEDITDLGPANEL2
, name
='panel2', 
 197               parent
=self
, pos
=wxPoint(330, 162), size
=wxSize(112, 40), 
 198               style
=wxTAB_TRAVERSAL
) 
 199         self
.panel2
.SetConstraints(LayoutAnchors(self
.panel2
, False, True, True, 
 202         self
.stc 
= wxStyledTextCtrl(id=wxID_STCSTYLEEDITDLGSTC
, name
='stc', 
 203               parent
=self
, pos
=wxPoint(8, 208), size
=wxSize(435, 207), 
 204               style
=wxSUNKEN_BORDER
) 
 205         self
.stc
.SetConstraints(LayoutAnchors(self
.stc
, True, True, True, True)) 
 206         self
.stc
.SetHelpText('The style preview window. Click or move the cursor over a spesific style to select the style for editing in the editors above.') 
 207         EVT_LEFT_UP(self
.stc
, self
.OnUpdateUI
) 
 208         EVT_KEY_UP(self
.stc
, self
.OnUpdateUI
) 
 210         self
.contextHelpButton1 
= wxContextHelpButton(parent
=self
, 
 211               pos
=wxPoint(8, 423), size
=wxSize(24, 24), style
=wxBU_AUTODRAW
) 
 212         self
.contextHelpButton1
.SetConstraints(LayoutAnchors(self
.contextHelpButton1
, 
 213               True, False, False, True)) 
 215         self
.okBtn 
= wxButton(id=wxID_STCSTYLEEDITDLGOKBTN
, label
='OK', 
 216               name
='okBtn', parent
=self
, pos
=wxPoint(282, 423), size
=wxSize(75, 
 218         self
.okBtn
.SetConstraints(LayoutAnchors(self
.okBtn
, False, False, True, 
 220         self
.okBtn
.SetToolTipString('Save changes to the config file') 
 221         EVT_BUTTON(self
.okBtn
, wxID_STCSTYLEEDITDLGOKBTN
, self
.OnOkbtnButton
) 
 223         self
.cancelBtn 
= wxButton(id=wxID_STCSTYLEEDITDLGCANCELBTN
, 
 224               label
='Cancel', name
='cancelBtn', parent
=self
, pos
=wxPoint(366, 
 225               423), size
=wxSize(75, 23), style
=0) 
 226         self
.cancelBtn
.SetConstraints(LayoutAnchors(self
.cancelBtn
, False, 
 228         self
.cancelBtn
.SetToolTipString('Close dialog without saving changes') 
 229         EVT_BUTTON(self
.cancelBtn
, wxID_STCSTYLEEDITDLGCANCELBTN
, 
 230               self
.OnCancelbtnButton
) 
 232         self
.staticText4 
= wxStaticText(id=wxID_STCSTYLEEDITDLGSTATICTEXT4
, 
 233               label
='Face:', name
='staticText4', parent
=self
.panel1
, 
 234               pos
=wxPoint(0, 0), size
=wxSize(48, 13), style
=0) 
 236         self
.fixedWidthChk 
= wxCheckBox(id=wxID_STCSTYLEEDITDLGFIXEDWIDTHCHK
, 
 237               label
='', name
='fixedWidthChk', parent
=self
.panel1
, pos
=wxPoint(0, 
 238               23), size
=wxSize(13, 19), style
=0) 
 239         self
.fixedWidthChk
.SetToolTipString('Check this for Fixed Width fonts') 
 240         EVT_CHECKBOX(self
.fixedWidthChk
, wxID_STCSTYLEEDITDLGFIXEDWIDTHCHK
, 
 241               self
.OnFixedwidthchkCheckbox
) 
 243         self
.faceCb 
= wxComboBox(choices
=[], id=wxID_STCSTYLEEDITDLGFACECB
, 
 244               name
='faceCb', parent
=self
.panel1
, pos
=wxPoint(17, 18), 
 245               size
=wxSize(105, 21), style
=0, validator
=wxDefaultValidator
, 
 248         self
.staticText7 
= wxStaticText(id=wxID_STCSTYLEEDITDLGSTATICTEXT7
, 
 249               label
='Size:', name
='staticText7', parent
=self
.panel2
, 
 250               pos
=wxPoint(0, 0), size
=wxSize(40, 13), style
=0) 
 252         self
.sizeCb 
= wxComboBox(choices
=[], id=wxID_STCSTYLEEDITDLGSIZECB
, 
 253               name
='sizeCb', parent
=self
.panel2
, pos
=wxPoint(0, 17), 
 254               size
=wxSize(91, 21), style
=0, validator
=wxDefaultValidator
, 
 257         self
.sizeOkBtn 
= wxButton(id=wxID_STCSTYLEEDITDLGSIZEOKBTN
, label
='ok', 
 258               name
='sizeOkBtn', parent
=self
.panel2
, pos
=wxPoint(90, 17), 
 259               size
=wxSize(21, 21), style
=0) 
 261         self
.faceOkBtn 
= wxButton(id=wxID_STCSTYLEEDITDLGFACEOKBTN
, label
='ok', 
 262               name
='faceOkBtn', parent
=self
.panel1
, pos
=wxPoint(122, 18), 
 263               size
=wxSize(21, 21), style
=0) 
 265         self
.fgColBtn 
= wxButton(id=wxID_STCSTYLEEDITDLGFGCOLBTN
, 
 266               label
='Foreground', name
='fgColBtn', parent
=self
.panel3
, 
 267               pos
=wxPoint(8, 16), size
=wxSize(72, 16), style
=0) 
 268         EVT_BUTTON(self
.fgColBtn
, wxID_STCSTYLEEDITDLGFGCOLBTN
, 
 269               self
.OnFgcolbtnButton
) 
 271         self
.fgColCb 
= wxComboBox(choices
=[], id=wxID_STCSTYLEEDITDLGFGCOLCB
, 
 272               name
='fgColCb', parent
=self
.panel3
, pos
=wxPoint(8, 32), 
 273               size
=wxSize(89, 21), style
=0, validator
=wxDefaultValidator
, 
 276         self
.fgColOkBtn 
= wxButton(id=wxID_STCSTYLEEDITDLGFGCOLOKBTN
, 
 277               label
='ok', name
='fgColOkBtn', parent
=self
.panel3
, pos
=wxPoint(96, 
 278               32), size
=wxSize(21, 21), style
=0) 
 280         self
.staticText3 
= wxStaticText(id=wxID_STCSTYLEEDITDLGSTATICTEXT3
, 
 281               label
='default', name
='staticText3', parent
=self
.panel3
, 
 282               pos
=wxPoint(100, 16), size
=wxSize(37, 16), style
=0) 
 284         self
.fgColDefCb 
= wxCheckBox(id=wxID_STCSTYLEEDITDLGFGCOLDEFCB
, 
 285               label
='checkBox1', name
='fgColDefCb', parent
=self
.panel3
, 
 286               pos
=wxPoint(120, 31), size
=wxSize(16, 16), style
=0) 
 288         self
.bgColBtn 
= wxButton(id=wxID_STCSTYLEEDITDLGBGCOLBTN
, 
 289               label
='Background', name
='bgColBtn', parent
=self
.panel3
, 
 290               pos
=wxPoint(8, 56), size
=wxSize(72, 16), style
=0) 
 291         EVT_BUTTON(self
.bgColBtn
, wxID_STCSTYLEEDITDLGBGCOLBTN
, 
 292               self
.OnBgcolbtnButton
) 
 294         self
.bgColCb 
= wxComboBox(choices
=[], id=wxID_STCSTYLEEDITDLGBGCOLCB
, 
 295               name
='bgColCb', parent
=self
.panel3
, pos
=wxPoint(8, 72), 
 296               size
=wxSize(89, 21), style
=0, validator
=wxDefaultValidator
, 
 299         self
.bgColOkBtn 
= wxButton(id=wxID_STCSTYLEEDITDLGBGCOLOKBTN
, 
 300               label
='ok', name
='bgColOkBtn', parent
=self
.panel3
, pos
=wxPoint(96, 
 301               72), size
=wxSize(21, 21), style
=0) 
 303         self
.staticBox2 
= wxStaticBox(id=wxID_STCSTYLEEDITDLGSTATICBOX2
, 
 304               label
='Text attributes', name
='staticBox2', parent
=self
.panel4
, 
 305               pos
=wxPoint(0, 0), size
=wxSize(112, 99), style
=0) 
 306         self
.staticBox2
.SetConstraints(LayoutAnchors(self
.staticBox2
, False, 
 308         self
.staticBox2
.SetHelpText('Text attribute flags.') 
 310         self
.staticText2 
= wxStaticText(id=wxID_STCSTYLEEDITDLGSTATICTEXT2
, 
 311               label
='default', name
='staticText2', parent
=self
.panel4
, 
 312               pos
=wxPoint(68, 11), size
=wxSize(37, 16), style
=0) 
 314         self
.taBoldDefCb 
= wxCheckBox(id=wxID_STCSTYLEEDITDLGTABOLDDEFCB
, 
 315               label
='checkBox1', name
='taBoldDefCb', parent
=self
.panel4
, 
 316               pos
=wxPoint(88, 27), size
=wxSize(16, 16), style
=0) 
 318         self
.taItalicDefCb 
= wxCheckBox(id=wxID_STCSTYLEEDITDLGTAITALICDEFCB
, 
 319               label
='checkBox1', name
='taItalicDefCb', parent
=self
.panel4
, 
 320               pos
=wxPoint(88, 43), size
=wxSize(16, 16), style
=0) 
 322         self
.taUnderlinedDefCb 
= wxCheckBox(id=wxID_STCSTYLEEDITDLGTAUNDERLINEDDEFCB
, 
 323               label
='checkBox1', name
='taUnderlinedDefCb', parent
=self
.panel4
, 
 324               pos
=wxPoint(88, 59), size
=wxSize(16, 16), style
=0) 
 326         self
.taEOLfilledDefCb 
= wxCheckBox(id=wxID_STCSTYLEEDITDLGTAEOLFILLEDDEFCB
, 
 327               label
='checkBox1', name
='taEOLfilledDefCb', parent
=self
.panel4
, 
 328               pos
=wxPoint(88, 75), size
=wxSize(16, 16), style
=0) 
 330         self
.taEOLfilledCb 
= wxCheckBox(id=wxID_STCSTYLEEDITDLGTAEOLFILLEDCB
, 
 331               label
='EOL filled', name
='taEOLfilledCb', parent
=self
.panel4
, 
 332               pos
=wxPoint(8, 75), size
=wxSize(72, 16), style
=0) 
 333         EVT_CHECKBOX(self
.taEOLfilledCb
, wxID_STCSTYLEEDITDLGTAEOLFILLEDCB
, 
 334               self
.OnTaeoffilledcbCheckbox
) 
 336         self
.taUnderlinedCb 
= wxCheckBox(id=wxID_STCSTYLEEDITDLGTAUNDERLINEDCB
, 
 337               label
='Underlined', name
='taUnderlinedCb', parent
=self
.panel4
, 
 338               pos
=wxPoint(8, 59), size
=wxSize(72, 16), style
=0) 
 339         EVT_CHECKBOX(self
.taUnderlinedCb
, wxID_STCSTYLEEDITDLGTAUNDERLINEDCB
, 
 340               self
.OnTaunderlinedcbCheckbox
) 
 342         self
.taItalicCb 
= wxCheckBox(id=wxID_STCSTYLEEDITDLGTAITALICCB
, 
 343               label
='Italic', name
='taItalicCb', parent
=self
.panel4
, 
 344               pos
=wxPoint(8, 43), size
=wxSize(72, 16), style
=0) 
 345         EVT_CHECKBOX(self
.taItalicCb
, wxID_STCSTYLEEDITDLGTAITALICCB
, 
 346               self
.OnTaitaliccbCheckbox
) 
 348         self
.taBoldCb 
= wxCheckBox(id=wxID_STCSTYLEEDITDLGTABOLDCB
, 
 349               label
='Bold', name
='taBoldCb', parent
=self
.panel4
, pos
=wxPoint(8, 
 350               27), size
=wxSize(72, 16), style
=0) 
 351         EVT_CHECKBOX(self
.taBoldCb
, wxID_STCSTYLEEDITDLGTABOLDCB
, 
 352               self
.OnTaboldcbCheckbox
) 
 354         self
.bgColDefCb 
= wxCheckBox(id=wxID_STCSTYLEEDITDLGBGCOLDEFCB
, 
 355               label
='checkBox1', name
='bgColDefCb', parent
=self
.panel3
, 
 356               pos
=wxPoint(120, 71), size
=wxSize(16, 16), style
=0) 
 358         self
.staticBox1 
= wxStaticBox(id=wxID_STCSTYLEEDITDLGSTATICBOX1
, 
 359               label
='Colour', name
='staticBox1', parent
=self
.panel3
, 
 360               pos
=wxPoint(0, 0), size
=wxSize(142, 99), style
=0) 
 361         self
.staticBox1
.SetConstraints(LayoutAnchors(self
.staticBox1
, False, 
 364         self
.faceDefCb 
= wxCheckBox(id=wxID_STCSTYLEEDITDLGFACEDEFCB
, 
 365               label
='checkBox1', name
='faceDefCb', parent
=self
.panel1
, 
 366               pos
=wxPoint(120, 0), size
=wxSize(16, 16), style
=0) 
 368         self
.taSizeDefCb 
= wxCheckBox(id=wxID_STCSTYLEEDITDLGTASIZEDEFCB
, 
 369               label
='checkBox1', name
='taSizeDefCb', parent
=self
.panel2
, 
 370               pos
=wxPoint(88, 0), size
=wxSize(16, 16), style
=0) 
 372     def __init__(self
, parent
, langTitle
, lang
, configFile
, STCsToUpdate
=()): 
 373         self
.stc_title 
= 'wxStyledTextCtrl Style Editor' 
 374         self
.stc_title 
= 'wxStyledTextCtrl Style Editor - %s' % langTitle
 
 375         if wxPlatform 
== '__WXMSW__': 
 376             self
.style_font_size 
= 8 
 378             self
.style_font_size 
= 10 
 379         self
._init
_ctrls
(parent
) 
 381         self
.configFile 
= configFile
 
 386         self
.STCsToUpdate 
= STCsToUpdate
 
 387         self
._blockUpdate 
= False 
 390         for combo
, okBtn
, evtRet
, evtCB
, evtRDC 
in ( 
 391          (self
.fgColCb
, self
.fgColOkBtn
, self
.OnfgColRet
, self
.OnfgColCombobox
, self
.OnGotoCommonDef
), 
 392          (self
.bgColCb
, self
.bgColOkBtn
, self
.OnbgColRet
, self
.OnbgColCombobox
, self
.OnGotoCommonDef
), 
 393          (self
.faceCb
, self
.faceOkBtn
, self
.OnfaceRet
, self
.OnfaceCombobox
, self
.OnGotoCommonDef
), 
 394          (self
.sizeCb
, self
.sizeOkBtn
, self
.OnsizeRet
, self
.OnsizeCombobox
, self
.OnGotoCommonDef
)): 
 395             self
.bindComboEvts(combo
, okBtn
, evtRet
, evtCB
, evtRDC
) 
 397         (self
.config
, self
.commonDefs
, self
.styleIdNames
, self
.styles
, 
 398          self
.styleGroupNames
, self
.predefStyleGroups
, 
 399          self
.otherLangStyleGroupNames
, self
.otherLangStyleGroups
, 
 400          self
.displaySrc
, self
.lexer
, self
.keywords
, self
.braceInfo
) = \
 
 401               initFromConfig(configFile
, lang
) 
 403         self
.currSpeedSetting 
= 'style.%s'%self
.lang
 
 404         for grp 
in [self
.currSpeedSetting
]+self
.styleGroupNames
: 
 405             self
.speedsettingCh
.Append(grp
) 
 406         self
.speedsettingCh
.SetSelection(0) 
 409         self
.stc
.SetMarginType(margin
, wxSTC_MARGIN_NUMBER
) 
 410         self
.stc
.SetMarginWidth(margin
, 25) 
 411         self
.stc
.SetMarginSensitive(margin
, True) 
 412         EVT_STC_MARGINCLICK(self
.stc
, wxID_STCSTYLEEDITDLGSTC
, self
.OnMarginClick
) 
 414         self
.stc
.SetUseTabs(False) 
 415         self
.stc
.SetTabWidth(4) 
 416         self
.stc
.SetIndentationGuides(True) 
 417         self
.stc
.SetEdgeMode(wxSTC_EDGE_BACKGROUND
) 
 418         self
.stc
.SetEdgeColumn(44) 
 422         self
.populateStyleSelector() 
 424         self
.defNames
, self
.defValues 
= parseProp(\
 
 425               self
.styleDict
.get(wxSTC_STYLE_DEFAULT
, '')) 
 426         self
.stc
.SetText(self
.displaySrc
) 
 427         self
.stc
.EmptyUndoBuffer() 
 428         self
.stc
.SetCurrentPos(self
.stc
.GetTextLength()) 
 429         self
.stc
.SetAnchor(self
.stc
.GetTextLength()) 
 431         self
.populateCombosWithCommonDefs() 
 433         # Logical grouping of controls and the property they edit 
 434         self
.allCtrls 
= [((self
.fgColBtn
, self
.fgColCb
, self
.fgColOkBtn
), self
.fgColDefCb
, 
 435                              'fore', wxID_STCSTYLEEDITDLGFGCOLDEFCB
), 
 436                          ((self
.bgColBtn
, self
.bgColCb
, self
.bgColOkBtn
), self
.bgColDefCb
, 
 437                              'back', wxID_STCSTYLEEDITDLGBGCOLDEFCB
), 
 438                          (self
.taBoldCb
, self
.taBoldDefCb
, 
 439                              'bold', wxID_STCSTYLEEDITDLGTABOLDDEFCB
), 
 440                          (self
.taItalicCb
, self
.taItalicDefCb
, 
 441                              'italic', wxID_STCSTYLEEDITDLGTAITALICDEFCB
), 
 442                          (self
.taUnderlinedCb
, self
.taUnderlinedDefCb
, 
 443                              'underline', wxID_STCSTYLEEDITDLGTAUNDERLINEDDEFCB
), 
 444                          (self
.taEOLfilledCb
, self
.taEOLfilledDefCb
, 
 445                              'eolfilled', wxID_STCSTYLEEDITDLGTAEOLFILLEDDEFCB
), 
 446                          ((self
.sizeCb
, self
.sizeOkBtn
), self
.taSizeDefCb
, 
 447                              'size', wxID_STCSTYLEEDITDLGTASIZEDEFCB
), 
 448                          ((self
.faceCb
, self
.faceOkBtn
, self
.fixedWidthChk
), self
.faceDefCb
, 
 449                              'face', wxID_STCSTYLEEDITDLGFACEDEFCB
)] 
 451         self
.clearCtrls(disableDefs
=True) 
 452         # centralised default checkbox event handler 
 454         for ctrl
, chb
, prop
, wid 
in self
.allCtrls
: 
 455             self
.chbIdMap
[wid
] = ctrl
, chb
, prop
, wid
 
 456             EVT_CHECKBOX(chb
, wid
, self
.OnDefaultCheckBox
) 
 457             chb
.SetToolTipString('Toggle defaults') 
 461 #---Property methods------------------------------------------------------------ 
 462     def getCtrlForProp(self
, findprop
): 
 463         for ctrl
, chb
, prop
, wid 
in self
.allCtrls
: 
 466         raise Exception('PropNotFound', findprop
) 
 468     def editProp(self
, on
, prop
, val
=''): 
 469         oldstyle 
= self
.rememberStyles() 
 471             if not self
.names
.count(prop
): 
 472                 self
.names
.append(prop
) 
 473             self
.values
[prop
] = val
 
 475             try: self
.names
.remove(prop
) 
 476             except ValueError: pass 
 477             try: del self
.values
[prop
] 
 478             except KeyError: pass 
 483         except KeyError, errkey
: 
 484             wxLogError('Name not found in Common definition, '\
 
 485                 'please enter valid reference. (%s)'%errkey
) 
 486             self
.restoreStyles(oldstyle
) 
 489 #---Control population methods-------------------------------------------------- 
 491         if self
._blockUpdate
: return 
 492         self
.styles
, self
.styleDict
, self
.styleNumIdxMap 
= \
 
 493               setSTCStyles(self
.stc
, self
.styles
, self
.styleIdNames
, 
 494               self
.commonDefs
, self
.lang
, self
.lexer
, self
.keywords
) 
 496     def updateStyle(self
): 
 497         # called after a control edited self.names, self.values 
 498         # Special case for saving common defs settings 
 499         if self
.styleNum 
== 'common': 
 500             strVal 
= self
.style
[2] = self
.values
.values()[0] 
 501             if self
.style
[1] == 'size': self
.style
[2] = int(strVal
) 
 503             self
.commonDefs
[self
.style
[0]] = self
.style
[2] 
 504             self
.styleDefST
.SetLabel(strVal
) 
 506             self
.style 
= writePropVal(self
.names
, self
.values
) 
 507             styleDecl 
= writeProp(self
.styleNum
, self
.style
, self
.lang
) 
 508             self
.styles
[self
.styleNumIdxMap
[self
.styleNum
]] = styleDecl
 
 509             self
.styleDefST
.SetLabel(self
.style
) 
 512     def findInStyles(self
, txt
, styles
): 
 514             if string
.find(style
, txt
) != -1: 
 518     def rememberStyles(self
): 
 519         return self
.names
[:], copy
.copy(self
.values
) 
 521     def restoreStyles(self
, style
): 
 522         self
.names
, self
.values 
= style
 
 525     def clearCtrls(self
, isDefault
=False, disableDefs
=False): 
 526         self
._blockUpdate 
= True 
 528             for ctrl
, chb
, prop
, wid 
in self
.allCtrls
: 
 529                 if prop 
in ('fore', 'back'): 
 530                     cbtn
, txt
, btn 
= ctrl
 
 531                     cbtn
.SetBackgroundColour(\
 
 532                           wxSystemSettings_GetSystemColour(wxSYS_COLOUR_BTNFACE
)) 
 533                     cbtn
.SetForegroundColour(wxColour(255, 255, 255)) 
 534                     cbtn
.Enable(isDefault
) 
 536                     txt
.Enable(isDefault
) 
 537                     btn
.Enable(isDefault
) 
 541                     cmb
.Enable(isDefault
) 
 542                     btn
.Enable(isDefault
) 
 546                     cmb
.Enable(isDefault
) 
 547                     btn
.Enable(isDefault
) 
 548                     chk
.Enable(isDefault
) 
 550                 elif prop 
in ('bold', 'italic', 'underline', 'eolfilled'): 
 552                     ctrl
.Enable(isDefault
) 
 554                 chb
.Enable(not isDefault 
and not disableDefs
) 
 557             self
._blockUpdate 
= False 
 559     def populateProp(self
, items
, default
, forceDisable
=False): 
 560         self
._blockUpdate 
= True 
 562             for name
, val 
in items
: 
 564                     ctrl
, chb 
= self
.getCtrlForProp(name
) 
 566                     if name 
in ('fore', 'back'): 
 567                         cbtn
, txt
, btn 
= ctrl
 
 568                         repval 
= val
%self
.commonDefs
 
 569                         cbtn
.SetBackgroundColour(strToCol(repval
)) 
 570                         cbtn
.SetForegroundColour(wxColour(0, 0, 0)) 
 571                         cbtn
.Enable(not forceDisable
) 
 573                         txt
.Enable(not forceDisable
) 
 574                         btn
.Enable(not forceDisable
) 
 575                         chb
.SetValue(default
) 
 579                         cmb
.Enable(not forceDisable
) 
 580                         btn
.Enable(not forceDisable
) 
 581                         chb
.SetValue(default
) 
 585                         cmb
.Enable(not forceDisable
) 
 586                         btn
.Enable(not forceDisable
) 
 587                         chk
.Enable(not forceDisable
) 
 588                         chb
.SetValue(default
) 
 589                     elif name 
in ('bold', 'italic', 'underline', 'eolfilled'): 
 590                         ctrl
.Enable(not forceDisable
) 
 592                         chb
.SetValue(default
) 
 594             self
._blockUpdate 
= False 
 596     def valIsCommonDef(self
, val
): 
 597         return len(val
) >= 5 and val
[:2] == '%(' 
 599     def populateCtrls(self
): 
 600         self
.clearCtrls(self
.styleNum 
== wxSTC_STYLE_DEFAULT
, 
 601             disableDefs
=self
.styleNum 
< 0) 
 603         # handle colour controls for settings 
 604         if self
.styleNum 
< 0: 
 605             self
.fgColDefCb
.Enable(True) 
 606             if self
.styleNum 
== -1: 
 607                 self
.bgColDefCb
.Enable(True) 
 609         # populate with default style 
 610         self
.populateProp(self
.defValues
.items(), True, 
 611             self
.styleNum 
!= wxSTC_STYLE_DEFAULT
) 
 612         # override with current settings 
 613         self
.populateProp(self
.values
.items(), False) 
 615     def getCommonDefPropType(self
, commonDefName
): 
 616         val 
= self
.commonDefs
[commonDefName
] 
 617         if type(val
) == type(0): return 'size' 
 618         if len(val
) == 7 and val
[0] == '#': return 'fore' 
 621     def bindComboEvts(self
, combo
, btn
, btnEvtMeth
, comboEvtMeth
, rdclickEvtMeth
): 
 622         EVT_COMBOBOX(combo
, combo
.GetId(), comboEvtMeth
) 
 623         EVT_BUTTON(btn
, btn
.GetId(), btnEvtMeth
) 
 624         EVT_RIGHT_DCLICK(combo
, rdclickEvtMeth
) 
 625         combo
.SetToolTipString('Select from list or click "ok" button on the right to change a manual entry, right double-click \n'\
 
 626             'the drop down button to select Common definition in the Style Editor (if applicable)') 
 627         btn
.SetToolTipString('Accept value') 
 629     def populateCombosWithCommonDefs(self
, fixedWidthOnly
=None): 
 630         self
._blockUpdate 
= True 
 632             commonDefs 
= {'fore': [], 'face': [], 'size': []}
 
 634             if self
.elementLb
.GetSelection() < self
.commonDefsStartIdx
: 
 635                 for common 
in self
.commonDefs
.keys(): 
 636                     prop 
= self
.getCommonDefPropType(common
) 
 637                     commonDefs
[prop
].append('%%(%s)%s'%(common
, 
 638                                                        prop
=='size' and 'd' or 's')) 
 641             currFg
, currBg 
= self
.fgColCb
.GetValue(), self
.bgColCb
.GetValue() 
 642             self
.fgColCb
.Clear(); self
.bgColCb
.Clear() 
 643             for colCommonDef 
in commonDefs
['fore']: 
 644                 self
.fgColCb
.Append(colCommonDef
) 
 645                 self
.bgColCb
.Append(colCommonDef
) 
 646             self
.fgColCb
.SetValue(currFg
); self
.bgColCb
.SetValue(currBg
) 
 649             if fixedWidthOnly 
is None: 
 650                 fixedWidthOnly 
= self
.fixedWidthChk
.GetValue() 
 651             fontEnum 
= wxFontEnumerator() 
 652             fontEnum
.EnumerateFacenames(fixedWidthOnly
=fixedWidthOnly
) 
 653             fontNameList 
= fontEnum
.GetFacenames() 
 655             currFace 
= self
.faceCb
.GetValue() 
 657             for colCommonDef 
in ['']+fontNameList
+commonDefs
['face']: 
 658                 self
.faceCb
.Append(colCommonDef
) 
 659             self
.faceCb
.SetValue(currFace
) 
 661             # Size (XXX add std font sizes) 
 662             currSize 
= self
.sizeCb
.GetValue() 
 664             for colCommonDef 
in commonDefs
['size']: 
 665                 self
.sizeCb
.Append(colCommonDef
) 
 666             self
.sizeCb
.SetValue(currSize
) 
 668             self
._blockUpdate 
= False 
 670     def populateStyleSelector(self
): 
 671         numStyles 
= self
.styleIdNames
.items() 
 673         self
.styleNumLookup 
= {} 
 678         for num
, name 
in numStyles
: 
 679             if num 
== wxSTC_STYLE_DEFAULT
: 
 680                 self
.elementLb
.InsertItems([name
, '----Language----'], 0) 
 681                 self
.elementLb
.Append('----Standard----') 
 682                 stdStart 
= stdPos 
= self
.elementLb
.GetCount() 
 685                 if num 
>= 33 and num 
< 40: 
 686                     self
.elementLb
.InsertItems([name
], stdStart 
+ stdOffset
) 
 687                     stdOffset 
= stdOffset 
+ 1 
 690                     self
.elementLb
.InsertItems([name
], stdStart 
+ extrOffset 
-1) 
 691                     extrOffset 
= extrOffset 
+ 1 
 694                     self
.elementLb
.Append(name
) 
 695             self
.styleNumLookup
[name
] = num
 
 698         self
.elementLb
.Append('----Settings----') 
 699         settings 
= settingsIdNames
.items() 
 700         settings
.sort();settings
.reverse() 
 701         for num
, name 
in settings
: 
 702             self
.elementLb
.Append(name
) 
 703             self
.styleNumLookup
[name
] = num
 
 706         self
.elementLb
.Append('----Common----') 
 707         self
.commonDefsStartIdx 
= self
.elementLb
.GetCount() 
 708         for common 
in self
.commonDefs
.keys(): 
 709             tpe 
= type(self
.commonDefs
[common
]) 
 710             self
.elementLb
.Append('%('+common
+')'+(tpe 
is type('') and 's' or 'd')) 
 711             self
.styleNumLookup
[common
] = num
 
 713 #---Colour methods-------------------------------------------------------------- 
 714     def getColourDlg(self
, colour
, title
=''): 
 715         data 
= wxColourData() 
 716         data
.SetColour(colour
) 
 717         data
.SetChooseFull(True) 
 718         dlg 
= wxColourDialog(self
, data
) 
 721             if dlg
.ShowModal() == wxID_OK
: 
 722                 data 
= dlg
.GetColourData() 
 723                 return data
.GetColour() 
 728     colDlgTitles 
= {'fore': 'Foreground', 'back': 'Background'}
 
 729     def editColProp(self
, colBtn
, colCb
, prop
): 
 730         col 
= self
.getColourDlg(colBtn
.GetBackgroundColour(), 
 731               self
.colDlgTitles
[prop
]+ ' colour') 
 733             colBtn
.SetForegroundColour(wxColour(0, 0, 0)) 
 734             colBtn
.SetBackgroundColour(col
) 
 735             colStr 
= colToStr(col
) 
 736             colCb
.SetValue(colStr
) 
 737             self
.editProp(True, prop
, colStr
) 
 739     def OnFgcolbtnButton(self
, event
): 
 740         self
.editColProp(self
.fgColBtn
, self
.fgColCb
, 'fore') 
 742     def OnBgcolbtnButton(self
, event
): 
 743         self
.editColProp(self
.bgColBtn
, self
.bgColCb
, 'back') 
 745     def editColTCProp(self
, colCb
, colBtn
, prop
, val
=None): 
 747             colStr 
= colCb
.GetValue() 
 751             col 
= strToCol(colStr
%self
.commonDefs
) 
 752         if self
.editProp(colStr
!='', prop
, colStr
): 
 754                 colBtn
.SetForegroundColour(wxColour(0, 0, 0)) 
 755                 colBtn
.SetBackgroundColour(col
) 
 757                 colBtn
.SetForegroundColour(wxColour(255, 255, 255)) 
 758                 colBtn
.SetBackgroundColour(\
 
 759                       wxSystemSettings_GetSystemColour(wxSYS_COLOUR_BTNFACE
)) 
 761     def OnfgColRet(self
, event
): 
 762         try: self
.editColTCProp(self
.fgColCb
, self
.fgColBtn
, 'fore') 
 763         except AssertionError: wxLogError('Not a valid colour value') 
 765     def OnfgColCombobox(self
, event
): 
 766         if self
._blockUpdate
: return 
 767         try: self
.editColTCProp(self
.fgColCb
, self
.fgColBtn
, 'fore', event
.GetString()) 
 768         except AssertionError: wxLogError('Not a valid colour value') 
 770     def OnbgColRet(self
, event
): 
 771         try: self
.editColTCProp(self
.bgColCb
, self
.bgColBtn
, 'back') 
 772         except AssertionError: wxLogError('Not a valid colour value') 
 774     def OnbgColCombobox(self
, event
): 
 775         if self
._blockUpdate
: return 
 776         try: self
.editColTCProp(self
.bgColCb
, self
.bgColBtn
, 'back', event
.GetString()) 
 777         except AssertionError: wxLogError('Not a valid colour value') 
 779 #---Text attribute events------------------------------------------------------- 
 780     def OnTaeoffilledcbCheckbox(self
, event
): 
 781         self
.editProp(event
.IsChecked(), 'eolfilled') 
 783     def OnTaitaliccbCheckbox(self
, event
): 
 784         self
.editProp(event
.IsChecked(), 'italic') 
 786     def OnTaboldcbCheckbox(self
, event
): 
 787         self
.editProp(event
.IsChecked(), 'bold') 
 789     def OnTaunderlinedcbCheckbox(self
, event
): 
 790         self
.editProp(event
.IsChecked(), 'underline') 
 792     def OnGotoCommonDef(self
, event
): 
 793         val 
= event
.GetEventObject().GetValue() 
 794         if self
.valIsCommonDef(val
): 
 795             idx 
= self
.elementLb
.FindString(val
) 
 797                 self
.elementLb
.SetSelection(idx
, True) 
 798                 self
.OnElementlbListbox(None) 
 800     def OnfaceRet(self
, event
): 
 801         self
.setFace(self
.faceCb
.GetValue()) 
 803     def OnfaceCombobox(self
, event
): 
 804         if self
._blockUpdate
: return 
 805         self
.setFace(event
.GetString()) 
 807     def setFace(self
, val
): 
 808         try: val
%self
.commonDefs
 
 809         except KeyError: wxLogError('Invalid common definition') 
 810         else: self
.editProp(val
!='', 'face', val
) 
 812     def OnsizeRet(self
, event
): 
 813         self
.setSize(self
.sizeCb
.GetValue()) 
 815     def OnsizeCombobox(self
, event
): 
 816         if self
._blockUpdate
: return 
 817         self
.setSize(event
.GetString()) 
 819     def setSize(self
, val
): 
 820         try: int(val
%self
.commonDefs
) 
 821         except ValueError: wxLogError('Not a valid integer size value') 
 822         except KeyError: wxLogError('Invalid common definition') 
 823         else: self
.editProp(val
!='', 'size', val
) 
 825 #---Main GUI events------------------------------------------------------------- 
 826     def OnElementlbListbox(self
, event
): 
 827         isCommon 
= self
.elementLb
.GetSelection() >= self
.commonDefsStartIdx
 
 828         self
.removeCommonItemBtn
.Enable(isCommon
) 
 830         styleIdent 
= self
.elementLb
.GetStringSelection() 
 831         # common definition selected 
 833             common 
= styleIdent
[2:-2] 
 834             prop 
= self
.getCommonDefPropType(common
) 
 835             self
.clearCtrls(disableDefs
=True) 
 837                 self
.fgColBtn
.Enable(True) 
 838                 self
.fgColCb
.Enable(True) 
 839                 self
.fgColOkBtn
.Enable(True) 
 841                 self
.faceCb
.Enable(True) 
 842                 self
.fixedWidthChk
.Enable(True) 
 843                 self
.faceOkBtn
.Enable(True) 
 845                 self
.sizeCb
.Enable(True) 
 846                 self
.sizeOkBtn
.Enable(True) 
 848             commonDefVal 
= str(self
.commonDefs
[common
]) 
 849             self
.styleDefST
.SetLabel(commonDefVal
) 
 850             self
.populateProp( [(prop
, commonDefVal
)], True) 
 852             self
.styleNum 
= 'common' 
 853             self
.style 
= [common
, prop
, commonDefVal
] 
 854             self
.names
, self
.values 
= [prop
], {prop: commonDefVal}
 
 856         # normal style element selected 
 857         elif len(styleIdent
) >=2 and styleIdent
[:2] != '--': 
 858             self
.styleNum 
= self
.styleNumLookup
[styleIdent
] 
 859             self
.style 
= self
.styleDict
[self
.styleNum
] 
 860             self
.names
, self
.values 
= parseProp(self
.style
) 
 861             if self
.styleNum 
== wxSTC_STYLE_DEFAULT
: 
 862                 self
.defNames
, self
.defValues 
= \
 
 863                       self
.names
, self
.values
 
 865             self
.checkBraces(self
.styleNum
) 
 867             self
.styleDefST
.SetLabel(self
.style
) 
 872             self
.clearCtrls(disableDefs
=True) 
 874                 self
.styleDefST
.SetLabel(styleCategoryDescriptions
[styleIdent
]) 
 876         self
.populateCombosWithCommonDefs() 
 878     def OnDefaultCheckBox(self
, event
): 
 879         if self
.chbIdMap
.has_key(event
.GetId()): 
 880             ctrl
, chb
, prop
, wid 
= self
.chbIdMap
[event
.GetId()] 
 881             restore 
= not event
.IsChecked() 
 882             if prop 
in ('fore', 'back'): 
 883                 cbtn
, cmb
, btn 
= ctrl
 
 888                     colStr 
= cmb
.GetValue() 
 889                     #if prop == 'fore': colStr = self.fgColCb.GetValue() 
 890                     #else: colStr = self.bgColCb.GetValue() 
 891                     if colStr
: self
.editProp(True, prop
, colStr
) 
 893                     self
.editProp(False, prop
) 
 897                 if val
: self
.editProp(restore
, prop
, val
) 
 902                 val 
= cmb
.GetStringSelection() 
 903                 if val
: self
.editProp(restore
, prop
, val
) 
 907             elif prop 
in ('bold', 'italic', 'underline', 'eolfilled'): 
 909                 if ctrl
.GetValue(): self
.editProp(restore
, prop
) 
 911     def OnOkbtnButton(self
, event
): 
 912         # write styles and common defs to the config 
 915             writeStylesToConfig(self
.config
, 'style.%s'%self
.lang
, self
.styles
) 
 916             self
.config
.SetPath('') 
 917             self
.config
.Write(commonDefsFile
, `self
.commonDefs`
) 
 920             for stc 
in self
.STCsToUpdate
: 
 921                 setSTCStyles(stc
, self
.styles
, self
.styleIdNames
, self
.commonDefs
, 
 922                       self
.lang
, self
.lexer
, self
.keywords
) 
 925         self
.EndModal(wxID_OK
) 
 927     def OnCancelbtnButton(self
, event
): 
 928         self
.EndModal(wxID_CANCEL
) 
 930     def OnCommondefsbtnButton(self
, event
): 
 931         dlg 
= wxTextEntryDialog(self
, 'Edit common definitions dictionary', 
 932               'Common definitions', pprint
.pformat(self
.commonDefs
), 
 933               style
=wxTE_MULTILINE | wxOK | wxCANCEL | wxCENTRE
) 
 935             if dlg
.ShowModal() == wxID_OK
: 
 936                 answer 
= eval(dlg
.GetValue()) 
 937                 assert type(answer
) is type({}), 'Not a valid dictionary' 
 938                 oldDefs 
= self
.commonDefs
 
 939                 self
.commonDefs 
= answer
 
 942                 except KeyError, badkey
: 
 943                     wxLogError(str(badkey
)+' not defined but required, \n'\
 
 944                           'reverting to previous common definition') 
 945                     self
.commonDefs 
= oldDefs
 
 947                 self
.populateCombosWithCommonDefs() 
 952     def OnSpeedsettingchChoice(self
, event
): 
 953         group 
= event
.GetString() 
 955             userStyles 
= 'style.%s'%self
.lang
 
 956             if self
.currSpeedSetting 
== userStyles
: 
 957                 self
.predefStyleGroups
[userStyles
] = self
.styles
 
 958             self
.styles 
= self
.predefStyleGroups
[group
] 
 960             self
.defNames
, self
.defValues 
= parseProp(\
 
 961                   self
.styleDict
.get(wxSTC_STYLE_DEFAULT
, '')) 
 962             self
.OnElementlbListbox(None) 
 963             self
.currSpeedSetting 
= group
 
 965     def OnFixedwidthchkCheckbox(self
, event
): 
 966         self
.populateCombosWithCommonDefs(event
.Checked()) 
 968     def OnAddsharebtnButton(self
, event
): 
 969         dlg 
= CommonDefDlg(self
) 
 971             if dlg
.ShowModal() == wxID_OK
: 
 972                 prop
, name 
= dlg
.result
 
 973                 if not self
.commonDefs
.has_key(name
): 
 974                     self
.commonDefs
[name
] = commonPropDefs
[prop
] 
 975                     self
.elementLb
.Append('%('+name
+')'+\
 
 976                      (type(commonPropDefs
[prop
]) is type('') and 's' or 'd')) 
 977                     self
.elementLb
.SetSelection(self
.elementLb
.GetCount()-1, True) 
 978                     self
.populateCombosWithCommonDefs() 
 979                     self
.OnElementlbListbox(None) 
 983     def OnRemovesharebtnButton(self
, event
): 
 984         ownGroup 
= 'style.%s'%self
.lang
 
 985         comDef 
= self
.elementLb
.GetStringSelection() 
 987         # Search ALL styles before removing 
 988         srchDct 
= {ownGroup: self.styles}
 
 989         srchDct
.update(self
.predefStyleGroups
) 
 990         srchDct
.update(self
.otherLangStyleGroups
) 
 993         for grpName
, styles 
in srchDct
.items(): 
 994             if self
.findInStyles(comDef
, styles
): 
 995                 matchList
.append(grpName
) 
 998             wxLogError('Aborted: '+comDef
+' is still used in the styles of the \n'\
 
 999                   'following groups in the config file (stc-styles.rc.cfg):\n'+ \
 
1000                   string
.join(matchList
, '\n')) 
1002             del self
.commonDefs
[comDef
[2:-2]] 
1004             self
.populateCombosWithCommonDefs() 
1005             selIdx 
= self
.elementLb
.GetSelection() 
1006             self
.elementLb
.Delete(selIdx
) 
1007             if selIdx 
== self
.elementLb
.GetCount(): 
1009             self
.elementLb
.SetSelection(selIdx
, True) 
1010             self
.OnElementlbListbox(None) 
1012 #---STC events------------------------------------------------------------------ 
1013     def OnUpdateUI(self
, event
): 
1014         styleBefore 
= self
.stc
.GetStyleAt(self
.stc
.GetCurrentPos()) 
1015         if self
.styleIdNames
.has_key(styleBefore
): 
1016             self
.elementLb
.SetStringSelection(self
.styleIdNames
[styleBefore
], 
1019             self
.elementLb
.SetSelection(0, False) 
1020             self
.styleDefST
.SetLabel('Style %d not defined, sorry.'%styleBefore
) 
1021         self
.OnElementlbListbox(None) 
1024     def checkBraces(self
, style
): 
1025         if style 
== wxSTC_STYLE_BRACELIGHT 
and self
.braceInfo
.has_key('good'): 
1026             line
, col 
= self
.braceInfo
['good'] 
1027             pos 
= self
.stc
.PositionFromLine(line
-1) + col
 
1028             braceOpposite 
= self
.stc
.BraceMatch(pos
) 
1029             if braceOpposite 
!= -1: 
1030                 self
.stc
.BraceHighlight(pos
, braceOpposite
) 
1031         elif style 
== wxSTC_STYLE_BRACEBAD 
and self
.braceInfo
.has_key('bad'): 
1032             line
, col 
= self
.braceInfo
['bad'] 
1033             pos 
= self
.stc
.PositionFromLine(line
-1) + col
 
1034             self
.stc
.BraceBadLight(pos
) 
1036             self
.stc
.BraceBadLight(-1) 
1039     def OnStcstyleeditdlgSize(self
, event
): 
1041         # Without this refresh, resizing leaves artifacts 
1045     def OnMarginClick(self
, event
): 
1046         self
.elementLb
.SetStringSelection('Line numbers', True) 
1047         self
.OnElementlbListbox(None) 
1050 #---Common definition dialog---------------------------------------------------- 
1052 [wxID_COMMONDEFDLG
, wxID_COMMONDEFDLGCANCELBTN
, wxID_COMMONDEFDLGCOMDEFNAMETC
, wxID_COMMONDEFDLGOKBTN
, wxID_COMMONDEFDLGPROPTYPERBX
, wxID_COMMONDEFDLGSTATICBOX1
] = map(lambda _init_ctrls
: wxNewId(), range(6)) 
1054 class CommonDefDlg(wxDialog
): 
1055     def _init_ctrls(self
, prnt
): 
1056         wxDialog
.__init
__(self
, id = wxID_COMMONDEFDLG
, name 
= 'CommonDefDlg', parent 
= prnt
, pos 
= wxPoint(398, 249), size 
= wxSize(192, 220), style 
= wxDEFAULT_DIALOG_STYLE
, title 
= 'Common definition') 
1057         self
.SetClientSize(wxSize(184, 200)) 
1059         self
.propTypeRBx 
= wxRadioBox(choices 
= ['Colour value', 'Font face', 'Size value'], id = wxID_COMMONDEFDLGPROPTYPERBX
, label 
= 'Property type', majorDimension 
= 1, name 
= 'propTypeRBx', parent 
= self
, point 
= wxPoint(8, 8), size 
= wxSize(168, 92), style 
= wxRA_SPECIFY_COLS
, validator 
= wxDefaultValidator
) 
1060         self
.propTypeRBx
.SetSelection(self
._propTypeIdx
) 
1062         self
.staticBox1 
= wxStaticBox(id = wxID_COMMONDEFDLGSTATICBOX1
, label 
= 'Name', name 
= 'staticBox1', parent 
= self
, pos 
= wxPoint(8, 108), size 
= wxSize(168, 46), style 
= 0) 
1064         self
.comDefNameTC 
= wxTextCtrl(id = wxID_COMMONDEFDLGCOMDEFNAMETC
, name 
= 'comDefNameTC', parent 
= self
, pos 
= wxPoint(16, 124), size 
= wxSize(152, 21), style 
= 0, value 
= '') 
1065         self
.comDefNameTC
.SetLabel(self
._comDefName
) 
1067         self
.okBtn 
= wxButton(id = wxID_COMMONDEFDLGOKBTN
, label 
= 'OK', name 
= 'okBtn', parent 
= self
, pos 
= wxPoint(8, 164), size 
= wxSize(80, 23), style 
= 0) 
1068         EVT_BUTTON(self
.okBtn
, wxID_COMMONDEFDLGOKBTN
, self
.OnOkbtnButton
) 
1070         self
.cancelBtn 
= wxButton(id = wxID_COMMONDEFDLGCANCELBTN
, label 
= 'Cancel', name 
= 'cancelBtn', parent 
= self
, pos 
= wxPoint(96, 164), size 
= wxSize(80, 23), style 
= 0) 
1071         EVT_BUTTON(self
.cancelBtn
, wxID_COMMONDEFDLGCANCELBTN
, self
.OnCancelbtnButton
) 
1073     def __init__(self
, parent
, name
='', propIdx
=0): 
1074         self
._comDefName 
= '' 
1075         self
._comDefName 
= name
 
1076         self
._propTypeIdx 
= 0 
1077         self
._propTypeIdx 
= propIdx
 
1078         self
._init
_ctrls
(parent
) 
1080         self
.propMap 
= {0: 'fore', 1: 'face', 2: 'size'}
 
1081         self
.result 
= ( '', '' ) 
1085     def OnOkbtnButton(self
, event
): 
1086         self
.result 
= ( self
.propMap
[self
.propTypeRBx
.GetSelection()], 
1087                         self
.comDefNameTC
.GetValue() ) 
1088         self
.EndModal(wxID_OK
) 
1090     def OnCancelbtnButton(self
, event
): 
1091         self
.result 
= ( '', '' ) 
1092         self
.EndModal(wxID_CANCEL
) 
1094 #---Functions useful outside of the editor---------------------------------- 
1096 def setSelectionColour(stc
, style
): 
1097     names
, values 
= parseProp(style
) 
1099         stc
.SetSelForeground(True, strToCol(values
['fore'])) 
1101         stc
.SetSelBackground(True, strToCol(values
['back'])) 
1103 def setCursorColour(stc
, style
): 
1104     names
, values 
= parseProp(style
) 
1106         stc
.SetCaretForeground(strToCol(values
['fore'])) 
1108 def setEdgeColour(stc
, style
): 
1109     names
, values 
= parseProp(style
) 
1111         stc
.SetEdgeColour(strToCol(values
['fore'])) 
1113 def strToCol(strCol
): 
1114     assert len(strCol
) == 7 and strCol
[0] == '#', 'Not a valid colour string' 
1115     return wxColour(string
.atoi('0x'+strCol
[1:3], 16), 
1116                     string
.atoi('0x'+strCol
[3:5], 16), 
1117                     string
.atoi('0x'+strCol
[5:7], 16)) 
1119     return '#%s%s%s' % (string
.zfill(string
.upper(hex(col
.Red())[2:]), 2), 
1120                         string
.zfill(string
.upper(hex(col
.Green())[2:]), 2), 
1121                         string
.zfill(string
.upper(hex(col
.Blue())[2:]), 2)) 
1123 def writeProp(num
, style
, lang
): 
1125         return 'style.%s.%s='%(lang
, string
.zfill(`num`
, 3)) + style
 
1127         return 'setting.%s.%d='%(lang
, num
) + style
 
1129 def writePropVal(names
, values
): 
1133             res
.append(values
[name
] and name
+':'+values
[name
] or name
) 
1134     return string
.join(res
, ',') 
1136 def parseProp(prop
): 
1137     items 
= string
.split(prop
, ',') 
1141         nameVal 
= string
.split(item
, ':') 
1142         names
.append(string
.strip(nameVal
[0])) 
1143         if len(nameVal
) == 1: 
1144             values
[nameVal
[0]] = '' 
1146             values
[nameVal
[0]] = string
.strip(nameVal
[1]) 
1147     return names
, values
 
1149 def parsePropLine(prop
): 
1150     name
, value 
= string
.split(prop
, '=') 
1151     return int(string
.split(name
, '.')[-1]), value
 
1153 def setSTCStyles(stc
, styles
, styleIdNames
, commonDefs
, lang
, lexer
, keywords
): 
1154     #wxLogMessage('Set style') 
1158     # build style dict based on given styles 
1159     for numStyle 
in styles
: 
1160         num
, style 
= parsePropLine(numStyle
) 
1161         styleDict
[num
] = style
 
1163     # Add blank style entries for undefined styles 
1165     styleItems 
= styleIdNames
.items() + settingsIdNames
.items() 
1168     for num
, name 
in styleItems
: 
1169         styleNumIdxMap
[num
] = idx
 
1170         if not styleDict
.has_key(num
): 
1172         newStyles
.append(writeProp(num
, styleDict
[num
], lang
)) 
1175     # Set background colour to reduce flashing effect on refresh or page switch 
1177     if styleDict
.has_key(0): prop 
= styleDict
[0] 
1178     else: prop 
= styleDict
[wxSTC_STYLE_DEFAULT
] 
1179     names
, vals 
= parseProp(prop
) 
1181         bkCol 
= strToCol(vals
['back']) 
1184     stc
.SetBackgroundColour(bkCol
) 
1186     # Set the styles on the wxSTC 
1188     stc
.StyleResetDefault() 
1189     stc
.ClearDocumentStyle() 
1191     stc
.SetKeyWords(0, keywords
) 
1192     stc
.StyleSetSpec(wxSTC_STYLE_DEFAULT
, 
1193           styleDict
[wxSTC_STYLE_DEFAULT
] % commonDefs
) 
1196     for num
, style 
in styleDict
.items(): 
1198             stc
.StyleSetSpec(num
, style 
% commonDefs
) 
1200             setSelectionColour(stc
, style 
% commonDefs
) 
1202             setCursorColour(stc
, style 
% commonDefs
) 
1204             setEdgeColour(stc
, style 
% commonDefs
) 
1206     stc
.Colourise(0, stc
.GetTextLength()) 
1209     return newStyles
, styleDict
, styleNumIdxMap
 
1211 #---Config reading and writing ------------------------------------------------- 
1212 commonDefsFile 
= 'common.defs.%s'%(wxPlatform 
== '__WXMSW__' and 'msw' or 'gtk') 
1214 def readPyValFromConfig(conf
, name
): 
1215     return eval(string
.replace(conf
.Read(name
), '\r\n', '\n')+'\n') 
1217 def initFromConfig(configFile
, lang
): 
1218     cfg 
= wxFileConfig(localFilename
=configFile
, style
=wxCONFIG_USE_LOCAL_FILE
) 
1219     cfg
.SetExpandEnvVars(False) 
1221     # read in all group names for this language 
1222     groupPrefix 
= 'style.%s'%lang
 
1223     gpLen 
= len(groupPrefix
) 
1224     predefStyleGroupNames
, otherLangStyleGroupNames 
= [], [] 
1225     cont
, val
, idx 
= cfg
.GetFirstGroup() 
1227         if val 
!= groupPrefix 
and len(val
) >= 5 and val
[:5] == 'style': 
1228             if len(val
) > gpLen 
and val
[:gpLen
] == groupPrefix
: 
1229                 predefStyleGroupNames
.append(val
) 
1231                 otherLangStyleGroupNames
.append(val
) 
1233         cont
, val
, idx 
= cfg
.GetNextGroup(idx
) 
1235     # read in common elements 
1236     commonDefs 
= readPyValFromConfig(cfg
, commonDefsFile
) 
1237     assert type(commonDefs
) is type({}), \
 
1238           'Common definitions (%s) not a valid dict'%commonDefsFile
 
1240     commonStyleIdNames 
= readPyValFromConfig(cfg
, 'common.styleidnames') 
1241     assert type(commonStyleIdNames
) is type({}), \
 
1242           'Common definitions (%s) not a valid dict'%'common.styleidnames' 
1244     # Lang spesific settings 
1246     styleIdNames 
= readPyValFromConfig(cfg
, 'styleidnames') 
1247     assert type(commonStyleIdNames
) is type({}), \
 
1248           'Not a valid dict [%s] styleidnames)'%lang
 
1249     styleIdNames
.update(commonStyleIdNames
) 
1250     braceInfo 
= readPyValFromConfig(cfg
, 'braces') 
1251     assert type(commonStyleIdNames
) is type({}), \
 
1252           'Not a valid dict [%s] braces)'%lang
 
1254     displaySrc 
= cfg
.Read('displaysrc') 
1255     lexer 
= readPyValFromConfig(cfg
, 'lexer') 
1256     keywords 
= cfg
.Read('keywords') 
1260     # read in current styles 
1261     styles 
= readStylesFromConfig(cfg
, groupPrefix
) 
1263     # read in predefined styles 
1264     predefStyleGroups 
= {} 
1265     for group 
in predefStyleGroupNames
: 
1266         predefStyleGroups
[group
] = readStylesFromConfig(cfg
, group
) 
1268     # read in all other style sections 
1269     otherLangStyleGroups 
= {} 
1270     for group 
in otherLangStyleGroupNames
: 
1271         otherLangStyleGroups
[group
] = readStylesFromConfig(cfg
, group
) 
1273     return (cfg
, commonDefs
, styleIdNames
, styles
, predefStyleGroupNames
, 
1274             predefStyleGroups
, otherLangStyleGroupNames
, otherLangStyleGroups
, 
1275             displaySrc
, lexer
, keywords
, braceInfo
) 
1277 def readStylesFromConfig(config
, group
): 
1279     config
.SetPath(group
) 
1281     cont
, val
, idx 
= config
.GetFirstEntry() 
1283         styles
.append(val
+'='+config
.Read(val
)) 
1284         cont
, val
, idx 
= config
.GetNextEntry(idx
) 
1289 def writeStylesToConfig(config
, group
, styles
): 
1291     config
.DeleteGroup(group
) 
1292     config
.SetPath(group
) 
1294     for style 
in styles
: 
1295         name
, value 
= string
.split(style
, '=') 
1296         config
.Write(name
, string
.strip(value
)) 
1300 #------------------------------------------------------------------------------- 
1301 def initSTC(stc
, config
, lang
): 
1302     """ Main module entry point. Initialise a wxSTC from given config file.""" 
1303     (cfg
, commonDefs
, styleIdNames
, styles
, predefStyleGroupNames
, 
1304      predefStyleGroups
, otherLangStyleGroupNames
, otherLangStyleGroups
, 
1305      displaySrc
, lexer
, keywords
, braceInfo
) = initFromConfig(config
, lang
) 
1307     setSTCStyles(stc
, styles
, styleIdNames
, commonDefs
, lang
, lexer
, keywords
) 
1309 #------------------------------------------------------------------------------- 
1310 if __name__ 
== '__main__': 
1311     from wxPython
.help import * 
1313     app 
= wxPySimpleApp() 
1315     provider 
= wxSimpleHelpProvider() 
1316     wxHelpProvider_Set(provider
) 
1318     base 
= os
.path
.split(__file__
)[0] 
1319     config 
= os
.path
.abspath(os
.path
.join(base
, 'stc-styles.rc.cfg')) 
1321         f 
= wxFrame(None, -1, 'Test frame (double click for editor)') 
1322         stc 
= wxStyledTextCtrl(f
, -1) 
1323         def OnDblClick(evt
, stc
=stc
): 
1324             dlg 
= STCStyleEditDlg(None, 'Python', 'python', config
, (stc
,)) 
1325             try: dlg
.ShowModal() 
1326             finally: dlg
.Destroy() 
1327         stc
.SetText(open('STCStyleEditor.py').read()) 
1328         EVT_LEFT_DCLICK(stc
, OnDblClick
) 
1329         initSTC(stc
, config
, 'python') 
1333         dlg 
= STCStyleEditDlg(None, 
1339             #'Properties', 'prop', 
1341         try: dlg
.ShowModal() 
1342         finally: dlg
.Destroy()