]>
Commit | Line | Data |
---|---|---|
9ce192d4 | 1 | // Scintilla source code edit control |
65ec6247 RD |
2 | /** @file LineMarker.cxx |
3 | ** Defines the look of a line marker in the margin . | |
4 | **/ | |
1dcf666d | 5 | // Copyright 1998-2011 by Neil Hodgson <neilh@scintilla.org> |
9ce192d4 RD |
6 | // The License.txt file describes the conditions under which this software may be distributed. |
7 | ||
9e730a78 RD |
8 | #include <string.h> |
9 | ||
1dcf666d RD |
10 | #include <vector> |
11 | #include <map> | |
12 | ||
9ce192d4 RD |
13 | #include "Platform.h" |
14 | ||
15 | #include "Scintilla.h" | |
9e730a78 | 16 | #include "XPM.h" |
9ce192d4 RD |
17 | #include "LineMarker.h" |
18 | ||
7e0c58e9 RD |
19 | #ifdef SCI_NAMESPACE |
20 | using namespace Scintilla; | |
21 | #endif | |
22 | ||
9e730a78 RD |
23 | void LineMarker::SetXPM(const char *textForm) { |
24 | delete pxpm; | |
25 | pxpm = new XPM(textForm); | |
26 | markType = SC_MARK_PIXMAP; | |
27 | } | |
28 | ||
1dcf666d | 29 | void LineMarker::SetXPM(const char *const *linesForm) { |
9e730a78 RD |
30 | delete pxpm; |
31 | pxpm = new XPM(linesForm); | |
32 | markType = SC_MARK_PIXMAP; | |
33 | } | |
34 | ||
1dcf666d RD |
35 | void LineMarker::SetRGBAImage(Point sizeRGBAImage, const unsigned char *pixelsRGBAImage) { |
36 | delete image; | |
37 | image = new RGBAImage(sizeRGBAImage.x, sizeRGBAImage.y, pixelsRGBAImage); | |
38 | markType = SC_MARK_RGBAIMAGE; | |
39 | } | |
40 | ||
41 | static void DrawBox(Surface *surface, int centreX, int centreY, int armSize, ColourDesired fore, ColourDesired back) { | |
65ec6247 RD |
42 | PRectangle rc; |
43 | rc.left = centreX - armSize; | |
44 | rc.top = centreY - armSize; | |
45 | rc.right = centreX + armSize + 1; | |
46 | rc.bottom = centreY + armSize + 1; | |
47 | surface->RectangleDraw(rc, back, fore); | |
48 | } | |
49 | ||
1dcf666d | 50 | static void DrawCircle(Surface *surface, int centreX, int centreY, int armSize, ColourDesired fore, ColourDesired back) { |
65ec6247 RD |
51 | PRectangle rcCircle; |
52 | rcCircle.left = centreX - armSize; | |
53 | rcCircle.top = centreY - armSize; | |
54 | rcCircle.right = centreX + armSize + 1; | |
55 | rcCircle.bottom = centreY + armSize + 1; | |
56 | surface->Ellipse(rcCircle, back, fore); | |
57 | } | |
58 | ||
1dcf666d | 59 | static void DrawPlus(Surface *surface, int centreX, int centreY, int armSize, ColourDesired fore) { |
65ec6247 RD |
60 | PRectangle rcV(centreX, centreY - armSize + 2, centreX + 1, centreY + armSize - 2 + 1); |
61 | surface->FillRectangle(rcV, fore); | |
62 | PRectangle rcH(centreX - armSize + 2, centreY, centreX + armSize - 2 + 1, centreY+1); | |
63 | surface->FillRectangle(rcH, fore); | |
64 | } | |
65 | ||
1dcf666d | 66 | static void DrawMinus(Surface *surface, int centreX, int centreY, int armSize, ColourDesired fore) { |
65ec6247 RD |
67 | PRectangle rcH(centreX - armSize + 2, centreY, centreX + armSize - 2 + 1, centreY+1); |
68 | surface->FillRectangle(rcH, fore); | |
69 | } | |
70 | ||
1dcf666d RD |
71 | void LineMarker::Draw(Surface *surface, PRectangle &rcWhole, Font &fontForCharacter, typeOfFold tFold, int marginStyle) { |
72 | ColourDesired head = back; | |
73 | ColourDesired body = back; | |
74 | ColourDesired tail = back; | |
75 | ||
76 | switch (tFold) { | |
77 | case LineMarker::head : | |
78 | case LineMarker::headWithTail : | |
79 | head = backSelected; | |
80 | tail = backSelected; | |
81 | break; | |
82 | case LineMarker::body : | |
83 | head = backSelected; | |
84 | body = backSelected; | |
85 | break; | |
86 | case LineMarker::tail : | |
87 | body = backSelected; | |
88 | tail = backSelected; | |
89 | break; | |
90 | default : | |
91 | // LineMarker::undefined | |
92 | break; | |
93 | } | |
94 | ||
9e730a78 RD |
95 | if ((markType == SC_MARK_PIXMAP) && (pxpm)) { |
96 | pxpm->Draw(surface, rcWhole); | |
97 | return; | |
98 | } | |
1dcf666d RD |
99 | if ((markType == SC_MARK_RGBAIMAGE) && (image)) { |
100 | // Make rectangle just large enough to fit image centred on centre of rcWhole | |
101 | PRectangle rcImage; | |
102 | rcImage.top = static_cast<int>(((rcWhole.top + rcWhole.bottom) - image->GetHeight()) / 2); | |
103 | rcImage.bottom = rcImage.top + image->GetHeight(); | |
104 | rcImage.left = static_cast<int>(((rcWhole.left + rcWhole.right) - image->GetWidth()) / 2); | |
105 | rcImage.right = rcImage.left + image->GetWidth(); | |
106 | surface->DrawRGBAImage(rcImage, image->GetWidth(), image->GetHeight(), image->Pixels()); | |
107 | return; | |
108 | } | |
65ec6247 RD |
109 | // Restrict most shapes a bit |
110 | PRectangle rc = rcWhole; | |
111 | rc.top++; | |
112 | rc.bottom--; | |
9ce192d4 RD |
113 | int minDim = Platform::Minimum(rc.Width(), rc.Height()); |
114 | minDim--; // Ensure does not go beyond edge | |
115 | int centreX = (rc.right + rc.left) / 2; | |
116 | int centreY = (rc.bottom + rc.top) / 2; | |
117 | int dimOn2 = minDim / 2; | |
118 | int dimOn4 = minDim / 4; | |
65ec6247 RD |
119 | int blobSize = dimOn2-1; |
120 | int armSize = dimOn2-2; | |
1dcf666d RD |
121 | if (marginStyle == SC_MARGIN_NUMBER || marginStyle == SC_MARGIN_TEXT || marginStyle == SC_MARGIN_RTEXT) { |
122 | // On textual margins move marker to the left to try to avoid overlapping the text | |
9ce192d4 RD |
123 | centreX = rc.left + dimOn2 + 1; |
124 | } | |
125 | if (markType == SC_MARK_ROUNDRECT) { | |
126 | PRectangle rcRounded = rc; | |
127 | rcRounded.left = rc.left + 1; | |
128 | rcRounded.right = rc.right - 1; | |
1dcf666d | 129 | surface->RoundedRectangle(rcRounded, fore, back); |
9ce192d4 RD |
130 | } else if (markType == SC_MARK_CIRCLE) { |
131 | PRectangle rcCircle; | |
132 | rcCircle.left = centreX - dimOn2; | |
133 | rcCircle.top = centreY - dimOn2; | |
134 | rcCircle.right = centreX + dimOn2; | |
135 | rcCircle.bottom = centreY + dimOn2; | |
1dcf666d | 136 | surface->Ellipse(rcCircle, fore, back); |
9ce192d4 RD |
137 | } else if (markType == SC_MARK_ARROW) { |
138 | Point pts[] = { | |
139 | Point(centreX - dimOn4, centreY - dimOn2), | |
140 | Point(centreX - dimOn4, centreY + dimOn2), | |
141 | Point(centreX + dimOn2 - dimOn4, centreY), | |
142 | }; | |
143 | surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]), | |
1dcf666d | 144 | fore, back); |
9ce192d4 RD |
145 | |
146 | } else if (markType == SC_MARK_ARROWDOWN) { | |
147 | Point pts[] = { | |
148 | Point(centreX - dimOn2, centreY - dimOn4), | |
149 | Point(centreX + dimOn2, centreY - dimOn4), | |
150 | Point(centreX, centreY + dimOn2 - dimOn4), | |
151 | }; | |
152 | surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]), | |
1dcf666d | 153 | fore, back); |
9ce192d4 RD |
154 | |
155 | } else if (markType == SC_MARK_PLUS) { | |
9ce192d4 RD |
156 | Point pts[] = { |
157 | Point(centreX - armSize, centreY - 1), | |
158 | Point(centreX - 1, centreY - 1), | |
159 | Point(centreX - 1, centreY - armSize), | |
160 | Point(centreX + 1, centreY - armSize), | |
161 | Point(centreX + 1, centreY - 1), | |
162 | Point(centreX + armSize, centreY -1), | |
163 | Point(centreX + armSize, centreY +1), | |
164 | Point(centreX + 1, centreY + 1), | |
165 | Point(centreX + 1, centreY + armSize), | |
166 | Point(centreX - 1, centreY + armSize), | |
167 | Point(centreX - 1, centreY + 1), | |
168 | Point(centreX - armSize, centreY + 1), | |
169 | }; | |
170 | surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]), | |
1dcf666d | 171 | fore, back); |
9ce192d4 RD |
172 | |
173 | } else if (markType == SC_MARK_MINUS) { | |
9ce192d4 RD |
174 | Point pts[] = { |
175 | Point(centreX - armSize, centreY - 1), | |
176 | Point(centreX + armSize, centreY -1), | |
177 | Point(centreX + armSize, centreY +1), | |
178 | Point(centreX - armSize, centreY + 1), | |
179 | }; | |
9ce192d4 | 180 | surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]), |
1dcf666d | 181 | fore, back); |
9ce192d4 RD |
182 | |
183 | } else if (markType == SC_MARK_SMALLRECT) { | |
184 | PRectangle rcSmall; | |
185 | rcSmall.left = rc.left + 1; | |
186 | rcSmall.top = rc.top + 2; | |
187 | rcSmall.right = rc.right - 1; | |
188 | rcSmall.bottom = rc.bottom - 2; | |
1dcf666d | 189 | surface->RectangleDraw(rcSmall, fore, back); |
9e730a78 | 190 | |
1dcf666d | 191 | } else if (markType == SC_MARK_EMPTY || markType == SC_MARK_BACKGROUND || |
9e96e16f | 192 | markType == SC_MARK_UNDERLINE || markType == SC_MARK_AVAILABLE) { |
9ce192d4 | 193 | // An invisible marker so don't draw anything |
9e730a78 | 194 | |
65ec6247 | 195 | } else if (markType == SC_MARK_VLINE) { |
1dcf666d | 196 | surface->PenColour(body); |
65ec6247 RD |
197 | surface->MoveTo(centreX, rcWhole.top); |
198 | surface->LineTo(centreX, rcWhole.bottom); | |
9e730a78 | 199 | |
65ec6247 | 200 | } else if (markType == SC_MARK_LCORNER) { |
1dcf666d | 201 | surface->PenColour(tail); |
65ec6247 | 202 | surface->MoveTo(centreX, rcWhole.top); |
1dcf666d RD |
203 | surface->LineTo(centreX, centreY); |
204 | surface->LineTo(rc.right - 1, centreY); | |
9e730a78 | 205 | |
65ec6247 | 206 | } else if (markType == SC_MARK_TCORNER) { |
1dcf666d RD |
207 | surface->PenColour(tail); |
208 | surface->MoveTo(centreX, centreY); | |
209 | surface->LineTo(rc.right - 1, centreY); | |
210 | ||
211 | surface->PenColour(body); | |
65ec6247 | 212 | surface->MoveTo(centreX, rcWhole.top); |
1dcf666d RD |
213 | surface->LineTo(centreX, centreY + 1); |
214 | ||
215 | surface->PenColour(head); | |
65ec6247 | 216 | surface->LineTo(centreX, rcWhole.bottom); |
9e730a78 | 217 | |
65ec6247 | 218 | } else if (markType == SC_MARK_LCORNERCURVE) { |
1dcf666d | 219 | surface->PenColour(tail); |
65ec6247 | 220 | surface->MoveTo(centreX, rcWhole.top); |
1dcf666d RD |
221 | surface->LineTo(centreX, centreY-3); |
222 | surface->LineTo(centreX+3, centreY); | |
223 | surface->LineTo(rc.right - 1, centreY); | |
9e730a78 | 224 | |
65ec6247 | 225 | } else if (markType == SC_MARK_TCORNERCURVE) { |
1dcf666d RD |
226 | surface->PenColour(tail); |
227 | surface->MoveTo(centreX, centreY-3); | |
228 | surface->LineTo(centreX+3, centreY); | |
229 | surface->LineTo(rc.right - 1, centreY); | |
230 | ||
231 | surface->PenColour(body); | |
65ec6247 | 232 | surface->MoveTo(centreX, rcWhole.top); |
1dcf666d | 233 | surface->LineTo(centreX, centreY-2); |
9e730a78 | 234 | |
1dcf666d RD |
235 | surface->PenColour(head); |
236 | surface->LineTo(centreX, rcWhole.bottom); | |
9e730a78 | 237 | |
65ec6247 | 238 | } else if (markType == SC_MARK_BOXPLUS) { |
1dcf666d RD |
239 | DrawBox(surface, centreX, centreY, blobSize, fore, head); |
240 | DrawPlus(surface, centreX, centreY, blobSize, tail); | |
9e730a78 | 241 | |
65ec6247 | 242 | } else if (markType == SC_MARK_BOXPLUSCONNECTED) { |
1dcf666d RD |
243 | if (tFold == LineMarker::headWithTail) |
244 | surface->PenColour(tail); | |
245 | else | |
246 | surface->PenColour(body); | |
65ec6247 RD |
247 | surface->MoveTo(centreX, centreY + blobSize); |
248 | surface->LineTo(centreX, rcWhole.bottom); | |
9e730a78 | 249 | |
1dcf666d | 250 | surface->PenColour(body); |
65ec6247 RD |
251 | surface->MoveTo(centreX, rcWhole.top); |
252 | surface->LineTo(centreX, centreY - blobSize); | |
9e730a78 | 253 | |
1dcf666d RD |
254 | DrawBox(surface, centreX, centreY, blobSize, fore, head); |
255 | DrawPlus(surface, centreX, centreY, blobSize, tail); | |
256 | ||
257 | if (tFold == LineMarker::body) { | |
258 | surface->PenColour(tail); | |
259 | surface->MoveTo(centreX + 1, centreY + blobSize); | |
260 | surface->LineTo(centreX + blobSize + 1, centreY + blobSize); | |
261 | ||
262 | surface->MoveTo(centreX + blobSize, centreY + blobSize); | |
263 | surface->LineTo(centreX + blobSize, centreY - blobSize); | |
264 | ||
265 | surface->MoveTo(centreX + 1, centreY - blobSize); | |
266 | surface->LineTo(centreX + blobSize + 1, centreY - blobSize); | |
267 | } | |
65ec6247 | 268 | } else if (markType == SC_MARK_BOXMINUS) { |
1dcf666d RD |
269 | DrawBox(surface, centreX, centreY, blobSize, fore, head); |
270 | DrawMinus(surface, centreX, centreY, blobSize, tail); | |
9e730a78 | 271 | |
1dcf666d | 272 | surface->PenColour(head); |
65ec6247 RD |
273 | surface->MoveTo(centreX, centreY + blobSize); |
274 | surface->LineTo(centreX, rcWhole.bottom); | |
9e730a78 | 275 | |
65ec6247 | 276 | } else if (markType == SC_MARK_BOXMINUSCONNECTED) { |
1dcf666d RD |
277 | DrawBox(surface, centreX, centreY, blobSize, fore, head); |
278 | DrawMinus(surface, centreX, centreY, blobSize, tail); | |
9e730a78 | 279 | |
1dcf666d | 280 | surface->PenColour(head); |
65ec6247 RD |
281 | surface->MoveTo(centreX, centreY + blobSize); |
282 | surface->LineTo(centreX, rcWhole.bottom); | |
9e730a78 | 283 | |
1dcf666d | 284 | surface->PenColour(body); |
65ec6247 RD |
285 | surface->MoveTo(centreX, rcWhole.top); |
286 | surface->LineTo(centreX, centreY - blobSize); | |
9e730a78 | 287 | |
1dcf666d RD |
288 | if (tFold == LineMarker::body) { |
289 | surface->PenColour(tail); | |
290 | surface->MoveTo(centreX + 1, centreY + blobSize); | |
291 | surface->LineTo(centreX + blobSize + 1, centreY + blobSize); | |
292 | ||
293 | surface->MoveTo(centreX + blobSize, centreY + blobSize); | |
294 | surface->LineTo(centreX + blobSize, centreY - blobSize); | |
295 | ||
296 | surface->MoveTo(centreX + 1, centreY - blobSize); | |
297 | surface->LineTo(centreX + blobSize + 1, centreY - blobSize); | |
298 | } | |
65ec6247 | 299 | } else if (markType == SC_MARK_CIRCLEPLUS) { |
1dcf666d RD |
300 | DrawCircle(surface, centreX, centreY, blobSize, fore, head); |
301 | DrawPlus(surface, centreX, centreY, blobSize, tail); | |
9e730a78 | 302 | |
65ec6247 | 303 | } else if (markType == SC_MARK_CIRCLEPLUSCONNECTED) { |
1dcf666d RD |
304 | if (tFold == LineMarker::headWithTail) |
305 | surface->PenColour(tail); | |
306 | else | |
307 | surface->PenColour(body); | |
65ec6247 RD |
308 | surface->MoveTo(centreX, centreY + blobSize); |
309 | surface->LineTo(centreX, rcWhole.bottom); | |
9e730a78 | 310 | |
1dcf666d | 311 | surface->PenColour(body); |
65ec6247 RD |
312 | surface->MoveTo(centreX, rcWhole.top); |
313 | surface->LineTo(centreX, centreY - blobSize); | |
9e730a78 | 314 | |
1dcf666d RD |
315 | DrawCircle(surface, centreX, centreY, blobSize, fore, head); |
316 | DrawPlus(surface, centreX, centreY, blobSize, tail); | |
317 | ||
65ec6247 | 318 | } else if (markType == SC_MARK_CIRCLEMINUS) { |
1dcf666d RD |
319 | DrawCircle(surface, centreX, centreY, blobSize, fore, head); |
320 | DrawMinus(surface, centreX, centreY, blobSize, tail); | |
9e730a78 | 321 | |
1dcf666d | 322 | surface->PenColour(head); |
65ec6247 RD |
323 | surface->MoveTo(centreX, centreY + blobSize); |
324 | surface->LineTo(centreX, rcWhole.bottom); | |
9e730a78 | 325 | |
65ec6247 | 326 | } else if (markType == SC_MARK_CIRCLEMINUSCONNECTED) { |
1dcf666d RD |
327 | DrawCircle(surface, centreX, centreY, blobSize, fore, head); |
328 | DrawMinus(surface, centreX, centreY, blobSize, tail); | |
9e730a78 | 329 | |
1dcf666d | 330 | surface->PenColour(head); |
65ec6247 RD |
331 | surface->MoveTo(centreX, centreY + blobSize); |
332 | surface->LineTo(centreX, rcWhole.bottom); | |
9e730a78 | 333 | |
1dcf666d | 334 | surface->PenColour(body); |
65ec6247 RD |
335 | surface->MoveTo(centreX, rcWhole.top); |
336 | surface->LineTo(centreX, centreY - blobSize); | |
9e730a78 | 337 | |
b8b0e402 RD |
338 | } else if (markType >= SC_MARK_CHARACTER) { |
339 | char character[1]; | |
340 | character[0] = static_cast<char>(markType - SC_MARK_CHARACTER); | |
1dcf666d | 341 | XYPOSITION width = surface->WidthText(fontForCharacter, character, 1); |
b8b0e402 RD |
342 | rc.left += (rc.Width() - width) / 2; |
343 | rc.right = rc.left + width; | |
9e730a78 | 344 | surface->DrawTextClipped(rc, fontForCharacter, rc.bottom - 2, |
1dcf666d | 345 | character, 1, fore, back); |
b8b0e402 | 346 | |
f114b858 RD |
347 | } else if (markType == SC_MARK_DOTDOTDOT) { |
348 | int right = centreX - 6; | |
349 | for (int b=0; b<3; b++) { | |
350 | PRectangle rcBlob(right, rc.bottom - 4, right + 2, rc.bottom-2); | |
1dcf666d | 351 | surface->FillRectangle(rcBlob, fore); |
f114b858 RD |
352 | right += 5; |
353 | } | |
354 | } else if (markType == SC_MARK_ARROWS) { | |
1dcf666d | 355 | surface->PenColour(fore); |
f114b858 RD |
356 | int right = centreX - 2; |
357 | for (int b=0; b<3; b++) { | |
358 | surface->MoveTo(right - 4, centreY - 4); | |
359 | surface->LineTo(right, centreY); | |
360 | surface->LineTo(right - 5, centreY + 5); | |
361 | right += 4; | |
362 | } | |
1e9bafca | 363 | } else if (markType == SC_MARK_SHORTARROW) { |
9ce192d4 RD |
364 | Point pts[] = { |
365 | Point(centreX, centreY + dimOn2), | |
366 | Point(centreX + dimOn2, centreY), | |
367 | Point(centreX, centreY - dimOn2), | |
368 | Point(centreX, centreY - dimOn4), | |
369 | Point(centreX - dimOn4, centreY - dimOn4), | |
370 | Point(centreX - dimOn4, centreY + dimOn4), | |
371 | Point(centreX, centreY + dimOn4), | |
372 | Point(centreX, centreY + dimOn2), | |
373 | }; | |
374 | surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]), | |
1dcf666d | 375 | fore, back); |
9e96e16f RD |
376 | } else if (markType == SC_MARK_LEFTRECT) { |
377 | PRectangle rcLeft = rcWhole; | |
378 | rcLeft.right = rcLeft.left + 4; | |
1dcf666d | 379 | surface->FillRectangle(rcLeft, back); |
1e9bafca | 380 | } else { // SC_MARK_FULLRECT |
1dcf666d | 381 | surface->FillRectangle(rcWhole, back); |
9ce192d4 RD |
382 | } |
383 | } |