/[pcsx2_0.9.7]/trunk/3rdparty/wxWidgets/src/generic/odcombo.cpp
ViewVC logotype

Annotation of /trunk/3rdparty/wxWidgets/src/generic/odcombo.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 31 - (hide annotations) (download)
Tue Sep 7 03:24:11 2010 UTC (10 years, 2 months ago) by william
File size: 29945 byte(s)
committing r3113 initial commit again...
1 william 31 /////////////////////////////////////////////////////////////////////////////
2     // Name: src/generic/odcombo.cpp
3     // Purpose: wxOwnerDrawnComboBox, wxVListBoxComboPopup
4     // Author: Jaakko Salli
5     // Modified by:
6     // Created: Apr-30-2006
7     // RCS-ID: $Id: odcombo.cpp 58203 2009-01-18 20:05:07Z JMS $
8     // Copyright: (c) 2005 Jaakko Salli
9     // Licence: wxWindows licence
10     /////////////////////////////////////////////////////////////////////////////
11    
12     // ============================================================================
13     // declarations
14     // ============================================================================
15    
16     // ----------------------------------------------------------------------------
17     // headers
18     // ----------------------------------------------------------------------------
19    
20     #include "wx/wxprec.h"
21    
22     #ifdef __BORLANDC__
23     #pragma hdrstop
24     #endif
25    
26     #if wxUSE_ODCOMBOBOX
27    
28     #include "wx/odcombo.h"
29    
30     #ifndef WX_PRECOMP
31     #include "wx/log.h"
32     #include "wx/combobox.h"
33     #include "wx/dcclient.h"
34     #include "wx/settings.h"
35     #include "wx/dialog.h"
36     #endif
37    
38     #include "wx/combo.h"
39    
40     // ============================================================================
41     // implementation
42     // ============================================================================
43    
44     // time in milliseconds before partial completion buffer drops
45     #define wxODCB_PARTIAL_COMPLETION_TIME 1000
46    
47     // ----------------------------------------------------------------------------
48     // wxVListBoxComboPopup is a wxVListBox customized to act as a popup control
49     //
50     // ----------------------------------------------------------------------------
51    
52    
53     BEGIN_EVENT_TABLE(wxVListBoxComboPopup, wxVListBox)
54     EVT_MOTION(wxVListBoxComboPopup::OnMouseMove)
55     EVT_KEY_DOWN(wxVListBoxComboPopup::OnKey)
56     EVT_LEFT_UP(wxVListBoxComboPopup::OnLeftClick)
57     END_EVENT_TABLE()
58    
59    
60     void wxVListBoxComboPopup::Init()
61     {
62     m_widestWidth = 0;
63     m_widestItem = -1;
64     m_widthsDirty = false;
65     m_findWidest = false;
66     m_itemHeight = 0;
67     m_value = -1;
68     m_itemHover = -1;
69     m_clientDataItemsType = wxClientData_None;
70     m_partialCompletionString = wxEmptyString;
71     }
72    
73     bool wxVListBoxComboPopup::Create(wxWindow* parent)
74     {
75     if ( !wxVListBox::Create(parent,
76     wxID_ANY,
77     wxDefaultPosition,
78     wxDefaultSize,
79     wxBORDER_SIMPLE | wxLB_INT_HEIGHT | wxWANTS_CHARS) )
80     return false;
81    
82     m_useFont = m_combo->GetFont();
83    
84     wxVListBox::SetItemCount(m_strings.GetCount());
85    
86     // TODO: Move this to SetFont
87     m_itemHeight = GetCharHeight() + 0;
88    
89     return true;
90     }
91    
92     wxVListBoxComboPopup::~wxVListBoxComboPopup()
93     {
94     Clear();
95     }
96    
97     bool wxVListBoxComboPopup::LazyCreate()
98     {
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).
102     return true;
103     }
104    
105     // paint the control itself
106     void wxVListBoxComboPopup::PaintComboControl( wxDC& dc, const wxRect& rect )
107     {
108     if ( !(m_combo->GetWindowStyle() & wxODCB_STD_CONTROL_PAINT) )
109     {
110     int flags = wxODCB_PAINTING_CONTROL;
111    
112     if ( m_combo->ShouldDrawFocus() )
113     flags |= wxODCB_PAINTING_SELECTED;
114    
115     OnDrawBg(dc, rect, m_value, flags);
116    
117     if ( m_value >= 0 )
118     {
119     OnDrawItem(dc,rect,m_value,flags);
120     return;
121     }
122     }
123    
124     wxComboPopup::PaintComboControl(dc,rect);
125     }
126    
127     void wxVListBoxComboPopup::OnDrawItem(wxDC& dc, const wxRect& rect, size_t n) const
128     {
129     // TODO: Maybe this code could be moved to wxVListBox::OnPaint?
130     dc.SetFont(m_useFont);
131    
132     int flags = 0;
133    
134     // Set correct text colour for selected items
135     if ( wxVListBox::GetSelection() == (int) n )
136     {
137     dc.SetTextForeground( wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT) );
138     flags |= wxODCB_PAINTING_SELECTED;
139     }
140     else
141     {
142     dc.SetTextForeground( wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT) );
143     }
144    
145     OnDrawItem(dc,rect,(int)n,flags);
146     }
147    
148     wxCoord wxVListBoxComboPopup::OnMeasureItem(size_t n) const
149     {
150     wxOwnerDrawnComboBox* combo = (wxOwnerDrawnComboBox*) m_combo;
151    
152     wxASSERT_MSG( combo->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox)),
153     wxT("you must subclass wxVListBoxComboPopup for drawing and measuring methods") );
154    
155     wxCoord h = combo->OnMeasureItem(n);
156     if ( h < 0 )
157     h = m_itemHeight;
158     return h;
159     }
160    
161     wxCoord wxVListBoxComboPopup::OnMeasureItemWidth(size_t n) const
162     {
163     wxOwnerDrawnComboBox* combo = (wxOwnerDrawnComboBox*) m_combo;
164    
165     wxASSERT_MSG( combo->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox)),
166     wxT("you must subclass wxVListBoxComboPopup for drawing and measuring methods") );
167    
168     return combo->OnMeasureItemWidth(n);
169     }
170    
171     void wxVListBoxComboPopup::OnDrawBg( wxDC& dc,
172     const wxRect& rect,
173     int item,
174     int flags ) const
175     {
176     wxOwnerDrawnComboBox* combo = (wxOwnerDrawnComboBox*) m_combo;
177    
178     wxASSERT_MSG( combo->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox)),
179     wxT("you must subclass wxVListBoxComboPopup for drawing and measuring methods") );
180    
181     if ( IsCurrent((size_t)item) && !(flags & wxODCB_PAINTING_CONTROL) )
182     flags |= wxODCB_PAINTING_SELECTED;
183    
184     combo->OnDrawBackground(dc,rect,item,flags);
185     }
186    
187     void wxVListBoxComboPopup::OnDrawBackground(wxDC& dc, const wxRect& rect, size_t n) const
188     {
189     OnDrawBg(dc,rect,(int)n,0);
190     }
191    
192     // This is called from wxVListBoxComboPopup::OnDrawItem, with text colour and font prepared
193     void wxVListBoxComboPopup::OnDrawItem( wxDC& dc, const wxRect& rect, int item, int flags ) const
194     {
195     wxOwnerDrawnComboBox* combo = (wxOwnerDrawnComboBox*) m_combo;
196    
197     wxASSERT_MSG( combo->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox)),
198     wxT("you must subclass wxVListBoxComboPopup for drawing and measuring methods") );
199    
200     combo->OnDrawItem(dc,rect,item,flags);
201     }
202    
203     void wxVListBoxComboPopup::DismissWithEvent()
204     {
205     StopPartialCompletion();
206    
207     int selection = wxVListBox::GetSelection();
208    
209     Dismiss();
210    
211     wxString valStr;
212     if ( selection != wxNOT_FOUND )
213     valStr = m_strings[selection];
214     else
215     valStr = wxEmptyString;
216    
217     m_value = selection;
218    
219     if ( valStr != m_combo->GetValue() )
220     m_combo->SetValueWithEvent(valStr);
221    
222     SendComboBoxEvent(selection);
223     }
224    
225     void wxVListBoxComboPopup::SendComboBoxEvent( int selection )
226     {
227     wxCommandEvent evt(wxEVT_COMMAND_COMBOBOX_SELECTED,m_combo->GetId());
228    
229     evt.SetEventObject(m_combo);
230    
231     evt.SetInt(selection);
232    
233     // Set client data, if any
234     if ( selection >= 0 && (int)m_clientDatas.GetCount() > selection )
235     {
236     void* clientData = m_clientDatas[selection];
237     if ( m_clientDataItemsType == wxClientData_Object )
238     evt.SetClientObject((wxClientData*)clientData);
239     else
240     evt.SetClientData(clientData);
241     }
242    
243     m_combo->GetEventHandler()->AddPendingEvent(evt);
244     }
245    
246     // returns true if key was consumed
247     bool wxVListBoxComboPopup::HandleKey( int keycode, bool saturate, wxChar unicode )
248     {
249     const int itemCount = GetCount();
250    
251     // keys do nothing in the empty control and returning immediately avoids
252     // using invalid indices below
253     if ( !itemCount )
254     return false;
255    
256     int value = m_value;
257     int comboStyle = m_combo->GetWindowStyle();
258    
259     // this is the character equivalent of the code
260     wxChar keychar = 0;
261     if ( keycode < WXK_START )
262     {
263     #if wxUSE_UNICODE
264     if ( unicode > 0 )
265     {
266     if ( wxIsprint(unicode) )
267     keychar = unicode;
268     }
269     else
270     #else
271     wxUnusedVar(unicode);
272     #endif
273     if ( wxIsprint(keycode) )
274     {
275     keychar = (wxChar) keycode;
276     }
277     }
278    
279     if ( keycode == WXK_DOWN || keycode == WXK_RIGHT )
280     {
281     value++;
282     StopPartialCompletion();
283     }
284     else if ( keycode == WXK_UP || keycode == WXK_LEFT )
285     {
286     value--;
287     StopPartialCompletion();
288     }
289     else if ( keycode == WXK_PAGEDOWN )
290     {
291     value+=10;
292     StopPartialCompletion();
293     }
294     else if ( keycode == WXK_PAGEUP )
295     {
296     value-=10;
297     StopPartialCompletion();
298     }
299     else if ( keychar && (comboStyle & wxCB_READONLY) )
300     {
301     // Try partial completion
302    
303     // find the new partial completion string
304     #if wxUSE_TIMER
305     if (m_partialCompletionTimer.IsRunning())
306     m_partialCompletionString+=wxString(keychar);
307     else
308     #endif // wxUSE_TIMER
309     m_partialCompletionString=wxString(keychar);
310    
311     // now search through the values to see if this is found
312     int found = -1;
313     unsigned int length=m_partialCompletionString.length();
314     int i;
315     for (i=0; i<itemCount; i++)
316     {
317     wxString item=GetString(i);
318     if (( item.length() >= length) && (! m_partialCompletionString.CmpNoCase(item.Left(length))))
319     {
320     found=i;
321     break;
322     }
323     }
324    
325     if (found<0)
326     {
327     StopPartialCompletion();
328     ::wxBell();
329     return true; // to stop the first value being set
330     }
331     else
332     {
333     value=i;
334     #if wxUSE_TIMER
335     m_partialCompletionTimer.Start(wxODCB_PARTIAL_COMPLETION_TIME, true);
336     #endif // wxUSE_TIMER
337     }
338     }
339     else
340     return false;
341    
342     if ( saturate )
343     {
344     if ( value >= itemCount )
345     value = itemCount - 1;
346     else if ( value < 0 )
347     value = 0;
348     }
349     else
350     {
351     if ( value >= itemCount )
352     value -= itemCount;
353     else if ( value < 0 )
354     value += itemCount;
355     }
356    
357     if ( value == m_value )
358     // Even if value was same, don't skip the event
359     // (good for consistency)
360     return true;
361    
362     m_value = value;
363    
364     if ( value >= 0 )
365     m_combo->SetValue(m_strings[value]);
366    
367     SendComboBoxEvent(m_value);
368    
369     return true;
370     }
371    
372     // stop partial completion
373     void wxVListBoxComboPopup::StopPartialCompletion()
374     {
375     m_partialCompletionString = wxEmptyString;
376     #if wxUSE_TIMER
377     m_partialCompletionTimer.Stop();
378     #endif // wxUSE_TIMER
379     }
380    
381     void wxVListBoxComboPopup::OnComboDoubleClick()
382     {
383     // Cycle on dclick (disable saturation to allow true cycling).
384     if ( !::wxGetKeyState(WXK_SHIFT) )
385     HandleKey(WXK_DOWN,false);
386     else
387     HandleKey(WXK_UP,false);
388     }
389    
390     void wxVListBoxComboPopup::OnComboKeyEvent( wxKeyEvent& event )
391     {
392     // Saturated key movement on
393     if ( !HandleKey(event.GetKeyCode(),true,
394     #if wxUSE_UNICODE
395     event.GetUnicodeKey()
396     #else
397     0
398     #endif
399     ) )
400     event.Skip();
401     }
402    
403     void wxVListBoxComboPopup::OnPopup()
404     {
405     // *must* set value after size is set (this is because of a vlbox bug)
406     wxVListBox::SetSelection(m_value);
407     }
408    
409     void wxVListBoxComboPopup::OnMouseMove(wxMouseEvent& event)
410     {
411     event.Skip();
412    
413     // Move selection to cursor if it is inside the popup
414    
415     int y = event.GetPosition().y;
416     int fromBottom = GetClientSize().y - y;
417    
418     // Since in any case we need to find out if the last item is only
419     // partially visible, we might just as well replicate the HitTest
420     // loop here.
421     const size_t lineMax = GetVisibleEnd();
422     for ( size_t line = GetVisibleBegin(); line < lineMax; line++ )
423     {
424     y -= OnGetLineHeight(line);
425     if ( y < 0 )
426     {
427     // Only change selection if item is fully visible
428     if ( (y + fromBottom) >= 0 )
429     {
430     wxVListBox::SetSelection((int)line);
431     return;
432     }
433     }
434     }
435     }
436    
437     void wxVListBoxComboPopup::OnLeftClick(wxMouseEvent& WXUNUSED(event))
438     {
439     DismissWithEvent();
440     }
441    
442     void wxVListBoxComboPopup::OnKey(wxKeyEvent& event)
443     {
444     // Hide popup if certain key or key combination was pressed
445     if ( m_combo->IsKeyPopupToggle(event) )
446     {
447     StopPartialCompletion();
448     Dismiss();
449     }
450     else if ( event.AltDown() )
451     {
452     // On both wxGTK and wxMSW, pressing Alt down seems to
453     // completely freeze things in popup (ie. arrow keys and
454     // enter won't work).
455     return;
456     }
457     // Select item if ENTER is pressed
458     else if ( event.GetKeyCode() == WXK_RETURN || event.GetKeyCode() == WXK_NUMPAD_ENTER )
459     {
460     DismissWithEvent();
461     }
462     else
463     {
464     int comboStyle = m_combo->GetWindowStyle();
465     int keycode = event.GetKeyCode();
466     // Process partial completion key codes here, but not the arrow keys as the base class will do that for us
467     if ((comboStyle & wxCB_READONLY) &&
468     (keycode >= WXK_SPACE) && (keycode <=255) && (keycode != WXK_DELETE) && wxIsprint(keycode))
469     {
470     OnComboKeyEvent(event);
471     SetSelection(m_value); // ensure the highlight bar moves
472     }
473     else
474     event.Skip();
475     }
476     }
477    
478     void wxVListBoxComboPopup::Insert( const wxString& item, int pos )
479     {
480     // Need to change selection?
481     wxString strValue;
482     if ( !(m_combo->GetWindowStyle() & wxCB_READONLY) &&
483     m_combo->GetValue() == item )
484     {
485     m_value = pos;
486     }
487    
488     m_strings.Insert(item,pos);
489     m_widths.Insert(-1,pos);
490     m_widthsDirty = true;
491    
492     if ( IsCreated() )
493     wxVListBox::SetItemCount( wxVListBox::GetItemCount()+1 );
494     }
495    
496     int wxVListBoxComboPopup::Append(const wxString& item)
497     {
498     int pos = (int)m_strings.GetCount();
499    
500     if ( m_combo->GetWindowStyle() & wxCB_SORT )
501     {
502     // Find position
503     // TODO: Could be optimized with binary search
504     wxArrayString strings = m_strings;
505     unsigned int i;
506    
507     for ( i=0; i<strings.GetCount(); i++ )
508     {
509     if ( item.Cmp(strings.Item(i)) < 0 )
510     {
511     pos = (int)i;
512     break;
513     }
514     }
515     }
516    
517     Insert(item,pos);
518    
519     return pos;
520     }
521    
522     void wxVListBoxComboPopup::Clear()
523     {
524     wxASSERT(m_combo);
525    
526     m_strings.Empty();
527     m_widths.Empty();
528    
529     m_widestWidth = 0;
530     m_widestItem = -1;
531    
532     ClearClientDatas();
533    
534     m_value = wxNOT_FOUND;
535    
536     if ( IsCreated() )
537     wxVListBox::SetItemCount(0);
538     }
539    
540     void wxVListBoxComboPopup::ClearClientDatas()
541     {
542     if ( m_clientDataItemsType == wxClientData_Object )
543     {
544     size_t i;
545     for ( i=0; i<m_clientDatas.GetCount(); i++ )
546     delete (wxClientData*) m_clientDatas[i];
547     }
548    
549     m_clientDatas.Empty();
550     }
551    
552     void wxVListBoxComboPopup::SetItemClientData( unsigned int n,
553     void* clientData,
554     wxClientDataType clientDataItemsType )
555     {
556     // It should be sufficient to update this variable only here
557     m_clientDataItemsType = clientDataItemsType;
558    
559     m_clientDatas.SetCount(n+1,NULL);
560     m_clientDatas[n] = clientData;
561    
562     ItemWidthChanged(n);
563     }
564    
565     void* wxVListBoxComboPopup::GetItemClientData(unsigned int n) const
566     {
567     if ( m_clientDatas.GetCount() > n )
568     return m_clientDatas[n];
569    
570     return NULL;
571     }
572    
573     void wxVListBoxComboPopup::Delete( unsigned int item )
574     {
575     // Remove client data, if set
576     if ( m_clientDatas.GetCount() )
577     {
578     if ( m_clientDataItemsType == wxClientData_Object )
579     delete (wxClientData*) m_clientDatas[item];
580    
581     m_clientDatas.RemoveAt(item);
582     }
583    
584     m_strings.RemoveAt(item);
585     m_widths.RemoveAt(item);
586    
587     if ( (int)item == m_widestItem )
588     m_findWidest = true;
589    
590     int sel = GetSelection();
591    
592     if ( IsCreated() )
593     wxVListBox::SetItemCount( wxVListBox::GetItemCount()-1 );
594    
595     // Fix selection
596     if ( (int)item < sel )
597     SetSelection(sel-1);
598     else if ( (int)item == sel )
599     SetSelection(wxNOT_FOUND);
600     }
601    
602     int wxVListBoxComboPopup::FindString(const wxString& s, bool bCase) const
603     {
604     return m_strings.Index(s, bCase);
605     }
606    
607     unsigned int wxVListBoxComboPopup::GetCount() const
608     {
609     return m_strings.GetCount();
610     }
611    
612     wxString wxVListBoxComboPopup::GetString( int item ) const
613     {
614     return m_strings[item];
615     }
616    
617     void wxVListBoxComboPopup::SetString( int item, const wxString& str )
618     {
619     m_strings[item] = str;
620     ItemWidthChanged(item);
621     }
622    
623     wxString wxVListBoxComboPopup::GetStringValue() const
624     {
625     if ( m_value >= 0 )
626     return m_strings[m_value];
627     return wxEmptyString;
628     }
629    
630     void wxVListBoxComboPopup::SetSelection( int item )
631     {
632     wxCHECK_RET( item == wxNOT_FOUND || ((unsigned int)item < GetCount()),
633     wxT("invalid index in wxVListBoxComboPopup::SetSelection") );
634    
635     m_value = item;
636    
637     if ( IsCreated() )
638     wxVListBox::SetSelection(item);
639     }
640    
641     int wxVListBoxComboPopup::GetSelection() const
642     {
643     return m_value;
644     }
645    
646     void wxVListBoxComboPopup::SetStringValue( const wxString& value )
647     {
648     int index = m_strings.Index(value);
649    
650     if ( index >= 0 && index < (int)wxVListBox::GetItemCount() )
651     {
652     m_value = index;
653     wxVListBox::SetSelection(index);
654     }
655     }
656    
657     void wxVListBoxComboPopup::CalcWidths()
658     {
659     bool doFindWidest = m_findWidest;
660    
661     // Measure items with dirty width.
662     if ( m_widthsDirty )
663     {
664     unsigned int i;
665     unsigned int n = m_widths.GetCount();
666     int dirtyHandled = 0;
667     wxArrayInt& widths = m_widths;
668    
669     // I think using wxDC::GetTextExtent is faster than
670     // wxWindow::GetTextExtent (assuming same dc is used
671     // for all calls, as we do here).
672     wxClientDC dc(m_combo);
673     dc.SetFont(m_useFont);
674    
675     for ( i=0; i<n; i++ )
676     {
677     if ( widths[i] < 0 )
678     {
679     wxCoord x = OnMeasureItemWidth(i);
680    
681     if ( x < 0 )
682     {
683     const wxString& text = m_strings[i];
684    
685     // To make sure performance won't suck in extreme scenarios,
686     // we'll estimate length after some arbitrary number of items
687     // have been checked precily.
688     if ( dirtyHandled < 1024 )
689     {
690     wxCoord y;
691     dc.GetTextExtent(text, &x, &y, 0, 0);
692     x += 4;
693     }
694     else
695     {
696     x = text.length() * (dc.GetCharWidth()+1);
697     }
698     }
699    
700     widths[i] = x;
701    
702     if ( x >= m_widestWidth )
703     {
704     m_widestWidth = x;
705     m_widestItem = (int)i;
706     }
707     else if ( (int)i == m_widestItem )
708     {
709     // Width of previously widest item has been decreased, so
710     // we'll have to check all to find current widest item.
711     doFindWidest = true;
712     }
713    
714     dirtyHandled++;
715     }
716     }
717    
718     m_widthsDirty = false;
719     }
720    
721     if ( doFindWidest )
722     {
723     unsigned int i;
724     unsigned int n = m_widths.GetCount();
725    
726     int bestWidth = -1;
727     int bestIndex = -1;
728    
729     for ( i=0; i<n; i++ )
730     {
731     int w = m_widths[i];
732     if ( w > bestWidth )
733     {
734     bestIndex = (int)i;
735     bestWidth = w;
736     }
737     }
738    
739     m_widestWidth = bestWidth;
740     m_widestItem = bestIndex;
741    
742     m_findWidest = false;
743     }
744     }
745    
746     wxSize wxVListBoxComboPopup::GetAdjustedSize( int minWidth, int prefHeight, int maxHeight )
747     {
748     int height = 250;
749    
750     maxHeight -= 2; // Must take borders into account
751    
752     if ( m_strings.GetCount() )
753     {
754     if ( prefHeight > 0 )
755     height = prefHeight;
756    
757     if ( height > maxHeight )
758     height = maxHeight;
759    
760     int totalHeight = GetTotalHeight(); // + 3;
761     if ( height >= totalHeight )
762     {
763     height = totalHeight;
764     }
765     else
766     {
767     // Adjust height to a multiple of the height of the first item
768     // NB: Calculations that take variable height into account
769     // are unnecessary.
770     int fih = GetLineHeight(0);
771     height -= height % fih;
772     }
773     }
774     else
775     height = 50;
776    
777     CalcWidths();
778    
779     // Take scrollbar into account in width calculations
780     int widestWidth = m_widestWidth + wxSystemSettings::GetMetric(wxSYS_VSCROLL_X);
781     return wxSize(minWidth > widestWidth ? minWidth : widestWidth,
782     height+2);
783     }
784    
785     //void wxVListBoxComboPopup::Populate( int n, const wxString choices[] )
786     void wxVListBoxComboPopup::Populate( const wxArrayString& choices )
787     {
788     int i;
789    
790     int n = choices.GetCount();
791    
792     for ( i=0; i<n; i++ )
793     {
794     const wxString& item = choices.Item(i);
795     m_strings.Add(item);
796     }
797    
798     m_widths.SetCount(n,-1);
799     m_widthsDirty = true;
800    
801     if ( IsCreated() )
802     wxVListBox::SetItemCount(n);
803    
804     // Sort the initial choices
805     if ( m_combo->GetWindowStyle() & wxCB_SORT )
806     m_strings.Sort();
807    
808     // Find initial selection
809     wxString strValue = m_combo->GetValue();
810     if ( strValue.length() )
811     m_value = m_strings.Index(strValue);
812     }
813    
814     // ----------------------------------------------------------------------------
815     // wxOwnerDrawnComboBox
816     // ----------------------------------------------------------------------------
817    
818    
819     BEGIN_EVENT_TABLE(wxOwnerDrawnComboBox, wxComboCtrl)
820     END_EVENT_TABLE()
821    
822    
823     IMPLEMENT_DYNAMIC_CLASS2(wxOwnerDrawnComboBox, wxComboCtrl, wxControlWithItems)
824    
825     void wxOwnerDrawnComboBox::Init()
826     {
827     }
828    
829     bool wxOwnerDrawnComboBox::Create(wxWindow *parent,
830     wxWindowID id,
831     const wxString& value,
832     const wxPoint& pos,
833     const wxSize& size,
834     long style,
835     const wxValidator& validator,
836     const wxString& name)
837     {
838     return wxComboCtrl::Create(parent,id,value,pos,size,style,validator,name);
839     }
840    
841     wxOwnerDrawnComboBox::wxOwnerDrawnComboBox(wxWindow *parent,
842     wxWindowID id,
843     const wxString& value,
844     const wxPoint& pos,
845     const wxSize& size,
846     const wxArrayString& choices,
847     long style,
848     const wxValidator& validator,
849     const wxString& name)
850     : wxComboCtrl()
851     {
852     Init();
853    
854     Create(parent,id,value,pos,size,choices,style, validator, name);
855     }
856    
857     bool wxOwnerDrawnComboBox::Create(wxWindow *parent,
858     wxWindowID id,
859     const wxString& value,
860     const wxPoint& pos,
861     const wxSize& size,
862     const wxArrayString& choices,
863     long style,
864     const wxValidator& validator,
865     const wxString& name)
866     {
867     m_initChs = choices;
868     //wxCArrayString chs(choices);
869    
870     //return Create(parent, id, value, pos, size, chs.GetCount(),
871     // chs.GetStrings(), style, validator, name);
872     return Create(parent, id, value, pos, size, 0,
873     NULL, style, validator, name);
874     }
875    
876     bool wxOwnerDrawnComboBox::Create(wxWindow *parent,
877     wxWindowID id,
878     const wxString& value,
879     const wxPoint& pos,
880     const wxSize& size,
881     int n,
882     const wxString choices[],
883     long style,
884     const wxValidator& validator,
885     const wxString& name)
886     {
887    
888     if ( !Create(parent, id, value, pos, size, style,
889     validator, name) )
890     {
891     return false;
892     }
893    
894     int i;
895     for ( i=0; i<n; i++ )
896     m_initChs.Add(choices[i]);
897    
898     return true;
899     }
900    
901     wxOwnerDrawnComboBox::~wxOwnerDrawnComboBox()
902     {
903     if ( m_popupInterface )
904     GetVListBoxComboPopup()->ClearClientDatas();
905     }
906    
907     void wxOwnerDrawnComboBox::DoSetPopupControl(wxComboPopup* popup)
908     {
909     if ( !popup )
910     {
911     popup = new wxVListBoxComboPopup();
912     }
913    
914     wxComboCtrl::DoSetPopupControl(popup);
915    
916     wxASSERT(popup);
917    
918     // Add initial choices to the wxVListBox
919     if ( !GetVListBoxComboPopup()->GetCount() )
920     {
921     GetVListBoxComboPopup()->Populate(m_initChs);
922     m_initChs.Clear();
923     }
924     }
925    
926     // ----------------------------------------------------------------------------
927     // wxOwnerDrawnComboBox item manipulation methods
928     // ----------------------------------------------------------------------------
929    
930     void wxOwnerDrawnComboBox::Clear()
931     {
932     EnsurePopupControl();
933    
934     GetVListBoxComboPopup()->Clear();
935    
936     SetValue(wxEmptyString);
937     }
938    
939     void wxOwnerDrawnComboBox::Delete(unsigned int n)
940     {
941     wxCHECK_RET( IsValid(n), _T("invalid index in wxOwnerDrawnComboBox::Delete") );
942    
943     if ( GetSelection() == (int) n )
944     SetValue(wxEmptyString);
945    
946     GetVListBoxComboPopup()->Delete(n);
947     }
948    
949     unsigned int wxOwnerDrawnComboBox::GetCount() const
950     {
951     if ( !m_popupInterface )
952     return m_initChs.GetCount();
953    
954     return GetVListBoxComboPopup()->GetCount();
955     }
956    
957     wxString wxOwnerDrawnComboBox::GetString(unsigned int n) const
958     {
959     wxCHECK_MSG( IsValid(n), wxEmptyString, _T("invalid index in wxOwnerDrawnComboBox::GetString") );
960    
961     if ( !m_popupInterface )
962     return m_initChs.Item(n);
963    
964     return GetVListBoxComboPopup()->GetString(n);
965     }
966    
967     void wxOwnerDrawnComboBox::SetString(unsigned int n, const wxString& s)
968     {
969     EnsurePopupControl();
970    
971     wxCHECK_RET( IsValid(n), _T("invalid index in wxOwnerDrawnComboBox::SetString") );
972    
973     GetVListBoxComboPopup()->SetString(n,s);
974     }
975    
976     int wxOwnerDrawnComboBox::FindString(const wxString& s, bool bCase) const
977     {
978     if ( !m_popupInterface )
979     return m_initChs.Index(s, bCase);
980    
981     return GetVListBoxComboPopup()->FindString(s, bCase);
982     }
983    
984     void wxOwnerDrawnComboBox::Select(int n)
985     {
986     EnsurePopupControl();
987    
988     wxCHECK_RET( (n == wxNOT_FOUND) || IsValid(n), _T("invalid index in wxOwnerDrawnComboBox::Select") );
989    
990     GetVListBoxComboPopup()->SetSelection(n);
991    
992     wxString str;
993     if ( n >= 0 )
994     str = GetVListBoxComboPopup()->GetString(n);
995    
996     // Refresh text portion in control
997     if ( m_text )
998     m_text->SetValue( str );
999     else
1000     m_valueString = str;
1001    
1002     Refresh();
1003     }
1004    
1005     int wxOwnerDrawnComboBox::GetSelection() const
1006     {
1007     if ( !m_popupInterface )
1008     return m_initChs.Index(m_valueString);
1009    
1010     return GetVListBoxComboPopup()->GetSelection();
1011     }
1012    
1013     int wxOwnerDrawnComboBox::DoAppend(const wxString& item)
1014     {
1015     EnsurePopupControl();
1016     wxASSERT(m_popupInterface);
1017    
1018     return GetVListBoxComboPopup()->Append(item);
1019     }
1020    
1021     int wxOwnerDrawnComboBox::DoInsert(const wxString& item, unsigned int pos)
1022     {
1023     EnsurePopupControl();
1024    
1025     wxCHECK_MSG(!(GetWindowStyle() & wxCB_SORT), -1, wxT("can't insert into sorted list"));
1026     wxCHECK_MSG(IsValidInsert(pos), -1, wxT("invalid index"));
1027    
1028     GetVListBoxComboPopup()->Insert(item,pos);
1029    
1030     return pos;
1031     }
1032    
1033     void wxOwnerDrawnComboBox::DoSetItemClientData(unsigned int n, void* clientData)
1034     {
1035     EnsurePopupControl();
1036    
1037     GetVListBoxComboPopup()->SetItemClientData(n,clientData,m_clientDataItemsType);
1038     }
1039    
1040     void* wxOwnerDrawnComboBox::DoGetItemClientData(unsigned int n) const
1041     {
1042     if ( !m_popupInterface )
1043     return NULL;
1044    
1045     return GetVListBoxComboPopup()->GetItemClientData(n);
1046     }
1047    
1048     void wxOwnerDrawnComboBox::DoSetItemClientObject(unsigned int n, wxClientData* clientData)
1049     {
1050     DoSetItemClientData(n, (void*) clientData);
1051     }
1052    
1053     wxClientData* wxOwnerDrawnComboBox::DoGetItemClientObject(unsigned int n) const
1054     {
1055     return (wxClientData*) DoGetItemClientData(n);
1056     }
1057    
1058     // ----------------------------------------------------------------------------
1059     // wxOwnerDrawnComboBox item drawing and measuring default implementations
1060     // ----------------------------------------------------------------------------
1061    
1062     void wxOwnerDrawnComboBox::OnDrawItem( wxDC& dc,
1063     const wxRect& rect,
1064     int item,
1065     int flags ) const
1066     {
1067     if ( flags & wxODCB_PAINTING_CONTROL )
1068     {
1069     dc.DrawText( GetValue(),
1070     rect.x + GetTextIndent(),
1071     (rect.height-dc.GetCharHeight())/2 + rect.y );
1072     }
1073     else
1074     {
1075     dc.DrawText( GetVListBoxComboPopup()->GetString(item), rect.x + 2, rect.y );
1076     }
1077     }
1078    
1079     wxCoord wxOwnerDrawnComboBox::OnMeasureItem( size_t WXUNUSED(item) ) const
1080     {
1081     return -1;
1082     }
1083    
1084     wxCoord wxOwnerDrawnComboBox::OnMeasureItemWidth( size_t WXUNUSED(item) ) const
1085     {
1086     return -1;
1087     }
1088    
1089     void wxOwnerDrawnComboBox::OnDrawBackground(wxDC& dc,
1090     const wxRect& rect,
1091     int WXUNUSED(item),
1092     int flags) const
1093     {
1094     // We need only to explicitly draw background for items
1095     // that should have selected background. Also, call PrepareBackground
1096     // always when painting the control so that clipping is done properly.
1097    
1098     if ( (flags & wxODCB_PAINTING_SELECTED) ||
1099     ((flags & wxODCB_PAINTING_CONTROL) && HasFlag(wxCB_READONLY)) )
1100     {
1101     int bgFlags = wxCONTROL_SELECTED;
1102    
1103     if ( !(flags & wxODCB_PAINTING_CONTROL) )
1104     bgFlags |= wxCONTROL_ISSUBMENU;
1105    
1106     PrepareBackground(dc, rect, bgFlags);
1107     }
1108     }
1109    
1110     #endif // wxUSE_ODCOMBOBOX

  ViewVC Help
Powered by ViewVC 1.1.22