Categories: wxWidgets

Getting Acquainted with Document-View architecture – Part II – Simple Text Editor

Today we’ll dig a little bit deeper into Document/View framework provided by wxWidgets and will see how to create a simple text editor using this framework.
We’ll take the source code from the previous article of this series and add some modifications. You will see below that modifications are rather simple and take almost no time.
First of all we have to make wxDocTemplate to handle desired file extensions (in our case it’s TXT).

DocViewTestApp.cpp

bool DocViewTestApp::OnInit()
{
 ...
 wxDocTemplate * docTemplate = new
  wxDocTemplate(m_DocManager, _("DocViewTest Document"),
  wxT("*.txt"), wxEmptyString,
  wxT("txt"), wxT("DocViewTest Doc"), wxT("DocViewTest View"),
  CLASSINFO(DocViewTestDocument), CLASSINFO(DocViewTestView));
...
}

As you can see, this task is very simple. We just changed the filter and default file extension parameter of wxDocTemplate.
After that we have to add a wxTextCtrl to our main frame.

DocViewTestMainFrame.h

class DocViewTestMainFrame : public wxDocParentFrame
{
...
public:
 enum
 {
  ID_EDITOR = wxID_HIGHEST+1
 };
 wxTextCtrl * m_Editor;
 ...
};

DocViewTestMainFrame.cpp

void DocViewTestMainFrame::CreateControls()
{
 SetMenuBar(CreateMenuBar());
 m_AuiManager.SetManagedWindow(this);

 m_Editor = new wxTextCtrl(this, ID_EDITOR, wxEmptyString, wxDefaultPosition,
  wxDefaultSize, wxTE_MULTILINE);

 m_AuiManager.AddPane(m_Editor, wxAuiPaneInfo().CenterPane().Name(_("Editor")));

 m_AuiManager.Update();
}

So, we added a new class member variable of wxTextCtrl type which represents the text editor.
Now we need to add the text editor accessible from Document class. Document objects can’t communicate with frame directly. They can access only views associated with them. So now we have to add a new method to our View class which will return the text editor associated with this view. Let’s call this method GetEditor().

DocViewTestView.h

class DocViewTestView : public wxView
{
...
public:
 ...
 wxTextCtrl * GetEditor();
...
};

DocViewTestView.cpp

wxTextCtrl * DocViewTestView::GetEditor()
{
 do
 {
  DocViewTestMainFrame * frame =
   wxDynamicCast(GetFrame(), DocViewTestMainFrame);
  if(!frame) break;
  return frame->m_Editor;
 }
 while(false);
 return NULL;
}

Perfectly, now we have to make our document class load and save files and also we have to add methods which will allow to set/retrieve the state of the document. These methods are Modify() and IsModified().

DocViewTestDocument.h

class DocViewTestDocument : public wxDocument
{
 DECLARE_DYNAMIC_CLASS(DocViewTestDocument)
public:
 DocViewTestDocument();
 virtual bool OnSaveDocument(const wxString& filename);
 virtual bool OnOpenDocument(const wxString& filename);
 virtual bool IsModified(void) const;
 virtual void Modify(bool mod);
};

DocViewTestDocument.cpp

bool DocViewTestDocument::IsModified(void) const
{
 bool res = wxDocument::IsModified();
    DocViewTestView * view = (DocViewTestView *)GetFirstView();
    if (view)
    {
        res |= view->GetEditor()->IsModified();
    }
    return res;
}

void DocViewTestDocument::Modify(bool mod)
{
    DocViewTestView * view = (DocViewTestView *)GetFirstView();

    wxDocument::Modify(mod);

    if (!mod && view && view->GetEditor())
 {
        view->GetEditor()->DiscardEdits();
 }
}

bool DocViewTestDocument::OnSaveDocument(const wxString& filename)
{
 wxLogTrace(wxTraceMask(), wxT("DocViewTestDocument::OnSaveDocument"));
 do
 {
  DocViewTestView * view = (DocViewTestView *)GetFirstView();
  if(!view) break;
  wxTextCtrl * editor = view->GetEditor();
  if(!editor) break;

  if (!editor->SaveFile(filename))
  {
   return false;
  }
  Modify(false);
#ifdef __WXMAC__
  wxFileName fn(filename) ;
  fn.MacSetDefaultTypeAndCreator() ;
#endif
 }
 while(false);
    return true;
}

bool DocViewTestDocument::OnOpenDocument(const wxString& filename)
{
 wxLogTrace(wxTraceMask(), wxT("DocViewTestDocument::OnOpenDocument"));
    do
 {
  DocViewTestView * view = (DocViewTestView *)GetFirstView();
  if(!view) break;
  wxTextCtrl * editor = view->GetEditor();
  if(!editor) break;

  if (!editor->LoadFile(filename))
  {
   return false;
  }

  SetFilename(filename, true);
  Modify(false);
  UpdateAllViews();
 }
 while(false);
    return true;
}

So, let’s see how it works. When user opens the document using file selector dialog, wxDocument::OnOpenDocument() method is called automatically by Document/View framework and the file name is passed to this method. In this method we obtain the pointer to text editor and call wxTextCtrl::LoadFile() method which loads and displays a file. After that (if the file was loaded successfully) we associate the file name with our document, reset “modified” flag and update the view (it is default behavior when wxDocument::UpdateAllViews() method is called. In fact, for this sample we may avoid calling of this method because DocViewTestView::OnUpdate() method does nothing).
Now let’s build our project and see how everything works.

Simple Text Editor in wxWidgets using Document/View Framework

Download the source code for this tutorial.

T-Rex

Share
Published by
T-Rex

Recent Posts

Разработка кроссплатформенных модульных приложений на C++ с библиотекой wxWidgets

Введение Уже долгое время не пишу статьи о разработке, хотя сам процесс написания мне очень…

10 years ago

wxWidgets App With Plugins (Windows/Linux/Mac) – Sample Source Code

I can see that there is still a lot of topics at wxWidgets forums related…

11 years ago

wxToolBox is Now Open-Source!

I've just published the source code of wxToolBox component and a couple of sample apps at…

11 years ago

Microsoft Kinect Helper Library and Sample for wxWidgets

Microsoft released their Kinect SDK several days ago. So, for those wxWidgets developers who are…

13 years ago

wxJSON 1.1.0 Released

JSON (JavaScript Object Notation) is a lightweight data-interchange format. It is easy for humans to…

14 years ago

wxRuby. Оно даже работает!

Вдохновленнный читаемой нынче книгой My Job Went to India: 52 Ways to Save Your Job…

15 years ago