]>
git.saurik.com Git - wxWidgets.git/blob - src/stc/scintilla/src/CallTip.cxx
3ea2d48fd31b65b402bf160760205f18244b9785
   1 // Scintilla source code edit control 
   3  ** Code for displaying call tips. 
   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. 
  13 #include "Scintilla.h" 
  18 using namespace Scintilla
; 
  21 static const int insetX 
= 5;    // text inset in x from calltip border 
  22 static const int widthArrow 
= 14; 
  26         inCallTipMode 
= false; 
  29         rectUp 
= PRectangle(0,0,0,0); 
  30         rectDown 
= PRectangle(0,0,0,0); 
  35         useStyleCallTip 
= false;    // for backwards compatibility 
  38         // proper apple colours for the default 
  39         colourBG
.desired 
= ColourDesired(0xff, 0xff, 0xc6); 
  40         colourUnSel
.desired 
= ColourDesired(0, 0, 0); 
  42         colourBG
.desired 
= ColourDesired(0xff, 0xff, 0xff); 
  43         colourUnSel
.desired 
= ColourDesired(0x80, 0x80, 0x80); 
  45         colourSel
.desired 
= ColourDesired(0, 0, 0x80); 
  46         colourShade
.desired 
= ColourDesired(0, 0, 0); 
  47         colourLight
.desired 
= ColourDesired(0xc0, 0xc0, 0xc0); 
  57 void CallTip::RefreshColourPalette(Palette 
&pal
, bool want
) { 
  58         pal
.WantFind(colourBG
, want
); 
  59         pal
.WantFind(colourUnSel
, want
); 
  60         pal
.WantFind(colourSel
, want
); 
  61         pal
.WantFind(colourShade
, want
); 
  62         pal
.WantFind(colourLight
, want
); 
  65 // Although this test includes 0, we should never see a \0 character. 
  66 static bool IsArrowCharacter(char ch
) { 
  67         return (ch 
== 0) || (ch 
== '\001') || (ch 
== '\002'); 
  70 // We ignore tabs unless a tab width has been set. 
  71 bool CallTip::IsTabCharacter(char ch
) { 
  72         return (tabSize 
> 0) && (ch 
== '\t'); 
  75 int CallTip::NextTabPos(int x
) { 
  76         if (tabSize 
> 0) {              // paranoia... not called unless this is true 
  77                 x 
-= insetX
;                // position relative to text 
  78                 x 
= (x 
+ tabSize
) / tabSize
;  // tab "number" 
  79                 return tabSize
*x 
+ insetX
;  // position of next tab 
  81                 return x 
+ 1;                 // arbitrary 
  85 // Draw a section of the call tip that does not include \n in one colour. 
  86 // The text may include up to numEnds tabs or arrow characters. 
  87 void CallTip::DrawChunk(Surface 
*surface
, int &x
, const char *s
, 
  88         int posStart
, int posEnd
, int ytext
, PRectangle rcClient
, 
  89         bool highlight
, bool draw
) { 
  91         int len 
= posEnd 
- posStart
; 
  93         // Divide the text into sections that are all text, or that are 
  94         // single arrows or single tab characters (if tabSize > 0). 
  96         const int numEnds 
= 10; 
  97         int ends
[numEnds 
+ 2]; 
  98         for (int i
=0;i
<len
;i
++) { 
  99                 if ((maxEnd 
< numEnds
) && 
 100                         (IsArrowCharacter(s
[i
]) || IsTabCharacter(s
[i
])) ) { 
 103                         ends
[maxEnd
++] = i
+1; 
 106         ends
[maxEnd
++] = len
; 
 109         for (int seg 
= 0; seg
<maxEnd
; seg
++) { 
 110                 int endSeg 
= ends
[seg
]; 
 111                 if (endSeg 
> startSeg
) { 
 112                         if (IsArrowCharacter(s
[startSeg
])) { 
 113                                 bool upArrow 
= s
[startSeg
] == '\001'; 
 115                                 rcClient
.right 
= rcClient
.left 
+ widthArrow
; 
 117                                         const int halfWidth 
= widthArrow 
/ 2 - 3; 
 118                                         const int centreX 
= rcClient
.left 
+ widthArrow 
/ 2 - 1; 
 119                                         const int centreY 
= (rcClient
.top 
+ rcClient
.bottom
) / 2; 
 120                                         surface
->FillRectangle(rcClient
, colourBG
.allocated
); 
 121                                         PRectangle 
rcClientInner(rcClient
.left 
+ 1, rcClient
.top 
+ 1, 
 122                                                                  rcClient
.right 
- 2, rcClient
.bottom 
- 1); 
 123                                         surface
->FillRectangle(rcClientInner
, colourUnSel
.allocated
); 
 125                                         if (upArrow
) {      // Up arrow 
 127                                                 Point(centreX 
- halfWidth
, centreY 
+ halfWidth 
/ 2), 
 128                                                 Point(centreX 
+ halfWidth
, centreY 
+ halfWidth 
/ 2), 
 129                                                 Point(centreX
, centreY 
- halfWidth 
+ halfWidth 
/ 2), 
 131                                                 surface
->Polygon(pts
, sizeof(pts
) / sizeof(pts
[0]), 
 132                                                                 colourBG
.allocated
, colourBG
.allocated
); 
 133                                         } else {            // Down arrow 
 135                                                 Point(centreX 
- halfWidth
, centreY 
- halfWidth 
/ 2), 
 136                                                 Point(centreX 
+ halfWidth
, centreY 
- halfWidth 
/ 2), 
 137                                                 Point(centreX
, centreY 
+ halfWidth 
- halfWidth 
/ 2), 
 139                                                 surface
->Polygon(pts
, sizeof(pts
) / sizeof(pts
[0]), 
 140                                                                 colourBG
.allocated
, colourBG
.allocated
); 
 143                                 xEnd 
= rcClient
.right
; 
 150                         } else if (IsTabCharacter(s
[startSeg
])) { 
 151                                 xEnd 
= NextTabPos(x
); 
 153                                 xEnd 
= x 
+ surface
->WidthText(font
, s 
+ startSeg
, endSeg 
- startSeg
); 
 156                                         rcClient
.right 
= xEnd
; 
 157                                         surface
->DrawTextTransparent(rcClient
, font
, ytext
, 
 158                                                                                 s
+startSeg
, endSeg 
- startSeg
, 
 159                                                                      highlight 
? colourSel
.allocated 
: colourUnSel
.allocated
); 
 168 int CallTip::PaintContents(Surface 
*surfaceWindow
, bool draw
) { 
 169         PRectangle rcClientPos 
= wCallTip
.GetClientPosition(); 
 170         PRectangle 
rcClientSize(0, 0, rcClientPos
.right 
- rcClientPos
.left
, 
 171                                 rcClientPos
.bottom 
- rcClientPos
.top
); 
 172         PRectangle 
rcClient(1, 1, rcClientSize
.right 
- 1, rcClientSize
.bottom 
- 1); 
 174         // To make a nice small call tip window, it is only sized to fit most normal characters without accents 
 175         int ascent 
= surfaceWindow
->Ascent(font
) - surfaceWindow
->InternalLeading(font
); 
 178         // Draw the definition in three parts: before highlight, highlighted, after highlight 
 179         int ytext 
= rcClient
.top 
+ ascent 
+ 1; 
 180         rcClient
.bottom 
= ytext 
+ surfaceWindow
->Descent(font
) + 1; 
 181         char *chunkVal 
= val
; 
 182         bool moreChunks 
= true; 
 186                 char *chunkEnd 
= strchr(chunkVal
, '\n'); 
 187                 if (chunkEnd 
== NULL
) { 
 188                         chunkEnd 
= chunkVal 
+ strlen(chunkVal
); 
 191                 int chunkOffset 
= chunkVal 
- val
; 
 192                 int chunkLength 
= chunkEnd 
- chunkVal
; 
 193                 int chunkEndOffset 
= chunkOffset 
+ chunkLength
; 
 194                 int thisStartHighlight 
= Platform::Maximum(startHighlight
, chunkOffset
); 
 195                 thisStartHighlight 
= Platform::Minimum(thisStartHighlight
, chunkEndOffset
); 
 196                 thisStartHighlight 
-= chunkOffset
; 
 197                 int thisEndHighlight 
= Platform::Maximum(endHighlight
, chunkOffset
); 
 198                 thisEndHighlight 
= Platform::Minimum(thisEndHighlight
, chunkEndOffset
); 
 199                 thisEndHighlight 
-= chunkOffset
; 
 200                 rcClient
.top 
= ytext 
- ascent 
- 1; 
 202                 int x 
= insetX
;     // start each line at this inset 
 204                 DrawChunk(surfaceWindow
, x
, chunkVal
, 0, thisStartHighlight
, 
 205                         ytext
, rcClient
, false, draw
); 
 206                 DrawChunk(surfaceWindow
, x
, chunkVal
, thisStartHighlight
, thisEndHighlight
, 
 207                         ytext
, rcClient
, true, draw
); 
 208                 DrawChunk(surfaceWindow
, x
, chunkVal
, thisEndHighlight
, chunkLength
, 
 209                         ytext
, rcClient
, false, draw
); 
 211                 chunkVal 
= chunkEnd 
+ 1; 
 213                 rcClient
.bottom 
+= lineHeight
; 
 214                 maxWidth 
= Platform::Maximum(maxWidth
, x
); 
 219 void CallTip::PaintCT(Surface 
*surfaceWindow
) { 
 222         PRectangle rcClientPos 
= wCallTip
.GetClientPosition(); 
 223         PRectangle 
rcClientSize(0, 0, rcClientPos
.right 
- rcClientPos
.left
, 
 224                                 rcClientPos
.bottom 
- rcClientPos
.top
); 
 225         PRectangle 
rcClient(1, 1, rcClientSize
.right 
- 1, rcClientSize
.bottom 
- 1); 
 227         surfaceWindow
->FillRectangle(rcClient
, colourBG
.allocated
); 
 229         offsetMain 
= insetX
;    // initial alignment assuming no arrows 
 230         PaintContents(surfaceWindow
, true); 
 233         // OSX doesn't put borders on "help tags" 
 234         // Draw a raised border around the edges of the window 
 235         surfaceWindow
->MoveTo(0, rcClientSize
.bottom 
- 1); 
 236         surfaceWindow
->PenColour(colourShade
.allocated
); 
 237         surfaceWindow
->LineTo(rcClientSize
.right 
- 1, rcClientSize
.bottom 
- 1); 
 238         surfaceWindow
->LineTo(rcClientSize
.right 
- 1, 0); 
 239         surfaceWindow
->PenColour(colourLight
.allocated
); 
 240         surfaceWindow
->LineTo(0, 0); 
 241         surfaceWindow
->LineTo(0, rcClientSize
.bottom 
- 1); 
 245 void CallTip::MouseClick(Point pt
) { 
 247         if (rectUp
.Contains(pt
)) 
 249         if (rectDown
.Contains(pt
)) 
 253 PRectangle 
CallTip::CallTipStart(int pos
, Point pt
, const char *defn
, 
 254                                  const char *faceName
, int size
, 
 255                                  int codePage_
, int characterSet
, Window 
&wParent
) { 
 259         val 
= new char[strlen(defn
) + 1]; 
 261         codePage 
= codePage_
; 
 262         Surface 
*surfaceMeasure 
= Surface::Allocate(); 
 265         surfaceMeasure
->Init(wParent
.GetID()); 
 266         surfaceMeasure
->SetUnicodeMode(SC_CP_UTF8 
== codePage
); 
 267         surfaceMeasure
->SetDBCSMode(codePage
); 
 270         inCallTipMode 
= true; 
 271         posStartCallTip 
= pos
; 
 272         int deviceHeight 
= surfaceMeasure
->DeviceHeightFont(size
); 
 273         font
.Create(faceName
, characterSet
, deviceHeight
, false, false); 
 274         // Look for multiple lines in the text 
 275         // Only support \n here - simply means container must avoid \r! 
 278         const char *look 
= val
; 
 279         rectUp 
= PRectangle(0,0,0,0); 
 280         rectDown 
= PRectangle(0,0,0,0); 
 281         offsetMain 
= insetX
;            // changed to right edge of any arrows 
 282         int width 
= PaintContents(surfaceMeasure
, false) + insetX
; 
 283         while ((newline 
= strchr(look
, '\n')) != NULL
) { 
 287         lineHeight 
= surfaceMeasure
->Height(font
); 
 289         // Extra line for border and an empty line at top and bottom. The returned 
 290         // rectangle is aligned to the right edge of the last arrow encountered in 
 291         // the tip text, else to the tip text left edge. 
 292         int height 
= lineHeight 
* numLines 
- surfaceMeasure
->InternalLeading(font
) + 2 + 2; 
 293         delete surfaceMeasure
; 
 294         return PRectangle(pt
.x 
- offsetMain
, pt
.y 
+ 1, pt
.x 
+ width 
- offsetMain
, pt
.y 
+ 1 + height
); 
 297 void CallTip::CallTipCancel() { 
 298         inCallTipMode 
= false; 
 299         if (wCallTip
.Created()) { 
 304 void CallTip::SetHighlight(int start
, int end
) { 
 305         // Avoid flashing by checking something has really changed 
 306         if ((start 
!= startHighlight
) || (end 
!= endHighlight
)) { 
 307                 startHighlight 
= start
; 
 309                 if (wCallTip
.Created()) { 
 310                         wCallTip
.InvalidateAll(); 
 315 // Set the tab size (sizes > 0 enable the use of tabs). This also enables the 
 316 // use of the STYLE_CALLTIP. 
 317 void CallTip::SetTabSize(int tabSz
) { 
 319         useStyleCallTip 
= true; 
 322 // It might be better to have two access functions for this and to use 
 323 // them for all settings of colours. 
 324 void CallTip::SetForeBack(const ColourPair 
&fore
, const ColourPair 
&back
) {