docview.cpp
来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C++ 代码 · 共 2,347 行 · 第 1/5 页
CPP
2,347 行
/////////////////////////////////////////////////////////////////////////////
// Name: src/common/docview.cpp
// Purpose: Document/view classes
// Author: Julian Smart
// Modified by:
// Created: 01/02/97
// RCS-ID: $Id: docview.cpp,v 1.136.2.2 2006/02/21 19:51:32 ABX Exp $
// Copyright: (c) Julian Smart
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// ============================================================================
// declarations
// ============================================================================
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
#pragma implementation "docview.h"
#endif
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#if wxUSE_DOC_VIEW_ARCHITECTURE
#ifndef WX_PRECOMP
#include "wx/string.h"
#include "wx/utils.h"
#include "wx/app.h"
#include "wx/dc.h"
#include "wx/dialog.h"
#include "wx/menu.h"
#include "wx/list.h"
#include "wx/filedlg.h"
#include "wx/intl.h"
#include "wx/log.h"
#endif
#include "wx/ffile.h"
#ifdef __WXMAC__
#include "wx/filename.h"
#endif
#ifdef __WXGTK__
#include "wx/mdi.h"
#endif
#if wxUSE_PRINTING_ARCHITECTURE
#include "wx/prntbase.h"
#include "wx/printdlg.h"
#endif
#include "wx/msgdlg.h"
#include "wx/choicdlg.h"
#include "wx/docview.h"
#include "wx/confbase.h"
#include "wx/file.h"
#include "wx/cmdproc.h"
#include "wx/tokenzr.h"
#include <stdio.h>
#include <string.h>
#if wxUSE_STD_IOSTREAM
#include "wx/ioswrap.h"
#if wxUSE_IOSTREAMH
#include <fstream.h>
#else
#include <fstream>
#endif
#else
#include "wx/wfstream.h"
#endif
// ----------------------------------------------------------------------------
// wxWidgets 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)
#if wxUSE_PRINTING_ARCHITECTURE
IMPLEMENT_DYNAMIC_CLASS(wxDocPrintout, wxPrintout)
#endif
IMPLEMENT_DYNAMIC_CLASS(wxFileHistory, wxObject)
// ----------------------------------------------------------------------------
// function prototypes
// ----------------------------------------------------------------------------
static inline wxString FindExtension(const wxChar *path);
static wxWindow* wxFindSuitableParent(void);
// ----------------------------------------------------------------------------
// local constants
// ----------------------------------------------------------------------------
static const wxChar *s_MRUEntryFormat = wxT("&%d %s");
// ============================================================================
// implementation
// ============================================================================
// ----------------------------------------------------------------------------
// local functions
// ----------------------------------------------------------------------------
static wxString FindExtension(const wxChar *path)
{
wxString ext;
wxSplitPath(path, NULL, NULL, &ext);
// VZ: extensions are considered not case sensitive - is this really a good
// idea?
return ext.MakeLower();
}
// ----------------------------------------------------------------------------
// Definition of wxDocument
// ----------------------------------------------------------------------------
wxDocument::wxDocument(wxDocument *parent)
{
m_documentModified = false;
m_documentParent = parent;
m_documentTemplate = (wxDocTemplate *) NULL;
m_commandProcessor = (wxCommandProcessor*) NULL;
m_savedYet = false;
}
bool wxDocument::DeleteContents()
{
return true;
}
wxDocument::~wxDocument()
{
DeleteContents();
if (m_commandProcessor)
delete m_commandProcessor;
if (GetDocumentManager())
GetDocumentManager()->RemoveDocument(this);
// Not safe to do here, since it'll invoke virtual view functions
// expecting to see valid derived objects: and by the time we get here,
// we've called destructors higher up.
//DeleteAllViews();
}
bool wxDocument::Close()
{
if (OnSaveModified())
return OnCloseDocument();
else
return false;
}
bool wxDocument::OnCloseDocument()
{
// Tell all views that we're about to close
NotifyClosing();
DeleteContents();
Modify(false);
return true;
}
// Note that this implicitly deletes the document when the last view is
// deleted.
bool wxDocument::DeleteAllViews()
{
wxDocManager* manager = GetDocumentManager();
// first check if all views agree to be closed
const wxList::iterator end = m_documentViews.end();
for ( wxList::iterator i = m_documentViews.begin(); i != end; ++i )
{
wxView *view = (wxView *)*i;
if ( !view->Close() )
return false;
}
// all views agreed to close, now do close them
if ( m_documentViews.empty() )
{
// normally the document would be implicitly deleted when the last view
// is, but if don't have any views, do it here instead
if ( manager && manager->GetDocuments().Member(this) )
delete this;
}
else // have views
{
// as we delete elements we iterate over, don't use the usual "from
// begin to end" loop
for ( ;; )
{
wxView *view = (wxView *)*m_documentViews.begin();
bool isLastOne = m_documentViews.size() == 1;
// this always deletes the node implicitly and if this is the last
// view also deletes this object itself (also implicitly, great),
// so we can't test for m_documentViews.empty() after calling this!
delete view;
if ( isLastOne )
break;
}
}
return true;
}
wxView *wxDocument::GetFirstView() const
{
if (m_documentViews.GetCount() == 0)
return (wxView *) NULL;
return (wxView *)m_documentViews.GetFirst()->GetData();
}
wxDocManager *wxDocument::GetDocumentManager() const
{
return (m_documentTemplate ? m_documentTemplate->GetDocumentManager() : (wxDocManager*) NULL);
}
bool wxDocument::OnNewDocument()
{
if (!OnSaveModified())
return false;
if (OnCloseDocument()==false) return false;
DeleteContents();
Modify(false);
SetDocumentSaved(false);
wxString name;
GetDocumentManager()->MakeDefaultName(name);
SetTitle(name);
SetFilename(name, true);
return true;
}
bool wxDocument::Save()
{
if (!IsModified() && m_savedYet)
return true;
if ( m_documentFile.empty() || !m_savedYet )
return SaveAs();
return OnSaveDocument(m_documentFile);
}
bool wxDocument::SaveAs()
{
wxDocTemplate *docTemplate = GetDocumentTemplate();
if (!docTemplate)
return false;
#if defined(__WXMSW__) || defined(__WXGTK__) || defined(__WXMAC__)
wxString filter = docTemplate->GetDescription() + wxT(" (") + docTemplate->GetFileFilter() + wxT(")|") + docTemplate->GetFileFilter();
// Now see if there are some other template with identical view and document
// classes, whose filters may also be used.
if (docTemplate->GetViewClassInfo() && docTemplate->GetDocClassInfo())
{
wxList::compatibility_iterator node = wxDocManager::GetDocumentManager()->GetTemplates().GetFirst();
while (node)
{
wxDocTemplate *t = (wxDocTemplate*) node->GetData();
if (t->IsVisible() && t != docTemplate &&
t->GetViewClassInfo() == docTemplate->GetViewClassInfo() &&
t->GetDocClassInfo() == docTemplate->GetDocClassInfo())
{
// add a '|' to separate this filter from the previous one
if ( !filter.empty() )
filter << wxT('|');
filter << t->GetDescription() << wxT(" (") << t->GetFileFilter() << wxT(") |")
<< t->GetFileFilter();
}
node = node->GetNext();
}
}
#else
wxString filter = docTemplate->GetFileFilter() ;
#endif
wxString tmp = wxFileSelector(_("Save as"),
docTemplate->GetDirectory(),
wxFileNameFromPath(GetFilename()),
docTemplate->GetDefaultExtension(),
filter,
wxSAVE | wxOVERWRITE_PROMPT,
GetDocumentWindow());
if (tmp.empty())
return false;
wxString fileName(tmp);
wxString path, name, ext;
wxSplitPath(fileName, & path, & name, & ext);
if (ext.empty())
{
fileName += wxT(".");
fileName += docTemplate->GetDefaultExtension();
}
SetFilename(fileName);
SetTitle(wxFileNameFromPath(fileName));
// Notify the views that the filename has changed
wxList::compatibility_iterator node = m_documentViews.GetFirst();
while (node)
{
wxView *view = (wxView *)node->GetData();
view->OnChangeFilename();
node = node->GetNext();
}
// Files that were not saved correctly are not added to the FileHistory.
if (!OnSaveDocument(m_documentFile))
return false;
// A file that doesn't use the default extension of its document template cannot be opened
// via the FileHistory, so we do not add it.
if (docTemplate->FileMatchesTemplate(fileName))
{
GetDocumentManager()->AddFileToHistory(fileName);
}
else
{
// The user will probably not be able to open the file again, so
// we could warn about the wrong file-extension here.
}
return true;
}
bool wxDocument::OnSaveDocument(const wxString& file)
{
if ( !file )
return false;
if ( !DoSaveDocument(file) )
return false;
Modify(false);
SetFilename(file);
SetDocumentSaved(true);
#ifdef __WXMAC__
wxFileName fn(file) ;
fn.MacSetDefaultTypeAndCreator() ;
#endif
return true;
}
bool wxDocument::OnOpenDocument(const wxString& file)
{
if (!OnSaveModified())
return false;
if ( !DoOpenDocument(file) )
return false;
SetFilename(file, true);
Modify(false);
m_savedYet = true;
UpdateAllViews();
return true;
}
#if wxUSE_STD_IOSTREAM
wxSTD istream& wxDocument::LoadObject(wxSTD istream& stream)
#else
wxInputStream& wxDocument::LoadObject(wxInputStream& stream)
#endif
{
return stream;
}
#if wxUSE_STD_IOSTREAM
wxSTD ostream& wxDocument::SaveObject(wxSTD ostream& stream)
#else
wxOutputStream& wxDocument::SaveObject(wxOutputStream& stream)
#endif
{
return stream;
}
bool wxDocument::Revert()
{
return false;
}
// Get title, or filename if no title, else unnamed
bool wxDocument::GetPrintableName(wxString& buf) const
{
if (!m_documentTitle.empty())
{
buf = m_documentTitle;
return true;
}
else if (!m_documentFile.empty())
{
buf = wxFileNameFromPath(m_documentFile);
return true;
}
else
{
buf = _("unnamed");
return true;
}
}
wxWindow *wxDocument::GetDocumentWindow() const
{
wxView *view = GetFirstView();
if (view)
return view->GetFrame();
else
return wxTheApp->GetTopWindow();
}
wxCommandProcessor *wxDocument::OnCreateCommandProcessor()
{
return new wxCommandProcessor;
}
// true if safe to close
bool wxDocument::OnSaveModified()
{
if (IsModified())
{
wxString title;
GetPrintableName(title);
wxString msgTitle;
if (!wxTheApp->GetAppName().empty())
msgTitle = wxTheApp->GetAppName();
else
msgTitle = wxString(_("Warning"));
wxString prompt;
prompt.Printf(_("Do you want to save changes to document %s?"),
(const wxChar *)title);
int res = wxMessageBox(prompt, msgTitle,
wxYES_NO|wxCANCEL|wxICON_QUESTION,
GetDocumentWindow());
if (res == wxNO)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?