⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 stcstyleeditor.py

📁 Wxpython Implemented on Windows CE, Source code
💻 PY
📖 第 1 页 / 共 4 页
字号:
        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 + -