]> git.saurik.com Git - wxWidgets.git/commitdiff
Applied patch for #15189 - avoid crash when deleting focused cell (dghart)
authorJulian Smart <julian@anthemion.co.uk>
Sun, 26 May 2013 15:32:12 +0000 (15:32 +0000)
committerJulian Smart <julian@anthemion.co.uk>
Sun, 26 May 2013 15:32:12 +0000 (15:32 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@74058 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

include/wx/richtext/richtextbuffer.h
interface/wx/richtext/richtextbuffer.h
src/richtext/richtextbuffer.cpp

index ce85bc5e6909a746c5210287bb2d77f1d8ebcfaa..761ed468a4a5e00d496cc1f392321a8df51a096c 100644 (file)
@@ -66,6 +66,7 @@
 #include "wx/cmdproc.h"
 #include "wx/txtstrm.h"
 #include "wx/variant.h"
 #include "wx/cmdproc.h"
 #include "wx/txtstrm.h"
 #include "wx/variant.h"
+#include "wx/position.h"
 
 #if wxUSE_DATAOBJ
 #include "wx/dataobj.h"
 
 #if wxUSE_DATAOBJ
 #include "wx/dataobj.h"
@@ -5683,6 +5684,11 @@ public:
     */
     virtual bool GetCellRowColumnPosition(long pos, int& row, int& col) const;
 
     */
     virtual bool GetCellRowColumnPosition(long pos, int& row, int& col) const;
 
+    /**
+        Returns the coordinates of the cell with keyboard focus, or (-1,-1) if none.
+    */    
+    virtual wxPosition GetFocusedCell() const;
+
 // Operations
 
     /**
 // Operations
 
     /**
index 7a12ac63928429a3e1f79c128093671f3cdc1fd8..7490004cbdc4d975e8865f9e909d35842e6f6153 100644 (file)
@@ -5506,6 +5506,11 @@ public:
     */
     virtual bool GetCellRowColumnPosition(long pos, int& row, int& col) const;
 
     */
     virtual bool GetCellRowColumnPosition(long pos, int& row, int& col) const;
 
+    /**
+        Returns the coordinates of the cell with keyboard focus, or (-1,-1) if none.
+    */    
+    virtual wxPosition GetFocusedCell() const;
+
 // Operations
 
     /**
 // Operations
 
     /**
index dfcc768eea2fc7aecb9605f0323d8880d814cc00..ec9da81006cb5f284294991f6b65ccdb42b828fa 100644 (file)
@@ -10241,21 +10241,64 @@ bool wxRichTextTable::SetCellStyle(const wxRichTextSelection& selection, const w
     return true;
 }
 
     return true;
 }
 
+wxPosition wxRichTextTable::GetFocusedCell() const
+{
+    wxPosition position(-1, -1);
+    const wxRichTextObject* focus = GetBuffer()->GetRichTextCtrl()->GetFocusObject();
+
+    for (int row = 0; row < GetRowCount(); ++row)
+    {
+        for (int col = 0; col < GetColumnCount(); ++col)
+        {
+            if (GetCell(row, col) == focus)
+            {
+              position.SetRow(row);
+              position.SetCol(col);
+              return position;
+            }
+        }
+    }
+
+    return position;
+}
+
 bool wxRichTextTable::DeleteRows(int startRow, int noRows)
 {
     wxASSERT((startRow + noRows) <= m_rowCount);
     if ((startRow + noRows) > m_rowCount)
         return false;
 
 bool wxRichTextTable::DeleteRows(int startRow, int noRows)
 {
     wxASSERT((startRow + noRows) <= m_rowCount);
     if ((startRow + noRows) > m_rowCount)
         return false;
 
+    wxCHECK_MSG(noRows != m_rowCount, false, "Trying to delete all the cells in a table");
+
     wxRichTextBuffer* buffer = GetBuffer();
     wxRichTextBuffer* buffer = GetBuffer();
+    wxRichTextCtrl* rtc = buffer->GetRichTextCtrl();
+
+    wxPosition position = GetFocusedCell();
+    int focusCol = position.GetCol();
+    int focusRow = position.GetRow();
+    if (focusRow >= startRow && focusRow < (startRow+noRows))
+    {
+        // Deleting a focused cell causes a segfault later when laying out, due to GetFocusedObject() returning an invalid object
+        if ((startRow + noRows) < m_rowCount)
+        {
+            // There are more rows after the one(s) to be deleted, so set focus in the first of them
+            rtc->SetFocusObject(GetCell(startRow + noRows, focusCol));
+        }
+        else
+        {
+            // Otherwise set focus in the preceding row
+            rtc->SetFocusObject(GetCell(startRow - 1, focusCol));
+        }
+    }
+
     wxRichTextAction* action = NULL;
     wxRichTextTable* clone = NULL;
     wxRichTextAction* action = NULL;
     wxRichTextTable* clone = NULL;
-    if (!buffer->GetRichTextCtrl()->SuppressingUndo())
+    if (!rtc->SuppressingUndo())
     {
         // Create a clone containing the current state of the table. It will be used to Undo the action
         clone = wxStaticCast(this->Clone(), wxRichTextTable);
         clone->SetParent(GetParent());
     {
         // Create a clone containing the current state of the table. It will be used to Undo the action
         clone = wxStaticCast(this->Clone(), wxRichTextTable);
         clone->SetParent(GetParent());
-        action = new wxRichTextAction(NULL, _("Delete row"), wxRICHTEXT_CHANGE_OBJECT, buffer, this, buffer->GetRichTextCtrl());
+        action = new wxRichTextAction(NULL, _("Delete row"), wxRICHTEXT_CHANGE_OBJECT, buffer, this, rtc);
         action->SetObject(this);
         action->SetPosition(GetRange().GetStart());
     }
         action->SetObject(this);
         action->SetPosition(GetRange().GetStart());
     }
@@ -10277,7 +10320,7 @@ bool wxRichTextTable::DeleteRows(int startRow, int noRows)
 
     m_rowCount = m_rowCount - noRows;
 
 
     m_rowCount = m_rowCount - noRows;
 
-    if (!buffer->GetRichTextCtrl()->SuppressingUndo())
+    if (!rtc->SuppressingUndo())
     {
         buffer->SubmitAction(action);
         // Finally store the original-state clone; doing so earlier would cause various failures
     {
         buffer->SubmitAction(action);
         // Finally store the original-state clone; doing so earlier would cause various failures
@@ -10293,15 +10336,37 @@ bool wxRichTextTable::DeleteColumns(int startCol, int noCols)
     if ((startCol + noCols) > m_colCount)
         return false;
 
     if ((startCol + noCols) > m_colCount)
         return false;
 
+    wxCHECK_MSG(noCols != m_colCount, false, "Trying to delete all the cells in a table");
+
     wxRichTextBuffer* buffer = GetBuffer();
     wxRichTextBuffer* buffer = GetBuffer();
+    wxRichTextCtrl* rtc = buffer->GetRichTextCtrl();
+
+    wxPosition position = GetFocusedCell();
+    int focusCol = position.GetCol();
+    int focusRow = position.GetRow();
+    if (focusCol >= startCol && focusCol < (startCol+noCols))
+    {
+        // Deleting a focused cell causes a segfault later when laying out, due to GetFocusedObject() returning an invalid object
+        if ((startCol + noCols) < m_colCount)
+        {
+            // There are more columns after the one(s) to be deleted, so set focus in the first of them
+            rtc->SetFocusObject(GetCell(focusRow, startCol + noCols));
+        }
+        else
+        {
+            // Otherwise set focus in the preceding column
+            rtc->SetFocusObject(GetCell(focusRow, startCol - 1));
+        }
+    }
+
     wxRichTextAction* action = NULL;
     wxRichTextTable* clone = NULL;
     wxRichTextAction* action = NULL;
     wxRichTextTable* clone = NULL;
-    if (!buffer->GetRichTextCtrl()->SuppressingUndo())
+    if (!rtc->SuppressingUndo())
     {
         // Create a clone containing the current state of the table. It will be used to Undo the action
         clone = wxStaticCast(this->Clone(), wxRichTextTable);
         clone->SetParent(GetParent());
     {
         // Create a clone containing the current state of the table. It will be used to Undo the action
         clone = wxStaticCast(this->Clone(), wxRichTextTable);
         clone->SetParent(GetParent());
-        action = new wxRichTextAction(NULL, _("Delete column"), wxRICHTEXT_CHANGE_OBJECT, buffer, this, buffer->GetRichTextCtrl());
+        action = new wxRichTextAction(NULL, _("Delete column"), wxRICHTEXT_CHANGE_OBJECT, buffer, this, rtc);
         action->SetObject(this);
         action->SetPosition(GetRange().GetStart());
     }
         action->SetObject(this);
         action->SetPosition(GetRange().GetStart());
     }
@@ -10327,7 +10392,7 @@ bool wxRichTextTable::DeleteColumns(int startCol, int noCols)
         m_rowCount = 0;
     m_colCount = m_colCount - noCols;
 
         m_rowCount = 0;
     m_colCount = m_colCount - noCols;
 
-    if (!buffer->GetRichTextCtrl()->SuppressingUndo())
+    if (!rtc->SuppressingUndo())
     {
         buffer->SubmitAction(action);
         // Finally store the original-state clone; doing so earlier would cause various failures
     {
         buffer->SubmitAction(action);
         // Finally store the original-state clone; doing so earlier would cause various failures