Added further API for intercepting deletion and content insertion
Added simple implementation of locked objects to sample git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@70465 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -3231,6 +3231,12 @@ public:
|
|||||||
|
|
||||||
virtual wxRichTextObject* Clone() const { return new wxRichTextParagraphLayoutBox(*this); }
|
virtual wxRichTextObject* Clone() const { return new wxRichTextParagraphLayoutBox(*this); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
Prepares the content just before insertion (or after buffer reset).
|
||||||
|
Currently is only called if undo mode is on.
|
||||||
|
*/
|
||||||
|
virtual void PrepareContent(wxRichTextParagraphLayoutBox& container);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Insert fragment into this box at the given position. If partialParagraph is true,
|
Insert fragment into this box at the given position. If partialParagraph is true,
|
||||||
it is assumed that the last (or only) paragraph is just a piece of data with no paragraph
|
it is assumed that the last (or only) paragraph is just a piece of data with no paragraph
|
||||||
|
@@ -1658,6 +1658,24 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual wxString GetPropertiesMenuLabel(wxRichTextObject* obj) { return obj->GetPropertiesMenuLabel(); }
|
virtual wxString GetPropertiesMenuLabel(wxRichTextObject* obj) { return obj->GetPropertiesMenuLabel(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
Prepares the content just before insertion (or after buffer reset). Called by the same function in wxRichTextBuffer.
|
||||||
|
Currently is only called if undo mode is on.
|
||||||
|
*/
|
||||||
|
virtual void PrepareContent(wxRichTextParagraphLayoutBox& WXUNUSED(container)) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Can we delete this range?
|
||||||
|
Sends an event to the control.
|
||||||
|
*/
|
||||||
|
virtual bool CanDeleteRange(wxRichTextParagraphLayoutBox& container, const wxRichTextRange& range) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Can we insert content at this position?
|
||||||
|
Sends an event to the control.
|
||||||
|
*/
|
||||||
|
virtual bool CanInsertContent(wxRichTextParagraphLayoutBox& container, long pos) const;
|
||||||
|
|
||||||
// Command handlers
|
// Command handlers
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -3111,6 +3111,12 @@ public:
|
|||||||
|
|
||||||
virtual wxRichTextObject* Clone() const { return new wxRichTextParagraphLayoutBox(*this); }
|
virtual wxRichTextObject* Clone() const { return new wxRichTextParagraphLayoutBox(*this); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
Prepares the content just before insertion (or after buffer reset).
|
||||||
|
Currently is only called if undo mode is on.
|
||||||
|
*/
|
||||||
|
virtual void PrepareContent(wxRichTextParagraphLayoutBox& container);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Insert fragment into this box at the given position. If partialParagraph is true,
|
Insert fragment into this box at the given position. If partialParagraph is true,
|
||||||
it is assumed that the last (or only) paragraph is just a piece of data with no paragraph
|
it is assumed that the last (or only) paragraph is just a piece of data with no paragraph
|
||||||
|
@@ -1617,6 +1617,24 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual wxString GetPropertiesMenuLabel(wxRichTextObject* obj);
|
virtual wxString GetPropertiesMenuLabel(wxRichTextObject* obj);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Prepares the content just before insertion (or after buffer reset). Called by the same function in wxRichTextBuffer.
|
||||||
|
Currently is only called if undo mode is on.
|
||||||
|
*/
|
||||||
|
virtual void PrepareContent(wxRichTextParagraphLayoutBox& WXUNUSED(container)) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Can we delete this range?
|
||||||
|
Sends an event to the control.
|
||||||
|
*/
|
||||||
|
virtual bool CanDeleteRange(wxRichTextParagraphLayoutBox& container, const wxRichTextRange& range) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Can we insert content at this position?
|
||||||
|
Sends an event to the control.
|
||||||
|
*/
|
||||||
|
virtual bool CanInsertContent(wxRichTextParagraphLayoutBox& container, long pos) const;
|
||||||
|
|
||||||
// Command handlers
|
// Command handlers
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -89,6 +89,49 @@
|
|||||||
// private classes
|
// private classes
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Define a new application type, each program should derive a class from wxApp
|
||||||
|
class MyRichTextCtrl: public wxRichTextCtrl
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MyRichTextCtrl( wxWindow* parent, wxWindowID id = -1, const wxString& value = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize,
|
||||||
|
long style = wxRE_MULTILINE, const wxValidator& validator = wxDefaultValidator, const wxString& name = wxTextCtrlNameStr):
|
||||||
|
wxRichTextCtrl(parent, id, value, pos, size, style, validator, name)
|
||||||
|
{
|
||||||
|
m_lockId = 0;
|
||||||
|
m_locked = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetLockId(long id) { m_lockId = id; }
|
||||||
|
long GetLockId() const { return m_lockId; }
|
||||||
|
|
||||||
|
void BeginLock() { m_lockId ++; m_locked = true; }
|
||||||
|
void EndLock() { m_locked = false; }
|
||||||
|
bool IsLocked() const { return m_locked; }
|
||||||
|
|
||||||
|
static void SetEnhancedDrawingHandler();
|
||||||
|
|
||||||
|
/**
|
||||||
|
Prepares the content just before insertion (or after buffer reset). Called by the same function in wxRichTextBuffer.
|
||||||
|
Currently is only called if undo mode is on.
|
||||||
|
*/
|
||||||
|
virtual void PrepareContent(wxRichTextParagraphLayoutBox& container);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Can we delete this range?
|
||||||
|
Sends an event to the control.
|
||||||
|
*/
|
||||||
|
virtual bool CanDeleteRange(wxRichTextParagraphLayoutBox& container, const wxRichTextRange& range) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Can we insert content at this position?
|
||||||
|
Sends an event to the control.
|
||||||
|
*/
|
||||||
|
virtual bool CanInsertContent(wxRichTextParagraphLayoutBox& container, long pos) const;
|
||||||
|
|
||||||
|
long m_lockId;
|
||||||
|
bool m_locked;
|
||||||
|
};
|
||||||
|
|
||||||
// Define a new application type, each program should derive a class from wxApp
|
// Define a new application type, each program should derive a class from wxApp
|
||||||
class MyApp : public wxApp
|
class MyApp : public wxApp
|
||||||
{
|
{
|
||||||
@@ -205,7 +248,7 @@ private:
|
|||||||
// any class wishing to process wxWidgets events must use this macro
|
// any class wishing to process wxWidgets events must use this macro
|
||||||
DECLARE_EVENT_TABLE()
|
DECLARE_EVENT_TABLE()
|
||||||
|
|
||||||
wxRichTextCtrl* m_richTextCtrl;
|
MyRichTextCtrl* m_richTextCtrl;
|
||||||
};
|
};
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -387,6 +430,8 @@ bool MyApp::OnInit()
|
|||||||
|
|
||||||
CreateStyles();
|
CreateStyles();
|
||||||
|
|
||||||
|
MyRichTextCtrl::SetEnhancedDrawingHandler();
|
||||||
|
|
||||||
// Add extra handlers (plain text is automatically added)
|
// Add extra handlers (plain text is automatically added)
|
||||||
wxRichTextBuffer::AddHandler(new wxRichTextXMLHandler);
|
wxRichTextBuffer::AddHandler(new wxRichTextXMLHandler);
|
||||||
wxRichTextBuffer::AddHandler(new wxRichTextHTMLHandler);
|
wxRichTextBuffer::AddHandler(new wxRichTextHTMLHandler);
|
||||||
@@ -736,7 +781,7 @@ MyFrame::MyFrame(const wxString& title, wxWindowID id, const wxPoint& pos,
|
|||||||
wxFont boldFont = wxFont(12, wxROMAN, wxNORMAL, wxBOLD);
|
wxFont boldFont = wxFont(12, wxROMAN, wxNORMAL, wxBOLD);
|
||||||
wxFont italicFont = wxFont(12, wxROMAN, wxITALIC, wxNORMAL);
|
wxFont italicFont = wxFont(12, wxROMAN, wxITALIC, wxNORMAL);
|
||||||
|
|
||||||
m_richTextCtrl = new wxRichTextCtrl(splitter, ID_RICHTEXT_CTRL, wxEmptyString, wxDefaultPosition, wxSize(200, 200), wxVSCROLL|wxHSCROLL|wxWANTS_CHARS);
|
m_richTextCtrl = new MyRichTextCtrl(splitter, ID_RICHTEXT_CTRL, wxEmptyString, wxDefaultPosition, wxSize(200, 200), wxVSCROLL|wxHSCROLL|wxWANTS_CHARS);
|
||||||
wxFont font(12, wxROMAN, wxNORMAL, wxNORMAL);
|
wxFont font(12, wxROMAN, wxNORMAL, wxNORMAL);
|
||||||
|
|
||||||
m_richTextCtrl->SetFont(font);
|
m_richTextCtrl->SetFont(font);
|
||||||
@@ -773,10 +818,27 @@ MyFrame::MyFrame(const wxString& title, wxWindowID id, const wxPoint& pos,
|
|||||||
// Write text
|
// Write text
|
||||||
void MyFrame::WriteInitialText()
|
void MyFrame::WriteInitialText()
|
||||||
{
|
{
|
||||||
wxRichTextCtrl& r = *m_richTextCtrl;
|
MyRichTextCtrl& r = *m_richTextCtrl;
|
||||||
|
|
||||||
r.SetDefaultStyle(wxRichTextAttr());
|
r.SetDefaultStyle(wxRichTextAttr());
|
||||||
|
|
||||||
|
// Add some locked content first - needs Undo to be enabled
|
||||||
|
{
|
||||||
|
r.BeginLock();
|
||||||
|
r.WriteText(wxString(wxT("This is a locked object.")));
|
||||||
|
r.EndLock();
|
||||||
|
|
||||||
|
r.WriteText(wxString(wxT(" This is unlocked text. ")));
|
||||||
|
|
||||||
|
r.BeginLock();
|
||||||
|
r.WriteText(wxString(wxT("More locked content.")));
|
||||||
|
r.EndLock();
|
||||||
|
r.Newline();
|
||||||
|
|
||||||
|
// Flush the Undo buffer
|
||||||
|
r.GetCommandProcessor()->ClearCommands();
|
||||||
|
}
|
||||||
|
|
||||||
r.BeginSuppressUndo();
|
r.BeginSuppressUndo();
|
||||||
|
|
||||||
r.Freeze();
|
r.Freeze();
|
||||||
@@ -1807,3 +1869,107 @@ void MyFrame::OnPageSetup(wxCommandEvent& WXUNUSED(event))
|
|||||||
|
|
||||||
// wxGetApp().GetPrinting()->PageSetup();
|
// wxGetApp().GetPrinting()->PageSetup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MyRichTextCtrl::PrepareContent(wxRichTextParagraphLayoutBox& container)
|
||||||
|
{
|
||||||
|
if (IsLocked())
|
||||||
|
{
|
||||||
|
// Lock all content that's about to be added to the control
|
||||||
|
wxRichTextObjectList::compatibility_iterator node = container.GetChildren().GetFirst();
|
||||||
|
while (node)
|
||||||
|
{
|
||||||
|
wxRichTextParagraph* para = wxDynamicCast(node->GetData(), wxRichTextParagraph);
|
||||||
|
if (para)
|
||||||
|
{
|
||||||
|
wxRichTextObjectList::compatibility_iterator childNode = para->GetChildren().GetFirst();
|
||||||
|
while (childNode)
|
||||||
|
{
|
||||||
|
wxRichTextObject* obj = childNode->GetData();
|
||||||
|
obj->GetProperties().SetProperty(wxT("Lock"), m_lockId);
|
||||||
|
|
||||||
|
childNode = childNode->GetNext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
node = node->GetNext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MyRichTextCtrl::CanDeleteRange(wxRichTextParagraphLayoutBox& container, const wxRichTextRange& range) const
|
||||||
|
{
|
||||||
|
long i;
|
||||||
|
for (i = range.GetStart(); i < range.GetEnd(); i++)
|
||||||
|
{
|
||||||
|
wxRichTextObject* obj = container.GetLeafObjectAtPosition(i);
|
||||||
|
if (obj && obj->GetProperties().HasProperty(wxT("Lock")))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MyRichTextCtrl::CanInsertContent(wxRichTextParagraphLayoutBox& container, long pos) const
|
||||||
|
{
|
||||||
|
wxRichTextObject* child1 = container.GetLeafObjectAtPosition(pos);
|
||||||
|
wxRichTextObject* child2 = container.GetLeafObjectAtPosition(pos-1);
|
||||||
|
|
||||||
|
long lock1 = -1, lock2 = -1;
|
||||||
|
|
||||||
|
if (child1 && child1->GetProperties().HasProperty(wxT("Lock")))
|
||||||
|
lock1 = child1->GetProperties().GetPropertyLong(wxT("Lock"));
|
||||||
|
if (child2 && child2->GetProperties().HasProperty(wxT("Lock")))
|
||||||
|
lock2 = child2->GetProperties().GetPropertyLong(wxT("Lock"));
|
||||||
|
|
||||||
|
if (lock1 != -1 && lock1 == lock2)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Don't allow insertion before a locked object if it's at the beginning of the buffer.
|
||||||
|
if (pos == 0 && lock1 != -1)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class wxRichTextEnhancedDrawingHandler: public wxRichTextDrawingHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
wxRichTextEnhancedDrawingHandler()
|
||||||
|
{
|
||||||
|
SetName(wxT("enhanceddrawing"));
|
||||||
|
m_lockBackgroundColour = wxColour(220, 220, 220);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns @true if this object has virtual attributes that we can provide.
|
||||||
|
*/
|
||||||
|
virtual bool HasVirtualAttributes(wxRichTextObject* obj) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Provides virtual attributes that we can provide.
|
||||||
|
*/
|
||||||
|
virtual bool GetVirtualAttributes(wxRichTextAttr& attr, wxRichTextObject* obj) const;
|
||||||
|
|
||||||
|
wxColour m_lockBackgroundColour;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool wxRichTextEnhancedDrawingHandler::HasVirtualAttributes(wxRichTextObject* obj) const
|
||||||
|
{
|
||||||
|
return obj->GetProperties().HasProperty(wxT("Lock"));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wxRichTextEnhancedDrawingHandler::GetVirtualAttributes(wxRichTextAttr& attr, wxRichTextObject* obj) const
|
||||||
|
{
|
||||||
|
if (obj->GetProperties().HasProperty(wxT("Lock")))
|
||||||
|
{
|
||||||
|
attr.SetBackgroundColour(m_lockBackgroundColour);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MyRichTextCtrl::SetEnhancedDrawingHandler()
|
||||||
|
{
|
||||||
|
wxRichTextBuffer::AddDrawingHandler(new wxRichTextEnhancedDrawingHandler);
|
||||||
|
}
|
||||||
|
@@ -3524,6 +3524,14 @@ bool wxRichTextParagraphLayoutBox::HasParagraphAttributes(const wxRichTextRange&
|
|||||||
return foundCount == matchingCount && foundCount != 0;
|
return foundCount == matchingCount && foundCount != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void wxRichTextParagraphLayoutBox::PrepareContent(wxRichTextParagraphLayoutBox& container)
|
||||||
|
{
|
||||||
|
wxRichTextBuffer* buffer = GetBuffer();
|
||||||
|
if (buffer && buffer->GetRichTextCtrl())
|
||||||
|
buffer->GetRichTextCtrl()->PrepareContent(container);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Set character or paragraph properties
|
/// Set character or paragraph properties
|
||||||
bool wxRichTextParagraphLayoutBox::SetProperties(const wxRichTextRange& range, const wxRichTextProperties& properties, int flags)
|
bool wxRichTextParagraphLayoutBox::SetProperties(const wxRichTextRange& range, const wxRichTextProperties& properties, int flags)
|
||||||
{
|
{
|
||||||
@@ -3697,6 +3705,8 @@ void wxRichTextParagraphLayoutBox::Reset()
|
|||||||
|
|
||||||
AddParagraph(wxEmptyString);
|
AddParagraph(wxEmptyString);
|
||||||
|
|
||||||
|
PrepareContent(*this);
|
||||||
|
|
||||||
InvalidateHierarchy(wxRICHTEXT_ALL);
|
InvalidateHierarchy(wxRICHTEXT_ALL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7201,6 +7211,9 @@ bool wxRichTextBuffer::EndBatchUndo()
|
|||||||
/// Submit immediately, or delay according to whether collapsing is on
|
/// Submit immediately, or delay according to whether collapsing is on
|
||||||
bool wxRichTextBuffer::SubmitAction(wxRichTextAction* action)
|
bool wxRichTextBuffer::SubmitAction(wxRichTextAction* action)
|
||||||
{
|
{
|
||||||
|
if (action && !action->GetNewParagraphs().IsEmpty())
|
||||||
|
PrepareContent(action->GetNewParagraphs());
|
||||||
|
|
||||||
if (BatchingUndo() && m_batchedCommand && !SuppressingUndo())
|
if (BatchingUndo() && m_batchedCommand && !SuppressingUndo())
|
||||||
{
|
{
|
||||||
wxRichTextCommand* cmd = new wxRichTextCommand(action->GetName());
|
wxRichTextCommand* cmd = new wxRichTextCommand(action->GetName());
|
||||||
|
@@ -1113,12 +1113,26 @@ void wxRichTextCtrl::OnChar(wxKeyEvent& event)
|
|||||||
// Must process this before translation, otherwise it's translated into a WXK_DELETE event.
|
// Must process this before translation, otherwise it's translated into a WXK_DELETE event.
|
||||||
if (event.CmdDown() && event.GetKeyCode() == WXK_BACK)
|
if (event.CmdDown() && event.GetKeyCode() == WXK_BACK)
|
||||||
{
|
{
|
||||||
|
if (!IsEditable())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (HasSelection() && !CanDeleteRange(* GetFocusObject(), GetSelectionRange()))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
BeginBatchUndo(_("Delete Text"));
|
BeginBatchUndo(_("Delete Text"));
|
||||||
|
|
||||||
long newPos = m_caretPosition;
|
long newPos = m_caretPosition;
|
||||||
|
|
||||||
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,
|
// 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.
|
// so subtract 1 for deleted character and add 1 for conversion to character position.
|
||||||
if (newPos > -1)
|
if (newPos > -1)
|
||||||
@@ -1128,13 +1142,25 @@ void wxRichTextCtrl::OnChar(wxKeyEvent& event)
|
|||||||
long pos = wxRichTextCtrl::FindNextWordPosition(-1);
|
long pos = wxRichTextCtrl::FindNextWordPosition(-1);
|
||||||
if (pos < newPos)
|
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;
|
processed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!processed)
|
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,6 +1176,8 @@ void wxRichTextCtrl::OnChar(wxKeyEvent& event)
|
|||||||
|
|
||||||
ScrollIntoView(m_caretPosition, WXK_LEFT);
|
ScrollIntoView(m_caretPosition, WXK_LEFT);
|
||||||
|
|
||||||
|
if (deletions > 0)
|
||||||
|
{
|
||||||
wxRichTextEvent cmdEvent(
|
wxRichTextEvent cmdEvent(
|
||||||
wxEVT_COMMAND_RICHTEXT_DELETE,
|
wxEVT_COMMAND_RICHTEXT_DELETE,
|
||||||
GetId());
|
GetId());
|
||||||
@@ -1158,6 +1186,7 @@ void wxRichTextCtrl::OnChar(wxKeyEvent& event)
|
|||||||
cmdEvent.SetPosition(m_caretPosition+1);
|
cmdEvent.SetPosition(m_caretPosition+1);
|
||||||
cmdEvent.SetContainer(GetFocusObject());
|
cmdEvent.SetContainer(GetFocusObject());
|
||||||
GetEventHandler()->ProcessEvent(cmdEvent);
|
GetEventHandler()->ProcessEvent(cmdEvent);
|
||||||
|
}
|
||||||
|
|
||||||
Update();
|
Update();
|
||||||
}
|
}
|
||||||
@@ -1177,10 +1206,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);
|
DeleteSelectedContent(& newPos);
|
||||||
|
|
||||||
if (event.ShiftDown())
|
if (event.ShiftDown())
|
||||||
@@ -1219,12 +1256,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,
|
// 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.
|
// so subtract 1 for deleted character and add 1 for conversion to character position.
|
||||||
if (newPos > -1)
|
if (newPos > -1)
|
||||||
@@ -1234,13 +1280,25 @@ void wxRichTextCtrl::OnChar(wxKeyEvent& event)
|
|||||||
long pos = wxRichTextCtrl::FindNextWordPosition(-1);
|
long pos = wxRichTextCtrl::FindNextWordPosition(-1);
|
||||||
if (pos < newPos)
|
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;
|
processed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!processed)
|
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,6 +1314,8 @@ void wxRichTextCtrl::OnChar(wxKeyEvent& event)
|
|||||||
|
|
||||||
ScrollIntoView(m_caretPosition, WXK_LEFT);
|
ScrollIntoView(m_caretPosition, WXK_LEFT);
|
||||||
|
|
||||||
|
if (deletions > 0)
|
||||||
|
{
|
||||||
wxRichTextEvent cmdEvent(
|
wxRichTextEvent cmdEvent(
|
||||||
wxEVT_COMMAND_RICHTEXT_DELETE,
|
wxEVT_COMMAND_RICHTEXT_DELETE,
|
||||||
GetId());
|
GetId());
|
||||||
@@ -1264,17 +1324,27 @@ void wxRichTextCtrl::OnChar(wxKeyEvent& event)
|
|||||||
cmdEvent.SetPosition(m_caretPosition+1);
|
cmdEvent.SetPosition(m_caretPosition+1);
|
||||||
cmdEvent.SetContainer(GetFocusObject());
|
cmdEvent.SetContainer(GetFocusObject());
|
||||||
GetEventHandler()->ProcessEvent(cmdEvent);
|
GetEventHandler()->ProcessEvent(cmdEvent);
|
||||||
|
}
|
||||||
|
|
||||||
Update();
|
Update();
|
||||||
}
|
}
|
||||||
else if (event.GetKeyCode() == WXK_DELETE)
|
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,
|
// Submit range in character positions, which are greater than caret positions,
|
||||||
if (newPos < GetFocusObject()->GetOwnRange().GetEnd()+1)
|
if (newPos < GetFocusObject()->GetOwnRange().GetEnd()+1)
|
||||||
{
|
{
|
||||||
@@ -1283,13 +1353,25 @@ void wxRichTextCtrl::OnChar(wxKeyEvent& event)
|
|||||||
long pos = wxRichTextCtrl::FindNextWordPosition(1);
|
long pos = wxRichTextCtrl::FindNextWordPosition(1);
|
||||||
if (pos != -1 && (pos > newPos))
|
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;
|
processed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!processed && newPos < (GetLastPosition()-1))
|
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,6 +1387,8 @@ void wxRichTextCtrl::OnChar(wxKeyEvent& event)
|
|||||||
|
|
||||||
ScrollIntoView(m_caretPosition, WXK_LEFT);
|
ScrollIntoView(m_caretPosition, WXK_LEFT);
|
||||||
|
|
||||||
|
if (deletions > 0)
|
||||||
|
{
|
||||||
wxRichTextEvent cmdEvent(
|
wxRichTextEvent cmdEvent(
|
||||||
wxEVT_COMMAND_RICHTEXT_DELETE,
|
wxEVT_COMMAND_RICHTEXT_DELETE,
|
||||||
GetId());
|
GetId());
|
||||||
@@ -1313,6 +1397,7 @@ void wxRichTextCtrl::OnChar(wxKeyEvent& event)
|
|||||||
cmdEvent.SetPosition(m_caretPosition+1);
|
cmdEvent.SetPosition(m_caretPosition+1);
|
||||||
cmdEvent.SetContainer(GetFocusObject());
|
cmdEvent.SetContainer(GetFocusObject());
|
||||||
GetEventHandler()->ProcessEvent(cmdEvent);
|
GetEventHandler()->ProcessEvent(cmdEvent);
|
||||||
|
}
|
||||||
|
|
||||||
Update();
|
Update();
|
||||||
}
|
}
|
||||||
@@ -1377,6 +1462,12 @@ void wxRichTextCtrl::OnChar(wxKeyEvent& event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!CanInsertContent(* GetFocusObject(), m_caretPosition+1))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (HasSelection() && !CanDeleteRange(* GetFocusObject(), GetSelectionRange()))
|
||||||
|
return;
|
||||||
|
|
||||||
BeginBatchUndo(_("Insert Text"));
|
BeginBatchUndo(_("Insert Text"));
|
||||||
|
|
||||||
long newPos = m_caretPosition;
|
long newPos = m_caretPosition;
|
||||||
@@ -3018,12 +3109,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 false;
|
||||||
|
|
||||||
return GetBuffer().CanPasteFromClipboard();
|
return GetBuffer().CanPasteFromClipboard();
|
||||||
@@ -3031,7 +3122,7 @@ bool wxRichTextCtrl::CanPaste() const
|
|||||||
|
|
||||||
bool wxRichTextCtrl::CanDeleteSelection() const
|
bool wxRichTextCtrl::CanDeleteSelection() const
|
||||||
{
|
{
|
||||||
return HasSelection() && IsEditable();
|
return HasSelection() && IsEditable() && CanDeleteRange(* GetFocusObject(), GetSelectionRange());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -4460,6 +4551,16 @@ 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#if wxRICHTEXT_USE_OWN_CARET
|
#if wxRICHTEXT_USE_OWN_CARET
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user