Forum: wxRuby Wx::Dialog: run code when OK button selected

E751df72a62c08522971d36c81adaf36?d=identicon&s=25 Josh Kjenner (jeemang)
on 2010-06-11 00:59
Howdy;

I'm using wxRuby to build menus for a Sketchup plug-in I'm working on.
(Specifically, I'm actually using wxSU, http://wxsu.sourceforge.net/,
which is basically wxRuby packaged up as a Sketchup plug-in).

I'm trying to create a custom dialog to gather information from the user
via text boxes (implemented with Wx::TextCtrl) and pull-down menus
(implemented with Wx::Choice). My problem is that I can't figure out how
to get the information entered via these means out of the Wx::Dialog
object they live in when the "OK" button is clicked. Here is the
relevant code:

## this is the WX code for an improved location dialog
class LocationDialog < Wx::Dialog

    def initialize

        ## set dialog characteristics
        title = "Location dialog"
        size = Wx::Size.new(250, 305)
        position = Wx::DEFAULT_POSITION
        style = Wx::SYSTEM_MENU
        name = "location dialog"

        ## create dialog
        super(WxSU.app.sketchup_frame, -1, title, position, size, style,
name)

        ## fields and buttons
        ## city
        citySTPos = Wx::Point.new(10,10)
        citySTSize = Wx::Size.new(110,20)
        cityST = Wx::StaticText.new(self, -1, 'city', citySTPos,
citySTSize, Wx::ALIGN_RIGHT)

        cityTCPos = Wx::Point.new(130,10)
        cityTCSize = Wx::Size.new(100,20)
        @cityTC = Wx::TextCtrl.new(self, -1, '', cityTCPos, cityTCSize,
Wx::TE_LEFT)

        ## timezone offset
        tzSTPos = Wx::Point.new(10,130)
        tzSTSize = Wx::Size.new(110,20)
        tzST = Wx::StaticText.new(self, -1, 'timezone offset', tzSTPos,
tzSTSize, Wx::ALIGN_RIGHT)

        tzCPos = Wx::Point.new(130,130)
        tzCSize = Wx::Size.new(70,20)
        tzChoices = (-12..12).to_a.collect{ |e| e.to_s }
        tzC = Wx::Choice.new(self, -1, tzCPos, tzCSize, tzChoices)

        ## a bunch more fields here that I've omitted for brevity

        ## okay button
        okBPos = Wx::Point.new(130,255)
        okBSize = Wx::Size.new(100,20)
        okButton = Wx::Button.new(self, Wx::ID_OK, 'okay', okBPos,
okBSize, Wx::BU_BOTTOM)
        self.set_affirmative_id(okButton.get_id()) ## identifies button
as dialog "OK" button
      #evt_button(okButton.get_id()) {|e| on_okButton(e)} # attempt 1
        #evt_button(okButton.get_id()) {|e| puts "test" } # attempt 2


      ## cancel button
        canBPos = Wx::Point.new(20,255)
        canBSize = Wx::Size.new(100,20)
        canButton = Wx::Button.new(self, Wx::ID_CANCEL, 'cancel',
canBPos, canBSize, Wx::BU_BOTTOM)
        self.set_escape_id(canButton.get_id()) ## identifies button as
dialog "cancel" button

    end ## initilize

end ## LocationDialog

I tried using the button event handling block to point the button to
another method ("attempt 1" commented out above), but when I do it this
way, I can't get the LocationDialog.show_modal method to return anything
but a Fixnum 0 when "OK" is clicked (it should be returning either a
Fixnum 5100, or a Wx::ID_OK), which is problematic because I need this
return value for logic elsewhere in my code.

I also tried simply putting the code I need right in the block ("attempt
2", commented out above). When I do this the code in the block executes
as I would hope, but nothing else I need to happen happens -- ie, the
dialog doesn't close, and the LocationDialog.show_modal doesn't return
the correct value.

So: I'm wondering how I can accomplish this. Any suggestions would be
very much appreciated.

Josh
3396e4a3df8a840faec520af8555a400?d=identicon&s=25 Mario Steele (Guest)
on 2010-06-11 23:27
(Received via mailing list)
Hello Josh,

Welcome to the wxRuby community, and thank you for using wxRuby with
wxSU.

While wxSU isn't a package we officially support, it's not much
different
then a Normal wxRuby application.  And your specific problem, does fall
into
the reign of wxRuby itself.  A common mis-conception about Dialogs, is
that
return values are anything of meaning, aside from the default values of
Wx::ID_OK, Wx::ID_CANCEL.  Wx::Dialog#show_modal will always return
these
values, to determine if the dialog was Cancelled, or okayed by the user.
 You should check for these values to ensure that your dialog was
accepted
by the user, before attempting to get any values from the dialog.

Now, with the establishment of how Wx::Dialog#show_modal returns values,
to
get your specific values out of the dialog, you have one of two ways in
which to gather the data from your custom Dialog.  Both methods are
similar,
in the way to extract the data, but one specific method is designed to
be
internal to your custom Dialog class, and the other is an external way.

The Internal way to get your data, is to create a method to retrieve the
values you need from your dialog, and return them as an array.

As such:

class LocationDialog < Wx::Dialog

  # After your initialization function add this:
  def get_values()
    values = []
    values << @cityTC.get_value
    values << @tzC.get_index
    return values
  end
end

The other method, is similar to the above method, but instead of having
the
function built into your Dialog class, you make your control instances
as
attributes on your Dialog Class itself, to get the values out of them.

Like So:

class LocationDialog < Wx::Dialog
  attr_reader :cityTC, :tzC

  # Do your initialization stuff here
end


Now, in your main app, where you do the Dialog#show_modal, you can use
either method to get the data.

The first Method:


  def on_get_info()
    dlg = LocationDialog.new
    if dlg.show_modal == Wx::ID_OK
      data = dlg.get_values()
      # Parse your data here
    end
    dlg.destroy
  end

The Second Method:

  def on_get_info()
    dlg = LocationDialog.new
    if dlg.show_modal == Wx::ID_OK
      city = dlg.cityTC.get_value
      tz = dlg.tzC.get_index
      # Parse your data here
    end
    dlg.destroy()
  end

My personal preference would be the first method, as all your data is
gathered at once.  But you can use any method you wish.  This is the
best
way to gather the data from a custom dialog that you have built.  If you
have any further questions, please feel free to ask on this list, as we
are
always happy to help out new comers.


hth,

Mario
E751df72a62c08522971d36c81adaf36?d=identicon&s=25 Josh Kjenner (jeemang)
on 2010-06-14 22:44
Hi Mario;

Thanks a lot for your response. I was able to solve my problem by using
"The First Method" you describe above. It's funny, I definitely had the
thought to create a method that would store the data collected from the
dialog's fields, but I couldn't figure out a way to call it between the
OK button being clicked and the dialog being destroyed. I'm a little
embarrassed I didn't think of using if/then -- thanks a lot for taking
the time to point it out to me!

Josh
3396e4a3df8a840faec520af8555a400?d=identicon&s=25 Mario Steele (Guest)
on 2010-06-17 16:22
(Received via mailing list)
Not a problem Josh,

Don't feel to bad about it, everyone starts out not knowing a thing, and
they learn.  Sometimes from Documentation, sometimes from others.
Whenever
you have a question, don't hesitate to ask, that's why we are here to
help
out the future developers that come along, wanting to use wxRuby in
whatever
shape or form, for something that they want to develop.

Have fun,

Mario
This topic is locked and can not be replied to.