When does the finish event get called in shoes? - ruby

Using Shoes, I would like to have a block executed upon window destruction. I thought I could use the finish event, but in the following piece of code, "Starting" is displayed, but "Finished" is never shown.
Shoes.app(:title => "Test") do
flow do
start do |obj|
alert("Starting")
end
finish do |obj|
alert("Finished")
end
button "Hello"
end
end

After doing some more researching...
It appears that the finish event in Shoes is currently only used for downloads.
In addition, it appears there is no onclose event currently, but it has been discussed.
http://article.gmane.org/gmane.comp.lib.shoes/2976
Apologies for answering my own question, but putting the knowledge out there for others.

Related

Running a Ruby class from a Shoes Edit Line

Hello All,
I have finished writing up a Ruby class to complete exactly what it is supposed to, but since it is Ruby, I have been running it through my terminal and I need this to be more user-friendly (i.e. have a GUI). So I googled this and came across Shoes, which seems to be a nice Ruby GUI toolkit, and exactly what I am looking for. However, despite my googling I can't seem to figure out how to use a Shoes GUI edit line to send an argument to the class I made. Here is the edit line
Shoes.app do
background white
para "Application Name"
stack(margin: 12) do
para "Message"
flow do
edit_line
button "Enter"
end
end
end
In short, is there some way to do a gets.chomp (or literally anything else that is similar) with this and set it equal to an instance variable?
Yes! Just assign the elements you want to keep track of to instance variables, and pass a block to the button (the block gets executed when the button is clicked). Try this:
Shoes.app do
background white
para "Application Name"
stack(margin: 12) do
#message = para "Message"
flow do
#edit_line = edit_line
button "Enter" do
#message.text = #edit_line.text
end
end
end
end

How to open a Glade-created window and wait for it to close, in Ruby?

I want to make my own window, using Glade (3.14.2).
At a certain point in my program, I want to
1) Put up the window and let the user do stuff
2) Wait for it to close
3) Get values from the window object
4) Continue on in my code
So basically, I want to treat the window like a modal dialog - but one that I write and control.
I've tried for a few hours. The window appears just fine, as designed in Glade. The user can interact with it.
When the window closes, code that's been connected with signal_connect('destroy') executes.
But the code that invoked the window's show() method... does not continue executing after the window closes.
class GrammarNodeEditor
#this makes the class visual:
include GladeGUI
def initialize(raw_node = nil, &close_block)
#raw_node = raw_node || {type: :Sequence, data: []}
#original_data = #raw_node[:data]
#close_block = close_block
end
def show
puts "GNE Window Opening"
load_glade(__FILE__)
#builder["window1"].title = "Edit/Create Grammar Node"
#builder["window1"].signal_connect('destroy') {|*args|
#close_block.call(self)
puts "GNE WINDOW DESTROY"
}
show_window()
puts "Done showing window"
end
Here is how I invoke it:
rhs_editor = GrammarNodeEditor.new {|obj|
puts "In closeblck, obj is #{obj.inspect}"
#rhs = obj.raw_node
}
puts "About to call show in GR:Init"
rhs_editor.show
puts "Back from calling show in GR:Init"
Here is the output:
About to call show in GR:Init
GNE Window Opening
In closeblck, obj is #<GrammarNodeEditor:0x7b82a88 #raw_node={:type=>:Sequence, :data=>[]}, [more junk here]>
GNE WINDOW DESTROY
The first two lines of output appear after I open the window. The 3rd and 4th appear when I close the window.
Note that "Done showing window" and "Back from calling show in GR:Init" are not printed at all.
Just to make this a little more interesting, I want to be able to do this from within code that puts up another window. My top-level window has a button to create a new Rule. The Rule must be initialized with a Node, and then the Rule must be edited. So first I need to put up a Node-definition window (as shown above) and then, when I have a Node defined, I want to put up a Rule window that uses that Node.
So I think I need to call this code within either the initialize() or the show() method of the GrammarRuleWindow class (another Glade-defined window).
Can someone explain why my puts's aren't being printed, and how to make the control flow go on through them?
Thanks!
...So it turned out the problem was that I had created the window's .glade file directly in Glade, rather than using the VisualRuby IDE.
Creating the .glade in VR adds some stuff to the file that VR needs. Specifically, the file needs to contain the line
<signal name="destroy" handler="destroy_window" swapped="no"/>
before the first <child...> tag.

Ensure that a popup has been closed with Capybara/Selenium

I am attempting to write a capybara spec which opens a popup, and then asserts that the popup has closed itself.
visit "/my_page"
click_button "Open My Popup"
within_window("MyPopup") do
# test things on MyPopup
end
sleep 1 # long enough that window.close() has been called in the popup
# ensure that MyPopup is closed
Things I've tried so far...
Counting the window handles:
page.driver.browser.window_handles.length
This remains at 2 even after the popup is closed
As this post suggests, check for the visibility of an element on the popup. This doesn't seem to work. Even though the popup has been closed, I can run assertions against the window as if it's still there, just as before:
within_window("MyPopup") do
# test things on MyPopup
end
I'm ensured that window.close is firing from the popup (by adding some JS that modifies the popup's DOM after the window.close() and asserting on those changes).
I'm fairly stumped here; anyone out there know the secret sauce for asserting that the window actually closed?
Maybe you should wait for your page has no some specific css?
It may look like this:
def wait_for(timeout = 10)
Timeout.timeout(timeout) do
loop do
break if yield
end
end
end
wait_for { page.first(:css, 'your.specific.css').nil? }

Ruby gtk2: button.sensitive = false - events still queue

I use a button on my ruby gtk2 app which starts a longish job processing and I want to disable the button while processing so that the user can't accidentally run it twice. I figured setting button.sensitive = false would do the job and tested it with the following code:
button.signal_connect(:clicked) do
button.sensitive = false
puts "clicked"
sleep 5
button.sensitive = true
end
Clicking on the button after the job has started still seems to put :clicked events on the stack so if I click the button twice more during the sleep, 'clicked' is displayed three times in the console window when I expected it would appear only once.
Do I misunderstand how this is meant to work? If it won't work the way I expect, is there a way to clear the event stack once the job is finished?
Thank you, Torimus - pointed me in the right direction. Apparently it helps if you read the documentation, specifically that of Gtk.events_pending?! Added the following after setting button.sensitive to force the main loop to do its thing:
while Gtk.events_pending? do
Gtk.main_iteration
end

Why is keypress not called after clicking on native controls?

Shoes.app do
keypress do |k|
if k==:f1
alert("Foo bar")
end
end
button "foo"
end
Pressing F1 causes the alert box to pop up but. Once i click the button "foo" i.e. if the focus changes to a native control in the app. the keypress events are no longer captured.
any way to get around it?
I am using windows xp.
This is still a bug in Shoes on Windows at the time of writing. If you can get away with doing a clear and redrawing everything you can get the keypress events back again, e.g:
Shoes.app do
def drawbutton
#holder.clear do
button "foo" do
drawbutton
end
end
end
#holder = stack
drawbutton
keypress do |k|
if k==:f1
alert("Foo bar")
end
end
end
Although this trick works for the example in your question, I'm not sure it would translate well to a real app.

Resources