Support more folding icon styles: arrows, +/- and no lines
[geany-mirror.git] / scintilla / LineMarker.cxx
blob0bfd479384aa872a99cea1d6ffe95974d54e8b7f
1 // Scintilla source code edit control
2 /** @file LineMarker.cxx
3 ** Defines the look of a line marker in the margin .
4 **/
5 // Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
6 // The License.txt file describes the conditions under which this software may be distributed.
8 #include <string.h>
10 #include "Platform.h"
12 #include "Scintilla.h"
13 #include "XPM.h"
14 #include "LineMarker.h"
16 #ifdef SCI_NAMESPACE
17 using namespace Scintilla;
18 #endif
20 void LineMarker::RefreshColourPalette(Palette &pal, bool want) {
21 pal.WantFind(fore, want);
22 pal.WantFind(back, want);
23 if (pxpm) {
24 pxpm->RefreshColourPalette(pal, want);
28 void LineMarker::SetXPM(const char *textForm) {
29 delete pxpm;
30 pxpm = new XPM(textForm);
31 markType = SC_MARK_PIXMAP;
34 void LineMarker::SetXPM(const char * const *linesForm) {
35 delete pxpm;
36 pxpm = new XPM(linesForm);
37 markType = SC_MARK_PIXMAP;
40 static void DrawBox(Surface *surface, int centreX, int centreY, int armSize, ColourAllocated fore, ColourAllocated back) {
41 PRectangle rc;
42 rc.left = centreX - armSize;
43 rc.top = centreY - armSize;
44 rc.right = centreX + armSize + 1;
45 rc.bottom = centreY + armSize + 1;
46 surface->RectangleDraw(rc, back, fore);
49 static void DrawCircle(Surface *surface, int centreX, int centreY, int armSize, ColourAllocated fore, ColourAllocated back) {
50 PRectangle rcCircle;
51 rcCircle.left = centreX - armSize;
52 rcCircle.top = centreY - armSize;
53 rcCircle.right = centreX + armSize + 1;
54 rcCircle.bottom = centreY + armSize + 1;
55 surface->Ellipse(rcCircle, back, fore);
58 static void DrawPlus(Surface *surface, int centreX, int centreY, int armSize, ColourAllocated fore) {
59 PRectangle rcV(centreX, centreY - armSize + 2, centreX + 1, centreY + armSize - 2 + 1);
60 surface->FillRectangle(rcV, fore);
61 PRectangle rcH(centreX - armSize + 2, centreY, centreX + armSize - 2 + 1, centreY+1);
62 surface->FillRectangle(rcH, fore);
65 static void DrawMinus(Surface *surface, int centreX, int centreY, int armSize, ColourAllocated fore) {
66 PRectangle rcH(centreX - armSize + 2, centreY, centreX + armSize - 2 + 1, centreY+1);
67 surface->FillRectangle(rcH, fore);
70 void LineMarker::Draw(Surface *surface, PRectangle &rcWhole, Font &fontForCharacter) {
71 if ((markType == SC_MARK_PIXMAP) && (pxpm)) {
72 pxpm->Draw(surface, rcWhole);
73 return;
75 // Restrict most shapes a bit
76 PRectangle rc = rcWhole;
77 rc.top++;
78 rc.bottom--;
79 int minDim = Platform::Minimum(rc.Width(), rc.Height());
80 minDim--; // Ensure does not go beyond edge
81 int centreX = (rc.right + rc.left) / 2;
82 int centreY = (rc.bottom + rc.top) / 2;
83 int dimOn2 = minDim / 2;
84 int dimOn4 = minDim / 4;
85 int blobSize = dimOn2-1;
86 int armSize = dimOn2-2;
87 if (rc.Width() > (rc.Height() * 2)) {
88 // Wide column is line number so move to left to try to avoid overlapping number
89 centreX = rc.left + dimOn2 + 1;
91 if (markType == SC_MARK_ROUNDRECT) {
92 PRectangle rcRounded = rc;
93 rcRounded.left = rc.left + 1;
94 rcRounded.right = rc.right - 1;
95 surface->RoundedRectangle(rcRounded, fore.allocated, back.allocated);
96 } else if (markType == SC_MARK_CIRCLE) {
97 PRectangle rcCircle;
98 rcCircle.left = centreX - dimOn2;
99 rcCircle.top = centreY - dimOn2;
100 rcCircle.right = centreX + dimOn2;
101 rcCircle.bottom = centreY + dimOn2;
102 surface->Ellipse(rcCircle, fore.allocated, back.allocated);
103 } else if (markType == SC_MARK_ARROW) {
104 Point pts[] = {
105 Point(centreX - dimOn4, centreY - dimOn2),
106 Point(centreX - dimOn4, centreY + dimOn2),
107 Point(centreX + dimOn2 - dimOn4, centreY),
109 surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]),
110 fore.allocated, back.allocated);
112 } else if (markType == SC_MARK_ARROWDOWN) {
113 Point pts[] = {
114 Point(centreX - dimOn2, centreY - dimOn4),
115 Point(centreX + dimOn2, centreY - dimOn4),
116 Point(centreX, centreY + dimOn2 - dimOn4),
118 surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]),
119 fore.allocated, back.allocated);
121 } else if (markType == SC_MARK_PLUS) {
122 Point pts[] = {
123 Point(centreX - armSize, centreY - 1),
124 Point(centreX - 1, centreY - 1),
125 Point(centreX - 1, centreY - armSize),
126 Point(centreX + 1, centreY - armSize),
127 Point(centreX + 1, centreY - 1),
128 Point(centreX + armSize, centreY -1),
129 Point(centreX + armSize, centreY +1),
130 Point(centreX + 1, centreY + 1),
131 Point(centreX + 1, centreY + armSize),
132 Point(centreX - 1, centreY + armSize),
133 Point(centreX - 1, centreY + 1),
134 Point(centreX - armSize, centreY + 1),
136 surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]),
137 fore.allocated, back.allocated);
139 } else if (markType == SC_MARK_MINUS) {
140 Point pts[] = {
141 Point(centreX - armSize, centreY - 1),
142 Point(centreX + armSize, centreY -1),
143 Point(centreX + armSize, centreY +1),
144 Point(centreX - armSize, centreY + 1),
146 surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]),
147 fore.allocated, back.allocated);
149 } else if (markType == SC_MARK_SMALLRECT) {
150 PRectangle rcSmall;
151 rcSmall.left = rc.left + 1;
152 rcSmall.top = rc.top + 2;
153 rcSmall.right = rc.right - 1;
154 rcSmall.bottom = rc.bottom - 2;
155 surface->RectangleDraw(rcSmall, fore.allocated, back.allocated);
157 } else if (markType == SC_MARK_EMPTY || markType == SC_MARK_BACKGROUND ||
158 markType == SC_MARK_UNDERLINE || markType == SC_MARK_AVAILABLE) {
159 // An invisible marker so don't draw anything
161 } else if (markType == SC_MARK_VLINE) {
162 surface->PenColour(back.allocated);
163 surface->MoveTo(centreX, rcWhole.top);
164 surface->LineTo(centreX, rcWhole.bottom);
166 } else if (markType == SC_MARK_LCORNER) {
167 surface->PenColour(back.allocated);
168 surface->MoveTo(centreX, rcWhole.top);
169 surface->LineTo(centreX, rc.top + dimOn2);
170 surface->LineTo(rc.right - 2, rc.top + dimOn2);
172 } else if (markType == SC_MARK_TCORNER) {
173 surface->PenColour(back.allocated);
174 surface->MoveTo(centreX, rcWhole.top);
175 surface->LineTo(centreX, rcWhole.bottom);
176 surface->MoveTo(centreX, rc.top + dimOn2);
177 surface->LineTo(rc.right - 2, rc.top + dimOn2);
179 } else if (markType == SC_MARK_LCORNERCURVE) {
180 surface->PenColour(back.allocated);
181 surface->MoveTo(centreX, rcWhole.top);
182 surface->LineTo(centreX, rc.top + dimOn2-3);
183 surface->LineTo(centreX+3, rc.top + dimOn2);
184 surface->LineTo(rc.right - 1, rc.top + dimOn2);
186 } else if (markType == SC_MARK_TCORNERCURVE) {
187 surface->PenColour(back.allocated);
188 surface->MoveTo(centreX, rcWhole.top);
189 surface->LineTo(centreX, rcWhole.bottom);
191 surface->MoveTo(centreX, rc.top + dimOn2-3);
192 surface->LineTo(centreX+3, rc.top + dimOn2);
193 surface->LineTo(rc.right - 1, rc.top + dimOn2);
195 } else if (markType == SC_MARK_BOXPLUS) {
196 surface->PenColour(back.allocated);
197 DrawBox(surface, centreX, centreY, blobSize, fore.allocated, back.allocated);
198 DrawPlus(surface, centreX, centreY, blobSize, back.allocated);
200 } else if (markType == SC_MARK_BOXPLUSCONNECTED) {
201 surface->PenColour(back.allocated);
202 DrawBox(surface, centreX, centreY, blobSize, fore.allocated, back.allocated);
203 DrawPlus(surface, centreX, centreY, blobSize, back.allocated);
205 surface->MoveTo(centreX, centreY + blobSize);
206 surface->LineTo(centreX, rcWhole.bottom);
208 surface->MoveTo(centreX, rcWhole.top);
209 surface->LineTo(centreX, centreY - blobSize);
211 } else if (markType == SC_MARK_BOXMINUS) {
212 surface->PenColour(back.allocated);
213 DrawBox(surface, centreX, centreY, blobSize, fore.allocated, back.allocated);
214 DrawMinus(surface, centreX, centreY, blobSize, back.allocated);
216 surface->MoveTo(centreX, centreY + blobSize);
217 surface->LineTo(centreX, rcWhole.bottom);
219 } else if (markType == SC_MARK_BOXMINUSCONNECTED) {
220 surface->PenColour(back.allocated);
221 DrawBox(surface, centreX, centreY, blobSize, fore.allocated, back.allocated);
222 DrawMinus(surface, centreX, centreY, blobSize, back.allocated);
224 surface->MoveTo(centreX, centreY + blobSize);
225 surface->LineTo(centreX, rcWhole.bottom);
227 surface->MoveTo(centreX, rcWhole.top);
228 surface->LineTo(centreX, centreY - blobSize);
230 } else if (markType == SC_MARK_CIRCLEPLUS) {
231 DrawCircle(surface, centreX, centreY, blobSize, fore.allocated, back.allocated);
232 surface->PenColour(back.allocated);
233 DrawPlus(surface, centreX, centreY, blobSize, back.allocated);
235 } else if (markType == SC_MARK_CIRCLEPLUSCONNECTED) {
236 DrawCircle(surface, centreX, centreY, blobSize, fore.allocated, back.allocated);
237 surface->PenColour(back.allocated);
238 DrawPlus(surface, centreX, centreY, blobSize, back.allocated);
240 surface->MoveTo(centreX, centreY + blobSize);
241 surface->LineTo(centreX, rcWhole.bottom);
243 surface->MoveTo(centreX, rcWhole.top);
244 surface->LineTo(centreX, centreY - blobSize);
246 } else if (markType == SC_MARK_CIRCLEMINUS) {
247 DrawCircle(surface, centreX, centreY, blobSize, fore.allocated, back.allocated);
248 surface->PenColour(back.allocated);
249 DrawMinus(surface, centreX, centreY, blobSize, back.allocated);
251 surface->MoveTo(centreX, centreY + blobSize);
252 surface->LineTo(centreX, rcWhole.bottom);
254 } else if (markType == SC_MARK_CIRCLEMINUSCONNECTED) {
255 DrawCircle(surface, centreX, centreY, blobSize, fore.allocated, back.allocated);
256 surface->PenColour(back.allocated);
257 DrawMinus(surface, centreX, centreY, blobSize, back.allocated);
259 surface->MoveTo(centreX, centreY + blobSize);
260 surface->LineTo(centreX, rcWhole.bottom);
262 surface->MoveTo(centreX, rcWhole.top);
263 surface->LineTo(centreX, centreY - blobSize);
265 } else if (markType >= SC_MARK_CHARACTER) {
266 char character[1];
267 character[0] = static_cast<char>(markType - SC_MARK_CHARACTER);
268 int width = surface->WidthText(fontForCharacter, character, 1);
269 rc.left += (rc.Width() - width) / 2;
270 rc.right = rc.left + width;
271 surface->DrawTextClipped(rc, fontForCharacter, rc.bottom - 2,
272 character, 1, fore.allocated, back.allocated);
274 } else if (markType == SC_MARK_DOTDOTDOT) {
275 int right = centreX - 6;
276 for (int b=0; b<3; b++) {
277 PRectangle rcBlob(right, rc.bottom - 4, right + 2, rc.bottom-2);
278 surface->FillRectangle(rcBlob, fore.allocated);
279 right += 5;
281 } else if (markType == SC_MARK_ARROWS) {
282 surface->PenColour(fore.allocated);
283 int right = centreX - 2;
284 for (int b=0; b<3; b++) {
285 surface->MoveTo(right - 4, centreY - 4);
286 surface->LineTo(right, centreY);
287 surface->LineTo(right - 5, centreY + 5);
288 right += 4;
290 } else if (markType == SC_MARK_SHORTARROW) {
291 Point pts[] = {
292 Point(centreX, centreY + dimOn2),
293 Point(centreX + dimOn2, centreY),
294 Point(centreX, centreY - dimOn2),
295 Point(centreX, centreY - dimOn4),
296 Point(centreX - dimOn4, centreY - dimOn4),
297 Point(centreX - dimOn4, centreY + dimOn4),
298 Point(centreX, centreY + dimOn4),
299 Point(centreX, centreY + dimOn2),
301 surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]),
302 fore.allocated, back.allocated);
303 } else if (markType == SC_MARK_LEFTRECT) {
304 PRectangle rcLeft = rcWhole;
305 rcLeft.right = rcLeft.left + 4;
306 surface->FillRectangle(rcLeft, back.allocated);
307 } else { // SC_MARK_FULLRECT
308 surface->FillRectangle(rcWhole, back.allocated);