You read that right! Glimmer is finally 1.0.0
This marks a big milestone since Glimmer has outgrown its single-library roots and has become an assortment of Ruby gems that work together:
- glimmer: Glimmer Ruby DSL Engine supporting multiple DSLs
- glimmer-dsl-swt: Glimmer DSL for SWT (JRuby Desktop Development GUI Library)
- glimmer-dsl-tk: Glimmer DSL for Tk (Ruby Desktop Development GUI Library)
- glimmer-dsl-opal: Glimmer DSL for Opal (Web GUI Adapter for Desktop Apps)
- glimmer-dsl-xml: Glimmer DSL for XML (& HTML)
- glimmer-dsl-css: Glimmer DSL for CSS
- Glimmer DSL for SWT 4.17.0.0: now supports the latest SWT 4.17 (released this month) and syncs its version with it (first two numbers represent the SWT version and the last are minor and patch)
- Nebula CDateTime Glimmer Custom Widget 1.5.0.0.1: now supports the latest Nebula CDateTime 1.5.0
- Glimmer DSL for XML 1.0.0: now runs on Glimmer 1.0.0
- Glimmer DSL for CSS 1.0.0: now runs on Glimmer 1.0.0
Contributors Wanted! (Submit a Glimmer App Sample to Get Started)
(The Original Glimmer Library Since 2007. Beware of Imitators!)
Glimmer is a Ruby DSL engine with support for the following DSLs:
- glimmer-dsl-swt: Glimmer DSL for SWT (JRuby Desktop Development GUI Library)
- glimmer-dsl-tk: Glimmer DSL for Tk (Ruby Desktop Development GUI Library)
- glimmer-dsl-opal: Glimmer DSL for Opal (Web GUI Adapter for Desktop Apps)
- glimmer-dsl-xml: Glimmer DSL for XML (& HTML)
- glimmer-dsl-css: Glimmer DSL for CSS
Glimmer and/or Glimmer DSLs receive two updates per month. You can trust Glimmer with your Ruby development needs.
- Glimmer 1.0.0
- Glimmer DSL for SWT (JRuby Desktop Development GUI Library)
- Glimmer DSL for Tk (Ruby Desktop Development GUI Library)
- Glimmer DSL for Opal (Web GUI Adapter for Desktop Apps)
- Glimmer DSL for XML (& HTML)
- Glimmer DSL for CSS
- Multi-DSL Support
- Glimmer Supporting Libraries
- Glimmer Process
- Resources
- Help
- Feature Suggestions
- Change Log
- Contributing
- Contributors
- Hire Me
- License
Glimmer DSL for SWT is a native-GUI cross-platform desktop development library written in JRuby, an OS-threaded faster version of Ruby. Glimmer's main innovation is a declarative Ruby DSL that enables productive and efficient authoring of desktop application user-interfaces while relying on the robust Eclipse SWT library. Glimmer DSL for SWT additionally innovates by having built-in data-binding support, which greatly facilitates synchronizing the GUI with domain models, thus achieving true decoupling of object oriented components and enabling developers to solve business problems (test-first) without worrying about GUI concerns. To get started quickly, Glimmer DSL for SWT offers scaffolding options for Apps, Gems, and Custom Widgets. Glimmer DSL for SWT also includes native-executable packaging support, sorely lacking in other libraries, thus enabling the delivery of desktop apps written in Ruby as truly native DMG/PKG/APP files on the Mac + App Store and MSI/EXE files on Windows.
Glimmer code (from samples/hello/hello_world.rb):
include Glimmer
shell {
text "Glimmer"
label {
text "Hello, World!"
}
}.open
Run:
glimmer sample:run[hello_world]
Glimmer app:
Glimmer code (from samples/elaborate/tic_tac_toe.rb):
# ...
@tic_tac_toe_board = Board.new
@shell = shell {
text "Tic-Tac-Toe"
minimum_size 150, 178
composite {
grid_layout 3, true
(1..3).each { |row|
(1..3).each { |column|
button {
layout_data :fill, :fill, true, true
text bind(@tic_tac_toe_board[row, column], :sign)
enabled bind(@tic_tac_toe_board[row, column], :empty)
font style: :bold, height: 20
on_widget_selected {
@tic_tac_toe_board.mark(row, column)
}
}
}
}
}
}
observe(@tic_tac_toe_board, :game_status) { |game_status|
display_win_message if game_status == Board::WIN
display_draw_message if game_status == Board::DRAW
}
# ...
Run:
glimmer sample:run[tic_tac_toe]
Glimmer app:
Glimmer code (from samples/elaborate/contact_manager.rb):
# ...
shell {
text "Contact Manager"
composite {
group {
grid_layout(2, false) {
margin_width 0
margin_height 0
}
layout_data :fill, :center, true, false
text 'Lookup Contacts'
font height: 24
label {
layout_data :right, :center, false, false
text "First &Name: "
font height: 16
}
text {
layout_data :fill, :center, true, false
text bind(@contact_manager_presenter, :first_name)
on_key_pressed {|key_event|
@contact_manager_presenter.find if key_event.keyCode == swt(:cr)
}
}
label {
layout_data :right, :center, false, false
text "&Last Name: "
font height: 16
}
text {
layout_data :fill, :center, true, false
text bind(@contact_manager_presenter, :last_name)
on_key_pressed {|key_event|
@contact_manager_presenter.find if key_event.keyCode == swt(:cr)
}
}
label {
layout_data :right, :center, false, false
text "&Email: "
font height: 16
}
text {
layout_data :fill, :center, true, false
text bind(@contact_manager_presenter, :email)
on_key_pressed {|key_event|
@contact_manager_presenter.find if key_event.keyCode == swt(:cr)
}
}
composite {
row_layout {
margin_width 0
margin_height 0
}
layout_data(:right, :center, false, false) {
horizontal_span 2
}
button {
text "&Find"
on_widget_selected { @contact_manager_presenter.find }
on_key_pressed {|key_event|
@contact_manager_presenter.find if key_event.keyCode == swt(:cr)
}
}
button {
text "&List All"
on_widget_selected { @contact_manager_presenter.list }
on_key_pressed {|key_event|
@contact_manager_presenter.list if key_event.keyCode == swt(:cr)
}
}
}
}
table(:multi) { |table_proxy|
layout_data {
horizontal_alignment :fill
vertical_alignment :fill
grab_excess_horizontal_space true
grab_excess_vertical_space true
height_hint 200
}
table_column {
text "First Name"
width 80
}
table_column {
text "Last Name"
width 80
}
table_column {
text "Email"
width 200
}
items bind(@contact_manager_presenter, :results),
column_properties(:first_name, :last_name, :email)
on_mouse_up { |event|
table_proxy.edit_table_item(event.table_item, event.column_index)
}
}
}
}.open
# ...
Run:
glimmer sample:run[contact_manager]
Glimmer App:
Are We There Yet? - Small Project Tracking App
Math Bowling - Elementary Level Math Game Featuring Bowling Rules
Tcl/Tk has evolved into a practical desktop GUI toolkit due to gaining true native widgets on Mac, Windows, and Linux in Tk version 8.5.
Additionally, Ruby 3.0 Ractor (formerly known as Guilds) supports truly parallel multi-threading, making both MRI and Tk finally viable for support in Glimmer (Ruby Desktop Development GUI Library) as an alternative to JRuby on SWT.
The trade-off is that while SWT provides a plethora of high quality reusable widgets for the Enterprise (such as Nebula), Tk enables very fast app startup time via MRI Ruby.
Glimmer DSL for Tk aims to provide a DSL similar to the Glimmer DSL for SWT to enable more productive desktop development in Ruby with:
- Declarative DSL syntax that visually maps to the GUI widget hierarchy
- Convention over configuration via smart defaults and automation of low-level details
- Requiring the least amount of syntax possible to build GUI
- Bidirectional Data-Binding to declaratively wire and automatically synchronize GUI with Business Models
- Custom Widget support
- Scaffolding for new custom widgets, apps, and gems
- Native-Executable packaging on Mac, Windows, and Linux
Glimmer code (from samples/hello/hello_world.rb):
include Glimmer
root {
label {
text 'Hello, World!'
}
}.open
Run (with the glimmer-dsl-tk gem installed):
ruby -r glimmer-dsl-tk -e "require '../samples/hello/hello_world.rb'"
Glimmer app:
Glimmer code (from samples/hello/hello_tab.rb):
include Glimmer
root {
title 'Hello, Tab!'
notebook {
frame(text: 'English') {
label {
text 'Hello, World!'
}
}
frame(text: 'French') {
label {
text 'Bonjour, Univers!'
}
}
}
}.open
Run (with the glimmer-dsl-tk gem installed):
ruby -r glimmer-dsl-tk -e "require '../samples/hello/hello_tab.rb'"
Glimmer app:
Glimmer code (from samples/hello/hello_combo.rb):
# ... more code precedes
root {
title 'Hello, Combo!'
combobox { |proxy|
state 'readonly'
text bind(person, :country)
}
button { |proxy|
text "Reset Selection"
command {
person.reset_country
}
}
}.open
# ... more code follows
Run (with the glimmer-dsl-tk gem installed):
ruby -r glimmer-dsl-tk -e "require '../samples/hello/hello_combo.rb'"
Glimmer app:
Glimmer DSL for Opal is an experimental proof-of-concept web GUI adapter for Glimmer desktop apps (i.e. apps built with Glimmer DSL for SWT). It webifies them via Rails, allowing Ruby desktop apps to run on the web via Opal Ruby without changing a line of code. Apps may then be custom-styled for the web with standard CSS.
Glimmer DSL for Opal webifier successfully reuses the entire Glimmer core DSL engine in Opal Ruby inside a web browser, and as such inherits the full range of powerful Glimmer desktop data-binding capabilities for the web.
Add the following require statement to app/assets/javascripts/application.rb
require 'samples/hello/hello_computed'
Or add the Glimmer code directly if you prefer to play around with it:
class HelloComputed
class Contact
attr_accessor :first_name, :last_name, :year_of_birth
def initialize(attribute_map)
@first_name = attribute_map[:first_name]
@last_name = attribute_map[:last_name]
@year_of_birth = attribute_map[:year_of_birth]
end
def name
"#{last_name}, #{first_name}"
end
def age
Time.now.year - year_of_birth.to_i
rescue
0
end
end
end
class HelloComputed
include Glimmer
def initialize
@contact = Contact.new(
first_name: 'Barry',
last_name: 'McKibbin',
year_of_birth: 1985
)
end
def launch
shell {
text 'Hello, Computed!'
composite {
grid_layout {
num_columns 2
make_columns_equal_width true
horizontal_spacing 20
vertical_spacing 10
}
label {text 'First &Name: '}
text {
text bind(@contact, :first_name)
layout_data {
horizontal_alignment :fill
grab_excess_horizontal_space true
}
}
label {text '&Last Name: '}
text {
text bind(@contact, :last_name)
layout_data {
horizontal_alignment :fill
grab_excess_horizontal_space true
}
}
label {text '&Year of Birth: '}
text {
text bind(@contact, :year_of_birth)
layout_data {
horizontal_alignment :fill
grab_excess_horizontal_space true
}
}
label {text 'Name: '}
label {
text bind(@contact, :name, computed_by: [:first_name, :last_name])
layout_data {
horizontal_alignment :fill
grab_excess_horizontal_space true
}
}
label {text 'Age: '}
label {
text bind(@contact, :age, on_write: :to_i, computed_by: [:year_of_birth])
layout_data {
horizontal_alignment :fill
grab_excess_horizontal_space true
}
}
}
}.open
end
end
HelloComputed.new.launch
Glimmer app on the desktop (using glimmer-dsl-swt
gem):
Glimmer app on the web (using glimmer-dsl-opal
gem):
Start the Rails server:
rails s
Visit http://localhost:3000
You should see "Hello, Computed!"
Add the following require statement to app/assets/javascripts/application.rb
require 'samples/hello/hello_list_single_selection'
Or add the Glimmer code directly if you prefer to play around with it:
class Person
attr_accessor :country, :country_options
def initialize
self.country_options=["", "Canada", "US", "Mexico"]
self.country = "Canada"
end
def reset_country
self.country = "Canada"
end
end
class HelloListSingleSelection
include Glimmer
def launch
person = Person.new
shell {
composite {
list {
selection bind(person, :country)
}
button {
text "Reset"
on_widget_selected do
person.reset_country
end
}
}
}.open
end
end
HelloListSingleSelection.new.launch
Glimmer app on the desktop (using glimmer-dsl-swt
gem):
Glimmer app on the web (using glimmer-dsl-opal
gem):
Start the Rails server:
rails s
Visit http://localhost:3000
You should see "Hello, List Single Selection!"
Add the following require statement to app/assets/javascripts/application.rb
require 'samples/hello/hello_list_multi_selection'
Or add the Glimmer code directly if you prefer to play around with it:
class Person
attr_accessor :provinces, :provinces_options
def initialize
self.provinces_options=[
"",
"Quebec",
"Ontario",
"Manitoba",
"Saskatchewan",
"Alberta",
"British Columbia",
"Nova Skotia",
"Newfoundland"
]
self.provinces = ["Quebec", "Manitoba", "Alberta"]
end
def reset_provinces
self.provinces = ["Quebec", "Manitoba", "Alberta"]
end
end
class HelloListMultiSelection
include Glimmer
def launch
person = Person.new
shell {
composite {
list(:multi) {
selection bind(person, :provinces)
}
button {
text "Reset"
on_widget_selected do
person.reset_provinces
end
}
}
}.open
end
end
HelloListMultiSelection.new.launch
Glimmer app on the desktop (using glimmer-dsl-swt
gem):
Glimmer app on the web (using glimmer-dsl-opal
gem):
Start the Rails server:
rails s
Visit http://localhost:3000
You should see "Hello, List Multi Selection!"
Glimmer DSL for XML provides Ruby syntax for building XML (eXtensible Markup Language) documents.
Within the context of desktop development, Glimmer DSL for XML is useful in providing XML data for the SWT Browser widget.
Simply start with html
keyword and add HTML inside its block using Glimmer DSL syntax.
Once done, you may call to_s
, to_xml
, or to_html
to get the formatted HTML output.
Here are all the Glimmer XML DSL top-level keywords:
html
tag
: enables custom tag creation for exceptional cases by passing tag name as '_name' attributename_space
: enables namespacing html tags
Element properties are typically passed as a key/value hash (e.g. section(id: 'main', class: 'accordion')
) . However, for properties like "selected" or "checked", you must leave value nil
or otherwise pass in front of the hash (e.g. input(:checked, type: 'checkbox')
)
Example (basic HTML):
@xml = html {
head {
meta(name: "viewport", content: "width=device-width, initial-scale=2.0")
}
body {
h1 { "Hello, World!" }
}
}
puts @xml
Output:
<html><head><meta name="viewport" content="width=device-width, initial-scale=2.0" /></head><body><h1>Hello, World!</h1></body></html>
Glimmer DSL for CSS provides Ruby syntax for building CSS (Cascading Style Sheets).
Within the context of Glimmer app development, Glimmer DSL for CSS is useful in providing CSS for the SWT Browser widget.
Simply start with css
keyword and add stylesheet rule sets inside its block using Glimmer DSL syntax.
Once done, you may call to_s
or to_css
to get the formatted CSS output.
css
is the only top-level keyword in the Glimmer CSS DSL
Selectors may be specified by s
keyword or HTML element keyword directly (e.g. body
)
Rule property values may be specified by pv
keyword or underscored property name directly (e.g. font_size
)
Example:
@css = css {
body {
font_size '1.1em'
pv 'background', 'white'
}
s('body > h1') {
background_color :red
pv 'font-size', '2em'
}
}
puts @css
Output:
body{font-size:1.1em;background:white}body > h1{background-color:red;font-size:2em}
Glimmer allows mixing DSLs, which comes in handy when doing things like using a desktop Browser widget with HTML and CSS.
Glimmer DSL syntax consists mainly of:
- keywords (e.g.
table
for a table widget) - style/args (e.g. :multi as in
table(:multi)
for a multi-line selection table widget) - content (e.g.
{ table_column { text 'Name'} }
as intable(:multi) { table_column { text 'name'} }
for a multi-line selection table widget with a table column having header text property'Name'
as content)
DSLs are activated by specific keywords. For example, the html
keyword activates the Glimmer DSL for XML. Glimmer automatically recognizes top-level keywords in each DSL and activates the DSL accordingly. Once done processing a nested DSL top-level keyword, Glimmer switches back to the prior DSL automatically.
Here is a list of notable 3rd party gems used by Glimmer and Glimmer DSLs:
- jeweler: generates app gems during Glimmer Scaffolding
- logging: provides extra logging capabilities not available in Ruby Logger such as multi-threaded buffered asynchronous logging (to avoid affecting app performance) and support for multiple appenders such as stdout, syslog, and log files (the last one is needed on Windows where syslog is not supported)
- nested_inherited_jruby_include_package: makes included SWT/Java packages available to all classes/modules that mix in the Glimmer module without having to manually reimport
- os: provides OS detection capabilities (e.g.
OS.mac?
orOS.windows?
) to write cross-platform code inexpensively - puts_debuggerer: helps in troubleshooting when adding
require 'pd'
and using thepd
command instead ofputs
orp
(also#pd_inspect
or#pdi
instead of#inspect
) - rake: used to implement and execute
glimmer
commands - rake-tui: Rake Text-based User Interface. Allows navigating rake tasks with arrow keys and filtering task list by typing to quickly find an run a rake task.
- super_module: used to cleanly write the Glimmer::UI:CustomWidget and Glimmer::UI::CustomShell modules
- text-table: renders textual data in a textual table for the command-line interface of Glimmer
- warbler: converts a Glimmer app into a Java JAR file during packaging
Glimmer Process is the lightweight software development process used for building Glimmer libraries and Glimmer apps, which goes beyond Agile, rendering all Agile processes obsolete. Glimmer Process is simply made up of 7 guidelines to pick and choose as necessary until software development needs are satisfied.
Learn more by reading the GPG (Glimmer Process Guidelines)
- Code Master Blog
- JRuby Cookbook by Justin Edelson & Henry Liu
- MountainWest RubyConf 2011 Video
- RubyConf 2008 Video
- InfoQ Article
- DZone Tutorial
You may submit issues on GitHub.
Click here to submit an issue.
These features have been suggested. You might see them in a future version of Glimmer. You are welcome to contribute more feature suggestions.
Glimmer DSL Engine specific tasks are at:
Contributors Wanted!
If you would like to contribute to Glimmer, please study up on Glimmer and SWT, run all Glimmer samples, and build a small sample app (perhaps from this TODO list) to add to glimmer-dsl-swt Hello or Elaborate samples via a Pull Request. Once done, contact me on Chat.
You may apply for contributing to any of these Glimmer DSL gems whether you prefer to focus on the desktop or web:
- glimmer-dsl-swt: Glimmer DSL for SWT (JRuby Desktop Development GUI Library)
- glimmer-dsl-tk: Glimmer DSL for Tk (Ruby Desktop Development GUI Library)
- glimmer-dsl-opal: Glimmer DSL for Opal (Web GUI Adapter for Desktop Apps)
- glimmer-dsl-xml: Glimmer DSL for XML (& HTML)
- glimmer-dsl-css: Glimmer DSL for CSS
- Andy Maleh (Founder)
- Dennis Theisen (Contributor)
Click here to view contributor commits.
If your company would like to invest fulltime in further development of the Glimmer open-source project, hire me.
Copyright (c) 2007-2020 - Andy Maleh.
--
Glimmer logo was made by Freepik from www.flaticon.com
No comments:
Post a Comment