Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
DSL for make a simple ruby GUI application
HTML Ruby Batchfile
Branch: master

update

latest commit 193b88403c
@glurp authored
Failed to load latest commit information.
bin creation
lib width entry and bug n field()
media creation
samples creation
spec whait one second for dynvar notification verificatio
tmp creation
.travis.yml supress gstreamer dependency
CHANGELOG.txt update
Gemfile test dependency
LICENSE.html update txt
README.md update
Rakefile.rb no giti on linux
Ruiby.gemspec dependancy 2.2.3 or more
VERSION update
doc.html update
gitc.bat ceation

README.md

Ruiby

Build Status Gem Version

A DSL for building simple GUI ruby application. Based on gtk.

Resources

Code: http://github.com/glurp/Ruiby

Doc: Reference+Exemples.

Gem : https://rubygems.org/gems/Ruiby

Status

NEW : 1.32.5 !! 05-12-2015

WARNING !!!! current ruby-gtk3 version 2.2.4 is buggy on Windows ruby/32, bt ok wirh Ruby/x64 !!!

TODO :

  • make a demo of a gadget: REST/gui canvas/dialog/config
  • grid : get selection double-click, debug...
  • waiting gtk3 > 2.2.4
  • Gadget api: atuel gadget are cairo drawing => to be encapsuled
  • editor / executor : console/canvas/widget+help
  • refactor samples demos with last improve: dynvar/autoslot...
  • resolve 100% gtk3 deprecated warning
  • corrections in ruiby_require(?)
  • complete treeview and tree_grid,
  • complete rspec => 99% coverage ?

Installation

1) system

Install Ruby 2.x

2) install Ruiby (Ruiby install ruby-gtk3 which install gtk3 libs)

> gem install Ruiby

> ruiby_demo             # check good installation with gtk3 (default)
> ruiby_sketchi          # write and test ruiby code

3) if you need video/gstreamer, install gst/clutter :

  > gem install gstreamer 
  > gem install clutter-gtk
  > gem install clutter-gstreamer

Here a working gem config on windows (15-September-2014, ruby 2.0.0p0) :

 pkg-config  1.1.4
       cairo 1.12.8
      glib2  2.2.0
 gobject-introspection  2.2.0
       gio2  2.2.0
        atk  2.2.0
      pango  2.2.0
 gdk_pixbuf2  2.2.0
       gdk3  2.2.0
       gtk3  2.2.0
  gstreamer  2.2.0
 cairo-gobject  2.2.0
    clutter  2.2.0
clutter-gtk  2.2.0
 clutter-gstreamer  2.2.0

Usage

DSL is usable via inherit, include, Ruiby.app bloc, or one-liner command.

By inherit:

class Application < Ruiby_gtk
    def initialize(t,w,h)
        super(t,w,h)
    end 
    def component()
      stack do
        ...
      end
    end
    .....your code....
end
Ruiby.start { Win.new("application title",350,10) }

By include, calling ruiby_component() :

class Win < Gtk::Window
    include Ruiby
    def initialize(t,w,h)
        super()
        add(@vb=VBox.new(false, 2)) 
        ....
    end 
    def add_a_ruiby_button() 
        ruiby_component do
            append_to(@vb) do 
                button("Hello Word #{@vb.children.size}") {
                    add_a_ruiby_button() 
                }
            end
        end
    end
end
Ruiby.start { Win.new("application title",350,10) }

Autonomous DSL, for little application :

require  'Ruiby'
Ruiby.app do
    stack do
        . . . 
    end
end

And, for very little application ('~' are replaced by guillemet):

> ruiby   button(~Continue ? ~) "{  exit!(0) }"
> ruiby   fields([%w{a b},%w{b c},%w{c d}]) { "|a,b,c|" p [a,b,c] if a; exit!(a ?0:1) }
> ruiby -width 100  -height 300 -title "Please, select a file" \
             l=list(~Files :~);l.set_data Dir.glob(~*~) ;  \
             buttoni(~Selected~) { puts l.selection ; exit!(0) } ;\
             buttoni(~Annul~) { exit!(1) }

Require

Simple usage with gtk3 :

require 'Ruiby'

Usage with Event Machine: preload event-machine before Ruiby :

require 'em-proxy'
require 'Ruiby'

Warning : EM.run is done when starting mainloop, after creation of window(s). So, if you need initialization of event-machine callback, do it in component(), in a after(0):

Ruiby.app do
  ....
  after(0) { EventMachine::start_server().. { ... } }
end

See samples/spygui.rb, for exemple of gui with EM.

Threading

Ruiby does not have confidence in gtk multi threading, so all Ruiby commands must be done in main thread context. A Ruiby delegate is provided in Kernel module for support multi-threading

A Queue is polled by main-window thread :

  • main window poll Queue , messagers are proc to be instance_eval() in the main window context
  • everywere, a thread can invoke invoke_gui {ruiby code}. this send to the main queue the proc, which will be evaluated asynchroniously

instance_eval is avoided in ruiby. He is used only for thread invoker : gui_invoke().

require_relative '../lib/Ruiby'
class App < Ruiby_gtk
    def initialize
        super("Testing Ruiby for Threading",150,0)
        threader(10)
        Thread.new { A.new.run }
    end
    def component()        
      stack do
        sloti(label("Hello, this is Thread test !"))
        stack { @lab=stacki { } }
      end
    end # endcomponent

end
class A
    def run
        loop do
            sleep(1) # thread...
            there=self 
            gui_invoke { append_to(@lab) { sloti( 
                    label( there.aaa )  # ! instance_eval on main window
            )  } }
        end
    end 
    def aaa() Time.now.to_s  end
end

Ruiby.start { App.new }

Observed Object/Variable

Dynamic variable

Often, a widget (an entry, a label, a slider...) show the value of a ruby variable. each time a code mofify this variable, it must modify the widget, and vice-versa... This is very tyring :)

With data binding, this notifications are done by the framework

So DynVar can be used for representing a value variable which is dynamics, ie. which must notify widgets which show the variable state.

So we can do :

  foo=DynVar.new(0)
  entry(foo)
  islider(foo)
  ....
  foo.value=43  
  ....

That works ! the entry and the slider will be updated.

A move on slider will update foo.value and the entry. Idem for a key in the entry : slider and foo.value will be updated.

if you want to be notified for your own traitment, you can observ a DynVar :

  foo.observ { |v| @socket.puts(v.to_s) rescue nil }

Here, a modification of foo variable will be send on the network...

Warning !! the block will always be executed in the main thread context (mainloop gtk context). So DynVar is a ressource internal to Ruiby framework.

Widget which accept DynVar are : entry, ientry, islider, label, check_button,

must be extend to button, togglebutton, combo, radio_button ... list, grid,...

Dynamic Object

Often, this kind of Dyn variables are members of a 'record', which should be organised by an Ruby Object (a Struct...)

So DynObject create a class, which is organised by a hash :

  • packet of variable name
  • put initial value for each
  • each variable will be a DynVar
  FooClass=make_DynClass("v1" => 1 , "v2" => 2, "s1" => 'Hello...')
  foo=FooClass.new( "s1" => Time.now.to_s ) # default value of s1 variable is replaced 
  ...
  label(" foo: ") ; entry(foo.s1)
  islider(foo.v1)
  islider(foo.v2)
  ....
  button("4x33") { Thread.new { foo.s1.value="s4e33" ; foo.v2.value=33 ; foo.v1.value=4} }
  ....

Dynamic Stock Object

DynObject can be persisted to filesystem : use make_StockDynObject, and instantiate with an object persistant ID

  FooClass=make_StockDynClass("v1"=> 1 , "v2" => 2, "s1" => 'Hello...')
  foo1=FooClass.new( "foo1" , "s1" => Time.now.to_s )
  foo2=FooClass.new( "foo2" , "s1" => (Time.now+10).to_s )
  ....
  button("Exit") { ruiby_exit} # on exit, foo1 and foo2 will been saved to {tmpdir}/<$0>.storage  
  ....

make_StockDynObject do both : Class creation and class instanciation.

  foo=make_StockDynObject("v1"=> 1 , "v2" => 2, "s1" => 'Hello...')
  ....
  button(foo.s1) { foo.s1.value= prompt("new S1 value ?")}
  button("Exit") { ruiby_exit} # on exit, foo1 and foo2 will been saved to {tmpdir}/<$0>.storage  
  ....

License

LGPL, CC BY-SA

Exemples

see samples in "./samples" directory (run all.rb) cd sampSee at end of Doc reference : Ex.

Something went wrong with that request. Please try again.