X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/4b5f3fe655deeb91d5d3abe8fad30c4a1cae63dc..9fa7b43626f2ee7be5c6e2fe5016117a8fb7062a:/src/motif/button.cpp diff --git a/src/motif/button.cpp b/src/motif/button.cpp index c3f5be3ec4..9df9eab55c 100644 --- a/src/motif/button.cpp +++ b/src/motif/button.cpp @@ -1,153 +1,248 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: button.cpp +// Name: src/motif/button.cpp // Purpose: wxButton // Author: Julian Smart // Modified by: // Created: 17/09/98 // RCS-ID: $Id$ // Copyright: (c) Julian Smart -// Licence: wxWindows licence +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// -#ifdef __GNUG__ -#pragma implementation "button.h" -#endif +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" #include "wx/button.h" -#include "wx/utils.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); -#if !USE_SHARED_LIBRARY -IMPLEMENT_DYNAMIC_CLASS(wxButton, wxControl) -#endif +#define MIN_WIDTH 78 +#define MIN_LARGE_HEIGHT 30 // Button -bool wxButton::Create(wxWindow *parent, wxWindowID id, const wxString& label, - const wxPoint& pos, - const wxSize& size, long style, - const wxValidator& validator, - const wxString& name) +bool wxButton::Create(wxWindow *parent, wxWindowID id, const wxString& lbl, + const wxPoint& pos, + const wxSize& size, long style, + const wxValidator& validator, + const wxString& name) { - SetName(name); - SetValidator(validator); - m_windowStyle = style; - m_backgroundColour = parent->GetBackgroundColour(); - m_foregroundColour = parent->GetForegroundColour(); + wxString label(lbl); + if (label.empty() && wxIsStockID(id)) + label = wxGetStockLabel(id); - parent->AddChild((wxButton *)this); + if( !CreateControl( parent, id, pos, size, style, validator, name ) ) + return false; + PreCreation(); - if (id == -1) - m_windowId = NewControlId(); - else - m_windowId = id; + wxXmString text( GetLabelText(label) ); - wxString label1(wxStripMenuCodes(label)); - - XmString text = XmStringCreateSimple ((char*) (const char*) label1); 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. - */ + * 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, - XmNlabelString, text, -// XmNdefaultButtonShadowThickness, 1, // See comment for wxButton::SetDefault - NULL); + 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; + + PostCreation(); + AttachWidget (parent, m_mainWidget, (WXWidget) NULL, + pos.x, pos.y, best.x, best.y); + + return true; +} - XmStringFree (text); +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(); +} - XtAddCallback ((Widget) m_mainWidget, XmNactivateCallback, (XtCallbackProc) wxButtonCallback, - (XtPointer) this); - m_windowFont = parent->GetFont(); - ChangeFont(FALSE); +wxWindow *wxButton::SetDefault() +{ + wxWindow *oldDefault = wxButtonBase::SetDefault(); + + // 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(); + } - SetCanAddEventHandler(TRUE); - AttachWidget (parent, m_mainWidget, (WXWidget) NULL, pos.x, pos.y, size.x, size.y); + XtVaSetValues ((Widget) parent->GetMainWidget(), + XmNdefaultButton, (Widget) GetMainWidget(), + NULL); - ChangeBackgroundColour(); + return oldDefault; +} - return TRUE; +static inline bool wxMotifLargeButtons() +{ + return wxSystemOptions::HasOption("motif.largebuttons") + && wxSystemOptions::GetOptionInt("motif.largebuttons") != 0; } -void wxButton::SetDefault() +/* static */ +wxSize wxButton::GetDefaultSize() { - wxWindow *parent = (wxWindow *)GetParent(); - if (parent) - parent->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) - for (wxNode * node = parent->GetChildren ()->First (); node; node = node->Next ()) - { - wxButton *item = (wxButton *) node->Data (); - if (item->IsKindOf(CLASSINFO(wxButton))) - { - bool managed = XtIsManaged((Widget) item->GetMainWidget()); - if (managed) - XtUnmanageChild ((Widget) item->GetMainWidget()); - - XtVaSetValues ((Widget) item->GetMainWidget(), - XmNdefaultButtonShadowThickness, 1, - NULL); - - if (managed) - XtManageChild ((Widget) item->GetMainWidget()); - } - } // while - -// XtVaSetValues((Widget)handle, XmNshowAsDefault, 1, NULL); - XtVaSetValues ((Widget) parent->GetMainWidget(), XmNdefaultButton, (Widget) GetMainWidget(), NULL); + // 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 ); } -void wxButton::Command (wxCommandEvent & event) +wxSize wxButton::DoGetBestSize() const { - ProcessCommand (event); + 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; } -void wxButtonCallback (Widget w, XtPointer clientData, XtPointer ptr) +wxSize wxButton::GetMinSize() const { - 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); + if( wxMotifLargeButtons() ) + return OldGetMinSize(); + + return DoGetBestSize(); } -void wxButton::ChangeFont(bool keepOriginalSize) +wxSize wxButton::OldGetMinSize() const { - wxWindow::ChangeFont(keepOriginalSize); + return OldGetBestSize(); } -void wxButton::ChangeBackgroundColour() +wxSize wxButton::OldGetBestSize() const { - DoChangeBackgroundColour(m_mainWidget, m_backgroundColour, TRUE); + 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::ChangeForegroundColour() +void wxButton::Command (wxCommandEvent & event) { - wxWindow::ChangeForegroundColour(); + 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); +}