|
1 # -*- coding: utf-8 -*- |
|
2 |
|
3 # Copyright (c) 2003 - 2019 Detlev Offenbach <detlev@die-offenbachs.de> |
|
4 # |
|
5 |
|
6 """ |
|
7 Module implementing the lexer mixin class. |
|
8 """ |
|
9 |
|
10 from __future__ import unicode_literals |
|
11 |
|
12 import copy |
|
13 |
|
14 from PyQt5.QtGui import QColor |
|
15 |
|
16 from .Lexer import Lexer |
|
17 |
|
18 import Preferences |
|
19 |
|
20 |
|
21 class SubstyledLexer(Lexer): |
|
22 """ |
|
23 Class to implement the sub-styled lexer mixin class. |
|
24 """ |
|
25 def __init__(self): |
|
26 """ |
|
27 Constructor |
|
28 """ |
|
29 super(SubstyledLexer, self).__init__() |
|
30 |
|
31 self.baseStyles = [] # list of style numbers, that support |
|
32 # sub-styling |
|
33 self.defaultSubStyles = {} |
|
34 # dictionary with sub-styling data |
|
35 # main key: base style number, value : dictionary with |
|
36 # 'SubStyleLength': int |
|
37 # 'SubStyles': list of dict with |
|
38 # 'Description': string containing a short description |
|
39 # 'Words': string of whitespace separated words to be styled |
|
40 # 'Style': dictionary with styling data (only difference to the |
|
41 # base style is required |
|
42 # 'fore': foreground color (int containing RGB values) |
|
43 # 'paper': background color (int containing RGB values) |
|
44 # 'eolfill': fill to eol (bool) |
|
45 # 'font_family': font family (str) |
|
46 # 'font_size: point size (int) |
|
47 # 'font_bold: bold font (bool) |
|
48 # 'font_italic: italic font (bool) |
|
49 # 'font_underline: underlined font (bool) |
|
50 |
|
51 self.subStyles = {} |
|
52 self.__subStylesInitialized = False |
|
53 |
|
54 def loadSubstyles(self): |
|
55 """ |
|
56 Public method to load the sub-styles from the settings file |
|
57 """ |
|
58 settings = Preferences.Prefs.settings |
|
59 |
|
60 self.loadDefaultSubStyles() |
|
61 |
|
62 for baseStyle in self.baseStyles: |
|
63 key = "Scintilla/{0}/style{1}/SubStyleLength".format( |
|
64 self.language(), baseStyle) |
|
65 if settings.contains(key): |
|
66 subStyleLength = int(settings.value(key), 0) |
|
67 self.subStyles[baseStyle] = {} |
|
68 self.subStyles[baseStyle]["SubStyleLength"] = subStyleLength |
|
69 if subStyleLength: |
|
70 self.subStyles[baseStyle]["SubStyles"] = [] |
|
71 for subStyle in range(subStyleLength): |
|
72 baseKey = "Scintilla/{0}/style{1}/substyle{2}/".format( |
|
73 self.language(), baseStyle, subStyle) |
|
74 subStyleData = {} |
|
75 subStyleData["Description"] = settings.value( |
|
76 baseKey + "Description", "") |
|
77 subStyleData["Words"] = settings.value( |
|
78 baseKey + "Words", "") |
|
79 style = {} |
|
80 |
|
81 key = baseKey + "fore" |
|
82 if settings.contains(key): |
|
83 style["fore"] = int(settings.value(key)) |
|
84 key = baseKey + "paper" |
|
85 if settings.contains(key): |
|
86 style["paper"] = int(settings.value(key)) |
|
87 key = baseKey + "eolfill" |
|
88 if settings.contains(key): |
|
89 style["eolfill"] = Preferences.toBool( |
|
90 settings.value(key)) |
|
91 key = baseKey + "font_family" |
|
92 if settings.contains(key): |
|
93 style["font_family"] = settings.value(key) |
|
94 key = baseKey + "font_size" |
|
95 if settings.contains(key): |
|
96 style["font_size"] = int(settings.value(key)) |
|
97 key = baseKey + "font_bold" |
|
98 if settings.contains(key): |
|
99 style["font_bold"] = Preferences.toBool( |
|
100 settings.value(key)) |
|
101 key = baseKey + "font_italic" |
|
102 if settings.contains(key): |
|
103 style["font_italic"] = Preferences.toBool( |
|
104 settings.value(key)) |
|
105 key = baseKey + "font_underline" |
|
106 if settings.contains(key): |
|
107 style["font_underline"] = Preferences.toBool( |
|
108 settings.value(key)) |
|
109 |
|
110 subStyleData["Style"] = style |
|
111 |
|
112 def loadDefaultSubStyles(self): |
|
113 """ |
|
114 Public method to load the default sub-style definitions. |
|
115 """ |
|
116 self.subStyles = copy.deepcopy(self.defaultSubStyles) |
|
117 |
|
118 def readSubstyles(self, editor): |
|
119 """ |
|
120 Public method to load the sub-styles and configure the editor. |
|
121 |
|
122 @param editor reference to the editor object |
|
123 @type QsciScintilla |
|
124 """ |
|
125 subStyleBasesLength = editor.SendScintilla( |
|
126 editor.SCI_GETSUBSTYLEBASES, 0, None) |
|
127 if not subStyleBasesLength: |
|
128 # lexer does not support sub-styling |
|
129 return |
|
130 |
|
131 self.loadSubstyles() |
|
132 |
|
133 # free existing sub-styles first |
|
134 editor.SendScintilla(editor.SCI_FREESUBSTYLES) |
|
135 subStyleBases = b"\00" * (subStyleBasesLength + 1) |
|
136 editor.SendScintilla(editor.SCI_GETSUBSTYLEBASES, 0, subStyleBases) |
|
137 distanceToSecondary = editor.SendScintilla( |
|
138 editor.SCI_DISTANCETOSECONDARYSTYLES) |
|
139 |
|
140 subStyleBases = [b for b in bytearray(subStyleBases[:-1])] |
|
141 if distanceToSecondary: |
|
142 subStyleBases.extend(b + distanceToSecondary for b in subStyleBases[:]) |
|
143 for baseStyleNo in subStyleBases: |
|
144 if baseStyleNo in self.subStyles: |
|
145 subStylesData = self.subStyles[baseStyleNo] |
|
146 subStyleLength = subStylesData["SubStyleLength"] |
|
147 subStyleStart = editor.SendScintilla( |
|
148 editor.SCI_ALLOCATESUBSTYLES, baseStyleNo, subStyleLength) |
|
149 if subStyleStart < 0: |
|
150 subStyleLength = 0 |
|
151 for subStyleIndex in range(subStyleLength): |
|
152 subStyle = subStylesData["SubStyles"][subStyleIndex] |
|
153 # set the words |
|
154 editor.SendScintilla( |
|
155 editor.SCI_SETIDENTIFIERS, |
|
156 subStyleStart + subStyleIndex, |
|
157 subStyle["Words"].encode()) |
|
158 |
|
159 # set the style |
|
160 styleNo = subStyleStart + subStyleIndex |
|
161 style = subStyle["Style"] |
|
162 if "fore" in style: |
|
163 color = QColor( |
|
164 style["fore"] >> 16 & 0xff, |
|
165 style["fore"] >> 8 & 0xff, |
|
166 style["fore"] & 0xff, |
|
167 ) |
|
168 else: |
|
169 color = self.color(baseStyleNo) |
|
170 self.setColor(color, styleNo) |
|
171 if "paper" in style: |
|
172 color = QColor( |
|
173 style["paper"] >> 16 & 0xff, |
|
174 style["paper"] >> 8 & 0xff, |
|
175 style["paper"] & 0xff, |
|
176 ) |
|
177 else: |
|
178 color = self.paper(baseStyleNo) |
|
179 self.setPaper(color, styleNo) |
|
180 if "eolfill" in style: |
|
181 eolFill = style["eolFill"] |
|
182 else: |
|
183 eolFill = self.eolFill(baseStyleNo) |
|
184 self.setEolFill(eolFill, styleNo) |
|
185 font = self.font(baseStyleNo) |
|
186 if "font_family" in style: |
|
187 font.setFamily(style["font_family"]) |
|
188 if "font_size" in style: |
|
189 font.setPointSize(style["font_size"]) |
|
190 if "font_bold" in style: |
|
191 font.setBold(style["font_bold"]) |
|
192 if "font_italic" in style: |
|
193 font.setItalic(style["font_italic"]) |
|
194 if "font_underline" in style: |
|
195 font.setUnderline(style["font_underline"]) |
|
196 self.setFont(font, styleNo) |
|
197 |
|
198 def writeSubstyles(self): |
|
199 """ |
|
200 Public method to save the sub-styles. |
|
201 """ |
|
202 |
|
203 def hasSubStyles(self): |
|
204 """ |
|
205 Public method to indicate the support of sub-styles. |
|
206 |
|
207 @return flag indicating sub-styling support |
|
208 @rtype bool |
|
209 """ |
|
210 return True |
|
211 |
|
212 def setSubstyleDescription(self, description, style, substyle): |
|
213 """ |
|
214 |
|
215 """ |
|
216 |
|
217 def substyleDescription(self, style, substyle): |
|
218 """ |
|
219 |
|
220 """ |
|
221 |
|
222 def setSubstyleColor(self, color, style, substyle): |
|
223 """ |
|
224 |
|
225 """ |
|
226 |
|
227 def substyleColor(self, style, substyle): |
|
228 """ |
|
229 |
|
230 """ |
|
231 |
|
232 def setSubstylePaper(self, color, style, substyle): |
|
233 """ |
|
234 |
|
235 """ |
|
236 |
|
237 def substylePaper(self, style, substyle): |
|
238 """ |
|
239 |
|
240 """ |
|
241 |
|
242 def setSubstyleEolFill(self, eolFill, style, substyle): |
|
243 """ |
|
244 |
|
245 """ |
|
246 |
|
247 def substyleEolFill(self, style, substyle): |
|
248 """ |
|
249 |
|
250 """ |
|
251 |
|
252 def setSubstyleFont(self, font, style, substyle): |
|
253 """ |
|
254 |
|
255 """ |
|
256 |
|
257 def substyleFont(self, style, substyle): |
|
258 """ |
|
259 |
|
260 """ |
|
261 |
|
262 def substyleDefaultDescription(self, style, substyle): |
|
263 """ |
|
264 |
|
265 """ |
|
266 |
|
267 def substyleDefaultColor(self, style, substyle): |
|
268 """ |
|
269 |
|
270 """ |
|
271 |
|
272 def substyleDefaultPaper(self, style, substyle): |
|
273 """ |
|
274 |
|
275 """ |
|
276 |
|
277 def substyleDefaultEolFill(self, style, substyle): |
|
278 """ |
|
279 |
|
280 """ |
|
281 |
|
282 def substyleDefaultFont(self, style, substyle): |
|
283 """ |
|
284 |
|
285 """ |