- wxHTML: render in RTL order inside RTL window (Richard Bullington-McGuire).
- wxRibbon: added EVT_RIBBONGALLERY_CLICKED event (John Roberts).
- wxRibbon: allow hiding the panels and showing tabs only (snowleopard).
+- Add support for child documents to docview framework.
- Add support for CP-866 encoding to wxEncodingConverter (madnut).
- Consistency fixes for keyboard events across all major ports.
- Added EVT_RIBBONBAR_TAB_LEFT_DCLICK event (snowleopard).
#if wxUSE_DOC_VIEW_ARCHITECTURE
#include "wx/list.h"
+#include "wx/dlist.h"
#include "wx/string.h"
#include "wx/frame.h"
#include "wx/filehistory.h"
// dialogs. Override if necessary.
virtual wxWindow *GetDocumentWindow() const;
+ // Returns true if this document is a child document corresponding to a
+ // part of the parent document and not a disk file as usual.
+ bool IsChildDocument() const { return m_documentParent != NULL; }
+
protected:
wxList m_documentViews;
wxString m_documentFile;
wxString m_documentTypeName;
wxDocTemplate* m_documentTemplate;
bool m_documentModified;
+
+ // if the document parent is non-NULL, it's a pseudo-document corresponding
+ // to a part of the parent document which can't be saved or loaded
+ // independently of its parent and is always closed when its parent is
wxDocument* m_documentParent;
+
wxCommandProcessor* m_commandProcessor;
bool m_savedYet;
wxString DoGetUserReadableName() const;
private:
+ // list of all documents whose m_documentParent is this one
+ typedef wxDList<wxDocument> DocsList;
+ DocsList m_childDocuments;
+
DECLARE_ABSTRACT_CLASS(wxDocument)
wxDECLARE_NO_COPY_CLASS(wxDocument);
};
void OnUpdateFileRevert(wxUpdateUIEvent& event);
void OnUpdateFileNew(wxUpdateUIEvent& event);
void OnUpdateFileSave(wxUpdateUIEvent& event);
+ void OnUpdateFileSaveAs(wxUpdateUIEvent& event);
void OnUpdateUndo(wxUpdateUIEvent& event);
void OnUpdateRedo(wxUpdateUIEvent& event);
@class wxDocument
The document class can be used to model an application's file-based data.
+
It is part of the document/view framework supported by wxWidgets, and
cooperates with the wxView, wxDocTemplate and wxDocManager classes.
+ A normal document is the one created without parent document and is
+ associated with a disk file. Since version 2.9.2 wxWidgets also supports a
+ special kind of documents called <em>child documents</em> which are virtual
+ in the sense that they do not correspond to a file but rather to a part of
+ their parent document. Because of this, the child documents can't be
+ created directly by user but can only be created by the parent document
+ (usually when it's being created itself). They also can't be independently
+ saved. A child document has its own view with the corresponding window.
+ This view can be closed by user but, importantly, is also automatically
+ closed when its parent document is closed. Thus, child documents may be
+ convenient for creating additional windows which need to be closed when the
+ main document is. The docview sample demonstrates this use of child
+ documents by creating a child document containing the information about the
+ parameters of the image opened in the main document.
+
@library{wxcore}
@category{docview}
/**
Constructor. Define your own default constructor to initialize
application-specific data.
+
+ @param parent
+ Specifying a non-@c NULL parent document here makes this document a
+ special <em>child document</em>, see their description in the class
+ documentation. Notice that this parameter exists but is ignored in
+ wxWidgets versions prior to 2.9.1.
*/
- wxDocument(wxDocument* parent = 0);
+ wxDocument(wxDocument* parent = NULL);
/**
Destructor. Removes itself from the document manager.
const wxList& GetViews() const;
//@}
+ /**
+ Returns true if this document is a child document corresponding to a
+ part of the parent document and not a disk file as usual.
+
+ This method can be used to check whether file-related operations make
+ sense for this document as they only apply to top-level documents and
+ not child ones.
+
+ @since 2.9.2
+ */
+ bool IsChildDocument() const;
+
/**
Returns @true if the document has been modified since the last save,
@false otherwise. You may need to override this if your document view
}
// ----------------------------------------------------------------------------
-// ImageDocument and wxImageDetailsDocument implementation
+// ImageDocument and ImageDetailsDocument implementation
// ----------------------------------------------------------------------------
IMPLEMENT_DYNAMIC_CLASS(ImageDocument, wxDocument)
return m_image.LoadFile(file);
}
+bool ImageDocument::OnOpenDocument(const wxString& filename)
+{
+ if ( !wxDocument::OnOpenDocument(filename) )
+ return false;
+
+ // we don't have a wxDocTemplate for the image details document as it's
+ // never created by wxWidgets automatically, instead just do it manually
+ ImageDetailsDocument * const docDetails = new ImageDetailsDocument(this);
+ docDetails->SetFilename(filename);
+
+ new ImageDetailsView(docDetails);
+
+ return true;
+}
+
+ImageDetailsDocument::ImageDetailsDocument(ImageDocument *parent)
+ : wxDocument(parent)
+{
+ const wxImage image = parent->GetImage();
+
+ m_size.x = image.GetWidth();
+ m_size.y = image.GetHeight();
+ m_numColours = image.CountColours();
+ m_type = image.GetType();
+ m_hasAlpha = image.HasAlpha();
+}
};
// ----------------------------------------------------------------------------
-// A document class representing an image
+// Image and image details document classes (both are read-only for simplicity)
// ----------------------------------------------------------------------------
+// This is a normal document containing an image, just like TextEditDocument
+// above contains some text. It can be created from an image file on disk as
+// usual.
class ImageDocument : public wxDocument
{
public:
ImageDocument() : wxDocument() { }
+ virtual bool OnOpenDocument(const wxString& file);
+
wxImage GetImage() const { return m_image; }
protected:
DECLARE_DYNAMIC_CLASS(ImageDocument)
};
+// This is a child document of ImageDocument: this document doesn't
+// correspond to any file on disk, it's part of ImageDocument and can't be
+// instantiated independently of it.
+class ImageDetailsDocument : public wxDocument
+{
+public:
+ ImageDetailsDocument(ImageDocument *parent);
+
+ // accessors for ImageDetailsView
+ wxSize GetSize() const { return m_size; }
+ unsigned long GetNumColours() const { return m_numColours; }
+ wxBitmapType GetType() const { return m_type; }
+ bool HasAlpha() const { return m_hasAlpha; }
+
+private:
+ // some information about the image we choose to show to the user
+ wxSize m_size;
+ unsigned long m_numColours;
+ wxBitmapType m_type;
+ bool m_hasAlpha;
+
+ wxDECLARE_NO_COPY_CLASS(ImageDetailsDocument);
+};
+
#endif // _WX_SAMPLES_DOCVIEW_DOC_H_
return true;
}
+// ----------------------------------------------------------------------------
+// ImageDetailsView
+// ----------------------------------------------------------------------------
+
+ImageDetailsView::ImageDetailsView(ImageDetailsDocument *doc)
+ : wxView()
+{
+ SetDocument(doc);
+
+ m_frame = wxGetApp().CreateChildFrame(this, false);
+ m_frame->SetTitle("Image Details");
+
+ wxPanel * const panel = new wxPanel(m_frame);
+ wxFlexGridSizer * const sizer = new wxFlexGridSizer(2, wxSize(5, 5));
+ const wxSizerFlags
+ flags = wxSizerFlags().Align(wxALIGN_CENTRE_VERTICAL).Border();
+
+ sizer->Add(new wxStaticText(panel, wxID_ANY, "Image &file:"), flags);
+ sizer->Add(new wxStaticText(panel, wxID_ANY, doc->GetFilename()), flags);
+
+ sizer->Add(new wxStaticText(panel, wxID_ANY, "Image &type:"), flags);
+ wxString typeStr;
+ switch ( doc->GetType() )
+ {
+ case wxBITMAP_TYPE_PNG:
+ typeStr = "PNG";
+ break;
+
+ case wxBITMAP_TYPE_JPEG:
+ typeStr = "JPEG";
+ break;
+
+ default:
+ typeStr = "Unknown";
+ }
+ sizer->Add(new wxStaticText(panel, wxID_ANY, typeStr), flags);
+
+ sizer->Add(new wxStaticText(panel, wxID_ANY, "Image &size:"), flags);
+ wxSize size = doc->GetSize();
+ sizer->Add(new wxStaticText(panel, wxID_ANY,
+ wxString::Format("%d*%d", size.x, size.y)),
+ flags);
+
+ sizer->Add(new wxStaticText(panel, wxID_ANY, "Number of unique &colours:"),
+ flags);
+ sizer->Add(new wxStaticText(panel, wxID_ANY,
+ wxString::Format("%lu", doc->GetNumColours())),
+ flags);
+
+ sizer->Add(new wxStaticText(panel, wxID_ANY, "Uses &alpha:"), flags);
+ sizer->Add(new wxStaticText(panel, wxID_ANY,
+ doc->HasAlpha() ? "Yes" : "No"), flags);
+
+ panel->SetSizer(sizer);
+ m_frame->SetClientSize(panel->GetBestSize());
+ m_frame->Show(true);
+}
+
+void ImageDetailsView::OnDraw(wxDC * WXUNUSED(dc))
+{
+ // nothing to do here, we use controls to show our information
+}
+
+bool ImageDetailsView::OnClose(bool deleteWindow)
+{
+ if ( wxGetApp().GetMode() != MyApp::Mode_Single && deleteWindow )
+ {
+ delete m_frame;
+ m_frame = NULL;
+ }
+
+ return true;
+}
DECLARE_DYNAMIC_CLASS(ImageView)
};
+// ----------------------------------------------------------------------------
+// ImageDetailsView
+// ----------------------------------------------------------------------------
+
+class ImageDetailsView : public wxView
+{
+public:
+ ImageDetailsView(ImageDetailsDocument *doc);
+
+ virtual void OnDraw(wxDC *dc);
+ virtual bool OnClose(bool deleteWindow);
+
+private:
+ wxFrame *m_frame;
+
+ wxDECLARE_NO_COPY_CLASS(ImageDetailsView);
+};
+
#endif // _WX_SAMPLES_DOCVIEW_VIEW_H_
wxDocument::wxDocument(wxDocument *parent)
{
m_documentModified = false;
- m_documentParent = parent;
m_documentTemplate = NULL;
+
+ m_documentParent = parent;
+ if ( parent )
+ parent->m_childDocuments.push_back(this);
+
m_commandProcessor = NULL;
m_savedYet = false;
}
if (GetDocumentManager())
GetDocumentManager()->RemoveDocument(this);
+ if ( m_documentParent )
+ m_documentParent->m_childDocuments.remove(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.
if ( !OnSaveModified() )
return false;
+ // When the parent document closes, its children must be closed as well as
+ // they can't exist without the parent.
+
+ // As usual, first check if all children can be closed.
+ DocsList::const_iterator it = m_childDocuments.begin();
+ for ( DocsList::const_iterator end = m_childDocuments.end(); it != end; ++it )
+ {
+ if ( !(*it)->OnSaveModified() )
+ {
+ // Leave the parent document opened if a child can't close.
+ return false;
+ }
+ }
+
+ // Now that they all did, do close them: as m_childDocuments is modified as
+ // we iterate over it, don't use the usual for-style iteration here.
+ while ( !m_childDocuments.empty() )
+ {
+ wxDocument * const childDoc = m_childDocuments.front();
+
+ // This will call OnSaveModified() once again but it shouldn't do
+ // anything as the document was just saved or marked as not needing to
+ // be saved by the call to OnSaveModified() that returned true above.
+ if ( !childDoc->Close() )
+ {
+ wxFAIL_MSG( "Closing the child document unexpectedly failed "
+ "after its OnSaveModified() returned true" );
+ }
+
+ // Delete the child document by deleting all its views.
+ childDoc->DeleteAllViews();
+ }
+
+
return OnCloseDocument();
}
wxDocManager *wxDocument::GetDocumentManager() const
{
+ // For child documents we use the same document manager as the parent, even
+ // though we don't have our own template (as children are not opened/saved
+ // directly).
+ if ( m_documentParent )
+ return m_documentParent->GetDocumentManager();
+
return m_documentTemplate ? m_documentTemplate->GetDocumentManager() : NULL;
}
EVT_UPDATE_UI(wxID_REVERT, wxDocManager::OnUpdateFileRevert)
EVT_UPDATE_UI(wxID_NEW, wxDocManager::OnUpdateFileNew)
EVT_UPDATE_UI(wxID_SAVE, wxDocManager::OnUpdateFileSave)
- EVT_UPDATE_UI(wxID_SAVEAS, wxDocManager::OnUpdateDisableIfNoDoc)
+ EVT_UPDATE_UI(wxID_SAVEAS, wxDocManager::OnUpdateFileSaveAs)
EVT_UPDATE_UI(wxID_UNDO, wxDocManager::OnUpdateUndo)
EVT_UPDATE_UI(wxID_REDO, wxDocManager::OnUpdateRedo)
void wxDocManager::OnUpdateFileSave(wxUpdateUIEvent& event)
{
wxDocument * const doc = GetCurrentDocument();
- event.Enable( doc && !doc->AlreadySaved() );
+ event.Enable( doc && !doc->IsChildDocument() && !doc->AlreadySaved() );
+}
+
+void wxDocManager::OnUpdateFileSaveAs(wxUpdateUIEvent& event)
+{
+ wxDocument * const doc = GetCurrentDocument();
+ event.Enable( doc && !doc->IsChildDocument() );
}
void wxDocManager::OnUpdateUndo(wxUpdateUIEvent& event)