📄 stcstyleeditor.py
字号:
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 == wx.stc.STC_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 == wx.stc.STC_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] = [wx.NewId() for _init_ctrls in range(6)]
class CommonDefDlg(wx.Dialog):
def _init_ctrls(self, prnt):
wx.Dialog.__init__(self, id = wxID_COMMONDEFDLG, name = 'CommonDefDlg', parent = prnt, pos = wx.Point(398, 249), size = wx.Size(192, 220), style= wx.DEFAULT_DIALOG_STYLE, title = 'Common definition')
self.SetClientSize(wx.Size(184, 200))
self.propTypeRBx = wx.RadioBox(choices = ['Colour value', 'Font face', 'Size value'], id = wxID_COMMONDEFDLGPROPTYPERBX, label = 'Property type', majorDimension = 1, name = 'propTypeRBx', parent = self, point = wx.Point(8, 8), size = wx.Size(168, 92), style= wx.RA_SPECIFY_COLS)
self.propTypeRBx.SetSelection(self._propTypeIdx)
self.staticBox1 = wx.StaticBox(id = wxID_COMMONDEFDLGSTATICBOX1, label = 'Name', name = 'staticBox1', parent = self, pos = wx.Point(8, 108), size = wx.Size(168, 46), style = 0)
self.comDefNameTC = wx.TextCtrl(id = wxID_COMMONDEFDLGCOMDEFNAMETC, name = 'comDefNameTC', parent = self, pos = wx.Point(16, 124), size = wx.Size(152, 21), style = 0, value = '')
self.comDefNameTC.SetLabel(self._comDefName)
self.okBtn = wx.Button(id = wxID_COMMONDEFDLGOKBTN, label = 'OK', name = 'okBtn', parent = self, pos = wx.Point(8, 164), size = wx.Size(80, 23), style = 0)
self.okBtn.Bind(wx.EVT_BUTTON, self.OnOkbtnButton, id=wxID_COMMONDEFDLGOKBTN)
self.cancelBtn = wx.Button(id = wxID_COMMONDEFDLGCANCELBTN, label = 'Cancel', name = 'cancelBtn', parent = self, pos = wx.Point(96, 164), size = wx.Size(80, 23), style = 0)
self.cancelBtn.Bind(wx.EVT_BUTTON, self.OnCancelbtnButton, id=wxID_COMMONDEFDLGCANCELBTN)
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(wx.BOTH)
def OnOkbtnButton(self, event):
self.result = ( self.propMap[self.propTypeRBx.GetSelection()],
self.comDefNameTC.GetValue() )
self.EndModal(wx.ID_OK)
def OnCancelbtnButton(self, event):
self.result = ( '', '' )
self.EndModal(wx.ID_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: '+strCol
return wx.Colour(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 ','.join(res)
def parseProp(prop):
items = prop.split(',')
names = []
values = {}
for item in items:
nameVal = item.split(':')
names.append(nameVal[0].strip())
if len(nameVal) == 1:
values[nameVal[0]] = ''
else:
values[nameVal[0]] = nameVal[1].strip()
return names, values
def parsePropLine(prop):
name, value = prop.split('=')
return int(name.split('.')[-1]), value
def setSTCStyles(stc, styles, styleIdNames, commonDefs, lang, lexer, keywords):
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[wx.stc.STC_STYLE_DEFAULT]
names, vals = parseProp(prop)
if 'back' in names:
bkCol = strToCol(vals['back']%commonDefs)
if bkCol is None:
bkCol = wx.WHITE
stc.SetBackgroundColour(bkCol)
# Set the styles on the wxSTC
stc.StyleResetDefault()
stc.ClearDocumentStyle()
stc.SetLexer(lexer)
stc.SetKeyWords(0, keywords)
stc.StyleSetSpec(wx.stc.STC_STYLE_DEFAULT,
styleDict[wx.stc.STC_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())
return newStyles, styleDict, styleNumIdxMap
#---Config reading and writing -------------------------------------------------
commonDefsFile = 'common.defs.%s'%(platformSettings[wx.Platform][0])
def readPyValFromConfig(conf, name):
ns = {}
#ns.update(wx.stc.__dict__)
ns.update(wxPython.stc.__dict__)
ns['wx'] = wx
value = conf.Read(name).replace('\r\n', '\n')+'\n'
try:
return eval(value, ns)
except:
print value
raise
def initFromConfig(configFile, lang):
if not os.path.exists(configFile):
raise Exception, 'Config file %s not found'%configFile
cfg = wx.FileConfig(localFilename=configFile, style= wx.CONFIG_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 specific 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 = style.split('=')
config.Write(name, value.strip())
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__':
app = wx.PySimpleApp()
provider = wx.SimpleHelpProvider()
wx.HelpProvider.Set(provider)
home = os.environ.get('HOME')
if home:
home = os.path.join(home, '.boa-constructor')
if not os.path.exists(home):
home = '.'
else:
home = '.'
config = os.path.abspath(os.path.join(home, 'stc-styles.rc.cfg'))
if 0:
f = wx.Frame(None, -1, 'Test frame (double click for editor)')
stc = wx.stc.StyledTextCtrl(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())
stc.Bind(wx.EVT_LEFT_DCLICK, 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()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -