diff options
-rw-r--r-- | gtk/PlatGTK.cxx | 12 | ||||
-rw-r--r-- | gtk/ScintillaGTK.cxx | 39 | ||||
-rw-r--r-- | include/Scintilla.h | 1 | ||||
-rw-r--r-- | include/Scintilla.iface | 1 | ||||
-rw-r--r-- | src/CallTip.cxx | 163 | ||||
-rw-r--r-- | src/CallTip.h | 12 | ||||
-rw-r--r-- | src/ScintillaBase.cxx | 14 | ||||
-rw-r--r-- | src/ScintillaBase.h | 1 | ||||
-rw-r--r-- | win32/ScintillaWin.cxx | 25 |
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); } |