Moving from TK to Fox

Have you, or do you know if anyone else has, produced an FXRuby for TK
users yet? That example I posted [Ruby-Talk:45298] which caused Ruby Tk
to blow up -- I'd like to try translating it to FXRuby. A quick rush
through the user guide didn't turn up much about entry widgets or label
widgets, which are the ones I need for this.

As far as I know, no one has written an "FXRuby for Tk Users" tutorial. But
I can give you a brief rundown of FOX's equivalents of Tk's Button, Entry,
and Label widgets.

The FOX button widget is called FXButton, and the "button.rb" example
program included with FXRuby shows off most everything you can do with them.
As with most FOX widgets, the FXButton#initialize method takes a large
number of arguments, but most of them have default values. To keep it
simple, start out with a button that just displays a label:

    pigButton = FXButton.new(parent, "Pig It")

and to connect that button to a message handler, use the FXButton#connect
method:

    pigButton.connect(SEL_COMMAND) do
      puts "Oink"
    end

The FOX equivalent of Tk's Entry widget is the FXTextField. For your program
you'll want to combine them with data targets, FOX's equivalent of Tk's
TkVariable:

    @host = FXDataTarget.new("") # for a string
    @host_entry = FXTextField.new(parent, 8,
        @host, FXDataTarget::ID_VALUE)

If you want to turn on "password" mode, where the user's input is masked by
asterisks, enable the TEXTFIELD_PASSWD mode for the text field:

    @passwd = FXDataTarget.new("") # for a string
    @pass_entry = FXTextField.new(parent, 8,
        @host, FXDataTarget::ID_VALUE,
        TEXTFIELD_NORMAL|TEXTFIELD_PASSWD)

Finally, FOX's equivalent of the Tk Label is (you guessed it) called FXLabel:

    myLabel = FXLabel.new(parent, "Remote Host:")

My advice would be to run through some of the examples included with FXRuby
and pick one that's close to the program you're designing, and then try
incrementally modifying that program to see what happens as you change it.
Luckily, Ruby makes this easy :wink:

Can I suggest that you link the filenames in chapter 2 (Examples) to the
actual code, so that we can see how to use these widgets, please?

Yes, this is a good suggestion. I will make a note to do this for the next
release.

Hope this helps,

Lyle

···

On Thu, 25 Jul 2002 11:59:53 +0100 (BST), Hugh Sasse Staff Elec Eng <hgs@dmu.ac.uk> wrote :

Have you, or do you know if anyone else has, produced an FXRuby for TK
users yet? That example I posted [Ruby-Talk:45298] which caused Ruby Tk

As far as I know, no one has written an “FXRuby for Tk Users” tutorial. But
I can give you a brief rundown of FOX’s equivalents of Tk’s Button, Entry,
and Label widgets.

    [Extremely helpful summary trimmed]

My advice would be to run through some of the examples included with FXRuby
and pick one that’s close to the program you’re designing, and then try
incrementally modifying that program to see what happens as you change it.
Luckily, Ruby makes this easy :wink:

    OK, I may take that approach as well.  Thanks

Can I suggest that you link the filenames in chapter 2 (Examples) to the
actual code, so that we can see how to use these widgets, please?

Yes, this is a good suggestion. I will make a note to do this for the next
release.

    Thank you.

Hope this helps,

    Very much so.

Lyle

    Thank you.
    Hugh
···

On Fri, 26 Jul 2002, lyle@knology.net wrote:

On Thu, 25 Jul 2002 11:59:53 +0100 (BST), Hugh Sasse Staff Elec Eng > hgs@dmu.ac.uk wrote :

i was wondering about this FXDataTarget stuff. that sets up an update
mechinism right? so the the GUI can ‘pull’ data from the app, as well as
push. seems to me such a pull strategy is lack lust. it requires
continual polling and potential delays. comments?

···

On Thu, 2002-07-25 at 09:09, lyle@knology.net wrote:

@host = FXDataTarget.new("") # for a string
@host_entry = FXTextField.new(parent, 8,
    @host, FXDataTarget::ID_VALUE)


~transami

The FOX button widget is called FXButton, and the “button.rb” example
[…]
The FOX equivalent of Tk’s Entry widget is the FXTextField. For your program
[…]
Finally, FOX’s equivalent of the Tk Label is (you guessed it) called FXLabel:
[…]

That was enough to get me there. Thank you. My code, which was
brutally “carved with an axe” from the Pig Latin example in
Programming Ruby (as you could tell by the unfinished stuff) now
looks like that below. I post it here (a) so you can use it as an
example and (b) so others trawling the archives can find it.

Can I suggest that you link the filenames in chapter 2 (Examples) to the
actual code, so that we can see how to use these widgets, please?

Yes, this is a good suggestion. I will make a note to do this for the next
release.

thank you.

Hope this helps,

It seems that FXDataTargets are not quite the same as Tcl’s linking of
variables to widgets – it is necessary to extract the value from the
FXDataTarget with a .value call. I note this here for those who
follow, it is not intended as a perjorative remark about your
description!

The serious thing that tripped me up near the end was the
application.create call, which I thought would be implicit in the show
or the run call. I don’t know what it does exactly, so I don’t
understand why it needs to be a separate call.

Also, application.init insists on taking an argument. If I’m not using
ARGV to pass the data this is not really what I want. I have not tried
leaving this call out since the code worked.

If these reflect aspects of the C++ API, may I suggest that you either
document their purpose in the Ruby API, or allow them to be assimilated
into soemthing more Rubyesque, because at the moment we have calls to
application.new, application.init and application.create.

Lyle

    Hugh

#!/usr/local/bin/ruby

A program to allow the transmission of a file inband.

require “fox”

include Fox

class Upload

attr_accessor :application

def do_connection()
    require 'net/telnet'
    # print "host #{@host.value}"
    # print "user #{@user.value}, pass #{@pass.value}"
    # print "file #{@file.value}"
    # return

    tn = Net::Telnet.new("Host" => @host.value)
    response = tn.login(@user.value, @pass.value)
    print response
    # tn.waitfor(@prompt.value)

    open(@file.value, "rb") { |fp|
        tn.print(%Q{cat | ruby -pe '$_ = $_.unpack("m").shift' > #{@file.value}})
        while line = fp.read(40)
            tn.print "#{[line].pack('m')}\n"
            sleep 0.1
            # print "#{[line].pack('m')}\n"
        end
        tn.print "\004\n"
        sleep 1
        tn.print "exit\n"
    }
end

def initialize()

    @application = FXApp.new("Uploader", "HughSasse")
@application.init(ARGV)

    entry_width = 15

main = FXMainWindow.new(@application, "Uploader", nil, nil, DECOR_ALL)

    # initilize varaibles
@host = FXDataTarget.new("") # for a string
@user = FXDataTarget.new("") # for a string
@pass = FXDataTarget.new("") # for a string
@prompt = FXDataTarget.new("") # for a string
@file = FXDataTarget.new("") # for a string
    @host_label = FXLabel.new(main, "Remote Host:")

@host_entry = FXTextField.new(main, entry_width,
    @host, FXDataTarget::ID_VALUE)

    @user_label = FXLabel.new(main, "username:")

@user_entry = FXTextField.new(main, entry_width,
    @user, FXDataTarget::ID_VALUE)

    @pass_label = FXLabel.new(main, "password:")

@pass_entry = FXTextField.new(main, entry_width,
    @pass, FXDataTarget::ID_VALUE,
        TEXTFIELD_NORMAL|TEXTFIELD_PASSWD)

    # @prompt_label = FXLabel.new(main, "prompt:")

# @prompt_entry = FXTextField.new(main, entry_width,
#     @prompt, FXDataTarget::ID_VALUE)

    @file_label = FXLabel.new(main,"File to send:")

@file_entry = FXTextField.new(main, entry_width,
    @file, FXDataTarget::ID_VALUE)

    @send_button = FXButton.new(main, "Send")
    @send_button.connect(SEL_COMMAND) { do_connection }

    @exit_button = FXButton.new(main, "Exit")
    @exit_button.connect(SEL_COMMAND) { exit 0 }

    @application.create
main.show(PLACEMENT_SCREEN)

end

end

uploader = Upload.new()
uploader.application.run

···

On Fri, 26 Jul 2002, lyle@knology.net wrote:

Tom Sawyer:

i was wondering about this FXDataTarget stuff. that sets up an update
mechinism right? so the the GUI can ‘pull’ data from the app, as well as
push. seems to me such a pull strategy is lack lust. it requires
continual polling and potential delays. comments?

what is there to say against pulling and pushing data? put queues and a
signalling mechanism between UI and application and you’re all set. the
"delays" are then only for people who can’t do something with their free
time :slight_smile:

clemens

Hugh Sasse Staff Elec Eng wrote:

It seems that FXDataTargets are not quite the same as Tcl’s linking of
variables to widgets – it is necessary to extract the value from the
FXDataTarget with a .value call. I note this here for those who
follow, it is not intended as a perjorative remark about your
description!

Ummm… you also have to call TkVariable#value to extract a Tk
Variable’s value. In both cases the object (FXDataTarget or TkVariable
instance) wraps around some other object that actually has the value of
interest. FXDataTarget builds on TkVariable a bit in that it can store
strings, integers or floats, whereas Tk’s Variable only stores strings.
Could you give me an example of what you’re talking about, i.e. a case
where you can use a TkVariable in place of TkVariable#value? Maybe
they’re doing some magic I’m not familiar with :wink:

The serious thing that tripped me up near the end was the
application.create call, which I thought would be implicit in the show
or the run call. I don’t know what it does exactly, so I don’t
understand why it needs to be a separate call.

Also, application.init insists on taking an argument. If I’m not using
ARGV to pass the data this is not really what I want. I have not tried
leaving this call out since the code worked.

If these reflect aspects of the C++ API, may I suggest that you either
document their purpose in the Ruby API, or allow them to be assimilated
into soemthing more Rubyesque, because at the moment we have calls to
application.new, application.init and application.create.

OK, I’ll consider some ways to simplify the startup code.

Thanks,

Lyle

···

On Fri, 26 Jul 2002, lyle@knology.net wrote:

Fox’s use of DataTargets puts this pull mechanism in the UI. that’s why
i think its probably not best to use it, as it should be inbetween.

···

On Thu, 2002-07-25 at 15:17, clemens fischer wrote:

what is there to say against pulling and pushing data? put queues and a
signalling mechanism between UI and application and you’re all set. the
"delays" are then only for people who can’t do something with their free
time :slight_smile:


~transami

[snip from Hugh Sasse]

If these reflect aspects of the C++ API, may I suggest that you either
document their purpose in the Ruby API, or allow them to be assimilated
into soemthing more Rubyesque, because at the moment we have calls to
application.new, application.init and application.create.

OK, I’ll consider some ways to simplify the startup code.

Interesting idea, Lyle. I wasn’t sure
how “set in stone” the Ruby API was. I
know that many parts aren’t, but some
might be.

Lyle: Let’s discuss this sometime, either
on or off the mailing list. I like Fox,
but I sometimes find pieces of the API
cumbersome (as Hugh does).

Hal

···

----- Original Message -----
From: “Lyle Johnson” lyle@users.sourceforge.net
Newsgroups: comp.lang.ruby
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Monday, July 29, 2002 8:54 AM
Subject: Re: Moving from TK to Fox.

Hal E. Fulton wrote:

From: “Lyle Johnson” lyle@users.sourceforge.net
Newsgroups: comp.lang.ruby
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Monday, July 29, 2002 8:54 AM
Subject: Re: Moving from TK to Fox.

[snip from Hugh Sasse]

If these reflect aspects of the C++ API, may I suggest that you either
document their purpose in the Ruby API, or allow them to be assimilated
into soemthing more Rubyesque, because at the moment we have calls to
application.new, application.init and application.create.

OK, I’ll consider some ways to simplify the startup code.

Interesting idea, Lyle. I wasn’t sure
how “set in stone” the Ruby API was. I
know that many parts aren’t, but some
might be.

The API is not set in stone, but there are at least two constraints for
me to consider when making changes.

One constraint is that there are certain things that must be done to
satisfy the underlying FOX library. To use Hugh’s case as an example, we
must construct an application (FXApp) instance; we must call
FXApp#init (which is different from Ruby’s initialize method) on that
instance and pass in a (possible empty) array of command line arguments;
and we must call FXApp#create to create the various server-side
resources (e.g. icons, fonts and windows).

Now, having said that, there’s no reason why we couldn’t hide some of
these nasty details away somewhere so that the FXRuby application
programmer is burdened with them. The scheme for connecting widget
events directly to Ruby procs (using the “connect” instance method) is
implemented entirely in Ruby code, layered on top of the real way you
have to do this in FOX. I did not change how FOX does things under the
hood, with its message maps and so forth, but I did make it more
accessible to Ruby programmers.

Another equally important constraint is to avoid making incompatible,
code-breaking changes to the API, and so the APIs that Hugh referred to
won’t actually go away. That is, code that calls FXApp#init directly or
whatever should still continue to work. But I don’t think that will be
too difficult to manage. To refer back to the previous example, people
can still write code to FXRuby’s original event-handling API (as
described in “The Ruby Way” and “Ruby Developer’s Guide”) even though
the new API is decidedly more “Rubyesque”.

Lyle: Let’s discuss this sometime, either
on or off the mailing list. I like Fox,
but I sometimes find pieces of the API
cumbersome (as Hugh does).

Yes, any comments and suggestions are welcome (either through the
mailing list, newsgroup or private e-mails). Please note that I’m not
really interested in discussing wholesale changes to the API, along
the lines of some other current threads (i.e. “Rouge” and friends).
However, if others in the Ruby community want to use FOX/FXRuby as a
springboard for implementing such new APIs, that’s great, and I wish
them success. And of course, I reserve the right to steal any of their
good ideas for FXRuby if I so choose :wink:

···

----- Original Message -----