X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/b33e0c2c5b51be1154da8f57dc808d2f1dd8ac45..76c67131022c84eb8c424adea124620da6b0d03e:/src/richtext/richtextctrl.cpp diff --git a/src/richtext/richtextctrl.cpp b/src/richtext/richtextctrl.cpp index dfd6c701be..e8eff5d801 100644 --- a/src/richtext/richtextctrl.cpp +++ b/src/richtext/richtextctrl.cpp @@ -65,6 +65,7 @@ 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 ); @@ -125,6 +126,9 @@ public: void Notify(); + bool GetRefreshEnabled() const { return m_refreshEnabled; } + void EnableRefresh(bool b) { m_refreshEnabled = b; } + protected: virtual void DoShow(); virtual void DoHide(); @@ -144,6 +148,7 @@ private: bool m_flashOn; wxRichTextCaretTimer m_timer; wxRichTextCtrl* m_richTextCtrl; + bool m_refreshEnabled; }; #endif @@ -227,8 +232,6 @@ wxRichTextCtrl::wxRichTextCtrl(wxWindow* parent, { Init(); Create(parent, id, value, pos, size, style, validator, name); - - SetDropTarget(new wxRichTextDropTarget(this)); } /// Creation @@ -328,6 +331,10 @@ bool wxRichTextCtrl::Create( wxWindow* parent, wxWindowID id, const wxString& va m_contextMenu->AppendSeparator(); m_contextMenu->Append(wxID_RICHTEXT_PROPERTIES1, _("&Properties")); +#if wxUSE_DRAG_AND_DROP + SetDropTarget(new wxRichTextDropTarget(this)); +#endif + return true; } @@ -349,9 +356,12 @@ void wxRichTextCtrl::Init() m_selectionAnchorObject = NULL; m_selectionState = wxRichTextCtrlSelectionState_Normal; m_editable = true; + m_verticalScrollbarEnabled = true; m_caretAtLineStart = false; m_dragging = false; +#if wxUSE_DRAG_AND_DROP m_preDrag = false; +#endif m_fullLayoutRequired = false; m_fullLayoutTime = 0; m_fullLayoutSavedPosition = 0; @@ -406,6 +416,11 @@ void wxRichTextCtrl::OnPaint(wxPaintEvent& WXUNUSED(event)) #if !wxRICHTEXT_USE_OWN_CARET if (GetCaret() && !IsFrozen()) GetCaret()->Hide(); +#else + // Stop the caret refreshing the control from within the + // paint handler + if (GetCaret()) + ((wxRichTextCaret*) GetCaret())->EnableRefresh(false); #endif { @@ -431,9 +446,10 @@ void wxRichTextCtrl::OnPaint(wxPaintEvent& WXUNUSED(event)) drawingArea.SetPosition(GetLogicalPoint(drawingArea.GetPosition())); wxRect availableSpace(GetClientSize()); + wxRichTextDrawingContext context(& GetBuffer()); if (GetBuffer().IsDirty()) { - GetBuffer().Layout(dc, availableSpace, wxRICHTEXT_FIXED_WIDTH|wxRICHTEXT_VARIABLE_HEIGHT); + GetBuffer().Layout(dc, context, availableSpace, availableSpace, wxRICHTEXT_FIXED_WIDTH|wxRICHTEXT_VARIABLE_HEIGHT); GetBuffer().Invalidate(wxRICHTEXT_NONE); SetupScrollbars(); } @@ -450,7 +466,7 @@ void wxRichTextCtrl::OnPaint(wxPaintEvent& WXUNUSED(event)) if ((GetExtraStyle() & wxRICHTEXT_EX_NO_GUIDELINES) == 0) flags |= wxRICHTEXT_DRAW_GUIDELINES; - GetBuffer().Draw(dc, GetBuffer().GetOwnRange(), GetSelection(), drawingArea, 0 /* descent */, flags); + GetBuffer().Draw(dc, context, GetBuffer().GetOwnRange(), GetSelection(), drawingArea, 0 /* descent */, flags); dc.DestroyClippingRegion(); @@ -460,6 +476,7 @@ void wxRichTextCtrl::OnPaint(wxPaintEvent& WXUNUSED(event)) #if wxRICHTEXT_USE_OWN_CARET if (GetCaret()->IsVisible()) { + PositionCaret(); ((wxRichTextCaret*) GetCaret())->DoDraw(& dc); } #endif @@ -470,10 +487,8 @@ void wxRichTextCtrl::OnPaint(wxPaintEvent& WXUNUSED(event)) GetCaret()->Show(); PositionCaret(); #else -#if !defined(__WXMAC__) - // Causes caret dropouts on Mac - PositionCaret(); -#endif + if (GetCaret()) + ((wxRichTextCaret*) GetCaret())->EnableRefresh(true); #endif } @@ -560,7 +575,8 @@ void wxRichTextCtrl::OnLeftClick(wxMouseEvent& event) long position = 0; wxRichTextObject* hitObj = NULL; wxRichTextObject* contextObj = NULL; - int hit = GetBuffer().HitTest(dc, event.GetLogicalPosition(dc), position, & hitObj, & contextObj); + wxRichTextDrawingContext context(& GetBuffer()); + int hit = GetBuffer().HitTest(dc, context, event.GetLogicalPosition(dc), position, & hitObj, & contextObj); #if wxUSE_DRAG_AND_DROP // If there's no selection, or we're not inside it, this isn't an attempt to initiate Drag'n'Drop @@ -626,8 +642,9 @@ void wxRichTextCtrl::OnLeftUp(wxMouseEvent& event) wxPoint logicalPt = event.GetLogicalPosition(dc); wxRichTextObject* hitObj = NULL; wxRichTextObject* contextObj = NULL; + wxRichTextDrawingContext context(& GetBuffer()); // Only get objects at this level, not nested, because otherwise we couldn't swipe text at a single level. - int hit = GetFocusObject()->HitTest(dc, logicalPt, position, & hitObj, & contextObj, wxRICHTEXT_HITTEST_NO_NESTED_OBJECTS); + int hit = GetFocusObject()->HitTest(dc, context, logicalPt, position, & hitObj, & contextObj, wxRICHTEXT_HITTEST_NO_NESTED_OBJECTS); #if wxUSE_DRAG_AND_DROP if (m_preDrag) @@ -639,7 +656,7 @@ void wxRichTextCtrl::OnLeftUp(wxMouseEvent& event) long position = 0; wxRichTextObject* hitObj = NULL; wxRichTextObject* contextObj = NULL; - int hit = GetBuffer().HitTest(dc, event.GetLogicalPosition(dc), position, & hitObj, & contextObj); + int hit = GetBuffer().HitTest(dc, context, event.GetLogicalPosition(dc), position, & hitObj, & contextObj); wxRichTextParagraphLayoutBox* oldFocusObject = GetFocusObject(); wxRichTextParagraphLayoutBox* container = wxDynamicCast(contextObj, wxRichTextParagraphLayoutBox); if (container && container != GetFocusObject() && container->AcceptsFocus()) @@ -810,7 +827,8 @@ void wxRichTextCtrl::OnMoveMouse(wxMouseEvent& event) flags = wxRICHTEXT_HITTEST_NO_NESTED_OBJECTS; container = GetFocusObject(); } - int hit = container->HitTest(dc, logicalPt, position, & hitObj, & contextObj, flags); + wxRichTextDrawingContext context(& GetBuffer()); + int hit = container->HitTest(dc, context, logicalPt, position, & hitObj, & contextObj, flags); // See if we need to change the cursor @@ -818,18 +836,8 @@ void wxRichTextCtrl::OnMoveMouse(wxMouseEvent& event) if (hit != wxRICHTEXT_HITTEST_NONE && !(hit & wxRICHTEXT_HITTEST_OUTSIDE) && hitObj) { wxRichTextParagraphLayoutBox* actualContainer = wxDynamicCast(contextObj, wxRichTextParagraphLayoutBox); - wxRichTextAttr attr; - if (actualContainer && GetStyle(position, attr, actualContainer)) - { - if (attr.HasFlag(wxTEXT_ATTR_URL)) - { - SetCursor(m_urlCursor); - } - else if (!attr.HasFlag(wxTEXT_ATTR_URL)) - { - SetCursor(m_textCursor); - } - } + if (actualContainer) + ProcessMouseMovement(actualContainer, hitObj, position, logicalPt); } else SetCursor(m_textCursor); @@ -854,7 +862,7 @@ void wxRichTextCtrl::OnMoveMouse(wxMouseEvent& event) // Check for dragging across multiple containers long position2 = 0; wxRichTextObject* hitObj2 = NULL, *contextObj2 = NULL; - int hit2 = GetBuffer().HitTest(dc, logicalPt, position2, & hitObj2, & contextObj2, 0); + int hit2 = GetBuffer().HitTest(dc, context, logicalPt, position2, & hitObj2, & contextObj2, 0); if (hit2 != wxRICHTEXT_HITTEST_NONE && !(hit2 & wxRICHTEXT_HITTEST_OUTSIDE) && hitObj2 && hitObj != hitObj2) { // See if we can find a common ancestor @@ -942,7 +950,8 @@ void wxRichTextCtrl::OnRightClick(wxMouseEvent& event) wxPoint logicalPt = event.GetLogicalPosition(dc); wxRichTextObject* hitObj = NULL; wxRichTextObject* contextObj = NULL; - int hit = GetFocusObject()->HitTest(dc, logicalPt, position, & hitObj, & contextObj); + wxRichTextDrawingContext context(& GetBuffer()); + int hit = GetFocusObject()->HitTest(dc, context, logicalPt, position, & hitObj, & contextObj); if (hitObj && hitObj->GetContainer() != GetFocusObject()) { @@ -1104,12 +1113,26 @@ void wxRichTextCtrl::OnChar(wxKeyEvent& event) // Must process this before translation, otherwise it's translated into a WXK_DELETE event. if (event.CmdDown() && event.GetKeyCode() == WXK_BACK) { + if (!IsEditable()) + { + return; + } + + if (HasSelection() && !CanDeleteRange(* GetFocusObject(), GetSelectionRange())) + { + return; + } + BeginBatchUndo(_("Delete Text")); long newPos = m_caretPosition; bool processed = DeleteSelectedContent(& newPos); + int deletions = 0; + if (processed) + deletions ++; + // Submit range in character positions, which are greater than caret positions, // so subtract 1 for deleted character and add 1 for conversion to character position. if (newPos > -1) @@ -1119,13 +1142,25 @@ void wxRichTextCtrl::OnChar(wxKeyEvent& event) long pos = wxRichTextCtrl::FindNextWordPosition(-1); if (pos < newPos) { - GetFocusObject()->DeleteRangeWithUndo(wxRichTextRange(pos+1, newPos), this, & GetBuffer()); + wxRichTextRange range(pos+1, newPos); + if (CanDeleteRange(* GetFocusObject(), range.FromInternal())) + { + GetFocusObject()->DeleteRangeWithUndo(range, this, & GetBuffer()); + deletions ++; + } processed = true; } } if (!processed) - GetFocusObject()->DeleteRangeWithUndo(wxRichTextRange(newPos, newPos), this, & GetBuffer()); + { + wxRichTextRange range(newPos, newPos); + if (CanDeleteRange(* GetFocusObject(), range.FromInternal())) + { + GetFocusObject()->DeleteRangeWithUndo(range, this, & GetBuffer()); + deletions ++; + } + } } EndBatchUndo(); @@ -1141,14 +1176,18 @@ void wxRichTextCtrl::OnChar(wxKeyEvent& event) ScrollIntoView(m_caretPosition, WXK_LEFT); - wxRichTextEvent cmdEvent( - wxEVT_COMMAND_RICHTEXT_DELETE, - GetId()); - cmdEvent.SetEventObject(this); - cmdEvent.SetFlags(flags); - cmdEvent.SetPosition(m_caretPosition+1); - cmdEvent.SetContainer(GetFocusObject()); - GetEventHandler()->ProcessEvent(cmdEvent); + // Always send this event; wxEVT_COMMAND_RICHTEXT_CONTENT_DELETED will be sent only if there is an actual deletion. + //if (deletions > 0) + { + wxRichTextEvent cmdEvent( + wxEVT_COMMAND_RICHTEXT_DELETE, + GetId()); + cmdEvent.SetEventObject(this); + cmdEvent.SetFlags(flags); + cmdEvent.SetPosition(m_caretPosition+1); + cmdEvent.SetContainer(GetFocusObject()); + GetEventHandler()->ProcessEvent(cmdEvent); + } Update(); } @@ -1168,22 +1207,30 @@ void wxRichTextCtrl::OnChar(wxKeyEvent& event) if (event.GetKeyCode() == WXK_RETURN) { - BeginBatchUndo(_("Insert Text")); + if (!CanInsertContent(* GetFocusObject(), m_caretPosition+1)) + return; long newPos = m_caretPosition; + if (HasSelection() && !CanDeleteRange(* GetFocusObject(), GetSelectionRange())) + { + return; + } + + BeginBatchUndo(_("Insert Text")); + DeleteSelectedContent(& newPos); if (event.ShiftDown()) { wxString text; text = wxRichTextLineBreakChar; - GetFocusObject()->InsertTextWithUndo(newPos+1, text, this, & GetBuffer()); + GetFocusObject()->InsertTextWithUndo(& GetBuffer(), newPos+1, text, this); m_caretAtLineStart = true; PositionCaret(); } else - GetFocusObject()->InsertNewlineWithUndo(newPos+1, this, & GetBuffer(), wxRICHTEXT_INSERT_WITH_PREVIOUS_PARAGRAPH_STYLE|wxRICHTEXT_INSERT_INTERACTIVE); + GetFocusObject()->InsertNewlineWithUndo(& GetBuffer(), newPos+1, this, wxRICHTEXT_INSERT_WITH_PREVIOUS_PARAGRAPH_STYLE|wxRICHTEXT_INSERT_INTERACTIVE); EndBatchUndo(); SetDefaultStyleToCursorStyle(); @@ -1210,12 +1257,21 @@ void wxRichTextCtrl::OnChar(wxKeyEvent& event) } else if (event.GetKeyCode() == WXK_BACK) { - BeginBatchUndo(_("Delete Text")); - long newPos = m_caretPosition; + if (HasSelection() && !CanDeleteRange(* GetFocusObject(), GetSelectionRange())) + { + return; + } + + BeginBatchUndo(_("Delete Text")); + bool processed = DeleteSelectedContent(& newPos); + int deletions = 0; + if (processed) + deletions ++; + // Submit range in character positions, which are greater than caret positions, // so subtract 1 for deleted character and add 1 for conversion to character position. if (newPos > -1) @@ -1225,13 +1281,25 @@ void wxRichTextCtrl::OnChar(wxKeyEvent& event) long pos = wxRichTextCtrl::FindNextWordPosition(-1); if (pos < newPos) { - GetFocusObject()->DeleteRangeWithUndo(wxRichTextRange(pos+1, newPos), this, & GetBuffer()); + wxRichTextRange range(pos+1, newPos); + if (CanDeleteRange(* GetFocusObject(), range.FromInternal())) + { + GetFocusObject()->DeleteRangeWithUndo(range, this, & GetBuffer()); + deletions ++; + } processed = true; } } if (!processed) - GetFocusObject()->DeleteRangeWithUndo(wxRichTextRange(newPos, newPos), this, & GetBuffer()); + { + wxRichTextRange range(newPos, newPos); + if (CanDeleteRange(* GetFocusObject(), range.FromInternal())) + { + GetFocusObject()->DeleteRangeWithUndo(range, this, & GetBuffer()); + deletions ++; + } + } } EndBatchUndo(); @@ -1247,25 +1315,38 @@ void wxRichTextCtrl::OnChar(wxKeyEvent& event) ScrollIntoView(m_caretPosition, WXK_LEFT); - wxRichTextEvent cmdEvent( - wxEVT_COMMAND_RICHTEXT_DELETE, - GetId()); - cmdEvent.SetEventObject(this); - cmdEvent.SetFlags(flags); - cmdEvent.SetPosition(m_caretPosition+1); - cmdEvent.SetContainer(GetFocusObject()); - GetEventHandler()->ProcessEvent(cmdEvent); + // Always send this event; wxEVT_COMMAND_RICHTEXT_CONTENT_DELETED will be sent only if there is an actual deletion. + //if (deletions > 0) + { + wxRichTextEvent cmdEvent( + wxEVT_COMMAND_RICHTEXT_DELETE, + GetId()); + cmdEvent.SetEventObject(this); + cmdEvent.SetFlags(flags); + cmdEvent.SetPosition(m_caretPosition+1); + cmdEvent.SetContainer(GetFocusObject()); + GetEventHandler()->ProcessEvent(cmdEvent); + } Update(); } else if (event.GetKeyCode() == WXK_DELETE) { - BeginBatchUndo(_("Delete Text")); - long newPos = m_caretPosition; + if (HasSelection() && !CanDeleteRange(* GetFocusObject(), GetSelectionRange())) + { + return; + } + + BeginBatchUndo(_("Delete Text")); + bool processed = DeleteSelectedContent(& newPos); + int deletions = 0; + if (processed) + deletions ++; + // Submit range in character positions, which are greater than caret positions, if (newPos < GetFocusObject()->GetOwnRange().GetEnd()+1) { @@ -1274,13 +1355,25 @@ void wxRichTextCtrl::OnChar(wxKeyEvent& event) long pos = wxRichTextCtrl::FindNextWordPosition(1); if (pos != -1 && (pos > newPos)) { - GetFocusObject()->DeleteRangeWithUndo(wxRichTextRange(newPos+1, pos), this, & GetBuffer()); + wxRichTextRange range(newPos+1, pos); + if (CanDeleteRange(* GetFocusObject(), range.FromInternal())) + { + GetFocusObject()->DeleteRangeWithUndo(range, this, & GetBuffer()); + deletions ++; + } processed = true; } } if (!processed && newPos < (GetLastPosition()-1)) - GetFocusObject()->DeleteRangeWithUndo(wxRichTextRange(newPos+1, newPos+1), this, & GetBuffer()); + { + wxRichTextRange range(newPos+1, newPos+1); + if (CanDeleteRange(* GetFocusObject(), range.FromInternal())) + { + GetFocusObject()->DeleteRangeWithUndo(range, this, & GetBuffer()); + deletions ++; + } + } } EndBatchUndo(); @@ -1296,14 +1389,18 @@ void wxRichTextCtrl::OnChar(wxKeyEvent& event) ScrollIntoView(m_caretPosition, WXK_LEFT); - wxRichTextEvent cmdEvent( - wxEVT_COMMAND_RICHTEXT_DELETE, - GetId()); - cmdEvent.SetEventObject(this); - cmdEvent.SetFlags(flags); - cmdEvent.SetPosition(m_caretPosition+1); - cmdEvent.SetContainer(GetFocusObject()); - GetEventHandler()->ProcessEvent(cmdEvent); + // Always send this event; wxEVT_COMMAND_RICHTEXT_CONTENT_DELETED will be sent only if there is an actual deletion. + //if (deletions > 0) + { + wxRichTextEvent cmdEvent( + wxEVT_COMMAND_RICHTEXT_DELETE, + GetId()); + cmdEvent.SetEventObject(this); + cmdEvent.SetFlags(flags); + cmdEvent.SetPosition(m_caretPosition+1); + cmdEvent.SetContainer(GetFocusObject()); + GetEventHandler()->ProcessEvent(cmdEvent); + } Update(); } @@ -1368,6 +1465,12 @@ void wxRichTextCtrl::OnChar(wxKeyEvent& event) } } + if (!CanInsertContent(* GetFocusObject(), m_caretPosition+1)) + return; + + if (HasSelection() && !CanDeleteRange(* GetFocusObject(), GetSelectionRange())) + return; + BeginBatchUndo(_("Insert Text")); long newPos = m_caretPosition; @@ -1378,7 +1481,7 @@ void wxRichTextCtrl::OnChar(wxKeyEvent& event) #else wxString str = (wxChar) event.GetKeyCode(); #endif - GetFocusObject()->InsertTextWithUndo(newPos+1, str, this, & GetBuffer(), 0); + GetFocusObject()->InsertTextWithUndo(& GetBuffer(), newPos+1, str, this, 0); EndBatchUndo(); @@ -1394,6 +1497,25 @@ void wxRichTextCtrl::OnChar(wxKeyEvent& event) } } +bool wxRichTextCtrl::ProcessMouseMovement(wxRichTextParagraphLayoutBox* container, wxRichTextObject* WXUNUSED(obj), long position, const wxPoint& WXUNUSED(pos)) +{ + wxRichTextAttr attr; + if (container && GetStyle(position, attr, container)) + { + if (attr.HasFlag(wxTEXT_ATTR_URL)) + { + SetCursor(m_urlCursor); + } + else if (!attr.HasFlag(wxTEXT_ATTR_URL)) + { + SetCursor(m_textCursor); + } + return true; + } + else + return false; +} + /// Delete content if there is a selection, e.g. when pressing a key. bool wxRichTextCtrl::DeleteSelectedContent(long* newPos) { @@ -1998,7 +2120,8 @@ bool wxRichTextCtrl::MoveDown(int noLines, int flags) wxRichTextObject* hitObj = NULL; wxRichTextObject* contextObj = NULL; - int hitTest = container->HitTest(dc, pt, newPos, & hitObj, & contextObj, hitTestFlags); + wxRichTextDrawingContext context(& GetBuffer()); + int hitTest = container->HitTest(dc, context, pt, newPos, & hitObj, & contextObj, hitTestFlags); if (hitObj && ((hitTest & wxRICHTEXT_HITTEST_NONE) == 0) && @@ -2436,7 +2559,7 @@ void wxRichTextCtrl::SetupScrollbars(bool atTop) if (IsFrozen()) return; - if (GetBuffer().IsEmpty()) + if (GetBuffer().IsEmpty() || !m_verticalScrollbarEnabled) { SetScrollbars(0, 0, 0, 0, 0, 0); return; @@ -2712,7 +2835,8 @@ wxRichTextCtrl::HitTest(const wxPoint& pt, wxRichTextObject* hitObj = NULL; wxRichTextObject* contextObj = NULL; - int hit = ((wxRichTextCtrl*)this)->GetFocusObject()->HitTest(dc, pt2, *pos, & hitObj, & contextObj, wxRICHTEXT_HITTEST_NO_NESTED_OBJECTS); + wxRichTextDrawingContext context((wxRichTextBuffer*) & GetBuffer()); + int hit = ((wxRichTextCtrl*)this)->GetFocusObject()->HitTest(dc, context, pt2, *pos, & hitObj, & contextObj, wxRICHTEXT_HITTEST_NO_NESTED_OBJECTS); if ((hit & wxRICHTEXT_HITTEST_BEFORE) && (hit & wxRICHTEXT_HITTEST_OUTSIDE)) return wxTE_HT_BEFORE; @@ -2734,7 +2858,8 @@ wxRichTextCtrl::FindContainerAtPoint(const wxPoint pt, long& position, int& hit, wxPoint logicalPt = GetLogicalPoint(pt); wxRichTextObject* contextObj = NULL; - hit = GetBuffer().HitTest(dc, logicalPt, position, &hitObj, &contextObj, flags); + wxRichTextDrawingContext context(& GetBuffer()); + hit = GetBuffer().HitTest(dc, context, logicalPt, position, &hitObj, &contextObj, flags); wxRichTextParagraphLayoutBox* container = wxDynamicCast(contextObj, wxRichTextParagraphLayoutBox); return container; @@ -2802,7 +2927,7 @@ void wxRichTextCtrl::DoWriteText(const wxString& value, int flags) { wxString valueUnix = wxTextFile::Translate(value, wxTextFileType_Unix); - GetFocusObject()->InsertTextWithUndo(m_caretPosition+1, valueUnix, this, & GetBuffer(), wxRICHTEXT_INSERT_WITH_PREVIOUS_PARAGRAPH_STYLE); + GetFocusObject()->InsertTextWithUndo(& GetBuffer(), m_caretPosition+1, valueUnix, this, wxRICHTEXT_INSERT_WITH_PREVIOUS_PARAGRAPH_STYLE); if ( flags & SetValue_SendEvent ) wxTextCtrl::SendTextUpdatedEvent(this); @@ -2840,7 +2965,7 @@ bool wxRichTextCtrl::WriteImage(const wxString& filename, wxBitmapType bitmapTyp bool wxRichTextCtrl::WriteImage(const wxRichTextImageBlock& imageBlock, const wxRichTextAttr& textAttr) { - return GetFocusObject()->InsertImageWithUndo(m_caretPosition+1, imageBlock, this, & GetBuffer(), 0, textAttr); + return GetFocusObject()->InsertImageWithUndo(& GetBuffer(), m_caretPosition+1, imageBlock, this, 0, textAttr); } bool wxRichTextCtrl::WriteImage(const wxBitmap& bitmap, wxBitmapType bitmapType, const wxRichTextAttr& textAttr) @@ -2868,7 +2993,7 @@ wxRichTextBox* wxRichTextCtrl::WriteTextBox(const wxRichTextAttr& textAttr) // The object returned is the one actually inserted into the buffer, // while the original one is deleted. - wxRichTextObject* obj = GetFocusObject()->InsertObjectWithUndo(m_caretPosition+1, textBox, this, & GetBuffer(), wxRICHTEXT_INSERT_WITH_PREVIOUS_PARAGRAPH_STYLE); + wxRichTextObject* obj = GetFocusObject()->InsertObjectWithUndo(& GetBuffer(), m_caretPosition+1, textBox, this, wxRICHTEXT_INSERT_WITH_PREVIOUS_PARAGRAPH_STYLE); wxRichTextBox* box = wxDynamicCast(obj, wxRichTextBox); return box; } @@ -2900,7 +3025,7 @@ wxRichTextTable* wxRichTextCtrl::WriteTable(int rows, int cols, const wxRichText // The object returned is the one actually inserted into the buffer, // while the original one is deleted. - wxRichTextObject* obj = GetFocusObject()->InsertObjectWithUndo(m_caretPosition+1, table, this, & GetBuffer(), wxRICHTEXT_INSERT_WITH_PREVIOUS_PARAGRAPH_STYLE); + wxRichTextObject* obj = GetFocusObject()->InsertObjectWithUndo(& GetBuffer(), m_caretPosition+1, table, this, wxRICHTEXT_INSERT_WITH_PREVIOUS_PARAGRAPH_STYLE); wxRichTextTable* tableResult = wxDynamicCast(obj, wxRichTextTable); return tableResult; } @@ -2909,7 +3034,7 @@ wxRichTextTable* wxRichTextCtrl::WriteTable(int rows, int cols, const wxRichText /// Insert a newline (actually paragraph) at the current insertion point. bool wxRichTextCtrl::Newline() { - return GetFocusObject()->InsertNewlineWithUndo(m_caretPosition+1, this, & GetBuffer(), wxRICHTEXT_INSERT_WITH_PREVIOUS_PARAGRAPH_STYLE); + return GetFocusObject()->InsertNewlineWithUndo(& GetBuffer(), m_caretPosition+1, this, wxRICHTEXT_INSERT_WITH_PREVIOUS_PARAGRAPH_STYLE); } /// Insert a line break at the current insertion point. @@ -2917,7 +3042,7 @@ bool wxRichTextCtrl::LineBreak() { wxString text; text = wxRichTextLineBreakChar; - return GetFocusObject()->InsertTextWithUndo(m_caretPosition+1, text, this, & GetBuffer()); + return GetFocusObject()->InsertTextWithUndo(& GetBuffer(), m_caretPosition+1, text, this); } // ---------------------------------------------------------------------------- @@ -2987,12 +3112,12 @@ bool wxRichTextCtrl::CanCopy() const bool wxRichTextCtrl::CanCut() const { - return HasSelection() && IsEditable(); + return CanDeleteSelection(); } bool wxRichTextCtrl::CanPaste() const { - if ( !IsEditable() ) + if ( !IsEditable() || !GetFocusObject() || !CanInsertContent(* GetFocusObject(), m_caretPosition+1)) return false; return GetBuffer().CanPasteFromClipboard(); @@ -3000,7 +3125,7 @@ bool wxRichTextCtrl::CanPaste() const bool wxRichTextCtrl::CanDeleteSelection() const { - return HasSelection() && IsEditable(); + return HasSelection() && IsEditable() && CanDeleteRange(* GetFocusObject(), GetSelectionRange()); } @@ -3328,8 +3453,8 @@ void wxRichTextCtrl::OnProperties(wxCommandEvent& event) if (idx >= 0 && idx < m_contextMenuPropertiesInfo.GetCount()) { wxRichTextObject* obj = m_contextMenuPropertiesInfo.GetObject(idx); - if (obj && obj->CanEditProperties()) - obj->EditProperties(this, & GetBuffer()); + if (obj && CanEditProperties(obj)) + EditProperties(obj, this); m_contextMenuPropertiesInfo.Clear(); } @@ -3368,7 +3493,8 @@ int wxRichTextCtrl::PrepareContextMenu(wxMenu* menu, const wxPoint& pt, bool add if (pt != wxDefaultPosition) { wxPoint logicalPt = GetLogicalPoint(ScreenToClient(pt)); - int hit = GetBuffer().HitTest(dc, logicalPt, position, & hitObj, & contextObj); + wxRichTextDrawingContext context(& GetBuffer()); + int hit = GetBuffer().HitTest(dc, context, logicalPt, position, & hitObj, & contextObj); if (hit == wxRICHTEXT_HITTEST_ON || hit == wxRICHTEXT_HITTEST_BEFORE || hit == wxRICHTEXT_HITTEST_AFTER) { @@ -3382,18 +3508,18 @@ int wxRichTextCtrl::PrepareContextMenu(wxMenu* menu, const wxPoint& pt, bool add } if (addPropertyCommands) - m_contextMenuPropertiesInfo.AddItems(actualContainer, hitObj); + m_contextMenuPropertiesInfo.AddItems(this, actualContainer, hitObj); } else { if (addPropertyCommands) - m_contextMenuPropertiesInfo.AddItems(GetFocusObject(), NULL); + m_contextMenuPropertiesInfo.AddItems(this, GetFocusObject(), NULL); } } else { if (addPropertyCommands) - m_contextMenuPropertiesInfo.AddItems(GetFocusObject(), NULL); + m_contextMenuPropertiesInfo.AddItems(this, GetFocusObject(), NULL); } } else @@ -3410,12 +3536,12 @@ int wxRichTextCtrl::PrepareContextMenu(wxMenu* menu, const wxPoint& pt, bool add if (hitObj && actualContainer) { if (addPropertyCommands) - m_contextMenuPropertiesInfo.AddItems(actualContainer, hitObj); + m_contextMenuPropertiesInfo.AddItems(this, actualContainer, hitObj); } else { if (addPropertyCommands) - m_contextMenuPropertiesInfo.AddItems(GetFocusObject(), NULL); + m_contextMenuPropertiesInfo.AddItems(this, GetFocusObject(), NULL); } } @@ -3557,6 +3683,11 @@ bool wxRichTextCtrl::GetUncombinedStyle(long position, wxRichTextAttr& style, wx return container->GetUncombinedStyle(position, style); } +bool wxRichTextCtrl::SetProperties(const wxRichTextRange& range, const wxRichTextProperties& properties, int flags) +{ + return GetFocusObject()->SetProperties(range.ToInternal(), properties, flags); +} + /// Set font, and also the buffer attributes bool wxRichTextCtrl::SetFont(const wxFont& font) { @@ -3651,7 +3782,8 @@ bool wxRichTextCtrl::GetCaretPositionForIndex(long position, wxRect& rect, wxRic if (!container) container = GetFocusObject(); - if (container->FindPosition(dc, position, pt, & height, m_caretAtLineStart)) + wxRichTextDrawingContext context(& GetBuffer()); + if (container->FindPosition(dc, context, position, pt, & height, m_caretAtLineStart)) { // Caret height can't be zero if (height == 0) @@ -3731,9 +3863,10 @@ bool wxRichTextCtrl::LayoutContent(bool onlyVisibleRect) PrepareDC(dc); + wxRichTextDrawingContext context(& GetBuffer()); GetBuffer().Defragment(); GetBuffer().UpdateRanges(); // If items were deleted, ranges need recalculation - GetBuffer().Layout(dc, availableSpace, flags); + GetBuffer().Layout(dc, context, availableSpace, availableSpace, flags); GetBuffer().Invalidate(wxRICHTEXT_NONE); if (!IsFrozen()) @@ -4006,10 +4139,22 @@ bool wxRichTextCtrl::ApplyStyle(wxRichTextStyleDefinition* def) // to change its style independently. flags |= wxRICHTEXT_SETSTYLE_PARAGRAPHS_ONLY; } - else + else if (def->IsKindOf(CLASSINFO(wxRichTextCharacterStyleDefinition))) attr.SetCharacterStyleName(def->GetName()); + else if (def->IsKindOf(CLASSINFO(wxRichTextBoxStyleDefinition))) + attr.GetTextBoxAttr().SetBoxStyleName(def->GetName()); - if (HasSelection()) + if (def->IsKindOf(CLASSINFO(wxRichTextBoxStyleDefinition))) + { + if (GetFocusObject() && (GetFocusObject() != & GetBuffer())) + { + SetStyle(GetFocusObject(), attr); + return true; + } + else + return false; + } + else if (HasSelection()) return SetStyleEx(GetSelectionRange(), attr, flags); else { @@ -4066,7 +4211,15 @@ bool wxRichTextCtrl::SetDefaultStyleToCursorStyle() // If at the start of a paragraph, use the next position. long pos = GetAdjustedCaretPosition(GetCaretPosition()); - if (GetUncombinedStyle(pos, attr)) + wxRichTextObject* obj = GetFocusObject()->GetLeafObjectAtPosition(pos); + if (obj && obj->IsTopLevel()) + { + // Don't use the attributes of a top-level object, since they might apply + // to content of the object, e.g. background colour. + SetDefaultStyle(wxRichTextAttr()); + return true; + } + else if (GetUncombinedStyle(pos, attr)) { SetDefaultStyle(attr); return true; @@ -4343,7 +4496,6 @@ void wxRichTextCtrl::OnDrop(wxCoord WXUNUSED(x), wxCoord WXUNUSED(y), wxDragResu wxRichTextParagraphLayoutBox* originContainer = GetSelection().GetContainer(); wxRichTextParagraphLayoutBox* destContainer = GetFocusObject(); // This will be the drop container, not necessarily the same as the origin one - wxRichTextBuffer* richTextBuffer = ((wxRichTextBufferDataObject*)DataObj)->GetRichTextBuffer(); if (richTextBuffer) { @@ -4364,7 +4516,7 @@ void wxRichTextCtrl::OnDrop(wxCoord WXUNUSED(x), wxCoord WXUNUSED(y), wxDragResu originContainer->DeleteRangeWithUndo(selectionrange, this, &GetBuffer()); } - destContainer->InsertParagraphsWithUndo(position+1, *richTextBuffer, this, &GetBuffer(), 0); + destContainer->InsertParagraphsWithUndo(&GetBuffer(), position+1, *richTextBuffer, this, 0); ShowPosition(position + richTextBuffer->GetOwnRange().GetEnd()); delete richTextBuffer; @@ -4375,7 +4527,6 @@ void wxRichTextCtrl::OnDrop(wxCoord WXUNUSED(x), wxCoord WXUNUSED(y), wxDragResu originContainer->DeleteRangeWithUndo(selectionrange, this, &GetBuffer()); } - SelectNone(); Refresh(); } @@ -4403,6 +4554,22 @@ bool wxRichTextDropSource::GiveFeedback(wxDragResult WXUNUSED(effect)) } #endif // wxUSE_DRAG_AND_DROP +bool wxRichTextCtrl::CanDeleteRange(wxRichTextParagraphLayoutBox& WXUNUSED(container), const wxRichTextRange& WXUNUSED(range)) const +{ + return true; +} + +bool wxRichTextCtrl::CanInsertContent(wxRichTextParagraphLayoutBox& WXUNUSED(container), long WXUNUSED(pos)) const +{ + return true; +} + +void wxRichTextCtrl::EnableVerticalScrollbar(bool enable) +{ + m_verticalScrollbarEnabled = enable; + SetupScrollbars(); +} + #if wxRICHTEXT_USE_OWN_CARET @@ -4413,6 +4580,7 @@ bool wxRichTextDropSource::GiveFeedback(wxDragResult WXUNUSED(effect)) void wxRichTextCaret::Init() { m_hasFocus = true; + m_refreshEnabled = true; m_xOld = m_yOld = -1; @@ -4457,7 +4625,7 @@ void wxRichTextCaret::DoMove() if (m_xOld != -1 && m_yOld != -1) { - if (m_richTextCtrl) + if (m_richTextCtrl && m_refreshEnabled) { wxRect rect(GetPosition(), GetSize()); m_richTextCtrl->RefreshRect(rect, false); @@ -4508,7 +4676,7 @@ void wxRichTextCaret::OnKillFocus() void wxRichTextCaret::Refresh() { - if (m_richTextCtrl) + if (m_richTextCtrl && m_refreshEnabled) { wxRect rect(GetPosition(), GetSize()); m_richTextCtrl->RefreshRect(rect, false); @@ -4640,17 +4808,17 @@ int wxRichTextContextMenuPropertiesInfo::AddMenuItems(wxMenu* menu, int startCmd // Add appropriate menu items for the current container and clicked on object // (and container's parent, if appropriate). -int wxRichTextContextMenuPropertiesInfo::AddItems(wxRichTextObject* container, wxRichTextObject* obj) +int wxRichTextContextMenuPropertiesInfo::AddItems(wxRichTextCtrl* ctrl, wxRichTextObject* container, wxRichTextObject* obj) { Clear(); - if (obj && obj->CanEditProperties()) - AddItem(obj->GetPropertiesMenuLabel(), obj); + if (obj && ctrl->CanEditProperties(obj)) + AddItem(ctrl->GetPropertiesMenuLabel(obj), obj); - if (container && container != obj && container->CanEditProperties() && m_labels.Index(container->GetPropertiesMenuLabel()) == wxNOT_FOUND) - AddItem(container->GetPropertiesMenuLabel(), container); + if (container && container != obj && ctrl->CanEditProperties(container) && m_labels.Index(ctrl->GetPropertiesMenuLabel(container)) == wxNOT_FOUND) + AddItem(ctrl->GetPropertiesMenuLabel(container), container); - if (container && container->GetParent() && container->GetParent()->CanEditProperties() && m_labels.Index(container->GetParent()->GetPropertiesMenuLabel()) == wxNOT_FOUND) - AddItem(container->GetParent()->GetPropertiesMenuLabel(), container->GetParent()); + if (container && container->GetParent() && ctrl->CanEditProperties(container->GetParent()) && m_labels.Index(ctrl->GetPropertiesMenuLabel(container->GetParent())) == wxNOT_FOUND) + AddItem(ctrl->GetPropertiesMenuLabel(container->GetParent()), container->GetParent()); return GetCount(); }