1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: Document/view classes
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart and Markus Holzem
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
21 #pragma implementation "docview.h"
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
31 #if wxUSE_DOC_VIEW_ARCHITECTURE
34 #include "wx/string.h"
38 #include "wx/dialog.h"
41 #include "wx/filedlg.h"
49 #if wxUSE_PRINTING_ARCHITECTURE
50 #include "wx/prntbase.h"
51 #include "wx/printdlg.h"
54 #include "wx/msgdlg.h"
55 #include "wx/choicdlg.h"
56 #include "wx/docview.h"
57 #include "wx/confbase.h"
62 #if wxUSE_STD_IOSTREAM
63 #include "wx/ioswrap.h"
70 #include "wx/wfstream.h"
73 // ----------------------------------------------------------------------------
75 // ----------------------------------------------------------------------------
77 #if !USE_SHARED_LIBRARY
78 IMPLEMENT_ABSTRACT_CLASS(wxDocument
, wxEvtHandler
)
79 IMPLEMENT_ABSTRACT_CLASS(wxView
, wxEvtHandler
)
80 IMPLEMENT_ABSTRACT_CLASS(wxDocTemplate
, wxObject
)
81 IMPLEMENT_DYNAMIC_CLASS(wxDocManager
, wxEvtHandler
)
82 IMPLEMENT_CLASS(wxDocChildFrame
, wxFrame
)
83 IMPLEMENT_CLASS(wxDocParentFrame
, wxFrame
)
85 #if wxUSE_PRINTING_ARCHITECTURE
86 IMPLEMENT_DYNAMIC_CLASS(wxDocPrintout
, wxPrintout
)
89 IMPLEMENT_CLASS(wxCommand
, wxObject
)
90 IMPLEMENT_DYNAMIC_CLASS(wxCommandProcessor
, wxObject
)
91 IMPLEMENT_DYNAMIC_CLASS(wxFileHistory
, wxObject
)
94 // ----------------------------------------------------------------------------
95 // function prototypes
96 // ----------------------------------------------------------------------------
98 static inline wxString
FindExtension(const wxChar
*path
);
100 // ============================================================================
102 // ============================================================================
104 // ----------------------------------------------------------------------------
106 // ----------------------------------------------------------------------------
108 static wxString
FindExtension(const wxChar
*path
)
111 wxSplitPath(path
, NULL
, NULL
, &ext
);
113 // VZ: extensions are considered not case sensitive - is this really a good
115 return ext
.MakeLower();
118 // ----------------------------------------------------------------------------
119 // Definition of wxDocument
120 // ----------------------------------------------------------------------------
122 wxDocument::wxDocument(wxDocument
*parent
)
124 m_documentModified
= FALSE
;
125 m_documentParent
= parent
;
126 m_documentTemplate
= (wxDocTemplate
*) NULL
;
130 bool wxDocument::DeleteContents()
135 wxDocument::~wxDocument()
139 if (m_commandProcessor
)
140 delete m_commandProcessor
;
142 GetDocumentManager()->RemoveDocument(this);
144 // Not safe to do here, since it'll invoke virtual view functions
145 // expecting to see valid derived objects: and by the time we get here,
146 // we've called destructors higher up.
150 bool wxDocument::Close()
152 if (OnSaveModified())
153 return OnCloseDocument();
158 bool wxDocument::OnCloseDocument()
165 // Note that this implicitly deletes the document when the last view is
167 bool wxDocument::DeleteAllViews()
169 wxNode
*node
= m_documentViews
.First();
172 wxView
*view
= (wxView
*)node
->Data();
176 wxNode
*next
= node
->Next();
178 delete view
; // Deletes node implicitly
184 wxView
*wxDocument::GetFirstView() const
186 if (m_documentViews
.Number() == 0)
187 return (wxView
*) NULL
;
188 return (wxView
*)m_documentViews
.First()->Data();
191 wxDocManager
*wxDocument::GetDocumentManager() const
193 return m_documentTemplate
->GetDocumentManager();
196 bool wxDocument::OnNewDocument()
198 if (!OnSaveModified())
201 if (OnCloseDocument()==FALSE
) return FALSE
;
204 SetDocumentSaved(FALSE
);
207 GetDocumentManager()->MakeDefaultName(name
);
209 SetFilename(name
, TRUE
);
214 bool wxDocument::Save()
218 if (!IsModified()) return TRUE
;
219 if (m_documentFile
== _T("") || !m_savedYet
)
222 ret
= OnSaveDocument(m_documentFile
);
224 SetDocumentSaved(TRUE
);
228 bool wxDocument::SaveAs()
230 wxDocTemplate
*docTemplate
= GetDocumentTemplate();
234 wxString tmp
= wxFileSelector(_("Save as"),
235 docTemplate
->GetDirectory(),
237 docTemplate
->GetDefaultExtension(),
238 docTemplate
->GetFileFilter(),
239 wxSAVE
| wxOVERWRITE_PROMPT
,
240 GetDocumentWindow());
245 wxString
fileName(tmp
);
246 wxString path
, name
, ext
;
247 wxSplitPath(fileName
, & path
, & name
, & ext
);
249 if (ext
.IsEmpty() || ext
== _T(""))
252 fileName
+= docTemplate
->GetDefaultExtension();
255 SetFilename(fileName
);
256 SetTitle(wxFileNameFromPath(fileName
));
258 GetDocumentManager()->AddFileToHistory(fileName
);
260 // Notify the views that the filename has changed
261 wxNode
*node
= m_documentViews
.First();
264 wxView
*view
= (wxView
*)node
->Data();
265 view
->OnChangeFilename();
269 return OnSaveDocument(m_documentFile
);
272 bool wxDocument::OnSaveDocument(const wxString
& file
)
278 if (wxTheApp
->GetAppName() != _T(""))
279 msgTitle
= wxTheApp
->GetAppName();
281 msgTitle
= wxString(_("File error"));
283 #if wxUSE_STD_IOSTREAM
284 ofstream
store(FNSTRINGCAST file
.fn_str());
285 if (store
.fail() || store
.bad())
287 wxFileOutputStream
store(FNSTRINGCAST file
.fn_str());
288 if (store
.LastError() != 0)
291 (void)wxMessageBox(_("Sorry, could not open this file for saving."), msgTitle
, wxOK
| wxICON_EXCLAMATION
,
292 GetDocumentWindow());
296 if (SaveObject(store
)==FALSE
)
298 (void)wxMessageBox(_("Sorry, could not save this file."), msgTitle
, wxOK
| wxICON_EXCLAMATION
,
299 GetDocumentWindow());
308 bool wxDocument::OnOpenDocument(const wxString
& file
)
310 if (!OnSaveModified())
314 if (wxTheApp
->GetAppName() != _T(""))
315 msgTitle
= wxTheApp
->GetAppName();
317 msgTitle
= wxString(_("File error"));
319 #if wxUSE_STD_IOSTREAM
320 ifstream
store(FNSTRINGCAST file
.fn_str());
321 if (store
.fail() || store
.bad())
323 wxFileInputStream
store(FNSTRINGCAST file
.fn_str());
324 if (store
.LastError() != 0)
327 (void)wxMessageBox(_("Sorry, could not open this file."), msgTitle
, wxOK
|wxICON_EXCLAMATION
,
328 GetDocumentWindow());
331 if (LoadObject(store
)==FALSE
)
333 (void)wxMessageBox(_("Sorry, could not open this file."), msgTitle
, wxOK
|wxICON_EXCLAMATION
,
334 GetDocumentWindow());
337 SetFilename(file
, TRUE
);
346 #if wxUSE_STD_IOSTREAM
347 istream
& wxDocument::LoadObject(istream
& stream
)
352 ostream
& wxDocument::SaveObject(ostream
& stream
)
357 bool wxDocument::LoadObject(wxInputStream
& stream
)
362 bool wxDocument::SaveObject(wxOutputStream
& stream
)
368 bool wxDocument::Revert()
374 // Get title, or filename if no title, else unnamed
375 bool wxDocument::GetPrintableName(wxString
& buf
) const
377 if (m_documentTitle
!= _T(""))
379 buf
= m_documentTitle
;
382 else if (m_documentFile
!= _T(""))
384 buf
= wxFileNameFromPath(m_documentFile
);
394 wxWindow
*wxDocument::GetDocumentWindow() const
396 wxView
*view
= GetFirstView();
398 return view
->GetFrame();
400 return wxTheApp
->GetTopWindow();
403 wxCommandProcessor
*wxDocument::OnCreateCommandProcessor()
405 return new wxCommandProcessor
;
408 // TRUE if safe to close
409 bool wxDocument::OnSaveModified()
414 GetPrintableName(title
);
417 if (wxTheApp
->GetAppName() != _T(""))
418 msgTitle
= wxTheApp
->GetAppName();
420 msgTitle
= wxString(_("Warning"));
423 prompt
.Printf(_("Do you want to save changes to document %s?"),
424 (const wxChar
*)title
);
425 int res
= wxMessageBox(prompt
, msgTitle
,
426 wxYES_NO
|wxCANCEL
|wxICON_QUESTION
,
427 GetDocumentWindow());
433 else if (res
== wxYES
)
435 else if (res
== wxCANCEL
)
441 bool wxDocument::Draw(wxDC
& WXUNUSED(context
))
446 bool wxDocument::AddView(wxView
*view
)
448 if (!m_documentViews
.Member(view
))
450 m_documentViews
.Append(view
);
456 bool wxDocument::RemoveView(wxView
*view
)
458 (void)m_documentViews
.DeleteObject(view
);
463 bool wxDocument::OnCreate(const wxString
& WXUNUSED(path
), long flags
)
465 if (GetDocumentTemplate()->CreateView(this, flags
))
471 // Called after a view is added or removed.
472 // The default implementation deletes the document if
473 // there are no more views.
474 void wxDocument::OnChangedViewList()
476 if (m_documentViews
.Number() == 0)
478 if (OnSaveModified())
485 void wxDocument::UpdateAllViews(wxView
*sender
, wxObject
*hint
)
487 wxNode
*node
= m_documentViews
.First();
490 wxView
*view
= (wxView
*)node
->Data();
491 view
->OnUpdate(sender
, hint
);
496 void wxDocument::SetFilename(const wxString
& filename
, bool notifyViews
)
498 m_documentFile
= filename
;
501 // Notify the views that the filename has changed
502 wxNode
*node
= m_documentViews
.First();
505 wxView
*view
= (wxView
*)node
->Data();
506 view
->OnChangeFilename();
512 // ----------------------------------------------------------------------------
514 // ----------------------------------------------------------------------------
519 m_viewDocument
= (wxDocument
*) NULL
;
522 m_viewFrame
= (wxFrame
*) NULL
;
527 GetDocumentManager()->ActivateView(this, FALSE
, TRUE
);
528 m_viewDocument
->RemoveView(this);
531 // Extend event processing to search the document's event table
532 bool wxView::ProcessEvent(wxEvent
& event
)
534 if ( !GetDocument() || !GetDocument()->ProcessEvent(event
) )
535 return wxEvtHandler::ProcessEvent(event
);
540 void wxView::OnActivateView(bool WXUNUSED(activate
), wxView
*WXUNUSED(activeView
), wxView
*WXUNUSED(deactiveView
))
544 void wxView::OnPrint(wxDC
*dc
, wxObject
*WXUNUSED(info
))
549 void wxView::OnUpdate(wxView
*WXUNUSED(sender
), wxObject
*WXUNUSED(hint
))
553 void wxView::OnChangeFilename()
555 if (GetFrame() && GetDocument())
558 GetDocument()->GetPrintableName(name
);
560 GetFrame()->SetTitle(name
);
564 void wxView::SetDocument(wxDocument
*doc
)
566 m_viewDocument
= doc
;
571 bool wxView::Close(bool deleteWindow
)
573 if (OnClose(deleteWindow
))
579 void wxView::Activate(bool activate
)
581 if (GetDocumentManager())
583 OnActivateView(activate
, this, GetDocumentManager()->GetCurrentView());
584 GetDocumentManager()->ActivateView(this, activate
);
588 bool wxView::OnClose(bool WXUNUSED(deleteWindow
))
590 return GetDocument() ? GetDocument()->Close() : TRUE
;
593 #if wxUSE_PRINTING_ARCHITECTURE
594 wxPrintout
*wxView::OnCreatePrintout()
596 return new wxDocPrintout(this);
598 #endif // wxUSE_PRINTING_ARCHITECTURE
600 // ----------------------------------------------------------------------------
602 // ----------------------------------------------------------------------------
604 wxDocTemplate::wxDocTemplate(wxDocManager
*manager
,
605 const wxString
& descr
,
606 const wxString
& filter
,
609 const wxString
& docTypeName
,
610 const wxString
& viewTypeName
,
611 wxClassInfo
*docClassInfo
,
612 wxClassInfo
*viewClassInfo
,
615 m_documentManager
= manager
;
616 m_description
= descr
;
619 m_fileFilter
= filter
;
621 m_docTypeName
= docTypeName
;
622 m_viewTypeName
= viewTypeName
;
623 m_documentManager
->AssociateTemplate(this);
625 m_docClassInfo
= docClassInfo
;
626 m_viewClassInfo
= viewClassInfo
;
629 wxDocTemplate::~wxDocTemplate()
631 m_documentManager
->DisassociateTemplate(this);
634 // Tries to dynamically construct an object of the right class.
635 wxDocument
*wxDocTemplate::CreateDocument(const wxString
& path
, long flags
)
638 return (wxDocument
*) NULL
;
639 wxDocument
*doc
= (wxDocument
*)m_docClassInfo
->CreateObject();
640 doc
->SetFilename(path
);
641 doc
->SetDocumentTemplate(this);
642 GetDocumentManager()->AddDocument(doc
);
643 doc
->SetCommandProcessor(doc
->OnCreateCommandProcessor());
645 if (doc
->OnCreate(path
, flags
))
650 return (wxDocument
*) NULL
;
654 wxView
*wxDocTemplate::CreateView(wxDocument
*doc
, long flags
)
656 if (!m_viewClassInfo
)
657 return (wxView
*) NULL
;
658 wxView
*view
= (wxView
*)m_viewClassInfo
->CreateObject();
659 view
->SetDocument(doc
);
660 if (view
->OnCreate(doc
, flags
))
667 return (wxView
*) NULL
;
671 // The default (very primitive) format detection: check is the extension is
672 // that of the template
673 bool wxDocTemplate::FileMatchesTemplate(const wxString
& path
)
675 return GetDefaultExtension().IsSameAs(FindExtension(path
));
678 // ----------------------------------------------------------------------------
680 // ----------------------------------------------------------------------------
682 BEGIN_EVENT_TABLE(wxDocManager
, wxEvtHandler
)
683 EVT_MENU(wxID_OPEN
, wxDocManager::OnFileOpen
)
684 EVT_MENU(wxID_CLOSE
, wxDocManager::OnFileClose
)
685 EVT_MENU(wxID_REVERT
, wxDocManager::OnFileRevert
)
686 EVT_MENU(wxID_NEW
, wxDocManager::OnFileNew
)
687 EVT_MENU(wxID_SAVE
, wxDocManager::OnFileSave
)
688 EVT_MENU(wxID_SAVEAS
, wxDocManager::OnFileSaveAs
)
689 EVT_MENU(wxID_UNDO
, wxDocManager::OnUndo
)
690 EVT_MENU(wxID_REDO
, wxDocManager::OnRedo
)
691 #if wxUSE_PRINTING_ARCHITECTURE
692 EVT_MENU(wxID_PRINT
, wxDocManager::OnPrint
)
693 EVT_MENU(wxID_PRINT_SETUP
, wxDocManager::OnPrintSetup
)
694 EVT_MENU(wxID_PREVIEW
, wxDocManager::OnPreview
)
698 wxDocManager::wxDocManager(long flags
, bool initialize
)
700 m_defaultDocumentNameCounter
= 1;
702 m_currentView
= (wxView
*) NULL
;
703 m_maxDocsOpen
= 10000;
704 m_fileHistory
= (wxFileHistory
*) NULL
;
709 wxDocManager::~wxDocManager()
713 delete m_fileHistory
;
716 bool wxDocManager::Clear(bool force
)
718 wxNode
*node
= m_docs
.First();
721 wxDocument
*doc
= (wxDocument
*)node
->Data();
722 wxNode
*next
= node
->Next();
724 if (!doc
->Close() && !force
)
727 // Implicitly deletes the document when the last
728 // view is removed (deleted)
729 doc
->DeleteAllViews();
731 // Check document is deleted
732 if (m_docs
.Member(doc
))
735 // This assumes that documents are not connected in
736 // any way, i.e. deleting one document does NOT
740 node
= m_templates
.First();
743 wxDocTemplate
*templ
= (wxDocTemplate
*) node
->Data();
744 wxNode
* next
= node
->Next();
751 bool wxDocManager::Initialize()
753 m_fileHistory
= OnCreateFileHistory();
757 wxFileHistory
*wxDocManager::OnCreateFileHistory()
759 return new wxFileHistory
;
762 void wxDocManager::OnFileClose(wxCommandEvent
& WXUNUSED(event
))
764 wxDocument
*doc
= GetCurrentDocument();
769 doc
->DeleteAllViews();
770 if (m_docs
.Member(doc
))
775 void wxDocManager::OnFileNew(wxCommandEvent
& WXUNUSED(event
))
777 CreateDocument(wxString(""), wxDOC_NEW
);
780 void wxDocManager::OnFileOpen(wxCommandEvent
& WXUNUSED(event
))
782 CreateDocument(wxString(""), 0);
785 void wxDocManager::OnFileRevert(wxCommandEvent
& WXUNUSED(event
))
787 wxDocument
*doc
= GetCurrentDocument();
793 void wxDocManager::OnFileSave(wxCommandEvent
& WXUNUSED(event
))
795 wxDocument
*doc
= GetCurrentDocument();
801 void wxDocManager::OnFileSaveAs(wxCommandEvent
& WXUNUSED(event
))
803 wxDocument
*doc
= GetCurrentDocument();
809 void wxDocManager::OnPrint(wxCommandEvent
& WXUNUSED(event
))
811 #if wxUSE_PRINTING_ARCHITECTURE
812 wxView
*view
= GetCurrentView();
816 wxPrintout
*printout
= view
->OnCreatePrintout();
820 printer
.Print(view
->GetFrame(), printout
, TRUE
);
824 #endif // wxUSE_PRINTING_ARCHITECTURE
827 void wxDocManager::OnPrintSetup(wxCommandEvent
& WXUNUSED(event
))
829 #if wxUSE_PRINTING_ARCHITECTURE
830 wxWindow
*parentWin
= wxTheApp
->GetTopWindow();
831 wxView
*view
= GetCurrentView();
833 parentWin
= view
->GetFrame();
835 wxPrintDialogData data
;
837 wxPrintDialog
printerDialog(parentWin
, & data
);
838 printerDialog
.GetPrintDialogData().SetSetupDialog(TRUE
);
839 printerDialog
.ShowModal();
840 #endif // wxUSE_PRINTING_ARCHITECTURE
843 void wxDocManager::OnPreview(wxCommandEvent
& WXUNUSED(event
))
845 #if wxUSE_PRINTING_ARCHITECTURE
846 wxView
*view
= GetCurrentView();
850 wxPrintout
*printout
= view
->OnCreatePrintout();
853 // Pass two printout objects: for preview, and possible printing.
854 wxPrintPreviewBase
*preview
= (wxPrintPreviewBase
*) NULL
;
855 preview
= new wxPrintPreview(printout
, view
->OnCreatePrintout());
857 wxPreviewFrame
*frame
= new wxPreviewFrame(preview
, (wxFrame
*)wxTheApp
->GetTopWindow(), _("Print Preview"),
858 wxPoint(100, 100), wxSize(600, 650));
859 frame
->Centre(wxBOTH
);
863 #endif // wxUSE_PRINTING_ARCHITECTURE
866 void wxDocManager::OnUndo(wxCommandEvent
& WXUNUSED(event
))
868 wxDocument
*doc
= GetCurrentDocument();
871 if (doc
->GetCommandProcessor())
872 doc
->GetCommandProcessor()->Undo();
875 void wxDocManager::OnRedo(wxCommandEvent
& WXUNUSED(event
))
877 wxDocument
*doc
= GetCurrentDocument();
880 if (doc
->GetCommandProcessor())
881 doc
->GetCommandProcessor()->Redo();
884 wxView
*wxDocManager::GetCurrentView() const
887 return m_currentView
;
888 if (m_docs
.Number() == 1)
890 wxDocument
* doc
= (wxDocument
*) m_docs
.First()->Data();
891 return doc
->GetFirstView();
893 return (wxView
*) NULL
;
896 // Extend event processing to search the view's event table
897 bool wxDocManager::ProcessEvent(wxEvent
& event
)
899 wxView
* view
= GetCurrentView();
902 if (view
->ProcessEvent(event
))
905 return wxEvtHandler::ProcessEvent(event
);
908 wxDocument
*wxDocManager::CreateDocument(const wxString
& path
, long flags
)
910 wxDocTemplate
**templates
= new wxDocTemplate
*[m_templates
.Number()];
913 for (i
= 0; i
< m_templates
.Number(); i
++)
915 wxDocTemplate
*temp
= (wxDocTemplate
*)(m_templates
.Nth(i
)->Data());
916 if (temp
->IsVisible())
925 return (wxDocument
*) NULL
;
928 // If we've reached the max number of docs, close the
930 if (GetDocuments().Number() >= m_maxDocsOpen
)
932 wxDocument
*doc
= (wxDocument
*)GetDocuments().First()->Data();
935 // Implicitly deletes the document when
936 // the last view is deleted
937 doc
->DeleteAllViews();
939 // Check we're really deleted
940 if (m_docs
.Member(doc
))
944 return (wxDocument
*) NULL
;
947 // New document: user chooses a template, unless there's only one.
948 if (flags
& wxDOC_NEW
)
952 wxDocTemplate
*temp
= templates
[0];
954 wxDocument
*newDoc
= temp
->CreateDocument(path
, flags
);
957 newDoc
->SetDocumentName(temp
->GetDocumentName());
958 newDoc
->SetDocumentTemplate(temp
);
959 newDoc
->OnNewDocument();
964 wxDocTemplate
*temp
= SelectDocumentType(templates
, n
);
968 wxDocument
*newDoc
= temp
->CreateDocument(path
, flags
);
971 newDoc
->SetDocumentName(temp
->GetDocumentName());
972 newDoc
->SetDocumentTemplate(temp
);
973 newDoc
->OnNewDocument();
978 return (wxDocument
*) NULL
;
982 wxDocTemplate
*temp
= (wxDocTemplate
*) NULL
;
984 wxString
path2(_T(""));
988 if (flags
& wxDOC_SILENT
)
989 temp
= FindTemplateForPath(path2
);
991 temp
= SelectDocumentPath(templates
, n
, path2
, flags
);
997 wxDocument
*newDoc
= temp
->CreateDocument(path2
, flags
);
1000 newDoc
->SetDocumentName(temp
->GetDocumentName());
1001 newDoc
->SetDocumentTemplate(temp
);
1002 if (!newDoc
->OnOpenDocument(path2
))
1005 return (wxDocument
*) NULL
;
1007 AddFileToHistory(path2
);
1012 return (wxDocument
*) NULL
;
1015 wxView
*wxDocManager::CreateView(wxDocument
*doc
, long flags
)
1017 wxDocTemplate
**templates
= new wxDocTemplate
*[m_templates
.Number()];
1020 for (i
= 0; i
< m_templates
.Number(); i
++)
1022 wxDocTemplate
*temp
= (wxDocTemplate
*)(m_templates
.Nth(i
)->Data());
1023 if (temp
->IsVisible())
1025 if (temp
->GetDocumentName() == doc
->GetDocumentName())
1027 templates
[n
] = temp
;
1035 return (wxView
*) NULL
;
1039 wxDocTemplate
*temp
= templates
[0];
1041 wxView
*view
= temp
->CreateView(doc
, flags
);
1043 view
->SetViewName(temp
->GetViewName());
1047 wxDocTemplate
*temp
= SelectViewType(templates
, n
);
1051 wxView
*view
= temp
->CreateView(doc
, flags
);
1053 view
->SetViewName(temp
->GetViewName());
1057 return (wxView
*) NULL
;
1060 // Not yet implemented
1061 void wxDocManager::DeleteTemplate(wxDocTemplate
*WXUNUSED(temp
), long WXUNUSED(flags
))
1065 // Not yet implemented
1066 bool wxDocManager::FlushDoc(wxDocument
*WXUNUSED(doc
))
1071 wxDocument
*wxDocManager::GetCurrentDocument() const
1074 return m_currentView
->GetDocument();
1076 return (wxDocument
*) NULL
;
1079 // Make a default document name
1080 bool wxDocManager::MakeDefaultName(wxString
& name
)
1082 name
.Printf(_("unnamed%d"), m_defaultDocumentNameCounter
);
1083 m_defaultDocumentNameCounter
++;
1088 // Not yet implemented
1089 wxDocTemplate
*wxDocManager::MatchTemplate(const wxString
& WXUNUSED(path
))
1091 return (wxDocTemplate
*) NULL
;
1094 // File history management
1095 void wxDocManager::AddFileToHistory(const wxString
& file
)
1098 m_fileHistory
->AddFileToHistory(file
);
1101 wxString
wxDocManager::GetHistoryFile(int i
) const
1106 histFile
= m_fileHistory
->GetHistoryFile(i
);
1111 void wxDocManager::FileHistoryUseMenu(wxMenu
*menu
)
1114 m_fileHistory
->UseMenu(menu
);
1117 void wxDocManager::FileHistoryRemoveMenu(wxMenu
*menu
)
1120 m_fileHistory
->RemoveMenu(menu
);
1124 void wxDocManager::FileHistoryLoad(wxConfigBase
& config
)
1127 m_fileHistory
->Load(config
);
1130 void wxDocManager::FileHistorySave(wxConfigBase
& config
)
1133 m_fileHistory
->Save(config
);
1137 void wxDocManager::FileHistoryAddFilesToMenu(wxMenu
* menu
)
1140 m_fileHistory
->AddFilesToMenu(menu
);
1143 void wxDocManager::FileHistoryAddFilesToMenu()
1146 m_fileHistory
->AddFilesToMenu();
1149 int wxDocManager::GetNoHistoryFiles() const
1152 return m_fileHistory
->GetNoHistoryFiles();
1158 // Find out the document template via matching in the document file format
1159 // against that of the template
1160 wxDocTemplate
*wxDocManager::FindTemplateForPath(const wxString
& path
)
1162 wxDocTemplate
*theTemplate
= (wxDocTemplate
*) NULL
;
1164 // Find the template which this extension corresponds to
1166 for (i
= 0; i
< m_templates
.Number(); i
++)
1168 wxDocTemplate
*temp
= (wxDocTemplate
*)m_templates
.Nth(i
)->Data();
1169 if ( temp
->FileMatchesTemplate(path
) )
1178 // Prompts user to open a file, using file specs in templates.
1179 // How to implement in wxWindows? Must extend the file selector
1180 // dialog or implement own; OR match the extension to the
1181 // template extension.
1183 wxDocTemplate
*wxDocManager::SelectDocumentPath(wxDocTemplate
**templates
,
1187 int WXUNUSED(noTemplates
),
1190 long WXUNUSED(flags
),
1191 bool WXUNUSED(save
))
1193 // We can only have multiple filters in Windows
1198 for (i
= 0; i
< noTemplates
; i
++)
1200 if (templates
[i
]->IsVisible())
1202 // add a '|' to separate this filter from the previous one
1203 if ( !descrBuf
.IsEmpty() )
1204 descrBuf
<< _T('|');
1206 descrBuf
<< templates
[i
]->GetDescription()
1207 << _T(" (") << templates
[i
]->GetFileFilter() << _T(") |")
1208 << templates
[i
]->GetFileFilter();
1212 wxString descrBuf
= _T("*.*");
1215 int FilterIndex
= 0;
1216 wxString pathTmp
= wxFileSelectorEx(_("Select a file"),
1222 wxTheApp
->GetTopWindow());
1224 if (!pathTmp
.IsEmpty())
1227 wxString theExt
= FindExtension(path
);
1229 return (wxDocTemplate
*) NULL
;
1231 // This is dodgy in that we're selecting the template on the
1232 // basis of the file extension, which may not be a standard
1233 // one. We really want to know exactly which template was
1234 // chosen by using a more advanced file selector.
1235 wxDocTemplate
*theTemplate
= FindTemplateForPath(path
);
1237 theTemplate
= templates
[FilterIndex
];
1244 return (wxDocTemplate
*) NULL
;
1247 // In all other windowing systems, until we have more advanced
1248 // file selectors, we must select the document type (template) first, and
1249 // _then_ pop up the file selector.
1250 wxDocTemplate
*temp
= SelectDocumentType(templates
, noTemplates
);
1252 return (wxDocTemplate
*) NULL
;
1254 wxChar
*pathTmp
= wxFileSelector(_("Select a file"), _T(""), _T(""),
1255 temp
->GetDefaultExtension(),
1256 temp
->GetFileFilter(),
1257 0, wxTheApp
->GetTopWindow());
1265 return (wxDocTemplate
*) NULL
;
1269 wxDocTemplate
*wxDocManager::SelectDocumentType(wxDocTemplate
**templates
,
1272 wxChar
**strings
= new wxChar
*[noTemplates
];
1273 wxChar
**data
= new wxChar
*[noTemplates
];
1276 for (i
= 0; i
< noTemplates
; i
++)
1278 if (templates
[i
]->IsVisible())
1280 strings
[n
] = WXSTRINGCAST templates
[i
]->m_description
;
1281 data
[n
] = (wxChar
*)templates
[i
];
1289 return (wxDocTemplate
*) NULL
;
1293 wxDocTemplate
*temp
= (wxDocTemplate
*)data
[0];
1299 wxDocTemplate
*theTemplate
= (wxDocTemplate
*)wxGetSingleChoiceData(_("Select a document template"), _("Templates"), n
,
1300 strings
, (char **)data
);
1306 wxDocTemplate
*wxDocManager::SelectViewType(wxDocTemplate
**templates
,
1309 wxChar
**strings
= new wxChar
*[noTemplates
];
1310 wxChar
**data
= new wxChar
*[noTemplates
];
1313 for (i
= 0; i
< noTemplates
; i
++)
1315 if (templates
[i
]->IsVisible() && (templates
[i
]->GetViewName() != _T("")))
1317 strings
[n
] = WXSTRINGCAST templates
[i
]->m_viewTypeName
;
1318 data
[n
] = (wxChar
*)templates
[i
];
1322 wxDocTemplate
*theTemplate
= (wxDocTemplate
*)wxGetSingleChoiceData(_("Select a document view"), _("Views"), n
,
1323 strings
, (char **)data
);
1329 void wxDocManager::AssociateTemplate(wxDocTemplate
*temp
)
1331 if (!m_templates
.Member(temp
))
1332 m_templates
.Append(temp
);
1335 void wxDocManager::DisassociateTemplate(wxDocTemplate
*temp
)
1337 m_templates
.DeleteObject(temp
);
1340 // Add and remove a document from the manager's list
1341 void wxDocManager::AddDocument(wxDocument
*doc
)
1343 if (!m_docs
.Member(doc
))
1347 void wxDocManager::RemoveDocument(wxDocument
*doc
)
1349 m_docs
.DeleteObject(doc
);
1352 // Views or windows should inform the document manager
1353 // when a view is going in or out of focus
1354 void wxDocManager::ActivateView(wxView
*view
, bool activate
, bool WXUNUSED(deleting
))
1356 // If we're deactiving, and if we're not actually deleting the view, then
1357 // don't reset the current view because we may be going to
1358 // a window without a view.
1359 // WHAT DID I MEAN BY THAT EXACTLY?
1363 if (m_currentView == view)
1364 m_currentView = NULL;
1370 m_currentView
= view
;
1372 m_currentView
= (wxView
*) NULL
;
1376 // ----------------------------------------------------------------------------
1377 // Default document child frame
1378 // ----------------------------------------------------------------------------
1380 BEGIN_EVENT_TABLE(wxDocChildFrame
, wxFrame
)
1381 EVT_ACTIVATE(wxDocChildFrame::OnActivate
)
1382 EVT_CLOSE(wxDocChildFrame::OnCloseWindow
)
1385 wxDocChildFrame::wxDocChildFrame(wxDocument
*doc
,
1389 const wxString
& title
,
1393 const wxString
& name
)
1394 : wxFrame(frame
, id
, title
, pos
, size
, style
, name
)
1396 m_childDocument
= doc
;
1399 view
->SetFrame(this);
1402 wxDocChildFrame::~wxDocChildFrame()
1406 // Extend event processing to search the view's event table
1407 bool wxDocChildFrame::ProcessEvent(wxEvent
& event
)
1410 m_childView
->Activate(TRUE
);
1412 if ( !m_childView
|| ! m_childView
->ProcessEvent(event
) )
1414 // Only hand up to the parent if it's a menu command
1415 if (!event
.IsKindOf(CLASSINFO(wxCommandEvent
)) || !GetParent() || !GetParent()->ProcessEvent(event
))
1416 return wxEvtHandler::ProcessEvent(event
);
1424 void wxDocChildFrame::OnActivate(wxActivateEvent
& event
)
1426 wxFrame::OnActivate(event
);
1429 m_childView
->Activate(event
.GetActive());
1432 void wxDocChildFrame::OnCloseWindow(wxCloseEvent
& event
)
1437 if (!event
.CanVeto())
1438 ans
= TRUE
; // Must delete.
1440 ans
= m_childView
->Close(FALSE
); // FALSE means don't delete associated window
1444 m_childView
->Activate(FALSE
);
1446 m_childView
= (wxView
*) NULL
;
1447 m_childDocument
= (wxDocument
*) NULL
;
1458 // ----------------------------------------------------------------------------
1459 // Default parent frame
1460 // ----------------------------------------------------------------------------
1462 BEGIN_EVENT_TABLE(wxDocParentFrame
, wxFrame
)
1463 EVT_MENU(wxID_EXIT
, wxDocParentFrame::OnExit
)
1464 EVT_MENU_RANGE(wxID_FILE1
, wxID_FILE9
, wxDocParentFrame::OnMRUFile
)
1465 EVT_CLOSE(wxDocParentFrame::OnCloseWindow
)
1468 wxDocParentFrame::wxDocParentFrame(wxDocManager
*manager
,
1471 const wxString
& title
,
1475 const wxString
& name
)
1476 : wxFrame(frame
, id
, title
, pos
, size
, style
, name
)
1478 m_docManager
= manager
;
1481 void wxDocParentFrame::OnExit(wxCommandEvent
& WXUNUSED(event
))
1486 void wxDocParentFrame::OnMRUFile(wxCommandEvent
& event
)
1488 wxString
f(m_docManager
->GetHistoryFile(event
.GetSelection() - wxID_FILE1
));
1490 (void)m_docManager
->CreateDocument(f
, wxDOC_SILENT
);
1493 // Extend event processing to search the view's event table
1494 bool wxDocParentFrame::ProcessEvent(wxEvent
& event
)
1496 // Try the document manager, then do default processing
1497 if (!m_docManager
|| !m_docManager
->ProcessEvent(event
))
1498 return wxEvtHandler::ProcessEvent(event
);
1503 // Define the behaviour for the frame closing
1504 // - must delete all frames except for the main one.
1505 void wxDocParentFrame::OnCloseWindow(wxCloseEvent
& event
)
1507 if (m_docManager
->Clear(!event
.CanVeto()))
1515 #if wxUSE_PRINTING_ARCHITECTURE
1517 wxDocPrintout::wxDocPrintout(wxView
*view
, const wxString
& title
)
1518 : wxPrintout(WXSTRINGCAST title
)
1520 m_printoutView
= view
;
1523 bool wxDocPrintout::OnPrintPage(int WXUNUSED(page
))
1527 // Get the logical pixels per inch of screen and printer
1528 int ppiScreenX
, ppiScreenY
;
1529 GetPPIScreen(&ppiScreenX
, &ppiScreenY
);
1530 int ppiPrinterX
, ppiPrinterY
;
1531 GetPPIPrinter(&ppiPrinterX
, &ppiPrinterY
);
1533 // This scales the DC so that the printout roughly represents the
1534 // the screen scaling. The text point size _should_ be the right size
1535 // but in fact is too small for some reason. This is a detail that will
1536 // need to be addressed at some point but can be fudged for the
1538 float scale
= (float)((float)ppiPrinterX
/(float)ppiScreenX
);
1540 // Now we have to check in case our real page size is reduced
1541 // (e.g. because we're drawing to a print preview memory DC)
1542 int pageWidth
, pageHeight
;
1544 dc
->GetSize(&w
, &h
);
1545 GetPageSizePixels(&pageWidth
, &pageHeight
);
1547 // If printer pageWidth == current DC width, then this doesn't
1548 // change. But w might be the preview bitmap width, so scale down.
1549 float overallScale
= scale
* (float)(w
/(float)pageWidth
);
1550 dc
->SetUserScale(overallScale
, overallScale
);
1554 m_printoutView
->OnDraw(dc
);
1559 bool wxDocPrintout::HasPage(int pageNum
)
1561 return (pageNum
== 1);
1564 bool wxDocPrintout::OnBeginDocument(int startPage
, int endPage
)
1566 if (!wxPrintout::OnBeginDocument(startPage
, endPage
))
1572 void wxDocPrintout::GetPageInfo(int *minPage
, int *maxPage
, int *selPageFrom
, int *selPageTo
)
1580 #endif // wxUSE_PRINTING_ARCHITECTURE
1582 // ----------------------------------------------------------------------------
1583 // Command processing framework
1584 // ----------------------------------------------------------------------------
1586 wxCommand::wxCommand(bool canUndoIt
, const wxString
& name
)
1588 m_canUndo
= canUndoIt
;
1589 m_commandName
= name
;
1592 wxCommand::~wxCommand()
1596 // Command processor
1597 wxCommandProcessor::wxCommandProcessor(int maxCommands
)
1599 m_maxNoCommands
= maxCommands
;
1600 m_currentCommand
= (wxNode
*) NULL
;
1601 m_commandEditMenu
= (wxMenu
*) NULL
;
1604 wxCommandProcessor::~wxCommandProcessor()
1609 // Pass a command to the processor. The processor calls Do();
1610 // if successful, is appended to the command history unless
1611 // storeIt is FALSE.
1612 bool wxCommandProcessor::Submit(wxCommand
*command
, bool storeIt
)
1614 bool success
= command
->Do();
1615 if (success
&& storeIt
)
1617 if (m_commands
.Number() == m_maxNoCommands
)
1619 wxNode
*firstNode
= m_commands
.First();
1620 wxCommand
*firstCommand
= (wxCommand
*)firstNode
->Data();
1621 delete firstCommand
;
1625 // Correct a bug: we must chop off the current 'branch'
1626 // so that we're at the end of the command list.
1627 if (!m_currentCommand
)
1631 wxNode
*node
= m_currentCommand
->Next();
1634 wxNode
*next
= node
->Next();
1635 delete (wxCommand
*)node
->Data();
1641 m_commands
.Append(command
);
1642 m_currentCommand
= m_commands
.Last();
1648 bool wxCommandProcessor::Undo()
1650 if (m_currentCommand
)
1652 wxCommand
*command
= (wxCommand
*)m_currentCommand
->Data();
1653 if (command
->CanUndo())
1655 bool success
= command
->Undo();
1658 m_currentCommand
= m_currentCommand
->Previous();
1667 bool wxCommandProcessor::Redo()
1669 wxCommand
*redoCommand
= (wxCommand
*) NULL
;
1670 wxNode
*redoNode
= (wxNode
*) NULL
;
1671 if (m_currentCommand
&& m_currentCommand
->Next())
1673 redoCommand
= (wxCommand
*)m_currentCommand
->Next()->Data();
1674 redoNode
= m_currentCommand
->Next();
1678 if (m_commands
.Number() > 0)
1680 redoCommand
= (wxCommand
*)m_commands
.First()->Data();
1681 redoNode
= m_commands
.First();
1687 bool success
= redoCommand
->Do();
1690 m_currentCommand
= redoNode
;
1698 bool wxCommandProcessor::CanUndo() const
1700 if (m_currentCommand
)
1701 return ((wxCommand
*)m_currentCommand
->Data())->CanUndo();
1705 bool wxCommandProcessor::CanRedo() const
1707 if ((m_currentCommand
!= (wxNode
*) NULL
) && (m_currentCommand
->Next() == (wxNode
*) NULL
))
1710 if ((m_currentCommand
!= (wxNode
*) NULL
) && (m_currentCommand
->Next() != (wxNode
*) NULL
))
1713 if ((m_currentCommand
== (wxNode
*) NULL
) && (m_commands
.Number() > 0))
1719 void wxCommandProcessor::Initialize()
1721 m_currentCommand
= m_commands
.Last();
1725 void wxCommandProcessor::SetMenuStrings()
1727 if (m_commandEditMenu
)
1730 if (m_currentCommand
)
1732 wxCommand
*command
= (wxCommand
*)m_currentCommand
->Data();
1733 wxString
commandName(command
->GetName());
1734 if (commandName
== _T("")) commandName
= _("Unnamed command");
1735 bool canUndo
= command
->CanUndo();
1737 buf
= wxString(_("&Undo ")) + commandName
;
1739 buf
= wxString(_("Can't &Undo ")) + commandName
;
1741 m_commandEditMenu
->SetLabel(wxID_UNDO
, buf
);
1742 m_commandEditMenu
->Enable(wxID_UNDO
, canUndo
);
1744 // We can redo, if we're not at the end of the history.
1745 if (m_currentCommand
->Next())
1747 wxCommand
*redoCommand
= (wxCommand
*)m_currentCommand
->Next()->Data();
1748 wxString
redoCommandName(redoCommand
->GetName());
1749 if (redoCommandName
== _T("")) redoCommandName
= _("Unnamed command");
1750 buf
= wxString(_("&Redo ")) + redoCommandName
;
1751 m_commandEditMenu
->SetLabel(wxID_REDO
, buf
);
1752 m_commandEditMenu
->Enable(wxID_REDO
, TRUE
);
1756 m_commandEditMenu
->SetLabel(wxID_REDO
, _("&Redo"));
1757 m_commandEditMenu
->Enable(wxID_REDO
, FALSE
);
1762 m_commandEditMenu
->SetLabel(wxID_UNDO
, _("&Undo"));
1763 m_commandEditMenu
->Enable(wxID_UNDO
, FALSE
);
1765 if (m_commands
.Number() == 0)
1767 m_commandEditMenu
->SetLabel(wxID_REDO
, _("&Redo"));
1768 m_commandEditMenu
->Enable(wxID_REDO
, FALSE
);
1772 // currentCommand is NULL but there are commands: this means that
1773 // we've undone to the start of the list, but can redo the first.
1774 wxCommand
*redoCommand
= (wxCommand
*)m_commands
.First()->Data();
1775 wxString
redoCommandName(redoCommand
->GetName());
1776 if (redoCommandName
== _T("")) redoCommandName
= _("Unnamed command");
1777 buf
= wxString(_("&Redo ")) + redoCommandName
;
1778 m_commandEditMenu
->SetLabel(wxID_REDO
, buf
);
1779 m_commandEditMenu
->Enable(wxID_REDO
, TRUE
);
1785 void wxCommandProcessor::ClearCommands()
1787 wxNode
*node
= m_commands
.First();
1790 wxCommand
*command
= (wxCommand
*)node
->Data();
1793 node
= m_commands
.First();
1795 m_currentCommand
= (wxNode
*) NULL
;
1798 // ----------------------------------------------------------------------------
1799 // File history processor
1800 // ----------------------------------------------------------------------------
1802 wxFileHistory::wxFileHistory(int maxFiles
)
1804 m_fileMaxFiles
= maxFiles
;
1806 m_fileHistory
= new wxChar
*[m_fileMaxFiles
];
1809 wxFileHistory::~wxFileHistory()
1812 for (i
= 0; i
< m_fileHistoryN
; i
++)
1813 delete[] m_fileHistory
[i
];
1814 delete[] m_fileHistory
;
1817 // File history management
1818 void wxFileHistory::AddFileToHistory(const wxString
& file
)
1821 // Check we don't already have this file
1822 for (i
= 0; i
< m_fileHistoryN
; i
++)
1824 if (m_fileHistory
[i
] && wxString(m_fileHistory
[i
]) == file
)
1828 // Add to the project file history:
1829 // Move existing files (if any) down so we can insert file at beginning.
1831 // First delete filename that has popped off the end of the array (if any)
1832 if (m_fileHistoryN
== m_fileMaxFiles
)
1834 delete[] m_fileHistory
[m_fileMaxFiles
-1];
1835 m_fileHistory
[m_fileMaxFiles
-1] = (wxChar
*) NULL
;
1837 if (m_fileHistoryN
< m_fileMaxFiles
)
1839 wxNode
* node
= m_fileMenus
.First();
1842 wxMenu
* menu
= (wxMenu
*) node
->Data();
1843 if (m_fileHistoryN
== 0)
1844 menu
->AppendSeparator();
1845 menu
->Append(wxID_FILE1
+m_fileHistoryN
, _("[EMPTY]"));
1846 node
= node
->Next();
1850 // Shuffle filenames down
1851 for (i
= (m_fileHistoryN
-1); i
> 0; i
--)
1853 m_fileHistory
[i
] = m_fileHistory
[i
-1];
1855 m_fileHistory
[0] = copystring(file
);
1857 for (i
= 0; i
< m_fileHistoryN
; i
++)
1858 if (m_fileHistory
[i
])
1861 buf
.Printf(_T("&%d %s"), i
+1, m_fileHistory
[i
]);
1862 wxNode
* node
= m_fileMenus
.First();
1865 wxMenu
* menu
= (wxMenu
*) node
->Data();
1866 menu
->SetLabel(wxID_FILE1
+i
, buf
);
1867 node
= node
->Next();
1872 wxString
wxFileHistory::GetHistoryFile(int i
) const
1874 if (i
< m_fileHistoryN
)
1875 return wxString(m_fileHistory
[i
]);
1877 return wxString("");
1880 void wxFileHistory::UseMenu(wxMenu
*menu
)
1882 if (!m_fileMenus
.Member(menu
))
1883 m_fileMenus
.Append(menu
);
1886 void wxFileHistory::RemoveMenu(wxMenu
*menu
)
1888 m_fileMenus
.DeleteObject(menu
);
1892 void wxFileHistory::Load(wxConfigBase
& config
)
1896 buf
.Printf(_T("file%d"), m_fileHistoryN
+1);
1897 wxString historyFile
;
1898 while ((m_fileHistoryN
<= m_fileMaxFiles
) && config
.Read(buf
, &historyFile
) && (historyFile
!= _T("")))
1900 m_fileHistory
[m_fileHistoryN
] = copystring((const wxChar
*) historyFile
);
1902 buf
.Printf(_T("file%d"), m_fileHistoryN
+1);
1908 void wxFileHistory::Save(wxConfigBase
& config
)
1911 for (i
= 0; i
< m_fileHistoryN
; i
++)
1914 buf
.Printf(_T("file%d"), i
+1);
1915 config
.Write(buf
, wxString(m_fileHistory
[i
]));
1918 #endif // wxUSE_CONFIG
1920 void wxFileHistory::AddFilesToMenu()
1922 if (m_fileHistoryN
> 0)
1924 wxNode
* node
= m_fileMenus
.First();
1927 wxMenu
* menu
= (wxMenu
*) node
->Data();
1928 menu
->AppendSeparator();
1930 for (i
= 0; i
< m_fileHistoryN
; i
++)
1932 if (m_fileHistory
[i
])
1935 buf
.Printf(_T("&%d %s"), i
+1, m_fileHistory
[i
]);
1936 menu
->Append(wxID_FILE1
+i
, buf
);
1939 node
= node
->Next();
1944 void wxFileHistory::AddFilesToMenu(wxMenu
* menu
)
1946 if (m_fileHistoryN
> 0)
1948 menu
->AppendSeparator();
1950 for (i
= 0; i
< m_fileHistoryN
; i
++)
1952 if (m_fileHistory
[i
])
1955 buf
.Printf(_T("&%d %s"), i
+1, m_fileHistory
[i
]);
1956 menu
->Append(wxID_FILE1
+i
, buf
);
1962 // ----------------------------------------------------------------------------
1963 // Permits compatibility with existing file formats and functions that
1964 // manipulate files directly
1965 // ----------------------------------------------------------------------------
1967 #if wxUSE_STD_IOSTREAM
1968 bool wxTransferFileToStream(const wxString
& filename
, ostream
& stream
)
1973 if ((fd1
= fopen (filename
.fn_str(), "rb")) == NULL
)
1976 while ((ch
= getc (fd1
)) != EOF
)
1977 stream
<< (unsigned char)ch
;
1983 bool wxTransferStreamToFile(istream
& stream
, const wxString
& filename
)
1988 if ((fd1
= fopen (filename
.fn_str(), "wb")) == NULL
)
1993 while (!stream
.eof())
2004 #endif // wxUSE_DOC_VIEW_ARCHITECTURE