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
); 
  38 #define MIN_LARGE_HEIGHT 30 
  42 bool wxButton::Create(wxWindow 
*parent
, wxWindowID id
, const wxString
& lbl
, 
  44                       const wxSize
& size
, long style
, 
  45                       const wxValidator
& validator
, 
  49     if (label
.empty() && wxIsStockID(id
)) 
  50         label 
= wxGetStockLabel(id
); 
  52     if( !CreateControl( parent
, id
, pos
, size
, style
, validator
, name 
) ) 
  56     wxXmString 
text( GetLabelText(label
) ); 
  58     Widget parentWidget 
= (Widget
) parent
->GetClientWidget(); 
  61     * Patch Note (important) 
  62     * There is no major reason to put a defaultButtonThickness here. 
  63     * Not requesting it give the ability to put wxButton with a spacing 
  64     * as small as requested. However, if some button become a DefaultButton, 
  65     * other buttons are no more aligned -- This is why we set 
  66     * defaultButtonThickness of ALL buttons belonging to the same wxPanel, 
  67     * in the ::SetDefaultButton method. 
  69     m_mainWidget 
= (WXWidget
) XtVaCreateManagedWidget ("button", 
  70         xmPushButtonWidgetClass
, 
  72         wxFont::GetFontTag(), m_font
.GetFontTypeC(XtDisplay(parentWidget
)), 
  73         XmNlabelString
, text(), 
  74         XmNrecomputeSize
, False
, 
  75         // See comment for wxButton::SetDefault 
  76         // XmNdefaultButtonShadowThickness, 1, 
  79     XtAddCallback ((Widget
) m_mainWidget
, 
  80                    XmNactivateCallback
, (XtCallbackProc
) wxButtonCallback
, 
  83     wxSize best 
= GetBestSize(); 
  84     if( size
.x 
!= -1 ) best
.x 
= size
.x
; 
  85     if( size
.y 
!= -1 ) best
.y 
= size
.y
; 
  88     AttachWidget (parent
, m_mainWidget
, (WXWidget
) NULL
, 
  89                   pos
.x
, pos
.y
, best
.x
, best
.y
); 
  94 void wxButton::SetDefaultShadowThicknessAndResize() 
  96     Widget buttonWidget 
= (Widget
)GetMainWidget(); 
  97     bool managed 
= XtIsManaged( buttonWidget 
); 
  99         XtUnmanageChild( buttonWidget 
); 
 101     XtVaSetValues( buttonWidget
, 
 102                    XmNdefaultButtonShadowThickness
, 1, 
 106         XtManageChild( buttonWidget 
); 
 108     // this can't currently be done, because user code that calls SetDefault 
 109     // will break otherwise 
 111     wxSize best 
= GetBestSize(), actual 
= GetSize(); 
 112     if( best
.x 
< actual
.x 
) best
.x 
= actual
.x
; 
 113     if( best
.y 
< actual
.y 
) best
.y 
= actual
.y
; 
 118     InvalidateBestSize(); 
 122 wxWindow 
*wxButton::SetDefault() 
 124     wxWindow 
*oldDefault 
= wxButtonBase::SetDefault(); 
 126     // We initially do not set XmNdefaultShadowThickness, to have 
 127     // small buttons.  Unfortunately, buttons are now mis-aligned. We 
 128     // try to correct this now -- setting this ressource to 1 for each 
 129     // button in the same row.  Because it's very hard to find 
 130     // wxButton in the same row, correction is straighforward: we set 
 131     // resource for all wxButton in this parent (but not sub panels) 
 133     wxWindow 
*parent 
= GetParent(); 
 134     for (wxWindowList::compatibility_iterator node 
= parent
->GetChildren().GetFirst (); 
 135          node
; node 
= node
->GetNext ()) 
 137         wxWindow 
*win 
= node
->GetData (); 
 138         wxButton 
*item 
= wxDynamicCast(win
, wxButton
); 
 140             item
->SetDefaultShadowThicknessAndResize(); 
 143     XtVaSetValues ((Widget
) parent
->GetMainWidget(), 
 144                    XmNdefaultButton
, (Widget
) GetMainWidget(), 
 150 static inline bool wxMotifLargeButtons() 
 152     return wxSystemOptions::HasOption("motif.largebuttons") 
 153         && wxSystemOptions::GetOptionInt("motif.largebuttons") != 0; 
 157 wxSize 
wxButton::GetDefaultSize() 
 159     // TODO: check font size as in wxMSW ?  MB 
 160     // Note: this is the button size (text + margin + shadow + defaultBorder) 
 161     return wxSize( MIN_WIDTH
, MIN_LARGE_HEIGHT 
); 
 164 wxSize 
wxButton::DoGetBestSize() const 
 166     if( wxMotifLargeButtons() ) 
 167         return OldGetBestSize(); 
 169     wxSize best 
= wxControl::DoGetBestSize(); 
 171     if( HasFlag( wxBU_EXACTFIT 
) ) 
 173     else if( best
.x 
< MIN_WIDTH 
) 
 179 wxSize 
wxButton::GetMinSize() const 
 181     if( wxMotifLargeButtons() ) 
 182         return OldGetMinSize(); 
 184     return DoGetBestSize(); 
 187 wxSize 
wxButton::OldGetMinSize() const 
 189     return OldGetBestSize(); 
 192 wxSize 
wxButton::OldGetBestSize() const 
 194     Dimension xmargin
, ymargin
, highlight
, shadow
, defThickness
; 
 196     XtVaGetValues( (Widget
)m_mainWidget
, 
 197                    XmNmarginWidth
, &xmargin
, 
 198                    XmNmarginHeight
, &ymargin
, 
 199                    XmNhighlightThickness
, &highlight
, 
 200                    XmNshadowThickness
, &shadow
, 
 201                    XmNdefaultButtonShadowThickness
, &defThickness
, 
 204     int x 
= 0;  int y 
= 0; 
 205     GetTextExtent( GetLabel(), &x
, &y 
); 
 207     int margin 
= highlight 
* 2 + 
 208         ( defThickness 
? ( ( shadow 
+ defThickness 
) * 4 ) : ( shadow 
* 2 ) ); 
 210     wxSize 
best( x 
+ xmargin 
* 2 + margin
, 
 211                  y 
+ ymargin 
* 2 + margin 
); 
 213     // all buttons have at least the standard size unless the user explicitly 
 214     // wants them to be of smaller size and used wxBU_EXACTFIT style when 
 215     // creating the button 
 216     if( !HasFlag( wxBU_EXACTFIT 
) ) 
 218         wxSize def 
= GetDefaultSize(); 
 219         int margin 
=  highlight 
* 2 + 
 220             ( defThickness 
? ( shadow 
* 4 + defThickness 
* 4 ) : 0 ); 
 233 void wxButton::Command (wxCommandEvent 
& event
) 
 235     ProcessCommand (event
); 
 238 void wxButtonCallback (Widget w
, XtPointer clientData
, XtPointer 
WXUNUSED(ptr
)) 
 240     if (!wxGetWindowFromTable(w
)) 
 241         // Widget has been deleted! 
 244     wxButton 
*item 
= (wxButton 
*) clientData
; 
 245     wxCommandEvent 
event (wxEVT_BUTTON
, item
->GetId()); 
 246     event
.SetEventObject(item
); 
 247     item
->ProcessCommand (event
);