Applied patch for #15189 - avoid crash when deleting focused cell (dghart)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@74058 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -66,6 +66,7 @@
|
|||||||
#include "wx/cmdproc.h"
|
#include "wx/cmdproc.h"
|
||||||
#include "wx/txtstrm.h"
|
#include "wx/txtstrm.h"
|
||||||
#include "wx/variant.h"
|
#include "wx/variant.h"
|
||||||
|
#include "wx/position.h"
|
||||||
|
|
||||||
#if wxUSE_DATAOBJ
|
#if wxUSE_DATAOBJ
|
||||||
#include "wx/dataobj.h"
|
#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
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -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
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -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)
|
bool wxRichTextTable::DeleteRows(int startRow, int noRows)
|
||||||
{
|
{
|
||||||
wxASSERT((startRow + noRows) <= m_rowCount);
|
wxASSERT((startRow + noRows) <= m_rowCount);
|
||||||
if ((startRow + noRows) > m_rowCount)
|
if ((startRow + noRows) > m_rowCount)
|
||||||
return false;
|
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;
|
wxRichTextAction* action = NULL;
|
||||||
wxRichTextTable* clone = 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
|
// Create a clone containing the current state of the table. It will be used to Undo the action
|
||||||
clone = wxStaticCast(this->Clone(), wxRichTextTable);
|
clone = wxStaticCast(this->Clone(), wxRichTextTable);
|
||||||
clone->SetParent(GetParent());
|
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->SetObject(this);
|
||||||
action->SetPosition(GetRange().GetStart());
|
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);
|
buffer->SubmitAction(action);
|
||||||
// Finally store the original-state clone; doing so earlier would cause various failures
|
// 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)
|
if ((startCol + noCols) > m_colCount)
|
||||||
return false;
|
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;
|
wxRichTextAction* action = NULL;
|
||||||
wxRichTextTable* clone = 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
|
// Create a clone containing the current state of the table. It will be used to Undo the action
|
||||||
clone = wxStaticCast(this->Clone(), wxRichTextTable);
|
clone = wxStaticCast(this->Clone(), wxRichTextTable);
|
||||||
clone->SetParent(GetParent());
|
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->SetObject(this);
|
||||||
action->SetPosition(GetRange().GetStart());
|
action->SetPosition(GetRange().GetStart());
|
||||||
}
|
}
|
||||||
@@ -10327,7 +10392,7 @@ bool wxRichTextTable::DeleteColumns(int startCol, int noCols)
|
|||||||
m_rowCount = 0;
|
m_rowCount = 0;
|
||||||
m_colCount = m_colCount - noCols;
|
m_colCount = m_colCount - noCols;
|
||||||
|
|
||||||
if (!buffer->GetRichTextCtrl()->SuppressingUndo())
|
if (!rtc->SuppressingUndo())
|
||||||
{
|
{
|
||||||
buffer->SubmitAction(action);
|
buffer->SubmitAction(action);
|
||||||
// Finally store the original-state clone; doing so earlier would cause various failures
|
// Finally store the original-state clone; doing so earlier would cause various failures
|
||||||
|
Reference in New Issue
Block a user