]>
git.saurik.com Git - wxWidgets.git/blob - src/stc/scintilla/src/CallTip.cxx
93e888d0e6b9f77f7a9d202d8130e806f074df20
   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         inCallTipMode 
= false; 
  27         colourBG
.desired 
= ColourDesired(0xff, 0xff, 0xff); 
  28         colourUnSel
.desired 
= ColourDesired(0x80, 0x80, 0x80); 
  29         colourSel
.desired 
= ColourDesired(0, 0, 0x80); 
  30         colourShade
.desired 
= ColourDesired(0, 0, 0); 
  31         colourLight
.desired 
= ColourDesired(0xc0, 0xc0, 0xc0); 
  41 const int widthArrow 
= 14; 
  43 void CallTip::RefreshColourPalette(Palette 
&pal
, bool want
) { 
  44         pal
.WantFind(colourBG
, want
); 
  45         pal
.WantFind(colourUnSel
, want
); 
  46         pal
.WantFind(colourSel
, want
); 
  47         pal
.WantFind(colourShade
, want
); 
  48         pal
.WantFind(colourLight
, want
); 
  51 static bool IsArrowCharacter(char ch
) { 
  52         return (ch 
== 0) || (ch 
== '\001') || (ch 
== '\002'); 
  55 void CallTip::DrawChunk(Surface 
*surface
, int &x
, const char *s
, 
  56         int posStart
, int posEnd
, int ytext
, PRectangle rcClient
, 
  57         bool highlight
, bool draw
) { 
  59         int len 
= posEnd 
- posStart
; 
  62         for (int i
=0;i
<len
;i
++) { 
  63                 if (IsArrowCharacter(s
[i
])) { 
  72         for (int seg 
= 0; seg
<maxEnd
; seg
++) { 
  73                 int endSeg 
= ends
[seg
]; 
  74                 if (endSeg 
> startSeg
) { 
  75                         if (IsArrowCharacter(s
[startSeg
])) { 
  76                                 xEnd 
= x 
+ widthArrow
; 
  79                                         const int halfWidth 
= widthArrow 
/ 2 - 3; 
  80                                         const int centreX 
= x 
+ widthArrow 
/ 2 - 1; 
  81                                         const int centreY 
= (rcClient
.top 
+ rcClient
.bottom
) / 2; 
  83                                         rcClient
.right 
= xEnd
; 
  84                                         surface
->FillRectangle(rcClient
, colourBG
.allocated
); 
  85                                         PRectangle 
rcClientInner(rcClient
.left
+1, rcClient
.top
+1, rcClient
.right
-2, rcClient
.bottom
-1); 
  86                                         surface
->FillRectangle(rcClientInner
, colourUnSel
.allocated
); 
  88                                         if (s
[startSeg
] == '\001') { 
  91                                                 Point(centreX 
- halfWidth
, centreY 
+ halfWidth 
/ 2), 
  92                                                 Point(centreX 
+ halfWidth
, centreY 
+ halfWidth 
/ 2), 
  93                                                 Point(centreX
, centreY 
- halfWidth 
+ halfWidth 
/ 2), 
  95                                                 surface
->Polygon(pts
, sizeof(pts
) / sizeof(pts
[0]), 
  96                                                                 colourBG
.allocated
, colourBG
.allocated
); 
 100                                                 Point(centreX 
- halfWidth
, centreY 
- halfWidth 
/ 2), 
 101                                                 Point(centreX 
+ halfWidth
, centreY 
- halfWidth 
/ 2), 
 102                                                 Point(centreX
, centreY 
+ halfWidth 
- halfWidth 
/ 2), 
 104                                                 surface
->Polygon(pts
, sizeof(pts
) / sizeof(pts
[0]), 
 105                                                                 colourBG
.allocated
, colourBG
.allocated
); 
 108                                         if (s
[startSeg
] == '\001') { 
 115                                 xEnd 
= x 
+ surface
->WidthText(font
, s
+startSeg
, endSeg 
- startSeg
); 
 118                                         rcClient
.right 
= xEnd
; 
 119                                         surface
->DrawTextNoClip(rcClient
, font
, ytext
, 
 120                                                                                 s
+startSeg
, endSeg 
- startSeg
, 
 121                                                                                 highlight 
? colourSel
.allocated 
: colourUnSel
.allocated
, 
 131 int CallTip::PaintContents(Surface 
*surfaceWindow
, bool draw
) { 
 132         PRectangle rcClientPos 
= wCallTip
.GetClientPosition(); 
 133         PRectangle 
rcClientSize(0, 0, rcClientPos
.right 
- rcClientPos
.left
, 
 134                                 rcClientPos
.bottom 
- rcClientPos
.top
); 
 135         PRectangle 
rcClient(1, 1, rcClientSize
.right 
- 1, rcClientSize
.bottom 
- 1); 
 137         // To make a nice small call tip window, it is only sized to fit most normal characters without accents 
 138         int ascent 
= surfaceWindow
->Ascent(font
) - surfaceWindow
->InternalLeading(font
); 
 141         // Draw the definition in three parts: before highlight, highlighted, after highlight 
 142         int ytext 
= rcClient
.top 
+ ascent 
+ 1; 
 143         rcClient
.bottom 
= ytext 
+ surfaceWindow
->Descent(font
) + 1; 
 144         char *chunkVal 
= val
; 
 145         bool moreChunks 
= true; 
 148                 char *chunkEnd 
= strchr(chunkVal
, '\n'); 
 149                 if (chunkEnd 
== NULL
) { 
 150                         chunkEnd 
= chunkVal 
+ strlen(chunkVal
); 
 153                 int chunkOffset 
= chunkVal 
- val
; 
 154                 int chunkLength 
= chunkEnd 
- chunkVal
; 
 155                 int chunkEndOffset 
= chunkOffset 
+ chunkLength
; 
 156                 int thisStartHighlight 
= Platform::Maximum(startHighlight
, chunkOffset
); 
 157                 thisStartHighlight 
= Platform::Minimum(thisStartHighlight
, chunkEndOffset
); 
 158                 thisStartHighlight 
-= chunkOffset
; 
 159                 int thisEndHighlight 
= Platform::Maximum(endHighlight
, chunkOffset
); 
 160                 thisEndHighlight 
= Platform::Minimum(thisEndHighlight
, chunkEndOffset
); 
 161                 thisEndHighlight 
-= chunkOffset
; 
 162                 rcClient
.top 
= ytext 
- ascent 
- 1; 
 166                 DrawChunk(surfaceWindow
, x
, chunkVal
, 0, thisStartHighlight
, 
 167                         ytext
, rcClient
, false, draw
); 
 168                 DrawChunk(surfaceWindow
, x
, chunkVal
, thisStartHighlight
, thisEndHighlight
, 
 169                         ytext
, rcClient
, true, draw
); 
 170                 DrawChunk(surfaceWindow
, x
, chunkVal
, thisEndHighlight
, chunkLength
, 
 171                         ytext
, rcClient
, false, draw
); 
 173                 chunkVal 
= chunkEnd 
+ 1; 
 175                 rcClient
.bottom 
+= lineHeight
; 
 176                 maxWidth 
= Platform::Maximum(maxWidth
, x
); 
 181 void CallTip::PaintCT(Surface 
*surfaceWindow
) { 
 184         PRectangle rcClientPos 
= wCallTip
.GetClientPosition(); 
 185         PRectangle 
rcClientSize(0, 0, rcClientPos
.right 
- rcClientPos
.left
, 
 186                                 rcClientPos
.bottom 
- rcClientPos
.top
); 
 187         PRectangle 
rcClient(1, 1, rcClientSize
.right 
- 1, rcClientSize
.bottom 
- 1); 
 189         surfaceWindow
->FillRectangle(rcClient
, colourBG
.allocated
); 
 192         PaintContents(surfaceWindow
, true); 
 194         // Draw a raised border around the edges of the window 
 195         surfaceWindow
->MoveTo(0, rcClientSize
.bottom 
- 1); 
 196         surfaceWindow
->PenColour(colourShade
.allocated
); 
 197         surfaceWindow
->LineTo(rcClientSize
.right 
- 1, rcClientSize
.bottom 
- 1); 
 198         surfaceWindow
->LineTo(rcClientSize
.right 
- 1, 0); 
 199         surfaceWindow
->PenColour(colourLight
.allocated
); 
 200         surfaceWindow
->LineTo(0, 0); 
 201         surfaceWindow
->LineTo(0, rcClientSize
.bottom 
- 1); 
 204 void CallTip::MouseClick(Point pt
) { 
 206         if (pt
.y 
< lineHeight
) { 
 207                 if ((pt
.x 
> xUp
) && (pt
.x 
< xUp 
+ widthArrow 
- 2)) { 
 209                 } else if ((pt
.x 
> xDown
) && (pt
.x 
< xDown 
+ widthArrow 
- 2)) { 
 215 PRectangle 
CallTip::CallTipStart(int pos
, Point pt
, const char *defn
, 
 216                                  const char *faceName
, int size
, 
 217                                  int codePage_
, Window 
&wParent
) { 
 221         val 
= new char[strlen(defn
) + 1]; 
 225         codePage 
= codePage_
; 
 226         Surface 
*surfaceMeasure 
= Surface::Allocate(); 
 229         surfaceMeasure
->Init(wParent
.GetID()); 
 230         surfaceMeasure
->SetUnicodeMode(SC_CP_UTF8 
== codePage
); 
 231         surfaceMeasure
->SetDBCSMode(codePage
); 
 234         inCallTipMode 
= true; 
 235         posStartCallTip 
= pos
; 
 236         int deviceHeight 
= surfaceMeasure
->DeviceHeightFont(size
); 
 237         font
.Create(faceName
, SC_CHARSET_DEFAULT
, deviceHeight
, false, false); 
 238         // Look for multiple lines in the text 
 239         // Only support \n here - simply means container must avoid \r! 
 242         const char *look 
= val
; 
 246         int width 
= PaintContents(surfaceMeasure
, false) + 5; 
 247         while ((newline 
= strchr(look
, '\n')) != NULL
) { 
 251         lineHeight 
= surfaceMeasure
->Height(font
); 
 252         // Extra line for border and an empty line at top and bottom 
 253         int height 
= lineHeight 
* numLines 
- surfaceMeasure
->InternalLeading(font
) + 2 + 2; 
 254         delete surfaceMeasure
; 
 255         return PRectangle(pt
.x 
- offsetMain
, pt
.y 
+ 1, pt
.x 
+ width 
- offsetMain
, pt
.y 
+ 1 + height
); 
 258 void CallTip::CallTipCancel() { 
 259         inCallTipMode 
= false; 
 260         if (wCallTip
.Created()) { 
 265 void CallTip::SetHighlight(int start
, int end
) { 
 266         // Avoid flashing by checking something has really changed 
 267         if ((start 
!= startHighlight
) || (end 
!= endHighlight
)) { 
 268                 startHighlight 
= start
; 
 270                 if (wCallTip
.Created()) { 
 271                         wCallTip
.InvalidateAll();