]> git.saurik.com Git - wxWidgets.git/blobdiff - src/osx/carbon/bmpbuttn.cpp
use correct scale when drawing
[wxWidgets.git] / src / osx / carbon / bmpbuttn.cpp
index 5757f50b845b2d53d27771ddaa4418e4039af97d..a655e9cb6980ab2c4a20856a831e2d3645347f12 100644 (file)
@@ -1,5 +1,5 @@
 /////////////////////////////////////////////////////////////////////////////
-// Name:        src/mac/carbon/bmpbuttn.cpp
+// Name:        src/osx/carbon/bmpbuttn.cpp
 // Purpose:     wxBitmapButton
 // Author:      Stefan Csomor
 // Modified by:
     #include "wx/dcmemory.h"
 #endif
 
-IMPLEMENT_DYNAMIC_CLASS(wxBitmapButton, wxButton)
+#include "wx/osx/private.h"
 
-#include "wx/mac/uma.h"
-
-//---------------------------------------------------------------------------
-// Helper functions
-
-static wxBitmap wxMakeStdSizeBitmap(const wxBitmap& bitmap)
+namespace
 {
-    // in Mac OS X the icon controls (which are used for borderless bitmap
-    // buttons) can have only one of the few standard sizes and if they
-    // don't, the OS rescales them automatically resulting in really ugly
-    // images, so centre the image in a square of standard size instead
-
-    // the supported sizes, sorted in decreasng order
-    static const int stdSizes[] = { 128, 48, 32, 16, 0 };
 
-    const int width = bitmap.GetWidth();
-    const int height = bitmap.GetHeight();
-
-    wxBitmap newBmp(bitmap);
-    
-    int n;
-    for ( n = 0; n < (int)WXSIZEOF(stdSizes); n++ )
+// define a derived class to override SetBitmap() and also to provide
+// InitButtonContentInfo() helper used by CreateBitmapButton()
+class wxMacBitmapButton : public wxMacControl, public wxButtonImpl
+{
+public:
+    wxMacBitmapButton(wxWindowMac* peer, const wxBitmap& bitmap, int style)
+        : wxMacControl(peer)
     {
-        const int sizeStd = stdSizes[n];
-        if ( width > sizeStd || height > sizeStd )
-        {
-            // it will become -1 if the bitmap is larger than the biggest
-            // supported size, this is intentional
-            n--;
-
-            break;
-        }
+        // decide what kind of contents the button will have: we want to use an
+        // icon for buttons with wxBORDER_NONE style as bevel buttons always do
+        // have a border but icons are limited to a few standard sizes only and
+        // are resized by the system with extremely ugly results if they don't
+        // fit (in the past we also tried being smart and pasting a bitmap
+        // instead of a larger square icon to avoid resizing but this resulted
+        // in buttons having different size than specified by wx API and
+        // breaking the layouts and still didn't look good so we don't even try
+        // to do this any more)
+        m_isIcon = (style & wxBORDER_NONE) &&
+                        bitmap.IsOk() && IsOfStandardSize(bitmap);
     }
 
-    if ( n != -1 )
+    virtual void SetBitmap(const wxBitmap& bitmap)
     {
-        const int sizeStd = stdSizes[n];
-        if ( width != sizeStd || height != sizeStd )
-        {
-            wxASSERT_MSG( width <= sizeStd && height <= sizeStd,
-                          _T("bitmap shouldn't be cropped") );
-
-            wxImage square_image = bitmap.ConvertToImage();
-            newBmp = square_image.Size
-                     (
-                         wxSize(sizeStd, sizeStd),
-                         wxPoint((sizeStd - width)/2, (sizeStd-height)/2)
-                     );
-        }
+        // unfortunately we can't avoid the ugly resizing problem mentioned
+        // above if a bitmap of supported size was used initially but was
+        // replaced with another one later as the control was already created
+        // as an icon control (although maybe we ought to recreate it?)
+        ControlButtonContentInfo info;
+        InitButtonContentInfo(info, bitmap);
+
+        if ( info.contentType == kControlContentIconRef )
+            SetData(kControlIconPart, kControlIconContentTag, info);
+        else if ( info.contentType != kControlNoContent )
+            SetData(kControlButtonPart, kControlBevelButtonContentTag, info);
+
+        wxMacReleaseBitmapButton(&info);
     }
-    //else: let the system rescale the bitmap
-
-    return newBmp;
-}
-
-//---------------------------------------------------------------------------
-
-bool wxBitmapButton::Create( wxWindow *parent,
-                             wxWindowID id, const wxBitmap& bitmap,
-                             const wxPoint& pos,
-                             const wxSize& size,
-                             long style,
-                             const wxValidator& validator,
-                             const wxString& name )
-{
-    m_macIsUserPane = false;
-
-    // since bitmapbuttonbase is subclass of button calling wxBitmapButtonBase::Create
-    // essentially creates an additional button
-    if ( !wxControl::Create( parent, id, pos, size, style, validator, name ) )
-        return false;
 
-    if ( style & wxBU_AUTODRAW )
+    void InitButtonContentInfo(ControlButtonContentInfo& info,
+                               const wxBitmap& bitmap)
     {
-        m_marginX =
-        m_marginY = wxDEFAULT_BUTTON_MARGIN;
+        wxMacCreateBitmapButton(&info, bitmap,
+                                m_isIcon ? kControlContentIconRef : 0);
     }
-    else
-    {
-        m_marginX =
-        m_marginY = 0;
-    }
-
-    OSStatus err = noErr;
-    ControlButtonContentInfo info;
-
-    Rect bounds = wxMacGetBoundsForControl( this, pos, size );
-    m_peer = new wxMacControl( this );
-
-    if ( bitmap.Ok() && HasFlag(wxBORDER_NONE) )
-        m_bmpNormal = wxMakeStdSizeBitmap(bitmap);
-    else
-        m_bmpNormal = bitmap;
-
 
-    if ( HasFlag( wxBORDER_NONE ) )
+    void SetPressedBitmap( const wxBitmap& WXUNUSED(bitmap) )
     {
-               // contrary to the docs this control only works with iconrefs
-        wxMacCreateBitmapButton( &info, m_bmpNormal, kControlContentIconRef );
-        err = CreateIconControl(
-                MAC_WXHWND(parent->MacGetTopLevelWindowRef()),
-                &bounds, &info, false, m_peer->GetControlRefAddr() );
+        // not implemented under Carbon
     }
-    else
+
+private:
+    // helper function: returns true if the given bitmap is of one of standard
+    // sizes supported by OS X icons
+    static bool IsOfStandardSize(const wxBitmap& bmp)
     {
-        wxMacCreateBitmapButton( &info, m_bmpNormal );
-        err = CreateBevelButtonControl(
-                MAC_WXHWND(parent->MacGetTopLevelWindowRef()), &bounds, CFSTR(""),
-                ((style & wxBU_AUTODRAW) ? kControlBevelButtonSmallBevel : kControlBevelButtonNormalBevel ),
-                kControlBehaviorOffsetContents, &info, 0, 0, 0, m_peer->GetControlRefAddr() );
+        const int w = bmp.GetWidth();
+
+        return bmp.GetHeight() == w &&
+                (w == 128 || w == 48 || w == 32 || w == 16);
     }
 
-    verify_noerr( err );
 
-    wxMacReleaseBitmapButton( &info );
-    wxASSERT_MSG( m_peer != NULL && m_peer->Ok(), wxT("No valid native Mac control") );
+    // true if this is an icon control, false if it's a bevel button
+    bool m_isIcon;
 
-    MacPostControlCreate( pos, size );
+    wxDECLARE_NO_COPY_CLASS(wxMacBitmapButton);
+};
 
-    return true;
-}
+} // anonymous namespace
 
-void wxBitmapButton::SetBitmapLabel( const wxBitmap& bitmap )
+wxWidgetImplType* wxWidgetImpl::CreateBitmapButton( wxWindowMac* wxpeer,
+                                    wxWindowMac* parent,
+                                    wxWindowID WXUNUSED(id),
+                                    const wxBitmap& bitmap,
+                                    const wxPoint& pos,
+                                    const wxSize& size,
+                                    long style,
+                                    long WXUNUSED(extraStyle))
 {
-    if ( HasFlag( wxBORDER_NONE ) )
-        m_bmpNormal = wxMakeStdSizeBitmap(bitmap);
-    else
-        m_bmpNormal = bitmap;
-    
-    InvalidateBestSize();
+    wxMacBitmapButton* peer = new wxMacBitmapButton(wxpeer, bitmap, style);
+
+    OSStatus err;
+    WXWindow macParent = MAC_WXHWND(parent->MacGetTopLevelWindowRef());
+    Rect bounds = wxMacGetBoundsForControl( wxpeer, pos, size );
 
     ControlButtonContentInfo info;
+    peer->InitButtonContentInfo(info, bitmap);
 
-    if ( HasFlag( wxBORDER_NONE ) )
-    {        
-        wxMacCreateBitmapButton( &info, m_bmpNormal, kControlContentIconRef );
-        if ( info.contentType != kControlNoContent )
-            m_peer->SetData( kControlIconPart, kControlIconContentTag, info );
-    }
-    else
+    if ( info.contentType == kControlContentIconRef )
     {
-        wxMacCreateBitmapButton( &info, m_bmpNormal );
-        if ( info.contentType != kControlNoContent )
-            m_peer->SetData( kControlButtonPart, kControlBevelButtonContentTag, info );
+        err = CreateIconControl
+              (
+                macParent,
+                &bounds,
+                &info,
+                false,
+                peer->GetControlRefAddr()
+              );
     }
-
-    wxMacReleaseBitmapButton( &info );
-}
-
-wxSize wxBitmapButton::DoGetBestSize() const
-{
-    wxSize best;
-
-    best.x = 2 * m_marginX;
-    best.y = 2 * m_marginY;
-    if ( m_bmpNormal.Ok() )
+    else // normal bevel button
     {
-        best.x += m_bmpNormal.GetWidth();
-        best.y += m_bmpNormal.GetHeight();
+        err = CreateBevelButtonControl
+              (
+                macParent,
+                &bounds,
+                CFSTR(""),
+                style & wxBU_AUTODRAW ? kControlBevelButtonSmallBevel
+                                      : kControlBevelButtonNormalBevel,
+                kControlBehaviorOffsetContents,
+                &info,
+                0,  // menu id (no associated menu)
+                0,  // menu behaviour (unused)
+                0,  // menu placement (unused too)
+                peer->GetControlRefAddr()
+              );
     }
 
-    return best;
+    verify_noerr( err );
+
+    wxMacReleaseBitmapButton( &info );
+    return peer;
 }
 
-#endif
+#endif // wxUSE_BMPBUTTON