librelist archives

« back to archive

Layout management in Green Shoes

Layout management in Green Shoes

From:
Ola Leifler
Date:
2013-04-13 @ 21:09
Hi,

I've used Green Shoes to make a simple GUI for updating databases that I 
plan to use for standalone DB upgrade packages we ship to our customers. I
love the overall simplicity of the Shoes approach to GUI building, and I 
very much like that I can have a toolkit bundled in a Gem that can be 
built into a standalone exe without external dependencies. However, I've 
found that there are some few cases when the layout management doesn't 
work as I would have expected, and the style/font management doesn't apply
to elements of a slot if applied to the slot.

I've extracted an example below where both the font management needs to be
applied to each element, hence the overloaded "para" method, and absolute 
positioning is applied to a number of elements to prevent them from being 
overlayed on top of others.

I've noted some segmentation faults with Green Shoes 1.1.373 on Windows 7,
so I use 1.1.367 in the example below, and some other crash forced me to 
use Ruby Gtk 1.1.5. Are there any changes in recent versions of Green 
Shoes and/or Ruby Gtk that could cause this?

Best regards
Ola


# -*- coding: utf-8 -*-
require 'green_shoes'
require 'optparse'

class Conf
  class << self
    attr_accessor :server, :db, :username, :password, :file_name

    def product_name
      "My product"
    end

    def product
      options[:product] || "product"
    end

    def server
      @server ||= options[:server]
    end

    def db
      @db ||= options[:db]
    end

    def username
      @username ||= options[:username]
    end

    def password
      @password ||= options[:password]
    end

    def sspi?
      options[:sspi]
    end

    def batch?
      options[:batch]
    end
    
    def backup_dir
      Etc.systmpdir
    end

    def sql_dir
      "."
    end

    def options
      @options ||= {}
      # Ignore command line arguments when running this script as a
      # standalone executable compiled by Ocra, in which case the
      # environment variable OCRA_EXECUTABLE is set to $0
      if @options.empty? && !ENV["OCRA_EXECUTABLE"]
        OptionParser.new do |opts|
          opts.banner = "Usage: ruby #{__FILE__} [options]"      
          opts.on("-p", "--product PRODUCT", "Select product") do |p|
            options[:product] = p
          end
          opts.on("-s", "--server SERVER", "Select server") do |p|
            options[:server] = p
          end
          opts.on("-d", "--database DATABASE", "Select database") do |p|
            options[:db] = p
          end
          opts.on("-u", "--username USERNAME", "SQL Server username") do |p|
            options[:username] = p
          end
          opts.on("-P", "--password PASSWORD", "SQL Server password") do |p|
            options[:password] = p
          end
          opts.on("-E", "--sspi", "Use Windows Authentication (SSPI)") do |p|
            options[:sspi] = true
          end
          opts.on("-b", "--batch", "Upgrade and close immediately") do |p|
            options[:batch] = true
          end
        end.parse!
      end
      @options
    end

  end
end

class Shoes
  class App   
    def icon filename=nil
      filename.nil? ? win.icon : win.icon = filename
      Gtk::Window.set_default_icon(win.icon)
    end
  end
end

# Only call Gtk.main_quit once to avoid warnings or errors related to
# "no Gtk main loop running"
class << Gtk; attr_accessor :running; end

class Object

  # Make sure Green Shoes does not crash on exit when exit is called with status
  def exit(status=true)
    if Gtk.running
      Gtk.main_quit
      File.delete Shoes::TMP_PNG_FILE if File.exist? Shoes::TMP_PNG_FILE
      Gtk.running=false
    end
  end
  
  # Override Green Shoes "confirm" method to provide dialog with a custom title
  def confirm title, msg
    $dde = true
    dialog = Gtk::Dialog.new(
      title, 
      get_win,
      Gtk::Dialog::MODAL | Gtk::Dialog::DESTROY_WITH_PARENT,
      [Gtk::Stock::OK, Gtk::Dialog::RESPONSE_ACCEPT],
      [Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_REJECT]
    )
    dialog.vbox.add Gtk::Label.new msg
    dialog.set_size_request 500, 100
    dialog.show_all
    ret = dialog.run == Gtk::Dialog::RESPONSE_ACCEPT
    dialog.destroy
    ret
  end

end

class DbUpgrade

  class << self
    def create(conf,product)
      new(conf,product)
    end
  end

  attr_accessor :callback, :num_upgrade_files

  def initialize(conf,product)
    @num_upgrade_files=10
  end

  def run
    # Mockup DB updater
    @num_upgrade_files.times do |i| 
      callback.call "#{i}_upgrade.sql" if callback
      sleep 1
    end
  end

end

class UpgradeGUI < Shoes
  url "/", :select
  url "/progress", :progress_window

  def current_setting
    "'#{Conf.server}/#{Conf.db}' for #{Conf.product_name}"
  end
  
  def initialize
    @step=0
    Gtk.running=true
  end

  def select
    background rgb(70,21,107)
    # Skip the form if command line parameters are provided
    if Conf.server && 
        Conf.db && 
        (Conf.sspi? || (Conf.username && Conf.password))
      visit "/progress"
    end
    flow do
      # Absolute positioning seems necessary here, why?
      stack left: 10, top: 100 do
        para "Server"
        @server = edit_line
        @server.text=Conf.server if Conf.server
        para "DB"
        @db = edit_line
        @db.text=Conf.db if Conf.db

        authentication_form

        button "Upgrade" do       
          Conf.server=@server.text
          Conf.db=@db.text
          if ! @use_sspi.checked?
            Conf.username=@username.text
            Conf.password=@password.text
          end
          if confirm("Confirm upgrade", 
                     "Upgrade DB #{current_setting}?")
            visit "/progress"
          end
        end
      end
    end
  end

  def progress_window
    
    background rgb(70,21,107)
    stack do
      para "Upgrading the DB #{current_setting}"
      @upgrade_file=stack { para "..." }
      # Absolute positioning seems necessary here, why?
      @p = progress top: 300, left: 50, width: 400
      
    end # stack
    
    run_upgrade
    
  end # progress_window

  def run_upgrade
    upgrader = DbUpgrade.create Conf, Conf.product
    @num_steps = upgrader.num_upgrade_files
    upgrader.callback = lambda do |file|
      @step+=1
      @update_file_name = file
    end
    upgrade_thread=Thread.new { upgrader.run }
    
    @animate = animate do
      @p.fraction = @step / @num_steps.to_f
      update_name @update_file_name
      if @p.fraction==1.0
        finish_upgrade
      end # if              
    end # animate

  end

  def username_password
    para "Username"
    @username = edit_line
    @username.text=Conf.username if Conf.username
    para "Password"
    @password = edit_line :secret => true
    @password.text=Conf.password if Conf.password
  end

  def para(text)
    # there seems to be a bug related to setting font styles, so I
    # cannot set styles on a slot but must set it on all elements
    super text, stroke: white, family: "Calibri"
  end

  def authentication_form
    flow do
      para "Windows authentication"
      @use_sspi = check do |c|
        if ! c.checked?
          @user_pwd.append do
            stack do
              username_password
            end
          end
        else
          @user_pwd.clear
        end
      end
      @use_sspi.checked=Conf.sspi?
      # Hide the username/password form if Windows authentication is
      # to be used
      @user_pwd = @use_sspi.checked? ? stack : stack { username_password }
    end
  end

  def update_name(name)
    @upgrade_file.clear
    @upgrade_file.append  { para name }
  end

  def finish_upgrade
    @animate.stop

    # Quit immediately when invoked by Ocra, so we can compile
    # this script without manual intervention
    if Conf.batch?
      exit
    end

    update_name "Done!"
    flow do
      # Absolute positioning seems necessary here, why?
      button "Close" ,top: 400, left: 150 do
        exit
      end
    end # flow 
  end

end

if $0 == __FILE__
  Shoes.app(title: "DB Upgrade tool for #{Conf.product_name}", 
            width: 400, 
            height: 500)
end


 

Re: [shoes] Layout management in Green Shoes

From:
ashbb
Date:
2013-04-14 @ 07:19
Hi Ola,

Thank you for developing a fantastic Green Shoes app! :-D

> I've found that there are some few cases when the layout management
doesn't
> work as I would have expected, and the style/font management doesn't
apply
> to elements of a slot if applied to the slot.
I ran your code with Green Shoes 1.1.367 on my Windows 7.

Watch this: http://www.rin-shun.com/shoes/ola_db_upgrade.swf.html

I'm using Ruby/GTK2 1.2.6.

I've not read your code yet. So, I don't figure out your problems (your
expected layout) well. The position of a progress bar or a close button?

Could you explain in more detail?

Regards,
ashbb

Re: [shoes] Layout management in Green Shoes

From:
Ola Leifler
Date:
2013-04-14 @ 08:26
Hi ashbb,

Thank you for your quick reply!

14 apr 2013 kl. 09.19 skrev ashbb:

> Hi Ola,
> 
> Thank you for developing a fantastic Green Shoes app! :-D
> 
> > I've found that there are some few cases when the layout management doesn't
> > work as I would have expected, and the style/font management doesn't apply 
> > to elements of a slot if applied to the slot.
> I ran your code with Green Shoes 1.1.367 on my Windows 7.
> 
> Watch this: http://www.rin-shun.com/shoes/ola_db_upgrade.swf.html
> 
> I'm using Ruby/GTK2 1.2.6.
> 

Ok, maybe I should try to upgrade from Ruby/Gtk 1.1.5 and see if the 
segfault error is resolved in 1.2.6. Maybe it resolves other issues as 
well..

> I've not read your code yet. So, I don't figure out your problems (your 
> expected layout) well. The position of a progress bar or a close button?
> 
> Could you explain in more detail?
> 

The elements I've had issues with are commented with

# Absolute positioning seems necessary here, why?

For example, the progress bar in the progress window is positioned at the 
very top, over the text, unless I provide absolute coordinates.

/Ola

Re: [shoes] Layout management in Green Shoes

From:
Ola Leifler
Date:
2013-04-14 @ 16:28
Hi again,

It seems that, with Gtk 1.2.6 and Green Shoes 1.1.373, the issue with the 
layout of a progress bar is resolved. However, that version introduces 
some error on quit:

C:/Ruby193/lib/ruby/gems/1.9.1/gems/green_shoes-1.1.373/lib/shoes/ruby.rb:
line 130
   Gtk-CRITICAL **:gtk_main_quit: assertion `main_loops != NULL' failed

Is Gtk.main_quit called twice?

I've redefined Object#exit to accomodate for an optional exit status 
(provided by Ocra when creating a standalone exe) and introduced a guard 
so as to not call Gtk.main_quit unless there is a running Gtk main loop 
(Gtk.running), but this does not seem to help? Can you reproduce this 
error on quit?

/Ola

14 apr 2013 kl. 10.26 skrev Ola Leifler:

> Hi ashbb,
> 
> Thank you for your quick reply!
> 
> 14 apr 2013 kl. 09.19 skrev ashbb:
> 
>> Hi Ola,
>> 
>> Thank you for developing a fantastic Green Shoes app! :-D
>> 
>> > I've found that there are some few cases when the layout management doesn't
>> > work as I would have expected, and the style/font management doesn't apply 
>> > to elements of a slot if applied to the slot.
>> I ran your code with Green Shoes 1.1.367 on my Windows 7.
>> 
>> Watch this: http://www.rin-shun.com/shoes/ola_db_upgrade.swf.html
>> 
>> I'm using Ruby/GTK2 1.2.6.
>> 
> 
> Ok, maybe I should try to upgrade from Ruby/Gtk 1.1.5 and see if the 
segfault error is resolved in 1.2.6. Maybe it resolves other issues as 
well..
> 
>> I've not read your code yet. So, I don't figure out your problems (your 
>> expected layout) well. The position of a progress bar or a close button?
>> 
>> Could you explain in more detail?
>> 
> 
> The elements I've had issues with are commented with
> 
> # Absolute positioning seems necessary here, why?
> 
> For example, the progress bar in the progress window is positioned at 
the very top, over the text, unless I provide absolute coordinates.
> 
> /Ola

Re: [shoes] Layout management in Green Shoes

From:
Ola Leifler
Date:
2013-04-14 @ 18:34
14 apr 2013 kl. 18.28 skrev Ola Leifler:

> Hi again,
> 
> It seems that, with Gtk 1.2.6 and Green Shoes 1.1.373, the issue with 
the layout of a progress bar is resolved.

Sorry, my bad, the error with overlayed elements still persists (progress 
bar showed on top of text) with the latest versions of the gems.

> However, that version introduces some error on quit:
> 
> 
C:/Ruby193/lib/ruby/gems/1.9.1/gems/green_shoes-1.1.373/lib/shoes/ruby.rb:
line 130
>    Gtk-CRITICAL **:gtk_main_quit: assertion `main_loops != NULL' failed
> 
> Is Gtk.main_quit called twice?
> 
> I've redefined Object#exit to accomodate for an optional exit status 
(provided by Ocra when creating a standalone exe) and introduced a guard 
so as to not call Gtk.main_quit unless there is a running Gtk main loop 
(Gtk.running), but this does not seem to help? Can you reproduce this 
error on quit?
> 
> /Ola
> 
> 14 apr 2013 kl. 10.26 skrev Ola Leif ler:
> 
>> Hi ashbb,
>> 
>> Thank you for your quick reply!
>> 
>> 14 apr 2013 kl. 09.19 skrev ashbb:
>> 
>>> Hi Ola,
>>> 
>>> Thank you for developing a fantastic Green Shoes app! :-D
>>> 
>>> > I've found that there are some few cases when the layout management doesn't
>>> > work as I would have expected, and the style/font management doesn't apply 
>>> > to elements of a slot if applied to the slot.
>>> I ran your code with Green Shoes 1.1.367 on my Windows 7.
>>> 
>>> Watch this: http://www.rin-shun.com/shoes/ola_db_upgrade.swf.html
>>> 
>>> I'm using Ruby/GTK2 1.2.6.
>>> 
>> 
>> Ok, maybe I should try to upgrade from Ruby/Gtk 1.1.5 and see if the 
segfault error is resolved in 1.2.6. Maybe it resolves other issues as 
well..
>> 
>>> I've not read your code yet. So, I don't figure out your problems (your 
>>> expected layout) well. The position of a progress bar or a close button?
>>> 
>>> Could you explain in more detail?
>>> 
>> 
>> The elements I've had issues with are commented with
>> 
>> # Absolute positioning seems necessary here, why?
>> 
>> For example, the progress bar in the progress window is positioned at 
the very top, over the text, unless I provide absolute coordinates.
>> 
>> /Ola
> 

Re: [shoes] Layout management in Green Shoes

From:
Sebastjan Hribar
Date:
2013-04-14 @ 20:28
Hi Ola,

great program and it runs fine on my ubuntu 12.04 laptop with Ruby 1.9.3 
and GTK 2.24.10 without any overlaying.

However, I also get this error:

/home/sebah/.rvm/gems/ruby-1.9.3-p392/gems/green_shoes-1.1.373/lib/shoes/ruby.rb: 
line 130
    Gtk-CRITICAL **:IA__gtk_main_quit: assertion `main_loops != NULL' failed


I haven't changed green shoes version yet so that's probably why.

kind regards
seba

Re: [shoes] Layout management in Green Shoes

From:
ashbb
Date:
2013-04-15 @ 11:08
Hi Ola, Seba and folks,

About an error on quit.
Look at this: https://github.com/ashbb/green_shoes/issues/72
I have no solution for now. :(
So, please use 1.1.367.

About three "why?"s.
1st: Slot(stack and flow) can't move to the position you set by absolute
coordinates. Use margin style like this:

Shoes.app do
  stack margin_left: 50, margin_top: 100 do
    stack do
      para 'hello'
      edit_line
    end
  end
end

2nd: You have to set absolute coordinates for progress bar as same as
oval/rect
shape.

3rd: Need to use append method. Try out this snippet.

Shoes.app do
  s = stack do
    3.times{para 'hello'}
  end
  timer(3){s.append{button 'button'}}
end

The above three are restrictions (differences from Red Shoes).
Sorry, they are not mentioned in Green Shoes manual. xx-P

ashbb

Re: [shoes] Layout management in Green Shoes

From:
Ola Leifler
Date:
2013-04-15 @ 18:42
Hi,

15 apr 2013 kl. 13.08 skrev ashbb:

> Hi Ola, Seba and folks,
> 
> About an error on quit.
> Look at this: https://github.com/ashbb/green_shoes/issues/72
> I have no solution for now. :(
> So, please use 1.1.367.
> 
> About three "why?"s.
> 1st: Slot(stack and flow) can't move to the position you set by absolute
> coordinates. Use margin style like this:
> 
> Shoes.app do
>   stack margin_left: 50, margin_top: 100 do
>     stack do
>       para 'hello'
>       edit_line
>     end
>   end
> end
> 
> 2nd: You have to set absolute coordinates for progress bar as same as oval/rect
> shape.
> 


Ah, that explains things :)


> 3rd: Need to use append method. Try out this snippet.
> 
> Shoes.app do
>   s = stack do
>     3.times{para 'hello'}
>   end
>   timer(3){s.append{button 'button'}}
> end
> 
> The above three are restrictions (differences from Red Shoes).
> Sorry, they are not mentioned in Green Shoes manual. xx-P

I also noticed that if I tried to use replace instead of clear/append, the
update thread seemed to hang.

Thanks for notifying my of these restrictions and keep up the good work 
with Green Shoes!

/Ola