X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/52b9ca21ac6c53d841028542771c839590a63db1..490da436c859b499a7726acd06af02304b0d925f:/src/common/docview.cpp diff --git a/src/common/docview.cpp b/src/common/docview.cpp index 02fdca8fe4..c368a8ee52 100644 --- a/src/common/docview.cpp +++ b/src/common/docview.cpp @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: docview.cpp +// Name: src/common/docview.cpp // Purpose: Document/view classes // Author: Julian Smart // Modified by: @@ -57,6 +57,7 @@ #include "wx/docview.h" #include "wx/confbase.h" #include "wx/file.h" +#include "wx/cmdproc.h" #include #include @@ -76,20 +77,18 @@ // wxWindows macros // ---------------------------------------------------------------------------- - IMPLEMENT_ABSTRACT_CLASS(wxDocument, wxEvtHandler) - IMPLEMENT_ABSTRACT_CLASS(wxView, wxEvtHandler) - IMPLEMENT_ABSTRACT_CLASS(wxDocTemplate, wxObject) - IMPLEMENT_DYNAMIC_CLASS(wxDocManager, wxEvtHandler) - IMPLEMENT_CLASS(wxDocChildFrame, wxFrame) - IMPLEMENT_CLASS(wxDocParentFrame, wxFrame) +IMPLEMENT_ABSTRACT_CLASS(wxDocument, wxEvtHandler) +IMPLEMENT_ABSTRACT_CLASS(wxView, wxEvtHandler) +IMPLEMENT_ABSTRACT_CLASS(wxDocTemplate, wxObject) +IMPLEMENT_DYNAMIC_CLASS(wxDocManager, wxEvtHandler) +IMPLEMENT_CLASS(wxDocChildFrame, wxFrame) +IMPLEMENT_CLASS(wxDocParentFrame, wxFrame) - #if wxUSE_PRINTING_ARCHITECTURE - IMPLEMENT_DYNAMIC_CLASS(wxDocPrintout, wxPrintout) - #endif +#if wxUSE_PRINTING_ARCHITECTURE + IMPLEMENT_DYNAMIC_CLASS(wxDocPrintout, wxPrintout) +#endif - IMPLEMENT_CLASS(wxCommand, wxObject) - IMPLEMENT_DYNAMIC_CLASS(wxCommandProcessor, wxObject) - IMPLEMENT_DYNAMIC_CLASS(wxFileHistory, wxObject) +IMPLEMENT_DYNAMIC_CLASS(wxFileHistory, wxObject) // ---------------------------------------------------------------------------- // function prototypes @@ -228,16 +227,13 @@ bool wxDocument::OnNewDocument() bool wxDocument::Save() { - bool ret = FALSE; + if (!IsModified() && m_savedYet) + return TRUE; - if (!IsModified()) return TRUE; - if (m_documentFile == wxT("") || !m_savedYet) - ret = SaveAs(); - else - ret = OnSaveDocument(m_documentFile); - if ( ret ) - SetDocumentSaved(TRUE); - return ret; + if ( m_documentFile.empty() || !m_savedYet ) + return SaveAs(); + + return OnSaveDocument(m_documentFile); } bool wxDocument::SaveAs() @@ -248,7 +244,7 @@ bool wxDocument::SaveAs() wxString tmp = wxFileSelector(_("Save as"), docTemplate->GetDirectory(), - GetFilename(), + wxFileNameFromPath(GetFilename()), docTemplate->GetDefaultExtension(), docTemplate->GetFileFilter(), wxSAVE | wxOVERWRITE_PROMPT, @@ -296,7 +292,7 @@ bool wxDocument::OnSaveDocument(const wxString& file) msgTitle = wxString(_("File error")); #if wxUSE_STD_IOSTREAM - ofstream store(wxString(file.fn_str()).mb_str()); + wxSTD ofstream store(wxString(file.fn_str()).mb_str()); if (store.fail() || store.bad()) #else wxFileOutputStream store(wxString(file.fn_str())); @@ -317,6 +313,7 @@ bool wxDocument::OnSaveDocument(const wxString& file) } Modify(FALSE); SetFilename(file); + SetDocumentSaved(TRUE); return TRUE; } @@ -332,7 +329,7 @@ bool wxDocument::OnOpenDocument(const wxString& file) msgTitle = wxString(_("File error")); #if wxUSE_STD_IOSTREAM - ifstream store(wxString(file.fn_str()).mb_str()); + wxSTD ifstream store(wxString(file.fn_str()).mb_str()); if (store.fail() || store.bad()) #else wxFileInputStream store(wxString(file.fn_str())); @@ -344,7 +341,8 @@ bool wxDocument::OnOpenDocument(const wxString& file) return FALSE; } #if wxUSE_STD_IOSTREAM - if (!LoadObject(store)) + LoadObject(store); + if ( !store && !store.eof() ) #else int res = LoadObject(store).LastError(); if ((res != wxSTREAM_NOERROR) && @@ -365,7 +363,7 @@ bool wxDocument::OnOpenDocument(const wxString& file) } #if wxUSE_STD_IOSTREAM -istream& wxDocument::LoadObject(istream& stream) +wxSTD istream& wxDocument::LoadObject(wxSTD istream& stream) #else wxInputStream& wxDocument::LoadObject(wxInputStream& stream) #endif @@ -374,7 +372,7 @@ wxInputStream& wxDocument::LoadObject(wxInputStream& stream) } #if wxUSE_STD_IOSTREAM -ostream& wxDocument::SaveObject(ostream& stream) +wxSTD ostream& wxDocument::SaveObject(wxSTD ostream& stream) #else wxOutputStream& wxDocument::SaveObject(wxOutputStream& stream) #endif @@ -596,7 +594,7 @@ bool wxView::Close(bool deleteWindow) void wxView::Activate(bool activate) { - if (GetDocumentManager()) + if (GetDocument() && GetDocumentManager()) { OnActivateView(activate, this, GetDocumentManager()->GetCurrentView()); GetDocumentManager()->ActivateView(this, activate); @@ -701,6 +699,7 @@ bool wxDocTemplate::FileMatchesTemplate(const wxString& path) BEGIN_EVENT_TABLE(wxDocManager, wxEvtHandler) EVT_MENU(wxID_OPEN, wxDocManager::OnFileOpen) EVT_MENU(wxID_CLOSE, wxDocManager::OnFileClose) + EVT_MENU(wxID_CLOSE_ALL, wxDocManager::OnFileCloseAll) EVT_MENU(wxID_REVERT, wxDocManager::OnFileRevert) EVT_MENU(wxID_NEW, wxDocManager::OnFileNew) EVT_MENU(wxID_SAVE, wxDocManager::OnFileSave) @@ -710,6 +709,7 @@ BEGIN_EVENT_TABLE(wxDocManager, wxEvtHandler) EVT_UPDATE_UI(wxID_OPEN, wxDocManager::OnUpdateFileOpen) EVT_UPDATE_UI(wxID_CLOSE, wxDocManager::OnUpdateFileClose) + EVT_UPDATE_UI(wxID_CLOSE_ALL, wxDocManager::OnUpdateFileClose) EVT_UPDATE_UI(wxID_REVERT, wxDocManager::OnUpdateFileRevert) EVT_UPDATE_UI(wxID_NEW, wxDocManager::OnUpdateFileNew) EVT_UPDATE_UI(wxID_SAVE, wxDocManager::OnUpdateFileSave) @@ -750,7 +750,7 @@ wxDocManager::~wxDocManager() sm_docManager = (wxDocManager*) NULL; } -bool wxDocManager::Clear(bool force) +bool wxDocManager::CloseDocuments(bool force) { wxNode *node = m_docs.First(); while (node) @@ -774,7 +774,15 @@ bool wxDocManager::Clear(bool force) // delete another. node = next; } - node = m_templates.First(); + return TRUE; +} + +bool wxDocManager::Clear(bool force) +{ + if (!CloseDocuments(force)) + return FALSE; + + wxNode *node = m_templates.First(); while (node) { wxDocTemplate *templ = (wxDocTemplate*) node->Data(); @@ -809,6 +817,11 @@ void wxDocManager::OnFileClose(wxCommandEvent& WXUNUSED(event)) } } +void wxDocManager::OnFileCloseAll(wxCommandEvent& WXUNUSED(event)) +{ + CloseDocuments(FALSE); +} + void wxDocManager::OnFileNew(wxCommandEvent& WXUNUSED(event)) { CreateDocument(wxString(""), wxDOC_NEW); @@ -948,7 +961,7 @@ void wxDocManager::OnUpdateFileNew(wxUpdateUIEvent& event) void wxDocManager::OnUpdateFileSave(wxUpdateUIEvent& event) { wxDocument *doc = GetCurrentDocument(); - event.Enable( (doc != (wxDocument*) NULL) ); + event.Enable( doc && doc->IsModified() ); } void wxDocManager::OnUpdateFileSaveAs(wxUpdateUIEvent& event) @@ -961,12 +974,16 @@ void wxDocManager::OnUpdateUndo(wxUpdateUIEvent& event) { wxDocument *doc = GetCurrentDocument(); event.Enable( (doc && doc->GetCommandProcessor() && doc->GetCommandProcessor()->CanUndo()) ); + if (doc && doc->GetCommandProcessor()) + doc->GetCommandProcessor()->SetMenuStrings(); } void wxDocManager::OnUpdateRedo(wxUpdateUIEvent& event) { wxDocument *doc = GetCurrentDocument(); event.Enable( (doc && doc->GetCommandProcessor() && doc->GetCommandProcessor()->CanRedo()) ); + if (doc && doc->GetCommandProcessor()) + doc->GetCommandProcessor()->SetMenuStrings(); } void wxDocManager::OnUpdatePrint(wxUpdateUIEvent& event) @@ -1046,7 +1063,10 @@ wxDocument *wxDocManager::CreateDocument(const wxString& path, long flags) delete doc; } else + { + delete[] templates; return (wxDocument *) NULL; + } } // New document: user chooses a template, unless there's only one. @@ -1176,8 +1196,9 @@ bool wxDocManager::FlushDoc(wxDocument *WXUNUSED(doc)) wxDocument *wxDocManager::GetCurrentDocument() const { - if (m_currentView) - return m_currentView->GetDocument(); + wxView *view = GetCurrentView(); + if (view) + return view->GetDocument(); else return (wxDocument *) NULL; } @@ -1441,15 +1462,47 @@ wxDocTemplate *wxDocManager::SelectDocumentType(wxDocTemplate **templates, wxDocTemplate **data = new wxDocTemplate *[noTemplates]; int i; int n = 0; - for (i = 0; i < noTemplates; i++) - { - if (templates[i]->IsVisible()) - { - strings.Add(templates[i]->m_description); - data[n] = templates[i]; - n ++; - } - } + + for (i = 0; i < noTemplates; i++) + { + if (templates[i]->IsVisible()) + { + int j; + bool want = TRUE; + for (j = 0; j < n; j++) + { + //filter out NOT unique documents + view combinations + if ( templates[i]->m_docTypeName == data[j]->m_docTypeName && + templates[i]->m_viewTypeName == data[j]->m_viewTypeName + ) + want = FALSE; + } + + if ( want ) + { + strings.Add(templates[i]->m_description); + + data[n] = templates[i]; + n ++; + } + } + } // for + + if (sort) + { + // Yes, this will be slow, but template lists + // are typically short. + int j; + n = strings.Count(); + for (i = 0; i < n; i++) + { + for (j = 0; j < noTemplates; j++) + { + if (strings[i] == templates[j]->m_description) + data[i] = templates[j]; + } + } + } wxDocTemplate *theTemplate; @@ -1489,17 +1542,46 @@ wxDocTemplate *wxDocManager::SelectViewType(wxDocTemplate **templates, wxDocTemplate **data = new wxDocTemplate *[noTemplates]; int i; int n = 0; + for (i = 0; i < noTemplates; i++) { wxDocTemplate *templ = templates[i]; if ( templ->IsVisible() && !templ->GetViewName().empty() ) { - strings.Add(templ->m_viewTypeName); - data[n] = templ; - n ++; + int j; + bool want = TRUE; + for (j = 0; j < n; j++) + { + //filter out NOT unique views + if ( templates[i]->m_viewTypeName == data[j]->m_viewTypeName ) + want = FALSE; + } + + if ( want ) + { + strings.Add(templ->m_viewTypeName); + data[n] = templ; + n ++; + } } } + if (sort) + { + // Yes, this will be slow, but template lists + // are typically short. + int j; + n = strings.Count(); + for (i = 0; i < n; i++) + { + for (j = 0; j < noTemplates; j++) + { + if (strings[i] == templates[j]->m_viewTypeName) + data[i] = templates[j]; + } + } + } + wxDocTemplate *theTemplate; // the same logic as above @@ -1704,7 +1786,7 @@ void wxDocParentFrame::OnMRUFile(wxCommandEvent& event) // about it m_docManager->RemoveFileFromHistory(n); - wxLogError(_("The file '%s' doesn't exist and couldn't be opened.\nIt has been also removed from the MRU files list."), + wxLogError(_("The file '%s' doesn't exist and couldn't be opened.\nIt has been removed from the most recently used files list."), filename.c_str()); } } @@ -1799,224 +1881,6 @@ void wxDocPrintout::GetPageInfo(int *minPage, int *maxPage, int *selPageFrom, in #endif // wxUSE_PRINTING_ARCHITECTURE -// ---------------------------------------------------------------------------- -// Command processing framework -// ---------------------------------------------------------------------------- - -wxCommand::wxCommand(bool canUndoIt, const wxString& name) -{ - m_canUndo = canUndoIt; - m_commandName = name; -} - -wxCommand::~wxCommand() -{ -} - -// Command processor -wxCommandProcessor::wxCommandProcessor(int maxCommands) -{ - m_maxNoCommands = maxCommands; - m_currentCommand = (wxNode *) NULL; - m_commandEditMenu = (wxMenu *) NULL; - m_undoAccelerator = wxT("\tCtrl+Z"); - m_redoAccelerator = wxT("\tCtrl+Y"); -} - -wxCommandProcessor::~wxCommandProcessor() -{ - ClearCommands(); -} - -// Pass a command to the processor. The processor calls Do(); -// if successful, is appended to the command history unless -// storeIt is FALSE. -bool wxCommandProcessor::Submit(wxCommand *command, bool storeIt) -{ - bool success = command->Do(); - if (success && storeIt) - { - if (m_commands.Number() == m_maxNoCommands) - { - wxNode *firstNode = m_commands.First(); - wxCommand *firstCommand = (wxCommand *)firstNode->Data(); - delete firstCommand; - delete firstNode; - } - - // Correct a bug: we must chop off the current 'branch' - // so that we're at the end of the command list. - if (!m_currentCommand) - ClearCommands(); - else - { - wxNode *node = m_currentCommand->Next(); - while (node) - { - wxNode *next = node->Next(); - delete (wxCommand *)node->Data(); - delete node; - node = next; - } - } - - m_commands.Append(command); - m_currentCommand = m_commands.Last(); - SetMenuStrings(); - } - return success; -} - -bool wxCommandProcessor::Undo() -{ - if (m_currentCommand) - { - wxCommand *command = (wxCommand *)m_currentCommand->Data(); - if (command->CanUndo()) - { - bool success = command->Undo(); - if (success) - { - m_currentCommand = m_currentCommand->Previous(); - SetMenuStrings(); - return TRUE; - } - } - } - return FALSE; -} - -bool wxCommandProcessor::Redo() -{ - wxCommand *redoCommand = (wxCommand *) NULL; - wxNode *redoNode = (wxNode *) NULL; - if (m_currentCommand && m_currentCommand->Next()) - { - redoCommand = (wxCommand *)m_currentCommand->Next()->Data(); - redoNode = m_currentCommand->Next(); - } - else - { - if (m_commands.Number() > 0) - { - redoCommand = (wxCommand *)m_commands.First()->Data(); - redoNode = m_commands.First(); - } - } - - if (redoCommand) - { - bool success = redoCommand->Do(); - if (success) - { - m_currentCommand = redoNode; - SetMenuStrings(); - return TRUE; - } - } - return FALSE; -} - -bool wxCommandProcessor::CanUndo() const -{ - if (m_currentCommand) - return ((wxCommand *)m_currentCommand->Data())->CanUndo(); - return FALSE; -} - -bool wxCommandProcessor::CanRedo() const -{ - if ((m_currentCommand != (wxNode*) NULL) && (m_currentCommand->Next() == (wxNode*) NULL)) - return FALSE; - - if ((m_currentCommand != (wxNode*) NULL) && (m_currentCommand->Next() != (wxNode*) NULL)) - return TRUE; - - if ((m_currentCommand == (wxNode*) NULL) && (m_commands.Number() > 0)) - return TRUE; - - return FALSE; -} - -void wxCommandProcessor::Initialize() -{ - m_currentCommand = m_commands.Last(); - SetMenuStrings(); -} - -void wxCommandProcessor::SetMenuStrings() -{ - if (m_commandEditMenu) - { - wxString buf; - if (m_currentCommand) - { - wxCommand *command = (wxCommand *)m_currentCommand->Data(); - wxString commandName(command->GetName()); - if (commandName == wxT("")) commandName = _("Unnamed command"); - bool canUndo = command->CanUndo(); - if (canUndo) - buf = wxString(_("&Undo ")) + commandName + m_undoAccelerator; - else - buf = wxString(_("Can't &Undo ")) + commandName + m_undoAccelerator; - - m_commandEditMenu->SetLabel(wxID_UNDO, buf); - m_commandEditMenu->Enable(wxID_UNDO, canUndo); - - // We can redo, if we're not at the end of the history. - if (m_currentCommand->Next()) - { - wxCommand *redoCommand = (wxCommand *)m_currentCommand->Next()->Data(); - wxString redoCommandName(redoCommand->GetName()); - if (redoCommandName == wxT("")) redoCommandName = _("Unnamed command"); - buf = wxString(_("&Redo ")) + redoCommandName + m_redoAccelerator; - m_commandEditMenu->SetLabel(wxID_REDO, buf); - m_commandEditMenu->Enable(wxID_REDO, TRUE); - } - else - { - m_commandEditMenu->SetLabel(wxID_REDO, _("&Redo") + m_redoAccelerator); - m_commandEditMenu->Enable(wxID_REDO, FALSE); - } - } - else - { - m_commandEditMenu->SetLabel(wxID_UNDO, _("&Undo") + m_undoAccelerator); - m_commandEditMenu->Enable(wxID_UNDO, FALSE); - - if (m_commands.Number() == 0) - { - m_commandEditMenu->SetLabel(wxID_REDO, _("&Redo") + m_redoAccelerator); - m_commandEditMenu->Enable(wxID_REDO, FALSE); - } - else - { - // currentCommand is NULL but there are commands: this means that - // we've undone to the start of the list, but can redo the first. - wxCommand *redoCommand = (wxCommand *)m_commands.First()->Data(); - wxString redoCommandName(redoCommand->GetName()); - if (redoCommandName == wxT("")) redoCommandName = _("Unnamed command"); - buf = wxString(_("&Redo ")) + redoCommandName + m_redoAccelerator; - m_commandEditMenu->SetLabel(wxID_REDO, buf); - m_commandEditMenu->Enable(wxID_REDO, TRUE); - } - } - } -} - -void wxCommandProcessor::ClearCommands() -{ - wxNode *node = m_commands.First(); - while (node) - { - wxCommand *command = (wxCommand *)node->Data(); - delete command; - delete node; - node = m_commands.First(); - } - m_currentCommand = (wxNode *) NULL; -} - // ---------------------------------------------------------------------------- // File history processor // ---------------------------------------------------------------------------- @@ -2124,11 +1988,6 @@ void wxFileHistory::RemoveFileFromHistory(int i) wxCHECK_RET( i < m_fileHistoryN, wxT("invalid index in wxFileHistory::RemoveFileFromHistory") ); - wxNode* node = m_fileMenus.First(); - while ( node ) - { - wxMenu* menu = (wxMenu*) node->Data(); - // delete the element from the array (could use memmove() too...) delete [] m_fileHistory[i]; @@ -2138,6 +1997,12 @@ void wxFileHistory::RemoveFileFromHistory(int i) m_fileHistory[j] = m_fileHistory[j + 1]; } + wxNode* node = m_fileMenus.First(); + while ( node ) + { + wxMenu* menu = (wxMenu*) node->Data(); + + // shuffle filenames up wxString buf; for ( j = i; j < m_fileHistoryN - 1; j++ ) @@ -2149,6 +2014,7 @@ void wxFileHistory::RemoveFileFromHistory(int i) node = node->Next(); // delete the last menu item which is unused now + if (menu->FindItem(wxID_FILE1 + m_fileHistoryN - 1)) menu->Delete(wxID_FILE1 + m_fileHistoryN - 1); // delete the last separator too if no more files are left @@ -2274,7 +2140,7 @@ void wxFileHistory::AddFilesToMenu(wxMenu* menu) // ---------------------------------------------------------------------------- #if wxUSE_STD_IOSTREAM -bool wxTransferFileToStream(const wxString& filename, ostream& stream) +bool wxTransferFileToStream(const wxString& filename, wxSTD ostream& stream) { FILE *fd1; int ch; @@ -2289,7 +2155,7 @@ bool wxTransferFileToStream(const wxString& filename, ostream& stream) return TRUE; } -bool wxTransferStreamToFile(istream& stream, const wxString& filename) +bool wxTransferStreamToFile(wxSTD istream& stream, const wxString& filename) { FILE *fd1; int ch;