1 #-----------------------------------------------------------------------------
2 # Name: STCStyleEditor.py
3 # Purpose: Style editor for the wxStyledTextCtrl
5 # Author: Riaan Booysen
9 # Copyright: (c) 2001 - 2005 Riaan Booysen
10 # Licence: wxWidgets 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 specific 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.defs.mac - Common definition dictionary used on wxMAC
29 common.styleidnames - STC styles shared by all languages
31 Each supported language defines the following groups:
33 displaysrc - Example source to display in the editor
34 braces - Dictionary defining the (line, column) for showing 'good' and 'bad'
35 brace matching (both keys optional)
36 keywords - Space separated list of keywords
37 lexer - wxSTC constant for the language lexer
38 styleidnames - Dictionary of language specific style numbers and names
40 [style.<language>] - The users current style values
41 [style.<language>.default] - Default style values (can be reverted from)
43 0 or more predefined style groups or 'themes'
44 [style.<language>.<predefined name>]
46 Currently the following languages are supported:
47 python, html, xml, cpp, text, props
48 Other languages can be added by just defining the above settings for them in
49 the config file (if wxSTC implements them).
51 Use the initSTC function to initialise your wxSTC from a config file.
54 import os
, sys
, string
, pprint
, copy
57 from wx
.lib
.anchors
import LayoutAnchors
59 import wxPython
.stc
# needed names from 2.4 for config files
61 settingsIdNames
= {-1: 'Selection', -2: 'Caret', -3: 'Edge'}
63 commonPropDefs
= {'fore': '#888888', 'size': 8,
66 styleCategoryDescriptions
= {
67 '----Language----': 'Styles specific to the language',
68 '----Standard----': 'Styles shared by all languages',
69 '----Settings----': 'Properties set by STC methods',
70 '----Common----': 'User definable values that can be shared between languages'}
72 platformSettings
= {'__WXMSW__': ('msw', 8),
73 '__WXGTK__': ('gtk', 10),
74 '__WXMAC__': ('mac', 11)}
76 [wxID_STCSTYLEEDITDLG
, wxID_STCSTYLEEDITDLGADDCOMMONITEMBTN
,
77 wxID_STCSTYLEEDITDLGBGCOLBTN
, wxID_STCSTYLEEDITDLGBGCOLCB
,
78 wxID_STCSTYLEEDITDLGBGCOLDEFCB
, wxID_STCSTYLEEDITDLGBGCOLOKBTN
,
79 wxID_STCSTYLEEDITDLGCANCELBTN
, wxID_STCSTYLEEDITDLGCONTEXTHELPBUTTON1
,
80 wxID_STCSTYLEEDITDLGELEMENTLB
, wxID_STCSTYLEEDITDLGFACECB
,
81 wxID_STCSTYLEEDITDLGFACEDEFCB
, wxID_STCSTYLEEDITDLGFACEOKBTN
,
82 wxID_STCSTYLEEDITDLGFGCOLBTN
, wxID_STCSTYLEEDITDLGFGCOLCB
,
83 wxID_STCSTYLEEDITDLGFGCOLDEFCB
, wxID_STCSTYLEEDITDLGFGCOLOKBTN
,
84 wxID_STCSTYLEEDITDLGFIXEDWIDTHCHK
, wxID_STCSTYLEEDITDLGOKBTN
,
85 wxID_STCSTYLEEDITDLGPANEL1
, wxID_STCSTYLEEDITDLGPANEL2
,
86 wxID_STCSTYLEEDITDLGPANEL3
, wxID_STCSTYLEEDITDLGPANEL4
,
87 wxID_STCSTYLEEDITDLGREMOVECOMMONITEMBTN
, wxID_STCSTYLEEDITDLGSIZECB
,
88 wxID_STCSTYLEEDITDLGSIZEOKBTN
, wxID_STCSTYLEEDITDLGSPEEDSETTINGCH
,
89 wxID_STCSTYLEEDITDLGSTATICBOX1
, wxID_STCSTYLEEDITDLGSTATICBOX2
,
90 wxID_STCSTYLEEDITDLGSTATICLINE1
, wxID_STCSTYLEEDITDLGSTATICTEXT2
,
91 wxID_STCSTYLEEDITDLGSTATICTEXT3
, wxID_STCSTYLEEDITDLGSTATICTEXT4
,
92 wxID_STCSTYLEEDITDLGSTATICTEXT6
, wxID_STCSTYLEEDITDLGSTATICTEXT7
,
93 wxID_STCSTYLEEDITDLGSTATICTEXT8
, wxID_STCSTYLEEDITDLGSTATICTEXT9
,
94 wxID_STCSTYLEEDITDLGSTC
, wxID_STCSTYLEEDITDLGSTYLEDEFST
,
95 wxID_STCSTYLEEDITDLGTABOLDCB
, wxID_STCSTYLEEDITDLGTABOLDDEFCB
,
96 wxID_STCSTYLEEDITDLGTAEOLFILLEDCB
, wxID_STCSTYLEEDITDLGTAEOLFILLEDDEFCB
,
97 wxID_STCSTYLEEDITDLGTAITALICCB
, wxID_STCSTYLEEDITDLGTAITALICDEFCB
,
98 wxID_STCSTYLEEDITDLGTASIZEDEFCB
, wxID_STCSTYLEEDITDLGTAUNDERLINEDCB
,
99 wxID_STCSTYLEEDITDLGTAUNDERLINEDDEFCB
,
100 ] = [wx
.NewId() for _init_ctrls
in range(47)]
102 class STCStyleEditDlg(wx
.Dialog
):
103 """ Style editor for the wxStyledTextCtrl """
104 _custom_classes
= {'wx.Window': ['wx.stc.StyledTextCtrl'],}
105 def _init_ctrls(self
, prnt
):
106 # generated method, don't edit
107 wx
.Dialog
.__init
__(self
, id=wxID_STCSTYLEEDITDLG
,
108 name
='STCStyleEditDlg', parent
=prnt
, pos
=wx
.Point(567, 292),
109 size
=wx
.Size(493, 482),
110 style
=wx
.WANTS_CHARS | wx
.DEFAULT_DIALOG_STYLE | wx
.RESIZE_BORDER
,
111 title
=self
.stc_title
)
112 self
.SetClientSize(wx
.Size(485, 455))
113 self
.SetAutoLayout(True)
114 self
.SetSizeHints(425, 400, -1, -1)
116 self
.Bind(wx
.EVT_SIZE
, self
.OnStcstyleeditdlgSize
)
118 self
.speedsettingCh
= wx
.Choice(choices
=[],
119 id=wxID_STCSTYLEEDITDLGSPEEDSETTINGCH
, name
='speedsettingCh',
120 parent
=self
, pos
=wx
.Point(96, 28), size
=wx
.Size(380, 21),
122 self
.speedsettingCh
.SetConstraints(LayoutAnchors(self
.speedsettingCh
,
123 True, True, True, False))
124 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.')
125 self
.speedsettingCh
.Bind(wx
.EVT_CHOICE
, self
.OnSpeedsettingchChoice
,
126 id=wxID_STCSTYLEEDITDLGSPEEDSETTINGCH
)
128 self
.elementLb
= wx
.ListBox(choices
=[],
129 id=wxID_STCSTYLEEDITDLGELEMENTLB
, name
='elementLb', parent
=self
,
130 pos
=wx
.Point(8, 70), size
=wx
.Size(175, 128), style
=0)
131 self
.elementLb
.SetConstraints(LayoutAnchors(self
.elementLb
, True, True,
133 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.')
134 self
.elementLb
.Bind(wx
.EVT_LISTBOX
, self
.OnElementlbListbox
,
135 id=wxID_STCSTYLEEDITDLGELEMENTLB
)
137 self
.addCommonItemBtn
= wx
.Button(id=wxID_STCSTYLEEDITDLGADDCOMMONITEMBTN
,
138 label
='Add', name
='addCommonItemBtn', parent
=self
, pos
=wx
.Point(8,
139 200), size
=wx
.Size(88, 17), style
=0)
140 self
.addCommonItemBtn
.SetToolTipString('Add new Common definition')
141 self
.addCommonItemBtn
.Bind(wx
.EVT_BUTTON
, self
.OnAddsharebtnButton
,
142 id=wxID_STCSTYLEEDITDLGADDCOMMONITEMBTN
)
144 self
.removeCommonItemBtn
= wx
.Button(id=wxID_STCSTYLEEDITDLGREMOVECOMMONITEMBTN
,
145 label
='Remove', name
='removeCommonItemBtn', parent
=self
,
146 pos
=wx
.Point(96, 200), size
=wx
.Size(88, 17), style
=0)
147 self
.removeCommonItemBtn
.SetToolTipString('Remove the selected Common definition')
148 self
.removeCommonItemBtn
.Bind(wx
.EVT_BUTTON
,
149 self
.OnRemovesharebtnButton
,
150 id=wxID_STCSTYLEEDITDLGREMOVECOMMONITEMBTN
)
152 self
.styleDefST
= wx
.StaticText(id=wxID_STCSTYLEEDITDLGSTYLEDEFST
,
153 label
='(nothing selected)', name
='styleDefST', parent
=self
,
154 pos
=wx
.Point(96, 8), size
=wx
.Size(376, 16),
155 style
=wx
.ST_NO_AUTORESIZE
)
156 self
.styleDefST
.SetFont(wx
.Font(self
.style_font_size
, wx
.SWISS
,
157 wx
.NORMAL
, wx
.BOLD
, False, ''))
158 self
.styleDefST
.SetConstraints(LayoutAnchors(self
.styleDefST
, True,
161 self
.staticLine1
= wx
.StaticLine(id=wxID_STCSTYLEEDITDLGSTATICLINE1
,
162 name
='staticLine1', parent
=self
, pos
=wx
.Point(48, 64),
163 size
=wx
.Size(135, 0), style
=wx
.LI_HORIZONTAL
)
164 self
.staticLine1
.SetConstraints(LayoutAnchors(self
.staticLine1
, True,
167 self
.staticText6
= wx
.StaticText(id=wxID_STCSTYLEEDITDLGSTATICTEXT6
,
168 label
='Style', name
='staticText6', parent
=self
, pos
=wx
.Point(8,
169 56), size
=wx
.Size(40, 13), style
=0)
171 self
.staticText8
= wx
.StaticText(id=wxID_STCSTYLEEDITDLGSTATICTEXT8
,
172 label
='Style def:', name
='staticText8', parent
=self
,
173 pos
=wx
.Point(8, 8), size
=wx
.Size(88, 13), style
=0)
175 self
.staticText9
= wx
.StaticText(id=wxID_STCSTYLEEDITDLGSTATICTEXT9
,
176 label
='SpeedSetting:', name
='staticText9', parent
=self
,
177 pos
=wx
.Point(8, 32), size
=wx
.Size(88, 13), style
=0)
179 self
.panel3
= wx
.Panel(id=wxID_STCSTYLEEDITDLGPANEL3
, name
='panel3',
180 parent
=self
, pos
=wx
.Point(199, 56), size
=wx
.Size(160, 120),
181 style
=wx
.TAB_TRAVERSAL
)
182 self
.panel3
.SetConstraints(LayoutAnchors(self
.panel3
, False, True, True,
185 self
.panel4
= wx
.Panel(id=wxID_STCSTYLEEDITDLGPANEL4
, name
='panel4',
186 parent
=self
, pos
=wx
.Point(364, 56), size
=wx
.Size(114, 120),
187 style
=wx
.TAB_TRAVERSAL
)
188 self
.panel4
.SetConstraints(LayoutAnchors(self
.panel4
, False, True, True,
191 self
.panel1
= wx
.Panel(id=wxID_STCSTYLEEDITDLGPANEL1
, name
='panel1',
192 parent
=self
, pos
=wx
.Point(202, 177), size
=wx
.Size(149, 40),
193 style
=wx
.TAB_TRAVERSAL
)
194 self
.panel1
.SetConstraints(LayoutAnchors(self
.panel1
, False, True, True,
197 self
.panel2
= wx
.Panel(id=wxID_STCSTYLEEDITDLGPANEL2
, name
='panel2',
198 parent
=self
, pos
=wx
.Point(364, 178), size
=wx
.Size(112, 40),
199 style
=wx
.TAB_TRAVERSAL
)
200 self
.panel2
.SetConstraints(LayoutAnchors(self
.panel2
, False, True, True,
203 self
.stc
= wx
.stc
.StyledTextCtrl(id=wxID_STCSTYLEEDITDLGSTC
, name
='stc',
204 parent
=self
, pos
=wx
.Point(8, 224), size
=wx
.Size(469, 191),
205 style
=wx
.SUNKEN_BORDER
)
206 self
.stc
.SetConstraints(LayoutAnchors(self
.stc
, True, True, True, True))
207 self
.stc
.SetHelpText('The style preview window. Click or move the cursor over a specific style to select the style for editing in the editors above.')
208 self
.stc
.Bind(wx
.EVT_LEFT_UP
, self
.OnUpdateUI
)
209 self
.stc
.Bind(wx
.EVT_KEY_UP
, self
.OnUpdateUI
)
211 self
.contextHelpButton1
= wx
.ContextHelpButton(parent
=self
,
212 pos
=wx
.Point(8, 423), size
=wx
.Size(24, 24), style
=wx
.BU_AUTODRAW
)
213 self
.contextHelpButton1
.SetConstraints(LayoutAnchors(self
.contextHelpButton1
,
214 True, False, False, True))
216 self
.okBtn
= wx
.Button(id=wxID_STCSTYLEEDITDLGOKBTN
, label
='OK',
217 name
='okBtn', parent
=self
, pos
=wx
.Point(316, 423),
218 size
=wx
.Size(75, 23), style
=0)
219 self
.okBtn
.SetConstraints(LayoutAnchors(self
.okBtn
, False, False, True,
221 self
.okBtn
.SetToolTipString('Save changes to the config file')
222 self
.okBtn
.Bind(wx
.EVT_BUTTON
, self
.OnOkbtnButton
,
223 id=wxID_STCSTYLEEDITDLGOKBTN
)
225 self
.cancelBtn
= wx
.Button(id=wxID_STCSTYLEEDITDLGCANCELBTN
,
226 label
='Cancel', name
='cancelBtn', parent
=self
, pos
=wx
.Point(400,
227 423), size
=wx
.Size(75, 23), style
=0)
228 self
.cancelBtn
.SetConstraints(LayoutAnchors(self
.cancelBtn
, False,
230 self
.cancelBtn
.SetToolTipString('Close dialog without saving changes')
231 self
.cancelBtn
.Bind(wx
.EVT_BUTTON
, self
.OnCancelbtnButton
,
232 id=wxID_STCSTYLEEDITDLGCANCELBTN
)
234 self
.staticText4
= wx
.StaticText(id=wxID_STCSTYLEEDITDLGSTATICTEXT4
,
235 label
='Face:', name
='staticText4', parent
=self
.panel1
,
236 pos
=wx
.Point(0, 0), size
=wx
.Size(48, 13), style
=0)
238 self
.fixedWidthChk
= wx
.CheckBox(id=wxID_STCSTYLEEDITDLGFIXEDWIDTHCHK
,
239 label
='', name
='fixedWidthChk', parent
=self
.panel1
,
240 pos
=wx
.Point(0, 23), size
=wx
.Size(16, 19), style
=0)
241 self
.fixedWidthChk
.SetToolTipString('Check this for Fixed Width fonts')
242 self
.fixedWidthChk
.Bind(wx
.EVT_CHECKBOX
, self
.OnFixedwidthchkCheckbox
,
243 id=wxID_STCSTYLEEDITDLGFIXEDWIDTHCHK
)
245 self
.faceCb
= wx
.ComboBox(choices
=[], id=wxID_STCSTYLEEDITDLGFACECB
,
246 name
='faceCb', parent
=self
.panel1
, pos
=wx
.Point(17, 18),
247 size
=wx
.Size(101, 21), style
=0, value
='')
249 self
.staticText7
= wx
.StaticText(id=wxID_STCSTYLEEDITDLGSTATICTEXT7
,
250 label
='Size:', name
='staticText7', parent
=self
.panel2
,
251 pos
=wx
.Point(0, 0), size
=wx
.Size(40, 13), style
=0)
253 self
.sizeCb
= wx
.ComboBox(choices
=[], id=wxID_STCSTYLEEDITDLGSIZECB
,
254 name
='sizeCb', parent
=self
.panel2
, pos
=wx
.Point(0, 17),
255 size
=wx
.Size(80, 21), style
=0, value
='')
257 self
.sizeOkBtn
= wx
.Button(id=wxID_STCSTYLEEDITDLGSIZEOKBTN
, label
='ok',
258 name
='sizeOkBtn', parent
=self
.panel2
, pos
=wx
.Point(80, 17),
259 size
=wx
.Size(32, 21), style
=0)
261 self
.faceOkBtn
= wx
.Button(id=wxID_STCSTYLEEDITDLGFACEOKBTN
, label
='ok',
262 name
='faceOkBtn', parent
=self
.panel1
, pos
=wx
.Point(117, 18),
263 size
=wx
.Size(32, 21), style
=0)
265 self
.fgColBtn
= wx
.Button(id=wxID_STCSTYLEEDITDLGFGCOLBTN
,
266 label
='Foreground', name
='fgColBtn', parent
=self
.panel3
,
267 pos
=wx
.Point(8, 16), size
=wx
.Size(96, 16), style
=0)
268 self
.fgColBtn
.Bind(wx
.EVT_BUTTON
, self
.OnFgcolbtnButton
,
269 id=wxID_STCSTYLEEDITDLGFGCOLBTN
)
271 self
.fgColCb
= wx
.ComboBox(choices
=[], id=wxID_STCSTYLEEDITDLGFGCOLCB
,
272 name
='fgColCb', parent
=self
.panel3
, pos
=wx
.Point(8, 32),
273 size
=wx
.Size(96, 21), style
=0, value
='')
275 self
.fgColOkBtn
= wx
.Button(id=wxID_STCSTYLEEDITDLGFGCOLOKBTN
,
276 label
='ok', name
='fgColOkBtn', parent
=self
.panel3
,
277 pos
=wx
.Point(104, 32), size
=wx
.Size(32, 21), style
=0)
279 self
.staticText3
= wx
.StaticText(id=wxID_STCSTYLEEDITDLGSTATICTEXT3
,
280 label
='default', name
='staticText3', parent
=self
.panel3
,
281 pos
=wx
.Point(112, 15), size
=wx
.Size(38, 16), style
=0)
283 self
.fgColDefCb
= wx
.CheckBox(id=wxID_STCSTYLEEDITDLGFGCOLDEFCB
,
284 label
='checkBox1', name
='fgColDefCb', parent
=self
.panel3
,
285 pos
=wx
.Point(136, 31), size
=wx
.Size(16, 16), style
=0)
287 self
.bgColBtn
= wx
.Button(id=wxID_STCSTYLEEDITDLGBGCOLBTN
,
288 label
='Background', name
='bgColBtn', parent
=self
.panel3
,
289 pos
=wx
.Point(8, 64), size
=wx
.Size(96, 16), style
=0)
290 self
.bgColBtn
.Bind(wx
.EVT_BUTTON
, self
.OnBgcolbtnButton
,
291 id=wxID_STCSTYLEEDITDLGBGCOLBTN
)
293 self
.bgColCb
= wx
.ComboBox(choices
=[], id=wxID_STCSTYLEEDITDLGBGCOLCB
,
294 name
='bgColCb', parent
=self
.panel3
, pos
=wx
.Point(8, 80),
295 size
=wx
.Size(96, 21), style
=0, value
='')
297 self
.bgColOkBtn
= wx
.Button(id=wxID_STCSTYLEEDITDLGBGCOLOKBTN
,
298 label
='ok', name
='bgColOkBtn', parent
=self
.panel3
,
299 pos
=wx
.Point(104, 80), size
=wx
.Size(32, 21), style
=0)
301 self
.staticBox2
= wx
.StaticBox(id=wxID_STCSTYLEEDITDLGSTATICBOX2
,
302 label
='Text attributes', name
='staticBox2', parent
=self
.panel4
,
303 pos
=wx
.Point(0, 0), size
=wx
.Size(112, 112), style
=0)
304 self
.staticBox2
.SetConstraints(LayoutAnchors(self
.staticBox2
, False,
306 self
.staticBox2
.SetHelpText('Text attribute flags.')
308 self
.staticText2
= wx
.StaticText(id=wxID_STCSTYLEEDITDLGSTATICTEXT2
,
309 label
='default', name
='staticText2', parent
=self
.panel4
,
310 pos
=wx
.Point(64, 12), size
=wx
.Size(40, 16), style
=0)
312 self
.taBoldDefCb
= wx
.CheckBox(id=wxID_STCSTYLEEDITDLGTABOLDDEFCB
,
313 label
='checkBox1', name
='taBoldDefCb', parent
=self
.panel4
,
314 pos
=wx
.Point(88, 27), size
=wx
.Size(16, 16), style
=0)
316 self
.taItalicDefCb
= wx
.CheckBox(id=wxID_STCSTYLEEDITDLGTAITALICDEFCB
,
317 label
='checkBox1', name
='taItalicDefCb', parent
=self
.panel4
,
318 pos
=wx
.Point(88, 48), size
=wx
.Size(16, 16), style
=0)
320 self
.taUnderlinedDefCb
= wx
.CheckBox(id=wxID_STCSTYLEEDITDLGTAUNDERLINEDDEFCB
,
321 label
='checkBox1', name
='taUnderlinedDefCb', parent
=self
.panel4
,
322 pos
=wx
.Point(88, 70), size
=wx
.Size(16, 16), style
=0)
324 self
.taEOLfilledDefCb
= wx
.CheckBox(id=wxID_STCSTYLEEDITDLGTAEOLFILLEDDEFCB
,
325 label
='checkBox1', name
='taEOLfilledDefCb', parent
=self
.panel4
,
326 pos
=wx
.Point(88, 92), size
=wx
.Size(16, 16), style
=0)
328 self
.taEOLfilledCb
= wx
.CheckBox(id=wxID_STCSTYLEEDITDLGTAEOLFILLEDCB
,
329 label
='EOL filled', name
='taEOLfilledCb', parent
=self
.panel4
,
330 pos
=wx
.Point(8, 92), size
=wx
.Size(80, 16), style
=0)
331 self
.taEOLfilledCb
.Bind(wx
.EVT_CHECKBOX
, self
.OnTaeoffilledcbCheckbox
,
332 id=wxID_STCSTYLEEDITDLGTAEOLFILLEDCB
)
334 self
.taUnderlinedCb
= wx
.CheckBox(id=wxID_STCSTYLEEDITDLGTAUNDERLINEDCB
,
335 label
='Underlined', name
='taUnderlinedCb', parent
=self
.panel4
,
336 pos
=wx
.Point(8, 70), size
=wx
.Size(80, 16), style
=0)
337 self
.taUnderlinedCb
.Bind(wx
.EVT_CHECKBOX
, self
.OnTaunderlinedcbCheckbox
,
338 id=wxID_STCSTYLEEDITDLGTAUNDERLINEDCB
)
340 self
.taItalicCb
= wx
.CheckBox(id=wxID_STCSTYLEEDITDLGTAITALICCB
,
341 label
='Italic', name
='taItalicCb', parent
=self
.panel4
,
342 pos
=wx
.Point(8, 48), size
=wx
.Size(80, 16), style
=0)
343 self
.taItalicCb
.Bind(wx
.EVT_CHECKBOX
, self
.OnTaitaliccbCheckbox
,
344 id=wxID_STCSTYLEEDITDLGTAITALICCB
)
346 self
.taBoldCb
= wx
.CheckBox(id=wxID_STCSTYLEEDITDLGTABOLDCB
,
347 label
='Bold', name
='taBoldCb', parent
=self
.panel4
, pos
=wx
.Point(8,
348 27), size
=wx
.Size(80, 16), style
=0)
349 self
.taBoldCb
.Bind(wx
.EVT_CHECKBOX
, self
.OnTaboldcbCheckbox
,
350 id=wxID_STCSTYLEEDITDLGTABOLDCB
)
352 self
.bgColDefCb
= wx
.CheckBox(id=wxID_STCSTYLEEDITDLGBGCOLDEFCB
,
353 label
='checkBox1', name
='bgColDefCb', parent
=self
.panel3
,
354 pos
=wx
.Point(136, 79), size
=wx
.Size(16, 16), style
=0)
356 self
.staticBox1
= wx
.StaticBox(id=wxID_STCSTYLEEDITDLGSTATICBOX1
,
357 label
='Colour', name
='staticBox1', parent
=self
.panel3
,
358 pos
=wx
.Point(0, 0), size
=wx
.Size(157, 112), style
=0)
359 self
.staticBox1
.SetConstraints(LayoutAnchors(self
.staticBox1
, False,
362 self
.faceDefCb
= wx
.CheckBox(id=wxID_STCSTYLEEDITDLGFACEDEFCB
,
363 label
='checkBox1', name
='faceDefCb', parent
=self
.panel1
,
364 pos
=wx
.Point(117, 0), size
=wx
.Size(16, 16), style
=0)
366 self
.taSizeDefCb
= wx
.CheckBox(id=wxID_STCSTYLEEDITDLGTASIZEDEFCB
,
367 label
='checkBox1', name
='taSizeDefCb', parent
=self
.panel2
,
368 pos
=wx
.Point(80, 0), size
=wx
.Size(16, 16), style
=0)
370 def __init__(self
, parent
, langTitle
, lang
, configFile
, STCsToUpdate
=()):
371 self
.stc_title
= 'wxStyledTextCtrl Style Editor'
372 self
.stc_title
= 'wxStyledTextCtrl Style Editor - %s' % langTitle
373 self
.style_font_size
= 8
374 self
.style_font_size
= platformSettings
[wx
.Platform
][1]
375 self
._init
_ctrls
(parent
)
377 self
.configFile
= configFile
382 self
.STCsToUpdate
= STCsToUpdate
383 self
._blockUpdate
= False
385 global commonPropDefs
386 commonPropDefs
= {'fore': '#888888', 'size': 8,
387 'face': wx
.SystemSettings
.GetFont(wx
.SYS_DEFAULT_GUI_FONT
).GetFaceName()}
389 for combo
, okBtn
, evtRet
, evtCB
, evtRDC
in (
390 (self
.fgColCb
, self
.fgColOkBtn
, self
.OnfgColRet
, self
.OnfgColCombobox
, self
.OnGotoCommonDef
),
391 (self
.bgColCb
, self
.bgColOkBtn
, self
.OnbgColRet
, self
.OnbgColCombobox
, self
.OnGotoCommonDef
),
392 (self
.faceCb
, self
.faceOkBtn
, self
.OnfaceRet
, self
.OnfaceCombobox
, self
.OnGotoCommonDef
),
393 (self
.sizeCb
, self
.sizeOkBtn
, self
.OnsizeRet
, self
.OnsizeCombobox
, self
.OnGotoCommonDef
)):
394 self
.bindComboEvts(combo
, okBtn
, evtRet
, evtCB
, evtRDC
)
396 (self
.config
, self
.commonDefs
, self
.styleIdNames
, self
.styles
,
397 self
.styleGroupNames
, self
.predefStyleGroups
,
398 self
.otherLangStyleGroupNames
, self
.otherLangStyleGroups
,
399 self
.displaySrc
, self
.lexer
, self
.keywords
, self
.braceInfo
) = \
400 initFromConfig(configFile
, lang
)
402 self
.currSpeedSetting
= 'style.%s'%self
.lang
403 for grp
in [self
.currSpeedSetting
]+self
.styleGroupNames
:
404 self
.speedsettingCh
.Append(grp
)
405 self
.speedsettingCh
.SetSelection(0)
408 self
.stc
.SetMarginType(margin
, wx
.stc
.STC_MARGIN_NUMBER
)
409 self
.stc
.SetMarginWidth(margin
, 25)
410 self
.stc
.SetMarginSensitive(margin
, True)
411 self
.stc
.Bind(wx
.stc
.EVT_STC_MARGINCLICK
, self
.OnMarginClick
, id=wxID_STCSTYLEEDITDLGSTC
)
413 self
.stc
.SetUseTabs(False)
414 self
.stc
.SetTabWidth(4)
415 self
.stc
.SetIndentationGuides(True)
416 self
.stc
.SetEdgeMode(wx
.stc
.STC_EDGE_BACKGROUND
)
417 self
.stc
.SetEdgeColumn(44)
421 self
.populateStyleSelector()
423 self
.defNames
, self
.defValues
= parseProp(\
424 self
.styleDict
.get(wx
.stc
.STC_STYLE_DEFAULT
, ''))
425 self
.stc
.SetText(self
.displaySrc
)
426 self
.stc
.EmptyUndoBuffer()
427 self
.stc
.SetCurrentPos(self
.stc
.GetTextLength())
428 self
.stc
.SetAnchor(self
.stc
.GetTextLength())
430 self
.populateCombosWithCommonDefs()
432 # Logical grouping of controls and the property they edit
433 self
.allCtrls
= [((self
.fgColBtn
, self
.fgColCb
, self
.fgColOkBtn
), self
.fgColDefCb
,
434 'fore', wxID_STCSTYLEEDITDLGFGCOLDEFCB
),
435 ((self
.bgColBtn
, self
.bgColCb
, self
.bgColOkBtn
), self
.bgColDefCb
,
436 'back', wxID_STCSTYLEEDITDLGBGCOLDEFCB
),
437 (self
.taBoldCb
, self
.taBoldDefCb
,
438 'bold', wxID_STCSTYLEEDITDLGTABOLDDEFCB
),
439 (self
.taItalicCb
, self
.taItalicDefCb
,
440 'italic', wxID_STCSTYLEEDITDLGTAITALICDEFCB
),
441 (self
.taUnderlinedCb
, self
.taUnderlinedDefCb
,
442 'underline', wxID_STCSTYLEEDITDLGTAUNDERLINEDDEFCB
),
443 (self
.taEOLfilledCb
, self
.taEOLfilledDefCb
,
444 'eolfilled', wxID_STCSTYLEEDITDLGTAEOLFILLEDDEFCB
),
445 ((self
.sizeCb
, self
.sizeOkBtn
), self
.taSizeDefCb
,
446 'size', wxID_STCSTYLEEDITDLGTASIZEDEFCB
),
447 ((self
.faceCb
, self
.faceOkBtn
, self
.fixedWidthChk
), self
.faceDefCb
,
448 'face', wxID_STCSTYLEEDITDLGFACEDEFCB
)]
450 self
.clearCtrls(disableDefs
=True)
451 # centralised default checkbox event handler
453 for ctrl
, chb
, prop
, wid
in self
.allCtrls
:
454 self
.chbIdMap
[wid
] = ctrl
, chb
, prop
, wid
455 chb
.Bind(wx
.EVT_CHECKBOX
, self
.OnDefaultCheckBox
, id=wid
)
456 chb
.SetToolTipString('Toggle defaults')
460 #---Property methods------------------------------------------------------------
461 def getCtrlForProp(self
, findprop
):
462 for ctrl
, chb
, prop
, wid
in self
.allCtrls
:
465 raise Exception('PropNotFound', findprop
)
467 def editProp(self
, on
, prop
, val
=''):
468 oldstyle
= self
.rememberStyles()
470 if not self
.names
.count(prop
):
471 self
.names
.append(prop
)
472 self
.values
[prop
] = val
474 try: self
.names
.remove(prop
)
475 except ValueError: pass
476 try: del self
.values
[prop
]
477 except KeyError: pass
482 except KeyError, errkey
:
483 wx
.LogError('Name not found in Common definition, '\
484 'please enter valid reference. (%s)'%errkey
)
485 self
.restoreStyles(oldstyle
)
488 #---Control population methods--------------------------------------------------
490 if self
._blockUpdate
: return
491 self
.styles
, self
.styleDict
, self
.styleNumIdxMap
= \
492 setSTCStyles(self
.stc
, self
.styles
, self
.styleIdNames
,
493 self
.commonDefs
, self
.lang
, self
.lexer
, self
.keywords
)
495 def updateStyle(self
):
496 # called after a control edited self.names, self.values
497 # Special case for saving common defs settings
498 if self
.styleNum
== 'common':
502 strVal
= self
.style
[2] = self
.values
.values()[0]
503 if self
.style
[1] == 'size': self
.style
[2] = int(strVal
)
505 self
.commonDefs
[self
.style
[0]] = self
.style
[2]
506 self
.styleDefST
.SetLabel(strVal
)
508 self
.style
= writePropVal(self
.names
, self
.values
)
509 styleDecl
= writeProp(self
.styleNum
, self
.style
, self
.lang
)
510 self
.styles
[self
.styleNumIdxMap
[self
.styleNum
]] = styleDecl
511 self
.styleDefST
.SetLabel(self
.style
)
514 def findInStyles(self
, txt
, styles
):
516 if style
.find(txt
) != -1:
520 def rememberStyles(self
):
521 return self
.names
[:], copy
.copy(self
.values
)
523 def restoreStyles(self
, style
):
524 self
.names
, self
.values
= style
527 def clearCtrls(self
, isDefault
=False, disableDefs
=False):
528 self
._blockUpdate
= True
530 for ctrl
, chb
, prop
, wid
in self
.allCtrls
:
531 if prop
in ('fore', 'back'):
532 cbtn
, txt
, btn
= ctrl
533 cbtn
.SetBackgroundColour(\
534 wx
.SystemSettings
.GetColour(wx
.SYS_COLOUR_BTNFACE
))
535 cbtn
.SetForegroundColour(wx
.Colour(255, 255, 255))
536 cbtn
.Enable(isDefault
)
538 txt
.Enable(isDefault
)
539 btn
.Enable(isDefault
)
543 cmb
.Enable(isDefault
)
544 btn
.Enable(isDefault
)
548 cmb
.Enable(isDefault
)
549 btn
.Enable(isDefault
)
550 chk
.Enable(isDefault
)
552 elif prop
in ('bold', 'italic', 'underline', 'eolfilled'):
554 ctrl
.Enable(isDefault
)
556 chb
.Enable(not isDefault
and not disableDefs
)
559 self
._blockUpdate
= False
561 def populateProp(self
, items
, default
, forceDisable
=False):
562 self
._blockUpdate
= True
564 for name
, val
in items
:
566 ctrl
, chb
= self
.getCtrlForProp(name
)
568 if name
in ('fore', 'back'):
569 cbtn
, txt
, btn
= ctrl
570 repval
= val
%self
.commonDefs
571 cbtn
.SetBackgroundColour(strToCol(repval
))
572 cbtn
.SetForegroundColour(wx
.Colour(0, 0, 0))
573 cbtn
.Enable(not forceDisable
)
575 txt
.Enable(not forceDisable
)
576 btn
.Enable(not forceDisable
)
577 chb
.SetValue(default
)
581 cmb
.Enable(not forceDisable
)
582 btn
.Enable(not forceDisable
)
583 chb
.SetValue(default
)
587 cmb
.Enable(not forceDisable
)
588 btn
.Enable(not forceDisable
)
589 chk
.Enable(not forceDisable
)
590 chb
.SetValue(default
)
591 elif name
in ('bold', 'italic', 'underline', 'eolfilled'):
592 ctrl
.Enable(not forceDisable
)
594 chb
.SetValue(default
)
596 self
._blockUpdate
= False
598 def valIsCommonDef(self
, val
):
599 return len(val
) >= 5 and val
[:2] == '%('
601 def populateCtrls(self
):
602 self
.clearCtrls(self
.styleNum
== wx
.stc
.STC_STYLE_DEFAULT
,
603 disableDefs
=self
.styleNum
< 0)
605 # handle colour controls for settings
606 if self
.styleNum
< 0:
607 self
.fgColDefCb
.Enable(True)
608 if self
.styleNum
== -1:
609 self
.bgColDefCb
.Enable(True)
611 # populate with default style
612 self
.populateProp(self
.defValues
.items(), True,
613 self
.styleNum
!= wx
.stc
.STC_STYLE_DEFAULT
)
614 # override with current settings
615 self
.populateProp(self
.values
.items(), False)
617 def getCommonDefPropType(self
, commonDefName
):
618 val
= self
.commonDefs
[commonDefName
]
619 if type(val
) == type(0): return 'size'
620 if len(val
) == 7 and val
[0] == '#': return 'fore'
623 def bindComboEvts(self
, combo
, btn
, btnEvtMeth
, comboEvtMeth
, rdclickEvtMeth
):
624 combo
.Bind(wx
.EVT_COMBOBOX
, comboEvtMeth
, id=combo
.GetId())
625 btn
.Bind(wx
.EVT_BUTTON
, btnEvtMeth
, id=btn
.GetId())
626 combo
.Bind(wx
.EVT_RIGHT_DCLICK
, rdclickEvtMeth
)
627 combo
.SetToolTipString('Select from list or click "ok" button on the right to change a manual entry, right double-click \n'\
628 'the drop down button to select Common definition in the Style Editor (if applicable)')
629 btn
.SetToolTipString('Accept value')
631 def populateCombosWithCommonDefs(self
, fixedWidthOnly
=None):
632 self
._blockUpdate
= True
634 commonDefs
= {'fore': [], 'face': [], 'size': []}
636 if self
.elementLb
.GetSelection() < self
.commonDefsStartIdx
:
637 for common
in self
.commonDefs
.keys():
638 prop
= self
.getCommonDefPropType(common
)
639 commonDefs
[prop
].append('%%(%s)%s'%(common
,
640 prop
=='size' and 'd' or 's'))
643 currFg
, currBg
= self
.fgColCb
.GetValue(), self
.bgColCb
.GetValue()
644 self
.fgColCb
.Clear(); self
.bgColCb
.Clear()
645 for colCommonDef
in commonDefs
['fore']:
646 self
.fgColCb
.Append(colCommonDef
)
647 self
.bgColCb
.Append(colCommonDef
)
648 self
.fgColCb
.SetValue(currFg
); self
.bgColCb
.SetValue(currBg
)
651 if fixedWidthOnly
is None:
652 fixedWidthOnly
= self
.fixedWidthChk
.GetValue()
653 fontEnum
= wx
.FontEnumerator()
654 fontEnum
.EnumerateFacenames(fixedWidthOnly
=fixedWidthOnly
)
655 fontNameList
= fontEnum
.GetFacenames()
658 currFace
= self
.faceCb
.GetValue()
660 for colCommonDef
in fontNameList
+commonDefs
['face']:
661 self
.faceCb
.Append(colCommonDef
)
662 self
.faceCb
.SetValue(currFace
)
664 # Size (XXX add std font sizes)
665 currSize
= self
.sizeCb
.GetValue()
667 for colCommonDef
in commonDefs
['size']:
668 self
.sizeCb
.Append(colCommonDef
)
669 self
.sizeCb
.SetValue(currSize
)
671 self
._blockUpdate
= False
673 def populateStyleSelector(self
):
674 numStyles
= self
.styleIdNames
.items()
676 self
.styleNumLookup
= {}
681 for num
, name
in numStyles
:
682 if num
== wx
.stc
.STC_STYLE_DEFAULT
:
683 self
.elementLb
.InsertItems([name
, '----Language----'], 0)
684 self
.elementLb
.Append('----Standard----')
685 stdStart
= stdPos
= self
.elementLb
.GetCount()
688 if num
>= 33 and num
< 40:
689 self
.elementLb
.InsertItems([name
], stdStart
+ stdOffset
)
690 stdOffset
= stdOffset
+ 1
693 self
.elementLb
.InsertItems([name
], stdStart
+ extrOffset
-1)
694 extrOffset
= extrOffset
+ 1
697 self
.elementLb
.Append(name
)
698 self
.styleNumLookup
[name
] = num
701 self
.elementLb
.Append('----Settings----')
702 settings
= settingsIdNames
.items()
703 settings
.sort();settings
.reverse()
704 for num
, name
in settings
:
705 self
.elementLb
.Append(name
)
706 self
.styleNumLookup
[name
] = num
709 self
.elementLb
.Append('----Common----')
710 self
.commonDefsStartIdx
= self
.elementLb
.GetCount()
711 for common
in self
.commonDefs
.keys():
712 tpe
= type(self
.commonDefs
[common
])
713 self
.elementLb
.Append('%('+common
+')'+(tpe
is type('') and 's' or 'd'))
714 self
.styleNumLookup
[common
] = num
716 #---Colour methods--------------------------------------------------------------
717 def getColourDlg(self
, colour
, title
=''):
718 data
= wx
.ColourData()
719 data
.SetColour(colour
)
720 data
.SetChooseFull(True)
721 dlg
= wx
.ColourDialog(self
, data
)
724 if dlg
.ShowModal() == wx
.ID_OK
:
725 data
= dlg
.GetColourData()
726 return data
.GetColour()
731 colDlgTitles
= {'fore': 'Foreground', 'back': 'Background'}
732 def editColProp(self
, colBtn
, colCb
, prop
):
733 col
= self
.getColourDlg(colBtn
.GetBackgroundColour(),
734 self
.colDlgTitles
[prop
]+ ' colour')
736 colBtn
.SetForegroundColour(wx
.Colour(0, 0, 0))
737 colBtn
.SetBackgroundColour(col
)
738 colStr
= colToStr(col
)
739 colCb
.SetValue(colStr
)
740 self
.editProp(True, prop
, colStr
)
742 def OnFgcolbtnButton(self
, event
):
743 self
.editColProp(self
.fgColBtn
, self
.fgColCb
, 'fore')
745 def OnBgcolbtnButton(self
, event
):
746 self
.editColProp(self
.bgColBtn
, self
.bgColCb
, 'back')
748 def editColTCProp(self
, colCb
, colBtn
, prop
, val
=None):
750 colStr
= colCb
.GetValue()
754 col
= strToCol(colStr
%self
.commonDefs
)
755 if self
.editProp(colStr
!='', prop
, colStr
):
757 colBtn
.SetForegroundColour(wx
.Colour(0, 0, 0))
758 colBtn
.SetBackgroundColour(col
)
760 colBtn
.SetForegroundColour(wx
.Colour(255, 255, 255))
761 colBtn
.SetBackgroundColour(\
762 wxSystemSettings
.GetColour(wx
.SYS_COLOUR_BTNFACE
))
764 def OnfgColRet(self
, event
):
765 try: self
.editColTCProp(self
.fgColCb
, self
.fgColBtn
, 'fore')
766 except AssertionError: wx
.LogError('Not a valid colour value')
768 def OnfgColCombobox(self
, event
):
769 if self
._blockUpdate
: return
770 try: self
.editColTCProp(self
.fgColCb
, self
.fgColBtn
, 'fore', event
.GetString())
771 except AssertionError: wx
.LogError('Not a valid colour value')
773 def OnbgColRet(self
, event
):
774 try: self
.editColTCProp(self
.bgColCb
, self
.bgColBtn
, 'back')
775 except AssertionError: wx
.LogError('Not a valid colour value')
777 def OnbgColCombobox(self
, event
):
778 if self
._blockUpdate
: return
779 try: self
.editColTCProp(self
.bgColCb
, self
.bgColBtn
, 'back', event
.GetString())
780 except AssertionError: wx
.LogError('Not a valid colour value')
782 #---Text attribute events-------------------------------------------------------
783 def OnTaeoffilledcbCheckbox(self
, event
):
784 self
.editProp(event
.IsChecked(), 'eolfilled')
786 def OnTaitaliccbCheckbox(self
, event
):
787 self
.editProp(event
.IsChecked(), 'italic')
789 def OnTaboldcbCheckbox(self
, event
):
790 self
.editProp(event
.IsChecked(), 'bold')
792 def OnTaunderlinedcbCheckbox(self
, event
):
793 self
.editProp(event
.IsChecked(), 'underline')
795 def OnGotoCommonDef(self
, event
):
796 val
= event
.GetEventObject().GetValue()
797 if self
.valIsCommonDef(val
):
798 idx
= self
.elementLb
.FindString(val
)
800 self
.elementLb
.SetSelection(idx
, True)
801 self
.OnElementlbListbox(None)
803 def OnfaceRet(self
, event
):
804 self
.setFace(self
.faceCb
.GetValue())
806 def OnfaceCombobox(self
, event
):
807 if self
._blockUpdate
: return
808 self
.setFace(event
.GetString())
810 def setFace(self
, val
):
811 try: val
%self
.commonDefs
812 except KeyError: wx
.LogError('Invalid common definition')
813 else: self
.editProp(val
!='', 'face', val
)
815 def OnsizeRet(self
, event
):
816 self
.setSize(self
.sizeCb
.GetValue())
818 def OnsizeCombobox(self
, event
):
819 if self
._blockUpdate
: return
820 self
.setSize(event
.GetString())
822 def setSize(self
, val
):
823 try: int(val
%self
.commonDefs
)
824 except ValueError: wx
.LogError('Not a valid integer size value')
825 except KeyError: wx
.LogError('Invalid common definition')
826 else: self
.editProp(val
!='', 'size', val
)
828 #---Main GUI events-------------------------------------------------------------
829 def OnElementlbListbox(self
, event
):
830 isCommon
= self
.elementLb
.GetSelection() >= self
.commonDefsStartIdx
831 self
.removeCommonItemBtn
.Enable(isCommon
)
833 styleIdent
= self
.elementLb
.GetStringSelection()
834 # common definition selected
836 common
= styleIdent
[2:-2]
837 prop
= self
.getCommonDefPropType(common
)
838 self
.clearCtrls(disableDefs
=True)
840 self
.fgColBtn
.Enable(True)
841 self
.fgColCb
.Enable(True)
842 self
.fgColOkBtn
.Enable(True)
844 self
.faceCb
.Enable(True)
845 self
.fixedWidthChk
.Enable(True)
846 self
.faceOkBtn
.Enable(True)
848 self
.sizeCb
.Enable(True)
849 self
.sizeOkBtn
.Enable(True)
851 commonDefVal
= str(self
.commonDefs
[common
])
852 self
.styleDefST
.SetLabel(commonDefVal
)
853 self
.populateProp( [(prop
, commonDefVal
)], True)
855 self
.styleNum
= 'common'
856 self
.style
= [common
, prop
, commonDefVal
]
857 self
.names
, self
.values
= [prop
], {prop: commonDefVal}
859 # normal style element selected
860 elif len(styleIdent
) >=2 and styleIdent
[:2] != '--':
861 self
.styleNum
= self
.styleNumLookup
[styleIdent
]
862 self
.style
= self
.styleDict
[self
.styleNum
]
863 self
.names
, self
.values
= parseProp(self
.style
)
864 if self
.styleNum
== wx
.stc
.STC_STYLE_DEFAULT
:
865 self
.defNames
, self
.defValues
= \
866 self
.names
, self
.values
868 self
.checkBraces(self
.styleNum
)
870 self
.styleDefST
.SetLabel(self
.style
)
875 self
.clearCtrls(disableDefs
=True)
877 self
.styleDefST
.SetLabel(styleCategoryDescriptions
[styleIdent
])
879 self
.populateCombosWithCommonDefs()
881 def OnDefaultCheckBox(self
, event
):
882 if self
.chbIdMap
.has_key(event
.GetId()):
883 ctrl
, chb
, prop
, wid
= self
.chbIdMap
[event
.GetId()]
884 restore
= not event
.IsChecked()
885 if prop
in ('fore', 'back'):
886 cbtn
, cmb
, btn
= ctrl
891 colStr
= cmb
.GetValue()
892 #if prop == 'fore': colStr = self.fgColCb.GetValue()
893 #else: colStr = self.bgColCb.GetValue()
894 if colStr
: self
.editProp(True, prop
, colStr
)
896 self
.editProp(False, prop
)
900 if val
: self
.editProp(restore
, prop
, val
)
905 val
= cmb
.GetStringSelection()
906 if val
: self
.editProp(restore
, prop
, val
)
910 elif prop
in ('bold', 'italic', 'underline', 'eolfilled'):
912 if ctrl
.GetValue(): self
.editProp(restore
, prop
)
914 def OnOkbtnButton(self
, event
):
915 # write styles and common defs to the config
918 writeStylesToConfig(self
.config
, 'style.%s'%self
.lang
, self
.styles
)
919 self
.config
.SetPath('')
920 self
.config
.Write(commonDefsFile
, `self
.commonDefs`
)
923 for stc
in self
.STCsToUpdate
:
924 setSTCStyles(stc
, self
.styles
, self
.styleIdNames
, self
.commonDefs
,
925 self
.lang
, self
.lexer
, self
.keywords
)
928 self
.EndModal(wx
.ID_OK
)
930 def OnCancelbtnButton(self
, event
):
931 self
.EndModal(wx
.ID_CANCEL
)
933 def OnCommondefsbtnButton(self
, event
):
934 dlg
= wx
.TextEntryDialog(self
, 'Edit common definitions dictionary',
935 'Common definitions', pprint
.pformat(self
.commonDefs
),
936 style
=wx
.TE_MULTILINE | wx
.OK | wx
.CANCEL | wx
.CENTRE
)
938 if dlg
.ShowModal() == wx
.ID_OK
:
939 answer
= eval(dlg
.GetValue(), stc
.__dict
__)
940 assert type(answer
) is type({}), 'Not a valid dictionary'
941 oldDefs
= self
.commonDefs
942 self
.commonDefs
= answer
945 except KeyError, badkey
:
946 wx
.LogError(str(badkey
)+' not defined but required, \n'\
947 'reverting to previous common definition')
948 self
.commonDefs
= oldDefs
950 self
.populateCombosWithCommonDefs()
955 def OnSpeedsettingchChoice(self
, event
):
956 group
= event
.GetString()
958 userStyles
= 'style.%s'%self
.lang
959 if self
.currSpeedSetting
== userStyles
:
960 self
.predefStyleGroups
[userStyles
] = self
.styles
961 self
.styles
= self
.predefStyleGroups
[group
]
963 self
.defNames
, self
.defValues
= parseProp(\
964 self
.styleDict
.get(wx
.stc
.STC_STYLE_DEFAULT
, ''))
965 self
.OnElementlbListbox(None)
966 self
.currSpeedSetting
= group
968 def OnFixedwidthchkCheckbox(self
, event
):
969 self
.populateCombosWithCommonDefs(event
.IsChecked())
971 def OnAddsharebtnButton(self
, event
):
972 dlg
= CommonDefDlg(self
)
974 if dlg
.ShowModal() == wx
.ID_OK
:
975 prop
, name
= dlg
.result
976 if not self
.commonDefs
.has_key(name
):
977 self
.commonDefs
[name
] = commonPropDefs
[prop
]
978 self
.elementLb
.Append('%('+name
+')'+\
979 (type(commonPropDefs
[prop
]) is type('') and 's' or 'd'))
980 self
.elementLb
.SetSelection(self
.elementLb
.GetCount()-1, True)
981 self
.populateCombosWithCommonDefs()
982 self
.OnElementlbListbox(None)
986 def OnRemovesharebtnButton(self
, event
):
987 ownGroup
= 'style.%s'%self
.lang
988 comDef
= self
.elementLb
.GetStringSelection()
990 # Search ALL styles before removing
991 srchDct
= {ownGroup: self.styles}
992 srchDct
.update(self
.predefStyleGroups
)
993 srchDct
.update(self
.otherLangStyleGroups
)
996 for grpName
, styles
in srchDct
.items():
997 if self
.findInStyles(comDef
, styles
):
998 matchList
.append(grpName
)
1001 wx
.LogError('Aborted: '+comDef
+' is still used in the styles of the \n'\
1002 'following groups in the config file (stc-styles.rc.cfg):\n'+ \
1003 '\n'.join(matchList
))
1005 del self
.commonDefs
[comDef
[2:-2]]
1007 self
.populateCombosWithCommonDefs()
1008 selIdx
= self
.elementLb
.GetSelection()
1009 self
.elementLb
.Delete(selIdx
)
1010 if selIdx
== self
.elementLb
.GetCount():
1012 self
.elementLb
.SetSelection(selIdx
, True)
1013 self
.OnElementlbListbox(None)
1015 #---STC events------------------------------------------------------------------
1016 def OnUpdateUI(self
, event
):
1017 styleBefore
= self
.stc
.GetStyleAt(self
.stc
.GetCurrentPos())
1018 if self
.styleIdNames
.has_key(styleBefore
):
1019 self
.elementLb
.SetStringSelection(self
.styleIdNames
[styleBefore
],
1022 self
.elementLb
.SetSelection(0, False)
1023 self
.styleDefST
.SetLabel('Style %d not defined, sorry.'%styleBefore
)
1024 self
.OnElementlbListbox(None)
1027 def checkBraces(self
, style
):
1028 if style
== wx
.stc
.STC_STYLE_BRACELIGHT
and self
.braceInfo
.has_key('good'):
1029 line
, col
= self
.braceInfo
['good']
1030 pos
= self
.stc
.PositionFromLine(line
-1) + col
1031 braceOpposite
= self
.stc
.BraceMatch(pos
)
1032 if braceOpposite
!= -1:
1033 self
.stc
.BraceHighlight(pos
, braceOpposite
)
1034 elif style
== wx
.stc
.STC_STYLE_BRACEBAD
and self
.braceInfo
.has_key('bad'):
1035 line
, col
= self
.braceInfo
['bad']
1036 pos
= self
.stc
.PositionFromLine(line
-1) + col
1037 self
.stc
.BraceBadLight(pos
)
1039 self
.stc
.BraceBadLight(-1)
1042 def OnStcstyleeditdlgSize(self
, event
):
1044 # Without this refresh, resizing leaves artifacts
1048 def OnMarginClick(self
, event
):
1049 self
.elementLb
.SetStringSelection('Line numbers', True)
1050 self
.OnElementlbListbox(None)
1053 #---Common definition dialog----------------------------------------------------
1055 [wxID_COMMONDEFDLG
, wxID_COMMONDEFDLGCANCELBTN
, wxID_COMMONDEFDLGCOMDEFNAMETC
, wxID_COMMONDEFDLGOKBTN
, wxID_COMMONDEFDLGPROPTYPERBX
, wxID_COMMONDEFDLGSTATICBOX1
] = [wx
.NewId() for _init_ctrls
in range(6)]
1057 class CommonDefDlg(wx
.Dialog
):
1058 def _init_ctrls(self
, prnt
):
1059 wx
.Dialog
.__init
__(self
, id = wxID_COMMONDEFDLG
, name
= 'CommonDefDlg', parent
= prnt
, pos
= wx
.Point(398, 249), size
= wx
.Size(192, 220), style
= wx
.DEFAULT_DIALOG_STYLE
, title
= 'Common definition')
1060 self
.SetClientSize(wx
.Size(184, 200))
1062 self
.propTypeRBx
= wx
.RadioBox(choices
= ['Colour value', 'Font face', 'Size value'], id = wxID_COMMONDEFDLGPROPTYPERBX
, label
= 'Property type', majorDimension
= 1, name
= 'propTypeRBx', parent
= self
, point
= wx
.Point(8, 8), size
= wx
.Size(168, 92), style
= wx
.RA_SPECIFY_COLS
)
1063 self
.propTypeRBx
.SetSelection(self
._propTypeIdx
)
1065 self
.staticBox1
= wx
.StaticBox(id = wxID_COMMONDEFDLGSTATICBOX1
, label
= 'Name', name
= 'staticBox1', parent
= self
, pos
= wx
.Point(8, 108), size
= wx
.Size(168, 46), style
= 0)
1067 self
.comDefNameTC
= wx
.TextCtrl(id = wxID_COMMONDEFDLGCOMDEFNAMETC
, name
= 'comDefNameTC', parent
= self
, pos
= wx
.Point(16, 124), size
= wx
.Size(152, 21), style
= 0, value
= '')
1068 self
.comDefNameTC
.SetLabel(self
._comDefName
)
1070 self
.okBtn
= wx
.Button(id = wxID_COMMONDEFDLGOKBTN
, label
= 'OK', name
= 'okBtn', parent
= self
, pos
= wx
.Point(8, 164), size
= wx
.Size(80, 23), style
= 0)
1071 self
.okBtn
.Bind(wx
.EVT_BUTTON
, self
.OnOkbtnButton
, id=wxID_COMMONDEFDLGOKBTN
)
1073 self
.cancelBtn
= wx
.Button(id = wxID_COMMONDEFDLGCANCELBTN
, label
= 'Cancel', name
= 'cancelBtn', parent
= self
, pos
= wx
.Point(96, 164), size
= wx
.Size(80, 23), style
= 0)
1074 self
.cancelBtn
.Bind(wx
.EVT_BUTTON
, self
.OnCancelbtnButton
, id=wxID_COMMONDEFDLGCANCELBTN
)
1076 def __init__(self
, parent
, name
='', propIdx
=0):
1077 self
._comDefName
= ''
1078 self
._comDefName
= name
1079 self
._propTypeIdx
= 0
1080 self
._propTypeIdx
= propIdx
1081 self
._init
_ctrls
(parent
)
1083 self
.propMap
= {0: 'fore', 1: 'face', 2: 'size'}
1084 self
.result
= ( '', '' )
1086 self
.Center(wx
.BOTH
)
1088 def OnOkbtnButton(self
, event
):
1089 self
.result
= ( self
.propMap
[self
.propTypeRBx
.GetSelection()],
1090 self
.comDefNameTC
.GetValue() )
1091 self
.EndModal(wx
.ID_OK
)
1093 def OnCancelbtnButton(self
, event
):
1094 self
.result
= ( '', '' )
1095 self
.EndModal(wx
.ID_CANCEL
)
1097 #---Functions useful outside of the editor----------------------------------
1099 def setSelectionColour(stc
, style
):
1100 names
, values
= parseProp(style
)
1102 stc
.SetSelForeground(True, strToCol(values
['fore']))
1104 stc
.SetSelBackground(True, strToCol(values
['back']))
1106 def setCursorColour(stc
, style
):
1107 names
, values
= parseProp(style
)
1109 stc
.SetCaretForeground(strToCol(values
['fore']))
1111 def setEdgeColour(stc
, style
):
1112 names
, values
= parseProp(style
)
1114 stc
.SetEdgeColour(strToCol(values
['fore']))
1116 def strToCol(strCol
):
1117 assert len(strCol
) == 7 and strCol
[0] == '#', 'Not a valid colour string: '+strCol
1118 return wx
.Colour(string
.atoi('0x'+strCol
[1:3], 16),
1119 string
.atoi('0x'+strCol
[3:5], 16),
1120 string
.atoi('0x'+strCol
[5:7], 16))
1122 return '#%s%s%s' % (string
.zfill(string
.upper(hex(col
.Red())[2:]), 2),
1123 string
.zfill(string
.upper(hex(col
.Green())[2:]), 2),
1124 string
.zfill(string
.upper(hex(col
.Blue())[2:]), 2))
1126 def writeProp(num
, style
, lang
):
1128 return 'style.%s.%s='%(lang
, string
.zfill(`num`
, 3)) + style
1130 return 'setting.%s.%d='%(lang
, num
) + style
1132 def writePropVal(names
, values
):
1136 res
.append(values
[name
] and name
+':'+values
[name
] or name
)
1137 return ','.join(res
)
1139 def parseProp(prop
):
1140 items
= prop
.split(',')
1144 nameVal
= item
.split(':')
1145 names
.append(nameVal
[0].strip())
1146 if len(nameVal
) == 1:
1147 values
[nameVal
[0]] = ''
1149 values
[nameVal
[0]] = nameVal
[1].strip()
1150 return names
, values
1152 def parsePropLine(prop
):
1153 name
, value
= prop
.split('=')
1154 return int(name
.split('.')[-1]), value
1156 def setSTCStyles(stc
, styles
, styleIdNames
, commonDefs
, lang
, lexer
, keywords
):
1160 # build style dict based on given styles
1161 for numStyle
in styles
:
1162 num
, style
= parsePropLine(numStyle
)
1163 styleDict
[num
] = style
1165 # Add blank style entries for undefined styles
1167 styleItems
= styleIdNames
.items() + settingsIdNames
.items()
1170 for num
, name
in styleItems
:
1171 styleNumIdxMap
[num
] = idx
1172 if not styleDict
.has_key(num
):
1174 newStyles
.append(writeProp(num
, styleDict
[num
], lang
))
1177 # Set background colour to reduce flashing effect on refresh or page switch
1179 if styleDict
.has_key(0): prop
= styleDict
[0]
1180 else: prop
= styleDict
[wx
.stc
.STC_STYLE_DEFAULT
]
1181 names
, vals
= parseProp(prop
)
1183 bkCol
= strToCol(vals
['back']%commonDefs
)
1186 stc
.SetBackgroundColour(bkCol
)
1188 # Set the styles on the wxSTC
1189 stc
.StyleResetDefault()
1190 stc
.ClearDocumentStyle()
1192 stc
.SetKeyWords(0, keywords
)
1193 stc
.StyleSetSpec(wx
.stc
.STC_STYLE_DEFAULT
,
1194 styleDict
[wx
.stc
.STC_STYLE_DEFAULT
] % commonDefs
)
1197 for num
, style
in styleDict
.items():
1199 stc
.StyleSetSpec(num
, style
% commonDefs
)
1201 setSelectionColour(stc
, style
% commonDefs
)
1203 setCursorColour(stc
, style
% commonDefs
)
1205 setEdgeColour(stc
, style
% commonDefs
)
1207 stc
.Colourise(0, stc
.GetTextLength())
1209 return newStyles
, styleDict
, styleNumIdxMap
1211 #---Config reading and writing -------------------------------------------------
1212 commonDefsFile
= 'common.defs.%s'%(platformSettings
[wx
.Platform
][0])
1214 def readPyValFromConfig(conf
, name
):
1216 #ns.update(wx.stc.__dict__)
1217 ns
.update(wxPython
.stc
.__dict
__)
1219 value
= conf
.Read(name
).replace('\r\n', '\n')+'\n'
1221 return eval(value
, ns
)
1226 def initFromConfig(configFile
, lang
):
1227 if not os
.path
.exists(configFile
):
1228 raise Exception, 'Config file %s not found'%configFile
1229 cfg
= wx
.FileConfig(localFilename
=configFile
, style
= wx
.CONFIG_USE_LOCAL_FILE
)
1230 cfg
.SetExpandEnvVars(False)
1232 # read in all group names for this language
1233 groupPrefix
= 'style.%s'%lang
1234 gpLen
= len(groupPrefix
)
1235 predefStyleGroupNames
, otherLangStyleGroupNames
= [], []
1236 cont
, val
, idx
= cfg
.GetFirstGroup()
1238 if val
!= groupPrefix
and len(val
) >= 5 and val
[:5] == 'style':
1239 if len(val
) > gpLen
and val
[:gpLen
] == groupPrefix
:
1240 predefStyleGroupNames
.append(val
)
1242 otherLangStyleGroupNames
.append(val
)
1244 cont
, val
, idx
= cfg
.GetNextGroup(idx
)
1246 # read in common elements
1247 commonDefs
= readPyValFromConfig(cfg
, commonDefsFile
)
1248 assert type(commonDefs
) is type({}), \
1249 'Common definitions (%s) not a valid dict'%commonDefsFile
1251 commonStyleIdNames
= readPyValFromConfig(cfg
, 'common.styleidnames')
1252 assert type(commonStyleIdNames
) is type({}), \
1253 'Common definitions (%s) not a valid dict'%'common.styleidnames'
1255 # Lang specific settings
1257 styleIdNames
= readPyValFromConfig(cfg
, 'styleidnames')
1258 assert type(commonStyleIdNames
) is type({}), \
1259 'Not a valid dict [%s] styleidnames)'%lang
1260 styleIdNames
.update(commonStyleIdNames
)
1261 braceInfo
= readPyValFromConfig(cfg
, 'braces')
1262 assert type(commonStyleIdNames
) is type({}), \
1263 'Not a valid dict [%s] braces)'%lang
1265 displaySrc
= cfg
.Read('displaysrc')
1266 lexer
= readPyValFromConfig(cfg
, 'lexer')
1267 keywords
= cfg
.Read('keywords')
1271 # read in current styles
1272 styles
= readStylesFromConfig(cfg
, groupPrefix
)
1274 # read in predefined styles
1275 predefStyleGroups
= {}
1276 for group
in predefStyleGroupNames
:
1277 predefStyleGroups
[group
] = readStylesFromConfig(cfg
, group
)
1279 # read in all other style sections
1280 otherLangStyleGroups
= {}
1281 for group
in otherLangStyleGroupNames
:
1282 otherLangStyleGroups
[group
] = readStylesFromConfig(cfg
, group
)
1284 return (cfg
, commonDefs
, styleIdNames
, styles
, predefStyleGroupNames
,
1285 predefStyleGroups
, otherLangStyleGroupNames
, otherLangStyleGroups
,
1286 displaySrc
, lexer
, keywords
, braceInfo
)
1288 def readStylesFromConfig(config
, group
):
1290 config
.SetPath(group
)
1292 cont
, val
, idx
= config
.GetFirstEntry()
1294 styles
.append(val
+'='+config
.Read(val
))
1295 cont
, val
, idx
= config
.GetNextEntry(idx
)
1300 def writeStylesToConfig(config
, group
, styles
):
1302 config
.DeleteGroup(group
)
1303 config
.SetPath(group
)
1305 for style
in styles
:
1306 name
, value
= style
.split('=')
1307 config
.Write(name
, value
.strip())
1311 #-------------------------------------------------------------------------------
1312 def initSTC(stc
, config
, lang
):
1313 """ Main module entry point. Initialise a wxSTC from given config file."""
1314 (cfg
, commonDefs
, styleIdNames
, styles
, predefStyleGroupNames
,
1315 predefStyleGroups
, otherLangStyleGroupNames
, otherLangStyleGroups
,
1316 displaySrc
, lexer
, keywords
, braceInfo
) = initFromConfig(config
, lang
)
1318 setSTCStyles(stc
, styles
, styleIdNames
, commonDefs
, lang
, lexer
, keywords
)
1320 #-------------------------------------------------------------------------------
1321 if __name__
== '__main__':
1322 app
= wx
.PySimpleApp()
1324 provider
= wx
.SimpleHelpProvider()
1325 wx
.HelpProvider
.Set(provider
)
1327 home
= os
.environ
.get('HOME')
1329 home
= os
.path
.join(home
, '.boa-constructor')
1330 if not os
.path
.exists(home
):
1335 config
= os
.path
.abspath(os
.path
.join(home
, 'stc-styles.rc.cfg'))
1337 f
= wx
.Frame(None, -1, 'Test frame (double click for editor)')
1338 stc
= wx
.stc
.StyledTextCtrl(f
, -1)
1339 def OnDblClick(evt
, stc
=stc
):
1340 dlg
= STCStyleEditDlg(None, 'Python', 'python', config
, (stc
,))
1341 try: dlg
.ShowModal()
1342 finally: dlg
.Destroy()
1343 stc
.SetText(open('STCStyleEditor.py').read())
1344 stc
.Bind(wx
.EVT_LEFT_DCLICK
, OnDblClick
)
1345 initSTC(stc
, config
, 'python')
1349 dlg
= STCStyleEditDlg(None,
1355 #'Properties', 'prop',
1357 try: dlg
.ShowModal()
1358 finally: dlg
.Destroy()