aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--gtk/PlatGTK.cxx12
-rw-r--r--gtk/ScintillaGTK.cxx39
-rw-r--r--include/Scintilla.h1
-rw-r--r--include/Scintilla.iface1
-rw-r--r--src/CallTip.cxx163
-rw-r--r--src/CallTip.h12
-rw-r--r--src/ScintillaBase.cxx14
-rw-r--r--src/ScintillaBase.h1
-rw-r--r--win32/ScintillaWin.cxx25
9 files changed, 208 insertions, 60 deletions
diff --git a/gtk/PlatGTK.cxx b/gtk/PlatGTK.cxx
index b8af29fbf..016e1b1d2 100644
--- a/gtk/PlatGTK.cxx
+++ b/gtk/PlatGTK.cxx
@@ -1664,11 +1664,13 @@ void ListBoxX::SetFont(Font &scint_font) {
#else
GtkStyle *styleCurrent = gtk_widget_get_style(GTK_WIDGET(PWidget(list)));
GdkFont *fontCurrent = gtk_style_get_font(styleCurrent);
- if (!gdk_font_equal(fontCurrent, PFont(scint_font)->pfont)) {
- GtkStyle *styleNew = gtk_style_copy(styleCurrent);
- gtk_style_set_font(styleNew, PFont(scint_font)->pfont);
- gtk_widget_set_style(GTK_WIDGET(PWidget(list)), styleNew);
- gtk_style_unref(styleCurrent);
+ if (PFont(scint_font)->pfont) {
+ if (!gdk_font_equal(fontCurrent, PFont(scint_font)->pfont)) {
+ GtkStyle *styleNew = gtk_style_copy(styleCurrent);
+ gtk_style_set_font(styleNew, PFont(scint_font)->pfont);
+ gtk_widget_set_style(GTK_WIDGET(PWidget(list)), styleNew);
+ gtk_style_unref(styleCurrent);
+ }
}
#endif
}
diff --git a/gtk/ScintillaGTK.cxx b/gtk/ScintillaGTK.cxx
index fce22ab9b..54c025fbc 100644
--- a/gtk/ScintillaGTK.cxx
+++ b/gtk/ScintillaGTK.cxx
@@ -202,7 +202,10 @@ private:
GtkSelectionData *selection_data, guint info, guint time);
static gint TimeOut(ScintillaGTK *sciThis);
static void PopUpCB(ScintillaGTK *sciThis, guint action, GtkWidget *widget);
+
static gint ExposeCT(GtkWidget *widget, GdkEventExpose *ose, CallTip *ct);
+ static gint PressCT(GtkWidget *widget, GdkEventButton *event, ScintillaGTK *sciThis);
+
static sptr_t DirectFunction(ScintillaGTK *sciThis,
unsigned int iMessage, uptr_t wParam, sptr_t lParam);
};
@@ -892,15 +895,22 @@ void ScintillaGTK::Paste() {
}
void ScintillaGTK::CreateCallTipWindow(PRectangle rc) {
- ct.wCallTip = gtk_window_new(GTK_WINDOW_POPUP);
- ct.wDraw = gtk_drawing_area_new();
- gtk_container_add(GTK_CONTAINER(PWidget(ct.wCallTip)), PWidget(ct.wDraw));
- gtk_signal_connect(GTK_OBJECT(PWidget(ct.wDraw)), "expose_event",
- GtkSignalFunc(ScintillaGTK::ExposeCT), &ct);
- gtk_widget_set_events(PWidget(ct.wDraw), GDK_EXPOSURE_MASK);
+ if (!ct.wCallTip.Created()) {
+ ct.wCallTip = gtk_window_new(GTK_WINDOW_POPUP);
+ ct.wDraw = gtk_drawing_area_new();
+ gtk_container_add(GTK_CONTAINER(PWidget(ct.wCallTip)), PWidget(ct.wDraw));
+ gtk_signal_connect(GTK_OBJECT(PWidget(ct.wDraw)), "expose_event",
+ GtkSignalFunc(ScintillaGTK::ExposeCT), &ct);
+ gtk_signal_connect(GTK_OBJECT(PWidget(ct.wDraw)), "button_press_event",
+ GtkSignalFunc(ScintillaGTK::PressCT), static_cast<void *>(this));
+ gtk_widget_set_events(PWidget(ct.wDraw),
+ GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK);
+ }
gtk_drawing_area_size(GTK_DRAWING_AREA(PWidget(ct.wDraw)),
rc.Width(), rc.Height());
ct.wDraw.Show();
+ gtk_widget_set_usize(PWidget(ct.wCallTip), rc.Width(), rc.Height());
+ //gtk_widget_queue_resize(PWidget(ct.wCallTip));
}
void ScintillaGTK::AddToPopUp(const char *label, int cmd, bool enabled) {
@@ -1702,6 +1712,23 @@ void ScintillaGTK::PopUpCB(ScintillaGTK *sciThis, guint action, GtkWidget *) {
}
}
+gint ScintillaGTK::PressCT(GtkWidget *widget, GdkEventButton *event, ScintillaGTK *sciThis) {
+ if (event->window != widget->window)
+ return FALSE;
+ if (event->type != GDK_BUTTON_PRESS)
+ return FALSE;
+ Point pt;
+ pt.x = int(event->x);
+ pt.y = int(event->y);
+ sciThis->ct.MouseClick(pt);
+ sciThis->CallTipClick();
+#if GTK_MAJOR_VERSION >= 2
+ return TRUE;
+#else
+ return FALSE;
+#endif
+}
+
gint ScintillaGTK::ExposeCT(GtkWidget *widget, GdkEventExpose * /*ose*/, CallTip *ctip) {
Surface *surfaceWindow = Surface::Allocate();
if (surfaceWindow) {
diff --git a/include/Scintilla.h b/include/Scintilla.h
index eaa2f1a44..c377d07cc 100644
--- a/include/Scintilla.h
+++ b/include/Scintilla.h
@@ -599,6 +599,7 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
#define SCN_ZOOM 2018
#define SCN_HOTSPOTCLICK 2019
#define SCN_HOTSPOTDOUBLECLICK 2020
+#define SCN_CALLTIPCLICK 2021
//--Autogenerated -- end of section automatically generated from Scintilla.iface
// These structures are defined to be exactly the same shape as the Win32
diff --git a/include/Scintilla.iface b/include/Scintilla.iface
index 1ea3be8b0..be04e6a04 100644
--- a/include/Scintilla.iface
+++ b/include/Scintilla.iface
@@ -2070,6 +2070,7 @@ evt void DwellEnd=2017(int position)
evt void Zoom=2018(void)
evt void HotSpotClick=2019(int modifiers, int position)
evt void HotSpotDoubleClick=2020(int modifiers, int position)
+evt void CallTipClick=2021(int position)
cat Deprecated
diff --git a/src/CallTip.cxx b/src/CallTip.cxx
index c83e2d2fd..2c91be5f4 100644
--- a/src/CallTip.cxx
+++ b/src/CallTip.cxx
@@ -18,6 +18,9 @@ CallTip::CallTip() {
inCallTipMode = false;
posStartCallTip = 0;
val = 0;
+ xUp = -100;
+ xDown = -100;
+ lineHeight = 1;
startHighlight = 0;
endHighlight = 0;
@@ -35,6 +38,8 @@ CallTip::~CallTip() {
val = 0;
}
+const int widthArrow = 14;
+
void CallTip::RefreshColourPalette(Palette &pal, bool want) {
pal.WantFind(colourBG, want);
pal.WantFind(colourUnSel, want);
@@ -43,24 +48,96 @@ void CallTip::RefreshColourPalette(Palette &pal, bool want) {
pal.WantFind(colourLight, want);
}
-void CallTip::PaintCT(Surface *surfaceWindow) {
- if (!val)
- return ;
+void CallTip::DrawChunk(Surface *surface, int &x, const char *s,
+ int posStart, int posEnd, int ytext, PRectangle rcClient, bool highlight, bool draw) {
+ s += posStart;
+ int len = posEnd - posStart;
+ int maxEnd = 0;
+ int ends[10];
+ for (int i=0;i<len;i++) {
+ if (s[i] <= '\002') {
+ if (i > 0)
+ ends[maxEnd++] = i;
+ ends[maxEnd++] = i+1;
+ }
+ }
+ ends[maxEnd++] = len;
+ int startSeg = 0;
+ int xEnd;
+ for (int seg = 0; seg<maxEnd; seg++) {
+ int endSeg = ends[seg];
+ if (endSeg > startSeg) {
+ if (s[startSeg] <= '\002') {
+ xEnd = x + widthArrow;
+ if (draw) {
+ const int halfWidth = widthArrow / 2 - 3;
+ const int centreX = x + widthArrow / 2 - 1;
+ const int centreY = ytext - halfWidth - 1;
+ rcClient.left = x;
+ rcClient.right = xEnd;
+ surface->FillRectangle(rcClient, colourBG.allocated);
+ PRectangle rcClientInner(rcClient.left+1, rcClient.top+1, rcClient.right-2, rcClient.bottom-1);
+ surface->FillRectangle(rcClientInner, colourUnSel.allocated);
+
+ if (s[startSeg] == '\001') {
+ // Up arrow
+ Point pts[] = {
+ Point(centreX - halfWidth, centreY + halfWidth / 2),
+ Point(centreX + halfWidth, centreY + halfWidth / 2),
+ Point(centreX, centreY - halfWidth + halfWidth / 2),
+ };
+ surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]),
+ colourBG.allocated, colourBG.allocated);
+ } else {
+ // Down arrow
+ Point pts[] = {
+ Point(centreX - halfWidth, centreY - halfWidth / 2 + 1),
+ Point(centreX + halfWidth, centreY - halfWidth / 2 + 1),
+ Point(centreX, centreY + halfWidth - halfWidth / 2 + 1),
+ };
+ surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]),
+ colourBG.allocated, colourBG.allocated);
+ }
+ } else {
+ if (s[startSeg] == '\001') {
+ xUp = x+1;
+ } else {
+ xDown = x+1;
+ }
+ }
+ } else {
+ xEnd = x + surface->WidthText(font, s+startSeg, endSeg - startSeg);
+ if (draw) {
+ rcClient.left = x;
+ rcClient.right = xEnd;
+ surface->DrawTextNoClip(rcClient, font, ytext,
+ s+startSeg, endSeg - startSeg,
+ highlight ? colourSel.allocated : colourUnSel.allocated,
+ colourBG.allocated);
+ }
+ }
+ x = xEnd;
+ startSeg = endSeg;
+ }
+ }
+}
+
+int CallTip::PaintContents(Surface *surfaceWindow, bool draw) {
PRectangle rcClientPos = wCallTip.GetClientPosition();
PRectangle rcClientSize(0, 0, rcClientPos.right - rcClientPos.left,
rcClientPos.bottom - rcClientPos.top);
PRectangle rcClient(1, 1, rcClientSize.right - 1, rcClientSize.bottom - 1);
- surfaceWindow->FillRectangle(rcClient, colourBG.allocated);
// To make a nice small call tip window, it is only sized to fit most normal characters without accents
- int lineHeight = surfaceWindow->Height(font);
int ascent = surfaceWindow->Ascent(font) - surfaceWindow->InternalLeading(font);
// For each line...
// Draw the definition in three parts: before highlight, highlighted, after highlight
int ytext = rcClient.top + ascent + 1;
+ rcClient.bottom = rcClient.top + lineHeight + 1;
char *chunkVal = val;
bool moreChunks = true;
+ int maxWidth = 0;
while (moreChunks) {
char *chunkEnd = strchr(chunkVal, '\n');
if (chunkEnd == NULL) {
@@ -76,36 +153,34 @@ void CallTip::PaintCT(Surface *surfaceWindow) {
int thisEndHighlight = Platform::Maximum(endHighlight, chunkOffset);
thisEndHighlight = Platform::Minimum(thisEndHighlight, chunkEndOffset);
thisEndHighlight -= chunkOffset;
- int x = 5;
- int xEnd = x + surfaceWindow->WidthText(font, chunkVal, thisStartHighlight);
- rcClient.left = x;
rcClient.top = ytext - ascent - 1;
- rcClient.right = xEnd;
- surfaceWindow->DrawTextNoClip(rcClient, font, ytext,
- chunkVal, thisStartHighlight,
- colourUnSel.allocated, colourBG.allocated);
- x = xEnd;
-
- xEnd = x + surfaceWindow->WidthText(font, chunkVal + thisStartHighlight,
- thisEndHighlight - thisStartHighlight);
- rcClient.top = ytext;
- rcClient.left = x;
- rcClient.right = xEnd;
- surfaceWindow->DrawTextNoClip(rcClient, font, ytext,
- chunkVal + thisStartHighlight, thisEndHighlight - thisStartHighlight,
- colourSel.allocated, colourBG.allocated);
- x = xEnd;
-
- xEnd = x + surfaceWindow->WidthText(font, chunkVal + thisEndHighlight,
- chunkLength - thisEndHighlight);
- rcClient.left = x;
- rcClient.right = xEnd;
- surfaceWindow->DrawTextNoClip(rcClient, font, ytext,
- chunkVal + thisEndHighlight, chunkLength - thisEndHighlight,
- colourUnSel.allocated, colourBG.allocated);
+
+ int x = 5;
+
+ DrawChunk(surfaceWindow, x, chunkVal, 0, thisStartHighlight, ytext, rcClient, false, draw);
+ DrawChunk(surfaceWindow, x, chunkVal, thisStartHighlight, thisEndHighlight, ytext, rcClient, true, draw);
+ DrawChunk(surfaceWindow, x, chunkVal, thisEndHighlight, chunkLength, ytext, rcClient, false, draw);
+
chunkVal = chunkEnd + 1;
ytext += lineHeight;
+ rcClient.bottom += lineHeight;
+ maxWidth = Platform::Maximum(maxWidth, x);
}
+ return maxWidth;
+}
+
+void CallTip::PaintCT(Surface *surfaceWindow) {
+ if (!val)
+ return;
+ PRectangle rcClientPos = wCallTip.GetClientPosition();
+ PRectangle rcClientSize(0, 0, rcClientPos.right - rcClientPos.left,
+ rcClientPos.bottom - rcClientPos.top);
+ PRectangle rcClient(1, 1, rcClientSize.right - 1, rcClientSize.bottom - 1);
+
+ surfaceWindow->FillRectangle(rcClient, colourBG.allocated);
+
+ PaintContents(surfaceWindow, true);
+
// Draw a raised border around the edges of the window
surfaceWindow->MoveTo(0, rcClientSize.bottom - 1);
surfaceWindow->PenColour(colourShade.allocated);
@@ -116,9 +191,21 @@ void CallTip::PaintCT(Surface *surfaceWindow) {
surfaceWindow->LineTo(0, rcClientSize.bottom - 1);
}
+void CallTip::MouseClick(Point pt) {
+ clickPlace = 0;
+ if (pt.y < lineHeight) {
+ if ((pt.x > xUp) && (pt.x < xUp + widthArrow - 2)) {
+ clickPlace = 1;
+ } else if ((pt.x > xDown) && (pt.x < xDown + widthArrow - 2)) {
+ clickPlace = 2;
+ }
+ }
+}
+
PRectangle CallTip::CallTipStart(int pos, Point pt, const char *defn,
const char *faceName, int size,
- int codePage_) {
+ int codePage_, Window &wParent) {
+ clickPlace = 0;
if (val)
delete []val;
val = new char[strlen(defn) + 1];
@@ -129,7 +216,7 @@ PRectangle CallTip::CallTipStart(int pos, Point pt, const char *defn,
Surface *surfaceMeasure = Surface::Allocate();
if (!surfaceMeasure)
return PRectangle();
- surfaceMeasure->Init(wCallTip.GetID());
+ surfaceMeasure->Init(wParent.GetID());
surfaceMeasure->SetUnicodeMode(SC_CP_UTF8 == codePage);
surfaceMeasure->SetDBCSMode(codePage);
startHighlight = 0;
@@ -140,19 +227,17 @@ PRectangle CallTip::CallTipStart(int pos, Point pt, const char *defn,
font.Create(faceName, SC_CHARSET_DEFAULT, deviceHeight, false, false);
// Look for multiple lines in the text
// Only support \n here - simply means container must avoid \r!
- int width = 0;
int numLines = 1;
const char *newline;
const char *look = val;
+ xUp = -100;
+ xDown = -100;
+ int width = PaintContents(surfaceMeasure, false) + 5;
while ((newline = strchr(look, '\n')) != NULL) {
- int thisWidth = surfaceMeasure->WidthText(font, look, newline - look);
- width = Platform::Maximum(width, thisWidth);
look = newline + 1;
numLines++;
}
- int lastWidth = surfaceMeasure->WidthText(font, look, static_cast<int>(strlen(look)));
- width = Platform::Maximum(width, lastWidth) + 10;
- int lineHeight = surfaceMeasure->Height(font);
+ lineHeight = surfaceMeasure->Height(font);
// Extra line for border and an empty line at top and bottom
int height = lineHeight * numLines - surfaceMeasure->InternalLeading(font) + 2 + 2;
delete surfaceMeasure;
diff --git a/src/CallTip.h b/src/CallTip.h
index 877d9f34e..ff61f32a5 100644
--- a/src/CallTip.h
+++ b/src/CallTip.h
@@ -15,9 +15,16 @@ class CallTip {
int endHighlight;
char *val;
Font font;
+ int xUp;
+ int xDown;
+ int lineHeight;
// Private so CallTip objects can not be copied
CallTip(const CallTip &) {}
CallTip &operator=(const CallTip &) { return *this; }
+ void DrawChunk(Surface *surface, int &x, const char *s,
+ int posStart, int posEnd, int ytext, PRectangle rcClient,
+ bool highlight, bool draw);
+ int PaintContents(Surface *surfaceWindow, bool draw);
public:
Window wCallTip;
@@ -30,6 +37,7 @@ public:
ColourPair colourShade;
ColourPair colourLight;
int codePage;
+ int clickPlace;
CallTip();
~CallTip();
@@ -39,9 +47,11 @@ public:
void PaintCT(Surface *surfaceWindow);
+ void MouseClick(Point pt);
+
/// Setup the calltip and return a rectangle of the area required.
PRectangle CallTipStart(int pos, Point pt, const char *defn,
- const char *faceName, int size, int codePage_);
+ const char *faceName, int size, int codePage_, Window &wParent);
void CallTipCancel();
diff --git a/src/ScintillaBase.cxx b/src/ScintillaBase.cxx
index 62cdcdd74..27179bcdc 100644
--- a/src/ScintillaBase.cxx
+++ b/src/ScintillaBase.cxx
@@ -345,6 +345,13 @@ void ScintillaBase::AutoCompleteCompleted() {
pdoc->EndUndoAction();
}
+void ScintillaBase::CallTipClick() {
+ SCNotification scn;
+ scn.nmhdr.code = SCN_CALLTIPCLICK;
+ scn.position = ct.clickPlace;
+ NotifyParent(scn);
+}
+
void ScintillaBase::ContextMenu(Point pt) {
if (displayPopupMenu) {
bool writable = !WndProc(SCI_GETREADONLY, 0, 0);
@@ -528,14 +535,15 @@ sptr_t ScintillaBase::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lPara
case SCI_CALLTIPSHOW: {
AutoCompleteCancel();
- if (!ct.wCallTip.Created()) {
+ //if (!ct.wCallTip.Created()) {
Point pt = LocationFromPosition(wParam);
pt.y += vs.lineHeight;
PRectangle rc = ct.CallTipStart(currentPos, pt,
reinterpret_cast<char *>(lParam),
vs.styles[STYLE_DEFAULT].fontName,
vs.styles[STYLE_DEFAULT].sizeZoomed,
- IsUnicodeMode());
+ IsUnicodeMode(),
+ wMain);
// If the call-tip window would be out of the client
// space, adjust so it displays above the text.
PRectangle rcClient = GetClientRectangle();
@@ -548,7 +556,7 @@ sptr_t ScintillaBase::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lPara
CreateCallTipWindow(rc);
ct.wCallTip.SetPositionRelative(rc, wMain);
ct.wCallTip.Show();
- }
+ //}
}
break;
diff --git a/src/ScintillaBase.h b/src/ScintillaBase.h
index 9a9433dd7..152d49f53 100644
--- a/src/ScintillaBase.h
+++ b/src/ScintillaBase.h
@@ -71,6 +71,7 @@ protected:
void AutoCompleteMoveToCurrentWord();
static void AutoCompleteDoubleClick(void* p);
+ void CallTipClick();
virtual void CreateCallTipWindow(PRectangle rc) = 0;
virtual void AddToPopUp(const char *label, int cmd=0, bool enabled=true) = 0;
diff --git a/win32/ScintillaWin.cxx b/win32/ScintillaWin.cxx
index 9307373e3..3c35234c6 100644
--- a/win32/ScintillaWin.cxx
+++ b/win32/ScintillaWin.cxx
@@ -512,6 +512,8 @@ sptr_t ScintillaWin::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam
if (cmd != LBN_SETFOCUS)
::SetFocus(MainHWND());
}
+ } else if (LoWord(wParam) == idCallTip) {
+ CallTipClick();
}
Command(LoWord(wParam));
#endif
@@ -1080,12 +1082,14 @@ void ScintillaWin::Paste() {
void ScintillaWin::CreateCallTipWindow(PRectangle) {
#ifdef TOTAL_CONTROL
- ct.wCallTip = ::CreateWindow(callClassName, "ACallTip",
- WS_VISIBLE | WS_CHILD, 100, 100, 150, 20,
- MainHWND(), reinterpret_cast<HMENU>(idCallTip),
- GetWindowInstance(MainHWND()),
- &ct);
- ct.wDraw = ct.wCallTip;
+ if (!ct.wCallTip.Created()) {
+ ct.wCallTip = ::CreateWindow(callClassName, "ACallTip",
+ WS_VISIBLE | WS_CHILD, 100, 100, 150, 20,
+ MainHWND(), reinterpret_cast<HMENU>(idCallTip),
+ GetWindowInstance(MainHWND()),
+ &ct);
+ ct.wDraw = ct.wCallTip;
+ }
#endif
}
@@ -1951,6 +1955,15 @@ sptr_t PASCAL ScintillaWin::CTWndProc(
}
::EndPaint(hWnd, &ps);
return 0;
+ } else if (iMessage == WM_LBUTTONDOWN) {
+ ctp->MouseClick(Point::FromLong(lParam));
+ ::SendMessage(::GetParent(hWnd), WM_COMMAND,
+ MAKELONG(::GetDlgCtrlID(hWnd), SCEN_CHANGE),
+ reinterpret_cast<LPARAM>(hWnd));
+ return 0;
+ } else if (iMessage == WM_SETCURSOR) {
+ ::SetCursor(::LoadCursor(NULL,IDC_ARROW));
+ return 0;
} else {
return ::DefWindowProc(hWnd, iMessage, wParam, lParam);
}