]>
Commit | Line | Data |
---|---|---|
9ce192d4 RD |
1 | // Scintilla source code edit control |
2 | // CallTip.cxx - code for displaying call tips | |
3 | // Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org> | |
4 | // The License.txt file describes the conditions under which this software may be distributed. | |
5 | ||
6 | #include <stdlib.h> | |
7 | #include <string.h> | |
8 | ||
9 | #include "Platform.h" | |
10 | ||
f6bcfd97 | 11 | #include "Scintilla.h" |
9ce192d4 RD |
12 | #include "CallTip.h" |
13 | ||
14 | CallTip::CallTip() { | |
15 | wCallTip = 0; | |
16 | inCallTipMode = false; | |
17 | posStartCallTip = 0; | |
18 | val = 0; | |
19 | startHighlight = 0; | |
20 | endHighlight = 0; | |
21 | ||
22 | colourBG.desired = Colour(0xff, 0xff, 0xff); | |
23 | colourUnSel.desired = Colour(0x80, 0x80, 0x80); | |
24 | colourSel.desired = Colour(0, 0, 0x80); | |
25 | colourShade.desired = Colour(0, 0, 0); | |
26 | colourLight.desired = Colour(0xc0, 0xc0, 0xc0); | |
27 | } | |
28 | ||
29 | CallTip::~CallTip() { | |
30 | wCallTip.Destroy(); | |
31 | delete []val; | |
32 | val = 0; | |
33 | } | |
34 | ||
35 | void CallTip::RefreshColourPalette(Palette &pal, bool want) { | |
36 | pal.WantFind(colourBG, want); | |
37 | pal.WantFind(colourUnSel, want); | |
38 | pal.WantFind(colourSel, want); | |
39 | pal.WantFind(colourShade, want); | |
40 | pal.WantFind(colourLight, want); | |
41 | } | |
42 | ||
43 | void CallTip::PaintCT(Surface *surfaceWindow) { | |
44 | if (!val) | |
45 | return; | |
46 | PRectangle rcClientPos = wCallTip.GetClientPosition(); | |
47 | PRectangle rcClientSize(0, 0, rcClientPos.right - rcClientPos.left, | |
48 | rcClientPos.bottom - rcClientPos.top); | |
49 | PRectangle rcClient(1, 1, rcClientSize.right - 1, rcClientSize.bottom - 1); | |
50 | ||
51 | surfaceWindow->FillRectangle(rcClient, colourBG.allocated); | |
52 | // To make a nice small call tip window, it is only sized to fit most normal characters without accents | |
53 | int lineHeight = surfaceWindow->Height(font); | |
54 | int ascent = surfaceWindow->Ascent(font) - surfaceWindow->InternalLeading(font); | |
55 | ||
56 | // For each line... | |
57 | // Draw the definition in three parts: before highlight, highlighted, after highlight | |
58 | int ytext = rcClient.top + ascent + 1; | |
59 | char *chunkVal = val; | |
60 | bool moreChunks = true; | |
61 | while (moreChunks) { | |
62 | char *chunkEnd = strchr(chunkVal, '\n'); | |
63 | if (chunkEnd == NULL) { | |
64 | chunkEnd = chunkVal + strlen(chunkVal); | |
65 | moreChunks = false; | |
66 | } | |
67 | int chunkOffset = chunkVal - val; | |
68 | int chunkLength = chunkEnd - chunkVal; | |
69 | int chunkEndOffset = chunkOffset + chunkLength; | |
70 | int thisStartHighlight = Platform::Maximum(startHighlight, chunkOffset); | |
71 | thisStartHighlight = Platform::Minimum(thisStartHighlight, chunkEndOffset); | |
72 | thisStartHighlight -= chunkOffset; | |
73 | int thisEndHighlight = Platform::Maximum(endHighlight, chunkOffset); | |
74 | thisEndHighlight = Platform::Minimum(thisEndHighlight, chunkEndOffset); | |
75 | thisEndHighlight -= chunkOffset; | |
76 | int x = 5; | |
77 | int xEnd = x + surfaceWindow->WidthText(font, chunkVal, thisStartHighlight); | |
78 | rcClient.left = x; | |
79 | rcClient.top = ytext - ascent - 1; | |
80 | rcClient.right = xEnd; | |
81 | surfaceWindow->DrawText(rcClient, font, ytext, | |
82 | chunkVal, thisStartHighlight, | |
83 | colourUnSel.allocated, colourBG.allocated); | |
84 | x = xEnd; | |
85 | ||
86 | xEnd = x + surfaceWindow->WidthText(font, chunkVal + thisStartHighlight, | |
87 | thisEndHighlight - thisStartHighlight); | |
88 | rcClient.top = ytext; | |
89 | rcClient.left = x; | |
90 | rcClient.right = xEnd; | |
91 | surfaceWindow->DrawText(rcClient, font, ytext, | |
92 | chunkVal + thisStartHighlight, thisEndHighlight - thisStartHighlight, | |
93 | colourSel.allocated, colourBG.allocated); | |
94 | x = xEnd; | |
95 | ||
96 | xEnd = x + surfaceWindow->WidthText(font, chunkVal + thisEndHighlight, | |
97 | chunkLength - thisEndHighlight); | |
98 | rcClient.left = x; | |
99 | rcClient.right = xEnd; | |
100 | surfaceWindow->DrawText(rcClient, font, ytext, | |
101 | chunkVal + thisEndHighlight, chunkLength - thisEndHighlight, | |
102 | colourUnSel.allocated, colourBG.allocated); | |
103 | chunkVal = chunkEnd + 1; | |
104 | ytext += lineHeight; | |
105 | } | |
106 | // Draw a raised border around the edges of the window | |
107 | surfaceWindow->MoveTo(0, rcClientSize.bottom - 1); | |
108 | surfaceWindow->PenColour(colourShade.allocated); | |
109 | surfaceWindow->LineTo(rcClientSize.right - 1, rcClientSize.bottom - 1); | |
110 | surfaceWindow->LineTo(rcClientSize.right - 1, 0); | |
111 | surfaceWindow->PenColour(colourLight.allocated); | |
112 | surfaceWindow->LineTo(0, 0); | |
113 | surfaceWindow->LineTo(0, rcClientSize.bottom - 1); | |
114 | } | |
115 | ||
116 | PRectangle CallTip::CallTipStart(int pos, Point pt, const char *defn, | |
117 | const char *faceName, int size) { | |
118 | Surface surfaceMeasure; | |
119 | surfaceMeasure.Init(); | |
120 | int deviceHeight = (size * surfaceMeasure.LogPixelsY()) / 72; | |
f6bcfd97 | 121 | font.Create(faceName, SC_CHARSET_DEFAULT, deviceHeight, false, false); |
9ce192d4 RD |
122 | if (val) |
123 | delete []val; | |
124 | val = new char[strlen(defn) + 1]; | |
125 | if (!val) | |
126 | return PRectangle(); | |
127 | strcpy(val, defn); | |
128 | startHighlight = 0; | |
129 | endHighlight = 0; | |
130 | inCallTipMode = true; | |
131 | posStartCallTip = pos; | |
132 | // Look for multiple lines in the text | |
133 | // Only support \n here - simply means container must avoid \r! | |
134 | int width = 0; | |
135 | int numLines = 1; | |
136 | const char *newline; | |
137 | const char *look = val; | |
138 | while ((newline = strchr(look, '\n')) != NULL) { | |
139 | int thisWidth = surfaceMeasure.WidthText(font, look, newline - look); | |
140 | width = Platform::Maximum(width, thisWidth); | |
141 | look = newline + 1; | |
142 | numLines++; | |
143 | } | |
144 | int lastWidth = surfaceMeasure.WidthText(font, look, strlen(look)); | |
145 | width = Platform::Maximum(width, lastWidth) + 10; | |
146 | int lineHeight = surfaceMeasure.Height(font); | |
147 | // Extra line for border and an empty line at top and bottom | |
148 | int height = lineHeight * numLines - surfaceMeasure.InternalLeading(font) + 2 + 2; | |
149 | return PRectangle(pt.x -5, pt.y + lineHeight + 1, pt.x + width - 5, pt.y + lineHeight + 1 + height); | |
150 | } | |
151 | ||
152 | ||
153 | void CallTip::CallTipCancel() { | |
154 | inCallTipMode = false; | |
155 | if (wCallTip.Created()) { | |
156 | wCallTip.Destroy(); | |
157 | } | |
158 | } | |
159 | ||
160 | void CallTip::SetHighlight(int start, int end) { | |
161 | // Avoid flashing by checking something has really changed | |
162 | if ((start != startHighlight) || (end != endHighlight)) { | |
163 | startHighlight = start; | |
164 | endHighlight = end; | |
165 | if (wCallTip.Created()) { | |
166 | wCallTip.InvalidateAll(); | |
167 | } | |
168 | } | |
169 | } |