wxRichTextRemoveStyle(child->GetAttributes(), style);
}
else if (resetExistingStyle)
+ {
+ // Preserve the URL as it's not really a formatting style but a property of the object
+ wxString url;
+ if (child->GetAttributes().HasURL() && !characterAttributes.HasURL())
+ url = child->GetAttributes().GetURL();
+
child->GetAttributes() = characterAttributes;
+
+ if (!url.IsEmpty())
+ child->GetAttributes().SetURL(url);
+ }
else
{
if (applyMinimal)
wxRichTextBuffer* buffer = GetBuffer();
if (buffer && buffer->GetRichTextCtrl())
{
- wxRichTextEvent event(wxEVT_COMMAND_RICHTEXT_BUFFER_RESET, buffer->GetRichTextCtrl()->GetId());
+ wxRichTextEvent event(wxEVT_RICHTEXT_BUFFER_RESET, buffer->GetRichTextCtrl()->GetId());
event.SetEventObject(buffer->GetRichTextCtrl());
event.SetContainer(this);
if (GetRichTextCtrl())
winid = GetRichTextCtrl()->GetId();
- wxRichTextEvent event(wxEVT_COMMAND_RICHTEXT_STYLESHEET_REPLACING, winid);
+ wxRichTextEvent event(wxEVT_RICHTEXT_STYLESHEET_REPLACING, winid);
event.SetEventObject(GetRichTextCtrl());
event.SetContainer(GetRichTextCtrl()->GetFocusObject());
event.SetOldStyleSheet(oldSheet);
SetStyleSheet(sheet);
- event.SetEventType(wxEVT_COMMAND_RICHTEXT_STYLESHEET_REPLACED);
+ event.SetEventType(wxEVT_RICHTEXT_STYLESHEET_REPLACED);
event.SetOldStyleSheet(NULL);
event.Allow();
{
m_cells.Clear();
DeleteChildren();
+ m_rowCount = 0;
+ m_colCount = 0;
}
bool wxRichTextTable::CreateTable(int rows, int cols)
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)
+ 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();
+ 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;
+ 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());
+ action = new wxRichTextAction(NULL, _("Delete row"), wxRICHTEXT_CHANGE_OBJECT, buffer, this, rtc);
+ action->SetObject(this);
+ action->SetPosition(GetRange().GetStart());
+ }
+
int i, j;
for (i = startRow; i < (startRow+noRows); i++)
{
m_rowCount = m_rowCount - noRows;
+ if (!rtc->SuppressingUndo())
+ {
+ buffer->SubmitAction(action);
+ // Finally store the original-state clone; doing so earlier would cause various failures
+ action->StoreObject(clone);
+ }
+
return true;
}
bool wxRichTextTable::DeleteColumns(int startCol, int noCols)
{
- wxASSERT((startCol + noCols) < m_colCount);
- if ((startCol + noCols) >= m_colCount)
+ wxASSERT((startCol + noCols) <= m_colCount);
+ 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();
+ 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;
+ 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());
+ action = new wxRichTextAction(NULL, _("Delete column"), wxRICHTEXT_CHANGE_OBJECT, buffer, this, rtc);
+ action->SetObject(this);
+ action->SetPosition(GetRange().GetStart());
+ }
+
bool deleteRows = (noCols == m_colCount);
int i, j;
for (i = 0; i < m_rowCount; i++)
{
wxRichTextObjectPtrArray& colArray = m_cells[deleteRows ? 0 : i];
- for (j = startCol; j < (startCol+noCols); j++)
+ for (j = 0; j < noCols; j++)
{
- wxRichTextObject* cell = colArray[j];
+ wxRichTextObject* cell = colArray[startCol];
RemoveChild(cell, true);
+ colArray.RemoveAt(startCol);
}
if (deleteRows)
m_rowCount = 0;
m_colCount = m_colCount - noCols;
+ if (!rtc->SuppressingUndo())
+ {
+ buffer->SubmitAction(action);
+ // Finally store the original-state clone; doing so earlier would cause various failures
+ action->StoreObject(clone);
+ }
+
return true;
}
if (startRow > m_rowCount)
return false;
+ wxRichTextBuffer* buffer = GetBuffer();
+ wxRichTextAction* action = NULL;
+ wxRichTextTable* clone = NULL;
+ if (!buffer->GetRichTextCtrl()->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());
+ action = new wxRichTextAction(NULL, _("Add row"), wxRICHTEXT_CHANGE_OBJECT, buffer, this, buffer->GetRichTextCtrl());
+ action->SetObject(this);
+ action->SetPosition(GetRange().GetStart());
+ }
+
int i, j;
for (i = 0; i < noRows; i++)
{
cell->GetAttributes() = attr;
AppendChild(cell);
+ cell->AddParagraph(wxEmptyString);
colArray.Add(cell);
}
}
m_rowCount = m_rowCount + noRows;
+
+ if (!buffer->GetRichTextCtrl()->SuppressingUndo())
+ {
+ buffer->SubmitAction(action);
+ // Finally store the original-state clone; doing so earlier would cause various failures
+ action->StoreObject(clone);
+ }
+
return true;
}
if (startCol > m_colCount)
return false;
+ wxRichTextBuffer* buffer = GetBuffer();
+ wxRichTextAction* action = NULL;
+ wxRichTextTable* clone = NULL;
+ if (!buffer->GetRichTextCtrl()->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());
+ action = new wxRichTextAction(NULL, _("Add column"), wxRICHTEXT_CHANGE_OBJECT, buffer, this, buffer->GetRichTextCtrl());
+ action->SetObject(this);
+ action->SetPosition(GetRange().GetStart());
+ }
+
int i, j;
for (i = 0; i < m_rowCount; i++)
{
cell->GetAttributes() = attr;
AppendChild(cell);
+ cell->AddParagraph(wxEmptyString);
if (startCol == m_colCount)
colArray.Add(cell);
m_colCount = m_colCount + noCols;
+ if (!buffer->GetRichTextCtrl()->SuppressingUndo())
+ {
+ buffer->SubmitAction(action);
+ // Finally store the original-state clone; doing so earlier would cause various failures
+ action->StoreObject(clone);
+ }
+
return true;
}
void wxRichTextModuleInit()
{
wxModule* module = new wxRichTextModule;
- module->Init();
wxModule::RegisterModule(module);
+ wxModule::InitializeModules();
}
UpdateAppearance(newCaretPosition, true /* send update event */, & optimizationLineCharPositions, & optimizationLineYPositions, true /* do */);
wxRichTextEvent cmdEvent(
- wxEVT_COMMAND_RICHTEXT_CONTENT_INSERTED,
+ wxEVT_RICHTEXT_CONTENT_INSERTED,
m_ctrl ? m_ctrl->GetId() : -1);
cmdEvent.SetEventObject(m_ctrl ? (wxObject*) m_ctrl : (wxObject*) m_buffer);
cmdEvent.SetRange(GetRange());
UpdateAppearance(caretPos, true /* send update event */, & optimizationLineCharPositions, & optimizationLineYPositions, true /* do */);
wxRichTextEvent cmdEvent(
- wxEVT_COMMAND_RICHTEXT_CONTENT_DELETED,
+ wxEVT_RICHTEXT_CONTENT_DELETED,
m_ctrl ? m_ctrl->GetId() : -1);
cmdEvent.SetEventObject(m_ctrl ? (wxObject*) m_ctrl : (wxObject*) m_buffer);
cmdEvent.SetRange(GetRange());
UpdateAppearance(GetPosition());
wxRichTextEvent cmdEvent(
- m_cmdId == wxRICHTEXT_CHANGE_STYLE ? wxEVT_COMMAND_RICHTEXT_STYLE_CHANGED : wxEVT_COMMAND_RICHTEXT_PROPERTIES_CHANGED,
+ m_cmdId == wxRICHTEXT_CHANGE_STYLE ? wxEVT_RICHTEXT_STYLE_CHANGED : wxEVT_RICHTEXT_PROPERTIES_CHANGED,
m_ctrl ? m_ctrl->GetId() : -1);
cmdEvent.SetEventObject(m_ctrl ? (wxObject*) m_ctrl : (wxObject*) m_buffer);
cmdEvent.SetRange(GetRange());
UpdateAppearance(GetPosition());
wxRichTextEvent cmdEvent(
- wxEVT_COMMAND_RICHTEXT_STYLE_CHANGED,
+ wxEVT_RICHTEXT_STYLE_CHANGED,
m_ctrl ? m_ctrl->GetId() : -1);
cmdEvent.SetEventObject(m_ctrl ? (wxObject*) m_ctrl : (wxObject*) m_buffer);
cmdEvent.SetRange(GetRange());
case wxRICHTEXT_CHANGE_OBJECT:
{
wxRichTextObject* obj = m_objectAddress.GetObject(m_buffer);
- // wxRichTextObject* obj = container->GetChildAtPosition(GetRange().GetStart());
- if (obj && m_object)
+ if (obj && m_object && m_ctrl)
{
- wxRichTextObjectList::compatibility_iterator node = container->GetChildren().Find(obj);
+ // The plan is to swap the current object with the stored, previous-state, clone
+ // We can't get 'node' from the containing buffer (as it doesn't directly store objects)
+ // so use the parent paragraph
+ wxRichTextParagraph* para = wxDynamicCast(obj->GetParent(), wxRichTextParagraph);
+ wxCHECK_MSG(para, false, "Invalid parent paragraph");
+
+ // The stored object, m_object, may have a stale parent paragraph. This would cause
+ // a crash during layout, so use obj's parent para, which should be the correct one.
+ // (An alternative would be to return the parent too from m_objectAddress.GetObject(),
+ // or to set obj's parent there before returning)
+ m_object->SetParent(para);
+
+ wxRichTextObjectList::compatibility_iterator node = para->GetChildren().Find(obj);
if (node)
{
wxRichTextObject* obj = node->GetData();
UpdateAppearance(newCaretPosition, true, /* send update event */ & optimizationLineCharPositions, & optimizationLineYPositions, false /* undo */);
wxRichTextEvent cmdEvent(
- wxEVT_COMMAND_RICHTEXT_CONTENT_DELETED,
+ wxEVT_RICHTEXT_CONTENT_DELETED,
m_ctrl ? m_ctrl->GetId() : -1);
cmdEvent.SetEventObject(m_ctrl ? (wxObject*) m_ctrl : (wxObject*) m_buffer);
cmdEvent.SetRange(GetRange());
UpdateAppearance(GetPosition(), true, /* send update event */ & optimizationLineCharPositions, & optimizationLineYPositions, false /* undo */);
wxRichTextEvent cmdEvent(
- wxEVT_COMMAND_RICHTEXT_CONTENT_INSERTED,
+ wxEVT_RICHTEXT_CONTENT_INSERTED,
m_ctrl ? m_ctrl->GetId() : -1);
cmdEvent.SetEventObject(m_ctrl ? (wxObject*) m_ctrl : (wxObject*) m_buffer);
cmdEvent.SetRange(GetRange());
UpdateAppearance(GetPosition());
wxRichTextEvent cmdEvent(
- m_cmdId == wxRICHTEXT_CHANGE_STYLE ? wxEVT_COMMAND_RICHTEXT_STYLE_CHANGED : wxEVT_COMMAND_RICHTEXT_PROPERTIES_CHANGED,
+ m_cmdId == wxRICHTEXT_CHANGE_STYLE ? wxEVT_RICHTEXT_STYLE_CHANGED : wxEVT_RICHTEXT_PROPERTIES_CHANGED,
m_ctrl ? m_ctrl->GetId() : -1);
cmdEvent.SetEventObject(m_ctrl ? (wxObject*) m_ctrl : (wxObject*) m_buffer);
cmdEvent.SetRange(GetRange());
// find the first line which is being drawn at the same position as it was
// before. Since we're talking about a simple insertion, we can assume
// that the rest of the window does not need to be redrawn.
+ long pos = GetRange().GetStart();
- wxRichTextParagraph* para = container->GetParagraphAtPosition(GetPosition());
+ wxRichTextParagraph* para = container->GetParagraphAtPosition(pos, false /* is not caret pos */);
// Since we support floating layout, we should redraw the whole para instead of just
// the first line touching the invalid range.
if (para)
{
- firstY = para->GetPosition().y;
+ // In case something was drawn above the paragraph,
+ // such as a line break, allow a little extra.
+ firstY = para->GetPosition().y - 4;
}
wxRichTextObjectList::compatibility_iterator node = container->GetChildren().Find(para);
// Stop, we're now the same as we were
foundEnd = true;
- lastY = pt.y;
+ lastY = pt.y + line->GetSize().y;
node2 = wxRichTextLineList::compatibility_iterator();
node = wxRichTextObjectList::compatibility_iterator();