X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/45f22d48cdd5f8cc57b9ddc6f48c7c953adbb940..ca21c76b2a55252b483a3fe7e426211c229b50dc:/src/generic/notebook.cpp diff --git a/src/generic/notebook.cpp b/src/generic/notebook.cpp index b1c74e6fb6..560ea1000f 100644 --- a/src/generic/notebook.cpp +++ b/src/generic/notebook.cpp @@ -1,6 +1,6 @@ /////////////////////////////////////////////////////////////////////////////// -// Name: notebook.cpp -// Purpose: implementation of wxNotebook +// Name: src/generic/notebook.cpp +// Purpose: generic implementation of wxNotebook // Author: Julian Smart // Modified by: // Created: 17/09/98 @@ -16,55 +16,93 @@ // ---------------------------------------------------------------------------- // headers // ---------------------------------------------------------------------------- -#ifdef __GNUG__ -#pragma implementation "notebook.h" -#endif // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" #ifdef __BORLANDC__ -#pragma hdrstop + #pragma hdrstop #endif -#include "wx/string.h" -#include "wx/log.h" -#include "wx/settings.h" -#include "wx/generic/imaglist.h" +#if wxUSE_NOTEBOOK + #include "wx/notebook.h" -#include "wx/dcclient.h" + +#ifndef WX_PRECOMP + #include "wx/string.h" + #include "wx/log.h" + #include "wx/dcclient.h" + #include "wx/settings.h" +#endif + +#include "wx/imaglist.h" +#include "wx/generic/tabg.h" // ---------------------------------------------------------------------------- // macros // ---------------------------------------------------------------------------- // check that the page index is valid -#define IS_VALID_PAGE(nPage) (((nPage) >= 0) && ((nPage) < GetPageCount())) +#define IS_VALID_PAGE(nPage) ((nPage) < GetPageCount()) // ---------------------------------------------------------------------------- // event table // ---------------------------------------------------------------------------- -DEFINE_EVENT_TYPE(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED) -DEFINE_EVENT_TYPE(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING) - -BEGIN_EVENT_TABLE(wxNotebook, wxControl) - EVT_NOTEBOOK_PAGE_CHANGED(-1, wxNotebook::OnSelChange) +BEGIN_EVENT_TABLE(wxNotebook, wxBookCtrlBase) + EVT_NOTEBOOK_PAGE_CHANGED(wxID_ANY, wxNotebook::OnSelChange) EVT_SIZE(wxNotebook::OnSize) EVT_PAINT(wxNotebook::OnPaint) EVT_MOUSE_EVENTS(wxNotebook::OnMouseEvent) EVT_SET_FOCUS(wxNotebook::OnSetFocus) EVT_NAVIGATION_KEY(wxNotebook::OnNavigationKey) -// EVT_IDLE(wxNotebook::OnIdle) END_EVENT_TABLE() -IMPLEMENT_DYNAMIC_CLASS(wxNotebook, wxControl) -IMPLEMENT_DYNAMIC_CLASS(wxNotebookEvent, wxCommandEvent) - // ============================================================================ // implementation // ============================================================================ +// ============================================================================ +// Private class +// ============================================================================ + +WX_DECLARE_HASH_MAP(int, wxNotebookPage*, wxIntegerHash, wxIntegerEqual, + wxIntToNotebookPageHashMap); + +WX_DECLARE_HASH_MAP(wxNotebookPage*, int, wxPointerHash, wxPointerEqual, + wxNotebookPageToIntHashMap); + +// This reuses wxTabView to draw the tabs. +class WXDLLEXPORT wxNotebookTabView: public wxTabView +{ +DECLARE_DYNAMIC_CLASS(wxNotebookTabView) +public: + wxNotebookTabView(wxNotebook* notebook, long style = wxTAB_STYLE_DRAW_BOX | wxTAB_STYLE_COLOUR_INTERIOR); + virtual ~wxNotebookTabView(void); + + // Called when a tab is activated + virtual void OnTabActivate(int activateId, int deactivateId); + // Allows vetoing + virtual bool OnTabPreActivate(int activateId, int deactivateId); + + // map integer ids used by wxTabView to wxNotebookPage pointers + int GetId(wxNotebookPage *page); + wxNotebookPage *GetPage(int id) { return m_idToPage[id]; } + +protected: + wxNotebook* m_notebook; + +private: + wxIntToNotebookPageHashMap m_idToPage; + wxNotebookPageToIntHashMap m_pageToId; + int m_nextid; +}; + +static int GetPageId(wxTabView *tabview, wxNotebookPage *page) +{ + return static_cast(tabview)->GetId(page); +} + // ---------------------------------------------------------------------------- // wxNotebook construction // ---------------------------------------------------------------------------- @@ -72,8 +110,8 @@ IMPLEMENT_DYNAMIC_CLASS(wxNotebookEvent, wxCommandEvent) // common part of all ctors void wxNotebook::Init() { - m_tabView = (wxNotebookTabView*) NULL; - m_nSelection = -1; + m_tabView = NULL; + m_selection = -1; } // default for dynamic class @@ -106,17 +144,17 @@ bool wxNotebook::Create(wxWindow *parent, // base init SetName(name); - m_windowId = id == -1 ? NewControlId() : id; + if ( (style & wxBK_ALIGN_MASK) == wxBK_DEFAULT ) + style |= wxBK_TOP; - // It's like a normal window... - if (!wxWindow::Create(parent, id, pos, size, style|wxNO_BORDER, name)) - return FALSE; + m_windowId = id == wxID_ANY ? NewControlId() : id; - SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE)); + if (!wxControl::Create(parent, id, pos, size, style|wxNO_BORDER, wxDefaultValidator, name)) + return false; SetTabView(new wxNotebookTabView(this)); - return TRUE; + return true; } // dtor @@ -134,24 +172,24 @@ int wxNotebook::GetRowCount() const return 0; } -int wxNotebook::SetSelection(int nPage) +int wxNotebook::SetSelection(size_t nPage) { - if (nPage == -1) - return 0; - wxASSERT( IS_VALID_PAGE(nPage) ); -#if defined (__WIN16__) - m_tabView->SetTabSelection(nPage); -#else wxNotebookPage* pPage = GetPage(nPage); - m_tabView->SetTabSelection((int) (long) pPage); -#endif + m_tabView->SetTabSelection(GetPageId(m_tabView, pPage)); + // TODO return 0; } +int wxNotebook::ChangeSelection(size_t nPage) +{ + // FIXME: currently it does generate events too + return SetSelection(nPage); +} + #if 0 void wxNotebook::AdvanceSelection(bool bForward) { @@ -164,41 +202,33 @@ void wxNotebook::AdvanceSelection(bool bForward) } #endif -bool wxNotebook::SetPageText(int nPage, const wxString& strText) +bool wxNotebook::SetPageText(size_t nPage, const wxString& strText) { wxASSERT( IS_VALID_PAGE(nPage) ); -#if defined (__WIN16__) - m_tabView->SetTabText(nPage, strText); - Refresh(); - return TRUE; -#else + wxNotebookPage* page = GetPage(nPage); if (page) { - m_tabView->SetTabText((int) (long) page, strText); + m_tabView->SetTabText(GetPageId(m_tabView, page), strText); Refresh(); - return TRUE; + return true; } -#endif - return FALSE; + + return false; } -wxString wxNotebook::GetPageText(int nPage) const +wxString wxNotebook::GetPageText(size_t nPage) const { wxASSERT( IS_VALID_PAGE(nPage) ); -#if defined (__WIN16__) - return m_tabView->GetTabText(nPage); -#else wxNotebookPage* page = ((wxNotebook*)this)->GetPage(nPage); if (page) - return m_tabView->GetTabText((int) (long) page); + return m_tabView->GetTabText(GetPageId(m_tabView, page)); else return wxEmptyString; -#endif } -int wxNotebook::GetPageImage(int nPage) const +int wxNotebook::GetPageImage(size_t WXUNUSED_UNLESS_DEBUG(nPage)) const { wxASSERT( IS_VALID_PAGE(nPage) ); @@ -206,12 +236,31 @@ int wxNotebook::GetPageImage(int nPage) const return 0; } -bool wxNotebook::SetPageImage(int nPage, int nImage) +bool wxNotebook::SetPageImage(size_t WXUNUSED_UNLESS_DEBUG(nPage), + int WXUNUSED(nImage)) { wxASSERT( IS_VALID_PAGE(nPage) ); // TODO - return FALSE; + return false; +} + +// set the size (the same for all pages) +void wxNotebook::SetPageSize(const wxSize& WXUNUSED(size)) +{ + // TODO +} + +// set the padding between tabs (in pixels) +void wxNotebook::SetPadding(const wxSize& WXUNUSED(padding)) +{ + // TODO +} + +// set the size of the tabs for wxNB_FIXEDWIDTH controls +void wxNotebook::SetTabSize(const wxSize& WXUNUSED(sz)) +{ + // TODO } // ---------------------------------------------------------------------------- @@ -219,46 +268,41 @@ bool wxNotebook::SetPageImage(int nPage, int nImage) // ---------------------------------------------------------------------------- // remove one page from the notebook and delete it -bool wxNotebook::DeletePage(int nPage) +bool wxNotebook::DeletePage(size_t nPage) { - wxCHECK( IS_VALID_PAGE(nPage), FALSE ); + wxCHECK( IS_VALID_PAGE(nPage), false ); - if (m_nSelection != -1) + if (m_selection != -1) { - m_pages[m_nSelection]->Show(FALSE); - m_pages[m_nSelection]->Lower(); + m_pages[m_selection]->Show(false); + m_pages[m_selection]->Lower(); } wxNotebookPage* pPage = GetPage(nPage); -#if defined (__WIN16__) - m_tabView->RemoveTab(nPage); -#else - m_tabView->RemoveTab((int) (long) pPage); -#endif + + m_tabView->RemoveTab(GetPageId(m_tabView, pPage)); m_pages.Remove(pPage); delete pPage; if (m_pages.GetCount() == 0) { - m_nSelection = -1; - m_tabView->SetTabSelection(-1, FALSE); + m_selection = -1; + m_tabView->SetTabSelection(-1, false); } - else if (m_nSelection > -1) + else if (m_selection > -1) { - m_nSelection = -1; -#if defined (__WIN16__) - m_tabView->SetTabSelection(0, FALSE); -#else - m_tabView->SetTabSelection((int) (long) GetPage(0), FALSE); -#endif - if (m_nSelection != 0) - ChangePage(-1, 0); + m_selection = -1; + + m_tabView->SetTabSelection(GetPageId(m_tabView, GetPage(0)), false); + + if (m_selection != 0) + ChangePage(-1, 0); } - RefreshLayout(FALSE); + RefreshLayout(false); - return TRUE; + return true; } bool wxNotebook::DeletePage(wxNotebookPage* page) @@ -267,54 +311,56 @@ bool wxNotebook::DeletePage(wxNotebookPage* page) if (pagePos > -1) return DeletePage(pagePos); else - return FALSE; + return false; +} + +bool wxNotebook::RemovePage(size_t nPage) +{ + return DoRemovePage(nPage) != NULL; } // remove one page from the notebook -bool wxNotebook::RemovePage(int nPage) +wxWindow* wxNotebook::DoRemovePage(size_t nPage) { - wxCHECK( IS_VALID_PAGE(nPage), FALSE ); + wxCHECK( IS_VALID_PAGE(nPage), NULL ); - m_pages[nPage]->Show(FALSE); + m_pages[nPage]->Show(false); // m_pages[nPage]->Lower(); wxNotebookPage* pPage = GetPage(nPage); -#if defined (__WIN16__) - m_tabView->RemoveTab(nPage); -#else - m_tabView->RemoveTab((int) (long) pPage); -#endif + + m_tabView->RemoveTab(GetPageId(m_tabView, pPage)); m_pages.Remove(pPage); if (m_pages.GetCount() == 0) { - m_nSelection = -1; - m_tabView->SetTabSelection(-1, TRUE); + m_selection = -1; + m_tabView->SetTabSelection(-1, true); } - else if (m_nSelection > -1) + else if (m_selection > -1) { // Only change the selection if the page we // deleted was the selection. - if (nPage == m_nSelection) + if (nPage == (size_t)m_selection) { - m_nSelection = -1; + m_selection = -1; // Select the first tab. Generates a ChangePage. - m_tabView->SetTabSelection((int) (long) GetPage(0), TRUE); + m_tabView->SetTabSelection(0, true); } else { - // We must adjust which tab we think is selected. + // We must adjust which tab we think is selected. // If greater than the page we deleted, it must be moved down // a notch. - if (m_nSelection > nPage) - m_nSelection -- ; + if (size_t(m_selection) > nPage) + m_selection -- ; } } - RefreshLayout(FALSE); + RefreshLayout(false); - return TRUE; + return pPage; } bool wxNotebook::RemovePage(wxNotebookPage* page) @@ -323,14 +369,14 @@ bool wxNotebook::RemovePage(wxNotebookPage* page) if (pagePos > -1) return RemovePage(pagePos); else - return FALSE; + return false; } // Find the position of the wxNotebookPage, -1 if not found. int wxNotebook::FindPagePosition(wxNotebookPage* page) const { - int nPageCount = GetPageCount(); - int nPage; + size_t nPageCount = GetPageCount(); + size_t nPage; for ( nPage = 0; nPage < nPageCount; nPage++ ) if (m_pages[nPage] == page) return nPage; @@ -340,36 +386,32 @@ int wxNotebook::FindPagePosition(wxNotebookPage* page) const // remove all pages bool wxNotebook::DeleteAllPages() { - m_tabView->ClearTabs(TRUE); + m_tabView->ClearTabs(true); - int nPageCount = GetPageCount(); - int nPage; + size_t nPageCount = GetPageCount(); + size_t nPage; for ( nPage = 0; nPage < nPageCount; nPage++ ) delete m_pages[nPage]; m_pages.Clear(); - return TRUE; + return true; } // same as AddPage() but does it at given position -bool wxNotebook::InsertPage(int nPage, +bool wxNotebook::InsertPage(size_t nPage, wxNotebookPage *pPage, const wxString& strText, bool bSelect, - int imageId) + int WXUNUSED(imageId)) { wxASSERT( pPage != NULL ); - wxCHECK( IS_VALID_PAGE(nPage) || nPage == GetPageCount(), FALSE ); + wxCHECK( IS_VALID_PAGE(nPage) || nPage == GetPageCount(), false ); + + m_tabView->AddTab(GetPageId(m_tabView, pPage), strText); -// For 16 bit integers (tabs limited to 32768) -#if defined (__WIN16__) - m_tabView->AddTab(nPage, strText); -#else - m_tabView->AddTab((int) (long) pPage, strText); -#endif if (!bSelect) - pPage->Show(FALSE); + pPage->Show(false); // save the pointer to the page m_pages.Insert(pPage, nPage); @@ -377,21 +419,18 @@ bool wxNotebook::InsertPage(int nPage, if (bSelect) { // This will cause ChangePage to be called, via OnSelPage -#if defined (__WIN16__) - m_tabView->SetTabSelection(nPage, TRUE); -#else - m_tabView->SetTabSelection((int) (long) pPage, TRUE); -#endif + + m_tabView->SetTabSelection(GetPageId(m_tabView, pPage), true); } // some page must be selected: either this one or the first one if there is // still no selection - if ( m_nSelection == -1 ) + if ( m_selection == -1 ) ChangePage(-1, 0); - RefreshLayout(FALSE); + RefreshLayout(false); - return TRUE; + return true; } // ---------------------------------------------------------------------------- @@ -402,10 +441,10 @@ bool wxNotebook::InsertPage(int nPage, // time because doing it in ::Create() doesn't work (for unknown reasons) void wxNotebook::OnSize(wxSizeEvent& event) { - static bool s_bFirstTime = TRUE; + static bool s_bFirstTime = true; if ( s_bFirstTime ) { // TODO: any first-time-size processing. - s_bFirstTime = FALSE; + s_bFirstTime = false; } RefreshLayout(); @@ -417,9 +456,12 @@ void wxNotebook::OnSize(wxSizeEvent& event) // This was supposed to cure the non-display of the notebook // until the user resizes the window. // What's going on? -void wxNotebook::OnIdle(wxIdleEvent& event) +void wxNotebook::OnInternalIdle() { - static bool s_bFirstTime = TRUE; + wxWindow::OnInternalIdle(); + +#if 0 + static bool s_bFirstTime = true; if ( s_bFirstTime ) { /* wxSize sz(GetSize()); @@ -436,9 +478,9 @@ void wxNotebook::OnIdle(wxIdleEvent& event) GetEventHandler()->ProcessEvent(sizeEvent); Refresh(); */ - s_bFirstTime = FALSE; + s_bFirstTime = false; } - event.Skip(); +#endif } // Implementation: calculate the layout of the view rect @@ -477,16 +519,16 @@ bool wxNotebook::RefreshLayout(bool force) m_tabView->LayoutTabs(); if (!force && (rect == oldRect)) - return FALSE; + return false; // fit the notebook page to the tab control's display area - unsigned int nCount = m_pages.Count(); - for ( unsigned int nPage = 0; nPage < nCount; nPage++ ) { + size_t nCount = m_pages.Count(); + for ( size_t nPage = 0; nPage < nCount; nPage++ ) { wxNotebookPage *pPage = m_pages[nPage]; + wxRect clientRect = GetAvailableClientSize(); if (pPage->IsShown()) { - wxRect clientRect = GetAvailableClientSize(); pPage->SetSize(clientRect.x, clientRect.y, clientRect.width, clientRect.height); if ( pPage->GetAutoLayout() ) pPage->Layout(); @@ -494,15 +536,15 @@ bool wxNotebook::RefreshLayout(bool force) } Refresh(); } - return TRUE; + return true; } -void wxNotebook::OnSelChange(wxNotebookEvent& event) +void wxNotebook::OnSelChange(wxBookCtrlEvent& event) { // is it our tab control? if ( event.GetEventObject() == this ) { - if (event.GetSelection() != m_nSelection) + if (event.GetSelection() != m_selection) ChangePage(event.GetOldSelection(), event.GetSelection()); } @@ -513,23 +555,25 @@ void wxNotebook::OnSelChange(wxNotebookEvent& event) void wxNotebook::OnSetFocus(wxFocusEvent& event) { // set focus to the currently selected page if any - if ( m_nSelection != -1 ) - m_pages[m_nSelection]->SetFocus(); + if ( m_selection != -1 ) + m_pages[m_selection]->SetFocus(); event.Skip(); } void wxNotebook::OnNavigationKey(wxNavigationKeyEvent& event) { - if ( event.IsWindowChange() ) { + if ( event.IsWindowChange() ) + { // change pages AdvanceSelection(event.GetDirection()); } else { // pass to the parent - if ( GetParent() ) { + if ( GetParent() ) + { event.SetCurrentFocus(this); - GetParent()->ProcessEvent(event); + GetParent()->ProcessWindowEvent(event); } } } @@ -543,17 +587,17 @@ void wxNotebook::OnNavigationKey(wxNavigationKeyEvent& event) void wxNotebook::SetConstraintSizes(bool /* recurse */) { // don't set the sizes of the pages - their correct size is not yet known - wxControl::SetConstraintSizes(FALSE); + wxControl::SetConstraintSizes(false); } bool wxNotebook::DoPhase(int /* nPhase */) { - return TRUE; + return true; } void wxNotebook::Command(wxCommandEvent& WXUNUSED(event)) { - wxFAIL_MSG("wxNotebook::Command not implemented"); + wxFAIL_MSG(wxT("wxNotebook::Command not implemented")); } // ---------------------------------------------------------------------------- @@ -567,7 +611,7 @@ void wxNotebook::ChangePage(int nOldSel, int nSel) wxASSERT( nOldSel != nSel ); // impossible if ( nOldSel != -1 ) { - m_pages[nOldSel]->Show(FALSE); + m_pages[nOldSel]->Show(false); m_pages[nOldSel]->Lower(); } @@ -578,11 +622,11 @@ void wxNotebook::ChangePage(int nOldSel, int nSel) Refresh(); - pPage->Show(TRUE); + pPage->Show(true); pPage->Raise(); pPage->SetFocus(); - m_nSelection = nSel; + m_selection = nSel; } void wxNotebook::OnMouseEvent(wxMouseEvent& event) @@ -598,6 +642,17 @@ void wxNotebook::OnPaint(wxPaintEvent& WXUNUSED(event) ) m_tabView->Draw(dc); } +wxSize wxNotebook::CalcSizeFromPage(const wxSize& sizePage) const +{ + // MBN: since the total tab height is really a function of the + // width, this should really call + // GetTotalTabHeightPretendingWidthIs(), but the current + // implementation will suffice, provided the wxNotebook has been + // created with a sensible initial width. + return wxSize( sizePage.x + 12, + sizePage.y + m_tabView->GetTotalTabHeight() + 6 + 4 ); +} + wxRect wxNotebook::GetAvailableClientSize() { int cw, ch; @@ -621,7 +676,8 @@ wxRect wxNotebook::GetAvailableClientSize() IMPLEMENT_CLASS(wxNotebookTabView, wxTabView) -wxNotebookTabView::wxNotebookTabView(wxNotebook *notebook, long style): wxTabView(style) +wxNotebookTabView::wxNotebookTabView(wxNotebook *notebook, long style) + : wxTabView(style), m_nextid(1) { m_notebook = notebook; @@ -634,31 +690,67 @@ wxNotebookTabView::~wxNotebookTabView(void) { } +int wxNotebookTabView::GetId(wxNotebookPage *page) +{ + int& id = m_pageToId[page]; + + if (!id) + { + id = m_nextid++; + m_idToPage[id] = page; + } + + return id; +} + // Called when a tab is activated void wxNotebookTabView::OnTabActivate(int activateId, int deactivateId) { if (!m_notebook) return; - wxNotebookEvent event(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED, m_notebook->GetId()); + wxBookCtrlEvent event(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED, m_notebook->GetId()); -#if defined (__WIN16__) - int activatePos = activateId; - int deactivatePos = deactivateId; -#else // Translate from wxTabView's ids (which aren't position-dependent) // to wxNotebook's (which are). - wxNotebookPage* pActive = (wxNotebookPage*) activateId; - wxNotebookPage* pDeactive = (wxNotebookPage*) deactivateId; + wxNotebookPage* pActive = GetPage(activateId); + wxNotebookPage* pDeactive = GetPage(deactivateId); int activatePos = m_notebook->FindPagePosition(pActive); int deactivatePos = m_notebook->FindPagePosition(pDeactive); -#endif event.SetEventObject(m_notebook); event.SetSelection(activatePos); event.SetOldSelection(deactivatePos); m_notebook->GetEventHandler()->ProcessEvent(event); } +// Allows Vetoing +bool wxNotebookTabView::OnTabPreActivate(int activateId, int deactivateId) +{ + bool retval = true; + + if (m_notebook) + { + wxBookCtrlEvent event(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING, m_notebook->GetId()); + + // Translate from wxTabView's ids (which aren't position-dependent) + // to wxNotebook's (which are). + wxNotebookPage* pActive = GetPage(activateId); + wxNotebookPage* pDeactive = GetPage(deactivateId); + + int activatePos = m_notebook->FindPagePosition(pActive); + int deactivatePos = m_notebook->FindPagePosition(pDeactive); + + event.SetEventObject(m_notebook); + event.SetSelection(activatePos); + event.SetOldSelection(deactivatePos); + if (m_notebook->GetEventHandler()->ProcessEvent(event)) + { + retval = event.IsAllowed(); + } + } + return retval; +} +#endif // wxUSE_NOTEBOOK