X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/732281950a766e94828787ff571f73fecb83949e..c37b0f0907b07878551a00165b0ad323bd2ccdaf:/src/richtext/richtextctrl.cpp diff --git a/src/richtext/richtextctrl.cpp b/src/richtext/richtextctrl.cpp index 9b40064ee8..69151389e1 100644 --- a/src/richtext/richtextctrl.cpp +++ b/src/richtext/richtextctrl.cpp @@ -4,7 +4,6 @@ // Author: Julian Smart // Modified by: // Created: 2005-09-30 -// RCS-ID: $Id$ // Copyright: (c) Julian Smart // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// @@ -49,26 +48,26 @@ #include "wx/app.h" WX_CHECK_BUILD_OPTIONS("wxRichTextCtrl") -wxDEFINE_EVENT( wxEVT_COMMAND_RICHTEXT_LEFT_CLICK, wxRichTextEvent ); -wxDEFINE_EVENT( wxEVT_COMMAND_RICHTEXT_MIDDLE_CLICK, wxRichTextEvent ); -wxDEFINE_EVENT( wxEVT_COMMAND_RICHTEXT_RIGHT_CLICK, wxRichTextEvent ); -wxDEFINE_EVENT( wxEVT_COMMAND_RICHTEXT_LEFT_DCLICK, wxRichTextEvent ); -wxDEFINE_EVENT( wxEVT_COMMAND_RICHTEXT_RETURN, wxRichTextEvent ); -wxDEFINE_EVENT( wxEVT_COMMAND_RICHTEXT_CHARACTER, wxRichTextEvent ); -wxDEFINE_EVENT( wxEVT_COMMAND_RICHTEXT_DELETE, wxRichTextEvent ); - -wxDEFINE_EVENT( wxEVT_COMMAND_RICHTEXT_STYLESHEET_REPLACING, wxRichTextEvent ); -wxDEFINE_EVENT( wxEVT_COMMAND_RICHTEXT_STYLESHEET_REPLACED, wxRichTextEvent ); -wxDEFINE_EVENT( wxEVT_COMMAND_RICHTEXT_STYLESHEET_CHANGING, wxRichTextEvent ); -wxDEFINE_EVENT( wxEVT_COMMAND_RICHTEXT_STYLESHEET_CHANGED, wxRichTextEvent ); - -wxDEFINE_EVENT( wxEVT_COMMAND_RICHTEXT_CONTENT_INSERTED, wxRichTextEvent ); -wxDEFINE_EVENT( wxEVT_COMMAND_RICHTEXT_CONTENT_DELETED, wxRichTextEvent ); -wxDEFINE_EVENT( wxEVT_COMMAND_RICHTEXT_STYLE_CHANGED, wxRichTextEvent ); -wxDEFINE_EVENT( wxEVT_COMMAND_RICHTEXT_PROPERTIES_CHANGED, wxRichTextEvent ); -wxDEFINE_EVENT( wxEVT_COMMAND_RICHTEXT_SELECTION_CHANGED, wxRichTextEvent ); -wxDEFINE_EVENT( wxEVT_COMMAND_RICHTEXT_BUFFER_RESET, wxRichTextEvent ); -wxDEFINE_EVENT( wxEVT_COMMAND_RICHTEXT_FOCUS_OBJECT_CHANGED, wxRichTextEvent ); +wxDEFINE_EVENT( wxEVT_RICHTEXT_LEFT_CLICK, wxRichTextEvent ); +wxDEFINE_EVENT( wxEVT_RICHTEXT_MIDDLE_CLICK, wxRichTextEvent ); +wxDEFINE_EVENT( wxEVT_RICHTEXT_RIGHT_CLICK, wxRichTextEvent ); +wxDEFINE_EVENT( wxEVT_RICHTEXT_LEFT_DCLICK, wxRichTextEvent ); +wxDEFINE_EVENT( wxEVT_RICHTEXT_RETURN, wxRichTextEvent ); +wxDEFINE_EVENT( wxEVT_RICHTEXT_CHARACTER, wxRichTextEvent ); +wxDEFINE_EVENT( wxEVT_RICHTEXT_DELETE, wxRichTextEvent ); + +wxDEFINE_EVENT( wxEVT_RICHTEXT_STYLESHEET_REPLACING, wxRichTextEvent ); +wxDEFINE_EVENT( wxEVT_RICHTEXT_STYLESHEET_REPLACED, wxRichTextEvent ); +wxDEFINE_EVENT( wxEVT_RICHTEXT_STYLESHEET_CHANGING, wxRichTextEvent ); +wxDEFINE_EVENT( wxEVT_RICHTEXT_STYLESHEET_CHANGED, wxRichTextEvent ); + +wxDEFINE_EVENT( wxEVT_RICHTEXT_CONTENT_INSERTED, wxRichTextEvent ); +wxDEFINE_EVENT( wxEVT_RICHTEXT_CONTENT_DELETED, wxRichTextEvent ); +wxDEFINE_EVENT( wxEVT_RICHTEXT_STYLE_CHANGED, wxRichTextEvent ); +wxDEFINE_EVENT( wxEVT_RICHTEXT_PROPERTIES_CHANGED, wxRichTextEvent ); +wxDEFINE_EVENT( wxEVT_RICHTEXT_SELECTION_CHANGED, wxRichTextEvent ); +wxDEFINE_EVENT( wxEVT_RICHTEXT_BUFFER_RESET, wxRichTextEvent ); +wxDEFINE_EVENT( wxEVT_RICHTEXT_FOCUS_OBJECT_CHANGED, wxRichTextEvent ); #if wxRICHTEXT_USE_OWN_CARET @@ -149,6 +148,8 @@ private: wxRichTextCaretTimer m_timer; wxRichTextCtrl* m_richTextCtrl; bool m_refreshEnabled; + wxPen m_caretPen; + wxBrush m_caretBrush; }; #endif @@ -355,6 +356,7 @@ void wxRichTextCtrl::Init() m_selectionAnchorObject = NULL; m_selectionState = wxRichTextCtrlSelectionState_Normal; m_editable = true; + m_useVirtualAttributes = false; m_verticalScrollbarEnabled = true; m_caretAtLineStart = false; m_dragging = false; @@ -437,9 +439,6 @@ void wxRichTextCtrl::OnPaint(wxPaintEvent& WXUNUSED(event)) dc.SetFont(GetFont()); - // Paint the background - PaintBackground(dc); - wxRect drawingArea(GetUpdateRegion().GetBox()); drawingArea.SetPosition(GetUnscaledPoint(GetLogicalPoint(drawingArea.GetPosition()))); drawingArea.SetSize(GetUnscaledSize(drawingArea.GetSize())); @@ -458,6 +457,9 @@ void wxRichTextCtrl::OnPaint(wxPaintEvent& WXUNUSED(event)) SetupScrollbars(); } + // Paint the background + PaintBackground(dc); + wxRect clipRect(availableSpace); clipRect.x += GetBuffer().GetLeftMargin(); clipRect.y += GetBuffer().GetTopMargin(); @@ -690,7 +692,7 @@ void wxRichTextCtrl::OnLeftUp(wxMouseEvent& event) if ((hit != wxRICHTEXT_HITTEST_NONE) && !(hit & wxRICHTEXT_HITTEST_OUTSIDE)) { wxRichTextEvent cmdEvent( - wxEVT_COMMAND_RICHTEXT_LEFT_CLICK, + wxEVT_RICHTEXT_LEFT_CLICK, GetId()); cmdEvent.SetEventObject(this); cmdEvent.SetPosition(position); @@ -751,6 +753,14 @@ void wxRichTextCtrl::OnLeftUp(wxMouseEvent& event) /// Mouse-movements void wxRichTextCtrl::OnMoveMouse(wxMouseEvent& event) { + if (!event.Dragging() && m_dragging) + { + // We may have accidentally lost a mouse-up event, especially on Linux + m_dragging = false; + if (GetCapture() == this) + ReleaseMouse(); + } + #if wxUSE_DRAG_AND_DROP size_t distance = 0; if (m_preDrag || m_dragging) @@ -981,7 +991,7 @@ void wxRichTextCtrl::OnRightClick(wxMouseEvent& event) } wxRichTextEvent cmdEvent( - wxEVT_COMMAND_RICHTEXT_RIGHT_CLICK, + wxEVT_RICHTEXT_RIGHT_CLICK, GetId()); cmdEvent.SetEventObject(this); cmdEvent.SetPosition(position); @@ -996,7 +1006,7 @@ void wxRichTextCtrl::OnRightClick(wxMouseEvent& event) void wxRichTextCtrl::OnLeftDClick(wxMouseEvent& WXUNUSED(event)) { wxRichTextEvent cmdEvent( - wxEVT_COMMAND_RICHTEXT_LEFT_DCLICK, + wxEVT_RICHTEXT_LEFT_DCLICK, GetId()); cmdEvent.SetEventObject(this); cmdEvent.SetPosition(m_caretPosition+1); @@ -1012,7 +1022,7 @@ void wxRichTextCtrl::OnLeftDClick(wxMouseEvent& WXUNUSED(event)) void wxRichTextCtrl::OnMiddleClick(wxMouseEvent& event) { wxRichTextEvent cmdEvent( - wxEVT_COMMAND_RICHTEXT_MIDDLE_CLICK, + wxEVT_RICHTEXT_MIDDLE_CLICK, GetId()); cmdEvent.SetEventObject(this); cmdEvent.SetPosition(m_caretPosition+1); @@ -1188,7 +1198,7 @@ void wxRichTextCtrl::OnChar(wxKeyEvent& event) ScrollIntoView(m_caretPosition, WXK_RIGHT); wxRichTextEvent cmdEvent( - wxEVT_COMMAND_RICHTEXT_RETURN, + wxEVT_RICHTEXT_RETURN, GetId()); cmdEvent.SetEventObject(this); cmdEvent.SetFlags(flags); @@ -1198,7 +1208,7 @@ void wxRichTextCtrl::OnChar(wxKeyEvent& event) if (!GetEventHandler()->ProcessEvent(cmdEvent)) { // Generate conventional event - wxCommandEvent textEvent(wxEVT_COMMAND_TEXT_ENTER, GetId()); + wxCommandEvent textEvent(wxEVT_TEXT_ENTER, GetId()); InitCommandEvent(textEvent); GetEventHandler()->ProcessEvent(textEvent); @@ -1268,10 +1278,10 @@ void wxRichTextCtrl::OnChar(wxKeyEvent& event) ScrollIntoView(m_caretPosition, WXK_LEFT); - // Always send this event; wxEVT_COMMAND_RICHTEXT_CONTENT_DELETED will be sent only if there is an actual deletion. + // Always send this event; wxEVT_RICHTEXT_CONTENT_DELETED will be sent only if there is an actual deletion. { wxRichTextEvent cmdEvent( - wxEVT_COMMAND_RICHTEXT_DELETE, + wxEVT_RICHTEXT_DELETE, GetId()); cmdEvent.SetEventObject(this); cmdEvent.SetFlags(flags); @@ -1307,7 +1317,7 @@ void wxRichTextCtrl::OnChar(wxKeyEvent& event) } wxRichTextEvent cmdEvent( - wxEVT_COMMAND_RICHTEXT_CHARACTER, + wxEVT_RICHTEXT_CHARACTER, GetId()); cmdEvent.SetEventObject(this); cmdEvent.SetFlags(flags); @@ -1492,10 +1502,10 @@ bool wxRichTextCtrl::ProcessBackKey(wxKeyEvent& event, int flags) ScrollIntoView(m_caretPosition, WXK_LEFT); - // Always send this event; wxEVT_COMMAND_RICHTEXT_CONTENT_DELETED will be sent only if there is an actual deletion. + // Always send this event; wxEVT_RICHTEXT_CONTENT_DELETED will be sent only if there is an actual deletion. { wxRichTextEvent cmdEvent( - wxEVT_COMMAND_RICHTEXT_DELETE, + wxEVT_RICHTEXT_DELETE, GetId()); cmdEvent.SetEventObject(this); cmdEvent.SetFlags(flags); @@ -2082,6 +2092,7 @@ bool wxRichTextCtrl::MoveDown(int noLines, int flags) wxRichTextParagraphLayoutBox* container = GetFocusObject(); int hitTestFlags = wxRICHTEXT_HITTEST_NO_NESTED_OBJECTS|wxRICHTEXT_HITTEST_NO_FLOATING_OBJECTS|wxRICHTEXT_HITTEST_HONOUR_ATOMIC; + bool lineIsEmpty = false; if (notInThisObject) { // If we know we're navigating out of the current object, @@ -2102,7 +2113,11 @@ bool wxRichTextCtrl::MoveDown(int noLines, int flags) { wxRichTextLine* lineObj = GetFocusObject()->GetLineForVisibleLineNumber(newLine); if (lineObj) + { pt.y = lineObj->GetAbsolutePosition().y + 2; + if (lineObj->GetRange().GetStart() == lineObj->GetRange().GetEnd()) + lineIsEmpty = true; + } else return false; } @@ -2134,6 +2149,15 @@ bool wxRichTextCtrl::MoveDown(int noLines, int flags) } bool caretLineStart = true; + + // If the line is empty, there is only one possible position for the caret, + // so force the 'before' state so FindCaretPositionForCharacterPosition doesn't + // just return the same position. + if (lineIsEmpty) + { + hitTest &= ~wxRICHTEXT_HITTEST_AFTER; + hitTest |= wxRICHTEXT_HITTEST_BEFORE; + } long caretPosition = FindCaretPositionForCharacterPosition(newPos, hitTest, container, caretLineStart); long newSelEnd = caretPosition; bool extendSel; @@ -2640,7 +2664,7 @@ bool wxRichTextCtrl::RecreateBuffer(const wxSize& size) // ---------------------------------------------------------------------------- // file IO functions // ---------------------------------------------------------------------------- - +#if wxUSE_FFILE && wxUSE_STREAMS bool wxRichTextCtrl::DoLoadFile(const wxString& filename, int fileType) { SetFocusObject(& GetBuffer(), true); @@ -2682,6 +2706,7 @@ bool wxRichTextCtrl::DoSaveFile(const wxString& filename, int fileType) return false; } +#endif // wxUSE_FFILE && wxUSE_STREAMS // ---------------------------------------------------------------------------- // wxRichTextCtrl specific functionality @@ -2919,7 +2944,8 @@ void wxRichTextCtrl::DoWriteText(const wxString& value, int flags) wxString valueUnix = wxTextFile::Translate(value, wxTextFileType_Unix); GetFocusObject()->InsertTextWithUndo(& GetBuffer(), m_caretPosition+1, valueUnix, this, wxRICHTEXT_INSERT_WITH_PREVIOUS_PARAGRAPH_STYLE); - GetBuffer().Defragment(); + wxRichTextDrawingContext context(& GetBuffer()); + GetBuffer().Defragment(context); if ( flags & SetValue_SendEvent ) wxTextCtrl::SendTextUpdatedEvent(this); @@ -3238,13 +3264,14 @@ void wxRichTextCtrl::Replace(long from, long to, SetSelection(from, to); - wxRichTextAttr attr = GetDefaultStyle(); + wxRichTextAttr attr(GetDefaultStyle()); DeleteSelectedContent(); SetDefaultStyle(attr); - DoWriteText(value, SetValue_SelectionOnly); + if (!value.IsEmpty()) + DoWriteText(value, SetValue_SelectionOnly); EndBatchUndo(); } @@ -3732,7 +3759,9 @@ void wxRichTextCtrl::PositionCaret(wxRichTextParagraphLayoutBox* container) wxRect caretRect; if (GetCaretPositionForIndex(GetCaretPosition(), caretRect, container)) { +#if !wxRICHTEXT_USE_OWN_CARET caretRect = GetScaledRect(caretRect); +#endif int topMargin = (int) (0.5 + GetScale()*GetBuffer().GetTopMargin()); int bottomMargin = (int) (0.5 + GetScale()*GetBuffer().GetBottomMargin()); wxPoint newPt = caretRect.GetPosition(); @@ -3865,13 +3894,16 @@ bool wxRichTextCtrl::LayoutContent(bool onlyVisibleRect) PrepareDC(dc); dc.SetFont(GetFont()); + dc.SetUserScale(GetScale(), GetScale()); wxRichTextDrawingContext context(& GetBuffer()); - GetBuffer().Defragment(); + GetBuffer().Defragment(context); GetBuffer().UpdateRanges(); // If items were deleted, ranges need recalculation GetBuffer().Layout(dc, context, availableSpace, availableSpace, flags); GetBuffer().Invalidate(wxRICHTEXT_NONE); + dc.SetUserScale(1.0, 1.0); + if (!IsFrozen() && !onlyVisibleRect) SetupScrollbars(); } @@ -4524,7 +4556,7 @@ bool wxRichTextCtrl::SetFocusObject(wxRichTextParagraphLayoutBox* obj, bool setC SetDefaultStyleToCursorStyle(); wxRichTextEvent cmdEvent( - wxEVT_COMMAND_RICHTEXT_FOCUS_OBJECT_CHANGED, + wxEVT_RICHTEXT_FOCUS_OBJECT_CHANGED, GetId()); cmdEvent.SetEventObject(this); cmdEvent.SetPosition(m_caretPosition+1); @@ -4747,7 +4779,7 @@ void wxRichTextCaret::DoShow() { m_flashOn = true; - if (!m_timer.IsRunning()) + if (!m_timer.IsRunning() && GetBlinkTime() > 0) m_timer.Start(GetBlinkTime()); Refresh(); @@ -4771,8 +4803,9 @@ void wxRichTextCaret::DoMove() { if (m_richTextCtrl && m_refreshEnabled) { - wxRect rect(GetPosition(), GetSize()); - m_richTextCtrl->RefreshRect(rect, false); + wxRect rect(wxPoint(m_xOld, m_yOld), GetSize()); + wxRect scaledRect = m_richTextCtrl->GetScaledRect(rect); + m_richTextCtrl->RefreshRect(scaledRect, false); } } } @@ -4823,16 +4856,22 @@ void wxRichTextCaret::Refresh() if (m_richTextCtrl && m_refreshEnabled) { wxRect rect(GetPosition(), GetSize()); - m_richTextCtrl->RefreshRect(rect, false); + wxRect rectScaled = m_richTextCtrl->GetScaledRect(rect); + m_richTextCtrl->RefreshRect(rectScaled, false); } } void wxRichTextCaret::DoDraw(wxDC *dc) { - dc->SetPen( *wxBLACK_PEN ); - - dc->SetBrush(*(m_hasFocus ? wxBLACK_BRUSH : wxTRANSPARENT_BRUSH)); - dc->SetPen(*wxBLACK_PEN); + wxBrush brush(m_caretBrush); + wxPen pen(m_caretPen); + if (m_richTextCtrl && m_richTextCtrl->GetBasicStyle().HasTextColour()) + { + brush = wxBrush(m_richTextCtrl->GetBasicStyle().GetTextColour()); + pen = wxPen(m_richTextCtrl->GetBasicStyle().GetTextColour()); + } + dc->SetBrush((m_hasFocus ? brush : *wxTRANSPARENT_BRUSH)); + dc->SetPen(pen); wxPoint pt(m_x, m_y);