///////////////////////////////////////////////////////////////////////////// // Name: wxCustomButton based on wxCustomToggleCtrl.cpp // Purpose: a toggle button // Author: Bruce Phillips // Modified by: John Labenski // Created: 11/05/2002 // RCS-ID: // Copyright: (c) Bruce Phillips, John Labenki // Licence: wxWidgets licence ///////////////////////////////////////////////////////////////////////////// #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma implementation "toggle.h" #endif // For compilers that support precompilation, includes "wx/wx.h". #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif #ifndef WX_PRECOMP #include "wx/control.h" #include "wx/settings.h" #include "wx/bitmap.h" #include "wx/timer.h" #include "wx/dc.h" #include "wx/dcclient.h" #endif // WX_PRECOMP #include "wx/tglbtn.h" #include "wx/image.h" #include "wx/things/toggle.h" // ========================================================================== // wxCustomButton // ========================================================================== IMPLEMENT_DYNAMIC_CLASS( wxCustomButton, wxControl ) BEGIN_EVENT_TABLE(wxCustomButton,wxControl) EVT_MOUSE_EVENTS ( wxCustomButton::OnMouseEvents ) EVT_PAINT ( wxCustomButton::OnPaint ) EVT_TIMER ( wxID_ANY, wxCustomButton::OnTimer) EVT_SIZE ( wxCustomButton::OnSize ) END_EVENT_TABLE() wxCustomButton::~wxCustomButton() { if (HasCapture()) ReleaseMouse(); if (m_timer) delete m_timer; } void wxCustomButton::Init() { m_focused = false; m_labelMargin = wxSize(4,4); m_bitmapMargin = wxSize(2,2); m_down = 0; m_timer = NULL; m_eventType = 0; m_button_style = wxCUSTBUT_TOGGLE|wxCUSTBUT_BOTTOM; } bool wxCustomButton::Create(wxWindow* parent, wxWindowID id, const wxString& label, const wxBitmap &bitmap, const wxPoint& pos, const wxSize& size, long style, const wxValidator& val, const wxString& name) { if (!wxControl::Create(parent,id,pos,size,wxNO_BORDER|wxCLIP_CHILDREN,val,name)) return false; wxControl::SetLabel(label); wxControl::SetBackgroundColour(parent->GetBackgroundColour()); wxControl::SetForegroundColour(parent->GetForegroundColour()); wxControl::SetFont(parent->GetFont()); if (bitmap.Ok()) m_bmpLabel = bitmap; if (!SetButtonStyle(style)) return false; wxSize bestSize = DoGetBestSize(); SetSize(wxSize(size.x<0 ? bestSize.x:size.x, size.y<0 ? bestSize.y:size.y)); SetBestSize(GetSize()); CalcLayout(true); return true; } void wxCustomButton::SetValue(bool depressed) { wxCHECK_RET(!(m_button_style & wxCUSTBUT_NOTOGGLE), wxT("can't set button state")); m_down = depressed ? 1 : 0; Refresh(false); } bool wxCustomButton::SetButtonStyle(long style) { int n_styles = 0; if ((style & wxCUSTBUT_LEFT) != 0) n_styles++; if ((style & wxCUSTBUT_RIGHT) != 0) n_styles++; if ((style & wxCUSTBUT_TOP) != 0) n_styles++; if ((style & wxCUSTBUT_BOTTOM) != 0) n_styles++; wxCHECK_MSG(n_styles < 2, false, wxT("Only one wxCustomButton label position allowed")); n_styles = 0; if ((style & wxCUSTBUT_NOTOGGLE) != 0) n_styles++; if ((style & wxCUSTBUT_BUTTON) != 0) n_styles++; if ((style & wxCUSTBUT_TOGGLE) != 0) n_styles++; if ((style & wxCUSTBUT_BUT_DCLICK_TOG) != 0) n_styles++; if ((style & wxCUSTBUT_TOG_DCLICK_BUT) != 0) n_styles++; wxCHECK_MSG(n_styles < 2, false, wxT("Only one wxCustomButton style allowed")); m_button_style = style; if ((m_button_style & wxCUSTBUT_BUTTON) != 0) m_down = 0; CalcLayout(true); return true; } void wxCustomButton::SetLabel( const wxString &label ) { wxControl::SetLabel(label); CalcLayout(true); } // sequence of events in GTK is up, dclick, up. void wxCustomButton::OnMouseEvents(wxMouseEvent& event) { if (m_button_style & wxCUSTBUT_NOTOGGLE) return; if (event.LeftDown() || event.RightDown()) { if (!HasCapture()) CaptureMouse(); // keep depressed until up m_down++; Redraw(); } else if (event.LeftDClick() || event.RightDClick()) { m_down++; // GTK eats second down event Redraw(); } else if (event.LeftUp()) { if (HasCapture()) ReleaseMouse(); m_eventType = wxEVT_LEFT_UP; if (wxRect(wxPoint(0,0), GetSize()).Inside(event.GetPosition())) { if ((m_button_style & wxCUSTBUT_BUTTON) && (m_down > 0)) { m_down = 0; Redraw(); SendEvent(); return; } else { if (!m_timer) { m_timer = new wxTimer(this, m_down+1); m_timer->Start(200, true); } else { m_eventType = wxEVT_LEFT_DCLICK; } if ((m_button_style & wxCUSTBUT_TOGGLE) && (m_button_style & wxCUSTBUT_TOG_DCLICK_BUT)) m_down++; } } Redraw(); } else if (event.RightUp()) { if (HasCapture()) ReleaseMouse(); m_eventType = wxEVT_RIGHT_UP; if (wxRect(wxPoint(0,0), GetSize()).Inside(event.GetPosition())) { if ((m_button_style & wxCUSTBUT_BUTTON) && (m_down > 0)) { m_down = 0; Redraw(); SendEvent(); return; } else { m_down++; if (!m_timer) { m_timer = new wxTimer(this, m_down); m_timer->Start(250, true); } else { m_eventType = wxEVT_RIGHT_DCLICK; } } } Redraw(); } else if (event.Entering()) { m_focused = true; if ((event.LeftIsDown() || event.RightIsDown()) && HasCapture()) m_down++; Redraw(); } else if (event.Leaving()) { m_focused = false; if ((event.LeftIsDown() || event.RightIsDown()) && HasCapture()) m_down--; Redraw(); } } void wxCustomButton::OnTimer( wxTimerEvent &event ) { m_timer->Stop(); delete m_timer; m_timer = NULL; // Clean up the button presses // FIXME - GTK eats second left down for a DClick, who know about the others? if (m_button_style & wxCUSTBUT_BUTTON) { m_down = 0; } else if (m_button_style & wxCUSTBUT_TOGGLE) { if (m_eventType == wxEVT_LEFT_UP) m_down = event.GetId()%2 ? 0 : 1; else m_down = event.GetId()%2 ? 1 : 0; } else if (m_button_style & wxCUSTBUT_BUT_DCLICK_TOG) { if (m_eventType == wxEVT_LEFT_DCLICK) m_down = event.GetId()%2 ? 0 : 1; else m_down = event.GetId()%2 ? 1 : 0; } else if (m_button_style & wxCUSTBUT_TOG_DCLICK_BUT) { if (m_eventType == wxEVT_LEFT_UP) m_down = event.GetId()%2 ? 0 : 1; else m_down = event.GetId()%2 ? 1 : 0; } Refresh(false); SendEvent(); } void wxCustomButton::SendEvent() { if (((m_button_style & wxCUSTBUT_TOGGLE) && (m_eventType == wxEVT_LEFT_UP)) || ((m_button_style & wxCUSTBUT_BUT_DCLICK_TOG) && (m_eventType == wxEVT_LEFT_DCLICK)) || ((m_button_style & wxCUSTBUT_TOG_DCLICK_BUT) && (m_eventType == wxEVT_LEFT_UP))) { wxCommandEvent eventOut(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, GetId()); eventOut.SetInt(m_down%2 ? 1 : 0); eventOut.SetExtraLong(m_eventType); eventOut.SetEventObject(this); GetEventHandler()->ProcessEvent(eventOut); } else { wxCommandEvent eventOut(wxEVT_COMMAND_BUTTON_CLICKED, GetId()); eventOut.SetInt(0); eventOut.SetExtraLong(m_eventType); eventOut.SetEventObject(this); GetEventHandler()->ProcessEvent(eventOut); } } wxBitmap wxCustomButton::CreateBitmapDisabled(const wxBitmap &bitmap) const { wxCHECK_MSG(bitmap.Ok(), wxNullBitmap, wxT("invalid bitmap")); unsigned char br = GetBackgroundColour().Red(); unsigned char bg = GetBackgroundColour().Green(); unsigned char bb = GetBackgroundColour().Blue(); wxImage image = bitmap.ConvertToImage(); int pos, width = image.GetWidth(), height = image.GetHeight(); unsigned char *img_data = image.GetData(); for (int j=0; j lh ? bh : lh; if (has_bitmap && has_label) lw -= wxMin(m_labelMargin.x, m_bitmapMargin.x); return wxSize(lw+bw, h); } int w = bw > lw ? bw : lw; if (has_bitmap && has_label) lh -= wxMin(m_labelMargin.y, m_bitmapMargin.y); return wxSize(w, lh+bh); } void wxCustomButton::CalcLayout(bool refresh) { int w, h; GetSize(&w,&h); int bw = 0, bh = 0; int lw = 0, lh = 0; if (m_bmpLabel.Ok()) // assume they're all the same size { bw = m_bmpLabel.GetWidth(); bh = m_bmpLabel.GetHeight(); } wxString label = GetLabel(); if (!label.IsEmpty()) { GetTextExtent(label, &lw, &lh); } // Center the label or bitmap if only one or the other if (!m_bmpLabel.Ok()) { m_bitmapPos = wxPoint(0,0); m_labelPos = wxPoint((w-lw)/2, (h-lh)/2); } else if (label.IsEmpty()) { m_bitmapPos = wxPoint((w-bw)/2, (h-bh)/2); m_labelPos = wxPoint(0,0); } else if (m_button_style & wxCUSTBUT_LEFT) { int mid_margin = wxMax(m_labelMargin.x, m_bitmapMargin.x); m_labelPos = wxPoint((w - (bw+lw+m_labelMargin.x+m_bitmapMargin.x+mid_margin))/2 + m_labelMargin.x, (h - lh)/2); m_bitmapPos = wxPoint(m_labelPos.x + lw + mid_margin, (h - bh)/2); } else if (m_button_style & wxCUSTBUT_RIGHT) { int mid_margin = wxMax(m_labelMargin.x, m_bitmapMargin.x); m_bitmapPos = wxPoint((w - (bw+lw+m_labelMargin.x+m_bitmapMargin.x+mid_margin))/2 + m_bitmapMargin.x, (h - bh)/2); m_labelPos = wxPoint(m_bitmapPos.x + bw + mid_margin, (h - lh)/2); } else if (m_button_style & wxCUSTBUT_TOP) { int mid_margin = wxMax(m_labelMargin.y, m_bitmapMargin.y); m_labelPos = wxPoint((w - lw)/2, (h - (bh+lh+m_labelMargin.y+m_bitmapMargin.y+mid_margin))/2 + m_labelMargin.y); m_bitmapPos = wxPoint((w - bw)/2, m_labelPos.y + lh + mid_margin); } else // if (m_button_style & wxCUSTBUT_BOTTOM) DEFAULT { int mid_margin = wxMax(m_labelMargin.y, m_bitmapMargin.y); m_bitmapPos = wxPoint((w - bw)/2, (h - (bh+lh+m_labelMargin.y+m_bitmapMargin.y+mid_margin))/2 + m_bitmapMargin.y); m_labelPos = wxPoint((w - lw)/2, m_bitmapPos.y + bh + mid_margin); } if (refresh) Refresh(false); }