]> git.saurik.com Git - wxWidgets.git/blame - src/motif/listbox.cpp
libpng vulnerability CAN-2004-0421
[wxWidgets.git] / src / motif / listbox.cpp
CommitLineData
4bb6408c
JS
1///////////////////////////////////////////////////////////////////////////////
2// Name: listbox.cpp
3// Purpose: wxListBox
4// Author: Julian Smart
5// Modified by:
6// Created: 17/09/98
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart
9// Licence: wxWindows licence
10///////////////////////////////////////////////////////////////////////////////
11
14f355c2 12#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
29006414 13 #pragma implementation "listbox.h"
4bb6408c
JS
14#endif
15
4dff3400
JJ
16#ifdef __VMS
17#define XtParent XTPARENT
18#define XtDisplay XTDISPLAY
19#endif
20
21# include "wx/listbox.h"
4bb6408c
JS
22#include "wx/settings.h"
23#include "wx/dynarray.h"
24#include "wx/log.h"
f97c9854 25#include "wx/utils.h"
584ad2a3 26#include "wx/arrstr.h"
f97c9854 27
338dd992
JJ
28#ifdef __VMS__
29#pragma message disable nosimpint
30#endif
f97c9854 31#include <Xm/List.h>
338dd992
JJ
32#ifdef __VMS__
33#pragma message enable nosimpint
34#endif
f97c9854 35#include "wx/motif/private.h"
4bb6408c 36
29006414 37 IMPLEMENT_DYNAMIC_CLASS(wxListBox, wxControl)
4bb6408c 38
29006414
VZ
39static void wxListBoxCallback(Widget w,
40 XtPointer clientData,
41 XmListCallbackStruct * cbs);
f97c9854 42
99ab3e3f
MB
43// ----------------------------------------------------------------------------
44// wxSizeKeeper
45// ----------------------------------------------------------------------------
46
47// helper class to reduce code duplication
48class wxSizeKeeper
49{
50 int m_x, m_y;
51 wxWindow* m_w;
52public:
53 wxSizeKeeper( wxWindow* w )
54 : m_w( w )
55 {
56 m_w->GetSize( &m_x, &m_y );
57 }
58
59 void Restore()
60 {
61 int x, y;
62
63 m_w->GetSize( &x, &y );
64 if( x != m_x || y != m_y )
65 m_w->SetSize( -1, -1, m_x, m_y );
66 }
67};
68
4bb6408c
JS
69// ============================================================================
70// list box control implementation
71// ============================================================================
72
73// Listbox item
99ab3e3f 74wxListBox::wxListBox()
4bb6408c 75{
f97c9854 76 m_noItems = 0;
4bb6408c
JS
77}
78
79bool wxListBox::Create(wxWindow *parent, wxWindowID id,
80 const wxPoint& pos,
81 const wxSize& size,
82 int n, const wxString choices[],
83 long style,
84 const wxValidator& validator,
85 const wxString& name)
86{
99ab3e3f
MB
87 if( !wxControl::CreateControl( parent, id, pos, size, style,
88 validator, name ) )
89 return FALSE;
90
f97c9854 91 m_noItems = n;
94b49b93 92 m_backgroundColour = * wxWHITE;
29006414 93
f97c9854 94 Widget parentWidget = (Widget) parent->GetClientWidget();
29006414 95
da494b40 96 WXFontType fontType = (WXFontType)NULL;
e1aae528
MB
97
98 if( m_font.Ok() )
99 {
da494b40 100 fontType = m_font.GetFontType(XtDisplay(parentWidget));
e1aae528
MB
101 }
102
103 Arg args[4];
99ab3e3f 104 int count = 0;
e1aae528
MB
105 XtSetArg( args[count], XmNlistSizePolicy, XmCONSTANT ); ++count;
106 XtSetArg( args[count], XmNselectionPolicy,
99ab3e3f
MB
107 ( m_windowStyle & wxLB_MULTIPLE ) ? XmMULTIPLE_SELECT :
108 ( m_windowStyle & wxLB_EXTENDED ) ? XmEXTENDED_SELECT :
109 XmBROWSE_SELECT );
110 ++count;
da494b40 111 if( fontType )
e1aae528 112 {
da494b40 113 XtSetArg( args[count], (String)wxFont::GetFontTag(), fontType );
e1aae528
MB
114 ++count;
115 }
99ab3e3f 116 if( m_windowStyle & wxLB_ALWAYS_SB )
f97c9854 117 {
e1aae528 118 XtSetArg( args[count], XmNscrollBarDisplayPolicy, XmSTATIC );
99ab3e3f 119 ++count;
f97c9854 120 }
29006414 121
d3a80c92
MB
122 Widget listWidget =
123 XmCreateScrolledList(parentWidget,
124 wxConstCast(name.c_str(), char), args, count);
29006414 125
f97c9854 126 m_mainWidget = (WXWidget) listWidget;
29006414 127
a4294b78 128 Set(n, choices);
29006414 129
f97c9854 130 XtManageChild (listWidget);
29006414 131
e1aae528
MB
132 wxSize best = GetBestSize();
133 if( size.x != -1 ) best.x = size.x;
134 if( size.y != -1 ) best.y = size.y;
29006414 135
ef41d80c
MB
136 XtAddCallback (listWidget,
137 XmNbrowseSelectionCallback,
138 (XtCallbackProc) wxListBoxCallback,
139 (XtPointer) this);
140 XtAddCallback (listWidget,
141 XmNextendedSelectionCallback,
142 (XtCallbackProc) wxListBoxCallback,
143 (XtPointer) this);
144 XtAddCallback (listWidget,
145 XmNmultipleSelectionCallback,
146 (XtCallbackProc) wxListBoxCallback,
147 (XtPointer) this);
148 XtAddCallback (listWidget,
149 XmNdefaultActionCallback,
150 (XtCallbackProc) wxListBoxCallback,
151 (XtPointer) this);
29006414 152
ef41d80c 153 AttachWidget (parent, m_mainWidget, (WXWidget) NULL,
e1aae528 154 pos.x, pos.y, best.x, best.y);
29006414 155
0d57be45 156 ChangeBackgroundColour();
29006414 157
f97c9854 158 return TRUE;
4bb6408c
JS
159}
160
584ad2a3
MB
161bool wxListBox::Create(wxWindow *parent, wxWindowID id,
162 const wxPoint& pos,
163 const wxSize& size,
164 const wxArrayString& choices,
165 long style,
166 const wxValidator& validator,
167 const wxString& name)
168{
169 wxCArrayString chs(choices);
170 return Create(parent, id, pos, size, chs.GetCount(), chs.GetStrings(),
171 style, validator, name);
172}
173
4bb6408c
JS
174wxListBox::~wxListBox()
175{
99ab3e3f
MB
176 if( HasClientObjectData() )
177 m_clientDataDict.DestroyData();
178}
179
180void wxListBox::SetSelectionPolicy()
181{
182 Widget listBox = (Widget)m_mainWidget;
183 Arg args[3];
184
185 XtSetArg( args[0], XmNlistSizePolicy, XmCONSTANT );
186
187 XtSetArg( args[1], XmNselectionPolicy,
188 ( m_windowStyle & wxLB_MULTIPLE ) ? XmMULTIPLE_SELECT :
189 ( m_windowStyle & wxLB_EXTENDED ) ? XmEXTENDED_SELECT :
190 XmBROWSE_SELECT );
191
192 XtSetValues( listBox, args, 2 );
4bb6408c
JS
193}
194
ef41d80c 195void wxListBox::DoSetFirstItem( int N )
4bb6408c 196{
2d120f83 197 int count, length;
29006414 198
2d120f83
JS
199 if (N < 0)
200 return;
201 XtVaGetValues ((Widget) m_mainWidget,
29006414
VZ
202 XmNvisibleItemCount, &count,
203 XmNitemCount, &length,
204 NULL);
2d120f83
JS
205 if ((N + count) >= length)
206 N = length - count;
207 XmListSetPos ((Widget) m_mainWidget, N + 1);
4bb6408c
JS
208}
209
4bb6408c
JS
210void wxListBox::Delete(int N)
211{
99ab3e3f 212 wxSizeKeeper sk( this );
2d120f83 213 Widget listBox = (Widget) m_mainWidget;
29006414 214
2d120f83 215 bool managed = XtIsManaged(listBox);
29006414 216
2d120f83
JS
217 if (managed)
218 XtUnmanageChild (listBox);
29006414 219
2d120f83 220 XmListDeletePos (listBox, N + 1);
29006414 221
2d120f83
JS
222 if (managed)
223 XtManageChild (listBox);
29006414 224
99ab3e3f
MB
225 sk.Restore();
226 m_clientDataDict.Delete(N, HasClientObjectData());
2d120f83 227 m_noItems --;
4bb6408c
JS
228}
229
ef41d80c 230int wxListBox::DoAppend(const wxString& item)
4bb6408c 231{
99ab3e3f 232 wxSizeKeeper sk( this );
2d120f83 233 Widget listBox = (Widget) m_mainWidget;
29006414 234
2d120f83 235 bool managed = XtIsManaged(listBox);
29006414 236
2d120f83
JS
237 if (managed)
238 XtUnmanageChild (listBox);
239 int n;
240 XtVaGetValues (listBox, XmNitemCount, &n, NULL);
99ab3e3f 241 wxXmString text( item );
2d120f83 242 // XmListAddItem(listBox, text, n + 1);
99ab3e3f 243 XmListAddItemUnselected (listBox, text(), 0);
29006414 244
2d120f83
JS
245 // It seems that if the list is cleared, we must re-ask for
246 // selection policy!!
99ab3e3f 247 SetSelectionPolicy();
29006414 248
2d120f83
JS
249 if (managed)
250 XtManageChild (listBox);
29006414 251
99ab3e3f 252 sk.Restore();
2d120f83 253 m_noItems ++;
ef41d80c
MB
254
255 return GetCount() - 1;
4bb6408c
JS
256}
257
ef41d80c 258void wxListBox::DoSetItems(const wxArrayString& items, void** clientData)
4bb6408c 259{
99ab3e3f 260 wxSizeKeeper sk( this );
2d120f83 261 Widget listBox = (Widget) m_mainWidget;
99ab3e3f
MB
262
263 if( HasClientObjectData() )
264 m_clientDataDict.DestroyData();
ef41d80c
MB
265
266 bool managed = XtIsManaged(listBox);
29006414 267
2d120f83
JS
268 if (managed)
269 XtUnmanageChild (listBox);
ef41d80c
MB
270 XmString *text = new XmString[items.GetCount()];
271 size_t i;
272 for (i = 0; i < items.GetCount(); ++i)
d3a80c92 273 text[i] = wxStringToXmString (items[i]);
29006414 274
ef41d80c
MB
275 if ( clientData )
276 for (i = 0; i < items.GetCount(); ++i)
99ab3e3f 277 m_clientDataDict.Set(i, (wxClientData*)clientData[i], FALSE);
ef41d80c
MB
278
279 XmListAddItems (listBox, text, items.GetCount(), 0);
280 for (i = 0; i < items.GetCount(); i++)
281 XmStringFree (text[i]);
282 delete[] text;
29006414 283
2d120f83
JS
284 // It seems that if the list is cleared, we must re-ask for
285 // selection policy!!
99ab3e3f 286 SetSelectionPolicy();
29006414 287
2d120f83
JS
288 if (managed)
289 XtManageChild (listBox);
29006414 290
99ab3e3f 291 sk.Restore();
29006414 292
ef41d80c 293 m_noItems = items.GetCount();
4bb6408c
JS
294}
295
9b1bd0c6 296int wxDoFindStringInList(Widget w, const wxString& s)
4bb6408c 297{
99ab3e3f 298 wxXmString str( s );
2d120f83
JS
299 int *positions = NULL;
300 int no_positions = 0;
9b1bd0c6 301 bool success = XmListGetMatchPos (w, str(),
ef41d80c 302 &positions, &no_positions);
99ab3e3f 303
2d120f83 304 if (success)
f97c9854 305 {
2d120f83
JS
306 int pos = positions[0];
307 if (positions)
308 XtFree ((char *) positions);
309 return pos - 1;
f97c9854 310 }
2d120f83
JS
311 else
312 return -1;
4bb6408c
JS
313}
314
9b1bd0c6
MB
315int wxListBox::FindString(const wxString& s) const
316{
317 return wxDoFindStringInList( (Widget)m_mainWidget, s );
318}
319
4bb6408c
JS
320void wxListBox::Clear()
321{
2d120f83
JS
322 if (m_noItems <= 0)
323 return;
29006414 324
99ab3e3f 325 wxSizeKeeper sk( this );
2d120f83 326 Widget listBox = (Widget) m_mainWidget;
29006414 327
2d120f83 328 XmListDeleteAllItems (listBox);
99ab3e3f
MB
329 if( HasClientObjectData() )
330 m_clientDataDict.DestroyData();
29006414 331
99ab3e3f 332 sk.Restore();
29006414 333
2d120f83 334 m_noItems = 0;
4bb6408c
JS
335}
336
337void wxListBox::SetSelection(int N, bool select)
338{
2d120f83
JS
339 m_inSetValue = TRUE;
340 if (select)
f97c9854 341 {
29006414
VZ
342#if 0
343 if (m_windowStyle & wxLB_MULTIPLE)
344 {
345 int *selections = NULL;
346 int n = GetSelections (&selections);
347
ef41d80c
MB
348 // This hack is supposed to work, to make it possible
349 // to select more than one item, but it DOESN'T under Motif 1.1.
29006414 350
ef41d80c
MB
351 XtVaSetValues ((Widget) m_mainWidget,
352 XmNselectionPolicy, XmMULTIPLE_SELECT,
353 NULL);
29006414
VZ
354
355 int i;
356 for (i = 0; i < n; i++)
ef41d80c
MB
357 XmListSelectPos ((Widget) m_mainWidget,
358 selections[i] + 1, FALSE);
29006414
VZ
359
360 XmListSelectPos ((Widget) m_mainWidget, N + 1, FALSE);
361
ef41d80c
MB
362 XtVaSetValues ((Widget) m_mainWidget,
363 XmNselectionPolicy, XmEXTENDED_SELECT,
364 NULL);
29006414
VZ
365 }
366 else
367#endif // 0
2d120f83 368 XmListSelectPos ((Widget) m_mainWidget, N + 1, FALSE);
29006414 369
f97c9854 370 }
2d120f83
JS
371 else
372 XmListDeselectPos ((Widget) m_mainWidget, N + 1);
29006414 373
2d120f83 374 m_inSetValue = FALSE;
4bb6408c
JS
375}
376
d7d38ea4 377bool wxListBox::IsSelected(int N) const
4bb6408c 378{
2d120f83
JS
379 // In Motif, no simple way to determine if the item is selected.
380 wxArrayInt theSelections;
381 int count = GetSelections (theSelections);
382 if (count == 0)
383 return FALSE;
384 else
385 {
386 int j;
387 for (j = 0; j < count; j++)
388 if (theSelections[j] == N)
389 return TRUE;
390 }
4bb6408c
JS
391 return FALSE;
392}
393
ef41d80c
MB
394void wxListBox::DoSetItemClientObject(int n, wxClientData* clientData)
395{
99ab3e3f 396 m_clientDataDict.Set(n, clientData, FALSE);
ef41d80c
MB
397}
398
399wxClientData* wxListBox::DoGetItemClientObject(int n) const
4bb6408c 400{
99ab3e3f 401 return m_clientDataDict.Get(n);
4bb6408c
JS
402}
403
ef41d80c 404void *wxListBox::DoGetItemClientData(int N) const
4bb6408c 405{
99ab3e3f 406 return (void*)m_clientDataDict.Get(N);
4bb6408c
JS
407}
408
ef41d80c 409void wxListBox::DoSetItemClientData(int N, void *Client_data)
4bb6408c 410{
99ab3e3f 411 m_clientDataDict.Set(N, (wxClientData*)Client_data, FALSE);
4bb6408c
JS
412}
413
414// Return number of selections and an array of selected integers
415int wxListBox::GetSelections(wxArrayInt& aSelections) const
416{
2d120f83 417 aSelections.Empty();
29006414 418
2d120f83
JS
419 Widget listBox = (Widget) m_mainWidget;
420 int *posList = NULL;
421 int posCnt = 0;
422 bool flag = XmListGetSelectedPos (listBox, &posList, &posCnt);
423 if (flag)
424 {
425 if (posCnt > 0)
426 {
427 aSelections.Alloc(posCnt);
29006414 428
2d120f83
JS
429 int i;
430 for (i = 0; i < posCnt; i++)
431 aSelections.Add(posList[i] - 1);
29006414 432
2d120f83
JS
433 XtFree ((char *) posList);
434 return posCnt;
435 }
436 else
437 return 0;
4bb6408c 438 }
2d120f83
JS
439 else
440 return 0;
4bb6408c
JS
441}
442
443// Get single selection, for single choice list items
9b1bd0c6 444int wxDoGetSelectionInList(Widget listBox)
4bb6408c 445{
f97c9854
JS
446 int *posList = NULL;
447 int posCnt = 0;
448 bool flag = XmListGetSelectedPos (listBox, &posList, &posCnt);
449 if (flag)
450 {
451 int id = -1;
452 if (posCnt > 0)
453 id = posList[0] - 1;
454 XtFree ((char *) posList);
455 return id;
456 }
457 else
458 return -1;
4bb6408c
JS
459}
460
9b1bd0c6
MB
461int wxListBox::GetSelection() const
462{
463 return wxDoGetSelectionInList((Widget) m_mainWidget);
464}
465
4bb6408c 466// Find string for position
e1aae528 467wxString wxDoGetStringInList( Widget listBox, int n )
4bb6408c 468{
f97c9854 469 XmString *strlist;
e1aae528
MB
470 int count;
471 XtVaGetValues( listBox,
472 XmNitemCount, &count,
473 XmNitems, &strlist,
474 NULL );
d40708e2 475 if( n < count && n >= 0 )
e1aae528 476 return wxXmStringToString( strlist[n] );
f97c9854
JS
477 else
478 return wxEmptyString;
4bb6408c
JS
479}
480
e1aae528
MB
481wxString wxListBox::GetString( int n ) const
482{
483 return wxDoGetStringInList( (Widget)m_mainWidget, n );
484}
485
ef41d80c 486void wxListBox::DoInsertItems(const wxArrayString& items, int pos)
4bb6408c 487{
99ab3e3f 488 wxSizeKeeper sk( this );
f97c9854 489 Widget listBox = (Widget) m_mainWidget;
29006414 490
f97c9854 491 bool managed = XtIsManaged(listBox);
29006414 492
f97c9854
JS
493 if (managed)
494 XtUnmanageChild(listBox);
29006414 495
ef41d80c
MB
496 XmString *text = new XmString[items.GetCount()];
497 size_t i;
2d120f83
JS
498 // Steve Hammes: Motif 1.1 compatibility
499 // #if XmVersion > 1100
500 // Corrected by Sergey Krasnov from Steve Hammes' code
f97c9854 501#if XmVersion > 1001
ef41d80c 502 for (i = 0; i < items.GetCount(); i++)
d3a80c92 503 text[i] = wxStringToXmString(items[i]);
ef41d80c 504 XmListAddItemsUnselected(listBox, text, items.GetCount(), pos+1);
f97c9854 505#else
ef41d80c 506 for (i = 0; i < items.GetCount(); i++)
f97c9854 507 {
d3a80c92 508 text[i] = wxStringToXmString(items[i]);
ef41d80c
MB
509 // Another Sergey correction
510 XmListAddItemUnselected(listBox, text[i], pos+i+1);
f97c9854
JS
511 }
512#endif
ef41d80c 513 for (i = 0; i < items.GetCount(); i++)
f97c9854 514 XmStringFree(text[i]);
f97c9854 515 delete[] text;
29006414 516
f97c9854
JS
517 // It seems that if the list is cleared, we must re-ask for
518 // selection policy!!
99ab3e3f 519 SetSelectionPolicy();
29006414 520
f97c9854
JS
521 if (managed)
522 XtManageChild(listBox);
29006414 523
99ab3e3f 524 sk.Restore();
29006414 525
ef41d80c 526 m_noItems += items.GetCount();
4bb6408c
JS
527}
528
529void wxListBox::SetString(int N, const wxString& s)
530{
99ab3e3f 531 wxSizeKeeper sk( this );
f97c9854 532 Widget listBox = (Widget) m_mainWidget;
29006414 533
99ab3e3f 534 wxXmString text( s );
29006414
VZ
535
536 // delete the item and add it again.
537 // FIXME isn't there a way to change it in place?
f97c9854 538 XmListDeletePos (listBox, N+1);
99ab3e3f 539 XmListAddItem (listBox, text(), N+1);
29006414 540
99ab3e3f 541 sk.Restore();
4bb6408c
JS
542}
543
4bb6408c
JS
544void wxListBox::Command (wxCommandEvent & event)
545{
f97c9854
JS
546 if (event.m_extraLong)
547 SetSelection (event.m_commandInt);
548 else
549 {
550 Deselect (event.m_commandInt);
551 return;
552 }
553 ProcessCommand (event);
554}
555
af111fc3 556void wxListBoxCallback (Widget WXUNUSED(w), XtPointer clientData,
2d120f83 557 XmListCallbackStruct * cbs)
f97c9854 558{
f97c9854 559 wxListBox *item = (wxListBox *) clientData;
29006414 560
a4294b78 561 if (item->InSetValue())
f97c9854 562 return;
29006414 563
ef41d80c
MB
564 wxEventType evtType;
565
566 if( cbs->reason == XmCR_DEFAULT_ACTION )
567 evtType = wxEVT_COMMAND_LISTBOX_DOUBLECLICKED;
568 else
569 evtType = wxEVT_COMMAND_LISTBOX_SELECTED;
570
571 int n = cbs->item_position - 1;
572 wxCommandEvent event (evtType, item->GetId());
573 if ( item->HasClientObjectData() )
574 event.SetClientObject( item->GetClientObject(n) );
575 else if ( item->HasClientUntypedData() )
576 event.SetClientData( item->GetClientData(n) );
577 event.m_commandInt = n;
578 event.m_extraLong = TRUE;
579 event.SetEventObject(item);
580 event.SetString( item->GetString( n ) );
581
582 int x = -1;
2b5f62a0 583 if( NULL != cbs->event && cbs->event->type == ButtonRelease )
ef41d80c
MB
584 {
585 XButtonEvent* evt = (XButtonEvent*)cbs->event;
586
587 x = evt->x;
588 }
589
f97c9854 590 switch (cbs->reason)
4bb6408c 591 {
2d120f83
JS
592 case XmCR_MULTIPLE_SELECT:
593 case XmCR_BROWSE_SELECT:
ef41d80c
MB
594#if wxUSE_CHECKLISTBOX
595 item->DoToggleItem( n, x );
596#endif
597 case XmCR_DEFAULT_ACTION:
598 item->GetEventHandler()->ProcessEvent(event);
599 break;
2d120f83 600 case XmCR_EXTENDED_SELECT:
ef41d80c 601 switch (cbs->selection_type)
f97c9854 602 {
ef41d80c
MB
603 case XmINITIAL:
604 case XmADDITION:
605 case XmMODIFICATION:
606 item->DoToggleItem( n, x );
607 item->GetEventHandler()->ProcessEvent(event);
f97c9854
JS
608 break;
609 }
ef41d80c 610 break;
4bb6408c 611 }
4bb6408c
JS
612}
613
89c7e962
JS
614WXWidget wxListBox::GetTopWidget() const
615{
2d120f83 616 return (WXWidget) XtParent( (Widget) m_mainWidget );
89c7e962 617}
0d57be45 618
0d57be45
JS
619void wxListBox::ChangeBackgroundColour()
620{
321db4b6 621 wxWindow::ChangeBackgroundColour();
29006414 622
02800301
JS
623 Widget parent = XtParent ((Widget) m_mainWidget);
624 Widget hsb, vsb;
29006414 625
02800301 626 XtVaGetValues (parent,
2d120f83
JS
627 XmNhorizontalScrollBar, &hsb,
628 XmNverticalScrollBar, &vsb,
629 NULL);
29006414 630
a91b47e8
JS
631 /* TODO: should scrollbars be affected? Should probably have separate
632 * function to change them (by default, taken from wxSystemSettings)
2d120f83 633 */
a756f210 634 wxColour backgroundColour = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
a8680e3e
MB
635 wxDoChangeBackgroundColour((WXWidget) hsb, backgroundColour, TRUE);
636 wxDoChangeBackgroundColour((WXWidget) vsb, backgroundColour, TRUE);
15d5ab67
JS
637
638 XtVaSetValues (hsb,
639 XmNtroughColor, backgroundColour.AllocColour(XtDisplay(hsb)),
640 NULL);
641 XtVaSetValues (vsb,
642 XmNtroughColor, backgroundColour.AllocColour(XtDisplay(vsb)),
643 NULL);
29006414 644
73d33f1a 645 // MBN: why change parent's background? It looks really ugly.
a8680e3e 646 // wxDoChangeBackgroundColour((WXWidget) parent, m_backgroundColour, TRUE);
0d57be45
JS
647}
648
649void wxListBox::ChangeForegroundColour()
650{
321db4b6 651 wxWindow::ChangeForegroundColour();
29006414 652
02800301
JS
653 Widget parent = XtParent ((Widget) m_mainWidget);
654 Widget hsb, vsb;
29006414
VZ
655
656 XtVaGetValues(parent,
657 XmNhorizontalScrollBar, &hsb,
658 XmNverticalScrollBar, &vsb,
659 NULL);
660
661 /* TODO: should scrollbars be affected? Should probably have separate
662 function to change them (by default, taken from wxSystemSettings)
663
a8680e3e
MB
664 wxDoChangeForegroundColour((WXWidget) hsb, m_foregroundColour);
665 wxDoChangeForegroundColour((WXWidget) vsb, m_foregroundColour);
666 wxDoChangeForegroundColour((WXWidget) parent, m_foregroundColour);
02800301 667 */
0d57be45
JS
668}
669
6adaedf0
JS
670int wxListBox::GetCount() const
671{
ef41d80c 672 return m_noItems;
6adaedf0 673}
e1aae528
MB
674
675#define LIST_SCROLL_SPACING 6
676
677wxSize wxDoGetListBoxBestSize( Widget listWidget, const wxWindow* window )
678{
679 int max;
680 Dimension spacing, highlight, xmargin, ymargin, shadow;
681 int width = 0;
682 int x, y;
683
684 XtVaGetValues( listWidget,
685 XmNitemCount, &max,
686 XmNlistSpacing, &spacing,
687 XmNhighlightThickness, &highlight,
688 XmNlistMarginWidth, &xmargin,
689 XmNlistMarginHeight, &ymargin,
690 XmNshadowThickness, &shadow,
691 NULL );
692
693 for( size_t i = 0; i < (size_t)max; ++i )
694 {
695 window->GetTextExtent( wxDoGetStringInList( listWidget, i ), &x, &y );
696 width = wxMax( width, x );
697 }
698
699 // use some arbitrary value if there are no strings
700 if( width == 0 )
701 width = 100;
702
703 // get my
704 window->GetTextExtent( "v", &x, &y );
705
706 // make it a little larger than widest string, plus the scrollbar
707 width += wxSystemSettings::GetMetric( wxSYS_VSCROLL_X )
708 + 2 * highlight + LIST_SCROLL_SPACING + 2 * xmargin + 2 * shadow;
709
710 // at least 3 items, at most 10
711 int height = wxMax( 3, wxMin( 10, max ) ) *
712 ( y + spacing + 2 * highlight ) + 2 * ymargin + 2 * shadow;
713
714 return wxSize( width, height );
715}
716
717wxSize wxListBox::DoGetBestSize() const
718{
719 return wxDoGetListBoxBestSize( (Widget)m_mainWidget, this );
720}
721