]> git.saurik.com Git - wxWidgets.git/blobdiff - src/richtext/richtextctrl.cpp
Fix stretchable spaces in wxToolBar after tool removal in wxMSW.
[wxWidgets.git] / src / richtext / richtextctrl.cpp
index 9395714d2dd95a6360029076ed092ee2b81cb643..e8eff5d801319effc3b75cdf8b88d1d72a0a38ad 100644 (file)
@@ -356,6 +356,7 @@ void wxRichTextCtrl::Init()
     m_selectionAnchorObject = NULL;
     m_selectionState = wxRichTextCtrlSelectionState_Normal;
     m_editable = true;
     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_caretAtLineStart = false;
     m_dragging = false;
 #if wxUSE_DRAG_AND_DROP
@@ -861,7 +862,6 @@ void wxRichTextCtrl::OnMoveMouse(wxMouseEvent& event)
         // Check for dragging across multiple containers
         long position2 = 0;
         wxRichTextObject* hitObj2 = NULL, *contextObj2 = NULL;
         // Check for dragging across multiple containers
         long position2 = 0;
         wxRichTextObject* hitObj2 = NULL, *contextObj2 = NULL;
-        wxRichTextDrawingContext context(& GetBuffer());
         int hit2 = GetBuffer().HitTest(dc, context, logicalPt, position2, & hitObj2, & contextObj2, 0);
         if (hit2 != wxRICHTEXT_HITTEST_NONE && !(hit2 & wxRICHTEXT_HITTEST_OUTSIDE) && hitObj2 && hitObj != hitObj2)
         {
         int hit2 = GetBuffer().HitTest(dc, context, logicalPt, position2, & hitObj2, & contextObj2, 0);
         if (hit2 != wxRICHTEXT_HITTEST_NONE && !(hit2 & wxRICHTEXT_HITTEST_OUTSIDE) && hitObj2 && hitObj != hitObj2)
         {
@@ -1113,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)
         {
         // 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);
 
             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)
             // 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)
@@ -1128,13 +1142,25 @@ void wxRichTextCtrl::OnChar(wxKeyEvent& event)
                     long pos = wxRichTextCtrl::FindNextWordPosition(-1);
                     if (pos < newPos)
                     {
                     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)
                         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();
             }
 
             EndBatchUndo();
@@ -1150,14 +1176,18 @@ void wxRichTextCtrl::OnChar(wxKeyEvent& event)
 
             ScrollIntoView(m_caretPosition, WXK_LEFT);
 
 
             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();
         }
 
             Update();
         }
@@ -1177,10 +1207,18 @@ void wxRichTextCtrl::OnChar(wxKeyEvent& event)
 
     if (event.GetKeyCode() == WXK_RETURN)
     {
 
     if (event.GetKeyCode() == WXK_RETURN)
     {
-        BeginBatchUndo(_("Insert Text"));
+        if (!CanInsertContent(* GetFocusObject(), m_caretPosition+1))
+            return;
 
         long newPos = m_caretPosition;
 
 
         long newPos = m_caretPosition;
 
+        if (HasSelection() && !CanDeleteRange(* GetFocusObject(), GetSelectionRange()))
+        {
+            return;
+        }
+
+        BeginBatchUndo(_("Insert Text"));
+
         DeleteSelectedContent(& newPos);
 
         if (event.ShiftDown())
         DeleteSelectedContent(& newPos);
 
         if (event.ShiftDown())
@@ -1219,12 +1257,21 @@ void wxRichTextCtrl::OnChar(wxKeyEvent& event)
     }
     else if (event.GetKeyCode() == WXK_BACK)
     {
     }
     else if (event.GetKeyCode() == WXK_BACK)
     {
-        BeginBatchUndo(_("Delete Text"));
-
         long newPos = m_caretPosition;
 
         long newPos = m_caretPosition;
 
+        if (HasSelection() && !CanDeleteRange(* GetFocusObject(), GetSelectionRange()))
+        {
+            return;
+        }
+
+        BeginBatchUndo(_("Delete Text"));
+
         bool processed = DeleteSelectedContent(& newPos);
 
         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)
         // 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)
@@ -1234,13 +1281,25 @@ void wxRichTextCtrl::OnChar(wxKeyEvent& event)
                 long pos = wxRichTextCtrl::FindNextWordPosition(-1);
                 if (pos < newPos)
                 {
                 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)
                     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();
         }
 
         EndBatchUndo();
@@ -1256,25 +1315,38 @@ void wxRichTextCtrl::OnChar(wxKeyEvent& event)
 
         ScrollIntoView(m_caretPosition, WXK_LEFT);
 
 
         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)
     {
 
         Update();
     }
     else if (event.GetKeyCode() == WXK_DELETE)
     {
-        BeginBatchUndo(_("Delete Text"));
-
         long newPos = m_caretPosition;
 
         long newPos = m_caretPosition;
 
+        if (HasSelection() && !CanDeleteRange(* GetFocusObject(), GetSelectionRange()))
+        {
+            return;
+        }
+
+        BeginBatchUndo(_("Delete Text"));
+
         bool processed = DeleteSelectedContent(& newPos);
 
         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)
         {
         // Submit range in character positions, which are greater than caret positions,
         if (newPos < GetFocusObject()->GetOwnRange().GetEnd()+1)
         {
@@ -1283,13 +1355,25 @@ void wxRichTextCtrl::OnChar(wxKeyEvent& event)
                 long pos = wxRichTextCtrl::FindNextWordPosition(1);
                 if (pos != -1 && (pos > newPos))
                 {
                 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))
                     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();
         }
 
         EndBatchUndo();
@@ -1305,14 +1389,18 @@ void wxRichTextCtrl::OnChar(wxKeyEvent& event)
 
         ScrollIntoView(m_caretPosition, WXK_LEFT);
 
 
         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();
     }
 
         Update();
     }
@@ -1377,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;
                 BeginBatchUndo(_("Insert Text"));
 
                 long newPos = m_caretPosition;
@@ -2465,7 +2559,7 @@ void wxRichTextCtrl::SetupScrollbars(bool atTop)
     if (IsFrozen())
         return;
 
     if (IsFrozen())
         return;
 
-    if (GetBuffer().IsEmpty())
+    if (GetBuffer().IsEmpty() || !m_verticalScrollbarEnabled)
     {
         SetScrollbars(0, 0, 0, 0, 0, 0);
         return;
     {
         SetScrollbars(0, 0, 0, 0, 0, 0);
         return;
@@ -3018,12 +3112,12 @@ bool wxRichTextCtrl::CanCopy() const
 
 bool wxRichTextCtrl::CanCut() const
 {
 
 bool wxRichTextCtrl::CanCut() const
 {
-    return HasSelection() && IsEditable();
+    return CanDeleteSelection();
 }
 
 bool wxRichTextCtrl::CanPaste() const
 {
 }
 
 bool wxRichTextCtrl::CanPaste() const
 {
-    if ( !IsEditable() )
+    if ( !IsEditable() || !GetFocusObject() || !CanInsertContent(* GetFocusObject(), m_caretPosition+1))
         return false;
 
     return GetBuffer().CanPasteFromClipboard();
         return false;
 
     return GetBuffer().CanPasteFromClipboard();
@@ -3031,7 +3125,7 @@ bool wxRichTextCtrl::CanPaste() const
 
 bool wxRichTextCtrl::CanDeleteSelection() const
 {
 
 bool wxRichTextCtrl::CanDeleteSelection() const
 {
-    return HasSelection() && IsEditable();
+    return HasSelection() && IsEditable() && CanDeleteRange(* GetFocusObject(), GetSelectionRange());
 }
 
 
 }
 
 
@@ -4460,6 +4554,22 @@ bool wxRichTextDropSource::GiveFeedback(wxDragResult WXUNUSED(effect))
 }
 #endif // wxUSE_DRAG_AND_DROP
 
 }
 #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
 
 
 #if wxRICHTEXT_USE_OWN_CARET