1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/common/docview.cpp 
   3 // Purpose:     Document/view classes 
   4 // Author:      Julian Smart 
   5 // Modified by: Vadim Zeitlin 
   8 // Copyright:   (c) Julian Smart 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  20 // For compilers that support precompilation, includes "wx.h". 
  21 #include "wx/wxprec.h" 
  27 #if wxUSE_DOC_VIEW_ARCHITECTURE 
  29 #include "wx/docview.h" 
  33     #include "wx/string.h" 
  37     #include "wx/dialog.h" 
  39     #include "wx/filedlg.h" 
  42     #include "wx/msgdlg.h" 
  44     #include "wx/choicdlg.h" 
  47 #if wxUSE_PRINTING_ARCHITECTURE 
  48     #include "wx/prntbase.h" 
  49     #include "wx/printdlg.h" 
  52 #include "wx/confbase.h" 
  53 #include "wx/filename.h" 
  56 #include "wx/cmdproc.h" 
  57 #include "wx/tokenzr.h" 
  58 #include "wx/filename.h" 
  59 #include "wx/stdpaths.h" 
  60 #include "wx/vector.h" 
  61 #include "wx/scopedarray.h" 
  62 #include "wx/scopedptr.h" 
  63 #include "wx/except.h" 
  65 #if wxUSE_STD_IOSTREAM 
  66     #include "wx/ioswrap.h" 
  67     #include "wx/beforestd.h" 
  73     #include "wx/afterstd.h" 
  75     #include "wx/wfstream.h" 
  78 typedef wxVector
<wxDocTemplate 
*> wxDocTemplates
; 
  80 // ---------------------------------------------------------------------------- 
  82 // ---------------------------------------------------------------------------- 
  84 IMPLEMENT_ABSTRACT_CLASS(wxDocument
, wxEvtHandler
) 
  85 IMPLEMENT_ABSTRACT_CLASS(wxView
, wxEvtHandler
) 
  86 IMPLEMENT_ABSTRACT_CLASS(wxDocTemplate
, wxObject
) 
  87 IMPLEMENT_DYNAMIC_CLASS(wxDocManager
, wxEvtHandler
) 
  88 IMPLEMENT_CLASS(wxDocChildFrame
, wxFrame
) 
  89 IMPLEMENT_CLASS(wxDocParentFrame
, wxFrame
) 
  91 #if wxUSE_PRINTING_ARCHITECTURE 
  92     IMPLEMENT_DYNAMIC_CLASS(wxDocPrintout
, wxPrintout
) 
  95 IMPLEMENT_DYNAMIC_CLASS(wxFileHistory
, wxObject
) 
  97 // ============================================================================ 
  99 // ============================================================================ 
 101 // ---------------------------------------------------------------------------- 
 103 // ---------------------------------------------------------------------------- 
 108 wxString 
FindExtension(const wxString
& path
) 
 111     wxFileName::SplitPath(path
, NULL
, NULL
, &ext
); 
 113     // VZ: extensions are considered not case sensitive - is this really a good 
 115     return ext
.MakeLower(); 
 118 // return the string used for the MRU list items in the menu 
 120 // NB: the index n is 0-based, as usual, but the strings start from 1 
 121 wxString 
GetMRUEntryLabel(int n
, const wxString
& path
) 
 123     // we need to quote '&' characters which are used for mnemonics 
 124     wxString 
pathInMenu(path
); 
 125     pathInMenu
.Replace("&", "&&"); 
 127     return wxString::Format("&%d %s", n 
+ 1, pathInMenu
); 
 130 } // anonymous namespace 
 132 // ---------------------------------------------------------------------------- 
 133 // Definition of wxDocument 
 134 // ---------------------------------------------------------------------------- 
 136 wxDocument::wxDocument(wxDocument 
*parent
) 
 138     m_documentModified 
= false; 
 139     m_documentParent 
= parent
; 
 140     m_documentTemplate 
= NULL
; 
 141     m_commandProcessor 
= NULL
; 
 145 bool wxDocument::DeleteContents() 
 150 wxDocument::~wxDocument() 
 154     delete m_commandProcessor
; 
 156     if (GetDocumentManager()) 
 157         GetDocumentManager()->RemoveDocument(this); 
 159     // Not safe to do here, since it'll invoke virtual view functions 
 160     // expecting to see valid derived objects: and by the time we get here, 
 161     // we've called destructors higher up. 
 165 bool wxDocument::Close() 
 167     if ( !OnSaveModified() ) 
 170     return OnCloseDocument(); 
 173 bool wxDocument::OnCloseDocument() 
 175     // Tell all views that we're about to close 
 182 // Note that this implicitly deletes the document when the last view is 
 184 bool wxDocument::DeleteAllViews() 
 186     wxDocManager
* manager 
= GetDocumentManager(); 
 188     // first check if all views agree to be closed 
 189     const wxList::iterator end 
= m_documentViews
.end(); 
 190     for ( wxList::iterator i 
= m_documentViews
.begin(); i 
!= end
; ++i 
) 
 192         wxView 
*view 
= (wxView 
*)*i
; 
 193         if ( !view
->Close() ) 
 197     // all views agreed to close, now do close them 
 198     if ( m_documentViews
.empty() ) 
 200         // normally the document would be implicitly deleted when the last view 
 201         // is, but if don't have any views, do it here instead 
 202         if ( manager 
&& manager
->GetDocuments().Member(this) ) 
 207         // as we delete elements we iterate over, don't use the usual "from 
 208         // begin to end" loop 
 211             wxView 
*view 
= (wxView 
*)*m_documentViews
.begin(); 
 213             bool isLastOne 
= m_documentViews
.size() == 1; 
 215             // this always deletes the node implicitly and if this is the last 
 216             // view also deletes this object itself (also implicitly, great), 
 217             // so we can't test for m_documentViews.empty() after calling this! 
 228 wxView 
*wxDocument::GetFirstView() const 
 230     if ( m_documentViews
.empty() ) 
 233     return static_cast<wxView 
*>(m_documentViews
.GetFirst()->GetData()); 
 236 void wxDocument::Modify(bool mod
) 
 238     if (mod 
!= m_documentModified
) 
 240         m_documentModified 
= mod
; 
 242         // Allow views to append asterix to the title 
 243         wxView
* view 
= GetFirstView(); 
 244         if (view
) view
->OnChangeFilename(); 
 248 wxDocManager 
*wxDocument::GetDocumentManager() const 
 250     return m_documentTemplate 
? m_documentTemplate
->GetDocumentManager() : NULL
; 
 253 bool wxDocument::OnNewDocument() 
 255     // notice that there is no need to neither reset nor even check the 
 256     // modified flag here as the document itself is a new object (this is only 
 257     // called from CreateDocument()) and so it shouldn't be saved anyhow even 
 258     // if it is modified -- this could happen if the user code creates 
 259     // documents pre-filled with some user-entered (and which hence must not be 
 262     SetDocumentSaved(false); 
 264     const wxString name 
= GetDocumentManager()->MakeNewDocumentName(); 
 266     SetFilename(name
, true); 
 271 bool wxDocument::Save() 
 273     if ( AlreadySaved() ) 
 276     if ( m_documentFile
.empty() || !m_savedYet 
) 
 279     return OnSaveDocument(m_documentFile
); 
 282 bool wxDocument::SaveAs() 
 284     wxDocTemplate 
*docTemplate 
= GetDocumentTemplate(); 
 288 #ifdef wxHAS_MULTIPLE_FILEDLG_FILTERS 
 289     wxString filter 
= docTemplate
->GetDescription() + wxT(" (") + 
 290         docTemplate
->GetFileFilter() + wxT(")|") + 
 291         docTemplate
->GetFileFilter(); 
 293     // Now see if there are some other template with identical view and document 
 294     // classes, whose filters may also be used. 
 295     if (docTemplate
->GetViewClassInfo() && docTemplate
->GetDocClassInfo()) 
 297         wxList::compatibility_iterator
 
 298             node 
= docTemplate
->GetDocumentManager()->GetTemplates().GetFirst(); 
 301             wxDocTemplate 
*t 
= (wxDocTemplate
*) node
->GetData(); 
 303             if (t
->IsVisible() && t 
!= docTemplate 
&& 
 304                 t
->GetViewClassInfo() == docTemplate
->GetViewClassInfo() && 
 305                 t
->GetDocClassInfo() == docTemplate
->GetDocClassInfo()) 
 307                 // add a '|' to separate this filter from the previous one 
 308                 if ( !filter
.empty() ) 
 311                 filter 
<< t
->GetDescription() 
 312                        << wxT(" (") << t
->GetFileFilter() << wxT(") |") 
 313                        << t
->GetFileFilter(); 
 316             node 
= node
->GetNext(); 
 320     wxString filter 
= docTemplate
->GetFileFilter() ; 
 323     wxString defaultDir 
= docTemplate
->GetDirectory(); 
 324     if ( defaultDir
.empty() ) 
 326         defaultDir 
= wxPathOnly(GetFilename()); 
 327         if ( defaultDir
.empty() ) 
 328             defaultDir 
= GetDocumentManager()->GetLastDirectory(); 
 331     wxString fileName 
= wxFileSelector(_("Save As"), 
 333             wxFileNameFromPath(GetFilename()), 
 334             docTemplate
->GetDefaultExtension(), 
 336             wxFD_SAVE 
| wxFD_OVERWRITE_PROMPT
, 
 337             GetDocumentWindow()); 
 339     if (fileName
.empty()) 
 340         return false; // cancelled by user 
 342     // Files that were not saved correctly are not added to the FileHistory. 
 343     if (!OnSaveDocument(fileName
)) 
 346     SetTitle(wxFileNameFromPath(fileName
)); 
 347     SetFilename(fileName
, true);    // will call OnChangeFileName automatically 
 349     // A file that doesn't use the default extension of its document template 
 350     // cannot be opened via the FileHistory, so we do not add it. 
 351     if (docTemplate
->FileMatchesTemplate(fileName
)) 
 353         GetDocumentManager()->AddFileToHistory(fileName
); 
 355     //else: the user will probably not be able to open the file again, so we 
 356     //      could warn about the wrong file-extension here 
 361 bool wxDocument::OnSaveDocument(const wxString
& file
) 
 366     if ( !DoSaveDocument(file
) ) 
 371     SetDocumentSaved(true); 
 372 #if defined( __WXOSX_MAC__ ) && wxOSX_USE_CARBON 
 373     wxFileName 
fn(file
) ; 
 374     fn
.MacSetDefaultTypeAndCreator() ; 
 379 bool wxDocument::OnOpenDocument(const wxString
& file
) 
 381     // notice that there is no need to check the modified flag here for the 
 382     // reasons explained in OnNewDocument() 
 384     if ( !DoOpenDocument(file
) ) 
 387     SetFilename(file
, true); 
 389     // stretching the logic a little this does make sense because the document 
 390     // had been saved into the file we just loaded it from, it just could have 
 391     // happened during a previous program execution, it's just that the name of 
 392     // this method is a bit unfortunate, it should probably have been called 
 393     // HasAssociatedFileName() 
 394     SetDocumentSaved(true); 
 401 #if wxUSE_STD_IOSTREAM 
 402 wxSTD istream
& wxDocument::LoadObject(wxSTD istream
& stream
) 
 404 wxInputStream
& wxDocument::LoadObject(wxInputStream
& stream
) 
 410 #if wxUSE_STD_IOSTREAM 
 411 wxSTD ostream
& wxDocument::SaveObject(wxSTD ostream
& stream
) 
 413 wxOutputStream
& wxDocument::SaveObject(wxOutputStream
& stream
) 
 419 bool wxDocument::Revert() 
 423             _("Discard changes and reload the last saved version?"), 
 424             wxTheApp
->GetAppDisplayName(), 
 425             wxYES_NO 
| wxCANCEL 
| wxICON_QUESTION
, 
 430     if ( !DoOpenDocument(GetFilename()) ) 
 440 // Get title, or filename if no title, else unnamed 
 441 #if WXWIN_COMPATIBILITY_2_8 
 442 bool wxDocument::GetPrintableName(wxString
& buf
) const 
 444     // this function can not only be overridden by the user code but also 
 445     // called by it so we need to ensure that we return the same thing as 
 446     // GetUserReadableName() but we can't call it because this would result in 
 447     // an infinite recursion, hence we use the helper DoGetUserReadableName() 
 448     buf 
= DoGetUserReadableName(); 
 452 #endif // WXWIN_COMPATIBILITY_2_8 
 454 wxString 
wxDocument::GetUserReadableName() const 
 456 #if WXWIN_COMPATIBILITY_2_8 
 457     // we need to call the old virtual function to ensure that the overridden 
 458     // version of it is still called 
 460     if ( GetPrintableName(name
) ) 
 462 #endif // WXWIN_COMPATIBILITY_2_8 
 464     return DoGetUserReadableName(); 
 467 wxString 
wxDocument::DoGetUserReadableName() const 
 469     if ( !m_documentTitle
.empty() ) 
 470         return m_documentTitle
; 
 472     if ( !m_documentFile
.empty() ) 
 473         return wxFileNameFromPath(m_documentFile
); 
 478 wxWindow 
*wxDocument::GetDocumentWindow() const 
 480     wxView 
* const view 
= GetFirstView(); 
 482     return view 
? view
->GetFrame() : wxTheApp
->GetTopWindow(); 
 485 wxCommandProcessor 
*wxDocument::OnCreateCommandProcessor() 
 487     return new wxCommandProcessor
; 
 490 // true if safe to close 
 491 bool wxDocument::OnSaveModified() 
 495         switch ( wxMessageBox
 
 499                      _("Do you want to save changes to %s?"), 
 500                      GetUserReadableName() 
 502                     wxTheApp
->GetAppDisplayName(), 
 503                     wxYES_NO 
| wxCANCEL 
| wxICON_QUESTION 
| wxCENTRE
 
 521 bool wxDocument::Draw(wxDC
& WXUNUSED(context
)) 
 526 bool wxDocument::AddView(wxView 
*view
) 
 528     if ( !m_documentViews
.Member(view
) ) 
 530         m_documentViews
.Append(view
); 
 536 bool wxDocument::RemoveView(wxView 
*view
) 
 538     (void)m_documentViews
.DeleteObject(view
); 
 543 bool wxDocument::OnCreate(const wxString
& WXUNUSED(path
), long flags
) 
 545     return GetDocumentTemplate()->CreateView(this, flags
) != NULL
; 
 548 // Called after a view is added or removed. 
 549 // The default implementation deletes the document if 
 550 // there are no more views. 
 551 void wxDocument::OnChangedViewList() 
 553     if ( m_documentViews
.empty() && OnSaveModified() ) 
 557 void wxDocument::UpdateAllViews(wxView 
*sender
, wxObject 
*hint
) 
 559     wxList::compatibility_iterator node 
= m_documentViews
.GetFirst(); 
 562         wxView 
*view 
= (wxView 
*)node
->GetData(); 
 564             view
->OnUpdate(sender
, hint
); 
 565         node 
= node
->GetNext(); 
 569 void wxDocument::NotifyClosing() 
 571     wxList::compatibility_iterator node 
= m_documentViews
.GetFirst(); 
 574         wxView 
*view 
= (wxView 
*)node
->GetData(); 
 575         view
->OnClosingDocument(); 
 576         node 
= node
->GetNext(); 
 580 void wxDocument::SetFilename(const wxString
& filename
, bool notifyViews
) 
 582     m_documentFile 
= filename
; 
 583     OnChangeFilename(notifyViews
); 
 586 void wxDocument::OnChangeFilename(bool notifyViews
) 
 590         // Notify the views that the filename has changed 
 591         wxList::compatibility_iterator node 
= m_documentViews
.GetFirst(); 
 594             wxView 
*view 
= (wxView 
*)node
->GetData(); 
 595             view
->OnChangeFilename(); 
 596             node 
= node
->GetNext(); 
 601 bool wxDocument::DoSaveDocument(const wxString
& file
) 
 603 #if wxUSE_STD_IOSTREAM 
 604     wxSTD ofstream 
store(file
.mb_str(), wxSTD 
ios::binary
); 
 607     wxFileOutputStream 
store(file
); 
 608     if ( store
.GetLastError() != wxSTREAM_NO_ERROR 
) 
 611         wxLogError(_("File \"%s\" could not be opened for writing."), file
); 
 615     if (!SaveObject(store
)) 
 617         wxLogError(_("Failed to save document to the file \"%s\"."), file
); 
 624 bool wxDocument::DoOpenDocument(const wxString
& file
) 
 626 #if wxUSE_STD_IOSTREAM 
 627     wxSTD ifstream 
store(file
.mb_str(), wxSTD 
ios::binary
); 
 630     wxFileInputStream 
store(file
); 
 631     if (store
.GetLastError() != wxSTREAM_NO_ERROR 
|| !store
.IsOk()) 
 634         wxLogError(_("File \"%s\" could not be opened for reading."), file
); 
 638 #if wxUSE_STD_IOSTREAM 
 642     int res 
= LoadObject(store
).GetLastError(); 
 643     if ( res 
!= wxSTREAM_NO_ERROR 
&& res 
!= wxSTREAM_EOF 
) 
 646         wxLogError(_("Failed to read document from the file \"%s\"."), file
); 
 654 // ---------------------------------------------------------------------------- 
 656 // ---------------------------------------------------------------------------- 
 660     m_viewDocument 
= NULL
; 
 664     m_docChildFrame 
= NULL
; 
 669     if (m_viewDocument 
&& GetDocumentManager()) 
 670         GetDocumentManager()->ActivateView(this, false); 
 672     // reset our frame view first, before removing it from the document as 
 673     // SetView(NULL) is a simple call while RemoveView() may result in user 
 674     // code being executed and this user code can, for example, show a message 
 675     // box which would result in an activation event for m_docChildFrame and so 
 676     // could reactivate the view being destroyed -- unless we reset it first 
 677     if ( m_docChildFrame 
&& m_docChildFrame
->GetView() == this ) 
 679         // prevent it from doing anything with us 
 680         m_docChildFrame
->SetView(NULL
); 
 682         // it doesn't make sense to leave the frame alive if its associated 
 683         // view doesn't exist any more so unconditionally close it as well 
 685         // notice that we only get here if m_docChildFrame is non-NULL in the 
 686         // first place and it will be always NULL if we're deleted because our 
 687         // frame was closed, so this only catches the case of directly deleting 
 688         // the view, as it happens if its creation fails in wxDocTemplate:: 
 689         // CreateView() for example 
 690         m_docChildFrame
->GetWindow()->Destroy(); 
 693     if ( m_viewDocument 
) 
 694         m_viewDocument
->RemoveView(this); 
 697 void wxView::SetDocChildFrame(wxDocChildFrameAnyBase 
*docChildFrame
) 
 699     SetFrame(docChildFrame 
? docChildFrame
->GetWindow() : NULL
); 
 700     m_docChildFrame 
= docChildFrame
; 
 703 bool wxView::TryBefore(wxEvent
& event
) 
 705     wxDocument 
* const doc 
= GetDocument(); 
 706     return doc 
&& doc
->ProcessEventHere(event
); 
 709 void wxView::OnActivateView(bool WXUNUSED(activate
), 
 710                             wxView 
*WXUNUSED(activeView
), 
 711                             wxView 
*WXUNUSED(deactiveView
)) 
 715 void wxView::OnPrint(wxDC 
*dc
, wxObject 
*WXUNUSED(info
)) 
 720 void wxView::OnUpdate(wxView 
*WXUNUSED(sender
), wxObject 
*WXUNUSED(hint
)) 
 724 void wxView::OnChangeFilename() 
 726     // GetFrame can return wxWindow rather than wxTopLevelWindow due to 
 727     // generic MDI implementation so use SetLabel rather than SetTitle. 
 728     // It should cause SetTitle() for top level windows. 
 729     wxWindow 
*win 
= GetFrame(); 
 732     wxDocument 
*doc 
= GetDocument(); 
 735     wxString label 
= doc
->GetUserReadableName(); 
 736     if (doc
->IsModified()) 
 740     win
->SetLabel(label
); 
 743 void wxView::SetDocument(wxDocument 
*doc
) 
 745     m_viewDocument 
= doc
; 
 750 bool wxView::Close(bool deleteWindow
) 
 752     return OnClose(deleteWindow
); 
 755 void wxView::Activate(bool activate
) 
 757     if (GetDocument() && GetDocumentManager()) 
 759         OnActivateView(activate
, this, GetDocumentManager()->GetCurrentView()); 
 760         GetDocumentManager()->ActivateView(this, activate
); 
 764 bool wxView::OnClose(bool WXUNUSED(deleteWindow
)) 
 766     return GetDocument() ? GetDocument()->Close() : true; 
 769 #if wxUSE_PRINTING_ARCHITECTURE 
 770 wxPrintout 
*wxView::OnCreatePrintout() 
 772     return new wxDocPrintout(this); 
 774 #endif // wxUSE_PRINTING_ARCHITECTURE 
 776 // ---------------------------------------------------------------------------- 
 778 // ---------------------------------------------------------------------------- 
 780 wxDocTemplate::wxDocTemplate(wxDocManager 
*manager
, 
 781                              const wxString
& descr
, 
 782                              const wxString
& filter
, 
 785                              const wxString
& docTypeName
, 
 786                              const wxString
& viewTypeName
, 
 787                              wxClassInfo 
*docClassInfo
, 
 788                              wxClassInfo 
*viewClassInfo
, 
 791     m_documentManager 
= manager
; 
 792     m_description 
= descr
; 
 795     m_fileFilter 
= filter
; 
 797     m_docTypeName 
= docTypeName
; 
 798     m_viewTypeName 
= viewTypeName
; 
 799     m_documentManager
->AssociateTemplate(this); 
 801     m_docClassInfo 
= docClassInfo
; 
 802     m_viewClassInfo 
= viewClassInfo
; 
 805 wxDocTemplate::~wxDocTemplate() 
 807     m_documentManager
->DisassociateTemplate(this); 
 810 // Tries to dynamically construct an object of the right class. 
 811 wxDocument 
*wxDocTemplate::CreateDocument(const wxString
& path
, long flags
) 
 813     // InitDocument() is supposed to delete the document object if its 
 814     // initialization fails so don't use wxScopedPtr<> here: this is fragile 
 815     // but unavoidable because the default implementation uses CreateView() 
 816     // which may -- or not -- create a wxView and if it does create it and its 
 817     // initialization fails then the view destructor will delete the document 
 818     // (via RemoveView()) and as we can't distinguish between the two cases we 
 819     // just have to assume that it always deletes it in case of failure 
 820     wxDocument 
* const doc 
= DoCreateDocument(); 
 822     return doc 
&& InitDocument(doc
, path
, flags
) ? doc 
: NULL
; 
 826 wxDocTemplate::InitDocument(wxDocument
* doc
, const wxString
& path
, long flags
) 
 828     doc
->SetFilename(path
); 
 829     doc
->SetDocumentTemplate(this); 
 830     GetDocumentManager()->AddDocument(doc
); 
 831     doc
->SetCommandProcessor(doc
->OnCreateCommandProcessor()); 
 833     if (doc
->OnCreate(path
, flags
)) 
 836     if (GetDocumentManager()->GetDocuments().Member(doc
)) 
 837         doc
->DeleteAllViews(); 
 841 wxView 
*wxDocTemplate::CreateView(wxDocument 
*doc
, long flags
) 
 843     wxScopedPtr
<wxView
> view(DoCreateView()); 
 847     view
->SetDocument(doc
); 
 848     if ( !view
->OnCreate(doc
, flags
) ) 
 851     return view
.release(); 
 854 // The default (very primitive) format detection: check is the extension is 
 855 // that of the template 
 856 bool wxDocTemplate::FileMatchesTemplate(const wxString
& path
) 
 858     wxStringTokenizer 
parser (GetFileFilter(), wxT(";")); 
 859     wxString anything 
= wxT ("*"); 
 860     while (parser
.HasMoreTokens()) 
 862         wxString filter 
= parser
.GetNextToken(); 
 863         wxString filterExt 
= FindExtension (filter
); 
 864         if ( filter
.IsSameAs (anything
)    || 
 865              filterExt
.IsSameAs (anything
) || 
 866              filterExt
.IsSameAs (FindExtension (path
)) ) 
 869     return GetDefaultExtension().IsSameAs(FindExtension(path
)); 
 872 wxDocument 
*wxDocTemplate::DoCreateDocument() 
 877     return static_cast<wxDocument 
*>(m_docClassInfo
->CreateObject()); 
 880 wxView 
*wxDocTemplate::DoCreateView() 
 882     if (!m_viewClassInfo
) 
 885     return static_cast<wxView 
*>(m_viewClassInfo
->CreateObject()); 
 888 // ---------------------------------------------------------------------------- 
 890 // ---------------------------------------------------------------------------- 
 892 BEGIN_EVENT_TABLE(wxDocManager
, wxEvtHandler
) 
 893     EVT_MENU(wxID_OPEN
, wxDocManager::OnFileOpen
) 
 894     EVT_MENU(wxID_CLOSE
, wxDocManager::OnFileClose
) 
 895     EVT_MENU(wxID_CLOSE_ALL
, wxDocManager::OnFileCloseAll
) 
 896     EVT_MENU(wxID_REVERT
, wxDocManager::OnFileRevert
) 
 897     EVT_MENU(wxID_NEW
, wxDocManager::OnFileNew
) 
 898     EVT_MENU(wxID_SAVE
, wxDocManager::OnFileSave
) 
 899     EVT_MENU(wxID_SAVEAS
, wxDocManager::OnFileSaveAs
) 
 900     EVT_MENU(wxID_UNDO
, wxDocManager::OnUndo
) 
 901     EVT_MENU(wxID_REDO
, wxDocManager::OnRedo
) 
 903     EVT_UPDATE_UI(wxID_OPEN
, wxDocManager::OnUpdateFileOpen
) 
 904     EVT_UPDATE_UI(wxID_CLOSE
, wxDocManager::OnUpdateDisableIfNoDoc
) 
 905     EVT_UPDATE_UI(wxID_CLOSE_ALL
, wxDocManager::OnUpdateDisableIfNoDoc
) 
 906     EVT_UPDATE_UI(wxID_REVERT
, wxDocManager::OnUpdateFileRevert
) 
 907     EVT_UPDATE_UI(wxID_NEW
, wxDocManager::OnUpdateFileNew
) 
 908     EVT_UPDATE_UI(wxID_SAVE
, wxDocManager::OnUpdateFileSave
) 
 909     EVT_UPDATE_UI(wxID_SAVEAS
, wxDocManager::OnUpdateDisableIfNoDoc
) 
 910     EVT_UPDATE_UI(wxID_UNDO
, wxDocManager::OnUpdateUndo
) 
 911     EVT_UPDATE_UI(wxID_REDO
, wxDocManager::OnUpdateRedo
) 
 913 #if wxUSE_PRINTING_ARCHITECTURE 
 914     EVT_MENU(wxID_PRINT
, wxDocManager::OnPrint
) 
 915     EVT_MENU(wxID_PREVIEW
, wxDocManager::OnPreview
) 
 917     EVT_UPDATE_UI(wxID_PRINT
, wxDocManager::OnUpdateDisableIfNoDoc
) 
 918     EVT_UPDATE_UI(wxID_PREVIEW
, wxDocManager::OnUpdateDisableIfNoDoc
) 
 922 wxDocManager
* wxDocManager::sm_docManager 
= NULL
; 
 924 wxDocManager::wxDocManager(long WXUNUSED(flags
), bool initialize
) 
 926     sm_docManager 
= this; 
 928     m_defaultDocumentNameCounter 
= 1; 
 929     m_currentView 
= NULL
; 
 930     m_maxDocsOpen 
= INT_MAX
; 
 931     m_fileHistory 
= NULL
; 
 936 wxDocManager::~wxDocManager() 
 939     delete m_fileHistory
; 
 940     sm_docManager 
= NULL
; 
 943 // closes the specified document 
 944 bool wxDocManager::CloseDocument(wxDocument
* doc
, bool force
) 
 946     if ( !doc
->Close() && !force 
) 
 949     // Implicitly deletes the document when 
 950     // the last view is deleted 
 951     doc
->DeleteAllViews(); 
 953     // Check we're really deleted 
 954     if (m_docs
.Member(doc
)) 
 960 bool wxDocManager::CloseDocuments(bool force
) 
 962     wxList::compatibility_iterator node 
= m_docs
.GetFirst(); 
 965         wxDocument 
*doc 
= (wxDocument 
*)node
->GetData(); 
 966         wxList::compatibility_iterator next 
= node
->GetNext(); 
 968         if (!CloseDocument(doc
, force
)) 
 971         // This assumes that documents are not connected in 
 972         // any way, i.e. deleting one document does NOT 
 979 bool wxDocManager::Clear(bool force
) 
 981     if (!CloseDocuments(force
)) 
 984     m_currentView 
= NULL
; 
 986     wxList::compatibility_iterator node 
= m_templates
.GetFirst(); 
 989         wxDocTemplate 
*templ 
= (wxDocTemplate
*) node
->GetData(); 
 990         wxList::compatibility_iterator next 
= node
->GetNext(); 
 997 bool wxDocManager::Initialize() 
 999     m_fileHistory 
= OnCreateFileHistory(); 
1003 wxString 
wxDocManager::GetLastDirectory() const 
1005     // if we haven't determined the last used directory yet, do it now 
1006     if ( m_lastDirectory
.empty() ) 
1008         // we're going to modify m_lastDirectory in this const method, so do it 
1009         // via non-const self pointer instead of const this one 
1010         wxDocManager 
* const self 
= const_cast<wxDocManager 
*>(this); 
1012         // first try to reuse the directory of the most recently opened file: 
1013         // this ensures that if the user opens a file, closes the program and 
1014         // runs it again the "Open file" dialog will open in the directory of 
1015         // the last file he used 
1016         if ( m_fileHistory 
&& m_fileHistory
->GetCount() ) 
1018             const wxString lastOpened 
= m_fileHistory
->GetHistoryFile(0); 
1019             const wxFileName 
fn(lastOpened
); 
1020             if ( fn
.DirExists() ) 
1022                 self
->m_lastDirectory 
= fn
.GetPath(); 
1024             //else: should we try the next one? 
1026         //else: no history yet 
1028         // if we don't have any files in the history (yet?), use the 
1029         // system-dependent default location for the document files 
1030         if ( m_lastDirectory
.empty() ) 
1032             self
->m_lastDirectory 
= wxStandardPaths::Get().GetAppDocumentsDir(); 
1036     return m_lastDirectory
; 
1039 wxFileHistory 
*wxDocManager::OnCreateFileHistory() 
1041     return new wxFileHistory
; 
1044 void wxDocManager::OnFileClose(wxCommandEvent
& WXUNUSED(event
)) 
1046     wxDocument 
*doc 
= GetCurrentDocument(); 
1051         doc
->DeleteAllViews(); 
1052         if (m_docs
.Member(doc
)) 
1057 void wxDocManager::OnFileCloseAll(wxCommandEvent
& WXUNUSED(event
)) 
1059     CloseDocuments(false); 
1062 void wxDocManager::OnFileNew(wxCommandEvent
& WXUNUSED(event
)) 
1064     CreateNewDocument(); 
1067 void wxDocManager::OnFileOpen(wxCommandEvent
& WXUNUSED(event
)) 
1069     if ( !CreateDocument("") ) 
1071         OnOpenFileFailure(); 
1075 void wxDocManager::OnFileRevert(wxCommandEvent
& WXUNUSED(event
)) 
1077     wxDocument 
*doc 
= GetCurrentDocument(); 
1083 void wxDocManager::OnFileSave(wxCommandEvent
& WXUNUSED(event
)) 
1085     wxDocument 
*doc 
= GetCurrentDocument(); 
1091 void wxDocManager::OnFileSaveAs(wxCommandEvent
& WXUNUSED(event
)) 
1093     wxDocument 
*doc 
= GetCurrentDocument(); 
1099 void wxDocManager::OnPrint(wxCommandEvent
& WXUNUSED(event
)) 
1101 #if wxUSE_PRINTING_ARCHITECTURE 
1102     wxView 
*view 
= GetActiveView(); 
1106     wxPrintout 
*printout 
= view
->OnCreatePrintout(); 
1110         printer
.Print(view
->GetFrame(), printout
, true); 
1114 #endif // wxUSE_PRINTING_ARCHITECTURE 
1117 void wxDocManager::OnPreview(wxCommandEvent
& WXUNUSED(event
)) 
1119 #if wxUSE_PRINTING_ARCHITECTURE 
1121     wxView 
*view 
= GetActiveView(); 
1125     wxPrintout 
*printout 
= view
->OnCreatePrintout(); 
1128         // Pass two printout objects: for preview, and possible printing. 
1129         wxPrintPreviewBase 
* 
1130             preview 
= new wxPrintPreview(printout
, view
->OnCreatePrintout()); 
1131         if ( !preview
->Ok() ) 
1134             wxLogError(_("Print preview creation failed.")); 
1139             frame 
= new wxPreviewFrame(preview
, wxTheApp
->GetTopWindow(), 
1140                                        _("Print Preview")); 
1141         frame
->Centre(wxBOTH
); 
1142         frame
->Initialize(); 
1145 #endif // wxUSE_PRINTING_ARCHITECTURE 
1148 void wxDocManager::OnUndo(wxCommandEvent
& event
) 
1150     wxCommandProcessor 
* const cmdproc 
= GetCurrentCommandProcessor(); 
1160 void wxDocManager::OnRedo(wxCommandEvent
& event
) 
1162     wxCommandProcessor 
* const cmdproc 
= GetCurrentCommandProcessor(); 
1172 // Handlers for UI update commands 
1174 void wxDocManager::OnUpdateFileOpen(wxUpdateUIEvent
& event
) 
1176     // CreateDocument() (which is called from OnFileOpen) may succeed 
1177     // only when there is at least a template: 
1178     event
.Enable( GetTemplates().GetCount()>0 ); 
1181 void wxDocManager::OnUpdateDisableIfNoDoc(wxUpdateUIEvent
& event
) 
1183     event
.Enable( GetCurrentDocument() != NULL 
); 
1186 void wxDocManager::OnUpdateFileRevert(wxUpdateUIEvent
& event
) 
1188     wxDocument
* doc 
= GetCurrentDocument(); 
1189     event
.Enable(doc 
&& doc
->IsModified() && doc
->GetDocumentSaved()); 
1192 void wxDocManager::OnUpdateFileNew(wxUpdateUIEvent
& event
) 
1194     // CreateDocument() (which is called from OnFileNew) may succeed 
1195     // only when there is at least a template: 
1196     event
.Enable( GetTemplates().GetCount()>0 ); 
1199 void wxDocManager::OnUpdateFileSave(wxUpdateUIEvent
& event
) 
1201     wxDocument 
* const doc 
= GetCurrentDocument(); 
1202     event
.Enable( doc 
&& !doc
->AlreadySaved() ); 
1205 void wxDocManager::OnUpdateUndo(wxUpdateUIEvent
& event
) 
1207     wxCommandProcessor 
* const cmdproc 
= GetCurrentCommandProcessor(); 
1210         event
.Enable(false); 
1214     event
.Enable(cmdproc
->CanUndo()); 
1215     cmdproc
->SetMenuStrings(); 
1218 void wxDocManager::OnUpdateRedo(wxUpdateUIEvent
& event
) 
1220     wxCommandProcessor 
* const cmdproc 
= GetCurrentCommandProcessor(); 
1223         event
.Enable(false); 
1227     event
.Enable(cmdproc
->CanRedo()); 
1228     cmdproc
->SetMenuStrings(); 
1231 wxView 
*wxDocManager::GetActiveView() const 
1233     wxView 
*view 
= GetCurrentView(); 
1235     if ( !view 
&& !m_docs
.empty() ) 
1237         // if we have exactly one document, consider its view to be the current 
1240         // VZ: I'm not exactly sure why is this needed but this is how this 
1241         //     code used to behave before the bug #9518 was fixed and it seems 
1242         //     safer to preserve the old logic 
1243         wxList::compatibility_iterator node 
= m_docs
.GetFirst(); 
1244         if ( !node
->GetNext() ) 
1246             wxDocument 
*doc 
= static_cast<wxDocument 
*>(node
->GetData()); 
1247             view 
= doc
->GetFirstView(); 
1249         //else: we have more than one document 
1255 bool wxDocManager::TryBefore(wxEvent
& event
) 
1257     wxView 
* const view 
= GetActiveView(); 
1258     return view 
&& view
->ProcessEventHere(event
); 
1264 // helper function: return only the visible templates 
1265 wxDocTemplates 
GetVisibleTemplates(const wxList
& allTemplates
) 
1267     // select only the visible templates 
1268     const size_t totalNumTemplates 
= allTemplates
.GetCount(); 
1269     wxDocTemplates templates
; 
1270     if ( totalNumTemplates 
) 
1272         templates
.reserve(totalNumTemplates
); 
1274         for ( wxList::const_iterator i 
= allTemplates
.begin(), 
1275                                    end 
= allTemplates
.end(); 
1279             wxDocTemplate 
* const temp 
= (wxDocTemplate 
*)*i
; 
1280             if ( temp
->IsVisible() ) 
1281                 templates
.push_back(temp
); 
1288 } // anonymous namespace 
1290 wxDocument 
*wxDocManager::CreateDocument(const wxString
& pathOrig
, long flags
) 
1292     // this ought to be const but SelectDocumentType/Path() are not 
1293     // const-correct and can't be changed as, being virtual, this risks 
1294     // breaking user code overriding them 
1295     wxDocTemplates 
templates(GetVisibleTemplates(m_templates
)); 
1296     const size_t numTemplates 
= templates
.size(); 
1297     if ( !numTemplates 
) 
1299         // no templates can be used, can't create document 
1304     // normally user should select the template to use but wxDOC_SILENT flag we 
1305     // choose one ourselves 
1306     wxString path 
= pathOrig
;   // may be modified below 
1307     wxDocTemplate 
*temp
; 
1308     if ( flags 
& wxDOC_SILENT 
) 
1310         wxASSERT_MSG( !path
.empty(), 
1311                       "using empty path with wxDOC_SILENT doesn't make sense" ); 
1313         temp 
= FindTemplateForPath(path
); 
1316             wxLogWarning(_("The format of file '%s' couldn't be determined."), 
1320     else // not silent, ask the user 
1322         // for the new file we need just the template, for an existing one we 
1323         // need the template and the path, unless it's already specified 
1324         if ( (flags 
& wxDOC_NEW
) || !path
.empty() ) 
1325             temp 
= SelectDocumentType(&templates
[0], numTemplates
); 
1327             temp 
= SelectDocumentPath(&templates
[0], numTemplates
, path
, flags
); 
1333     // check whether the document with this path is already opened 
1334     if ( !path
.empty() ) 
1336         const wxFileName 
fn(path
); 
1337         for ( wxList::const_iterator i 
= m_docs
.begin(); i 
!= m_docs
.end(); ++i 
) 
1339             wxDocument 
* const doc 
= (wxDocument
*)*i
; 
1341             if ( fn 
== doc
->GetFilename() ) 
1343                 // file already open, just activate it and return 
1344                 if ( doc
->GetFirstView() ) 
1346                     ActivateView(doc
->GetFirstView()); 
1347                     if ( doc
->GetDocumentWindow() ) 
1348                         doc
->GetDocumentWindow()->SetFocus(); 
1356     // no, we need to create a new document 
1359     // if we've reached the max number of docs, close the first one. 
1360     if ( (int)GetDocuments().GetCount() >= m_maxDocsOpen 
) 
1362         if ( !CloseDocument((wxDocument 
*)GetDocuments().GetFirst()->GetData()) ) 
1364             // can't open the new document if closing the old one failed 
1370     // do create and initialize the new document finally 
1371     wxDocument 
* const docNew 
= temp
->CreateDocument(path
, flags
); 
1375     docNew
->SetDocumentName(temp
->GetDocumentName()); 
1376     docNew
->SetDocumentTemplate(temp
); 
1380         // call the appropriate function depending on whether we're creating a 
1381         // new file or opening an existing one 
1382         if ( !(flags 
& wxDOC_NEW 
? docNew
->OnNewDocument() 
1383                                  : docNew
->OnOpenDocument(path
)) ) 
1385             docNew
->DeleteAllViews(); 
1389     wxCATCH_ALL( docNew
->DeleteAllViews(); throw; ) 
1391     // add the successfully opened file to MRU, but only if we're going to be 
1392     // able to reopen it successfully later which requires the template for 
1393     // this document to be retrievable from the file extension 
1394     if ( !(flags 
& wxDOC_NEW
) && temp
->FileMatchesTemplate(path
) ) 
1395         AddFileToHistory(path
); 
1400 wxView 
*wxDocManager::CreateView(wxDocument 
*doc
, long flags
) 
1402     wxDocTemplates 
templates(GetVisibleTemplates(m_templates
)); 
1403     const size_t numTemplates 
= templates
.size(); 
1405     if ( numTemplates 
== 0 ) 
1408     wxDocTemplate 
* const 
1409     temp 
= numTemplates 
== 1 ? templates
[0] 
1410                              : SelectViewType(&templates
[0], numTemplates
); 
1415     wxView 
*view 
= temp
->CreateView(doc
, flags
); 
1417         view
->SetViewName(temp
->GetViewName()); 
1421 // Not yet implemented 
1423 wxDocManager::DeleteTemplate(wxDocTemplate 
*WXUNUSED(temp
), long WXUNUSED(flags
)) 
1427 // Not yet implemented 
1428 bool wxDocManager::FlushDoc(wxDocument 
*WXUNUSED(doc
)) 
1433 wxDocument 
*wxDocManager::GetCurrentDocument() const 
1435     wxView 
* const view 
= GetActiveView(); 
1436     return view 
? view
->GetDocument() : NULL
; 
1439 wxCommandProcessor 
*wxDocManager::GetCurrentCommandProcessor() const 
1441     wxDocument 
* const doc 
= GetCurrentDocument(); 
1442     return doc 
? doc
->GetCommandProcessor() : NULL
; 
1445 // Make a default name for a new document 
1446 #if WXWIN_COMPATIBILITY_2_8 
1447 bool wxDocManager::MakeDefaultName(wxString
& WXUNUSED(name
)) 
1449     // we consider that this function can only be overridden by the user code, 
1450     // not called by it as it only makes sense to call it internally, so we 
1451     // don't bother to return anything from here 
1454 #endif // WXWIN_COMPATIBILITY_2_8 
1456 wxString 
wxDocManager::MakeNewDocumentName() 
1460 #if WXWIN_COMPATIBILITY_2_8 
1461     if ( !MakeDefaultName(name
) ) 
1462 #endif // WXWIN_COMPATIBILITY_2_8 
1464         name
.Printf(_("unnamed%d"), m_defaultDocumentNameCounter
); 
1465         m_defaultDocumentNameCounter
++; 
1471 // Make a frame title (override this to do something different) 
1472 // If docName is empty, a document is not currently active. 
1473 wxString 
wxDocManager::MakeFrameTitle(wxDocument
* doc
) 
1475     wxString appName 
= wxTheApp
->GetAppDisplayName(); 
1481         wxString docName 
= doc
->GetUserReadableName(); 
1482         title 
= docName 
+ wxString(_(" - ")) + appName
; 
1488 // Not yet implemented 
1489 wxDocTemplate 
*wxDocManager::MatchTemplate(const wxString
& WXUNUSED(path
)) 
1494 // File history management 
1495 void wxDocManager::AddFileToHistory(const wxString
& file
) 
1498         m_fileHistory
->AddFileToHistory(file
); 
1501 void wxDocManager::RemoveFileFromHistory(size_t i
) 
1504         m_fileHistory
->RemoveFileFromHistory(i
); 
1507 wxString 
wxDocManager::GetHistoryFile(size_t i
) const 
1512         histFile 
= m_fileHistory
->GetHistoryFile(i
); 
1517 void wxDocManager::FileHistoryUseMenu(wxMenu 
*menu
) 
1520         m_fileHistory
->UseMenu(menu
); 
1523 void wxDocManager::FileHistoryRemoveMenu(wxMenu 
*menu
) 
1526         m_fileHistory
->RemoveMenu(menu
); 
1530 void wxDocManager::FileHistoryLoad(const wxConfigBase
& config
) 
1533         m_fileHistory
->Load(config
); 
1536 void wxDocManager::FileHistorySave(wxConfigBase
& config
) 
1539         m_fileHistory
->Save(config
); 
1543 void wxDocManager::FileHistoryAddFilesToMenu(wxMenu
* menu
) 
1546         m_fileHistory
->AddFilesToMenu(menu
); 
1549 void wxDocManager::FileHistoryAddFilesToMenu() 
1552         m_fileHistory
->AddFilesToMenu(); 
1555 size_t wxDocManager::GetHistoryFilesCount() const 
1557     return m_fileHistory 
? m_fileHistory
->GetCount() : 0; 
1561 // Find out the document template via matching in the document file format 
1562 // against that of the template 
1563 wxDocTemplate 
*wxDocManager::FindTemplateForPath(const wxString
& path
) 
1565     wxDocTemplate 
*theTemplate 
= NULL
; 
1567     // Find the template which this extension corresponds to 
1568     for (size_t i 
= 0; i 
< m_templates
.GetCount(); i
++) 
1570         wxDocTemplate 
*temp 
= (wxDocTemplate 
*)m_templates
.Item(i
)->GetData(); 
1571         if ( temp
->FileMatchesTemplate(path
) ) 
1580 // Prompts user to open a file, using file specs in templates. 
1581 // Must extend the file selector dialog or implement own; OR 
1582 // match the extension to the template extension. 
1584 wxDocTemplate 
*wxDocManager::SelectDocumentPath(wxDocTemplate 
**templates
, 
1587                                                 long WXUNUSED(flags
), 
1588                                                 bool WXUNUSED(save
)) 
1590 #ifdef wxHAS_MULTIPLE_FILEDLG_FILTERS 
1593     for (int i 
= 0; i 
< noTemplates
; i
++) 
1595         if (templates
[i
]->IsVisible()) 
1597             // add a '|' to separate this filter from the previous one 
1598             if ( !descrBuf
.empty() ) 
1599                 descrBuf 
<< wxT('|'); 
1601             descrBuf 
<< templates
[i
]->GetDescription() 
1602                 << wxT(" (") << templates
[i
]->GetFileFilter() << wxT(") |") 
1603                 << templates
[i
]->GetFileFilter(); 
1607     wxString descrBuf 
= wxT("*.*"); 
1608     wxUnusedVar(noTemplates
); 
1611     int FilterIndex 
= -1; 
1613     wxString pathTmp 
= wxFileSelectorEx(_("Open File"), 
1619     wxDocTemplate 
*theTemplate 
= NULL
; 
1620     if (!pathTmp
.empty()) 
1622         if (!wxFileExists(pathTmp
)) 
1625             if (!wxTheApp
->GetAppDisplayName().empty()) 
1626                 msgTitle 
= wxTheApp
->GetAppDisplayName(); 
1628                 msgTitle 
= wxString(_("File error")); 
1630             wxMessageBox(_("Sorry, could not open this file."), 
1632                          wxOK 
| wxICON_EXCLAMATION 
| wxCENTRE
); 
1634             path 
= wxEmptyString
; 
1638         SetLastDirectory(wxPathOnly(pathTmp
)); 
1642         // first choose the template using the extension, if this fails (i.e. 
1643         // wxFileSelectorEx() didn't fill it), then use the path 
1644         if ( FilterIndex 
!= -1 ) 
1645             theTemplate 
= templates
[FilterIndex
]; 
1647             theTemplate 
= FindTemplateForPath(path
); 
1650             // Since we do not add files with non-default extensions to the 
1651             // file history this can only happen if the application changes the 
1652             // allowed templates in runtime. 
1653             wxMessageBox(_("Sorry, the format for this file is unknown."), 
1655                          wxOK 
| wxICON_EXCLAMATION 
| wxCENTRE
); 
1666 wxDocTemplate 
*wxDocManager::SelectDocumentType(wxDocTemplate 
**templates
, 
1667                                                 int noTemplates
, bool sort
) 
1669     wxArrayString strings
; 
1670     wxScopedArray
<wxDocTemplate 
*> data(new wxDocTemplate 
*[noTemplates
]); 
1674     for (i 
= 0; i 
< noTemplates
; i
++) 
1676         if (templates
[i
]->IsVisible()) 
1680             for (j 
= 0; j 
< n
; j
++) 
1682                 //filter out NOT unique documents + view combinations 
1683                 if ( templates
[i
]->m_docTypeName 
== data
[j
]->m_docTypeName 
&& 
1684                      templates
[i
]->m_viewTypeName 
== data
[j
]->m_viewTypeName
 
1691                 strings
.Add(templates
[i
]->m_description
); 
1693                 data
[n
] = templates
[i
]; 
1701         strings
.Sort(); // ascending sort 
1702         // Yes, this will be slow, but template lists 
1703         // are typically short. 
1705         n 
= strings
.Count(); 
1706         for (i 
= 0; i 
< n
; i
++) 
1708             for (j 
= 0; j 
< noTemplates
; j
++) 
1710                 if (strings
[i
] == templates
[j
]->m_description
) 
1711                     data
[i
] = templates
[j
]; 
1716     wxDocTemplate 
*theTemplate
; 
1721             // no visible templates, hence nothing to choose from 
1726             // don't propose the user to choose if he has no choice 
1727             theTemplate 
= data
[0]; 
1731             // propose the user to choose one of several 
1732             theTemplate 
= (wxDocTemplate 
*)wxGetSingleChoiceData
 
1734                             _("Select a document template"), 
1744 wxDocTemplate 
*wxDocManager::SelectViewType(wxDocTemplate 
**templates
, 
1745                                             int noTemplates
, bool sort
) 
1747     wxArrayString strings
; 
1748     wxScopedArray
<wxDocTemplate 
*> data(new wxDocTemplate 
*[noTemplates
]); 
1752     for (i 
= 0; i 
< noTemplates
; i
++) 
1754         wxDocTemplate 
*templ 
= templates
[i
]; 
1755         if ( templ
->IsVisible() && !templ
->GetViewName().empty() ) 
1759             for (j 
= 0; j 
< n
; j
++) 
1761                 //filter out NOT unique views 
1762                 if ( templates
[i
]->m_viewTypeName 
== data
[j
]->m_viewTypeName 
) 
1768                 strings
.Add(templ
->m_viewTypeName
); 
1777         strings
.Sort(); // ascending sort 
1778         // Yes, this will be slow, but template lists 
1779         // are typically short. 
1781         n 
= strings
.Count(); 
1782         for (i 
= 0; i 
< n
; i
++) 
1784             for (j 
= 0; j 
< noTemplates
; j
++) 
1786                 if (strings
[i
] == templates
[j
]->m_viewTypeName
) 
1787                     data
[i
] = templates
[j
]; 
1792     wxDocTemplate 
*theTemplate
; 
1794     // the same logic as above 
1802             theTemplate 
= data
[0]; 
1806             theTemplate 
= (wxDocTemplate 
*)wxGetSingleChoiceData
 
1808                             _("Select a document view"), 
1819 void wxDocManager::AssociateTemplate(wxDocTemplate 
*temp
) 
1821     if (!m_templates
.Member(temp
)) 
1822         m_templates
.Append(temp
); 
1825 void wxDocManager::DisassociateTemplate(wxDocTemplate 
*temp
) 
1827     m_templates
.DeleteObject(temp
); 
1830 // Add and remove a document from the manager's list 
1831 void wxDocManager::AddDocument(wxDocument 
*doc
) 
1833     if (!m_docs
.Member(doc
)) 
1837 void wxDocManager::RemoveDocument(wxDocument 
*doc
) 
1839     m_docs
.DeleteObject(doc
); 
1842 // Views or windows should inform the document manager 
1843 // when a view is going in or out of focus 
1844 void wxDocManager::ActivateView(wxView 
*view
, bool activate
) 
1848         m_currentView 
= view
; 
1852         if ( m_currentView 
== view 
) 
1854             // don't keep stale pointer 
1855             m_currentView 
= NULL
; 
1860 // ---------------------------------------------------------------------------- 
1861 // wxDocChildFrameAnyBase 
1862 // ---------------------------------------------------------------------------- 
1864 bool wxDocChildFrameAnyBase::CloseView(wxCloseEvent
& event
) 
1868         // notice that we must call wxView::Close() and OnClose() called from 
1869         // it in any case, even if we know that we are going to close anyhow 
1870         if ( !m_childView
->Close(false) && event
.CanVeto() ) 
1876         m_childView
->Activate(false); 
1878         // it is important to reset m_childView frame pointer to NULL before 
1879         // deleting it because while normally it is the frame which deletes the 
1880         // view when it's closed, the view also closes the frame if it is 
1881         // deleted directly not by us as indicated by its doc child frame 
1882         // pointer still being set 
1883         m_childView
->SetDocChildFrame(NULL
); 
1888     m_childDocument 
= NULL
; 
1893 // ---------------------------------------------------------------------------- 
1894 // Default parent frame 
1895 // ---------------------------------------------------------------------------- 
1897 BEGIN_EVENT_TABLE(wxDocParentFrame
, wxFrame
) 
1898     EVT_MENU(wxID_EXIT
, wxDocParentFrame::OnExit
) 
1899     EVT_MENU_RANGE(wxID_FILE1
, wxID_FILE9
, wxDocParentFrame::OnMRUFile
) 
1900     EVT_CLOSE(wxDocParentFrame::OnCloseWindow
) 
1903 wxDocParentFrame::wxDocParentFrame() 
1905     m_docManager 
= NULL
; 
1908 wxDocParentFrame::wxDocParentFrame(wxDocManager 
*manager
, 
1911                                    const wxString
& title
, 
1915                                    const wxString
& name
) 
1916                 : wxFrame(frame
, id
, title
, pos
, size
, style
, name
) 
1918     m_docManager 
= manager
; 
1921 bool wxDocParentFrame::Create(wxDocManager 
*manager
, 
1924                               const wxString
& title
, 
1928                               const wxString
& name
) 
1930     m_docManager 
= manager
; 
1931     return base_type::Create(frame
, id
, title
, pos
, size
, style
, name
); 
1934 void wxDocParentFrame::OnExit(wxCommandEvent
& WXUNUSED(event
)) 
1939 void wxDocParentFrame::OnMRUFile(wxCommandEvent
& event
) 
1941     int n 
= event
.GetId() - wxID_FILE1
;  // the index in MRU list 
1942     wxString 
filename(m_docManager
->GetHistoryFile(n
)); 
1943     if ( filename
.empty() ) 
1946     wxString errMsg
; // must contain exactly one "%s" if non-empty 
1947     if ( wxFile::Exists(filename
) ) 
1950         if ( m_docManager
->CreateDocument(filename
, wxDOC_SILENT
) ) 
1953         errMsg 
= _("The file '%s' couldn't be opened."); 
1955     else // file doesn't exist 
1957         errMsg 
= _("The file '%s' doesn't exist and couldn't be opened."); 
1961     wxASSERT_MSG( !errMsg
.empty(), "should have an error message" ); 
1963     // remove the file which we can't open from the MRU list 
1964     m_docManager
->RemoveFileFromHistory(n
); 
1966     // and tell the user about it 
1967     wxLogError(errMsg 
+ '\n' + 
1968                _("It has been removed from the most recently used files list."), 
1972 // Extend event processing to search the view's event table 
1973 bool wxDocParentFrame::TryBefore(wxEvent
& event
) 
1975     if ( m_docManager 
&& m_docManager
->ProcessEventHere(event
) ) 
1978     return wxFrame::TryBefore(event
); 
1981 // Define the behaviour for the frame closing 
1982 // - must delete all frames except for the main one. 
1983 void wxDocParentFrame::OnCloseWindow(wxCloseEvent
& event
) 
1985     if (m_docManager
->Clear(!event
.CanVeto())) 
1993 #if wxUSE_PRINTING_ARCHITECTURE 
1995 wxDocPrintout::wxDocPrintout(wxView 
*view
, const wxString
& title
) 
1998     m_printoutView 
= view
; 
2001 bool wxDocPrintout::OnPrintPage(int WXUNUSED(page
)) 
2005     // Get the logical pixels per inch of screen and printer 
2006     int ppiScreenX
, ppiScreenY
; 
2007     GetPPIScreen(&ppiScreenX
, &ppiScreenY
); 
2008     wxUnusedVar(ppiScreenY
); 
2009     int ppiPrinterX
, ppiPrinterY
; 
2010     GetPPIPrinter(&ppiPrinterX
, &ppiPrinterY
); 
2011     wxUnusedVar(ppiPrinterY
); 
2013     // This scales the DC so that the printout roughly represents the 
2014     // the screen scaling. The text point size _should_ be the right size 
2015     // but in fact is too small for some reason. This is a detail that will 
2016     // need to be addressed at some point but can be fudged for the 
2018     float scale 
= (float)((float)ppiPrinterX
/(float)ppiScreenX
); 
2020     // Now we have to check in case our real page size is reduced 
2021     // (e.g. because we're drawing to a print preview memory DC) 
2022     int pageWidth
, pageHeight
; 
2024     dc
->GetSize(&w
, &h
); 
2025     GetPageSizePixels(&pageWidth
, &pageHeight
); 
2026     wxUnusedVar(pageHeight
); 
2028     // If printer pageWidth == current DC width, then this doesn't 
2029     // change. But w might be the preview bitmap width, so scale down. 
2030     float overallScale 
= scale 
* (float)(w
/(float)pageWidth
); 
2031     dc
->SetUserScale(overallScale
, overallScale
); 
2035         m_printoutView
->OnDraw(dc
); 
2040 bool wxDocPrintout::HasPage(int pageNum
) 
2042     return (pageNum 
== 1); 
2045 bool wxDocPrintout::OnBeginDocument(int startPage
, int endPage
) 
2047     if (!wxPrintout::OnBeginDocument(startPage
, endPage
)) 
2053 void wxDocPrintout::GetPageInfo(int *minPage
, int *maxPage
, 
2054                                 int *selPageFrom
, int *selPageTo
) 
2062 #endif // wxUSE_PRINTING_ARCHITECTURE 
2064 // ---------------------------------------------------------------------------- 
2065 // File history (a.k.a. MRU, most recently used, files list) 
2066 // ---------------------------------------------------------------------------- 
2068 wxFileHistory::wxFileHistory(size_t maxFiles
, wxWindowID idBase
) 
2070     m_fileMaxFiles 
= maxFiles
; 
2074 void wxFileHistory::AddFileToHistory(const wxString
& file
) 
2076     // check if we don't already have this file 
2077     const wxFileName 
fnNew(file
); 
2079            numFiles 
= m_fileHistory
.size(); 
2080     for ( i 
= 0; i 
< numFiles
; i
++ ) 
2082         if ( fnNew 
== m_fileHistory
[i
] ) 
2084             // we do have it, move it to the top of the history 
2085             RemoveFileFromHistory(i
); 
2091     // if we already have a full history, delete the one at the end 
2092     if ( numFiles 
== m_fileMaxFiles 
) 
2094         RemoveFileFromHistory(--numFiles
); 
2097     // add a new menu item to all file menus (they will be updated below) 
2098     for ( wxList::compatibility_iterator node 
= m_fileMenus
.GetFirst(); 
2100         node 
= node
->GetNext() ) 
2102         wxMenu 
* const menu 
= (wxMenu 
*)node
->GetData(); 
2104         if ( !numFiles 
&& menu
->GetMenuItemCount() ) 
2105             menu
->AppendSeparator(); 
2107         // label doesn't matter, it will be set below anyhow, but it can't 
2108         // be empty (this is supposed to indicate a stock item) 
2109         menu
->Append(m_idBase 
+ numFiles
, " "); 
2112     // insert the new file in the beginning of the file history 
2113     m_fileHistory
.insert(m_fileHistory
.begin(), file
); 
2116     // update the labels in all menus 
2117     for ( i 
= 0; i 
< numFiles
; i
++ ) 
2119         // if in same directory just show the filename; otherwise the full path 
2120         const wxFileName 
fnOld(m_fileHistory
[i
]); 
2122         wxString pathInMenu
; 
2123         if ( fnOld
.GetPath() == fnNew
.GetPath() ) 
2125             pathInMenu 
= fnOld
.GetFullName(); 
2127         else // file in different directory 
2129             // absolute path; could also set relative path 
2130             pathInMenu 
= m_fileHistory
[i
]; 
2133         for ( wxList::compatibility_iterator node 
= m_fileMenus
.GetFirst(); 
2135               node 
= node
->GetNext() ) 
2137             wxMenu 
* const menu 
= (wxMenu 
*)node
->GetData(); 
2139             menu
->SetLabel(m_idBase 
+ i
, GetMRUEntryLabel(i
, pathInMenu
)); 
2144 void wxFileHistory::RemoveFileFromHistory(size_t i
) 
2146     size_t numFiles 
= m_fileHistory
.size(); 
2147     wxCHECK_RET( i 
< numFiles
, 
2148                  wxT("invalid index in wxFileHistory::RemoveFileFromHistory") ); 
2150     // delete the element from the array 
2151     m_fileHistory
.RemoveAt(i
); 
2154     for ( wxList::compatibility_iterator node 
= m_fileMenus
.GetFirst(); 
2156           node 
= node
->GetNext() ) 
2158         wxMenu 
* const menu 
= (wxMenu 
*) node
->GetData(); 
2160         // shift filenames up 
2161         for ( size_t j 
= i
; j 
< numFiles
; j
++ ) 
2163             menu
->SetLabel(m_idBase 
+ j
, GetMRUEntryLabel(j
, m_fileHistory
[j
])); 
2166         // delete the last menu item which is unused now 
2167         const wxWindowID lastItemId 
= m_idBase 
+ numFiles
; 
2168         if ( menu
->FindItem(lastItemId
) ) 
2169             menu
->Delete(lastItemId
); 
2171         // delete the last separator too if no more files are left 
2172         if ( m_fileHistory
.empty() ) 
2174             const wxMenuItemList::compatibility_iterator
 
2175                 nodeLast 
= menu
->GetMenuItems().GetLast(); 
2178                 wxMenuItem 
* const lastMenuItem 
= nodeLast
->GetData(); 
2179                 if ( lastMenuItem
->IsSeparator() ) 
2180                     menu
->Delete(lastMenuItem
); 
2182             //else: menu is empty somehow 
2187 void wxFileHistory::UseMenu(wxMenu 
*menu
) 
2189     if ( !m_fileMenus
.Member(menu
) ) 
2190         m_fileMenus
.Append(menu
); 
2193 void wxFileHistory::RemoveMenu(wxMenu 
*menu
) 
2195     m_fileMenus
.DeleteObject(menu
); 
2199 void wxFileHistory::Load(const wxConfigBase
& config
) 
2201     m_fileHistory
.Clear(); 
2204     buf
.Printf(wxT("file%d"), 1); 
2206     wxString historyFile
; 
2207     while ((m_fileHistory
.GetCount() < m_fileMaxFiles
) && 
2208            config
.Read(buf
, &historyFile
) && !historyFile
.empty()) 
2210         m_fileHistory
.Add(historyFile
); 
2212         buf
.Printf(wxT("file%d"), (int)m_fileHistory
.GetCount()+1); 
2213         historyFile 
= wxEmptyString
; 
2219 void wxFileHistory::Save(wxConfigBase
& config
) 
2222     for (i 
= 0; i 
< m_fileMaxFiles
; i
++) 
2225         buf
.Printf(wxT("file%d"), (int)i
+1); 
2226         if (i 
< m_fileHistory
.GetCount()) 
2227             config
.Write(buf
, wxString(m_fileHistory
[i
])); 
2229             config
.Write(buf
, wxEmptyString
); 
2232 #endif // wxUSE_CONFIG 
2234 void wxFileHistory::AddFilesToMenu() 
2236     if ( m_fileHistory
.empty() ) 
2239     for ( wxList::compatibility_iterator node 
= m_fileMenus
.GetFirst(); 
2241           node 
= node
->GetNext() ) 
2243         AddFilesToMenu((wxMenu 
*) node
->GetData()); 
2247 void wxFileHistory::AddFilesToMenu(wxMenu
* menu
) 
2249     if ( m_fileHistory
.empty() ) 
2252     if ( menu
->GetMenuItemCount() ) 
2253         menu
->AppendSeparator(); 
2255     for ( size_t i 
= 0; i 
< m_fileHistory
.GetCount(); i
++ ) 
2257         menu
->Append(m_idBase 
+ i
, GetMRUEntryLabel(i
, m_fileHistory
[i
])); 
2261 // ---------------------------------------------------------------------------- 
2262 // Permits compatibility with existing file formats and functions that 
2263 // manipulate files directly 
2264 // ---------------------------------------------------------------------------- 
2266 #if wxUSE_STD_IOSTREAM 
2268 bool wxTransferFileToStream(const wxString
& filename
, wxSTD ostream
& stream
) 
2271     wxFFile 
file(filename
, wxT("rb")); 
2273     wxFile 
file(filename
, wxFile::read
); 
2275     if ( !file
.IsOpened() ) 
2283         nRead 
= file
.Read(buf
, WXSIZEOF(buf
)); 
2287         stream
.write(buf
, nRead
); 
2291     while ( !file
.Eof() ); 
2296 bool wxTransferStreamToFile(wxSTD istream
& stream
, const wxString
& filename
) 
2299     wxFFile 
file(filename
, wxT("wb")); 
2301     wxFile 
file(filename
, wxFile::write
); 
2303     if ( !file
.IsOpened() ) 
2309         stream
.read(buf
, WXSIZEOF(buf
)); 
2310         if ( !stream
.bad() ) // fail may be set on EOF, don't use operator!() 
2312             if ( !file
.Write(buf
, stream
.gcount()) ) 
2316     while ( !stream
.eof() ); 
2321 #else // !wxUSE_STD_IOSTREAM 
2323 bool wxTransferFileToStream(const wxString
& filename
, wxOutputStream
& stream
) 
2326     wxFFile 
file(filename
, wxT("rb")); 
2328     wxFile 
file(filename
, wxFile::read
); 
2330     if ( !file
.IsOpened() ) 
2338         nRead 
= file
.Read(buf
, WXSIZEOF(buf
)); 
2342         stream
.Write(buf
, nRead
); 
2346     while ( !file
.Eof() ); 
2351 bool wxTransferStreamToFile(wxInputStream
& stream
, const wxString
& filename
) 
2354     wxFFile 
file(filename
, wxT("wb")); 
2356     wxFile 
file(filename
, wxFile::write
); 
2358     if ( !file
.IsOpened() ) 
2364         stream
.Read(buf
, WXSIZEOF(buf
)); 
2366         const size_t nRead 
= stream
.LastRead(); 
2375         if ( !file
.Write(buf
, nRead
) ) 
2382 #endif // wxUSE_STD_IOSTREAM/!wxUSE_STD_IOSTREAM 
2384 #endif // wxUSE_DOC_VIEW_ARCHITECTURE