glimmer-dsl-gtk
glimmer-dsl-swt
glimmer-dsl-gtk | glimmer-dsl-swt | |
---|---|---|
3 | 24 | |
19 | 98 | |
- | - | |
2.3 | 6.3 | |
10 months ago | 17 days ago | |
Ruby | Ruby | |
GNU Lesser General Public License v3.0 only | MIT License |
Stars - the number of stars that a project has on GitHub. Growth - month over month growth in stars.
Activity is a relative number indicating how actively a project is being developed. Recent commits have higher weight than older ones.
For example, an activity of 9.0 indicates that a project is amongst the top 10% of the most actively developed projects that we are tracking.
glimmer-dsl-gtk
-
2021 Was The Year of The Ruby Desktop!!!
Glimmer DSL for GTK (Ruby-GNOME Desktop Development GUI Library)
-
Glimmer DSL for GTK Tetris + Cairo Tutorial Inspired by Mohit Sindhwani
# From: https://github.com/AndyObtiva/glimmer-dsl-gtk#tetris require 'glimmer-dsl-gtk' require_relative 'tetris/model/game' class Tetris include Glimmer BLOCK_SIZE = 25 BEVEL_CONSTANT = 20 COLOR_GRAY = [192, 192, 192] def initialize @game = Model::Game.new end def launch create_gui register_observers @game.start! @main_window.show end def create_gui @main_window = window { title 'Glimmer Tetris' default_size Model::Game::PLAYFIELD_WIDTH * BLOCK_SIZE, Model::Game::PLAYFIELD_HEIGHT * BLOCK_SIZE # + 98 box(:vertical) { tetris_menu_bar box(:horizontal) { @playfield_blocks = playfield(playfield_width: @game.playfield_width, playfield_height: @game.playfield_height, block_size: BLOCK_SIZE) score_board } } on(:key_press_event) do |widget, key_event| case key_event.keyval when 65364 # down arrow @game.down! when 32 # space @game.down!(instant: true) when 65362 # up arrow case @game.up_arrow_action when :instant_down @game.down!(instant: true) when :rotate_right @game.rotate!(:right) when :rotate_left @game.rotate!(:left) end when 65361 # left arrow @game.left! when 65363 # right arrow @game.right! when 65506 # right shift @game.rotate!(:right) when 65505 # left shift @game.rotate!(:left) else # Do Nothing end end } end def register_observers observe(@game, :game_over) do |game_over| if game_over show_game_over_dialog else start_moving_tetrominos_down end end @game.playfield_height.times do |row| @game.playfield_width.times do |column| observe(@game.playfield[row][column], :color) do |new_color| color = new_color block = @playfield_blocks[row][column] block[:background_square].fill = color block[:top_bevel_edge].fill = [color[0] + 4*BEVEL_CONSTANT, color[1] + 4*BEVEL_CONSTANT, color[2] + 4*BEVEL_CONSTANT] block[:right_bevel_edge].fill = [color[0] - BEVEL_CONSTANT, color[1] - BEVEL_CONSTANT, color[2] - BEVEL_CONSTANT] block[:bottom_bevel_edge].fill = [color[0] - BEVEL_CONSTANT, color[1] - BEVEL_CONSTANT, color[2] - BEVEL_CONSTANT] block[:left_bevel_edge].fill = [color[0] - BEVEL_CONSTANT, color[1] - BEVEL_CONSTANT, color[2] - BEVEL_CONSTANT] block[:border_square].stroke = new_color == Model::Block::COLOR_CLEAR ? COLOR_GRAY : color block[:drawing_area].queue_draw false end end end Model::Game::PREVIEW_PLAYFIELD_HEIGHT.times do |row| Model::Game::PREVIEW_PLAYFIELD_WIDTH.times do |column| observe(@game.preview_playfield[row][column], :color) do |new_color| color = new_color block = @preview_playfield_blocks[row][column] block[:background_square].fill = color block[:top_bevel_edge].fill = [color[0] + 4*BEVEL_CONSTANT, color[1] + 4*BEVEL_CONSTANT, color[2] + 4*BEVEL_CONSTANT] block[:right_bevel_edge].fill = [color[0] - BEVEL_CONSTANT, color[1] - BEVEL_CONSTANT, color[2] - BEVEL_CONSTANT] block[:bottom_bevel_edge].fill = [color[0] - BEVEL_CONSTANT, color[1] - BEVEL_CONSTANT, color[2] - BEVEL_CONSTANT] block[:left_bevel_edge].fill = [color[0] - BEVEL_CONSTANT, color[1] - BEVEL_CONSTANT, color[2] - BEVEL_CONSTANT] block[:border_square].stroke = new_color == Model::Block::COLOR_CLEAR ? COLOR_GRAY : color block[:drawing_area].queue_draw end end end observe(@game, :score) do |new_score| @score_label.text = new_score.to_s end observe(@game, :lines) do |new_lines| @lines_label.text = new_lines.to_s end observe(@game, :level) do |new_level| @level_label.text = new_level.to_s end end def tetris_menu_bar menu_bar { menu_item(label: 'Game') { |mi| m = menu { check_menu_item(label: 'Pause') { on(:activate) do @game.paused = [email protected]? end } menu_item(label: 'Restart') { on(:activate) do @game.restart! end } separator_menu_item menu_item(label: 'Exit') { on(:activate) do @main_window.close end } } mi.submenu = m.gtk } menu_item(label: 'View') { |mi| m = menu { menu_item(label: 'Show High Scores') { on(:activate) do show_high_score_dialog end } menu_item(label: 'Clear High Scores') { on(:activate) do @game.clear_high_scores! end } } mi.submenu = m.gtk } menu_item(label: 'Options') { |mi| m = menu { rmi = radio_menu_item(nil, 'Instant Down on Up') { on(:activate) do @game.instant_down_on_up! end } default_rmi = radio_menu_item(rmi.group, 'Rotate Right on Up') { on(:activate) do @game.rotate_right_on_up! end } default_rmi.activate radio_menu_item(rmi.group, 'Rotate Left on Up') { on(:activate) do @game.rotate_left_on_up! end } } mi.submenu = m.gtk } menu_item(label: 'Options') { |mi| m = menu { menu_item(label: 'About') { on(:activate) do show_about_dialog end } } mi.submenu = m.gtk } } end def score_board box(:vertical) { label @preview_playfield_blocks = playfield(playfield_width: Model::Game::PREVIEW_PLAYFIELD_WIDTH, playfield_height: Model::Game::PREVIEW_PLAYFIELD_HEIGHT, block_size: BLOCK_SIZE) label label('Score') @score_label = label label label('Lines') @lines_label = label label label('Level') @level_label = label label } end def playfield(playfield_width: , playfield_height: , block_size: , &extra_content) blocks = [] box(:vertical) { playfield_height.times.map do |row| blocks << [] box(:horizontal) { playfield_width.times.map do |column| blocks.last << block(row: row, column: column, block_size: block_size) end } end extra_content&.call } blocks end def block(row: , column: , block_size: , &extra_content) block = {} bevel_pixel_size = 0.16 * block_size.to_f color = Model::Block::COLOR_CLEAR block[:drawing_area] = drawing_area { size_request block_size, block_size block[:background_square] = square(0, 0, block_size) { fill *color } block[:top_bevel_edge] = polygon(0, 0, block_size, 0, block_size - bevel_pixel_size, bevel_pixel_size, bevel_pixel_size, bevel_pixel_size) { fill color[0] + 4*BEVEL_CONSTANT, color[1] + 4*BEVEL_CONSTANT, color[2] + 4*BEVEL_CONSTANT } block[:right_bevel_edge] = polygon(block_size, 0, block_size - bevel_pixel_size, bevel_pixel_size, block_size - bevel_pixel_size, block_size - bevel_pixel_size, block_size, block_size) { fill color[0] - BEVEL_CONSTANT, color[1] - BEVEL_CONSTANT, color[2] - BEVEL_CONSTANT } block[:bottom_bevel_edge] = polygon(block_size, block_size, 0, block_size, bevel_pixel_size, block_size - bevel_pixel_size, block_size - bevel_pixel_size, block_size - bevel_pixel_size) { fill color[0] - BEVEL_CONSTANT, color[1] - BEVEL_CONSTANT, color[2] - BEVEL_CONSTANT } block[:left_bevel_edge] = polygon(0, 0, 0, block_size, bevel_pixel_size, block_size - bevel_pixel_size, bevel_pixel_size, bevel_pixel_size) { fill color[0] - BEVEL_CONSTANT, color[1] - BEVEL_CONSTANT, color[2] - BEVEL_CONSTANT } block[:border_square] = square(0, 0, block_size) { stroke *COLOR_GRAY } extra_content&.call } block end def start_moving_tetrominos_down unless @tetrominos_start_moving_down @tetrominos_start_moving_down = true GLib::Timeout.add(@game.delay*1000) do @game.down! if [email protected]_over? && [email protected]? true end end end def show_game_over_dialog message_dialog(@main_window) { |md| title 'Game Over!' text "Score: #{@game.high_scores.first.score}\nLines: #{@game.high_scores.first.lines}\nLevel: #{@game.high_scores.first.level}" on(:response) do md.destroy end }.show @game.restart! false end def show_high_score_dialog game_paused = [email protected] @game.paused = true if @game.high_scores.empty? high_scores_string = "No games have been scored yet." else high_scores_string = @game.high_scores.map do |high_score| "#{high_score.name} | Score: #{high_score.score} | Lines: #{high_score.lines} | Level: #{high_score.level}" end.join("\n") end message_dialog(@main_window) { |md| title 'High Scores' text high_scores_string on(:response) do md.destroy end }.show @game.paused = game_paused end def show_about_dialog message_dialog(@main_window) { |md| title 'About' text "Glimmer Tetris\n\nGlimmer DSL for GTK\n\nElaborate Sample\n\nCopyright (c) 2021-2022 Andy Maleh" on(:response) do md.destroy end }.show end end Tetris.new.launch
-
Glimmer DSL for GTK
Yes, I've done it! I built an entire Glimmer DSL in one day! I built Glimmer DSL for GTK after receiving an issue request for it on the Glimmer project page on GitHub!
glimmer-dsl-swt
-
Glimmer DSL for SWT Table Cell Data-Binding of Background/Foreground/Font/Image
Well, I am happy to announce that the same single line of code that data-binds a table does even more now as of the latest release made yesterday! In Glimmer DSL for SWT v4.24.3.0, that line of code also data-binds the following additional table cell properties without any change to the view code:
-
_why's Estate
There are various limitations, no doubt. I don't mean to imply otherwise. And I am not sure if it is equivalent to shoes (though glimmer-swt may be equivalent, check it out here: https://github.com/AndyObtiva/glimmer-dsl-swt although it also uses java so it's not identical to shoes either).
-
Glimmer DSL for SWT v4.24.1.0 Improved Hello, Canvas Path!
# From: https://github.com/AndyObtiva/glimmer-dsl-swt/blob/development/docs/reference/GLIMMER_SAMPLES.md#hello-canvas-path require 'glimmer-dsl-swt' class HelloCanvasPath include Glimmer::UI::Application after_body do regenerate end body { shell { grid_layout { margin_width 0 margin_height 0 margin_top 5 } text 'Hello, Canvas Path!' minimum_size 800, 700 @button = button { layout_data :center, :center, true, false text 'Regenerate' enabled false on_widget_selected do regenerate end } canvas { layout_data :fill, :fill, true, true background :white text('line', 15, 200) { foreground :red } @path1 = path { antialias :on foreground :red } text('quad', 15, 300) { foreground :dark_green } @path2 = path { antialias :on foreground :dark_green } text('cubic', 15, 400) { foreground :blue } @path3 = path { antialias :on foreground :blue } } on_widget_disposed do # safe to kill thread as data is in memory only, so no risk of data loss @thread.kill end } } def regenerate @thread = Thread.new do @button.enabled = false @path1.clear @path2.clear @path3.clear y1 = y2 = y3 = 300 700.times.each do |x| x += 55 x1 = x - 2 x2 = x - 1 x3 = x y1 = y3 y2 = y1 y3 = [[y3 + (rand*24 - 12), 0].max, 700].min @path1.content { line(x1, y1 - 100) } if x % 2 == 0 @path2.content { quad(x1, y1, x2, y2) } end if x % 3 == 0 @path3.content { cubic(x1, y1 + 100, x2, y2 + 100, x3, y3 + 100) } end sleep(0.01) end @button.enabled = true end end end HelloCanvasPath.launch
- Why Ruby is More Readable than Python
-
Glimmer DSL for SWT Hello, Canvas Data-Binding! (+ Quads & Cubics)
Glimmer DSL for SWT v4.24.0.2 has been released with the following changes:
-
Using ActiveRecord with SQLite DB in a JRuby Desktop App
SQLite is the simplest relational database to use from JRuby desktop applications, it is built-in on all platforms (Mac, Windows, and Linux), and it can be utilized conveniently via ActiveRecord, the Rails object-relational mapping library following the Active Record Enterprise Application Architecture Pattern. In fact, I have used it a few years ago to build Are We There Yet?, a small project management app, using Glimmer DSL for SWT and bidirectional data-binding. In this blog post tutorial, I cover how to configure a SQLite database and connect to it using ActiveRecord from within a Ruby desktop application, data-binding the ActiveRecord Model to the GUI View bidirectionally.
-
2021 Was The Year of The Ruby Desktop!!!
Native Executable Packaging for CRuby (Glimmer in JRuby already has Native Executable Packaging support for building Mac APP/DMG/PKG files, Windows EXE/MSI files, and Linux DEB/RPM files)
-
Glimmer Metronome - Tap-based Tempo & Up/Down Beat Toggling
Happy Glimmering!
- Quarto Game, Custom Shapes, and Canvas Shape DSL Tutorial
-
Glimmer DSL for SWT File Drag and Drop
# From: https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/docs/reference/GLIMMER_SAMPLES.md#hello-drag-and-drop require 'glimmer-dsl-swt' class Location attr_accessor :country def country_options %w[USA Canada Mexico Columbia UK Australia Germany Italy Spain] end end @location = Location.new include Glimmer shell { text 'Hello, Drag and Drop!' tab_folder { tab_item { fill_layout text 'List' list { selection <=> [@location, :country] # Option 1: Automatic Drag Data Setting drag_source true # Option 2: Manual Drag Data Setting # on_drag_set_data do |event| # drag_widget = event.widget.control # event.data = drag_widget.selection.first # end # Option 3: Full Customization of Drag Source (details at: https://www.eclipse.org/articles/Article-SWT-DND/DND-in-SWT.html) # drag_source(:drop_copy) { # options: :drop_copy, :drop_link, :drop_move, :drop_target_move # transfer :text # options: :text, :file, :rtf # # on_drag_start do |event| # drag_widget = event.widget.control.data('proxy') # obtain Glimmer widget proxy since it permits nicer syntax for setting cursor via symbol # drag_widget.cursor = :wait # end # # on_drag_set_data do |event| # drag_widget = event.widget.control # event.data = drag_widget.selection.first # end # # on_drag_finished do |event| # drag_widget = event.widget.control.data('proxy') # obtain Glimmer widget proxy since it permits nicer syntax for setting cursor via symbol # drag_widget.cursor = :arrow # end # } } list { # Option 1: Automatic Drop Data Consumption drop_target true # drop_target :unique # setting drop_target to :unique makes the list not add the same data twice # Option 2: Manual Drop Data Consumption # on_drop do |event| # drop_widget = event.widget.control # drop_widget.add(event.data) # drop_widget.select(drop_widget.items.count - 1) # end # Option 3: Full Customization of Drop Target (details at: https://www.eclipse.org/articles/Article-SWT-DND/DND-in-SWT.html) # drop_target(:drop_copy) { # options: :drop_copy, :drop_link, :drop_move, :drop_target_move # transfer :text # options: :text, :file, :rtf # # on_drag_enter do |event| # ### event.detail = DND::DROP_NONE # To reject a drop, you can set event.detail to DND::DROP_NONE # drop_widget = event.widget.control.data('proxy') # obtain Glimmer widget proxy since it permits nicer syntax for setting background via symbol # drop_widget.background = :red # end # # on_drag_leave do |event| # drop_widget = event.widget.control.data('proxy') # obtain Glimmer widget proxy since it permits nicer syntax for setting background via symbol # drop_widget.background = :white # end # # on_drop do |event| # drop_widget = event.widget.control.data('proxy') # obtain Glimmer widget proxy since it permits nicer syntax for setting background/cursor via symbol # drop_widget.background = :white # drop_widget.add(event.data) # drop_widget.select(drop_widget.items.count - 1) # drop_widget.cursor = :arrow # end # } } } tab_item { grid_layout 2, true text 'Label' label { layout_data { horizontal_span 2 } text 'Drag text from any label and drop it unto another label' } { Argentina: :green, Brazil: :red, Finland: :yellow, Sweden: :magenta, Denmark: :gray, Iceland: :cyan }.each do |country, color| label { layout_data :fill, :fill, true, true text country font height: 20 background color drag_source true drop_target true } end } tab_item { grid_layout 2, true text 'Text' label { text 'Drag' } label { text 'Drop To Insert' } text { layout_data :fill, :center, true, false text 'Text1' drag_source true } text { layout_data :fill, :center, true, false text 'Drop To Insert' drop_target true } label { text 'Drag' } label { text 'Drop To Replace' } text { layout_data :fill, :center, true, false text 'Text2' drag_source true } text { layout_data :fill, :center, true, false text 'Drop To Replace' drop_target :replace } } tab_item { grid_layout 2, true text 'Spinner' label { text 'Drag' } label { text 'Drop To Insert' } spinner { layout_data :fill, :center, true, false selection 30 drag_source true } spinner { layout_data :fill, :center, true, false drop_target true } } tab_item { fill_layout text 'File' @drop_zone_label = label(:center, :wrap) { text 'Drop One File Or More Here' background :white rectangle { foreground :black line_width 4 line_style :dash } drop_target(:drop_copy) { transfer :file on_drag_enter do |event| drop_widget = event.widget.control.data('proxy') # obtain Glimmer widget proxy since it permits nicer syntax for setting background via symbol drop_widget.background = :yellow end on_drag_leave do |event| drop_widget = event.widget.control.data('proxy') # obtain Glimmer widget proxy since it permits nicer syntax for setting background via symbol drop_widget.background = :white end on_drop do |event| drop_widget = event.widget.control.data('proxy') # obtain Glimmer widget proxy since it permits nicer syntax for setting background/cursor via symbol drop_widget.background = :white @drop_zone_label.text = event.data.to_a.join("\n") end } } } } }.open
What are some alternatives?
glimmer-dsl-libui - Glimmer DSL for LibUI - Prerequisite-Free Ruby Desktop Development Cross-Platform Native GUI Library - The Quickest Way From Zero To GUI - If You Liked Shoes, You'll Love Glimmer! - No need to pre-install any prerequisites. Just install the gem and have platform-independent GUI that just works on Mac, Windows, and Linux.
Glimmer - DSL Framework consisting of a DSL Engine and a Data-Binding Library used in Glimmer DSL for SWT (JRuby Desktop Development GUI Framework), Glimmer DSL for Opal (Pure Ruby Web GUI), Glimmer DSL for LibUI (Prerequisite-Free Ruby Desktop Development GUI Library), Glimmer DSL for Tk (Ruby Tk Desktop Development GUI Library), Glimmer DSL for GTK (Ruby-GNOME Desktop Development GUI Library), Glimmer DSL for XML (& HTML), and Glimmer DSL for CSS
glimmer-dsl-tk - Glimmer DSL for Tk (Ruby Tk Desktop Development GUI Library)
glimmer-dsl-swing - Glimmer DSL for Swing (JRuby Swing Desktop Development GUI Library) - Enables development of desktop applications using Java Swing and Java 2D, including vector graphics and AWT geometry.
RubyGnome2 - A set of bindings for the GNOME libraries to use from Ruby.
Shoes - Shoes 4 : the next version of Shoes
Glimmer DSL for Opal - Glimmer DSL for Opal (Pure-Ruby Web GUI and Auto-Webifier of Desktop Apps)
glimmer-dsl-fx - Glimmer DSL for FX (FOX Toolkit Ruby Desktop Development GUI Library)
Gladiator (Glimmer Editor) - Gladiator (short for Glimmer Editor) is a Glimmer DSL for SWT sample project under on-going development that demonstrates how to build a text editor in Ruby using Glimmer DSL for SWT (JRuby Desktop Development GUI Library). It is not intended to be a full-fledged editor by any means, yet mostly a fun educational exercise in using Glimmer. Gladiator is also a personal tool for shaping an editor exactly the way I like, with all the keyboard shortcuts I prefer. I leave building truly professional text editors to software tooling experts who would hopefully use Glimmer one day. Otherwise, I have been happily using Gladiator to develop all my open-source projects since May of 2020.