1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/common/docview.cpp 
   3 // Purpose:     Document/view classes 
   4 // Author:      Julian Smart 
   8 // Copyright:   (c) Julian Smart 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  20 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) 
  21     #pragma implementation "docview.h" 
  24 // For compilers that support precompilation, includes "wx.h". 
  25 #include "wx/wxprec.h" 
  31 #if wxUSE_DOC_VIEW_ARCHITECTURE 
  34     #include "wx/string.h" 
  38     #include "wx/dialog.h" 
  41     #include "wx/filedlg.h" 
  49     #include "wx/filename.h" 
  56 #if wxUSE_PRINTING_ARCHITECTURE 
  57   #include "wx/prntbase.h" 
  58   #include "wx/printdlg.h" 
  61 #include "wx/msgdlg.h" 
  62 #include "wx/choicdlg.h" 
  63 #include "wx/docview.h" 
  64 #include "wx/confbase.h" 
  66 #include "wx/cmdproc.h" 
  71 #if wxUSE_STD_IOSTREAM 
  72   #include "wx/ioswrap.h" 
  79   #include "wx/wfstream.h" 
  82 // ---------------------------------------------------------------------------- 
  84 // ---------------------------------------------------------------------------- 
  86 IMPLEMENT_ABSTRACT_CLASS(wxDocument
, wxEvtHandler
) 
  87 IMPLEMENT_ABSTRACT_CLASS(wxView
, wxEvtHandler
) 
  88 IMPLEMENT_ABSTRACT_CLASS(wxDocTemplate
, wxObject
) 
  89 IMPLEMENT_DYNAMIC_CLASS(wxDocManager
, wxEvtHandler
) 
  90 IMPLEMENT_CLASS(wxDocChildFrame
, wxFrame
) 
  91 IMPLEMENT_CLASS(wxDocParentFrame
, wxFrame
) 
  93 #if wxUSE_PRINTING_ARCHITECTURE 
  94     IMPLEMENT_DYNAMIC_CLASS(wxDocPrintout
, wxPrintout
) 
  97 IMPLEMENT_DYNAMIC_CLASS(wxFileHistory
, wxObject
) 
  99 // ---------------------------------------------------------------------------- 
 100 // function prototypes 
 101 // ---------------------------------------------------------------------------- 
 103 static inline wxString 
FindExtension(const wxChar 
*path
); 
 104 static wxWindow
* wxFindSuitableParent(void); 
 106 // ---------------------------------------------------------------------------- 
 108 // ---------------------------------------------------------------------------- 
 110 static const wxChar 
*s_MRUEntryFormat 
= wxT("&%d %s"); 
 112 // ============================================================================ 
 114 // ============================================================================ 
 116 // ---------------------------------------------------------------------------- 
 118 // ---------------------------------------------------------------------------- 
 120 static wxString 
FindExtension(const wxChar 
*path
) 
 123     wxSplitPath(path
, NULL
, NULL
, &ext
); 
 125     // VZ: extensions are considered not case sensitive - is this really a good 
 127     return ext
.MakeLower(); 
 130 // ---------------------------------------------------------------------------- 
 131 // Definition of wxDocument 
 132 // ---------------------------------------------------------------------------- 
 134 wxDocument::wxDocument(wxDocument 
*parent
) 
 136     m_documentModified 
= FALSE
; 
 137     m_documentParent 
= parent
; 
 138     m_documentTemplate 
= (wxDocTemplate 
*) NULL
; 
 139     m_commandProcessor 
= (wxCommandProcessor
*) NULL
; 
 143 bool wxDocument::DeleteContents() 
 148 wxDocument::~wxDocument() 
 152     if (m_commandProcessor
) 
 153         delete m_commandProcessor
; 
 155     if (GetDocumentManager()) 
 156         GetDocumentManager()->RemoveDocument(this); 
 158     // Not safe to do here, since it'll invoke virtual view functions 
 159     // expecting to see valid derived objects: and by the time we get here, 
 160     // we've called destructors higher up. 
 164 bool wxDocument::Close() 
 166     if (OnSaveModified()) 
 167         return OnCloseDocument(); 
 172 bool wxDocument::OnCloseDocument() 
 174     // Tell all views that we're about to close 
 181 // Note that this implicitly deletes the document when the last view is 
 183 bool wxDocument::DeleteAllViews() 
 185     wxDocManager
* manager 
= GetDocumentManager(); 
 186     wxList::iterator it
, en
; 
 188     for ( it 
= m_documentViews
.begin(), en 
= m_documentViews
.end(); 
 192         wxView 
*view 
= (wxView 
*)*it
; 
 196         wxList::iterator next 
= it
; ++next
; 
 198         delete view
; // Deletes node implicitly 
 201     // If we haven't yet deleted the document (for example 
 202     // if there were no views) then delete it. 
 203     if (manager 
&& manager
->GetDocuments().Member(this)) 
 209 wxView 
*wxDocument::GetFirstView() const 
 211     if (m_documentViews
.GetCount() == 0) 
 212         return (wxView 
*) NULL
; 
 213     return (wxView 
*)m_documentViews
.GetFirst()->GetData(); 
 216 wxDocManager 
*wxDocument::GetDocumentManager() const 
 218     return (m_documentTemplate 
? m_documentTemplate
->GetDocumentManager() : (wxDocManager
*) NULL
); 
 221 bool wxDocument::OnNewDocument() 
 223     if (!OnSaveModified()) 
 226     if (OnCloseDocument()==FALSE
) return FALSE
; 
 229     SetDocumentSaved(FALSE
); 
 232     GetDocumentManager()->MakeDefaultName(name
); 
 234     SetFilename(name
, TRUE
); 
 239 bool wxDocument::Save() 
 241     if (!IsModified() && m_savedYet
) 
 244     if ( m_documentFile
.empty() || !m_savedYet 
) 
 247     return OnSaveDocument(m_documentFile
); 
 250 bool wxDocument::SaveAs() 
 252     wxDocTemplate 
*docTemplate 
= GetDocumentTemplate(); 
 256 #if defined(__WXMSW__) || defined(__WXGTK__) || defined(__WXMAC__) 
 257     wxString filter 
= docTemplate
->GetDescription() + wxT(" (") + docTemplate
->GetFileFilter() + wxT(")|") + docTemplate
->GetFileFilter(); 
 259     // Now see if there are some other template with identical view and document 
 260     // classes, whose filters may also be used. 
 262     if (docTemplate
->GetViewClassInfo() && docTemplate
->GetDocClassInfo()) 
 264         wxList::compatibility_iterator node 
= wxDocManager::GetDocumentManager()->GetTemplates().GetFirst(); 
 267             wxDocTemplate 
*t 
= (wxDocTemplate
*) node
->GetData(); 
 269             if (t
->IsVisible() && t 
!= docTemplate 
&& 
 270                 t
->GetViewClassInfo() == docTemplate
->GetViewClassInfo() && 
 271                 t
->GetDocClassInfo() == docTemplate
->GetDocClassInfo()) 
 273                 // add a '|' to separate this filter from the previous one 
 274                 if ( !filter
.IsEmpty() ) 
 277                 filter 
<< t
->GetDescription() << wxT(" (") << t
->GetFileFilter() << wxT(") |") 
 278                        << t
->GetFileFilter(); 
 281             node 
= node
->GetNext(); 
 285     wxString filter 
= docTemplate
->GetFileFilter() ; 
 287     wxString tmp 
= wxFileSelector(_("Save as"), 
 288             docTemplate
->GetDirectory(), 
 289             wxFileNameFromPath(GetFilename()), 
 290             docTemplate
->GetDefaultExtension(), 
 292             wxSAVE 
| wxOVERWRITE_PROMPT
, 
 293             GetDocumentWindow()); 
 298     wxString 
fileName(tmp
); 
 299     wxString path
, name
, ext
; 
 300     wxSplitPath(fileName
, & path
, & name
, & ext
); 
 302     if (ext
.IsEmpty() || ext 
== wxT("")) 
 304         fileName 
+= wxT("."); 
 305         fileName 
+= docTemplate
->GetDefaultExtension(); 
 308     SetFilename(fileName
); 
 309     SetTitle(wxFileNameFromPath(fileName
)); 
 311     // Notify the views that the filename has changed 
 312     wxList::compatibility_iterator node 
= m_documentViews
.GetFirst(); 
 315         wxView 
*view 
= (wxView 
*)node
->GetData(); 
 316         view
->OnChangeFilename(); 
 317         node 
= node
->GetNext(); 
 320     // Files that were not saved correctly are not added to the FileHistory. 
 321     if (!OnSaveDocument(m_documentFile
)) 
 324    // A file that doesn't use the default extension of its document template cannot be opened 
 325    // via the FileHistory, so we do not add it. 
 326    if (docTemplate
->FileMatchesTemplate(fileName
)) 
 328        GetDocumentManager()->AddFileToHistory(fileName
); 
 332        // The user will probably not be able to open the file again, so 
 333        // we could warn about the wrong file-extension here. 
 338 bool wxDocument::OnSaveDocument(const wxString
& file
) 
 344     if (wxTheApp
->GetAppName() != wxT("")) 
 345         msgTitle 
= wxTheApp
->GetAppName(); 
 347         msgTitle 
= wxString(_("File error")); 
 349 #if wxUSE_STD_IOSTREAM 
 350     wxSTD ofstream 
store(file
.mb_str()); 
 351     if (store
.fail() || store
.bad()) 
 353     wxFileOutputStream 
store(file
); 
 354     if (store
.GetLastError() != wxSTREAM_NO_ERROR
) 
 357         (void)wxMessageBox(_("Sorry, could not open this file for saving."), msgTitle
, wxOK 
| wxICON_EXCLAMATION
, 
 358                            GetDocumentWindow()); 
 362     if (!SaveObject(store
)) 
 364         (void)wxMessageBox(_("Sorry, could not save this file."), msgTitle
, wxOK 
| wxICON_EXCLAMATION
, 
 365                            GetDocumentWindow()); 
 371     SetDocumentSaved(TRUE
); 
 373     wxFileName 
fn(file
) ; 
 374     fn
.MacSetDefaultTypeAndCreator() ; 
 379 bool wxDocument::OnOpenDocument(const wxString
& file
) 
 381     if (!OnSaveModified()) 
 385     if (wxTheApp
->GetAppName() != wxT("")) 
 386         msgTitle 
= wxTheApp
->GetAppName(); 
 388         msgTitle 
= wxString(_("File error")); 
 390 #if wxUSE_STD_IOSTREAM 
 391     wxSTD ifstream 
store(file
.mb_str()); 
 392     if (store
.fail() || store
.bad()) 
 394     wxFileInputStream 
store(file
); 
 395     if (store
.GetLastError() != wxSTREAM_NO_ERROR
) 
 398         (void)wxMessageBox(_("Sorry, could not open this file."), msgTitle
, wxOK
|wxICON_EXCLAMATION
, 
 399                            GetDocumentWindow()); 
 402 #if wxUSE_STD_IOSTREAM 
 404     if ( !store 
&& !store
.eof() ) 
 406     int res 
= LoadObject(store
).GetLastError(); 
 407     if ((res 
!= wxSTREAM_NO_ERROR
) && 
 408         (res 
!= wxSTREAM_EOF
)) 
 411         (void)wxMessageBox(_("Sorry, could not open this file."), msgTitle
, wxOK
|wxICON_EXCLAMATION
, 
 412                            GetDocumentWindow()); 
 415     SetFilename(file
, TRUE
); 
 424 #if wxUSE_STD_IOSTREAM 
 425 wxSTD istream
& wxDocument::LoadObject(wxSTD istream
& stream
) 
 427 wxInputStream
& wxDocument::LoadObject(wxInputStream
& stream
) 
 433 #if wxUSE_STD_IOSTREAM 
 434 wxSTD ostream
& wxDocument::SaveObject(wxSTD ostream
& stream
) 
 436 wxOutputStream
& wxDocument::SaveObject(wxOutputStream
& stream
) 
 442 bool wxDocument::Revert() 
 448 // Get title, or filename if no title, else unnamed 
 449 bool wxDocument::GetPrintableName(wxString
& buf
) const 
 451     if (m_documentTitle 
!= wxT("")) 
 453         buf 
= m_documentTitle
; 
 456     else if (m_documentFile 
!= wxT("")) 
 458         buf 
= wxFileNameFromPath(m_documentFile
); 
 468 wxWindow 
*wxDocument::GetDocumentWindow() const 
 470     wxView 
*view 
= GetFirstView(); 
 472         return view
->GetFrame(); 
 474         return wxTheApp
->GetTopWindow(); 
 477 wxCommandProcessor 
*wxDocument::OnCreateCommandProcessor() 
 479     return new wxCommandProcessor
; 
 482 // TRUE if safe to close 
 483 bool wxDocument::OnSaveModified() 
 488         GetPrintableName(title
); 
 491         if (wxTheApp
->GetAppName() != wxT("")) 
 492             msgTitle 
= wxTheApp
->GetAppName(); 
 494             msgTitle 
= wxString(_("Warning")); 
 497         prompt
.Printf(_("Do you want to save changes to document %s?"), 
 498                 (const wxChar 
*)title
); 
 499         int res 
= wxMessageBox(prompt
, msgTitle
, 
 500                 wxYES_NO
|wxCANCEL
|wxICON_QUESTION
, 
 501                 GetDocumentWindow()); 
 507         else if (res 
== wxYES
) 
 509         else if (res 
== wxCANCEL
) 
 515 bool wxDocument::Draw(wxDC
& WXUNUSED(context
)) 
 520 bool wxDocument::AddView(wxView 
*view
) 
 522     if (!m_documentViews
.Member(view
)) 
 524         m_documentViews
.Append(view
); 
 530 bool wxDocument::RemoveView(wxView 
*view
) 
 532     (void)m_documentViews
.DeleteObject(view
); 
 537 bool wxDocument::OnCreate(const wxString
& WXUNUSED(path
), long flags
) 
 539     if (GetDocumentTemplate()->CreateView(this, flags
)) 
 545 // Called after a view is added or removed. 
 546 // The default implementation deletes the document if 
 547 // there are no more views. 
 548 void wxDocument::OnChangedViewList() 
 550     if (m_documentViews
.GetCount() == 0) 
 552         if (OnSaveModified()) 
 559 void wxDocument::UpdateAllViews(wxView 
*sender
, wxObject 
*hint
) 
 561     wxList::compatibility_iterator node 
= m_documentViews
.GetFirst(); 
 564         wxView 
*view 
= (wxView 
*)node
->GetData(); 
 566             view
->OnUpdate(sender
, hint
); 
 567         node 
= node
->GetNext(); 
 571 void wxDocument::NotifyClosing() 
 573     wxList::compatibility_iterator node 
= m_documentViews
.GetFirst(); 
 576         wxView 
*view 
= (wxView 
*)node
->GetData(); 
 577         view
->OnClosingDocument(); 
 578         node 
= node
->GetNext(); 
 582 void wxDocument::SetFilename(const wxString
& filename
, bool notifyViews
) 
 584     m_documentFile 
= filename
; 
 587         // Notify the views that the filename has changed 
 588         wxList::compatibility_iterator node 
= m_documentViews
.GetFirst(); 
 591             wxView 
*view 
= (wxView 
*)node
->GetData(); 
 592             view
->OnChangeFilename(); 
 593             node 
= node
->GetNext(); 
 598 // ---------------------------------------------------------------------------- 
 600 // ---------------------------------------------------------------------------- 
 604     m_viewDocument 
= (wxDocument
*) NULL
; 
 606     m_viewFrame 
= (wxFrame 
*) NULL
; 
 611     GetDocumentManager()->ActivateView(this, FALSE
); 
 612     m_viewDocument
->RemoveView(this); 
 615 // Extend event processing to search the document's event table 
 616 bool wxView::ProcessEvent(wxEvent
& event
) 
 618     if ( !GetDocument() || !GetDocument()->ProcessEvent(event
) ) 
 619         return wxEvtHandler::ProcessEvent(event
); 
 624 void wxView::OnActivateView(bool WXUNUSED(activate
), wxView 
*WXUNUSED(activeView
), wxView 
*WXUNUSED(deactiveView
)) 
 628 void wxView::OnPrint(wxDC 
*dc
, wxObject 
*WXUNUSED(info
)) 
 633 void wxView::OnUpdate(wxView 
*WXUNUSED(sender
), wxObject 
*WXUNUSED(hint
)) 
 637 void wxView::OnChangeFilename() 
 639     if (GetFrame() && GetDocument()) 
 643         GetDocument()->GetPrintableName(title
); 
 645         GetFrame()->SetTitle(title
); 
 649 void wxView::SetDocument(wxDocument 
*doc
) 
 651     m_viewDocument 
= doc
; 
 656 bool wxView::Close(bool deleteWindow
) 
 658     if (OnClose(deleteWindow
)) 
 664 void wxView::Activate(bool activate
) 
 666     if (GetDocument() && GetDocumentManager()) 
 668         OnActivateView(activate
, this, GetDocumentManager()->GetCurrentView()); 
 669         GetDocumentManager()->ActivateView(this, activate
); 
 673 bool wxView::OnClose(bool WXUNUSED(deleteWindow
)) 
 675     return GetDocument() ? GetDocument()->Close() : TRUE
; 
 678 #if wxUSE_PRINTING_ARCHITECTURE 
 679 wxPrintout 
*wxView::OnCreatePrintout() 
 681     return new wxDocPrintout(this); 
 683 #endif // wxUSE_PRINTING_ARCHITECTURE 
 685 // ---------------------------------------------------------------------------- 
 687 // ---------------------------------------------------------------------------- 
 689 wxDocTemplate::wxDocTemplate(wxDocManager 
*manager
, 
 690                              const wxString
& descr
, 
 691                              const wxString
& filter
, 
 694                              const wxString
& docTypeName
, 
 695                              const wxString
& viewTypeName
, 
 696                              wxClassInfo 
*docClassInfo
, 
 697                              wxClassInfo 
*viewClassInfo
, 
 700     m_documentManager 
= manager
; 
 701     m_description 
= descr
; 
 704     m_fileFilter 
= filter
; 
 706     m_docTypeName 
= docTypeName
; 
 707     m_viewTypeName 
= viewTypeName
; 
 708     m_documentManager
->AssociateTemplate(this); 
 710     m_docClassInfo 
= docClassInfo
; 
 711     m_viewClassInfo 
= viewClassInfo
; 
 714 wxDocTemplate::~wxDocTemplate() 
 716     m_documentManager
->DisassociateTemplate(this); 
 719 // Tries to dynamically construct an object of the right class. 
 720 wxDocument 
*wxDocTemplate::CreateDocument(const wxString
& path
, long flags
) 
 723         return (wxDocument 
*) NULL
; 
 724     wxDocument 
*doc 
= (wxDocument 
*)m_docClassInfo
->CreateObject(); 
 726     if (InitDocument(doc
, path
, flags
)) 
 732         return (wxDocument 
*) NULL
; 
 736 bool wxDocTemplate::InitDocument(wxDocument
* doc
, const wxString
& path
, long flags
) 
 738     doc
->SetFilename(path
); 
 739     doc
->SetDocumentTemplate(this); 
 740     GetDocumentManager()->AddDocument(doc
); 
 741     doc
->SetCommandProcessor(doc
->OnCreateCommandProcessor()); 
 743     if (doc
->OnCreate(path
, flags
)) 
 747         if (GetDocumentManager()->GetDocuments().Member(doc
)) 
 748             doc
->DeleteAllViews(); 
 753 wxView 
*wxDocTemplate::CreateView(wxDocument 
*doc
, long flags
) 
 755     if (!m_viewClassInfo
) 
 756         return (wxView 
*) NULL
; 
 757     wxView 
*view 
= (wxView 
*)m_viewClassInfo
->CreateObject(); 
 758     view
->SetDocument(doc
); 
 759     if (view
->OnCreate(doc
, flags
)) 
 766         return (wxView 
*) NULL
; 
 770 // The default (very primitive) format detection: check is the extension is 
 771 // that of the template 
 772 bool wxDocTemplate::FileMatchesTemplate(const wxString
& path
) 
 774     return GetDefaultExtension().IsSameAs(FindExtension(path
)); 
 777 // ---------------------------------------------------------------------------- 
 779 // ---------------------------------------------------------------------------- 
 781 BEGIN_EVENT_TABLE(wxDocManager
, wxEvtHandler
) 
 782     EVT_MENU(wxID_OPEN
, wxDocManager::OnFileOpen
) 
 783     EVT_MENU(wxID_CLOSE
, wxDocManager::OnFileClose
) 
 784     EVT_MENU(wxID_CLOSE_ALL
, wxDocManager::OnFileCloseAll
) 
 785     EVT_MENU(wxID_REVERT
, wxDocManager::OnFileRevert
) 
 786     EVT_MENU(wxID_NEW
, wxDocManager::OnFileNew
) 
 787     EVT_MENU(wxID_SAVE
, wxDocManager::OnFileSave
) 
 788     EVT_MENU(wxID_SAVEAS
, wxDocManager::OnFileSaveAs
) 
 789     EVT_MENU(wxID_UNDO
, wxDocManager::OnUndo
) 
 790     EVT_MENU(wxID_REDO
, wxDocManager::OnRedo
) 
 792     EVT_UPDATE_UI(wxID_OPEN
, wxDocManager::OnUpdateFileOpen
) 
 793     EVT_UPDATE_UI(wxID_CLOSE
, wxDocManager::OnUpdateFileClose
) 
 794     EVT_UPDATE_UI(wxID_CLOSE_ALL
, wxDocManager::OnUpdateFileClose
) 
 795     EVT_UPDATE_UI(wxID_REVERT
, wxDocManager::OnUpdateFileRevert
) 
 796     EVT_UPDATE_UI(wxID_NEW
, wxDocManager::OnUpdateFileNew
) 
 797     EVT_UPDATE_UI(wxID_SAVE
, wxDocManager::OnUpdateFileSave
) 
 798     EVT_UPDATE_UI(wxID_SAVEAS
, wxDocManager::OnUpdateFileSaveAs
) 
 799     EVT_UPDATE_UI(wxID_UNDO
, wxDocManager::OnUpdateUndo
) 
 800     EVT_UPDATE_UI(wxID_REDO
, wxDocManager::OnUpdateRedo
) 
 802 #if wxUSE_PRINTING_ARCHITECTURE 
 803     EVT_MENU(wxID_PRINT
, wxDocManager::OnPrint
) 
 804     EVT_MENU(wxID_PRINT_SETUP
, wxDocManager::OnPrintSetup
) 
 805     EVT_MENU(wxID_PREVIEW
, wxDocManager::OnPreview
) 
 807     EVT_UPDATE_UI(wxID_PRINT
, wxDocManager::OnUpdatePrint
) 
 808     EVT_UPDATE_UI(wxID_PRINT_SETUP
, wxDocManager::OnUpdatePrintSetup
) 
 809     EVT_UPDATE_UI(wxID_PREVIEW
, wxDocManager::OnUpdatePreview
) 
 813 wxDocManager
* wxDocManager::sm_docManager 
= (wxDocManager
*) NULL
; 
 815 wxDocManager::wxDocManager(long flags
, bool initialize
) 
 817     m_defaultDocumentNameCounter 
= 1; 
 819     m_currentView 
= (wxView 
*) NULL
; 
 820     m_maxDocsOpen 
= 10000; 
 821     m_fileHistory 
= (wxFileHistory 
*) NULL
; 
 824     sm_docManager 
= this; 
 827 wxDocManager::~wxDocManager() 
 831         delete m_fileHistory
; 
 832     sm_docManager 
= (wxDocManager
*) NULL
; 
 835 // closes the specified document 
 836 bool wxDocManager::CloseDocument(wxDocument
* doc
, bool force
) 
 838     if (doc
->Close() || force
) 
 840         // Implicitly deletes the document when 
 841         // the last view is deleted 
 842         doc
->DeleteAllViews(); 
 844         // Check we're really deleted 
 845         if (m_docs
.Member(doc
)) 
 853 bool wxDocManager::CloseDocuments(bool force
) 
 855     wxList::compatibility_iterator node 
= m_docs
.GetFirst(); 
 858         wxDocument 
*doc 
= (wxDocument 
*)node
->GetData(); 
 859         wxList::compatibility_iterator next 
= node
->GetNext(); 
 861         if (!CloseDocument(doc
, force
)) 
 864         // This assumes that documents are not connected in 
 865         // any way, i.e. deleting one document does NOT 
 872 bool wxDocManager::Clear(bool force
) 
 874     if (!CloseDocuments(force
)) 
 877     wxList::compatibility_iterator node 
= m_templates
.GetFirst(); 
 880         wxDocTemplate 
*templ 
= (wxDocTemplate
*) node
->GetData(); 
 881         wxList::compatibility_iterator next 
= node
->GetNext(); 
 888 bool wxDocManager::Initialize() 
 890     m_fileHistory 
= OnCreateFileHistory(); 
 894 wxFileHistory 
*wxDocManager::OnCreateFileHistory() 
 896     return new wxFileHistory
; 
 899 void wxDocManager::OnFileClose(wxCommandEvent
& WXUNUSED(event
)) 
 901     wxDocument 
*doc 
= GetCurrentDocument(); 
 906         doc
->DeleteAllViews(); 
 907         if (m_docs
.Member(doc
)) 
 912 void wxDocManager::OnFileCloseAll(wxCommandEvent
& WXUNUSED(event
)) 
 914     CloseDocuments(FALSE
); 
 917 void wxDocManager::OnFileNew(wxCommandEvent
& WXUNUSED(event
)) 
 919     CreateDocument( wxT(""), wxDOC_NEW 
); 
 922 void wxDocManager::OnFileOpen(wxCommandEvent
& WXUNUSED(event
)) 
 924     if ( !CreateDocument( wxT(""), 0) ) 
 930 void wxDocManager::OnFileRevert(wxCommandEvent
& WXUNUSED(event
)) 
 932     wxDocument 
*doc 
= GetCurrentDocument(); 
 938 void wxDocManager::OnFileSave(wxCommandEvent
& WXUNUSED(event
)) 
 940     wxDocument 
*doc 
= GetCurrentDocument(); 
 946 void wxDocManager::OnFileSaveAs(wxCommandEvent
& WXUNUSED(event
)) 
 948     wxDocument 
*doc 
= GetCurrentDocument(); 
 954 void wxDocManager::OnPrint(wxCommandEvent
& WXUNUSED(event
)) 
 956 #if wxUSE_PRINTING_ARCHITECTURE 
 957     wxView 
*view 
= GetCurrentView(); 
 961     wxPrintout 
*printout 
= view
->OnCreatePrintout(); 
 965         printer
.Print(view
->GetFrame(), printout
, TRUE
); 
 969 #endif // wxUSE_PRINTING_ARCHITECTURE 
 972 void wxDocManager::OnPrintSetup(wxCommandEvent
& WXUNUSED(event
)) 
 974 #if wxUSE_PRINTING_ARCHITECTURE 
 975     wxWindow 
*parentWin 
= wxTheApp
->GetTopWindow(); 
 976     wxView 
*view 
= GetCurrentView(); 
 978         parentWin 
= view
->GetFrame(); 
 980     wxPrintDialogData data
; 
 982     wxPrintDialog 
printerDialog(parentWin
, &data
); 
 983     printerDialog
.GetPrintDialogData().SetSetupDialog(TRUE
); 
 984     printerDialog
.ShowModal(); 
 985 #endif // wxUSE_PRINTING_ARCHITECTURE 
 988 void wxDocManager::OnPreview(wxCommandEvent
& WXUNUSED(event
)) 
 990 #if wxUSE_PRINTING_ARCHITECTURE 
 991     wxView 
*view 
= GetCurrentView(); 
 995     wxPrintout 
*printout 
= view
->OnCreatePrintout(); 
 998         // Pass two printout objects: for preview, and possible printing. 
 999         wxPrintPreviewBase 
*preview 
= new wxPrintPreview(printout
, view
->OnCreatePrintout()); 
1000         if ( !preview
->Ok() ) 
1003             wxMessageBox( _("Sorry, print preview needs a printer to be installed.") ); 
1007         wxPreviewFrame 
*frame 
= new wxPreviewFrame(preview
, (wxFrame 
*)wxTheApp
->GetTopWindow(), _("Print Preview"), 
1008                 wxPoint(100, 100), wxSize(600, 650)); 
1009         frame
->Centre(wxBOTH
); 
1010         frame
->Initialize(); 
1013 #endif // wxUSE_PRINTING_ARCHITECTURE 
1016 void wxDocManager::OnUndo(wxCommandEvent
& event
) 
1018     wxDocument 
*doc 
= GetCurrentDocument(); 
1021     if (doc
->GetCommandProcessor()) 
1022         doc
->GetCommandProcessor()->Undo(); 
1027 void wxDocManager::OnRedo(wxCommandEvent
& event
) 
1029     wxDocument 
*doc 
= GetCurrentDocument(); 
1032     if (doc
->GetCommandProcessor()) 
1033         doc
->GetCommandProcessor()->Redo(); 
1038 // Handlers for UI update commands 
1040 void wxDocManager::OnUpdateFileOpen(wxUpdateUIEvent
& event
) 
1042     event
.Enable( TRUE 
); 
1045 void wxDocManager::OnUpdateFileClose(wxUpdateUIEvent
& event
) 
1047     wxDocument 
*doc 
= GetCurrentDocument(); 
1048     event
.Enable( (doc 
!= (wxDocument
*) NULL
) ); 
1051 void wxDocManager::OnUpdateFileRevert(wxUpdateUIEvent
& event
) 
1053     wxDocument 
*doc 
= GetCurrentDocument(); 
1054     event
.Enable( (doc 
!= (wxDocument
*) NULL
) ); 
1057 void wxDocManager::OnUpdateFileNew(wxUpdateUIEvent
& event
) 
1059     event
.Enable( TRUE 
); 
1062 void wxDocManager::OnUpdateFileSave(wxUpdateUIEvent
& event
) 
1064     wxDocument 
*doc 
= GetCurrentDocument(); 
1065     event
.Enable( doc 
&& doc
->IsModified() ); 
1068 void wxDocManager::OnUpdateFileSaveAs(wxUpdateUIEvent
& event
) 
1070     wxDocument 
*doc 
= GetCurrentDocument(); 
1071     event
.Enable( (doc 
!= (wxDocument
*) NULL
) ); 
1074 void wxDocManager::OnUpdateUndo(wxUpdateUIEvent
& event
) 
1076     wxDocument 
*doc 
= GetCurrentDocument(); 
1078         event
.Enable(FALSE
); 
1079     else if (!doc
->GetCommandProcessor()) 
1083         event
.Enable( doc
->GetCommandProcessor()->CanUndo() ); 
1084         doc
->GetCommandProcessor()->SetMenuStrings(); 
1088 void wxDocManager::OnUpdateRedo(wxUpdateUIEvent
& event
) 
1090     wxDocument 
*doc 
= GetCurrentDocument(); 
1092         event
.Enable(FALSE
); 
1093     else if (!doc
->GetCommandProcessor()) 
1097         event
.Enable( doc
->GetCommandProcessor()->CanRedo() ); 
1098         doc
->GetCommandProcessor()->SetMenuStrings(); 
1102 void wxDocManager::OnUpdatePrint(wxUpdateUIEvent
& event
) 
1104     wxDocument 
*doc 
= GetCurrentDocument(); 
1105     event
.Enable( (doc 
!= (wxDocument
*) NULL
) ); 
1108 void wxDocManager::OnUpdatePrintSetup(wxUpdateUIEvent
& event
) 
1110     event
.Enable( TRUE 
); 
1113 void wxDocManager::OnUpdatePreview(wxUpdateUIEvent
& event
) 
1115     wxDocument 
*doc 
= GetCurrentDocument(); 
1116     event
.Enable( (doc 
!= (wxDocument
*) NULL
) ); 
1119 wxView 
*wxDocManager::GetCurrentView() const 
1122         return m_currentView
; 
1123     if (m_docs
.GetCount() == 1) 
1125         wxDocument
* doc 
= (wxDocument
*) m_docs
.GetFirst()->GetData(); 
1126         return doc
->GetFirstView(); 
1128     return (wxView 
*) NULL
; 
1131 // Extend event processing to search the view's event table 
1132 bool wxDocManager::ProcessEvent(wxEvent
& event
) 
1134     wxView
* view 
= GetCurrentView(); 
1137         if (view
->ProcessEvent(event
)) 
1140     return wxEvtHandler::ProcessEvent(event
); 
1143 wxDocument 
*wxDocManager::CreateDocument(const wxString
& path
, long flags
) 
1145     wxDocTemplate   
**templates 
= new wxDocTemplate 
*[m_templates
.GetCount()]; 
1148     for (size_t i 
= 0; i 
< m_templates
.GetCount(); i
++) 
1150         wxDocTemplate 
*temp 
= (wxDocTemplate 
*)(m_templates
.Item(i
)->GetData()); 
1151         if (temp
->IsVisible()) 
1153             templates
[n
] = temp
; 
1160         return (wxDocument 
*) NULL
; 
1163     wxDocument
* docToClose 
= NULL
; 
1165     // If we've reached the max number of docs, close the 
1167     if ( (int)GetDocuments().GetCount() >= m_maxDocsOpen 
) 
1169         wxDocument 
*doc 
= (wxDocument 
*)GetDocuments().GetFirst()->GetData(); 
1173     // New document: user chooses a template, unless there's only one. 
1174     if (flags 
& wxDOC_NEW
) 
1180                 if (!CloseDocument(docToClose
, FALSE
)) 
1187             wxDocTemplate 
*temp 
= templates
[0]; 
1189             wxDocument 
*newDoc 
= temp
->CreateDocument(path
, flags
); 
1193                 newDoc
->SetDocumentName(temp
->GetDocumentName()); 
1194                 newDoc
->SetDocumentTemplate(temp
); 
1195                 newDoc
->OnNewDocument(); 
1200         wxDocTemplate 
*temp 
= SelectDocumentType(templates
, n
); 
1206                 if (!CloseDocument(docToClose
, FALSE
)) 
1212             wxDocument 
*newDoc 
= temp
->CreateDocument(path
, flags
); 
1216                 newDoc
->SetDocumentName(temp
->GetDocumentName()); 
1217                 newDoc
->SetDocumentTemplate(temp
); 
1218                 newDoc
->OnNewDocument(); 
1223             return (wxDocument 
*) NULL
; 
1226     // Existing document 
1227     wxDocTemplate 
*temp
; 
1229     wxString 
path2(wxT("")); 
1230     if (path 
!= wxT("")) 
1233     if (flags 
& wxDOC_SILENT
) 
1235         temp 
= FindTemplateForPath(path2
); 
1238             // Since we do not add files with non-default extensions to the FileHistory this 
1239             // can only happen if the application changes the allowed templates in runtime. 
1240             (void)wxMessageBox(_("Sorry, the format for this file is unknown."), 
1242                                wxOK 
| wxICON_EXCLAMATION
, wxFindSuitableParent()); 
1246         temp 
= SelectDocumentPath(templates
, n
, path2
, flags
); 
1254             if (!CloseDocument(docToClose
, FALSE
)) 
1260         wxDocument 
*newDoc 
= temp
->CreateDocument(path2
, flags
); 
1263             newDoc
->SetDocumentName(temp
->GetDocumentName()); 
1264             newDoc
->SetDocumentTemplate(temp
); 
1265             if (!newDoc
->OnOpenDocument(path2
)) 
1267                 newDoc
->DeleteAllViews(); 
1268                 // delete newDoc; // Implicitly deleted by DeleteAllViews 
1269                 return (wxDocument 
*) NULL
; 
1271             // A file that doesn't use the default extension of its document 
1272             // template cannot be opened via the FileHistory, so we do not 
1274             if (temp
->FileMatchesTemplate(path2
)) 
1275                 AddFileToHistory(path2
); 
1280     return (wxDocument 
*) NULL
; 
1283 wxView 
*wxDocManager::CreateView(wxDocument 
*doc
, long flags
) 
1285     wxDocTemplate   
**templates 
= new wxDocTemplate 
*[m_templates
.GetCount()]; 
1288     for (size_t i 
= 0; i 
< m_templates
.GetCount(); i
++) 
1290         wxDocTemplate 
*temp 
= (wxDocTemplate 
*)(m_templates
.Item(i
)->GetData()); 
1291         if (temp
->IsVisible()) 
1293             if (temp
->GetDocumentName() == doc
->GetDocumentName()) 
1295                 templates
[n
] = temp
; 
1303         return (wxView 
*) NULL
; 
1307         wxDocTemplate 
*temp 
= templates
[0]; 
1309         wxView 
*view 
= temp
->CreateView(doc
, flags
); 
1311             view
->SetViewName(temp
->GetViewName()); 
1315     wxDocTemplate 
*temp 
= SelectViewType(templates
, n
); 
1319         wxView 
*view 
= temp
->CreateView(doc
, flags
); 
1321             view
->SetViewName(temp
->GetViewName()); 
1325         return (wxView 
*) NULL
; 
1328 // Not yet implemented 
1329 void wxDocManager::DeleteTemplate(wxDocTemplate 
*WXUNUSED(temp
), long WXUNUSED(flags
)) 
1333 // Not yet implemented 
1334 bool wxDocManager::FlushDoc(wxDocument 
*WXUNUSED(doc
)) 
1339 wxDocument 
*wxDocManager::GetCurrentDocument() const 
1341     wxView 
*view 
= GetCurrentView(); 
1343         return view
->GetDocument(); 
1345         return (wxDocument 
*) NULL
; 
1348 // Make a default document name 
1349 bool wxDocManager::MakeDefaultName(wxString
& name
) 
1351     name
.Printf(_("unnamed%d"), m_defaultDocumentNameCounter
); 
1352     m_defaultDocumentNameCounter
++; 
1357 // Make a frame title (override this to do something different) 
1358 // If docName is empty, a document is not currently active. 
1359 wxString 
wxDocManager::MakeFrameTitle(wxDocument
* doc
) 
1361     wxString appName 
= wxTheApp
->GetAppName(); 
1368         doc
->GetPrintableName(docName
); 
1369         title 
= docName 
+ wxString(_(" - ")) + appName
; 
1375 // Not yet implemented 
1376 wxDocTemplate 
*wxDocManager::MatchTemplate(const wxString
& WXUNUSED(path
)) 
1378     return (wxDocTemplate 
*) NULL
; 
1381 // File history management 
1382 void wxDocManager::AddFileToHistory(const wxString
& file
) 
1385         m_fileHistory
->AddFileToHistory(file
); 
1388 void wxDocManager::RemoveFileFromHistory(size_t i
) 
1391         m_fileHistory
->RemoveFileFromHistory(i
); 
1394 wxString 
wxDocManager::GetHistoryFile(size_t i
) const 
1399         histFile 
= m_fileHistory
->GetHistoryFile(i
); 
1404 void wxDocManager::FileHistoryUseMenu(wxMenu 
*menu
) 
1407         m_fileHistory
->UseMenu(menu
); 
1410 void wxDocManager::FileHistoryRemoveMenu(wxMenu 
*menu
) 
1413         m_fileHistory
->RemoveMenu(menu
); 
1417 void wxDocManager::FileHistoryLoad(wxConfigBase
& config
) 
1420         m_fileHistory
->Load(config
); 
1423 void wxDocManager::FileHistorySave(wxConfigBase
& config
) 
1426         m_fileHistory
->Save(config
); 
1430 void wxDocManager::FileHistoryAddFilesToMenu(wxMenu
* menu
) 
1433         m_fileHistory
->AddFilesToMenu(menu
); 
1436 void wxDocManager::FileHistoryAddFilesToMenu() 
1439         m_fileHistory
->AddFilesToMenu(); 
1442 size_t wxDocManager::GetHistoryFilesCount() const 
1444     return m_fileHistory 
? m_fileHistory
->GetCount() : 0; 
1448 // Find out the document template via matching in the document file format 
1449 // against that of the template 
1450 wxDocTemplate 
*wxDocManager::FindTemplateForPath(const wxString
& path
) 
1452     wxDocTemplate 
*theTemplate 
= (wxDocTemplate 
*) NULL
; 
1454     // Find the template which this extension corresponds to 
1455     for (size_t i 
= 0; i 
< m_templates
.GetCount(); i
++) 
1457         wxDocTemplate 
*temp 
= (wxDocTemplate 
*)m_templates
.Item(i
)->GetData(); 
1458         if ( temp
->FileMatchesTemplate(path
) ) 
1467 // Try to get a more suitable parent frame than the top window, 
1468 // for selection dialogs. Otherwise you may get an unexpected 
1469 // window being activated when a dialog is shown. 
1470 static wxWindow
* wxFindSuitableParent() 
1472     wxWindow
* parent 
= wxTheApp
->GetTopWindow(); 
1474     wxWindow
* focusWindow 
= wxWindow::FindFocus(); 
1477         while (focusWindow 
&& 
1478                 !focusWindow
->IsKindOf(CLASSINFO(wxDialog
)) && 
1479                 !focusWindow
->IsKindOf(CLASSINFO(wxFrame
))) 
1481             focusWindow 
= focusWindow
->GetParent(); 
1484             parent 
= focusWindow
; 
1489 // Prompts user to open a file, using file specs in templates. 
1490 // Must extend the file selector dialog or implement own; OR 
1491 // match the extension to the template extension. 
1493 wxDocTemplate 
*wxDocManager::SelectDocumentPath(wxDocTemplate 
**templates
, 
1494 #if defined(__WXMSW__) || defined(__WXGTK__) || defined(__WXMAC__) 
1497                                                 int WXUNUSED(noTemplates
), 
1500                                                 long WXUNUSED(flags
), 
1501                                                 bool WXUNUSED(save
)) 
1503     // We can only have multiple filters in Windows and GTK 
1504 #if defined(__WXMSW__) || defined(__WXGTK__) || defined(__WXMAC__) 
1508     for (i 
= 0; i 
< noTemplates
; i
++) 
1510         if (templates
[i
]->IsVisible()) 
1512             // add a '|' to separate this filter from the previous one 
1513             if ( !descrBuf
.IsEmpty() ) 
1514                 descrBuf 
<< wxT('|'); 
1516             descrBuf 
<< templates
[i
]->GetDescription() 
1517                 << wxT(" (") << templates
[i
]->GetFileFilter() << wxT(") |") 
1518                 << templates
[i
]->GetFileFilter(); 
1522     wxString descrBuf 
= wxT("*.*"); 
1525     int FilterIndex 
= -1; 
1527     wxWindow
* parent 
= wxFindSuitableParent(); 
1529     wxString pathTmp 
= wxFileSelectorEx(_("Select a file"), 
1537     wxDocTemplate 
*theTemplate 
= (wxDocTemplate 
*)NULL
; 
1538     if (!pathTmp
.IsEmpty()) 
1540         if (!wxFileExists(pathTmp
)) 
1543             if (!wxTheApp
->GetAppName().IsEmpty()) 
1544                 msgTitle 
= wxTheApp
->GetAppName(); 
1546                 msgTitle 
= wxString(_("File error")); 
1548             (void)wxMessageBox(_("Sorry, could not open this file."), msgTitle
, wxOK 
| wxICON_EXCLAMATION
, 
1552             return (wxDocTemplate 
*) NULL
; 
1554         m_lastDirectory 
= wxPathOnly(pathTmp
); 
1558         // first choose the template using the extension, if this fails (i.e. 
1559         // wxFileSelectorEx() didn't fill it), then use the path 
1560         if ( FilterIndex 
!= -1 ) 
1561             theTemplate 
= templates
[FilterIndex
]; 
1563             theTemplate 
= FindTemplateForPath(path
); 
1566             // Since we do not add files with non-default extensions to the FileHistory this 
1567             // can only happen if the application changes the allowed templates in runtime. 
1568             (void)wxMessageBox(_("Sorry, the format for this file is unknown."), 
1570                                 wxOK 
| wxICON_EXCLAMATION
, wxFindSuitableParent()); 
1581 wxDocTemplate 
*wxDocManager::SelectDocumentType(wxDocTemplate 
**templates
, 
1582                                                 int noTemplates
, bool sort
) 
1584     wxArrayString strings
; 
1585     wxDocTemplate 
**data 
= new wxDocTemplate 
*[noTemplates
]; 
1589     for (i 
= 0; i 
< noTemplates
; i
++) 
1591         if (templates
[i
]->IsVisible()) 
1595             for (j 
= 0; j 
< n
; j
++) 
1597                 //filter out NOT unique documents + view combinations 
1598                 if ( templates
[i
]->m_docTypeName 
== data
[j
]->m_docTypeName 
&& 
1599                      templates
[i
]->m_viewTypeName 
== data
[j
]->m_viewTypeName
 
1606                 strings
.Add(templates
[i
]->m_description
); 
1608                 data
[n
] = templates
[i
]; 
1616         strings
.Sort(); // ascending sort 
1617         // Yes, this will be slow, but template lists 
1618         // are typically short. 
1620         n 
= strings
.Count(); 
1621         for (i 
= 0; i 
< n
; i
++) 
1623             for (j 
= 0; j 
< noTemplates
; j
++) 
1625                 if (strings
[i
] == templates
[j
]->m_description
) 
1626                     data
[i
] = templates
[j
]; 
1631     wxDocTemplate 
*theTemplate
; 
1636             // no visible templates, hence nothing to choose from 
1641             // don't propose the user to choose if he heas no choice 
1642             theTemplate 
= data
[0]; 
1646             // propose the user to choose one of several 
1647             theTemplate 
= (wxDocTemplate 
*)wxGetSingleChoiceData
 
1649                             _("Select a document template"), 
1653                             wxFindSuitableParent() 
1662 wxDocTemplate 
*wxDocManager::SelectViewType(wxDocTemplate 
**templates
, 
1663                                             int noTemplates
, bool sort
) 
1665     wxArrayString strings
; 
1666     wxDocTemplate 
**data 
= new wxDocTemplate 
*[noTemplates
]; 
1670     for (i 
= 0; i 
< noTemplates
; i
++) 
1672         wxDocTemplate 
*templ 
= templates
[i
]; 
1673         if ( templ
->IsVisible() && !templ
->GetViewName().empty() ) 
1677             for (j 
= 0; j 
< n
; j
++) 
1679                 //filter out NOT unique views 
1680                 if ( templates
[i
]->m_viewTypeName 
== data
[j
]->m_viewTypeName 
) 
1686                 strings
.Add(templ
->m_viewTypeName
); 
1695         strings
.Sort(); // ascending sort 
1696         // Yes, this will be slow, but template lists 
1697         // are typically short. 
1699         n 
= strings
.Count(); 
1700         for (i 
= 0; i 
< n
; i
++) 
1702             for (j 
= 0; j 
< noTemplates
; j
++) 
1704                 if (strings
[i
] == templates
[j
]->m_viewTypeName
) 
1705                     data
[i
] = templates
[j
]; 
1710     wxDocTemplate 
*theTemplate
; 
1712     // the same logic as above 
1716             theTemplate 
= (wxDocTemplate 
*)NULL
; 
1720             theTemplate 
= data
[0]; 
1724             theTemplate 
= (wxDocTemplate 
*)wxGetSingleChoiceData
 
1726                             _("Select a document view"), 
1730                             wxFindSuitableParent() 
1739 void wxDocManager::AssociateTemplate(wxDocTemplate 
*temp
) 
1741     if (!m_templates
.Member(temp
)) 
1742         m_templates
.Append(temp
); 
1745 void wxDocManager::DisassociateTemplate(wxDocTemplate 
*temp
) 
1747     m_templates
.DeleteObject(temp
); 
1750 // Add and remove a document from the manager's list 
1751 void wxDocManager::AddDocument(wxDocument 
*doc
) 
1753     if (!m_docs
.Member(doc
)) 
1757 void wxDocManager::RemoveDocument(wxDocument 
*doc
) 
1759     m_docs
.DeleteObject(doc
); 
1762 // Views or windows should inform the document manager 
1763 // when a view is going in or out of focus 
1764 void wxDocManager::ActivateView(wxView 
*view
, bool activate
) 
1768         m_currentView 
= view
; 
1772         if ( m_currentView 
== view 
) 
1774             // don't keep stale pointer 
1775             m_currentView 
= (wxView 
*) NULL
; 
1780 // ---------------------------------------------------------------------------- 
1781 // Default document child frame 
1782 // ---------------------------------------------------------------------------- 
1784 BEGIN_EVENT_TABLE(wxDocChildFrame
, wxFrame
) 
1785     EVT_ACTIVATE(wxDocChildFrame::OnActivate
) 
1786     EVT_CLOSE(wxDocChildFrame::OnCloseWindow
) 
1789 wxDocChildFrame::wxDocChildFrame(wxDocument 
*doc
, 
1793                                  const wxString
& title
, 
1797                                  const wxString
& name
) 
1798                : wxFrame(frame
, id
, title
, pos
, size
, style
, name
) 
1800     m_childDocument 
= doc
; 
1803         view
->SetFrame(this); 
1806 wxDocChildFrame::~wxDocChildFrame() 
1810 // Extend event processing to search the view's event table 
1811 bool wxDocChildFrame::ProcessEvent(wxEvent
& event
) 
1814         m_childView
->Activate(TRUE
); 
1816     if ( !m_childView 
|| ! m_childView
->ProcessEvent(event
) ) 
1818         // Only hand up to the parent if it's a menu command 
1819         if (!event
.IsKindOf(CLASSINFO(wxCommandEvent
)) || !GetParent() || !GetParent()->ProcessEvent(event
)) 
1820             return wxEvtHandler::ProcessEvent(event
); 
1828 void wxDocChildFrame::OnActivate(wxActivateEvent
& event
) 
1830     wxFrame::OnActivate(event
); 
1833         m_childView
->Activate(event
.GetActive()); 
1836 void wxDocChildFrame::OnCloseWindow(wxCloseEvent
& event
) 
1840         bool ans 
= event
.CanVeto() 
1841                     ? m_childView
->Close(FALSE
) // FALSE means don't delete associated window 
1842                     : TRUE
; // Must delete. 
1846             m_childView
->Activate(FALSE
); 
1848             m_childView 
= (wxView 
*) NULL
; 
1849             m_childDocument 
= (wxDocument 
*) NULL
; 
1860 // ---------------------------------------------------------------------------- 
1861 // Default parent frame 
1862 // ---------------------------------------------------------------------------- 
1864 BEGIN_EVENT_TABLE(wxDocParentFrame
, wxFrame
) 
1865     EVT_MENU(wxID_EXIT
, wxDocParentFrame::OnExit
) 
1866     EVT_MENU_RANGE(wxID_FILE1
, wxID_FILE9
, wxDocParentFrame::OnMRUFile
) 
1867     EVT_CLOSE(wxDocParentFrame::OnCloseWindow
) 
1870 wxDocParentFrame::wxDocParentFrame(wxDocManager 
*manager
, 
1873                                    const wxString
& title
, 
1877                                    const wxString
& name
) 
1878                 : wxFrame(frame
, id
, title
, pos
, size
, style
, name
) 
1880     m_docManager 
= manager
; 
1883 void wxDocParentFrame::OnExit(wxCommandEvent
& WXUNUSED(event
)) 
1888 void wxDocParentFrame::OnMRUFile(wxCommandEvent
& event
) 
1890     int n 
= event
.GetId() - wxID_FILE1
;  // the index in MRU list 
1891     wxString 
filename(m_docManager
->GetHistoryFile(n
)); 
1892     if ( !filename
.IsEmpty() ) 
1894         // verify that the file exists before doing anything else 
1895         if ( wxFile::Exists(filename
) ) 
1898             if (!m_docManager
->CreateDocument(filename
, wxDOC_SILENT
)) 
1900                 // remove the file from the MRU list. The user should already be notified. 
1901                 m_docManager
->RemoveFileFromHistory(n
); 
1903                 wxLogError(_("The file '%s' couldn't be opened.\nIt has been removed from the most recently used files list."), 
1909             // remove the bogus filename from the MRU list and notify the user 
1911             m_docManager
->RemoveFileFromHistory(n
); 
1913             wxLogError(_("The file '%s' doesn't exist and couldn't be opened.\nIt has been removed from the most recently used files list."), 
1919 // Extend event processing to search the view's event table 
1920 bool wxDocParentFrame::ProcessEvent(wxEvent
& event
) 
1922     // Try the document manager, then do default processing 
1923     if (!m_docManager 
|| !m_docManager
->ProcessEvent(event
)) 
1924         return wxEvtHandler::ProcessEvent(event
); 
1929 // Define the behaviour for the frame closing 
1930 // - must delete all frames except for the main one. 
1931 void wxDocParentFrame::OnCloseWindow(wxCloseEvent
& event
) 
1933     if (m_docManager
->Clear(!event
.CanVeto())) 
1941 #if wxUSE_PRINTING_ARCHITECTURE 
1943 wxDocPrintout::wxDocPrintout(wxView 
*view
, const wxString
& title
) 
1946     m_printoutView 
= view
; 
1949 bool wxDocPrintout::OnPrintPage(int WXUNUSED(page
)) 
1953     // Get the logical pixels per inch of screen and printer 
1954     int ppiScreenX
, ppiScreenY
; 
1955     GetPPIScreen(&ppiScreenX
, &ppiScreenY
); 
1956     wxUnusedVar(ppiScreenY
); 
1957     int ppiPrinterX
, ppiPrinterY
; 
1958     GetPPIPrinter(&ppiPrinterX
, &ppiPrinterY
); 
1959     wxUnusedVar(ppiPrinterY
); 
1961     // This scales the DC so that the printout roughly represents the 
1962     // the screen scaling. The text point size _should_ be the right size 
1963     // but in fact is too small for some reason. This is a detail that will 
1964     // need to be addressed at some point but can be fudged for the 
1966     float scale 
= (float)((float)ppiPrinterX
/(float)ppiScreenX
); 
1968     // Now we have to check in case our real page size is reduced 
1969     // (e.g. because we're drawing to a print preview memory DC) 
1970     int pageWidth
, pageHeight
; 
1972     dc
->GetSize(&w
, &h
); 
1973     GetPageSizePixels(&pageWidth
, &pageHeight
); 
1974     wxUnusedVar(pageHeight
); 
1976     // If printer pageWidth == current DC width, then this doesn't 
1977     // change. But w might be the preview bitmap width, so scale down. 
1978     float overallScale 
= scale 
* (float)(w
/(float)pageWidth
); 
1979     dc
->SetUserScale(overallScale
, overallScale
); 
1983         m_printoutView
->OnDraw(dc
); 
1988 bool wxDocPrintout::HasPage(int pageNum
) 
1990     return (pageNum 
== 1); 
1993 bool wxDocPrintout::OnBeginDocument(int startPage
, int endPage
) 
1995     if (!wxPrintout::OnBeginDocument(startPage
, endPage
)) 
2001 void wxDocPrintout::GetPageInfo(int *minPage
, int *maxPage
, int *selPageFrom
, int *selPageTo
) 
2009 #endif // wxUSE_PRINTING_ARCHITECTURE 
2011 // ---------------------------------------------------------------------------- 
2012 // File history processor 
2013 // ---------------------------------------------------------------------------- 
2015 static inline wxChar
* MYcopystring(const wxString
& s
) 
2017     wxChar
* copy 
= new wxChar
[s
.length() + 1]; 
2018     return wxStrcpy(copy
, s
.c_str()); 
2021 static inline wxChar
* MYcopystring(const wxChar
* s
) 
2023     wxChar
* copy 
= new wxChar
[wxStrlen(s
) + 1]; 
2024     return wxStrcpy(copy
, s
); 
2027 wxFileHistory::wxFileHistory(size_t maxFiles
, wxWindowID idBase
) 
2029     m_fileMaxFiles 
= maxFiles
; 
2032     m_fileHistory 
= new wxChar 
*[m_fileMaxFiles
]; 
2035 wxFileHistory::~wxFileHistory() 
2038     for (i 
= 0; i 
< m_fileHistoryN
; i
++) 
2039         delete[] m_fileHistory
[i
]; 
2040     delete[] m_fileHistory
; 
2043 // File history management 
2044 void wxFileHistory::AddFileToHistory(const wxString
& file
) 
2048     // Check we don't already have this file 
2049     for (i 
= 0; i 
< m_fileHistoryN
; i
++) 
2051 #if defined( __WXMSW__ ) // Add any other OSes with case insensitive file names 
2052         wxString testString
; 
2053         if ( m_fileHistory
[i
] ) 
2054             testString 
= m_fileHistory
[i
]; 
2055         if ( m_fileHistory
[i
] && ( file
.Lower() == testString
.Lower() ) ) 
2057         if ( m_fileHistory
[i
] && ( file 
== m_fileHistory
[i
] ) ) 
2060             // we do have it, move it to the top of the history 
2061             RemoveFileFromHistory (i
); 
2062             AddFileToHistory (file
); 
2067     // if we already have a full history, delete the one at the end 
2068     if ( m_fileMaxFiles 
== m_fileHistoryN 
) 
2070         RemoveFileFromHistory (m_fileHistoryN 
- 1); 
2071         AddFileToHistory (file
); 
2075     // Add to the project file history: 
2076     // Move existing files (if any) down so we can insert file at beginning. 
2077     if (m_fileHistoryN 
< m_fileMaxFiles
) 
2079         wxList::compatibility_iterator node 
= m_fileMenus
.GetFirst(); 
2082             wxMenu
* menu 
= (wxMenu
*) node
->GetData(); 
2083             if ( m_fileHistoryN 
== 0 && menu
->GetMenuItemCount() ) 
2085                 menu
->AppendSeparator(); 
2087             menu
->Append(m_idBase
+m_fileHistoryN
, _("[EMPTY]")); 
2088             node 
= node
->GetNext(); 
2092     // Shuffle filenames down 
2093     for (i 
= (m_fileHistoryN
-1); i 
> 0; i
--) 
2095         m_fileHistory
[i
] = m_fileHistory
[i
-1]; 
2097     m_fileHistory
[0] = MYcopystring(file
); 
2099     // this is the directory of the last opened file 
2100     wxString pathCurrent
; 
2101     wxSplitPath( m_fileHistory
[0], &pathCurrent
, NULL
, NULL 
); 
2102     for (i 
= 0; i 
< m_fileHistoryN
; i
++) 
2104         if ( m_fileHistory
[i
] ) 
2106             // if in same directory just show the filename; otherwise the full 
2108             wxString pathInMenu
, path
, filename
, ext
; 
2109             wxSplitPath( m_fileHistory
[i
], &path
, &filename
, &ext 
); 
2110             if ( path 
== pathCurrent 
) 
2112                 pathInMenu 
= filename
; 
2114                     pathInMenu 
= pathInMenu 
+ wxFILE_SEP_EXT 
+ ext
; 
2118                 // absolute path; could also set relative path 
2119                 pathInMenu 
= m_fileHistory
[i
]; 
2123             buf
.Printf(s_MRUEntryFormat
, i 
+ 1, pathInMenu
.c_str()); 
2124             wxList::compatibility_iterator node 
= m_fileMenus
.GetFirst(); 
2127                 wxMenu
* menu 
= (wxMenu
*) node
->GetData(); 
2128                 menu
->SetLabel(m_idBase 
+ i
, buf
); 
2129                 node 
= node
->GetNext(); 
2135 void wxFileHistory::RemoveFileFromHistory(size_t i
) 
2137     wxCHECK_RET( i 
< m_fileHistoryN
, 
2138                  wxT("invalid index in wxFileHistory::RemoveFileFromHistory") ); 
2140     // delete the element from the array (could use memmove() too...) 
2141     delete [] m_fileHistory
[i
]; 
2144     for ( j 
= i
; j 
< m_fileHistoryN 
- 1; j
++ ) 
2146         m_fileHistory
[j
] = m_fileHistory
[j 
+ 1]; 
2149     wxList::compatibility_iterator node 
= m_fileMenus
.GetFirst(); 
2152          wxMenu
* menu 
= (wxMenu
*) node
->GetData(); 
2154          // shuffle filenames up 
2156          for ( j 
= i
; j 
< m_fileHistoryN 
- 1; j
++ ) 
2158              buf
.Printf(s_MRUEntryFormat
, j 
+ 1, m_fileHistory
[j
]); 
2159              menu
->SetLabel(m_idBase 
+ j
, buf
); 
2162          node 
= node
->GetNext(); 
2164         // delete the last menu item which is unused now 
2165         wxWindowID lastItemId 
= m_idBase 
+ m_fileHistoryN 
- 1; 
2166         if (menu
->FindItem(lastItemId
)) 
2168             menu
->Delete(lastItemId
); 
2171         // delete the last separator too if no more files are left 
2172         if ( m_fileHistoryN 
== 1 ) 
2174             wxMenuItemList::compatibility_iterator node 
= menu
->GetMenuItems().GetLast(); 
2177                 wxMenuItem 
*menuItem 
= node
->GetData(); 
2178                 if ( menuItem
->IsSeparator() ) 
2180                     menu
->Delete(menuItem
); 
2182                 //else: should we search backwards for the last separator? 
2184             //else: menu is empty somehow 
2191 wxString 
wxFileHistory::GetHistoryFile(size_t i
) const 
2194     if ( i 
< m_fileHistoryN 
) 
2196         s 
= m_fileHistory
[i
]; 
2200         wxFAIL_MSG( wxT("bad index in wxFileHistory::GetHistoryFile") ); 
2206 void wxFileHistory::UseMenu(wxMenu 
*menu
) 
2208     if (!m_fileMenus
.Member(menu
)) 
2209         m_fileMenus
.Append(menu
); 
2212 void wxFileHistory::RemoveMenu(wxMenu 
*menu
) 
2214     m_fileMenus
.DeleteObject(menu
); 
2218 void wxFileHistory::Load(wxConfigBase
& config
) 
2222     buf
.Printf(wxT("file%d"), (int)m_fileHistoryN
+1); 
2223     wxString historyFile
; 
2224     while ((m_fileHistoryN 
< m_fileMaxFiles
) && config
.Read(buf
, &historyFile
) && (historyFile 
!= wxT(""))) 
2226         m_fileHistory
[m_fileHistoryN
] = MYcopystring((const wxChar
*) historyFile
); 
2228         buf
.Printf(wxT("file%d"), (int)m_fileHistoryN
+1); 
2229         historyFile 
= wxT(""); 
2234 void wxFileHistory::Save(wxConfigBase
& config
) 
2237     for (i 
= 0; i 
< m_fileMaxFiles
; i
++) 
2240         buf
.Printf(wxT("file%d"), (int)i
+1); 
2241         if (i 
< m_fileHistoryN
) 
2242             config
.Write(buf
, wxString(m_fileHistory
[i
])); 
2244             config
.Write(buf
, wxEmptyString
); 
2247 #endif // wxUSE_CONFIG 
2249 void wxFileHistory::AddFilesToMenu() 
2251     if (m_fileHistoryN 
> 0) 
2253         wxList::compatibility_iterator node 
= m_fileMenus
.GetFirst(); 
2256             wxMenu
* menu 
= (wxMenu
*) node
->GetData(); 
2257             if (menu
->GetMenuItemCount()) 
2259                 menu
->AppendSeparator(); 
2263             for (i 
= 0; i 
< m_fileHistoryN
; i
++) 
2265                 if (m_fileHistory
[i
]) 
2268                     buf
.Printf(s_MRUEntryFormat
, i
+1, m_fileHistory
[i
]); 
2269                     menu
->Append(m_idBase
+i
, buf
); 
2272             node 
= node
->GetNext(); 
2277 void wxFileHistory::AddFilesToMenu(wxMenu
* menu
) 
2279     if (m_fileHistoryN 
> 0) 
2281         if (menu
->GetMenuItemCount()) 
2283             menu
->AppendSeparator(); 
2287         for (i 
= 0; i 
< m_fileHistoryN
; i
++) 
2289             if (m_fileHistory
[i
]) 
2292                 buf
.Printf(s_MRUEntryFormat
, i
+1, m_fileHistory
[i
]); 
2293                 menu
->Append(m_idBase
+i
, buf
); 
2299 // ---------------------------------------------------------------------------- 
2300 // Permits compatibility with existing file formats and functions that 
2301 // manipulate files directly 
2302 // ---------------------------------------------------------------------------- 
2304 #if wxUSE_STD_IOSTREAM 
2306 bool wxTransferFileToStream(const wxString
& filename
, wxSTD ostream
& stream
) 
2308     wxFFile 
file(filename
, _T("rb")); 
2309     if ( !file
.IsOpened() ) 
2317         nRead 
= file
.Read(buf
, WXSIZEOF(buf
)); 
2321         stream
.write(buf
, nRead
); 
2325     while ( !file
.Eof() ); 
2330 bool wxTransferStreamToFile(wxSTD istream
& stream
, const wxString
& filename
) 
2332     wxFFile 
file(filename
, _T("wb")); 
2333     if ( !file
.IsOpened() ) 
2339         stream
.read(buf
, WXSIZEOF(buf
)); 
2340         if ( !stream
.bad() ) // fail may be set on EOF, don't use operator!() 
2342             if ( !file
.Write(buf
, stream
.gcount()) ) 
2346     while ( !stream
.eof() ); 
2351 #else // !wxUSE_STD_IOSTREAM 
2353 bool wxTransferFileToStream(const wxString
& filename
, wxOutputStream
& stream
) 
2355     wxFFile 
file(filename
, _T("rb")); 
2356     if ( !file
.IsOpened() ) 
2364         nRead 
= file
.Read(buf
, WXSIZEOF(buf
)); 
2368         stream
.Write(buf
, nRead
); 
2372     while ( !file
.Eof() ); 
2377 bool wxTransferStreamToFile(wxInputStream
& stream
, const wxString
& filename
) 
2379     wxFFile 
file(filename
, _T("wb")); 
2380     if ( !file
.IsOpened() ) 
2386         stream
.Read(buf
, WXSIZEOF(buf
)); 
2388         const size_t nRead 
= stream
.LastRead(); 
2389         if ( !nRead 
|| !file
.Write(buf
, nRead
) ) 
2392     while ( !stream
.Eof() ); 
2397 #endif // wxUSE_STD_IOSTREAM/!wxUSE_STD_IOSTREAM 
2399 #endif // wxUSE_DOC_VIEW_ARCHITECTURE