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
This commit is contained in:
Julian Smart 2008-04-29 09:10:32 +00:00
parent 0b822969a6
commit 1c13f06e4e
3 changed files with 256 additions and 16 deletions

View File

@ -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

View File

@ -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())

View File

@ -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