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