// implementation
// ============================================================================
+// time in milliseconds before partial completion buffer drops
+#define wxODCB_PARTIAL_COMPLETION_TIME 1000
// ----------------------------------------------------------------------------
// wxVListBoxComboPopup is a wxVListBox customized to act as a popup control
m_value = -1;
m_itemHover = -1;
m_clientDataItemsType = wxClientData_None;
+ m_partialCompletionString = wxEmptyString;
}
bool wxVListBoxComboPopup::Create(wxWindow* parent)
{
if ( !(m_combo->GetWindowStyle() & wxODCB_STD_CONTROL_PAINT) )
{
- OnDrawBg(dc,rect,m_value,wxODCB_PAINTING_CONTROL);
+ int flags = wxODCB_PAINTING_CONTROL;
+
+ if ( m_combo->ShouldDrawFocus() )
+ flags |= wxODCB_PAINTING_SELECTED;
+
+ OnDrawBg(dc, rect, m_value, flags);
+
if ( m_value >= 0 )
{
OnDrawItem(dc,rect,m_value,wxODCB_PAINTING_CONTROL);
wxASSERT_MSG( combo->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox)),
wxT("you must subclass wxVListBoxComboPopup for drawing and measuring methods") );
+ if ( IsCurrent((size_t)item) && !(flags & wxODCB_PAINTING_CONTROL) )
+ flags |= wxODCB_PAINTING_SELECTED;
+
combo->OnDrawBackground(dc,rect,item,flags);
}
void wxVListBoxComboPopup::DismissWithEvent()
{
+ StopPartialCompletion();
+
int selection = wxVListBox::GetSelection();
Dismiss();
m_value = selection;
if ( valStr != m_combo->GetValue() )
- m_combo->SetValue(valStr);
+ m_combo->SetValueWithEvent(valStr);
SendComboBoxEvent(selection);
}
}
// returns true if key was consumed
-bool wxVListBoxComboPopup::HandleKey( int keycode, bool saturate )
+bool wxVListBoxComboPopup::HandleKey( int keycode, bool saturate, wxChar unicode )
{
int value = m_value;
int itemCount = GetCount();
+ int comboStyle = m_combo->GetWindowStyle();
+
+ // this is the character equivalent of the code
+ wxChar keychar=0;
+ if ((keycode >= WXK_SPACE) && (keycode <=255) && (keycode != WXK_DELETE) && wxIsprint(keycode))
+ {
+ keychar = (wxChar)keycode;
+ }
+ else if (unicode>0)
+ {
+ keychar = unicode;
+ }
if ( keycode == WXK_DOWN || keycode == WXK_RIGHT )
{
value++;
+ StopPartialCompletion();
}
else if ( keycode == WXK_UP || keycode == WXK_LEFT )
{
value--;
+ StopPartialCompletion();
}
else if ( keycode == WXK_PAGEDOWN )
{
value+=10;
+ StopPartialCompletion();
}
else if ( keycode == WXK_PAGEUP )
{
value-=10;
+ StopPartialCompletion();
+ }
+ else if ( comboStyle & wxCB_READONLY )
+ {
+ // Try partial completion
+
+ // find the new partial completion string
+#if wxUSE_TIMER
+ if (m_partialCompletionTimer.IsRunning())
+ m_partialCompletionString+=wxString(keychar);
+ else
+#endif // wxUSE_TIMER
+ m_partialCompletionString=wxString(keychar);
+
+ // now search through the values to see if this is found
+ int found = -1;
+ unsigned int length=m_partialCompletionString.length();
+ int i;
+ for (i=0; i<itemCount; i++)
+ {
+ wxString item=GetString(i);
+ if (( item.length() >= length) && (! m_partialCompletionString.CmpNoCase(item.Left(length))))
+ {
+ found=i;
+ break;
+ }
+ }
+
+ if (found<0)
+ {
+ StopPartialCompletion();
+ ::wxBell();
+ return true; // to stop the first value being set
+ }
+ else
+ {
+ value=i;
+#if wxUSE_TIMER
+ m_partialCompletionTimer.Start(wxODCB_PARTIAL_COMPLETION_TIME, true);
+#endif // wxUSE_TIMER
+ }
}
else
return false;
return true;
}
+// stop partial completion
+void wxVListBoxComboPopup::StopPartialCompletion()
+{
+ m_partialCompletionString = wxEmptyString;
+#if wxUSE_TIMER
+ m_partialCompletionTimer.Stop();
+#endif // wxUSE_TIMER
+}
+
void wxVListBoxComboPopup::OnComboDoubleClick()
{
// Cycle on dclick (disable saturation to allow true cycling).
void wxVListBoxComboPopup::OnComboKeyEvent( wxKeyEvent& event )
{
// Saturated key movement on
- if ( !HandleKey(event.GetKeyCode(),true) )
+ if ( !HandleKey(event.GetKeyCode(),true,
+#if wxUSE_UNICODE
+ event.GetUnicodeKey()
+#else
+ 0
+#endif
+ ) )
event.Skip();
}
void wxVListBoxComboPopup::OnKey(wxKeyEvent& event)
{
+ // Hide popup if certain key or key combination was pressed
+ if ( m_combo->IsKeyPopupToggle(event) )
+ {
+ StopPartialCompletion();
+ Dismiss();
+ }
+ else if ( event.AltDown() )
+ {
+ // On both wxGTK and wxMSW, pressing Alt down seems to
+ // completely freeze things in popup (ie. arrow keys and
+ // enter won't work).
+ return;
+ }
// Select item if ENTER is pressed
- if ( event.GetKeyCode() == WXK_RETURN || event.GetKeyCode() == WXK_NUMPAD_ENTER )
+ else if ( event.GetKeyCode() == WXK_RETURN || event.GetKeyCode() == WXK_NUMPAD_ENTER )
{
DismissWithEvent();
}
- // Hide popup if ESC is pressed
- else if ( event.GetKeyCode() == WXK_ESCAPE )
- Dismiss();
else
- event.Skip();
+ {
+ int comboStyle = m_combo->GetWindowStyle();
+ int keycode = event.GetKeyCode();
+ // Process partial completion key codes here, but not the arrow keys as the base class will do that for us
+ if ((comboStyle & wxCB_READONLY) &&
+ (keycode >= WXK_SPACE) && (keycode <=255) && (keycode != WXK_DELETE) && wxIsprint(keycode))
+ {
+ OnComboKeyEvent(event);
+ SetSelection(m_value); // ensure the highlight bar moves
+ }
+ else
+ event.Skip();
+ }
}
void wxVListBoxComboPopup::Insert( const wxString& item, int pos )
if ( (int)item == m_widestItem )
m_findWidest = true;
+ int sel = GetSelection();
+
if ( IsCreated() )
wxVListBox::SetItemCount( wxVListBox::GetItemCount()-1 );
+
+ // Fix selection
+ if ( (int)item < sel )
+ SetSelection(sel-1);
+ else if ( (int)item == sel )
+ SetSelection(wxNOT_FOUND);
}
int wxVListBoxComboPopup::FindString(const wxString& s, bool bCase) const
{
int height = 250;
+ maxHeight -= 2; // Must take borders into account
+
if ( m_strings.GetCount() )
{
if ( prefHeight > 0 )
// NB: Calculations that take variable height into account
// are unnecessary.
int fih = GetLineHeight(0);
- int shown = height/fih;
- height = shown * fih;
+ height -= height % fih;
}
}
else
return -1;
}
-void wxOwnerDrawnComboBox::OnDrawBackground(wxDC& dc, const wxRect& rect, int item, int flags) const
+void wxOwnerDrawnComboBox::OnDrawBackground(wxDC& dc,
+ const wxRect& rect,
+ int WXUNUSED(item),
+ int flags) const
{
- // we need to render selected and current items differently
- if ( GetVListBoxComboPopup()->IsCurrent((size_t)item) )
+ // We need only to explicitly draw background for items
+ // that should have selected background. Also, call PrepareBackground
+ // always when painting the control so that clipping is done properly.
+
+ if ( (flags & wxODCB_PAINTING_SELECTED) ||
+ ((flags & wxODCB_PAINTING_CONTROL) && HasFlag(wxCB_READONLY)) )
{
- DrawFocusBackground(dc,
- rect,
- (flags&wxODCB_PAINTING_CONTROL?0:wxCONTROL_ISSUBMENU) |
- wxCONTROL_SELECTED);
+ int bgFlags = wxCONTROL_SELECTED;
+
+ if ( !(flags & wxODCB_PAINTING_CONTROL) )
+ bgFlags |= wxCONTROL_ISSUBMENU;
+
+ PrepareBackground(dc, rect, bgFlags);
}
- //else: do nothing for the normal items
}
#endif // wxUSE_ODCOMBOBOX