+// ----------------------------------------------------------------------------
+// button image data
+// ----------------------------------------------------------------------------
+
+// we use different data classes for owner drawn buttons and for themed XP ones
+
+class wxButtonImageData
+{
+public:
+ wxButtonImageData() { }
+
+ virtual wxBitmap GetBitmap(wxButton::State which) const = 0;
+ virtual void SetBitmap(const wxBitmap& bitmap, wxButton::State which) = 0;
+
+ virtual wxSize GetBitmapMargins() const = 0;
+ virtual void SetBitmapMargins(wxCoord x, wxCoord y) = 0;
+
+ virtual bool IsHorizontal() const = 0;
+ virtual void SetBitmapPosition(wxDirection dir) = 0;
+
+private:
+ wxDECLARE_NO_COPY_CLASS(wxButtonImageData);
+};
+
+namespace
+{
+
+class wxODButtonImageData : public wxButtonImageData
+{
+public:
+ wxODButtonImageData() { m_dir = wxLEFT; }
+
+ virtual wxBitmap GetBitmap(wxButton::State which) const
+ {
+ return m_bitmaps[which];
+ }
+
+ virtual void SetBitmap(const wxBitmap& bitmap, wxButton::State which)
+ {
+ m_bitmaps[which] = bitmap;
+ }
+
+ virtual wxSize GetBitmapMargins() const
+ {
+ return m_margin;
+ }
+
+ virtual void SetBitmapMargins(wxCoord x, wxCoord y)
+ {
+ m_margin = wxSize(x, y);
+ }
+
+ virtual bool IsHorizontal() const
+ {
+ return m_dir == wxLEFT || m_dir == wxRIGHT;
+ }
+
+ virtual void SetBitmapPosition(wxDirection dir)
+ {
+ m_dir = dir;
+ }
+
+private:
+ // just store the values passed to us to be able to retrieve them later
+ // from the drawing code
+ wxBitmap m_bitmaps[wxButton::State_Max];
+ wxSize m_margin;
+ wxDirection m_dir;
+
+ wxDECLARE_NO_COPY_CLASS(wxODButtonImageData);
+};
+
+#if wxUSE_UXTHEME
+
+class wxXPButtonImageData : public wxButtonImageData
+{
+public:
+ // we must be constructed with the size of our images as we need to create
+ // the image list
+ wxXPButtonImageData(wxButton *btn, const wxSize& size)
+ : m_iml(size.x, size.y, true /* use mask */, wxButton::State_Max),
+ m_hwndBtn(GetHwndOf(btn))
+ {
+ m_data.himl = GetHimagelistOf(&m_iml);
+
+ // use default margins
+ m_data.margin.left =
+ m_data.margin.right = btn->GetCharWidth();
+ m_data.margin.top =
+ m_data.margin.bottom = btn->GetCharHeight() / 2;
+
+ // and default alignment
+ m_data.uAlign = BUTTON_IMAGELIST_ALIGN_LEFT;
+ }
+
+ virtual wxBitmap GetBitmap(wxButton::State which) const
+ {
+ return m_iml.GetBitmap(which);
+ }
+
+ virtual void SetBitmap(const wxBitmap& bitmap, wxButton::State which)
+ {
+ const int imagesToAdd = which - m_iml.GetImageCount();
+ if ( imagesToAdd >= 0 )
+ {
+ if ( imagesToAdd > 0 )
+ {
+ const wxBitmap bmpNormal = GetBitmap(wxButton::State_Normal);
+ for ( int n = 0; n < imagesToAdd; n++ )
+ m_iml.Add(bmpNormal);
+ }
+
+ m_iml.Add(bitmap);
+ }
+ else // we already have this bitmap
+ {
+ m_iml.Replace(which, bitmap);
+ }
+
+ UpdateImageInfo();
+ }
+
+ virtual wxSize GetBitmapMargins() const
+ {
+ return wxSize(m_data.margin.left, m_data.margin.top);
+ }
+
+ virtual void SetBitmapMargins(wxCoord x, wxCoord y)
+ {
+ RECT& margin = m_data.margin;
+ margin.left =
+ margin.right = x;
+ margin.top =
+ margin.bottom = y;
+
+ if ( !::SendMessage(m_hwndBtn, BCM_SETTEXTMARGIN, 0, (LPARAM)&margin) )
+ {
+ wxLogDebug("SendMessage(BCM_SETTEXTMARGIN) failed");
+ }
+ }
+
+ virtual bool IsHorizontal() const
+ {
+ return m_data.uAlign == BUTTON_IMAGELIST_ALIGN_LEFT ||
+ m_data.uAlign == BUTTON_IMAGELIST_ALIGN_RIGHT;
+ }
+
+ virtual void SetBitmapPosition(wxDirection dir)
+ {
+ UINT alignNew;
+ switch ( dir )
+ {
+ default:
+ wxFAIL_MSG( "invalid direction" );
+ // fall through
+
+ case wxLEFT:
+ alignNew = BUTTON_IMAGELIST_ALIGN_LEFT;
+ break;
+
+ case wxRIGHT:
+ alignNew = BUTTON_IMAGELIST_ALIGN_RIGHT;
+ break;
+
+ case wxTOP:
+ alignNew = BUTTON_IMAGELIST_ALIGN_TOP;
+ break;
+
+ case wxBOTTOM:
+ alignNew = BUTTON_IMAGELIST_ALIGN_BOTTOM;
+ break;
+ }
+
+ if ( alignNew != m_data.uAlign )
+ {
+ m_data.uAlign = alignNew;
+ UpdateImageInfo();
+ }
+ }
+
+private:
+ void UpdateImageInfo()
+ {
+ if ( !::SendMessage(m_hwndBtn, BCM_SETIMAGELIST, 0, (LPARAM)&m_data) )
+ {
+ wxLogDebug("SendMessage(BCM_SETIMAGELIST) failed");
+ }
+ }
+
+ // we store image list separately to be able to use convenient wxImageList
+ // methods instead of working with raw HIMAGELIST
+ wxImageList m_iml;
+
+ // store the rest of the data in BCM_SETIMAGELIST-friendly form
+ BUTTON_IMAGELIST m_data;
+
+ // the button we're associated with
+ const HWND m_hwndBtn;
+
+
+ wxDECLARE_NO_COPY_CLASS(wxXPButtonImageData);
+};
+
+#endif // wxUSE_UXTHEME
+
+} // anonymous namespace
+