X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/b2680ced12cbbed16990007c5fa3ea7730700122..8a07956565ddccd1720abf4e510945593128d774:/src/osx/carbon/bmpbuttn.cpp diff --git a/src/osx/carbon/bmpbuttn.cpp b/src/osx/carbon/bmpbuttn.cpp index 4421c143d7..a655e9cb69 100644 --- a/src/osx/carbon/bmpbuttn.cpp +++ b/src/osx/carbon/bmpbuttn.cpp @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: src/mac/carbon/bmpbuttn.cpp +// Name: src/osx/carbon/bmpbuttn.cpp // Purpose: wxBitmapButton // Author: Stefan Csomor // Modified by: @@ -20,170 +20,132 @@ #include "wx/dcmemory.h" #endif -IMPLEMENT_DYNAMIC_CLASS(wxBitmapButton, wxButton) +#include "wx/osx/private.h" -#include "wx/osx/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->IsOk(), 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