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