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