///////////////////////////////////////////////////////////////////////////// // Name: src/motif/button.cpp // Purpose: wxButton // Author: Julian Smart // Modified by: // Created: 17/09/98 // RCS-ID: $Id: button.cpp 50982 2008-01-01 20:38:33Z VZ $ // Copyright: (c) Julian Smart // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" #include "wx/button.h" #ifdef __VMS__ #pragma message disable nosimpint #endif #include #include #ifdef __VMS__ #pragma message enable nosimpint #endif #ifndef WX_PRECOMP #include "wx/toplevel.h" #endif #include "wx/stockitem.h" #include "wx/motif/private.h" #include "wx/sysopt.h" void wxButtonCallback (Widget w, XtPointer clientData, XtPointer ptr); IMPLEMENT_DYNAMIC_CLASS(wxButton, wxControl) #define MIN_WIDTH 78 #define MIN_LARGE_HEIGHT 30 // Button bool wxButton::Create(wxWindow *parent, wxWindowID id, const wxString& lbl, const wxPoint& pos, const wxSize& size, long style, const wxValidator& validator, const wxString& name) { wxString label(lbl); if (label.empty() && wxIsStockID(id)) label = wxGetStockLabel(id); if( !CreateControl( parent, id, pos, size, style, validator, name ) ) return false; wxXmString text( GetLabelText(label) ); Widget parentWidget = (Widget) parent->GetClientWidget(); /* * Patch Note (important) * There is no major reason to put a defaultButtonThickness here. * Not requesting it give the ability to put wxButton with a spacing * as small as requested. However, if some button become a DefaultButton, * other buttons are no more aligned -- This is why we set * defaultButtonThickness of ALL buttons belonging to the same wxPanel, * in the ::SetDefaultButton method. */ m_mainWidget = (WXWidget) XtVaCreateManagedWidget ("button", xmPushButtonWidgetClass, parentWidget, wxFont::GetFontTag(), m_font.GetFontTypeC(XtDisplay(parentWidget)), XmNlabelString, text(), XmNrecomputeSize, False, // See comment for wxButton::SetDefault // XmNdefaultButtonShadowThickness, 1, NULL); XtAddCallback ((Widget) m_mainWidget, XmNactivateCallback, (XtCallbackProc) wxButtonCallback, (XtPointer) this); wxSize best = GetBestSize(); if( size.x != -1 ) best.x = size.x; if( size.y != -1 ) best.y = size.y; AttachWidget (parent, m_mainWidget, (WXWidget) NULL, pos.x, pos.y, best.x, best.y); ChangeBackgroundColour(); return true; } void wxButton::SetDefaultShadowThicknessAndResize() { Widget buttonWidget = (Widget)GetMainWidget(); bool managed = XtIsManaged( buttonWidget ); if( managed ) XtUnmanageChild( buttonWidget ); XtVaSetValues( buttonWidget, XmNdefaultButtonShadowThickness, 1, NULL ); if( managed ) XtManageChild( buttonWidget ); // this can't currently be done, because user code that calls SetDefault // will break otherwise #if 0 wxSize best = GetBestSize(), actual = GetSize(); if( best.x < actual.x ) best.x = actual.x; if( best.y < actual.y ) best.y = actual.y; if( best != actual ) SetSize( best ); #endif InvalidateBestSize(); } void wxButton::SetDefault() { wxTopLevelWindow *tlw = wxDynamicCast(wxGetTopLevelParent(this), wxTopLevelWindow); if ( tlw ) tlw->SetDefaultItem(this); // We initially do not set XmNdefaultShadowThickness, to have // small buttons. Unfortunately, buttons are now mis-aligned. We // try to correct this now -- setting this ressource to 1 for each // button in the same row. Because it's very hard to find // wxButton in the same row, correction is straighforward: we set // resource for all wxButton in this parent (but not sub panels) wxWindow *parent = GetParent(); for (wxWindowList::compatibility_iterator node = parent->GetChildren().GetFirst (); node; node = node->GetNext ()) { wxWindow *win = node->GetData (); wxButton *item = wxDynamicCast(win, wxButton); if (item) item->SetDefaultShadowThicknessAndResize(); } XtVaSetValues ((Widget) parent->GetMainWidget(), XmNdefaultButton, (Widget) GetMainWidget(), NULL); } static inline bool wxMotifLargeButtons() { return wxSystemOptions::HasOption("motif.largebuttons") && wxSystemOptions::GetOptionInt("motif.largebuttons") != 0; } /* static */ wxSize wxButton::GetDefaultSize() { // TODO: check font size as in wxMSW ? MB // Note: this is the button size (text + margin + shadow + defaultBorder) return wxSize( MIN_WIDTH, MIN_LARGE_HEIGHT ); } wxSize wxButton::DoGetBestSize() const { if( wxMotifLargeButtons() ) return OldGetBestSize(); wxSize best = wxControl::DoGetBestSize(); if( HasFlag( wxBU_EXACTFIT ) ) return best; else if( best.x < MIN_WIDTH ) best.x = MIN_WIDTH; return best; } wxSize wxButton::GetMinSize() const { if( wxMotifLargeButtons() ) return OldGetMinSize(); return DoGetBestSize(); } wxSize wxButton::OldGetMinSize() const { return OldGetBestSize(); } wxSize wxButton::OldGetBestSize() const { Dimension xmargin, ymargin, highlight, shadow, defThickness; XtVaGetValues( (Widget)m_mainWidget, XmNmarginWidth, &xmargin, XmNmarginHeight, &ymargin, XmNhighlightThickness, &highlight, XmNshadowThickness, &shadow, XmNdefaultButtonShadowThickness, &defThickness, NULL ); int x = 0; int y = 0; GetTextExtent( GetLabel(), &x, &y ); int margin = highlight * 2 + ( defThickness ? ( ( shadow + defThickness ) * 4 ) : ( shadow * 2 ) ); wxSize best( x + xmargin * 2 + margin, y + ymargin * 2 + margin ); // all buttons have at least the standard size unless the user explicitly // wants them to be of smaller size and used wxBU_EXACTFIT style when // creating the button if( !HasFlag( wxBU_EXACTFIT ) ) { wxSize def = GetDefaultSize(); int margin = highlight * 2 + ( defThickness ? ( shadow * 4 + defThickness * 4 ) : 0 ); def.x += margin; def.y += margin; if( def.x > best.x ) best.x = def.x; if( def.y > best.y ) best.y = def.y; } return best; } void wxButton::Command (wxCommandEvent & event) { ProcessCommand (event); } void wxButtonCallback (Widget w, XtPointer clientData, XtPointer WXUNUSED(ptr)) { if (!wxGetWindowFromTable(w)) // Widget has been deleted! return; wxButton *item = (wxButton *) clientData; wxCommandEvent event (wxEVT_COMMAND_BUTTON_CLICKED, item->GetId()); event.SetEventObject(item); item->ProcessCommand (event); }