///////////////////////////////////////////////////////////////////////////////
-// Name: notebook.cpp
+// Name: src/os2/notebook.cpp
// Purpose: implementation of wxNotebook
// Author: David Webster
-// Modified by:
+// Modified by:
// Created: 10/12/99
// RCS-ID: $Id$
// Copyright: (c) David Webster
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
-// wxWindows
+#if wxUSE_NOTEBOOK
+
+#include "wx/notebook.h"
+
+// wxWidgets
#ifndef WX_PRECOMP
- #include <wx/string.h>
+ #include "wx/app.h"
+ #include "wx/dcclient.h"
+ #include "wx/string.h"
+ #include "wx/settings.h"
+ #include "wx/log.h"
+ #include "wx/event.h"
+ #include "wx/control.h"
#endif // WX_PRECOMP
-#include <wx/log.h>
-#include <wx/imaglist.h>
-#include <wx/event.h>
-#include <wx/control.h>
-#include <wx/notebook.h>
-
-#include <wx/os2/private.h>
+#include "wx/imaglist.h"
+#include "wx/os2/private.h"
// ----------------------------------------------------------------------------
// macros
// ----------------------------------------------------------------------------
+
// check that the page index is valid
-#define IS_VALID_PAGE(nPage) (((nPage) >= 0) && ((nPage) < GetPageCount()))
+#define IS_VALID_PAGE(nPage) ( \
+ /* size_t is _always_ >= 0 */ \
+ /* ((nPage) >= 0) && */ \
+ ((nPage) < GetPageCount()) \
+ )
// hide the ugly cast
-#define m_hwnd (HWND)GetHWND()
+#define m_hWnd (HWND)GetHWND()
// ----------------------------------------------------------------------------
// constants
// ----------------------------------------------------------------------------
-// This is a work-around for missing defines in gcc-2.95 headers
-#ifndef TCS_RIGHT
- #define TCS_RIGHT 0x0002
-#endif
-
-#ifndef TCS_VERTICAL
- #define TCS_VERTICAL 0x0080
-#endif
-
-#ifndef TCS_BOTTOM
- #define TCS_BOTTOM TCS_RIGHT
-#endif
-
// ----------------------------------------------------------------------------
// event table
// ----------------------------------------------------------------------------
-#if !USE_SHARED_LIBRARIES
- BEGIN_EVENT_TABLE(wxNotebook, wxControl)
- EVT_NOTEBOOK_PAGE_CHANGED(-1, wxNotebook::OnSelChange)
+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(wxID_ANY, wxNotebook::OnSelChange)
EVT_SIZE(wxNotebook::OnSize)
EVT_SET_FOCUS(wxNotebook::OnSetFocus)
EVT_NAVIGATION_KEY(wxNotebook::OnNavigationKey)
- END_EVENT_TABLE()
+END_EVENT_TABLE()
- IMPLEMENT_DYNAMIC_CLASS(wxNotebook, wxControl)
- IMPLEMENT_DYNAMIC_CLASS(wxNotebookEvent, wxNotifyEvent)
-#endif
+IMPLEMENT_DYNAMIC_CLASS(wxNotebook, wxControl)
+IMPLEMENT_DYNAMIC_CLASS(wxNotebookEvent, wxNotifyEvent)
// ============================================================================
// implementation
// wxNotebook construction
// ----------------------------------------------------------------------------
-// common part of all ctors
+//
+// Common part of all ctors
+//
void wxNotebook::Init()
{
- m_pImageList = NULL;
+ m_imageList = NULL;
m_nSelection = -1;
-}
+ m_nTabSize = 0;
+} // end of wxNotebook::Init
-// default for dynamic class
+//
+// Default for dynamic class
+//
wxNotebook::wxNotebook()
{
Init();
-}
-
-// the same arguments as for wxControl
-wxNotebook::wxNotebook(wxWindow *parent,
- wxWindowID id,
- const wxPoint& pos,
- const wxSize& size,
- long style,
- const wxString& name)
+} // end of wxNotebook::wxNotebook
+
+//
+// The same arguments as for wxControl
+//
+wxNotebook::wxNotebook(
+ wxWindow* pParent
+, wxWindowID vId
+, const wxPoint& rPos
+, const wxSize& rSize
+, long lStyle
+, const wxString& rsName
+)
{
Init();
-
- Create(parent, id, pos, size, style, name);
-}
-
+ Create( pParent
+ ,vId
+ ,rPos
+ ,rSize
+ ,lStyle
+ ,rsName
+ );
+} // end of wxNotebook::wxNotebook
+
+//
// Create() function
-bool wxNotebook::Create(wxWindow *parent,
- wxWindowID id,
- const wxPoint& pos,
- const wxSize& size,
- long style,
- const wxString& name)
+//
+bool wxNotebook::Create( wxWindow* pParent,
+ wxWindowID vId,
+ const wxPoint& rPos,
+ const wxSize& rSize,
+ long lStyle,
+ const wxString& rsName )
{
- // base init
- if ( !CreateBase(parent, id, pos, size, style, wxDefaultValidator, name) )
- return FALSE;
-
- // colors and font
- m_backgroundColour = wxColour(GetSysColor(COLOR_BTNFACE));
- m_foregroundColour = *wxBLACK ;
-
- // TODO:
-/*
- // style
- m_windowStyle = style | wxTAB_TRAVERSAL;
-
- long tabStyle = WS_CHILD | WS_VISIBLE | WS_TABSTOP | TCS_TABS;
-
- if (m_windowStyle & wxCLIP_CHILDREN)
- tabStyle |= WS_CLIPCHILDREN;
- if ( m_windowStyle & wxTC_MULTILINE )
- tabStyle |= TCS_MULTILINE;
- if ( m_windowStyle & wxBORDER )
- tabStyle &= WS_BORDER;
- if (m_windowStyle & wxNB_FIXEDWIDTH)
- tabStyle |= TCS_FIXEDWIDTH ;
- if (m_windowStyle & wxNB_BOTTOM)
- tabStyle |= TCS_RIGHT;
- if (m_windowStyle & wxNB_LEFT)
- tabStyle |= TCS_VERTICAL;
- if (m_windowStyle & wxNB_RIGHT)
- tabStyle |= TCS_VERTICAL|TCS_RIGHT;
-
-
- if ( !MSWCreate(GetId(), GetParent(), WC_TABCONTROL,
- this, NULL, pos.x, pos.y, size.x, size.y,
- tabStyle, NULL, 0) )
- {
- return FALSE;
- }
-
- // Not all compilers recognise SetWindowFont
- ::SendMessage(GetHwnd(), WM_SETFONT,
- (WPARAM)::GetStockObject(DEFAULT_GUI_FONT), TRUE);
-
-
- if ( parent != NULL )
- parent->AddChild(this);
-*/
- SubclassWin(m_hWnd);
-
- return FALSE;
-}
-
-// dtor
-wxNotebook::~wxNotebook()
+ if ( (lStyle & wxBK_ALIGN_MASK) == wxBK_DEFAULT )
+ lStyle |= wxBK_TOP;
+ //
+ // Base init
+ //
+ if (!CreateControl( pParent
+ ,vId
+ ,rPos
+ ,rSize
+ ,lStyle
+ ,wxDefaultValidator
+ ,rsName
+ ))
+ return false;
+
+ //
+ // Notebook, so explicitly specify 0 as last parameter
+ //
+ if (!OS2CreateControl( wxT("NOTEBOOK")
+ ,wxEmptyString
+ ,rPos
+ ,rSize
+ ,lStyle | wxTAB_TRAVERSAL
+ ))
+ return false;
+
+ SetBackgroundColour(wxColour(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE)));
+ return true;
+} // end of wxNotebook::Create
+
+WXDWORD wxNotebook::OS2GetStyle (
+ long lStyle
+, WXDWORD* pdwExstyle
+) const
{
-}
+ WXDWORD dwTabStyle = wxControl::OS2GetStyle( lStyle
+ ,pdwExstyle
+ );
+
+ dwTabStyle |= WS_TABSTOP | BKS_SOLIDBIND | BKS_ROUNDEDTABS | BKS_TABTEXTCENTER | BKS_TABBEDDIALOG;
+
+ if (lStyle & wxBK_BOTTOM)
+ dwTabStyle |= BKS_MAJORTABBOTTOM | BKS_BACKPAGESBL;
+ else if (lStyle & wxBK_RIGHT)
+ dwTabStyle |= BKS_MAJORTABRIGHT | BKS_BACKPAGESBR;
+ else if (lStyle & wxBK_LEFT)
+ dwTabStyle |= BKS_MAJORTABLEFT | BKS_BACKPAGESTL;
+ else // default to top
+ dwTabStyle |= BKS_MAJORTABTOP | BKS_BACKPAGESTR;
+
+ //
+ // Ex style
+ //
+ if (pdwExstyle )
+ {
+ //
+ // Note that we never want to have the default WS_EX_CLIENTEDGE style
+ // as it looks too ugly for the notebooks
+ //
+ *pdwExstyle = 0;
+ }
+ return dwTabStyle;
+} // end of wxNotebook::OS2GetStyle
// ----------------------------------------------------------------------------
// wxNotebook accessors
// ----------------------------------------------------------------------------
-int wxNotebook::GetPageCount() const
+
+size_t wxNotebook::GetPageCount() const
{
- return m_aPages.Count();
-}
+ //
+ // Consistency check
+ //
+ wxASSERT((int)m_pages.Count() == (int)::WinSendMsg(GetHWND(), BKM_QUERYPAGECOUNT, (MPARAM)0, (MPARAM)BKA_END));
+ return m_pages.Count();
+} // end of wxNotebook::GetPageCount
int wxNotebook::GetRowCount() const
{
- // TODO
- return 0;
-}
-
-int wxNotebook::SetSelection(int nPage)
+ return (int)::WinSendMsg( GetHWND()
+ ,BKM_QUERYPAGECOUNT
+ ,(MPARAM)0
+ ,(MPARAM)BKA_MAJOR
+ );
+} // end of wxNotebook::GetRowCount
+
+int wxNotebook::SetSelection( size_t nPage )
{
- wxCHECK_MSG( IS_VALID_PAGE(nPage), -1, wxT("notebook page out of range") );
-
- ChangePage(m_nSelection, nPage);
+ wxCHECK_MSG( IS_VALID_PAGE(nPage), wxNOT_FOUND, wxT("notebook page out of range") );
- // TODO
- return 0;
-}
+ if (nPage != (size_t)m_nSelection)
+ {
+ wxNotebookEvent vEvent( wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING
+ ,m_windowId
+ );
+
+ vEvent.SetSelection(nPage);
+ vEvent.SetOldSelection(m_nSelection);
+ vEvent.SetEventObject(this);
+ if (!GetEventHandler()->ProcessEvent(vEvent) || vEvent.IsAllowed())
+ {
-void wxNotebook::AdvanceSelection(bool bForward)
-{
- int nSel = GetSelection();
- int nMax = GetPageCount() - 1;
- if ( bForward )
- SetSelection(nSel == nMax ? 0 : nSel + 1);
- else
- SetSelection(nSel == 0 ? nMax : nSel - 1);
-}
+ //
+ // Program allows the page change
+ //
+ vEvent.SetEventType(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED);
+ GetEventHandler()->ProcessEvent(vEvent);
+
+ ::WinSendMsg( GetHWND()
+ ,BKM_TURNTOPAGE
+ ,MPFROMLONG((ULONG)m_alPageId[nPage])
+ ,(MPARAM)0
+ );
+ }
+ }
+ m_nSelection = nPage;
+ return nPage;
+} // end of wxNotebook::SetSelection
-bool wxNotebook::SetPageText(int nPage, const wxString& strText)
+int wxNotebook::ChangeSelection( size_t nPage )
{
- wxCHECK_MSG( IS_VALID_PAGE(nPage), FALSE, wxT("notebook page out of range") );
+ wxCHECK_MSG( IS_VALID_PAGE(nPage), wxNOT_FOUND, wxT("notebook page out of range") );
- // TODO
- return FALSE;
+ if (nPage != (size_t)m_nSelection)
+ {
+ ::WinSendMsg( GetHWND()
+ ,BKM_TURNTOPAGE
+ ,MPFROMLONG((ULONG)m_alPageId[nPage])
+ ,(MPARAM)0
+ );
+ }
+ m_nSelection = nPage;
+ return nPage;
}
-wxString wxNotebook::GetPageText(int nPage) const
+bool wxNotebook::SetPageText( size_t nPage,
+ const wxString& rsStrText )
{
- wxCHECK_MSG( IS_VALID_PAGE(nPage), wxT(""), wxT("notebook page out of range") );
-
- // TODO
- return wxString("");
-}
-
-int wxNotebook::GetPageImage(int nPage) const
+ wxCHECK_MSG( IS_VALID_PAGE(nPage), false, wxT("notebook page out of range") );
+ return (bool)::WinSendMsg( m_hWnd
+ ,BKM_SETTABTEXT
+ ,MPFROMLONG((ULONG)m_alPageId[nPage])
+ ,MPFROMP((PSZ)rsStrText.c_str())
+ );
+} // end of wxNotebook::SetPageText
+
+wxString wxNotebook::GetPageText ( size_t nPage ) const
{
- wxCHECK_MSG( IS_VALID_PAGE(nPage), -1, wxT("notebook page out of range") );
+ BOOKTEXT vBookText;
+ wxChar zBuf[256];
+ wxString sStr;
+ ULONG ulRc;
+
+ wxCHECK_MSG( IS_VALID_PAGE(nPage), wxEmptyString, wxT("notebook page out of range") );
+
+ memset(&vBookText, '\0', sizeof(BOOKTEXT));
+ vBookText.textLen = 0; // This will get the length
+ ulRc = LONGFROMMR(::WinSendMsg( m_hWnd
+ ,BKM_QUERYTABTEXT
+ ,MPFROMLONG((ULONG)m_alPageId[nPage])
+ ,MPFROMP(&vBookText)
+ ));
+ if (ulRc == (ULONG)BOOKERR_INVALID_PARAMETERS || ulRc == 0L)
+ {
+ if (ulRc == (ULONG)BOOKERR_INVALID_PARAMETERS)
+ {
+ wxLogError(wxT("Invalid Page Id for page text querry."));
+ }
+ return wxEmptyString;
+ }
+ vBookText.textLen = ulRc + 1; // To get the null terminator
+ vBookText.pString = (char*)zBuf;
+
+ //
+ // Now get the actual text
+ //
+ ulRc = LONGFROMMR(::WinSendMsg( m_hWnd
+ ,BKM_QUERYTABTEXT
+ ,MPFROMLONG((ULONG)m_alPageId[nPage])
+ ,MPFROMP(&vBookText)
+ ));
+ if (ulRc == (ULONG)BOOKERR_INVALID_PARAMETERS || ulRc == 0L)
+ {
+ return wxEmptyString;
+ }
+ if (ulRc > 255L)
+ ulRc = 255L;
- // TODO
- return 0;
-}
+ vBookText.pString[ulRc] = '\0';
+ sStr = (wxChar*)vBookText.pString;
+ return sStr;
+} // end of wxNotebook::GetPageText
-bool wxNotebook::SetPageImage(int nPage, int nImage)
+int wxNotebook::GetPageImage ( size_t nPage ) const
{
- wxCHECK_MSG( IS_VALID_PAGE(nPage), FALSE, wxT("notebook page out of range") );
-
- // TODO
- return FALSE;
-}
+ wxCHECK_MSG( IS_VALID_PAGE(nPage), wxNOT_FOUND, wxT("notebook page out of range") );
+
+ //
+ // For OS/2 just return the page
+ //
+ return nPage;
+} // end of wxNotebook::GetPageImage
+
+bool wxNotebook::SetPageImage (
+ size_t nPage
+, int nImage
+)
+{
+ wxBitmap vBitmap = (wxBitmap)m_imageList->GetBitmap(nImage);
+
+ return (bool)::WinSendMsg( GetHWND()
+ ,BKM_SETTABBITMAP
+ ,MPFROMLONG((ULONG)m_alPageId[nPage])
+ ,(MPARAM)wxFlipBmp(vBitmap.GetHBITMAP())
+ );
+} // end of wxNotebook::SetPageImage
+
+void wxNotebook::SetImageList (
+ wxImageList* pImageList
+)
+{
+ //
+ // Does not really do anything yet, but at least we need to
+ // update the base class.
+ //
+ wxNotebookBase::SetImageList(pImageList);
+} // end of wxNotebook::SetImageList
-void wxNotebook::SetImageList(wxImageList* imageList)
-{
- m_pImageList = imageList;
- // TODO
-}
+// ----------------------------------------------------------------------------
+// wxNotebook size settings
+// ----------------------------------------------------------------------------
+void wxNotebook::SetPageSize (
+ const wxSize& rSize
+)
+{
+ SetSize(rSize);
+} // end of wxNotebook::SetPageSize
-void wxNotebook::SetTabSize(const wxSize& sz)
+void wxNotebook::SetPadding (
+ const wxSize& WXUNUSED(rPadding)
+)
{
- // TODO
-}
+ //
+ // No padding in OS/2
+ //
+} // end of wxNotebook::SetPadding
+
+void wxNotebook::SetTabSize (
+ const wxSize& rSize
+)
+{
+ ::WinSendMsg( GetHWND()
+ ,BKM_SETDIMENSIONS
+ ,MPFROM2SHORT( (USHORT)rSize.x
+ ,(USHORT)rSize.y
+ )
+ ,(MPARAM)BKA_MAJORTAB
+ );
+} // end of wxNotebook::SetTabSize
// ----------------------------------------------------------------------------
// wxNotebook operations
// ----------------------------------------------------------------------------
-// remove one page from the notebook
-bool wxNotebook::DeletePage(int nPage)
+//
+// Remove one page from the notebook, without deleting
+//
+wxNotebookPage* wxNotebook::DoRemovePage ( size_t nPage )
{
- wxCHECK_MSG( IS_VALID_PAGE(nPage), FALSE, wxT("notebook page out of range") );
+ wxNotebookPage* pPageRemoved = wxNotebookBase::DoRemovePage(nPage);
- // TODO: delete native widget page
+ if (!pPageRemoved)
+ return NULL;
- delete m_aPages[nPage];
- m_aPages.Remove(nPage);
+ ::WinSendMsg( GetHWND()
+ ,BKM_DELETEPAGE
+ ,MPFROMLONG((ULONG)m_alPageId[nPage])
+ ,(MPARAM)BKA_TAB
+ );
+ if (m_pages.IsEmpty())
+ {
+ //
+ // No selection any more, the notebook becamse empty
+ //
+ m_nSelection = -1;
+ }
+ else // notebook still not empty
+ {
+ //
+ // Change the selected page if it was deleted or became invalid
+ //
+ int nSelNew;
- return TRUE;
-}
+ if (m_nSelection == (int)GetPageCount())
+ {
+ //
+ // Last page deleted, make the new last page the new selection
+ //
+ nSelNew = m_nSelection - 1;
+ }
+ else if (nPage <= (size_t)m_nSelection)
+ {
+ //
+ // We must show another page, even if it has the same index
+ //
+ nSelNew = m_nSelection;
+ }
+ else // nothing changes for the currently selected page
+ {
+ nSelNew = -1;
+
+ //
+ // We still must refresh the current page: this needs to be done
+ // for some unknown reason if the tab control shows the up-down
+ // control (i.e. when there are too many pages) -- otherwise after
+ // deleting a page nothing at all is shown
+ //
+ m_pages[m_nSelection]->Refresh();
+ }
+
+ if (nSelNew != -1)
+ {
+ //
+ // m_nSelection must be always valid so reset it before calling
+ // SetSelection()
+ //
+ m_nSelection = -1;
+ SetSelection(nSelNew);
+ }
+ }
+ return pPageRemoved;
+} // end of wxNotebook::DoRemovePage
-// remove one page from the notebook, without deleting the window
-bool wxNotebook::RemovePage(int nPage)
+//
+// Remove all pages
+//
+bool wxNotebook::DeleteAllPages()
{
- wxCHECK_MSG( IS_VALID_PAGE(nPage), FALSE, wxT("notebook page out of range") );
+ int nPageCount = GetPageCount();
+ int nPage;
+
+ for (nPage = 0; nPage < nPageCount; nPage++)
+ delete m_pages[nPage];
+ m_pages.Clear();
+ ::WinSendMsg( GetHWND()
+ ,BKM_DELETEPAGE
+ ,(MPARAM)0
+ ,(MPARAM)BKA_ALL
+ );
+ m_nSelection = -1;
- m_aPages.Remove(nPage);
+ return true;
+} // end of wxNotebook::DeleteAllPages
+
+//
+// Add a page to the notebook
+//
+bool wxNotebook::AddPage (
+ wxNotebookPage* pPage
+, const wxString& rStrText
+, bool bSelect
+, int nImageId
+)
+{
+ return InsertPage( GetPageCount()
+ ,pPage
+ ,rStrText
+ ,bSelect
+ ,nImageId
+ );
+} // end of wxNotebook::AddPage
+
+//
+// Same as AddPage() but does it at given position
+//
+bool wxNotebook::InsertPage ( size_t nPage,
+ wxNotebookPage* pPage,
+ const wxString& rsStrText,
+ bool bSelect,
+ int nImageId )
+{
+ ULONG ulApiPage;
- return TRUE;
-}
+ wxASSERT( pPage != NULL );
+ wxCHECK( IS_VALID_PAGE(nPage) || nPage == GetPageCount(), false );
+
+ //
+ // Under OS/2 we can only insert FIRST, LAST, NEXT or PREV. Requires
+ // two different calls to the API. Page 1 uses the BKA_FIRST. Subsequent
+ // pages use the previous page ID coupled with a BKA_NEXT call. Unlike
+ // Windows, OS/2 uses an internal Page ID to ID the pages.
+ //
+ // OS/2 also has a nice auto-size feature that automatically sizes the
+ // the attached window so we don't have to worry about the size of the
+ // window on the page.
+ //
+ if (nPage == 0)
+ {
+ ulApiPage = LONGFROMMR(::WinSendMsg( GetHWND()
+ ,BKM_INSERTPAGE
+ ,(MPARAM)0
+ ,MPFROM2SHORT(BKA_AUTOPAGESIZE | BKA_MAJOR, BKA_FIRST)
+ ));
+ if (ulApiPage == 0L)
+ {
+ ERRORID vError;
+ wxString sError;
-// remove all pages
-bool wxNotebook::DeleteAllPages()
-{
- // TODO: delete native widget pages
+ vError = ::WinGetLastError(vHabmain);
+ sError = wxPMErrorToStr(vError);
+ return false;
+ }
+ m_alPageId.Insert((long)ulApiPage, nPage);
+ }
+ else
+ {
+ ulApiPage = LONGFROMMR(::WinSendMsg( GetHWND()
+ ,BKM_INSERTPAGE
+ ,MPFROMLONG((ULONG)m_alPageId[nPage - 1])
+ ,MPFROM2SHORT(BKA_AUTOPAGESIZE | BKA_MAJOR, BKA_NEXT)
+ ));
+ if (ulApiPage == 0L)
+ {
+ ERRORID vError;
+ wxString sError;
- int nPageCount = GetPageCount();
- int nPage;
- for ( nPage = 0; nPage < nPageCount; nPage++ )
- delete m_aPages[nPage];
+ vError = ::WinGetLastError(vHabmain);
+ sError = wxPMErrorToStr(vError);
+ return false;
+ }
+ m_alPageId.Insert((long)ulApiPage, nPage);
+ }
- m_aPages.Clear();
+ //
+ // Associate a window handle with the page
+ //
+ if (pPage)
+ {
+ if (!::WinSendMsg( GetHWND()
+ ,BKM_SETPAGEWINDOWHWND
+ ,MPFROMLONG((ULONG)m_alPageId[nPage])
+ ,MPFROMHWND(pPage->GetHWND())
+ ))
+ return false;
+ }
+ //
+ // If the inserted page is before the selected one, we must update the
+ // index of the selected page
+ //
+ if (nPage <= (size_t)m_nSelection)
+ {
+ //
+ // One extra page added
+ //
+ m_nSelection++;
+ }
- return TRUE;
-}
+ if (pPage)
+ {
+ //
+ // Save the pointer to the page
+ //
+ m_pages.Insert( pPage
+ ,nPage
+ );
+ }
-// add a page to the notebook
-bool wxNotebook::AddPage(wxNotebookPage *pPage,
- const wxString& strText,
- bool bSelect,
- int imageId)
-{
- return InsertPage(GetPageCount(), pPage, strText, bSelect, imageId);
-}
+ //
+ // Now set TAB dimenstions
+ //
-// same as AddPage() but does it at given position
-bool wxNotebook::InsertPage(int nPage,
- wxNotebookPage *pPage,
- const wxString& strText,
- bool bSelect,
- int imageId)
-{
- wxASSERT( pPage != NULL );
- wxCHECK( IS_VALID_PAGE(nPage) || nPage == GetPageCount(), FALSE );
+ wxWindowDC vDC(this);
+ wxCoord nTextX;
+ wxCoord nTextY;
- // TODO: insert native widget page
+ vDC.GetTextExtent(rsStrText, &nTextX, &nTextY);
+ nTextY *= 2;
+ nTextX = (wxCoord)(nTextX * 1.3);
+ if (nTextX > m_nTabSize)
+ {
+ m_nTabSize = nTextX;
+ ::WinSendMsg( GetHWND()
+ ,BKM_SETDIMENSIONS
+ ,MPFROM2SHORT((USHORT)m_nTabSize, (USHORT)nTextY)
+ ,(MPARAM)BKA_MAJORTAB
+ );
+ }
+ //
+ // Now set any TAB text
+ //
+ if (!rsStrText.empty())
+ {
+ if (!SetPageText( nPage
+ ,rsStrText
+ ))
+ return false;
+ }
- // save the pointer to the page
- m_aPages.Insert(pPage, nPage);
+ //
+ // Now set any TAB bitmap image
+ //
+ if (nImageId != -1)
+ {
+ if (!SetPageImage( nPage
+ ,nImageId
+ ))
+ return false;
+ }
- // some page must be selected: either this one or the first one if there is
+ if (pPage)
+ {
+ //
+ // Don't show pages by default (we'll need to adjust their size first)
+ //
+ HWND hWnd = GetWinHwnd(pPage);
+
+ WinSetWindowULong( hWnd
+ ,QWL_STYLE
+ ,WinQueryWindowULong( hWnd
+ ,QWL_STYLE
+ ) & ~WS_VISIBLE
+ );
+
+ //
+ // This updates internal flag too - otherwise it will get out of sync
+ //
+ pPage->Show(false);
+ }
+
+ //
+ // Some page should be selected: either this one or the first one if there is
// still no selection
- if ( bSelect )
- m_nSelection = nPage;
+ //
+ int nSelNew = -1;
+
+ if (bSelect)
+ nSelNew = nPage;
else if ( m_nSelection == -1 )
- m_nSelection = 0;
+ nSelNew = 0;
- return TRUE;
-}
+ if (nSelNew != -1)
+ SetSelection(nSelNew);
+
+ InvalidateBestSize();
+
+ return true;
+} // end of wxNotebook::InsertPage
// ----------------------------------------------------------------------------
// wxNotebook callbacks
// ----------------------------------------------------------------------------
+void wxNotebook::OnSize(
+ wxSizeEvent& rEvent
+)
+{
+ rEvent.Skip();
+} // end of wxNotebook::OnSize
-// @@@ OnSize() is used for setting the font when it's called for the first
-// time because doing it in ::Create() doesn't work (for unknown reasons)
-void wxNotebook::OnSize(wxSizeEvent& event)
+void wxNotebook::OnSelChange (
+ wxNotebookEvent& rEvent
+)
{
- static bool s_bFirstTime = TRUE;
- if ( s_bFirstTime ) {
- // TODO: any first-time-size processing.
- s_bFirstTime = FALSE;
- }
+ //
+ // Is it our tab control?
+ //
+ if (rEvent.GetEventObject() == this)
+ {
+ int nPageCount = GetPageCount();
+ int nSel;
+ ULONG ulOS2Sel = (ULONG)rEvent.GetOldSelection();
+ bool bFound = false;
- // TODO: all this may or may not be necessary for your platform
+ for (nSel = 0; nSel < nPageCount; nSel++)
+ {
+ if (ulOS2Sel == (ULONG)m_alPageId[nSel])
+ {
+ bFound = true;
+ break;
+ }
+ }
- // emulate page change (it's esp. important to do it first time because
- // otherwise our page would stay invisible)
- int nSel = m_nSelection;
- m_nSelection = -1;
- SetSelection(nSel);
-
- // fit the notebook page to the tab control's display area
- int w, h;
- GetSize(&w, &h);
-
- unsigned int nCount = m_aPages.Count();
- for ( unsigned int nPage = 0; nPage < nCount; nPage++ ) {
- wxNotebookPage *pPage = m_aPages[nPage];
- pPage->SetSize(0, 0, w, h);
- if ( pPage->GetAutoLayout() )
- pPage->Layout();
- }
+ if (!bFound)
+ return;
- // Processing continues to next OnSize
- event.Skip();
-}
+ m_pages[nSel]->Show(false);
-void wxNotebook::OnSelChange(wxNotebookEvent& event)
-{
- // is it our tab control?
- if ( event.GetEventObject() == this )
- {
- int sel = event.GetOldSelection();
- if ( sel != -1 )
- m_aPages[sel]->Show(FALSE);
-
- sel = event.GetSelection();
- if ( sel != -1 )
+ ulOS2Sel = (ULONG)rEvent.GetSelection();
+
+ bFound = false;
+
+ for (nSel = 0; nSel < nPageCount; nSel++)
{
- wxNotebookPage *pPage = m_aPages[sel];
- pPage->Show(TRUE);
- pPage->SetFocus();
+ if (ulOS2Sel == (ULONG)m_alPageId[nSel])
+ {
+ bFound = true;
+ break;
+ }
}
-
- m_nSelection = sel;
- }
- // we want to give others a chance to process this message as well
- event.Skip();
-}
-void wxNotebook::OnSetFocus(wxFocusEvent& event)
-{
- // set focus to the currently selected page if any
- if ( m_nSelection != -1 )
- m_aPages[m_nSelection]->SetFocus();
+ if (!bFound)
+ return;
- event.Skip();
-}
+ wxNotebookPage* pPage = m_pages[nSel];
+
+ pPage->Show(true);
+ m_nSelection = nSel;
+ }
+
+ //
+ // We want to give others a chance to process this message as well
+ //
+ rEvent.Skip();
+} // end of wxNotebook::OnSelChange
-void wxNotebook::OnNavigationKey(wxNavigationKeyEvent& event)
+void wxNotebook::OnSetFocus (
+ wxFocusEvent& rEvent
+)
{
- if ( event.IsWindowChange() ) {
- // change pages
- AdvanceSelection(event.GetDirection());
+ //
+ // This function is only called when the focus is explicitly set (i.e. from
+ // the program) to the notebook - in this case we don't need the
+ // complicated OnNavigationKey() logic because the programmer knows better
+ // what [s]he wants
+ //
+ // set focus to the currently selected page if any
+ //
+ if (m_nSelection != -1)
+ m_pages[m_nSelection]->SetFocus();
+ rEvent.Skip();
+} // end of wxNotebook::OnSetFocus
+
+void wxNotebook::OnNavigationKey (
+ wxNavigationKeyEvent& rEvent
+)
+{
+ if (rEvent.IsWindowChange())
+ {
+ //
+ // Change pages
+ //
+ AdvanceSelection(rEvent.GetDirection());
}
- else {
- // pass to the parent
- if ( GetParent() ) {
- event.SetCurrentFocus(this);
- GetParent()->ProcessEvent(event);
+ else
+ {
+ //
+ // We get this event in 2 cases
+ //
+ // a) one of our pages might have generated it because the user TABbed
+ // out from it in which case we should propagate the event upwards and
+ // our parent will take care of setting the focus to prev/next sibling
+ //
+ // or
+ //
+ // b) the parent panel wants to give the focus to us so that we
+ // forward it to our selected page. We can't deal with this in
+ // OnSetFocus() because we don't know which direction the focus came
+ // from in this case and so can't choose between setting the focus to
+ // first or last panel child
+ //
+ wxWindow* pParent = GetParent();
+
+ if (rEvent.GetEventObject() == pParent)
+ {
+ //
+ // No, it doesn't come from child, case (b): forward to a page
+ //
+ if (m_nSelection != -1)
+ {
+ //
+ // So that the page knows that the event comes from it's parent
+ // and is being propagated downwards
+ //
+ rEvent.SetEventObject(this);
+
+ wxWindow* pPage = m_pages[m_nSelection];
+
+ if (!pPage->GetEventHandler()->ProcessEvent(rEvent))
+ {
+ pPage->SetFocus();
+ }
+ //else: page manages focus inside it itself
+ }
+ else
+ {
+ //
+ // We have no pages - still have to give focus to _something_
+ //
+ SetFocus();
+ }
+ }
+ else
+ {
+ //
+ // It comes from our child, case (a), pass to the parent
+ //
+ if (pParent)
+ {
+ rEvent.SetCurrentFocus(this);
+ pParent->GetEventHandler()->ProcessEvent(rEvent);
+ }
}
}
-}
+} // end of wxNotebook::OnNavigationKey
// ----------------------------------------------------------------------------
// wxNotebook base class virtuals
// ----------------------------------------------------------------------------
-// override these 2 functions to do nothing: everything is done in OnSize
-
-void wxNotebook::SetConstraintSizes(bool /* recurse */)
-{
- // don't set the sizes of the pages - their correct size is not yet known
- wxControl::SetConstraintSizes(FALSE);
-}
-
-bool wxNotebook::DoPhase(int /* nPhase */)
+//
+// Override these 2 functions to do nothing: everything is done in OnSize
+//
+void wxNotebook::SetConstraintSizes( bool WXUNUSED(bRecurse) )
{
- return TRUE;
-}
+ //
+ // Don't set the sizes of the pages - their correct size is not yet known
+ //
+ wxControl::SetConstraintSizes(false);
+} // end of wxNotebook::SetConstraintSizes
-bool wxNotebook::OS2OnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM* result)
+bool wxNotebook::DoPhase ( int WXUNUSED(nPhase) )
{
- wxNotebookEvent event(wxEVT_NULL, m_windowId);
-//TODO:
-/*
- NMHDR* hdr = (NMHDR *)lParam;
- switch ( hdr->code ) {
- case TCN_SELCHANGE:
- event.SetEventType(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED);
- break;
-
- case TCN_SELCHANGING:
- event.SetEventType(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING);
- break;
-
- default:
- return wxControl::MSWOnNotify(idCtrl, lParam, result);
- }
-*/
- event.SetSelection(TabCtrl_GetCurSel(m_hwnd));
- event.SetOldSelection(m_nSelection);
- event.SetEventObject(this);
- event.SetInt(idCtrl);
-
- bool processed = GetEventHandler()->ProcessEvent(event);
- *result = !event.IsAllowed();
- return processed;
-}
+ return true;
+} // end of wxNotebook::DoPhase
// ----------------------------------------------------------------------------
-// wxNotebook helper functions
+// wxNotebook Windows message handlers
// ----------------------------------------------------------------------------
-
-// hide the currently active panel and show the new one
-void wxNotebook::ChangePage(int nOldSel, int nSel)
+bool wxNotebook::OS2OnScroll ( int nOrientation,
+ WXWORD wSBCode,
+ WXWORD wPos,
+ WXHWND wControl )
{
- // MT-FIXME should use a real semaphore
- static bool s_bInsideChangePage = FALSE;
-
- // when we call ProcessEvent(), our own OnSelChange() is called which calls
- // this function - break the infinite loop
- if ( s_bInsideChangePage )
- return;
-
- // it's not an error (the message may be generated by the tab control itself)
- // and it may happen - just do nothing
- if ( nSel == nOldSel )
- return;
-
- s_bInsideChangePage = TRUE;
-
- wxNotebookEvent event(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING, m_windowId);
- event.SetSelection(nSel);
- event.SetOldSelection(nOldSel);
- event.SetEventObject(this);
- if ( ProcessEvent(event) && !event.IsAllowed() )
- {
- // program doesn't allow the page change
- s_bInsideChangePage = FALSE;
- return;
- }
-
- event.SetEventType(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED);
- ProcessEvent(event);
-
- s_bInsideChangePage = FALSE;
-}
-
+ //
+ // Don't generate EVT_SCROLLWIN events for the WM_SCROLLs coming from the
+ // up-down control
+ //
+ if (wControl)
+ return false;
+ return wxNotebookBase::OS2OnScroll( nOrientation
+ ,wSBCode
+ ,wPos
+ ,wControl
+ );
+} // end of wxNotebook::OS2OnScroll
+
+#endif // wxUSE_NOTEBOOK