From 3c55b3652b16f892e9064460bbeea94769f3d27c Mon Sep 17 00:00:00 2001
From: Julian Smart <julian@anthemion.co.uk>
Date: Mon, 30 Jan 2006 15:35:04 +0000
Subject: [PATCH] Added wxToolbook class

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@37214 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
---
 docs/latex/wx/classes.tex  |   1 +
 docs/latex/wx/tbook.tex    |   7 +-
 docs/latex/wx/toolbook.tex |  48 +++++
 include/wx/toolbook.h      | 147 ++++++++++++++
 src/generic/toolbkg.cpp    | 405 +++++++++++++++++++++++++++++++++++++
 5 files changed, 606 insertions(+), 2 deletions(-)
 create mode 100644 docs/latex/wx/toolbook.tex
 create mode 100644 include/wx/toolbook.h
 create mode 100644 src/generic/toolbkg.cpp

diff --git a/docs/latex/wx/classes.tex b/docs/latex/wx/classes.tex
index ffbe9e6dcc..158edda4be 100644
--- a/docs/latex/wx/classes.tex
+++ b/docs/latex/wx/classes.tex
@@ -346,6 +346,7 @@
 \input tipwin.tex
 \input tglbtn.tex
 \input toolbar.tex
+\input toolbook.tex
 \input tooltip.tex
 \input tlw.tex
 \input treebook.tex
diff --git a/docs/latex/wx/tbook.tex b/docs/latex/wx/tbook.tex
index 4e25b09c47..1b10d024cd 100644
--- a/docs/latex/wx/tbook.tex
+++ b/docs/latex/wx/tbook.tex
@@ -11,17 +11,20 @@
 
 \section{wxBookCtrl overview}\label{wxbookctrloverview}
 
-Classes: \helpref{wxNotebook}{wxnotebook}, \helpref{wxListbook}{wxlistbook}, \helpref{wxChoicebook}{wxchoicebook}
+Classes: \helpref{wxNotebook}{wxnotebook}, \helpref{wxListbook}{wxlistbook}, \helpref{wxChoicebook}{wxchoicebook}, 
+\helpref{wxTreebook}{wxtreebook}, \helpref{wxToolbook}{wxtoolbook}
 
 \subsection{Introduction}\label{wxbookctrlintro}
 
 A book control is a convenient way of displaying multiple pages of information,
-displayed one page at a time. wxWidgets has three variants of this control:
+displayed one page at a time. wxWidgets has five variants of this control:
 
 \begin{itemize}\itemsep=0pt
 \item \helpref{wxNotebook}{wxnotebook}: uses a row of tabs
 \item \helpref{wxListbook}{wxlistbook}: controlled by a \helpref{wxListCtrl}{wxlistctrl}
 \item \helpref{wxChoicebook}{wxchoicebook}: controlled by a \helpref{wxChoice}{wxchoice}
+\item \helpref{wxTreebook}{wxtreebook}: controlled by a \helpref{wxTreeCtrl}{wxtreectrl}
+\item \helpref{wxToolbook}{wxtoolbook}: controlled by a \helpref{wxToolBar}{wxtoolbar}
 \end{itemize}
 
 \subsection{Best book}\label{wxbestbookctrl}
diff --git a/docs/latex/wx/toolbook.tex b/docs/latex/wx/toolbook.tex
new file mode 100644
index 0000000000..4621496d18
--- /dev/null
+++ b/docs/latex/wx/toolbook.tex
@@ -0,0 +1,48 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Name:        toolbook.tex
+%% Purpose:     wxToolbook documentation
+%% Author:      Julian Smart
+%% Modified by:
+%% Created:     2006-01-30
+%% RCS-ID:      $Id$
+%% Copyright:   (c) 2006 Julian Smart
+%% License:     wxWindows license
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\section{\class{wxToolbook}}\label{wxtoolbook}
+
+wxToolbook is a class similar to \helpref{wxNotebook}{wxnotebook} but which
+uses a \helpref{wxToolBar}{wxtoolbar} to show the labels instead of the
+tabs.
+
+There is no documentation for this class yet but its usage is
+identical to wxNotebook (except for the features clearly related to tabs
+only), so please refer to that class documentation for now. You can also
+use the \helpref{notebook sample}{samplenotebook} to see wxToolbook in action.
+
+\wxheading{Derived from}
+
+wxBookCtrlBase\\
+\helpref{wxControl}{wxcontrol}\\
+\helpref{wxControl}{wxcontrol}\\
+\helpref{wxWindow}{wxwindow}\\
+\helpref{wxEvtHandler}{wxevthandler}\\
+\helpref{wxObject}{wxobject}
+
+\wxheading{Include files}
+
+<wx/toolbook.h>
+
+\wxheading{Window styles}
+
+\twocolwidtha{5cm}
+\begin{twocollist}\itemsep=0pt
+
+\twocolitem{\windowstyle{wxLB\_DEFAULT}}{Choose the default location for the
+labels depending on the current platform (currently always the top).}
+\end{twocollist}
+
+\wxheading{See also}
+
+\helpref{wxBookCtrl}{wxbookctrloverview}, \helpref{wxNotebook}{wxnotebook}, \helpref{notebook sample}{samplenotebook}
+
diff --git a/include/wx/toolbook.h b/include/wx/toolbook.h
new file mode 100644
index 0000000000..f5b6fc8f1e
--- /dev/null
+++ b/include/wx/toolbook.h
@@ -0,0 +1,147 @@
+///////////////////////////////////////////////////////////////////////////////
+// Name:        wx/toolbook.h
+// Purpose:     wxToolbook: wxToolBar and wxNotebook combination
+// Author:      Julian Smart
+// Modified by:
+// Created:     2006-01-29
+// RCS-ID:      $Id$
+// Copyright:   (c) 2006 Julian Smart
+// Licence:     wxWindows licence
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef _WX_TOOLBOOK_H_
+#define _WX_TOOLBOOK_H_
+
+#include "wx/defs.h"
+
+#if wxUSE_TOOLBOOK
+
+#include "wx/bookctrl.h"
+
+class WXDLLEXPORT wxToolBarBase;
+class WXDLLEXPORT wxCommandEvent;
+
+// ----------------------------------------------------------------------------
+// wxToolbook
+// ----------------------------------------------------------------------------
+
+class WXDLLEXPORT wxToolbook : public wxBookCtrlBase
+{
+public:
+    wxToolbook()
+    {
+        Init();
+    }
+
+    wxToolbook(wxWindow *parent,
+               wxWindowID id,
+               const wxPoint& pos = wxDefaultPosition,
+               const wxSize& size = wxDefaultSize,
+               long style = 0,
+               const wxString& name = wxEmptyString)
+    {
+        Init();
+
+        (void)Create(parent, id, pos, size, style, name);
+    }
+
+    // quasi ctor
+    bool Create(wxWindow *parent,
+                wxWindowID id,
+                const wxPoint& pos = wxDefaultPosition,
+                const wxSize& size = wxDefaultSize,
+                long style = 0,
+                const wxString& name = wxEmptyString);
+
+
+    virtual int GetSelection() const;
+    virtual bool SetPageText(size_t n, const wxString& strText);
+    virtual wxString GetPageText(size_t n) const;
+    virtual int GetPageImage(size_t n) const;
+    virtual bool SetPageImage(size_t n, int imageId);
+    virtual wxSize CalcSizeFromPage(const wxSize& sizePage) const;
+    virtual bool InsertPage(size_t n,
+                            wxWindow *page,
+                            const wxString& text,
+                            bool bSelect = false,
+                            int imageId = -1);
+    virtual int SetSelection(size_t n);
+    virtual void SetImageList(wxImageList *imageList);
+
+    virtual bool DeleteAllPages();
+
+    wxToolBarBase* GetToolBar() const { return (wxToolBarBase*)m_bookctrl; }
+
+    // Not part of the wxBookctrl API, but must be called in OnIdle or
+    // by application to realize the toolbar and select the initial page.
+    void Realize();
+
+protected:
+    virtual wxWindow *DoRemovePage(size_t page);
+
+    // get the size which the list control should have
+    virtual wxSize GetControllerSize() const;
+
+    // event handlers
+    void OnToolSelected(wxCommandEvent& event);
+    void OnSize(wxSizeEvent& event);
+    void OnIdle(wxIdleEvent& event);
+
+    // the currently selected page or wxNOT_FOUND if none
+    int m_selection;
+
+    // whether the toolbar needs to be realized
+    bool m_needsRealizing;
+
+    // maximum bitmap size
+    wxSize  m_maxBitmapSize;
+
+private:
+    // common part of all constructors
+    void Init();
+
+    DECLARE_EVENT_TABLE()
+    DECLARE_DYNAMIC_CLASS_NO_COPY(wxToolbook)
+};
+
+// ----------------------------------------------------------------------------
+// listbook event class and related stuff
+// ----------------------------------------------------------------------------
+
+class WXDLLEXPORT wxToolbookEvent : public wxBookCtrlBaseEvent
+{
+public:
+    wxToolbookEvent(wxEventType commandType = wxEVT_NULL, int id = 0,
+                    int nSel = wxNOT_FOUND, int nOldSel = wxNOT_FOUND)
+        : wxBookCtrlBaseEvent(commandType, id, nSel, nOldSel)
+    {
+    }
+
+    wxToolbookEvent(const wxToolbookEvent& event)
+        : wxBookCtrlBaseEvent(event)
+    {
+    }
+
+    virtual wxEvent *Clone() const { return new wxToolbookEvent(*this); }
+
+private:
+    DECLARE_DYNAMIC_CLASS_NO_ASSIGN(wxToolbookEvent)
+};
+
+extern WXDLLIMPEXP_CORE const wxEventType wxEVT_COMMAND_TOOLBOOK_PAGE_CHANGED;
+extern WXDLLIMPEXP_CORE const wxEventType wxEVT_COMMAND_TOOLBOOK_PAGE_CHANGING;
+
+typedef void (wxEvtHandler::*wxToolbookEventFunction)(wxToolbookEvent&);
+
+#define wxToolbookEventHandler(func) \
+    (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(wxToolbookEventFunction, &func)
+
+#define EVT_TOOLBOOK_PAGE_CHANGED(winid, fn) \
+    wx__DECLARE_EVT1(wxEVT_COMMAND_TOOLBOOK_PAGE_CHANGED, winid, wxToolbookEventHandler(fn))
+
+#define EVT_TOOLBOOK_PAGE_CHANGING(winid, fn) \
+    wx__DECLARE_EVT1(wxEVT_COMMAND_TOOLBOOK_PAGE_CHANGING, winid, wxToolbookEventHandler(fn))
+
+#endif // wxUSE_TOOLBOOK
+
+#endif // _WX_TOOLBOOK_H_
diff --git a/src/generic/toolbkg.cpp b/src/generic/toolbkg.cpp
new file mode 100644
index 0000000000..611db38af5
--- /dev/null
+++ b/src/generic/toolbkg.cpp
@@ -0,0 +1,405 @@
+///////////////////////////////////////////////////////////////////////////////
+// Name:        src/generic/toolbkg.cpp
+// Purpose:     generic implementation of wxToolbook
+// Author:      Julian Smart
+// Modified by:
+// Created:     2006-01-29
+// RCS-ID:      $Id$
+// Copyright:   (c) 2006 Julian Smart
+// Licence:     wxWindows licence
+///////////////////////////////////////////////////////////////////////////////
+
+// ============================================================================
+// declarations
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// headers
+// ----------------------------------------------------------------------------
+
+// For compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+    #pragma hdrstop
+#endif
+
+#if wxUSE_LISTBOOK
+
+#include "wx/toolbar.h"
+#include "wx/toolbook.h"
+#include "wx/settings.h"
+#include "wx/sysopt.h"
+
+// ----------------------------------------------------------------------------
+// various wxWidgets macros
+// ----------------------------------------------------------------------------
+
+// check that the page index is valid
+#define IS_VALID_PAGE(nPage) ((nPage) < GetPageCount())
+
+// ----------------------------------------------------------------------------
+// event table
+// ----------------------------------------------------------------------------
+
+IMPLEMENT_DYNAMIC_CLASS(wxToolbook, wxBookCtrlBase)
+IMPLEMENT_DYNAMIC_CLASS(wxToolbookEvent, wxNotifyEvent)
+
+const wxEventType wxEVT_COMMAND_TOOLBOOK_PAGE_CHANGING = wxNewEventType();
+const wxEventType wxEVT_COMMAND_TOOLBOOK_PAGE_CHANGED = wxNewEventType();
+const int wxID_TOOLBOOKTOOLBAR = wxNewId();
+
+BEGIN_EVENT_TABLE(wxToolbook, wxBookCtrlBase)
+    EVT_SIZE(wxToolbook::OnSize)
+    EVT_TOOL_RANGE(1, 50, wxToolbook::OnToolSelected)
+    EVT_IDLE(wxToolbook::OnIdle)
+END_EVENT_TABLE()
+
+// ============================================================================
+// wxToolbook implementation
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// wxToolbook creation
+// ----------------------------------------------------------------------------
+
+void wxToolbook::Init()
+{
+    m_selection = wxNOT_FOUND;
+    m_needsRealizing = false;
+}
+
+bool
+wxToolbook::Create(wxWindow *parent,
+                   wxWindowID id,
+                   const wxPoint& pos,
+                   const wxSize& size,
+                   long style,
+                   const wxString& name)
+{
+    if ( (style & wxBK_ALIGN_MASK) == wxBK_DEFAULT )
+    {
+        style |= wxBK_TOP;
+    }
+
+    // no border for this control
+    style &= ~wxBORDER_MASK;
+    style |= wxBORDER_NONE;
+
+    if ( !wxControl::Create(parent, id, pos, size, style,
+                            wxDefaultValidator, name) )
+        return false;
+
+    // TODO: make configurable
+    m_bookctrl = new wxToolBar
+                 (
+                    this,
+                    wxID_TOOLBOOKTOOLBAR,
+                    wxDefaultPosition,
+                    wxDefaultSize,
+                    wxTB_HORIZONTAL|wxTB_TEXT|wxTB_FLAT|wxTB_NODIVIDER
+                 );
+
+    return true;
+}
+
+// ----------------------------------------------------------------------------
+// wxToolbook geometry management
+// ----------------------------------------------------------------------------
+
+wxSize wxToolbook::GetControllerSize() const
+{
+    const wxSize sizeClient = GetClientSize(),
+                 sizeBorder = m_bookctrl->GetSize() - m_bookctrl->GetClientSize(),
+                 sizeToolBar = GetToolBar()->GetSize() + sizeBorder;
+
+    wxSize size;
+
+    if ( IsVertical() )
+    {
+        size.x = sizeClient.x;
+        size.y = sizeToolBar.y;
+    }
+    else // left/right aligned
+    {
+        size.x = sizeToolBar.x;
+        size.y = sizeClient.y;
+    }
+
+    return size;
+}
+
+void wxToolbook::OnSize(wxSizeEvent& event)
+{
+    if (m_needsRealizing)
+        Realize();
+    
+    wxBookCtrlBase::OnSize(event);
+}
+
+wxSize wxToolbook::CalcSizeFromPage(const wxSize& sizePage) const
+{
+    // we need to add the size of the list control and the border between
+    const wxSize sizeToolBar = GetControllerSize();
+
+    wxSize size = sizePage;
+    if ( IsVertical() )
+    {
+        size.y += sizeToolBar.y + GetInternalBorder();
+    }
+    else // left/right aligned
+    {
+        size.x += sizeToolBar.x + GetInternalBorder();
+    }
+
+    return size;
+}
+
+
+// ----------------------------------------------------------------------------
+// accessing the pages
+// ----------------------------------------------------------------------------
+
+bool wxToolbook::SetPageText(size_t n, const wxString& strText)
+{
+    // Assume tool ids start from 1
+    wxToolBarToolBase* tool = GetToolBar()->FindById(n+1);
+    if (tool)
+    {
+        tool->SetLabel(strText);
+        return true;
+    }
+    else
+        return false;
+}
+
+wxString wxToolbook::GetPageText(size_t n) const
+{
+    wxToolBarToolBase* tool = GetToolBar()->FindById(n+1);
+    if (tool)
+    {
+        return tool->GetLabel();
+    }
+    else
+        return wxEmptyString;
+}
+
+int wxToolbook::GetPageImage(size_t WXUNUSED(n)) const
+{
+    wxFAIL_MSG( _T("wxToolbook::GetPageImage() not implemented") );
+
+    return wxNOT_FOUND;
+}
+
+bool wxToolbook::SetPageImage(size_t n, int imageId)
+{
+    wxASSERT( GetImageList() != NULL );
+    if (!GetImageList())
+        return false;
+    
+    wxToolBarToolBase* tool = GetToolBar()->FindById(n+1);
+    if (tool)
+    {
+        // Find the image list index for this tool
+        wxBitmap bitmap = GetImageList()->GetBitmap(imageId);
+        tool->SetNormalBitmap(bitmap);
+        return true;
+    }
+    else
+        return false;
+}
+
+// ----------------------------------------------------------------------------
+// image list stuff
+// ----------------------------------------------------------------------------
+
+void wxToolbook::SetImageList(wxImageList *imageList)
+{
+    wxBookCtrlBase::SetImageList(imageList);
+}
+
+// ----------------------------------------------------------------------------
+// selection
+// ----------------------------------------------------------------------------
+
+int wxToolbook::GetSelection() const
+{
+    return m_selection;
+}
+
+int wxToolbook::SetSelection(size_t n)
+{
+    wxCHECK_MSG( IS_VALID_PAGE(n), wxNOT_FOUND,
+                 wxT("invalid page index in wxToolbook::SetSelection()") );
+
+    const int oldSel = m_selection;
+
+    if ( int(n) != m_selection )
+    {
+        wxToolbookEvent event(wxEVT_COMMAND_TOOLBOOK_PAGE_CHANGING, m_windowId);
+        event.SetSelection(n);
+        event.SetOldSelection(m_selection);
+        event.SetEventObject(this);
+        if ( !GetEventHandler()->ProcessEvent(event) || event.IsAllowed() )
+        {
+            if ( m_selection != wxNOT_FOUND )
+                m_pages[m_selection]->Hide();
+
+            wxWindow *page = m_pages[n];
+            page->SetSize(GetPageRect());
+            page->Show();
+
+            // change m_selection now to ignore the selection change event
+            m_selection = n;
+            GetToolBar()->ToggleTool(n+1, true);
+
+            // program allows the page change
+            event.SetEventType(wxEVT_COMMAND_TOOLBOOK_PAGE_CHANGED);
+            (void)GetEventHandler()->ProcessEvent(event);
+        }
+    }
+
+    return oldSel;
+}
+
+// Not part of the wxBookctrl API, but must be called in OnIdle or
+// by application to realize the toolbar and select the initial page.
+void wxToolbook::Realize()
+{
+    if (m_needsRealizing)
+    {
+        GetToolBar()->SetToolBitmapSize(m_maxBitmapSize);
+        
+        wxSystemOptions::SetOption(wxT("msw.remap"), 0);
+        GetToolBar()->Realize();
+        wxSystemOptions::SetOption(wxT("msw.remap"), 1);
+    }
+    
+    m_needsRealizing = false;
+    
+    if (m_selection == -1)
+        m_selection = 0;
+
+    if (GetPageCount() > 0)
+    {
+        int sel = m_selection;
+        m_selection = -1;
+        SetSelection(sel);
+    }
+    
+    DoSize();
+}
+
+void wxToolbook::OnIdle(wxIdleEvent& event)
+{
+    if (m_needsRealizing)
+        Realize();
+    event.Skip();
+}
+
+// ----------------------------------------------------------------------------
+// adding/removing the pages
+// ----------------------------------------------------------------------------
+
+bool
+wxToolbook::InsertPage(size_t n,
+                       wxWindow *page,
+                       const wxString& text,
+                       bool bSelect,
+                       int imageId)
+{
+    if ( !wxBookCtrlBase::InsertPage(n, page, text, bSelect, imageId) )
+        return false;
+
+    m_needsRealizing = true;
+    
+    wxASSERT(GetImageList() != NULL);
+    
+    if (!GetImageList())
+        return false;
+
+    // On Windows, we can lose information by using GetBitmap, so extract icon instead
+    wxIcon icon = GetImageList()->GetIcon(imageId);
+    wxBitmap bitmap;
+    bitmap.CopyFromIcon(icon);
+    
+    m_maxBitmapSize.x = wxMax(bitmap.GetWidth(), m_maxBitmapSize.x);
+    m_maxBitmapSize.y = wxMax(bitmap.GetHeight(), m_maxBitmapSize.y);
+    
+    GetToolBar()->SetToolBitmapSize(m_maxBitmapSize);
+    GetToolBar()->AddRadioTool(n+1, text, bitmap, wxNullBitmap, text);
+
+    if (bSelect)
+    {
+        // GetToolBar()->ToggleTool(n, true);
+        m_selection = n;
+    }
+    else
+        page->Hide();
+
+    InvalidateBestSize();
+    return true;
+}
+
+wxWindow *wxToolbook::DoRemovePage(size_t page)
+{
+    const size_t page_count = GetPageCount();
+    wxWindow *win = wxBookCtrlBase::DoRemovePage(page);
+
+    if ( win )
+    {
+        GetToolBar()->DeleteTool(page+1);
+
+        if (m_selection >= (int)page)
+        {
+            // force new sel valid if possible
+            int sel = m_selection - 1;
+            if (page_count == 1)
+                sel = wxNOT_FOUND;
+            else if ((page_count == 2) || (sel == -1))
+                sel = 0;
+
+            // force sel invalid if deleting current page - don't try to hide it
+            m_selection = (m_selection == (int)page) ? wxNOT_FOUND : m_selection - 1;
+
+            if ((sel != wxNOT_FOUND) && (sel != m_selection))
+                SetSelection(sel);
+        }
+    }
+
+    return win;
+}
+
+
+bool wxToolbook::DeleteAllPages()
+{
+    GetToolBar()->ClearTools();
+    return wxBookCtrlBase::DeleteAllPages();
+}
+
+// ----------------------------------------------------------------------------
+// wxToolbook events
+// ----------------------------------------------------------------------------
+
+void wxToolbook::OnToolSelected(wxCommandEvent& event)
+{
+    const int selNew = event.GetId() -1;
+
+    if ( selNew == m_selection )
+    {
+        // this event can only come from our own Select(m_selection) below
+        // which we call when the page change is vetoed, so we should simply
+        // ignore it
+        return;
+    }
+
+    SetSelection(selNew);
+
+    // change wasn't allowed, return to previous state
+    if (m_selection != selNew)
+    {
+        GetToolBar()->ToggleTool(m_selection, false);
+    }
+}
+
+#endif // wxUSE_TOOLBOOK
-- 
2.50.0

