Validation and ComboBox


#1

I’m trying to make a ComboBox that can be typed into but only accepts
entries that are already in the drop-down list. I hoped a combination of
the CB_DROPDOWN style and a TextValidator with the FILTER_INCLUDE_LIST
would make that happen, but the validator seems to be ignored. Is that
combination supposed to do what I want? If so, please review the code
below and let me know where my mistake is.

Relevant libraries/platform: Ubuntu 8.04, Ruby 1.8.6, wxWidgets 2.8.9
(deb from the apt.wxwidgets.org repository), wxruby 1.9.10 gem.

David Peoples


#!/usr/bin/env ruby
require ‘wx’

class MyFrame < Wx::Frame
def initialize(title)
super(nil, :title => title, :size => [ 400, 300 ])
panel = Wx::Panel.new(self, -1)
@combo_choices = [“Apple”, “Aardvark”, “Banana”, “Berry”, “Canada”,
“Cantaloupe”, “Cauliflower”, “Dummy”]
validator = Wx::TextValidator.new(Wx::FILTER_INCLUDE_LIST)
validator.includes = @combo_choices
combobox = Wx::ComboBox.new(panel, -1, “”, Wx::Point.new(15,15),
Wx::Size.new(-1,-1), @combo_choices, Wx::CB_DROPDOWN, validator,
“my_combobox”)
end
end

Wx::App.run do
self.app_name = “Test validated combobox”
frame = MyFrame.new(“ComboBox test”)
frame.show
end


#2

David Peoples wrote:

I’m trying to make a ComboBox that can be typed into but only accepts
entries that are already in the drop-down list.

I’m presumably missing something, but why not just use a Wx::Choice if
you want a fixed list?

I hoped a combination of
the CB_DROPDOWN style and a TextValidator with the FILTER_INCLUDE_LIST
would make that happen, but the validator seems to be ignored. Is that
combination supposed to do what I want?

Thanks for mentioning this, as I hadn’t really looked into this use of
Validators before.

Firstly, from an assertion failure I get with the debug build, it seems
TextValidator is only for use with TextCtrl, not anything else like
ComboBox.

With INCLUDE_LIST and EXCLUDE_LIST, the Validator clearly can’t validate
on each keystroke as it does with the other types, where it blocks
incorrect characters (eg limiting it to numerics only). wxWidgets
expects the control to be part of a Dialog, and validates it only when
the Dialog is dismissed.

Since the automatic message one gets on a validation failure is not very
helpful anyway (it’s hardcoded to “XXXX is not valid”), I’d suggest it’d
be easier to roll your own. Trap the event when the contents should be
checked (eg evt_kill_focus, or clicking “OK” on a dialog button) and act
accordingly, eg

combobox.evt_kill_focus do
unless @combo_choices.include?(combobox.value)
# do some warning
end
end

alex


#3

On Thu, 2009-02-19 at 01:06 +0000, Alex F. wrote:

David Peoples wrote:

I’m trying to make a ComboBox that can be typed into but only accepts
entries that are already in the drop-down list.

I’m presumably missing something, but why not just use a Wx::Choice if
you want a fixed list?

My application needs to allow fairly high speed heads-down text entry
with as close to zero mouse use as possible. The Wx::Choice control has
a very clumsy keyboard interface. The app I’m converting was written in
Delphi on Windows, and the custom combobox controls there had an
excellent keyboard driven autocomplete operation I’m trying to emulate
here.

After looking closer at the docs I realized that I can get fairly close
to what I want with an evt_text() handler and manipulating the text with
ComboBox#set_value. ComboBox#set_text_selection_range isn’t doing at all
what I expected, so I’ll probably work around that by displaying the
list of potential matches somewhere below the combobox control while
text entry is going on. Kludgy and a lot of work, but at least probably
will work.

I’ve never stopped being shocked at how crude some of the controls are
in Gtk and KDE, compared to what I was used to. At least wxWidgets gives
fairly easy access to the edit control in the combobox, which none of
the other ruby GUIs do, as far as I could work out.

Thanks for your help!

David


#4

David Peoples wrote:

My application needs to allow fairly high speed heads-down text entry
with as close to zero mouse use as possible. The Wx::Choice control has
a very clumsy keyboard interface. The app I’m converting was written in
Delphi on Windows, and the custom combobox controls there had an
excellent keyboard driven autocomplete operation I’m trying to emulate
here.

Makes sense. I implemented a control similar to this, can’t find the
code now but it went roughly like:

evt_text(combobox) do
  val = combobox.value
  if @last_val == val # deletion
    val = val[0..-2]
  end
  matches = @combo_choices.grep(/^#{val}/)

  combobox.clear
  combobox.append matches
  if not matches.empty?
    combobox.value = matches.first
    combobox.set_text_selection_range( val.length,
                                       matches.first.length)
  end
  @last_val = val
end

Obviously you’d probably want to refine this and turn it into a
self-contained class. But it should be usable completely
keyboard-driven.

a