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" 
  18 #include "wx/arrstr.h" 
  21 #pragma message disable nosimpint 
  25 #pragma message enable nosimpint 
  28 // use the new, shiny combobox for Motif 2.x 
  29 #if (XmVersion >= 2000) 
  32 #pragma message disable nosimpint 
  34 #include <Xm/ComboBox.h> 
  38 #pragma message enable nosimpint 
  41 #include "wx/motif/private.h" 
  44 static Widget 
GetXmList( const wxComboBox
* cb 
) 
  47     XtVaGetValues( (Widget
)cb
->GetMainWidget(), 
  54 static Widget 
GetXmText( const wxComboBox
* cb 
) 
  57     XtVaGetValues( (Widget
)cb
->GetMainWidget(), 
  64 void  wxComboBoxCallback (Widget w
, XtPointer clientData
, 
  65                           XmComboBoxCallbackStruct 
* cbs
); 
  67 IMPLEMENT_DYNAMIC_CLASS(wxComboBox
, wxControl
) 
  69 bool wxComboBox::Create(wxWindow 
*parent
, wxWindowID id
, 
  70                         const wxString
& value
, 
  73                         int n
, const wxString choices
[], 
  75                         const wxValidator
& validator
, 
  78     if( !CreateControl( parent
, id
, pos
, size
, style
, validator
, name 
) ) 
  81     Widget parentWidget 
= (Widget
) parent
->GetClientWidget(); 
  83     int cb_type 
= ( style 
& wxCB_SIMPLE 
) ? XmCOMBO_BOX 
: 
  84                   ( style 
& wxCB_READONLY 
) ? XmDROP_DOWN_LIST 
: 
  85                   ( style 
& wxCB_DROPDOWN 
) ? XmDROP_DOWN_COMBO_BOX 
: 
  86     // default to wxCB_DROPDOWN 
  87                                               XmDROP_DOWN_COMBO_BOX
; 
  88     if( cb_type 
== XmDROP_DOWN_COMBO_BOX 
) 
  89         SetWindowStyle( style 
| wxCB_DROPDOWN 
); 
  91     Widget buttonWidget
= XtVaCreateManagedWidget(name
.c_str(), 
  92         xmComboBoxWidgetClass
, parentWidget
, 
  93         XmNcomboBoxType
, cb_type
, 
  96     m_mainWidget 
= (Widget
) buttonWidget
; 
  99     for ( i 
= 0; i 
< n
; ++i
) 
 100         Append( choices
[i
] ); 
 102     XtManageChild (buttonWidget
); 
 108     XtAddCallback (buttonWidget
, XmNselectionCallback
, 
 109                    (XtCallbackProc
) wxComboBoxCallback
, 
 111     XtAddCallback (GetXmText(this), XmNvalueChangedCallback
, 
 112                    (XtCallbackProc
) wxComboBoxCallback
, 
 115     wxSize best 
= GetBestSize(); 
 116     if( size
.x 
!= wxDefaultCoord 
) best
.x 
= size
.x
; 
 117     if( size
.y 
!= wxDefaultCoord 
) best
.y 
= size
.y
; 
 119     AttachWidget (parent
, m_mainWidget
, (WXWidget
) NULL
, 
 120                   pos
.x
, pos
.y
, best
.x
, best
.y
); 
 122     ChangeBackgroundColour(); 
 127 bool wxComboBox::Create(wxWindow 
*parent
, wxWindowID id
, 
 128                         const wxString
& value
, 
 131                         const wxArrayString
& choices
, 
 133                         const wxValidator
& validator
, 
 134                         const wxString
& name
) 
 136     wxCArrayString 
chs(choices
); 
 137     return Create(parent
, id
, value
, pos
, size
, chs
.GetCount(), 
 138                   chs
.GetStrings(), style
, validator
, name
); 
 141 void wxComboBox::AdjustDropDownListSize() 
 143     int newListCount 
= -1, itemCount 
= GetCount(); 
 148     else if( itemCount 
< MAX 
) 
 149         newListCount 
= itemCount
; 
 153     XtVaSetValues( GetXmList(this), 
 154                    XmNvisibleItemCount
, newListCount
, 
 158 wxComboBox::~wxComboBox() 
 160     DetachWidget((Widget
) m_mainWidget
); // Removes event handlers 
 161     XtDestroyWidget((Widget
) m_mainWidget
); 
 162     m_mainWidget 
= (WXWidget
) 0; 
 163     if ( HasClientObjectData() ) 
 164         m_clientDataDict
.DestroyData(); 
 167 void wxComboBox::DoSetSize(int x
, int y
, int width
, int WXUNUSED(height
), int sizeFlags
) 
 169     // Necessary so it doesn't call wxChoice::SetSize 
 170     wxWindow::DoSetSize(x
, y
, width
, DoGetBestSize().y
, sizeFlags
); 
 173 wxString 
wxComboBox::GetValue() const 
 175     char* s 
= XmTextGetString (GetXmText (this)); 
 182 void wxComboBox::SetString(unsigned int n
, const wxString
& s
) 
 185     Widget listBox 
= GetXmList(this); 
 187     // delete the item and add it again. 
 188     // FIXME isn't there a way to change it in place? 
 189     XmListDeletePos (listBox
, n
+1); 
 190     XmListAddItem (listBox
, text(), n
+1); 
 193 void wxComboBox::SetValue(const wxString
& value
) 
 197     // Fix crash; probably an OpenMotif bug 
 198     const char* val 
= value
.c_str() ? value
.c_str() : ""; 
 199     XtVaSetValues( GetXmText(this), 
 200                    XmNvalue
, wxConstCast(val
, char), 
 203     m_inSetValue 
= false; 
 206 int wxComboBox::DoAppend(const wxString
& item
) 
 208     wxXmString 
str( item
.c_str() ); 
 209     XmComboBoxAddItem((Widget
) m_mainWidget
, str(), 0, False
); 
 211     AdjustDropDownListSize(); 
 213     return GetCount() - 1; 
 216 int wxComboBox::DoInsert(const wxString
& item
, unsigned int pos
) 
 218     wxCHECK_MSG(!(GetWindowStyle() & wxCB_SORT
), -1, wxT("can't insert into sorted list")); 
 219     wxCHECK_MSG(IsValidInsert(pos
), -1, wxT("invalid index")); 
 221     if (pos 
== GetCount()) 
 222         return DoAppend(item
); 
 224     wxXmString 
str( item
.c_str() ); 
 225     XmComboBoxAddItem((Widget
) m_mainWidget
, str(), pos
+1, False
); 
 227     AdjustDropDownListSize(); 
 229     return GetCount() - 1; 
 232 void wxComboBox::Delete(unsigned int n
) 
 234 #ifdef LESSTIF_VERSION 
 235     XmListDeletePos (GetXmList(this), n 
+ 1); 
 237     XmComboBoxDeletePos((Widget
) m_mainWidget
, n
+1); 
 240     m_clientDataDict
.Delete(n
, HasClientObjectData()); 
 243     AdjustDropDownListSize(); 
 246 void wxComboBox::Clear() 
 248 #ifdef LESSTIF_VERSION 
 249     XmListDeleteAllItems (GetXmList(this)); 
 251     while(m_noStrings 
> 0) 
 253         XmComboBoxDeletePos((Widget
) m_mainWidget
, m_noStrings
--); 
 257     if ( HasClientObjectData() ) 
 258         m_clientDataDict
.DestroyData(); 
 260     AdjustDropDownListSize(); 
 263 void wxComboBox::SetSelection (int n
) 
 265     m_inSetSelection 
= true; 
 267 #if wxCHECK_LESSTIF() 
 268     XmListSelectPos (GetXmList(this), n 
+ 1, false); 
 269     SetValue(GetString(n
)); 
 272     wxXmString 
str(GetString(n
).c_str()); 
 273     XmComboBoxSelectItem((Widget
) m_mainWidget
, str()); 
 275     XtVaSetValues( (Widget
)m_mainWidget
, 
 276                    XmNselectedPosition
, n
, 
 280     m_inSetSelection 
= false; 
 283 int wxComboBox::GetSelection (void) const 
 285     return wxDoGetSelectionInList( GetXmList( this ) ); 
 288 wxString 
wxComboBox::GetString(unsigned int n
) const 
 290     return wxDoGetStringInList( GetXmList(this), n 
); 
 293 int wxComboBox::FindString(const wxString
& s
, bool WXUNUSED(bCase
)) const 
 295     // FIXME: back to base class for not supported value of bCase 
 297     return wxDoFindStringInList( GetXmList( this ), s 
); 
 300 // Clipboard operations 
 301 void wxComboBox::Copy() 
 303     XmTextCopy( GetXmText(this), CurrentTime 
); 
 306 void wxComboBox::Cut() 
 308     XmTextCut( GetXmText(this), CurrentTime 
); 
 311 void wxComboBox::Paste() 
 313     XmTextPaste( GetXmText(this) ); 
 316 void wxComboBox::SetEditable(bool WXUNUSED(editable
)) 
 321 void wxComboBox::SetInsertionPoint(long pos
) 
 323     XmTextSetInsertionPosition( GetXmText(this), (XmTextPosition
)pos 
); 
 326 void wxComboBox::SetInsertionPointEnd() 
 328     SetInsertionPoint( GetLastPosition() ); 
 331 long wxComboBox::GetInsertionPoint() const 
 333     return (long)XmTextGetInsertionPosition( GetXmText(this) ); 
 336 wxTextPos 
wxComboBox::GetLastPosition() const 
 338     XmTextPosition pos 
= XmTextGetLastPosition( GetXmText(this) ); 
 342 void wxComboBox::Replace(long from
, long to
, const wxString
& value
) 
 344     XmTextReplace( GetXmText(this), (XmTextPosition
)from
, (XmTextPosition
)to
, 
 345                    wxConstCast(value
.c_str(), char) ); 
 348 void wxComboBox::Remove(long from
, long to
) 
 350     SetSelection( from
, to 
); 
 351     XmTextRemove( GetXmText(this) ); 
 354 void wxComboBox::SetSelection(long from
, long to
) 
 357         to 
= GetLastPosition(); 
 359     XmTextSetSelection( GetXmText(this), (XmTextPosition
)from
, 
 360                         (XmTextPosition
)to
, (Time
)0 ); 
 363 void  wxComboBoxCallback (Widget 
WXUNUSED(w
), XtPointer clientData
, 
 364                           XmComboBoxCallbackStruct 
* cbs
) 
 366     wxComboBox 
*item 
= (wxComboBox 
*) clientData
; 
 368     if( item
->m_inSetSelection 
) return; 
 374     case XmCR_SINGLE_SELECT
: 
 375     case XmCR_BROWSE_SELECT
: 
 378             wxCommandEvent 
event (wxEVT_COMMAND_COMBOBOX_SELECTED
, 
 380             int idx 
= cbs
->item_position
; 
 382             event
.SetString( item
->GetString (idx
) ); 
 383             if ( item
->HasClientObjectData() ) 
 384                 event
.SetClientObject( item
->GetClientObject(idx
) ); 
 385             else if ( item
->HasClientUntypedData() ) 
 386                 event
.SetClientData( item
->GetClientData(idx
) ); 
 387             event
.SetExtraLong(true); 
 388             event
.SetEventObject(item
); 
 389             item
->GetEventHandler()->ProcessEvent(event
); 
 392     case XmCR_VALUE_CHANGED
: 
 394             wxCommandEvent 
event (wxEVT_COMMAND_TEXT_UPDATED
, item
->GetId()); 
 396             event
.SetString( item
->GetValue() ); 
 397             event
.SetExtraLong(true); 
 398             event
.SetEventObject(item
); 
 399             item
->GetEventHandler()->ProcessEvent(event
); 
 407 void wxComboBox::ChangeFont(bool keepOriginalSize
) 
 411         wxDoChangeFont( GetXmText(this), m_font 
); 
 412         wxDoChangeFont( GetXmList(this), m_font 
); 
 415     // Don't use the base class wxChoice's ChangeFont 
 416     wxWindow::ChangeFont(keepOriginalSize
); 
 419 void wxComboBox::ChangeBackgroundColour() 
 421     wxWindow::ChangeBackgroundColour(); 
 424 void wxComboBox::ChangeForegroundColour() 
 426     wxWindow::ChangeForegroundColour(); 
 429 wxSize 
wxComboBox::DoGetBestSize() const 
 431     if( (GetWindowStyle() & wxCB_DROPDOWN
) == wxCB_DROPDOWN 
|| 
 432         (GetWindowStyle() & wxCB_READONLY
) == wxCB_READONLY 
) 
 434         Dimension arrowW
, arrowS
, highlight
, xmargin
, ymargin
, shadow
; 
 436         XtVaGetValues( (Widget
)m_mainWidget
, 
 437                        XmNarrowSize
, &arrowW
, 
 438                        XmNarrowSpacing
, &arrowS
, 
 439                        XmNhighlightThickness
, &highlight
, 
 440                        XmNmarginWidth
, &xmargin
, 
 441                        XmNmarginHeight
, &ymargin
, 
 442                        XmNshadowThickness
, &shadow
, 
 445         wxSize listSize 
= wxDoGetListBoxBestSize( GetXmList(this), this ); 
 446         wxSize textSize 
= wxDoGetSingleTextCtrlBestSize( GetXmText(this), 
 449         // FIXME arbitrary constants 
 450         return wxSize( listSize
.x 
+ arrowW 
+ arrowS 
+ 2 * highlight
 
 451                                   + 2 * shadow 
+ 2 * xmargin 
, 
 452                        textSize
.y 
+ 2 * highlight 
+ 2 * ymargin 
+ 2 * shadow 
); 
 455         return wxWindow::DoGetBestSize(); 
 458 #endif // XmVersion >= 2000 
 460 #endif // wxUSE_COMBOBOX