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"
40 // ============================================================================
42 // ============================================================================
44 // time in milliseconds before partial completion buffer drops
45 #define wxODCB_PARTIAL_COMPLETION_TIME 1000
47 // ----------------------------------------------------------------------------
48 // wxVListBoxComboPopup is a wxVListBox customized to act as a popup control
50 // ----------------------------------------------------------------------------
53 BEGIN_EVENT_TABLE(wxVListBoxComboPopup
, wxVListBox
)
54 EVT_MOTION(wxVListBoxComboPopup
::OnMouseMove
)
55 EVT_KEY_DOWN(wxVListBoxComboPopup
::OnKey
)
56 EVT_LEFT_UP(wxVListBoxComboPopup
::OnLeftClick
)
60 void wxVListBoxComboPopup
::Init()
64 m_widthsDirty
= false;
69 m_clientDataItemsType
= wxClientData_None
;
70 m_partialCompletionString
= wxEmptyString
;
73 bool wxVListBoxComboPopup
::Create(wxWindow
* parent
)
75 if ( !wxVListBox
::Create(parent
,
79 wxBORDER_SIMPLE
| wxLB_INT_HEIGHT
| wxWANTS_CHARS
) )
82 m_useFont
= m_combo
->GetFont();
84 wxVListBox
::SetItemCount(m_strings
.GetCount());
86 // TODO: Move this to SetFont
87 m_itemHeight
= GetCharHeight() + 0;
92 wxVListBoxComboPopup
::~wxVListBoxComboPopup()
97 bool wxVListBoxComboPopup
::LazyCreate()
99 // NB: There is a bug with wxVListBox that can be avoided by creating
100 // it later (bug causes empty space to be shown if initial selection
101 // is at the end of a list longer than the control can show at once).
105 // paint the control itself
106 void wxVListBoxComboPopup
::PaintComboControl( wxDC
& dc
, const wxRect
& rect
)
108 if ( !(m_combo
->GetWindowStyle() & wxODCB_STD_CONTROL_PAINT
) )
110 OnDrawBg(dc
,rect
,m_value
,wxODCB_PAINTING_CONTROL
);
113 OnDrawItem(dc
,rect
,m_value
,wxODCB_PAINTING_CONTROL
);
118 wxComboPopup
::PaintComboControl(dc
,rect
);
121 void wxVListBoxComboPopup
::OnDrawItem(wxDC
& dc
, const wxRect
& rect
, size_t n
) const
123 // TODO: Maybe this code could be moved to wxVListBox::OnPaint?
124 dc
.SetFont(m_useFont
);
126 // Set correct text colour for selected items
127 if ( wxVListBox
::GetSelection() == (int) n
)
128 dc
.SetTextForeground( wxSystemSettings
::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT
) );
130 dc
.SetTextForeground( wxSystemSettings
::GetColour(wxSYS_COLOUR_WINDOWTEXT
) );
132 OnDrawItem(dc
,rect
,(int)n
,0);
135 wxCoord wxVListBoxComboPopup
::OnMeasureItem(size_t n
) const
137 wxOwnerDrawnComboBox
* combo
= (wxOwnerDrawnComboBox
*) m_combo
;
139 wxASSERT_MSG( combo
->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox
)),
140 wxT("you must subclass wxVListBoxComboPopup for drawing and measuring methods") );
142 wxCoord h
= combo
->OnMeasureItem(n
);
148 wxCoord wxVListBoxComboPopup
::OnMeasureItemWidth(size_t n
) const
150 wxOwnerDrawnComboBox
* combo
= (wxOwnerDrawnComboBox
*) m_combo
;
152 wxASSERT_MSG( combo
->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox
)),
153 wxT("you must subclass wxVListBoxComboPopup for drawing and measuring methods") );
155 return combo
->OnMeasureItemWidth(n
);
158 void wxVListBoxComboPopup
::OnDrawBg( wxDC
& dc
,
163 wxOwnerDrawnComboBox
* combo
= (wxOwnerDrawnComboBox
*) m_combo
;
165 wxASSERT_MSG( combo
->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox
)),
166 wxT("you must subclass wxVListBoxComboPopup for drawing and measuring methods") );
168 combo
->OnDrawBackground(dc
,rect
,item
,flags
);
171 void wxVListBoxComboPopup
::OnDrawBackground(wxDC
& dc
, const wxRect
& rect
, size_t n
) const
173 OnDrawBg(dc
,rect
,(int)n
,0);
176 // This is called from wxVListBoxComboPopup::OnDrawItem, with text colour and font prepared
177 void wxVListBoxComboPopup
::OnDrawItem( wxDC
& dc
, const wxRect
& rect
, int item
, int flags
) const
179 wxOwnerDrawnComboBox
* combo
= (wxOwnerDrawnComboBox
*) m_combo
;
181 wxASSERT_MSG( combo
->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox
)),
182 wxT("you must subclass wxVListBoxComboPopup for drawing and measuring methods") );
184 combo
->OnDrawItem(dc
,rect
,item
,flags
);
187 void wxVListBoxComboPopup
::DismissWithEvent()
189 StopPartialCompletion();
191 int selection
= wxVListBox
::GetSelection();
196 if ( selection
!= wxNOT_FOUND
)
197 valStr
= m_strings
[selection
];
199 valStr
= wxEmptyString
;
203 if ( valStr
!= m_combo
->GetValue() )
204 m_combo
->SetValue(valStr
);
206 SendComboBoxEvent(selection
);
209 void wxVListBoxComboPopup
::SendComboBoxEvent( int selection
)
211 wxCommandEvent
evt(wxEVT_COMMAND_COMBOBOX_SELECTED
,m_combo
->GetId());
213 evt
.SetEventObject(m_combo
);
215 evt
.SetInt(selection
);
217 // Set client data, if any
218 if ( selection
>= 0 && (int)m_clientDatas
.GetCount() > selection
)
220 void* clientData
= m_clientDatas
[selection
];
221 if ( m_clientDataItemsType
== wxClientData_Object
)
222 evt
.SetClientObject((wxClientData
*)clientData
);
224 evt
.SetClientData(clientData
);
227 m_combo
->GetEventHandler()->AddPendingEvent(evt
);
230 // returns true if key was consumed
231 bool wxVListBoxComboPopup
::HandleKey( int keycode
, bool saturate
, wxChar unicode
)
234 int itemCount
= GetCount();
235 int comboStyle
= m_combo
->GetWindowStyle();
237 // this is the character equivalent of the code
239 if ((keycode
>= WXK_SPACE
) && (keycode
<=255) && (keycode
!= WXK_DELETE
) && wxIsprint(keycode
))
248 if ( keycode
== WXK_DOWN
|| keycode
== WXK_RIGHT
)
251 StopPartialCompletion();
253 else if ( keycode
== WXK_UP
|| keycode
== WXK_LEFT
)
256 StopPartialCompletion();
258 else if ( keycode
== WXK_PAGEDOWN
)
261 StopPartialCompletion();
263 else if ( keycode
== WXK_PAGEUP
)
266 StopPartialCompletion();
268 else if ( comboStyle
&& wxCB_READONLY
)
270 // Try partial completion
272 // find the new partial completion string
273 if (m_partialCompletionTimer
.IsRunning())
274 m_partialCompletionString
+=wxString(keychar
);
276 m_partialCompletionString
=wxString(keychar
);
278 // now search through the values to see if this is found
280 unsigned int length
=m_partialCompletionString
.Length();
282 for (i
=0; i
<itemCount
; i
++)
284 wxString item
=GetString(i
);
285 if (( item
.Length() >=length
) && (! m_partialCompletionString
.CmpNoCase(item
.Left(length
))))
294 StopPartialCompletion();
296 return true; // to stop the first value being set
301 m_partialCompletionTimer
.Start(wxODCB_PARTIAL_COMPLETION_TIME
, true);
309 if ( value
>= itemCount
)
310 value
= itemCount
- 1;
311 else if ( value
< 0 )
316 if ( value
>= itemCount
)
318 else if ( value
< 0 )
322 if ( value
== m_value
)
323 // Even if value was same, don't skip the event
324 // (good for consistency)
330 m_combo
->SetValue(m_strings
[value
]);
332 SendComboBoxEvent(m_value
);
337 // stop partial completion
338 void wxVListBoxComboPopup
::StopPartialCompletion()
340 m_partialCompletionString
= wxEmptyString
;
341 m_partialCompletionTimer
.Stop();
344 void wxVListBoxComboPopup
::OnComboDoubleClick()
346 // Cycle on dclick (disable saturation to allow true cycling).
347 if ( !::wxGetKeyState(WXK_SHIFT
) )
348 HandleKey(WXK_DOWN
,false);
350 HandleKey(WXK_UP
,false);
353 void wxVListBoxComboPopup
::OnComboKeyEvent( wxKeyEvent
& event
)
355 // Saturated key movement on
356 if ( !HandleKey(event
.GetKeyCode(),true,
358 event
.GetUnicodeKey()
366 void wxVListBoxComboPopup
::OnPopup()
368 // *must* set value after size is set (this is because of a vlbox bug)
369 wxVListBox
::SetSelection(m_value
);
372 void wxVListBoxComboPopup
::OnMouseMove(wxMouseEvent
& event
)
376 // Move selection to cursor if it is inside the popup
378 int y
= event
.GetPosition().y
;
379 int fromBottom
= GetClientSize().y
- y
;
381 // Since in any case we need to find out if the last item is only
382 // partially visible, we might just as well replicate the HitTest
384 const size_t lineMax
= GetVisibleEnd();
385 for ( size_t line
= GetVisibleBegin(); line
< lineMax
; line
++ )
387 y
-= OnGetLineHeight(line
);
390 // Only change selection if item is fully visible
391 if ( (y
+ fromBottom
) >= 0 )
393 wxVListBox
::SetSelection((int)line
);
400 void wxVListBoxComboPopup
::OnLeftClick(wxMouseEvent
& WXUNUSED(event
))
405 void wxVListBoxComboPopup
::OnKey(wxKeyEvent
& event
)
407 // Select item if ENTER is pressed
408 if ( event
.GetKeyCode() == WXK_RETURN
|| event
.GetKeyCode() == WXK_NUMPAD_ENTER
)
412 // Hide popup if ESC is pressed
413 else if ( event
.GetKeyCode() == WXK_ESCAPE
)
415 StopPartialCompletion();
420 int comboStyle
= m_combo
->GetWindowStyle();
421 int keycode
= event
.GetKeyCode();
422 // Process partial completion key codes here, but not the arrow keys as the base class will do that for us
423 if ((comboStyle
&& wxCB_READONLY
) &&
424 (keycode
>= WXK_SPACE
) && (keycode
<=255) && (keycode
!= WXK_DELETE
) && wxIsprint(keycode
))
426 OnComboKeyEvent(event
);
427 SetSelection(m_value
); // ensure the highlight bar moves
434 void wxVListBoxComboPopup
::Insert( const wxString
& item
, int pos
)
436 // Need to change selection?
438 if ( !(m_combo
->GetWindowStyle() & wxCB_READONLY
) &&
439 m_combo
->GetValue() == item
)
444 m_strings
.Insert(item
,pos
);
445 m_widths
.Insert(-1,pos
);
446 m_widthsDirty
= true;
449 wxVListBox
::SetItemCount( wxVListBox
::GetItemCount()+1 );
452 int wxVListBoxComboPopup
::Append(const wxString
& item
)
454 int pos
= (int)m_strings
.GetCount();
456 if ( m_combo
->GetWindowStyle() & wxCB_SORT
)
459 // TODO: Could be optimized with binary search
460 wxArrayString strings
= m_strings
;
463 for ( i
=0; i
<strings
.GetCount(); i
++ )
465 if ( item
.Cmp(strings
.Item(i
)) < 0 )
478 void wxVListBoxComboPopup
::Clear()
490 m_value
= wxNOT_FOUND
;
493 wxVListBox
::SetItemCount(0);
496 void wxVListBoxComboPopup
::ClearClientDatas()
498 if ( m_clientDataItemsType
== wxClientData_Object
)
501 for ( i
=0; i
<m_clientDatas
.GetCount(); i
++ )
502 delete (wxClientData
*) m_clientDatas
[i
];
505 m_clientDatas
.Empty();
508 void wxVListBoxComboPopup
::SetItemClientData( unsigned int n
,
510 wxClientDataType clientDataItemsType
)
512 // It should be sufficient to update this variable only here
513 m_clientDataItemsType
= clientDataItemsType
;
515 m_clientDatas
.SetCount(n
+1,NULL
);
516 m_clientDatas
[n
] = clientData
;
521 void* wxVListBoxComboPopup
::GetItemClientData(unsigned int n
) const
523 if ( m_clientDatas
.GetCount() > n
)
524 return m_clientDatas
[n
];
529 void wxVListBoxComboPopup
::Delete( unsigned int item
)
531 // Remove client data, if set
532 if ( m_clientDatas
.GetCount() )
534 if ( m_clientDataItemsType
== wxClientData_Object
)
535 delete (wxClientData
*) m_clientDatas
[item
];
537 m_clientDatas
.RemoveAt(item
);
540 m_strings
.RemoveAt(item
);
541 m_widths
.RemoveAt(item
);
543 if ( (int)item
== m_widestItem
)
547 wxVListBox
::SetItemCount( wxVListBox
::GetItemCount()-1 );
550 int wxVListBoxComboPopup
::FindString(const wxString
& s
, bool bCase
) const
552 return m_strings
.Index(s
, bCase
);
555 unsigned int wxVListBoxComboPopup
::GetCount() const
557 return m_strings
.GetCount();
560 wxString wxVListBoxComboPopup
::GetString( int item
) const
562 return m_strings
[item
];
565 void wxVListBoxComboPopup
::SetString( int item
, const wxString
& str
)
567 m_strings
[item
] = str
;
568 ItemWidthChanged(item
);
571 wxString wxVListBoxComboPopup
::GetStringValue() const
574 return m_strings
[m_value
];
575 return wxEmptyString
;
578 void wxVListBoxComboPopup
::SetSelection( int item
)
580 wxCHECK_RET( item
== wxNOT_FOUND
|| ((unsigned int)item
< GetCount()),
581 wxT("invalid index in wxVListBoxComboPopup::SetSelection") );
586 wxVListBox
::SetSelection(item
);
589 int wxVListBoxComboPopup
::GetSelection() const
594 void wxVListBoxComboPopup
::SetStringValue( const wxString
& value
)
596 int index
= m_strings
.Index(value
);
600 if ( index
>= -1 && index
< (int)wxVListBox
::GetItemCount() )
601 wxVListBox
::SetSelection(index
);
604 void wxVListBoxComboPopup
::CalcWidths()
606 bool doFindWidest
= m_findWidest
;
608 // Measure items with dirty width.
612 unsigned int n
= m_widths
.GetCount();
613 int dirtyHandled
= 0;
614 wxArrayInt
& widths
= m_widths
;
616 // I think using wxDC::GetTextExtent is faster than
617 // wxWindow::GetTextExtent (assuming same dc is used
618 // for all calls, as we do here).
619 wxClientDC
dc(m_combo
);
620 dc
.SetFont(m_useFont
);
622 for ( i
=0; i
<n
; i
++ )
626 wxCoord x
= OnMeasureItemWidth(i
);
630 const wxString
& text
= m_strings
[i
];
632 // To make sure performance won't suck in extreme scenarios,
633 // we'll estimate length after some arbitrary number of items
634 // have been checked precily.
635 if ( dirtyHandled
< 1024 )
638 dc
.GetTextExtent(text
, &x
, &y
, 0, 0);
643 x
= text
.length() * (dc
.GetCharWidth()+1);
649 if ( x
>= m_widestWidth
)
652 m_widestItem
= (int)i
;
654 else if ( (int)i
== m_widestItem
)
656 // Width of previously widest item has been decreased, so
657 // we'll have to check all to find current widest item.
665 m_widthsDirty
= false;
671 unsigned int n
= m_widths
.GetCount();
676 for ( i
=0; i
<n
; i
++ )
686 m_widestWidth
= bestWidth
;
687 m_widestItem
= bestIndex
;
689 m_findWidest
= false;
693 wxSize wxVListBoxComboPopup
::GetAdjustedSize( int minWidth
, int prefHeight
, int maxHeight
)
697 if ( m_strings
.GetCount() )
699 if ( prefHeight
> 0 )
702 if ( height
> maxHeight
)
705 int totalHeight
= GetTotalHeight(); // + 3;
706 if ( height
>= totalHeight
)
708 height
= totalHeight
;
712 // Adjust height to a multiple of the height of the first item
713 // NB: Calculations that take variable height into account
715 int fih
= GetLineHeight(0);
716 int shown
= height
/fih
;
717 height
= shown
* fih
;
725 // Take scrollbar into account in width calculations
726 int widestWidth
= m_widestWidth
+ wxSystemSettings
::GetMetric(wxSYS_VSCROLL_X
);
727 return wxSize(minWidth
> widestWidth ? minWidth
: widestWidth
,
731 //void wxVListBoxComboPopup::Populate( int n, const wxString choices[] )
732 void wxVListBoxComboPopup
::Populate( const wxArrayString
& choices
)
736 int n
= choices
.GetCount();
738 for ( i
=0; i
<n
; i
++ )
740 const wxString
& item
= choices
.Item(i
);
744 m_widths
.SetCount(n
,-1);
745 m_widthsDirty
= true;
748 wxVListBox
::SetItemCount(n
);
750 // Sort the initial choices
751 if ( m_combo
->GetWindowStyle() & wxCB_SORT
)
754 // Find initial selection
755 wxString strValue
= m_combo
->GetValue();
756 if ( strValue
.length() )
757 m_value
= m_strings
.Index(strValue
);
760 // ----------------------------------------------------------------------------
761 // wxOwnerDrawnComboBox
762 // ----------------------------------------------------------------------------
765 BEGIN_EVENT_TABLE(wxOwnerDrawnComboBox
, wxComboCtrl
)
769 IMPLEMENT_DYNAMIC_CLASS2(wxOwnerDrawnComboBox
, wxComboCtrl
, wxControlWithItems
)
771 void wxOwnerDrawnComboBox
::Init()
775 bool wxOwnerDrawnComboBox
::Create(wxWindow
*parent
,
777 const wxString
& value
,
781 const wxValidator
& validator
,
782 const wxString
& name
)
784 return wxComboCtrl
::Create(parent
,id
,value
,pos
,size
,style
,validator
,name
);
787 wxOwnerDrawnComboBox
::wxOwnerDrawnComboBox(wxWindow
*parent
,
789 const wxString
& value
,
792 const wxArrayString
& choices
,
794 const wxValidator
& validator
,
795 const wxString
& name
)
800 Create(parent
,id
,value
,pos
,size
,choices
,style
, validator
, name
);
803 bool wxOwnerDrawnComboBox
::Create(wxWindow
*parent
,
805 const wxString
& value
,
808 const wxArrayString
& choices
,
810 const wxValidator
& validator
,
811 const wxString
& name
)
814 //wxCArrayString chs(choices);
816 //return Create(parent, id, value, pos, size, chs.GetCount(),
817 // chs.GetStrings(), style, validator, name);
818 return Create(parent
, id
, value
, pos
, size
, 0,
819 NULL
, style
, validator
, name
);
822 bool wxOwnerDrawnComboBox
::Create(wxWindow
*parent
,
824 const wxString
& value
,
828 const wxString choices
[],
830 const wxValidator
& validator
,
831 const wxString
& name
)
834 if ( !Create(parent
, id
, value
, pos
, size
, style
,
841 for ( i
=0; i
<n
; i
++ )
842 m_initChs
.Add(choices
[i
]);
847 wxOwnerDrawnComboBox
::~wxOwnerDrawnComboBox()
849 if ( m_popupInterface
)
850 GetVListBoxComboPopup()->ClearClientDatas();
853 void wxOwnerDrawnComboBox
::DoSetPopupControl(wxComboPopup
* popup
)
857 popup
= new wxVListBoxComboPopup();
860 wxComboCtrl
::DoSetPopupControl(popup
);
864 // Add initial choices to the wxVListBox
865 if ( !GetVListBoxComboPopup()->GetCount() )
867 GetVListBoxComboPopup()->Populate(m_initChs
);
872 // ----------------------------------------------------------------------------
873 // wxOwnerDrawnComboBox item manipulation methods
874 // ----------------------------------------------------------------------------
876 void wxOwnerDrawnComboBox
::Clear()
878 EnsurePopupControl();
880 GetVListBoxComboPopup()->Clear();
882 SetValue(wxEmptyString
);
885 void wxOwnerDrawnComboBox
::Delete(unsigned int n
)
887 wxCHECK_RET( IsValid(n
), _T("invalid index in wxOwnerDrawnComboBox::Delete") );
889 if ( GetSelection() == (int) n
)
890 SetValue(wxEmptyString
);
892 GetVListBoxComboPopup()->Delete(n
);
895 unsigned int wxOwnerDrawnComboBox
::GetCount() const
897 if ( !m_popupInterface
)
898 return m_initChs
.GetCount();
900 return GetVListBoxComboPopup()->GetCount();
903 wxString wxOwnerDrawnComboBox
::GetString(unsigned int n
) const
905 wxCHECK_MSG( IsValid(n
), wxEmptyString
, _T("invalid index in wxOwnerDrawnComboBox::GetString") );
907 if ( !m_popupInterface
)
908 return m_initChs
.Item(n
);
910 return GetVListBoxComboPopup()->GetString(n
);
913 void wxOwnerDrawnComboBox
::SetString(unsigned int n
, const wxString
& s
)
915 EnsurePopupControl();
917 wxCHECK_RET( IsValid(n
), _T("invalid index in wxOwnerDrawnComboBox::SetString") );
919 GetVListBoxComboPopup()->SetString(n
,s
);
922 int wxOwnerDrawnComboBox
::FindString(const wxString
& s
, bool bCase
) const
924 if ( !m_popupInterface
)
925 return m_initChs
.Index(s
, bCase
);
927 return GetVListBoxComboPopup()->FindString(s
, bCase
);
930 void wxOwnerDrawnComboBox
::Select(int n
)
932 EnsurePopupControl();
934 wxCHECK_RET( (n
== wxNOT_FOUND
) || IsValid(n
), _T("invalid index in wxOwnerDrawnComboBox::Select") );
936 GetVListBoxComboPopup()->SetSelection(n
);
940 str
= GetVListBoxComboPopup()->GetString(n
);
942 // Refresh text portion in control
944 m_text
->SetValue( str
);
951 int wxOwnerDrawnComboBox
::GetSelection() const
953 if ( !m_popupInterface
)
954 return m_initChs
.Index(m_valueString
);
956 return GetVListBoxComboPopup()->GetSelection();
959 int wxOwnerDrawnComboBox
::DoAppend(const wxString
& item
)
961 EnsurePopupControl();
962 wxASSERT(m_popupInterface
);
964 return GetVListBoxComboPopup()->Append(item
);
967 int wxOwnerDrawnComboBox
::DoInsert(const wxString
& item
, unsigned int pos
)
969 EnsurePopupControl();
971 wxCHECK_MSG(!(GetWindowStyle() & wxCB_SORT
), -1, wxT("can't insert into sorted list"));
972 wxCHECK_MSG(IsValidInsert(pos
), -1, wxT("invalid index"));
974 GetVListBoxComboPopup()->Insert(item
,pos
);
979 void wxOwnerDrawnComboBox
::DoSetItemClientData(unsigned int n
, void* clientData
)
981 EnsurePopupControl();
983 GetVListBoxComboPopup()->SetItemClientData(n
,clientData
,m_clientDataItemsType
);
986 void* wxOwnerDrawnComboBox
::DoGetItemClientData(unsigned int n
) const
988 if ( !m_popupInterface
)
991 return GetVListBoxComboPopup()->GetItemClientData(n
);
994 void wxOwnerDrawnComboBox
::DoSetItemClientObject(unsigned int n
, wxClientData
* clientData
)
996 DoSetItemClientData(n
, (void*) clientData
);
999 wxClientData
* wxOwnerDrawnComboBox
::DoGetItemClientObject(unsigned int n
) const
1001 return (wxClientData
*) DoGetItemClientData(n
);
1004 // ----------------------------------------------------------------------------
1005 // wxOwnerDrawnComboBox item drawing and measuring default implementations
1006 // ----------------------------------------------------------------------------
1008 void wxOwnerDrawnComboBox
::OnDrawItem( wxDC
& dc
,
1013 if ( flags
& wxODCB_PAINTING_CONTROL
)
1015 dc
.DrawText( GetValue(),
1016 rect
.x
+ GetTextIndent(),
1017 (rect
.height
-dc
.GetCharHeight())/2 + rect
.y
);
1021 dc
.DrawText( GetVListBoxComboPopup()->GetString(item
), rect
.x
+ 2, rect
.y
);
1025 wxCoord wxOwnerDrawnComboBox
::OnMeasureItem( size_t WXUNUSED(item
) ) const
1030 wxCoord wxOwnerDrawnComboBox
::OnMeasureItemWidth( size_t WXUNUSED(item
) ) const
1035 void wxOwnerDrawnComboBox
::OnDrawBackground(wxDC
& dc
, const wxRect
& rect
, int item
, int flags
) const
1037 // we need to render selected and current items differently
1038 if ( GetVListBoxComboPopup()->IsCurrent((size_t)item
) )
1040 DrawFocusBackground(dc
,
1042 (flags
&wxODCB_PAINTING_CONTROL?
0:wxCONTROL_ISSUBMENU
) |
1043 wxCONTROL_SELECTED
);
1045 //else: do nothing for the normal items
1048 #endif // wxUSE_ODCOMBOBOX