X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/321db4b6bf15df209942b9c0e6c744c8e7074d1b..09ff2ee1632c8c484134da2a31d0d5c4d0a4bef4:/src/motif/listbox.cpp diff --git a/src/motif/listbox.cpp b/src/motif/listbox.cpp index 246ee2d909..6f4520e02e 100644 --- a/src/motif/listbox.cpp +++ b/src/motif/listbox.cpp @@ -9,37 +9,74 @@ // Licence: wxWindows licence /////////////////////////////////////////////////////////////////////////////// -#ifdef __GNUG__ -#pragma implementation "listbox.h" +#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) + #pragma implementation "listbox.h" #endif -#include "wx/listbox.h" +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#ifdef __VMS +#define XtParent XTPARENT +#define XtDisplay XTDISPLAY +#endif + +# include "wx/listbox.h" #include "wx/settings.h" #include "wx/dynarray.h" #include "wx/log.h" #include "wx/utils.h" +#include "wx/arrstr.h" +#ifdef __VMS__ +#pragma message disable nosimpint +#endif #include +#ifdef __VMS__ +#pragma message enable nosimpint +#endif #include "wx/motif/private.h" -#if !USE_SHARED_LIBRARY - IMPLEMENT_DYNAMIC_CLASS(wxListBox, wxControl) -#endif + IMPLEMENT_DYNAMIC_CLASS(wxListBox, wxControl) -void wxListBoxCallback (Widget w, XtPointer clientData, - XmListCallbackStruct * cbs); +static void wxListBoxCallback(Widget w, + XtPointer clientData, + XmListCallbackStruct * cbs); -void wxListBoxDefaultActionProc (Widget list_w, XtPointer client_data, XmListCallbackStruct * cbs); +// ---------------------------------------------------------------------------- +// wxSizeKeeper +// ---------------------------------------------------------------------------- + +// helper class to reduce code duplication +class wxSizeKeeper +{ + int m_x, m_y; + wxWindow* m_w; +public: + wxSizeKeeper( wxWindow* w ) + : m_w( w ) + { + m_w->GetSize( &m_x, &m_y ); + } + + void Restore() + { + int x, y; + + m_w->GetSize( &x, &y ); + if( x != m_x || y != m_y ) + m_w->SetSize( -1, -1, m_x, m_y ); + } +}; // ============================================================================ // list box control implementation // ============================================================================ // Listbox item -wxListBox::wxListBox(): m_clientDataList(wxKEY_INTEGER) +wxListBox::wxListBox() { m_noItems = 0; - m_selected = 0; } bool wxListBox::Create(wxWindow *parent, wxWindowID id, @@ -50,39 +87,44 @@ bool wxListBox::Create(wxWindow *parent, wxWindowID id, const wxValidator& validator, const wxString& name) { - m_windowStyle = style; - m_noItems = n; - m_selected = 0; - m_backgroundColour = parent->GetBackgroundColour(); - m_foregroundColour = parent->GetForegroundColour(); + if( !wxControl::CreateControl( parent, id, pos, size, style, + validator, name ) ) + return FALSE; - SetName(name); - SetValidator(validator); + m_noItems = n; + m_backgroundColour = * wxWHITE; - if (parent) parent->AddChild(this); + Widget parentWidget = (Widget) parent->GetClientWidget(); - m_windowId = ( id == -1 ) ? (int)NewControlId() : id; + WXFontType fontType = (WXFontType)NULL; - Widget parentWidget = (Widget) parent->GetClientWidget(); + if( m_font.Ok() ) + { + fontType = m_font.GetFontType(XtDisplay(parentWidget)); + } - Arg args[3]; - int count; - XtSetArg (args[0], XmNlistSizePolicy, XmCONSTANT); - if (m_windowStyle & wxLB_MULTIPLE) - XtSetArg (args[1], XmNselectionPolicy, XmMULTIPLE_SELECT); - else if (m_windowStyle & wxLB_EXTENDED) - XtSetArg (args[1], XmNselectionPolicy, XmEXTENDED_SELECT); - else - XtSetArg (args[1], XmNselectionPolicy, XmBROWSE_SELECT); - if (m_windowStyle & wxLB_ALWAYS_SB) + Arg args[4]; + int count = 0; + XtSetArg( args[count], XmNlistSizePolicy, XmCONSTANT ); ++count; + XtSetArg( args[count], XmNselectionPolicy, + ( m_windowStyle & wxLB_MULTIPLE ) ? XmMULTIPLE_SELECT : + ( m_windowStyle & wxLB_EXTENDED ) ? XmEXTENDED_SELECT : + XmBROWSE_SELECT ); + ++count; + if( fontType ) { - XtSetArg (args[2], XmNscrollBarDisplayPolicy, XmSTATIC); - count = 3; + XtSetArg( args[count], (String)wxFont::GetFontTag(), fontType ); + ++count; + } + if( m_windowStyle & wxLB_ALWAYS_SB ) + { + XtSetArg( args[count], XmNscrollBarDisplayPolicy, XmSTATIC ); + ++count; } - else - count = 2; - Widget listWidget = XmCreateScrolledList (parentWidget, (char*) (const char*) name, args, count); + Widget listWidget = + XmCreateScrolledList(parentWidget, + wxConstCast(name.c_str(), char), args, count); m_mainWidget = (WXWidget) listWidget; @@ -90,388 +132,320 @@ bool wxListBox::Create(wxWindow *parent, wxWindowID id, XtManageChild (listWidget); - long width = size.x; - long height = size.y; - if (width == -1) - width = 150; - if (height == -1) - height = 80; - - XtAddCallback (listWidget, XmNbrowseSelectionCallback, (XtCallbackProc) wxListBoxCallback, - (XtPointer) this); - XtAddCallback (listWidget, XmNextendedSelectionCallback, (XtCallbackProc) wxListBoxCallback, - (XtPointer) this); - XtAddCallback (listWidget, XmNmultipleSelectionCallback, (XtCallbackProc) wxListBoxCallback, - (XtPointer) this); - - XtAddCallback (listWidget, XmNdefaultActionCallback, (XtCallbackProc) wxListBoxDefaultActionProc, - (XtPointer) this); - - AttachWidget (parent, m_mainWidget, (WXWidget) NULL, pos.x, pos.y, width, height); - - m_backgroundColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOW); + wxSize best = GetBestSize(); + if( size.x != -1 ) best.x = size.x; + if( size.y != -1 ) best.y = size.y; + + XtAddCallback (listWidget, + XmNbrowseSelectionCallback, + (XtCallbackProc) wxListBoxCallback, + (XtPointer) this); + XtAddCallback (listWidget, + XmNextendedSelectionCallback, + (XtCallbackProc) wxListBoxCallback, + (XtPointer) this); + XtAddCallback (listWidget, + XmNmultipleSelectionCallback, + (XtCallbackProc) wxListBoxCallback, + (XtPointer) this); + XtAddCallback (listWidget, + XmNdefaultActionCallback, + (XtCallbackProc) wxListBoxCallback, + (XtPointer) this); + + AttachWidget (parent, m_mainWidget, (WXWidget) NULL, + pos.x, pos.y, best.x, best.y); - SetFont(* parent->GetFont()); ChangeBackgroundColour(); return TRUE; } +bool wxListBox::Create(wxWindow *parent, wxWindowID id, + const wxPoint& pos, + const wxSize& size, + const wxArrayString& choices, + long style, + const wxValidator& validator, + const wxString& name) +{ + wxCArrayString chs(choices); + return Create(parent, id, pos, size, chs.GetCount(), chs.GetStrings(), + style, validator, name); +} + wxListBox::~wxListBox() { + if( HasClientObjectData() ) + m_clientDataDict.DestroyData(); } -void wxListBox::SetFirstItem(int N) +void wxListBox::SetSelectionPolicy() { - int count, length; + Widget listBox = (Widget)m_mainWidget; + Arg args[3]; + + XtSetArg( args[0], XmNlistSizePolicy, XmCONSTANT ); + + XtSetArg( args[1], XmNselectionPolicy, + ( m_windowStyle & wxLB_MULTIPLE ) ? XmMULTIPLE_SELECT : + ( m_windowStyle & wxLB_EXTENDED ) ? XmEXTENDED_SELECT : + XmBROWSE_SELECT ); - if (N < 0) - return; - XtVaGetValues ((Widget) m_mainWidget, - XmNvisibleItemCount, &count, - XmNitemCount, &length, - NULL); - if ((N + count) >= length) - N = length - count; - XmListSetPos ((Widget) m_mainWidget, N + 1); + XtSetValues( listBox, args, 2 ); } -void wxListBox::SetFirstItem(const wxString& s) +void wxListBox::DoSetFirstItem( int N ) { - int N = FindString (s); + int count, length; - if (N >= 0) - SetFirstItem (N); + if (N < 0) + return; + XtVaGetValues ((Widget) m_mainWidget, + XmNvisibleItemCount, &count, + XmNitemCount, &length, + NULL); + if ((N + count) >= length) + N = length - count; + XmListSetPos ((Widget) m_mainWidget, N + 1); } void wxListBox::Delete(int N) { - int width1, height1; - int width2, height2; - Widget listBox = (Widget) m_mainWidget; - GetSize (&width1, &height1); - - bool managed = XtIsManaged(listBox); - - if (managed) - XtUnmanageChild (listBox); + wxSizeKeeper sk( this ); + Widget listBox = (Widget) m_mainWidget; - XmListDeletePos (listBox, N + 1); + bool managed = XtIsManaged(listBox); - if (managed) - XtManageChild (listBox); + if (managed) + XtUnmanageChild (listBox); - GetSize (&width2, &height2); - // Correct for randomly resized listbox - bad boy, Motif! - if (width1 != width2 || height1 != height2) - SetSize (-1, -1, width1, height1); + XmListDeletePos (listBox, N + 1); - // (JDH) need to add code here to take care of clientDataList - wxNode *node = m_clientDataList.Find((long)N); // get item from list - if (node) m_clientDataList.DeleteNode(node); // if existed then delete from list - node = m_clientDataList.First(); // we now have to adjust all keys that - while (node) // are >=N+1 - { if (node->key.integer >= (long)(N+1)) // very ugly C++ wise but no other way - node->key.integer--; // to look at or change key value - node = node->Next(); - } + if (managed) + XtManageChild (listBox); - m_noItems --; + sk.Restore(); + m_clientDataDict.Delete(N, HasClientObjectData()); + m_noItems --; } -void wxListBox::Append(const wxString& item) +int wxListBox::DoAppend(const wxString& item) { - int width1, height1; - int width2, height2; + wxSizeKeeper sk( this ); + Widget listBox = (Widget) m_mainWidget; - Widget listBox = (Widget) m_mainWidget; - GetSize (&width1, &height1); + bool managed = XtIsManaged(listBox); + + if (managed) + XtUnmanageChild (listBox); + int n; + XtVaGetValues (listBox, XmNitemCount, &n, NULL); + wxXmString text( item ); + // XmListAddItem(listBox, text, n + 1); + XmListAddItemUnselected (listBox, text(), 0); + + // It seems that if the list is cleared, we must re-ask for + // selection policy!! + SetSelectionPolicy(); - bool managed = XtIsManaged(listBox); + if (managed) + XtManageChild (listBox); - if (managed) - XtUnmanageChild (listBox); - int n; - XtVaGetValues (listBox, XmNitemCount, &n, NULL); - XmString text = XmStringCreateSimple ((char*) (const char*) item); -// XmListAddItem(listBox, text, n + 1); - XmListAddItemUnselected (listBox, text, 0); - XmStringFree (text); + sk.Restore(); + m_noItems ++; - // It seems that if the list is cleared, we must re-ask for - // selection policy!! - Arg args[3]; - XtSetArg (args[0], XmNlistSizePolicy, XmCONSTANT); - if (m_windowStyle & wxLB_MULTIPLE) - XtSetArg (args[1], XmNselectionPolicy, XmMULTIPLE_SELECT); - else if (m_windowStyle & wxLB_EXTENDED) - XtSetArg (args[1], XmNselectionPolicy, XmEXTENDED_SELECT); - else - XtSetArg (args[1], XmNselectionPolicy, XmBROWSE_SELECT); - XtSetValues (listBox, args, 2); - - if (managed) - XtManageChild (listBox); - - GetSize (&width2, &height2); - // Correct for randomly resized listbox - bad boy, Motif! - if (width1 != width2 || height1 != height2) - SetSize (-1, -1, width1, height1); - m_noItems ++; -} - -void wxListBox::Append(const wxString& item, char *clientData) -{ - int width1, height1; - int width2, height2; + return GetCount() - 1; +} - Widget listBox = (Widget) m_mainWidget; +void wxListBox::DoSetItems(const wxArrayString& items, void** clientData) +{ + wxSizeKeeper sk( this ); + Widget listBox = (Widget) m_mainWidget; - GetSize (&width1, &height1); - Bool managed = XtIsManaged(listBox); + if( HasClientObjectData() ) + m_clientDataDict.DestroyData(); - if (managed) - XtUnmanageChild (listBox); + bool managed = XtIsManaged(listBox); - int n; - XtVaGetValues (listBox, XmNitemCount, &n, NULL); - XmString text = XmStringCreateSimple ((char*) (const char*) item); -// XmListAddItem(listBox, text, n + 1); - XmListAddItemUnselected (listBox, text, 0); - XmStringFree (text); + if (managed) + XtUnmanageChild (listBox); + XmString *text = new XmString[items.GetCount()]; + size_t i; + for (i = 0; i < items.GetCount(); ++i) + text[i] = wxStringToXmString (items[i]); + + if ( clientData ) + for (i = 0; i < items.GetCount(); ++i) + m_clientDataDict.Set(i, (wxClientData*)clientData[i], FALSE); + + XmListAddItems (listBox, text, items.GetCount(), 0); + for (i = 0; i < items.GetCount(); i++) + XmStringFree (text[i]); + delete[] text; - // It seems that if the list is cleared, we must re-ask for - // selection policy!! - Arg args[3]; - XtSetArg (args[0], XmNlistSizePolicy, XmCONSTANT); - if (m_windowStyle & wxLB_MULTIPLE) - XtSetArg (args[1], XmNselectionPolicy, XmMULTIPLE_SELECT); - else if (m_windowStyle & wxLB_EXTENDED) - XtSetArg (args[1], XmNselectionPolicy, XmEXTENDED_SELECT); - else - XtSetArg (args[1], XmNselectionPolicy, XmBROWSE_SELECT); - XtSetValues (listBox, args, 2); - - m_clientDataList.Append ((long) n, (wxObject *) clientData); - - if (managed) - XtManageChild (listBox); - - GetSize (&width2, &height2); - - // Correct for randomly resized listbox - bad boy, Motif! - if (width1 != width2 || height1 != height2) - SetSize (-1, -1, width1, height1); - - m_noItems ++; -} - -void wxListBox::Set(int n, const wxString *choices, char** clientData) -{ - m_clientDataList.Clear(); - int width1, height1; - int width2, height2; - - Widget listBox = (Widget) m_mainWidget; - GetSize (&width1, &height1); + // It seems that if the list is cleared, we must re-ask for + // selection policy!! + SetSelectionPolicy(); - bool managed = XtIsManaged(listBox); - - if (managed) - XtUnmanageChild (listBox); -/*** - for (int i=0; iData (); - else - return NULL; + return m_clientDataDict.Get(n); } -void wxListBox::SetClientData(int N, char *Client_data) +void *wxListBox::DoGetItemClientData(int N) const { - wxNode *node = m_clientDataList.Find ((long) N); - if (node) - node->SetData ((wxObject *)Client_data); - else - node = m_clientDataList.Append((long) N, (wxObject*) Client_data); + return (void*)m_clientDataDict.Get(N); +} + +void wxListBox::DoSetItemClientData(int N, void *Client_data) +{ + m_clientDataDict.Set(N, (wxClientData*)Client_data, FALSE); } // Return number of selections and an array of selected integers int wxListBox::GetSelections(wxArrayInt& aSelections) const { - aSelections.Empty(); + aSelections.Empty(); - Widget listBox = (Widget) m_mainWidget; - int *posList = NULL; - int posCnt = 0; - bool flag = XmListGetSelectedPos (listBox, &posList, &posCnt); - if (flag) - { - if (posCnt > 0) - { - aSelections.Alloc(posCnt); + Widget listBox = (Widget) m_mainWidget; + int *posList = NULL; + int posCnt = 0; + bool flag = XmListGetSelectedPos (listBox, &posList, &posCnt); + if (flag) + { + if (posCnt > 0) + { + aSelections.Alloc(posCnt); - int i; - for (i = 0; i < posCnt; i++) - aSelections.Add(posList[i] - 1); + int i; + for (i = 0; i < posCnt; i++) + aSelections.Add(posList[i] - 1); - XtFree ((char *) posList); - return posCnt; - } - else - return 0; + XtFree ((char *) posList); + return posCnt; + } + else + return 0; } - else - return 0; + else + return 0; } // Get single selection, for single choice list items -int wxListBox::GetSelection() const +int wxDoGetSelectionInList(Widget listBox) { - Widget listBox = (Widget) m_mainWidget; int *posList = NULL; int posCnt = 0; bool flag = XmListGetSelectedPos (listBox, &posList, &posCnt); @@ -487,272 +461,264 @@ int wxListBox::GetSelection() const return -1; } +int wxListBox::GetSelection() const +{ + return wxDoGetSelectionInList((Widget) m_mainWidget); +} + // Find string for position -wxString wxListBox::GetString(int N) const +wxString wxDoGetStringInList( Widget listBox, int n ) { - Widget listBox = (Widget) m_mainWidget; XmString *strlist; - int n; - XtVaGetValues (listBox, XmNitemCount, &n, XmNitems, &strlist, NULL); - if (N <= n && N >= 0) - { - char *txt; - if (XmStringGetLtoR (strlist[N], XmSTRING_DEFAULT_CHARSET, &txt)) - { - wxString str(txt); - XtFree (txt); - return str; - } - else - return wxEmptyString; - } + int count; + XtVaGetValues( listBox, + XmNitemCount, &count, + XmNitems, &strlist, + NULL ); + if( n < count && n >= 0 ) + return wxXmStringToString( strlist[n] ); else return wxEmptyString; } -void wxListBox::SetSize(int x, int y, int width, int height, int sizeFlags) +wxString wxListBox::GetString( int n ) const { - wxWindow::SetSize(x, y, width, height, sizeFlags); - - // Check resulting size is correct - int tempW, tempH; - GetSize (&tempW, &tempH); - - /* - if (tempW != width || tempH != height) - { - cout << "wxListBox::SetSize sizes not set correctly."); - } - */ + return wxDoGetStringInList( (Widget)m_mainWidget, n ); } -void wxListBox::InsertItems(int nItems, const wxString items[], int pos) +void wxListBox::DoInsertItems(const wxArrayString& items, int pos) { - int width1, height1; - int width2, height2; - + wxSizeKeeper sk( this ); Widget listBox = (Widget) m_mainWidget; - GetSize(&width1, &height1); - bool managed = XtIsManaged(listBox); if (managed) XtUnmanageChild(listBox); - - XmString *text = new XmString[nItems]; - int i; - // Steve Hammes: Motif 1.1 compatibility -// #if XmVersion > 1100 -// Corrected by Sergey Krasnov from Steve Hammes' code + + XmString *text = new XmString[items.GetCount()]; + size_t i; + // Steve Hammes: Motif 1.1 compatibility + // #if XmVersion > 1100 + // Corrected by Sergey Krasnov from Steve Hammes' code #if XmVersion > 1001 - for (i = 0; i < nItems; i++) - text[i] = XmStringCreateSimple((char*) (const char*) items[i]); - XmListAddItemsUnselected(listBox, text, nItems, pos+1); + for (i = 0; i < items.GetCount(); i++) + text[i] = wxStringToXmString(items[i]); + XmListAddItemsUnselected(listBox, text, items.GetCount(), pos+1); #else - for (i = 0; i < nItems; i++) + for (i = 0; i < items.GetCount(); i++) { - text[i] = XmStringCreateSimple((char*) (const char*) items[i]); -// XmListAddItemUnselected(listBox, text[i], i); - XmListAddItemUnselected(listBox, text[i], pos+i+1); // Another Sergey correction + text[i] = wxStringToXmString(items[i]); + // Another Sergey correction + XmListAddItemUnselected(listBox, text[i], pos+i+1); } #endif - for (i = 0; i < nItems; i++) + for (i = 0; i < items.GetCount(); i++) XmStringFree(text[i]); - delete[] text; // It seems that if the list is cleared, we must re-ask for // selection policy!! - Arg args[3]; - XtSetArg(args[0], XmNlistSizePolicy, XmCONSTANT); - if (m_windowStyle & wxLB_MULTIPLE) - XtSetArg(args[1], XmNselectionPolicy, XmMULTIPLE_SELECT); - else if (m_windowStyle & wxLB_EXTENDED) - XtSetArg(args[1], XmNselectionPolicy, XmEXTENDED_SELECT); - else XtSetArg(args[1], XmNselectionPolicy, XmBROWSE_SELECT); - XtSetValues(listBox,args,2) ; + SetSelectionPolicy(); if (managed) XtManageChild(listBox); - GetSize(&width2, &height2); - // Correct for randomly resized listbox - bad boy, Motif! - if (width1 != width2 /*|| height1 != height2*/) - SetSize(-1, -1, width1, height1); + sk.Restore(); - m_noItems += nItems; + m_noItems += items.GetCount(); } void wxListBox::SetString(int N, const wxString& s) { - int width1, height1; - int width2, height2; - + wxSizeKeeper sk( this ); Widget listBox = (Widget) m_mainWidget; - GetSize (&width1, &height1); - XmString text = XmStringCreateSimple ((char*) (const char*) s); + wxXmString text( s ); - // WHAT'S THE MOTIF CALL TO SET THE TEXT OF AN EXISTING - // ITEM??? - // There isn't one, so delete the item and add it again. + // delete the item and add it again. + // FIXME isn't there a way to change it in place? XmListDeletePos (listBox, N+1); - XmListAddItem (listBox, text, N+1); - - XmStringFree(text); - -/* - // It seems that if the list is cleared, we must re-ask for - // selection policy!! - Arg args[3]; - XtSetArg (args[0], XmNlistSizePolicy, XmCONSTANT); - if (m_windowStyle & wxLB_MULTIPLE) - XtSetArg (args[1], XmNselectionPolicy, XmMULTIPLE_SELECT); - else if (m_windowStyle & wxLB_EXTENDED) - XtSetArg (args[1], XmNselectionPolicy, XmEXTENDED_SELECT); - else - XtSetArg (args[1], XmNselectionPolicy, XmBROWSE_SELECT); - XtSetValues (listBox, args, 2); -*/ - - GetSize (&width2, &height2); - // Correct for randomly resized listbox - bad boy, Motif! - if (width1 != width2 || height1 != height2) - SetSize (-1, -1, width1, height1); -} - -int wxListBox::Number () const -{ - return m_noItems; -} + XmListAddItem (listBox, text(), N+1); -// For single selection items only -wxString wxListBox::GetStringSelection () const -{ - int sel = GetSelection (); - if (sel > -1) - return this->GetString (sel); - else - return wxString(""); -} - -bool wxListBox::SetStringSelection (const wxString& s, bool flag) -{ - int sel = FindString (s); - if (sel > -1) - { - SetSelection (sel, flag); - return TRUE; - } - else - return FALSE; + sk.Restore(); } void wxListBox::Command (wxCommandEvent & event) { - if (event.m_extraLong) - SetSelection (event.m_commandInt); + if (event.GetExtraLong()) + SetSelection (event.GetInt()); else { - Deselect (event.m_commandInt); + Deselect (event.GetInt()); return; } ProcessCommand (event); } -void wxListBoxCallback (Widget w, XtPointer clientData, - XmListCallbackStruct * cbs) +void wxListBoxCallback (Widget WXUNUSED(w), XtPointer clientData, + XmListCallbackStruct * cbs) { -/* - if (cbs->reason == XmCR_EXTENDED_SELECT) - cout << "*** Extend select\n"; - else if (cbs->reason == XmCR_SINGLE_SELECT) - cout << "*** Single select\n"; - else if (cbs->reason == XmCR_MULTIPLE_SELECT) - cout << "*** Multiple select\n"; - else if (cbs->reason == XmCR_BROWSE_SELECT) - cout << "*** Browse select\n"; - - if (cbs->selection_type == XmMODIFICATION) - cout << "*** Modification\n"; - else if (cbs->selection_type == XmINITIAL) - cout << "*** Initial\n"; - else if (cbs->selection_type == XmADDITION) - cout << "*** Addition\n"; - */ - wxListBox *item = (wxListBox *) clientData; if (item->InSetValue()) return; - wxCommandEvent event (wxEVT_COMMAND_LISTBOX_SELECTED); + wxEventType evtType; + + if( cbs->reason == XmCR_DEFAULT_ACTION ) + evtType = wxEVT_COMMAND_LISTBOX_DOUBLECLICKED; + else + evtType = wxEVT_COMMAND_LISTBOX_SELECTED; + + int n = cbs->item_position - 1; + wxCommandEvent event (evtType, item->GetId()); + if ( item->HasClientObjectData() ) + event.SetClientObject( item->GetClientObject(n) ); + else if ( item->HasClientUntypedData() ) + event.SetClientData( item->GetClientData(n) ); + event.SetInt(n); + event.SetExtraLong(TRUE); + event.SetEventObject(item); + event.SetString( item->GetString( n ) ); + + int x = -1; + if( NULL != cbs->event && cbs->event->type == ButtonRelease ) + { + XButtonEvent* evt = (XButtonEvent*)cbs->event; + + x = evt->x; + } + switch (cbs->reason) { - case XmCR_MULTIPLE_SELECT: - case XmCR_BROWSE_SELECT: - { - event.m_clientData = item->GetClientData (cbs->item_position - 1); - //event.commandString = item->GetStringSelection(); - event.m_commandInt = cbs->item_position - 1; - event.m_extraLong = TRUE; - event.SetEventObject(item); - item->ProcessCommand (event); - //delete[] event.commandString; // Let's not store the command string any more - break; - } - case XmCR_EXTENDED_SELECT: + case XmCR_MULTIPLE_SELECT: + case XmCR_BROWSE_SELECT: +#if wxUSE_CHECKLISTBOX + item->DoToggleItem( n, x ); +#endif + case XmCR_DEFAULT_ACTION: + item->GetEventHandler()->ProcessEvent(event); + break; + case XmCR_EXTENDED_SELECT: + switch (cbs->selection_type) { - switch (cbs->selection_type) - { - case XmINITIAL: - case XmADDITION: - case XmMODIFICATION: - { - event.m_clientData = item->GetClientData (cbs->item_position - 1); - event.m_commandInt = cbs->item_position - 1; - event.m_extraLong = TRUE; - event.SetEventObject(item); - item->ProcessCommand (event); - break; - } - } + case XmINITIAL: + case XmADDITION: + case XmMODIFICATION: + item->DoToggleItem( n, x ); + item->GetEventHandler()->ProcessEvent(event); break; } + break; } } -/* Respond by getting the - * designated "default button" in the action area and activate it - * as if the user had selected it. - */ -void wxListBoxDefaultActionProc (Widget list_w, XtPointer client_data, XmListCallbackStruct * cbs) +WXWidget wxListBox::GetTopWidget() const +{ + return (WXWidget) XtParent( (Widget) m_mainWidget ); +} + +void wxListBox::ChangeBackgroundColour() { - wxListBox *lbox = (wxListBox *) client_data; + wxWindow::ChangeBackgroundColour(); + + Widget parent = XtParent ((Widget) m_mainWidget); + Widget hsb, vsb; + + XtVaGetValues (parent, + XmNhorizontalScrollBar, &hsb, + XmNverticalScrollBar, &vsb, + NULL); + + /* TODO: should scrollbars be affected? Should probably have separate + * function to change them (by default, taken from wxSystemSettings) + */ + wxColour backgroundColour = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE); + wxDoChangeBackgroundColour((WXWidget) hsb, backgroundColour, TRUE); + wxDoChangeBackgroundColour((WXWidget) vsb, backgroundColour, TRUE); - wxCommandEvent event(wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, lbox->GetId()); - event.SetEventObject( lbox ); - lbox->GetEventHandler()->ProcessEvent(event) ; + XtVaSetValues (hsb, + XmNtroughColor, backgroundColour.AllocColour(XtDisplay(hsb)), + NULL); + XtVaSetValues (vsb, + XmNtroughColor, backgroundColour.AllocColour(XtDisplay(vsb)), + NULL); + + // MBN: why change parent's background? It looks really ugly. + // wxDoChangeBackgroundColour((WXWidget) parent, m_backgroundColour, TRUE); } -WXWidget wxListBox::GetTopWidget() const +void wxListBox::ChangeForegroundColour() { - return (WXWidget) XtParent( (Widget) m_mainWidget ); + wxWindow::ChangeForegroundColour(); + + Widget parent = XtParent ((Widget) m_mainWidget); + Widget hsb, vsb; + + XtVaGetValues(parent, + XmNhorizontalScrollBar, &hsb, + XmNverticalScrollBar, &vsb, + NULL); + + /* TODO: should scrollbars be affected? Should probably have separate + function to change them (by default, taken from wxSystemSettings) + + wxDoChangeForegroundColour((WXWidget) hsb, m_foregroundColour); + wxDoChangeForegroundColour((WXWidget) vsb, m_foregroundColour); + wxDoChangeForegroundColour((WXWidget) parent, m_foregroundColour); + */ } -void wxListBox::ChangeFont() +int wxListBox::GetCount() const { - wxWindow::ChangeFont(); + return m_noItems; } -void wxListBox::ChangeBackgroundColour() +#define LIST_SCROLL_SPACING 6 + +wxSize wxDoGetListBoxBestSize( Widget listWidget, const wxWindow* window ) { - wxWindow::ChangeBackgroundColour(); + int max; + Dimension spacing, highlight, xmargin, ymargin, shadow; + int width = 0; + int x, y; + + XtVaGetValues( listWidget, + XmNitemCount, &max, + XmNlistSpacing, &spacing, + XmNhighlightThickness, &highlight, + XmNlistMarginWidth, &xmargin, + XmNlistMarginHeight, &ymargin, + XmNshadowThickness, &shadow, + NULL ); + + for( size_t i = 0; i < (size_t)max; ++i ) + { + window->GetTextExtent( wxDoGetStringInList( listWidget, i ), &x, &y ); + width = wxMax( width, x ); + } + + // use some arbitrary value if there are no strings + if( width == 0 ) + width = 100; + + // get my + window->GetTextExtent( "v", &x, &y ); + + // make it a little larger than widest string, plus the scrollbar + width += wxSystemSettings::GetMetric( wxSYS_VSCROLL_X ) + + 2 * highlight + LIST_SCROLL_SPACING + 2 * xmargin + 2 * shadow; + + // at least 3 items, at most 10 + int height = wxMax( 3, wxMin( 10, max ) ) * + ( y + spacing + 2 * highlight ) + 2 * ymargin + 2 * shadow; + + return wxSize( width, height ); } -void wxListBox::ChangeForegroundColour() +wxSize wxListBox::DoGetBestSize() const { - wxWindow::ChangeForegroundColour(); + return wxDoGetListBoxBestSize( (Widget)m_mainWidget, this ); }