X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/2d143b6689b9ce3f02398d1ee4129f6a21024183..d87098c062ac92e38434f89eba372fa8547ebaa4:/samples/richtext/richtext.cpp?ds=sidebyside diff --git a/samples/richtext/richtext.cpp b/samples/richtext/richtext.cpp index 860e15d022..d50ec7b575 100644 --- a/samples/richtext/richtext.cpp +++ b/samples/richtext/richtext.cpp @@ -35,6 +35,7 @@ #include "wx/sstream.h" #include "wx/html/htmlwin.h" #include "wx/stopwatch.h" +#include "wx/sysopt.h" #if wxUSE_FILESYSTEM #include "wx/filesys.h" @@ -45,7 +46,7 @@ #include "wx/cshelp.h" #endif -#ifndef __WXMSW__ +#ifndef wxHAS_IMAGES_IN_RESOURCES #include "../sample.xpm" #endif @@ -89,6 +90,49 @@ // 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 class MyApp : public wxApp { @@ -205,7 +249,7 @@ private: // any class wishing to process wxWidgets events must use this macro DECLARE_EVENT_TABLE() - wxRichTextCtrl* m_richTextCtrl; + MyRichTextCtrl* m_richTextCtrl; }; // ---------------------------------------------------------------------------- @@ -387,6 +431,8 @@ bool MyApp::OnInit() CreateStyles(); + MyRichTextCtrl::SetEnhancedDrawingHandler(); + // Add extra handlers (plain text is automatically added) wxRichTextBuffer::AddHandler(new wxRichTextXMLHandler); wxRichTextBuffer::AddHandler(new wxRichTextHTMLHandler); @@ -589,6 +635,10 @@ MyFrame::MyFrame(const wxString& title, wxWindowID id, const wxPoint& pos, const wxSize& size, long style) : wxFrame(NULL, id, title, pos, size, style) { +#ifdef __WXMAC__ + SetWindowVariant(wxWINDOW_VARIANT_SMALL); +#endif + // set the frame icon SetIcon(wxICON(sample)); @@ -699,7 +749,21 @@ MyFrame::MyFrame(const wxString& title, wxWindowID id, const wxPoint& pos, } #endif - wxToolBar* toolBar = CreateToolBar(); + wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL); + SetSizer(sizer); + + // On Mac, don't create a 'native' wxToolBar because small bitmaps are not supported by native + // toolbars. On Mac, a non-native, small-bitmap toolbar doesn't show unless it is explicitly + // managed, hence the use of sizers. In a real application, use larger icons for the main + // toolbar to avoid the need for this workaround. Or, use the toolbar in a container window + // as part of a more complex hierarchy, and the toolbar will automatically be non-native. + + wxSystemOptions::SetOption(wxT("mac.toolbar.no-native"), 1); + + wxToolBar* toolBar = new wxToolBar(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, + wxNO_BORDER|wxTB_FLAT|wxTB_NODIVIDER|wxTB_NOALIGN); + + sizer->Add(toolBar, 0, wxEXPAND); toolBar->AddTool(wxID_OPEN, wxEmptyString, wxBitmap(open_xpm), _("Open")); toolBar->AddTool(wxID_SAVEAS, wxEmptyString, wxBitmap(save_xpm), _("Save")); @@ -723,20 +787,21 @@ MyFrame::MyFrame(const wxString& title, wxWindowID id, const wxPoint& pos, toolBar->AddTool(ID_FORMAT_INDENT_MORE, wxEmptyString, wxBitmap(indentmore_xpm), _("Indent More")); toolBar->AddSeparator(); toolBar->AddTool(ID_FORMAT_FONT, wxEmptyString, wxBitmap(font_xpm), _("Font")); - toolBar->AddTool(ID_FORMAT_IMAGE, wxString("Im"), wxBitmap(font_xpm), _("Image Property")); + toolBar->AddSeparator(); - wxRichTextStyleComboCtrl* combo = new wxRichTextStyleComboCtrl(toolBar, ID_RICHTEXT_STYLE_COMBO, wxDefaultPosition, wxSize(200, -1)); + wxRichTextStyleComboCtrl* combo = new wxRichTextStyleComboCtrl(toolBar, ID_RICHTEXT_STYLE_COMBO, wxDefaultPosition, wxSize(160, -1), wxCB_READONLY); toolBar->AddControl(combo); toolBar->Realize(); - wxSplitterWindow* splitter = new wxSplitterWindow(this, wxID_ANY, wxDefaultPosition, GetClientSize(), wxSP_LIVE_UPDATE); + wxSplitterWindow* splitter = new wxSplitterWindow(this, wxID_ANY, wxDefaultPosition, wxSize(100,100), wxSP_LIVE_UPDATE); + sizer->Add(splitter, 1, wxEXPAND); wxFont textFont = wxFont(12, wxROMAN, wxNORMAL, wxNORMAL); wxFont boldFont = wxFont(12, wxROMAN, wxNORMAL, wxBOLD); 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); m_richTextCtrl->SetFont(font); @@ -761,6 +826,8 @@ MyFrame::MyFrame(const wxString& title, wxWindowID id, const wxPoint& pos, splitter->SplitVertically(m_richTextCtrl, styleListCtrl, 500); } + Layout(); + splitter->UpdateSize(); styleListCtrl->SetStyleSheet(wxGetApp().GetStyleSheet()); @@ -773,14 +840,14 @@ MyFrame::MyFrame(const wxString& title, wxWindowID id, const wxPoint& pos, // Write text void MyFrame::WriteInitialText() { - wxRichTextCtrl& r = *m_richTextCtrl; + MyRichTextCtrl& r = *m_richTextCtrl; r.SetDefaultStyle(wxRichTextAttr()); - r.BeginSuppressUndo(); - r.Freeze(); + r.BeginSuppressUndo(); + r.BeginParagraphSpacing(0, 20); r.BeginAlignment(wxTEXT_ALIGNMENT_CENTRE); @@ -1038,9 +1105,26 @@ void MyFrame::WriteInitialText() } #endif - r.Thaw(); - r.EndSuppressUndo(); + + // 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.Thaw(); } // event handlers @@ -1807,3 +1891,107 @@ void MyFrame::OnPageSetup(wxCommandEvent& WXUNUSED(event)) // 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); +}