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