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 int flags
= wxODCB_PAINTING_CONTROL
;
112 if ( m_combo
->ShouldDrawFocus() )
113 flags
|= wxODCB_PAINTING_SELECTED
;
115 OnDrawBg(dc
, rect
, m_value
, flags
);
119 OnDrawItem(dc
,rect
,m_value
,wxODCB_PAINTING_CONTROL
);
124 wxComboPopup::PaintComboControl(dc
,rect
);
127 void wxVListBoxComboPopup::OnDrawItem(wxDC
& dc
, const wxRect
& rect
, size_t n
) const
129 // TODO: Maybe this code could be moved to wxVListBox::OnPaint?
130 dc
.SetFont(m_useFont
);
132 // Set correct text colour for selected items
133 if ( wxVListBox::GetSelection() == (int) n
)
134 dc
.SetTextForeground( wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT
) );
136 dc
.SetTextForeground( wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT
) );
138 OnDrawItem(dc
,rect
,(int)n
,0);
141 wxCoord
wxVListBoxComboPopup::OnMeasureItem(size_t n
) const
143 wxOwnerDrawnComboBox
* combo
= (wxOwnerDrawnComboBox
*) m_combo
;
145 wxASSERT_MSG( combo
->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox
)),
146 wxT("you must subclass wxVListBoxComboPopup for drawing and measuring methods") );
148 wxCoord h
= combo
->OnMeasureItem(n
);
154 wxCoord
wxVListBoxComboPopup::OnMeasureItemWidth(size_t n
) const
156 wxOwnerDrawnComboBox
* combo
= (wxOwnerDrawnComboBox
*) m_combo
;
158 wxASSERT_MSG( combo
->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox
)),
159 wxT("you must subclass wxVListBoxComboPopup for drawing and measuring methods") );
161 return combo
->OnMeasureItemWidth(n
);
164 void wxVListBoxComboPopup::OnDrawBg( wxDC
& dc
,
169 wxOwnerDrawnComboBox
* combo
= (wxOwnerDrawnComboBox
*) m_combo
;
171 wxASSERT_MSG( combo
->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox
)),
172 wxT("you must subclass wxVListBoxComboPopup for drawing and measuring methods") );
174 if ( IsCurrent((size_t)item
) && !(flags
& wxODCB_PAINTING_CONTROL
) )
175 flags
|= wxODCB_PAINTING_SELECTED
;
177 combo
->OnDrawBackground(dc
,rect
,item
,flags
);
180 void wxVListBoxComboPopup::OnDrawBackground(wxDC
& dc
, const wxRect
& rect
, size_t n
) const
182 OnDrawBg(dc
,rect
,(int)n
,0);
185 // This is called from wxVListBoxComboPopup::OnDrawItem, with text colour and font prepared
186 void wxVListBoxComboPopup::OnDrawItem( wxDC
& dc
, const wxRect
& rect
, int item
, int flags
) const
188 wxOwnerDrawnComboBox
* combo
= (wxOwnerDrawnComboBox
*) m_combo
;
190 wxASSERT_MSG( combo
->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox
)),
191 wxT("you must subclass wxVListBoxComboPopup for drawing and measuring methods") );
193 combo
->OnDrawItem(dc
,rect
,item
,flags
);
196 void wxVListBoxComboPopup::DismissWithEvent()
198 StopPartialCompletion();
200 int selection
= wxVListBox::GetSelection();
205 if ( selection
!= wxNOT_FOUND
)
206 valStr
= m_strings
[selection
];
208 valStr
= wxEmptyString
;
212 if ( valStr
!= m_combo
->GetValue() )
213 m_combo
->SetValueWithEvent(valStr
);
215 SendComboBoxEvent(selection
);
218 void wxVListBoxComboPopup::SendComboBoxEvent( int selection
)
220 wxCommandEvent
evt(wxEVT_COMMAND_COMBOBOX_SELECTED
,m_combo
->GetId());
222 evt
.SetEventObject(m_combo
);
224 evt
.SetInt(selection
);
226 // Set client data, if any
227 if ( selection
>= 0 && (int)m_clientDatas
.GetCount() > selection
)
229 void* clientData
= m_clientDatas
[selection
];
230 if ( m_clientDataItemsType
== wxClientData_Object
)
231 evt
.SetClientObject((wxClientData
*)clientData
);
233 evt
.SetClientData(clientData
);
236 m_combo
->GetEventHandler()->AddPendingEvent(evt
);
239 // returns true if key was consumed
240 bool wxVListBoxComboPopup::HandleKey( int keycode
, bool saturate
, wxChar unicode
)
243 int itemCount
= GetCount();
244 int comboStyle
= m_combo
->GetWindowStyle();
246 // this is the character equivalent of the code
248 if ((keycode
>= WXK_SPACE
) && (keycode
<=255) && (keycode
!= WXK_DELETE
) && wxIsprint(keycode
))
250 keychar
= (wxChar
)keycode
;
257 if ( keycode
== WXK_DOWN
|| keycode
== WXK_RIGHT
)
260 StopPartialCompletion();
262 else if ( keycode
== WXK_UP
|| keycode
== WXK_LEFT
)
265 StopPartialCompletion();
267 else if ( keycode
== WXK_PAGEDOWN
)
270 StopPartialCompletion();
272 else if ( keycode
== WXK_PAGEUP
)
275 StopPartialCompletion();
277 else if ( comboStyle
& wxCB_READONLY
)
279 // Try partial completion
281 // find the new partial completion string
283 if (m_partialCompletionTimer
.IsRunning())
284 m_partialCompletionString
+=wxString(keychar
);
286 #endif // wxUSE_TIMER
287 m_partialCompletionString
=wxString(keychar
);
289 // now search through the values to see if this is found
291 unsigned int length
=m_partialCompletionString
.length();
293 for (i
=0; i
<itemCount
; i
++)
295 wxString item
=GetString(i
);
296 if (( item
.length() >= length
) && (! m_partialCompletionString
.CmpNoCase(item
.Left(length
))))
305 StopPartialCompletion();
307 return true; // to stop the first value being set
313 m_partialCompletionTimer
.Start(wxODCB_PARTIAL_COMPLETION_TIME
, true);
314 #endif // wxUSE_TIMER
322 if ( value
>= itemCount
)
323 value
= itemCount
- 1;
324 else if ( value
< 0 )
329 if ( value
>= itemCount
)
331 else if ( value
< 0 )
335 if ( value
== m_value
)
336 // Even if value was same, don't skip the event
337 // (good for consistency)
343 m_combo
->SetValue(m_strings
[value
]);
345 SendComboBoxEvent(m_value
);
350 // stop partial completion
351 void wxVListBoxComboPopup::StopPartialCompletion()
353 m_partialCompletionString
= wxEmptyString
;
355 m_partialCompletionTimer
.Stop();
356 #endif // wxUSE_TIMER
359 void wxVListBoxComboPopup::OnComboDoubleClick()
361 // Cycle on dclick (disable saturation to allow true cycling).
362 if ( !::wxGetKeyState(WXK_SHIFT
) )
363 HandleKey(WXK_DOWN
,false);
365 HandleKey(WXK_UP
,false);
368 void wxVListBoxComboPopup::OnComboKeyEvent( wxKeyEvent
& event
)
370 // Saturated key movement on
371 if ( !HandleKey(event
.GetKeyCode(),true,
373 event
.GetUnicodeKey()
381 void wxVListBoxComboPopup::OnPopup()
383 // *must* set value after size is set (this is because of a vlbox bug)
384 wxVListBox::SetSelection(m_value
);
387 void wxVListBoxComboPopup::OnMouseMove(wxMouseEvent
& event
)
391 // Move selection to cursor if it is inside the popup
393 int y
= event
.GetPosition().y
;
394 int fromBottom
= GetClientSize().y
- y
;
396 // Since in any case we need to find out if the last item is only
397 // partially visible, we might just as well replicate the HitTest
399 const size_t lineMax
= GetVisibleEnd();
400 for ( size_t line
= GetVisibleBegin(); line
< lineMax
; line
++ )
402 y
-= OnGetRowHeight(line
);
405 // Only change selection if item is fully visible
406 if ( (y
+ fromBottom
) >= 0 )
408 wxVListBox::SetSelection((int)line
);
415 void wxVListBoxComboPopup::OnLeftClick(wxMouseEvent
& WXUNUSED(event
))
420 void wxVListBoxComboPopup::OnKey(wxKeyEvent
& event
)
422 // Hide popup if certain key or key combination was pressed
423 if ( m_combo
->IsKeyPopupToggle(event
) )
425 StopPartialCompletion();
428 else if ( event
.AltDown() )
430 // On both wxGTK and wxMSW, pressing Alt down seems to
431 // completely freeze things in popup (ie. arrow keys and
432 // enter won't work).
435 // Select item if ENTER is pressed
436 else if ( event
.GetKeyCode() == WXK_RETURN
|| event
.GetKeyCode() == WXK_NUMPAD_ENTER
)
442 int comboStyle
= m_combo
->GetWindowStyle();
443 int keycode
= event
.GetKeyCode();
444 // Process partial completion key codes here, but not the arrow keys as the base class will do that for us
445 if ((comboStyle
& wxCB_READONLY
) &&
446 (keycode
>= WXK_SPACE
) && (keycode
<=255) && (keycode
!= WXK_DELETE
) && wxIsprint(keycode
))
448 OnComboKeyEvent(event
);
449 SetSelection(m_value
); // ensure the highlight bar moves
456 void wxVListBoxComboPopup::Insert( const wxString
& item
, int pos
)
458 // Need to change selection?
460 if ( !(m_combo
->GetWindowStyle() & wxCB_READONLY
) &&
461 m_combo
->GetValue() == item
)
466 m_strings
.Insert(item
,pos
);
467 m_widths
.Insert(-1,pos
);
468 m_widthsDirty
= true;
471 wxVListBox::SetItemCount( wxVListBox::GetItemCount()+1 );
474 int wxVListBoxComboPopup::Append(const wxString
& item
)
476 int pos
= (int)m_strings
.GetCount();
478 if ( m_combo
->GetWindowStyle() & wxCB_SORT
)
481 // TODO: Could be optimized with binary search
482 wxArrayString strings
= m_strings
;
485 for ( i
=0; i
<strings
.GetCount(); i
++ )
487 if ( item
.Cmp(strings
.Item(i
)) < 0 )
500 void wxVListBoxComboPopup::Clear()
512 m_value
= wxNOT_FOUND
;
515 wxVListBox::SetItemCount(0);
518 void wxVListBoxComboPopup::ClearClientDatas()
520 if ( m_clientDataItemsType
== wxClientData_Object
)
523 for ( i
=0; i
<m_clientDatas
.GetCount(); i
++ )
524 delete (wxClientData
*) m_clientDatas
[i
];
527 m_clientDatas
.Empty();
530 void wxVListBoxComboPopup::SetItemClientData( unsigned int n
,
532 wxClientDataType clientDataItemsType
)
534 // It should be sufficient to update this variable only here
535 m_clientDataItemsType
= clientDataItemsType
;
537 m_clientDatas
.SetCount(n
+1,NULL
);
538 m_clientDatas
[n
] = clientData
;
543 void* wxVListBoxComboPopup::GetItemClientData(unsigned int n
) const
545 if ( m_clientDatas
.GetCount() > n
)
546 return m_clientDatas
[n
];
551 void wxVListBoxComboPopup::Delete( unsigned int item
)
553 // Remove client data, if set
554 if ( m_clientDatas
.GetCount() )
556 if ( m_clientDataItemsType
== wxClientData_Object
)
557 delete (wxClientData
*) m_clientDatas
[item
];
559 m_clientDatas
.RemoveAt(item
);
562 m_strings
.RemoveAt(item
);
563 m_widths
.RemoveAt(item
);
565 if ( (int)item
== m_widestItem
)
568 int sel
= GetSelection();
571 wxVListBox::SetItemCount( wxVListBox::GetItemCount()-1 );
574 if ( (int)item
< sel
)
576 else if ( (int)item
== sel
)
577 SetSelection(wxNOT_FOUND
);
580 int wxVListBoxComboPopup::FindString(const wxString
& s
, bool bCase
) const
582 return m_strings
.Index(s
, bCase
);
585 unsigned int wxVListBoxComboPopup::GetCount() const
587 return m_strings
.GetCount();
590 wxString
wxVListBoxComboPopup::GetString( int item
) const
592 return m_strings
[item
];
595 void wxVListBoxComboPopup::SetString( int item
, const wxString
& str
)
597 m_strings
[item
] = str
;
598 ItemWidthChanged(item
);
601 wxString
wxVListBoxComboPopup::GetStringValue() const
604 return m_strings
[m_value
];
605 return wxEmptyString
;
608 void wxVListBoxComboPopup::SetSelection( int item
)
610 wxCHECK_RET( item
== wxNOT_FOUND
|| ((unsigned int)item
< GetCount()),
611 wxT("invalid index in wxVListBoxComboPopup::SetSelection") );
616 wxVListBox::SetSelection(item
);
619 int wxVListBoxComboPopup::GetSelection() const
624 void wxVListBoxComboPopup::SetStringValue( const wxString
& value
)
626 int index
= m_strings
.Index(value
);
630 if ( index
>= -1 && index
< (int)wxVListBox::GetItemCount() )
631 wxVListBox::SetSelection(index
);
634 void wxVListBoxComboPopup::CalcWidths()
636 bool doFindWidest
= m_findWidest
;
638 // Measure items with dirty width.
642 unsigned int n
= m_widths
.GetCount();
643 int dirtyHandled
= 0;
644 wxArrayInt
& widths
= m_widths
;
646 // I think using wxDC::GetTextExtent is faster than
647 // wxWindow::GetTextExtent (assuming same dc is used
648 // for all calls, as we do here).
649 wxClientDC
dc(m_combo
);
650 dc
.SetFont(m_useFont
);
652 for ( i
=0; i
<n
; i
++ )
656 wxCoord x
= OnMeasureItemWidth(i
);
660 const wxString
& text
= m_strings
[i
];
662 // To make sure performance won't suck in extreme scenarios,
663 // we'll estimate length after some arbitrary number of items
664 // have been checked precily.
665 if ( dirtyHandled
< 1024 )
668 dc
.GetTextExtent(text
, &x
, &y
, 0, 0);
673 x
= text
.length() * (dc
.GetCharWidth()+1);
679 if ( x
>= m_widestWidth
)
682 m_widestItem
= (int)i
;
684 else if ( (int)i
== m_widestItem
)
686 // Width of previously widest item has been decreased, so
687 // we'll have to check all to find current widest item.
695 m_widthsDirty
= false;
701 unsigned int n
= m_widths
.GetCount();
706 for ( i
=0; i
<n
; i
++ )
716 m_widestWidth
= bestWidth
;
717 m_widestItem
= bestIndex
;
719 m_findWidest
= false;
723 wxSize
wxVListBoxComboPopup::GetAdjustedSize( int minWidth
, int prefHeight
, int maxHeight
)
727 maxHeight
-= 2; // Must take borders into account
729 if ( m_strings
.GetCount() )
731 if ( prefHeight
> 0 )
734 if ( height
> maxHeight
)
737 int totalHeight
= GetTotalHeight(); // + 3;
738 if ( height
>= totalHeight
)
740 height
= totalHeight
;
744 // Adjust height to a multiple of the height of the first item
745 // NB: Calculations that take variable height into account
747 int fih
= GetLineHeight(0);
748 height
-= height
% fih
;
756 // Take scrollbar into account in width calculations
757 int widestWidth
= m_widestWidth
+ wxSystemSettings::GetMetric(wxSYS_VSCROLL_X
);
758 return wxSize(minWidth
> widestWidth
? minWidth
: widestWidth
,
762 //void wxVListBoxComboPopup::Populate( int n, const wxString choices[] )
763 void wxVListBoxComboPopup::Populate( const wxArrayString
& choices
)
767 int n
= choices
.GetCount();
769 for ( i
=0; i
<n
; i
++ )
771 const wxString
& item
= choices
.Item(i
);
775 m_widths
.SetCount(n
,-1);
776 m_widthsDirty
= true;
779 wxVListBox::SetItemCount(n
);
781 // Sort the initial choices
782 if ( m_combo
->GetWindowStyle() & wxCB_SORT
)
785 // Find initial selection
786 wxString strValue
= m_combo
->GetValue();
787 if ( strValue
.length() )
788 m_value
= m_strings
.Index(strValue
);
791 // ----------------------------------------------------------------------------
792 // wxOwnerDrawnComboBox
793 // ----------------------------------------------------------------------------
796 BEGIN_EVENT_TABLE(wxOwnerDrawnComboBox
, wxComboCtrl
)
800 IMPLEMENT_DYNAMIC_CLASS2(wxOwnerDrawnComboBox
, wxComboCtrl
, wxControlWithItems
)
802 void wxOwnerDrawnComboBox::Init()
806 bool wxOwnerDrawnComboBox::Create(wxWindow
*parent
,
808 const wxString
& value
,
812 const wxValidator
& validator
,
813 const wxString
& name
)
815 return wxComboCtrl::Create(parent
,id
,value
,pos
,size
,style
,validator
,name
);
818 wxOwnerDrawnComboBox::wxOwnerDrawnComboBox(wxWindow
*parent
,
820 const wxString
& value
,
823 const wxArrayString
& choices
,
825 const wxValidator
& validator
,
826 const wxString
& name
)
831 Create(parent
,id
,value
,pos
,size
,choices
,style
, validator
, name
);
834 bool wxOwnerDrawnComboBox::Create(wxWindow
*parent
,
836 const wxString
& value
,
839 const wxArrayString
& choices
,
841 const wxValidator
& validator
,
842 const wxString
& name
)
845 //wxCArrayString chs(choices);
847 //return Create(parent, id, value, pos, size, chs.GetCount(),
848 // chs.GetStrings(), style, validator, name);
849 return Create(parent
, id
, value
, pos
, size
, 0,
850 NULL
, style
, validator
, name
);
853 bool wxOwnerDrawnComboBox::Create(wxWindow
*parent
,
855 const wxString
& value
,
859 const wxString choices
[],
861 const wxValidator
& validator
,
862 const wxString
& name
)
865 if ( !Create(parent
, id
, value
, pos
, size
, style
,
872 for ( i
=0; i
<n
; i
++ )
873 m_initChs
.Add(choices
[i
]);
878 wxOwnerDrawnComboBox::~wxOwnerDrawnComboBox()
880 if ( m_popupInterface
)
881 GetVListBoxComboPopup()->ClearClientDatas();
884 void wxOwnerDrawnComboBox::DoSetPopupControl(wxComboPopup
* popup
)
888 popup
= new wxVListBoxComboPopup();
891 wxComboCtrl::DoSetPopupControl(popup
);
895 // Add initial choices to the wxVListBox
896 if ( !GetVListBoxComboPopup()->GetCount() )
898 GetVListBoxComboPopup()->Populate(m_initChs
);
903 // ----------------------------------------------------------------------------
904 // wxOwnerDrawnComboBox item manipulation methods
905 // ----------------------------------------------------------------------------
907 void wxOwnerDrawnComboBox::Clear()
909 EnsurePopupControl();
911 GetVListBoxComboPopup()->Clear();
913 SetValue(wxEmptyString
);
916 void wxOwnerDrawnComboBox::Delete(unsigned int n
)
918 wxCHECK_RET( IsValid(n
), _T("invalid index in wxOwnerDrawnComboBox::Delete") );
920 if ( GetSelection() == (int) n
)
921 SetValue(wxEmptyString
);
923 GetVListBoxComboPopup()->Delete(n
);
926 unsigned int wxOwnerDrawnComboBox::GetCount() const
928 if ( !m_popupInterface
)
929 return m_initChs
.GetCount();
931 return GetVListBoxComboPopup()->GetCount();
934 wxString
wxOwnerDrawnComboBox::GetString(unsigned int n
) const
936 wxCHECK_MSG( IsValid(n
), wxEmptyString
, _T("invalid index in wxOwnerDrawnComboBox::GetString") );
938 if ( !m_popupInterface
)
939 return m_initChs
.Item(n
);
941 return GetVListBoxComboPopup()->GetString(n
);
944 void wxOwnerDrawnComboBox::SetString(unsigned int n
, const wxString
& s
)
946 EnsurePopupControl();
948 wxCHECK_RET( IsValid(n
), _T("invalid index in wxOwnerDrawnComboBox::SetString") );
950 GetVListBoxComboPopup()->SetString(n
,s
);
953 int wxOwnerDrawnComboBox::FindString(const wxString
& s
, bool bCase
) const
955 if ( !m_popupInterface
)
956 return m_initChs
.Index(s
, bCase
);
958 return GetVListBoxComboPopup()->FindString(s
, bCase
);
961 void wxOwnerDrawnComboBox::Select(int n
)
963 EnsurePopupControl();
965 wxCHECK_RET( (n
== wxNOT_FOUND
) || IsValid(n
), _T("invalid index in wxOwnerDrawnComboBox::Select") );
967 GetVListBoxComboPopup()->SetSelection(n
);
971 str
= GetVListBoxComboPopup()->GetString(n
);
973 // Refresh text portion in control
975 m_text
->SetValue( str
);
982 int wxOwnerDrawnComboBox::GetSelection() const
984 if ( !m_popupInterface
)
985 return m_initChs
.Index(m_valueString
);
987 return GetVListBoxComboPopup()->GetSelection();
990 int wxOwnerDrawnComboBox::DoAppend(const wxString
& item
)
992 EnsurePopupControl();
993 wxASSERT(m_popupInterface
);
995 return GetVListBoxComboPopup()->Append(item
);
998 int wxOwnerDrawnComboBox::DoInsert(const wxString
& item
, unsigned int pos
)
1000 EnsurePopupControl();
1002 wxCHECK_MSG(!(GetWindowStyle() & wxCB_SORT
), -1, wxT("can't insert into sorted list"));
1003 wxCHECK_MSG(IsValidInsert(pos
), -1, wxT("invalid index"));
1005 GetVListBoxComboPopup()->Insert(item
,pos
);
1010 void wxOwnerDrawnComboBox::DoSetItemClientData(unsigned int n
, void* clientData
)
1012 EnsurePopupControl();
1014 GetVListBoxComboPopup()->SetItemClientData(n
,clientData
,m_clientDataItemsType
);
1017 void* wxOwnerDrawnComboBox::DoGetItemClientData(unsigned int n
) const
1019 if ( !m_popupInterface
)
1022 return GetVListBoxComboPopup()->GetItemClientData(n
);
1025 void wxOwnerDrawnComboBox::DoSetItemClientObject(unsigned int n
, wxClientData
* clientData
)
1027 DoSetItemClientData(n
, (void*) clientData
);
1030 wxClientData
* wxOwnerDrawnComboBox::DoGetItemClientObject(unsigned int n
) const
1032 return (wxClientData
*) DoGetItemClientData(n
);
1035 // ----------------------------------------------------------------------------
1036 // wxOwnerDrawnComboBox item drawing and measuring default implementations
1037 // ----------------------------------------------------------------------------
1039 void wxOwnerDrawnComboBox::OnDrawItem( wxDC
& dc
,
1044 if ( flags
& wxODCB_PAINTING_CONTROL
)
1046 dc
.DrawText( GetValue(),
1047 rect
.x
+ GetTextIndent(),
1048 (rect
.height
-dc
.GetCharHeight())/2 + rect
.y
);
1052 dc
.DrawText( GetVListBoxComboPopup()->GetString(item
), rect
.x
+ 2, rect
.y
);
1056 wxCoord
wxOwnerDrawnComboBox::OnMeasureItem( size_t WXUNUSED(item
) ) const
1061 wxCoord
wxOwnerDrawnComboBox::OnMeasureItemWidth( size_t WXUNUSED(item
) ) const
1066 void wxOwnerDrawnComboBox::OnDrawBackground(wxDC
& dc
,
1071 // We need only to explicitly draw background for items
1072 // that should have selected background. Also, call PrepareBackground
1073 // always when painting the control so that clipping is done properly.
1075 if ( (flags
& wxODCB_PAINTING_SELECTED
) ||
1076 ((flags
& wxODCB_PAINTING_CONTROL
) && HasFlag(wxCB_READONLY
)) )
1078 int bgFlags
= wxCONTROL_SELECTED
;
1080 if ( !(flags
& wxODCB_PAINTING_CONTROL
) )
1081 bgFlags
|= wxCONTROL_ISSUBMENU
;
1083 PrepareBackground(dc
, rect
, bgFlags
);
1087 #endif // wxUSE_ODCOMBOBOX