X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/3727c043a846bed24554c47b723da9fbe3b9a010..e27619029d56533297ca5d79f614646d8c8354a2:/src/stc/PlatWX.cpp diff --git a/src/stc/PlatWX.cpp b/src/stc/PlatWX.cpp index 2e5309ef25..7512383fca 100644 --- a/src/stc/PlatWX.cpp +++ b/src/stc/PlatWX.cpp @@ -4,18 +4,45 @@ // Robin Dunn // The License.txt file describes the conditions under which this software may be distributed. +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +#if wxUSE_STC + +#ifndef WX_PRECOMP + #include "wx/menu.h" + #include "wx/dcmemory.h" + #include "wx/settings.h" +#endif // WX_PRECOMP + #include -#include -#include -#include -#include -#include -#include +#if wxUSE_DISPLAY +#include "wx/display.h" +#endif + +#include "wx/encconv.h" +#include "wx/listctrl.h" +#include "wx/mstream.h" +#include "wx/image.h" +#include "wx/imaglist.h" +#include "wx/tokenzr.h" + +#ifdef wxHAS_RAW_BITMAP +#include "wx/rawbmp.h" +#endif +#if wxUSE_GRAPHICS_CONTEXT +#include "wx/dcgraph.h" +#endif #include "Platform.h" #include "PlatWX.h" #include "wx/stc/stc.h" +#include "wx/stc/private.h" @@ -41,19 +68,34 @@ wxColour wxColourFromCA(const ColourAllocated& ca) { (unsigned char)cd.GetBlue()); } +wxColour wxColourFromCAandAlpha(const ColourAllocated& ca, int alpha) { + ColourDesired cd(ca.AsLong()); + return wxColour((unsigned char)cd.GetRed(), + (unsigned char)cd.GetGreen(), + (unsigned char)cd.GetBlue(), + (unsigned char)alpha); +} + //---------------------------------------------------------------------- Palette::Palette() { used = 0; allowRealization = false; + size = 100; + entries = new ColourPair[size]; } Palette::~Palette() { Release(); + delete [] entries; + entries = 0; } void Palette::Release() { used = 0; + delete [] entries; + size = 100; + entries = new ColourPair[size]; } // This method either adds a colour to the list of wanted colours (want==true) @@ -66,11 +108,20 @@ void Palette::WantFind(ColourPair &cp, bool want) { return; } - if (used < numEntries) { - entries[used].desired = cp.desired; - entries[used].allocated.Set(cp.desired.AsLong()); - used++; + if (used >= size) { + int sizeNew = size * 2; + ColourPair *entriesNew = new ColourPair[sizeNew]; + for (int j=0; jSetNoAntiAliasing(!extraFontFlag); id = font; } @@ -161,6 +212,8 @@ public: virtual void FillRectangle(PRectangle rc, ColourAllocated back); virtual void FillRectangle(PRectangle rc, Surface &surfacePattern); virtual void RoundedRectangle(PRectangle rc, ColourAllocated fore, ColourAllocated back); + virtual void AlphaRectangle(PRectangle rc, int cornerSize, ColourAllocated fill, int alphaFill, + ColourAllocated outline, int alphaOutline, int flags); virtual void Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back); virtual void Copy(PRectangle rc, Point from, Surface &surfaceSource); @@ -248,11 +301,11 @@ bool SurfaceImpl::Initialised() { void SurfaceImpl::PenColour(ColourAllocated fore) { - hdc->SetPen(wxPen(wxColourFromCA(fore), 1, wxSOLID)); + hdc->SetPen(wxPen(wxColourFromCA(fore))); } void SurfaceImpl::BrushColour(ColourAllocated back) { - hdc->SetBrush(wxBrush(wxColourFromCA(back), wxSOLID)); + hdc->SetBrush(wxBrush(wxColourFromCA(back))); } void SurfaceImpl::SetFont(Font &font_) { @@ -303,7 +356,7 @@ void SurfaceImpl::FillRectangle(PRectangle rc, Surface &surfacePattern) { if (((SurfaceImpl&)surfacePattern).bitmap) br = wxBrush(*((SurfaceImpl&)surfacePattern).bitmap); else // Something is wrong so display in red - br = wxBrush(*wxRED, wxSOLID); + br = wxBrush(*wxRED); hdc->SetPen(*wxTRANSPARENT_PEN); hdc->SetBrush(br); hdc->DrawRectangle(wxRectFromPRectangle(rc)); @@ -315,6 +368,97 @@ void SurfaceImpl::RoundedRectangle(PRectangle rc, ColourAllocated fore, ColourAl hdc->DrawRoundedRectangle(wxRectFromPRectangle(rc), 4); } +#ifdef __WXMSW__ +#define wxPy_premultiply(p, a) ((p) * (a) / 0xff) +#else +#define wxPy_premultiply(p, a) (p) +#endif + +void SurfaceImpl::AlphaRectangle(PRectangle rc, int cornerSize, + ColourAllocated fill, int alphaFill, + ColourAllocated outline, int alphaOutline, + int /*flags*/) { +#if wxUSE_GRAPHICS_CONTEXT + wxGCDC dc(*(wxMemoryDC*)hdc); + wxColour penColour(wxColourFromCAandAlpha(outline, alphaOutline)); + wxColour brushColour(wxColourFromCAandAlpha(fill, alphaFill)); + dc.SetPen(wxPen(penColour)); + dc.SetBrush(wxBrush(brushColour)); + dc.DrawRoundedRectangle(wxRectFromPRectangle(rc), cornerSize); + return; +#else + +#ifdef wxHAS_RAW_BITMAP + + // TODO: do something with cornerSize + wxUnusedVar(cornerSize); + + int x, y; + wxRect r = wxRectFromPRectangle(rc); + wxBitmap bmp(r.width, r.height, 32); + wxAlphaPixelData pixData(bmp); + + // Set the fill pixels + ColourDesired cdf(fill.AsLong()); + int red = cdf.GetRed(); + int green = cdf.GetGreen(); + int blue = cdf.GetBlue(); + + wxAlphaPixelData::Iterator p(pixData); + for (y=0; yDrawBitmap(bmp, r.x, r.y, true); + +#else + wxUnusedVar(cornerSize); + wxUnusedVar(alphaFill); + wxUnusedVar(alphaOutline); + RectangleDraw(rc, outline, fill); +#endif +#endif +} + void SurfaceImpl::Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back) { PenColour(fore); BrushColour(back); @@ -362,13 +506,13 @@ void SurfaceImpl::DrawTextTransparent(PRectangle rc, Font &font, int ybase, SetFont(font); hdc->SetTextForeground(wxColourFromCA(fore)); - hdc->SetBackgroundMode(wxTRANSPARENT); + hdc->SetBackgroundMode(wxBRUSHSTYLE_TRANSPARENT); // ybase is where the baseline should be, but wxWin uses the upper left // corner, so I need to calculate the real position for the text... hdc->DrawText(stc2wx(s, len), rc.left, ybase - font.ascent); - hdc->SetBackgroundMode(wxSOLID); + hdc->SetBackgroundMode(wxBRUSHSTYLE_SOLID); } @@ -403,8 +547,12 @@ void SurfaceImpl::MeasureWidths(Font &font, const char *s, int len, int *positio #else // If not unicode then just use the widths we have +#if wxUSE_STL + std::copy(tpos.begin(), tpos.end(), positions); +#else memcpy(positions, tpos.begin(), len * sizeof(int)); #endif +#endif } @@ -538,13 +686,11 @@ void Window::Show(bool show) { void Window::InvalidateAll() { GETWIN(id)->Refresh(false); - wxWakeUpIdle(); } void Window::InvalidateRectangle(PRectangle rc) { wxRect r = wxRectFromPRectangle(rc); GETWIN(id)->Refresh(false, &r); - wxWakeUpIdle(); } void Window::SetFont(Font &font) { @@ -552,7 +698,7 @@ void Window::SetFont(Font &font) { } void Window::SetCursor(Cursor curs) { - int cursorId; + wxStockCursor cursorId; switch (curs) { case cursorText: @@ -583,20 +729,34 @@ void Window::SetCursor(Cursor curs) { cursorId = wxCURSOR_ARROW; break; } -#ifdef __WXMOTIF__ - wxCursor wc = wxStockCursor(cursorId) ; -#else - wxCursor wc = wxCursor(cursorId) ; -#endif - GETWIN(id)->SetCursor(wc); + + wxCursor wc = wxCursor(cursorId); + if(curs != cursorLast) + { + GETWIN(id)->SetCursor(wc); + cursorLast = curs; + } } void Window::SetTitle(const char *s) { - GETWIN(id)->SetTitle(stc2wx(s)); + GETWIN(id)->SetLabel(stc2wx(s)); } +// Returns rectangle of monitor pt is on +PRectangle Window::GetMonitorRect(Point pt) { + wxRect rect; + if (! id) return PRectangle(); +#if wxUSE_DISPLAY + // Get the display the point is found on + int n = wxDisplay::GetFromPoint(wxPoint(pt.x, pt.y)); + wxDisplay dpy(n == wxNOT_FOUND ? 0 : n); + rect = dpy.GetGeometry(); +#endif + return PRectangleFromwxRect(rect); +} + //---------------------------------------------------------------------- // Helper classes for ListBox @@ -658,8 +818,8 @@ END_EVENT_TABLE() -#if wxUSE_POPUPWIN //----------------------------------- -#include +#if wxUSE_POPUPWIN //----------------------------------- +#include "wx/popupwin.h" // @@ -668,9 +828,9 @@ END_EVENT_TABLE() // implement wxPopupWindow for the Mac!!) // // In the meantime, be careful to duplicate any changes as needed... -// - -// A popup window to place the wxSTCListBox upon +// + +// A popup window to place the wxSTCListBox upon class wxSTCListBoxWin : public wxPopupWindow { private: @@ -678,12 +838,13 @@ private: CallBackAction doubleClickAction; void* doubleClickActionData; public: - wxSTCListBoxWin(wxWindow* parent, wxWindowID id) : + wxSTCListBoxWin(wxWindow* parent, wxWindowID id, Point WXUNUSED(location)) : wxPopupWindow(parent, wxBORDER_NONE) { + SetBackgroundColour(*wxBLACK); // for our simple border - lv = new wxSTCListBox(parent, id, wxDefaultPosition, wxDefaultSize, + lv = new wxSTCListBox(parent, id, wxPoint(-50,-50), wxDefaultSize, wxLC_REPORT | wxLC_SINGLE_SEL | wxLC_NO_HEADER | wxBORDER_NONE); lv->SetCursor(wxCursor(wxCURSOR_ARROW)); lv->InsertColumn(0, wxEmptyString); @@ -694,7 +855,7 @@ public: // "right" to the user. But since the wxPopupWindow or its children // can't receive focus then we have to pull a fast one and temporarily // parent the listctrl on the STC window and then call SetFocus and - // then reparent it back to the popup. + // then reparent it back to the popup. lv->SetFocus(); lv->Reparent(this); #ifdef __WXMSW__ @@ -785,19 +946,30 @@ BEGIN_EVENT_TABLE(wxSTCListBoxWin, wxPopupWindow) EVT_LIST_ITEM_ACTIVATED(wxID_ANY, wxSTCListBoxWin::OnActivate) END_EVENT_TABLE() - -#else // wxUSE_POPUPWIN ----------------------------------- -// A normal window to place the wxSTCListBox upon. -class wxSTCListBoxWin : public wxWindow { +#else // !wxUSE_POPUPWIN ----------------------------------- +#include "wx/frame.h" + +// A normal window to place the wxSTCListBox upon, but make it behave as much +// like a wxPopupWindow as possible +class wxSTCListBoxWin : public wxFrame { private: wxListView* lv; CallBackAction doubleClickAction; void* doubleClickActionData; public: - wxSTCListBoxWin(wxWindow* parent, wxWindowID id) : - wxWindow(parent, id, wxDefaultPosition, wxSize(0,0), wxSIMPLE_BORDER ) + wxSTCListBoxWin(wxWindow* parent, wxWindowID id, Point location) : + wxFrame(parent, id, wxEmptyString, wxPoint(location.x, location.y), wxSize(0,0), + wxFRAME_NO_TASKBAR + | wxFRAME_FLOAT_ON_PARENT +#ifdef __WXMAC__ + | wxPOPUP_WINDOW + | wxNO_BORDER +#else + | wxSIMPLE_BORDER +#endif + ) { lv = new wxSTCListBox(this, id, wxDefaultPosition, wxDefaultSize, @@ -818,7 +990,8 @@ public: // messages/events for the list control when Scintilla wants to // close it, so do a pending delete of it instead of destroying // immediately. - bool Destroy() { + bool Destroy() + { #ifdef __WXMAC__ // The bottom edge of this window is not getting properly // refreshed upon deletion, so help it out... @@ -833,7 +1006,8 @@ public: } - int IconWidth() { + int IconWidth() + { wxImageList* il = lv->GetImageList(wxIMAGE_LIST_SMALL); if (il != NULL) { int w, h; @@ -844,18 +1018,22 @@ public: } - void SetDoubleClickAction(CallBackAction action, void *data) { + void SetDoubleClickAction(CallBackAction action, void *data) + { doubleClickAction = action; doubleClickActionData = data; } - void OnFocus(wxFocusEvent& event) { + void OnFocus(wxFocusEvent& event) + { + ActivateParent(); GetParent()->SetFocus(); event.Skip(); } - void OnSize(wxSizeEvent& event) { + void OnSize(wxSizeEvent& event) + { // resize the child wxSize sz = GetClientSize(); lv->SetSize(sz); @@ -866,15 +1044,44 @@ public: event.Skip(); } + void ActivateParent() + { + // Although we're a frame, we always want the parent to be active, so + // raise it whenever we get shown, focused, etc. + wxTopLevelWindow *frame = wxDynamicCast( + wxGetTopLevelParent(GetParent()), wxTopLevelWindow); + if (frame) + frame->Raise(); + } + + + virtual void DoSetSize(int x, int y, + int width, int height, + int sizeFlags = wxSIZE_AUTO) + { + // convert coords to screen coords since we're a top-level window + if (x != wxDefaultCoord) { + GetParent()->ClientToScreen(&x, NULL); + } + if (y != wxDefaultCoord) { + GetParent()->ClientToScreen(NULL, &y); + } + wxFrame::DoSetSize(x, y, width, height, sizeFlags); + } + + virtual bool Show(bool show = true) + { + bool rv = wxFrame::Show(show); + if (rv && show) + ActivateParent(); #ifdef __WXMAC__ - virtual bool Show(bool show = true) { - bool rv = wxWindow::Show(show); GetParent()->Refresh(false); +#endif return rv; } -#endif - - void OnActivate(wxListEvent& WXUNUSED(event)) { + + void OnActivate(wxListEvent& WXUNUSED(event)) + { doubleClickAction(doubleClickActionData); } @@ -910,7 +1117,8 @@ private: bool unicodeMode; int desiredVisibleRows; int aveCharWidth; - int maxStrWidth; + size_t maxStrWidth; + Point location; // Caret location at which the list is opened wxImageList* imgList; wxArrayInt* imgTypeMap; @@ -919,13 +1127,15 @@ public: ~ListBoxImpl(); virtual void SetFont(Font &font); - virtual void Create(Window &parent, int ctrlID, int lineHeight_, bool unicodeMode_); + virtual void Create(Window &parent, int ctrlID, Point location_, int lineHeight_, bool unicodeMode_); virtual void SetAverageCharWidth(int width); virtual void SetVisibleRows(int rows); + virtual int GetVisibleRows() const; virtual PRectangle GetDesiredRect(); virtual int CaretFromEdge(); virtual void Clear(); virtual void Append(char *s, int type = -1); + void Append(const wxString& text, int type); virtual int Length(); virtual void Select(int n); virtual int GetSelection(); @@ -934,7 +1144,7 @@ public: virtual void RegisterImage(int type, const char *xpm_data); virtual void ClearRegisteredImages(); virtual void SetDoubleClickAction(CallBackAction, void *); - + virtual void SetList(const char* list, char separator, char typesep); }; @@ -962,11 +1172,12 @@ void ListBoxImpl::SetFont(Font &font) { } -void ListBoxImpl::Create(Window &parent, int ctrlID, int lineHeight_, bool unicodeMode_) { +void ListBoxImpl::Create(Window &parent, int ctrlID, Point location_, int lineHeight_, bool unicodeMode_) { + location = location_; lineHeight = lineHeight_; unicodeMode = unicodeMode_; maxStrWidth = 0; - id = new wxSTCListBoxWin(GETWIN(parent.GetID()), ctrlID); + id = new wxSTCListBoxWin(GETWIN(parent.GetID()), ctrlID, location); if (imgList != NULL) GETLB(id)->SetImageList(imgList, wxIMAGE_LIST_SMALL); } @@ -982,10 +1193,14 @@ void ListBoxImpl::SetVisibleRows(int rows) { } +int ListBoxImpl::GetVisibleRows() const { + return desiredVisibleRows; +} + PRectangle ListBoxImpl::GetDesiredRect() { // wxListCtrl doesn't have a DoGetBestSize, so instead we kept track of // the max size in Append and calculate it here... - int maxw = maxStrWidth; + int maxw = maxStrWidth * aveCharWidth; int maxh ; // give it a default if there are no lines, and/or add a bit more @@ -1031,18 +1246,37 @@ void ListBoxImpl::Clear() { void ListBoxImpl::Append(char *s, int type) { - wxString text = stc2wx(s); + Append(stc2wx(s), type); +} + +void ListBoxImpl::Append(const wxString& text, int type) { long count = GETLB(id)->GetItemCount(); long itemID = GETLB(id)->InsertItem(count, wxEmptyString); + long idx = -1; GETLB(id)->SetItem(itemID, 1, text); - int itemWidth = 0; - GETLB(id)->GetTextExtent(text, &itemWidth, NULL); - maxStrWidth = wxMax(maxStrWidth, itemWidth); + maxStrWidth = wxMax(maxStrWidth, text.length()); if (type != -1) { wxCHECK_RET(imgTypeMap, wxT("Unexpected NULL imgTypeMap")); - long idx = imgTypeMap->Item(type); - GETLB(id)->SetItemImage(itemID, idx, idx); + idx = imgTypeMap->Item(type); } + GETLB(id)->SetItemImage(itemID, idx, idx); +} + +void ListBoxImpl::SetList(const char* list, char separator, char typesep) { + GETLB(id)->Freeze(); + Clear(); + wxStringTokenizer tkzr(stc2wx(list), (wxChar)separator); + while ( tkzr.HasMoreTokens() ) { + wxString token = tkzr.GetNextToken(); + long type = -1; + int pos = token.Find(typesep); + if (pos != -1) { + token.Mid(pos+1).ToLong(&type); + token.Truncate(pos); + } + Append(token, (int)type); + } + GETLB(id)->Thaw(); } @@ -1057,7 +1291,7 @@ void ListBoxImpl::Select(int n) { n = 0; select = false; } - GETLB(id)->Focus(n); + GETLB(id)->EnsureVisible(n); GETLB(id)->Select(n, select); } @@ -1125,7 +1359,6 @@ void ListBoxImpl::SetDoubleClickAction(CallBackAction action, void *data) { } - ListBox::ListBox() { } @@ -1195,9 +1428,6 @@ unsigned int Platform::DoubleClickTime() { bool Platform::MouseButtonBounce() { return false; } -void Platform::DebugDisplay(const char *s) { - wxLogDebug(stc2wx(s)); -} bool Platform::IsKeyDown(int WXUNUSED(key)) { return false; // I don't think we'll need this. @@ -1218,7 +1448,7 @@ long Platform::SendScintillaPointer(WindowID w, void *lParam) { wxStyledTextCtrl* stc = (wxStyledTextCtrl*)w; - return stc->SendMsg(msg, wParam, (long)lParam); + return stc->SendMsg(msg, wParam, (wxIntPtr)lParam); } @@ -1238,7 +1468,15 @@ int Platform::Maximum(int a, int b) { return b; } -#define TRACE +//#define TRACE + +void Platform::DebugDisplay(const char *s) { +#ifdef TRACE + wxLogDebug(stc2wx(s)); +#else + wxUnusedVar(s); +#endif +} void Platform::DebugPrintf(const char *format, ...) { #ifdef TRACE @@ -1248,6 +1486,8 @@ void Platform::DebugPrintf(const char *format, ...) { vsprintf(buffer,format,pArguments); va_end(pArguments); Platform::DebugDisplay(buffer); +#else + wxUnusedVar(format); #endif } @@ -1261,6 +1501,7 @@ bool Platform::ShowAssertionPopUps(bool assertionPopUps_) { } void Platform::Assert(const char *c, const char *file, int line) { +#ifdef TRACE char buffer[2000]; sprintf(buffer, "Assertion [%s] failed at %s %d", c, file, line); if (assertionPopUps) { @@ -1268,18 +1509,16 @@ void Platform::Assert(const char *c, const char *file, int line) { wxMessageBox(stc2wx(buffer), wxT("Assertion failure"), wxICON_HAND | wxOK); -// if (idButton == IDRETRY) { -// ::DebugBreak(); -// } else if (idButton == IDIGNORE) { -// // all OK -// } else { -// abort(); -// } } else { strcat(buffer, "\r\n"); Platform::DebugDisplay(buffer); abort(); } +#else + wxUnusedVar(c); + wxUnusedVar(file); + wxUnusedVar(line); +#endif } @@ -1308,11 +1547,20 @@ int Platform::DBCSCharMaxLength() { //---------------------------------------------------------------------- ElapsedTime::ElapsedTime() { - wxStartTimer(); + wxLongLong localTime = wxGetLocalTimeMillis(); + littleBit = localTime.GetLo(); + bigBit = localTime.GetHi(); } double ElapsedTime::Duration(bool reset) { - double result = wxGetElapsedTime(reset); + wxLongLong prevTime(bigBit, littleBit); + wxLongLong localTime = wxGetLocalTimeMillis(); + if(reset) { + littleBit = localTime.GetLo(); + bigBit = localTime.GetHi(); + } + wxLongLong duration = localTime - prevTime; + double result = duration.ToDouble(); result /= 1000.0; return result; } @@ -1332,10 +1580,10 @@ wxString stc2wx(const char* str, size_t len) if (!len) return wxEmptyString; - size_t wclen = UCS2Length(str, len); + size_t wclen = UTF16Length(str, len); wxWCharBuffer buffer(wclen+1); - size_t actualLen = UCS2FromUTF8(str, len, buffer.data(), wclen+1); + size_t actualLen = UTF16FromUTF8(str, len, buffer.data(), wclen+1); return wxString(buffer.data(), actualLen); } @@ -1354,7 +1602,7 @@ const wxWX2MBbuf wx2stc(const wxString& str) size_t len = UTF8Length(wcstr, wclen); wxCharBuffer buffer(len+1); - UTF8FromUCS2(wcstr, wclen, buffer.data(), len); + UTF8FromUTF16(wcstr, wclen, buffer.data(), len); // TODO check NULL termination!! @@ -1363,8 +1611,4 @@ const wxWX2MBbuf wx2stc(const wxString& str) #endif - - - - - +#endif // wxUSE_STC