Index: compile_rules.py ================================================================== --- compile_rules.py +++ compile_rules.py @@ -25,26 +25,26 @@ def convertRGBToInteger (r, g, b): return (r & 255) << 16 | (g & 255) << 8 | (b & 255) -def convertHSLToInteger (h, s, l): +def convertHSLToRBG (h, s, l): r, g, b = colorsys.hls_to_rgb(h/360, l/100, s/100) - return convertRGBToInteger(round(r*255), round(g*255), round(b*255)) + return [round(r*255), round(g*255), round(b*255)] -def createColors (lOptColor): - dAppColor = {} - for sApp, dOptColor in lOptColor: - if sApp == "Writer": - dAppColor["dOptColor"+sApp] = { sKey: convertHSLToInteger(*aColor) for sKey, aColor in dOptColor.items() } - elif sApp in ("Firefox", "Thunderbird"): - dAppColor["dOptColor"+sApp] = { sKey: "hsl({}, {}%, {}%)".format(*aColor) for sKey, aColor in dOptColor.items() } - else: - dAppColor["dOptColor"+sApp] = dOptColor - #print(dAppColor) - return dAppColor +def createColors (dColor): + dColorType = { + "sCSS": {}, # dictionary of colors as strings for HTML/CSS (example: hsl(0, 50%, 50%)) + "aRGB": {}, # dictionary of colors as RGB tuple + "nInt": {} # dictionary of colors as integer values (for Writer) + } + for sKey, aHSL in dColor.items(): + dColorType["sCSS"][sKey] = "hsl({}, {}%, {}%)".format(*aHSL) + dColorType["aRGB"][sKey] = convertHSLToRBG(*aHSL) + dColorType["nInt"][sKey] = convertRGBToInteger(*dColorType["aRGB"][sKey]) + return dColorType def prepareFunction (s): "convert simple rule syntax to a string of Python code" s = s.replace("__also__", "bCondMemo") @@ -410,10 +410,11 @@ sLang = "" sDefaultUILang = "" lStructOpt = [] lOpt = [] lOptColor = [] + dColor = {} dOptLabel = {} dOptPriority = {} for sLine in lOptionLines: sLine = sLine.strip() if sLine.startswith("OPTGROUP/"): @@ -423,16 +424,19 @@ lOpt = [ [s, {}] for s in sLine[12:].strip().split() ] # don’t use tuples (s, {}), because unknown to JS elif sLine.startswith("OPT/"): m = re.match("OPT/([a-z0-9]+):(.+)$", sLine) for i, sOpt in enumerate(m.group(2).split()): lOpt[i][1][m.group(1)] = eval(sOpt) - elif sLine.startswith("OPTCOLORSOFTWARE:"): - lOptColor = [ [s, {}] for s in sLine[17:].strip().split() ] # don’t use tuples (s, {}), because unknown to JS + elif sLine.startswith("OPTCOLORTHEME:"): + lOptColor = [ [s, {}] for s in sLine[14:].strip().split() ] # don’t use tuples (s, {}), because unknown to JS elif sLine.startswith("OPTCOLOR/"): m = re.match("OPTCOLOR/([a-z0-9]+):(.+)$", sLine) for i, sColor in enumerate(m.group(2).split()): - lOptColor[i][1][m.group(1)] = [ int(s) for s in sColor.split(",") ] + lOptColor[i][1][m.group(1)] = sColor + elif sLine.startswith("COLOR/"): + m = re.match("COLOR/([a-z0-9]+):(.+)$", sLine) + dColor[m.group(1)] = [ int(s) for s in m.group(2).strip().split(",") ] elif sLine.startswith("OPTPRIORITY/"): m = re.match("OPTPRIORITY/([a-z0-9]+): *([0-9])$", sLine) dOptPriority[m.group(1)] = int(m.group(2)) elif sLine.startswith("OPTLANG/"): m = re.match("OPTLANG/([a-z][a-z](?:_[A-Z][A-Z]|)):(.+)$", sLine) @@ -446,13 +450,15 @@ dOptLabel[sLang][m.group(1)] = list(map(str.strip, m.group(2).split("|"))) if "|" in m.group(2) else [m.group(2).strip(), ""] else: print("# Error. Wrong option line in:\n ") print(sLine) print(" options defined for: " + ", ".join([ t[0] for t in lOpt ])) - dOptions = { "lStructOpt": lStructOpt, "dOptLabel": dOptLabel, "sDefaultUILang": sDefaultUILang } + dOptions = { + "lStructOpt": lStructOpt, "dOptLabel": dOptLabel, "sDefaultUILang": sDefaultUILang, \ + "dColorType": createColors(dColor), "dOptColor": { s: d for s, d in lOptColor } + } dOptions.update({ "dOpt"+k: v for k, v in lOpt }) - dOptions.update(createColors(lOptColor)) return dOptions, dOptPriority def printBookmark (nLevel, sComment, nLine): "print bookmark within the rules file" @@ -499,11 +505,11 @@ lTest.append("{:<8}".format(i) + " " + sLine[5:].strip()) elif sLine.startswith("TODO:"): # todo pass elif sLine.startswith(("OPTGROUP/", "OPTSOFTWARE:", "OPT/", \ - "OPTCOLORSOFTWARE:", "OPTCOLOR/", \ + "COLOR/", "OPTCOLORTHEME:", "OPTCOLOR/", \ "OPTLANG/", "OPTDEFAULTUILANG:", \ "OPTLABEL/", "OPTPRIORITY/")): # options lOpt.append(sLine) elif sLine.startswith("!!"): Index: gc_core/js/lang_core/gc_options.js ================================================================== --- gc_core/js/lang_core/gc_options.js +++ gc_core/js/lang_core/gc_options.js @@ -11,15 +11,25 @@ return this.dOpt[sContext]; } return this.dOpt["JavaScript"]; }, - getOptionsColors: function (sContext="JavaScript") { - if (this.dOptColor.hasOwnProperty(sContext)) { - return this.dOptColor[sContext]; + getOptionsColors: function (sTheme="Default", sColorType="aRGB") { + let dOptColor = (this.dOptColor.hasOwnProperty()) ? this.dOptColor[sTheme] : this.dOptColor["Default"]; + let dColorType = (this.dColorType.hasOwnProperty(sColorType)) ? this.dColorType[sColorType] : this.dColorType["aRGB"]; + let dColor = {}; + try { + for (let [sOpt, sColor] of Object.entries(this.dOptColor)) { + dColor[sOpt] = dColorType[sColor]; + } + console.log(dColor); + return dColor; } - return this.dOptColor["JavaScript"]; + catch (e) { + console.error(e); + return {} + } }, lStructOpt: ${lStructOpt}, dOpt: { @@ -26,15 +36,13 @@ "JavaScript": new Map (${dOptJavaScript}), "Firefox": new Map (${dOptFirefox}), "Thunderbird": new Map (${dOptThunderbird}), }, - dOptColor: { - "JavaScript": new Map (${dOptColorJavaScript}), - "Firefox": new Map (${dOptColorFirefox}), - "Thunderbird": new Map (${dOptColorThunderbird}), - }, + dColorType: ${dColorType}, + + dOptColor: ${dOptColor}, dOptLabel: ${dOptLabel} } @@ -41,8 +49,9 @@ if (typeof(exports) !== 'undefined') { exports.getOptions = gc_options.getOptions; exports.getOptionsColors = gc_options.getOptionsColors; exports.lStructOpt = gc_options.lStructOpt; exports.dOpt = gc_options.dOpt; + exports.dColorType = gc_options.dColorType; exports.dOptColor = gc_options.dOptColor; exports.dOptLabel = gc_options.dOptLabel; } Index: gc_core/py/lang_core/gc_engine.py ================================================================== --- gc_core/py/lang_core/gc_engine.py +++ gc_core/py/lang_core/gc_engine.py @@ -43,28 +43,31 @@ _rules_graph = None # module gc_rules_graph # Data _sAppContext = "" # what software is running _dOptions = None +_dOptionsColors = None _oSpellChecker = None _oTokenizer = None _aIgnoredRules = set() #### Initialization -def load (sContext="Python"): +def load (sContext="Python", sColorType="aRGB"): "initialization of the grammar checker" global _oSpellChecker global _sAppContext global _dOptions + global _dOptionsColors global _oTokenizer try: _oSpellChecker = SpellChecker("${lang}", "${dic_main_filename_py}", "${dic_extended_filename_py}", "${dic_community_filename_py}", "${dic_personal_filename_py}") _sAppContext = sContext _dOptions = dict(gc_options.getOptions(sContext)) # duplication necessary, to be able to reset to default + _dOptionsColors = gc_options.getOptionsColors(sContext, sColorType) _oTokenizer = _oSpellChecker.getTokenizer() _oSpellChecker.activateStorage() except: traceback.print_exc() @@ -609,11 +612,11 @@ sMessage = globals()[sMsg[1:]](sText, m) if sMsg[0:1] == "=" else m.expand(sMsg) if bShowRuleId: sMessage += " # " + sLineId + " # " + sRuleId # if _bWriterError: - return self._createErrorForWriter(nStart, nEnd - nStart, sRuleId, sMessage, lSugg, sURL) + return self._createErrorForWriter(nStart, nEnd - nStart, sRuleId, sOption, sMessage, lSugg, sURL) else: return self._createErrorAsDict(nStart, nEnd, sLineId, sRuleId, sOption, sMessage, lSugg, sURL, bContext) def _createErrorFromTokens (self, sSugg, nTokenOffset, nLastToken, iFirstToken, nStart, nEnd, sLineId, sRuleId, bCaseSvty, sMsg, sURL, bShowRuleId, sOption, bContext): # suggestions @@ -630,39 +633,40 @@ sMessage = globals()[sMsg[1:]](self.lToken, nTokenOffset, nLastToken) if sMsg[0:1] == "=" else self._expand(sMsg, nTokenOffset, nLastToken) if bShowRuleId: sMessage += " " + sLineId + " # " + sRuleId # if _bWriterError: - return self._createErrorForWriter(nStart, nEnd - nStart, sRuleId, sMessage, lSugg, sURL) + return self._createErrorForWriter(nStart, nEnd - nStart, sRuleId, sOption, sMessage, lSugg, sURL) else: return self._createErrorAsDict(nStart, nEnd, sLineId, sRuleId, sOption, sMessage, lSugg, sURL, bContext) - def _createErrorForWriter (self, nStart, nLen, sRuleId, sMessage, lSugg, sURL): + def _createErrorForWriter (self, nStart, nLen, sRuleId, sOption, sMessage, lSugg, sURL): xErr = SingleProofreadingError() # uno.createUnoStruct( "com.sun.star.linguistic2.SingleProofreadingError" ) xErr.nErrorStart = nStart xErr.nErrorLength = nLen xErr.nErrorType = PROOFREADING xErr.aRuleIdentifier = sRuleId xErr.aShortComment = sMessage # sMessage.split("|")[0] # in context menu xErr.aFullComment = sMessage # sMessage.split("|")[-1] # in dialog xErr.aSuggestions = tuple(lSugg) #xPropertyLineType = PropertyValue(Name="LineType", Value=5) # DASH or WAVE - #xPropertyLineColor = PropertyValue(Name="LineColor", Value=getRGB("FFAA00")) + xPropertyLineColor = PropertyValue(Name="LineColor", Value=_dOptionsColors.get(sOption, 33023)) if sURL: xPropertyURL = PropertyValue(Name="FullCommentURL", Value=sURL) - xErr.aProperties = (xPropertyURL,) + xErr.aProperties = (xPropertyURL, xPropertyLineColor) else: - xErr.aProperties = () + xErr.aProperties = (xPropertyLineColor,) return xErr def _createErrorAsDict (self, nStart, nEnd, sLineId, sRuleId, sOption, sMessage, lSugg, sURL, bContext): dErr = { "nStart": nStart, "nEnd": nEnd, "sLineId": sLineId, "sRuleId": sRuleId, "sType": sOption if sOption else "notype", + "aColor": _dOptionsColors.get(sOption, [100, 100, 255]), "sMessage": sMessage, "aSuggestions": lSugg, "URL": sURL } if bContext: Index: gc_core/py/lang_core/gc_options.py ================================================================== --- gc_core/py/lang_core/gc_options.py +++ gc_core/py/lang_core/gc_options.py @@ -1,10 +1,12 @@ """ Grammar checker default options """ # generated code, do not edit + +import traceback def getUI (sLang): "returns dictionary of UI labels" if sLang in _dOptLabel: return _dOptLabel[sLang] @@ -11,33 +13,35 @@ return _dOptLabel["fr"] def getOptions (sContext="Python"): "returns dictionary of options" - if sContext in dOpt: - return dOpt[sContext] - return dOpt["Python"] + if sContext in _dOpt: + return _dOpt[sContext] + return _dOpt["Python"] -def getOptionsColors (sContext="Python"): - "returns dictionary of options" - if sContext in dOptColor: - return dOptColor[sContext] - return dOptColor["Python"] +def getOptionsColors (sTheme="Default", sColorType="aRGB"): + "returns dictionary of options colors" + dOptColor = _dOptColor[sTheme] if sTheme in _dOptColor else _dOptColor["Default"] + dColorType = _dColorType[sColorType] if sColorType in _dColorType else _dColorType["aRGB"] + try: + return { sOpt: dColorType[sColor] for sOpt, sColor in dOptColor.items() } + except: + traceback.print_exc() + return {} lStructOpt = ${lStructOpt} -dOpt = { +_dOpt = { "Python": ${dOptPython}, "Server": ${dOptServer}, "Writer": ${dOptWriter} } -dOptColor = { - "Python": ${dOptColorPython}, - "Server": ${dOptColorServer}, - "Writer": ${dOptColorWriter} -} +_dColorType= ${dColorType} + +_dOptColor = ${dOptColor} _dOptLabel = ${dOptLabel} Index: gc_lang/fr/webext/content_scripts/panel_gc.css ================================================================== --- gc_lang/fr/webext/content_scripts/panel_gc.css +++ gc_lang/fr/webext/content_scripts/panel_gc.css @@ -66,11 +66,11 @@ background-color: hsl(0, 50%, 40%); color: hsl(0, 0%, 100%); } -/* +/* TOOLTIP */ img#grammalecte_tooltip_arrow { position: absolute; display: none; @@ -263,40 +263,40 @@ color: hsl(0, 0%, 100%); box-shadow: 0px 0px 0px 3px hsla(0, 50%, 50%, 0.2); } /* elems */ -mark.grammalecte_error_typo, -mark.grammalecte_error_esp, -mark.grammalecte_error_nbsp, -mark.grammalecte_error_eif, -mark.grammalecte_error_maj, -mark.grammalecte_error_virg, -mark.grammalecte_error_tu, -mark.grammalecte_error_num, -mark.grammalecte_error_unit, -mark.grammalecte_error_nf, -mark.grammalecte_error_liga, -mark.grammalecte_error_mapos, +mark.grammalecte_error_typo, +mark.grammalecte_error_esp, +mark.grammalecte_error_nbsp, +mark.grammalecte_error_eif, +mark.grammalecte_error_maj, +mark.grammalecte_error_virg, +mark.grammalecte_error_tu, +mark.grammalecte_error_num, +mark.grammalecte_error_unit, +mark.grammalecte_error_nf, +mark.grammalecte_error_liga, +mark.grammalecte_error_mapos, mark.grammalecte_error_chim { background-color: hsl(30, 70%, 50%); color: hsl(30, 10%, 96%); /*text-decoration: underline wavy hsl(30, 70%, 50%);*/ } -mark.grammalecte_error_typo:hover, -mark.grammalecte_error_esp:hover, -mark.grammalecte_error_nbsp:hover, -mark.grammalecte_error_eif:hover, -mark.grammalecte_error_maj:hover, -mark.grammalecte_error_virg:hover, -mark.grammalecte_error_tu:hover, -mark.grammalecte_error_num:hover, -mark.grammalecte_error_unit:hover, -mark.grammalecte_error_nf:hover, -mark.grammalecte_error_liga:hover, -mark.grammalecte_error_mapos:hover, +mark.grammalecte_error_typo:hover, +mark.grammalecte_error_esp:hover, +mark.grammalecte_error_nbsp:hover, +mark.grammalecte_error_eif:hover, +mark.grammalecte_error_maj:hover, +mark.grammalecte_error_virg:hover, +mark.grammalecte_error_tu:hover, +mark.grammalecte_error_num:hover, +mark.grammalecte_error_unit:hover, +mark.grammalecte_error_nf:hover, +mark.grammalecte_error_liga:hover, +mark.grammalecte_error_mapos:hover, mark.grammalecte_error_chim:hover { background-color: hsl(30, 80%, 45%); color: hsl(30, 10%, 96%); box-shadow: 0px 0px 0px 3px hsla(30, 50%, 50%, 0.2); } @@ -326,68 +326,68 @@ color: hsl(210, 10%, 96%); box-shadow: 0px 0px 0px 3px hsla(210, 50%, 50%, 0.2); } /* elems */ -mark.grammalecte_error_conj, -mark.grammalecte_error_infi, -mark.grammalecte_error_imp, -mark.grammalecte_error_inte, -mark.grammalecte_error_ppas, +mark.grammalecte_error_conj, +mark.grammalecte_error_infi, +mark.grammalecte_error_imp, +mark.grammalecte_error_inte, +mark.grammalecte_error_ppas, mark.grammalecte_error_vmode { background-color: hsl(300, 30%, 40%); color: hsl(300, 10%, 96%); /*text-decoration: underline wavy hsl(300, 40%, 40%);*/ } -mark.grammalecte_error_conj:hover, -mark.grammalecte_error_infi:hover, -mark.grammalecte_error_imp:hover, -mark.grammalecte_error_inte:hover, -mark.grammalecte_error_ppas:hover, +mark.grammalecte_error_conj:hover, +mark.grammalecte_error_infi:hover, +mark.grammalecte_error_imp:hover, +mark.grammalecte_error_inte:hover, +mark.grammalecte_error_ppas:hover, mark.grammalecte_error_vmode:hover { background-color: hsl(300, 40%, 30%); color: hsl(300, 10%, 96%); box-shadow: 0px 0px 0px 3px hsla(300, 50%, 50%, 0.2); } /* elems */ -mark.grammalecte_error_conf, +mark.grammalecte_error_conf, mark.grammalecte_error_ocr { background-color: hsl(270, 40%, 30%); color: hsl(270, 10%, 96%); /*text-decoration: underline wavy hsl(270, 40%, 30%);*/ } -mark.grammalecte_error_conf:hover, +mark.grammalecte_error_conf:hover, mark.grammalecte_error_ocr:hover { background-color: hsl(270, 50%, 20%); color: hsl(270, 10%, 96%); box-shadow: 0px 0px 0px 3px hsla(270, 50%, 50%, 0.2); } /* elems */ -mark.grammalecte_error_bs, -mark.grammalecte_error_pleo, -mark.grammalecte_error_neg, -mark.grammalecte_error_redon1, -mark.grammalecte_error_redon2, -mark.grammalecte_error_mc, -mark.grammalecte_error_date, +mark.grammalecte_error_bs, +mark.grammalecte_error_pleo, +mark.grammalecte_error_neg, +mark.grammalecte_error_redon1, +mark.grammalecte_error_redon2, +mark.grammalecte_error_mc, +mark.grammalecte_error_date, mark.grammalecte_error_notype { background-color: hsl(180, 50%, 40%); color: hsl(180, 10%, 96%); /*text-decoration: underline wavy hsl(180, 50%, 40%);*/ } -mark.grammalecte_error_bs:hover, -mark.grammalecte_error_pleo:hover, -mark.grammalecte_error_neg:hover, -mark.grammalecte_error_redon1:hover, -mark.grammalecte_error_redon2:hover, -mark.grammalecte_error_mc:hover, -mark.grammalecte_error_date:hover, +mark.grammalecte_error_bs:hover, +mark.grammalecte_error_pleo:hover, +mark.grammalecte_error_neg:hover, +mark.grammalecte_error_redon1:hover, +mark.grammalecte_error_redon2:hover, +mark.grammalecte_error_mc:hover, +mark.grammalecte_error_date:hover, mark.grammalecte_error_notype:hover { background-color: hsl(180, 60%, 30%); color: hsl(180, 10%, 96%); box-shadow: 0px 0px 0px 3px hsla(180, 50%, 50%, 0.2); }