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"
35 #if wxUSE_DOC_VIEW_ARCHITECTURE
38 #include "wx/string.h"
42 #include "wx/dialog.h"
45 #include "wx/filedlg.h"
53 #if wxUSE_PRINTING_ARCHITECTURE
54 #include "wx/prntbase.h"
55 #include "wx/printdlg.h"
58 #include "wx/msgdlg.h"
59 #include "wx/choicdlg.h"
60 #include "wx/docview.h"
61 #include "wx/confbase.h"
66 #include "wx/ioswrap.h"
74 // ----------------------------------------------------------------------------
76 // ----------------------------------------------------------------------------
78 #if !USE_SHARED_LIBRARY
79 IMPLEMENT_ABSTRACT_CLASS(wxDocument
, wxEvtHandler
)
80 IMPLEMENT_ABSTRACT_CLASS(wxView
, wxEvtHandler
)
81 IMPLEMENT_ABSTRACT_CLASS(wxDocTemplate
, wxObject
)
82 IMPLEMENT_DYNAMIC_CLASS(wxDocManager
, wxEvtHandler
)
83 IMPLEMENT_CLASS(wxDocChildFrame
, wxFrame
)
84 IMPLEMENT_CLASS(wxDocParentFrame
, wxFrame
)
86 #if wxUSE_PRINTING_ARCHITECTURE
87 IMPLEMENT_DYNAMIC_CLASS(wxDocPrintout
, wxPrintout
)
90 IMPLEMENT_CLASS(wxCommand
, wxObject
)
91 IMPLEMENT_DYNAMIC_CLASS(wxCommandProcessor
, wxObject
)
92 IMPLEMENT_DYNAMIC_CLASS(wxFileHistory
, wxObject
)
95 // ----------------------------------------------------------------------------
96 // function prototypes
97 // ----------------------------------------------------------------------------
99 static inline wxString
FindExtension(const wxChar
*path
);
101 // ============================================================================
103 // ============================================================================
105 // ----------------------------------------------------------------------------
107 // ----------------------------------------------------------------------------
109 static wxString
FindExtension(const wxChar
*path
)
112 wxSplitPath(path
, NULL
, NULL
, &ext
);
114 // VZ: extensions are considered not case sensitive - is this really a good
116 return ext
.MakeLower();
119 // ----------------------------------------------------------------------------
120 // Definition of wxDocument
121 // ----------------------------------------------------------------------------
123 wxDocument::wxDocument(wxDocument
*parent
)
125 m_documentModified
= FALSE
;
126 m_documentParent
= parent
;
127 m_documentTemplate
= (wxDocTemplate
*) NULL
;
131 bool wxDocument::DeleteContents()
136 wxDocument::~wxDocument()
140 if (m_commandProcessor
)
141 delete m_commandProcessor
;
143 GetDocumentManager()->RemoveDocument(this);
145 // Not safe to do here, since it'll invoke virtual view functions
146 // expecting to see valid derived objects: and by the time we get here,
147 // we've called destructors higher up.
151 bool wxDocument::Close()
153 if (OnSaveModified())
154 return OnCloseDocument();
159 bool wxDocument::OnCloseDocument()
166 // Note that this implicitly deletes the document when the last view is
168 bool wxDocument::DeleteAllViews()
170 wxNode
*node
= m_documentViews
.First();
173 wxView
*view
= (wxView
*)node
->Data();
177 wxNode
*next
= node
->Next();
179 delete view
; // Deletes node implicitly
185 wxView
*wxDocument::GetFirstView() const
187 if (m_documentViews
.Number() == 0)
188 return (wxView
*) NULL
;
189 return (wxView
*)m_documentViews
.First()->Data();
192 wxDocManager
*wxDocument::GetDocumentManager() const
194 return m_documentTemplate
->GetDocumentManager();
197 bool wxDocument::OnNewDocument()
199 if (!OnSaveModified())
202 if (OnCloseDocument()==FALSE
) return FALSE
;
205 SetDocumentSaved(FALSE
);
208 GetDocumentManager()->MakeDefaultName(name
);
210 SetFilename(name
, TRUE
);
215 bool wxDocument::Save()
219 if (!IsModified()) return TRUE
;
220 if (m_documentFile
== _T("") || !m_savedYet
)
223 ret
= OnSaveDocument(m_documentFile
);
225 SetDocumentSaved(TRUE
);
229 bool wxDocument::SaveAs()
231 wxDocTemplate
*docTemplate
= GetDocumentTemplate();
235 wxString tmp
= wxFileSelector(_("Save as"),
236 docTemplate
->GetDirectory(),
238 docTemplate
->GetDefaultExtension(),
239 docTemplate
->GetFileFilter(),
240 wxSAVE
| wxOVERWRITE_PROMPT
,
241 GetDocumentWindow());
246 wxString
fileName(tmp
);
247 wxString path
, name
, ext
;
248 wxSplitPath(fileName
, & path
, & name
, & ext
);
250 if (ext
.IsEmpty() || ext
== _T(""))
253 fileName
+= docTemplate
->GetDefaultExtension();
256 SetFilename(fileName
);
257 SetTitle(wxFileNameFromPath(fileName
));
259 GetDocumentManager()->AddFileToHistory(fileName
);
261 // Notify the views that the filename has changed
262 wxNode
*node
= m_documentViews
.First();
265 wxView
*view
= (wxView
*)node
->Data();
266 view
->OnChangeFilename();
270 return OnSaveDocument(m_documentFile
);
273 bool wxDocument::OnSaveDocument(const wxString
& file
)
279 if (wxTheApp
->GetAppName() != _T(""))
280 msgTitle
= wxTheApp
->GetAppName();
282 msgTitle
= wxString(_("File error"));
284 ofstream
store(file
.fn_str());
285 if (store
.fail() || store
.bad())
287 (void)wxMessageBox(_("Sorry, could not open this file for saving."), msgTitle
, wxOK
| wxICON_EXCLAMATION
,
288 GetDocumentWindow());
292 if (SaveObject(store
)==FALSE
)
294 (void)wxMessageBox(_("Sorry, could not save this file."), msgTitle
, wxOK
| wxICON_EXCLAMATION
,
295 GetDocumentWindow());
304 bool wxDocument::OnOpenDocument(const wxString
& file
)
306 if (!OnSaveModified())
310 if (wxTheApp
->GetAppName() != _T(""))
311 msgTitle
= wxTheApp
->GetAppName();
313 msgTitle
= wxString(_("File error"));
315 ifstream
store(file
.fn_str());
316 if (store
.fail() || store
.bad())
318 (void)wxMessageBox(_("Sorry, could not open this file."), msgTitle
, wxOK
|wxICON_EXCLAMATION
,
319 GetDocumentWindow());
322 if (LoadObject(store
)==FALSE
)
324 (void)wxMessageBox(_("Sorry, could not open this file."), msgTitle
, wxOK
|wxICON_EXCLAMATION
,
325 GetDocumentWindow());
328 SetFilename(file
, TRUE
);
337 istream
& wxDocument::LoadObject(istream
& stream
)
339 // wxObject::LoadObject(stream);
344 ostream
& wxDocument::SaveObject(ostream
& stream
)
346 // wxObject::SaveObject(stream);
351 bool wxDocument::Revert()
357 // Get title, or filename if no title, else unnamed
358 bool wxDocument::GetPrintableName(wxString
& buf
) const
360 if (m_documentTitle
!= _T(""))
362 buf
= m_documentTitle
;
365 else if (m_documentFile
!= _T(""))
367 buf
= wxFileNameFromPath(m_documentFile
);
377 wxWindow
*wxDocument::GetDocumentWindow() const
379 wxView
*view
= GetFirstView();
381 return view
->GetFrame();
383 return wxTheApp
->GetTopWindow();
386 wxCommandProcessor
*wxDocument::OnCreateCommandProcessor()
388 return new wxCommandProcessor
;
391 // TRUE if safe to close
392 bool wxDocument::OnSaveModified()
397 GetPrintableName(title
);
400 if (wxTheApp
->GetAppName() != _T(""))
401 msgTitle
= wxTheApp
->GetAppName();
403 msgTitle
= wxString(_("Warning"));
406 prompt
.Printf(_("Do you want to save changes to document %s?"),
407 (const wxChar
*)title
);
408 int res
= wxMessageBox(prompt
, msgTitle
,
409 wxYES_NO
|wxCANCEL
|wxICON_QUESTION
,
410 GetDocumentWindow());
416 else if (res
== wxYES
)
418 else if (res
== wxCANCEL
)
424 bool wxDocument::Draw(wxDC
& WXUNUSED(context
))
429 bool wxDocument::AddView(wxView
*view
)
431 if (!m_documentViews
.Member(view
))
433 m_documentViews
.Append(view
);
439 bool wxDocument::RemoveView(wxView
*view
)
441 (void)m_documentViews
.DeleteObject(view
);
446 bool wxDocument::OnCreate(const wxString
& WXUNUSED(path
), long flags
)
448 if (GetDocumentTemplate()->CreateView(this, flags
))
454 // Called after a view is added or removed.
455 // The default implementation deletes the document if
456 // there are no more views.
457 void wxDocument::OnChangedViewList()
459 if (m_documentViews
.Number() == 0)
461 if (OnSaveModified())
468 void wxDocument::UpdateAllViews(wxView
*sender
, wxObject
*hint
)
470 wxNode
*node
= m_documentViews
.First();
473 wxView
*view
= (wxView
*)node
->Data();
474 view
->OnUpdate(sender
, hint
);
479 void wxDocument::SetFilename(const wxString
& filename
, bool notifyViews
)
481 m_documentFile
= filename
;
484 // Notify the views that the filename has changed
485 wxNode
*node
= m_documentViews
.First();
488 wxView
*view
= (wxView
*)node
->Data();
489 view
->OnChangeFilename();
495 // ----------------------------------------------------------------------------
497 // ----------------------------------------------------------------------------
502 m_viewDocument
= (wxDocument
*) NULL
;
505 m_viewFrame
= (wxFrame
*) NULL
;
510 GetDocumentManager()->ActivateView(this, FALSE
, TRUE
);
511 m_viewDocument
->RemoveView(this);
514 // Extend event processing to search the document's event table
515 bool wxView::ProcessEvent(wxEvent
& event
)
517 if ( !GetDocument() || !GetDocument()->ProcessEvent(event
) )
518 return wxEvtHandler::ProcessEvent(event
);
523 void wxView::OnActivateView(bool WXUNUSED(activate
), wxView
*WXUNUSED(activeView
), wxView
*WXUNUSED(deactiveView
))
527 void wxView::OnPrint(wxDC
*dc
, wxObject
*WXUNUSED(info
))
532 void wxView::OnUpdate(wxView
*WXUNUSED(sender
), wxObject
*WXUNUSED(hint
))
536 void wxView::OnChangeFilename()
538 if (GetFrame() && GetDocument())
541 GetDocument()->GetPrintableName(name
);
543 GetFrame()->SetTitle(name
);
547 void wxView::SetDocument(wxDocument
*doc
)
549 m_viewDocument
= doc
;
554 bool wxView::Close(bool deleteWindow
)
556 if (OnClose(deleteWindow
))
562 void wxView::Activate(bool activate
)
564 if (GetDocumentManager())
566 OnActivateView(activate
, this, GetDocumentManager()->GetCurrentView());
567 GetDocumentManager()->ActivateView(this, activate
);
571 bool wxView::OnClose(bool WXUNUSED(deleteWindow
))
573 return GetDocument() ? GetDocument()->Close() : TRUE
;
576 #if wxUSE_PRINTING_ARCHITECTURE
577 wxPrintout
*wxView::OnCreatePrintout()
579 return new wxDocPrintout(this);
581 #endif // wxUSE_PRINTING_ARCHITECTURE
583 // ----------------------------------------------------------------------------
585 // ----------------------------------------------------------------------------
587 wxDocTemplate::wxDocTemplate(wxDocManager
*manager
,
588 const wxString
& descr
,
589 const wxString
& filter
,
592 const wxString
& docTypeName
,
593 const wxString
& viewTypeName
,
594 wxClassInfo
*docClassInfo
,
595 wxClassInfo
*viewClassInfo
,
598 m_documentManager
= manager
;
599 m_description
= descr
;
602 m_fileFilter
= filter
;
604 m_docTypeName
= docTypeName
;
605 m_viewTypeName
= viewTypeName
;
606 m_documentManager
->AssociateTemplate(this);
608 m_docClassInfo
= docClassInfo
;
609 m_viewClassInfo
= viewClassInfo
;
612 wxDocTemplate::~wxDocTemplate()
614 m_documentManager
->DisassociateTemplate(this);
617 // Tries to dynamically construct an object of the right class.
618 wxDocument
*wxDocTemplate::CreateDocument(const wxString
& path
, long flags
)
621 return (wxDocument
*) NULL
;
622 wxDocument
*doc
= (wxDocument
*)m_docClassInfo
->CreateObject();
623 doc
->SetFilename(path
);
624 doc
->SetDocumentTemplate(this);
625 GetDocumentManager()->AddDocument(doc
);
626 doc
->SetCommandProcessor(doc
->OnCreateCommandProcessor());
628 if (doc
->OnCreate(path
, flags
))
633 return (wxDocument
*) NULL
;
637 wxView
*wxDocTemplate::CreateView(wxDocument
*doc
, long flags
)
639 if (!m_viewClassInfo
)
640 return (wxView
*) NULL
;
641 wxView
*view
= (wxView
*)m_viewClassInfo
->CreateObject();
642 view
->SetDocument(doc
);
643 if (view
->OnCreate(doc
, flags
))
650 return (wxView
*) NULL
;
654 // The default (very primitive) format detection: check is the extension is
655 // that of the template
656 bool wxDocTemplate::FileMatchesTemplate(const wxString
& path
)
658 return GetDefaultExtension().IsSameAs(FindExtension(path
));
661 // ----------------------------------------------------------------------------
663 // ----------------------------------------------------------------------------
665 BEGIN_EVENT_TABLE(wxDocManager
, wxEvtHandler
)
666 EVT_MENU(wxID_OPEN
, wxDocManager::OnFileOpen
)
667 EVT_MENU(wxID_CLOSE
, wxDocManager::OnFileClose
)
668 EVT_MENU(wxID_REVERT
, wxDocManager::OnFileRevert
)
669 EVT_MENU(wxID_NEW
, wxDocManager::OnFileNew
)
670 EVT_MENU(wxID_SAVE
, wxDocManager::OnFileSave
)
671 EVT_MENU(wxID_SAVEAS
, wxDocManager::OnFileSaveAs
)
672 EVT_MENU(wxID_UNDO
, wxDocManager::OnUndo
)
673 EVT_MENU(wxID_REDO
, wxDocManager::OnRedo
)
674 #if wxUSE_PRINTING_ARCHITECTURE
675 EVT_MENU(wxID_PRINT
, wxDocManager::OnPrint
)
676 EVT_MENU(wxID_PRINT_SETUP
, wxDocManager::OnPrintSetup
)
677 EVT_MENU(wxID_PREVIEW
, wxDocManager::OnPreview
)
681 wxDocManager::wxDocManager(long flags
, bool initialize
)
683 m_defaultDocumentNameCounter
= 1;
685 m_currentView
= (wxView
*) NULL
;
686 m_maxDocsOpen
= 10000;
687 m_fileHistory
= (wxFileHistory
*) NULL
;
692 wxDocManager::~wxDocManager()
696 delete m_fileHistory
;
699 bool wxDocManager::Clear(bool force
)
701 wxNode
*node
= m_docs
.First();
704 wxDocument
*doc
= (wxDocument
*)node
->Data();
705 wxNode
*next
= node
->Next();
707 if (!doc
->Close() && !force
)
710 // Implicitly deletes the document when the last
711 // view is removed (deleted)
712 doc
->DeleteAllViews();
714 // Check document is deleted
715 if (m_docs
.Member(doc
))
718 // This assumes that documents are not connected in
719 // any way, i.e. deleting one document does NOT
723 node
= m_templates
.First();
726 wxDocTemplate
*templ
= (wxDocTemplate
*) node
->Data();
727 wxNode
* next
= node
->Next();
734 bool wxDocManager::Initialize()
736 m_fileHistory
= OnCreateFileHistory();
740 wxFileHistory
*wxDocManager::OnCreateFileHistory()
742 return new wxFileHistory
;
745 void wxDocManager::OnFileClose(wxCommandEvent
& WXUNUSED(event
))
747 wxDocument
*doc
= GetCurrentDocument();
752 doc
->DeleteAllViews();
753 if (m_docs
.Member(doc
))
758 void wxDocManager::OnFileNew(wxCommandEvent
& WXUNUSED(event
))
760 CreateDocument(wxString(""), wxDOC_NEW
);
763 void wxDocManager::OnFileOpen(wxCommandEvent
& WXUNUSED(event
))
765 CreateDocument(wxString(""), 0);
768 void wxDocManager::OnFileRevert(wxCommandEvent
& WXUNUSED(event
))
770 wxDocument
*doc
= GetCurrentDocument();
776 void wxDocManager::OnFileSave(wxCommandEvent
& WXUNUSED(event
))
778 wxDocument
*doc
= GetCurrentDocument();
784 void wxDocManager::OnFileSaveAs(wxCommandEvent
& WXUNUSED(event
))
786 wxDocument
*doc
= GetCurrentDocument();
792 void wxDocManager::OnPrint(wxCommandEvent
& WXUNUSED(event
))
794 #if wxUSE_PRINTING_ARCHITECTURE
795 wxView
*view
= GetCurrentView();
799 wxPrintout
*printout
= view
->OnCreatePrintout();
803 printer
.Print(view
->GetFrame(), printout
, TRUE
);
807 #endif // wxUSE_PRINTING_ARCHITECTURE
810 void wxDocManager::OnPrintSetup(wxCommandEvent
& WXUNUSED(event
))
812 #if wxUSE_PRINTING_ARCHITECTURE
813 wxWindow
*parentWin
= wxTheApp
->GetTopWindow();
814 wxView
*view
= GetCurrentView();
816 parentWin
= view
->GetFrame();
818 wxPrintDialogData data
;
820 wxPrintDialog
printerDialog(parentWin
, & data
);
821 printerDialog
.GetPrintDialogData().SetSetupDialog(TRUE
);
822 printerDialog
.ShowModal();
823 #endif // wxUSE_PRINTING_ARCHITECTURE
826 void wxDocManager::OnPreview(wxCommandEvent
& WXUNUSED(event
))
828 #if wxUSE_PRINTING_ARCHITECTURE
829 wxView
*view
= GetCurrentView();
833 wxPrintout
*printout
= view
->OnCreatePrintout();
836 // Pass two printout objects: for preview, and possible printing.
837 wxPrintPreviewBase
*preview
= (wxPrintPreviewBase
*) NULL
;
838 preview
= new wxPrintPreview(printout
, view
->OnCreatePrintout());
840 wxPreviewFrame
*frame
= new wxPreviewFrame(preview
, (wxFrame
*)wxTheApp
->GetTopWindow(), _("Print Preview"),
841 wxPoint(100, 100), wxSize(600, 650));
842 frame
->Centre(wxBOTH
);
846 #endif // wxUSE_PRINTING_ARCHITECTURE
849 void wxDocManager::OnUndo(wxCommandEvent
& WXUNUSED(event
))
851 wxDocument
*doc
= GetCurrentDocument();
854 if (doc
->GetCommandProcessor())
855 doc
->GetCommandProcessor()->Undo();
858 void wxDocManager::OnRedo(wxCommandEvent
& WXUNUSED(event
))
860 wxDocument
*doc
= GetCurrentDocument();
863 if (doc
->GetCommandProcessor())
864 doc
->GetCommandProcessor()->Redo();
867 wxView
*wxDocManager::GetCurrentView() const
870 return m_currentView
;
871 if (m_docs
.Number() == 1)
873 wxDocument
* doc
= (wxDocument
*) m_docs
.First()->Data();
874 return doc
->GetFirstView();
876 return (wxView
*) NULL
;
879 // Extend event processing to search the view's event table
880 bool wxDocManager::ProcessEvent(wxEvent
& event
)
882 wxView
* view
= GetCurrentView();
885 if (view
->ProcessEvent(event
))
888 return wxEvtHandler::ProcessEvent(event
);
891 wxDocument
*wxDocManager::CreateDocument(const wxString
& path
, long flags
)
893 wxDocTemplate
**templates
= new wxDocTemplate
*[m_templates
.Number()];
896 for (i
= 0; i
< m_templates
.Number(); i
++)
898 wxDocTemplate
*temp
= (wxDocTemplate
*)(m_templates
.Nth(i
)->Data());
899 if (temp
->IsVisible())
908 return (wxDocument
*) NULL
;
911 // If we've reached the max number of docs, close the
913 if (GetDocuments().Number() >= m_maxDocsOpen
)
915 wxDocument
*doc
= (wxDocument
*)GetDocuments().First()->Data();
918 // Implicitly deletes the document when
919 // the last view is deleted
920 doc
->DeleteAllViews();
922 // Check we're really deleted
923 if (m_docs
.Member(doc
))
927 return (wxDocument
*) NULL
;
930 // New document: user chooses a template, unless there's only one.
931 if (flags
& wxDOC_NEW
)
935 wxDocTemplate
*temp
= templates
[0];
937 wxDocument
*newDoc
= temp
->CreateDocument(path
, flags
);
940 newDoc
->SetDocumentName(temp
->GetDocumentName());
941 newDoc
->SetDocumentTemplate(temp
);
942 newDoc
->OnNewDocument();
947 wxDocTemplate
*temp
= SelectDocumentType(templates
, n
);
951 wxDocument
*newDoc
= temp
->CreateDocument(path
, flags
);
954 newDoc
->SetDocumentName(temp
->GetDocumentName());
955 newDoc
->SetDocumentTemplate(temp
);
956 newDoc
->OnNewDocument();
961 return (wxDocument
*) NULL
;
965 wxDocTemplate
*temp
= (wxDocTemplate
*) NULL
;
967 wxString
path2(_T(""));
971 if (flags
& wxDOC_SILENT
)
972 temp
= FindTemplateForPath(path2
);
974 temp
= SelectDocumentPath(templates
, n
, path2
, flags
);
980 wxDocument
*newDoc
= temp
->CreateDocument(path2
, flags
);
983 newDoc
->SetDocumentName(temp
->GetDocumentName());
984 newDoc
->SetDocumentTemplate(temp
);
985 if (!newDoc
->OnOpenDocument(path2
))
988 return (wxDocument
*) NULL
;
990 AddFileToHistory(path2
);
995 return (wxDocument
*) NULL
;
998 wxView
*wxDocManager::CreateView(wxDocument
*doc
, long flags
)
1000 wxDocTemplate
**templates
= new wxDocTemplate
*[m_templates
.Number()];
1003 for (i
= 0; i
< m_templates
.Number(); i
++)
1005 wxDocTemplate
*temp
= (wxDocTemplate
*)(m_templates
.Nth(i
)->Data());
1006 if (temp
->IsVisible())
1008 if (temp
->GetDocumentName() == doc
->GetDocumentName())
1010 templates
[n
] = temp
;
1018 return (wxView
*) NULL
;
1022 wxDocTemplate
*temp
= templates
[0];
1024 wxView
*view
= temp
->CreateView(doc
, flags
);
1026 view
->SetViewName(temp
->GetViewName());
1030 wxDocTemplate
*temp
= SelectViewType(templates
, n
);
1034 wxView
*view
= temp
->CreateView(doc
, flags
);
1036 view
->SetViewName(temp
->GetViewName());
1040 return (wxView
*) NULL
;
1043 // Not yet implemented
1044 void wxDocManager::DeleteTemplate(wxDocTemplate
*WXUNUSED(temp
), long WXUNUSED(flags
))
1048 // Not yet implemented
1049 bool wxDocManager::FlushDoc(wxDocument
*WXUNUSED(doc
))
1054 wxDocument
*wxDocManager::GetCurrentDocument() const
1057 return m_currentView
->GetDocument();
1059 return (wxDocument
*) NULL
;
1062 // Make a default document name
1063 bool wxDocManager::MakeDefaultName(wxString
& name
)
1065 name
.Printf(_("unnamed%d"), m_defaultDocumentNameCounter
);
1066 m_defaultDocumentNameCounter
++;
1071 // Not yet implemented
1072 wxDocTemplate
*wxDocManager::MatchTemplate(const wxString
& WXUNUSED(path
))
1074 return (wxDocTemplate
*) NULL
;
1077 // File history management
1078 void wxDocManager::AddFileToHistory(const wxString
& file
)
1081 m_fileHistory
->AddFileToHistory(file
);
1084 wxString
wxDocManager::GetHistoryFile(int i
) const
1089 histFile
= m_fileHistory
->GetHistoryFile(i
);
1094 void wxDocManager::FileHistoryUseMenu(wxMenu
*menu
)
1097 m_fileHistory
->UseMenu(menu
);
1100 void wxDocManager::FileHistoryRemoveMenu(wxMenu
*menu
)
1103 m_fileHistory
->RemoveMenu(menu
);
1107 void wxDocManager::FileHistoryLoad(wxConfigBase
& config
)
1110 m_fileHistory
->Load(config
);
1113 void wxDocManager::FileHistorySave(wxConfigBase
& config
)
1116 m_fileHistory
->Save(config
);
1120 void wxDocManager::FileHistoryAddFilesToMenu(wxMenu
* menu
)
1123 m_fileHistory
->AddFilesToMenu(menu
);
1126 void wxDocManager::FileHistoryAddFilesToMenu()
1129 m_fileHistory
->AddFilesToMenu();
1132 int wxDocManager::GetNoHistoryFiles() const
1135 return m_fileHistory
->GetNoHistoryFiles();
1141 // Find out the document template via matching in the document file format
1142 // against that of the template
1143 wxDocTemplate
*wxDocManager::FindTemplateForPath(const wxString
& path
)
1145 wxDocTemplate
*theTemplate
= (wxDocTemplate
*) NULL
;
1147 // Find the template which this extension corresponds to
1149 for (i
= 0; i
< m_templates
.Number(); i
++)
1151 wxDocTemplate
*temp
= (wxDocTemplate
*)m_templates
.Nth(i
)->Data();
1152 if ( temp
->FileMatchesTemplate(path
) )
1161 // Prompts user to open a file, using file specs in templates.
1162 // How to implement in wxWindows? Must extend the file selector
1163 // dialog or implement own; OR match the extension to the
1164 // template extension.
1166 wxDocTemplate
*wxDocManager::SelectDocumentPath(wxDocTemplate
**templates
,
1170 int WXUNUSED(noTemplates
),
1173 long WXUNUSED(flags
),
1174 bool WXUNUSED(save
))
1176 // We can only have multiple filters in Windows
1181 for (i
= 0; i
< noTemplates
; i
++)
1183 if (templates
[i
]->IsVisible())
1185 // add a '|' to separate this filter from the previous one
1186 if ( !descrBuf
.IsEmpty() )
1187 descrBuf
<< _T('|');
1189 descrBuf
<< templates
[i
]->GetDescription()
1190 << _T(" (") << templates
[i
]->GetFileFilter() << _T(") |")
1191 << templates
[i
]->GetFileFilter();
1195 wxString descrBuf
= _T("*.*");
1198 int FilterIndex
= 0;
1199 wxString pathTmp
= wxFileSelectorEx(_("Select a file"),
1205 wxTheApp
->GetTopWindow());
1207 if (!pathTmp
.IsEmpty())
1210 wxString theExt
= FindExtension(path
);
1212 return (wxDocTemplate
*) NULL
;
1214 // This is dodgy in that we're selecting the template on the
1215 // basis of the file extension, which may not be a standard
1216 // one. We really want to know exactly which template was
1217 // chosen by using a more advanced file selector.
1218 wxDocTemplate
*theTemplate
= FindTemplateForPath(path
);
1220 theTemplate
= templates
[FilterIndex
];
1227 return (wxDocTemplate
*) NULL
;
1230 // In all other windowing systems, until we have more advanced
1231 // file selectors, we must select the document type (template) first, and
1232 // _then_ pop up the file selector.
1233 wxDocTemplate
*temp
= SelectDocumentType(templates
, noTemplates
);
1235 return (wxDocTemplate
*) NULL
;
1237 wxChar
*pathTmp
= wxFileSelector(_("Select a file"), _T(""), _T(""),
1238 temp
->GetDefaultExtension(),
1239 temp
->GetFileFilter(),
1240 0, wxTheApp
->GetTopWindow());
1248 return (wxDocTemplate
*) NULL
;
1252 wxDocTemplate
*wxDocManager::SelectDocumentType(wxDocTemplate
**templates
,
1255 wxChar
**strings
= new wxChar
*[noTemplates
];
1256 wxChar
**data
= new wxChar
*[noTemplates
];
1259 for (i
= 0; i
< noTemplates
; i
++)
1261 if (templates
[i
]->IsVisible())
1263 strings
[n
] = WXSTRINGCAST templates
[i
]->m_description
;
1264 data
[n
] = (wxChar
*)templates
[i
];
1272 return (wxDocTemplate
*) NULL
;
1276 wxDocTemplate
*temp
= (wxDocTemplate
*)data
[0];
1282 wxDocTemplate
*theTemplate
= (wxDocTemplate
*)wxGetSingleChoiceData(_("Select a document template"), _("Templates"), n
,
1289 wxDocTemplate
*wxDocManager::SelectViewType(wxDocTemplate
**templates
,
1292 wxChar
**strings
= new wxChar
*[noTemplates
];
1293 wxChar
**data
= new wxChar
*[noTemplates
];
1296 for (i
= 0; i
< noTemplates
; i
++)
1298 if (templates
[i
]->IsVisible() && (templates
[i
]->GetViewName() != _T("")))
1300 strings
[n
] = WXSTRINGCAST templates
[i
]->m_viewTypeName
;
1301 data
[n
] = (wxChar
*)templates
[i
];
1305 wxDocTemplate
*theTemplate
= (wxDocTemplate
*)wxGetSingleChoiceData(_("Select a document view"), _("Views"), n
,
1312 void wxDocManager::AssociateTemplate(wxDocTemplate
*temp
)
1314 if (!m_templates
.Member(temp
))
1315 m_templates
.Append(temp
);
1318 void wxDocManager::DisassociateTemplate(wxDocTemplate
*temp
)
1320 m_templates
.DeleteObject(temp
);
1323 // Add and remove a document from the manager's list
1324 void wxDocManager::AddDocument(wxDocument
*doc
)
1326 if (!m_docs
.Member(doc
))
1330 void wxDocManager::RemoveDocument(wxDocument
*doc
)
1332 m_docs
.DeleteObject(doc
);
1335 // Views or windows should inform the document manager
1336 // when a view is going in or out of focus
1337 void wxDocManager::ActivateView(wxView
*view
, bool activate
, bool WXUNUSED(deleting
))
1339 // If we're deactiving, and if we're not actually deleting the view, then
1340 // don't reset the current view because we may be going to
1341 // a window without a view.
1342 // WHAT DID I MEAN BY THAT EXACTLY?
1346 if (m_currentView == view)
1347 m_currentView = NULL;
1353 m_currentView
= view
;
1355 m_currentView
= (wxView
*) NULL
;
1359 // ----------------------------------------------------------------------------
1360 // Default document child frame
1361 // ----------------------------------------------------------------------------
1363 BEGIN_EVENT_TABLE(wxDocChildFrame
, wxFrame
)
1364 EVT_ACTIVATE(wxDocChildFrame::OnActivate
)
1365 EVT_CLOSE(wxDocChildFrame::OnCloseWindow
)
1368 wxDocChildFrame::wxDocChildFrame(wxDocument
*doc
,
1372 const wxString
& title
,
1376 const wxString
& name
)
1377 : wxFrame(frame
, id
, title
, pos
, size
, style
, name
)
1379 m_childDocument
= doc
;
1382 view
->SetFrame(this);
1385 wxDocChildFrame::~wxDocChildFrame()
1389 // Extend event processing to search the view's event table
1390 bool wxDocChildFrame::ProcessEvent(wxEvent
& event
)
1393 m_childView
->Activate(TRUE
);
1395 if ( !m_childView
|| ! m_childView
->ProcessEvent(event
) )
1397 // Only hand up to the parent if it's a menu command
1398 if (!event
.IsKindOf(CLASSINFO(wxCommandEvent
)) || !GetParent() || !GetParent()->ProcessEvent(event
))
1399 return wxEvtHandler::ProcessEvent(event
);
1407 void wxDocChildFrame::OnActivate(wxActivateEvent
& event
)
1409 wxFrame::OnActivate(event
);
1412 m_childView
->Activate(event
.GetActive());
1415 void wxDocChildFrame::OnCloseWindow(wxCloseEvent
& event
)
1420 if (!event
.CanVeto())
1421 ans
= TRUE
; // Must delete.
1423 ans
= m_childView
->Close(FALSE
); // FALSE means don't delete associated window
1427 m_childView
->Activate(FALSE
);
1429 m_childView
= (wxView
*) NULL
;
1430 m_childDocument
= (wxDocument
*) NULL
;
1441 // ----------------------------------------------------------------------------
1442 // Default parent frame
1443 // ----------------------------------------------------------------------------
1445 BEGIN_EVENT_TABLE(wxDocParentFrame
, wxFrame
)
1446 EVT_MENU(wxID_EXIT
, wxDocParentFrame::OnExit
)
1447 EVT_MENU_RANGE(wxID_FILE1
, wxID_FILE9
, wxDocParentFrame::OnMRUFile
)
1448 EVT_CLOSE(wxDocParentFrame::OnCloseWindow
)
1451 wxDocParentFrame::wxDocParentFrame(wxDocManager
*manager
,
1454 const wxString
& title
,
1458 const wxString
& name
)
1459 : wxFrame(frame
, id
, title
, pos
, size
, style
, name
)
1461 m_docManager
= manager
;
1464 void wxDocParentFrame::OnExit(wxCommandEvent
& WXUNUSED(event
))
1469 void wxDocParentFrame::OnMRUFile(wxCommandEvent
& event
)
1471 wxString
f(m_docManager
->GetHistoryFile(event
.GetSelection() - wxID_FILE1
));
1473 (void)m_docManager
->CreateDocument(f
, wxDOC_SILENT
);
1476 // Extend event processing to search the view's event table
1477 bool wxDocParentFrame::ProcessEvent(wxEvent
& event
)
1479 // Try the document manager, then do default processing
1480 if (!m_docManager
|| !m_docManager
->ProcessEvent(event
))
1481 return wxEvtHandler::ProcessEvent(event
);
1486 // Define the behaviour for the frame closing
1487 // - must delete all frames except for the main one.
1488 void wxDocParentFrame::OnCloseWindow(wxCloseEvent
& event
)
1490 if (m_docManager
->Clear(!event
.CanVeto()))
1498 #if wxUSE_PRINTING_ARCHITECTURE
1500 wxDocPrintout::wxDocPrintout(wxView
*view
, const wxString
& title
)
1501 : wxPrintout(WXSTRINGCAST title
)
1503 m_printoutView
= view
;
1506 bool wxDocPrintout::OnPrintPage(int WXUNUSED(page
))
1510 // Get the logical pixels per inch of screen and printer
1511 int ppiScreenX
, ppiScreenY
;
1512 GetPPIScreen(&ppiScreenX
, &ppiScreenY
);
1513 int ppiPrinterX
, ppiPrinterY
;
1514 GetPPIPrinter(&ppiPrinterX
, &ppiPrinterY
);
1516 // This scales the DC so that the printout roughly represents the
1517 // the screen scaling. The text point size _should_ be the right size
1518 // but in fact is too small for some reason. This is a detail that will
1519 // need to be addressed at some point but can be fudged for the
1521 float scale
= (float)((float)ppiPrinterX
/(float)ppiScreenX
);
1523 // Now we have to check in case our real page size is reduced
1524 // (e.g. because we're drawing to a print preview memory DC)
1525 int pageWidth
, pageHeight
;
1527 dc
->GetSize(&w
, &h
);
1528 GetPageSizePixels(&pageWidth
, &pageHeight
);
1530 // If printer pageWidth == current DC width, then this doesn't
1531 // change. But w might be the preview bitmap width, so scale down.
1532 float overallScale
= scale
* (float)(w
/(float)pageWidth
);
1533 dc
->SetUserScale(overallScale
, overallScale
);
1537 m_printoutView
->OnDraw(dc
);
1542 bool wxDocPrintout::HasPage(int pageNum
)
1544 return (pageNum
== 1);
1547 bool wxDocPrintout::OnBeginDocument(int startPage
, int endPage
)
1549 if (!wxPrintout::OnBeginDocument(startPage
, endPage
))
1555 void wxDocPrintout::GetPageInfo(int *minPage
, int *maxPage
, int *selPageFrom
, int *selPageTo
)
1563 #endif // wxUSE_PRINTING_ARCHITECTURE
1565 // ----------------------------------------------------------------------------
1566 // Command processing framework
1567 // ----------------------------------------------------------------------------
1569 wxCommand::wxCommand(bool canUndoIt
, const wxString
& name
)
1571 m_canUndo
= canUndoIt
;
1572 m_commandName
= name
;
1575 wxCommand::~wxCommand()
1579 // Command processor
1580 wxCommandProcessor::wxCommandProcessor(int maxCommands
)
1582 m_maxNoCommands
= maxCommands
;
1583 m_currentCommand
= (wxNode
*) NULL
;
1584 m_commandEditMenu
= (wxMenu
*) NULL
;
1587 wxCommandProcessor::~wxCommandProcessor()
1592 // Pass a command to the processor. The processor calls Do();
1593 // if successful, is appended to the command history unless
1594 // storeIt is FALSE.
1595 bool wxCommandProcessor::Submit(wxCommand
*command
, bool storeIt
)
1597 bool success
= command
->Do();
1598 if (success
&& storeIt
)
1600 if (m_commands
.Number() == m_maxNoCommands
)
1602 wxNode
*firstNode
= m_commands
.First();
1603 wxCommand
*firstCommand
= (wxCommand
*)firstNode
->Data();
1604 delete firstCommand
;
1608 // Correct a bug: we must chop off the current 'branch'
1609 // so that we're at the end of the command list.
1610 if (!m_currentCommand
)
1614 wxNode
*node
= m_currentCommand
->Next();
1617 wxNode
*next
= node
->Next();
1618 delete (wxCommand
*)node
->Data();
1624 m_commands
.Append(command
);
1625 m_currentCommand
= m_commands
.Last();
1631 bool wxCommandProcessor::Undo()
1633 if (m_currentCommand
)
1635 wxCommand
*command
= (wxCommand
*)m_currentCommand
->Data();
1636 if (command
->CanUndo())
1638 bool success
= command
->Undo();
1641 m_currentCommand
= m_currentCommand
->Previous();
1650 bool wxCommandProcessor::Redo()
1652 wxCommand
*redoCommand
= (wxCommand
*) NULL
;
1653 wxNode
*redoNode
= (wxNode
*) NULL
;
1654 if (m_currentCommand
&& m_currentCommand
->Next())
1656 redoCommand
= (wxCommand
*)m_currentCommand
->Next()->Data();
1657 redoNode
= m_currentCommand
->Next();
1661 if (m_commands
.Number() > 0)
1663 redoCommand
= (wxCommand
*)m_commands
.First()->Data();
1664 redoNode
= m_commands
.First();
1670 bool success
= redoCommand
->Do();
1673 m_currentCommand
= redoNode
;
1681 bool wxCommandProcessor::CanUndo() const
1683 if (m_currentCommand
)
1684 return ((wxCommand
*)m_currentCommand
->Data())->CanUndo();
1688 bool wxCommandProcessor::CanRedo() const
1690 if ((m_currentCommand
!= (wxNode
*) NULL
) && (m_currentCommand
->Next() == (wxNode
*) NULL
))
1693 if ((m_currentCommand
!= (wxNode
*) NULL
) && (m_currentCommand
->Next() != (wxNode
*) NULL
))
1696 if ((m_currentCommand
== (wxNode
*) NULL
) && (m_commands
.Number() > 0))
1702 void wxCommandProcessor::Initialize()
1704 m_currentCommand
= m_commands
.Last();
1708 void wxCommandProcessor::SetMenuStrings()
1710 if (m_commandEditMenu
)
1713 if (m_currentCommand
)
1715 wxCommand
*command
= (wxCommand
*)m_currentCommand
->Data();
1716 wxString
commandName(command
->GetName());
1717 if (commandName
== _T("")) commandName
= _("Unnamed command");
1718 bool canUndo
= command
->CanUndo();
1720 buf
= wxString(_("&Undo ")) + commandName
;
1722 buf
= wxString(_("Can't &Undo ")) + commandName
;
1724 m_commandEditMenu
->SetLabel(wxID_UNDO
, buf
);
1725 m_commandEditMenu
->Enable(wxID_UNDO
, canUndo
);
1727 // We can redo, if we're not at the end of the history.
1728 if (m_currentCommand
->Next())
1730 wxCommand
*redoCommand
= (wxCommand
*)m_currentCommand
->Next()->Data();
1731 wxString
redoCommandName(redoCommand
->GetName());
1732 if (redoCommandName
== _T("")) redoCommandName
= _("Unnamed command");
1733 buf
= wxString(_("&Redo ")) + redoCommandName
;
1734 m_commandEditMenu
->SetLabel(wxID_REDO
, buf
);
1735 m_commandEditMenu
->Enable(wxID_REDO
, TRUE
);
1739 m_commandEditMenu
->SetLabel(wxID_REDO
, _("&Redo"));
1740 m_commandEditMenu
->Enable(wxID_REDO
, FALSE
);
1745 m_commandEditMenu
->SetLabel(wxID_UNDO
, _("&Undo"));
1746 m_commandEditMenu
->Enable(wxID_UNDO
, FALSE
);
1748 if (m_commands
.Number() == 0)
1750 m_commandEditMenu
->SetLabel(wxID_REDO
, _("&Redo"));
1751 m_commandEditMenu
->Enable(wxID_REDO
, FALSE
);
1755 // currentCommand is NULL but there are commands: this means that
1756 // we've undone to the start of the list, but can redo the first.
1757 wxCommand
*redoCommand
= (wxCommand
*)m_commands
.First()->Data();
1758 wxString
redoCommandName(redoCommand
->GetName());
1759 if (redoCommandName
== _T("")) redoCommandName
= _("Unnamed command");
1760 buf
= wxString(_("&Redo ")) + redoCommandName
;
1761 m_commandEditMenu
->SetLabel(wxID_REDO
, buf
);
1762 m_commandEditMenu
->Enable(wxID_REDO
, TRUE
);
1768 void wxCommandProcessor::ClearCommands()
1770 wxNode
*node
= m_commands
.First();
1773 wxCommand
*command
= (wxCommand
*)node
->Data();
1776 node
= m_commands
.First();
1778 m_currentCommand
= (wxNode
*) NULL
;
1781 // ----------------------------------------------------------------------------
1782 // File history processor
1783 // ----------------------------------------------------------------------------
1785 wxFileHistory::wxFileHistory(int maxFiles
)
1787 m_fileMaxFiles
= maxFiles
;
1789 m_fileHistory
= new wxChar
*[m_fileMaxFiles
];
1792 wxFileHistory::~wxFileHistory()
1795 for (i
= 0; i
< m_fileHistoryN
; i
++)
1796 delete[] m_fileHistory
[i
];
1797 delete[] m_fileHistory
;
1800 // File history management
1801 void wxFileHistory::AddFileToHistory(const wxString
& file
)
1804 // Check we don't already have this file
1805 for (i
= 0; i
< m_fileHistoryN
; i
++)
1807 if (m_fileHistory
[i
] && wxString(m_fileHistory
[i
]) == file
)
1811 // Add to the project file history:
1812 // Move existing files (if any) down so we can insert file at beginning.
1814 // First delete filename that has popped off the end of the array (if any)
1815 if (m_fileHistoryN
== m_fileMaxFiles
)
1817 delete[] m_fileHistory
[m_fileMaxFiles
-1];
1818 m_fileHistory
[m_fileMaxFiles
-1] = (wxChar
*) NULL
;
1820 if (m_fileHistoryN
< m_fileMaxFiles
)
1822 wxNode
* node
= m_fileMenus
.First();
1825 wxMenu
* menu
= (wxMenu
*) node
->Data();
1826 if (m_fileHistoryN
== 0)
1827 menu
->AppendSeparator();
1828 menu
->Append(wxID_FILE1
+m_fileHistoryN
, _("[EMPTY]"));
1829 node
= node
->Next();
1833 // Shuffle filenames down
1834 for (i
= (m_fileHistoryN
-1); i
> 0; i
--)
1836 m_fileHistory
[i
] = m_fileHistory
[i
-1];
1838 m_fileHistory
[0] = copystring(file
);
1840 for (i
= 0; i
< m_fileHistoryN
; i
++)
1841 if (m_fileHistory
[i
])
1844 buf
.Printf(_T("&%d %s"), i
+1, m_fileHistory
[i
]);
1845 wxNode
* node
= m_fileMenus
.First();
1848 wxMenu
* menu
= (wxMenu
*) node
->Data();
1849 menu
->SetLabel(wxID_FILE1
+i
, buf
);
1850 node
= node
->Next();
1855 wxString
wxFileHistory::GetHistoryFile(int i
) const
1857 if (i
< m_fileHistoryN
)
1858 return wxString(m_fileHistory
[i
]);
1860 return wxString("");
1863 void wxFileHistory::UseMenu(wxMenu
*menu
)
1865 if (!m_fileMenus
.Member(menu
))
1866 m_fileMenus
.Append(menu
);
1869 void wxFileHistory::RemoveMenu(wxMenu
*menu
)
1871 m_fileMenus
.DeleteObject(menu
);
1875 void wxFileHistory::Load(wxConfigBase
& config
)
1879 buf
.Printf(_T("file%d"), m_fileHistoryN
+1);
1880 wxString historyFile
;
1881 while ((m_fileHistoryN
<= m_fileMaxFiles
) && config
.Read(buf
, &historyFile
) && (historyFile
!= _T("")))
1883 m_fileHistory
[m_fileHistoryN
] = copystring((const wxChar
*) historyFile
);
1885 buf
.Printf(_T("file%d"), m_fileHistoryN
+1);
1891 void wxFileHistory::Save(wxConfigBase
& config
)
1894 for (i
= 0; i
< m_fileHistoryN
; i
++)
1897 buf
.Printf(_T("file%d"), i
+1);
1898 config
.Write(buf
, wxString(m_fileHistory
[i
]));
1901 #endif // wxUSE_CONFIG
1903 void wxFileHistory::AddFilesToMenu()
1905 if (m_fileHistoryN
> 0)
1907 wxNode
* node
= m_fileMenus
.First();
1910 wxMenu
* menu
= (wxMenu
*) node
->Data();
1911 menu
->AppendSeparator();
1913 for (i
= 0; i
< m_fileHistoryN
; i
++)
1915 if (m_fileHistory
[i
])
1918 buf
.Printf(_T("&%d %s"), i
+1, m_fileHistory
[i
]);
1919 menu
->Append(wxID_FILE1
+i
, buf
);
1922 node
= node
->Next();
1927 void wxFileHistory::AddFilesToMenu(wxMenu
* menu
)
1929 if (m_fileHistoryN
> 0)
1931 menu
->AppendSeparator();
1933 for (i
= 0; i
< m_fileHistoryN
; i
++)
1935 if (m_fileHistory
[i
])
1938 buf
.Printf(_T("&%d %s"), i
+1, m_fileHistory
[i
]);
1939 menu
->Append(wxID_FILE1
+i
, buf
);
1945 // ----------------------------------------------------------------------------
1946 // Permits compatibility with existing file formats and functions that
1947 // manipulate files directly
1948 // ----------------------------------------------------------------------------
1950 bool wxTransferFileToStream(const wxString
& filename
, ostream
& stream
)
1955 if ((fd1
= fopen (filename
.fn_str(), "rb")) == NULL
)
1958 while ((ch
= getc (fd1
)) != EOF
)
1959 stream
<< (unsigned char)ch
;
1965 bool wxTransferStreamToFile(istream
& stream
, const wxString
& filename
)
1970 if ((fd1
= fopen (filename
.fn_str(), "wb")) == NULL
)
1975 while (!stream
.eof())
1985 #endif // wxUSE_DOC_VIEW_ARCHITECTURE