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
30 #include "wx/string.h"
34 #include "wx/dialog.h"
37 #include "wx/filedlg.h"
45 #include "wx/filename.h"
52 #if wxUSE_PRINTING_ARCHITECTURE
53 #include "wx/prntbase.h"
54 #include "wx/printdlg.h"
57 #include "wx/msgdlg.h"
58 #include "wx/choicdlg.h"
59 #include "wx/docview.h"
60 #include "wx/confbase.h"
62 #include "wx/cmdproc.h"
63 #include "wx/tokenzr.h"
68 #if wxUSE_STD_IOSTREAM
69 #include "wx/ioswrap.h"
76 #include "wx/wfstream.h"
79 // ----------------------------------------------------------------------------
81 // ----------------------------------------------------------------------------
83 IMPLEMENT_ABSTRACT_CLASS(wxDocument
, wxEvtHandler
)
84 IMPLEMENT_ABSTRACT_CLASS(wxView
, wxEvtHandler
)
85 IMPLEMENT_ABSTRACT_CLASS(wxDocTemplate
, wxObject
)
86 IMPLEMENT_DYNAMIC_CLASS(wxDocManager
, wxEvtHandler
)
87 IMPLEMENT_CLASS(wxDocChildFrame
, wxFrame
)
88 IMPLEMENT_CLASS(wxDocParentFrame
, wxFrame
)
90 #if wxUSE_PRINTING_ARCHITECTURE
91 IMPLEMENT_DYNAMIC_CLASS(wxDocPrintout
, wxPrintout
)
94 IMPLEMENT_DYNAMIC_CLASS(wxFileHistory
, wxObject
)
96 // ----------------------------------------------------------------------------
97 // function prototypes
98 // ----------------------------------------------------------------------------
100 static inline wxString
FindExtension(const wxChar
*path
);
101 static wxWindow
* wxFindSuitableParent(void);
103 // ----------------------------------------------------------------------------
105 // ----------------------------------------------------------------------------
107 static const wxChar
*s_MRUEntryFormat
= wxT("&%d %s");
109 // ============================================================================
111 // ============================================================================
113 // ----------------------------------------------------------------------------
115 // ----------------------------------------------------------------------------
117 static wxString
FindExtension(const wxChar
*path
)
120 wxSplitPath(path
, NULL
, NULL
, &ext
);
122 // VZ: extensions are considered not case sensitive - is this really a good
124 return ext
.MakeLower();
127 // ----------------------------------------------------------------------------
128 // Definition of wxDocument
129 // ----------------------------------------------------------------------------
131 wxDocument::wxDocument(wxDocument
*parent
)
133 m_documentModified
= false;
134 m_documentParent
= parent
;
135 m_documentTemplate
= (wxDocTemplate
*) NULL
;
136 m_commandProcessor
= (wxCommandProcessor
*) NULL
;
140 bool wxDocument::DeleteContents()
145 wxDocument::~wxDocument()
149 if (m_commandProcessor
)
150 delete m_commandProcessor
;
152 if (GetDocumentManager())
153 GetDocumentManager()->RemoveDocument(this);
155 // Not safe to do here, since it'll invoke virtual view functions
156 // expecting to see valid derived objects: and by the time we get here,
157 // we've called destructors higher up.
161 bool wxDocument::Close()
163 if (OnSaveModified())
164 return OnCloseDocument();
169 bool wxDocument::OnCloseDocument()
171 // Tell all views that we're about to close
178 // Note that this implicitly deletes the document when the last view is
180 bool wxDocument::DeleteAllViews()
182 wxDocManager
* manager
= GetDocumentManager();
184 // first check if all views agree to be closed
185 const wxList::iterator end
= m_documentViews
.end();
186 for ( wxList::iterator i
= m_documentViews
.begin(); i
!= end
; ++i
)
188 wxView
*view
= (wxView
*)*i
;
189 if ( !view
->Close() )
193 // all views agreed to close, now do close them
194 if ( m_documentViews
.empty() )
196 // normally the document would be implicitly deleted when the last view
197 // is, but if don't have any views, do it here instead
198 if ( manager
&& manager
->GetDocuments().Member(this) )
203 // as we delete elements we iterate over, don't use the usual "from
204 // begin to end" loop
207 wxView
*view
= (wxView
*)*m_documentViews
.begin();
209 bool isLastOne
= m_documentViews
.size() == 1;
211 // this always deletes the node implicitly and if this is the last
212 // view also deletes this object itself (also implicitly, great),
213 // so we can't test for m_documentViews.empty() after calling this!
224 wxView
*wxDocument::GetFirstView() const
226 if (m_documentViews
.GetCount() == 0)
227 return (wxView
*) NULL
;
228 return (wxView
*)m_documentViews
.GetFirst()->GetData();
231 wxDocManager
*wxDocument::GetDocumentManager() const
233 return (m_documentTemplate
? m_documentTemplate
->GetDocumentManager() : (wxDocManager
*) NULL
);
236 bool wxDocument::OnNewDocument()
238 if (!OnSaveModified())
241 if (OnCloseDocument()==false) return false;
244 SetDocumentSaved(false);
247 GetDocumentManager()->MakeDefaultName(name
);
249 SetFilename(name
, true);
254 bool wxDocument::Save()
256 if (!IsModified() && m_savedYet
)
259 if ( m_documentFile
.empty() || !m_savedYet
)
262 return OnSaveDocument(m_documentFile
);
265 bool wxDocument::SaveAs()
267 wxDocTemplate
*docTemplate
= GetDocumentTemplate();
271 #if defined(__WXMSW__) || defined(__WXGTK__) || defined(__WXMAC__)
272 wxString filter
= docTemplate
->GetDescription() + wxT(" (") + docTemplate
->GetFileFilter() + wxT(")|") + docTemplate
->GetFileFilter();
274 // Now see if there are some other template with identical view and document
275 // classes, whose filters may also be used.
277 if (docTemplate
->GetViewClassInfo() && docTemplate
->GetDocClassInfo())
279 wxList::compatibility_iterator node
= wxDocManager::GetDocumentManager()->GetTemplates().GetFirst();
282 wxDocTemplate
*t
= (wxDocTemplate
*) node
->GetData();
284 if (t
->IsVisible() && t
!= docTemplate
&&
285 t
->GetViewClassInfo() == docTemplate
->GetViewClassInfo() &&
286 t
->GetDocClassInfo() == docTemplate
->GetDocClassInfo())
288 // add a '|' to separate this filter from the previous one
289 if ( !filter
.empty() )
292 filter
<< t
->GetDescription() << wxT(" (") << t
->GetFileFilter() << wxT(") |")
293 << t
->GetFileFilter();
296 node
= node
->GetNext();
300 wxString filter
= docTemplate
->GetFileFilter() ;
302 wxString tmp
= wxFileSelector(_("Save as"),
303 docTemplate
->GetDirectory(),
304 wxFileNameFromPath(GetFilename()),
305 docTemplate
->GetDefaultExtension(),
307 wxSAVE
| wxOVERWRITE_PROMPT
,
308 GetDocumentWindow());
313 wxString
fileName(tmp
);
314 wxString path
, name
, ext
;
315 wxSplitPath(fileName
, & path
, & name
, & ext
);
319 fileName
+= wxT(".");
320 fileName
+= docTemplate
->GetDefaultExtension();
323 SetFilename(fileName
);
324 SetTitle(wxFileNameFromPath(fileName
));
326 // Notify the views that the filename has changed
327 wxList::compatibility_iterator node
= m_documentViews
.GetFirst();
330 wxView
*view
= (wxView
*)node
->GetData();
331 view
->OnChangeFilename();
332 node
= node
->GetNext();
335 // Files that were not saved correctly are not added to the FileHistory.
336 if (!OnSaveDocument(m_documentFile
))
339 // A file that doesn't use the default extension of its document template cannot be opened
340 // via the FileHistory, so we do not add it.
341 if (docTemplate
->FileMatchesTemplate(fileName
))
343 GetDocumentManager()->AddFileToHistory(fileName
);
347 // The user will probably not be able to open the file again, so
348 // we could warn about the wrong file-extension here.
353 bool wxDocument::OnSaveDocument(const wxString
& file
)
358 if ( !DoSaveDocument(file
) )
363 SetDocumentSaved(true);
365 wxFileName
fn(file
) ;
366 fn
.MacSetDefaultTypeAndCreator() ;
371 bool wxDocument::OnOpenDocument(const wxString
& file
)
373 if (!OnSaveModified())
376 if ( !DoOpenDocument(file
) )
379 SetFilename(file
, true);
388 #if wxUSE_STD_IOSTREAM
389 wxSTD istream
& wxDocument::LoadObject(wxSTD istream
& stream
)
391 wxInputStream
& wxDocument::LoadObject(wxInputStream
& stream
)
397 #if wxUSE_STD_IOSTREAM
398 wxSTD ostream
& wxDocument::SaveObject(wxSTD ostream
& stream
)
400 wxOutputStream
& wxDocument::SaveObject(wxOutputStream
& stream
)
406 bool wxDocument::Revert()
412 // Get title, or filename if no title, else unnamed
413 bool wxDocument::GetPrintableName(wxString
& buf
) const
415 if (!m_documentTitle
.empty())
417 buf
= m_documentTitle
;
420 else if (!m_documentFile
.empty())
422 buf
= wxFileNameFromPath(m_documentFile
);
432 wxWindow
*wxDocument::GetDocumentWindow() const
434 wxView
*view
= GetFirstView();
436 return view
->GetFrame();
438 return wxTheApp
->GetTopWindow();
441 wxCommandProcessor
*wxDocument::OnCreateCommandProcessor()
443 return new wxCommandProcessor
;
446 // true if safe to close
447 bool wxDocument::OnSaveModified()
452 GetPrintableName(title
);
455 if (!wxTheApp
->GetAppName().empty())
456 msgTitle
= wxTheApp
->GetAppName();
458 msgTitle
= wxString(_("Warning"));
461 prompt
.Printf(_("Do you want to save changes to document %s?"),
462 (const wxChar
*)title
);
463 int res
= wxMessageBox(prompt
, msgTitle
,
464 wxYES_NO
|wxCANCEL
|wxICON_QUESTION
,
465 GetDocumentWindow());
471 else if (res
== wxYES
)
473 else if (res
== wxCANCEL
)
479 bool wxDocument::Draw(wxDC
& WXUNUSED(context
))
484 bool wxDocument::AddView(wxView
*view
)
486 if (!m_documentViews
.Member(view
))
488 m_documentViews
.Append(view
);
494 bool wxDocument::RemoveView(wxView
*view
)
496 (void)m_documentViews
.DeleteObject(view
);
501 bool wxDocument::OnCreate(const wxString
& WXUNUSED(path
), long flags
)
503 if (GetDocumentTemplate()->CreateView(this, flags
))
509 // Called after a view is added or removed.
510 // The default implementation deletes the document if
511 // there are no more views.
512 void wxDocument::OnChangedViewList()
514 if (m_documentViews
.GetCount() == 0)
516 if (OnSaveModified())
523 void wxDocument::UpdateAllViews(wxView
*sender
, wxObject
*hint
)
525 wxList::compatibility_iterator node
= m_documentViews
.GetFirst();
528 wxView
*view
= (wxView
*)node
->GetData();
530 view
->OnUpdate(sender
, hint
);
531 node
= node
->GetNext();
535 void wxDocument::NotifyClosing()
537 wxList::compatibility_iterator node
= m_documentViews
.GetFirst();
540 wxView
*view
= (wxView
*)node
->GetData();
541 view
->OnClosingDocument();
542 node
= node
->GetNext();
546 void wxDocument::SetFilename(const wxString
& filename
, bool notifyViews
)
548 m_documentFile
= filename
;
551 // Notify the views that the filename has changed
552 wxList::compatibility_iterator node
= m_documentViews
.GetFirst();
555 wxView
*view
= (wxView
*)node
->GetData();
556 view
->OnChangeFilename();
557 node
= node
->GetNext();
562 bool wxDocument::DoSaveDocument(const wxString
& file
)
565 if (!wxTheApp
->GetAppName().empty())
566 msgTitle
= wxTheApp
->GetAppName();
568 msgTitle
= wxString(_("File error"));
570 #if wxUSE_STD_IOSTREAM
571 wxSTD ofstream
store(file
.mb_str(), wxSTD
ios::binary
);
572 if (store
.fail() || store
.bad())
574 wxFileOutputStream
store(file
);
575 if (store
.GetLastError() != wxSTREAM_NO_ERROR
)
578 (void)wxMessageBox(_("Sorry, could not open this file for saving."), msgTitle
, wxOK
| wxICON_EXCLAMATION
,
579 GetDocumentWindow());
583 if (!SaveObject(store
))
585 (void)wxMessageBox(_("Sorry, could not save this file."), msgTitle
, wxOK
| wxICON_EXCLAMATION
,
586 GetDocumentWindow());
594 bool wxDocument::DoOpenDocument(const wxString
& file
)
596 #if wxUSE_STD_IOSTREAM
597 wxSTD ifstream
store(file
.mb_str(), wxSTD
ios::binary
);
598 if (!store
.fail() && !store
.bad())
600 wxFileInputStream
store(file
);
601 if (store
.GetLastError() == wxSTREAM_NO_ERROR
)
604 #if wxUSE_STD_IOSTREAM
606 if ( !!store
|| store
.eof() )
608 int res
= LoadObject(store
).GetLastError();
609 if ( res
== wxSTREAM_NO_ERROR
|| res
== wxSTREAM_EOF
)
614 wxLogError(_("Sorry, could not open this file."));
619 // ----------------------------------------------------------------------------
621 // ----------------------------------------------------------------------------
625 m_viewDocument
= (wxDocument
*) NULL
;
627 m_viewFrame
= (wxFrame
*) NULL
;
632 GetDocumentManager()->ActivateView(this, false);
633 m_viewDocument
->RemoveView(this);
636 // Extend event processing to search the document's event table
637 bool wxView::ProcessEvent(wxEvent
& event
)
639 if ( !GetDocument() || !GetDocument()->ProcessEvent(event
) )
640 return wxEvtHandler::ProcessEvent(event
);
645 void wxView::OnActivateView(bool WXUNUSED(activate
), wxView
*WXUNUSED(activeView
), wxView
*WXUNUSED(deactiveView
))
649 void wxView::OnPrint(wxDC
*dc
, wxObject
*WXUNUSED(info
))
654 void wxView::OnUpdate(wxView
*WXUNUSED(sender
), wxObject
*WXUNUSED(hint
))
658 void wxView::OnChangeFilename()
660 // GetFrame can return wxWindow rather than wxTopLevelWindow due to
661 // generic MDI implementation so use SetLabel rather than SetTitle.
662 // It should cause SetTitle() for top level windows.
663 wxWindow
*win
= GetFrame();
666 wxDocument
*doc
= GetDocument();
670 doc
->GetPrintableName(name
);
674 void wxView::SetDocument(wxDocument
*doc
)
676 m_viewDocument
= doc
;
681 bool wxView::Close(bool deleteWindow
)
683 if (OnClose(deleteWindow
))
689 void wxView::Activate(bool activate
)
691 if (GetDocument() && GetDocumentManager())
693 OnActivateView(activate
, this, GetDocumentManager()->GetCurrentView());
694 GetDocumentManager()->ActivateView(this, activate
);
698 bool wxView::OnClose(bool WXUNUSED(deleteWindow
))
700 return GetDocument() ? GetDocument()->Close() : true;
703 #if wxUSE_PRINTING_ARCHITECTURE
704 wxPrintout
*wxView::OnCreatePrintout()
706 return new wxDocPrintout(this);
708 #endif // wxUSE_PRINTING_ARCHITECTURE
710 // ----------------------------------------------------------------------------
712 // ----------------------------------------------------------------------------
714 wxDocTemplate::wxDocTemplate(wxDocManager
*manager
,
715 const wxString
& descr
,
716 const wxString
& filter
,
719 const wxString
& docTypeName
,
720 const wxString
& viewTypeName
,
721 wxClassInfo
*docClassInfo
,
722 wxClassInfo
*viewClassInfo
,
725 m_documentManager
= manager
;
726 m_description
= descr
;
729 m_fileFilter
= filter
;
731 m_docTypeName
= docTypeName
;
732 m_viewTypeName
= viewTypeName
;
733 m_documentManager
->AssociateTemplate(this);
735 m_docClassInfo
= docClassInfo
;
736 m_viewClassInfo
= viewClassInfo
;
739 wxDocTemplate::~wxDocTemplate()
741 m_documentManager
->DisassociateTemplate(this);
744 // Tries to dynamically construct an object of the right class.
745 wxDocument
*wxDocTemplate::CreateDocument(const wxString
& path
, long flags
)
747 wxDocument
*doc
= DoCreateDocument();
749 return (wxDocument
*) NULL
;
751 if (InitDocument(doc
, path
, flags
))
757 return (wxDocument
*) NULL
;
761 bool wxDocTemplate::InitDocument(wxDocument
* doc
, const wxString
& path
, long flags
)
763 doc
->SetFilename(path
);
764 doc
->SetDocumentTemplate(this);
765 GetDocumentManager()->AddDocument(doc
);
766 doc
->SetCommandProcessor(doc
->OnCreateCommandProcessor());
768 if (doc
->OnCreate(path
, flags
))
772 if (GetDocumentManager()->GetDocuments().Member(doc
))
773 doc
->DeleteAllViews();
778 wxView
*wxDocTemplate::CreateView(wxDocument
*doc
, long flags
)
780 wxView
*view
= DoCreateView();
782 return (wxView
*) NULL
;
784 view
->SetDocument(doc
);
785 if (view
->OnCreate(doc
, flags
))
792 return (wxView
*) NULL
;
796 // The default (very primitive) format detection: check is the extension is
797 // that of the template
798 bool wxDocTemplate::FileMatchesTemplate(const wxString
& path
)
800 wxStringTokenizer
parser (GetFileFilter(), wxT(";"));
801 wxString anything
= wxT ("*");
802 while (parser
.HasMoreTokens())
804 wxString filter
= parser
.GetNextToken();
805 wxString filterExt
= FindExtension (filter
);
806 if ( filter
.IsSameAs (anything
) ||
807 filterExt
.IsSameAs (anything
) ||
808 filterExt
.IsSameAs (FindExtension (path
)) )
811 return GetDefaultExtension().IsSameAs(FindExtension(path
));
814 wxDocument
*wxDocTemplate::DoCreateDocument()
817 return (wxDocument
*) NULL
;
819 return (wxDocument
*)m_docClassInfo
->CreateObject();
822 wxView
*wxDocTemplate::DoCreateView()
824 if (!m_viewClassInfo
)
825 return (wxView
*) NULL
;
827 return (wxView
*)m_viewClassInfo
->CreateObject();
830 // ----------------------------------------------------------------------------
832 // ----------------------------------------------------------------------------
834 BEGIN_EVENT_TABLE(wxDocManager
, wxEvtHandler
)
835 EVT_MENU(wxID_OPEN
, wxDocManager::OnFileOpen
)
836 EVT_MENU(wxID_CLOSE
, wxDocManager::OnFileClose
)
837 EVT_MENU(wxID_CLOSE_ALL
, wxDocManager::OnFileCloseAll
)
838 EVT_MENU(wxID_REVERT
, wxDocManager::OnFileRevert
)
839 EVT_MENU(wxID_NEW
, wxDocManager::OnFileNew
)
840 EVT_MENU(wxID_SAVE
, wxDocManager::OnFileSave
)
841 EVT_MENU(wxID_SAVEAS
, wxDocManager::OnFileSaveAs
)
842 EVT_MENU(wxID_UNDO
, wxDocManager::OnUndo
)
843 EVT_MENU(wxID_REDO
, wxDocManager::OnRedo
)
845 EVT_UPDATE_UI(wxID_OPEN
, wxDocManager::OnUpdateFileOpen
)
846 EVT_UPDATE_UI(wxID_CLOSE
, wxDocManager::OnUpdateFileClose
)
847 EVT_UPDATE_UI(wxID_CLOSE_ALL
, wxDocManager::OnUpdateFileClose
)
848 EVT_UPDATE_UI(wxID_REVERT
, wxDocManager::OnUpdateFileRevert
)
849 EVT_UPDATE_UI(wxID_NEW
, wxDocManager::OnUpdateFileNew
)
850 EVT_UPDATE_UI(wxID_SAVE
, wxDocManager::OnUpdateFileSave
)
851 EVT_UPDATE_UI(wxID_SAVEAS
, wxDocManager::OnUpdateFileSaveAs
)
852 EVT_UPDATE_UI(wxID_UNDO
, wxDocManager::OnUpdateUndo
)
853 EVT_UPDATE_UI(wxID_REDO
, wxDocManager::OnUpdateRedo
)
855 #if wxUSE_PRINTING_ARCHITECTURE
856 EVT_MENU(wxID_PRINT
, wxDocManager::OnPrint
)
857 EVT_MENU(wxID_PREVIEW
, wxDocManager::OnPreview
)
859 EVT_UPDATE_UI(wxID_PRINT
, wxDocManager::OnUpdatePrint
)
860 EVT_UPDATE_UI(wxID_PREVIEW
, wxDocManager::OnUpdatePreview
)
864 wxDocManager
* wxDocManager::sm_docManager
= (wxDocManager
*) NULL
;
866 wxDocManager::wxDocManager(long flags
, bool initialize
)
868 m_defaultDocumentNameCounter
= 1;
870 m_currentView
= (wxView
*) NULL
;
871 m_maxDocsOpen
= 10000;
872 m_fileHistory
= (wxFileHistory
*) NULL
;
875 sm_docManager
= this;
878 wxDocManager::~wxDocManager()
882 delete m_fileHistory
;
883 sm_docManager
= (wxDocManager
*) NULL
;
886 // closes the specified document
887 bool wxDocManager::CloseDocument(wxDocument
* doc
, bool force
)
889 if (doc
->Close() || force
)
891 // Implicitly deletes the document when
892 // the last view is deleted
893 doc
->DeleteAllViews();
895 // Check we're really deleted
896 if (m_docs
.Member(doc
))
904 bool wxDocManager::CloseDocuments(bool force
)
906 wxList::compatibility_iterator node
= m_docs
.GetFirst();
909 wxDocument
*doc
= (wxDocument
*)node
->GetData();
910 wxList::compatibility_iterator next
= node
->GetNext();
912 if (!CloseDocument(doc
, force
))
915 // This assumes that documents are not connected in
916 // any way, i.e. deleting one document does NOT
923 bool wxDocManager::Clear(bool force
)
925 if (!CloseDocuments(force
))
928 m_currentView
= NULL
;
930 wxList::compatibility_iterator node
= m_templates
.GetFirst();
933 wxDocTemplate
*templ
= (wxDocTemplate
*) node
->GetData();
934 wxList::compatibility_iterator next
= node
->GetNext();
941 bool wxDocManager::Initialize()
943 m_fileHistory
= OnCreateFileHistory();
947 wxFileHistory
*wxDocManager::OnCreateFileHistory()
949 return new wxFileHistory
;
952 void wxDocManager::OnFileClose(wxCommandEvent
& WXUNUSED(event
))
954 wxDocument
*doc
= GetCurrentDocument();
959 doc
->DeleteAllViews();
960 if (m_docs
.Member(doc
))
965 void wxDocManager::OnFileCloseAll(wxCommandEvent
& WXUNUSED(event
))
967 CloseDocuments(false);
970 void wxDocManager::OnFileNew(wxCommandEvent
& WXUNUSED(event
))
972 CreateDocument( wxEmptyString
, wxDOC_NEW
);
975 void wxDocManager::OnFileOpen(wxCommandEvent
& WXUNUSED(event
))
977 if ( !CreateDocument( wxEmptyString
, 0) )
983 void wxDocManager::OnFileRevert(wxCommandEvent
& WXUNUSED(event
))
985 wxDocument
*doc
= GetCurrentDocument();
991 void wxDocManager::OnFileSave(wxCommandEvent
& WXUNUSED(event
))
993 wxDocument
*doc
= GetCurrentDocument();
999 void wxDocManager::OnFileSaveAs(wxCommandEvent
& WXUNUSED(event
))
1001 wxDocument
*doc
= GetCurrentDocument();
1007 void wxDocManager::OnPrint(wxCommandEvent
& WXUNUSED(event
))
1009 #if wxUSE_PRINTING_ARCHITECTURE
1010 wxView
*view
= GetCurrentView();
1014 wxPrintout
*printout
= view
->OnCreatePrintout();
1018 printer
.Print(view
->GetFrame(), printout
, true);
1022 #endif // wxUSE_PRINTING_ARCHITECTURE
1025 void wxDocManager::OnPreview(wxCommandEvent
& WXUNUSED(event
))
1027 #if wxUSE_PRINTING_ARCHITECTURE
1028 wxView
*view
= GetCurrentView();
1032 wxPrintout
*printout
= view
->OnCreatePrintout();
1035 // Pass two printout objects: for preview, and possible printing.
1036 wxPrintPreviewBase
*preview
= new wxPrintPreview(printout
, view
->OnCreatePrintout());
1037 if ( !preview
->Ok() )
1040 wxMessageBox( _("Sorry, print preview needs a printer to be installed.") );
1044 wxPreviewFrame
*frame
= new wxPreviewFrame(preview
, (wxFrame
*)wxTheApp
->GetTopWindow(), _("Print Preview"),
1045 wxPoint(100, 100), wxSize(600, 650));
1046 frame
->Centre(wxBOTH
);
1047 frame
->Initialize();
1050 #endif // wxUSE_PRINTING_ARCHITECTURE
1053 void wxDocManager::OnUndo(wxCommandEvent
& event
)
1055 wxDocument
*doc
= GetCurrentDocument();
1058 if (doc
->GetCommandProcessor())
1059 doc
->GetCommandProcessor()->Undo();
1064 void wxDocManager::OnRedo(wxCommandEvent
& event
)
1066 wxDocument
*doc
= GetCurrentDocument();
1069 if (doc
->GetCommandProcessor())
1070 doc
->GetCommandProcessor()->Redo();
1075 // Handlers for UI update commands
1077 void wxDocManager::OnUpdateFileOpen(wxUpdateUIEvent
& event
)
1079 event
.Enable( true );
1082 void wxDocManager::OnUpdateFileClose(wxUpdateUIEvent
& event
)
1084 wxDocument
*doc
= GetCurrentDocument();
1085 event
.Enable( (doc
!= (wxDocument
*) NULL
) );
1088 void wxDocManager::OnUpdateFileRevert(wxUpdateUIEvent
& event
)
1090 wxDocument
*doc
= GetCurrentDocument();
1091 event
.Enable( (doc
!= (wxDocument
*) NULL
) );
1094 void wxDocManager::OnUpdateFileNew(wxUpdateUIEvent
& event
)
1096 event
.Enable( true );
1099 void wxDocManager::OnUpdateFileSave(wxUpdateUIEvent
& event
)
1101 wxDocument
*doc
= GetCurrentDocument();
1102 event
.Enable( doc
&& doc
->IsModified() );
1105 void wxDocManager::OnUpdateFileSaveAs(wxUpdateUIEvent
& event
)
1107 wxDocument
*doc
= GetCurrentDocument();
1108 event
.Enable( (doc
!= (wxDocument
*) NULL
) );
1111 void wxDocManager::OnUpdateUndo(wxUpdateUIEvent
& event
)
1113 wxDocument
*doc
= GetCurrentDocument();
1115 event
.Enable(false);
1116 else if (!doc
->GetCommandProcessor())
1120 event
.Enable( doc
->GetCommandProcessor()->CanUndo() );
1121 doc
->GetCommandProcessor()->SetMenuStrings();
1125 void wxDocManager::OnUpdateRedo(wxUpdateUIEvent
& event
)
1127 wxDocument
*doc
= GetCurrentDocument();
1129 event
.Enable(false);
1130 else if (!doc
->GetCommandProcessor())
1134 event
.Enable( doc
->GetCommandProcessor()->CanRedo() );
1135 doc
->GetCommandProcessor()->SetMenuStrings();
1139 void wxDocManager::OnUpdatePrint(wxUpdateUIEvent
& event
)
1141 wxDocument
*doc
= GetCurrentDocument();
1142 event
.Enable( (doc
!= (wxDocument
*) NULL
) );
1145 void wxDocManager::OnUpdatePreview(wxUpdateUIEvent
& event
)
1147 wxDocument
*doc
= GetCurrentDocument();
1148 event
.Enable( (doc
!= (wxDocument
*) NULL
) );
1151 wxView
*wxDocManager::GetCurrentView() const
1154 return m_currentView
;
1155 if (m_docs
.GetCount() == 1)
1157 wxDocument
* doc
= (wxDocument
*) m_docs
.GetFirst()->GetData();
1158 return doc
->GetFirstView();
1160 return (wxView
*) NULL
;
1163 // Extend event processing to search the view's event table
1164 bool wxDocManager::ProcessEvent(wxEvent
& event
)
1166 wxView
* view
= GetCurrentView();
1169 if (view
->ProcessEvent(event
))
1172 return wxEvtHandler::ProcessEvent(event
);
1175 wxDocument
*wxDocManager::CreateDocument(const wxString
& path
, long flags
)
1177 wxDocTemplate
**templates
= new wxDocTemplate
*[m_templates
.GetCount()];
1180 for (size_t i
= 0; i
< m_templates
.GetCount(); i
++)
1182 wxDocTemplate
*temp
= (wxDocTemplate
*)(m_templates
.Item(i
)->GetData());
1183 if (temp
->IsVisible())
1185 templates
[n
] = temp
;
1192 return (wxDocument
*) NULL
;
1195 wxDocument
* docToClose
= NULL
;
1197 // If we've reached the max number of docs, close the
1199 if ( (int)GetDocuments().GetCount() >= m_maxDocsOpen
)
1201 wxDocument
*doc
= (wxDocument
*)GetDocuments().GetFirst()->GetData();
1205 // New document: user chooses a template, unless there's only one.
1206 if (flags
& wxDOC_NEW
)
1212 if (!CloseDocument(docToClose
, false))
1219 wxDocTemplate
*temp
= templates
[0];
1221 wxDocument
*newDoc
= temp
->CreateDocument(path
, flags
);
1225 newDoc
->SetDocumentName(temp
->GetDocumentName());
1226 newDoc
->SetDocumentTemplate(temp
);
1227 if (!newDoc
->OnNewDocument() )
1229 // Document is implicitly deleted by DeleteAllViews
1230 newDoc
->DeleteAllViews();
1237 wxDocTemplate
*temp
= SelectDocumentType(templates
, n
);
1243 if (!CloseDocument(docToClose
, false))
1249 wxDocument
*newDoc
= temp
->CreateDocument(path
, flags
);
1253 newDoc
->SetDocumentName(temp
->GetDocumentName());
1254 newDoc
->SetDocumentTemplate(temp
);
1255 if (!newDoc
->OnNewDocument() )
1257 // Document is implicitly deleted by DeleteAllViews
1258 newDoc
->DeleteAllViews();
1265 return (wxDocument
*) NULL
;
1268 // Existing document
1269 wxDocTemplate
*temp
;
1271 wxString path2
= path
;
1273 if (flags
& wxDOC_SILENT
)
1275 temp
= FindTemplateForPath(path2
);
1278 // Since we do not add files with non-default extensions to the FileHistory this
1279 // can only happen if the application changes the allowed templates in runtime.
1280 (void)wxMessageBox(_("Sorry, the format for this file is unknown."),
1282 wxOK
| wxICON_EXCLAMATION
, wxFindSuitableParent());
1286 temp
= SelectDocumentPath(templates
, n
, path2
, flags
);
1294 if (!CloseDocument(docToClose
, false))
1300 //see if this file is already open
1301 for (size_t i
= 0; i
< GetDocuments().GetCount(); ++i
)
1303 wxDocument
* currentDoc
= (wxDocument
*)(GetDocuments().Item(i
)->GetData());
1305 //file paths are case-insensitive on Windows
1306 if (path2
.CmpNoCase(currentDoc
->GetFilename()) == 0)
1308 if (path2
.Cmp(currentDoc
->GetFilename()) == 0)
1311 //file already open. Just activate it and return
1312 if (currentDoc
->GetFirstView())
1314 ActivateView(currentDoc
->GetFirstView(), true);
1315 if (currentDoc
->GetDocumentWindow())
1316 currentDoc
->GetDocumentWindow()->SetFocus();
1322 wxDocument
*newDoc
= temp
->CreateDocument(path2
, flags
);
1325 newDoc
->SetDocumentName(temp
->GetDocumentName());
1326 newDoc
->SetDocumentTemplate(temp
);
1327 if (!newDoc
->OnOpenDocument(path2
))
1329 newDoc
->DeleteAllViews();
1330 // delete newDoc; // Implicitly deleted by DeleteAllViews
1331 return (wxDocument
*) NULL
;
1333 // A file that doesn't use the default extension of its document
1334 // template cannot be opened via the FileHistory, so we do not
1336 if (temp
->FileMatchesTemplate(path2
))
1337 AddFileToHistory(path2
);
1342 return (wxDocument
*) NULL
;
1345 wxView
*wxDocManager::CreateView(wxDocument
*doc
, long flags
)
1347 wxDocTemplate
**templates
= new wxDocTemplate
*[m_templates
.GetCount()];
1350 for (size_t i
= 0; i
< m_templates
.GetCount(); i
++)
1352 wxDocTemplate
*temp
= (wxDocTemplate
*)(m_templates
.Item(i
)->GetData());
1353 if (temp
->IsVisible())
1355 if (temp
->GetDocumentName() == doc
->GetDocumentName())
1357 templates
[n
] = temp
;
1365 return (wxView
*) NULL
;
1369 wxDocTemplate
*temp
= templates
[0];
1371 wxView
*view
= temp
->CreateView(doc
, flags
);
1373 view
->SetViewName(temp
->GetViewName());
1377 wxDocTemplate
*temp
= SelectViewType(templates
, n
);
1381 wxView
*view
= temp
->CreateView(doc
, flags
);
1383 view
->SetViewName(temp
->GetViewName());
1387 return (wxView
*) NULL
;
1390 // Not yet implemented
1391 void wxDocManager::DeleteTemplate(wxDocTemplate
*WXUNUSED(temp
), long WXUNUSED(flags
))
1395 // Not yet implemented
1396 bool wxDocManager::FlushDoc(wxDocument
*WXUNUSED(doc
))
1401 wxDocument
*wxDocManager::GetCurrentDocument() const
1403 wxView
*view
= GetCurrentView();
1405 return view
->GetDocument();
1407 return (wxDocument
*) NULL
;
1410 // Make a default document name
1411 bool wxDocManager::MakeDefaultName(wxString
& name
)
1413 name
.Printf(_("unnamed%d"), m_defaultDocumentNameCounter
);
1414 m_defaultDocumentNameCounter
++;
1419 // Make a frame title (override this to do something different)
1420 // If docName is empty, a document is not currently active.
1421 wxString
wxDocManager::MakeFrameTitle(wxDocument
* doc
)
1423 wxString appName
= wxTheApp
->GetAppName();
1430 doc
->GetPrintableName(docName
);
1431 title
= docName
+ wxString(_(" - ")) + appName
;
1437 // Not yet implemented
1438 wxDocTemplate
*wxDocManager::MatchTemplate(const wxString
& WXUNUSED(path
))
1440 return (wxDocTemplate
*) NULL
;
1443 // File history management
1444 void wxDocManager::AddFileToHistory(const wxString
& file
)
1447 m_fileHistory
->AddFileToHistory(file
);
1450 void wxDocManager::RemoveFileFromHistory(size_t i
)
1453 m_fileHistory
->RemoveFileFromHistory(i
);
1456 wxString
wxDocManager::GetHistoryFile(size_t i
) const
1461 histFile
= m_fileHistory
->GetHistoryFile(i
);
1466 void wxDocManager::FileHistoryUseMenu(wxMenu
*menu
)
1469 m_fileHistory
->UseMenu(menu
);
1472 void wxDocManager::FileHistoryRemoveMenu(wxMenu
*menu
)
1475 m_fileHistory
->RemoveMenu(menu
);
1479 void wxDocManager::FileHistoryLoad(wxConfigBase
& config
)
1482 m_fileHistory
->Load(config
);
1485 void wxDocManager::FileHistorySave(wxConfigBase
& config
)
1488 m_fileHistory
->Save(config
);
1492 void wxDocManager::FileHistoryAddFilesToMenu(wxMenu
* menu
)
1495 m_fileHistory
->AddFilesToMenu(menu
);
1498 void wxDocManager::FileHistoryAddFilesToMenu()
1501 m_fileHistory
->AddFilesToMenu();
1504 size_t wxDocManager::GetHistoryFilesCount() const
1506 return m_fileHistory
? m_fileHistory
->GetCount() : 0;
1510 // Find out the document template via matching in the document file format
1511 // against that of the template
1512 wxDocTemplate
*wxDocManager::FindTemplateForPath(const wxString
& path
)
1514 wxDocTemplate
*theTemplate
= (wxDocTemplate
*) NULL
;
1516 // Find the template which this extension corresponds to
1517 for (size_t i
= 0; i
< m_templates
.GetCount(); i
++)
1519 wxDocTemplate
*temp
= (wxDocTemplate
*)m_templates
.Item(i
)->GetData();
1520 if ( temp
->FileMatchesTemplate(path
) )
1529 // Try to get a more suitable parent frame than the top window,
1530 // for selection dialogs. Otherwise you may get an unexpected
1531 // window being activated when a dialog is shown.
1532 static wxWindow
* wxFindSuitableParent()
1534 wxWindow
* parent
= wxTheApp
->GetTopWindow();
1536 wxWindow
* focusWindow
= wxWindow::FindFocus();
1539 while (focusWindow
&&
1540 !focusWindow
->IsKindOf(CLASSINFO(wxDialog
)) &&
1541 !focusWindow
->IsKindOf(CLASSINFO(wxFrame
)))
1543 focusWindow
= focusWindow
->GetParent();
1546 parent
= focusWindow
;
1551 // Prompts user to open a file, using file specs in templates.
1552 // Must extend the file selector dialog or implement own; OR
1553 // match the extension to the template extension.
1555 wxDocTemplate
*wxDocManager::SelectDocumentPath(wxDocTemplate
**templates
,
1556 #if defined(__WXMSW__) || defined(__WXGTK__) || defined(__WXMAC__)
1559 int WXUNUSED(noTemplates
),
1562 long WXUNUSED(flags
),
1563 bool WXUNUSED(save
))
1565 // We can only have multiple filters in Windows and GTK
1566 #if defined(__WXMSW__) || defined(__WXGTK__) || defined(__WXMAC__)
1570 for (i
= 0; i
< noTemplates
; i
++)
1572 if (templates
[i
]->IsVisible())
1574 // add a '|' to separate this filter from the previous one
1575 if ( !descrBuf
.empty() )
1576 descrBuf
<< wxT('|');
1578 descrBuf
<< templates
[i
]->GetDescription()
1579 << wxT(" (") << templates
[i
]->GetFileFilter() << wxT(") |")
1580 << templates
[i
]->GetFileFilter();
1584 wxString descrBuf
= wxT("*.*");
1587 int FilterIndex
= -1;
1589 wxWindow
* parent
= wxFindSuitableParent();
1591 wxString pathTmp
= wxFileSelectorEx(_("Select a file"),
1599 wxDocTemplate
*theTemplate
= (wxDocTemplate
*)NULL
;
1600 if (!pathTmp
.empty())
1602 if (!wxFileExists(pathTmp
))
1605 if (!wxTheApp
->GetAppName().empty())
1606 msgTitle
= wxTheApp
->GetAppName();
1608 msgTitle
= wxString(_("File error"));
1610 (void)wxMessageBox(_("Sorry, could not open this file."), msgTitle
, wxOK
| wxICON_EXCLAMATION
,
1613 path
= wxEmptyString
;
1614 return (wxDocTemplate
*) NULL
;
1616 m_lastDirectory
= wxPathOnly(pathTmp
);
1620 // first choose the template using the extension, if this fails (i.e.
1621 // wxFileSelectorEx() didn't fill it), then use the path
1622 if ( FilterIndex
!= -1 )
1623 theTemplate
= templates
[FilterIndex
];
1625 theTemplate
= FindTemplateForPath(path
);
1628 // Since we do not add files with non-default extensions to the FileHistory this
1629 // can only happen if the application changes the allowed templates in runtime.
1630 (void)wxMessageBox(_("Sorry, the format for this file is unknown."),
1632 wxOK
| wxICON_EXCLAMATION
, wxFindSuitableParent());
1637 path
= wxEmptyString
;
1643 wxDocTemplate
*wxDocManager::SelectDocumentType(wxDocTemplate
**templates
,
1644 int noTemplates
, bool sort
)
1646 wxArrayString strings
;
1647 wxDocTemplate
**data
= new wxDocTemplate
*[noTemplates
];
1651 for (i
= 0; i
< noTemplates
; i
++)
1653 if (templates
[i
]->IsVisible())
1657 for (j
= 0; j
< n
; j
++)
1659 //filter out NOT unique documents + view combinations
1660 if ( templates
[i
]->m_docTypeName
== data
[j
]->m_docTypeName
&&
1661 templates
[i
]->m_viewTypeName
== data
[j
]->m_viewTypeName
1668 strings
.Add(templates
[i
]->m_description
);
1670 data
[n
] = templates
[i
];
1678 strings
.Sort(); // ascending sort
1679 // Yes, this will be slow, but template lists
1680 // are typically short.
1682 n
= strings
.Count();
1683 for (i
= 0; i
< n
; i
++)
1685 for (j
= 0; j
< noTemplates
; j
++)
1687 if (strings
[i
] == templates
[j
]->m_description
)
1688 data
[i
] = templates
[j
];
1693 wxDocTemplate
*theTemplate
;
1698 // no visible templates, hence nothing to choose from
1703 // don't propose the user to choose if he heas no choice
1704 theTemplate
= data
[0];
1708 // propose the user to choose one of several
1709 theTemplate
= (wxDocTemplate
*)wxGetSingleChoiceData
1711 _("Select a document template"),
1715 wxFindSuitableParent()
1724 wxDocTemplate
*wxDocManager::SelectViewType(wxDocTemplate
**templates
,
1725 int noTemplates
, bool sort
)
1727 wxArrayString strings
;
1728 wxDocTemplate
**data
= new wxDocTemplate
*[noTemplates
];
1732 for (i
= 0; i
< noTemplates
; i
++)
1734 wxDocTemplate
*templ
= templates
[i
];
1735 if ( templ
->IsVisible() && !templ
->GetViewName().empty() )
1739 for (j
= 0; j
< n
; j
++)
1741 //filter out NOT unique views
1742 if ( templates
[i
]->m_viewTypeName
== data
[j
]->m_viewTypeName
)
1748 strings
.Add(templ
->m_viewTypeName
);
1757 strings
.Sort(); // ascending sort
1758 // Yes, this will be slow, but template lists
1759 // are typically short.
1761 n
= strings
.Count();
1762 for (i
= 0; i
< n
; i
++)
1764 for (j
= 0; j
< noTemplates
; j
++)
1766 if (strings
[i
] == templates
[j
]->m_viewTypeName
)
1767 data
[i
] = templates
[j
];
1772 wxDocTemplate
*theTemplate
;
1774 // the same logic as above
1778 theTemplate
= (wxDocTemplate
*)NULL
;
1782 theTemplate
= data
[0];
1786 theTemplate
= (wxDocTemplate
*)wxGetSingleChoiceData
1788 _("Select a document view"),
1792 wxFindSuitableParent()
1801 void wxDocManager::AssociateTemplate(wxDocTemplate
*temp
)
1803 if (!m_templates
.Member(temp
))
1804 m_templates
.Append(temp
);
1807 void wxDocManager::DisassociateTemplate(wxDocTemplate
*temp
)
1809 m_templates
.DeleteObject(temp
);
1812 // Add and remove a document from the manager's list
1813 void wxDocManager::AddDocument(wxDocument
*doc
)
1815 if (!m_docs
.Member(doc
))
1819 void wxDocManager::RemoveDocument(wxDocument
*doc
)
1821 m_docs
.DeleteObject(doc
);
1824 // Views or windows should inform the document manager
1825 // when a view is going in or out of focus
1826 void wxDocManager::ActivateView(wxView
*view
, bool activate
)
1830 m_currentView
= view
;
1834 if ( m_currentView
== view
)
1836 // don't keep stale pointer
1837 m_currentView
= (wxView
*) NULL
;
1842 // ----------------------------------------------------------------------------
1843 // Default document child frame
1844 // ----------------------------------------------------------------------------
1846 BEGIN_EVENT_TABLE(wxDocChildFrame
, wxFrame
)
1847 EVT_ACTIVATE(wxDocChildFrame::OnActivate
)
1848 EVT_CLOSE(wxDocChildFrame::OnCloseWindow
)
1851 wxDocChildFrame::wxDocChildFrame(wxDocument
*doc
,
1855 const wxString
& title
,
1859 const wxString
& name
)
1860 : wxFrame(frame
, id
, title
, pos
, size
, style
, name
)
1862 m_childDocument
= doc
;
1865 view
->SetFrame(this);
1868 // Extend event processing to search the view's event table
1869 bool wxDocChildFrame::ProcessEvent(wxEvent
& event
)
1872 m_childView
->Activate(true);
1874 if ( !m_childView
|| ! m_childView
->ProcessEvent(event
) )
1876 // Only hand up to the parent if it's a menu command
1877 if (!event
.IsKindOf(CLASSINFO(wxCommandEvent
)) || !GetParent() || !GetParent()->ProcessEvent(event
))
1878 return wxEvtHandler::ProcessEvent(event
);
1886 void wxDocChildFrame::OnActivate(wxActivateEvent
& event
)
1888 wxFrame::OnActivate(event
);
1891 m_childView
->Activate(event
.GetActive());
1894 void wxDocChildFrame::OnCloseWindow(wxCloseEvent
& event
)
1898 bool ans
= event
.CanVeto()
1899 ? m_childView
->Close(false) // false means don't delete associated window
1900 : true; // Must delete.
1904 m_childView
->Activate(false);
1906 m_childView
= (wxView
*) NULL
;
1907 m_childDocument
= (wxDocument
*) NULL
;
1918 // ----------------------------------------------------------------------------
1919 // Default parent frame
1920 // ----------------------------------------------------------------------------
1922 BEGIN_EVENT_TABLE(wxDocParentFrame
, wxFrame
)
1923 EVT_MENU(wxID_EXIT
, wxDocParentFrame::OnExit
)
1924 EVT_MENU_RANGE(wxID_FILE1
, wxID_FILE9
, wxDocParentFrame::OnMRUFile
)
1925 EVT_CLOSE(wxDocParentFrame::OnCloseWindow
)
1928 wxDocParentFrame::wxDocParentFrame(wxDocManager
*manager
,
1931 const wxString
& title
,
1935 const wxString
& name
)
1936 : wxFrame(frame
, id
, title
, pos
, size
, style
, name
)
1938 m_docManager
= manager
;
1941 void wxDocParentFrame::OnExit(wxCommandEvent
& WXUNUSED(event
))
1946 void wxDocParentFrame::OnMRUFile(wxCommandEvent
& event
)
1948 int n
= event
.GetId() - wxID_FILE1
; // the index in MRU list
1949 wxString
filename(m_docManager
->GetHistoryFile(n
));
1950 if ( !filename
.empty() )
1952 // verify that the file exists before doing anything else
1953 if ( wxFile::Exists(filename
) )
1956 if (!m_docManager
->CreateDocument(filename
, wxDOC_SILENT
))
1958 // remove the file from the MRU list. The user should already be notified.
1959 m_docManager
->RemoveFileFromHistory(n
);
1961 wxLogError(_("The file '%s' couldn't be opened.\nIt has been removed from the most recently used files list."),
1967 // remove the bogus filename from the MRU list and notify the user
1969 m_docManager
->RemoveFileFromHistory(n
);
1971 wxLogError(_("The file '%s' doesn't exist and couldn't be opened.\nIt has been removed from the most recently used files list."),
1977 // Extend event processing to search the view's event table
1978 bool wxDocParentFrame::ProcessEvent(wxEvent
& event
)
1980 // Try the document manager, then do default processing
1981 if (!m_docManager
|| !m_docManager
->ProcessEvent(event
))
1982 return wxEvtHandler::ProcessEvent(event
);
1987 // Define the behaviour for the frame closing
1988 // - must delete all frames except for the main one.
1989 void wxDocParentFrame::OnCloseWindow(wxCloseEvent
& event
)
1991 if (m_docManager
->Clear(!event
.CanVeto()))
1999 #if wxUSE_PRINTING_ARCHITECTURE
2001 wxDocPrintout::wxDocPrintout(wxView
*view
, const wxString
& title
)
2004 m_printoutView
= view
;
2007 bool wxDocPrintout::OnPrintPage(int WXUNUSED(page
))
2011 // Get the logical pixels per inch of screen and printer
2012 int ppiScreenX
, ppiScreenY
;
2013 GetPPIScreen(&ppiScreenX
, &ppiScreenY
);
2014 wxUnusedVar(ppiScreenY
);
2015 int ppiPrinterX
, ppiPrinterY
;
2016 GetPPIPrinter(&ppiPrinterX
, &ppiPrinterY
);
2017 wxUnusedVar(ppiPrinterY
);
2019 // This scales the DC so that the printout roughly represents the
2020 // the screen scaling. The text point size _should_ be the right size
2021 // but in fact is too small for some reason. This is a detail that will
2022 // need to be addressed at some point but can be fudged for the
2024 float scale
= (float)((float)ppiPrinterX
/(float)ppiScreenX
);
2026 // Now we have to check in case our real page size is reduced
2027 // (e.g. because we're drawing to a print preview memory DC)
2028 int pageWidth
, pageHeight
;
2030 dc
->GetSize(&w
, &h
);
2031 GetPageSizePixels(&pageWidth
, &pageHeight
);
2032 wxUnusedVar(pageHeight
);
2034 // If printer pageWidth == current DC width, then this doesn't
2035 // change. But w might be the preview bitmap width, so scale down.
2036 float overallScale
= scale
* (float)(w
/(float)pageWidth
);
2037 dc
->SetUserScale(overallScale
, overallScale
);
2041 m_printoutView
->OnDraw(dc
);
2046 bool wxDocPrintout::HasPage(int pageNum
)
2048 return (pageNum
== 1);
2051 bool wxDocPrintout::OnBeginDocument(int startPage
, int endPage
)
2053 if (!wxPrintout::OnBeginDocument(startPage
, endPage
))
2059 void wxDocPrintout::GetPageInfo(int *minPage
, int *maxPage
, int *selPageFrom
, int *selPageTo
)
2067 #endif // wxUSE_PRINTING_ARCHITECTURE
2069 // ----------------------------------------------------------------------------
2070 // File history processor
2071 // ----------------------------------------------------------------------------
2073 static inline wxChar
* MYcopystring(const wxString
& s
)
2075 wxChar
* copy
= new wxChar
[s
.length() + 1];
2076 return wxStrcpy(copy
, s
.c_str());
2079 static inline wxChar
* MYcopystring(const wxChar
* s
)
2081 wxChar
* copy
= new wxChar
[wxStrlen(s
) + 1];
2082 return wxStrcpy(copy
, s
);
2085 wxFileHistory::wxFileHistory(size_t maxFiles
, wxWindowID idBase
)
2087 m_fileMaxFiles
= maxFiles
;
2090 m_fileHistory
= new wxChar
*[m_fileMaxFiles
];
2093 wxFileHistory::~wxFileHistory()
2096 for (i
= 0; i
< m_fileHistoryN
; i
++)
2097 delete[] m_fileHistory
[i
];
2098 delete[] m_fileHistory
;
2101 // File history management
2102 void wxFileHistory::AddFileToHistory(const wxString
& file
)
2106 // Check we don't already have this file
2107 for (i
= 0; i
< m_fileHistoryN
; i
++)
2109 #if defined( __WXMSW__ ) // Add any other OSes with case insensitive file names
2110 wxString testString
;
2111 if ( m_fileHistory
[i
] )
2112 testString
= m_fileHistory
[i
];
2113 if ( m_fileHistory
[i
] && ( file
.Lower() == testString
.Lower() ) )
2115 if ( m_fileHistory
[i
] && ( file
== m_fileHistory
[i
] ) )
2118 // we do have it, move it to the top of the history
2119 RemoveFileFromHistory (i
);
2120 AddFileToHistory (file
);
2125 // if we already have a full history, delete the one at the end
2126 if ( m_fileMaxFiles
== m_fileHistoryN
)
2128 RemoveFileFromHistory (m_fileHistoryN
- 1);
2129 AddFileToHistory (file
);
2133 // Add to the project file history:
2134 // Move existing files (if any) down so we can insert file at beginning.
2135 if (m_fileHistoryN
< m_fileMaxFiles
)
2137 wxList::compatibility_iterator node
= m_fileMenus
.GetFirst();
2140 wxMenu
* menu
= (wxMenu
*) node
->GetData();
2141 if ( m_fileHistoryN
== 0 && menu
->GetMenuItemCount() )
2143 menu
->AppendSeparator();
2145 menu
->Append(m_idBase
+m_fileHistoryN
, _("[EMPTY]"));
2146 node
= node
->GetNext();
2150 // Shuffle filenames down
2151 for (i
= (m_fileHistoryN
-1); i
> 0; i
--)
2153 m_fileHistory
[i
] = m_fileHistory
[i
-1];
2155 m_fileHistory
[0] = MYcopystring(file
);
2157 // this is the directory of the last opened file
2158 wxString pathCurrent
;
2159 wxSplitPath( m_fileHistory
[0], &pathCurrent
, NULL
, NULL
);
2160 for (i
= 0; i
< m_fileHistoryN
; i
++)
2162 if ( m_fileHistory
[i
] )
2164 // if in same directory just show the filename; otherwise the full
2166 wxString pathInMenu
, path
, filename
, ext
;
2167 wxSplitPath( m_fileHistory
[i
], &path
, &filename
, &ext
);
2168 if ( path
== pathCurrent
)
2170 pathInMenu
= filename
;
2172 pathInMenu
= pathInMenu
+ wxFILE_SEP_EXT
+ ext
;
2176 // absolute path; could also set relative path
2177 pathInMenu
= m_fileHistory
[i
];
2180 // we need to quote '&' characters which are used for mnemonics
2181 pathInMenu
.Replace(_T("&"), _T("&&"));
2183 buf
.Printf(s_MRUEntryFormat
, i
+ 1, pathInMenu
.c_str());
2184 wxList::compatibility_iterator node
= m_fileMenus
.GetFirst();
2187 wxMenu
* menu
= (wxMenu
*) node
->GetData();
2188 menu
->SetLabel(m_idBase
+ i
, buf
);
2189 node
= node
->GetNext();
2195 void wxFileHistory::RemoveFileFromHistory(size_t i
)
2197 wxCHECK_RET( i
< m_fileHistoryN
,
2198 wxT("invalid index in wxFileHistory::RemoveFileFromHistory") );
2200 // delete the element from the array (could use memmove() too...)
2201 delete [] m_fileHistory
[i
];
2204 for ( j
= i
; j
< m_fileHistoryN
- 1; j
++ )
2206 m_fileHistory
[j
] = m_fileHistory
[j
+ 1];
2209 wxList::compatibility_iterator node
= m_fileMenus
.GetFirst();
2212 wxMenu
* menu
= (wxMenu
*) node
->GetData();
2214 // shuffle filenames up
2216 for ( j
= i
; j
< m_fileHistoryN
- 1; j
++ )
2218 buf
.Printf(s_MRUEntryFormat
, j
+ 1, m_fileHistory
[j
]);
2219 menu
->SetLabel(m_idBase
+ j
, buf
);
2222 node
= node
->GetNext();
2224 // delete the last menu item which is unused now
2225 wxWindowID lastItemId
= m_idBase
+ wx_truncate_cast(wxWindowID
, m_fileHistoryN
) - 1;
2226 if (menu
->FindItem(lastItemId
))
2228 menu
->Delete(lastItemId
);
2231 // delete the last separator too if no more files are left
2232 if ( m_fileHistoryN
== 1 )
2234 wxMenuItemList::compatibility_iterator nodeLast
= menu
->GetMenuItems().GetLast();
2237 wxMenuItem
*menuItem
= nodeLast
->GetData();
2238 if ( menuItem
->IsSeparator() )
2240 menu
->Delete(menuItem
);
2242 //else: should we search backwards for the last separator?
2244 //else: menu is empty somehow
2251 wxString
wxFileHistory::GetHistoryFile(size_t i
) const
2254 if ( i
< m_fileHistoryN
)
2256 s
= m_fileHistory
[i
];
2260 wxFAIL_MSG( wxT("bad index in wxFileHistory::GetHistoryFile") );
2266 void wxFileHistory::UseMenu(wxMenu
*menu
)
2268 if (!m_fileMenus
.Member(menu
))
2269 m_fileMenus
.Append(menu
);
2272 void wxFileHistory::RemoveMenu(wxMenu
*menu
)
2274 m_fileMenus
.DeleteObject(menu
);
2278 void wxFileHistory::Load(wxConfigBase
& config
)
2282 buf
.Printf(wxT("file%d"), (int)m_fileHistoryN
+1);
2283 wxString historyFile
;
2284 while ((m_fileHistoryN
< m_fileMaxFiles
) && config
.Read(buf
, &historyFile
) && (!historyFile
.empty()))
2286 m_fileHistory
[m_fileHistoryN
] = MYcopystring((const wxChar
*) historyFile
);
2288 buf
.Printf(wxT("file%d"), (int)m_fileHistoryN
+1);
2289 historyFile
= wxEmptyString
;
2294 void wxFileHistory::Save(wxConfigBase
& config
)
2297 for (i
= 0; i
< m_fileMaxFiles
; i
++)
2300 buf
.Printf(wxT("file%d"), (int)i
+1);
2301 if (i
< m_fileHistoryN
)
2302 config
.Write(buf
, wxString(m_fileHistory
[i
]));
2304 config
.Write(buf
, wxEmptyString
);
2307 #endif // wxUSE_CONFIG
2309 void wxFileHistory::AddFilesToMenu()
2311 if (m_fileHistoryN
> 0)
2313 wxList::compatibility_iterator node
= m_fileMenus
.GetFirst();
2316 wxMenu
* menu
= (wxMenu
*) node
->GetData();
2317 if (menu
->GetMenuItemCount())
2319 menu
->AppendSeparator();
2323 for (i
= 0; i
< m_fileHistoryN
; i
++)
2325 if (m_fileHistory
[i
])
2328 buf
.Printf(s_MRUEntryFormat
, i
+1, m_fileHistory
[i
]);
2329 menu
->Append(m_idBase
+i
, buf
);
2332 node
= node
->GetNext();
2337 void wxFileHistory::AddFilesToMenu(wxMenu
* menu
)
2339 if (m_fileHistoryN
> 0)
2341 if (menu
->GetMenuItemCount())
2343 menu
->AppendSeparator();
2347 for (i
= 0; i
< m_fileHistoryN
; i
++)
2349 if (m_fileHistory
[i
])
2352 buf
.Printf(s_MRUEntryFormat
, i
+1, m_fileHistory
[i
]);
2353 menu
->Append(m_idBase
+i
, buf
);
2359 // ----------------------------------------------------------------------------
2360 // Permits compatibility with existing file formats and functions that
2361 // manipulate files directly
2362 // ----------------------------------------------------------------------------
2364 #if wxUSE_STD_IOSTREAM
2366 bool wxTransferFileToStream(const wxString
& filename
, wxSTD ostream
& stream
)
2368 wxFFile
file(filename
, _T("rb"));
2369 if ( !file
.IsOpened() )
2377 nRead
= file
.Read(buf
, WXSIZEOF(buf
));
2381 stream
.write(buf
, nRead
);
2385 while ( !file
.Eof() );
2390 bool wxTransferStreamToFile(wxSTD istream
& stream
, const wxString
& filename
)
2392 wxFFile
file(filename
, _T("wb"));
2393 if ( !file
.IsOpened() )
2399 stream
.read(buf
, WXSIZEOF(buf
));
2400 if ( !stream
.bad() ) // fail may be set on EOF, don't use operator!()
2402 if ( !file
.Write(buf
, stream
.gcount()) )
2406 while ( !stream
.eof() );
2411 #else // !wxUSE_STD_IOSTREAM
2413 bool wxTransferFileToStream(const wxString
& filename
, wxOutputStream
& stream
)
2415 wxFFile
file(filename
, _T("rb"));
2416 if ( !file
.IsOpened() )
2424 nRead
= file
.Read(buf
, WXSIZEOF(buf
));
2428 stream
.Write(buf
, nRead
);
2432 while ( !file
.Eof() );
2437 bool wxTransferStreamToFile(wxInputStream
& stream
, const wxString
& filename
)
2439 wxFFile
file(filename
, _T("wb"));
2440 if ( !file
.IsOpened() )
2446 stream
.Read(buf
, WXSIZEOF(buf
));
2448 const size_t nRead
= stream
.LastRead();
2449 if ( !nRead
|| !file
.Write(buf
, nRead
) )
2452 while ( !stream
.Eof() );
2457 #endif // wxUSE_STD_IOSTREAM/!wxUSE_STD_IOSTREAM
2459 #endif // wxUSE_DOC_VIEW_ARCHITECTURE