]> git.saurik.com Git - wxWidgets.git/blame - wxPython/samples/StyleEditor/STCStyleEditor.py
clear BUILD_ANIMATE when CORE_ONLY == 1
[wxWidgets.git] / wxPython / samples / StyleEditor / STCStyleEditor.py
CommitLineData
00b6c4e3
RD
1#-----------------------------------------------------------------------------
2# Name: STCStyleEditor.py
3# Purpose: Style editor for the wxStyledTextCtrl
4#
5# Author: Riaan Booysen
6#
7# Created: 2001/08/20
8# RCS-ID: $Id$
1e4a197e 9# Copyright: (c) 2001 - 2002 Riaan Booysen
00b6c4e3
RD
10# Licence: wxWindows license
11#-----------------------------------------------------------------------------
12#Boa:Dialog:STCStyleEditDlg
13
14""" Style editor for the wxStyledTextCtrl.
15
16Reads in property style definitions from a config file.
17Modified styled can be saved (and optionally applied to a given list of STCs)
18
1114f46e 19It can also maintain a Common definition dictionary of font names, colours and
00b6c4e3
RD
20sizes which can be shared across multiple language style definitions.
21This is also used to store platform spesific settings as fonts and sizes
22vary with platform.
23
24The following items are defined in the stc-styles.rc.cfg file.
25
26common.defs.msw - Common definition dictionary used on wxMSW
27common.defs.gtk - Common definition dictionary used on wxGTK
28common.styleidnames - STC styles shared by all languages
29
30Each supported language defines the following groups:
31[<language>]
32displaysrc - Example source to display in the editor
33braces - Dictionary defining the (line, column) for showing 'good' and 'bad'
34 brace matching (both keys optional)
35keywords - Space separated list of keywords
36lexer - wxSTC constant for the language lexer
37styleidnames - Dictionary of language spesific style numbers and names
38
39[style.<language>] - The users current style values
40[style.<language>.default] - Default style values (can be reverted from)
41
420 or more predefined style groups or 'themes'
43[style.<language>.<predefined name>]
44
1114f46e 45Currently the following languages are supported:
00b6c4e3
RD
46 python, html, xml, cpp, text, props
47Other languages can be added by just defining the above settings for them in
48the config file (if wxSTC implements them).
49
50Use the initSTC function to initialise your wxSTC from a config file.
51"""
52
53import os, sys, string, pprint, copy
54
55from wxPython.wx import *
1e4a197e 56from wxPython.help import *
00b6c4e3
RD
57from wxPython.lib.anchors import LayoutAnchors
58from wxPython.stc import *
59
60settingsIdNames = {-1: 'Selection', -2: 'Caret', -3: 'Edge'}
61
abd78a9f 62commonPropDefs = {}
00b6c4e3
RD
63
64styleCategoryDescriptions = {
1e4a197e
RD
65 '----Language----': 'Styles spesific to the language',
66 '----Standard----': 'Styles shared by all languages',
67 '----Settings----': 'Properties set by STC methods',
68 '----Common----': 'User definable values that can be shared between languages'}
69
70[wxID_STCSTYLEEDITDLG, wxID_STCSTYLEEDITDLGADDCOMMONITEMBTN,
71 wxID_STCSTYLEEDITDLGBGCOLBTN, wxID_STCSTYLEEDITDLGBGCOLCB,
72 wxID_STCSTYLEEDITDLGBGCOLDEFCB, wxID_STCSTYLEEDITDLGBGCOLOKBTN,
73 wxID_STCSTYLEEDITDLGCANCELBTN, wxID_STCSTYLEEDITDLGCONTEXTHELPBUTTON1,
74 wxID_STCSTYLEEDITDLGELEMENTLB, wxID_STCSTYLEEDITDLGFACECB,
75 wxID_STCSTYLEEDITDLGFACEDEFCB, wxID_STCSTYLEEDITDLGFACEOKBTN,
76 wxID_STCSTYLEEDITDLGFGCOLBTN, wxID_STCSTYLEEDITDLGFGCOLCB,
77 wxID_STCSTYLEEDITDLGFGCOLDEFCB, wxID_STCSTYLEEDITDLGFGCOLOKBTN,
78 wxID_STCSTYLEEDITDLGFIXEDWIDTHCHK, wxID_STCSTYLEEDITDLGOKBTN,
79 wxID_STCSTYLEEDITDLGPANEL1, wxID_STCSTYLEEDITDLGPANEL2,
80 wxID_STCSTYLEEDITDLGPANEL3, wxID_STCSTYLEEDITDLGPANEL4,
81 wxID_STCSTYLEEDITDLGREMOVECOMMONITEMBTN, wxID_STCSTYLEEDITDLGSIZECB,
82 wxID_STCSTYLEEDITDLGSIZEOKBTN, wxID_STCSTYLEEDITDLGSPEEDSETTINGCH,
83 wxID_STCSTYLEEDITDLGSTATICBOX1, wxID_STCSTYLEEDITDLGSTATICBOX2,
84 wxID_STCSTYLEEDITDLGSTATICLINE1, wxID_STCSTYLEEDITDLGSTATICTEXT2,
85 wxID_STCSTYLEEDITDLGSTATICTEXT3, wxID_STCSTYLEEDITDLGSTATICTEXT4,
86 wxID_STCSTYLEEDITDLGSTATICTEXT6, wxID_STCSTYLEEDITDLGSTATICTEXT7,
87 wxID_STCSTYLEEDITDLGSTATICTEXT8, wxID_STCSTYLEEDITDLGSTATICTEXT9,
88 wxID_STCSTYLEEDITDLGSTC, wxID_STCSTYLEEDITDLGSTYLEDEFST,
89 wxID_STCSTYLEEDITDLGTABOLDCB, wxID_STCSTYLEEDITDLGTABOLDDEFCB,
90 wxID_STCSTYLEEDITDLGTAEOLFILLEDCB, wxID_STCSTYLEEDITDLGTAEOLFILLEDDEFCB,
91 wxID_STCSTYLEEDITDLGTAITALICCB, wxID_STCSTYLEEDITDLGTAITALICDEFCB,
92 wxID_STCSTYLEEDITDLGTASIZEDEFCB, wxID_STCSTYLEEDITDLGTAUNDERLINEDCB,
93 wxID_STCSTYLEEDITDLGTAUNDERLINEDDEFCB,
94] = map(lambda _init_ctrls: wxNewId(), range(47))
00b6c4e3
RD
95
96class STCStyleEditDlg(wxDialog):
97 """ Style editor for the wxStyledTextCtrl """
98 _custom_classes = {'wxWindow' : ['wxStyledTextCtrl']}
1114f46e 99 def _init_utils(self):
1e4a197e 100 # generated method, don't edit
00b6c4e3
RD
101 pass
102
1114f46e 103 def _init_ctrls(self, prnt):
1e4a197e
RD
104 # generated method, don't edit
105 wxDialog.__init__(self, id=wxID_STCSTYLEEDITDLG, name='STCStyleEditDlg',
106 parent=prnt, pos=wxPoint(583, 291), size=wxSize(459, 482),
107 style=wxWANTS_CHARS | wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER,
108 title=self.stc_title)
00b6c4e3 109 self._init_utils()
1e4a197e
RD
110 self.SetClientSize(wxSize(451, 455))
111 self.SetAutoLayout(True)
00b6c4e3 112 self.SetSizeHints(425, 400, -1, -1)
1e4a197e 113 self.Center(wxBOTH)
00b6c4e3
RD
114 EVT_SIZE(self, self.OnStcstyleeditdlgSize)
115
1e4a197e
RD
116 self.speedsettingCh = wxChoice(choices=[],
117 id=wxID_STCSTYLEEDITDLGSPEEDSETTINGCH, name='speedsettingCh',
118 parent=self, pos=wxPoint(96, 28), size=wxSize(346, 21), style=0,
119 validator=wxDefaultValidator)
120 self.speedsettingCh.SetConstraints(LayoutAnchors(self.speedsettingCh,
121 True, True, True, False))
122 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.')
123 EVT_CHOICE(self.speedsettingCh, wxID_STCSTYLEEDITDLGSPEEDSETTINGCH,
124 self.OnSpeedsettingchChoice)
125
126 self.elementLb = wxListBox(choices=[], id=wxID_STCSTYLEEDITDLGELEMENTLB,
127 name='elementLb', parent=self, pos=wxPoint(8, 72),
128 size=wxSize(160, 112), style=0, validator=wxDefaultValidator)
129 self.elementLb.SetConstraints(LayoutAnchors(self.elementLb, True, True,
130 True, False))
131 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.')
132 EVT_LISTBOX(self.elementLb, wxID_STCSTYLEEDITDLGELEMENTLB,
133 self.OnElementlbListbox)
134
135 self.addCommonItemBtn = wxButton(id=wxID_STCSTYLEEDITDLGADDCOMMONITEMBTN,
136 label='Add', name='addCommonItemBtn', parent=self, pos=wxPoint(8,
137 184), size=wxSize(80, 17), style=0)
138 self.addCommonItemBtn.SetToolTipString('Add new Common definition')
139 EVT_BUTTON(self.addCommonItemBtn, wxID_STCSTYLEEDITDLGADDCOMMONITEMBTN,
140 self.OnAddsharebtnButton)
00b6c4e3 141
1e4a197e
RD
142 self.removeCommonItemBtn = wxButton(id=wxID_STCSTYLEEDITDLGREMOVECOMMONITEMBTN,
143 label='Remove', name='removeCommonItemBtn', parent=self,
144 pos=wxPoint(88, 184), size=wxSize(80, 17), style=0)
145 self.removeCommonItemBtn.SetToolTipString('Remove the selected Common definition')
146 EVT_BUTTON(self.removeCommonItemBtn,
147 wxID_STCSTYLEEDITDLGREMOVECOMMONITEMBTN,
148 self.OnRemovesharebtnButton)
149
150 self.styleDefST = wxStaticText(id=wxID_STCSTYLEEDITDLGSTYLEDEFST,
151 label='(nothing selected)', name='styleDefST', parent=self,
152 pos=wxPoint(96, 8), size=wxSize(366, 16),
153 style=wxST_NO_AUTORESIZE)
154 self.styleDefST.SetFont(wxFont(self.style_font_size, wxSWISS, wxNORMAL,
155 wxBOLD, False, ''))
156 self.styleDefST.SetConstraints(LayoutAnchors(self.styleDefST, True,
157 True, True, False))
158
159 self.staticLine1 = wxStaticLine(id=wxID_STCSTYLEEDITDLGSTATICLINE1,
160 name='staticLine1', parent=self, pos=wxPoint(48, 62),
161 size=wxSize(120, 2), style=wxLI_HORIZONTAL)
162 self.staticLine1.SetConstraints(LayoutAnchors(self.staticLine1, True,
163 True, True, False))
164
165 self.staticText6 = wxStaticText(id=wxID_STCSTYLEEDITDLGSTATICTEXT6,
166 label='Style', name='staticText6', parent=self, pos=wxPoint(8,
167 56), size=wxSize(40, 13), style=0)
168
169 self.staticText8 = wxStaticText(id=wxID_STCSTYLEEDITDLGSTATICTEXT8,
170 label='Style def:', name='staticText8', parent=self,
171 pos=wxPoint(8, 8), size=wxSize(88, 13), style=0)
172
173 self.staticText9 = wxStaticText(id=wxID_STCSTYLEEDITDLGSTATICTEXT9,
174 label='SpeedSetting:', name='staticText9', parent=self,
175 pos=wxPoint(8, 32), size=wxSize(88, 13), style=0)
176
177 self.panel3 = wxPanel(id=wxID_STCSTYLEEDITDLGPANEL3, name='panel3',
178 parent=self, pos=wxPoint(176, 56), size=wxSize(146, 104),
179 style=wxTAB_TRAVERSAL)
180 self.panel3.SetConstraints(LayoutAnchors(self.panel3, False, True, True,
181 False))
182
183 self.panel4 = wxPanel(id=wxID_STCSTYLEEDITDLGPANEL4, name='panel4',
184 parent=self, pos=wxPoint(330, 56), size=wxSize(114, 104),
185 style=wxTAB_TRAVERSAL)
186 self.panel4.SetConstraints(LayoutAnchors(self.panel4, False, True, True,
187 False))
188
189 self.panel1 = wxPanel(id=wxID_STCSTYLEEDITDLGPANEL1, name='panel1',
190 parent=self, pos=wxPoint(176, 161), size=wxSize(143, 40),
191 style=wxTAB_TRAVERSAL)
192 self.panel1.SetConstraints(LayoutAnchors(self.panel1, False, True, True,
193 False))
194
195 self.panel2 = wxPanel(id=wxID_STCSTYLEEDITDLGPANEL2, name='panel2',
196 parent=self, pos=wxPoint(330, 162), size=wxSize(112, 40),
197 style=wxTAB_TRAVERSAL)
198 self.panel2.SetConstraints(LayoutAnchors(self.panel2, False, True, True,
199 False))
200
201 self.stc = wxStyledTextCtrl(id=wxID_STCSTYLEEDITDLGSTC, name='stc',
202 parent=self, pos=wxPoint(8, 208), size=wxSize(435, 207),
203 style=wxSUNKEN_BORDER)
204 self.stc.SetConstraints(LayoutAnchors(self.stc, True, True, True, True))
205 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.')
206 EVT_LEFT_UP(self.stc, self.OnUpdateUI)
207 EVT_KEY_UP(self.stc, self.OnUpdateUI)
00b6c4e3 208
1e4a197e
RD
209 self.contextHelpButton1 = wxContextHelpButton(parent=self,
210 pos=wxPoint(8, 423), size=wxSize(24, 24), style=wxBU_AUTODRAW)
211 self.contextHelpButton1.SetConstraints(LayoutAnchors(self.contextHelpButton1,
212 True, False, False, True))
00b6c4e3 213
1e4a197e
RD
214 self.okBtn = wxButton(id=wxID_STCSTYLEEDITDLGOKBTN, label='OK',
215 name='okBtn', parent=self, pos=wxPoint(282, 423), size=wxSize(75,
216 23), style=0)
217 self.okBtn.SetConstraints(LayoutAnchors(self.okBtn, False, False, True,
218 True))
00b6c4e3
RD
219 self.okBtn.SetToolTipString('Save changes to the config file')
220 EVT_BUTTON(self.okBtn, wxID_STCSTYLEEDITDLGOKBTN, self.OnOkbtnButton)
221
1e4a197e
RD
222 self.cancelBtn = wxButton(id=wxID_STCSTYLEEDITDLGCANCELBTN,
223 label='Cancel', name='cancelBtn', parent=self, pos=wxPoint(366,
224 423), size=wxSize(75, 23), style=0)
225 self.cancelBtn.SetConstraints(LayoutAnchors(self.cancelBtn, False,
226 False, True, True))
00b6c4e3 227 self.cancelBtn.SetToolTipString('Close dialog without saving changes')
1e4a197e
RD
228 EVT_BUTTON(self.cancelBtn, wxID_STCSTYLEEDITDLGCANCELBTN,
229 self.OnCancelbtnButton)
00b6c4e3 230
1e4a197e
RD
231 self.staticText4 = wxStaticText(id=wxID_STCSTYLEEDITDLGSTATICTEXT4,
232 label='Face:', name='staticText4', parent=self.panel1,
233 pos=wxPoint(0, 0), size=wxSize(48, 13), style=0)
00b6c4e3 234
1e4a197e
RD
235 self.fixedWidthChk = wxCheckBox(id=wxID_STCSTYLEEDITDLGFIXEDWIDTHCHK,
236 label='', name='fixedWidthChk', parent=self.panel1, pos=wxPoint(0,
237 23), size=wxSize(13, 19), style=0)
00b6c4e3 238 self.fixedWidthChk.SetToolTipString('Check this for Fixed Width fonts')
1e4a197e
RD
239 EVT_CHECKBOX(self.fixedWidthChk, wxID_STCSTYLEEDITDLGFIXEDWIDTHCHK,
240 self.OnFixedwidthchkCheckbox)
241
242 self.faceCb = wxComboBox(choices=[], id=wxID_STCSTYLEEDITDLGFACECB,
243 name='faceCb', parent=self.panel1, pos=wxPoint(17, 18),
244 size=wxSize(105, 21), style=0, validator=wxDefaultValidator,
245 value='')
246
247 self.staticText7 = wxStaticText(id=wxID_STCSTYLEEDITDLGSTATICTEXT7,
248 label='Size:', name='staticText7', parent=self.panel2,
249 pos=wxPoint(0, 0), size=wxSize(40, 13), style=0)
250
251 self.sizeCb = wxComboBox(choices=[], id=wxID_STCSTYLEEDITDLGSIZECB,
252 name='sizeCb', parent=self.panel2, pos=wxPoint(0, 17),
253 size=wxSize(91, 21), style=0, validator=wxDefaultValidator,
254 value='')
255
256 self.sizeOkBtn = wxButton(id=wxID_STCSTYLEEDITDLGSIZEOKBTN, label='ok',
257 name='sizeOkBtn', parent=self.panel2, pos=wxPoint(90, 17),
258 size=wxSize(21, 21), style=0)
259
260 self.faceOkBtn = wxButton(id=wxID_STCSTYLEEDITDLGFACEOKBTN, label='ok',
261 name='faceOkBtn', parent=self.panel1, pos=wxPoint(122, 18),
262 size=wxSize(21, 21), style=0)
263
264 self.fgColBtn = wxButton(id=wxID_STCSTYLEEDITDLGFGCOLBTN,
265 label='Foreground', name='fgColBtn', parent=self.panel3,
266 pos=wxPoint(8, 16), size=wxSize(72, 16), style=0)
267 EVT_BUTTON(self.fgColBtn, wxID_STCSTYLEEDITDLGFGCOLBTN,
268 self.OnFgcolbtnButton)
269
270 self.fgColCb = wxComboBox(choices=[], id=wxID_STCSTYLEEDITDLGFGCOLCB,
271 name='fgColCb', parent=self.panel3, pos=wxPoint(8, 32),
272 size=wxSize(89, 21), style=0, validator=wxDefaultValidator,
273 value='')
274
275 self.fgColOkBtn = wxButton(id=wxID_STCSTYLEEDITDLGFGCOLOKBTN,
276 label='ok', name='fgColOkBtn', parent=self.panel3, pos=wxPoint(96,
277 32), size=wxSize(21, 21), style=0)
278
279 self.staticText3 = wxStaticText(id=wxID_STCSTYLEEDITDLGSTATICTEXT3,
280 label='default', name='staticText3', parent=self.panel3,
281 pos=wxPoint(100, 16), size=wxSize(37, 16), style=0)
282
283 self.fgColDefCb = wxCheckBox(id=wxID_STCSTYLEEDITDLGFGCOLDEFCB,
284 label='checkBox1', name='fgColDefCb', parent=self.panel3,
285 pos=wxPoint(120, 31), size=wxSize(16, 16), style=0)
286
287 self.bgColBtn = wxButton(id=wxID_STCSTYLEEDITDLGBGCOLBTN,
288 label='Background', name='bgColBtn', parent=self.panel3,
289 pos=wxPoint(8, 56), size=wxSize(72, 16), style=0)
290 EVT_BUTTON(self.bgColBtn, wxID_STCSTYLEEDITDLGBGCOLBTN,
291 self.OnBgcolbtnButton)
292
293 self.bgColCb = wxComboBox(choices=[], id=wxID_STCSTYLEEDITDLGBGCOLCB,
294 name='bgColCb', parent=self.panel3, pos=wxPoint(8, 72),
295 size=wxSize(89, 21), style=0, validator=wxDefaultValidator,
296 value='')
297
298 self.bgColOkBtn = wxButton(id=wxID_STCSTYLEEDITDLGBGCOLOKBTN,
299 label='ok', name='bgColOkBtn', parent=self.panel3, pos=wxPoint(96,
300 72), size=wxSize(21, 21), style=0)
301
302 self.staticBox2 = wxStaticBox(id=wxID_STCSTYLEEDITDLGSTATICBOX2,
303 label='Text attributes', name='staticBox2', parent=self.panel4,
304 pos=wxPoint(0, 0), size=wxSize(112, 99), style=0)
305 self.staticBox2.SetConstraints(LayoutAnchors(self.staticBox2, False,
306 True, True, False))
307 self.staticBox2.SetHelpText('Text attribute flags.')
308
309 self.staticText2 = wxStaticText(id=wxID_STCSTYLEEDITDLGSTATICTEXT2,
310 label='default', name='staticText2', parent=self.panel4,
311 pos=wxPoint(68, 11), size=wxSize(37, 16), style=0)
312
313 self.taBoldDefCb = wxCheckBox(id=wxID_STCSTYLEEDITDLGTABOLDDEFCB,
314 label='checkBox1', name='taBoldDefCb', parent=self.panel4,
315 pos=wxPoint(88, 27), size=wxSize(16, 16), style=0)
316
317 self.taItalicDefCb = wxCheckBox(id=wxID_STCSTYLEEDITDLGTAITALICDEFCB,
318 label='checkBox1', name='taItalicDefCb', parent=self.panel4,
319 pos=wxPoint(88, 43), size=wxSize(16, 16), style=0)
320
321 self.taUnderlinedDefCb = wxCheckBox(id=wxID_STCSTYLEEDITDLGTAUNDERLINEDDEFCB,
322 label='checkBox1', name='taUnderlinedDefCb', parent=self.panel4,
323 pos=wxPoint(88, 59), size=wxSize(16, 16), style=0)
324
325 self.taEOLfilledDefCb = wxCheckBox(id=wxID_STCSTYLEEDITDLGTAEOLFILLEDDEFCB,
326 label='checkBox1', name='taEOLfilledDefCb', parent=self.panel4,
327 pos=wxPoint(88, 75), size=wxSize(16, 16), style=0)
328
329 self.taEOLfilledCb = wxCheckBox(id=wxID_STCSTYLEEDITDLGTAEOLFILLEDCB,
330 label='EOL filled', name='taEOLfilledCb', parent=self.panel4,
331 pos=wxPoint(8, 75), size=wxSize(72, 16), style=0)
332 EVT_CHECKBOX(self.taEOLfilledCb, wxID_STCSTYLEEDITDLGTAEOLFILLEDCB,
333 self.OnTaeoffilledcbCheckbox)
334
335 self.taUnderlinedCb = wxCheckBox(id=wxID_STCSTYLEEDITDLGTAUNDERLINEDCB,
336 label='Underlined', name='taUnderlinedCb', parent=self.panel4,
337 pos=wxPoint(8, 59), size=wxSize(72, 16), style=0)
338 EVT_CHECKBOX(self.taUnderlinedCb, wxID_STCSTYLEEDITDLGTAUNDERLINEDCB,
339 self.OnTaunderlinedcbCheckbox)
340
341 self.taItalicCb = wxCheckBox(id=wxID_STCSTYLEEDITDLGTAITALICCB,
342 label='Italic', name='taItalicCb', parent=self.panel4,
343 pos=wxPoint(8, 43), size=wxSize(72, 16), style=0)
344 EVT_CHECKBOX(self.taItalicCb, wxID_STCSTYLEEDITDLGTAITALICCB,
345 self.OnTaitaliccbCheckbox)
346
347 self.taBoldCb = wxCheckBox(id=wxID_STCSTYLEEDITDLGTABOLDCB,
348 label='Bold', name='taBoldCb', parent=self.panel4, pos=wxPoint(8,
349 27), size=wxSize(72, 16), style=0)
350 EVT_CHECKBOX(self.taBoldCb, wxID_STCSTYLEEDITDLGTABOLDCB,
351 self.OnTaboldcbCheckbox)
352
353 self.bgColDefCb = wxCheckBox(id=wxID_STCSTYLEEDITDLGBGCOLDEFCB,
354 label='checkBox1', name='bgColDefCb', parent=self.panel3,
355 pos=wxPoint(120, 71), size=wxSize(16, 16), style=0)
356
357 self.staticBox1 = wxStaticBox(id=wxID_STCSTYLEEDITDLGSTATICBOX1,
358 label='Colour', name='staticBox1', parent=self.panel3,
359 pos=wxPoint(0, 0), size=wxSize(142, 99), style=0)
360 self.staticBox1.SetConstraints(LayoutAnchors(self.staticBox1, False,
361 True, True, False))
362
363 self.faceDefCb = wxCheckBox(id=wxID_STCSTYLEEDITDLGFACEDEFCB,
364 label='checkBox1', name='faceDefCb', parent=self.panel1,
365 pos=wxPoint(120, 0), size=wxSize(16, 16), style=0)
366
367 self.taSizeDefCb = wxCheckBox(id=wxID_STCSTYLEEDITDLGTASIZEDEFCB,
368 label='checkBox1', name='taSizeDefCb', parent=self.panel2,
369 pos=wxPoint(88, 0), size=wxSize(16, 16), style=0)
00b6c4e3 370
1114f46e 371 def __init__(self, parent, langTitle, lang, configFile, STCsToUpdate=()):
abd78a9f
RD
372 global commonPropDefs
373 commonPropDefs = {'fore': '#888888',
374 'size': 8,
375 'face': wxSystemSettings_GetSystemFont(wxSYS_DEFAULT_GUI_FONT).GetFaceName()}
376
00b6c4e3
RD
377 self.stc_title = 'wxStyledTextCtrl Style Editor'
378 self.stc_title = 'wxStyledTextCtrl Style Editor - %s' % langTitle
1e4a197e
RD
379 if wxPlatform == '__WXMSW__':
380 self.style_font_size = 8
381 else:
382 self.style_font_size = 10
00b6c4e3 383 self._init_ctrls(parent)
00b6c4e3
RD
384 self.lang = lang
385 self.configFile = configFile
386 self.style = ''
1e4a197e 387 self.styleNum = 0
00b6c4e3
RD
388 self.names = []
389 self.values = {}
390 self.STCsToUpdate = STCsToUpdate
1e4a197e 391 self._blockUpdate = False
1114f46e 392
1e4a197e
RD
393
394 for combo, okBtn, evtRet, evtCB, evtRDC in (
395 (self.fgColCb, self.fgColOkBtn, self.OnfgColRet, self.OnfgColCombobox, self.OnGotoCommonDef),
396 (self.bgColCb, self.bgColOkBtn, self.OnbgColRet, self.OnbgColCombobox, self.OnGotoCommonDef),
397 (self.faceCb, self.faceOkBtn, self.OnfaceRet, self.OnfaceCombobox, self.OnGotoCommonDef),
398 (self.sizeCb, self.sizeOkBtn, self.OnsizeRet, self.OnsizeCombobox, self.OnGotoCommonDef)):
399 self.bindComboEvts(combo, okBtn, evtRet, evtCB, evtRDC)
1114f46e
RD
400
401 (self.config, self.commonDefs, self.styleIdNames, self.styles,
402 self.styleGroupNames, self.predefStyleGroups,
00b6c4e3
RD
403 self.otherLangStyleGroupNames, self.otherLangStyleGroups,
404 self.displaySrc, self.lexer, self.keywords, self.braceInfo) = \
1114f46e
RD
405 initFromConfig(configFile, lang)
406
00b6c4e3
RD
407 self.currSpeedSetting = 'style.%s'%self.lang
408 for grp in [self.currSpeedSetting]+self.styleGroupNames:
409 self.speedsettingCh.Append(grp)
410 self.speedsettingCh.SetSelection(0)
1114f46e 411
00b6c4e3
RD
412 margin = 0
413 self.stc.SetMarginType(margin, wxSTC_MARGIN_NUMBER)
414 self.stc.SetMarginWidth(margin, 25)
1e4a197e 415 self.stc.SetMarginSensitive(margin, True)
00b6c4e3
RD
416 EVT_STC_MARGINCLICK(self.stc, wxID_STCSTYLEEDITDLGSTC, self.OnMarginClick)
417
1e4a197e 418 self.stc.SetUseTabs(False)
00b6c4e3 419 self.stc.SetTabWidth(4)
1e4a197e 420 self.stc.SetIndentationGuides(True)
00b6c4e3
RD
421 self.stc.SetEdgeMode(wxSTC_EDGE_BACKGROUND)
422 self.stc.SetEdgeColumn(44)
1114f46e 423
00b6c4e3
RD
424 self.setStyles()
425
426 self.populateStyleSelector()
427
428 self.defNames, self.defValues = parseProp(\
429 self.styleDict.get(wxSTC_STYLE_DEFAULT, ''))
00b6c4e3
RD
430 self.stc.SetText(self.displaySrc)
431 self.stc.EmptyUndoBuffer()
432 self.stc.SetCurrentPos(self.stc.GetTextLength())
433 self.stc.SetAnchor(self.stc.GetTextLength())
434
435 self.populateCombosWithCommonDefs()
436
437 # Logical grouping of controls and the property they edit
1e4a197e 438 self.allCtrls = [((self.fgColBtn, self.fgColCb, self.fgColOkBtn), self.fgColDefCb,
00b6c4e3 439 'fore', wxID_STCSTYLEEDITDLGFGCOLDEFCB),
1e4a197e 440 ((self.bgColBtn, self.bgColCb, self.bgColOkBtn), self.bgColDefCb,
00b6c4e3 441 'back', wxID_STCSTYLEEDITDLGBGCOLDEFCB),
1114f46e 442 (self.taBoldCb, self.taBoldDefCb,
00b6c4e3 443 'bold', wxID_STCSTYLEEDITDLGTABOLDDEFCB),
1114f46e
RD
444 (self.taItalicCb, self.taItalicDefCb,
445 'italic', wxID_STCSTYLEEDITDLGTAITALICDEFCB),
446 (self.taUnderlinedCb, self.taUnderlinedDefCb,
00b6c4e3 447 'underline', wxID_STCSTYLEEDITDLGTAUNDERLINEDDEFCB),
1114f46e 448 (self.taEOLfilledCb, self.taEOLfilledDefCb,
00b6c4e3 449 'eolfilled', wxID_STCSTYLEEDITDLGTAEOLFILLEDDEFCB),
1e4a197e 450 ((self.sizeCb, self.sizeOkBtn), self.taSizeDefCb,
00b6c4e3 451 'size', wxID_STCSTYLEEDITDLGTASIZEDEFCB),
1e4a197e 452 ((self.faceCb, self.faceOkBtn, self.fixedWidthChk), self.faceDefCb,
00b6c4e3
RD
453 'face', wxID_STCSTYLEEDITDLGFACEDEFCB)]
454
1e4a197e 455 self.clearCtrls(disableDefs=True)
00b6c4e3
RD
456 # centralised default checkbox event handler
457 self.chbIdMap = {}
458 for ctrl, chb, prop, wid in self.allCtrls:
459 self.chbIdMap[wid] = ctrl, chb, prop, wid
460 EVT_CHECKBOX(chb, wid, self.OnDefaultCheckBox)
461 chb.SetToolTipString('Toggle defaults')
1114f46e 462
00b6c4e3 463 self.Center(wxBOTH)
1114f46e 464
00b6c4e3
RD
465#---Property methods------------------------------------------------------------
466 def getCtrlForProp(self, findprop):
467 for ctrl, chb, prop, wid in self.allCtrls:
468 if findprop == prop:
469 return ctrl, chb
470 raise Exception('PropNotFound', findprop)
1114f46e 471
00b6c4e3
RD
472 def editProp(self, on, prop, val=''):
473 oldstyle = self.rememberStyles()
474 if on:
475 if not self.names.count(prop):
476 self.names.append(prop)
477 self.values[prop] = val
478 else:
479 try: self.names.remove(prop)
480 except ValueError: pass
481 try: del self.values[prop]
482 except KeyError: pass
1114f46e 483
00b6c4e3
RD
484 try:
485 self.updateStyle()
1e4a197e 486 return True
00b6c4e3
RD
487 except KeyError, errkey:
488 wxLogError('Name not found in Common definition, '\
489 'please enter valid reference. (%s)'%errkey)
490 self.restoreStyles(oldstyle)
1e4a197e 491 return False
00b6c4e3
RD
492
493#---Control population methods--------------------------------------------------
494 def setStyles(self):
1e4a197e 495 if self._blockUpdate: return
00b6c4e3 496 self.styles, self.styleDict, self.styleNumIdxMap = \
1114f46e 497 setSTCStyles(self.stc, self.styles, self.styleIdNames,
00b6c4e3 498 self.commonDefs, self.lang, self.lexer, self.keywords)
1114f46e 499
00b6c4e3
RD
500 def updateStyle(self):
501 # called after a control edited self.names, self.values
502 # Special case for saving common defs settings
503 if self.styleNum == 'common':
504 strVal = self.style[2] = self.values.values()[0]
505 if self.style[1] == 'size': self.style[2] = int(strVal)
1114f46e 506
00b6c4e3
RD
507 self.commonDefs[self.style[0]] = self.style[2]
508 self.styleDefST.SetLabel(strVal)
509 else:
510 self.style = writePropVal(self.names, self.values)
511 styleDecl = writeProp(self.styleNum, self.style, self.lang)
512 self.styles[self.styleNumIdxMap[self.styleNum]] = styleDecl
513 self.styleDefST.SetLabel(self.style)
514 self.setStyles()
1114f46e 515
00b6c4e3
RD
516 def findInStyles(self, txt, styles):
517 for style in styles:
518 if string.find(style, txt) != -1:
1e4a197e
RD
519 return True
520 return False
00b6c4e3
RD
521
522 def rememberStyles(self):
523 return self.names[:], copy.copy(self.values)
524
525 def restoreStyles(self, style):
526 self.names, self.values = style
527 self.updateStyle()
528
1e4a197e
RD
529 def clearCtrls(self, isDefault=False, disableDefs=False):
530 self._blockUpdate = True
531 try:
532 for ctrl, chb, prop, wid in self.allCtrls:
533 if prop in ('fore', 'back'):
534 cbtn, txt, btn = ctrl
535 cbtn.SetBackgroundColour(\
536 wxSystemSettings_GetSystemColour(wxSYS_COLOUR_BTNFACE))
537 cbtn.SetForegroundColour(wxColour(255, 255, 255))
538 cbtn.Enable(isDefault)
539 txt.SetValue('')
540 txt.Enable(isDefault)
541 btn.Enable(isDefault)
542 elif prop == 'size':
543 cmb, btn = ctrl
544 cmb.SetValue('')
545 cmb.Enable(isDefault)
546 btn.Enable(isDefault)
547 elif prop == 'face':
548 cmb, btn, chk = ctrl
549 cmb.SetValue('')
550 cmb.Enable(isDefault)
551 btn.Enable(isDefault)
552 chk.Enable(isDefault)
553 chk.SetValue(False)
554 elif prop in ('bold', 'italic', 'underline', 'eolfilled'):
555 ctrl.SetValue(False)
556 ctrl.Enable(isDefault)
557
558 chb.Enable(not isDefault and not disableDefs)
559 chb.SetValue(True)
560 finally:
561 self._blockUpdate = False
562
563 def populateProp(self, items, default, forceDisable=False):
564 self._blockUpdate = True
565 try:
566 for name, val in items:
567 if name:
568 ctrl, chb = self.getCtrlForProp(name)
569
570 if name in ('fore', 'back'):
571 cbtn, txt, btn = ctrl
572 repval = val%self.commonDefs
573 cbtn.SetBackgroundColour(strToCol(repval))
574 cbtn.SetForegroundColour(wxColour(0, 0, 0))
575 cbtn.Enable(not forceDisable)
576 txt.SetValue(val)
577 txt.Enable(not forceDisable)
578 btn.Enable(not forceDisable)
579 chb.SetValue(default)
580 elif name == 'size':
581 cmb, btn = ctrl
582 cmb.SetValue(val)
583 cmb.Enable(not forceDisable)
584 btn.Enable(not forceDisable)
585 chb.SetValue(default)
586 elif name == 'face':
587 cmb, btn, chk = ctrl
588 cmb.SetValue(val)
589 cmb.Enable(not forceDisable)
590 btn.Enable(not forceDisable)
591 chk.Enable(not forceDisable)
592 chb.SetValue(default)
593 elif name in ('bold', 'italic', 'underline', 'eolfilled'):
594 ctrl.Enable(not forceDisable)
595 ctrl.SetValue(True)
596 chb.SetValue(default)
597 finally:
598 self._blockUpdate = False
1114f46e 599
00b6c4e3
RD
600 def valIsCommonDef(self, val):
601 return len(val) >= 5 and val[:2] == '%('
1114f46e 602
00b6c4e3
RD
603 def populateCtrls(self):
604 self.clearCtrls(self.styleNum == wxSTC_STYLE_DEFAULT,
605 disableDefs=self.styleNum < 0)
606
607 # handle colour controls for settings
608 if self.styleNum < 0:
1e4a197e 609 self.fgColDefCb.Enable(True)
00b6c4e3 610 if self.styleNum == -1:
1e4a197e 611 self.bgColDefCb.Enable(True)
1114f46e 612
00b6c4e3 613 # populate with default style
1e4a197e 614 self.populateProp(self.defValues.items(), True,
00b6c4e3
RD
615 self.styleNum != wxSTC_STYLE_DEFAULT)
616 # override with current settings
1e4a197e 617 self.populateProp(self.values.items(), False)
1114f46e 618
00b6c4e3
RD
619 def getCommonDefPropType(self, commonDefName):
620 val = self.commonDefs[commonDefName]
621 if type(val) == type(0): return 'size'
622 if len(val) == 7 and val[0] == '#': return 'fore'
623 return 'face'
624
1e4a197e
RD
625 def bindComboEvts(self, combo, btn, btnEvtMeth, comboEvtMeth, rdclickEvtMeth):
626 EVT_COMBOBOX(combo, combo.GetId(), comboEvtMeth)
627 EVT_BUTTON(btn, btn.GetId(), btnEvtMeth)
00b6c4e3 628 EVT_RIGHT_DCLICK(combo, rdclickEvtMeth)
1e4a197e
RD
629 combo.SetToolTipString('Select from list or click "ok" button on the right to change a manual entry, right double-click \n'\
630 'the drop down button to select Common definition in the Style Editor (if applicable)')
631 btn.SetToolTipString('Accept value')
00b6c4e3
RD
632
633 def populateCombosWithCommonDefs(self, fixedWidthOnly=None):
1e4a197e
RD
634 self._blockUpdate = True
635 try:
636 commonDefs = {'fore': [], 'face': [], 'size': []}
637
638 if self.elementLb.GetSelection() < self.commonDefsStartIdx:
639 for common in self.commonDefs.keys():
640 prop = self.getCommonDefPropType(common)
641 commonDefs[prop].append('%%(%s)%s'%(common,
642 prop=='size' and 'd' or 's'))
643
644 # Colours
645 currFg, currBg = self.fgColCb.GetValue(), self.bgColCb.GetValue()
646 self.fgColCb.Clear(); self.bgColCb.Clear()
647 for colCommonDef in commonDefs['fore']:
648 self.fgColCb.Append(colCommonDef)
649 self.bgColCb.Append(colCommonDef)
650 self.fgColCb.SetValue(currFg); self.bgColCb.SetValue(currBg)
651
652 # Font
653 if fixedWidthOnly is None:
654 fixedWidthOnly = self.fixedWidthChk.GetValue()
655 fontEnum = wxFontEnumerator()
656 fontEnum.EnumerateFacenames(fixedWidthOnly=fixedWidthOnly)
657 fontNameList = fontEnum.GetFacenames()
658
659 currFace = self.faceCb.GetValue()
660 self.faceCb.Clear()
661 for colCommonDef in ['']+fontNameList+commonDefs['face']:
662 self.faceCb.Append(colCommonDef)
663 self.faceCb.SetValue(currFace)
664
665 # Size (XXX add std font sizes)
666 currSize = self.sizeCb.GetValue()
667 self.sizeCb.Clear()
668 for colCommonDef in commonDefs['size']:
669 self.sizeCb.Append(colCommonDef)
670 self.sizeCb.SetValue(currSize)
671 finally:
672 self._blockUpdate = False
00b6c4e3
RD
673
674 def populateStyleSelector(self):
675 numStyles = self.styleIdNames.items()
676 numStyles.sort()
677 self.styleNumLookup = {}
678 stdStart = -1
679 stdOffset = 0
680 extrOffset = 0
681 # add styles
682 for num, name in numStyles:
683 if num == wxSTC_STYLE_DEFAULT:
1e4a197e
RD
684 self.elementLb.InsertItems([name, '----Language----'], 0)
685 self.elementLb.Append('----Standard----')
1f443284 686 stdStart = stdPos = self.elementLb.GetCount()
00b6c4e3
RD
687 else:
688 # std styles
689 if num >= 33 and num < 40:
690 self.elementLb.InsertItems([name], stdStart + stdOffset)
691 stdOffset = stdOffset + 1
692 # extra styles
1114f46e 693 elif num >= 40:
00b6c4e3
RD
694 self.elementLb.InsertItems([name], stdStart + extrOffset -1)
695 extrOffset = extrOffset + 1
696 # normal lang styles
697 else:
698 self.elementLb.Append(name)
699 self.styleNumLookup[name] = num
700
701 # add settings
1e4a197e 702 self.elementLb.Append('----Settings----')
00b6c4e3
RD
703 settings = settingsIdNames.items()
704 settings.sort();settings.reverse()
705 for num, name in settings:
706 self.elementLb.Append(name)
707 self.styleNumLookup[name] = num
708
709 # add definitions
1e4a197e 710 self.elementLb.Append('----Common----')
1f443284 711 self.commonDefsStartIdx = self.elementLb.GetCount()
00b6c4e3
RD
712 for common in self.commonDefs.keys():
713 tpe = type(self.commonDefs[common])
714 self.elementLb.Append('%('+common+')'+(tpe is type('') and 's' or 'd'))
715 self.styleNumLookup[common] = num
1114f46e 716
00b6c4e3
RD
717#---Colour methods--------------------------------------------------------------
718 def getColourDlg(self, colour, title=''):
719 data = wxColourData()
720 data.SetColour(colour)
1e4a197e 721 data.SetChooseFull(True)
00b6c4e3
RD
722 dlg = wxColourDialog(self, data)
723 try:
724 dlg.SetTitle(title)
725 if dlg.ShowModal() == wxID_OK:
726 data = dlg.GetColourData()
727 return data.GetColour()
728 finally:
729 dlg.Destroy()
730 return None
731
732 colDlgTitles = {'fore': 'Foreground', 'back': 'Background'}
733 def editColProp(self, colBtn, colCb, prop):
1114f46e 734 col = self.getColourDlg(colBtn.GetBackgroundColour(),
00b6c4e3 735 self.colDlgTitles[prop]+ ' colour')
1114f46e 736 if col:
00b6c4e3
RD
737 colBtn.SetForegroundColour(wxColour(0, 0, 0))
738 colBtn.SetBackgroundColour(col)
739 colStr = colToStr(col)
740 colCb.SetValue(colStr)
1e4a197e 741 self.editProp(True, prop, colStr)
00b6c4e3
RD
742
743 def OnFgcolbtnButton(self, event):
744 self.editColProp(self.fgColBtn, self.fgColCb, 'fore')
745
746 def OnBgcolbtnButton(self, event):
747 self.editColProp(self.bgColBtn, self.bgColCb, 'back')
748
1e4a197e
RD
749 def editColTCProp(self, colCb, colBtn, prop, val=None):
750 if val is None:
751 colStr = colCb.GetValue()
752 else:
753 colStr = val
1114f46e 754 if colStr:
00b6c4e3
RD
755 col = strToCol(colStr%self.commonDefs)
756 if self.editProp(colStr!='', prop, colStr):
1114f46e 757 if colStr:
00b6c4e3
RD
758 colBtn.SetForegroundColour(wxColour(0, 0, 0))
759 colBtn.SetBackgroundColour(col)
760 else:
761 colBtn.SetForegroundColour(wxColour(255, 255, 255))
762 colBtn.SetBackgroundColour(\
763 wxSystemSettings_GetSystemColour(wxSYS_COLOUR_BTNFACE))
764
765 def OnfgColRet(self, event):
766 try: self.editColTCProp(self.fgColCb, self.fgColBtn, 'fore')
767 except AssertionError: wxLogError('Not a valid colour value')
768
1e4a197e
RD
769 def OnfgColCombobox(self, event):
770 if self._blockUpdate: return
771 try: self.editColTCProp(self.fgColCb, self.fgColBtn, 'fore', event.GetString())
772 except AssertionError: wxLogError('Not a valid colour value')
773
00b6c4e3
RD
774 def OnbgColRet(self, event):
775 try: self.editColTCProp(self.bgColCb, self.bgColBtn, 'back')
776 except AssertionError: wxLogError('Not a valid colour value')
777
1e4a197e
RD
778 def OnbgColCombobox(self, event):
779 if self._blockUpdate: return
780 try: self.editColTCProp(self.bgColCb, self.bgColBtn, 'back', event.GetString())
781 except AssertionError: wxLogError('Not a valid colour value')
782
00b6c4e3
RD
783#---Text attribute events-------------------------------------------------------
784 def OnTaeoffilledcbCheckbox(self, event):
785 self.editProp(event.IsChecked(), 'eolfilled')
786
787 def OnTaitaliccbCheckbox(self, event):
788 self.editProp(event.IsChecked(), 'italic')
789
790 def OnTaboldcbCheckbox(self, event):
791 self.editProp(event.IsChecked(), 'bold')
792
793 def OnTaunderlinedcbCheckbox(self, event):
794 self.editProp(event.IsChecked(), 'underline')
795
796 def OnGotoCommonDef(self, event):
797 val = event.GetEventObject().GetValue()
798 if self.valIsCommonDef(val):
799 idx = self.elementLb.FindString(val)
800 if idx != -1:
1e4a197e 801 self.elementLb.SetSelection(idx, True)
00b6c4e3
RD
802 self.OnElementlbListbox(None)
803
804 def OnfaceRet(self, event):
1e4a197e
RD
805 self.setFace(self.faceCb.GetValue())
806
807 def OnfaceCombobox(self, event):
808 if self._blockUpdate: return
809 self.setFace(event.GetString())
810
811 def setFace(self, val):
00b6c4e3
RD
812 try: val%self.commonDefs
813 except KeyError: wxLogError('Invalid common definition')
814 else: self.editProp(val!='', 'face', val)
815
816 def OnsizeRet(self, event):
1e4a197e
RD
817 self.setSize(self.sizeCb.GetValue())
818
819 def OnsizeCombobox(self, event):
820 if self._blockUpdate: return
821 self.setSize(event.GetString())
822
823 def setSize(self, val):
00b6c4e3
RD
824 try: int(val%self.commonDefs)
825 except ValueError: wxLogError('Not a valid integer size value')
826 except KeyError: wxLogError('Invalid common definition')
827 else: self.editProp(val!='', 'size', val)
828
829#---Main GUI events-------------------------------------------------------------
830 def OnElementlbListbox(self, event):
831 isCommon = self.elementLb.GetSelection() >= self.commonDefsStartIdx
832 self.removeCommonItemBtn.Enable(isCommon)
833
834 styleIdent = self.elementLb.GetStringSelection()
835 # common definition selected
836 if isCommon:
837 common = styleIdent[2:-2]
838 prop = self.getCommonDefPropType(common)
1e4a197e 839 self.clearCtrls(disableDefs=True)
00b6c4e3 840 if prop == 'fore':
1e4a197e
RD
841 self.fgColBtn.Enable(True)
842 self.fgColCb.Enable(True)
843 self.fgColOkBtn.Enable(True)
00b6c4e3 844 elif prop == 'face':
1e4a197e
RD
845 self.faceCb.Enable(True)
846 self.fixedWidthChk.Enable(True)
847 self.faceOkBtn.Enable(True)
00b6c4e3 848 elif prop == 'size':
1e4a197e
RD
849 self.sizeCb.Enable(True)
850 self.sizeOkBtn.Enable(True)
00b6c4e3
RD
851
852 commonDefVal = str(self.commonDefs[common])
853 self.styleDefST.SetLabel(commonDefVal)
1e4a197e 854 self.populateProp( [(prop, commonDefVal)], True)
00b6c4e3
RD
855
856 self.styleNum = 'common'
857 self.style = [common, prop, commonDefVal]
858 self.names, self.values = [prop], {prop: commonDefVal}
1114f46e 859
00b6c4e3
RD
860 # normal style element selected
861 elif len(styleIdent) >=2 and styleIdent[:2] != '--':
862 self.styleNum = self.styleNumLookup[styleIdent]
863 self.style = self.styleDict[self.styleNum]
864 self.names, self.values = parseProp(self.style)
00b6c4e3
RD
865 if self.styleNum == wxSTC_STYLE_DEFAULT:
866 self.defNames, self.defValues = \
867 self.names, self.values
868
869 self.checkBraces(self.styleNum)
1114f46e 870
00b6c4e3 871 self.styleDefST.SetLabel(self.style)
1114f46e 872
00b6c4e3
RD
873 self.populateCtrls()
874 # separator selected
875 else:
1e4a197e 876 self.clearCtrls(disableDefs=True)
00b6c4e3
RD
877 if styleIdent:
878 self.styleDefST.SetLabel(styleCategoryDescriptions[styleIdent])
879
880 self.populateCombosWithCommonDefs()
1114f46e 881
00b6c4e3 882 def OnDefaultCheckBox(self, event):
1e4a197e
RD
883 if self.chbIdMap.has_key(event.GetId()):
884 ctrl, chb, prop, wid = self.chbIdMap[event.GetId()]
885 restore = not event.IsChecked()
886 if prop in ('fore', 'back'):
887 cbtn, cmb, btn = ctrl
888 cbtn.Enable(restore)
889 cmb.Enable(restore)
890 btn.Enable(restore)
891 if restore:
892 colStr = cmb.GetValue()
893 #if prop == 'fore': colStr = self.fgColCb.GetValue()
894 #else: colStr = self.bgColCb.GetValue()
895 if colStr: self.editProp(True, prop, colStr)
896 else:
897 self.editProp(False, prop)
898 elif prop == 'size':
899 cmb, btn = ctrl
900 val = cmb.GetValue()
901 if val: self.editProp(restore, prop, val)
902 cmb.Enable(restore)
903 btn.Enable(restore)
904 elif prop == 'face':
905 cmb, btn, chk = ctrl
906 val = cmb.GetStringSelection()
907 if val: self.editProp(restore, prop, val)
908 cmb.Enable(restore)
909 btn.Enable(restore)
910 chk.Enable(restore)
911 elif prop in ('bold', 'italic', 'underline', 'eolfilled'):
912 ctrl.Enable(restore)
913 if ctrl.GetValue(): self.editProp(restore, prop)
00b6c4e3
RD
914
915 def OnOkbtnButton(self, event):
916 # write styles and common defs to the config
1e4a197e
RD
917 wxBeginBusyCursor()
918 try:
919 writeStylesToConfig(self.config, 'style.%s'%self.lang, self.styles)
920 self.config.SetPath('')
921 self.config.Write(commonDefsFile, `self.commonDefs`)
922 self.config.Flush()
923
924 for stc in self.STCsToUpdate:
925 setSTCStyles(stc, self.styles, self.styleIdNames, self.commonDefs,
926 self.lang, self.lexer, self.keywords)
927 finally:
928 wxEndBusyCursor()
00b6c4e3
RD
929 self.EndModal(wxID_OK)
930
931 def OnCancelbtnButton(self, event):
932 self.EndModal(wxID_CANCEL)
933
934 def OnCommondefsbtnButton(self, event):
1114f46e 935 dlg = wxTextEntryDialog(self, 'Edit common definitions dictionary',
00b6c4e3
RD
936 'Common definitions', pprint.pformat(self.commonDefs),
937 style=wxTE_MULTILINE | wxOK | wxCANCEL | wxCENTRE)
938 try:
939 if dlg.ShowModal() == wxID_OK:
940 answer = eval(dlg.GetValue())
941 assert type(answer) is type({}), 'Not a valid dictionary'
942 oldDefs = self.commonDefs
943 self.commonDefs = answer
944 try:
945 self.setStyles()
946 except KeyError, badkey:
947 wxLogError(str(badkey)+' not defined but required, \n'\
948 'reverting to previous common definition')
949 self.commonDefs = oldDefs
950 self.setStyles()
951 self.populateCombosWithCommonDefs()
1114f46e 952
00b6c4e3
RD
953 finally:
954 dlg.Destroy()
955
956 def OnSpeedsettingchChoice(self, event):
957 group = event.GetString()
958 if group:
959 userStyles = 'style.%s'%self.lang
960 if self.currSpeedSetting == userStyles:
961 self.predefStyleGroups[userStyles] = self.styles
962 self.styles = self.predefStyleGroups[group]
963 self.setStyles()
964 self.defNames, self.defValues = parseProp(\
965 self.styleDict.get(wxSTC_STYLE_DEFAULT, ''))
966 self.OnElementlbListbox(None)
967 self.currSpeedSetting = group
968
969 def OnFixedwidthchkCheckbox(self, event):
970 self.populateCombosWithCommonDefs(event.Checked())
971
972 def OnAddsharebtnButton(self, event):
973 dlg = CommonDefDlg(self)
974 try:
975 if dlg.ShowModal() == wxID_OK:
976 prop, name = dlg.result
977 if not self.commonDefs.has_key(name):
978 self.commonDefs[name] = commonPropDefs[prop]
979 self.elementLb.Append('%('+name+')'+\
980 (type(commonPropDefs[prop]) is type('') and 's' or 'd'))
1f443284 981 self.elementLb.SetSelection(self.elementLb.GetCount()-1, True)
00b6c4e3
RD
982 self.populateCombosWithCommonDefs()
983 self.OnElementlbListbox(None)
984 finally:
985 dlg.Destroy()
986
987 def OnRemovesharebtnButton(self, event):
988 ownGroup = 'style.%s'%self.lang
1114f46e
RD
989 comDef = self.elementLb.GetStringSelection()
990
00b6c4e3
RD
991 # Search ALL styles before removing
992 srchDct = {ownGroup: self.styles}
993 srchDct.update(self.predefStyleGroups)
994 srchDct.update(self.otherLangStyleGroups)
995
996 matchList = []
997 for grpName, styles in srchDct.items():
998 if self.findInStyles(comDef, styles):
999 matchList.append(grpName)
1000
1001 if matchList:
1002 wxLogError('Aborted: '+comDef+' is still used in the styles of the \n'\
1003 'following groups in the config file (stc-styles.rc.cfg):\n'+ \
1004 string.join(matchList, '\n'))
1005 else:
1006 del self.commonDefs[comDef[2:-2]]
1007 self.setStyles()
1008 self.populateCombosWithCommonDefs()
1009 selIdx = self.elementLb.GetSelection()
1010 self.elementLb.Delete(selIdx)
1f443284 1011 if selIdx == self.elementLb.GetCount():
00b6c4e3 1012 selIdx = selIdx - 1
1e4a197e 1013 self.elementLb.SetSelection(selIdx, True)
00b6c4e3
RD
1014 self.OnElementlbListbox(None)
1015
1016#---STC events------------------------------------------------------------------
1017 def OnUpdateUI(self, event):
1e4a197e
RD
1018 styleBefore = self.stc.GetStyleAt(self.stc.GetCurrentPos())
1019 if self.styleIdNames.has_key(styleBefore):
1020 self.elementLb.SetStringSelection(self.styleIdNames[styleBefore],
1021 True)
1022 else:
1023 self.elementLb.SetSelection(0, False)
1024 self.styleDefST.SetLabel('Style %d not defined, sorry.'%styleBefore)
1025 self.OnElementlbListbox(None)
00b6c4e3
RD
1026 event.Skip()
1027
1028 def checkBraces(self, style):
1029 if style == wxSTC_STYLE_BRACELIGHT and self.braceInfo.has_key('good'):
1030 line, col = self.braceInfo['good']
1031 pos = self.stc.PositionFromLine(line-1) + col
1032 braceOpposite = self.stc.BraceMatch(pos)
1033 if braceOpposite != -1:
1034 self.stc.BraceHighlight(pos, braceOpposite)
1035 elif style == wxSTC_STYLE_BRACEBAD and self.braceInfo.has_key('bad'):
1036 line, col = self.braceInfo['bad']
1037 pos = self.stc.PositionFromLine(line-1) + col
1038 self.stc.BraceBadLight(pos)
1039 else:
1040 self.stc.BraceBadLight(-1)
1041 return
1042
1043 def OnStcstyleeditdlgSize(self, event):
1044 self.Layout()
1045 # Without this refresh, resizing leaves artifacts
1046 self.Refresh(1)
1047 event.Skip()
1048
1049 def OnMarginClick(self, event):
1e4a197e 1050 self.elementLb.SetStringSelection('Line numbers', True)
00b6c4e3
RD
1051 self.OnElementlbListbox(None)
1052
1114f46e 1053
00b6c4e3
RD
1054#---Common definition dialog----------------------------------------------------
1055
1056[wxID_COMMONDEFDLG, wxID_COMMONDEFDLGCANCELBTN, wxID_COMMONDEFDLGCOMDEFNAMETC, wxID_COMMONDEFDLGOKBTN, wxID_COMMONDEFDLGPROPTYPERBX, wxID_COMMONDEFDLGSTATICBOX1] = map(lambda _init_ctrls: wxNewId(), range(6))
1057
1058class CommonDefDlg(wxDialog):
1059 def _init_ctrls(self, prnt):
1060 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')
1e4a197e 1061 self.SetClientSize(wxSize(184, 200))
00b6c4e3 1062
1e4a197e 1063 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)
00b6c4e3
RD
1064 self.propTypeRBx.SetSelection(self._propTypeIdx)
1065
1e4a197e 1066 self.staticBox1 = wxStaticBox(id = wxID_COMMONDEFDLGSTATICBOX1, label = 'Name', name = 'staticBox1', parent = self, pos = wxPoint(8, 108), size = wxSize(168, 46), style = 0)
00b6c4e3 1067
1e4a197e 1068 self.comDefNameTC = wxTextCtrl(id = wxID_COMMONDEFDLGCOMDEFNAMETC, name = 'comDefNameTC', parent = self, pos = wxPoint(16, 124), size = wxSize(152, 21), style = 0, value = '')
00b6c4e3
RD
1069 self.comDefNameTC.SetLabel(self._comDefName)
1070
1e4a197e 1071 self.okBtn = wxButton(id = wxID_COMMONDEFDLGOKBTN, label = 'OK', name = 'okBtn', parent = self, pos = wxPoint(8, 164), size = wxSize(80, 23), style = 0)
00b6c4e3
RD
1072 EVT_BUTTON(self.okBtn, wxID_COMMONDEFDLGOKBTN, self.OnOkbtnButton)
1073
1e4a197e 1074 self.cancelBtn = wxButton(id = wxID_COMMONDEFDLGCANCELBTN, label = 'Cancel', name = 'cancelBtn', parent = self, pos = wxPoint(96, 164), size = wxSize(80, 23), style = 0)
00b6c4e3
RD
1075 EVT_BUTTON(self.cancelBtn, wxID_COMMONDEFDLGCANCELBTN, self.OnCancelbtnButton)
1076
1077 def __init__(self, parent, name='', propIdx=0):
1078 self._comDefName = ''
1079 self._comDefName = name
1080 self._propTypeIdx = 0
1081 self._propTypeIdx = propIdx
1082 self._init_ctrls(parent)
1114f46e
RD
1083
1084 self.propMap = {0: 'fore', 1: 'face', 2: 'size'}
00b6c4e3
RD
1085 self.result = ( '', '' )
1086
1087 self.Center(wxBOTH)
1088
1089 def OnOkbtnButton(self, event):
1090 self.result = ( self.propMap[self.propTypeRBx.GetSelection()],
1091 self.comDefNameTC.GetValue() )
1092 self.EndModal(wxID_OK)
1093
1094 def OnCancelbtnButton(self, event):
1095 self.result = ( '', '' )
1096 self.EndModal(wxID_CANCEL)
1114f46e 1097
00b6c4e3 1098#---Functions useful outside of the editor----------------------------------
1114f46e 1099
00b6c4e3
RD
1100def setSelectionColour(stc, style):
1101 names, values = parseProp(style)
1102 if 'fore' in names:
1e4a197e 1103 stc.SetSelForeground(True, strToCol(values['fore']))
00b6c4e3 1104 if 'back' in names:
1e4a197e 1105 stc.SetSelBackground(True, strToCol(values['back']))
00b6c4e3
RD
1106
1107def setCursorColour(stc, style):
1108 names, values = parseProp(style)
1109 if 'fore' in names:
1110 stc.SetCaretForeground(strToCol(values['fore']))
1111
1112def setEdgeColour(stc, style):
1113 names, values = parseProp(style)
1114 if 'fore' in names:
1115 stc.SetEdgeColour(strToCol(values['fore']))
1116
1117def strToCol(strCol):
1118 assert len(strCol) == 7 and strCol[0] == '#', 'Not a valid colour string'
1114f46e
RD
1119 return wxColour(string.atoi('0x'+strCol[1:3], 16),
1120 string.atoi('0x'+strCol[3:5], 16),
00b6c4e3
RD
1121 string.atoi('0x'+strCol[5:7], 16))
1122def colToStr(col):
1114f46e 1123 return '#%s%s%s' % (string.zfill(string.upper(hex(col.Red())[2:]), 2),
00b6c4e3
RD
1124 string.zfill(string.upper(hex(col.Green())[2:]), 2),
1125 string.zfill(string.upper(hex(col.Blue())[2:]), 2))
1126
1127def writeProp(num, style, lang):
1128 if num >= 0:
1129 return 'style.%s.%s='%(lang, string.zfill(`num`, 3)) + style
1130 else:
1131 return 'setting.%s.%d='%(lang, num) + style
1132
1133def writePropVal(names, values):
1134 res = []
1135 for name in names:
1136 if name:
1137 res.append(values[name] and name+':'+values[name] or name)
1138 return string.join(res, ',')
1139
1140def parseProp(prop):
1141 items = string.split(prop, ',')
1142 names = []
1143 values = {}
1144 for item in items:
1145 nameVal = string.split(item, ':')
1146 names.append(string.strip(nameVal[0]))
1147 if len(nameVal) == 1:
1148 values[nameVal[0]] = ''
1149 else:
1150 values[nameVal[0]] = string.strip(nameVal[1])
1151 return names, values
1114f46e 1152
00b6c4e3
RD
1153def parsePropLine(prop):
1154 name, value = string.split(prop, '=')
1155 return int(string.split(name, '.')[-1]), value
1156
1157def setSTCStyles(stc, styles, styleIdNames, commonDefs, lang, lexer, keywords):
1e4a197e 1158 #wxLogMessage('Set style')
00b6c4e3
RD
1159 styleDict = {}
1160 styleNumIdxMap = {}
1161
1162 # build style dict based on given styles
1163 for numStyle in styles:
1164 num, style = parsePropLine(numStyle)
1165 styleDict[num] = style
1166
1167 # Add blank style entries for undefined styles
1168 newStyles = []
1169 styleItems = styleIdNames.items() + settingsIdNames.items()
1170 styleItems.sort()
1171 idx = 0
1172 for num, name in styleItems:
1173 styleNumIdxMap[num] = idx
1174 if not styleDict.has_key(num):
1175 styleDict[num] = ''
1176 newStyles.append(writeProp(num, styleDict[num], lang))
1177 idx = idx + 1
1178
1e4a197e
RD
1179 # Set background colour to reduce flashing effect on refresh or page switch
1180 bkCol = None
1181 if styleDict.has_key(0): prop = styleDict[0]
1182 else: prop = styleDict[wxSTC_STYLE_DEFAULT]
1183 names, vals = parseProp(prop)
1184 if 'back' in names:
1185 bkCol = strToCol(vals['back'])
1186 if bkCol is None:
1187 bkCol = wxWHITE
1188 stc.SetBackgroundColour(bkCol)
1189
00b6c4e3 1190 # Set the styles on the wxSTC
1e4a197e 1191# stc.Show(False)
00b6c4e3
RD
1192 stc.StyleResetDefault()
1193 stc.ClearDocumentStyle()
1194 stc.SetLexer(lexer)
1195 stc.SetKeyWords(0, keywords)
1114f46e 1196 stc.StyleSetSpec(wxSTC_STYLE_DEFAULT,
00b6c4e3
RD
1197 styleDict[wxSTC_STYLE_DEFAULT] % commonDefs)
1198 stc.StyleClearAll()
1199
1200 for num, style in styleDict.items():
1201 if num >= 0:
1202 stc.StyleSetSpec(num, style % commonDefs)
1203 elif num == -1:
1204 setSelectionColour(stc, style % commonDefs)
1205 elif num == -2:
1206 setCursorColour(stc, style % commonDefs)
1207 elif num == -3:
1208 setEdgeColour(stc, style % commonDefs)
1209
1210 stc.Colourise(0, stc.GetTextLength())
1e4a197e 1211# stc.Show(True)
1114f46e 1212
00b6c4e3
RD
1213 return newStyles, styleDict, styleNumIdxMap
1214
1215#---Config reading and writing -------------------------------------------------
1216commonDefsFile = 'common.defs.%s'%(wxPlatform == '__WXMSW__' and 'msw' or 'gtk')
1217
1e4a197e
RD
1218def readPyValFromConfig(conf, name):
1219 return eval(string.replace(conf.Read(name), '\r\n', '\n')+'\n')
1220
00b6c4e3
RD
1221def initFromConfig(configFile, lang):
1222 cfg = wxFileConfig(localFilename=configFile, style=wxCONFIG_USE_LOCAL_FILE)
1e4a197e 1223 cfg.SetExpandEnvVars(False)
00b6c4e3
RD
1224
1225 # read in all group names for this language
1226 groupPrefix = 'style.%s'%lang
1227 gpLen = len(groupPrefix)
1228 predefStyleGroupNames, otherLangStyleGroupNames = [], []
1229 cont, val, idx = cfg.GetFirstGroup()
1230 while cont:
1231 if val != groupPrefix and len(val) >= 5 and val[:5] == 'style':
1232 if len(val) > gpLen and val[:gpLen] == groupPrefix:
1233 predefStyleGroupNames.append(val)
1234 else:
1235 otherLangStyleGroupNames.append(val)
1114f46e 1236
00b6c4e3 1237 cont, val, idx = cfg.GetNextGroup(idx)
1114f46e 1238
00b6c4e3 1239 # read in common elements
1e4a197e 1240 commonDefs = readPyValFromConfig(cfg, commonDefsFile)
00b6c4e3
RD
1241 assert type(commonDefs) is type({}), \
1242 'Common definitions (%s) not a valid dict'%commonDefsFile
1243
1e4a197e 1244 commonStyleIdNames = readPyValFromConfig(cfg, 'common.styleidnames')
00b6c4e3
RD
1245 assert type(commonStyleIdNames) is type({}), \
1246 'Common definitions (%s) not a valid dict'%'common.styleidnames'
1247
1248 # Lang spesific settings
1114f46e 1249 cfg.SetPath(lang)
1e4a197e 1250 styleIdNames = readPyValFromConfig(cfg, 'styleidnames')
00b6c4e3
RD
1251 assert type(commonStyleIdNames) is type({}), \
1252 'Not a valid dict [%s] styleidnames)'%lang
1253 styleIdNames.update(commonStyleIdNames)
1e4a197e 1254 braceInfo = readPyValFromConfig(cfg, 'braces')
00b6c4e3
RD
1255 assert type(commonStyleIdNames) is type({}), \
1256 'Not a valid dict [%s] braces)'%lang
1114f46e 1257
00b6c4e3 1258 displaySrc = cfg.Read('displaysrc')
1e4a197e 1259 lexer = readPyValFromConfig(cfg, 'lexer')
00b6c4e3
RD
1260 keywords = cfg.Read('keywords')
1261
1262 cfg.SetPath('')
1263
1264 # read in current styles
1265 styles = readStylesFromConfig(cfg, groupPrefix)
1266
1114f46e 1267 # read in predefined styles
00b6c4e3
RD
1268 predefStyleGroups = {}
1269 for group in predefStyleGroupNames:
1270 predefStyleGroups[group] = readStylesFromConfig(cfg, group)
1271
1272 # read in all other style sections
1273 otherLangStyleGroups = {}
1274 for group in otherLangStyleGroupNames:
1275 otherLangStyleGroups[group] = readStylesFromConfig(cfg, group)
1114f46e
RD
1276
1277 return (cfg, commonDefs, styleIdNames, styles, predefStyleGroupNames,
00b6c4e3
RD
1278 predefStyleGroups, otherLangStyleGroupNames, otherLangStyleGroups,
1279 displaySrc, lexer, keywords, braceInfo)
1280
1281def readStylesFromConfig(config, group):
1282 config.SetPath('')
1114f46e 1283 config.SetPath(group)
00b6c4e3
RD
1284 styles = []
1285 cont, val, idx = config.GetFirstEntry()
1286 while cont:
1287 styles.append(val+'='+config.Read(val))
1288 cont, val, idx = config.GetNextEntry(idx)
1289 config.SetPath('')
1290
1291 return styles
1292
1293def writeStylesToConfig(config, group, styles):
1294 config.SetPath('')
1295 config.DeleteGroup(group)
1296 config.SetPath(group)
1297
1298 for style in styles:
1299 name, value = string.split(style, '=')
1300 config.Write(name, string.strip(value))
1301
1302 config.SetPath('')
1303
1304#-------------------------------------------------------------------------------
1305def initSTC(stc, config, lang):
1306 """ Main module entry point. Initialise a wxSTC from given config file."""
1114f46e 1307 (cfg, commonDefs, styleIdNames, styles, predefStyleGroupNames,
00b6c4e3
RD
1308 predefStyleGroups, otherLangStyleGroupNames, otherLangStyleGroups,
1309 displaySrc, lexer, keywords, braceInfo) = initFromConfig(config, lang)
1114f46e 1310
00b6c4e3
RD
1311 setSTCStyles(stc, styles, styleIdNames, commonDefs, lang, lexer, keywords)
1312
1313#-------------------------------------------------------------------------------
1314if __name__ == '__main__':
1e4a197e
RD
1315 from wxPython.help import *
1316
00b6c4e3 1317 app = wxPySimpleApp()
1114f46e 1318
1e4a197e
RD
1319 provider = wxSimpleHelpProvider()
1320 wxHelpProvider_Set(provider)
1321
1f443284
RD
1322 base = os.path.split(__file__)[0]
1323 config = os.path.abspath(os.path.join(base, 'stc-styles.rc.cfg'))
00b6c4e3
RD
1324 if 0:
1325 f = wxFrame(None, -1, 'Test frame (double click for editor)')
1326 stc = wxStyledTextCtrl(f, -1)
1327 def OnDblClick(evt, stc=stc):
1328 dlg = STCStyleEditDlg(None, 'Python', 'python', config, (stc,))
1329 try: dlg.ShowModal()
1330 finally: dlg.Destroy()
1331 stc.SetText(open('STCStyleEditor.py').read())
1332 EVT_LEFT_DCLICK(stc, OnDblClick)
1333 initSTC(stc, config, 'python')
1e4a197e 1334 f.Show(True)
00b6c4e3
RD
1335 app.MainLoop()
1336 else:
1114f46e 1337 dlg = STCStyleEditDlg(None,
00b6c4e3
RD
1338 'Python', 'python',
1339 #'HTML', 'html',
1340 #'XML', 'xml',
1114f46e
RD
1341 #'C++', 'cpp',
1342 #'Text', 'text',
1343 #'Properties', 'prop',
00b6c4e3
RD
1344 config)
1345 try: dlg.ShowModal()
1346 finally: dlg.Destroy()