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:
Julian Smart
2012-01-25 15:10:09 +00:00
parent eccdb55165
commit cc2aecdef5
7 changed files with 369 additions and 41 deletions

View File

@@ -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

View File

@@ -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
/** /**

View File

@@ -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

View File

@@ -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
/** /**

View File

@@ -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);
}

View File

@@ -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());

View File

@@ -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