wxWidgets/wxPython/samples/StyleEditor/STCStyleEditor.py
2003-03-25 06:35:27 +00:00

1344 lines
56 KiB
Python

#-----------------------------------------------------------------------------
# Name: STCStyleEditor.py
# Purpose: Style editor for the wxStyledTextCtrl
#
# Author: Riaan Booysen
#
# Created: 2001/08/20
# RCS-ID: $Id$
# Copyright: (c) 2001 - 2002 Riaan Booysen
# Licence: wxWindows license
#-----------------------------------------------------------------------------
#Boa:Dialog:STCStyleEditDlg
""" Style editor for the wxStyledTextCtrl.
Reads in property style definitions from a config file.
Modified styled can be saved (and optionally applied to a given list of STCs)
It can also maintain a Common definition dictionary of font names, colours and
sizes which can be shared across multiple language style definitions.
This is also used to store platform spesific settings as fonts and sizes
vary with platform.
The following items are defined in the stc-styles.rc.cfg file.
common.defs.msw - Common definition dictionary used on wxMSW
common.defs.gtk - Common definition dictionary used on wxGTK
common.styleidnames - STC styles shared by all languages
Each supported language defines the following groups:
[<language>]
displaysrc - Example source to display in the editor
braces - Dictionary defining the (line, column) for showing 'good' and 'bad'
brace matching (both keys optional)
keywords - Space separated list of keywords
lexer - wxSTC constant for the language lexer
styleidnames - Dictionary of language spesific style numbers and names
[style.<language>] - The users current style values
[style.<language>.default] - Default style values (can be reverted from)
0 or more predefined style groups or 'themes'
[style.<language>.<predefined name>]
Currently the following languages are supported:
python, html, xml, cpp, text, props
Other languages can be added by just defining the above settings for them in
the config file (if wxSTC implements them).
Use the initSTC function to initialise your wxSTC from a config file.
"""
import os, sys, string, pprint, copy
from wxPython.wx import *
from wxPython.help import *
from wxPython.lib.anchors import LayoutAnchors
from wxPython.stc import *
settingsIdNames = {-1: 'Selection', -2: 'Caret', -3: 'Edge'}
commonPropDefs = {'fore': '#888888', 'size': 8,
'face': wxSystemSettings_GetSystemFont(wxSYS_DEFAULT_GUI_FONT).GetFaceName()}
styleCategoryDescriptions = {
'----Language----': 'Styles spesific to the language',
'----Standard----': 'Styles shared by all languages',
'----Settings----': 'Properties set by STC methods',
'----Common----': 'User definable values that can be shared between languages'}
[wxID_STCSTYLEEDITDLG, wxID_STCSTYLEEDITDLGADDCOMMONITEMBTN,
wxID_STCSTYLEEDITDLGBGCOLBTN, wxID_STCSTYLEEDITDLGBGCOLCB,
wxID_STCSTYLEEDITDLGBGCOLDEFCB, wxID_STCSTYLEEDITDLGBGCOLOKBTN,
wxID_STCSTYLEEDITDLGCANCELBTN, wxID_STCSTYLEEDITDLGCONTEXTHELPBUTTON1,
wxID_STCSTYLEEDITDLGELEMENTLB, wxID_STCSTYLEEDITDLGFACECB,
wxID_STCSTYLEEDITDLGFACEDEFCB, wxID_STCSTYLEEDITDLGFACEOKBTN,
wxID_STCSTYLEEDITDLGFGCOLBTN, wxID_STCSTYLEEDITDLGFGCOLCB,
wxID_STCSTYLEEDITDLGFGCOLDEFCB, wxID_STCSTYLEEDITDLGFGCOLOKBTN,
wxID_STCSTYLEEDITDLGFIXEDWIDTHCHK, wxID_STCSTYLEEDITDLGOKBTN,
wxID_STCSTYLEEDITDLGPANEL1, wxID_STCSTYLEEDITDLGPANEL2,
wxID_STCSTYLEEDITDLGPANEL3, wxID_STCSTYLEEDITDLGPANEL4,
wxID_STCSTYLEEDITDLGREMOVECOMMONITEMBTN, wxID_STCSTYLEEDITDLGSIZECB,
wxID_STCSTYLEEDITDLGSIZEOKBTN, 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(47))
class STCStyleEditDlg(wxDialog):
""" Style editor for the wxStyledTextCtrl """
_custom_classes = {'wxWindow' : ['wxStyledTextCtrl']}
def _init_utils(self):
# generated method, don't edit
pass
def _init_ctrls(self, prnt):
# generated method, don't edit
wxDialog.__init__(self, id=wxID_STCSTYLEEDITDLG, name='STCStyleEditDlg',
parent=prnt, pos=wxPoint(583, 291), size=wxSize(459, 482),
style=wxWANTS_CHARS | wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER,
title=self.stc_title)
self._init_utils()
self.SetClientSize(wxSize(451, 455))
self.SetAutoLayout(True)
self.SetSizeHints(425, 400, -1, -1)
self.Center(wxBOTH)
EVT_SIZE(self, self.OnStcstyleeditdlgSize)
self.speedsettingCh = wxChoice(choices=[],
id=wxID_STCSTYLEEDITDLGSPEEDSETTINGCH, name='speedsettingCh',
parent=self, pos=wxPoint(96, 28), size=wxSize(346, 21), style=0,
validator=wxDefaultValidator)
self.speedsettingCh.SetConstraints(LayoutAnchors(self.speedsettingCh,
True, True, True, False))
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.')
EVT_CHOICE(self.speedsettingCh, wxID_STCSTYLEEDITDLGSPEEDSETTINGCH,
self.OnSpeedsettingchChoice)
self.elementLb = wxListBox(choices=[], id=wxID_STCSTYLEEDITDLGELEMENTLB,
name='elementLb', parent=self, pos=wxPoint(8, 72),
size=wxSize(160, 112), style=0, validator=wxDefaultValidator)
self.elementLb.SetConstraints(LayoutAnchors(self.elementLb, True, True,
True, False))
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.')
EVT_LISTBOX(self.elementLb, wxID_STCSTYLEEDITDLGELEMENTLB,
self.OnElementlbListbox)
self.addCommonItemBtn = wxButton(id=wxID_STCSTYLEEDITDLGADDCOMMONITEMBTN,
label='Add', name='addCommonItemBtn', parent=self, pos=wxPoint(8,
184), size=wxSize(80, 17), style=0)
self.addCommonItemBtn.SetToolTipString('Add new Common definition')
EVT_BUTTON(self.addCommonItemBtn, wxID_STCSTYLEEDITDLGADDCOMMONITEMBTN,
self.OnAddsharebtnButton)
self.removeCommonItemBtn = wxButton(id=wxID_STCSTYLEEDITDLGREMOVECOMMONITEMBTN,
label='Remove', name='removeCommonItemBtn', parent=self,
pos=wxPoint(88, 184), size=wxSize(80, 17), style=0)
self.removeCommonItemBtn.SetToolTipString('Remove the selected Common definition')
EVT_BUTTON(self.removeCommonItemBtn,
wxID_STCSTYLEEDITDLGREMOVECOMMONITEMBTN,
self.OnRemovesharebtnButton)
self.styleDefST = wxStaticText(id=wxID_STCSTYLEEDITDLGSTYLEDEFST,
label='(nothing selected)', name='styleDefST', parent=self,
pos=wxPoint(96, 8), size=wxSize(366, 16),
style=wxST_NO_AUTORESIZE)
self.styleDefST.SetFont(wxFont(self.style_font_size, wxSWISS, wxNORMAL,
wxBOLD, False, ''))
self.styleDefST.SetConstraints(LayoutAnchors(self.styleDefST, True,
True, True, False))
self.staticLine1 = wxStaticLine(id=wxID_STCSTYLEEDITDLGSTATICLINE1,
name='staticLine1', parent=self, pos=wxPoint(48, 62),
size=wxSize(120, 2), style=wxLI_HORIZONTAL)
self.staticLine1.SetConstraints(LayoutAnchors(self.staticLine1, True,
True, True, False))
self.staticText6 = wxStaticText(id=wxID_STCSTYLEEDITDLGSTATICTEXT6,
label='Style', name='staticText6', parent=self, pos=wxPoint(8,
56), size=wxSize(40, 13), style=0)
self.staticText8 = wxStaticText(id=wxID_STCSTYLEEDITDLGSTATICTEXT8,
label='Style def:', name='staticText8', parent=self,
pos=wxPoint(8, 8), size=wxSize(88, 13), style=0)
self.staticText9 = wxStaticText(id=wxID_STCSTYLEEDITDLGSTATICTEXT9,
label='SpeedSetting:', name='staticText9', parent=self,
pos=wxPoint(8, 32), size=wxSize(88, 13), style=0)
self.panel3 = wxPanel(id=wxID_STCSTYLEEDITDLGPANEL3, name='panel3',
parent=self, pos=wxPoint(176, 56), size=wxSize(146, 104),
style=wxTAB_TRAVERSAL)
self.panel3.SetConstraints(LayoutAnchors(self.panel3, False, True, True,
False))
self.panel4 = wxPanel(id=wxID_STCSTYLEEDITDLGPANEL4, name='panel4',
parent=self, pos=wxPoint(330, 56), size=wxSize(114, 104),
style=wxTAB_TRAVERSAL)
self.panel4.SetConstraints(LayoutAnchors(self.panel4, False, True, True,
False))
self.panel1 = wxPanel(id=wxID_STCSTYLEEDITDLGPANEL1, name='panel1',
parent=self, pos=wxPoint(176, 161), size=wxSize(143, 40),
style=wxTAB_TRAVERSAL)
self.panel1.SetConstraints(LayoutAnchors(self.panel1, False, True, True,
False))
self.panel2 = wxPanel(id=wxID_STCSTYLEEDITDLGPANEL2, name='panel2',
parent=self, pos=wxPoint(330, 162), size=wxSize(112, 40),
style=wxTAB_TRAVERSAL)
self.panel2.SetConstraints(LayoutAnchors(self.panel2, False, True, True,
False))
self.stc = wxStyledTextCtrl(id=wxID_STCSTYLEEDITDLGSTC, name='stc',
parent=self, pos=wxPoint(8, 208), size=wxSize(435, 207),
style=wxSUNKEN_BORDER)
self.stc.SetConstraints(LayoutAnchors(self.stc, True, True, True, True))
self.stc.SetHelpText('The style preview window. Click or move the cursor over a spesific style to select the style for editing in the editors above.')
EVT_LEFT_UP(self.stc, self.OnUpdateUI)
EVT_KEY_UP(self.stc, self.OnUpdateUI)
self.contextHelpButton1 = wxContextHelpButton(parent=self,
pos=wxPoint(8, 423), size=wxSize(24, 24), style=wxBU_AUTODRAW)
self.contextHelpButton1.SetConstraints(LayoutAnchors(self.contextHelpButton1,
True, False, False, True))
self.okBtn = wxButton(id=wxID_STCSTYLEEDITDLGOKBTN, label='OK',
name='okBtn', parent=self, pos=wxPoint(282, 423), size=wxSize(75,
23), style=0)
self.okBtn.SetConstraints(LayoutAnchors(self.okBtn, False, False, True,
True))
self.okBtn.SetToolTipString('Save changes to the config file')
EVT_BUTTON(self.okBtn, wxID_STCSTYLEEDITDLGOKBTN, self.OnOkbtnButton)
self.cancelBtn = wxButton(id=wxID_STCSTYLEEDITDLGCANCELBTN,
label='Cancel', name='cancelBtn', parent=self, pos=wxPoint(366,
423), size=wxSize(75, 23), style=0)
self.cancelBtn.SetConstraints(LayoutAnchors(self.cancelBtn, False,
False, True, True))
self.cancelBtn.SetToolTipString('Close dialog without saving changes')
EVT_BUTTON(self.cancelBtn, wxID_STCSTYLEEDITDLGCANCELBTN,
self.OnCancelbtnButton)
self.staticText4 = wxStaticText(id=wxID_STCSTYLEEDITDLGSTATICTEXT4,
label='Face:', name='staticText4', parent=self.panel1,
pos=wxPoint(0, 0), size=wxSize(48, 13), style=0)
self.fixedWidthChk = wxCheckBox(id=wxID_STCSTYLEEDITDLGFIXEDWIDTHCHK,
label='', name='fixedWidthChk', parent=self.panel1, pos=wxPoint(0,
23), size=wxSize(13, 19), style=0)
self.fixedWidthChk.SetToolTipString('Check this for Fixed Width fonts')
EVT_CHECKBOX(self.fixedWidthChk, wxID_STCSTYLEEDITDLGFIXEDWIDTHCHK,
self.OnFixedwidthchkCheckbox)
self.faceCb = wxComboBox(choices=[], id=wxID_STCSTYLEEDITDLGFACECB,
name='faceCb', parent=self.panel1, pos=wxPoint(17, 18),
size=wxSize(105, 21), style=0, validator=wxDefaultValidator,
value='')
self.staticText7 = wxStaticText(id=wxID_STCSTYLEEDITDLGSTATICTEXT7,
label='Size:', name='staticText7', parent=self.panel2,
pos=wxPoint(0, 0), size=wxSize(40, 13), style=0)
self.sizeCb = wxComboBox(choices=[], id=wxID_STCSTYLEEDITDLGSIZECB,
name='sizeCb', parent=self.panel2, pos=wxPoint(0, 17),
size=wxSize(91, 21), style=0, validator=wxDefaultValidator,
value='')
self.sizeOkBtn = wxButton(id=wxID_STCSTYLEEDITDLGSIZEOKBTN, label='ok',
name='sizeOkBtn', parent=self.panel2, pos=wxPoint(90, 17),
size=wxSize(21, 21), style=0)
self.faceOkBtn = wxButton(id=wxID_STCSTYLEEDITDLGFACEOKBTN, label='ok',
name='faceOkBtn', parent=self.panel1, pos=wxPoint(122, 18),
size=wxSize(21, 21), style=0)
self.fgColBtn = wxButton(id=wxID_STCSTYLEEDITDLGFGCOLBTN,
label='Foreground', name='fgColBtn', parent=self.panel3,
pos=wxPoint(8, 16), size=wxSize(72, 16), style=0)
EVT_BUTTON(self.fgColBtn, wxID_STCSTYLEEDITDLGFGCOLBTN,
self.OnFgcolbtnButton)
self.fgColCb = wxComboBox(choices=[], id=wxID_STCSTYLEEDITDLGFGCOLCB,
name='fgColCb', parent=self.panel3, pos=wxPoint(8, 32),
size=wxSize(89, 21), style=0, validator=wxDefaultValidator,
value='')
self.fgColOkBtn = wxButton(id=wxID_STCSTYLEEDITDLGFGCOLOKBTN,
label='ok', name='fgColOkBtn', parent=self.panel3, pos=wxPoint(96,
32), size=wxSize(21, 21), style=0)
self.staticText3 = wxStaticText(id=wxID_STCSTYLEEDITDLGSTATICTEXT3,
label='default', name='staticText3', parent=self.panel3,
pos=wxPoint(100, 16), size=wxSize(37, 16), style=0)
self.fgColDefCb = wxCheckBox(id=wxID_STCSTYLEEDITDLGFGCOLDEFCB,
label='checkBox1', name='fgColDefCb', parent=self.panel3,
pos=wxPoint(120, 31), size=wxSize(16, 16), style=0)
self.bgColBtn = wxButton(id=wxID_STCSTYLEEDITDLGBGCOLBTN,
label='Background', name='bgColBtn', parent=self.panel3,
pos=wxPoint(8, 56), size=wxSize(72, 16), style=0)
EVT_BUTTON(self.bgColBtn, wxID_STCSTYLEEDITDLGBGCOLBTN,
self.OnBgcolbtnButton)
self.bgColCb = wxComboBox(choices=[], id=wxID_STCSTYLEEDITDLGBGCOLCB,
name='bgColCb', parent=self.panel3, pos=wxPoint(8, 72),
size=wxSize(89, 21), style=0, validator=wxDefaultValidator,
value='')
self.bgColOkBtn = wxButton(id=wxID_STCSTYLEEDITDLGBGCOLOKBTN,
label='ok', name='bgColOkBtn', parent=self.panel3, pos=wxPoint(96,
72), size=wxSize(21, 21), style=0)
self.staticBox2 = wxStaticBox(id=wxID_STCSTYLEEDITDLGSTATICBOX2,
label='Text attributes', name='staticBox2', parent=self.panel4,
pos=wxPoint(0, 0), size=wxSize(112, 99), style=0)
self.staticBox2.SetConstraints(LayoutAnchors(self.staticBox2, False,
True, True, False))
self.staticBox2.SetHelpText('Text attribute flags.')
self.staticText2 = wxStaticText(id=wxID_STCSTYLEEDITDLGSTATICTEXT2,
label='default', name='staticText2', parent=self.panel4,
pos=wxPoint(68, 11), size=wxSize(37, 16), style=0)
self.taBoldDefCb = wxCheckBox(id=wxID_STCSTYLEEDITDLGTABOLDDEFCB,
label='checkBox1', name='taBoldDefCb', parent=self.panel4,
pos=wxPoint(88, 27), size=wxSize(16, 16), style=0)
self.taItalicDefCb = wxCheckBox(id=wxID_STCSTYLEEDITDLGTAITALICDEFCB,
label='checkBox1', name='taItalicDefCb', parent=self.panel4,
pos=wxPoint(88, 43), size=wxSize(16, 16), style=0)
self.taUnderlinedDefCb = wxCheckBox(id=wxID_STCSTYLEEDITDLGTAUNDERLINEDDEFCB,
label='checkBox1', name='taUnderlinedDefCb', parent=self.panel4,
pos=wxPoint(88, 59), size=wxSize(16, 16), style=0)
self.taEOLfilledDefCb = wxCheckBox(id=wxID_STCSTYLEEDITDLGTAEOLFILLEDDEFCB,
label='checkBox1', name='taEOLfilledDefCb', parent=self.panel4,
pos=wxPoint(88, 75), size=wxSize(16, 16), style=0)
self.taEOLfilledCb = wxCheckBox(id=wxID_STCSTYLEEDITDLGTAEOLFILLEDCB,
label='EOL filled', name='taEOLfilledCb', parent=self.panel4,
pos=wxPoint(8, 75), size=wxSize(72, 16), style=0)
EVT_CHECKBOX(self.taEOLfilledCb, wxID_STCSTYLEEDITDLGTAEOLFILLEDCB,
self.OnTaeoffilledcbCheckbox)
self.taUnderlinedCb = wxCheckBox(id=wxID_STCSTYLEEDITDLGTAUNDERLINEDCB,
label='Underlined', name='taUnderlinedCb', parent=self.panel4,
pos=wxPoint(8, 59), size=wxSize(72, 16), style=0)
EVT_CHECKBOX(self.taUnderlinedCb, wxID_STCSTYLEEDITDLGTAUNDERLINEDCB,
self.OnTaunderlinedcbCheckbox)
self.taItalicCb = wxCheckBox(id=wxID_STCSTYLEEDITDLGTAITALICCB,
label='Italic', name='taItalicCb', parent=self.panel4,
pos=wxPoint(8, 43), size=wxSize(72, 16), style=0)
EVT_CHECKBOX(self.taItalicCb, wxID_STCSTYLEEDITDLGTAITALICCB,
self.OnTaitaliccbCheckbox)
self.taBoldCb = wxCheckBox(id=wxID_STCSTYLEEDITDLGTABOLDCB,
label='Bold', name='taBoldCb', parent=self.panel4, pos=wxPoint(8,
27), size=wxSize(72, 16), style=0)
EVT_CHECKBOX(self.taBoldCb, wxID_STCSTYLEEDITDLGTABOLDCB,
self.OnTaboldcbCheckbox)
self.bgColDefCb = wxCheckBox(id=wxID_STCSTYLEEDITDLGBGCOLDEFCB,
label='checkBox1', name='bgColDefCb', parent=self.panel3,
pos=wxPoint(120, 71), size=wxSize(16, 16), style=0)
self.staticBox1 = wxStaticBox(id=wxID_STCSTYLEEDITDLGSTATICBOX1,
label='Colour', name='staticBox1', parent=self.panel3,
pos=wxPoint(0, 0), size=wxSize(142, 99), style=0)
self.staticBox1.SetConstraints(LayoutAnchors(self.staticBox1, False,
True, True, False))
self.faceDefCb = wxCheckBox(id=wxID_STCSTYLEEDITDLGFACEDEFCB,
label='checkBox1', name='faceDefCb', parent=self.panel1,
pos=wxPoint(120, 0), size=wxSize(16, 16), style=0)
self.taSizeDefCb = wxCheckBox(id=wxID_STCSTYLEEDITDLGTASIZEDEFCB,
label='checkBox1', name='taSizeDefCb', parent=self.panel2,
pos=wxPoint(88, 0), size=wxSize(16, 16), style=0)
def __init__(self, parent, langTitle, lang, configFile, STCsToUpdate=()):
self.stc_title = 'wxStyledTextCtrl Style Editor'
self.stc_title = 'wxStyledTextCtrl Style Editor - %s' % langTitle
if wxPlatform == '__WXMSW__':
self.style_font_size = 8
else:
self.style_font_size = 10
self._init_ctrls(parent)
self.lang = lang
self.configFile = configFile
self.style = ''
self.styleNum = 0
self.names = []
self.values = {}
self.STCsToUpdate = STCsToUpdate
self._blockUpdate = False
for combo, okBtn, evtRet, evtCB, evtRDC in (
(self.fgColCb, self.fgColOkBtn, self.OnfgColRet, self.OnfgColCombobox, self.OnGotoCommonDef),
(self.bgColCb, self.bgColOkBtn, self.OnbgColRet, self.OnbgColCombobox, self.OnGotoCommonDef),
(self.faceCb, self.faceOkBtn, self.OnfaceRet, self.OnfaceCombobox, self.OnGotoCommonDef),
(self.sizeCb, self.sizeOkBtn, self.OnsizeRet, self.OnsizeCombobox, self.OnGotoCommonDef)):
self.bindComboEvts(combo, okBtn, evtRet, evtCB, evtRDC)
(self.config, self.commonDefs, self.styleIdNames, self.styles,
self.styleGroupNames, self.predefStyleGroups,
self.otherLangStyleGroupNames, self.otherLangStyleGroups,
self.displaySrc, self.lexer, self.keywords, self.braceInfo) = \
initFromConfig(configFile, lang)
self.currSpeedSetting = 'style.%s'%self.lang
for grp in [self.currSpeedSetting]+self.styleGroupNames:
self.speedsettingCh.Append(grp)
self.speedsettingCh.SetSelection(0)
margin = 0
self.stc.SetMarginType(margin, wxSTC_MARGIN_NUMBER)
self.stc.SetMarginWidth(margin, 25)
self.stc.SetMarginSensitive(margin, True)
EVT_STC_MARGINCLICK(self.stc, wxID_STCSTYLEEDITDLGSTC, self.OnMarginClick)
self.stc.SetUseTabs(False)
self.stc.SetTabWidth(4)
self.stc.SetIndentationGuides(True)
self.stc.SetEdgeMode(wxSTC_EDGE_BACKGROUND)
self.stc.SetEdgeColumn(44)
self.setStyles()
self.populateStyleSelector()
self.defNames, self.defValues = parseProp(\
self.styleDict.get(wxSTC_STYLE_DEFAULT, ''))
self.stc.SetText(self.displaySrc)
self.stc.EmptyUndoBuffer()
self.stc.SetCurrentPos(self.stc.GetTextLength())
self.stc.SetAnchor(self.stc.GetTextLength())
self.populateCombosWithCommonDefs()
# Logical grouping of controls and the property they edit
self.allCtrls = [((self.fgColBtn, self.fgColCb, self.fgColOkBtn), self.fgColDefCb,
'fore', wxID_STCSTYLEEDITDLGFGCOLDEFCB),
((self.bgColBtn, self.bgColCb, self.bgColOkBtn), self.bgColDefCb,
'back', wxID_STCSTYLEEDITDLGBGCOLDEFCB),
(self.taBoldCb, self.taBoldDefCb,
'bold', wxID_STCSTYLEEDITDLGTABOLDDEFCB),
(self.taItalicCb, self.taItalicDefCb,
'italic', wxID_STCSTYLEEDITDLGTAITALICDEFCB),
(self.taUnderlinedCb, self.taUnderlinedDefCb,
'underline', wxID_STCSTYLEEDITDLGTAUNDERLINEDDEFCB),
(self.taEOLfilledCb, self.taEOLfilledDefCb,
'eolfilled', wxID_STCSTYLEEDITDLGTAEOLFILLEDDEFCB),
((self.sizeCb, self.sizeOkBtn), self.taSizeDefCb,
'size', wxID_STCSTYLEEDITDLGTASIZEDEFCB),
((self.faceCb, self.faceOkBtn, self.fixedWidthChk), self.faceDefCb,
'face', wxID_STCSTYLEEDITDLGFACEDEFCB)]
self.clearCtrls(disableDefs=True)
# centralised default checkbox event handler
self.chbIdMap = {}
for ctrl, chb, prop, wid in self.allCtrls:
self.chbIdMap[wid] = ctrl, chb, prop, wid
EVT_CHECKBOX(chb, wid, self.OnDefaultCheckBox)
chb.SetToolTipString('Toggle defaults')
self.Center(wxBOTH)
#---Property methods------------------------------------------------------------
def getCtrlForProp(self, findprop):
for ctrl, chb, prop, wid in self.allCtrls:
if findprop == prop:
return ctrl, chb
raise Exception('PropNotFound', findprop)
def editProp(self, on, prop, val=''):
oldstyle = self.rememberStyles()
if on:
if not self.names.count(prop):
self.names.append(prop)
self.values[prop] = val
else:
try: self.names.remove(prop)
except ValueError: pass
try: del self.values[prop]
except KeyError: pass
try:
self.updateStyle()
return True
except KeyError, errkey:
wxLogError('Name not found in Common definition, '\
'please enter valid reference. (%s)'%errkey)
self.restoreStyles(oldstyle)
return False
#---Control population methods--------------------------------------------------
def setStyles(self):
if self._blockUpdate: return
self.styles, self.styleDict, self.styleNumIdxMap = \
setSTCStyles(self.stc, self.styles, self.styleIdNames,
self.commonDefs, self.lang, self.lexer, self.keywords)
def updateStyle(self):
# called after a control edited self.names, self.values
# Special case for saving common defs settings
if self.styleNum == 'common':
strVal = self.style[2] = self.values.values()[0]
if self.style[1] == 'size': self.style[2] = int(strVal)
self.commonDefs[self.style[0]] = self.style[2]
self.styleDefST.SetLabel(strVal)
else:
self.style = writePropVal(self.names, self.values)
styleDecl = writeProp(self.styleNum, self.style, self.lang)
self.styles[self.styleNumIdxMap[self.styleNum]] = styleDecl
self.styleDefST.SetLabel(self.style)
self.setStyles()
def findInStyles(self, txt, styles):
for style in styles:
if string.find(style, txt) != -1:
return True
return False
def rememberStyles(self):
return self.names[:], copy.copy(self.values)
def restoreStyles(self, style):
self.names, self.values = style
self.updateStyle()
def clearCtrls(self, isDefault=False, disableDefs=False):
self._blockUpdate = True
try:
for ctrl, chb, prop, wid in self.allCtrls:
if prop in ('fore', 'back'):
cbtn, txt, btn = ctrl
cbtn.SetBackgroundColour(\
wxSystemSettings_GetSystemColour(wxSYS_COLOUR_BTNFACE))
cbtn.SetForegroundColour(wxColour(255, 255, 255))
cbtn.Enable(isDefault)
txt.SetValue('')
txt.Enable(isDefault)
btn.Enable(isDefault)
elif prop == 'size':
cmb, btn = ctrl
cmb.SetValue('')
cmb.Enable(isDefault)
btn.Enable(isDefault)
elif prop == 'face':
cmb, btn, chk = ctrl
cmb.SetValue('')
cmb.Enable(isDefault)
btn.Enable(isDefault)
chk.Enable(isDefault)
chk.SetValue(False)
elif prop in ('bold', 'italic', 'underline', 'eolfilled'):
ctrl.SetValue(False)
ctrl.Enable(isDefault)
chb.Enable(not isDefault and not disableDefs)
chb.SetValue(True)
finally:
self._blockUpdate = False
def populateProp(self, items, default, forceDisable=False):
self._blockUpdate = True
try:
for name, val in items:
if name:
ctrl, chb = self.getCtrlForProp(name)
if name in ('fore', 'back'):
cbtn, txt, btn = ctrl
repval = val%self.commonDefs
cbtn.SetBackgroundColour(strToCol(repval))
cbtn.SetForegroundColour(wxColour(0, 0, 0))
cbtn.Enable(not forceDisable)
txt.SetValue(val)
txt.Enable(not forceDisable)
btn.Enable(not forceDisable)
chb.SetValue(default)
elif name == 'size':
cmb, btn = ctrl
cmb.SetValue(val)
cmb.Enable(not forceDisable)
btn.Enable(not forceDisable)
chb.SetValue(default)
elif name == 'face':
cmb, btn, chk = ctrl
cmb.SetValue(val)
cmb.Enable(not forceDisable)
btn.Enable(not forceDisable)
chk.Enable(not forceDisable)
chb.SetValue(default)
elif name in ('bold', 'italic', 'underline', 'eolfilled'):
ctrl.Enable(not forceDisable)
ctrl.SetValue(True)
chb.SetValue(default)
finally:
self._blockUpdate = False
def valIsCommonDef(self, val):
return len(val) >= 5 and val[:2] == '%('
def populateCtrls(self):
self.clearCtrls(self.styleNum == wxSTC_STYLE_DEFAULT,
disableDefs=self.styleNum < 0)
# handle colour controls for settings
if self.styleNum < 0:
self.fgColDefCb.Enable(True)
if self.styleNum == -1:
self.bgColDefCb.Enable(True)
# populate with default style
self.populateProp(self.defValues.items(), True,
self.styleNum != wxSTC_STYLE_DEFAULT)
# override with current settings
self.populateProp(self.values.items(), False)
def getCommonDefPropType(self, commonDefName):
val = self.commonDefs[commonDefName]
if type(val) == type(0): return 'size'
if len(val) == 7 and val[0] == '#': return 'fore'
return 'face'
def bindComboEvts(self, combo, btn, btnEvtMeth, comboEvtMeth, rdclickEvtMeth):
EVT_COMBOBOX(combo, combo.GetId(), comboEvtMeth)
EVT_BUTTON(btn, btn.GetId(), btnEvtMeth)
EVT_RIGHT_DCLICK(combo, rdclickEvtMeth)
combo.SetToolTipString('Select from list or click "ok" button on the right to change a manual entry, right double-click \n'\
'the drop down button to select Common definition in the Style Editor (if applicable)')
btn.SetToolTipString('Accept value')
def populateCombosWithCommonDefs(self, fixedWidthOnly=None):
self._blockUpdate = True
try:
commonDefs = {'fore': [], 'face': [], 'size': []}
if self.elementLb.GetSelection() < self.commonDefsStartIdx:
for common in self.commonDefs.keys():
prop = self.getCommonDefPropType(common)
commonDefs[prop].append('%%(%s)%s'%(common,
prop=='size' and 'd' or 's'))
# Colours
currFg, currBg = self.fgColCb.GetValue(), self.bgColCb.GetValue()
self.fgColCb.Clear(); self.bgColCb.Clear()
for colCommonDef in commonDefs['fore']:
self.fgColCb.Append(colCommonDef)
self.bgColCb.Append(colCommonDef)
self.fgColCb.SetValue(currFg); self.bgColCb.SetValue(currBg)
# Font
if fixedWidthOnly is None:
fixedWidthOnly = self.fixedWidthChk.GetValue()
fontEnum = wxFontEnumerator()
fontEnum.EnumerateFacenames(fixedWidthOnly=fixedWidthOnly)
fontNameList = fontEnum.GetFacenames()
currFace = self.faceCb.GetValue()
self.faceCb.Clear()
for colCommonDef in ['']+fontNameList+commonDefs['face']:
self.faceCb.Append(colCommonDef)
self.faceCb.SetValue(currFace)
# Size (XXX add std font sizes)
currSize = self.sizeCb.GetValue()
self.sizeCb.Clear()
for colCommonDef in commonDefs['size']:
self.sizeCb.Append(colCommonDef)
self.sizeCb.SetValue(currSize)
finally:
self._blockUpdate = False
def populateStyleSelector(self):
numStyles = self.styleIdNames.items()
numStyles.sort()
self.styleNumLookup = {}
stdStart = -1
stdOffset = 0
extrOffset = 0
# add styles
for num, name in numStyles:
if num == wxSTC_STYLE_DEFAULT:
self.elementLb.InsertItems([name, '----Language----'], 0)
self.elementLb.Append('----Standard----')
stdStart = stdPos = self.elementLb.Number()
else:
# std styles
if num >= 33 and num < 40:
self.elementLb.InsertItems([name], stdStart + stdOffset)
stdOffset = stdOffset + 1
# extra styles
elif num >= 40:
self.elementLb.InsertItems([name], stdStart + extrOffset -1)
extrOffset = extrOffset + 1
# normal lang styles
else:
self.elementLb.Append(name)
self.styleNumLookup[name] = num
# add settings
self.elementLb.Append('----Settings----')
settings = settingsIdNames.items()
settings.sort();settings.reverse()
for num, name in settings:
self.elementLb.Append(name)
self.styleNumLookup[name] = num
# add definitions
self.elementLb.Append('----Common----')
self.commonDefsStartIdx = self.elementLb.Number()
for common in self.commonDefs.keys():
tpe = type(self.commonDefs[common])
self.elementLb.Append('%('+common+')'+(tpe is type('') and 's' or 'd'))
self.styleNumLookup[common] = num
#---Colour methods--------------------------------------------------------------
def getColourDlg(self, colour, title=''):
data = wxColourData()
data.SetColour(colour)
data.SetChooseFull(True)
dlg = wxColourDialog(self, data)
try:
dlg.SetTitle(title)
if dlg.ShowModal() == wxID_OK:
data = dlg.GetColourData()
return data.GetColour()
finally:
dlg.Destroy()
return None
colDlgTitles = {'fore': 'Foreground', 'back': 'Background'}
def editColProp(self, colBtn, colCb, prop):
col = self.getColourDlg(colBtn.GetBackgroundColour(),
self.colDlgTitles[prop]+ ' colour')
if col:
colBtn.SetForegroundColour(wxColour(0, 0, 0))
colBtn.SetBackgroundColour(col)
colStr = colToStr(col)
colCb.SetValue(colStr)
self.editProp(True, prop, colStr)
def OnFgcolbtnButton(self, event):
self.editColProp(self.fgColBtn, self.fgColCb, 'fore')
def OnBgcolbtnButton(self, event):
self.editColProp(self.bgColBtn, self.bgColCb, 'back')
def editColTCProp(self, colCb, colBtn, prop, val=None):
if val is None:
colStr = colCb.GetValue()
else:
colStr = val
if colStr:
col = strToCol(colStr%self.commonDefs)
if self.editProp(colStr!='', prop, colStr):
if colStr:
colBtn.SetForegroundColour(wxColour(0, 0, 0))
colBtn.SetBackgroundColour(col)
else:
colBtn.SetForegroundColour(wxColour(255, 255, 255))
colBtn.SetBackgroundColour(\
wxSystemSettings_GetSystemColour(wxSYS_COLOUR_BTNFACE))
def OnfgColRet(self, event):
try: self.editColTCProp(self.fgColCb, self.fgColBtn, 'fore')
except AssertionError: wxLogError('Not a valid colour value')
def OnfgColCombobox(self, event):
if self._blockUpdate: return
try: self.editColTCProp(self.fgColCb, self.fgColBtn, 'fore', event.GetString())
except AssertionError: wxLogError('Not a valid colour value')
def OnbgColRet(self, event):
try: self.editColTCProp(self.bgColCb, self.bgColBtn, 'back')
except AssertionError: wxLogError('Not a valid colour value')
def OnbgColCombobox(self, event):
if self._blockUpdate: return
try: self.editColTCProp(self.bgColCb, self.bgColBtn, 'back', event.GetString())
except AssertionError: wxLogError('Not a valid colour value')
#---Text attribute events-------------------------------------------------------
def OnTaeoffilledcbCheckbox(self, event):
self.editProp(event.IsChecked(), 'eolfilled')
def OnTaitaliccbCheckbox(self, event):
self.editProp(event.IsChecked(), 'italic')
def OnTaboldcbCheckbox(self, event):
self.editProp(event.IsChecked(), 'bold')
def OnTaunderlinedcbCheckbox(self, event):
self.editProp(event.IsChecked(), 'underline')
def OnGotoCommonDef(self, event):
val = event.GetEventObject().GetValue()
if self.valIsCommonDef(val):
idx = self.elementLb.FindString(val)
if idx != -1:
self.elementLb.SetSelection(idx, True)
self.OnElementlbListbox(None)
def OnfaceRet(self, event):
self.setFace(self.faceCb.GetValue())
def OnfaceCombobox(self, event):
if self._blockUpdate: return
self.setFace(event.GetString())
def setFace(self, val):
try: val%self.commonDefs
except KeyError: wxLogError('Invalid common definition')
else: self.editProp(val!='', 'face', val)
def OnsizeRet(self, event):
self.setSize(self.sizeCb.GetValue())
def OnsizeCombobox(self, event):
if self._blockUpdate: return
self.setSize(event.GetString())
def setSize(self, val):
try: int(val%self.commonDefs)
except ValueError: wxLogError('Not a valid integer size value')
except KeyError: wxLogError('Invalid common definition')
else: self.editProp(val!='', 'size', val)
#---Main GUI events-------------------------------------------------------------
def OnElementlbListbox(self, event):
isCommon = self.elementLb.GetSelection() >= self.commonDefsStartIdx
self.removeCommonItemBtn.Enable(isCommon)
styleIdent = self.elementLb.GetStringSelection()
# common definition selected
if isCommon:
common = styleIdent[2:-2]
prop = self.getCommonDefPropType(common)
self.clearCtrls(disableDefs=True)
if prop == 'fore':
self.fgColBtn.Enable(True)
self.fgColCb.Enable(True)
self.fgColOkBtn.Enable(True)
elif prop == 'face':
self.faceCb.Enable(True)
self.fixedWidthChk.Enable(True)
self.faceOkBtn.Enable(True)
elif prop == 'size':
self.sizeCb.Enable(True)
self.sizeOkBtn.Enable(True)
commonDefVal = str(self.commonDefs[common])
self.styleDefST.SetLabel(commonDefVal)
self.populateProp( [(prop, commonDefVal)], True)
self.styleNum = 'common'
self.style = [common, prop, commonDefVal]
self.names, self.values = [prop], {prop: commonDefVal}
# normal style element selected
elif len(styleIdent) >=2 and styleIdent[:2] != '--':
self.styleNum = self.styleNumLookup[styleIdent]
self.style = self.styleDict[self.styleNum]
self.names, self.values = parseProp(self.style)
if self.styleNum == wxSTC_STYLE_DEFAULT:
self.defNames, self.defValues = \
self.names, self.values
self.checkBraces(self.styleNum)
self.styleDefST.SetLabel(self.style)
self.populateCtrls()
# separator selected
else:
self.clearCtrls(disableDefs=True)
if styleIdent:
self.styleDefST.SetLabel(styleCategoryDescriptions[styleIdent])
self.populateCombosWithCommonDefs()
def OnDefaultCheckBox(self, event):
if self.chbIdMap.has_key(event.GetId()):
ctrl, chb, prop, wid = self.chbIdMap[event.GetId()]
restore = not event.IsChecked()
if prop in ('fore', 'back'):
cbtn, cmb, btn = ctrl
cbtn.Enable(restore)
cmb.Enable(restore)
btn.Enable(restore)
if restore:
colStr = cmb.GetValue()
#if prop == 'fore': colStr = self.fgColCb.GetValue()
#else: colStr = self.bgColCb.GetValue()
if colStr: self.editProp(True, prop, colStr)
else:
self.editProp(False, prop)
elif prop == 'size':
cmb, btn = ctrl
val = cmb.GetValue()
if val: self.editProp(restore, prop, val)
cmb.Enable(restore)
btn.Enable(restore)
elif prop == 'face':
cmb, btn, chk = ctrl
val = cmb.GetStringSelection()
if val: self.editProp(restore, prop, val)
cmb.Enable(restore)
btn.Enable(restore)
chk.Enable(restore)
elif prop in ('bold', 'italic', 'underline', 'eolfilled'):
ctrl.Enable(restore)
if ctrl.GetValue(): self.editProp(restore, prop)
def OnOkbtnButton(self, event):
# write styles and common defs to the config
wxBeginBusyCursor()
try:
writeStylesToConfig(self.config, 'style.%s'%self.lang, self.styles)
self.config.SetPath('')
self.config.Write(commonDefsFile, `self.commonDefs`)
self.config.Flush()
for stc in self.STCsToUpdate:
setSTCStyles(stc, self.styles, self.styleIdNames, self.commonDefs,
self.lang, self.lexer, self.keywords)
finally:
wxEndBusyCursor()
self.EndModal(wxID_OK)
def OnCancelbtnButton(self, event):
self.EndModal(wxID_CANCEL)
def OnCommondefsbtnButton(self, event):
dlg = wxTextEntryDialog(self, 'Edit common definitions dictionary',
'Common definitions', pprint.pformat(self.commonDefs),
style=wxTE_MULTILINE | wxOK | wxCANCEL | wxCENTRE)
try:
if dlg.ShowModal() == wxID_OK:
answer = eval(dlg.GetValue())
assert type(answer) is type({}), 'Not a valid dictionary'
oldDefs = self.commonDefs
self.commonDefs = answer
try:
self.setStyles()
except KeyError, badkey:
wxLogError(str(badkey)+' not defined but required, \n'\
'reverting to previous common definition')
self.commonDefs = oldDefs
self.setStyles()
self.populateCombosWithCommonDefs()
finally:
dlg.Destroy()
def OnSpeedsettingchChoice(self, event):
group = event.GetString()
if group:
userStyles = 'style.%s'%self.lang
if self.currSpeedSetting == userStyles:
self.predefStyleGroups[userStyles] = self.styles
self.styles = self.predefStyleGroups[group]
self.setStyles()
self.defNames, self.defValues = parseProp(\
self.styleDict.get(wxSTC_STYLE_DEFAULT, ''))
self.OnElementlbListbox(None)
self.currSpeedSetting = group
def OnFixedwidthchkCheckbox(self, event):
self.populateCombosWithCommonDefs(event.Checked())
def OnAddsharebtnButton(self, event):
dlg = CommonDefDlg(self)
try:
if dlg.ShowModal() == wxID_OK:
prop, name = dlg.result
if not self.commonDefs.has_key(name):
self.commonDefs[name] = commonPropDefs[prop]
self.elementLb.Append('%('+name+')'+\
(type(commonPropDefs[prop]) is type('') and 's' or 'd'))
self.elementLb.SetSelection(self.elementLb.Number()-1, True)
self.populateCombosWithCommonDefs()
self.OnElementlbListbox(None)
finally:
dlg.Destroy()
def OnRemovesharebtnButton(self, event):
ownGroup = 'style.%s'%self.lang
comDef = self.elementLb.GetStringSelection()
# Search ALL styles before removing
srchDct = {ownGroup: self.styles}
srchDct.update(self.predefStyleGroups)
srchDct.update(self.otherLangStyleGroups)
matchList = []
for grpName, styles in srchDct.items():
if self.findInStyles(comDef, styles):
matchList.append(grpName)
if matchList:
wxLogError('Aborted: '+comDef+' is still used in the styles of the \n'\
'following groups in the config file (stc-styles.rc.cfg):\n'+ \
string.join(matchList, '\n'))
else:
del self.commonDefs[comDef[2:-2]]
self.setStyles()
self.populateCombosWithCommonDefs()
selIdx = self.elementLb.GetSelection()
self.elementLb.Delete(selIdx)
if selIdx == self.elementLb.Number():
selIdx = selIdx - 1
self.elementLb.SetSelection(selIdx, True)
self.OnElementlbListbox(None)
#---STC events------------------------------------------------------------------
def OnUpdateUI(self, event):
styleBefore = self.stc.GetStyleAt(self.stc.GetCurrentPos())
if self.styleIdNames.has_key(styleBefore):
self.elementLb.SetStringSelection(self.styleIdNames[styleBefore],
True)
else:
self.elementLb.SetSelection(0, False)
self.styleDefST.SetLabel('Style %d not defined, sorry.'%styleBefore)
self.OnElementlbListbox(None)
event.Skip()
def checkBraces(self, style):
if style == wxSTC_STYLE_BRACELIGHT and self.braceInfo.has_key('good'):
line, col = self.braceInfo['good']
pos = self.stc.PositionFromLine(line-1) + col
braceOpposite = self.stc.BraceMatch(pos)
if braceOpposite != -1:
self.stc.BraceHighlight(pos, braceOpposite)
elif style == wxSTC_STYLE_BRACEBAD and self.braceInfo.has_key('bad'):
line, col = self.braceInfo['bad']
pos = self.stc.PositionFromLine(line-1) + col
self.stc.BraceBadLight(pos)
else:
self.stc.BraceBadLight(-1)
return
def OnStcstyleeditdlgSize(self, event):
self.Layout()
# Without this refresh, resizing leaves artifacts
self.Refresh(1)
event.Skip()
def OnMarginClick(self, event):
self.elementLb.SetStringSelection('Line numbers', True)
self.OnElementlbListbox(None)
#---Common definition dialog----------------------------------------------------
[wxID_COMMONDEFDLG, wxID_COMMONDEFDLGCANCELBTN, wxID_COMMONDEFDLGCOMDEFNAMETC, wxID_COMMONDEFDLGOKBTN, wxID_COMMONDEFDLGPROPTYPERBX, wxID_COMMONDEFDLGSTATICBOX1] = map(lambda _init_ctrls: wxNewId(), range(6))
class CommonDefDlg(wxDialog):
def _init_ctrls(self, prnt):
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')
self.SetClientSize(wxSize(184, 200))
self.propTypeRBx = wxRadioBox(choices = ['Colour value', 'Font face', 'Size value'], id = wxID_COMMONDEFDLGPROPTYPERBX, label = 'Property type', majorDimension = 1, name = 'propTypeRBx', parent = self, point = wxPoint(8, 8), size = wxSize(168, 92), style = wxRA_SPECIFY_COLS, validator = wxDefaultValidator)
self.propTypeRBx.SetSelection(self._propTypeIdx)
self.staticBox1 = wxStaticBox(id = wxID_COMMONDEFDLGSTATICBOX1, label = 'Name', name = 'staticBox1', parent = self, pos = wxPoint(8, 108), size = wxSize(168, 46), style = 0)
self.comDefNameTC = wxTextCtrl(id = wxID_COMMONDEFDLGCOMDEFNAMETC, name = 'comDefNameTC', parent = self, pos = wxPoint(16, 124), size = wxSize(152, 21), style = 0, value = '')
self.comDefNameTC.SetLabel(self._comDefName)
self.okBtn = wxButton(id = wxID_COMMONDEFDLGOKBTN, label = 'OK', name = 'okBtn', parent = self, pos = wxPoint(8, 164), size = wxSize(80, 23), style = 0)
EVT_BUTTON(self.okBtn, wxID_COMMONDEFDLGOKBTN, self.OnOkbtnButton)
self.cancelBtn = wxButton(id = wxID_COMMONDEFDLGCANCELBTN, label = 'Cancel', name = 'cancelBtn', parent = self, pos = wxPoint(96, 164), size = wxSize(80, 23), style = 0)
EVT_BUTTON(self.cancelBtn, wxID_COMMONDEFDLGCANCELBTN, self.OnCancelbtnButton)
def __init__(self, parent, name='', propIdx=0):
self._comDefName = ''
self._comDefName = name
self._propTypeIdx = 0
self._propTypeIdx = propIdx
self._init_ctrls(parent)
self.propMap = {0: 'fore', 1: 'face', 2: 'size'}
self.result = ( '', '' )
self.Center(wxBOTH)
def OnOkbtnButton(self, event):
self.result = ( self.propMap[self.propTypeRBx.GetSelection()],
self.comDefNameTC.GetValue() )
self.EndModal(wxID_OK)
def OnCancelbtnButton(self, event):
self.result = ( '', '' )
self.EndModal(wxID_CANCEL)
#---Functions useful outside of the editor----------------------------------
def setSelectionColour(stc, style):
names, values = parseProp(style)
if 'fore' in names:
stc.SetSelForeground(True, strToCol(values['fore']))
if 'back' in names:
stc.SetSelBackground(True, strToCol(values['back']))
def setCursorColour(stc, style):
names, values = parseProp(style)
if 'fore' in names:
stc.SetCaretForeground(strToCol(values['fore']))
def setEdgeColour(stc, style):
names, values = parseProp(style)
if 'fore' in names:
stc.SetEdgeColour(strToCol(values['fore']))
def strToCol(strCol):
assert len(strCol) == 7 and strCol[0] == '#', 'Not a valid colour string'
return wxColour(string.atoi('0x'+strCol[1:3], 16),
string.atoi('0x'+strCol[3:5], 16),
string.atoi('0x'+strCol[5:7], 16))
def colToStr(col):
return '#%s%s%s' % (string.zfill(string.upper(hex(col.Red())[2:]), 2),
string.zfill(string.upper(hex(col.Green())[2:]), 2),
string.zfill(string.upper(hex(col.Blue())[2:]), 2))
def writeProp(num, style, lang):
if num >= 0:
return 'style.%s.%s='%(lang, string.zfill(`num`, 3)) + style
else:
return 'setting.%s.%d='%(lang, num) + style
def writePropVal(names, values):
res = []
for name in names:
if name:
res.append(values[name] and name+':'+values[name] or name)
return string.join(res, ',')
def parseProp(prop):
items = string.split(prop, ',')
names = []
values = {}
for item in items:
nameVal = string.split(item, ':')
names.append(string.strip(nameVal[0]))
if len(nameVal) == 1:
values[nameVal[0]] = ''
else:
values[nameVal[0]] = string.strip(nameVal[1])
return names, values
def parsePropLine(prop):
name, value = string.split(prop, '=')
return int(string.split(name, '.')[-1]), value
def setSTCStyles(stc, styles, styleIdNames, commonDefs, lang, lexer, keywords):
#wxLogMessage('Set style')
styleDict = {}
styleNumIdxMap = {}
# build style dict based on given styles
for numStyle in styles:
num, style = parsePropLine(numStyle)
styleDict[num] = style
# Add blank style entries for undefined styles
newStyles = []
styleItems = styleIdNames.items() + settingsIdNames.items()
styleItems.sort()
idx = 0
for num, name in styleItems:
styleNumIdxMap[num] = idx
if not styleDict.has_key(num):
styleDict[num] = ''
newStyles.append(writeProp(num, styleDict[num], lang))
idx = idx + 1
# Set background colour to reduce flashing effect on refresh or page switch
bkCol = None
if styleDict.has_key(0): prop = styleDict[0]
else: prop = styleDict[wxSTC_STYLE_DEFAULT]
names, vals = parseProp(prop)
if 'back' in names:
bkCol = strToCol(vals['back'])
if bkCol is None:
bkCol = wxWHITE
stc.SetBackgroundColour(bkCol)
# Set the styles on the wxSTC
# stc.Show(False)
stc.StyleResetDefault()
stc.ClearDocumentStyle()
stc.SetLexer(lexer)
stc.SetKeyWords(0, keywords)
stc.StyleSetSpec(wxSTC_STYLE_DEFAULT,
styleDict[wxSTC_STYLE_DEFAULT] % commonDefs)
stc.StyleClearAll()
for num, style in styleDict.items():
if num >= 0:
stc.StyleSetSpec(num, style % commonDefs)
elif num == -1:
setSelectionColour(stc, style % commonDefs)
elif num == -2:
setCursorColour(stc, style % commonDefs)
elif num == -3:
setEdgeColour(stc, style % commonDefs)
stc.Colourise(0, stc.GetTextLength())
# stc.Show(True)
return newStyles, styleDict, styleNumIdxMap
#---Config reading and writing -------------------------------------------------
commonDefsFile = 'common.defs.%s'%(wxPlatform == '__WXMSW__' and 'msw' or 'gtk')
def readPyValFromConfig(conf, name):
return eval(string.replace(conf.Read(name), '\r\n', '\n')+'\n')
def initFromConfig(configFile, lang):
cfg = wxFileConfig(localFilename=configFile, style=wxCONFIG_USE_LOCAL_FILE)
cfg.SetExpandEnvVars(False)
# read in all group names for this language
groupPrefix = 'style.%s'%lang
gpLen = len(groupPrefix)
predefStyleGroupNames, otherLangStyleGroupNames = [], []
cont, val, idx = cfg.GetFirstGroup()
while cont:
if val != groupPrefix and len(val) >= 5 and val[:5] == 'style':
if len(val) > gpLen and val[:gpLen] == groupPrefix:
predefStyleGroupNames.append(val)
else:
otherLangStyleGroupNames.append(val)
cont, val, idx = cfg.GetNextGroup(idx)
# read in common elements
commonDefs = readPyValFromConfig(cfg, commonDefsFile)
assert type(commonDefs) is type({}), \
'Common definitions (%s) not a valid dict'%commonDefsFile
commonStyleIdNames = readPyValFromConfig(cfg, 'common.styleidnames')
assert type(commonStyleIdNames) is type({}), \
'Common definitions (%s) not a valid dict'%'common.styleidnames'
# Lang spesific settings
cfg.SetPath(lang)
styleIdNames = readPyValFromConfig(cfg, 'styleidnames')
assert type(commonStyleIdNames) is type({}), \
'Not a valid dict [%s] styleidnames)'%lang
styleIdNames.update(commonStyleIdNames)
braceInfo = readPyValFromConfig(cfg, 'braces')
assert type(commonStyleIdNames) is type({}), \
'Not a valid dict [%s] braces)'%lang
displaySrc = cfg.Read('displaysrc')
lexer = readPyValFromConfig(cfg, 'lexer')
keywords = cfg.Read('keywords')
cfg.SetPath('')
# read in current styles
styles = readStylesFromConfig(cfg, groupPrefix)
# read in predefined styles
predefStyleGroups = {}
for group in predefStyleGroupNames:
predefStyleGroups[group] = readStylesFromConfig(cfg, group)
# read in all other style sections
otherLangStyleGroups = {}
for group in otherLangStyleGroupNames:
otherLangStyleGroups[group] = readStylesFromConfig(cfg, group)
return (cfg, commonDefs, styleIdNames, styles, predefStyleGroupNames,
predefStyleGroups, otherLangStyleGroupNames, otherLangStyleGroups,
displaySrc, lexer, keywords, braceInfo)
def readStylesFromConfig(config, group):
config.SetPath('')
config.SetPath(group)
styles = []
cont, val, idx = config.GetFirstEntry()
while cont:
styles.append(val+'='+config.Read(val))
cont, val, idx = config.GetNextEntry(idx)
config.SetPath('')
return styles
def writeStylesToConfig(config, group, styles):
config.SetPath('')
config.DeleteGroup(group)
config.SetPath(group)
for style in styles:
name, value = string.split(style, '=')
config.Write(name, string.strip(value))
config.SetPath('')
#-------------------------------------------------------------------------------
def initSTC(stc, config, lang):
""" Main module entry point. Initialise a wxSTC from given config file."""
(cfg, commonDefs, styleIdNames, styles, predefStyleGroupNames,
predefStyleGroups, otherLangStyleGroupNames, otherLangStyleGroups,
displaySrc, lexer, keywords, braceInfo) = initFromConfig(config, lang)
setSTCStyles(stc, styles, styleIdNames, commonDefs, lang, lexer, keywords)
#-------------------------------------------------------------------------------
if __name__ == '__main__':
from wxPython.help import *
app = wxPySimpleApp()
provider = wxSimpleHelpProvider()
wxHelpProvider_Set(provider)
home = os.environ.get('HOME')
if home: home = os.path.join(home, '.boa')
config = os.path.abspath(os.path.join(home, 'stc-styles.rc.cfg'))
if 0:
f = wxFrame(None, -1, 'Test frame (double click for editor)')
stc = wxStyledTextCtrl(f, -1)
def OnDblClick(evt, stc=stc):
dlg = STCStyleEditDlg(None, 'Python', 'python', config, (stc,))
try: dlg.ShowModal()
finally: dlg.Destroy()
stc.SetText(open('STCStyleEditor.py').read())
EVT_LEFT_DCLICK(stc, OnDblClick)
initSTC(stc, config, 'python')
f.Show(True)
app.MainLoop()
else:
dlg = STCStyleEditDlg(None,
'Python', 'python',
#'HTML', 'html',
#'XML', 'xml',
#'C++', 'cpp',
#'Text', 'text',
#'Properties', 'prop',
config)
try: dlg.ShowModal()
finally: dlg.Destroy()