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 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
27 #if wxUSE_DOC_VIEW_ARCHITECTURE
29 #include "wx/docview.h"
33 #include "wx/string.h"
37 #include "wx/dialog.h"
39 #include "wx/filedlg.h"
42 #include "wx/msgdlg.h"
44 #include "wx/choicdlg.h"
50 #include "wx/filename.h"
53 #if wxUSE_PRINTING_ARCHITECTURE
54 #include "wx/prntbase.h"
55 #include "wx/printdlg.h"
58 #include "wx/confbase.h"
60 #include "wx/cmdproc.h"
61 #include "wx/tokenzr.h"
62 #include "wx/filename.h"
67 #if wxUSE_STD_IOSTREAM
68 #include "wx/ioswrap.h"
75 #include "wx/wfstream.h"
78 // ----------------------------------------------------------------------------
80 // ----------------------------------------------------------------------------
82 IMPLEMENT_ABSTRACT_CLASS(wxDocument
, wxEvtHandler
)
83 IMPLEMENT_ABSTRACT_CLASS(wxView
, wxEvtHandler
)
84 IMPLEMENT_ABSTRACT_CLASS(wxDocTemplate
, wxObject
)
85 IMPLEMENT_DYNAMIC_CLASS(wxDocManager
, wxEvtHandler
)
86 IMPLEMENT_CLASS(wxDocChildFrame
, wxFrame
)
87 IMPLEMENT_CLASS(wxDocParentFrame
, wxFrame
)
89 #if wxUSE_PRINTING_ARCHITECTURE
90 IMPLEMENT_DYNAMIC_CLASS(wxDocPrintout
, wxPrintout
)
93 IMPLEMENT_DYNAMIC_CLASS(wxFileHistory
, wxObject
)
95 // ----------------------------------------------------------------------------
96 // function prototypes
97 // ----------------------------------------------------------------------------
99 static wxWindow
* wxFindSuitableParent(void);
101 // ----------------------------------------------------------------------------
103 // ----------------------------------------------------------------------------
105 static const wxChar
*s_MRUEntryFormat
= wxT("&%d %s");
107 // ============================================================================
109 // ============================================================================
111 // ----------------------------------------------------------------------------
113 // ----------------------------------------------------------------------------
115 static wxString
FindExtension(const wxString
& path
)
118 wxSplitPath(path
, NULL
, NULL
, &ext
);
120 // VZ: extensions are considered not case sensitive - is this really a good
122 return ext
.MakeLower();
125 // ----------------------------------------------------------------------------
126 // Definition of wxDocument
127 // ----------------------------------------------------------------------------
129 wxDocument::wxDocument(wxDocument
*parent
)
131 m_documentModified
= false;
132 m_documentParent
= parent
;
133 m_documentTemplate
= (wxDocTemplate
*) NULL
;
134 m_commandProcessor
= (wxCommandProcessor
*) NULL
;
138 bool wxDocument::DeleteContents()
143 wxDocument::~wxDocument()
147 if (m_commandProcessor
)
148 delete m_commandProcessor
;
150 if (GetDocumentManager())
151 GetDocumentManager()->RemoveDocument(this);
153 // Not safe to do here, since it'll invoke virtual view functions
154 // expecting to see valid derived objects: and by the time we get here,
155 // we've called destructors higher up.
159 bool wxDocument::Close()
161 if (OnSaveModified())
162 return OnCloseDocument();
167 bool wxDocument::OnCloseDocument()
169 // Tell all views that we're about to close
176 // Note that this implicitly deletes the document when the last view is
178 bool wxDocument::DeleteAllViews()
180 wxDocManager
* manager
= GetDocumentManager();
182 // first check if all views agree to be closed
183 const wxList::iterator end
= m_documentViews
.end();
184 for ( wxList::iterator i
= m_documentViews
.begin(); i
!= end
; ++i
)
186 wxView
*view
= (wxView
*)*i
;
187 if ( !view
->Close() )
191 // all views agreed to close, now do close them
192 if ( m_documentViews
.empty() )
194 // normally the document would be implicitly deleted when the last view
195 // is, but if don't have any views, do it here instead
196 if ( manager
&& manager
->GetDocuments().Member(this) )
201 // as we delete elements we iterate over, don't use the usual "from
202 // begin to end" loop
205 wxView
*view
= (wxView
*)*m_documentViews
.begin();
207 bool isLastOne
= m_documentViews
.size() == 1;
209 // this always deletes the node implicitly and if this is the last
210 // view also deletes this object itself (also implicitly, great),
211 // so we can't test for m_documentViews.empty() after calling this!
222 wxView
*wxDocument::GetFirstView() const
224 if (m_documentViews
.GetCount() == 0)
225 return (wxView
*) NULL
;
226 return (wxView
*)m_documentViews
.GetFirst()->GetData();
229 wxDocManager
*wxDocument::GetDocumentManager() const
231 return (m_documentTemplate
? m_documentTemplate
->GetDocumentManager() : (wxDocManager
*) NULL
);
234 bool wxDocument::OnNewDocument()
236 if (!OnSaveModified())
239 if (OnCloseDocument()==false) return false;
242 SetDocumentSaved(false);
244 const wxString name
= GetDocumentManager()->MakeNewDocumentName();
246 SetFilename(name
, true);
251 bool wxDocument::Save()
253 if (!IsModified() && m_savedYet
)
256 if ( m_documentFile
.empty() || !m_savedYet
)
259 return OnSaveDocument(m_documentFile
);
262 bool wxDocument::SaveAs()
264 wxDocTemplate
*docTemplate
= GetDocumentTemplate();
268 #if defined(__WXMSW__) || defined(__WXGTK__) || defined(__WXMAC__)
269 wxString filter
= docTemplate
->GetDescription() + wxT(" (") + docTemplate
->GetFileFilter() + wxT(")|") + docTemplate
->GetFileFilter();
271 // Now see if there are some other template with identical view and document
272 // classes, whose filters may also be used.
274 if (docTemplate
->GetViewClassInfo() && docTemplate
->GetDocClassInfo())
276 wxList::compatibility_iterator node
= docTemplate
->GetDocumentManager()->GetTemplates().GetFirst();
279 wxDocTemplate
*t
= (wxDocTemplate
*) node
->GetData();
281 if (t
->IsVisible() && t
!= docTemplate
&&
282 t
->GetViewClassInfo() == docTemplate
->GetViewClassInfo() &&
283 t
->GetDocClassInfo() == docTemplate
->GetDocClassInfo())
285 // add a '|' to separate this filter from the previous one
286 if ( !filter
.empty() )
289 filter
<< t
->GetDescription() << wxT(" (") << t
->GetFileFilter() << wxT(") |")
290 << t
->GetFileFilter();
293 node
= node
->GetNext();
297 wxString filter
= docTemplate
->GetFileFilter() ;
299 wxString tmp
= wxFileSelector(_("Save as"),
300 docTemplate
->GetDirectory(),
301 wxFileNameFromPath(GetFilename()),
302 docTemplate
->GetDefaultExtension(),
304 wxFD_SAVE
| wxFD_OVERWRITE_PROMPT
,
305 GetDocumentWindow());
310 wxString
fileName(tmp
);
311 wxString path
, name
, ext
;
312 wxSplitPath(fileName
, & path
, & name
, & ext
);
316 fileName
+= wxT(".");
317 fileName
+= docTemplate
->GetDefaultExtension();
320 SetFilename(fileName
);
321 SetTitle(wxFileNameFromPath(fileName
));
323 // Notify the views that the filename has changed
324 wxList::compatibility_iterator node
= m_documentViews
.GetFirst();
327 wxView
*view
= (wxView
*)node
->GetData();
328 view
->OnChangeFilename();
329 node
= node
->GetNext();
332 // Files that were not saved correctly are not added to the FileHistory.
333 if (!OnSaveDocument(m_documentFile
))
336 // A file that doesn't use the default extension of its document template cannot be opened
337 // via the FileHistory, so we do not add it.
338 if (docTemplate
->FileMatchesTemplate(fileName
))
340 GetDocumentManager()->AddFileToHistory(fileName
);
344 // The user will probably not be able to open the file again, so
345 // we could warn about the wrong file-extension here.
350 bool wxDocument::OnSaveDocument(const wxString
& file
)
355 if ( !DoSaveDocument(file
) )
360 SetDocumentSaved(true);
362 wxFileName
fn(file
) ;
363 fn
.MacSetDefaultTypeAndCreator() ;
368 bool wxDocument::OnOpenDocument(const wxString
& file
)
370 if (!OnSaveModified())
373 if ( !DoOpenDocument(file
) )
376 SetFilename(file
, true);
385 #if wxUSE_STD_IOSTREAM
386 wxSTD istream
& wxDocument::LoadObject(wxSTD istream
& stream
)
388 wxInputStream
& wxDocument::LoadObject(wxInputStream
& stream
)
394 #if wxUSE_STD_IOSTREAM
395 wxSTD ostream
& wxDocument::SaveObject(wxSTD ostream
& stream
)
397 wxOutputStream
& wxDocument::SaveObject(wxOutputStream
& stream
)
403 bool wxDocument::Revert()
409 // Get title, or filename if no title, else unnamed
410 #if WXWIN_COMPATIBILITY_2_8
411 bool wxDocument::GetPrintableName(wxString
& buf
) const
413 // this function can not only be overridden by the user code but also
414 // called by it so we need to ensure that we return the same thing as
415 // GetUserReadableName() but we can't call it because this would result in
416 // an infinite recursion, hence we use the helper DoGetUserReadableName()
417 buf
= DoGetUserReadableName();
421 #endif // WXWIN_COMPATIBILITY_2_8
423 wxString
wxDocument::GetUserReadableName() const
425 #if WXWIN_COMPATIBILITY_2_8
426 // we need to call the old virtual function to ensure that the overridden
427 // version of it is still called
429 if ( GetPrintableName(name
) )
431 #endif // WXWIN_COMPATIBILITY_2_8
433 return DoGetUserReadableName();
436 wxString
wxDocument::DoGetUserReadableName() const
438 if ( !m_documentTitle
.empty() )
439 return m_documentTitle
;
441 if ( !m_documentFile
.empty() )
442 return wxFileNameFromPath(m_documentFile
);
447 wxWindow
*wxDocument::GetDocumentWindow() const
449 wxView
*view
= GetFirstView();
451 return view
->GetFrame();
453 return wxTheApp
->GetTopWindow();
456 wxCommandProcessor
*wxDocument::OnCreateCommandProcessor()
458 return new wxCommandProcessor
;
461 // true if safe to close
462 bool wxDocument::OnSaveModified()
466 wxString title
= GetUserReadableName();
469 if (!wxTheApp
->GetAppName().empty())
470 msgTitle
= wxTheApp
->GetAppName();
472 msgTitle
= wxString(_("Warning"));
475 prompt
.Printf(_("Do you want to save changes to document %s?"), title
);
476 int res
= wxMessageBox(prompt
, msgTitle
,
477 wxYES_NO
|wxCANCEL
|wxICON_QUESTION
,
478 GetDocumentWindow());
484 else if (res
== wxYES
)
486 else if (res
== wxCANCEL
)
492 bool wxDocument::Draw(wxDC
& WXUNUSED(context
))
497 bool wxDocument::AddView(wxView
*view
)
499 if (!m_documentViews
.Member(view
))
501 m_documentViews
.Append(view
);
507 bool wxDocument::RemoveView(wxView
*view
)
509 (void)m_documentViews
.DeleteObject(view
);
514 bool wxDocument::OnCreate(const wxString
& WXUNUSED(path
), long flags
)
516 if (GetDocumentTemplate()->CreateView(this, flags
))
522 // Called after a view is added or removed.
523 // The default implementation deletes the document if
524 // there are no more views.
525 void wxDocument::OnChangedViewList()
527 if (m_documentViews
.GetCount() == 0)
529 if (OnSaveModified())
536 void wxDocument::UpdateAllViews(wxView
*sender
, wxObject
*hint
)
538 wxList::compatibility_iterator node
= m_documentViews
.GetFirst();
541 wxView
*view
= (wxView
*)node
->GetData();
543 view
->OnUpdate(sender
, hint
);
544 node
= node
->GetNext();
548 void wxDocument::NotifyClosing()
550 wxList::compatibility_iterator node
= m_documentViews
.GetFirst();
553 wxView
*view
= (wxView
*)node
->GetData();
554 view
->OnClosingDocument();
555 node
= node
->GetNext();
559 void wxDocument::SetFilename(const wxString
& filename
, bool notifyViews
)
561 m_documentFile
= filename
;
564 // Notify the views that the filename has changed
565 wxList::compatibility_iterator node
= m_documentViews
.GetFirst();
568 wxView
*view
= (wxView
*)node
->GetData();
569 view
->OnChangeFilename();
570 node
= node
->GetNext();
575 bool wxDocument::DoSaveDocument(const wxString
& file
)
578 if (!wxTheApp
->GetAppName().empty())
579 msgTitle
= wxTheApp
->GetAppName();
581 msgTitle
= wxString(_("File error"));
583 #if wxUSE_STD_IOSTREAM
584 wxSTD ofstream
store(file
.mb_str(), wxSTD
ios::binary
);
585 if (store
.fail() || store
.bad())
587 wxFileOutputStream
store(file
);
588 if (store
.GetLastError() != wxSTREAM_NO_ERROR
)
591 (void)wxMessageBox(_("Sorry, could not open this file for saving."), msgTitle
, wxOK
| wxICON_EXCLAMATION
,
592 GetDocumentWindow());
596 if (!SaveObject(store
))
598 (void)wxMessageBox(_("Sorry, could not save this file."), msgTitle
, wxOK
| wxICON_EXCLAMATION
,
599 GetDocumentWindow());
607 bool wxDocument::DoOpenDocument(const wxString
& file
)
609 #if wxUSE_STD_IOSTREAM
610 wxSTD ifstream
store(file
.mb_str(), wxSTD
ios::binary
);
611 if (!store
.fail() && !store
.bad())
613 wxFileInputStream
store(file
);
614 if (store
.GetLastError() == wxSTREAM_NO_ERROR
)
617 #if wxUSE_STD_IOSTREAM
619 if ( !!store
|| store
.eof() )
621 int res
= LoadObject(store
).GetLastError();
622 if ( res
== wxSTREAM_NO_ERROR
|| res
== wxSTREAM_EOF
)
627 wxLogError(_("Sorry, could not open this file."));
632 // ----------------------------------------------------------------------------
634 // ----------------------------------------------------------------------------
638 m_viewDocument
= (wxDocument
*) NULL
;
640 m_viewFrame
= (wxFrame
*) NULL
;
645 GetDocumentManager()->ActivateView(this, false);
646 m_viewDocument
->RemoveView(this);
649 // Extend event processing to search the document's event table
650 bool wxView::ProcessEvent(wxEvent
& event
)
652 if ( !GetDocument() || !GetDocument()->ProcessEvent(event
) )
653 return wxEvtHandler::ProcessEvent(event
);
658 void wxView::OnActivateView(bool WXUNUSED(activate
), wxView
*WXUNUSED(activeView
), wxView
*WXUNUSED(deactiveView
))
662 void wxView::OnPrint(wxDC
*dc
, wxObject
*WXUNUSED(info
))
667 void wxView::OnUpdate(wxView
*WXUNUSED(sender
), wxObject
*WXUNUSED(hint
))
671 void wxView::OnChangeFilename()
673 // GetFrame can return wxWindow rather than wxTopLevelWindow due to
674 // generic MDI implementation so use SetLabel rather than SetTitle.
675 // It should cause SetTitle() for top level windows.
676 wxWindow
*win
= GetFrame();
679 wxDocument
*doc
= GetDocument();
682 win
->SetLabel(doc
->GetUserReadableName());
685 void wxView::SetDocument(wxDocument
*doc
)
687 m_viewDocument
= doc
;
692 bool wxView::Close(bool deleteWindow
)
694 if (OnClose(deleteWindow
))
700 void wxView::Activate(bool activate
)
702 if (GetDocument() && GetDocumentManager())
704 OnActivateView(activate
, this, GetDocumentManager()->GetCurrentView());
705 GetDocumentManager()->ActivateView(this, activate
);
709 bool wxView::OnClose(bool WXUNUSED(deleteWindow
))
711 return GetDocument() ? GetDocument()->Close() : true;
714 #if wxUSE_PRINTING_ARCHITECTURE
715 wxPrintout
*wxView::OnCreatePrintout()
717 return new wxDocPrintout(this);
719 #endif // wxUSE_PRINTING_ARCHITECTURE
721 // ----------------------------------------------------------------------------
723 // ----------------------------------------------------------------------------
725 wxDocTemplate::wxDocTemplate(wxDocManager
*manager
,
726 const wxString
& descr
,
727 const wxString
& filter
,
730 const wxString
& docTypeName
,
731 const wxString
& viewTypeName
,
732 wxClassInfo
*docClassInfo
,
733 wxClassInfo
*viewClassInfo
,
736 m_documentManager
= manager
;
737 m_description
= descr
;
740 m_fileFilter
= filter
;
742 m_docTypeName
= docTypeName
;
743 m_viewTypeName
= viewTypeName
;
744 m_documentManager
->AssociateTemplate(this);
746 m_docClassInfo
= docClassInfo
;
747 m_viewClassInfo
= viewClassInfo
;
750 wxDocTemplate::~wxDocTemplate()
752 m_documentManager
->DisassociateTemplate(this);
755 // Tries to dynamically construct an object of the right class.
756 wxDocument
*wxDocTemplate::CreateDocument(const wxString
& path
, long flags
)
758 wxDocument
*doc
= DoCreateDocument();
760 return (wxDocument
*) NULL
;
762 if (InitDocument(doc
, path
, flags
))
768 return (wxDocument
*) NULL
;
772 bool wxDocTemplate::InitDocument(wxDocument
* doc
, const wxString
& path
, long flags
)
774 doc
->SetFilename(path
);
775 doc
->SetDocumentTemplate(this);
776 GetDocumentManager()->AddDocument(doc
);
777 doc
->SetCommandProcessor(doc
->OnCreateCommandProcessor());
779 if (doc
->OnCreate(path
, flags
))
783 if (GetDocumentManager()->GetDocuments().Member(doc
))
784 doc
->DeleteAllViews();
789 wxView
*wxDocTemplate::CreateView(wxDocument
*doc
, long flags
)
791 wxView
*view
= DoCreateView();
793 return (wxView
*) NULL
;
795 view
->SetDocument(doc
);
796 if (view
->OnCreate(doc
, flags
))
803 return (wxView
*) NULL
;
807 // The default (very primitive) format detection: check is the extension is
808 // that of the template
809 bool wxDocTemplate::FileMatchesTemplate(const wxString
& path
)
811 wxStringTokenizer
parser (GetFileFilter(), wxT(";"));
812 wxString anything
= wxT ("*");
813 while (parser
.HasMoreTokens())
815 wxString filter
= parser
.GetNextToken();
816 wxString filterExt
= FindExtension (filter
);
817 if ( filter
.IsSameAs (anything
) ||
818 filterExt
.IsSameAs (anything
) ||
819 filterExt
.IsSameAs (FindExtension (path
)) )
822 return GetDefaultExtension().IsSameAs(FindExtension(path
));
825 wxDocument
*wxDocTemplate::DoCreateDocument()
828 return (wxDocument
*) NULL
;
830 return (wxDocument
*)m_docClassInfo
->CreateObject();
833 wxView
*wxDocTemplate::DoCreateView()
835 if (!m_viewClassInfo
)
836 return (wxView
*) NULL
;
838 return (wxView
*)m_viewClassInfo
->CreateObject();
841 // ----------------------------------------------------------------------------
843 // ----------------------------------------------------------------------------
845 BEGIN_EVENT_TABLE(wxDocManager
, wxEvtHandler
)
846 EVT_MENU(wxID_OPEN
, wxDocManager::OnFileOpen
)
847 EVT_MENU(wxID_CLOSE
, wxDocManager::OnFileClose
)
848 EVT_MENU(wxID_CLOSE_ALL
, wxDocManager::OnFileCloseAll
)
849 EVT_MENU(wxID_REVERT
, wxDocManager::OnFileRevert
)
850 EVT_MENU(wxID_NEW
, wxDocManager::OnFileNew
)
851 EVT_MENU(wxID_SAVE
, wxDocManager::OnFileSave
)
852 EVT_MENU(wxID_SAVEAS
, wxDocManager::OnFileSaveAs
)
853 EVT_MENU(wxID_UNDO
, wxDocManager::OnUndo
)
854 EVT_MENU(wxID_REDO
, wxDocManager::OnRedo
)
856 EVT_UPDATE_UI(wxID_OPEN
, wxDocManager::OnUpdateFileOpen
)
857 EVT_UPDATE_UI(wxID_CLOSE
, wxDocManager::OnUpdateFileClose
)
858 EVT_UPDATE_UI(wxID_CLOSE_ALL
, wxDocManager::OnUpdateFileClose
)
859 EVT_UPDATE_UI(wxID_REVERT
, wxDocManager::OnUpdateFileRevert
)
860 EVT_UPDATE_UI(wxID_NEW
, wxDocManager::OnUpdateFileNew
)
861 EVT_UPDATE_UI(wxID_SAVE
, wxDocManager::OnUpdateFileSave
)
862 EVT_UPDATE_UI(wxID_SAVEAS
, wxDocManager::OnUpdateFileSaveAs
)
863 EVT_UPDATE_UI(wxID_UNDO
, wxDocManager::OnUpdateUndo
)
864 EVT_UPDATE_UI(wxID_REDO
, wxDocManager::OnUpdateRedo
)
866 #if wxUSE_PRINTING_ARCHITECTURE
867 EVT_MENU(wxID_PRINT
, wxDocManager::OnPrint
)
868 EVT_MENU(wxID_PREVIEW
, wxDocManager::OnPreview
)
870 EVT_UPDATE_UI(wxID_PRINT
, wxDocManager::OnUpdatePrint
)
871 EVT_UPDATE_UI(wxID_PREVIEW
, wxDocManager::OnUpdatePreview
)
875 wxDocManager
* wxDocManager::sm_docManager
= (wxDocManager
*) NULL
;
877 wxDocManager::wxDocManager(long flags
, bool initialize
)
879 m_defaultDocumentNameCounter
= 1;
881 m_currentView
= (wxView
*) NULL
;
882 m_maxDocsOpen
= 10000;
883 m_fileHistory
= (wxFileHistory
*) NULL
;
886 sm_docManager
= this;
889 wxDocManager::~wxDocManager()
893 delete m_fileHistory
;
894 sm_docManager
= (wxDocManager
*) NULL
;
897 // closes the specified document
898 bool wxDocManager::CloseDocument(wxDocument
* doc
, bool force
)
900 if (doc
->Close() || force
)
902 // Implicitly deletes the document when
903 // the last view is deleted
904 doc
->DeleteAllViews();
906 // Check we're really deleted
907 if (m_docs
.Member(doc
))
915 bool wxDocManager::CloseDocuments(bool force
)
917 wxList::compatibility_iterator node
= m_docs
.GetFirst();
920 wxDocument
*doc
= (wxDocument
*)node
->GetData();
921 wxList::compatibility_iterator next
= node
->GetNext();
923 if (!CloseDocument(doc
, force
))
926 // This assumes that documents are not connected in
927 // any way, i.e. deleting one document does NOT
934 bool wxDocManager::Clear(bool force
)
936 if (!CloseDocuments(force
))
939 m_currentView
= NULL
;
941 wxList::compatibility_iterator node
= m_templates
.GetFirst();
944 wxDocTemplate
*templ
= (wxDocTemplate
*) node
->GetData();
945 wxList::compatibility_iterator next
= node
->GetNext();
952 bool wxDocManager::Initialize()
954 m_fileHistory
= OnCreateFileHistory();
958 wxFileHistory
*wxDocManager::OnCreateFileHistory()
960 return new wxFileHistory
;
963 void wxDocManager::OnFileClose(wxCommandEvent
& WXUNUSED(event
))
965 wxDocument
*doc
= GetCurrentDocument();
970 doc
->DeleteAllViews();
971 if (m_docs
.Member(doc
))
976 void wxDocManager::OnFileCloseAll(wxCommandEvent
& WXUNUSED(event
))
978 CloseDocuments(false);
981 void wxDocManager::OnFileNew(wxCommandEvent
& WXUNUSED(event
))
983 CreateDocument( wxEmptyString
, wxDOC_NEW
);
986 void wxDocManager::OnFileOpen(wxCommandEvent
& WXUNUSED(event
))
988 if ( !CreateDocument( wxEmptyString
, 0) )
994 void wxDocManager::OnFileRevert(wxCommandEvent
& WXUNUSED(event
))
996 wxDocument
*doc
= GetCurrentDocument();
1002 void wxDocManager::OnFileSave(wxCommandEvent
& WXUNUSED(event
))
1004 wxDocument
*doc
= GetCurrentDocument();
1010 void wxDocManager::OnFileSaveAs(wxCommandEvent
& WXUNUSED(event
))
1012 wxDocument
*doc
= GetCurrentDocument();
1018 void wxDocManager::OnPrint(wxCommandEvent
& WXUNUSED(event
))
1020 #if wxUSE_PRINTING_ARCHITECTURE
1021 wxView
*view
= GetCurrentView();
1025 wxPrintout
*printout
= view
->OnCreatePrintout();
1029 printer
.Print(view
->GetFrame(), printout
, true);
1033 #endif // wxUSE_PRINTING_ARCHITECTURE
1036 void wxDocManager::OnPreview(wxCommandEvent
& WXUNUSED(event
))
1038 #if wxUSE_PRINTING_ARCHITECTURE
1039 wxView
*view
= GetCurrentView();
1043 wxPrintout
*printout
= view
->OnCreatePrintout();
1046 // Pass two printout objects: for preview, and possible printing.
1047 wxPrintPreviewBase
*preview
= new wxPrintPreview(printout
, view
->OnCreatePrintout());
1048 if ( !preview
->Ok() )
1051 wxMessageBox( _("Sorry, print preview needs a printer to be installed.") );
1055 wxPreviewFrame
*frame
= new wxPreviewFrame(preview
, (wxFrame
*)wxTheApp
->GetTopWindow(), _("Print Preview"),
1056 wxPoint(100, 100), wxSize(600, 650));
1057 frame
->Centre(wxBOTH
);
1058 frame
->Initialize();
1061 #endif // wxUSE_PRINTING_ARCHITECTURE
1064 void wxDocManager::OnUndo(wxCommandEvent
& event
)
1066 wxDocument
*doc
= GetCurrentDocument();
1069 if (doc
->GetCommandProcessor())
1070 doc
->GetCommandProcessor()->Undo();
1075 void wxDocManager::OnRedo(wxCommandEvent
& event
)
1077 wxDocument
*doc
= GetCurrentDocument();
1080 if (doc
->GetCommandProcessor())
1081 doc
->GetCommandProcessor()->Redo();
1086 // Handlers for UI update commands
1088 void wxDocManager::OnUpdateFileOpen(wxUpdateUIEvent
& event
)
1090 event
.Enable( true );
1093 void wxDocManager::OnUpdateFileClose(wxUpdateUIEvent
& event
)
1095 wxDocument
*doc
= GetCurrentDocument();
1096 event
.Enable( (doc
!= (wxDocument
*) NULL
) );
1099 void wxDocManager::OnUpdateFileRevert(wxUpdateUIEvent
& event
)
1101 wxDocument
*doc
= GetCurrentDocument();
1102 event
.Enable( (doc
!= (wxDocument
*) NULL
) );
1105 void wxDocManager::OnUpdateFileNew(wxUpdateUIEvent
& event
)
1107 event
.Enable( true );
1110 void wxDocManager::OnUpdateFileSave(wxUpdateUIEvent
& event
)
1112 wxDocument
*doc
= GetCurrentDocument();
1113 event
.Enable( doc
&& doc
->IsModified() );
1116 void wxDocManager::OnUpdateFileSaveAs(wxUpdateUIEvent
& event
)
1118 wxDocument
*doc
= GetCurrentDocument();
1119 event
.Enable( (doc
!= (wxDocument
*) NULL
) );
1122 void wxDocManager::OnUpdateUndo(wxUpdateUIEvent
& event
)
1124 wxDocument
*doc
= GetCurrentDocument();
1126 event
.Enable(false);
1127 else if (!doc
->GetCommandProcessor())
1131 event
.Enable( doc
->GetCommandProcessor()->CanUndo() );
1132 doc
->GetCommandProcessor()->SetMenuStrings();
1136 void wxDocManager::OnUpdateRedo(wxUpdateUIEvent
& event
)
1138 wxDocument
*doc
= GetCurrentDocument();
1140 event
.Enable(false);
1141 else if (!doc
->GetCommandProcessor())
1145 event
.Enable( doc
->GetCommandProcessor()->CanRedo() );
1146 doc
->GetCommandProcessor()->SetMenuStrings();
1150 void wxDocManager::OnUpdatePrint(wxUpdateUIEvent
& event
)
1152 wxDocument
*doc
= GetCurrentDocument();
1153 event
.Enable( (doc
!= (wxDocument
*) NULL
) );
1156 void wxDocManager::OnUpdatePreview(wxUpdateUIEvent
& event
)
1158 wxDocument
*doc
= GetCurrentDocument();
1159 event
.Enable( (doc
!= (wxDocument
*) NULL
) );
1162 wxView
*wxDocManager::GetCurrentView() const
1165 return m_currentView
;
1166 if (m_docs
.GetCount() == 1)
1168 wxDocument
* doc
= (wxDocument
*) m_docs
.GetFirst()->GetData();
1169 return doc
->GetFirstView();
1171 return (wxView
*) NULL
;
1174 // Extend event processing to search the view's event table
1175 bool wxDocManager::ProcessEvent(wxEvent
& event
)
1177 wxView
* view
= GetCurrentView();
1180 if (view
->ProcessEvent(event
))
1183 return wxEvtHandler::ProcessEvent(event
);
1186 wxDocument
*wxDocManager::CreateDocument(const wxString
& path
, long flags
)
1188 wxDocTemplate
**templates
= new wxDocTemplate
*[m_templates
.GetCount()];
1191 for (size_t i
= 0; i
< m_templates
.GetCount(); i
++)
1193 wxDocTemplate
*temp
= (wxDocTemplate
*)(m_templates
.Item(i
)->GetData());
1194 if (temp
->IsVisible())
1196 templates
[n
] = temp
;
1203 return (wxDocument
*) NULL
;
1206 wxDocument
* docToClose
= NULL
;
1208 // If we've reached the max number of docs, close the
1210 if ( (int)GetDocuments().GetCount() >= m_maxDocsOpen
)
1212 wxDocument
*doc
= (wxDocument
*)GetDocuments().GetFirst()->GetData();
1216 // New document: user chooses a template, unless there's only one.
1217 if (flags
& wxDOC_NEW
)
1223 if (!CloseDocument(docToClose
, false))
1230 wxDocTemplate
*temp
= templates
[0];
1232 wxDocument
*newDoc
= temp
->CreateDocument(path
, flags
);
1236 newDoc
->SetDocumentName(temp
->GetDocumentName());
1237 newDoc
->SetDocumentTemplate(temp
);
1238 if (!newDoc
->OnNewDocument() )
1240 // Document is implicitly deleted by DeleteAllViews
1241 newDoc
->DeleteAllViews();
1248 wxDocTemplate
*temp
= SelectDocumentType(templates
, n
);
1254 if (!CloseDocument(docToClose
, false))
1260 wxDocument
*newDoc
= temp
->CreateDocument(path
, flags
);
1264 newDoc
->SetDocumentName(temp
->GetDocumentName());
1265 newDoc
->SetDocumentTemplate(temp
);
1266 if (!newDoc
->OnNewDocument() )
1268 // Document is implicitly deleted by DeleteAllViews
1269 newDoc
->DeleteAllViews();
1276 return (wxDocument
*) NULL
;
1279 // Existing document
1280 wxDocTemplate
*temp
;
1282 wxString path2
= path
;
1284 if (flags
& wxDOC_SILENT
)
1286 temp
= FindTemplateForPath(path2
);
1289 // Since we do not add files with non-default extensions to the FileHistory this
1290 // can only happen if the application changes the allowed templates in runtime.
1291 (void)wxMessageBox(_("Sorry, the format for this file is unknown."),
1293 wxOK
| wxICON_EXCLAMATION
, wxFindSuitableParent());
1297 temp
= SelectDocumentPath(templates
, n
, path2
, flags
);
1305 if (!CloseDocument(docToClose
, false))
1311 //see if this file is already open
1312 for (size_t i
= 0; i
< GetDocuments().GetCount(); ++i
)
1314 wxDocument
* currentDoc
= (wxDocument
*)(GetDocuments().Item(i
)->GetData());
1316 //file paths are case-insensitive on Windows
1317 if (path2
.CmpNoCase(currentDoc
->GetFilename()) == 0)
1319 if (path2
.Cmp(currentDoc
->GetFilename()) == 0)
1322 //file already open. Just activate it and return
1323 if (currentDoc
->GetFirstView())
1325 ActivateView(currentDoc
->GetFirstView(), true);
1326 if (currentDoc
->GetDocumentWindow())
1327 currentDoc
->GetDocumentWindow()->SetFocus();
1333 wxDocument
*newDoc
= temp
->CreateDocument(path2
, flags
);
1336 newDoc
->SetDocumentName(temp
->GetDocumentName());
1337 newDoc
->SetDocumentTemplate(temp
);
1338 if (!newDoc
->OnOpenDocument(path2
))
1340 newDoc
->DeleteAllViews();
1341 // delete newDoc; // Implicitly deleted by DeleteAllViews
1342 return (wxDocument
*) NULL
;
1344 // A file that doesn't use the default extension of its document
1345 // template cannot be opened via the FileHistory, so we do not
1347 if (temp
->FileMatchesTemplate(path2
))
1348 AddFileToHistory(path2
);
1353 return (wxDocument
*) NULL
;
1356 wxView
*wxDocManager::CreateView(wxDocument
*doc
, long flags
)
1358 wxDocTemplate
**templates
= new wxDocTemplate
*[m_templates
.GetCount()];
1361 for (size_t i
= 0; i
< m_templates
.GetCount(); i
++)
1363 wxDocTemplate
*temp
= (wxDocTemplate
*)(m_templates
.Item(i
)->GetData());
1364 if (temp
->IsVisible())
1366 if (temp
->GetDocumentName() == doc
->GetDocumentName())
1368 templates
[n
] = temp
;
1376 return (wxView
*) NULL
;
1380 wxDocTemplate
*temp
= templates
[0];
1382 wxView
*view
= temp
->CreateView(doc
, flags
);
1384 view
->SetViewName(temp
->GetViewName());
1388 wxDocTemplate
*temp
= SelectViewType(templates
, n
);
1392 wxView
*view
= temp
->CreateView(doc
, flags
);
1394 view
->SetViewName(temp
->GetViewName());
1398 return (wxView
*) NULL
;
1401 // Not yet implemented
1402 void wxDocManager::DeleteTemplate(wxDocTemplate
*WXUNUSED(temp
), long WXUNUSED(flags
))
1406 // Not yet implemented
1407 bool wxDocManager::FlushDoc(wxDocument
*WXUNUSED(doc
))
1412 wxDocument
*wxDocManager::GetCurrentDocument() const
1414 wxView
*view
= GetCurrentView();
1416 return view
->GetDocument();
1418 return (wxDocument
*) NULL
;
1421 // Make a default name for a new document
1422 #if WXWIN_COMPATIBILITY_2_8
1423 bool wxDocManager::MakeDefaultName(wxString
& WXUNUSED(name
))
1425 // we consider that this function can only be overridden by the user code,
1426 // not called by it as it only makes sense to call it internally, so we
1427 // don't bother to return anything from here
1430 #endif // WXWIN_COMPATIBILITY_2_8
1432 wxString
wxDocManager::MakeNewDocumentName()
1436 #if WXWIN_COMPATIBILITY_2_8
1437 if ( !MakeDefaultName(name
) )
1438 #endif // WXWIN_COMPATIBILITY_2_8
1440 name
.Printf(_("unnamed%d"), m_defaultDocumentNameCounter
);
1441 m_defaultDocumentNameCounter
++;
1447 // Make a frame title (override this to do something different)
1448 // If docName is empty, a document is not currently active.
1449 wxString
wxDocManager::MakeFrameTitle(wxDocument
* doc
)
1451 wxString appName
= wxTheApp
->GetAppName();
1457 wxString docName
= doc
->GetUserReadableName();
1458 title
= docName
+ wxString(_(" - ")) + appName
;
1464 // Not yet implemented
1465 wxDocTemplate
*wxDocManager::MatchTemplate(const wxString
& WXUNUSED(path
))
1467 return (wxDocTemplate
*) NULL
;
1470 // File history management
1471 void wxDocManager::AddFileToHistory(const wxString
& file
)
1474 m_fileHistory
->AddFileToHistory(file
);
1477 void wxDocManager::RemoveFileFromHistory(size_t i
)
1480 m_fileHistory
->RemoveFileFromHistory(i
);
1483 wxString
wxDocManager::GetHistoryFile(size_t i
) const
1488 histFile
= m_fileHistory
->GetHistoryFile(i
);
1493 void wxDocManager::FileHistoryUseMenu(wxMenu
*menu
)
1496 m_fileHistory
->UseMenu(menu
);
1499 void wxDocManager::FileHistoryRemoveMenu(wxMenu
*menu
)
1502 m_fileHistory
->RemoveMenu(menu
);
1506 void wxDocManager::FileHistoryLoad(wxConfigBase
& config
)
1509 m_fileHistory
->Load(config
);
1512 void wxDocManager::FileHistorySave(wxConfigBase
& config
)
1515 m_fileHistory
->Save(config
);
1519 void wxDocManager::FileHistoryAddFilesToMenu(wxMenu
* menu
)
1522 m_fileHistory
->AddFilesToMenu(menu
);
1525 void wxDocManager::FileHistoryAddFilesToMenu()
1528 m_fileHistory
->AddFilesToMenu();
1531 size_t wxDocManager::GetHistoryFilesCount() const
1533 return m_fileHistory
? m_fileHistory
->GetCount() : 0;
1537 // Find out the document template via matching in the document file format
1538 // against that of the template
1539 wxDocTemplate
*wxDocManager::FindTemplateForPath(const wxString
& path
)
1541 wxDocTemplate
*theTemplate
= (wxDocTemplate
*) NULL
;
1543 // Find the template which this extension corresponds to
1544 for (size_t i
= 0; i
< m_templates
.GetCount(); i
++)
1546 wxDocTemplate
*temp
= (wxDocTemplate
*)m_templates
.Item(i
)->GetData();
1547 if ( temp
->FileMatchesTemplate(path
) )
1556 // Try to get a more suitable parent frame than the top window,
1557 // for selection dialogs. Otherwise you may get an unexpected
1558 // window being activated when a dialog is shown.
1559 static wxWindow
* wxFindSuitableParent()
1561 wxWindow
* parent
= wxTheApp
->GetTopWindow();
1563 wxWindow
* focusWindow
= wxWindow::FindFocus();
1566 while (focusWindow
&&
1567 !focusWindow
->IsKindOf(CLASSINFO(wxDialog
)) &&
1568 !focusWindow
->IsKindOf(CLASSINFO(wxFrame
)))
1570 focusWindow
= focusWindow
->GetParent();
1573 parent
= focusWindow
;
1578 // Prompts user to open a file, using file specs in templates.
1579 // Must extend the file selector dialog or implement own; OR
1580 // match the extension to the template extension.
1582 wxDocTemplate
*wxDocManager::SelectDocumentPath(wxDocTemplate
**templates
,
1583 #if defined(__WXMSW__) || defined(__WXGTK__) || defined(__WXMAC__)
1586 int WXUNUSED(noTemplates
),
1589 long WXUNUSED(flags
),
1590 bool WXUNUSED(save
))
1592 // We can only have multiple filters in Windows and GTK
1593 #if defined(__WXMSW__) || defined(__WXGTK__) || defined(__WXMAC__)
1597 for (i
= 0; i
< noTemplates
; i
++)
1599 if (templates
[i
]->IsVisible())
1601 // add a '|' to separate this filter from the previous one
1602 if ( !descrBuf
.empty() )
1603 descrBuf
<< wxT('|');
1605 descrBuf
<< templates
[i
]->GetDescription()
1606 << wxT(" (") << templates
[i
]->GetFileFilter() << wxT(") |")
1607 << templates
[i
]->GetFileFilter();
1611 wxString descrBuf
= wxT("*.*");
1614 int FilterIndex
= -1;
1616 wxWindow
* parent
= wxFindSuitableParent();
1618 wxString pathTmp
= wxFileSelectorEx(_("Select a file"),
1626 wxDocTemplate
*theTemplate
= (wxDocTemplate
*)NULL
;
1627 if (!pathTmp
.empty())
1629 if (!wxFileExists(pathTmp
))
1632 if (!wxTheApp
->GetAppName().empty())
1633 msgTitle
= wxTheApp
->GetAppName();
1635 msgTitle
= wxString(_("File error"));
1637 (void)wxMessageBox(_("Sorry, could not open this file."), msgTitle
, wxOK
| wxICON_EXCLAMATION
,
1640 path
= wxEmptyString
;
1641 return (wxDocTemplate
*) NULL
;
1643 m_lastDirectory
= wxPathOnly(pathTmp
);
1647 // first choose the template using the extension, if this fails (i.e.
1648 // wxFileSelectorEx() didn't fill it), then use the path
1649 if ( FilterIndex
!= -1 )
1650 theTemplate
= templates
[FilterIndex
];
1652 theTemplate
= FindTemplateForPath(path
);
1655 // Since we do not add files with non-default extensions to the FileHistory this
1656 // can only happen if the application changes the allowed templates in runtime.
1657 (void)wxMessageBox(_("Sorry, the format for this file is unknown."),
1659 wxOK
| wxICON_EXCLAMATION
, wxFindSuitableParent());
1664 path
= wxEmptyString
;
1670 wxDocTemplate
*wxDocManager::SelectDocumentType(wxDocTemplate
**templates
,
1671 int noTemplates
, bool sort
)
1673 wxArrayString strings
;
1674 wxDocTemplate
**data
= new wxDocTemplate
*[noTemplates
];
1678 for (i
= 0; i
< noTemplates
; i
++)
1680 if (templates
[i
]->IsVisible())
1684 for (j
= 0; j
< n
; j
++)
1686 //filter out NOT unique documents + view combinations
1687 if ( templates
[i
]->m_docTypeName
== data
[j
]->m_docTypeName
&&
1688 templates
[i
]->m_viewTypeName
== data
[j
]->m_viewTypeName
1695 strings
.Add(templates
[i
]->m_description
);
1697 data
[n
] = templates
[i
];
1705 strings
.Sort(); // ascending sort
1706 // Yes, this will be slow, but template lists
1707 // are typically short.
1709 n
= strings
.Count();
1710 for (i
= 0; i
< n
; i
++)
1712 for (j
= 0; j
< noTemplates
; j
++)
1714 if (strings
[i
] == templates
[j
]->m_description
)
1715 data
[i
] = templates
[j
];
1720 wxDocTemplate
*theTemplate
;
1725 // no visible templates, hence nothing to choose from
1730 // don't propose the user to choose if he heas no choice
1731 theTemplate
= data
[0];
1735 // propose the user to choose one of several
1736 theTemplate
= (wxDocTemplate
*)wxGetSingleChoiceData
1738 _("Select a document template"),
1742 wxFindSuitableParent()
1751 wxDocTemplate
*wxDocManager::SelectViewType(wxDocTemplate
**templates
,
1752 int noTemplates
, bool sort
)
1754 wxArrayString strings
;
1755 wxDocTemplate
**data
= new wxDocTemplate
*[noTemplates
];
1759 for (i
= 0; i
< noTemplates
; i
++)
1761 wxDocTemplate
*templ
= templates
[i
];
1762 if ( templ
->IsVisible() && !templ
->GetViewName().empty() )
1766 for (j
= 0; j
< n
; j
++)
1768 //filter out NOT unique views
1769 if ( templates
[i
]->m_viewTypeName
== data
[j
]->m_viewTypeName
)
1775 strings
.Add(templ
->m_viewTypeName
);
1784 strings
.Sort(); // ascending sort
1785 // Yes, this will be slow, but template lists
1786 // are typically short.
1788 n
= strings
.Count();
1789 for (i
= 0; i
< n
; i
++)
1791 for (j
= 0; j
< noTemplates
; j
++)
1793 if (strings
[i
] == templates
[j
]->m_viewTypeName
)
1794 data
[i
] = templates
[j
];
1799 wxDocTemplate
*theTemplate
;
1801 // the same logic as above
1805 theTemplate
= (wxDocTemplate
*)NULL
;
1809 theTemplate
= data
[0];
1813 theTemplate
= (wxDocTemplate
*)wxGetSingleChoiceData
1815 _("Select a document view"),
1819 wxFindSuitableParent()
1828 void wxDocManager::AssociateTemplate(wxDocTemplate
*temp
)
1830 if (!m_templates
.Member(temp
))
1831 m_templates
.Append(temp
);
1834 void wxDocManager::DisassociateTemplate(wxDocTemplate
*temp
)
1836 m_templates
.DeleteObject(temp
);
1839 // Add and remove a document from the manager's list
1840 void wxDocManager::AddDocument(wxDocument
*doc
)
1842 if (!m_docs
.Member(doc
))
1846 void wxDocManager::RemoveDocument(wxDocument
*doc
)
1848 m_docs
.DeleteObject(doc
);
1851 // Views or windows should inform the document manager
1852 // when a view is going in or out of focus
1853 void wxDocManager::ActivateView(wxView
*view
, bool activate
)
1857 m_currentView
= view
;
1861 if ( m_currentView
== view
)
1863 // don't keep stale pointer
1864 m_currentView
= (wxView
*) NULL
;
1869 // ----------------------------------------------------------------------------
1870 // Default document child frame
1871 // ----------------------------------------------------------------------------
1873 BEGIN_EVENT_TABLE(wxDocChildFrame
, wxFrame
)
1874 EVT_ACTIVATE(wxDocChildFrame::OnActivate
)
1875 EVT_CLOSE(wxDocChildFrame::OnCloseWindow
)
1878 wxDocChildFrame::wxDocChildFrame(wxDocument
*doc
,
1882 const wxString
& title
,
1886 const wxString
& name
)
1887 : wxFrame(frame
, id
, title
, pos
, size
, style
, name
)
1889 m_childDocument
= doc
;
1892 view
->SetFrame(this);
1895 // Extend event processing to search the view's event table
1896 bool wxDocChildFrame::ProcessEvent(wxEvent
& event
)
1899 m_childView
->Activate(true);
1901 if ( !m_childView
|| ! m_childView
->ProcessEvent(event
) )
1903 // Only hand up to the parent if it's a menu command
1904 if (!event
.IsKindOf(CLASSINFO(wxCommandEvent
)) || !GetParent() || !GetParent()->ProcessEvent(event
))
1905 return wxEvtHandler::ProcessEvent(event
);
1913 void wxDocChildFrame::OnActivate(wxActivateEvent
& event
)
1915 wxFrame::OnActivate(event
);
1918 m_childView
->Activate(event
.GetActive());
1921 void wxDocChildFrame::OnCloseWindow(wxCloseEvent
& event
)
1925 bool ans
= event
.CanVeto()
1926 ? m_childView
->Close(false) // false means don't delete associated window
1927 : true; // Must delete.
1931 m_childView
->Activate(false);
1933 m_childView
= (wxView
*) NULL
;
1934 m_childDocument
= (wxDocument
*) NULL
;
1945 // ----------------------------------------------------------------------------
1946 // Default parent frame
1947 // ----------------------------------------------------------------------------
1949 BEGIN_EVENT_TABLE(wxDocParentFrame
, wxFrame
)
1950 EVT_MENU(wxID_EXIT
, wxDocParentFrame::OnExit
)
1951 EVT_MENU_RANGE(wxID_FILE1
, wxID_FILE9
, wxDocParentFrame::OnMRUFile
)
1952 EVT_CLOSE(wxDocParentFrame::OnCloseWindow
)
1955 wxDocParentFrame::wxDocParentFrame()
1957 m_docManager
= NULL
;
1960 wxDocParentFrame::wxDocParentFrame(wxDocManager
*manager
,
1963 const wxString
& title
,
1967 const wxString
& name
)
1968 : wxFrame(frame
, id
, title
, pos
, size
, style
, name
)
1970 m_docManager
= manager
;
1973 bool wxDocParentFrame::Create(wxDocManager
*manager
,
1976 const wxString
& title
,
1980 const wxString
& name
)
1982 m_docManager
= manager
;
1983 return base_type::Create(frame
, id
, title
, pos
, size
, style
, name
);
1986 void wxDocParentFrame::OnExit(wxCommandEvent
& WXUNUSED(event
))
1991 void wxDocParentFrame::OnMRUFile(wxCommandEvent
& event
)
1993 int n
= event
.GetId() - wxID_FILE1
; // the index in MRU list
1994 wxString
filename(m_docManager
->GetHistoryFile(n
));
1995 if ( !filename
.empty() )
1997 // verify that the file exists before doing anything else
1998 if ( wxFile::Exists(filename
) )
2001 if (!m_docManager
->CreateDocument(filename
, wxDOC_SILENT
))
2003 // remove the file from the MRU list. The user should already be notified.
2004 m_docManager
->RemoveFileFromHistory(n
);
2006 wxLogError(_("The file '%s' couldn't be opened.\nIt has been removed from the most recently used files list."),
2012 // remove the bogus filename from the MRU list and notify the user
2014 m_docManager
->RemoveFileFromHistory(n
);
2016 wxLogError(_("The file '%s' doesn't exist and couldn't be opened.\nIt has been removed from the most recently used files list."),
2022 // Extend event processing to search the view's event table
2023 bool wxDocParentFrame::ProcessEvent(wxEvent
& event
)
2025 // Try the document manager, then do default processing
2026 if (!m_docManager
|| !m_docManager
->ProcessEvent(event
))
2027 return wxEvtHandler::ProcessEvent(event
);
2032 // Define the behaviour for the frame closing
2033 // - must delete all frames except for the main one.
2034 void wxDocParentFrame::OnCloseWindow(wxCloseEvent
& event
)
2036 if (m_docManager
->Clear(!event
.CanVeto()))
2044 #if wxUSE_PRINTING_ARCHITECTURE
2046 wxDocPrintout::wxDocPrintout(wxView
*view
, const wxString
& title
)
2049 m_printoutView
= view
;
2052 bool wxDocPrintout::OnPrintPage(int WXUNUSED(page
))
2056 // Get the logical pixels per inch of screen and printer
2057 int ppiScreenX
, ppiScreenY
;
2058 GetPPIScreen(&ppiScreenX
, &ppiScreenY
);
2059 wxUnusedVar(ppiScreenY
);
2060 int ppiPrinterX
, ppiPrinterY
;
2061 GetPPIPrinter(&ppiPrinterX
, &ppiPrinterY
);
2062 wxUnusedVar(ppiPrinterY
);
2064 // This scales the DC so that the printout roughly represents the
2065 // the screen scaling. The text point size _should_ be the right size
2066 // but in fact is too small for some reason. This is a detail that will
2067 // need to be addressed at some point but can be fudged for the
2069 float scale
= (float)((float)ppiPrinterX
/(float)ppiScreenX
);
2071 // Now we have to check in case our real page size is reduced
2072 // (e.g. because we're drawing to a print preview memory DC)
2073 int pageWidth
, pageHeight
;
2075 dc
->GetSize(&w
, &h
);
2076 GetPageSizePixels(&pageWidth
, &pageHeight
);
2077 wxUnusedVar(pageHeight
);
2079 // If printer pageWidth == current DC width, then this doesn't
2080 // change. But w might be the preview bitmap width, so scale down.
2081 float overallScale
= scale
* (float)(w
/(float)pageWidth
);
2082 dc
->SetUserScale(overallScale
, overallScale
);
2086 m_printoutView
->OnDraw(dc
);
2091 bool wxDocPrintout::HasPage(int pageNum
)
2093 return (pageNum
== 1);
2096 bool wxDocPrintout::OnBeginDocument(int startPage
, int endPage
)
2098 if (!wxPrintout::OnBeginDocument(startPage
, endPage
))
2104 void wxDocPrintout::GetPageInfo(int *minPage
, int *maxPage
, int *selPageFrom
, int *selPageTo
)
2112 #endif // wxUSE_PRINTING_ARCHITECTURE
2114 // ----------------------------------------------------------------------------
2115 // File history processor
2116 // ----------------------------------------------------------------------------
2118 wxFileHistory::wxFileHistory(size_t maxFiles
, wxWindowID idBase
)
2120 m_fileMaxFiles
= maxFiles
;
2124 wxFileHistory::~wxFileHistory()
2128 void wxFileHistory::AddFileToHistory(const wxString
& file
)
2130 wxFileName
fn(file
);
2133 // Check we don't already have this file
2134 for (i
= 0; i
< m_fileHistory
.GetCount(); i
++)
2136 // we need to do a comparison using wxFileNames because it knows
2137 // how to exactly compare files on the different platforms
2138 // (e.g. handle case [in]sensitive filesystems)
2139 if ( fn
== wxFileName(m_fileHistory
[i
]) )
2141 // we do have it, move it to the top of the history
2142 RemoveFileFromHistory (i
);
2143 AddFileToHistory (file
);
2148 // if we already have a full history, delete the one at the end
2149 if ( m_fileMaxFiles
== m_fileHistory
.GetCount() )
2151 RemoveFileFromHistory (m_fileHistory
.GetCount() - 1);
2152 AddFileToHistory (file
);
2156 // Add to the project file history:
2157 // Move existing files (if any) down so we can insert file at beginning.
2158 if (m_fileHistory
.GetCount() < m_fileMaxFiles
)
2160 wxList::compatibility_iterator node
= m_fileMenus
.GetFirst();
2163 wxMenu
* menu
= (wxMenu
*) node
->GetData();
2164 if ( m_fileHistory
.IsEmpty() && menu
->GetMenuItemCount() )
2166 menu
->AppendSeparator();
2168 menu
->Append(m_idBase
+m_fileHistory
.GetCount(), _("[EMPTY]"));
2169 node
= node
->GetNext();
2173 m_fileHistory
.Insert(file
, 0);
2175 // this is the directory of the last opened file
2176 wxString pathCurrent
;
2177 wxSplitPath( m_fileHistory
[0], &pathCurrent
, NULL
, NULL
);
2178 for (i
= 0; i
< m_fileHistory
.GetCount(); i
++)
2180 // if in same directory just show the filename; otherwise the full
2182 wxString pathInMenu
, path
, filename
, ext
;
2183 wxSplitPath( m_fileHistory
[i
], &path
, &filename
, &ext
);
2184 if ( path
== pathCurrent
)
2186 pathInMenu
= filename
;
2188 pathInMenu
= pathInMenu
+ wxFILE_SEP_EXT
+ ext
;
2192 // absolute path; could also set relative path
2193 pathInMenu
= m_fileHistory
[i
];
2196 // we need to quote '&' characters which are used for mnemonics
2197 pathInMenu
.Replace(_T("&"), _T("&&"));
2200 buf
.Printf(s_MRUEntryFormat
, i
+ 1, pathInMenu
.c_str());
2202 wxList::compatibility_iterator node
= m_fileMenus
.GetFirst();
2205 wxMenu
* menu
= (wxMenu
*) node
->GetData();
2206 menu
->SetLabel(m_idBase
+ i
, buf
);
2207 node
= node
->GetNext();
2212 void wxFileHistory::RemoveFileFromHistory(size_t i
)
2214 wxCHECK_RET( i
< m_fileHistory
.GetCount(),
2215 wxT("invalid index in wxFileHistory::RemoveFileFromHistory") );
2217 // delete the element from the array
2218 m_fileHistory
.RemoveAt(i
);
2220 wxList::compatibility_iterator node
= m_fileMenus
.GetFirst();
2223 wxMenu
* menu
= (wxMenu
*) node
->GetData();
2225 // shuffle filenames up
2227 for ( size_t j
= i
; j
< m_fileHistory
.GetCount(); j
++ )
2229 buf
.Printf(s_MRUEntryFormat
, j
+ 1, m_fileHistory
[j
].c_str());
2230 menu
->SetLabel(m_idBase
+ j
, buf
);
2233 node
= node
->GetNext();
2235 // delete the last menu item which is unused now
2236 wxWindowID lastItemId
= m_idBase
+ wx_truncate_cast(wxWindowID
, m_fileHistory
.GetCount());
2237 if (menu
->FindItem(lastItemId
))
2239 menu
->Delete(lastItemId
);
2242 // delete the last separator too if no more files are left
2243 if ( m_fileHistory
.GetCount() == 0 )
2245 wxMenuItemList::compatibility_iterator nodeLast
= menu
->GetMenuItems().GetLast();
2248 wxMenuItem
*menuItem
= nodeLast
->GetData();
2249 if ( menuItem
->IsSeparator() )
2251 menu
->Delete(menuItem
);
2253 //else: should we search backwards for the last separator?
2255 //else: menu is empty somehow
2260 void wxFileHistory::UseMenu(wxMenu
*menu
)
2262 if (!m_fileMenus
.Member(menu
))
2263 m_fileMenus
.Append(menu
);
2266 void wxFileHistory::RemoveMenu(wxMenu
*menu
)
2268 m_fileMenus
.DeleteObject(menu
);
2272 void wxFileHistory::Load(wxConfigBase
& config
)
2274 m_fileHistory
.Clear();
2277 buf
.Printf(wxT("file%d"), 1);
2279 wxString historyFile
;
2280 while ((m_fileHistory
.GetCount() < m_fileMaxFiles
) &&
2281 config
.Read(buf
, &historyFile
) && !historyFile
.empty())
2283 m_fileHistory
.Add(historyFile
);
2285 buf
.Printf(wxT("file%d"), (int)m_fileHistory
.GetCount()+1);
2286 historyFile
= wxEmptyString
;
2292 void wxFileHistory::Save(wxConfigBase
& config
)
2295 for (i
= 0; i
< m_fileMaxFiles
; i
++)
2298 buf
.Printf(wxT("file%d"), (int)i
+1);
2299 if (i
< m_fileHistory
.GetCount())
2300 config
.Write(buf
, wxString(m_fileHistory
[i
]));
2302 config
.Write(buf
, wxEmptyString
);
2305 #endif // wxUSE_CONFIG
2307 void wxFileHistory::AddFilesToMenu()
2309 if (m_fileHistory
.GetCount() > 0)
2311 wxList::compatibility_iterator node
= m_fileMenus
.GetFirst();
2314 wxMenu
* menu
= (wxMenu
*) node
->GetData();
2315 if (menu
->GetMenuItemCount())
2317 menu
->AppendSeparator();
2321 for (i
= 0; i
< m_fileHistory
.GetCount(); i
++)
2324 buf
.Printf(s_MRUEntryFormat
, i
+1, m_fileHistory
[i
].c_str());
2325 menu
->Append(m_idBase
+i
, buf
);
2327 node
= node
->GetNext();
2332 void wxFileHistory::AddFilesToMenu(wxMenu
* menu
)
2334 if (m_fileHistory
.GetCount() > 0)
2336 if (menu
->GetMenuItemCount())
2338 menu
->AppendSeparator();
2342 for (i
= 0; i
< m_fileHistory
.GetCount(); i
++)
2345 buf
.Printf(s_MRUEntryFormat
, i
+1, m_fileHistory
[i
].c_str());
2346 menu
->Append(m_idBase
+i
, buf
);
2351 // ----------------------------------------------------------------------------
2352 // Permits compatibility with existing file formats and functions that
2353 // manipulate files directly
2354 // ----------------------------------------------------------------------------
2356 #if wxUSE_STD_IOSTREAM
2358 bool wxTransferFileToStream(const wxString
& filename
, wxSTD ostream
& stream
)
2360 wxFFile
file(filename
, _T("rb"));
2361 if ( !file
.IsOpened() )
2369 nRead
= file
.Read(buf
, WXSIZEOF(buf
));
2373 stream
.write(buf
, nRead
);
2377 while ( !file
.Eof() );
2382 bool wxTransferStreamToFile(wxSTD istream
& stream
, const wxString
& filename
)
2384 wxFFile
file(filename
, _T("wb"));
2385 if ( !file
.IsOpened() )
2391 stream
.read(buf
, WXSIZEOF(buf
));
2392 if ( !stream
.bad() ) // fail may be set on EOF, don't use operator!()
2394 if ( !file
.Write(buf
, stream
.gcount()) )
2398 while ( !stream
.eof() );
2403 #else // !wxUSE_STD_IOSTREAM
2405 bool wxTransferFileToStream(const wxString
& filename
, wxOutputStream
& stream
)
2407 wxFFile
file(filename
, _T("rb"));
2408 if ( !file
.IsOpened() )
2416 nRead
= file
.Read(buf
, WXSIZEOF(buf
));
2420 stream
.Write(buf
, nRead
);
2424 while ( !file
.Eof() );
2429 bool wxTransferStreamToFile(wxInputStream
& stream
, const wxString
& filename
)
2431 wxFFile
file(filename
, _T("wb"));
2432 if ( !file
.IsOpened() )
2438 stream
.Read(buf
, WXSIZEOF(buf
));
2440 const size_t nRead
= stream
.LastRead();
2441 if ( !nRead
|| !file
.Write(buf
, nRead
) )
2444 while ( !stream
.Eof() );
2449 #endif // wxUSE_STD_IOSTREAM/!wxUSE_STD_IOSTREAM
2451 #endif // wxUSE_DOC_VIEW_ARCHITECTURE