1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/docview.cpp
3 // Purpose: Document/view classes
4 // Author: Julian Smart
5 // Modified by: Vadim Zeitlin
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
27 #if wxUSE_DOC_VIEW_ARCHITECTURE
29 #include "wx/docview.h"
33 #include "wx/string.h"
37 #include "wx/dialog.h"
39 #include "wx/filedlg.h"
42 #include "wx/msgdlg.h"
44 #include "wx/choicdlg.h"
47 #if wxUSE_PRINTING_ARCHITECTURE
48 #include "wx/prntbase.h"
49 #include "wx/printdlg.h"
52 #include "wx/confbase.h"
53 #include "wx/filename.h"
56 #include "wx/cmdproc.h"
57 #include "wx/tokenzr.h"
58 #include "wx/filename.h"
59 #include "wx/stdpaths.h"
60 #include "wx/vector.h"
61 #include "wx/scopedarray.h"
62 #include "wx/scopedptr.h"
63 #include "wx/scopeguard.h"
64 #include "wx/except.h"
66 #if wxUSE_STD_IOSTREAM
67 #include "wx/ioswrap.h"
68 #include "wx/beforestd.h"
74 #include "wx/afterstd.h"
76 #include "wx/wfstream.h"
79 typedef wxVector
<wxDocTemplate
*> wxDocTemplates
;
81 // ----------------------------------------------------------------------------
83 // ----------------------------------------------------------------------------
85 IMPLEMENT_ABSTRACT_CLASS(wxDocument
, wxEvtHandler
)
86 IMPLEMENT_ABSTRACT_CLASS(wxView
, wxEvtHandler
)
87 IMPLEMENT_ABSTRACT_CLASS(wxDocTemplate
, wxObject
)
88 IMPLEMENT_DYNAMIC_CLASS(wxDocManager
, wxEvtHandler
)
89 IMPLEMENT_CLASS(wxDocChildFrame
, wxFrame
)
90 IMPLEMENT_CLASS(wxDocParentFrame
, wxFrame
)
92 #if wxUSE_PRINTING_ARCHITECTURE
93 IMPLEMENT_DYNAMIC_CLASS(wxDocPrintout
, wxPrintout
)
96 // ============================================================================
98 // ============================================================================
100 // ----------------------------------------------------------------------------
102 // ----------------------------------------------------------------------------
107 wxString
FindExtension(const wxString
& path
)
110 wxFileName::SplitPath(path
, NULL
, NULL
, &ext
);
112 // VZ: extensions are considered not case sensitive - is this really a good
114 return ext
.MakeLower();
117 } // anonymous namespace
119 // ----------------------------------------------------------------------------
120 // Definition of wxDocument
121 // ----------------------------------------------------------------------------
123 wxDocument::wxDocument(wxDocument
*parent
)
125 m_documentModified
= false;
126 m_documentTemplate
= NULL
;
128 m_documentParent
= parent
;
130 parent
->m_childDocuments
.push_back(this);
132 m_commandProcessor
= NULL
;
136 bool wxDocument::DeleteContents()
141 wxDocument::~wxDocument()
143 delete m_commandProcessor
;
145 if (GetDocumentManager())
146 GetDocumentManager()->RemoveDocument(this);
148 if ( m_documentParent
)
149 m_documentParent
->m_childDocuments
.remove(this);
151 // Not safe to do here, since it'll invoke virtual view functions
152 // expecting to see valid derived objects: and by the time we get here,
153 // we've called destructors higher up.
157 bool wxDocument::Close()
159 if ( !OnSaveModified() )
162 // When the parent document closes, its children must be closed as well as
163 // they can't exist without the parent.
165 // As usual, first check if all children can be closed.
166 DocsList::const_iterator it
= m_childDocuments
.begin();
167 for ( DocsList::const_iterator end
= m_childDocuments
.end(); it
!= end
; ++it
)
169 if ( !(*it
)->OnSaveModified() )
171 // Leave the parent document opened if a child can't close.
176 // Now that they all did, do close them: as m_childDocuments is modified as
177 // we iterate over it, don't use the usual for-style iteration here.
178 while ( !m_childDocuments
.empty() )
180 wxDocument
* const childDoc
= m_childDocuments
.front();
182 // This will call OnSaveModified() once again but it shouldn't do
183 // anything as the document was just saved or marked as not needing to
184 // be saved by the call to OnSaveModified() that returned true above.
185 if ( !childDoc
->Close() )
187 wxFAIL_MSG( "Closing the child document unexpectedly failed "
188 "after its OnSaveModified() returned true" );
191 // Delete the child document by deleting all its views.
192 childDoc
->DeleteAllViews();
196 return OnCloseDocument();
199 bool wxDocument::OnCloseDocument()
201 // Tell all views that we're about to close
208 // Note that this implicitly deletes the document when the last view is
210 bool wxDocument::DeleteAllViews()
212 wxDocManager
* manager
= GetDocumentManager();
214 // first check if all views agree to be closed
215 const wxList::iterator end
= m_documentViews
.end();
216 for ( wxList::iterator i
= m_documentViews
.begin(); i
!= end
; ++i
)
218 wxView
*view
= (wxView
*)*i
;
219 if ( !view
->Close() )
223 // all views agreed to close, now do close them
224 if ( m_documentViews
.empty() )
226 // normally the document would be implicitly deleted when the last view
227 // is, but if don't have any views, do it here instead
228 if ( manager
&& manager
->GetDocuments().Member(this) )
233 // as we delete elements we iterate over, don't use the usual "from
234 // begin to end" loop
237 wxView
*view
= (wxView
*)*m_documentViews
.begin();
239 bool isLastOne
= m_documentViews
.size() == 1;
241 // this always deletes the node implicitly and if this is the last
242 // view also deletes this object itself (also implicitly, great),
243 // so we can't test for m_documentViews.empty() after calling this!
254 wxView
*wxDocument::GetFirstView() const
256 if ( m_documentViews
.empty() )
259 return static_cast<wxView
*>(m_documentViews
.GetFirst()->GetData());
262 void wxDocument::Modify(bool mod
)
264 if (mod
!= m_documentModified
)
266 m_documentModified
= mod
;
268 // Allow views to append asterix to the title
269 wxView
* view
= GetFirstView();
270 if (view
) view
->OnChangeFilename();
274 wxDocManager
*wxDocument::GetDocumentManager() const
276 // For child documents we use the same document manager as the parent, even
277 // though we don't have our own template (as children are not opened/saved
279 if ( m_documentParent
)
280 return m_documentParent
->GetDocumentManager();
282 return m_documentTemplate
? m_documentTemplate
->GetDocumentManager() : NULL
;
285 bool wxDocument::OnNewDocument()
287 // notice that there is no need to neither reset nor even check the
288 // modified flag here as the document itself is a new object (this is only
289 // called from CreateDocument()) and so it shouldn't be saved anyhow even
290 // if it is modified -- this could happen if the user code creates
291 // documents pre-filled with some user-entered (and which hence must not be
294 SetDocumentSaved(false);
296 const wxString name
= GetDocumentManager()->MakeNewDocumentName();
298 SetFilename(name
, true);
303 bool wxDocument::Save()
305 if ( AlreadySaved() )
308 if ( m_documentFile
.empty() || !m_savedYet
)
311 return OnSaveDocument(m_documentFile
);
314 bool wxDocument::SaveAs()
316 wxDocTemplate
*docTemplate
= GetDocumentTemplate();
320 #ifdef wxHAS_MULTIPLE_FILEDLG_FILTERS
321 wxString filter
= docTemplate
->GetDescription() + wxT(" (") +
322 docTemplate
->GetFileFilter() + wxT(")|") +
323 docTemplate
->GetFileFilter();
325 // Now see if there are some other template with identical view and document
326 // classes, whose filters may also be used.
327 if (docTemplate
->GetViewClassInfo() && docTemplate
->GetDocClassInfo())
329 wxList::compatibility_iterator
330 node
= docTemplate
->GetDocumentManager()->GetTemplates().GetFirst();
333 wxDocTemplate
*t
= (wxDocTemplate
*) node
->GetData();
335 if (t
->IsVisible() && t
!= docTemplate
&&
336 t
->GetViewClassInfo() == docTemplate
->GetViewClassInfo() &&
337 t
->GetDocClassInfo() == docTemplate
->GetDocClassInfo())
339 // add a '|' to separate this filter from the previous one
340 if ( !filter
.empty() )
343 filter
<< t
->GetDescription()
344 << wxT(" (") << t
->GetFileFilter() << wxT(") |")
345 << t
->GetFileFilter();
348 node
= node
->GetNext();
352 wxString filter
= docTemplate
->GetFileFilter() ;
355 wxString defaultDir
= docTemplate
->GetDirectory();
356 if ( defaultDir
.empty() )
358 defaultDir
= wxPathOnly(GetFilename());
359 if ( defaultDir
.empty() )
360 defaultDir
= GetDocumentManager()->GetLastDirectory();
363 wxString fileName
= wxFileSelector(_("Save As"),
365 wxFileNameFromPath(GetFilename()),
366 docTemplate
->GetDefaultExtension(),
368 wxFD_SAVE
| wxFD_OVERWRITE_PROMPT
,
369 GetDocumentWindow());
371 if (fileName
.empty())
372 return false; // cancelled by user
374 // Files that were not saved correctly are not added to the FileHistory.
375 if (!OnSaveDocument(fileName
))
378 SetTitle(wxFileNameFromPath(fileName
));
379 SetFilename(fileName
, true); // will call OnChangeFileName automatically
381 // A file that doesn't use the default extension of its document template
382 // cannot be opened via the FileHistory, so we do not add it.
383 if (docTemplate
->FileMatchesTemplate(fileName
))
385 GetDocumentManager()->AddFileToHistory(fileName
);
387 //else: the user will probably not be able to open the file again, so we
388 // could warn about the wrong file-extension here
393 bool wxDocument::OnSaveDocument(const wxString
& file
)
398 if ( !DoSaveDocument(file
) )
401 if ( m_commandProcessor
)
402 m_commandProcessor
->MarkAsSaved();
406 SetDocumentSaved(true);
407 #if defined( __WXOSX_MAC__ ) && wxOSX_USE_CARBON
408 wxFileName
fn(file
) ;
409 fn
.MacSetDefaultTypeAndCreator() ;
414 bool wxDocument::OnOpenDocument(const wxString
& file
)
416 // notice that there is no need to check the modified flag here for the
417 // reasons explained in OnNewDocument()
419 if ( !DoOpenDocument(file
) )
422 SetFilename(file
, true);
424 // stretching the logic a little this does make sense because the document
425 // had been saved into the file we just loaded it from, it just could have
426 // happened during a previous program execution, it's just that the name of
427 // this method is a bit unfortunate, it should probably have been called
428 // HasAssociatedFileName()
429 SetDocumentSaved(true);
436 #if wxUSE_STD_IOSTREAM
437 wxSTD istream
& wxDocument::LoadObject(wxSTD istream
& stream
)
439 wxInputStream
& wxDocument::LoadObject(wxInputStream
& stream
)
445 #if wxUSE_STD_IOSTREAM
446 wxSTD ostream
& wxDocument::SaveObject(wxSTD ostream
& stream
)
448 wxOutputStream
& wxDocument::SaveObject(wxOutputStream
& stream
)
454 bool wxDocument::Revert()
458 _("Discard changes and reload the last saved version?"),
459 wxTheApp
->GetAppDisplayName(),
460 wxYES_NO
| wxCANCEL
| wxICON_QUESTION
,
465 if ( !DoOpenDocument(GetFilename()) )
475 // Get title, or filename if no title, else unnamed
476 #if WXWIN_COMPATIBILITY_2_8
477 bool wxDocument::GetPrintableName(wxString
& buf
) const
479 // this function cannot only be overridden by the user code but also
480 // called by it so we need to ensure that we return the same thing as
481 // GetUserReadableName() but we can't call it because this would result in
482 // an infinite recursion, hence we use the helper DoGetUserReadableName()
483 buf
= DoGetUserReadableName();
487 #endif // WXWIN_COMPATIBILITY_2_8
489 wxString
wxDocument::GetUserReadableName() const
491 #if WXWIN_COMPATIBILITY_2_8
492 // we need to call the old virtual function to ensure that the overridden
493 // version of it is still called
495 if ( GetPrintableName(name
) )
497 #endif // WXWIN_COMPATIBILITY_2_8
499 return DoGetUserReadableName();
502 wxString
wxDocument::DoGetUserReadableName() const
504 if ( !m_documentTitle
.empty() )
505 return m_documentTitle
;
507 if ( !m_documentFile
.empty() )
508 return wxFileNameFromPath(m_documentFile
);
513 wxWindow
*wxDocument::GetDocumentWindow() const
515 wxView
* const view
= GetFirstView();
517 return view
? view
->GetFrame() : wxTheApp
->GetTopWindow();
520 wxCommandProcessor
*wxDocument::OnCreateCommandProcessor()
522 return new wxCommandProcessor
;
525 // true if safe to close
526 bool wxDocument::OnSaveModified()
530 switch ( wxMessageBox
534 _("Do you want to save changes to %s?"),
535 GetUserReadableName()
537 wxTheApp
->GetAppDisplayName(),
538 wxYES_NO
| wxCANCEL
| wxICON_QUESTION
| wxCENTRE
556 bool wxDocument::Draw(wxDC
& WXUNUSED(context
))
561 bool wxDocument::AddView(wxView
*view
)
563 if ( !m_documentViews
.Member(view
) )
565 m_documentViews
.Append(view
);
571 bool wxDocument::RemoveView(wxView
*view
)
573 (void)m_documentViews
.DeleteObject(view
);
578 bool wxDocument::OnCreate(const wxString
& WXUNUSED(path
), long flags
)
580 return GetDocumentTemplate()->CreateView(this, flags
) != NULL
;
583 // Called after a view is added or removed.
584 // The default implementation deletes the document if
585 // there are no more views.
586 void wxDocument::OnChangedViewList()
588 if ( m_documentViews
.empty() && OnSaveModified() )
592 void wxDocument::UpdateAllViews(wxView
*sender
, wxObject
*hint
)
594 wxList::compatibility_iterator node
= m_documentViews
.GetFirst();
597 wxView
*view
= (wxView
*)node
->GetData();
599 view
->OnUpdate(sender
, hint
);
600 node
= node
->GetNext();
604 void wxDocument::NotifyClosing()
606 wxList::compatibility_iterator node
= m_documentViews
.GetFirst();
609 wxView
*view
= (wxView
*)node
->GetData();
610 view
->OnClosingDocument();
611 node
= node
->GetNext();
615 void wxDocument::SetFilename(const wxString
& filename
, bool notifyViews
)
617 m_documentFile
= filename
;
618 OnChangeFilename(notifyViews
);
621 void wxDocument::OnChangeFilename(bool notifyViews
)
625 // Notify the views that the filename has changed
626 wxList::compatibility_iterator node
= m_documentViews
.GetFirst();
629 wxView
*view
= (wxView
*)node
->GetData();
630 view
->OnChangeFilename();
631 node
= node
->GetNext();
636 bool wxDocument::DoSaveDocument(const wxString
& file
)
638 #if wxUSE_STD_IOSTREAM
639 wxSTD ofstream
store(file
.mb_str(), wxSTD
ios::binary
);
642 wxFileOutputStream
store(file
);
643 if ( store
.GetLastError() != wxSTREAM_NO_ERROR
)
646 wxLogError(_("File \"%s\" could not be opened for writing."), file
);
650 if (!SaveObject(store
))
652 wxLogError(_("Failed to save document to the file \"%s\"."), file
);
659 bool wxDocument::DoOpenDocument(const wxString
& file
)
661 #if wxUSE_STD_IOSTREAM
662 wxSTD ifstream
store(file
.mb_str(), wxSTD
ios::binary
);
665 wxFileInputStream
store(file
);
666 if (store
.GetLastError() != wxSTREAM_NO_ERROR
|| !store
.IsOk())
669 wxLogError(_("File \"%s\" could not be opened for reading."), file
);
673 #if wxUSE_STD_IOSTREAM
677 int res
= LoadObject(store
).GetLastError();
678 if ( res
!= wxSTREAM_NO_ERROR
&& res
!= wxSTREAM_EOF
)
681 wxLogError(_("Failed to read document from the file \"%s\"."), file
);
689 // ----------------------------------------------------------------------------
691 // ----------------------------------------------------------------------------
695 m_viewDocument
= NULL
;
699 m_docChildFrame
= NULL
;
704 if (m_viewDocument
&& GetDocumentManager())
705 GetDocumentManager()->ActivateView(this, false);
707 // reset our frame view first, before removing it from the document as
708 // SetView(NULL) is a simple call while RemoveView() may result in user
709 // code being executed and this user code can, for example, show a message
710 // box which would result in an activation event for m_docChildFrame and so
711 // could reactivate the view being destroyed -- unless we reset it first
712 if ( m_docChildFrame
&& m_docChildFrame
->GetView() == this )
714 // prevent it from doing anything with us
715 m_docChildFrame
->SetView(NULL
);
717 // it doesn't make sense to leave the frame alive if its associated
718 // view doesn't exist any more so unconditionally close it as well
720 // notice that we only get here if m_docChildFrame is non-NULL in the
721 // first place and it will be always NULL if we're deleted because our
722 // frame was closed, so this only catches the case of directly deleting
723 // the view, as it happens if its creation fails in wxDocTemplate::
724 // CreateView() for example
725 m_docChildFrame
->GetWindow()->Destroy();
728 if ( m_viewDocument
)
729 m_viewDocument
->RemoveView(this);
732 void wxView::SetDocChildFrame(wxDocChildFrameAnyBase
*docChildFrame
)
734 SetFrame(docChildFrame
? docChildFrame
->GetWindow() : NULL
);
735 m_docChildFrame
= docChildFrame
;
738 bool wxView::TryBefore(wxEvent
& event
)
740 wxDocument
* const doc
= GetDocument();
741 return doc
&& doc
->ProcessEventLocally(event
);
744 void wxView::OnActivateView(bool WXUNUSED(activate
),
745 wxView
*WXUNUSED(activeView
),
746 wxView
*WXUNUSED(deactiveView
))
750 void wxView::OnPrint(wxDC
*dc
, wxObject
*WXUNUSED(info
))
755 void wxView::OnUpdate(wxView
*WXUNUSED(sender
), wxObject
*WXUNUSED(hint
))
759 void wxView::OnChangeFilename()
761 // GetFrame can return wxWindow rather than wxTopLevelWindow due to
762 // generic MDI implementation so use SetLabel rather than SetTitle.
763 // It should cause SetTitle() for top level windows.
764 wxWindow
*win
= GetFrame();
767 wxDocument
*doc
= GetDocument();
770 wxString label
= doc
->GetUserReadableName();
771 if (doc
->IsModified())
775 win
->SetLabel(label
);
778 void wxView::SetDocument(wxDocument
*doc
)
780 m_viewDocument
= doc
;
785 bool wxView::Close(bool deleteWindow
)
787 return OnClose(deleteWindow
);
790 void wxView::Activate(bool activate
)
792 if (GetDocument() && GetDocumentManager())
794 OnActivateView(activate
, this, GetDocumentManager()->GetCurrentView());
795 GetDocumentManager()->ActivateView(this, activate
);
799 bool wxView::OnClose(bool WXUNUSED(deleteWindow
))
801 return GetDocument() ? GetDocument()->Close() : true;
804 #if wxUSE_PRINTING_ARCHITECTURE
805 wxPrintout
*wxView::OnCreatePrintout()
807 return new wxDocPrintout(this);
809 #endif // wxUSE_PRINTING_ARCHITECTURE
811 // ----------------------------------------------------------------------------
813 // ----------------------------------------------------------------------------
815 wxDocTemplate::wxDocTemplate(wxDocManager
*manager
,
816 const wxString
& descr
,
817 const wxString
& filter
,
820 const wxString
& docTypeName
,
821 const wxString
& viewTypeName
,
822 wxClassInfo
*docClassInfo
,
823 wxClassInfo
*viewClassInfo
,
826 m_documentManager
= manager
;
827 m_description
= descr
;
830 m_fileFilter
= filter
;
832 m_docTypeName
= docTypeName
;
833 m_viewTypeName
= viewTypeName
;
834 m_documentManager
->AssociateTemplate(this);
836 m_docClassInfo
= docClassInfo
;
837 m_viewClassInfo
= viewClassInfo
;
840 wxDocTemplate::~wxDocTemplate()
842 m_documentManager
->DisassociateTemplate(this);
845 // Tries to dynamically construct an object of the right class.
846 wxDocument
*wxDocTemplate::CreateDocument(const wxString
& path
, long flags
)
848 // InitDocument() is supposed to delete the document object if its
849 // initialization fails so don't use wxScopedPtr<> here: this is fragile
850 // but unavoidable because the default implementation uses CreateView()
851 // which may -- or not -- create a wxView and if it does create it and its
852 // initialization fails then the view destructor will delete the document
853 // (via RemoveView()) and as we can't distinguish between the two cases we
854 // just have to assume that it always deletes it in case of failure
855 wxDocument
* const doc
= DoCreateDocument();
857 return doc
&& InitDocument(doc
, path
, flags
) ? doc
: NULL
;
861 wxDocTemplate::InitDocument(wxDocument
* doc
, const wxString
& path
, long flags
)
863 wxScopeGuard g
= wxMakeObjGuard(*doc
, &wxDocument::DeleteAllViews
);
865 doc
->SetFilename(path
);
866 doc
->SetDocumentTemplate(this);
867 GetDocumentManager()->AddDocument(doc
);
868 doc
->SetCommandProcessor(doc
->OnCreateCommandProcessor());
870 if ( !doc
->OnCreate(path
, flags
) )
873 g
.Dismiss(); // no need to call DeleteAllViews() anymore
878 wxView
*wxDocTemplate::CreateView(wxDocument
*doc
, long flags
)
880 wxScopedPtr
<wxView
> view(DoCreateView());
884 view
->SetDocument(doc
);
885 if ( !view
->OnCreate(doc
, flags
) )
888 return view
.release();
891 // The default (very primitive) format detection: check is the extension is
892 // that of the template
893 bool wxDocTemplate::FileMatchesTemplate(const wxString
& path
)
895 wxStringTokenizer
parser (GetFileFilter(), wxT(";"));
896 wxString anything
= wxT ("*");
897 while (parser
.HasMoreTokens())
899 wxString filter
= parser
.GetNextToken();
900 wxString filterExt
= FindExtension (filter
);
901 if ( filter
.IsSameAs (anything
) ||
902 filterExt
.IsSameAs (anything
) ||
903 filterExt
.IsSameAs (FindExtension (path
)) )
906 return GetDefaultExtension().IsSameAs(FindExtension(path
));
909 wxDocument
*wxDocTemplate::DoCreateDocument()
914 return static_cast<wxDocument
*>(m_docClassInfo
->CreateObject());
917 wxView
*wxDocTemplate::DoCreateView()
919 if (!m_viewClassInfo
)
922 return static_cast<wxView
*>(m_viewClassInfo
->CreateObject());
925 // ----------------------------------------------------------------------------
927 // ----------------------------------------------------------------------------
929 BEGIN_EVENT_TABLE(wxDocManager
, wxEvtHandler
)
930 EVT_MENU(wxID_OPEN
, wxDocManager::OnFileOpen
)
931 EVT_MENU(wxID_CLOSE
, wxDocManager::OnFileClose
)
932 EVT_MENU(wxID_CLOSE_ALL
, wxDocManager::OnFileCloseAll
)
933 EVT_MENU(wxID_REVERT
, wxDocManager::OnFileRevert
)
934 EVT_MENU(wxID_NEW
, wxDocManager::OnFileNew
)
935 EVT_MENU(wxID_SAVE
, wxDocManager::OnFileSave
)
936 EVT_MENU(wxID_SAVEAS
, wxDocManager::OnFileSaveAs
)
937 EVT_MENU(wxID_UNDO
, wxDocManager::OnUndo
)
938 EVT_MENU(wxID_REDO
, wxDocManager::OnRedo
)
940 // We don't know in advance how many items can there be in the MRU files
941 // list so set up OnMRUFile() as a handler for all menu events and do the
942 // check for the id of the menu item clicked inside it.
943 EVT_MENU(wxID_ANY
, wxDocManager::OnMRUFile
)
945 EVT_UPDATE_UI(wxID_OPEN
, wxDocManager::OnUpdateFileOpen
)
946 EVT_UPDATE_UI(wxID_CLOSE
, wxDocManager::OnUpdateDisableIfNoDoc
)
947 EVT_UPDATE_UI(wxID_CLOSE_ALL
, wxDocManager::OnUpdateDisableIfNoDoc
)
948 EVT_UPDATE_UI(wxID_REVERT
, wxDocManager::OnUpdateFileRevert
)
949 EVT_UPDATE_UI(wxID_NEW
, wxDocManager::OnUpdateFileNew
)
950 EVT_UPDATE_UI(wxID_SAVE
, wxDocManager::OnUpdateFileSave
)
951 EVT_UPDATE_UI(wxID_SAVEAS
, wxDocManager::OnUpdateFileSaveAs
)
952 EVT_UPDATE_UI(wxID_UNDO
, wxDocManager::OnUpdateUndo
)
953 EVT_UPDATE_UI(wxID_REDO
, wxDocManager::OnUpdateRedo
)
955 #if wxUSE_PRINTING_ARCHITECTURE
956 EVT_MENU(wxID_PRINT
, wxDocManager::OnPrint
)
957 EVT_MENU(wxID_PREVIEW
, wxDocManager::OnPreview
)
958 EVT_MENU(wxID_PRINT_SETUP
, wxDocManager::OnPageSetup
)
960 EVT_UPDATE_UI(wxID_PRINT
, wxDocManager::OnUpdateDisableIfNoDoc
)
961 EVT_UPDATE_UI(wxID_PREVIEW
, wxDocManager::OnUpdateDisableIfNoDoc
)
962 // NB: we keep "Print setup" menu item always enabled as it can be used
963 // even without an active document
964 #endif // wxUSE_PRINTING_ARCHITECTURE
967 wxDocManager
* wxDocManager::sm_docManager
= NULL
;
969 wxDocManager::wxDocManager(long WXUNUSED(flags
), bool initialize
)
971 sm_docManager
= this;
973 m_defaultDocumentNameCounter
= 1;
974 m_currentView
= NULL
;
975 m_maxDocsOpen
= INT_MAX
;
976 m_fileHistory
= NULL
;
981 wxDocManager::~wxDocManager()
984 delete m_fileHistory
;
985 sm_docManager
= NULL
;
988 // closes the specified document
989 bool wxDocManager::CloseDocument(wxDocument
* doc
, bool force
)
991 if ( !doc
->Close() && !force
)
994 // Implicitly deletes the document when
995 // the last view is deleted
996 doc
->DeleteAllViews();
998 // Check we're really deleted
999 if (m_docs
.Member(doc
))
1005 bool wxDocManager::CloseDocuments(bool force
)
1007 wxList::compatibility_iterator node
= m_docs
.GetFirst();
1010 wxDocument
*doc
= (wxDocument
*)node
->GetData();
1011 wxList::compatibility_iterator next
= node
->GetNext();
1013 if (!CloseDocument(doc
, force
))
1016 // This assumes that documents are not connected in
1017 // any way, i.e. deleting one document does NOT
1024 bool wxDocManager::Clear(bool force
)
1026 if (!CloseDocuments(force
))
1029 m_currentView
= NULL
;
1031 wxList::compatibility_iterator node
= m_templates
.GetFirst();
1034 wxDocTemplate
*templ
= (wxDocTemplate
*) node
->GetData();
1035 wxList::compatibility_iterator next
= node
->GetNext();
1042 bool wxDocManager::Initialize()
1044 m_fileHistory
= OnCreateFileHistory();
1048 wxString
wxDocManager::GetLastDirectory() const
1050 // if we haven't determined the last used directory yet, do it now
1051 if ( m_lastDirectory
.empty() )
1053 // we're going to modify m_lastDirectory in this const method, so do it
1054 // via non-const self pointer instead of const this one
1055 wxDocManager
* const self
= const_cast<wxDocManager
*>(this);
1057 // first try to reuse the directory of the most recently opened file:
1058 // this ensures that if the user opens a file, closes the program and
1059 // runs it again the "Open file" dialog will open in the directory of
1060 // the last file he used
1061 if ( m_fileHistory
&& m_fileHistory
->GetCount() )
1063 const wxString lastOpened
= m_fileHistory
->GetHistoryFile(0);
1064 const wxFileName
fn(lastOpened
);
1065 if ( fn
.DirExists() )
1067 self
->m_lastDirectory
= fn
.GetPath();
1069 //else: should we try the next one?
1071 //else: no history yet
1073 // if we don't have any files in the history (yet?), use the
1074 // system-dependent default location for the document files
1075 if ( m_lastDirectory
.empty() )
1077 self
->m_lastDirectory
= wxStandardPaths::Get().GetAppDocumentsDir();
1081 return m_lastDirectory
;
1084 wxFileHistory
*wxDocManager::OnCreateFileHistory()
1086 return new wxFileHistory
;
1089 void wxDocManager::OnFileClose(wxCommandEvent
& WXUNUSED(event
))
1091 wxDocument
*doc
= GetCurrentDocument();
1096 void wxDocManager::OnFileCloseAll(wxCommandEvent
& WXUNUSED(event
))
1098 CloseDocuments(false);
1101 void wxDocManager::OnFileNew(wxCommandEvent
& WXUNUSED(event
))
1103 CreateNewDocument();
1106 void wxDocManager::OnFileOpen(wxCommandEvent
& WXUNUSED(event
))
1108 if ( !CreateDocument("") )
1110 OnOpenFileFailure();
1114 void wxDocManager::OnFileRevert(wxCommandEvent
& WXUNUSED(event
))
1116 wxDocument
*doc
= GetCurrentDocument();
1122 void wxDocManager::OnFileSave(wxCommandEvent
& WXUNUSED(event
))
1124 wxDocument
*doc
= GetCurrentDocument();
1130 void wxDocManager::OnFileSaveAs(wxCommandEvent
& WXUNUSED(event
))
1132 wxDocument
*doc
= GetCurrentDocument();
1138 void wxDocManager::OnMRUFile(wxCommandEvent
& event
)
1140 // Check if the id is in the range assigned to MRU list entries.
1141 const int id
= event
.GetId();
1142 if ( id
>= wxID_FILE1
&&
1143 id
< wxID_FILE1
+ static_cast<int>(m_fileHistory
->GetCount()) )
1145 DoOpenMRUFile(id
- wxID_FILE1
);
1153 void wxDocManager::DoOpenMRUFile(unsigned n
)
1155 wxString
filename(GetHistoryFile(n
));
1156 if ( filename
.empty() )
1159 wxString errMsg
; // must contain exactly one "%s" if non-empty
1160 if ( wxFile::Exists(filename
) )
1162 // Try to open it but don't give an error if it failed: this could be
1163 // normal, e.g. because the user cancelled opening it, and we don't
1164 // have any useful information to put in the error message anyhow, so
1165 // we assume that in case of an error the appropriate message had been
1167 (void)CreateDocument(filename
, wxDOC_SILENT
);
1169 else // file doesn't exist
1171 OnMRUFileNotExist(n
, filename
);
1175 void wxDocManager::OnMRUFileNotExist(unsigned n
, const wxString
& filename
)
1177 // remove the file which we can't open from the MRU list
1178 RemoveFileFromHistory(n
);
1180 // and tell the user about it
1181 wxLogError(_("The file '%s' doesn't exist and couldn't be opened.\n"
1182 "It has been removed from the most recently used files list."),
1186 #if wxUSE_PRINTING_ARCHITECTURE
1188 void wxDocManager::OnPrint(wxCommandEvent
& WXUNUSED(event
))
1190 wxView
*view
= GetActiveView();
1194 wxPrintout
*printout
= view
->OnCreatePrintout();
1197 wxPrintDialogData
printDialogData(m_pageSetupDialogData
.GetPrintData());
1198 wxPrinter
printer(&printDialogData
);
1199 printer
.Print(view
->GetFrame(), printout
, true);
1205 void wxDocManager::OnPageSetup(wxCommandEvent
& WXUNUSED(event
))
1207 wxPageSetupDialog
dlg(wxTheApp
->GetTopWindow(), &m_pageSetupDialogData
);
1208 if ( dlg
.ShowModal() == wxID_OK
)
1210 m_pageSetupDialogData
= dlg
.GetPageSetupData();
1214 wxPreviewFrame
* wxDocManager::CreatePreviewFrame(wxPrintPreviewBase
* preview
,
1216 const wxString
& title
)
1218 return new wxPreviewFrame(preview
, parent
, title
);
1221 void wxDocManager::OnPreview(wxCommandEvent
& WXUNUSED(event
))
1224 wxView
*view
= GetActiveView();
1228 wxPrintout
*printout
= view
->OnCreatePrintout();
1231 wxPrintDialogData
printDialogData(m_pageSetupDialogData
.GetPrintData());
1233 // Pass two printout objects: for preview, and possible printing.
1234 wxPrintPreviewBase
*
1235 preview
= new wxPrintPreview(printout
,
1236 view
->OnCreatePrintout(),
1238 if ( !preview
->IsOk() )
1241 wxLogError(_("Print preview creation failed."));
1245 wxPreviewFrame
* frame
= CreatePreviewFrame(preview
,
1246 wxTheApp
->GetTopWindow(),
1247 _("Print Preview"));
1248 wxCHECK_RET( frame
, "should create a print preview frame" );
1250 frame
->Centre(wxBOTH
);
1251 frame
->Initialize();
1255 #endif // wxUSE_PRINTING_ARCHITECTURE
1257 void wxDocManager::OnUndo(wxCommandEvent
& event
)
1259 wxCommandProcessor
* const cmdproc
= GetCurrentCommandProcessor();
1269 void wxDocManager::OnRedo(wxCommandEvent
& event
)
1271 wxCommandProcessor
* const cmdproc
= GetCurrentCommandProcessor();
1281 // Handlers for UI update commands
1283 void wxDocManager::OnUpdateFileOpen(wxUpdateUIEvent
& event
)
1285 // CreateDocument() (which is called from OnFileOpen) may succeed
1286 // only when there is at least a template:
1287 event
.Enable( GetTemplates().GetCount()>0 );
1290 void wxDocManager::OnUpdateDisableIfNoDoc(wxUpdateUIEvent
& event
)
1292 event
.Enable( GetCurrentDocument() != NULL
);
1295 void wxDocManager::OnUpdateFileRevert(wxUpdateUIEvent
& event
)
1297 wxDocument
* doc
= GetCurrentDocument();
1298 event
.Enable(doc
&& doc
->IsModified() && doc
->GetDocumentSaved());
1301 void wxDocManager::OnUpdateFileNew(wxUpdateUIEvent
& event
)
1303 // CreateDocument() (which is called from OnFileNew) may succeed
1304 // only when there is at least a template:
1305 event
.Enable( GetTemplates().GetCount()>0 );
1308 void wxDocManager::OnUpdateFileSave(wxUpdateUIEvent
& event
)
1310 wxDocument
* const doc
= GetCurrentDocument();
1311 event
.Enable( doc
&& !doc
->IsChildDocument() && !doc
->AlreadySaved() );
1314 void wxDocManager::OnUpdateFileSaveAs(wxUpdateUIEvent
& event
)
1316 wxDocument
* const doc
= GetCurrentDocument();
1317 event
.Enable( doc
&& !doc
->IsChildDocument() );
1320 void wxDocManager::OnUpdateUndo(wxUpdateUIEvent
& event
)
1322 wxCommandProcessor
* const cmdproc
= GetCurrentCommandProcessor();
1325 // If we don't have any document at all, the menu item should really be
1327 if ( !GetCurrentDocument() )
1328 event
.Enable(false);
1329 else // But if we do have it, it might handle wxID_UNDO on its own
1333 event
.Enable(cmdproc
->CanUndo());
1334 cmdproc
->SetMenuStrings();
1337 void wxDocManager::OnUpdateRedo(wxUpdateUIEvent
& event
)
1339 wxCommandProcessor
* const cmdproc
= GetCurrentCommandProcessor();
1342 // Use same logic as in OnUpdateUndo() above.
1343 if ( !GetCurrentDocument() )
1344 event
.Enable(false);
1349 event
.Enable(cmdproc
->CanRedo());
1350 cmdproc
->SetMenuStrings();
1353 wxView
*wxDocManager::GetActiveView() const
1355 wxView
*view
= GetCurrentView();
1357 if ( !view
&& !m_docs
.empty() )
1359 // if we have exactly one document, consider its view to be the current
1362 // VZ: I'm not exactly sure why is this needed but this is how this
1363 // code used to behave before the bug #9518 was fixed and it seems
1364 // safer to preserve the old logic
1365 wxList::compatibility_iterator node
= m_docs
.GetFirst();
1366 if ( !node
->GetNext() )
1368 wxDocument
*doc
= static_cast<wxDocument
*>(node
->GetData());
1369 view
= doc
->GetFirstView();
1371 //else: we have more than one document
1377 bool wxDocManager::TryBefore(wxEvent
& event
)
1379 wxView
* const view
= GetActiveView();
1380 return view
&& view
->ProcessEventLocally(event
);
1386 // helper function: return only the visible templates
1387 wxDocTemplates
GetVisibleTemplates(const wxList
& allTemplates
)
1389 // select only the visible templates
1390 const size_t totalNumTemplates
= allTemplates
.GetCount();
1391 wxDocTemplates templates
;
1392 if ( totalNumTemplates
)
1394 templates
.reserve(totalNumTemplates
);
1396 for ( wxList::const_iterator i
= allTemplates
.begin(),
1397 end
= allTemplates
.end();
1401 wxDocTemplate
* const temp
= (wxDocTemplate
*)*i
;
1402 if ( temp
->IsVisible() )
1403 templates
.push_back(temp
);
1410 } // anonymous namespace
1412 void wxDocManager::ActivateDocument(wxDocument
*doc
)
1414 wxView
* const view
= doc
->GetFirstView();
1418 view
->Activate(true);
1419 if ( wxWindow
*win
= view
->GetFrame() )
1423 wxDocument
*wxDocManager::CreateDocument(const wxString
& pathOrig
, long flags
)
1425 // this ought to be const but SelectDocumentType/Path() are not
1426 // const-correct and can't be changed as, being virtual, this risks
1427 // breaking user code overriding them
1428 wxDocTemplates
templates(GetVisibleTemplates(m_templates
));
1429 const size_t numTemplates
= templates
.size();
1430 if ( !numTemplates
)
1432 // no templates can be used, can't create document
1437 // normally user should select the template to use but wxDOC_SILENT flag we
1438 // choose one ourselves
1439 wxString path
= pathOrig
; // may be modified below
1440 wxDocTemplate
*temp
;
1441 if ( flags
& wxDOC_SILENT
)
1443 wxASSERT_MSG( !path
.empty(),
1444 "using empty path with wxDOC_SILENT doesn't make sense" );
1446 temp
= FindTemplateForPath(path
);
1449 wxLogWarning(_("The format of file '%s' couldn't be determined."),
1453 else // not silent, ask the user
1455 // for the new file we need just the template, for an existing one we
1456 // need the template and the path, unless it's already specified
1457 if ( (flags
& wxDOC_NEW
) || !path
.empty() )
1458 temp
= SelectDocumentType(&templates
[0], numTemplates
);
1460 temp
= SelectDocumentPath(&templates
[0], numTemplates
, path
, flags
);
1466 // check whether the document with this path is already opened
1467 if ( !path
.empty() )
1469 const wxFileName
fn(path
);
1470 for ( wxList::const_iterator i
= m_docs
.begin(); i
!= m_docs
.end(); ++i
)
1472 wxDocument
* const doc
= (wxDocument
*)*i
;
1474 if ( fn
== doc
->GetFilename() )
1476 // file already open, just activate it and return
1477 ActivateDocument(doc
);
1484 // no, we need to create a new document
1487 // if we've reached the max number of docs, close the first one.
1488 if ( (int)GetDocuments().GetCount() >= m_maxDocsOpen
)
1490 if ( !CloseDocument((wxDocument
*)GetDocuments().GetFirst()->GetData()) )
1492 // can't open the new document if closing the old one failed
1498 // do create and initialize the new document finally
1499 wxDocument
* const docNew
= temp
->CreateDocument(path
, flags
);
1503 docNew
->SetDocumentName(temp
->GetDocumentName());
1504 docNew
->SetDocumentTemplate(temp
);
1508 // call the appropriate function depending on whether we're creating a
1509 // new file or opening an existing one
1510 if ( !(flags
& wxDOC_NEW
? docNew
->OnNewDocument()
1511 : docNew
->OnOpenDocument(path
)) )
1513 docNew
->DeleteAllViews();
1517 wxCATCH_ALL( docNew
->DeleteAllViews(); throw; )
1519 // add the successfully opened file to MRU, but only if we're going to be
1520 // able to reopen it successfully later which requires the template for
1521 // this document to be retrievable from the file extension
1522 if ( !(flags
& wxDOC_NEW
) && temp
->FileMatchesTemplate(path
) )
1523 AddFileToHistory(path
);
1525 // at least under Mac (where views are top level windows) it seems to be
1526 // necessary to manually activate the new document to bring it to the
1527 // forefront -- and it shouldn't hurt doing this under the other platforms
1528 ActivateDocument(docNew
);
1533 wxView
*wxDocManager::CreateView(wxDocument
*doc
, long flags
)
1535 wxDocTemplates
templates(GetVisibleTemplates(m_templates
));
1536 const size_t numTemplates
= templates
.size();
1538 if ( numTemplates
== 0 )
1541 wxDocTemplate
* const
1542 temp
= numTemplates
== 1 ? templates
[0]
1543 : SelectViewType(&templates
[0], numTemplates
);
1548 wxView
*view
= temp
->CreateView(doc
, flags
);
1550 view
->SetViewName(temp
->GetViewName());
1554 // Not yet implemented
1556 wxDocManager::DeleteTemplate(wxDocTemplate
*WXUNUSED(temp
), long WXUNUSED(flags
))
1560 // Not yet implemented
1561 bool wxDocManager::FlushDoc(wxDocument
*WXUNUSED(doc
))
1566 wxDocument
*wxDocManager::GetCurrentDocument() const
1568 wxView
* const view
= GetActiveView();
1569 return view
? view
->GetDocument() : NULL
;
1572 wxCommandProcessor
*wxDocManager::GetCurrentCommandProcessor() const
1574 wxDocument
* const doc
= GetCurrentDocument();
1575 return doc
? doc
->GetCommandProcessor() : NULL
;
1578 // Make a default name for a new document
1579 #if WXWIN_COMPATIBILITY_2_8
1580 bool wxDocManager::MakeDefaultName(wxString
& WXUNUSED(name
))
1582 // we consider that this function can only be overridden by the user code,
1583 // not called by it as it only makes sense to call it internally, so we
1584 // don't bother to return anything from here
1587 #endif // WXWIN_COMPATIBILITY_2_8
1589 wxString
wxDocManager::MakeNewDocumentName()
1593 #if WXWIN_COMPATIBILITY_2_8
1594 if ( !MakeDefaultName(name
) )
1595 #endif // WXWIN_COMPATIBILITY_2_8
1597 name
.Printf(_("unnamed%d"), m_defaultDocumentNameCounter
);
1598 m_defaultDocumentNameCounter
++;
1604 // Make a frame title (override this to do something different)
1605 // If docName is empty, a document is not currently active.
1606 wxString
wxDocManager::MakeFrameTitle(wxDocument
* doc
)
1608 wxString appName
= wxTheApp
->GetAppDisplayName();
1614 wxString docName
= doc
->GetUserReadableName();
1615 title
= docName
+ wxString(_(" - ")) + appName
;
1621 // Not yet implemented
1622 wxDocTemplate
*wxDocManager::MatchTemplate(const wxString
& WXUNUSED(path
))
1627 // File history management
1628 void wxDocManager::AddFileToHistory(const wxString
& file
)
1631 m_fileHistory
->AddFileToHistory(file
);
1634 void wxDocManager::RemoveFileFromHistory(size_t i
)
1637 m_fileHistory
->RemoveFileFromHistory(i
);
1640 wxString
wxDocManager::GetHistoryFile(size_t i
) const
1645 histFile
= m_fileHistory
->GetHistoryFile(i
);
1650 void wxDocManager::FileHistoryUseMenu(wxMenu
*menu
)
1653 m_fileHistory
->UseMenu(menu
);
1656 void wxDocManager::FileHistoryRemoveMenu(wxMenu
*menu
)
1659 m_fileHistory
->RemoveMenu(menu
);
1663 void wxDocManager::FileHistoryLoad(const wxConfigBase
& config
)
1666 m_fileHistory
->Load(config
);
1669 void wxDocManager::FileHistorySave(wxConfigBase
& config
)
1672 m_fileHistory
->Save(config
);
1676 void wxDocManager::FileHistoryAddFilesToMenu(wxMenu
* menu
)
1679 m_fileHistory
->AddFilesToMenu(menu
);
1682 void wxDocManager::FileHistoryAddFilesToMenu()
1685 m_fileHistory
->AddFilesToMenu();
1688 size_t wxDocManager::GetHistoryFilesCount() const
1690 return m_fileHistory
? m_fileHistory
->GetCount() : 0;
1694 // Find out the document template via matching in the document file format
1695 // against that of the template
1696 wxDocTemplate
*wxDocManager::FindTemplateForPath(const wxString
& path
)
1698 wxDocTemplate
*theTemplate
= NULL
;
1700 // Find the template which this extension corresponds to
1701 for (size_t i
= 0; i
< m_templates
.GetCount(); i
++)
1703 wxDocTemplate
*temp
= (wxDocTemplate
*)m_templates
.Item(i
)->GetData();
1704 if ( temp
->FileMatchesTemplate(path
) )
1713 // Prompts user to open a file, using file specs in templates.
1714 // Must extend the file selector dialog or implement own; OR
1715 // match the extension to the template extension.
1717 wxDocTemplate
*wxDocManager::SelectDocumentPath(wxDocTemplate
**templates
,
1720 long WXUNUSED(flags
),
1721 bool WXUNUSED(save
))
1723 #ifdef wxHAS_MULTIPLE_FILEDLG_FILTERS
1726 for (int i
= 0; i
< noTemplates
; i
++)
1728 if (templates
[i
]->IsVisible())
1730 // add a '|' to separate this filter from the previous one
1731 if ( !descrBuf
.empty() )
1732 descrBuf
<< wxT('|');
1734 descrBuf
<< templates
[i
]->GetDescription()
1735 << wxT(" (") << templates
[i
]->GetFileFilter() << wxT(") |")
1736 << templates
[i
]->GetFileFilter();
1740 wxString descrBuf
= wxT("*.*");
1741 wxUnusedVar(noTemplates
);
1744 int FilterIndex
= -1;
1746 wxString pathTmp
= wxFileSelectorEx(_("Open File"),
1751 wxFD_OPEN
| wxFD_FILE_MUST_EXIST
);
1753 wxDocTemplate
*theTemplate
= NULL
;
1754 if (!pathTmp
.empty())
1756 if (!wxFileExists(pathTmp
))
1759 if (!wxTheApp
->GetAppDisplayName().empty())
1760 msgTitle
= wxTheApp
->GetAppDisplayName();
1762 msgTitle
= wxString(_("File error"));
1764 wxMessageBox(_("Sorry, could not open this file."),
1766 wxOK
| wxICON_EXCLAMATION
| wxCENTRE
);
1768 path
= wxEmptyString
;
1772 SetLastDirectory(wxPathOnly(pathTmp
));
1776 // first choose the template using the extension, if this fails (i.e.
1777 // wxFileSelectorEx() didn't fill it), then use the path
1778 if ( FilterIndex
!= -1 )
1779 theTemplate
= templates
[FilterIndex
];
1781 theTemplate
= FindTemplateForPath(path
);
1784 // Since we do not add files with non-default extensions to the
1785 // file history this can only happen if the application changes the
1786 // allowed templates in runtime.
1787 wxMessageBox(_("Sorry, the format for this file is unknown."),
1789 wxOK
| wxICON_EXCLAMATION
| wxCENTRE
);
1800 wxDocTemplate
*wxDocManager::SelectDocumentType(wxDocTemplate
**templates
,
1801 int noTemplates
, bool sort
)
1803 wxArrayString strings
;
1804 wxScopedArray
<wxDocTemplate
*> data(new wxDocTemplate
*[noTemplates
]);
1808 for (i
= 0; i
< noTemplates
; i
++)
1810 if (templates
[i
]->IsVisible())
1814 for (j
= 0; j
< n
; j
++)
1816 //filter out NOT unique documents + view combinations
1817 if ( templates
[i
]->m_docTypeName
== data
[j
]->m_docTypeName
&&
1818 templates
[i
]->m_viewTypeName
== data
[j
]->m_viewTypeName
1825 strings
.Add(templates
[i
]->m_description
);
1827 data
[n
] = templates
[i
];
1835 strings
.Sort(); // ascending sort
1836 // Yes, this will be slow, but template lists
1837 // are typically short.
1839 n
= strings
.Count();
1840 for (i
= 0; i
< n
; i
++)
1842 for (j
= 0; j
< noTemplates
; j
++)
1844 if (strings
[i
] == templates
[j
]->m_description
)
1845 data
[i
] = templates
[j
];
1850 wxDocTemplate
*theTemplate
;
1855 // no visible templates, hence nothing to choose from
1860 // don't propose the user to choose if he has no choice
1861 theTemplate
= data
[0];
1865 // propose the user to choose one of several
1866 theTemplate
= (wxDocTemplate
*)wxGetSingleChoiceData
1868 _("Select a document template"),
1878 wxDocTemplate
*wxDocManager::SelectViewType(wxDocTemplate
**templates
,
1879 int noTemplates
, bool sort
)
1881 wxArrayString strings
;
1882 wxScopedArray
<wxDocTemplate
*> data(new wxDocTemplate
*[noTemplates
]);
1886 for (i
= 0; i
< noTemplates
; i
++)
1888 wxDocTemplate
*templ
= templates
[i
];
1889 if ( templ
->IsVisible() && !templ
->GetViewName().empty() )
1893 for (j
= 0; j
< n
; j
++)
1895 //filter out NOT unique views
1896 if ( templates
[i
]->m_viewTypeName
== data
[j
]->m_viewTypeName
)
1902 strings
.Add(templ
->m_viewTypeName
);
1911 strings
.Sort(); // ascending sort
1912 // Yes, this will be slow, but template lists
1913 // are typically short.
1915 n
= strings
.Count();
1916 for (i
= 0; i
< n
; i
++)
1918 for (j
= 0; j
< noTemplates
; j
++)
1920 if (strings
[i
] == templates
[j
]->m_viewTypeName
)
1921 data
[i
] = templates
[j
];
1926 wxDocTemplate
*theTemplate
;
1928 // the same logic as above
1936 theTemplate
= data
[0];
1940 theTemplate
= (wxDocTemplate
*)wxGetSingleChoiceData
1942 _("Select a document view"),
1953 void wxDocManager::AssociateTemplate(wxDocTemplate
*temp
)
1955 if (!m_templates
.Member(temp
))
1956 m_templates
.Append(temp
);
1959 void wxDocManager::DisassociateTemplate(wxDocTemplate
*temp
)
1961 m_templates
.DeleteObject(temp
);
1964 wxDocTemplate
* wxDocManager::FindTemplate(const wxClassInfo
* classinfo
)
1966 for ( wxList::compatibility_iterator node
= m_templates
.GetFirst();
1968 node
= node
->GetNext() )
1970 wxDocTemplate
* t
= wxStaticCast(node
->GetData(), wxDocTemplate
);
1971 if ( t
->GetDocClassInfo() == classinfo
)
1978 // Add and remove a document from the manager's list
1979 void wxDocManager::AddDocument(wxDocument
*doc
)
1981 if (!m_docs
.Member(doc
))
1985 void wxDocManager::RemoveDocument(wxDocument
*doc
)
1987 m_docs
.DeleteObject(doc
);
1990 // Views or windows should inform the document manager
1991 // when a view is going in or out of focus
1992 void wxDocManager::ActivateView(wxView
*view
, bool activate
)
1996 m_currentView
= view
;
2000 if ( m_currentView
== view
)
2002 // don't keep stale pointer
2003 m_currentView
= NULL
;
2008 // ----------------------------------------------------------------------------
2009 // wxDocChildFrameAnyBase
2010 // ----------------------------------------------------------------------------
2012 bool wxDocChildFrameAnyBase::CloseView(wxCloseEvent
& event
)
2016 // notice that we must call wxView::Close() and OnClose() called from
2017 // it in any case, even if we know that we are going to close anyhow
2018 if ( !m_childView
->Close(false) && event
.CanVeto() )
2024 m_childView
->Activate(false);
2026 // it is important to reset m_childView frame pointer to NULL before
2027 // deleting it because while normally it is the frame which deletes the
2028 // view when it's closed, the view also closes the frame if it is
2029 // deleted directly not by us as indicated by its doc child frame
2030 // pointer still being set
2031 m_childView
->SetDocChildFrame(NULL
);
2032 wxDELETE(m_childView
);
2035 m_childDocument
= NULL
;
2040 // ----------------------------------------------------------------------------
2041 // wxDocParentFrameAnyBase
2042 // ----------------------------------------------------------------------------
2044 #if wxUSE_PRINTING_ARCHITECTURE
2049 wxString
GetAppropriateTitle(const wxView
*view
, const wxString
& titleGiven
)
2051 wxString
title(titleGiven
);
2052 if ( title
.empty() )
2054 if ( view
&& view
->GetDocument() )
2055 title
= view
->GetDocument()->GetUserReadableName();
2057 title
= _("Printout");
2063 } // anonymous namespace
2065 wxDocPrintout::wxDocPrintout(wxView
*view
, const wxString
& title
)
2066 : wxPrintout(GetAppropriateTitle(view
, title
))
2068 m_printoutView
= view
;
2071 bool wxDocPrintout::OnPrintPage(int WXUNUSED(page
))
2075 // Get the logical pixels per inch of screen and printer
2076 int ppiScreenX
, ppiScreenY
;
2077 GetPPIScreen(&ppiScreenX
, &ppiScreenY
);
2078 wxUnusedVar(ppiScreenY
);
2079 int ppiPrinterX
, ppiPrinterY
;
2080 GetPPIPrinter(&ppiPrinterX
, &ppiPrinterY
);
2081 wxUnusedVar(ppiPrinterY
);
2083 // This scales the DC so that the printout roughly represents the
2084 // the screen scaling. The text point size _should_ be the right size
2085 // but in fact is too small for some reason. This is a detail that will
2086 // need to be addressed at some point but can be fudged for the
2088 float scale
= (float)((float)ppiPrinterX
/(float)ppiScreenX
);
2090 // Now we have to check in case our real page size is reduced
2091 // (e.g. because we're drawing to a print preview memory DC)
2092 int pageWidth
, pageHeight
;
2094 dc
->GetSize(&w
, &h
);
2095 GetPageSizePixels(&pageWidth
, &pageHeight
);
2096 wxUnusedVar(pageHeight
);
2098 // If printer pageWidth == current DC width, then this doesn't
2099 // change. But w might be the preview bitmap width, so scale down.
2100 float overallScale
= scale
* (float)(w
/(float)pageWidth
);
2101 dc
->SetUserScale(overallScale
, overallScale
);
2105 m_printoutView
->OnDraw(dc
);
2110 bool wxDocPrintout::HasPage(int pageNum
)
2112 return (pageNum
== 1);
2115 bool wxDocPrintout::OnBeginDocument(int startPage
, int endPage
)
2117 if (!wxPrintout::OnBeginDocument(startPage
, endPage
))
2123 void wxDocPrintout::GetPageInfo(int *minPage
, int *maxPage
,
2124 int *selPageFrom
, int *selPageTo
)
2132 #endif // wxUSE_PRINTING_ARCHITECTURE
2134 // ----------------------------------------------------------------------------
2135 // Permits compatibility with existing file formats and functions that
2136 // manipulate files directly
2137 // ----------------------------------------------------------------------------
2139 #if wxUSE_STD_IOSTREAM
2141 bool wxTransferFileToStream(const wxString
& filename
, wxSTD ostream
& stream
)
2144 wxFFile
file(filename
, wxT("rb"));
2146 wxFile
file(filename
, wxFile::read
);
2148 if ( !file
.IsOpened() )
2156 nRead
= file
.Read(buf
, WXSIZEOF(buf
));
2160 stream
.write(buf
, nRead
);
2164 while ( !file
.Eof() );
2169 bool wxTransferStreamToFile(wxSTD istream
& stream
, const wxString
& filename
)
2172 wxFFile
file(filename
, wxT("wb"));
2174 wxFile
file(filename
, wxFile::write
);
2176 if ( !file
.IsOpened() )
2182 stream
.read(buf
, WXSIZEOF(buf
));
2183 if ( !stream
.bad() ) // fail may be set on EOF, don't use operator!()
2185 if ( !file
.Write(buf
, stream
.gcount()) )
2189 while ( !stream
.eof() );
2194 #else // !wxUSE_STD_IOSTREAM
2196 bool wxTransferFileToStream(const wxString
& filename
, wxOutputStream
& stream
)
2199 wxFFile
file(filename
, wxT("rb"));
2201 wxFile
file(filename
, wxFile::read
);
2203 if ( !file
.IsOpened() )
2211 nRead
= file
.Read(buf
, WXSIZEOF(buf
));
2215 stream
.Write(buf
, nRead
);
2219 while ( !file
.Eof() );
2224 bool wxTransferStreamToFile(wxInputStream
& stream
, const wxString
& filename
)
2227 wxFFile
file(filename
, wxT("wb"));
2229 wxFile
file(filename
, wxFile::write
);
2231 if ( !file
.IsOpened() )
2237 stream
.Read(buf
, WXSIZEOF(buf
));
2239 const size_t nRead
= stream
.LastRead();
2248 if ( !file
.Write(buf
, nRead
) )
2255 #endif // wxUSE_STD_IOSTREAM/!wxUSE_STD_IOSTREAM
2257 #endif // wxUSE_DOC_VIEW_ARCHITECTURE