From 1c13f06e4e758005ab5a92459482bc0ffd25b145 Mon Sep 17 00:00:00 2001 From: Julian Smart Date: Tue, 29 Apr 2008 09:10:32 +0000 Subject: [PATCH] Added a wxRichTextCtrl-specific caret implementation in case of need git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@53409 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/richtext/richtextbuffer.h | 11 +- src/richtext/richtextbuffer.cpp | 6 + src/richtext/richtextctrl.cpp | 255 +++++++++++++++++++++++++-- 3 files changed, 256 insertions(+), 16 deletions(-) diff --git a/include/wx/richtext/richtextbuffer.h b/include/wx/richtext/richtextbuffer.h index c5e4fb68b4..ea9a405e6f 100644 --- a/include/wx/richtext/richtextbuffer.h +++ b/include/wx/richtext/richtextbuffer.h @@ -74,6 +74,14 @@ #define wxRichTextAttr wxTextAttr #define wxTextAttrEx wxTextAttr +// Setting wxRICHTEXT_USE_OWN_CARET to 1 implements a non-flashing +// cursor reliably without using wxClientDC in case there +// are platform-specific problems with the generic caret. +#define wxRICHTEXT_USE_OWN_CARET 0 + +// Switch off for binary compatibility, on for faster drawing +#define wxRICHTEXT_USE_OPTIMIZED_LINE_DRAWING 1 + /*! * Special characters */ @@ -210,9 +218,6 @@ class WXDLLIMPEXP_FWD_RICHTEXT wxRichTextBuffer; #define wxSCRIPT_MUL_FACTOR 1.5 -// Leave on for faster drawing, by storing the length of each object in a line -#define wxRICHTEXT_USE_OPTIMIZED_LINE_DRAWING 1 - /*! * wxRichTextFontTable * Manages quick access to a pool of fonts for rendering rich text diff --git a/src/richtext/richtextbuffer.cpp b/src/richtext/richtextbuffer.cpp index b6b9fcf674..92e0577424 100644 --- a/src/richtext/richtextbuffer.cpp +++ b/src/richtext/richtextbuffer.cpp @@ -6922,6 +6922,9 @@ void wxRichTextAction::UpdateAppearance(long caretPosition, bool sendUpdateEvent #endif m_ctrl->Refresh(false); +#if wxRICHTEXT_USE_OWN_CARET + m_ctrl->PositionCaret(); +#endif if (sendUpdateEvent) wxTextCtrl::SendTextUpdatedEvent(m_ctrl); } @@ -7071,6 +7074,9 @@ bool wxRichTextImage::GetRangeSize(const wxRichTextRange& range, wxSize& size, i if (!range.IsWithin(GetRange())) return false; + if (!m_image.Ok()) + ((wxRichTextImage*) this)->LoadFromBlock(); + if (partialExtents) { if (m_image.Ok()) diff --git a/src/richtext/richtextctrl.cpp b/src/richtext/richtextctrl.cpp index 61ff087e2b..c0ba3cbd98 100644 --- a/src/richtext/richtextctrl.cpp +++ b/src/richtext/richtextctrl.cpp @@ -56,6 +56,69 @@ DEFINE_EVENT_TYPE(wxEVT_COMMAND_RICHTEXT_STYLE_CHANGED) DEFINE_EVENT_TYPE(wxEVT_COMMAND_RICHTEXT_SELECTION_CHANGED) DEFINE_EVENT_TYPE(wxEVT_COMMAND_RICHTEXT_BUFFER_RESET) +#if wxRICHTEXT_USE_OWN_CARET + +/*! + * wxRichTextCaret + * + * This implements a non-flashing cursor in case there + * are platform-specific problems with the generic caret. + * wxRICHTEXT_USE_OWN_CARET is set in richtextbuffer.h. + */ + +class wxRichTextCaret: public wxCaret +{ +public: + // ctors + // ----- + // default - use Create() + wxRichTextCaret() { Init(); } + // creates a block caret associated with the given window + wxRichTextCaret(wxRichTextCtrl *window, int width, int height) + : wxCaret(window, width, height) { Init(); m_richTextCtrl = window; } + wxRichTextCaret(wxRichTextCtrl *window, const wxSize& size) + : wxCaret(window, size) { Init(); m_richTextCtrl = window; } + + virtual ~wxRichTextCaret(); + + // implementation + // -------------- + + // called by wxWindow (not using the event tables) + virtual void OnSetFocus(); + virtual void OnKillFocus(); + + // draw the caret on the given DC + void DoDraw(wxDC *dc); + + // get the visible count + int GetVisibleCount() const { return m_countVisible; } + + // delay repositioning + bool GetNeedsUpdate() const { return m_needsUpdate; } + void SetNeedsUpdate(bool needsUpdate = true ) { m_needsUpdate = needsUpdate; } + +protected: + virtual void DoShow(); + virtual void DoHide(); + virtual void DoMove(); + virtual void DoSize(); + + // refresh the caret + void Refresh(); + +private: + void Init(); + + int m_xOld, + m_yOld; + bool m_hasFocus; // true => our window has focus + bool m_needsUpdate; // must be repositioned + + wxRichTextCtrl* m_richTextCtrl; +}; +#endif + IMPLEMENT_CLASS( wxRichTextCtrl, wxControl ) IMPLEMENT_CLASS( wxRichTextEvent, wxNotifyEvent ) @@ -168,8 +231,11 @@ bool wxRichTextCtrl::Create( wxWindow* parent, wxWindowID id, const wxString& va GetBuffer().Reset(); GetBuffer().SetRichTextCtrl(this); +#if wxRICHTEXT_USE_OWN_CARET + SetCaret(new wxRichTextCaret(this, wxRICHTEXT_DEFAULT_CARET_WIDTH, 16)); +#else SetCaret(new wxCaret(this, wxRICHTEXT_DEFAULT_CARET_WIDTH, 16)); - GetCaret()->Show(); +#endif // Tell the sizers to use the given or best size SetInitialSize(size); @@ -250,8 +316,10 @@ void wxRichTextCtrl::Clear() /// Painting void wxRichTextCtrl::OnPaint(wxPaintEvent& WXUNUSED(event)) { - if (GetCaret() && GetCaret()->IsVisible()) +#if !wxRICHTEXT_USE_OWN_CARET + if (GetCaret() && !IsFrozen()) GetCaret()->Hide(); +#endif { #if wxRICHTEXT_BUFFERED_PAINTING @@ -284,12 +352,19 @@ void wxRichTextCtrl::OnPaint(wxPaintEvent& WXUNUSED(event)) } GetBuffer().Draw(dc, GetBuffer().GetRange(), GetInternalSelectionRange(), drawingArea, 0 /* descent */, 0 /* flags */); +#if wxRICHTEXT_USE_OWN_CARET + if (GetCaret()->IsVisible()) + { + ((wxRichTextCaret*) GetCaret())->DoDraw(& dc); + } +#endif } - if (GetCaret() && !GetCaret()->IsVisible()) +#if !wxRICHTEXT_USE_OWN_CARET + if (GetCaret()) GetCaret()->Show(); - PositionCaret(); +#endif } // Empty implementation, to prevent flicker @@ -301,22 +376,33 @@ void wxRichTextCtrl::OnSetFocus(wxFocusEvent& WXUNUSED(event)) { if (GetCaret()) { - if (!GetCaret()->IsVisible()) - GetCaret()->Show(); +#if !wxRICHTEXT_USE_OWN_CARET PositionCaret(); +#endif + GetCaret()->Show(); } - // if (!IsFrozen()) - // Refresh(false); +#if defined(__WXGTK__) && !wxRICHTEXT_USE_OWN_CARET + // Work around dropouts when control is focused + if (!IsFrozen()) + { + Refresh(false); + } +#endif } void wxRichTextCtrl::OnKillFocus(wxFocusEvent& WXUNUSED(event)) { - if (GetCaret() && GetCaret()->IsVisible()) + if (GetCaret()) GetCaret()->Hide(); - // if (!IsFrozen()) - // Refresh(false); +#if defined(__WXGTK__) && !wxRICHTEXT_USE_OWN_CARET + // Work around dropouts when control is focused + if (!IsFrozen()) + { + Refresh(false); + } +#endif } void wxRichTextCtrl::OnCaptureLost(wxMouseCaptureLostEvent& WXUNUSED(event)) @@ -1138,7 +1224,9 @@ bool wxRichTextCtrl::ScrollIntoView(long position, int keyCode) } } +#if !wxRICHTEXT_USE_OWN_CARET if (scrolled) +#endif PositionCaret(); return scrolled; @@ -1749,6 +1837,15 @@ void wxRichTextCtrl::OnSize(wxSizeEvent& event) /// Idle-time processing void wxRichTextCtrl::OnIdle(wxIdleEvent& event) { +#if wxRICHTEXT_USE_OWN_CARET + if (((wxRichTextCaret*) GetCaret())->GetNeedsUpdate()) + { + ((wxRichTextCaret*) GetCaret())->SetNeedsUpdate(false); + PositionCaret(); + GetCaret()->Show(); + } +#endif + const int layoutInterval = wxRICHTEXT_DEFAULT_LAYOUT_INTERVAL; if (m_fullLayoutRequired && (wxGetLocalTimeMillis() > (m_fullLayoutTime + layoutInterval))) @@ -1774,7 +1871,14 @@ void wxRichTextCtrl::OnIdle(wxIdleEvent& event) /// Scrolling void wxRichTextCtrl::OnScroll(wxScrollWinEvent& event) { - // Not used +#if wxRICHTEXT_USE_OWN_CARET + if (!((wxRichTextCaret*) GetCaret())->GetNeedsUpdate()) + { + GetCaret()->Hide(); + ((wxRichTextCaret*) GetCaret())->SetNeedsUpdate(); + } +#endif + event.Skip(); } @@ -2694,8 +2798,11 @@ void wxRichTextCtrl::PositionCaret() wxPoint pt = GetPhysicalPoint(newPt); if (GetCaret()->GetPosition() != pt || GetCaret()->GetSize() != newSz) { + GetCaret()->Hide(); + if (GetCaret()->GetSize() != newSz) + GetCaret()->SetSize(newSz); GetCaret()->Move(pt); - GetCaret()->SetSize(newSz); + GetCaret()->Show(); } } } @@ -3237,5 +3344,127 @@ bool wxRichTextCtrl::RefreshForSelectionChange(const wxRichTextRange& oldSelecti return true; } +#if wxRICHTEXT_USE_OWN_CARET + +// ---------------------------------------------------------------------------- +// initialization and destruction +// ---------------------------------------------------------------------------- + +void wxRichTextCaret::Init() +{ + m_hasFocus = true; + + m_xOld = + m_yOld = -1; + m_richTextCtrl = NULL; + m_needsUpdate = false; +} + +wxRichTextCaret::~wxRichTextCaret() +{ +} + +// ---------------------------------------------------------------------------- +// showing/hiding/moving the caret (base class interface) +// ---------------------------------------------------------------------------- + +void wxRichTextCaret::DoShow() +{ + Refresh(); +} + +void wxRichTextCaret::DoHide() +{ + Refresh(); +} + +void wxRichTextCaret::DoMove() +{ + if (IsVisible()) + { + Refresh(); + + if (m_xOld != -1 && m_yOld != -1) + { + if (m_richTextCtrl) + { + wxRect rect(GetPosition(), GetSize()); + m_richTextCtrl->RefreshRect(rect, false); + } + } + } + + m_xOld = m_x; + m_yOld = m_y; +} + +void wxRichTextCaret::DoSize() +{ + int countVisible = m_countVisible; + if (countVisible > 0) + { + m_countVisible = 0; + DoHide(); + } + + if (countVisible > 0) + { + m_countVisible = countVisible; + DoShow(); + } +} + +// ---------------------------------------------------------------------------- +// handling the focus +// ---------------------------------------------------------------------------- + +void wxRichTextCaret::OnSetFocus() +{ + m_hasFocus = true; + + if ( IsVisible() ) + Refresh(); +} + +void wxRichTextCaret::OnKillFocus() +{ + m_hasFocus = false; +} + +// ---------------------------------------------------------------------------- +// drawing the caret +// ---------------------------------------------------------------------------- + +void wxRichTextCaret::Refresh() +{ + if (m_richTextCtrl) + { + wxRect rect(GetPosition(), GetSize()); + m_richTextCtrl->RefreshRect(rect, false); + } +} + +void wxRichTextCaret::DoDraw(wxDC *dc) +{ + dc->SetPen( *wxBLACK_PEN ); + + dc->SetBrush(*(m_hasFocus ? wxBLACK_BRUSH : wxTRANSPARENT_BRUSH)); + dc->SetPen(*wxBLACK_PEN); + + // VZ: unfortunately, the rectangle comes out a pixel smaller when this is + // done under wxGTK - no idea why + //dc->SetLogicalFunction(wxINVERT); + + wxPoint pt(m_x, m_y); + + if (m_richTextCtrl) + { + pt = m_richTextCtrl->GetLogicalPoint(pt); + } + dc->DrawRectangle(pt.x, pt.y, m_width, m_height); +} +#endif + // wxRICHTEXT_USE_OWN_CARET + #endif // wxUSE_RICHTEXT -- 2.47.2