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 + -
显示快捷键?