]> git.saurik.com Git - wxWidgets.git/blobdiff - src/osx/window_osx.cpp
simplify Refresh() and Update()
[wxWidgets.git] / src / osx / window_osx.cpp
index d4edf5f180a629b2f75dbc1ebff2f4f0672caf0e..b9817fbfc108ed1af488756b191a5dcdbbfe0a20 100644 (file)
@@ -61,6 +61,8 @@
 #include "wx/dnd.h"
 #endif
 
+#include "wx/graphics.h"
+
 #if wxOSX_USE_CARBON
 #include "wx/osx/uma.h"
 #else
@@ -139,8 +141,6 @@ wxWindowMac::~wxWindowMac()
 {
     SendDestroyEvent();
 
-    m_isBeingDeleted = true;
-
     MacInvalidateBorders() ;
 
 #ifndef __WXUNIVERSAL__
@@ -151,7 +151,7 @@ wxWindowMac::~wxWindowMac()
         if ( frame )
         {
             if ( frame->GetLastFocus() == this )
-                frame->SetLastFocus((wxWindow*)NULL);
+                frame->SetLastFocus(NULL);
             break;
         }
     }
@@ -272,19 +272,11 @@ void wxWindowMac::MacPostControlCreate(const wxPoint& WXUNUSED(pos), const wxSiz
 {
     wxASSERT_MSG( m_peer != NULL && m_peer->IsOk() , wxT("No valid mac control") ) ;
 
-#if wxOSX_USE_CARBON
-    m_peer->SetReference( (URefCon) this ) ;
-#endif
-
     GetParent()->AddChild( this );
 
-#if wxOSX_USE_CARBON
     m_peer->InstallEventHandler();
+    m_peer->Embed(GetParent()->GetPeer());
 
-    ControlRef container = (ControlRef) GetParent()->GetHandle() ;
-    wxASSERT_MSG( container != NULL , wxT("No valid mac container control") ) ;
-    ::EmbedControl( m_peer->GetControlRef() , container ) ;
-#endif
     GetParent()->MacChildAdded() ;
 
     // adjust font, controlsize etc
@@ -292,7 +284,8 @@ void wxWindowMac::MacPostControlCreate(const wxPoint& WXUNUSED(pos), const wxSiz
 
     m_peer->SetLabel( wxStripMenuCodes(m_label, wxStrip_Mnemonics), GetFont().GetEncoding() ) ;
 
-    if (!m_macIsUserPane)
+    // for controls we want to use best size for wxDefaultSize params )
+    if ( !m_macIsUserPane )
         SetInitialSize(size);
 
     SetCursor( *wxSTANDARD_CURSOR ) ;
@@ -310,11 +303,43 @@ void wxWindowMac::DoSetWindowVariant( wxWindowVariant variant )
         return;
 
     m_peer->SetControlSize( variant );
+#if wxOSX_USE_CARBON
+    ControlSize size ;
+
+    // we will get that from the settings later
+    // and make this NORMAL later, but first
+    // we have a few calculations that we must fix
+
+    switch ( variant )
+    {
+        case wxWINDOW_VARIANT_NORMAL :
+            size = kControlSizeNormal;
+            break ;
+
+        case wxWINDOW_VARIANT_SMALL :
+            size = kControlSizeSmall;
+            break ;
+
+        case wxWINDOW_VARIANT_MINI :
+            // not always defined in the headers
+            size = 3 ;
+            break ;
+
+        case wxWINDOW_VARIANT_LARGE :
+            size = kControlSizeLarge;
+            break ;
+
+        default:
+            wxFAIL_MSG(_T("unexpected window variant"));
+            break ;
+    }
+    m_peer->SetData<ControlSize>(kControlEntireControl, kControlSizeTag, &size ) ;
+#endif
+
 #if wxOSX_USE_COCOA_OR_CARBON
     wxFont font ;
 
-#if wxOSX_USE_CARBON
-    ControlSize size ;
+#if wxOSX_USE_ATSU_TEXT
     ThemeFontID themeFont = kThemeSystemFont ;
 
     // we will get that from the settings later
@@ -324,23 +349,19 @@ void wxWindowMac::DoSetWindowVariant( wxWindowVariant variant )
     switch ( variant )
     {
         case wxWINDOW_VARIANT_NORMAL :
-            size = kControlSizeNormal;
             themeFont = kThemeSystemFont ;
             break ;
 
         case wxWINDOW_VARIANT_SMALL :
-            size = kControlSizeSmall;
             themeFont = kThemeSmallSystemFont ;
             break ;
 
         case wxWINDOW_VARIANT_MINI :
             // not always defined in the headers
-            size = 3 ;
             themeFont = 109 ;
             break ;
 
         case wxWINDOW_VARIANT_LARGE :
-            size = kControlSizeLarge;
             themeFont = kThemeSystemFont ;
             break ;
 
@@ -349,7 +370,6 @@ void wxWindowMac::DoSetWindowVariant( wxWindowVariant variant )
             break ;
     }
 
-    m_peer->SetData<ControlSize>(kControlEntireControl, kControlSizeTag, &size ) ;
     font.MacCreateFromThemeFont( themeFont ) ;
 #else
     CTFontUIFontType themeFont = kCTFontSystemFontType ;
@@ -384,8 +404,8 @@ void wxWindowMac::DoSetWindowVariant( wxWindowVariant variant )
 
 void wxWindowMac::MacUpdateControlFont()
 {
-
-    m_peer->SetFont( GetFont() , GetForegroundColour() , GetWindowStyle() ) ;
+    if ( m_peer )
+        m_peer->SetFont( GetFont() , GetForegroundColour() , GetWindowStyle() ) ;
 
     // do not trigger refreshes upon invisible and possible partly created objects
     if ( IsShownOnScreen() )
@@ -437,6 +457,7 @@ void wxWindowMac::SetFocus()
 void wxWindowMac::DoCaptureMouse()
 {
     wxApp::s_captureWindow = (wxWindow*) this ;
+    m_peer->CaptureMouse() ;
 }
 
 wxWindow * wxWindowBase::GetCapture()
@@ -447,14 +468,15 @@ wxWindow * wxWindowBase::GetCapture()
 void wxWindowMac::DoReleaseMouse()
 {
     wxApp::s_captureWindow = NULL ;
+
+    m_peer->ReleaseMouse() ;
 }
 
 #if wxUSE_DRAG_AND_DROP
 
 void wxWindowMac::SetDropTarget(wxDropTarget *pDropTarget)
 {
-    if ( m_dropTarget != NULL )
-        delete m_dropTarget;
+    delete m_dropTarget;
 
     m_dropTarget = pDropTarget;
     if ( m_dropTarget != NULL )
@@ -483,9 +505,8 @@ bool wxWindowMac::MacGetBoundsForControl(
     x = (int)pos.x;
     y = (int)pos.y;
 
-    // TODO: the default calls may be used as soon as PostCreateControl Is moved here
-    w = wxMax(size.x, 0) ; // WidthDefault( size.x );
-    h = wxMax(size.y, 0) ; // HeightDefault( size.y ) ;
+    w = WidthDefault( size.x ); 
+    h = HeightDefault( size.y ); 
 
     x += MacGetLeftBorderSize() ;
     y += MacGetTopBorderSize() ;
@@ -654,8 +675,8 @@ wxSize wxWindowMac::DoGetSizeFromClientSize( const wxSize & size )  const
     m_peer->GetContentArea( left, top, innerwidth, innerheight );
     m_peer->GetSize( outerwidth, outerheight );
     
-    sizeTotal.x += left + (outerwidth-innerwidth);
-    sizeTotal.y += top + (outerheight-innerheight);
+    sizeTotal.x += outerwidth-innerwidth;
+    sizeTotal.y += outerheight-innerheight;
     
     sizeTotal.x += MacGetLeftBorderSize() + MacGetRightBorderSize() ;
     sizeTotal.y += MacGetTopBorderSize() + MacGetBottomBorderSize() ;
@@ -703,37 +724,8 @@ bool wxWindowMac::SetCursor(const wxCursor& cursor)
     wxASSERT_MSG( m_cursor.Ok(),
         wxT("cursor must be valid after call to the base version"));
 
-    wxWindowMac *mouseWin = 0 ;
-#if wxOSX_USE_CARBON
-    {
-        wxNonOwnedWindow *tlw = MacGetTopLevelWindow() ;
-        WindowRef window = (WindowRef) ( tlw ? tlw->GetWXWindow() : 0 ) ;
-
-        ControlPartCode part ;
-        ControlRef control ;
-        Point pt ;
- #if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5
-        HIPoint hiPoint ;
-        HIGetMousePosition(kHICoordSpaceWindow, window, &hiPoint);
-        pt.h = hiPoint.x;
-        pt.v = hiPoint.y;
- #else
-        GetGlobalMouse( &pt );
-        int x = pt.h;
-        int y = pt.v;
-        ScreenToClient(&x, &y);
-        pt.h = x;
-        pt.v = y;
-#endif
-        control = FindControlUnderMouse( pt , window , &part ) ;
-        if ( control )
-            mouseWin = wxFindWindowFromWXWidget( (WXWidget) control ) ;
-
-    }
-#endif
-
-    if ( mouseWin == this && !wxIsBusy() )
-        m_cursor.MacInstall() ;
+    if ( GetPeer() != NULL )
+        GetPeer()->SetCursor( m_cursor );
 
     return true ;
 }
@@ -755,30 +747,8 @@ bool wxWindowMac::DoPopupMenu(wxMenu *menu, int x, int y)
     {
         ClientToScreen( &x , &y ) ;
     }
-#ifdef __WXOSX_CARBON__
-    long menuResult = ::PopUpMenuSelect((MenuHandle) menu->GetHMenu() , y, x, 0) ;
-    if ( HiWord(menuResult) != 0 )
-    {
-        MenuCommand macid;
-        GetMenuItemCommandID( GetMenuHandle(HiWord(menuResult)) , LoWord(menuResult) , &macid );
-        int id = wxMacCommandToId( macid );
-        wxMenuItem* item = NULL ;
-        wxMenu* realmenu ;
-        item = menu->FindItem( id, &realmenu ) ;
-        if ( item )
-        {
-            if (item->IsCheckable())
-                item->Check( !item->IsChecked() ) ;
-
-            menu->SendEvent( id , item->IsCheckable() ? item->IsChecked() : -1 ) ;
-        }
-    }
-
-#else
+    menu->GetPeer()->PopUp(this, x, y);
     menu->SetInvokingWindow( NULL );
-    return false;
-#endif
-
     return true;
 #else
     // actually this shouldn't be called, because universal is having its own implementation
@@ -994,6 +964,13 @@ void wxWindowMac::DoSetSize(int x, int y, int width, int height, int sizeFlags)
         // TODO: REMOVE
         MacRepositionScrollBars() ; // we might have a real position shift
 
+        if (sizeFlags & wxSIZE_FORCE_EVENT)
+        {
+            wxSizeEvent event( wxSize(width,height), GetId() );
+            event.SetEventObject( this );
+            HandleWindowEvent( event );
+        }
+
         return;
     }
 
@@ -1134,19 +1111,21 @@ bool wxWindowMac::MacIsReallyHilited()
 
 int wxWindowMac::GetCharHeight() const
 {
-    wxClientDC dc( (wxWindow*)this ) ;
+    wxCoord height;
+    GetTextExtent( wxT("g") , NULL , &height , NULL , NULL , NULL );
 
-    return dc.GetCharHeight() ;
+    return height;
 }
 
 int wxWindowMac::GetCharWidth() const
 {
-    wxClientDC dc( (wxWindow*)this ) ;
+    wxCoord width;
+    GetTextExtent( wxT("g") , &width , NULL , NULL , NULL , NULL );
 
-    return dc.GetCharWidth() ;
+    return width;
 }
 
-void wxWindowMac::GetTextExtent(const wxString& string, int *x, int *y,
+void wxWindowMac::GetTextExtent(const wxString& str, int *x, int *y,
                            int *descent, int *externalLeading, const wxFont *theFont ) const
 {
     const wxFont *fontToUse = theFont;
@@ -1157,17 +1136,22 @@ void wxWindowMac::GetTextExtent(const wxString& string, int *x, int *y,
         fontToUse = &tempFont;
     }
 
-    wxClientDC dc( (wxWindow*) this ) ;
-    wxCoord lx,ly,ld,le ;
-    dc.GetTextExtent( string , &lx , &ly , &ld, &le, (wxFont *)fontToUse ) ;
+    wxGraphicsContext* ctx = wxGraphicsContext::Create();
+    ctx->SetFont( *fontToUse, *wxBLACK );
+
+    wxDouble h , d , e , w;
+    ctx->GetTextExtent( str, &w, &h, &d, &e );
+    
+    delete ctx;
+    
     if ( externalLeading )
-        *externalLeading = le ;
+        *externalLeading = (wxCoord)(e+0.5);
     if ( descent )
-        *descent = ld ;
+        *descent = (wxCoord)(d+0.5);
     if ( x )
-        *x = lx ;
+        *x = (wxCoord)(w+0.5);
     if ( y )
-        *y = ly ;
+        *y = (wxCoord)(h+0.5);
 }
 
 /*
@@ -1861,9 +1845,9 @@ bool wxWindowMac::MacDoRedraw( void* updatergnr , long time )
             // the grow-box area of a scrolled window (scroll sample)
             wxDC* dc = new wxWindowDC(this);
             if ( IsTopLevel() )
-                dc->SetClippingRegion(wxRegion(HIShapeCreateWithQDRgn(updatergn)));
+                dc->SetDeviceClippingRegion(wxRegion(HIShapeCreateWithQDRgn(updatergn)));
             else
-                dc->SetClippingRegion(wxRegion(HIShapeCreateWithQDRgn(newupdate)));
+                dc->SetDeviceClippingRegion(wxRegion(HIShapeCreateWithQDRgn(newupdate)));
 
             wxEraseEvent eevent( GetId(), dc );
             eevent.SetEventObject( this );
@@ -2231,9 +2215,7 @@ void wxWindowMac::OnPaint( wxPaintEvent & WXUNUSED(event) )
 #endif
 }
 
-void wxWindowMac::MacHandleControlClick(WXWidget WXUNUSED(control),
-                                        wxInt16 WXUNUSED(controlpart),
-                                        bool WXUNUSED(mouseStillDown))
+void wxWindowMac::TriggerScrollEvent( wxEventType WXUNUSED(scrollEvent) )
 {
 }
 
@@ -2247,7 +2229,7 @@ Rect wxMacGetBoundsForControl( wxWindowMac* window , const wxPoint& pos , const
     return bounds ;
 }
 
-bool wxWindowMac::HandleClicked( double timestampsec )
+bool wxWindowMac::OSXHandleClicked( double timestampsec )
 {
     return false;
 }
@@ -2255,7 +2237,7 @@ bool wxWindowMac::HandleClicked( double timestampsec )
 wxInt32 wxWindowMac::MacControlHit(WXEVENTHANDLERREF WXUNUSED(handler) , WXEVENTREF event )
 {
 #if wxOSX_USE_COCOA_OR_CARBON
-    if ( HandleClicked( GetEventTime((EventRef)event) ) )
+    if ( OSXHandleClicked( GetEventTime((EventRef)event) ) )
         return noErr;
         
     return eventNotHandledErr ;
@@ -2321,10 +2303,103 @@ bool wxWindowMac::IsShownOnScreen() const
     return wxWindowBase::IsShownOnScreen();
 }
 
+bool wxWindowMac::OSXHandleKeyEvent( wxKeyEvent& event )
+{
+    bool handled = HandleWindowEvent( event ) ;
+    if ( handled && event.GetSkipped() )
+        handled = false ;
+
+#if wxUSE_ACCEL
+    if ( !handled && event.GetEventType() == wxEVT_KEY_DOWN)
+    {
+        wxWindow *ancestor = this;
+        while (ancestor)
+        {
+            int command = ancestor->GetAcceleratorTable()->GetCommand( event );
+            if (command != -1)
+            {
+                wxEvtHandler * const handler = ancestor->GetEventHandler();
+
+                wxCommandEvent command_event( wxEVT_COMMAND_MENU_SELECTED, command );
+                handled = handler->ProcessEvent( command_event );
+
+                if ( !handled )
+                {
+                    // accelerators can also be used with buttons, try them too
+                    command_event.SetEventType(wxEVT_COMMAND_BUTTON_CLICKED);
+                    handled = handler->ProcessEvent( command_event );
+                }
+
+                break;
+            }
+
+            if (ancestor->IsTopLevel())
+                break;
+
+            ancestor = ancestor->GetParent();
+        }
+    }
+#endif // wxUSE_ACCEL
+
+    return handled ;
+}
+
 //
 // wxWidgetImpl 
 //
 
+WX_DECLARE_HASH_MAP(WXWidget, wxWidgetImpl*, wxPointerHash, wxPointerEqual, MacControlMap);
+
+static MacControlMap wxWinMacControlList;
+
+wxWindowMac *wxFindWindowFromWXWidget(WXWidget inControl )
+{
+    wxWidgetImpl* impl = wxWidgetImpl::FindFromWXWidget( inControl );
+    if ( impl )
+        return impl->GetWXPeer();
+    
+    return NULL;
+}
+
+wxWidgetImpl *wxWidgetImpl::FindFromWXWidget(WXWidget inControl )
+{
+    MacControlMap::iterator node = wxWinMacControlList.find(inControl);
+
+    return (node == wxWinMacControlList.end()) ? NULL : node->second;
+}
+
+void wxWidgetImpl::Associate(WXWidget inControl, wxWidgetImpl *impl)
+{
+    // adding NULL ControlRef is (first) surely a result of an error and
+    // (secondly) breaks native event processing
+    wxCHECK_RET( inControl != (WXWidget) NULL, wxT("attempt to add a NULL WXWidget to control map") );
+
+    wxWinMacControlList[inControl] = impl;
+}
+
+void wxWidgetImpl::RemoveAssociations(wxWidgetImpl* impl)
+{
+   // iterate over all the elements in the class
+    // is the iterator stable ? as we might have two associations pointing to the same wxWindow
+    // we should go on...
+
+    bool found = true ;
+    while ( found )
+    {
+        found = false ;
+        MacControlMap::iterator it;
+        for ( it = wxWinMacControlList.begin(); it != wxWinMacControlList.end(); ++it )
+        {
+            if ( it->second == impl )
+            {
+                wxWinMacControlList.erase(it);
+                found = true ;
+                break;
+            }
+        }
+    }
+}
+
 IMPLEMENT_ABSTRACT_CLASS( wxWidgetImpl , wxObject )
 
 wxWidgetImpl::wxWidgetImpl( wxWindowMac* peer , bool isRootControl )