]> git.saurik.com Git - wxWidgets.git/blobdiff - samples/docview/docview.cpp
Ticket #10108 (bitmap from wxImage depth regression)
[wxWidgets.git] / samples / docview / docview.cpp
index e29218b6a9297e9c13553b23b034cbbf18b726d5..3f0b6c747b7192e59b6633a40419cf5b0f7802ff 100644 (file)
 /////////////////////////////////////////////////////////////////////////////
-// Name:        docview.cpp
+// Name:        samples/docview/docview.cpp
 // Purpose:     Document/view demo
 // Author:      Julian Smart
-// Modified by:
+// Modified by: Vadim Zeitlin: merge with the MDI version and general cleanup
 // Created:     04/01/98
 // RCS-ID:      $Id$
-// Copyright:   (c) Julian Smart
+// Copyright:   (c) 1998 Julian Smart
+//              (c) 2008 Vadim Zeitlin
 // Licence:     wxWindows license
 /////////////////////////////////////////////////////////////////////////////
 
 /*
-* Purpose:  Document/view architecture demo for wxWidgets class library
-*           Run with no arguments for multiple top-level windows, -single
-*           for a single window.
-*/
-
+    This sample show document/view support in wxWidgets.
+
+    It can be run in several ways:
+        * With "--mdi" command line option to use multiple MDI child frames
+          for the multiple documents (this is the default).
+        * With "--sdi" command line option to use multiple top level windows
+          for the multiple documents
+        * With "--single" command line option to support opening a single
+          document only
+
+    Notice that doing it like this somewhat complicates the code, you could
+    make things much simpler in your own programs by using either
+    wxDocParentFrame or wxDocMDIParentFrame unconditionally (and never using
+    the single mode) instead of supporting all of them as this sample does.
+ */
+
+// ----------------------------------------------------------------------------
+// headers
+// ----------------------------------------------------------------------------
 
 // For compilers that support precompilation, includes "wx/wx.h".
 #include "wx/wxprec.h"
 
 #ifdef __BORLANDC__
-#pragma hdrstop
+    #pragma hdrstop
 #endif
 
 #ifndef WX_PRECOMP
-#include "wx/wx.h"
+    #include "wx/wx.h"
+    #include "wx/stockitem.h"
 #endif
 
 #if !wxUSE_DOC_VIEW_ARCHITECTURE
-#error You must set wxUSE_DOC_VIEW_ARCHITECTURE to 1 in setup.h!
+    #error You must set wxUSE_DOC_VIEW_ARCHITECTURE to 1 in setup.h!
 #endif
 
 #include "wx/docview.h"
+#include "wx/docmdi.h"
 
 #include "docview.h"
 #include "doc.h"
 #include "view.h"
+
+#include "wx/cmdline.h"
+
 #ifdef __WXMAC__
-#include "wx/filename.h"
+    #include "wx/filename.h"
 #endif
-#include "wx/stockitem.h"
 
-static MyFrame* frame = NULL;
+#if !defined(__WXMSW__) && !defined(__WXPM__)
+    #include "doc.xpm"
+    #include "chart.xpm"
+    #include "notepad.xpm"
+#endif
 
-// In single window mode, don't have any child windows; use
-// main window.
-bool singleWindowMode = false;
+// ----------------------------------------------------------------------------
+// MyApp implementation
+// ----------------------------------------------------------------------------
 
 IMPLEMENT_APP(MyApp)
 
-MyApp::MyApp(void)
+BEGIN_EVENT_TABLE(MyApp, wxApp)
+    EVT_MENU(wxID_ABOUT, MyApp::OnAbout)
+END_EVENT_TABLE()
+
+MyApp::MyApp()
 {
-    m_docManager = NULL;
+#if wxUSE_MDI_ARCHITECTURE
+    m_mode = Mode_MDI;
+#else
+    m_mode = Mode_SDI;
+#endif
+
+    m_canvas = NULL;
+    m_menuEdit = NULL;
 }
 
-bool MyApp::OnInit(void)
+// constants for the command line options names
+namespace CmdLineOption
 {
-    if ( !wxApp::OnInit() )
-        return false;
-    SetAppName(wxT("DocView Demo"));
 
+const char * const MDI = "mdi";
+const char * const SDI = "sdi";
+const char * const SINGLE = "single";
+
+} // namespace CmdLineOption
+
+void MyApp::OnInitCmdLine(wxCmdLineParser& parser)
+{
+    wxApp::OnInitCmdLine(parser);
+
+    parser.AddSwitch("", CmdLineOption::MDI,
+                     "run in MDI mode: multiple documents, single window");
+    parser.AddSwitch("", CmdLineOption::SDI,
+                     "run in SDI mode: multiple documents, multiple windows");
+    parser.AddSwitch("", CmdLineOption::SINGLE,
+                     "run in single document mode");
+}
+
+bool MyApp::OnCmdLineParsed(wxCmdLineParser& parser)
+{
+    int numModeOptions = 0;
+
+#if wxUSE_MDI_ARCHITECTURE
+    if ( parser.Found(CmdLineOption::MDI) )
+    {
+        m_mode = Mode_MDI;
+        numModeOptions++;
+    }
+#endif // wxUSE_MDI_ARCHITECTURE
+
+    if ( parser.Found(CmdLineOption::SDI) )
+    {
+        m_mode = Mode_SDI;
+        numModeOptions++;
+    }
 
-    //// Find out if we're:
-    ////  multiple window: multiple windows, each view in a separate frame
-    ////  single window:   one view (within the main frame) and one document at a time, as in Windows Write.
-    ////                   In single window mode, we only allow one document type
-    if (argc > 1)
+    if ( parser.Found(CmdLineOption::SINGLE) )
     {
-        if (wxStrcmp(argv[1], wxT("-single")) == 0)
-        {
-            singleWindowMode = true;
-        }
+        m_mode = Mode_Single;
+        numModeOptions++;
     }
 
+    if ( numModeOptions > 1 )
+    {
+        wxLogError("Only a single option choosing the mode can be given.");
+        return false;
+    }
+
+    return wxApp::OnCmdLineParsed(parser);
+}
+
+bool MyApp::OnInit()
+{
+    if ( !wxApp::OnInit() )
+        return false;
+
+    SetAppName("DocView Sample");
+
     //// Create a document manager
-    m_docManager = new wxDocManager;
+    wxDocManager *docManager = new wxDocManager;
 
     //// Create a template relating drawing documents to their views
-    new wxDocTemplate(m_docManager, wxT("Drawing"), wxT("*.drw"), wxT(""), wxT("drw"), wxT("Drawing Doc"), wxT("Drawing View"),
-        CLASSINFO(DrawingDocument), CLASSINFO(DrawingView));
+    new wxDocTemplate(docManager, "Drawing", "*.drw", "", "drw",
+                      "Drawing Doc", "Drawing View",
+                      CLASSINFO(DrawingDocument), CLASSINFO(DrawingView));
 #ifdef __WXMAC__
-    wxFileName::MacRegisterDefaultTypeAndCreator( wxT("drw") , 'WXMB' , 'WXMA' ) ;
+    wxFileName::MacRegisterDefaultTypeAndCreator("drw" , 'WXMB' , 'WXMA');
 #endif
 
-    if (singleWindowMode)
+    if ( m_mode == Mode_Single )
     {
-        // If we've only got one window, we only get to edit
-        // one document at a time. Therefore no text editing, just
-        // doodling.
-        m_docManager->SetMaxDocsOpen(1);
+        // If we've only got one window, we only get to edit one document at a
+        // time. Therefore no text editing, just doodling.
+        docManager->SetMaxDocsOpen(1);
     }
-    else
+    else // multiple documents mode: allow documents of different types
     {
-        //// Create a template relating text documents to their views
-        new wxDocTemplate(m_docManager, wxT("Text"), wxT("*.txt;*.text"), wxT(""), wxT("txt;text"), wxT("Text Doc"), wxT("Text View"),
-        CLASSINFO(TextEditDocument), CLASSINFO(TextEditView));
+        // Create a template relating text documents to their views
+        new wxDocTemplate(docManager, "Text", "*.txt;*.text", "", "txt;text",
+                          "Text Doc", "Text View",
+                          CLASSINFO(TextEditDocument), CLASSINFO(TextEditView));
 #ifdef __WXMAC__
-        wxFileName::MacRegisterDefaultTypeAndCreator( wxT("txt") , 'TEXT' , 'WXMA' ) ;
+        wxFileName::MacRegisterDefaultTypeAndCreator("txt" , 'TEXT' , 'WXMA');
 #endif
     }
 
-    //// Create the main frame window
-    frame = new MyFrame(m_docManager, NULL, wxID_ANY, GetAppDisplayName(), wxPoint(0, 0), wxSize(500, 400), wxDEFAULT_FRAME_STYLE);
-
-    //// Give it an icon (this is ignored in MDI mode: uses resources)
-#ifdef __WXMSW__
-    frame->SetIcon(wxIcon(wxT("doc_icn")));
-#endif
-
-    //// Make a menubar
-    wxMenu *file_menu = new wxMenu;
-    wxMenu *edit_menu = NULL;
-
-    file_menu->Append(wxID_NEW);
-    file_menu->Append(wxID_OPEN);
-
-    if (singleWindowMode)
+    // create the main frame window
+    wxFrame *frame;
+#if wxUSE_MDI_ARCHITECTURE
+    if ( m_mode == Mode_MDI )
     {
-        file_menu->Append(wxID_CLOSE);
-        file_menu->Append(wxID_SAVE);
-        file_menu->Append(wxID_SAVEAS);
-        file_menu->AppendSeparator();
-        file_menu->Append(wxID_PRINT);
-        file_menu->Append(wxID_PRINT_SETUP, wxT("Print &Setup..."));
-        file_menu->Append(wxID_PREVIEW);
-
-        edit_menu = new wxMenu;
-        edit_menu->Append(wxID_UNDO);
-        edit_menu->Append(wxID_REDO);
-        edit_menu->AppendSeparator();
-        edit_menu->Append(DOCVIEW_CUT, wxT("&Cut last segment"));
-
-        frame->m_editMenu = edit_menu;
+        frame = new wxDocMDIParentFrame(docManager, NULL, wxID_ANY,
+                                        GetAppDisplayName(),
+                                        wxDefaultPosition,
+                                        wxSize(500, 400));
+    }
+    else
+#endif // wxUSE_MDI_ARCHITECTURE
+    {
+        frame = new wxDocParentFrame(docManager, NULL, wxID_ANY,
+                                     GetAppDisplayName(),
+                                     wxDefaultPosition,
+                                     wxSize(500, 400));
     }
 
-    file_menu->AppendSeparator();
-    file_menu->Append(wxID_EXIT);
+    // and its menu bar
+    wxMenu *menuFile = new wxMenu;
 
-    // A nice touch: a history of files visited. Use this menu.
-    m_docManager->FileHistoryUseMenu(file_menu);
+    menuFile->Append(wxID_NEW);
+    menuFile->Append(wxID_OPEN);
 
-    wxMenu *help_menu = new wxMenu;
-    help_menu->Append(DOCVIEW_ABOUT);
+    if ( m_mode == Mode_Single )
+        AppendDocumentFileCommands(menuFile, true);
 
-    wxMenuBar *menu_bar = new wxMenuBar;
+    menuFile->AppendSeparator();
+    menuFile->Append(wxID_EXIT);
 
-    menu_bar->Append(file_menu, wxGetStockLabel(wxID_FILE));
-    if (edit_menu)
-        menu_bar->Append(edit_menu, wxGetStockLabel(wxID_EDIT));
-    menu_bar->Append(help_menu, wxGetStockLabel(wxID_HELP));
+    // A nice touch: a history of files visited. Use this menu.
+    docManager->FileHistoryUseMenu(menuFile);
 
-    if (singleWindowMode)
-        frame->m_canvas = frame->CreateCanvas(NULL, frame);
+    if ( m_mode == Mode_Single )
+    {
+        m_canvas = new MyCanvas(NULL, frame);
+        m_menuEdit = CreateDrawingEditMenu();
+    }
 
-    //// Associate the menu bar with the frame
-    frame->SetMenuBar(menu_bar);
+    CreateMenuBarForFrame(frame, menuFile, m_menuEdit);
 
+    frame->SetIcon(wxICON(doc));
     frame->Centre(wxBOTH);
     frame->Show(true);
 
@@ -163,131 +228,153 @@ bool MyApp::OnInit(void)
     return true;
 }
 
-int MyApp::OnExit(void)
+int MyApp::OnExit()
 {
-    delete m_docManager;
-    return 0;
+    delete wxDocManager::GetDocumentManager();
+
+    return wxApp::OnExit();
 }
 
-/*
-* Centralised code for creating a document frame.
-* Called from view.cpp, when a view is created, but not used at all
-* in 'single window' mode.
-*/
+void MyApp::AppendDocumentFileCommands(wxMenu *menu, bool supportsPrinting)
+{
+    menu->Append(wxID_CLOSE);
+    menu->Append(wxID_SAVE);
+    menu->Append(wxID_SAVEAS);
 
-wxFrame *MyApp::CreateChildFrame(wxDocument *doc, wxView *view, bool isCanvas)
+    if ( supportsPrinting )
+    {
+        menu->AppendSeparator();
+        menu->Append(wxID_PRINT);
+        menu->Append(wxID_PRINT_SETUP, "Print &Setup...");
+        menu->Append(wxID_PREVIEW);
+    }
+}
+
+wxMenu *MyApp::CreateDrawingEditMenu()
 {
-    //// Make a child frame
-    wxDocChildFrame *subframe = new wxDocChildFrame(doc, view, GetMainFrame(), wxID_ANY, wxT("Child Frame"),
-        wxPoint(10, 10), wxSize(300, 300), wxDEFAULT_FRAME_STYLE);
+    wxMenu * const menu = new wxMenu;
+    menu->Append(wxID_UNDO);
+    menu->Append(wxID_REDO);
+    menu->AppendSeparator();
+    menu->Append(wxID_CUT, "&Cut last segment");
 
-#ifdef __WXMSW__
-    subframe->SetIcon(wxString(isCanvas ? wxT("chrt_icn") : wxT("notepad_icn")));
-#endif
+    return menu;
+}
 
-    //// Make a menubar
-    wxMenu *file_menu = new wxMenu;
+void MyApp::CreateMenuBarForFrame(wxFrame *frame, wxMenu *file, wxMenu *edit)
+{
+    wxMenuBar *menubar = new wxMenuBar;
 
-    file_menu->Append(wxID_NEW);
-    file_menu->Append(wxID_OPEN);
-    file_menu->Append(wxID_CLOSE);
-    file_menu->Append(wxID_SAVE);
-    file_menu->Append(wxID_SAVEAS);
+    menubar->Append(file, wxGetStockLabel(wxID_FILE));
 
-    if (isCanvas)
-    {
-        file_menu->AppendSeparator();
-        file_menu->Append(wxID_PRINT);
-        file_menu->Append(wxID_PRINT_SETUP, wxT("Print &Setup..."));
-        file_menu->Append(wxID_PREVIEW);
-    }
+    if ( edit )
+        menubar->Append(edit, wxGetStockLabel(wxID_EDIT));
 
-    wxMenu *edit_menu = new wxMenu;
+    wxMenu *help= new wxMenu;
+    help->Append(wxID_ABOUT);
+    menubar->Append(help, wxGetStockLabel(wxID_HELP));
 
-    if (isCanvas)
-    {
-        edit_menu->Append(wxID_UNDO);
-        edit_menu->Append(wxID_REDO);
-        edit_menu->AppendSeparator();
-        edit_menu->Append(DOCVIEW_CUT, wxT("&Cut last segment"));
+    frame->SetMenuBar(menubar);
+}
 
-        doc->GetCommandProcessor()->SetEditMenu(edit_menu);
+wxFrame *MyApp::CreateChildFrame(wxDocument *doc, wxView *view, bool isCanvas)
+{
+    // create a child frame of appropriate class for the current mode
+    wxFrame *subframe;
+#if wxUSE_MDI_ARCHITECTURE
+    if ( GetMode() == Mode_MDI )
+    {
+        subframe = new wxDocMDIChildFrame
+                       (
+                            doc,
+                            view,
+                            wxStaticCast(GetTopWindow(), wxDocMDIParentFrame),
+                            wxID_ANY,
+                            "Child Frame",
+                            wxDefaultPosition,
+                            wxSize(300, 300)
+                       );
     }
     else
+#endif // wxUSE_MDI_ARCHITECTURE
     {
-        edit_menu->Append(wxID_COPY);
-        edit_menu->Append(wxID_PASTE);
-        edit_menu->Append(wxID_SELECTALL);
+        subframe = new wxDocChildFrame
+                       (
+                            doc,
+                            view,
+                            wxStaticCast(GetTopWindow(), wxDocParentFrame),
+                            wxID_ANY,
+                            "Child Frame",
+                            wxDefaultPosition,
+                            wxSize(300, 300)
+                       );
+
+        subframe->Centre(wxBOTH);
     }
 
-    wxMenu *help_menu = new wxMenu;
-    help_menu->Append(DOCVIEW_ABOUT);
-
-    wxMenuBar *menu_bar = new wxMenuBar;
-
-    menu_bar->Append(file_menu, wxGetStockLabel(wxID_FILE));
-    menu_bar->Append(edit_menu, wxGetStockLabel(wxID_EDIT));
-    menu_bar->Append(help_menu, wxGetStockLabel(wxID_HELP));
+    wxMenu *menuFile = new wxMenu;
 
-    //// Associate the menu bar with the frame
-    subframe->SetMenuBar(menu_bar);
+    menuFile->Append(wxID_NEW);
+    menuFile->Append(wxID_OPEN);
+    AppendDocumentFileCommands(menuFile, isCanvas);
+    menuFile->AppendSeparator();
+    menuFile->Append(wxID_EXIT);
 
-    subframe->Centre(wxBOTH);
-
-    return subframe;
-}
+    wxMenu *menuEdit;
+    if ( isCanvas )
+    {
+        menuEdit = CreateDrawingEditMenu();
 
-/*
-* This is the top-level window of the application.
-*/
+        doc->GetCommandProcessor()->SetEditMenu(menuEdit);
+        doc->GetCommandProcessor()->Initialize();
+    }
+    else // text frame
+    {
+        menuEdit = new wxMenu;
+        menuEdit->Append(wxID_COPY);
+        menuEdit->Append(wxID_PASTE);
+        menuEdit->Append(wxID_SELECTALL);
+    }
 
-IMPLEMENT_CLASS(MyFrame, wxDocParentFrame)
-BEGIN_EVENT_TABLE(MyFrame, wxDocParentFrame)
-    EVT_MENU(DOCVIEW_ABOUT, MyFrame::OnAbout)
-END_EVENT_TABLE()
+    CreateMenuBarForFrame(subframe, menuFile, menuEdit);
 
-MyFrame::MyFrame(wxDocManager *manager, wxFrame *frame, wxWindowID id, const wxString& title,
-                 const wxPoint& pos, const wxSize& size, const long type):
-wxDocParentFrame(manager, frame, id, title, pos, size, type)
-{
-    // This pointer only needed if in single window mode
-    m_canvas = NULL;
-    m_editMenu = NULL;
-}
+    subframe->SetIcon(isCanvas ? wxICON(chrt) : wxICON(notepad));
 
-void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event) )
-{
-    wxMessageBox(wxT("DocView Demo\nAuthor: Julian Smart\nUsage: docview.exe [-single]"), wxT("About DocView"));
-/*
-    Better, but brings in adv lib
-    wxAboutDialogInfo info;
-    info.SetName(wxTheApp->GetAppDisplayName());
-    info.AddDeveloper(wxT("Julian Smart"));
-    wxAboutBox(info);
-*/
+    return subframe;
 }
 
-// Creates a canvas. Called either from view.cc when a new drawing
-// view is created, or in OnInit as a child of the main window,
-// if in 'single window' mode.
-MyCanvas *MyFrame::CreateCanvas(DrawingView* view, wxFrame *parent)
+void MyApp::OnAbout(wxCommandEvent& WXUNUSED(event))
 {
-    wxSize size = parent->GetClientSize();
-
-    // Non-retained canvas
-    MyCanvas* canvas = new MyCanvas(view, parent, wxPoint(0, 0), size, 0);
-    canvas->SetCursor(wxCursor(wxCURSOR_PENCIL));
-
-    // Give it scrollbars
-    canvas->SetScrollbars(20, 20, 50, 50);
-    canvas->SetBackgroundColour(*wxWHITE);
-    canvas->ClearBackground();
-
-    return canvas;
-}
+    wxString modeName;
+    switch ( m_mode )
+    {
+#if wxUSE_MDI_ARCHITECTURE
+        case Mode_MDI:
+            modeName = "MDI";
+            break;
+#endif // wxUSE_MDI_ARCHITECTURE
+
+        case Mode_SDI:
+            modeName = "SDI";
+            break;
+
+        case Mode_Single:
+            modeName = "single document";
+            break;
+
+        default:
+            wxFAIL_MSG( "unknown mode ");
+    }
 
-MyFrame *GetMainFrame(void)
-{
-    return frame;
+    wxLogMessage
+    (
+        "This is the wxWidgets Document/View Sample\n"
+        "running in %s mode.\n"
+        "\n"
+        "Authors: Julian Smart, Vadim Zeitlin\n"
+        "\n"
+        "Usage: docview [--{mdi,sdi,single}]",
+        modeName
+    );
 }