]> git.saurik.com Git - wxWidgets.git/blame - src/stc/scintilla/src/LineMarker.cxx
wxMessageBox off the main thread lost result code.
[wxWidgets.git] / src / stc / scintilla / src / LineMarker.cxx
CommitLineData
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
20using namespace Scintilla;
21#endif
22
9e730a78
RD
23void LineMarker::SetXPM(const char *textForm) {
24 delete pxpm;
25 pxpm = new XPM(textForm);
26 markType = SC_MARK_PIXMAP;
27}
28
1dcf666d 29void 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
35void 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
41static 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 50static 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 59static 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 66static 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
71void 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}