1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/generic/odcombo.cpp
3 // Purpose: wxOwnerDrawnComboBox, wxVListBoxComboPopup
4 // Author: Jaakko Salli
6 // Created: Apr-30-2006
8 // Copyright: (c) 2005 Jaakko Salli
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 #include "wx/wxprec.h"
28 #include "wx/odcombo.h"
32 #include "wx/combobox.h"
33 #include "wx/dcclient.h"
34 #include "wx/settings.h"
35 #include "wx/dialog.h"
36 #include "wx/textctrl.h"
41 // ============================================================================
43 // ============================================================================
45 // time in milliseconds before partial completion buffer drops
46 #define wxODCB_PARTIAL_COMPLETION_TIME 1000
48 // ----------------------------------------------------------------------------
49 // wxVListBoxComboPopup is a wxVListBox customized to act as a popup control
51 // ----------------------------------------------------------------------------
54 BEGIN_EVENT_TABLE(wxVListBoxComboPopup
, wxVListBox
)
55 EVT_MOTION(wxVListBoxComboPopup::OnMouseMove
)
56 EVT_KEY_DOWN(wxVListBoxComboPopup::OnKey
)
57 EVT_LEFT_UP(wxVListBoxComboPopup::OnLeftClick
)
61 void wxVListBoxComboPopup::Init()
65 m_widthsDirty
= false;
70 m_clientDataItemsType
= wxClientData_None
;
71 m_partialCompletionString
= wxEmptyString
;
74 bool wxVListBoxComboPopup::Create(wxWindow
* parent
)
76 if ( !wxVListBox::Create(parent
,
80 wxBORDER_SIMPLE
| wxLB_INT_HEIGHT
| wxWANTS_CHARS
) )
83 m_useFont
= m_combo
->GetFont();
85 wxVListBox::SetItemCount(m_strings
.GetCount());
87 // TODO: Move this to SetFont
88 m_itemHeight
= GetCharHeight() + 0;
93 wxVListBoxComboPopup::~wxVListBoxComboPopup()
98 bool wxVListBoxComboPopup::LazyCreate()
100 // NB: There is a bug with wxVListBox that can be avoided by creating
101 // it later (bug causes empty space to be shown if initial selection
102 // is at the end of a list longer than the control can show at once).
106 // paint the control itself
107 void wxVListBoxComboPopup::PaintComboControl( wxDC
& dc
, const wxRect
& rect
)
109 if ( !(m_combo
->GetWindowStyle() & wxODCB_STD_CONTROL_PAINT
) )
111 int flags
= wxODCB_PAINTING_CONTROL
;
113 if ( m_combo
->ShouldDrawFocus() )
114 flags
|= wxODCB_PAINTING_SELECTED
;
116 OnDrawBg(dc
, rect
, m_value
, flags
);
120 OnDrawItem(dc
,rect
,m_value
,flags
);
125 wxComboPopup::PaintComboControl(dc
,rect
);
128 void wxVListBoxComboPopup::OnDrawItem(wxDC
& dc
, const wxRect
& rect
, size_t n
) const
130 // TODO: Maybe this code could be moved to wxVListBox::OnPaint?
131 dc
.SetFont(m_useFont
);
135 // Set correct text colour for selected items
136 if ( wxVListBox::GetSelection() == (int) n
)
138 dc
.SetTextForeground( wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT
) );
139 flags
|= wxODCB_PAINTING_SELECTED
;
143 dc
.SetTextForeground( wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT
) );
146 OnDrawItem(dc
,rect
,(int)n
,flags
);
149 wxCoord
wxVListBoxComboPopup::OnMeasureItem(size_t n
) const
151 wxOwnerDrawnComboBox
* combo
= (wxOwnerDrawnComboBox
*) m_combo
;
153 wxASSERT_MSG( combo
->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox
)),
154 wxT("you must subclass wxVListBoxComboPopup for drawing and measuring methods") );
156 wxCoord h
= combo
->OnMeasureItem(n
);
162 wxCoord
wxVListBoxComboPopup::OnMeasureItemWidth(size_t n
) const
164 wxOwnerDrawnComboBox
* combo
= (wxOwnerDrawnComboBox
*) m_combo
;
166 wxASSERT_MSG( combo
->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox
)),
167 wxT("you must subclass wxVListBoxComboPopup for drawing and measuring methods") );
169 return combo
->OnMeasureItemWidth(n
);
172 void wxVListBoxComboPopup::OnDrawBg( wxDC
& dc
,
177 wxOwnerDrawnComboBox
* combo
= (wxOwnerDrawnComboBox
*) m_combo
;
179 wxASSERT_MSG( combo
->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox
)),
180 wxT("you must subclass wxVListBoxComboPopup for drawing and measuring methods") );
182 if ( IsCurrent((size_t)item
) && !(flags
& wxODCB_PAINTING_CONTROL
) )
183 flags
|= wxODCB_PAINTING_SELECTED
;
185 combo
->OnDrawBackground(dc
,rect
,item
,flags
);
188 void wxVListBoxComboPopup::OnDrawBackground(wxDC
& dc
, const wxRect
& rect
, size_t n
) const
190 OnDrawBg(dc
,rect
,(int)n
,0);
193 // This is called from wxVListBoxComboPopup::OnDrawItem, with text colour and font prepared
194 void wxVListBoxComboPopup::OnDrawItem( wxDC
& dc
, const wxRect
& rect
, int item
, int flags
) const
196 wxOwnerDrawnComboBox
* combo
= (wxOwnerDrawnComboBox
*) m_combo
;
198 wxASSERT_MSG( combo
->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox
)),
199 wxT("you must subclass wxVListBoxComboPopup for drawing and measuring methods") );
201 combo
->OnDrawItem(dc
,rect
,item
,flags
);
204 void wxVListBoxComboPopup::DismissWithEvent()
206 StopPartialCompletion();
208 int selection
= wxVListBox::GetSelection();
212 if ( selection
!= wxNOT_FOUND
)
213 m_stringValue
= m_strings
[selection
];
215 m_stringValue
= wxEmptyString
;
217 if ( m_stringValue
!= m_combo
->GetValue() )
218 m_combo
->SetValueWithEvent(m_stringValue
);
222 SendComboBoxEvent(selection
);
225 void wxVListBoxComboPopup::SendComboBoxEvent( int selection
)
227 wxCommandEvent
evt(wxEVT_COMMAND_COMBOBOX_SELECTED
,m_combo
->GetId());
229 evt
.SetEventObject(m_combo
);
231 evt
.SetInt(selection
);
233 // Set client data, if any
234 if ( selection
>= 0 && (int)m_clientDatas
.GetCount() > selection
)
236 void* clientData
= m_clientDatas
[selection
];
237 if ( m_clientDataItemsType
== wxClientData_Object
)
238 evt
.SetClientObject((wxClientData
*)clientData
);
240 evt
.SetClientData(clientData
);
243 m_combo
->GetEventHandler()->AddPendingEvent(evt
);
246 // returns true if key was consumed
247 bool wxVListBoxComboPopup::HandleKey( int keycode
, bool saturate
, wxChar unicode
)
250 int itemCount
= GetCount();
251 int comboStyle
= m_combo
->GetWindowStyle();
253 // this is the character equivalent of the code
255 if ((keycode
>= WXK_SPACE
) && (keycode
<=255) && (keycode
!= WXK_DELETE
) && wxIsprint(keycode
))
257 keychar
= (wxChar
)keycode
;
264 if ( keycode
== WXK_DOWN
|| keycode
== WXK_RIGHT
)
267 StopPartialCompletion();
269 else if ( keycode
== WXK_UP
|| keycode
== WXK_LEFT
)
272 StopPartialCompletion();
274 else if ( keycode
== WXK_PAGEDOWN
)
277 StopPartialCompletion();
279 else if ( keycode
== WXK_PAGEUP
)
282 StopPartialCompletion();
284 else if ( comboStyle
& wxCB_READONLY
)
286 // Try partial completion
288 // find the new partial completion string
290 if (m_partialCompletionTimer
.IsRunning())
291 m_partialCompletionString
+=wxString(keychar
);
293 #endif // wxUSE_TIMER
294 m_partialCompletionString
=wxString(keychar
);
296 // now search through the values to see if this is found
298 unsigned int length
=m_partialCompletionString
.length();
300 for (i
=0; i
<itemCount
; i
++)
302 wxString item
=GetString(i
);
303 if (( item
.length() >= length
) && (! m_partialCompletionString
.CmpNoCase(item
.Left(length
))))
312 StopPartialCompletion();
314 return true; // to stop the first value being set
320 m_partialCompletionTimer
.Start(wxODCB_PARTIAL_COMPLETION_TIME
, true);
321 #endif // wxUSE_TIMER
329 if ( value
>= itemCount
)
330 value
= itemCount
- 1;
331 else if ( value
< 0 )
336 if ( value
>= itemCount
)
338 else if ( value
< 0 )
342 if ( value
== m_value
)
343 // Even if value was same, don't skip the event
344 // (good for consistency)
350 m_combo
->SetValue(m_strings
[value
]);
352 SendComboBoxEvent(m_value
);
357 // stop partial completion
358 void wxVListBoxComboPopup::StopPartialCompletion()
360 m_partialCompletionString
= wxEmptyString
;
362 m_partialCompletionTimer
.Stop();
363 #endif // wxUSE_TIMER
366 void wxVListBoxComboPopup::OnComboDoubleClick()
368 // Cycle on dclick (disable saturation to allow true cycling).
369 if ( !::wxGetKeyState(WXK_SHIFT
) )
370 HandleKey(WXK_DOWN
,false);
372 HandleKey(WXK_UP
,false);
375 void wxVListBoxComboPopup::OnComboKeyEvent( wxKeyEvent
& event
)
377 // Saturated key movement on
378 if ( !HandleKey(event
.GetKeyCode(),true,
380 event
.GetUnicodeKey()
388 void wxVListBoxComboPopup::OnPopup()
390 // *must* set value after size is set (this is because of a vlbox bug)
391 wxVListBox::SetSelection(m_value
);
394 void wxVListBoxComboPopup::OnMouseMove(wxMouseEvent
& event
)
398 // Move selection to cursor if it is inside the popup
400 int y
= event
.GetPosition().y
;
401 int fromBottom
= GetClientSize().y
- y
;
403 // Since in any case we need to find out if the last item is only
404 // partially visible, we might just as well replicate the HitTest
406 const size_t lineMax
= GetVisibleEnd();
407 for ( size_t line
= GetVisibleBegin(); line
< lineMax
; line
++ )
409 y
-= OnGetRowHeight(line
);
412 // Only change selection if item is fully visible
413 if ( (y
+ fromBottom
) >= 0 )
415 wxVListBox::SetSelection((int)line
);
422 void wxVListBoxComboPopup::OnLeftClick(wxMouseEvent
& WXUNUSED(event
))
427 void wxVListBoxComboPopup::OnKey(wxKeyEvent
& event
)
429 // Hide popup if certain key or key combination was pressed
430 if ( m_combo
->IsKeyPopupToggle(event
) )
432 StopPartialCompletion();
435 else if ( event
.AltDown() )
437 // On both wxGTK and wxMSW, pressing Alt down seems to
438 // completely freeze things in popup (ie. arrow keys and
439 // enter won't work).
442 // Select item if ENTER is pressed
443 else if ( event
.GetKeyCode() == WXK_RETURN
|| event
.GetKeyCode() == WXK_NUMPAD_ENTER
)
449 int comboStyle
= m_combo
->GetWindowStyle();
450 int keycode
= event
.GetKeyCode();
451 // Process partial completion key codes here, but not the arrow keys as the base class will do that for us
452 if ((comboStyle
& wxCB_READONLY
) &&
453 (keycode
>= WXK_SPACE
) && (keycode
<=255) && (keycode
!= WXK_DELETE
) && wxIsprint(keycode
))
455 OnComboKeyEvent(event
);
456 SetSelection(m_value
); // ensure the highlight bar moves
463 void wxVListBoxComboPopup::Insert( const wxString
& item
, int pos
)
465 // Need to change selection?
467 if ( !(m_combo
->GetWindowStyle() & wxCB_READONLY
) &&
468 m_combo
->GetValue() == item
)
473 m_strings
.Insert(item
,pos
);
474 m_clientDatas
.Insert(NULL
, pos
);
476 m_widths
.Insert(-1,pos
);
477 m_widthsDirty
= true;
480 wxVListBox::SetItemCount( wxVListBox::GetItemCount()+1 );
483 int wxVListBoxComboPopup::Append(const wxString
& item
)
485 int pos
= (int)m_strings
.GetCount();
487 if ( m_combo
->GetWindowStyle() & wxCB_SORT
)
490 // TODO: Could be optimized with binary search
491 wxArrayString strings
= m_strings
;
494 for ( i
=0; i
<strings
.GetCount(); i
++ )
496 if ( item
.Cmp(strings
.Item(i
)) < 0 )
509 void wxVListBoxComboPopup::Clear()
521 m_value
= wxNOT_FOUND
;
524 wxVListBox::SetItemCount(0);
527 void wxVListBoxComboPopup::ClearClientDatas()
529 if ( m_clientDataItemsType
== wxClientData_Object
)
532 for ( i
=0; i
<m_clientDatas
.GetCount(); i
++ )
533 delete (wxClientData
*) m_clientDatas
[i
];
536 m_clientDatas
.Empty();
539 void wxVListBoxComboPopup::SetItemClientData( unsigned int n
,
541 wxClientDataType clientDataItemsType
)
543 // It should be sufficient to update this variable only here
544 m_clientDataItemsType
= clientDataItemsType
;
546 m_clientDatas
[n
] = clientData
;
551 void* wxVListBoxComboPopup::GetItemClientData(unsigned int n
) const
553 if ( m_clientDatas
.GetCount() > n
)
554 return m_clientDatas
[n
];
559 void wxVListBoxComboPopup::Delete( unsigned int item
)
561 // Remove client data, if set
562 if ( m_clientDatas
.GetCount() )
564 if ( m_clientDataItemsType
== wxClientData_Object
)
565 delete (wxClientData
*) m_clientDatas
[item
];
567 m_clientDatas
.RemoveAt(item
);
570 m_strings
.RemoveAt(item
);
571 m_widths
.RemoveAt(item
);
573 if ( (int)item
== m_widestItem
)
576 int sel
= GetSelection();
579 wxVListBox::SetItemCount( wxVListBox::GetItemCount()-1 );
582 if ( (int)item
< sel
)
584 else if ( (int)item
== sel
)
585 SetSelection(wxNOT_FOUND
);
588 int wxVListBoxComboPopup::FindString(const wxString
& s
, bool bCase
) const
590 return m_strings
.Index(s
, bCase
);
593 unsigned int wxVListBoxComboPopup::GetCount() const
595 return m_strings
.GetCount();
598 wxString
wxVListBoxComboPopup::GetString( int item
) const
600 return m_strings
[item
];
603 void wxVListBoxComboPopup::SetString( int item
, const wxString
& str
)
605 m_strings
[item
] = str
;
606 ItemWidthChanged(item
);
609 wxString
wxVListBoxComboPopup::GetStringValue() const
611 return m_stringValue
;
614 void wxVListBoxComboPopup::SetSelection( int item
)
616 wxCHECK_RET( item
== wxNOT_FOUND
|| ((unsigned int)item
< GetCount()),
617 wxT("invalid index in wxVListBoxComboPopup::SetSelection") );
622 m_stringValue
= m_strings
[item
];
624 m_stringValue
= wxEmptyString
;
627 wxVListBox::SetSelection(item
);
630 int wxVListBoxComboPopup::GetSelection() const
635 void wxVListBoxComboPopup::SetStringValue( const wxString
& value
)
637 int index
= m_strings
.Index(value
);
639 m_stringValue
= value
;
641 if ( index
>= 0 && index
< (int)wxVListBox::GetItemCount() )
643 wxVListBox::SetSelection(index
);
648 void wxVListBoxComboPopup::CalcWidths()
650 bool doFindWidest
= m_findWidest
;
652 // Measure items with dirty width.
656 unsigned int n
= m_widths
.GetCount();
657 int dirtyHandled
= 0;
658 wxArrayInt
& widths
= m_widths
;
660 // I think using wxDC::GetTextExtent is faster than
661 // wxWindow::GetTextExtent (assuming same dc is used
662 // for all calls, as we do here).
663 wxClientDC
dc(m_combo
);
664 dc
.SetFont(m_useFont
);
666 for ( i
=0; i
<n
; i
++ )
670 wxCoord x
= OnMeasureItemWidth(i
);
674 const wxString
& text
= m_strings
[i
];
676 // To make sure performance won't suck in extreme scenarios,
677 // we'll estimate length after some arbitrary number of items
678 // have been checked precily.
679 if ( dirtyHandled
< 1024 )
682 dc
.GetTextExtent(text
, &x
, &y
, 0, 0);
687 x
= text
.length() * (dc
.GetCharWidth()+1);
693 if ( x
>= m_widestWidth
)
696 m_widestItem
= (int)i
;
698 else if ( (int)i
== m_widestItem
)
700 // Width of previously widest item has been decreased, so
701 // we'll have to check all to find current widest item.
709 m_widthsDirty
= false;
715 unsigned int n
= m_widths
.GetCount();
720 for ( i
=0; i
<n
; i
++ )
730 m_widestWidth
= bestWidth
;
731 m_widestItem
= bestIndex
;
733 m_findWidest
= false;
737 wxSize
wxVListBoxComboPopup::GetAdjustedSize( int minWidth
, int prefHeight
, int maxHeight
)
741 maxHeight
-= 2; // Must take borders into account
743 if ( m_strings
.GetCount() )
745 if ( prefHeight
> 0 )
748 if ( height
> maxHeight
)
751 int totalHeight
= GetTotalHeight(); // + 3;
752 if ( height
>= totalHeight
)
754 height
= totalHeight
;
758 // Adjust height to a multiple of the height of the first item
759 // NB: Calculations that take variable height into account
761 int fih
= GetLineHeight(0);
762 height
-= height
% fih
;
770 // Take scrollbar into account in width calculations
771 int widestWidth
= m_widestWidth
+ wxSystemSettings::GetMetric(wxSYS_VSCROLL_X
);
772 return wxSize(minWidth
> widestWidth
? minWidth
: widestWidth
,
776 //void wxVListBoxComboPopup::Populate( int n, const wxString choices[] )
777 void wxVListBoxComboPopup::Populate( const wxArrayString
& choices
)
781 int n
= choices
.GetCount();
783 for ( i
=0; i
<n
; i
++ )
785 const wxString
& item
= choices
.Item(i
);
789 m_widths
.SetCount(n
,-1);
790 m_widthsDirty
= true;
793 wxVListBox::SetItemCount(n
);
795 // Sort the initial choices
796 if ( m_combo
->GetWindowStyle() & wxCB_SORT
)
799 // Find initial selection
800 wxString strValue
= m_combo
->GetValue();
801 if ( strValue
.length() )
802 m_value
= m_strings
.Index(strValue
);
805 // ----------------------------------------------------------------------------
806 // wxOwnerDrawnComboBox
807 // ----------------------------------------------------------------------------
810 BEGIN_EVENT_TABLE(wxOwnerDrawnComboBox
, wxComboCtrl
)
814 #if wxUSE_EXTENDED_RTTI
815 IMPLEMENT_DYNAMIC_CLASS2_XTI(wxOwnerDrawnComboBox
, wxComboCtrl
, wxControlWithItems
, "wx/odcombo.h")
817 wxBEGIN_PROPERTIES_TABLE(wxOwnerDrawnComboBox
)
818 wxEND_PROPERTIES_TABLE()
820 wxBEGIN_HANDLERS_TABLE(wxOwnerDrawnComboBox
)
821 wxEND_HANDLERS_TABLE()
823 wxCONSTRUCTOR_5( wxOwnerDrawnComboBox
, wxWindow
* , Parent
, wxWindowID
, Id
, wxString
, Value
, wxPoint
, Position
, wxSize
, Size
)
825 IMPLEMENT_DYNAMIC_CLASS2(wxOwnerDrawnComboBox
, wxComboCtrl
, wxControlWithItems
)
828 void wxOwnerDrawnComboBox::Init()
832 bool wxOwnerDrawnComboBox::Create(wxWindow
*parent
,
834 const wxString
& value
,
838 const wxValidator
& validator
,
839 const wxString
& name
)
841 return wxComboCtrl::Create(parent
,id
,value
,pos
,size
,style
,validator
,name
);
844 wxOwnerDrawnComboBox::wxOwnerDrawnComboBox(wxWindow
*parent
,
846 const wxString
& value
,
849 const wxArrayString
& choices
,
851 const wxValidator
& validator
,
852 const wxString
& name
)
857 Create(parent
,id
,value
,pos
,size
,choices
,style
, validator
, name
);
860 bool wxOwnerDrawnComboBox::Create(wxWindow
*parent
,
862 const wxString
& value
,
865 const wxArrayString
& choices
,
867 const wxValidator
& validator
,
868 const wxString
& name
)
871 //wxCArrayString chs(choices);
873 //return Create(parent, id, value, pos, size, chs.GetCount(),
874 // chs.GetStrings(), style, validator, name);
875 return Create(parent
, id
, value
, pos
, size
, 0,
876 NULL
, style
, validator
, name
);
879 bool wxOwnerDrawnComboBox::Create(wxWindow
*parent
,
881 const wxString
& value
,
885 const wxString choices
[],
887 const wxValidator
& validator
,
888 const wxString
& name
)
891 if ( !Create(parent
, id
, value
, pos
, size
, style
,
898 for ( i
=0; i
<n
; i
++ )
899 m_initChs
.Add(choices
[i
]);
904 wxOwnerDrawnComboBox::~wxOwnerDrawnComboBox()
906 if ( m_popupInterface
)
907 GetVListBoxComboPopup()->ClearClientDatas();
910 void wxOwnerDrawnComboBox::DoSetPopupControl(wxComboPopup
* popup
)
914 popup
= new wxVListBoxComboPopup();
917 wxComboCtrl::DoSetPopupControl(popup
);
921 // Add initial choices to the wxVListBox
922 if ( !GetVListBoxComboPopup()->GetCount() )
924 GetVListBoxComboPopup()->Populate(m_initChs
);
929 // ----------------------------------------------------------------------------
930 // wxOwnerDrawnComboBox item manipulation methods
931 // ----------------------------------------------------------------------------
933 void wxOwnerDrawnComboBox::DoClear()
935 EnsurePopupControl();
937 GetVListBoxComboPopup()->Clear();
939 SetValue(wxEmptyString
);
942 void wxOwnerDrawnComboBox::DoDeleteOneItem(unsigned int n
)
944 wxCHECK_RET( IsValid(n
), _T("invalid index in wxOwnerDrawnComboBox::Delete") );
946 if ( GetSelection() == (int) n
)
947 SetValue(wxEmptyString
);
949 GetVListBoxComboPopup()->Delete(n
);
952 unsigned int wxOwnerDrawnComboBox::GetCount() const
954 if ( !m_popupInterface
)
955 return m_initChs
.GetCount();
957 return GetVListBoxComboPopup()->GetCount();
960 wxString
wxOwnerDrawnComboBox::GetString(unsigned int n
) const
962 wxCHECK_MSG( IsValid(n
), wxEmptyString
, _T("invalid index in wxOwnerDrawnComboBox::GetString") );
964 if ( !m_popupInterface
)
965 return m_initChs
.Item(n
);
967 return GetVListBoxComboPopup()->GetString(n
);
970 void wxOwnerDrawnComboBox::SetString(unsigned int n
, const wxString
& s
)
972 EnsurePopupControl();
974 wxCHECK_RET( IsValid(n
), _T("invalid index in wxOwnerDrawnComboBox::SetString") );
976 GetVListBoxComboPopup()->SetString(n
,s
);
979 int wxOwnerDrawnComboBox::FindString(const wxString
& s
, bool bCase
) const
981 if ( !m_popupInterface
)
982 return m_initChs
.Index(s
, bCase
);
984 return GetVListBoxComboPopup()->FindString(s
, bCase
);
987 void wxOwnerDrawnComboBox::Select(int n
)
989 EnsurePopupControl();
991 wxCHECK_RET( (n
== wxNOT_FOUND
) || IsValid(n
), _T("invalid index in wxOwnerDrawnComboBox::Select") );
993 GetVListBoxComboPopup()->SetSelection(n
);
997 str
= GetVListBoxComboPopup()->GetString(n
);
999 // Refresh text portion in control
1001 m_text
->SetValue( str
);
1003 m_valueString
= str
;
1008 int wxOwnerDrawnComboBox::GetSelection() const
1010 if ( !m_popupInterface
)
1011 return m_initChs
.Index(m_valueString
);
1013 return GetVListBoxComboPopup()->GetSelection();
1016 int wxOwnerDrawnComboBox::DoInsertItems(const wxArrayStringsAdapter
& items
,
1019 wxClientDataType type
)
1021 EnsurePopupControl();
1023 const unsigned int count
= items
.GetCount();
1024 for( unsigned int i
= 0; i
< count
; ++i
, ++pos
)
1026 GetVListBoxComboPopup()->Insert(items
[i
], pos
);
1027 AssignNewItemClientData(pos
, clientData
, i
, type
);
1033 void wxOwnerDrawnComboBox::DoSetItemClientData(unsigned int n
, void* clientData
)
1035 EnsurePopupControl();
1037 GetVListBoxComboPopup()->SetItemClientData(n
, clientData
,
1038 GetClientDataType());
1041 void* wxOwnerDrawnComboBox::DoGetItemClientData(unsigned int n
) const
1043 if ( !m_popupInterface
)
1046 return GetVListBoxComboPopup()->GetItemClientData(n
);
1049 // ----------------------------------------------------------------------------
1050 // wxOwnerDrawnComboBox item drawing and measuring default implementations
1051 // ----------------------------------------------------------------------------
1053 void wxOwnerDrawnComboBox::OnDrawItem( wxDC
& dc
,
1058 if ( flags
& wxODCB_PAINTING_CONTROL
)
1060 dc
.DrawText( GetValue(),
1061 rect
.x
+ GetTextIndent(),
1062 (rect
.height
-dc
.GetCharHeight())/2 + rect
.y
);
1066 dc
.DrawText( GetVListBoxComboPopup()->GetString(item
), rect
.x
+ 2, rect
.y
);
1070 wxCoord
wxOwnerDrawnComboBox::OnMeasureItem( size_t WXUNUSED(item
) ) const
1075 wxCoord
wxOwnerDrawnComboBox::OnMeasureItemWidth( size_t WXUNUSED(item
) ) const
1080 void wxOwnerDrawnComboBox::OnDrawBackground(wxDC
& dc
,
1085 // We need only to explicitly draw background for items
1086 // that should have selected background. Also, call PrepareBackground
1087 // always when painting the control so that clipping is done properly.
1089 if ( (flags
& wxODCB_PAINTING_SELECTED
) ||
1090 ((flags
& wxODCB_PAINTING_CONTROL
) && HasFlag(wxCB_READONLY
)) )
1092 int bgFlags
= wxCONTROL_SELECTED
;
1094 if ( !(flags
& wxODCB_PAINTING_CONTROL
) )
1095 bgFlags
|= wxCONTROL_ISSUBMENU
;
1097 PrepareBackground(dc
, rect
, bgFlags
);
1101 #endif // wxUSE_ODCOMBOBOX