1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     Document/view classes 
   4 // Author:      Julian Smart 
   8 // Copyright:   (c) Julian Smart and Markus Holzem 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  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" 
  50 #if wxUSE_PRINTING_ARCHITECTURE 
  51   #include "wx/prntbase.h" 
  52   #include "wx/printdlg.h" 
  55 #include "wx/msgdlg.h" 
  56 #include "wx/choicdlg.h" 
  57 #include "wx/docview.h" 
  58 #include "wx/confbase.h" 
  64 #if wxUSE_STD_IOSTREAM 
  65   #include "wx/ioswrap.h" 
  72   #include "wx/wfstream.h" 
  75 // ---------------------------------------------------------------------------- 
  77 // ---------------------------------------------------------------------------- 
  79     IMPLEMENT_ABSTRACT_CLASS(wxDocument
, wxEvtHandler
) 
  80     IMPLEMENT_ABSTRACT_CLASS(wxView
, wxEvtHandler
) 
  81     IMPLEMENT_ABSTRACT_CLASS(wxDocTemplate
, wxObject
) 
  82     IMPLEMENT_DYNAMIC_CLASS(wxDocManager
, wxEvtHandler
) 
  83     IMPLEMENT_CLASS(wxDocChildFrame
, wxFrame
) 
  84     IMPLEMENT_CLASS(wxDocParentFrame
, wxFrame
) 
  86     #if wxUSE_PRINTING_ARCHITECTURE 
  87         IMPLEMENT_DYNAMIC_CLASS(wxDocPrintout
, wxPrintout
) 
  90     IMPLEMENT_CLASS(wxCommand
, wxObject
) 
  91     IMPLEMENT_DYNAMIC_CLASS(wxCommandProcessor
, wxObject
) 
  92     IMPLEMENT_DYNAMIC_CLASS(wxFileHistory
, wxObject
) 
  94 // ---------------------------------------------------------------------------- 
  95 // function prototypes 
  96 // ---------------------------------------------------------------------------- 
  98 static inline wxString 
FindExtension(const wxChar 
*path
); 
 100 // ---------------------------------------------------------------------------- 
 102 // ---------------------------------------------------------------------------- 
 104 static const wxChar 
*s_MRUEntryFormat 
= wxT("&%d %s"); 
 106 // ============================================================================ 
 108 // ============================================================================ 
 110 // ---------------------------------------------------------------------------- 
 112 // ---------------------------------------------------------------------------- 
 114 static wxString 
FindExtension(const wxChar 
*path
) 
 117     wxSplitPath(path
, NULL
, NULL
, &ext
); 
 119     // VZ: extensions are considered not case sensitive - is this really a good 
 121     return ext
.MakeLower(); 
 124 // ---------------------------------------------------------------------------- 
 125 // Definition of wxDocument 
 126 // ---------------------------------------------------------------------------- 
 128 wxDocument::wxDocument(wxDocument 
*parent
) 
 130     m_documentModified 
= FALSE
; 
 131     m_documentParent 
= parent
; 
 132     m_documentTemplate 
= (wxDocTemplate 
*) NULL
; 
 133     m_commandProcessor 
= (wxCommandProcessor
*) NULL
; 
 137 bool wxDocument::DeleteContents() 
 142 wxDocument::~wxDocument() 
 146     if (m_commandProcessor
) 
 147         delete m_commandProcessor
; 
 149     if (GetDocumentManager()) 
 150         GetDocumentManager()->RemoveDocument(this); 
 152     // Not safe to do here, since it'll invoke virtual view functions 
 153     // expecting to see valid derived objects: and by the time we get here, 
 154     // we've called destructors higher up. 
 158 bool wxDocument::Close() 
 160     if (OnSaveModified()) 
 161         return OnCloseDocument(); 
 166 bool wxDocument::OnCloseDocument() 
 173 // Note that this implicitly deletes the document when the last view is 
 175 bool wxDocument::DeleteAllViews() 
 177     wxDocManager
* manager 
= GetDocumentManager(); 
 179     wxNode 
*node 
= m_documentViews
.First(); 
 182         wxView 
*view 
= (wxView 
*)node
->Data(); 
 186         wxNode 
*next 
= node
->Next(); 
 188         delete view
; // Deletes node implicitly 
 191     // If we haven't yet deleted the document (for example 
 192     // if there were no views) then delete it. 
 193     if (manager 
&& manager
->GetDocuments().Member(this)) 
 199 wxView 
*wxDocument::GetFirstView() const 
 201     if (m_documentViews
.Number() == 0) 
 202         return (wxView 
*) NULL
; 
 203     return (wxView 
*)m_documentViews
.First()->Data(); 
 206 wxDocManager 
*wxDocument::GetDocumentManager() const 
 208     return (m_documentTemplate 
? m_documentTemplate
->GetDocumentManager() : (wxDocManager
*) NULL
); 
 211 bool wxDocument::OnNewDocument() 
 213     if (!OnSaveModified()) 
 216     if (OnCloseDocument()==FALSE
) return FALSE
; 
 219     SetDocumentSaved(FALSE
); 
 222     GetDocumentManager()->MakeDefaultName(name
); 
 224     SetFilename(name
, TRUE
); 
 229 bool wxDocument::Save() 
 233     if (!IsModified()) return TRUE
; 
 234     if (m_documentFile 
== wxT("") || !m_savedYet
) 
 237         ret 
= OnSaveDocument(m_documentFile
); 
 239         SetDocumentSaved(TRUE
); 
 243 bool wxDocument::SaveAs() 
 245     wxDocTemplate 
*docTemplate 
= GetDocumentTemplate(); 
 249     wxString tmp 
= wxFileSelector(_("Save as"), 
 250             docTemplate
->GetDirectory(), 
 252             docTemplate
->GetDefaultExtension(), 
 253             docTemplate
->GetFileFilter(), 
 254             wxSAVE 
| wxOVERWRITE_PROMPT
, 
 255             GetDocumentWindow()); 
 260     wxString 
fileName(tmp
); 
 261     wxString path
, name
, ext
; 
 262     wxSplitPath(fileName
, & path
, & name
, & ext
); 
 264     if (ext
.IsEmpty() || ext 
== wxT("")) 
 267         fileName 
+= docTemplate
->GetDefaultExtension(); 
 270     SetFilename(fileName
); 
 271     SetTitle(wxFileNameFromPath(fileName
)); 
 273     GetDocumentManager()->AddFileToHistory(fileName
); 
 275     // Notify the views that the filename has changed 
 276     wxNode 
*node 
= m_documentViews
.First(); 
 279         wxView 
*view 
= (wxView 
*)node
->Data(); 
 280         view
->OnChangeFilename(); 
 284     return OnSaveDocument(m_documentFile
); 
 287 bool wxDocument::OnSaveDocument(const wxString
& file
) 
 293     if (wxTheApp
->GetAppName() != wxT("")) 
 294         msgTitle 
= wxTheApp
->GetAppName(); 
 296         msgTitle 
= wxString(_("File error")); 
 298 #if wxUSE_STD_IOSTREAM 
 299     ofstream 
store(wxString(file
.fn_str()).mb_str()); 
 300     if (store
.fail() || store
.bad()) 
 302     wxFileOutputStream 
store(wxString(file
.fn_str())); 
 303     if (store
.LastError() != wxSTREAM_NOERROR
) 
 306         (void)wxMessageBox(_("Sorry, could not open this file for saving."), msgTitle
, wxOK 
| wxICON_EXCLAMATION
, 
 307                            GetDocumentWindow()); 
 311     if (!SaveObject(store
)) 
 313         (void)wxMessageBox(_("Sorry, could not save this file."), msgTitle
, wxOK 
| wxICON_EXCLAMATION
, 
 314                            GetDocumentWindow()); 
 323 bool wxDocument::OnOpenDocument(const wxString
& file
) 
 325     if (!OnSaveModified()) 
 329     if (wxTheApp
->GetAppName() != wxT("")) 
 330         msgTitle 
= wxTheApp
->GetAppName(); 
 332         msgTitle 
= wxString(_("File error")); 
 334 #if wxUSE_STD_IOSTREAM 
 335     ifstream 
store(wxString(file
.fn_str()).mb_str()); 
 336     if (store
.fail() || store
.bad()) 
 338     wxFileInputStream 
store(wxString(file
.fn_str())); 
 339     if (store
.LastError() != wxSTREAM_NOERROR
) 
 342         (void)wxMessageBox(_("Sorry, could not open this file."), msgTitle
, wxOK
|wxICON_EXCLAMATION
, 
 343                            GetDocumentWindow()); 
 346 #if wxUSE_STD_IOSTREAM 
 347     if (!LoadObject(store
)) 
 349     int res 
= LoadObject(store
).LastError(); 
 350     if ((res 
!= wxSTREAM_NOERROR
) && 
 351         (res 
!= wxSTREAM_EOF
)) 
 354         (void)wxMessageBox(_("Sorry, could not open this file."), msgTitle
, wxOK
|wxICON_EXCLAMATION
, 
 355                            GetDocumentWindow()); 
 358     SetFilename(file
, TRUE
); 
 367 #if wxUSE_STD_IOSTREAM 
 368 istream
& wxDocument::LoadObject(istream
& stream
) 
 370 wxInputStream
& wxDocument::LoadObject(wxInputStream
& stream
) 
 376 #if wxUSE_STD_IOSTREAM 
 377 ostream
& wxDocument::SaveObject(ostream
& stream
) 
 379 wxOutputStream
& wxDocument::SaveObject(wxOutputStream
& stream
) 
 385 bool wxDocument::Revert() 
 391 // Get title, or filename if no title, else unnamed 
 392 bool wxDocument::GetPrintableName(wxString
& buf
) const 
 394     if (m_documentTitle 
!= wxT("")) 
 396         buf 
= m_documentTitle
; 
 399     else if (m_documentFile 
!= wxT("")) 
 401         buf 
= wxFileNameFromPath(m_documentFile
); 
 411 wxWindow 
*wxDocument::GetDocumentWindow() const 
 413     wxView 
*view 
= GetFirstView(); 
 415         return view
->GetFrame(); 
 417         return wxTheApp
->GetTopWindow(); 
 420 wxCommandProcessor 
*wxDocument::OnCreateCommandProcessor() 
 422     return new wxCommandProcessor
; 
 425 // TRUE if safe to close 
 426 bool wxDocument::OnSaveModified() 
 431         GetPrintableName(title
); 
 434         if (wxTheApp
->GetAppName() != wxT("")) 
 435             msgTitle 
= wxTheApp
->GetAppName(); 
 437             msgTitle 
= wxString(_("Warning")); 
 440         prompt
.Printf(_("Do you want to save changes to document %s?"), 
 441                 (const wxChar 
*)title
); 
 442         int res 
= wxMessageBox(prompt
, msgTitle
, 
 443                 wxYES_NO
|wxCANCEL
|wxICON_QUESTION
, 
 444                 GetDocumentWindow()); 
 450         else if (res 
== wxYES
) 
 452         else if (res 
== wxCANCEL
) 
 458 bool wxDocument::Draw(wxDC
& WXUNUSED(context
)) 
 463 bool wxDocument::AddView(wxView 
*view
) 
 465     if (!m_documentViews
.Member(view
)) 
 467         m_documentViews
.Append(view
); 
 473 bool wxDocument::RemoveView(wxView 
*view
) 
 475     (void)m_documentViews
.DeleteObject(view
); 
 480 bool wxDocument::OnCreate(const wxString
& WXUNUSED(path
), long flags
) 
 482     if (GetDocumentTemplate()->CreateView(this, flags
)) 
 488 // Called after a view is added or removed. 
 489 // The default implementation deletes the document if 
 490 // there are no more views. 
 491 void wxDocument::OnChangedViewList() 
 493     if (m_documentViews
.Number() == 0) 
 495         if (OnSaveModified()) 
 502 void wxDocument::UpdateAllViews(wxView 
*sender
, wxObject 
*hint
) 
 504     wxNode 
*node 
= m_documentViews
.First(); 
 507         wxView 
*view 
= (wxView 
*)node
->Data(); 
 508         view
->OnUpdate(sender
, hint
); 
 513 void wxDocument::SetFilename(const wxString
& filename
, bool notifyViews
) 
 515     m_documentFile 
= filename
; 
 518         // Notify the views that the filename has changed 
 519         wxNode 
*node 
= m_documentViews
.First(); 
 522             wxView 
*view 
= (wxView 
*)node
->Data(); 
 523             view
->OnChangeFilename(); 
 529 // ---------------------------------------------------------------------------- 
 531 // ---------------------------------------------------------------------------- 
 536     m_viewDocument 
= (wxDocument
*) NULL
; 
 538     m_viewTypeName 
= wxT(""); 
 539     m_viewFrame 
= (wxFrame 
*) NULL
; 
 544 //    GetDocumentManager()->ActivateView(this, FALSE, TRUE); 
 545     m_viewDocument
->RemoveView(this); 
 548 // Extend event processing to search the document's event table 
 549 bool wxView::ProcessEvent(wxEvent
& event
) 
 551     if ( !GetDocument() || !GetDocument()->ProcessEvent(event
) ) 
 552         return wxEvtHandler::ProcessEvent(event
); 
 557 void wxView::OnActivateView(bool WXUNUSED(activate
), wxView 
*WXUNUSED(activeView
), wxView 
*WXUNUSED(deactiveView
)) 
 561 void wxView::OnPrint(wxDC 
*dc
, wxObject 
*WXUNUSED(info
)) 
 566 void wxView::OnUpdate(wxView 
*WXUNUSED(sender
), wxObject 
*WXUNUSED(hint
)) 
 570 void wxView::OnChangeFilename() 
 572     if (GetFrame() && GetDocument()) 
 576         GetDocument()->GetPrintableName(title
); 
 578         GetFrame()->SetTitle(title
); 
 582 void wxView::SetDocument(wxDocument 
*doc
) 
 584     m_viewDocument 
= doc
; 
 589 bool wxView::Close(bool deleteWindow
) 
 591     if (OnClose(deleteWindow
)) 
 597 void wxView::Activate(bool activate
) 
 599     if (GetDocumentManager()) 
 601         OnActivateView(activate
, this, GetDocumentManager()->GetCurrentView()); 
 602         GetDocumentManager()->ActivateView(this, activate
); 
 606 bool wxView::OnClose(bool WXUNUSED(deleteWindow
)) 
 608     return GetDocument() ? GetDocument()->Close() : TRUE
; 
 611 #if wxUSE_PRINTING_ARCHITECTURE 
 612 wxPrintout 
*wxView::OnCreatePrintout() 
 614     return new wxDocPrintout(this); 
 616 #endif // wxUSE_PRINTING_ARCHITECTURE 
 618 // ---------------------------------------------------------------------------- 
 620 // ---------------------------------------------------------------------------- 
 622 wxDocTemplate::wxDocTemplate(wxDocManager 
*manager
, 
 623                              const wxString
& descr
, 
 624                              const wxString
& filter
, 
 627                              const wxString
& docTypeName
, 
 628                              const wxString
& viewTypeName
, 
 629                              wxClassInfo 
*docClassInfo
, 
 630                              wxClassInfo 
*viewClassInfo
, 
 633     m_documentManager 
= manager
; 
 634     m_description 
= descr
; 
 637     m_fileFilter 
= filter
; 
 639     m_docTypeName 
= docTypeName
; 
 640     m_viewTypeName 
= viewTypeName
; 
 641     m_documentManager
->AssociateTemplate(this); 
 643     m_docClassInfo 
= docClassInfo
; 
 644     m_viewClassInfo 
= viewClassInfo
; 
 647 wxDocTemplate::~wxDocTemplate() 
 649     m_documentManager
->DisassociateTemplate(this); 
 652 // Tries to dynamically construct an object of the right class. 
 653 wxDocument 
*wxDocTemplate::CreateDocument(const wxString
& path
, long flags
) 
 656         return (wxDocument 
*) NULL
; 
 657     wxDocument 
*doc 
= (wxDocument 
*)m_docClassInfo
->CreateObject(); 
 658     doc
->SetFilename(path
); 
 659     doc
->SetDocumentTemplate(this); 
 660     GetDocumentManager()->AddDocument(doc
); 
 661     doc
->SetCommandProcessor(doc
->OnCreateCommandProcessor()); 
 663     if (doc
->OnCreate(path
, flags
)) 
 667         if (GetDocumentManager()->GetDocuments().Member(doc
)) 
 668             doc
->DeleteAllViews(); 
 669         return (wxDocument 
*) NULL
; 
 673 wxView 
*wxDocTemplate::CreateView(wxDocument 
*doc
, long flags
) 
 675     if (!m_viewClassInfo
) 
 676         return (wxView 
*) NULL
; 
 677     wxView 
*view 
= (wxView 
*)m_viewClassInfo
->CreateObject(); 
 678     view
->SetDocument(doc
); 
 679     if (view
->OnCreate(doc
, flags
)) 
 686         return (wxView 
*) NULL
; 
 690 // The default (very primitive) format detection: check is the extension is 
 691 // that of the template 
 692 bool wxDocTemplate::FileMatchesTemplate(const wxString
& path
) 
 694     return GetDefaultExtension().IsSameAs(FindExtension(path
)); 
 697 // ---------------------------------------------------------------------------- 
 699 // ---------------------------------------------------------------------------- 
 701 BEGIN_EVENT_TABLE(wxDocManager
, wxEvtHandler
) 
 702     EVT_MENU(wxID_OPEN
, wxDocManager::OnFileOpen
) 
 703     EVT_MENU(wxID_CLOSE
, wxDocManager::OnFileClose
) 
 704     EVT_MENU(wxID_REVERT
, wxDocManager::OnFileRevert
) 
 705     EVT_MENU(wxID_NEW
, wxDocManager::OnFileNew
) 
 706     EVT_MENU(wxID_SAVE
, wxDocManager::OnFileSave
) 
 707     EVT_MENU(wxID_SAVEAS
, wxDocManager::OnFileSaveAs
) 
 708     EVT_MENU(wxID_UNDO
, wxDocManager::OnUndo
) 
 709     EVT_MENU(wxID_REDO
, wxDocManager::OnRedo
) 
 711     EVT_UPDATE_UI(wxID_OPEN
, wxDocManager::OnUpdateFileOpen
) 
 712     EVT_UPDATE_UI(wxID_CLOSE
, wxDocManager::OnUpdateFileClose
) 
 713     EVT_UPDATE_UI(wxID_REVERT
, wxDocManager::OnUpdateFileRevert
) 
 714     EVT_UPDATE_UI(wxID_NEW
, wxDocManager::OnUpdateFileNew
) 
 715     EVT_UPDATE_UI(wxID_SAVE
, wxDocManager::OnUpdateFileSave
) 
 716     EVT_UPDATE_UI(wxID_SAVEAS
, wxDocManager::OnUpdateFileSaveAs
) 
 717     EVT_UPDATE_UI(wxID_UNDO
, wxDocManager::OnUpdateUndo
) 
 718     EVT_UPDATE_UI(wxID_REDO
, wxDocManager::OnUpdateRedo
) 
 720 #if wxUSE_PRINTING_ARCHITECTURE 
 721     EVT_MENU(wxID_PRINT
, wxDocManager::OnPrint
) 
 722     EVT_MENU(wxID_PRINT_SETUP
, wxDocManager::OnPrintSetup
) 
 723     EVT_MENU(wxID_PREVIEW
, wxDocManager::OnPreview
) 
 725     EVT_UPDATE_UI(wxID_PRINT
, wxDocManager::OnUpdatePrint
) 
 726     EVT_UPDATE_UI(wxID_PRINT_SETUP
, wxDocManager::OnUpdatePrintSetup
) 
 727     EVT_UPDATE_UI(wxID_PREVIEW
, wxDocManager::OnUpdatePreview
) 
 731 wxDocManager
* wxDocManager::sm_docManager 
= (wxDocManager
*) NULL
; 
 733 wxDocManager::wxDocManager(long flags
, bool initialize
) 
 735     m_defaultDocumentNameCounter 
= 1; 
 737     m_currentView 
= (wxView 
*) NULL
; 
 738     m_maxDocsOpen 
= 10000; 
 739     m_fileHistory 
= (wxFileHistory 
*) NULL
; 
 742     sm_docManager 
= this; 
 745 wxDocManager::~wxDocManager() 
 749         delete m_fileHistory
; 
 750     sm_docManager 
= (wxDocManager
*) NULL
; 
 753 bool wxDocManager::Clear(bool force
) 
 755     wxNode 
*node 
= m_docs
.First(); 
 758         wxDocument 
*doc 
= (wxDocument 
*)node
->Data(); 
 759         wxNode 
*next 
= node
->Next(); 
 761         if (!doc
->Close() && !force
) 
 764         // Implicitly deletes the document when the last 
 765         // view is removed (deleted) 
 766         doc
->DeleteAllViews(); 
 768         // Check document is deleted 
 769         if (m_docs
.Member(doc
)) 
 772         // This assumes that documents are not connected in 
 773         // any way, i.e. deleting one document does NOT 
 777     node 
= m_templates
.First(); 
 780         wxDocTemplate 
*templ 
= (wxDocTemplate
*) node
->Data(); 
 781         wxNode
* next 
= node
->Next(); 
 788 bool wxDocManager::Initialize() 
 790     m_fileHistory 
= OnCreateFileHistory(); 
 794 wxFileHistory 
*wxDocManager::OnCreateFileHistory() 
 796     return new wxFileHistory
; 
 799 void wxDocManager::OnFileClose(wxCommandEvent
& WXUNUSED(event
)) 
 801     wxDocument 
*doc 
= GetCurrentDocument(); 
 806         doc
->DeleteAllViews(); 
 807         if (m_docs
.Member(doc
)) 
 812 void wxDocManager::OnFileNew(wxCommandEvent
& WXUNUSED(event
)) 
 814     CreateDocument(wxString(""), wxDOC_NEW
); 
 817 void wxDocManager::OnFileOpen(wxCommandEvent
& WXUNUSED(event
)) 
 819     if ( !CreateDocument(wxString(""), 0) ) 
 825 void wxDocManager::OnFileRevert(wxCommandEvent
& WXUNUSED(event
)) 
 827     wxDocument 
*doc 
= GetCurrentDocument(); 
 833 void wxDocManager::OnFileSave(wxCommandEvent
& WXUNUSED(event
)) 
 835     wxDocument 
*doc 
= GetCurrentDocument(); 
 841 void wxDocManager::OnFileSaveAs(wxCommandEvent
& WXUNUSED(event
)) 
 843     wxDocument 
*doc 
= GetCurrentDocument(); 
 849 void wxDocManager::OnPrint(wxCommandEvent
& WXUNUSED(event
)) 
 851 #if wxUSE_PRINTING_ARCHITECTURE 
 852     wxView 
*view 
= GetCurrentView(); 
 856     wxPrintout 
*printout 
= view
->OnCreatePrintout(); 
 860         printer
.Print(view
->GetFrame(), printout
, TRUE
); 
 864 #endif // wxUSE_PRINTING_ARCHITECTURE 
 867 void wxDocManager::OnPrintSetup(wxCommandEvent
& WXUNUSED(event
)) 
 869 #if wxUSE_PRINTING_ARCHITECTURE 
 870     wxWindow 
*parentWin 
= wxTheApp
->GetTopWindow(); 
 871     wxView 
*view 
= GetCurrentView(); 
 873         parentWin 
= view
->GetFrame(); 
 875     wxPrintDialogData data
; 
 877     wxPrintDialog 
printerDialog(parentWin
, &data
); 
 878     printerDialog
.GetPrintDialogData().SetSetupDialog(TRUE
); 
 879     printerDialog
.ShowModal(); 
 880 #endif // wxUSE_PRINTING_ARCHITECTURE 
 883 void wxDocManager::OnPreview(wxCommandEvent
& WXUNUSED(event
)) 
 885 #if wxUSE_PRINTING_ARCHITECTURE 
 886     wxView 
*view 
= GetCurrentView(); 
 890     wxPrintout 
*printout 
= view
->OnCreatePrintout(); 
 893         // Pass two printout objects: for preview, and possible printing. 
 894         wxPrintPreviewBase 
*preview 
= (wxPrintPreviewBase 
*) NULL
; 
 895         preview 
= new wxPrintPreview(printout
, view
->OnCreatePrintout()); 
 897         wxPreviewFrame 
*frame 
= new wxPreviewFrame(preview
, (wxFrame 
*)wxTheApp
->GetTopWindow(), _("Print Preview"), 
 898                 wxPoint(100, 100), wxSize(600, 650)); 
 899         frame
->Centre(wxBOTH
); 
 903 #endif // wxUSE_PRINTING_ARCHITECTURE 
 906 void wxDocManager::OnUndo(wxCommandEvent
& WXUNUSED(event
)) 
 908     wxDocument 
*doc 
= GetCurrentDocument(); 
 911     if (doc
->GetCommandProcessor()) 
 912         doc
->GetCommandProcessor()->Undo(); 
 915 void wxDocManager::OnRedo(wxCommandEvent
& WXUNUSED(event
)) 
 917     wxDocument 
*doc 
= GetCurrentDocument(); 
 920     if (doc
->GetCommandProcessor()) 
 921         doc
->GetCommandProcessor()->Redo(); 
 924 // Handlers for UI update commands 
 926 void wxDocManager::OnUpdateFileOpen(wxUpdateUIEvent
& event
) 
 928     event
.Enable( TRUE 
); 
 931 void wxDocManager::OnUpdateFileClose(wxUpdateUIEvent
& event
) 
 933     wxDocument 
*doc 
= GetCurrentDocument(); 
 934     event
.Enable( (doc 
!= (wxDocument
*) NULL
) ); 
 937 void wxDocManager::OnUpdateFileRevert(wxUpdateUIEvent
& event
) 
 939     wxDocument 
*doc 
= GetCurrentDocument(); 
 940     event
.Enable( (doc 
!= (wxDocument
*) NULL
) ); 
 943 void wxDocManager::OnUpdateFileNew(wxUpdateUIEvent
& event
) 
 945     event
.Enable( TRUE 
); 
 948 void wxDocManager::OnUpdateFileSave(wxUpdateUIEvent
& event
) 
 950     wxDocument 
*doc 
= GetCurrentDocument(); 
 951     event
.Enable( (doc 
!= (wxDocument
*) NULL
) ); 
 954 void wxDocManager::OnUpdateFileSaveAs(wxUpdateUIEvent
& event
) 
 956     wxDocument 
*doc 
= GetCurrentDocument(); 
 957     event
.Enable( (doc 
!= (wxDocument
*) NULL
) ); 
 960 void wxDocManager::OnUpdateUndo(wxUpdateUIEvent
& event
) 
 962     wxDocument 
*doc 
= GetCurrentDocument(); 
 963     event
.Enable( (doc 
&& doc
->GetCommandProcessor() && doc
->GetCommandProcessor()->CanUndo()) ); 
 966 void wxDocManager::OnUpdateRedo(wxUpdateUIEvent
& event
) 
 968     wxDocument 
*doc 
= GetCurrentDocument(); 
 969     event
.Enable( (doc 
&& doc
->GetCommandProcessor() && doc
->GetCommandProcessor()->CanRedo()) ); 
 972 void wxDocManager::OnUpdatePrint(wxUpdateUIEvent
& event
) 
 974     wxDocument 
*doc 
= GetCurrentDocument(); 
 975     event
.Enable( (doc 
!= (wxDocument
*) NULL
) ); 
 978 void wxDocManager::OnUpdatePrintSetup(wxUpdateUIEvent
& event
) 
 980     event
.Enable( TRUE 
); 
 983 void wxDocManager::OnUpdatePreview(wxUpdateUIEvent
& event
) 
 985     wxDocument 
*doc 
= GetCurrentDocument(); 
 986     event
.Enable( (doc 
!= (wxDocument
*) NULL
) ); 
 989 wxView 
*wxDocManager::GetCurrentView() const 
 992         return m_currentView
; 
 993     if (m_docs
.Number() == 1) 
 995         wxDocument
* doc 
= (wxDocument
*) m_docs
.First()->Data(); 
 996         return doc
->GetFirstView(); 
 998     return (wxView 
*) NULL
; 
1001 // Extend event processing to search the view's event table 
1002 bool wxDocManager::ProcessEvent(wxEvent
& event
) 
1004     wxView
* view 
= GetCurrentView(); 
1007         if (view
->ProcessEvent(event
)) 
1010     return wxEvtHandler::ProcessEvent(event
); 
1013 wxDocument 
*wxDocManager::CreateDocument(const wxString
& path
, long flags
) 
1015     wxDocTemplate 
**templates 
= new wxDocTemplate 
*[m_templates
.Number()]; 
1018     for (i 
= 0; i 
< m_templates
.Number(); i
++) 
1020         wxDocTemplate 
*temp 
= (wxDocTemplate 
*)(m_templates
.Nth(i
)->Data()); 
1021         if (temp
->IsVisible()) 
1023             templates
[n
] = temp
; 
1030         return (wxDocument 
*) NULL
; 
1033     // If we've reached the max number of docs, close the 
1035     if (GetDocuments().Number() >= m_maxDocsOpen
) 
1037         wxDocument 
*doc 
= (wxDocument 
*)GetDocuments().First()->Data(); 
1040             // Implicitly deletes the document when 
1041             // the last view is deleted 
1042             doc
->DeleteAllViews(); 
1044             // Check we're really deleted 
1045             if (m_docs
.Member(doc
)) 
1049             return (wxDocument 
*) NULL
; 
1052     // New document: user chooses a template, unless there's only one. 
1053     if (flags 
& wxDOC_NEW
) 
1057             wxDocTemplate 
*temp 
= templates
[0]; 
1059             wxDocument 
*newDoc 
= temp
->CreateDocument(path
, flags
); 
1062                 newDoc
->SetDocumentName(temp
->GetDocumentName()); 
1063                 newDoc
->SetDocumentTemplate(temp
); 
1064                 newDoc
->OnNewDocument(); 
1069         wxDocTemplate 
*temp 
= SelectDocumentType(templates
, n
); 
1073             wxDocument 
*newDoc 
= temp
->CreateDocument(path
, flags
); 
1076                 newDoc
->SetDocumentName(temp
->GetDocumentName()); 
1077                 newDoc
->SetDocumentTemplate(temp
); 
1078                 newDoc
->OnNewDocument(); 
1083             return (wxDocument 
*) NULL
; 
1086     // Existing document 
1087     wxDocTemplate 
*temp 
= (wxDocTemplate 
*) NULL
; 
1089     wxString 
path2(wxT("")); 
1090     if (path 
!= wxT("")) 
1093     if (flags 
& wxDOC_SILENT
) 
1094         temp 
= FindTemplateForPath(path2
); 
1096         temp 
= SelectDocumentPath(templates
, n
, path2
, flags
); 
1102         wxDocument 
*newDoc 
= temp
->CreateDocument(path2
, flags
); 
1105             newDoc
->SetDocumentName(temp
->GetDocumentName()); 
1106             newDoc
->SetDocumentTemplate(temp
); 
1107             if (!newDoc
->OnOpenDocument(path2
)) 
1109                 newDoc
->DeleteAllViews(); 
1110                 // delete newDoc; // Implicitly deleted by DeleteAllViews 
1111                 return (wxDocument 
*) NULL
; 
1113             AddFileToHistory(path2
); 
1118     return (wxDocument 
*) NULL
; 
1121 wxView 
*wxDocManager::CreateView(wxDocument 
*doc
, long flags
) 
1123     wxDocTemplate 
**templates 
= new wxDocTemplate 
*[m_templates
.Number()]; 
1126     for (i 
= 0; i 
< m_templates
.Number(); i
++) 
1128         wxDocTemplate 
*temp 
= (wxDocTemplate 
*)(m_templates
.Nth(i
)->Data()); 
1129         if (temp
->IsVisible()) 
1131             if (temp
->GetDocumentName() == doc
->GetDocumentName()) 
1133                 templates
[n
] = temp
; 
1141         return (wxView 
*) NULL
; 
1145         wxDocTemplate 
*temp 
= templates
[0]; 
1147         wxView 
*view 
= temp
->CreateView(doc
, flags
); 
1149             view
->SetViewName(temp
->GetViewName()); 
1153     wxDocTemplate 
*temp 
= SelectViewType(templates
, n
); 
1157         wxView 
*view 
= temp
->CreateView(doc
, flags
); 
1159             view
->SetViewName(temp
->GetViewName()); 
1163         return (wxView 
*) NULL
; 
1166 // Not yet implemented 
1167 void wxDocManager::DeleteTemplate(wxDocTemplate 
*WXUNUSED(temp
), long WXUNUSED(flags
)) 
1171 // Not yet implemented 
1172 bool wxDocManager::FlushDoc(wxDocument 
*WXUNUSED(doc
)) 
1177 wxDocument 
*wxDocManager::GetCurrentDocument() const 
1180         return m_currentView
->GetDocument(); 
1182         return (wxDocument 
*) NULL
; 
1185 // Make a default document name 
1186 bool wxDocManager::MakeDefaultName(wxString
& name
) 
1188     name
.Printf(_("unnamed%d"), m_defaultDocumentNameCounter
); 
1189     m_defaultDocumentNameCounter
++; 
1194 // Make a frame title (override this to do something different) 
1195 // If docName is empty, a document is not currently active. 
1196 wxString 
wxDocManager::MakeFrameTitle(wxDocument
* doc
) 
1198     wxString appName 
= wxTheApp
->GetAppName(); 
1205         doc
->GetPrintableName(docName
); 
1206         title 
= docName 
+ wxString(_(" - ")) + appName
; 
1212 // Not yet implemented 
1213 wxDocTemplate 
*wxDocManager::MatchTemplate(const wxString
& WXUNUSED(path
)) 
1215     return (wxDocTemplate 
*) NULL
; 
1218 // File history management 
1219 void wxDocManager::AddFileToHistory(const wxString
& file
) 
1222         m_fileHistory
->AddFileToHistory(file
); 
1225 void wxDocManager::RemoveFileFromHistory(int i
) 
1228         m_fileHistory
->RemoveFileFromHistory(i
); 
1231 wxString 
wxDocManager::GetHistoryFile(int i
) const 
1236         histFile 
= m_fileHistory
->GetHistoryFile(i
); 
1241 void wxDocManager::FileHistoryUseMenu(wxMenu 
*menu
) 
1244         m_fileHistory
->UseMenu(menu
); 
1247 void wxDocManager::FileHistoryRemoveMenu(wxMenu 
*menu
) 
1250         m_fileHistory
->RemoveMenu(menu
); 
1254 void wxDocManager::FileHistoryLoad(wxConfigBase
& config
) 
1257         m_fileHistory
->Load(config
); 
1260 void wxDocManager::FileHistorySave(wxConfigBase
& config
) 
1263         m_fileHistory
->Save(config
); 
1267 void wxDocManager::FileHistoryAddFilesToMenu(wxMenu
* menu
) 
1270         m_fileHistory
->AddFilesToMenu(menu
); 
1273 void wxDocManager::FileHistoryAddFilesToMenu() 
1276         m_fileHistory
->AddFilesToMenu(); 
1279 int wxDocManager::GetNoHistoryFiles() const 
1282         return m_fileHistory
->GetNoHistoryFiles(); 
1288 // Find out the document template via matching in the document file format 
1289 // against that of the template 
1290 wxDocTemplate 
*wxDocManager::FindTemplateForPath(const wxString
& path
) 
1292     wxDocTemplate 
*theTemplate 
= (wxDocTemplate 
*) NULL
; 
1294     // Find the template which this extension corresponds to 
1296     for (i 
= 0; i 
< m_templates
.Number(); i
++) 
1298         wxDocTemplate 
*temp 
= (wxDocTemplate 
*)m_templates
.Nth(i
)->Data(); 
1299         if ( temp
->FileMatchesTemplate(path
) ) 
1308 // Try to get a more suitable parent frame than the top window, 
1309 // for selection dialogs. Otherwise you may get an unexpected 
1310 // window being activated when a dialog is shown. 
1311 static wxWindow
* wxFindSuitableParent() 
1313     wxWindow
* parent 
= wxTheApp
->GetTopWindow(); 
1315     wxWindow
* focusWindow 
= wxWindow::FindFocus(); 
1318         while (focusWindow 
&& 
1319                 !focusWindow
->IsKindOf(CLASSINFO(wxDialog
)) && 
1320                 !focusWindow
->IsKindOf(CLASSINFO(wxFrame
))) 
1322             focusWindow 
= focusWindow
->GetParent(); 
1325             parent 
= focusWindow
; 
1330 // Prompts user to open a file, using file specs in templates. 
1331 // How to implement in wxWindows? Must extend the file selector 
1332 // dialog or implement own; OR match the extension to the 
1333 // template extension. 
1335 wxDocTemplate 
*wxDocManager::SelectDocumentPath(wxDocTemplate 
**templates
, 
1336 #if defined(__WXMSW__) || defined(__WXGTK__) 
1339                                                 int WXUNUSED(noTemplates
), 
1342                                                 long WXUNUSED(flags
), 
1343                                                 bool WXUNUSED(save
)) 
1345     // We can only have multiple filters in Windows and GTK 
1346 #if defined(__WXMSW__) || defined(__WXGTK__) 
1350     for (i 
= 0; i 
< noTemplates
; i
++) 
1352         if (templates
[i
]->IsVisible()) 
1354             // add a '|' to separate this filter from the previous one 
1355             if ( !descrBuf
.IsEmpty() ) 
1356                 descrBuf 
<< wxT('|'); 
1358             descrBuf 
<< templates
[i
]->GetDescription() 
1359                 << wxT(" (") << templates
[i
]->GetFileFilter() << wxT(") |") 
1360                 << templates
[i
]->GetFileFilter(); 
1364     wxString descrBuf 
= wxT("*.*"); 
1367     int FilterIndex 
= -1; 
1369     wxWindow
* parent 
= wxFindSuitableParent(); 
1371     wxString pathTmp 
= wxFileSelectorEx(_("Select a file"), 
1379     wxDocTemplate 
*theTemplate 
= (wxDocTemplate 
*)NULL
; 
1380     if (!pathTmp
.IsEmpty()) 
1382         if (!wxFileExists(pathTmp
)) 
1385             if (!wxTheApp
->GetAppName().IsEmpty()) 
1386                 msgTitle 
= wxTheApp
->GetAppName(); 
1388                 msgTitle 
= wxString(_("File error")); 
1390             (void)wxMessageBox(_("Sorry, could not open this file."), msgTitle
, wxOK 
| wxICON_EXCLAMATION
, 
1394             return (wxDocTemplate 
*) NULL
; 
1396         m_lastDirectory 
= wxPathOnly(pathTmp
); 
1400         // first choose the template using the extension, if this fails (i.e. 
1401         // wxFileSelectorEx() didn't fill it), then use the path 
1402         if ( FilterIndex 
!= -1 ) 
1403             theTemplate 
= templates
[FilterIndex
]; 
1405             theTemplate 
= FindTemplateForPath(path
); 
1415     // In all other windowing systems, until we have more advanced 
1416     // file selectors, we must select the document type (template) first, and 
1417     // _then_ pop up the file selector. 
1418     wxDocTemplate 
*temp 
= SelectDocumentType(templates
, noTemplates
); 
1420         return (wxDocTemplate 
*) NULL
; 
1422     wxChar 
*pathTmp 
= wxFileSelector(_("Select a file"), wxT(""), wxT(""), 
1423             temp
->GetDefaultExtension(), 
1424             temp
->GetFileFilter(), 
1425             0, wxTheApp
->GetTopWindow()); 
1433         return (wxDocTemplate 
*) NULL
; 
1437 wxDocTemplate 
*wxDocManager::SelectDocumentType(wxDocTemplate 
**templates
, 
1440     wxChar 
**strings 
= new wxChar 
*[noTemplates
]; 
1441     wxChar 
**data 
= new wxChar 
*[noTemplates
]; 
1444     for (i 
= 0; i 
< noTemplates
; i
++) 
1446         if (templates
[i
]->IsVisible()) 
1448             strings
[n
] = (wxChar 
*)templates
[i
]->m_description
.c_str(); 
1449             data
[n
] = (wxChar 
*)templates
[i
]; 
1457         return (wxDocTemplate 
*) NULL
; 
1461         wxDocTemplate 
*temp 
= (wxDocTemplate 
*)data
[0]; 
1467     wxWindow
* parent 
= wxFindSuitableParent(); 
1469     wxDocTemplate 
*theTemplate 
= (wxDocTemplate 
*)wxGetSingleChoiceData(_("Select a document template"), _("Templates"), n
, 
1470             strings
, (void **)data
, parent
); 
1476 wxDocTemplate 
*wxDocManager::SelectViewType(wxDocTemplate 
**templates
, 
1479     wxChar 
**strings 
= new wxChar 
*[noTemplates
]; 
1480     wxChar 
**data 
= new wxChar 
*[noTemplates
]; 
1483     for (i 
= 0; i 
< noTemplates
; i
++) 
1485         if (templates
[i
]->IsVisible() && (templates
[i
]->GetViewName() != wxT(""))) 
1487             strings
[n
] = (wxChar 
*)templates
[i
]->m_viewTypeName
.c_str(); 
1488             data
[n
] = (wxChar 
*)templates
[i
]; 
1492     wxWindow
* parent 
= wxFindSuitableParent(); 
1494     wxDocTemplate 
*theTemplate 
= (wxDocTemplate 
*)wxGetSingleChoiceData(_("Select a document view"), _("Views"), n
, 
1495             strings
, (void **)data
, parent
); 
1501 void wxDocManager::AssociateTemplate(wxDocTemplate 
*temp
) 
1503     if (!m_templates
.Member(temp
)) 
1504         m_templates
.Append(temp
); 
1507 void wxDocManager::DisassociateTemplate(wxDocTemplate 
*temp
) 
1509     m_templates
.DeleteObject(temp
); 
1512 // Add and remove a document from the manager's list 
1513 void wxDocManager::AddDocument(wxDocument 
*doc
) 
1515     if (!m_docs
.Member(doc
)) 
1519 void wxDocManager::RemoveDocument(wxDocument 
*doc
) 
1521     m_docs
.DeleteObject(doc
); 
1524 // Views or windows should inform the document manager 
1525 // when a view is going in or out of focus 
1526 void wxDocManager::ActivateView(wxView 
*view
, bool activate
, bool WXUNUSED(deleting
)) 
1528     // If we're deactiving, and if we're not actually deleting the view, then 
1529     // don't reset the current view because we may be going to 
1530     // a window without a view. 
1531     // WHAT DID I MEAN BY THAT EXACTLY? 
1535        if (m_currentView == view) 
1536        m_currentView = NULL; 
1542             m_currentView 
= view
; 
1544             m_currentView 
= (wxView 
*) NULL
; 
1548 // ---------------------------------------------------------------------------- 
1549 // Default document child frame 
1550 // ---------------------------------------------------------------------------- 
1552 BEGIN_EVENT_TABLE(wxDocChildFrame
, wxFrame
) 
1553     EVT_ACTIVATE(wxDocChildFrame::OnActivate
) 
1554     EVT_CLOSE(wxDocChildFrame::OnCloseWindow
) 
1557 wxDocChildFrame::wxDocChildFrame(wxDocument 
*doc
, 
1561                                  const wxString
& title
, 
1565                                  const wxString
& name
) 
1566                : wxFrame(frame
, id
, title
, pos
, size
, style
, name
) 
1568     m_childDocument 
= doc
; 
1571         view
->SetFrame(this); 
1574 wxDocChildFrame::~wxDocChildFrame() 
1578 // Extend event processing to search the view's event table 
1579 bool wxDocChildFrame::ProcessEvent(wxEvent
& event
) 
1582         m_childView
->Activate(TRUE
); 
1584     if ( !m_childView 
|| ! m_childView
->ProcessEvent(event
) ) 
1586         // Only hand up to the parent if it's a menu command 
1587         if (!event
.IsKindOf(CLASSINFO(wxCommandEvent
)) || !GetParent() || !GetParent()->ProcessEvent(event
)) 
1588             return wxEvtHandler::ProcessEvent(event
); 
1596 void wxDocChildFrame::OnActivate(wxActivateEvent
& event
) 
1598     wxFrame::OnActivate(event
); 
1601         m_childView
->Activate(event
.GetActive()); 
1604 void wxDocChildFrame::OnCloseWindow(wxCloseEvent
& event
) 
1609         if (!event
.CanVeto()) 
1610             ans 
= TRUE
; // Must delete. 
1612             ans 
= m_childView
->Close(FALSE
); // FALSE means don't delete associated window 
1616             m_childView
->Activate(FALSE
); 
1618             m_childView 
= (wxView 
*) NULL
; 
1619             m_childDocument 
= (wxDocument 
*) NULL
; 
1630 // ---------------------------------------------------------------------------- 
1631 // Default parent frame 
1632 // ---------------------------------------------------------------------------- 
1634 BEGIN_EVENT_TABLE(wxDocParentFrame
, wxFrame
) 
1635     EVT_MENU(wxID_EXIT
, wxDocParentFrame::OnExit
) 
1636     EVT_MENU_RANGE(wxID_FILE1
, wxID_FILE9
, wxDocParentFrame::OnMRUFile
) 
1637     EVT_CLOSE(wxDocParentFrame::OnCloseWindow
) 
1640 wxDocParentFrame::wxDocParentFrame(wxDocManager 
*manager
, 
1643                                    const wxString
& title
, 
1647                                    const wxString
& name
) 
1648                 : wxFrame(frame
, id
, title
, pos
, size
, style
, name
) 
1650     m_docManager 
= manager
; 
1653 void wxDocParentFrame::OnExit(wxCommandEvent
& WXUNUSED(event
)) 
1658 void wxDocParentFrame::OnMRUFile(wxCommandEvent
& event
) 
1660     int n 
= event
.GetId() - wxID_FILE1
;  // the index in MRU list 
1661     wxString 
filename(m_docManager
->GetHistoryFile(n
)); 
1662     if ( !filename
.IsEmpty() ) 
1664         // verify that the file exists before doing anything else 
1665         if ( wxFile::Exists(filename
) ) 
1668             (void)m_docManager
->CreateDocument(filename
, wxDOC_SILENT
); 
1672             // remove the bogus filename from the MRU list and notify the user 
1674             m_docManager
->RemoveFileFromHistory(n
); 
1676             wxLogError(_("The file '%s' doesn't exist and couldn't be opened.\nIt has been also removed from the MRU files list."), 
1682 // Extend event processing to search the view's event table 
1683 bool wxDocParentFrame::ProcessEvent(wxEvent
& event
) 
1685     // Try the document manager, then do default processing 
1686     if (!m_docManager 
|| !m_docManager
->ProcessEvent(event
)) 
1687         return wxEvtHandler::ProcessEvent(event
); 
1692 // Define the behaviour for the frame closing 
1693 // - must delete all frames except for the main one. 
1694 void wxDocParentFrame::OnCloseWindow(wxCloseEvent
& event
) 
1696     if (m_docManager
->Clear(!event
.CanVeto())) 
1704 #if wxUSE_PRINTING_ARCHITECTURE 
1706 wxDocPrintout::wxDocPrintout(wxView 
*view
, const wxString
& title
) 
1709     m_printoutView 
= view
; 
1712 bool wxDocPrintout::OnPrintPage(int WXUNUSED(page
)) 
1716     // Get the logical pixels per inch of screen and printer 
1717     int ppiScreenX
, ppiScreenY
; 
1718     GetPPIScreen(&ppiScreenX
, &ppiScreenY
); 
1719     int ppiPrinterX
, ppiPrinterY
; 
1720     GetPPIPrinter(&ppiPrinterX
, &ppiPrinterY
); 
1722     // This scales the DC so that the printout roughly represents the 
1723     // the screen scaling. The text point size _should_ be the right size 
1724     // but in fact is too small for some reason. This is a detail that will 
1725     // need to be addressed at some point but can be fudged for the 
1727     float scale 
= (float)((float)ppiPrinterX
/(float)ppiScreenX
); 
1729     // Now we have to check in case our real page size is reduced 
1730     // (e.g. because we're drawing to a print preview memory DC) 
1731     int pageWidth
, pageHeight
; 
1733     dc
->GetSize(&w
, &h
); 
1734     GetPageSizePixels(&pageWidth
, &pageHeight
); 
1736     // If printer pageWidth == current DC width, then this doesn't 
1737     // change. But w might be the preview bitmap width, so scale down. 
1738     float overallScale 
= scale 
* (float)(w
/(float)pageWidth
); 
1739     dc
->SetUserScale(overallScale
, overallScale
); 
1743         m_printoutView
->OnDraw(dc
); 
1748 bool wxDocPrintout::HasPage(int pageNum
) 
1750     return (pageNum 
== 1); 
1753 bool wxDocPrintout::OnBeginDocument(int startPage
, int endPage
) 
1755     if (!wxPrintout::OnBeginDocument(startPage
, endPage
)) 
1761 void wxDocPrintout::GetPageInfo(int *minPage
, int *maxPage
, int *selPageFrom
, int *selPageTo
) 
1769 #endif // wxUSE_PRINTING_ARCHITECTURE 
1771 // ---------------------------------------------------------------------------- 
1772 // Command processing framework 
1773 // ---------------------------------------------------------------------------- 
1775 wxCommand::wxCommand(bool canUndoIt
, const wxString
& name
) 
1777     m_canUndo 
= canUndoIt
; 
1778     m_commandName 
= name
; 
1781 wxCommand::~wxCommand() 
1785 // Command processor 
1786 wxCommandProcessor::wxCommandProcessor(int maxCommands
) 
1788     m_maxNoCommands 
= maxCommands
; 
1789     m_currentCommand 
= (wxNode 
*) NULL
; 
1790     m_commandEditMenu 
= (wxMenu 
*) NULL
; 
1793 wxCommandProcessor::~wxCommandProcessor() 
1798 // Pass a command to the processor. The processor calls Do(); 
1799 // if successful, is appended to the command history unless 
1800 // storeIt is FALSE. 
1801 bool wxCommandProcessor::Submit(wxCommand 
*command
, bool storeIt
) 
1803     bool success 
= command
->Do(); 
1804     if (success 
&& storeIt
) 
1806         if (m_commands
.Number() == m_maxNoCommands
) 
1808             wxNode 
*firstNode 
= m_commands
.First(); 
1809             wxCommand 
*firstCommand 
= (wxCommand 
*)firstNode
->Data(); 
1810             delete firstCommand
; 
1814         // Correct a bug: we must chop off the current 'branch' 
1815         // so that we're at the end of the command list. 
1816         if (!m_currentCommand
) 
1820             wxNode 
*node 
= m_currentCommand
->Next(); 
1823                 wxNode 
*next 
= node
->Next(); 
1824                 delete (wxCommand 
*)node
->Data(); 
1830         m_commands
.Append(command
); 
1831         m_currentCommand 
= m_commands
.Last(); 
1837 bool wxCommandProcessor::Undo() 
1839     if (m_currentCommand
) 
1841         wxCommand 
*command 
= (wxCommand 
*)m_currentCommand
->Data(); 
1842         if (command
->CanUndo()) 
1844             bool success 
= command
->Undo(); 
1847                 m_currentCommand 
= m_currentCommand
->Previous(); 
1856 bool wxCommandProcessor::Redo() 
1858     wxCommand 
*redoCommand 
= (wxCommand 
*) NULL
; 
1859     wxNode 
*redoNode 
= (wxNode 
*) NULL
; 
1860     if (m_currentCommand 
&& m_currentCommand
->Next()) 
1862         redoCommand 
= (wxCommand 
*)m_currentCommand
->Next()->Data(); 
1863         redoNode 
= m_currentCommand
->Next(); 
1867         if (m_commands
.Number() > 0) 
1869             redoCommand 
= (wxCommand 
*)m_commands
.First()->Data(); 
1870             redoNode 
= m_commands
.First(); 
1876         bool success 
= redoCommand
->Do(); 
1879             m_currentCommand 
= redoNode
; 
1887 bool wxCommandProcessor::CanUndo() const 
1889     if (m_currentCommand
) 
1890         return ((wxCommand 
*)m_currentCommand
->Data())->CanUndo(); 
1894 bool wxCommandProcessor::CanRedo() const 
1896     if ((m_currentCommand 
!= (wxNode
*) NULL
) && (m_currentCommand
->Next() == (wxNode
*) NULL
)) 
1899     if ((m_currentCommand 
!= (wxNode
*) NULL
) && (m_currentCommand
->Next() != (wxNode
*) NULL
)) 
1902     if ((m_currentCommand 
== (wxNode
*) NULL
) && (m_commands
.Number() > 0)) 
1908 void wxCommandProcessor::Initialize() 
1910     m_currentCommand 
= m_commands
.Last(); 
1914 void wxCommandProcessor::SetMenuStrings() 
1916     if (m_commandEditMenu
) 
1919         if (m_currentCommand
) 
1921             wxCommand 
*command 
= (wxCommand 
*)m_currentCommand
->Data(); 
1922             wxString 
commandName(command
->GetName()); 
1923             if (commandName 
== wxT("")) commandName 
= _("Unnamed command"); 
1924             bool canUndo 
= command
->CanUndo(); 
1926                 buf 
= wxString(_("&Undo ")) + commandName
; 
1928                 buf 
= wxString(_("Can't &Undo ")) + commandName
; 
1930             m_commandEditMenu
->SetLabel(wxID_UNDO
, buf
); 
1931             m_commandEditMenu
->Enable(wxID_UNDO
, canUndo
); 
1933             // We can redo, if we're not at the end of the history. 
1934             if (m_currentCommand
->Next()) 
1936                 wxCommand 
*redoCommand 
= (wxCommand 
*)m_currentCommand
->Next()->Data(); 
1937                 wxString 
redoCommandName(redoCommand
->GetName()); 
1938                 if (redoCommandName 
== wxT("")) redoCommandName 
= _("Unnamed command"); 
1939                 buf 
= wxString(_("&Redo ")) + redoCommandName
; 
1940                 m_commandEditMenu
->SetLabel(wxID_REDO
, buf
); 
1941                 m_commandEditMenu
->Enable(wxID_REDO
, TRUE
); 
1945                 m_commandEditMenu
->SetLabel(wxID_REDO
, _("&Redo")); 
1946                 m_commandEditMenu
->Enable(wxID_REDO
, FALSE
); 
1951             m_commandEditMenu
->SetLabel(wxID_UNDO
, _("&Undo")); 
1952             m_commandEditMenu
->Enable(wxID_UNDO
, FALSE
); 
1954             if (m_commands
.Number() == 0) 
1956                 m_commandEditMenu
->SetLabel(wxID_REDO
, _("&Redo")); 
1957                 m_commandEditMenu
->Enable(wxID_REDO
, FALSE
); 
1961                 // currentCommand is NULL but there are commands: this means that 
1962                 // we've undone to the start of the list, but can redo the first. 
1963                 wxCommand 
*redoCommand 
= (wxCommand 
*)m_commands
.First()->Data(); 
1964                 wxString 
redoCommandName(redoCommand
->GetName()); 
1965                 if (redoCommandName 
== wxT("")) redoCommandName 
= _("Unnamed command"); 
1966                 buf 
= wxString(_("&Redo ")) + redoCommandName
; 
1967                 m_commandEditMenu
->SetLabel(wxID_REDO
, buf
); 
1968                 m_commandEditMenu
->Enable(wxID_REDO
, TRUE
); 
1974 void wxCommandProcessor::ClearCommands() 
1976     wxNode 
*node 
= m_commands
.First(); 
1979         wxCommand 
*command 
= (wxCommand 
*)node
->Data(); 
1982         node 
= m_commands
.First(); 
1984     m_currentCommand 
= (wxNode 
*) NULL
; 
1987 // ---------------------------------------------------------------------------- 
1988 // File history processor 
1989 // ---------------------------------------------------------------------------- 
1991 wxFileHistory::wxFileHistory(int maxFiles
) 
1993     m_fileMaxFiles 
= maxFiles
; 
1995     m_fileHistory 
= new wxChar 
*[m_fileMaxFiles
]; 
1998 wxFileHistory::~wxFileHistory() 
2001     for (i 
= 0; i 
< m_fileHistoryN
; i
++) 
2002         delete[] m_fileHistory
[i
]; 
2003     delete[] m_fileHistory
; 
2006 // File history management 
2007 void wxFileHistory::AddFileToHistory(const wxString
& file
) 
2010     // Check we don't already have this file 
2011     for (i 
= 0; i 
< m_fileHistoryN
; i
++) 
2013         if (m_fileHistory
[i
] && wxString(m_fileHistory
[i
]) == file
) 
2017     // Add to the project file history: 
2018     // Move existing files (if any) down so we can insert file at beginning. 
2020     // First delete filename that has popped off the end of the array (if any) 
2021     if (m_fileHistoryN 
== m_fileMaxFiles
) 
2023         delete[] m_fileHistory
[m_fileMaxFiles
-1]; 
2024         m_fileHistory
[m_fileMaxFiles
-1] = (wxChar 
*) NULL
; 
2026     if (m_fileHistoryN 
< m_fileMaxFiles
) 
2028         wxNode
* node 
= m_fileMenus
.First(); 
2031             wxMenu
* menu 
= (wxMenu
*) node
->Data(); 
2032             if (m_fileHistoryN 
== 0) 
2033                 menu
->AppendSeparator(); 
2034             menu
->Append(wxID_FILE1
+m_fileHistoryN
, _("[EMPTY]")); 
2035             node 
= node
->Next(); 
2039     // Shuffle filenames down 
2040     for (i 
= (m_fileHistoryN
-1); i 
> 0; i
--) 
2042         m_fileHistory
[i
] = m_fileHistory
[i
-1]; 
2044     m_fileHistory
[0] = copystring(file
); 
2046     for (i 
= 0; i 
< m_fileHistoryN
; i
++) 
2047         if (m_fileHistory
[i
]) 
2050             buf
.Printf(s_MRUEntryFormat
, i
+1, m_fileHistory
[i
]); 
2051             wxNode
* node 
= m_fileMenus
.First(); 
2054                 wxMenu
* menu 
= (wxMenu
*) node
->Data(); 
2055                 menu
->SetLabel(wxID_FILE1
+i
, buf
); 
2056                 node 
= node
->Next(); 
2061 void wxFileHistory::RemoveFileFromHistory(int i
) 
2063     wxCHECK_RET( i 
< m_fileHistoryN
, 
2064                  wxT("invalid index in wxFileHistory::RemoveFileFromHistory") ); 
2066     wxNode
* node 
= m_fileMenus
.First(); 
2069         wxMenu
* menu 
= (wxMenu
*) node
->Data(); 
2071         // delete the element from the array (could use memmove() too...) 
2072         delete [] m_fileHistory
[i
]; 
2075         for ( j 
= i
; j 
< m_fileHistoryN 
- 1; j
++ ) 
2077             m_fileHistory
[j
] = m_fileHistory
[j 
+ 1]; 
2080         // shuffle filenames up 
2082         for ( j 
= i
; j 
< m_fileHistoryN 
- 1; j
++ ) 
2084             buf
.Printf(s_MRUEntryFormat
, j 
+ 1, m_fileHistory
[j
]); 
2085             menu
->SetLabel(wxID_FILE1 
+ j
, buf
); 
2088         node 
= node
->Next(); 
2090         // delete the last menu item which is unused now 
2091         menu
->Delete(wxID_FILE1 
+ m_fileHistoryN 
- 1); 
2093         // delete the last separator too if no more files are left 
2094         if ( m_fileHistoryN 
== 1 ) 
2096             wxMenuItemList::Node 
*node 
= menu
->GetMenuItems().GetLast(); 
2099                 wxMenuItem 
*menuItem 
= node
->GetData(); 
2100                 if ( menuItem
->IsSeparator() ) 
2102                     menu
->Delete(menuItem
); 
2104                 //else: should we search backwards for the last separator? 
2106             //else: menu is empty somehow 
2113 wxString 
wxFileHistory::GetHistoryFile(int i
) const 
2116     if ( i 
< m_fileHistoryN 
) 
2118         s 
= m_fileHistory
[i
]; 
2122         wxFAIL_MSG( wxT("bad index in wxFileHistory::GetHistoryFile") ); 
2128 void wxFileHistory::UseMenu(wxMenu 
*menu
) 
2130     if (!m_fileMenus
.Member(menu
)) 
2131         m_fileMenus
.Append(menu
); 
2134 void wxFileHistory::RemoveMenu(wxMenu 
*menu
) 
2136     m_fileMenus
.DeleteObject(menu
); 
2140 void wxFileHistory::Load(wxConfigBase
& config
) 
2144     buf
.Printf(wxT("file%d"), m_fileHistoryN
+1); 
2145     wxString historyFile
; 
2146     while ((m_fileHistoryN 
<= m_fileMaxFiles
) && config
.Read(buf
, &historyFile
) && (historyFile 
!= wxT(""))) 
2148         m_fileHistory
[m_fileHistoryN
] = copystring((const wxChar
*) historyFile
); 
2150         buf
.Printf(wxT("file%d"), m_fileHistoryN
+1); 
2151         historyFile 
= wxT(""); 
2156 void wxFileHistory::Save(wxConfigBase
& config
) 
2159     for (i 
= 0; i 
< m_fileHistoryN
; i
++) 
2162         buf
.Printf(wxT("file%d"), i
+1); 
2163         config
.Write(buf
, wxString(m_fileHistory
[i
])); 
2166 #endif // wxUSE_CONFIG 
2168 void wxFileHistory::AddFilesToMenu() 
2170     if (m_fileHistoryN 
> 0) 
2172         wxNode
* node 
= m_fileMenus
.First(); 
2175             wxMenu
* menu 
= (wxMenu
*) node
->Data(); 
2176             menu
->AppendSeparator(); 
2178             for (i 
= 0; i 
< m_fileHistoryN
; i
++) 
2180                 if (m_fileHistory
[i
]) 
2183                     buf
.Printf(s_MRUEntryFormat
, i
+1, m_fileHistory
[i
]); 
2184                     menu
->Append(wxID_FILE1
+i
, buf
); 
2187             node 
= node
->Next(); 
2192 void wxFileHistory::AddFilesToMenu(wxMenu
* menu
) 
2194     if (m_fileHistoryN 
> 0) 
2196         menu
->AppendSeparator(); 
2198         for (i 
= 0; i 
< m_fileHistoryN
; i
++) 
2200             if (m_fileHistory
[i
]) 
2203                 buf
.Printf(s_MRUEntryFormat
, i
+1, m_fileHistory
[i
]); 
2204                 menu
->Append(wxID_FILE1
+i
, buf
); 
2210 // ---------------------------------------------------------------------------- 
2211 // Permits compatibility with existing file formats and functions that 
2212 // manipulate files directly 
2213 // ---------------------------------------------------------------------------- 
2215 #if wxUSE_STD_IOSTREAM 
2216 bool wxTransferFileToStream(const wxString
& filename
, ostream
& stream
) 
2221     if ((fd1 
= wxFopen (filename
.fn_str(), _T("rb"))) == NULL
) 
2224     while ((ch 
= getc (fd1
)) != EOF
) 
2225         stream 
<< (unsigned char)ch
; 
2231 bool wxTransferStreamToFile(istream
& stream
, const wxString
& filename
) 
2236     if ((fd1 
= wxFopen (filename
.fn_str(), _T("wb"))) == NULL
) 
2241     while (!stream
.eof()) 
2251 bool wxTransferFileToStream(const wxString
& filename
, wxOutputStream
& stream
) 
2256     if ((fd1 
= wxFopen (filename
, wxT("rb"))) == NULL
) 
2259     while ((ch 
= getc (fd1
)) != EOF
) 
2260         stream
.PutC((char) ch
); 
2266 bool wxTransferStreamToFile(wxInputStream
& stream
, const wxString
& filename
) 
2271     if ((fd1 
= wxFopen (filename
, wxT("wb"))) == NULL
) 
2276     int len 
= stream
.StreamSize(); 
2277     // TODO: is this the correct test for EOF? 
2278     while (stream
.TellI() < (len 
- 1)) 
2288 #endif // wxUSE_DOC_VIEW_ARCHITECTURE