1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/motif/combobox_native.cpp 
   3 // Purpose:     wxComboBox class 
   4 // Author:      Julian Smart, Ian Brown 
   8 // Copyright:   (c) Julian Smart 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // For compilers that support precompilation, includes "wx.h". 
  13 #include "wx/wxprec.h" 
  17 #include "wx/combobox.h" 
  20     #include "wx/arrstr.h" 
  24 #pragma message disable nosimpint 
  28 #pragma message enable nosimpint 
  31 // use the new, shiny combobox for Motif 2.x 
  32 #if (XmVersion >= 2000) 
  35 #pragma message disable nosimpint 
  37 #include <Xm/ComboBox.h> 
  41 #pragma message enable nosimpint 
  44 #include "wx/motif/private.h" 
  47 static Widget 
GetXmList( const wxComboBox
* cb 
) 
  50     XtVaGetValues( (Widget
)cb
->GetMainWidget(), 
  57 static Widget 
GetXmText( const wxComboBox
* cb 
) 
  60     XtVaGetValues( (Widget
)cb
->GetMainWidget(), 
  67 void  wxComboBoxCallback (Widget w
, XtPointer clientData
, 
  68                           XmComboBoxCallbackStruct 
* cbs
); 
  70 IMPLEMENT_DYNAMIC_CLASS(wxComboBox
, wxControl
) 
  72 bool wxComboBox::Create(wxWindow 
*parent
, wxWindowID id
, 
  73                         const wxString
& value
, 
  76                         int n
, const wxString choices
[], 
  78                         const wxValidator
& validator
, 
  81     if( !CreateControl( parent
, id
, pos
, size
, style
, validator
, name 
) ) 
  85     Widget parentWidget 
= (Widget
) parent
->GetClientWidget(); 
  87     int cb_type 
= ( style 
& wxCB_SIMPLE 
) ? XmCOMBO_BOX 
: 
  88                   ( style 
& wxCB_READONLY 
) ? XmDROP_DOWN_LIST 
: 
  89                   ( style 
& wxCB_DROPDOWN 
) ? XmDROP_DOWN_COMBO_BOX 
: 
  90     // default to wxCB_DROPDOWN 
  91                                               XmDROP_DOWN_COMBO_BOX
; 
  92     if( cb_type 
== XmDROP_DOWN_COMBO_BOX 
) 
  93         SetWindowStyle( style 
| wxCB_DROPDOWN 
); 
  95     Widget buttonWidget
= XtVaCreateManagedWidget(name
.c_str(), 
  96         xmComboBoxWidgetClass
, parentWidget
, 
  97         XmNcomboBoxType
, cb_type
, 
 100     m_mainWidget 
= (Widget
) buttonWidget
; 
 103     for ( i 
= 0; i 
< n
; ++i
) 
 104         Append( choices
[i
] ); 
 106     XtManageChild (buttonWidget
); 
 110     XtAddCallback (buttonWidget
, XmNselectionCallback
, 
 111                    (XtCallbackProc
) wxComboBoxCallback
, 
 113     XtAddCallback (GetXmText(this), XmNvalueChangedCallback
, 
 114                    (XtCallbackProc
) wxComboBoxCallback
, 
 117     wxSize best 
= GetBestSize(); 
 118     if( size
.x 
!= wxDefaultCoord 
) best
.x 
= size
.x
; 
 119     if( size
.y 
!= wxDefaultCoord 
) best
.y 
= size
.y
; 
 122     AttachWidget (parent
, m_mainWidget
, (WXWidget
) NULL
, 
 123                   pos
.x
, pos
.y
, best
.x
, best
.y
); 
 128 bool wxComboBox::Create(wxWindow 
*parent
, wxWindowID id
, 
 129                         const wxString
& value
, 
 132                         const wxArrayString
& choices
, 
 134                         const wxValidator
& validator
, 
 135                         const wxString
& name
) 
 137     wxCArrayString 
chs(choices
); 
 138     return Create(parent
, id
, value
, pos
, size
, chs
.GetCount(), 
 139                   chs
.GetStrings(), style
, validator
, name
); 
 142 void wxComboBox::AdjustDropDownListSize() 
 144     int newListCount 
= -1, itemCount 
= GetCount(); 
 149     else if( itemCount 
< MAX 
) 
 150         newListCount 
= itemCount
; 
 154     XtVaSetValues( GetXmList(this), 
 155                    XmNvisibleItemCount
, newListCount
, 
 159 wxComboBox::~wxComboBox() 
 161     DetachWidget((Widget
) m_mainWidget
); // Removes event handlers 
 162     XtDestroyWidget((Widget
) m_mainWidget
); 
 163     m_mainWidget 
= (WXWidget
) 0; 
 166 void wxComboBox::DoSetSize(int x
, int y
, int width
, int WXUNUSED(height
), int sizeFlags
) 
 168     // Necessary so it doesn't call wxChoice::SetSize 
 169     wxWindow::DoSetSize(x
, y
, width
, DoGetBestSize().y
, sizeFlags
); 
 172 void wxComboBox::SetString(unsigned int n
, const wxString
& s
) 
 175     Widget listBox 
= GetXmList(this); 
 177     // delete the item and add it again. 
 178     // FIXME isn't there a way to change it in place? 
 179     XmListDeletePos (listBox
, n
+1); 
 180     XmListAddItem (listBox
, text(), n
+1); 
 183 void wxComboBox::SetValue(const wxString
& value
) 
 187     XtVaSetValues( GetXmText(this), 
 188                    XmNvalue
, (const char*)value
.mb_str(), 
 191     m_inSetValue 
= false; 
 194 int wxComboBox::DoInsertItems(const wxArrayStringsAdapter 
& items
, 
 196                               void **clientData
, wxClientDataType type
) 
 198     const unsigned int numItems 
= items
.GetCount(); 
 200     AllocClientData(numItems
); 
 201     for ( unsigned int i 
= 0; i 
< numItems
; ++i
, ++pos 
) 
 203         wxXmString 
str( items
[i
].c_str() ); 
 204         XmComboBoxAddItem((Widget
) m_mainWidget
, str(), 
 205                           GetMotifPosition(pos
), False
); 
 207         InsertNewItemClientData(pos
, clientData
, i
, type
); 
 210     AdjustDropDownListSize(); 
 215 void wxComboBox::DoDeleteOneItem(unsigned int n
) 
 217 #ifdef LESSTIF_VERSION 
 218     XmListDeletePos (GetXmList(this), n 
+ 1); 
 220     XmComboBoxDeletePos((Widget
) m_mainWidget
, n
+1); 
 223     wxControlWithItems::DoDeleteOneItem(n
); 
 224     m_stringArray
.RemoveAt(size_t(n
)); 
 226     AdjustDropDownListSize(); 
 229 void wxComboBox::Clear() 
 231 #ifdef LESSTIF_VERSION 
 232     XmListDeleteAllItems (GetXmList(this)); 
 234     size_t n 
= m_stringArray
.GetCount(); 
 237         XmComboBoxDeletePos((Widget
) m_mainWidget
, n
--); 
 241     m_stringArray
.Clear(); 
 242     AdjustDropDownListSize(); 
 244     wxTextEntry::Clear(); 
 247 void wxComboBox::SetSelection (int n
) 
 249     m_inSetSelection 
= true; 
 251 #if wxCHECK_LESSTIF() 
 252     XmListSelectPos (GetXmList(this), n 
+ 1, false); 
 253     SetValue(GetString(n
)); 
 256     wxXmString 
str(GetString(n
).c_str()); 
 257     XmComboBoxSelectItem((Widget
) m_mainWidget
, str()); 
 259     XtVaSetValues( (Widget
)m_mainWidget
, 
 260                    XmNselectedPosition
, n
, 
 264     m_inSetSelection 
= false; 
 267 int wxComboBox::GetSelection() const 
 269     return wxDoGetSelectionInList( GetXmList( this ) ); 
 272 wxString 
wxComboBox::GetString(unsigned int n
) const 
 274     return wxDoGetStringInList( GetXmList(this), n 
); 
 277 int wxComboBox::FindString(const wxString
& s
, bool WXUNUSED(bCase
)) const 
 279     // FIXME: back to base class for not supported value of bCase 
 281     return wxDoFindStringInList( GetXmList( this ), s 
); 
 284 void  wxComboBoxCallback (Widget 
WXUNUSED(w
), XtPointer clientData
, 
 285                           XmComboBoxCallbackStruct 
* cbs
) 
 287     wxComboBox 
*item 
= (wxComboBox 
*) clientData
; 
 289     if( item
->m_inSetSelection 
) return; 
 295     case XmCR_SINGLE_SELECT
: 
 296     case XmCR_BROWSE_SELECT
: 
 299             wxCommandEvent 
event (wxEVT_COMMAND_COMBOBOX_SELECTED
, 
 301             int idx 
= cbs
->item_position
; 
 303             event
.SetString( item
->GetString (idx
) ); 
 304             if ( item
->HasClientObjectData() ) 
 305                 event
.SetClientObject( item
->GetClientObject(idx
) ); 
 306             else if ( item
->HasClientUntypedData() ) 
 307                 event
.SetClientData( item
->GetClientData(idx
) ); 
 308             event
.SetExtraLong(true); 
 309             event
.SetEventObject(item
); 
 310             item
->HandleWindowEvent(event
); 
 313     case XmCR_VALUE_CHANGED
: 
 315             wxCommandEvent 
event (wxEVT_COMMAND_TEXT_UPDATED
, item
->GetId()); 
 317             event
.SetString( item
->GetValue() ); 
 318             event
.SetExtraLong(true); 
 319             event
.SetEventObject(item
); 
 320             item
->HandleWindowEvent(event
); 
 328 void wxComboBox::ChangeFont(bool keepOriginalSize
) 
 330     if( m_font
.Ok() && m_mainWidget 
!= NULL 
) 
 332         wxDoChangeFont( GetXmText(this), m_font 
); 
 333         wxDoChangeFont( GetXmList(this), m_font 
); 
 336     // Don't use the base class wxChoice's ChangeFont 
 337     wxWindow::ChangeFont(keepOriginalSize
); 
 340 void wxComboBox::ChangeBackgroundColour() 
 342     wxWindow::ChangeBackgroundColour(); 
 345 void wxComboBox::ChangeForegroundColour() 
 347     wxWindow::ChangeForegroundColour(); 
 350 wxSize 
wxComboBox::DoGetBestSize() const 
 352     if( (GetWindowStyle() & wxCB_DROPDOWN
) == wxCB_DROPDOWN 
|| 
 353         (GetWindowStyle() & wxCB_READONLY
) == wxCB_READONLY 
) 
 355         Dimension arrowW
, arrowS
, highlight
, xmargin
, ymargin
, shadow
; 
 357         XtVaGetValues( (Widget
)m_mainWidget
, 
 358                        XmNarrowSize
, &arrowW
, 
 359                        XmNarrowSpacing
, &arrowS
, 
 360                        XmNhighlightThickness
, &highlight
, 
 361                        XmNmarginWidth
, &xmargin
, 
 362                        XmNmarginHeight
, &ymargin
, 
 363                        XmNshadowThickness
, &shadow
, 
 366         wxSize listSize 
= wxDoGetListBoxBestSize( GetXmList(this), this ); 
 367         wxSize textSize 
= wxDoGetSingleTextCtrlBestSize( GetXmText(this), 
 370         // FIXME arbitrary constants 
 371         return wxSize( listSize
.x 
+ arrowW 
+ arrowS 
+ 2 * highlight
 
 372                                   + 2 * shadow 
+ 2 * xmargin 
, 
 373                        textSize
.y 
+ 2 * highlight 
+ 2 * ymargin 
+ 2 * shadow 
); 
 376         return wxWindow::DoGetBestSize(); 
 379 WXWidget 
wxComboBox::GetTextWidget() const 
 381     return (WXWidget
)GetXmText(this); 
 384 #endif // XmVersion >= 2000 
 386 #endif // wxUSE_COMBOBOX