]> git.saurik.com Git - wxWidgets.git/blobdiff - src/osx/carbon/notebmac.cpp
Fit modeless preferences dialog to its contents too.
[wxWidgets.git] / src / osx / carbon / notebmac.cpp
index c534473ad4e8e92f996b61fa4f3f19fb1b87f163..fe2412e02323cbd0fa2755cf4e21bbe668aff43f 100644 (file)
@@ -1,5 +1,5 @@
 ///////////////////////////////////////////////////////////////////////////////
-// Name:        src/mac/carbon/notebmac.cpp
+// Name:        src/osx/carbon/notebmac.cpp
 // Purpose:     implementation of wxNotebook
 // Author:      Stefan Csomor
 // Modified by:
 
 #include "wx/string.h"
 #include "wx/imaglist.h"
-#include "wx/osx/uma.h"
+#include "wx/osx/private.h"
 
 
 // check that the page index is valid
 #define IS_VALID_PAGE(nPage) ((nPage) < GetPageCount())
 
-BEGIN_EVENT_TABLE(wxNotebook, wxBookCtrlBase)
-    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()
-
-IMPLEMENT_DYNAMIC_CLASS(wxNotebook, wxBookCtrlBase)
-
-
-// common part of all ctors
-void wxNotebook::Init()
+class wxCarbonTabView : public wxMacControl
 {
-    m_nSelection = -1;
-}
-
-// 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 )
-{
-    Init();
-
-    Create( parent, id, pos, size, style, name );
-}
+public:
+    wxCarbonTabView( wxWindowMac* peer ) : wxMacControl(peer )
+    {
+    }
+    
+    // Added by Mark Newsam
+    // When a page is added or deleted to the notebook this function updates
+    // information held in the control so that it matches the order
+    // the user would expect.
+    //
+    void SetupTabs( const wxNotebook& notebook)
+    {
+        const size_t countPages = notebook.GetPageCount();
+        SetMaximum( countPages ) ;
+        
+        wxNotebookPage *page;
+        ControlTabInfoRecV1 info;
+        
+        for (size_t ii = 0; ii < countPages; ii++)
+        {
+            page = (wxNotebookPage*) notebook.GetPage(ii);
+            info.version = kControlTabInfoVersionOne;
+            info.iconSuiteID = 0;
+            wxCFStringRef cflabel( page->GetLabel(), page->GetFont().GetEncoding() ) ;
+            info.name = cflabel ;
+            SetData<ControlTabInfoRecV1>( ii + 1, kControlTabInfoTag, &info ) ;
+            
+            if ( notebook.GetImageList() && notebook.GetPageImage(ii) >= 0 )
+            {
+                const wxBitmap bmap = notebook.GetImageList()->GetBitmap( notebook.GetPageImage( ii ) ) ;
+                if ( bmap.IsOk() )
+                {
+                    ControlButtonContentInfo info ;
+                    
+                    wxMacCreateBitmapButton( &info, bmap ) ;
+                    
+                    OSStatus err = SetData<ControlButtonContentInfo>( ii + 1, kControlTabImageContentTag, &info );
+                    if ( err != noErr )
+                    {
+                        wxFAIL_MSG("Error when setting icon on tab");
+                    }
+                    
+                    wxMacReleaseBitmapButton( &info ) ;
+                }
+            }
+            SetTabEnabled( ii + 1, true ) ;
+        }
+    }
+    
+    int TabHitTest(const wxPoint & pt, long* flags)
+    {
+        int resultV = wxNOT_FOUND;
+        
+        wxNotebook *notebookpeer = wxDynamicCast( GetWXPeer() , wxNotebook );
+        if ( NULL == notebookpeer )
+            return wxNOT_FOUND;
+        
+        const int countPages = notebookpeer->GetPageCount();
+        
+        // we have to convert from Client to Window relative coordinates
+        wxPoint adjustedPt = pt + GetWXPeer()->GetClientAreaOrigin();
+        // and now to HIView native ones
+        adjustedPt.x -= GetWXPeer()->MacGetLeftBorderSize() ;
+        adjustedPt.y -= GetWXPeer()->MacGetTopBorderSize() ;
+        
+        HIPoint hipoint= { adjustedPt.x , adjustedPt.y } ;
+        HIViewPartCode outPart = 0 ;
+        OSStatus err = HIViewGetPartHit( GetControlRef(), &hipoint, &outPart );
+        
+        int max = GetMaximum() ;
+        if ( outPart == 0 && max > 0 )
+        {
+            // this is a hack, as unfortunately a hit on an already selected tab returns 0,
+            // so we have to go some extra miles to make sure we select something different
+            // and try again ..
+            int val = GetValue() ;
+            int maxval = max ;
+            if ( max == 1 )
+            {
+                SetMaximum( 2 ) ;
+                maxval = 2 ;
+            }
+            
+            if ( val == 1 )
+                SetValue( maxval ) ;
+            else
+                SetValue( 1 ) ;
+            
+            err = HIViewGetPartHit( GetControlRef(), &hipoint, &outPart );
+            
+            SetValue( val ) ;
+            if ( max == 1 )
+                SetMaximum( 1 ) ;
+        }
+        
+        if ( outPart >= 1 && outPart <= countPages )
+            resultV = outPart - 1 ;
+        
+        if (flags != NULL)
+        {
+            *flags = 0;
+            
+            // we cannot differentiate better
+            if (resultV >= 0)
+                *flags |= wxBK_HITTEST_ONLABEL;
+            else
+                *flags |= wxBK_HITTEST_NOWHERE;
+        }
+        
+        return resultV;
+        
+    }
+    
+};
 
-bool wxNotebook::Create( wxWindow *parent,
-    wxWindowID id,
-    const wxPoint& pos,
-    const wxSize& size,
-    long style,
-    const wxString& name )
+wxWidgetImplType* wxWidgetImpl::CreateTabView( wxWindowMac* wxpeer,
+                                    wxWindowMac* parent,
+                                    wxWindowID WXUNUSED(id),
+                                    const wxPoint& pos,
+                                    const wxSize& size,
+                                    long style,
+                                    long WXUNUSED(extraStyle))
 {
-    m_macIsUserPane = false ;
-
-    if (! (style & wxBK_ALIGN_MASK))
-        style |= wxBK_TOP;
-
-    if ( !wxNotebookBase::Create( parent, id, pos, size, style, name ) )
-        return false;
-
-    Rect bounds = wxMacGetBoundsForControl( this, pos, size );
+    Rect bounds = wxMacGetBoundsForControl( wxpeer, pos, size );
 
     if ( bounds.right <= bounds.left )
         bounds.right = bounds.left + 100;
@@ -89,15 +163,15 @@ bool wxNotebook::Create( wxWindow *parent,
         bounds.bottom = bounds.top + 100;
 
     UInt16 tabstyle = kControlTabDirectionNorth;
-    if ( HasFlag(wxBK_LEFT) )
+    if ( style & wxBK_LEFT )
         tabstyle = kControlTabDirectionWest;
-    else if ( HasFlag( wxBK_RIGHT ) )
+    else if ( style & wxBK_RIGHT )
         tabstyle = kControlTabDirectionEast;
-    else if ( HasFlag( wxBK_BOTTOM ) )
+    else if ( style & wxBK_BOTTOM )
         tabstyle = kControlTabDirectionSouth;
 
     ControlTabSize tabsize;
-    switch (GetWindowVariant())
+    switch (wxpeer->GetWindowVariant())
     {
         case wxWINDOW_VARIANT_MINI:
             tabsize = 3 ;
@@ -112,505 +186,14 @@ bool wxNotebook::Create( wxWindow *parent,
             break;
     }
 
-    m_peer = new wxMacControl( this );
+    wxMacControl* peer = new wxCarbonTabView( wxpeer );
+    
     OSStatus err = CreateTabsControl(
         MAC_WXHWND(parent->MacGetTopLevelWindowRef()), &bounds,
-        tabsize, tabstyle, 0, NULL, m_peer->GetControlRefAddr() );
+        tabsize, tabstyle, 0, NULL, peer->GetControlRefAddr() );
     verify_noerr( err );
 
-    MacPostControlCreate( pos, size );
-
-    return true ;
-}
-
-// dtor
-wxNotebook::~wxNotebook()
-{
-}
-
-// ----------------------------------------------------------------------------
-// wxNotebook accessors
-// ----------------------------------------------------------------------------
-
-void wxNotebook::SetPadding(const wxSize& WXUNUSED(padding))
-{
-    // unsupported by OS
-}
-
-void wxNotebook::SetTabSize(const wxSize& WXUNUSED(sz))
-{
-    // unsupported by OS
-}
-
-void wxNotebook::SetPageSize(const wxSize& size)
-{
-    SetSize( CalcSizeFromPage( size ) );
-}
-
-wxSize wxNotebook::CalcSizeFromPage(const wxSize& sizePage) const
-{
-    return DoGetSizeFromClientSize( sizePage );
-}
-
-int wxNotebook::DoSetSelection(size_t nPage, int flags)
-{
-    wxCHECK_MSG( IS_VALID_PAGE(nPage), wxNOT_FOUND, wxT("DoSetSelection: invalid notebook page") );
-
-    if ( m_nSelection == wxNOT_FOUND || nPage != (size_t)m_nSelection )
-    {
-        if ( flags & SetSelection_SendEvent )
-        {
-            if ( !SendPageChangingEvent(nPage) )
-            {
-                // vetoed by program
-                return m_nSelection;
-            }
-            //else: program allows the page change
-
-            SendPageChangedEvent(m_nSelection, nPage);
-        }
-
-        ChangePage(m_nSelection, nPage);
-    }
-    //else: no change
-
-    return m_nSelection;
-}
-
-bool wxNotebook::SetPageText(size_t nPage, const wxString& strText)
-{
-    wxCHECK_MSG( IS_VALID_PAGE(nPage), false, wxT("SetPageText: invalid notebook page") );
-
-    wxNotebookPage *page = m_pages[nPage];
-    page->SetLabel(wxStripMenuCodes(strText));
-    MacSetupTabs();
-
-    return true;
-}
-
-wxString wxNotebook::GetPageText(size_t nPage) const
-{
-    wxCHECK_MSG( IS_VALID_PAGE(nPage), wxEmptyString, wxT("GetPageText: invalid notebook page") );
-
-    wxNotebookPage *page = m_pages[nPage];
-
-    return page->GetLabel();
-}
-
-int wxNotebook::GetPageImage(size_t nPage) const
-{
-    wxCHECK_MSG( IS_VALID_PAGE(nPage), wxNOT_FOUND, wxT("GetPageImage: invalid notebook page") );
-
-    return m_images[nPage];
-}
-
-bool wxNotebook::SetPageImage(size_t nPage, int nImage)
-{
-    wxCHECK_MSG( IS_VALID_PAGE(nPage), false,
-        wxT("SetPageImage: invalid notebook page") );
-    wxCHECK_MSG( m_imageList && nImage < m_imageList->GetImageCount(), false,
-        wxT("SetPageImage: invalid image index") );
-
-    if ( nImage != m_images[nPage] )
-    {
-        // if the item didn't have an icon before or, on the contrary, did have
-        // it but has lost it now, its size will change - but if the icon just
-        // changes, it won't
-        m_images[nPage] = nImage;
-
-        MacSetupTabs() ;
-    }
-
-    return true;
-}
-
-// ----------------------------------------------------------------------------
-// wxNotebook operations
-// ----------------------------------------------------------------------------
-
-// remove one page from the notebook, without deleting the window
-wxNotebookPage* wxNotebook::DoRemovePage(size_t nPage)
-{
-    wxCHECK_MSG( IS_VALID_PAGE(nPage), NULL,
-        wxT("DoRemovePage: invalid notebook page") );
-
-    wxNotebookPage* page = m_pages[nPage] ;
-    m_pages.RemoveAt(nPage);
-
-    MacSetupTabs();
-
-    if (m_nSelection >= (int)GetPageCount())
-        m_nSelection = GetPageCount() - 1;
-
-    if (m_nSelection >= 0)
-        m_pages[m_nSelection]->Show(true);
-
-    InvalidateBestSize();
-
-    return page;
-}
-
-// remove all pages
-bool wxNotebook::DeleteAllPages()
-{
-    WX_CLEAR_ARRAY(m_pages) ;
-    MacSetupTabs();
-    m_nSelection = -1 ;
-    InvalidateBestSize();
-
-    return true;
-}
-
-// same as AddPage() but does it at given position
-bool wxNotebook::InsertPage(size_t nPage,
-    wxNotebookPage *pPage,
-    const wxString& strText,
-    bool bSelect,
-    int imageId )
-{
-    if ( !wxNotebookBase::InsertPage( nPage, pPage, strText, bSelect, imageId ) )
-        return false;
-
-    wxASSERT_MSG( pPage->GetParent() == this, wxT("notebook pages must have notebook as parent") );
-
-    // don't show pages by default (we'll need to adjust their size first)
-    pPage->Show( false ) ;
-
-    pPage->SetLabel( wxStripMenuCodes(strText) );
-
-    m_images.Insert( imageId, nPage );
-
-    MacSetupTabs();
-
-    wxRect rect = GetPageRect() ;
-    pPage->SetSize( rect );
-    if ( pPage->GetAutoLayout() )
-        pPage->Layout();
-
-    // now deal with the selection
-    // ---------------------------
-
-    // if the inserted page is before the selected one, we must update the
-    // index of the selected page
-
-    if ( int(nPage) <= m_nSelection )
-    {
-        m_nSelection++;
-
-        // while this still is the same page showing, we need to update the tabs
-        m_peer->SetValue( m_nSelection + 1 ) ;
-    }
-
-    // some page should be selected: either this one or the first one if there
-    // is still no selection
-    int selNew = -1;
-    if ( bSelect )
-        selNew = nPage;
-    else if ( m_nSelection == -1 )
-        selNew = 0;
-
-    if ( selNew != -1 )
-        SetSelection( selNew );
-
-    InvalidateBestSize();
-
-    return true;
-}
-
-int wxNotebook::HitTest(const wxPoint& pt, long * flags) const
-{
-    int resultV = wxNOT_FOUND;
-
-    const int countPages = GetPageCount();
-
-    // we have to convert from Client to Window relative coordinates
-    wxPoint adjustedPt = pt + GetClientAreaOrigin();
-    // and now to HIView native ones
-    adjustedPt.x -= MacGetLeftBorderSize() ;
-    adjustedPt.y -= MacGetTopBorderSize() ;
-
-    HIPoint hipoint= { adjustedPt.x , adjustedPt.y } ;
-    HIViewPartCode outPart = 0 ;
-    OSStatus err = HIViewGetPartHit( m_peer->GetControlRef(), &hipoint, &outPart );
-
-    int max = m_peer->GetMaximum() ;
-    if ( outPart == 0 && max > 0 )
-    {
-        // this is a hack, as unfortunately a hit on an already selected tab returns 0,
-        // so we have to go some extra miles to make sure we select something different
-        // and try again ..
-        int val = m_peer->GetValue() ;
-        int maxval = max ;
-        if ( max == 1 )
-        {
-            m_peer->SetMaximum( 2 ) ;
-            maxval = 2 ;
-        }
-
-        if ( val == 1 )
-            m_peer->SetValue( maxval ) ;
-        else
-             m_peer->SetValue( 1 ) ;
-
-        err = HIViewGetPartHit( m_peer->GetControlRef(), &hipoint, &outPart );
-
-        m_peer->SetValue( val ) ;
-        if ( max == 1 )
-            m_peer->SetMaximum( 1 ) ;
-    }
-
-    if ( outPart >= 1 && outPart <= countPages )
-        resultV = outPart - 1 ;
-
-    if (flags != NULL)
-    {
-        *flags = 0;
-
-        // we cannot differentiate better
-        if (resultV >= 0)
-            *flags |= wxBK_HITTEST_ONLABEL;
-        else
-            *flags |= wxBK_HITTEST_NOWHERE;
-    }
-
-    return resultV;
-}
-
-// Added by Mark Newsam
-// When a page is added or deleted to the notebook this function updates
-// information held in the control so that it matches the order
-// the user would expect.
-//
-void wxNotebook::MacSetupTabs()
-{
-    m_peer->SetMaximum( GetPageCount() ) ;
-
-    wxNotebookPage *page;
-    ControlTabInfoRecV1 info;
-
-    const size_t countPages = GetPageCount();
-    for (size_t ii = 0; ii < countPages; ii++)
-    {
-        page = m_pages[ii];
-        info.version = kControlTabInfoVersionOne;
-        info.iconSuiteID = 0;
-        wxCFStringRef cflabel( page->GetLabel(), GetFont().GetEncoding() ) ;
-        info.name = cflabel ;
-        m_peer->SetData<ControlTabInfoRecV1>( ii + 1, kControlTabInfoTag, &info ) ;
-
-        if ( GetImageList() && GetPageImage(ii) >= 0 )
-        {
-            const wxBitmap bmap = GetImageList()->GetBitmap( GetPageImage( ii ) ) ;
-            if ( bmap.Ok() )
-            {
-                ControlButtonContentInfo info ;
-
-                wxMacCreateBitmapButton( &info, bmap ) ;
-
-                OSStatus err = m_peer->SetData<ControlButtonContentInfo>( ii + 1, kControlTabImageContentTag, &info );
-                if ( err != noErr )
-                {
-                    wxFAIL_MSG("Error when setting icon on tab");
-                }
-
-                wxMacReleaseBitmapButton( &info ) ;
-            }
-        }
-
-        m_peer->SetTabEnabled( ii + 1, true ) ;
-    }
-
-    Refresh();
-}
-
-wxRect wxNotebook::GetPageRect() const
-{
-    wxSize size = GetClientSize() ;
-
-    return wxRect( 0 , 0 , size.x , size.y ) ;
-}
-
-// ----------------------------------------------------------------------------
-// wxNotebook callbacks
-// ----------------------------------------------------------------------------
-
-// @@@ 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)
-{
-    unsigned int nCount = m_pages.Count();
-    wxRect rect = GetPageRect() ;
-
-    for ( unsigned int nPage = 0; nPage < nCount; nPage++ )
-    {
-        wxNotebookPage *pPage = m_pages[nPage];
-        pPage->SetSize(rect);
-        if ( pPage->GetAutoLayout() )
-            pPage->Layout();
-    }
-
-    // Processing continues to next OnSize
-    event.Skip();
-}
-
-void wxNotebook::OnSelChange(wxBookCtrlEvent& event)
-{
-    // is it our tab control?
-    if ( event.GetEventObject() == this )
-        ChangePage(event.GetOldSelection(), event.GetSelection());
-
-    // 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_pages[m_nSelection]->SetFocus();
-
-    event.Skip();
-}
-
-void wxNotebook::OnNavigationKey(wxNavigationKeyEvent& event)
-{
-    if ( event.IsWindowChange() )
-    {
-        // change pages
-        AdvanceSelection( event.GetDirection() );
-    }
-    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 *parent = GetParent();
-
-        // the cast is here to fix a GCC ICE
-        if ( ((wxWindow*)event.GetEventObject()) == parent )
-        {
-            // 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
-                event.SetEventObject( this );
-
-                wxWindow *page = m_pages[m_nSelection];
-                if ( !page->HandleWindowEvent( event ) )
-                {
-                    page->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 ( parent )
-            {
-                event.SetCurrentFocus( this );
-                parent->HandleWindowEvent( event );
-            }
-        }
-    }
-}
-
-// ----------------------------------------------------------------------------
-// wxNotebook base class virtuals
-// ----------------------------------------------------------------------------
-
-#if wxUSE_CONSTRAINTS
-
-// override these 2 functions to do nothing: everything is done in OnSize
-
-void wxNotebook::SetConstraintSizes(bool WXUNUSED(recurse))
-{
-    // don't set the sizes of the pages - their correct size is not yet known
-    wxControl::SetConstraintSizes( false );
-}
-
-bool wxNotebook::DoPhase(int WXUNUSED(nPhase))
-{
-    return true;
-}
-
-#endif // wxUSE_CONSTRAINTS
-
-void wxNotebook::Command(wxCommandEvent& WXUNUSED(event))
-{
-    wxFAIL_MSG(wxT("wxNotebook::Command not implemented"));
-}
-
-// ----------------------------------------------------------------------------
-// wxNotebook helper functions
-// ----------------------------------------------------------------------------
-
-// hide the currently active panel and show the new one
-void wxNotebook::ChangePage(int nOldSel, int nSel)
-{
-    if (nOldSel == nSel)
-        return;
-
-    if ( nOldSel != -1 )
-        m_pages[nOldSel]->Show( false );
-
-    if ( nSel != -1 )
-    {
-        wxNotebookPage *pPage = m_pages[nSel];
-        pPage->Show( true );
-        pPage->SetFocus();
-    }
-
-    m_nSelection = nSel;
-    m_peer->SetValue( m_nSelection + 1 ) ;
-}
-
-wxInt32 wxNotebook::MacControlHit(WXEVENTHANDLERREF WXUNUSED(handler) , WXEVENTREF WXUNUSED(event) )
-{
-    OSStatus status = eventNotHandledErr ;
-
-    SInt32 newSel = m_peer->GetValue() - 1 ;
-    if ( newSel != m_nSelection )
-    {
-        wxBookCtrlEvent changing(
-            wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING, m_windowId,
-            newSel , m_nSelection );
-        changing.SetEventObject( this );
-        HandleWindowEvent( changing );
-
-        if ( changing.IsAllowed() )
-        {
-            wxBookCtrlEvent event(
-                wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED, m_windowId,
-                newSel, m_nSelection );
-            event.SetEventObject( this );
-            HandleWindowEvent( event );
-        }
-        else
-        {
-            m_peer->SetValue( m_nSelection + 1 ) ;
-        }
-
-        status = noErr ;
-    }
-
-    return (wxInt32)status ;
+    return peer;
 }
 
 #endif