1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/motif/button.cpp 
   4 // Author:      Julian Smart 
   8 // Copyright:   (c) Julian Smart 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // For compilers that support precompilation, includes "wx.h". 
  13 #include "wx/wxprec.h" 
  15 #include "wx/button.h" 
  18 #pragma message disable nosimpint 
  20 #include <Xm/PushBG.h> 
  23 #pragma message enable nosimpint 
  28     #include "wx/toplevel.h" 
  31 #include "wx/stockitem.h" 
  32 #include "wx/motif/private.h" 
  33 #include "wx/sysopt.h" 
  35 void wxButtonCallback (Widget w
, XtPointer clientData
, XtPointer ptr
); 
  37 IMPLEMENT_DYNAMIC_CLASS(wxButton
, wxControl
) 
  40 #define MIN_LARGE_HEIGHT 30 
  44 bool wxButton::Create(wxWindow 
*parent
, wxWindowID id
, const wxString
& lbl
, 
  46                       const wxSize
& size
, long style
, 
  47                       const wxValidator
& validator
, 
  51     if (label
.empty() && wxIsStockID(id
)) 
  52         label 
= wxGetStockLabel(id
); 
  54     if( !CreateControl( parent
, id
, pos
, size
, style
, validator
, name 
) ) 
  58     wxXmString 
text( GetLabelText(label
) ); 
  60     Widget parentWidget 
= (Widget
) parent
->GetClientWidget(); 
  63     * Patch Note (important) 
  64     * There is no major reason to put a defaultButtonThickness here. 
  65     * Not requesting it give the ability to put wxButton with a spacing 
  66     * as small as requested. However, if some button become a DefaultButton, 
  67     * other buttons are no more aligned -- This is why we set 
  68     * defaultButtonThickness of ALL buttons belonging to the same wxPanel, 
  69     * in the ::SetDefaultButton method. 
  71     m_mainWidget 
= (WXWidget
) XtVaCreateManagedWidget ("button", 
  72         xmPushButtonWidgetClass
, 
  74         wxFont::GetFontTag(), m_font
.GetFontTypeC(XtDisplay(parentWidget
)), 
  75         XmNlabelString
, text(), 
  76         XmNrecomputeSize
, False
, 
  77         // See comment for wxButton::SetDefault 
  78         // XmNdefaultButtonShadowThickness, 1, 
  81     XtAddCallback ((Widget
) m_mainWidget
, 
  82                    XmNactivateCallback
, (XtCallbackProc
) wxButtonCallback
, 
  85     wxSize best 
= GetBestSize(); 
  86     if( size
.x 
!= -1 ) best
.x 
= size
.x
; 
  87     if( size
.y 
!= -1 ) best
.y 
= size
.y
; 
  90     AttachWidget (parent
, m_mainWidget
, (WXWidget
) NULL
, 
  91                   pos
.x
, pos
.y
, best
.x
, best
.y
); 
  96 void wxButton::SetDefaultShadowThicknessAndResize() 
  98     Widget buttonWidget 
= (Widget
)GetMainWidget(); 
  99     bool managed 
= XtIsManaged( buttonWidget 
); 
 101         XtUnmanageChild( buttonWidget 
); 
 103     XtVaSetValues( buttonWidget
, 
 104                    XmNdefaultButtonShadowThickness
, 1, 
 108         XtManageChild( buttonWidget 
); 
 110     // this can't currently be done, because user code that calls SetDefault 
 111     // will break otherwise 
 113     wxSize best 
= GetBestSize(), actual 
= GetSize(); 
 114     if( best
.x 
< actual
.x 
) best
.x 
= actual
.x
; 
 115     if( best
.y 
< actual
.y 
) best
.y 
= actual
.y
; 
 120     InvalidateBestSize(); 
 124 wxWindow 
*wxButton::SetDefault() 
 126     wxWindow 
*oldDefault 
= wxButtonBase::SetDefault(); 
 128     // We initially do not set XmNdefaultShadowThickness, to have 
 129     // small buttons.  Unfortunately, buttons are now mis-aligned. We 
 130     // try to correct this now -- setting this ressource to 1 for each 
 131     // button in the same row.  Because it's very hard to find 
 132     // wxButton in the same row, correction is straighforward: we set 
 133     // resource for all wxButton in this parent (but not sub panels) 
 135     wxWindow 
*parent 
= GetParent(); 
 136     for (wxWindowList::compatibility_iterator node 
= parent
->GetChildren().GetFirst (); 
 137          node
; node 
= node
->GetNext ()) 
 139         wxWindow 
*win 
= node
->GetData (); 
 140         wxButton 
*item 
= wxDynamicCast(win
, wxButton
); 
 142             item
->SetDefaultShadowThicknessAndResize(); 
 145     XtVaSetValues ((Widget
) parent
->GetMainWidget(), 
 146                    XmNdefaultButton
, (Widget
) GetMainWidget(), 
 152 static inline bool wxMotifLargeButtons() 
 154     return wxSystemOptions::HasOption("motif.largebuttons") 
 155         && wxSystemOptions::GetOptionInt("motif.largebuttons") != 0; 
 159 wxSize 
wxButton::GetDefaultSize() 
 161     // TODO: check font size as in wxMSW ?  MB 
 162     // Note: this is the button size (text + margin + shadow + defaultBorder) 
 163     return wxSize( MIN_WIDTH
, MIN_LARGE_HEIGHT 
); 
 166 wxSize 
wxButton::DoGetBestSize() const 
 168     if( wxMotifLargeButtons() ) 
 169         return OldGetBestSize(); 
 171     wxSize best 
= wxControl::DoGetBestSize(); 
 173     if( HasFlag( wxBU_EXACTFIT 
) ) 
 175     else if( best
.x 
< MIN_WIDTH 
) 
 181 wxSize 
wxButton::GetMinSize() const 
 183     if( wxMotifLargeButtons() ) 
 184         return OldGetMinSize(); 
 186     return DoGetBestSize(); 
 189 wxSize 
wxButton::OldGetMinSize() const 
 191     return OldGetBestSize(); 
 194 wxSize 
wxButton::OldGetBestSize() const 
 196     Dimension xmargin
, ymargin
, highlight
, shadow
, defThickness
; 
 198     XtVaGetValues( (Widget
)m_mainWidget
, 
 199                    XmNmarginWidth
, &xmargin
, 
 200                    XmNmarginHeight
, &ymargin
, 
 201                    XmNhighlightThickness
, &highlight
, 
 202                    XmNshadowThickness
, &shadow
, 
 203                    XmNdefaultButtonShadowThickness
, &defThickness
, 
 206     int x 
= 0;  int y 
= 0; 
 207     GetTextExtent( GetLabel(), &x
, &y 
); 
 209     int margin 
= highlight 
* 2 + 
 210         ( defThickness 
? ( ( shadow 
+ defThickness 
) * 4 ) : ( shadow 
* 2 ) ); 
 212     wxSize 
best( x 
+ xmargin 
* 2 + margin
, 
 213                  y 
+ ymargin 
* 2 + margin 
); 
 215     // all buttons have at least the standard size unless the user explicitly 
 216     // wants them to be of smaller size and used wxBU_EXACTFIT style when 
 217     // creating the button 
 218     if( !HasFlag( wxBU_EXACTFIT 
) ) 
 220         wxSize def 
= GetDefaultSize(); 
 221         int margin 
=  highlight 
* 2 + 
 222             ( defThickness 
? ( shadow 
* 4 + defThickness 
* 4 ) : 0 ); 
 235 void wxButton::Command (wxCommandEvent 
& event
) 
 237     ProcessCommand (event
); 
 240 void wxButtonCallback (Widget w
, XtPointer clientData
, XtPointer 
WXUNUSED(ptr
)) 
 242     if (!wxGetWindowFromTable(w
)) 
 243         // Widget has been deleted! 
 246     wxButton 
*item 
= (wxButton 
*) clientData
; 
 247     wxCommandEvent 
event (wxEVT_COMMAND_BUTTON_CLICKED
, item
->GetId()); 
 248     event
.SetEventObject(item
); 
 249     item
->ProcessCommand (event
);