glimmer-dsl-swt 0.6.4 → 0.6.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +3 -2
- data/VERSION +1 -1
- data/lib/ext/glimmer/config.rb +17 -1
- data/lib/glimmer-dsl-swt.rb +5 -9
- data/lib/glimmer/data_binding/table_items_binding.rb +4 -1
- data/lib/glimmer/dsl/swt/exec_expression.rb +7 -1
- data/lib/glimmer/launcher.rb +37 -23
- data/lib/glimmer/rake_task.rb +61 -73
- data/lib/glimmer/scaffold.rb +19 -3
- data/lib/glimmer/swt/shell_proxy.rb +0 -1
- data/lib/glimmer/swt/style_constantizable.rb +1 -0
- data/lib/glimmer/swt/table_proxy.rb +16 -4
- data/lib/glimmer/swt/widget_proxy.rb +53 -37
- data/samples/elaborate/user_profile.rb +55 -0
- metadata +42 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f8cb96b5eda19eb65af0d9fa5b8f79050a341f5f148e78c13a27b18c07cef083
|
4
|
+
data.tar.gz: 6e925dab92f1ea52557c2f9078a1c7b0b0068225644da25ce81677e6d4b9fca4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f23a464b36497e60e0379b90a1f17f630d84c0ff01359a89a9dd8cfe008306bbbd779c1b456c3ff17cdbaae331b795b1241597d57b653e063c3aa8af7f463ce7
|
7
|
+
data.tar.gz: 02a87c762461b89acac3385dfb2ab4ea0089e6b3b4320f60e843758e5b28df2036cb4524e8b0851b792576401857de3e77e9981bf92ee98205ddfadf425cbf8a
|
data/README.md
CHANGED
@@ -1,11 +1,11 @@
|
|
1
|
-
# [<img src="https://raw.githubusercontent.com/AndyObtiva/glimmer/master/images/glimmer-logo-hi-res.png" height=85 />](https://github.com/AndyObtiva/glimmer) Glimmer DSL for SWT 0.6.
|
1
|
+
# [<img src="https://raw.githubusercontent.com/AndyObtiva/glimmer/master/images/glimmer-logo-hi-res.png" height=85 />](https://github.com/AndyObtiva/glimmer) Glimmer DSL for SWT 0.6.9 (JRuby Desktop GUI)
|
2
2
|
[![Gem Version](https://badge.fury.io/rb/glimmer-dsl-swt.svg)](http://badge.fury.io/rb/glimmer-dsl-swt)
|
3
3
|
[![Travis CI](https://travis-ci.com/AndyObtiva/glimmer-dsl-swt.svg?branch=master)](https://travis-ci.com/github/AndyObtiva/glimmer-dsl-swt)
|
4
4
|
[![Coverage Status](https://coveralls.io/repos/github/AndyObtiva/glimmer-dsl-swt/badge.svg?branch=master)](https://coveralls.io/github/AndyObtiva/glimmer-dsl-swt?branch=master)
|
5
5
|
[![Maintainability](https://api.codeclimate.com/v1/badges/aaf1cba142dd351f84bd/maintainability)](https://codeclimate.com/github/AndyObtiva/glimmer-dsl-swt/maintainability)
|
6
6
|
[![Join the chat at https://gitter.im/AndyObtiva/glimmer](https://badges.gitter.im/AndyObtiva/glimmer.svg)](https://gitter.im/AndyObtiva/glimmer?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
7
7
|
|
8
|
-
[Glimmer](https://github.com/AndyObtiva/glimmer) DSL for [SWT](https://www.eclipse.org/swt/) enables desktop development with [Glimmer](https://github.com/AndyObtiva/glimmer).
|
8
|
+
[Glimmer](https://github.com/AndyObtiva/glimmer) DSL for [SWT](https://www.eclipse.org/swt/) enables desktop development with [Glimmer](https://github.com/AndyObtiva/glimmer) in [JRuby](https://www.jruby.org/).
|
9
9
|
|
10
10
|
[Glimmer](https://github.com/AndyObtiva/glimmer) is a native-GUI cross-platform desktop development library written in Ruby. Glimmer's main innovation is a JRuby DSL that enables productive and efficient authoring of desktop application user-interfaces while relying on the robust Eclipse SWT library. Glimmer additionally innovates by having built-in data-binding support to greatly facilitate synchronizing the GUI with domain models. As a result, that achieves true decoupling of object oriented components, enabling developers to solve business problems without worrying about GUI concerns, or alternatively drive development GUI-first, and then write clean business models test-first afterwards.
|
11
11
|
|
@@ -15,6 +15,7 @@ Other [Glimmer](https://github.com/AndyObtiva/glimmer) DSL gems:
|
|
15
15
|
- [glimmer-dsl-opal](https://github.com/AndyObtiva/glimmer-dsl-opal): Glimmer DSL for Opal (Web GUI Adapter for Desktop Apps)
|
16
16
|
- [glimmer-dsl-xml](https://github.com/AndyObtiva/glimmer-dsl-xml): Glimmer DSL for XML (& HTML)
|
17
17
|
- [glimmer-dsl-css](https://github.com/AndyObtiva/glimmer-dsl-css): Glimmer DSL for CSS (Cascading Style Sheets)
|
18
|
+
- [glimmer-dsl-tk](https://github.com/AndyObtiva/glimmer-dsl-tk): Glimmer DSL for Tk (MRI Ruby Desktop GUI)
|
18
19
|
|
19
20
|
## Example
|
20
21
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.6.
|
1
|
+
0.6.9
|
data/lib/ext/glimmer/config.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'glimmer/config'
|
2
|
+
|
1
3
|
module Glimmer
|
2
4
|
module Config
|
3
5
|
DEFAULT_IMPORT_SWT_PACKAGES = [
|
@@ -9,6 +11,11 @@ module Glimmer
|
|
9
11
|
'org.eclipse.swt.custom',
|
10
12
|
'org.eclipse.swt.dnd',
|
11
13
|
]
|
14
|
+
|
15
|
+
# This may be configured with extra sample directories from custom widget/shell gems
|
16
|
+
# following the convention of a `samples/subdirectory` where subdirectory is the
|
17
|
+
# custom widget/shell name or something representative of a group of samples (e.g. c_date_time).
|
18
|
+
SAMPLE_DIRECTORIES = []
|
12
19
|
|
13
20
|
class << self
|
14
21
|
# Tells Glimmer to import SWT packages into including class (default: true)
|
@@ -48,6 +55,10 @@ module Glimmer
|
|
48
55
|
|
49
56
|
def logging_appender_options
|
50
57
|
@@logging_appender_options = {async: true, auto_flushing: 500, write_size: 500, flush_period: 60, immediate_at: [:error, :fatal], layout: logging_layout} unless defined? @@logging_appender_options
|
58
|
+
# TODO make this a glimmer command option
|
59
|
+
if ENV['GLIMMER_LOGGER_ASYNC'].to_s.downcase == 'false'
|
60
|
+
@@logging_appender_options.merge!(async: false, auto_flushing: 1, immediate_at: [:debug, :info, :warn, :error, :fatal])
|
61
|
+
end
|
51
62
|
@@logging_appender_options
|
52
63
|
end
|
53
64
|
|
@@ -90,12 +101,16 @@ module Glimmer
|
|
90
101
|
end
|
91
102
|
logger.appenders = appenders
|
92
103
|
end
|
104
|
+
|
93
105
|
end
|
106
|
+
|
94
107
|
end
|
108
|
+
|
95
109
|
end
|
110
|
+
|
96
111
|
end
|
97
112
|
|
98
|
-
Glimmer::Config.reset_logger!
|
113
|
+
Glimmer::Config.reset_logger! unless ENV['GLIMMER_LOGGER_ENABLED'].to_s.downcase == 'false'
|
99
114
|
if ENV['GLIMMER_LOGGER_LEVEL']
|
100
115
|
# if glimmer log level is being overridden for debugging purposes, then disable async logging making logging immediate
|
101
116
|
Glimmer::Config.logging_appender_options = Glimmer::Config.logging_appender_options.merge(async: false, auto_flushing: 1)
|
@@ -106,6 +121,7 @@ if ENV['GLIMMER_LOGGER_LEVEL']
|
|
106
121
|
puts e.message
|
107
122
|
end
|
108
123
|
end
|
124
|
+
|
109
125
|
Glimmer::Config.excluded_keyword_checkers << lambda do |method_symbol, *args|
|
110
126
|
method = method_symbol.to_s
|
111
127
|
result = false
|
data/lib/glimmer-dsl-swt.rb
CHANGED
@@ -2,15 +2,11 @@ $LOAD_PATH.unshift(File.expand_path('..', __FILE__))
|
|
2
2
|
|
3
3
|
# External requires
|
4
4
|
require 'java'
|
5
|
-
if ENV['
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
require 'logging'
|
11
|
-
require 'nested_inherited_jruby_include_package'
|
12
|
-
require 'super_module'
|
13
|
-
end
|
5
|
+
require 'puts_debuggerer' if ("#{ENV['pd']}#{ENV['PD']}").to_s.downcase.include?('true')
|
6
|
+
require 'glimmer'
|
7
|
+
require 'logging'
|
8
|
+
require 'nested_inherited_jruby_include_package'
|
9
|
+
require 'super_module'
|
14
10
|
|
15
11
|
# Internal requires
|
16
12
|
require 'ext/glimmer/config'
|
@@ -30,7 +30,10 @@ module Glimmer
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def call(new_model_collection=nil)
|
33
|
-
new_model_collection = @model_binding.evaluate_property # this ensures applying converters (e.g. :on_read)
|
33
|
+
new_model_collection = @model_binding.evaluate_property # this ensures applying converters (e.g. :on_read)
|
34
|
+
table_cells = @table.swt_widget.items.map {|item| @table.column_properties.size.times.map {|i| item.get_text(i)} }
|
35
|
+
model_cells = new_model_collection.to_a.map {|m| @table.cells_for(m)}
|
36
|
+
return if table_cells == model_cells
|
34
37
|
if new_model_collection and new_model_collection.is_a?(Array)
|
35
38
|
@table_items_observer_registration&.unobserve
|
36
39
|
@table_items_observer_registration = observe(new_model_collection, @column_properties)
|
@@ -20,7 +20,13 @@ module Glimmer
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def interpret(parent, keyword, *args, &block)
|
23
|
-
Glimmer::SWT::DisplayProxy.instance.swt_display.send(exec_operation
|
23
|
+
Glimmer::SWT::DisplayProxy.instance.swt_display.send(exec_operation) do |*args|
|
24
|
+
begin
|
25
|
+
block.call(*args)
|
26
|
+
rescue => e
|
27
|
+
Glimmer::Config.logger.error e.full_message
|
28
|
+
end
|
29
|
+
end
|
24
30
|
end
|
25
31
|
end
|
26
32
|
end
|
data/lib/glimmer/launcher.rb
CHANGED
@@ -1,39 +1,30 @@
|
|
1
1
|
require 'fileutils'
|
2
|
-
|
3
|
-
require_relative 'rake_task'
|
2
|
+
require 'os'
|
4
3
|
|
5
4
|
module Glimmer
|
6
5
|
class Launcher
|
7
6
|
OPERATING_SYSTEMS_SUPPORTED = ["mac", "windows", "linux"]
|
8
7
|
|
9
|
-
|
8
|
+
TEXT_USAGE = <<~MULTI_LINE_STRING
|
10
9
|
Glimmer (Ruby Desktop Development GUI Library) - JRuby Gem: glimmer-dsl-swt v#{File.read(File.expand_path('../../../VERSION', __FILE__))}
|
11
10
|
Usage: glimmer [--quiet] [--debug] [--log-level=VALUE] [[ENV_VAR=VALUE]...] [[-jruby-option]...] (application.rb or task[task_args]) [[application2.rb]...]
|
12
11
|
|
13
|
-
Runs Glimmer applications
|
14
|
-
|
15
|
-
Either a single task or one or more applications may be specified.
|
16
|
-
|
17
|
-
When a task is specified, it runs via rake. Some tasks take arguments in square brackets.
|
18
|
-
|
19
|
-
Available tasks are below (if you do not see any, please add `require 'glimmer/rake_task'` to Rakefile and rerun or run rake -T):
|
20
|
-
MULTI_LINE_STRING
|
21
|
-
|
22
|
-
TEXT_USAGE_SUFFIX = <<~MULTI_LINE_STRING
|
12
|
+
Runs Glimmer applications and tasks.
|
23
13
|
|
24
14
|
When applications are specified, they are run using JRuby,
|
25
15
|
automatically preloading the glimmer Ruby gem and SWT jar dependency.
|
26
16
|
|
27
|
-
Optionally, extra Glimmer options, JRuby options and environment variables may be passed in.
|
17
|
+
Optionally, extra Glimmer options, JRuby options, and/or environment variables may be passed in.
|
28
18
|
|
29
19
|
Glimmer options:
|
30
20
|
- "--quiet" : Does not announce file path of Glimmer application being launched
|
31
21
|
- "--debug" : Displays extra debugging information, passes "--debug" to JRuby, and enables debug logging
|
32
22
|
- "--log-level=VALUE" : Sets Glimmer's Ruby logger level ("ERROR" / "WARN" / "INFO" / "DEBUG"; default is none)
|
33
23
|
|
34
|
-
|
24
|
+
Tasks are run via rake. Some tasks take arguments in square brackets.
|
35
25
|
|
36
|
-
|
26
|
+
Available tasks are below (if you do not see any, please add `require 'glimmer/rake_task'` to Rakefile and rerun or run rake -T):
|
27
|
+
|
37
28
|
MULTI_LINE_STRING
|
38
29
|
|
39
30
|
GLIMMER_LIB_LOCAL = File.expand_path(File.join('lib', 'glimmer-dsl-swt.rb'))
|
@@ -108,6 +99,7 @@ module Glimmer
|
|
108
99
|
if the_glimmer_lib == GLIMMER_LIB_LOCAL
|
109
100
|
devmode_require = '-r puts_debuggerer '
|
110
101
|
end
|
102
|
+
require_relative 'rake_task'
|
111
103
|
rake_tasks = Rake.application.tasks.map(&:to_s).map {|t| t.sub('glimmer:', '')}
|
112
104
|
|
113
105
|
# handle a bash quirk with calling package[msi] while there is a "packages" directory locally (it passes package[msi] as packages)
|
@@ -180,14 +172,36 @@ module Glimmer
|
|
180
172
|
end
|
181
173
|
|
182
174
|
def display_usage
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
175
|
+
puts TEXT_USAGE
|
176
|
+
display_tasks
|
177
|
+
end
|
178
|
+
|
179
|
+
def display_tasks
|
180
|
+
if OS.windows?
|
181
|
+
tasks = Rake.application.tasks
|
182
|
+
task_lines = tasks.reject do |task|
|
183
|
+
task.comment.nil?
|
184
|
+
end.map do |task|
|
185
|
+
max_task_size = tasks.map(&:name_with_args).map(&:size).max + 1
|
186
|
+
task_name = task.name_with_args.sub('glimmer:', '')
|
187
|
+
line = "glimmer #{task_name.ljust(max_task_size)} # #{task.comment}"
|
188
|
+
bound = TTY::Screen.width - 6
|
189
|
+
line.size <= bound ? line : "#{line[0..(bound - 3)]}..."
|
190
|
+
end
|
191
|
+
puts task_lines.to_a
|
192
|
+
else
|
193
|
+
require 'rake-tui'
|
194
|
+
require 'tty-screen'
|
195
|
+
require_relative 'rake_task'
|
196
|
+
Rake::TUI.run(branding_header: nil, prompt_question: 'Select a Glimmer task to run:') do |task, tasks|
|
197
|
+
max_task_size = tasks.map(&:name_with_args).map(&:size).max + 1
|
198
|
+
task_name = task.name_with_args.sub('glimmer:', '')
|
199
|
+
line = "glimmer #{task_name.ljust(max_task_size)} # #{task.comment}"
|
200
|
+
bound = TTY::Screen.width - 6
|
201
|
+
line.size <= bound ? line : "#{line[0..(bound - 3)]}..."
|
202
|
+
end
|
189
203
|
end
|
190
|
-
end
|
204
|
+
end
|
191
205
|
|
192
206
|
def extract_application_paths(options)
|
193
207
|
options.select do |option|
|
data/lib/glimmer/rake_task.rb
CHANGED
@@ -2,102 +2,91 @@ require 'rake'
|
|
2
2
|
|
3
3
|
require_relative 'package'
|
4
4
|
|
5
|
+
ENV['GLIMMER_LOGGER_ENABLED'] = 'false'
|
6
|
+
require_relative '../ext/glimmer/config.rb'
|
7
|
+
|
8
|
+
Glimmer::Config::SAMPLE_DIRECTORIES << File.expand_path('../../../samples/hello', __FILE__)
|
9
|
+
Glimmer::Config::SAMPLE_DIRECTORIES << File.expand_path('../../../samples/elaborate', __FILE__)
|
10
|
+
|
5
11
|
namespace :glimmer do
|
6
12
|
namespace :sample do
|
13
|
+
task :requires do
|
14
|
+
require 'text-table'
|
15
|
+
require 'facets/string/titlecase'
|
16
|
+
require 'facets/string/underscore'
|
17
|
+
|
18
|
+
require_relative 'launcher'
|
19
|
+
end
|
20
|
+
|
21
|
+
task :glimmer_gems do
|
22
|
+
glimmer_cw_gems = Gem.find_latest_files('glimmer-cw-*')
|
23
|
+
glimmer_cs_gems = Gem.find_latest_files('glimmer-cs-*')
|
24
|
+
glimmer_dsl_gems = Gem.find_latest_files('glimmer-dsl-*')
|
25
|
+
glimmer_gem_lib_files = glimmer_cw_gems + glimmer_cs_gems + glimmer_dsl_gems
|
26
|
+
glimmer_gem_lib_files = glimmer_gem_lib_files.map {|file| file.sub(/\.rb$/, '')}.uniq.reject {|file| file.include?('glimmer-cs-gladiator')}
|
27
|
+
glimmer_gem_lib_files.each {|file| require file}
|
28
|
+
end
|
29
|
+
|
7
30
|
desc 'Runs a Glimmer internal sample [included in gem]. If no name is supplied, it runs all samples.'
|
8
|
-
task :run, [:name] => :requires do |t, args|
|
31
|
+
task :run, [:name] => [:requires, :glimmer_gems] do |t, args|
|
9
32
|
name = args[:name]
|
10
33
|
name = name.underscore.downcase unless name.nil?
|
11
|
-
samples =
|
34
|
+
samples = Glimmer::Config::SAMPLE_DIRECTORIES.map {|dir| Dir.glob(File.join(dir, '*.rb'))}.reduce(:+).sort
|
12
35
|
samples = samples.select {|path| path.include?("#{name}.rb")} unless name.nil?
|
13
36
|
Rake::Task['glimmer:sample:code'].invoke(name) if samples.size == 1
|
14
37
|
Glimmer::Launcher.new(samples << '--quiet=false').launch
|
15
38
|
end
|
16
39
|
|
17
|
-
namespace :run do
|
18
|
-
task :hello do
|
19
|
-
samples = Dir.glob(File.expand_path('../../../samples/hello/*.rb', __FILE__)).sort
|
20
|
-
Glimmer::Launcher.new(samples << '--quiet=false').launch
|
21
|
-
end
|
22
|
-
|
23
|
-
task :elaborate do
|
24
|
-
samples = Dir.glob(File.expand_path('../../../samples/elaborate/*.rb', __FILE__)).sort
|
25
|
-
Glimmer::Launcher.new(samples << '--quiet=false').launch
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
40
|
desc 'Lists Glimmer internal samples [included in gem]. Filters by query if specified (query is optional)'
|
30
|
-
task :list, [:query] do |t, args|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
namespace :list do
|
36
|
-
task :hello, [:query] => :requires do |t, args|
|
37
|
-
array_of_arrays = Dir.glob(File.expand_path('../../../samples/hello/*.rb', __FILE__)).map do |path|
|
41
|
+
task :list, [:query] => [:requires, :glimmer_gems] do |t, args|
|
42
|
+
Glimmer::Config::SAMPLE_DIRECTORIES.each do |dir|
|
43
|
+
sample_group_name = File.basename(dir)
|
44
|
+
human_sample_group_name = sample_group_name.underscore.titlecase
|
45
|
+
array_of_arrays = Dir.glob(File.join(dir, '*.rb')).map do |path|
|
38
46
|
File.basename(path, '.rb')
|
39
47
|
end.select do |path|
|
40
48
|
args[:query].nil? || path.include?(args[:query])
|
41
49
|
end.map do |path|
|
42
50
|
[path, path.underscore.titlecase, "#{'bin/' if Glimmer::Launcher.dev_mode?}glimmer sample:run[#{path}]"]
|
43
51
|
end.sort
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
52
|
+
if array_of_arrays.empty?
|
53
|
+
puts "No Glimmer #{human_sample_group_name} Samples match the query."
|
54
|
+
else
|
55
|
+
puts
|
56
|
+
puts " Glimmer #{human_sample_group_name} Samples:"
|
57
|
+
puts Text::Table.new(
|
58
|
+
:head => %w[Name Description Run],
|
59
|
+
:rows => array_of_arrays,
|
60
|
+
:horizontal_padding => 1,
|
61
|
+
:vertical_boundary => ' ',
|
62
|
+
:horizontal_boundary => ' ',
|
63
|
+
:boundary_intersection => ' '
|
64
|
+
)
|
65
|
+
end
|
54
66
|
end
|
55
|
-
|
56
|
-
task :elaborate, [:query] => :requires do |t, args|
|
57
|
-
array_of_arrays = Dir.glob(File.expand_path('../../../samples/elaborate/*.rb', __FILE__)).map do |path|
|
58
|
-
File.basename(path, '.rb')
|
59
|
-
end.select do |path|
|
60
|
-
args[:query].nil? || path.include?(args[:query])
|
61
|
-
end.map do |path|
|
62
|
-
[path, path.underscore.titlecase, "#{'bin/' if Glimmer::Launcher.dev_mode?}glimmer sample:run[#{path}]"]
|
63
|
-
end.sort
|
64
|
-
puts
|
65
|
-
puts " Glimmer Elaborate Samples (run all via: #{'bin/' if Glimmer::Launcher.dev_mode?}glimmer sample:run:elaborate):"
|
66
|
-
puts Text::Table.new(
|
67
|
-
:head => %w[Name Description Run],
|
68
|
-
:rows => array_of_arrays,
|
69
|
-
:horizontal_padding => 1,
|
70
|
-
:vertical_boundary => ' ',
|
71
|
-
:horizontal_boundary => ' ',
|
72
|
-
:boundary_intersection => ' '
|
73
|
-
)
|
74
|
-
end
|
75
67
|
end
|
76
|
-
|
68
|
+
|
77
69
|
desc 'Outputs code for a Glimmer internal sample [included in gem] (name is required)'
|
78
|
-
task :code, [:name] => :requires do |t, args|
|
79
|
-
|
70
|
+
task :code, [:name] => [:requires, :glimmer_gems] do |t, args|
|
71
|
+
require 'tty-markdown' unless OS.windows?
|
72
|
+
samples = Glimmer::Config::SAMPLE_DIRECTORIES.map {|dir| Dir.glob(File.join(dir, '*.rb'))}.reduce(:+).sort
|
80
73
|
sample = samples.detect {|path| path.include?("#{args[:name].to_s.underscore.downcase}.rb")}
|
81
74
|
sample_additional_files = Dir.glob(File.join(sample.sub('.rb', ''), '**', '*.rb'))
|
82
|
-
([sample] + sample_additional_files).
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
75
|
+
code = ([sample] + sample_additional_files).map do |file|
|
76
|
+
<<~RUBY
|
77
|
+
|
78
|
+
# #{file}
|
79
|
+
|
80
|
+
#{File.read(file)}
|
81
|
+
|
82
|
+
# # #
|
83
|
+
|
84
|
+
RUBY
|
85
|
+
end.join("\n")
|
86
|
+
code = TTY::Markdown.parse("```ruby\n#{code}\n```") unless OS.windows?
|
87
|
+
puts code
|
91
88
|
end
|
92
89
|
|
93
|
-
task :requires do
|
94
|
-
require 'text-table'
|
95
|
-
require 'facets/string/titlecase'
|
96
|
-
require 'facets/string/underscore'
|
97
|
-
|
98
|
-
require_relative 'launcher'
|
99
|
-
end
|
100
|
-
|
101
90
|
end
|
102
91
|
|
103
92
|
namespace :package do
|
@@ -137,7 +126,6 @@ namespace :glimmer do
|
|
137
126
|
Rake::Task['glimmer:package:native'].execute(args)
|
138
127
|
end
|
139
128
|
|
140
|
-
|
141
129
|
desc 'Scaffold Glimmer application directory structure to build a new app'
|
142
130
|
task :scaffold, [:app_name] do |t, args|
|
143
131
|
require_relative 'scaffold'
|
data/lib/glimmer/scaffold.rb
CHANGED
@@ -4,6 +4,8 @@ require 'facets'
|
|
4
4
|
|
5
5
|
# TODO refactor to nest under RakeTask namespace
|
6
6
|
|
7
|
+
MAIN_OBJECT = self
|
8
|
+
|
7
9
|
class Scaffold
|
8
10
|
class << self
|
9
11
|
include FileUtils
|
@@ -179,6 +181,13 @@ class Scaffold
|
|
179
181
|
def custom_shell_gem(custom_shell_name, namespace)
|
180
182
|
gem_name = "glimmer-cs-#{compact_name(custom_shell_name)}"
|
181
183
|
gem_summary = "#{human_name(custom_shell_name)} - Glimmer Custom Shell"
|
184
|
+
begin
|
185
|
+
custom_shell_keyword = dsl_widget_name(custom_shell_name)
|
186
|
+
MAIN_OBJECT.method(custom_shell_keyword)
|
187
|
+
return puts("CustomShell keyword `#{custom_shell_keyword}` is unavailable (occupied by a built-in Ruby method)! Please pick a different name.")
|
188
|
+
rescue NameError
|
189
|
+
# No Op (keyword is not taken by a built in Ruby method)
|
190
|
+
end
|
182
191
|
if namespace
|
183
192
|
gem_name += "-#{compact_name(namespace)}"
|
184
193
|
gem_summary += " (#{human_name(namespace)})"
|
@@ -350,12 +359,19 @@ class Scaffold
|
|
350
359
|
end
|
351
360
|
|
352
361
|
def gem_bin_file(gem_name, custom_shell_name, namespace)
|
362
|
+
# TODO change this so that it does not mix Glimmer unto the main object
|
353
363
|
<<~MULTI_LINE_STRING
|
354
364
|
require_relative '../lib/#{gem_name}'
|
355
365
|
|
356
|
-
|
366
|
+
class #{class_name(custom_shell_name)}App
|
367
|
+
include Glimmer
|
368
|
+
|
369
|
+
def open
|
370
|
+
#{dsl_widget_name(custom_shell_name)}.open
|
371
|
+
end
|
372
|
+
end
|
357
373
|
|
358
|
-
#{
|
374
|
+
#{class_name(custom_shell_name)}App.new.open
|
359
375
|
MULTI_LINE_STRING
|
360
376
|
end
|
361
377
|
|
@@ -394,7 +410,7 @@ class Scaffold
|
|
394
410
|
" -name '#{human_name(custom_shell_name)}'" +
|
395
411
|
" -title '#{human_name(custom_shell_name)}'" +
|
396
412
|
" -Bmac.CFBundleName='#{human_name(custom_shell_name)}'" +
|
397
|
-
" -Bmac.CFBundleIdentifier='org.#{namespace ? compact_name(namespace) : compact_name(custom_shell_name)}.application.#{compact_name(custom_shell_name)}'"
|
413
|
+
" -Bmac.CFBundleIdentifier='org.#{namespace ? compact_name(namespace) : compact_name(custom_shell_name)}.application.#{compact_name(custom_shell_name).capitalize}'"
|
398
414
|
# " -BlicenseType=" +
|
399
415
|
# " -Bmac.category=" +
|
400
416
|
# " -Bmac.signing-key-developer-id-app="
|
@@ -36,7 +36,8 @@ module Glimmer
|
|
36
36
|
class << self
|
37
37
|
def editors
|
38
38
|
@editors ||= {
|
39
|
-
|
39
|
+
# ensure editor can work with string keys not just symbols (leave one string in for testing)
|
40
|
+
'text' => {
|
40
41
|
widget_value_property: :text,
|
41
42
|
editor_gui: lambda do |args, model, property, table_proxy|
|
42
43
|
table_proxy.table_editor.minimumHeight = 20
|
@@ -209,9 +210,19 @@ module Glimmer
|
|
209
210
|
@editor = args
|
210
211
|
end
|
211
212
|
|
213
|
+
def cells_for(model)
|
214
|
+
column_properties.map {|property| model.send(property)}
|
215
|
+
end
|
216
|
+
|
217
|
+
def cells
|
218
|
+
column_count = @table.column_properties.size
|
219
|
+
swt_widget.items.map {|item| column_count.times.map {|i| item.get_text(i)} }
|
220
|
+
end
|
221
|
+
|
212
222
|
def sort
|
213
223
|
return unless sort_property && (sort_type || sort_block || sort_by_block)
|
214
224
|
array = model_binding.evaluate_property
|
225
|
+
array = array.sort_by(&:hash) # this ensures consistent subsequent sorting in case there are equivalent sorts to avoid an infinite loop
|
215
226
|
# Converting value to_s first to handle nil cases. Should work with numeric, boolean, and date fields
|
216
227
|
if sort_block
|
217
228
|
sorted_array = array.sort(&sort_block)
|
@@ -293,6 +304,7 @@ module Glimmer
|
|
293
304
|
end
|
294
305
|
|
295
306
|
def edit_table_item(table_item, column_index, before_write: nil, after_write: nil, after_cancel: nil)
|
307
|
+
require 'facets/hash/symbolize_keys'
|
296
308
|
return if table_item.nil?
|
297
309
|
model = table_item.data
|
298
310
|
property = column_properties[column_index]
|
@@ -304,10 +316,10 @@ module Glimmer
|
|
304
316
|
editor_config = editor_config.to_a
|
305
317
|
editor_widget_options = editor_config.last.is_a?(Hash) ? editor_config.last : {}
|
306
318
|
editor_widget_arg_last_index = editor_config.last.is_a?(Hash) ? -2 : -1
|
307
|
-
editor_widget = editor_config[0] || :text
|
319
|
+
editor_widget = (editor_config[0] || :text).to_sym
|
308
320
|
editor_widget_args = editor_config[1..editor_widget_arg_last_index]
|
309
321
|
model_editing_property = editor_widget_options[:property] || property
|
310
|
-
widget_value_property = TableProxy::editors[editor_widget][:widget_value_property]
|
322
|
+
widget_value_property = TableProxy::editors.symbolize_keys[editor_widget][:widget_value_property]
|
311
323
|
|
312
324
|
@cancel_edit = lambda do |event=nil|
|
313
325
|
@cancel_in_progress = true
|
@@ -344,7 +356,7 @@ module Glimmer
|
|
344
356
|
end
|
345
357
|
|
346
358
|
content {
|
347
|
-
@table_editor_widget_proxy = TableProxy::editors[editor_widget][:editor_gui].call(editor_widget_args, model, model_editing_property, self)
|
359
|
+
@table_editor_widget_proxy = TableProxy::editors.symbolize_keys[editor_widget][:editor_gui].call(editor_widget_args, model, model_editing_property, self)
|
348
360
|
}
|
349
361
|
@table_editor.setEditor(@table_editor_widget_proxy.swt_widget, table_item, column_index)
|
350
362
|
rescue => e
|
@@ -25,6 +25,7 @@ module Glimmer
|
|
25
25
|
"arrow" => [:arrow],
|
26
26
|
"button" => [:push],
|
27
27
|
"checkbox" => [:check],
|
28
|
+
"check" => [:check],
|
28
29
|
"drag_source" => [:drop_copy],
|
29
30
|
"drop_target" => [:drop_copy],
|
30
31
|
"list" => [:border, :v_scroll],
|
@@ -41,21 +42,17 @@ module Glimmer
|
|
41
42
|
|
42
43
|
DEFAULT_INITIALIZERS = {
|
43
44
|
"composite" => lambda do |composite|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
45
|
+
if composite.get_layout.nil?
|
46
|
+
layout = GridLayout.new
|
47
|
+
layout.marginWidth = 15
|
48
|
+
layout.marginHeight = 15
|
49
|
+
composite.layout = layout
|
50
|
+
end
|
48
51
|
end,
|
49
52
|
"scrolled_composite" => lambda do |scrolled_composite|
|
50
53
|
scrolled_composite.expand_horizontal = true
|
51
54
|
scrolled_composite.expand_vertical = true
|
52
55
|
end,
|
53
|
-
"shell" => lambda do |shell|
|
54
|
-
layout = FillLayout.new
|
55
|
-
layout.marginWidth = 15
|
56
|
-
layout.marginHeight = 15
|
57
|
-
shell.layout = layout
|
58
|
-
end,
|
59
56
|
"table" => lambda do |table|
|
60
57
|
table.setHeaderVisible(true)
|
61
58
|
table.setLinesVisible(true)
|
@@ -64,17 +61,35 @@ module Glimmer
|
|
64
61
|
table_column.setWidth(80)
|
65
62
|
end,
|
66
63
|
"group" => lambda do |group|
|
67
|
-
group.
|
64
|
+
group.layout = GridLayout.new if group.get_layout.nil?
|
68
65
|
end,
|
69
66
|
}
|
70
67
|
|
68
|
+
KEYWORD_ALIASES = {
|
69
|
+
'radio' => 'button',
|
70
|
+
'checkbox' => 'button',
|
71
|
+
'check' => 'button',
|
72
|
+
'toggle' => 'button',
|
73
|
+
'arrow' => 'button',
|
74
|
+
}
|
75
|
+
|
71
76
|
class << self
|
72
|
-
|
73
|
-
|
77
|
+
# Instantiates the right WidgetProxy subclass for passed in keyword
|
78
|
+
# Args are: keyword, parent, swt_widget_args (including styles)
|
79
|
+
def create(*init_args, swt_widget: nil)
|
80
|
+
return swt_widget.get_data('proxy') if swt_widget&.get_data('proxy')
|
81
|
+
keyword, parent, args = init_args
|
82
|
+
selected_widget_proxy_class = widget_proxy_class(keyword || underscored_widget_name(swt_widget))
|
83
|
+
if init_args.empty?
|
84
|
+
selected_widget_proxy_class.new(swt_widget: swt_widget)
|
85
|
+
else
|
86
|
+
selected_widget_proxy_class.new(*init_args)
|
87
|
+
end
|
74
88
|
end
|
75
89
|
|
76
90
|
def widget_proxy_class(keyword)
|
77
91
|
begin
|
92
|
+
keyword = KEYWORD_ALIASES[keyword] if KEYWORD_ALIASES[keyword]
|
78
93
|
class_name = "#{keyword.camelcase(:upper)}Proxy".to_sym
|
79
94
|
Glimmer::SWT.const_get(class_name)
|
80
95
|
rescue
|
@@ -88,11 +103,16 @@ module Glimmer
|
|
88
103
|
end
|
89
104
|
|
90
105
|
attr_reader :parent_proxy, :swt_widget, :drag_source_proxy, :drop_target_proxy, :drag_source_style, :drag_source_transfer, :drop_target_transfer
|
91
|
-
|
106
|
+
|
92
107
|
# Initializes a new SWT Widget
|
93
108
|
#
|
109
|
+
# It is preferred to use `::create` method instead since it instantiates the
|
110
|
+
# right subclass per widget keyword
|
111
|
+
#
|
112
|
+
# keyword, parent, swt_widget_args (including styles)
|
113
|
+
#
|
94
114
|
# Styles is a comma separate list of symbols representing SWT styles in lower case
|
95
|
-
def initialize(*init_args, swt_widget: nil)
|
115
|
+
def initialize(*init_args, swt_widget: nil)
|
96
116
|
if swt_widget.nil?
|
97
117
|
underscored_widget_name, parent, args = init_args
|
98
118
|
@parent_proxy = parent
|
@@ -103,11 +123,14 @@ module Glimmer
|
|
103
123
|
@swt_widget = swt_widget
|
104
124
|
underscored_widget_name = self.class.underscored_widget_name(@swt_widget)
|
105
125
|
parent_proxy_class = self.class.widget_proxy_class(self.class.underscored_widget_name(@swt_widget.parent))
|
106
|
-
|
126
|
+
parent = swt_widget.parent
|
127
|
+
@parent_proxy = parent.get_data('proxy') || parent_proxy_class.new(swt_widget: parent)
|
128
|
+
end
|
129
|
+
if @swt_widget&.get_data('proxy').nil?
|
130
|
+
@swt_widget.set_data('proxy', self)
|
131
|
+
DEFAULT_INITIALIZERS[underscored_widget_name]&.call(@swt_widget)
|
132
|
+
@parent_proxy.post_initialize_child(self)
|
107
133
|
end
|
108
|
-
@swt_widget.set_data('proxy', self)
|
109
|
-
DEFAULT_INITIALIZERS[underscored_widget_name]&.call(@swt_widget)
|
110
|
-
@parent_proxy.post_initialize_child(self)
|
111
134
|
end
|
112
135
|
|
113
136
|
# Subclasses may override to perform post initialization work on an added child
|
@@ -315,7 +338,7 @@ module Glimmer
|
|
315
338
|
|
316
339
|
# This supports widgets in and out of basic SWT
|
317
340
|
def self.swt_widget_class_for(underscored_widget_name)
|
318
|
-
underscored_widget_name =
|
341
|
+
underscored_widget_name = KEYWORD_ALIASES[underscored_widget_name] if KEYWORD_ALIASES[underscored_widget_name]
|
319
342
|
swt_widget_name = underscored_widget_name.camelcase(:upper)
|
320
343
|
swt_widget_class = eval(swt_widget_name)
|
321
344
|
unless swt_widget_class.ancestors.include?(org.eclipse.swt.widgets.Widget)
|
@@ -342,11 +365,7 @@ module Glimmer
|
|
342
365
|
end
|
343
366
|
|
344
367
|
def has_style?(style)
|
345
|
-
|
346
|
-
comparison = SWTProxy[style]
|
347
|
-
rescue
|
348
|
-
comparison = DNDProxy[style]
|
349
|
-
end
|
368
|
+
comparison = interpret_style(style)
|
350
369
|
(@swt_widget.style & comparison) == comparison
|
351
370
|
end
|
352
371
|
|
@@ -457,6 +476,7 @@ module Glimmer
|
|
457
476
|
rescue => e
|
458
477
|
Glimmer::Config.logger.debug {"Neither WidgetProxy nor #{swt_widget.class.name} can handle the method ##{method}"}
|
459
478
|
super
|
479
|
+
# TODO consider get_attribute too
|
460
480
|
end
|
461
481
|
|
462
482
|
def respond_to?(method, *args, &block)
|
@@ -468,21 +488,17 @@ module Glimmer
|
|
468
488
|
private
|
469
489
|
|
470
490
|
def style(underscored_widget_name, styles)
|
471
|
-
styles = [styles].flatten.compact
|
472
|
-
if styles.empty?
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
DNDProxy[*styles]
|
479
|
-
end
|
480
|
-
end
|
491
|
+
styles = [styles].flatten.compact
|
492
|
+
styles = default_style(underscored_widget_name) if styles.empty?
|
493
|
+
interpret_style(*styles)
|
494
|
+
end
|
495
|
+
|
496
|
+
def interpret_style(*styles)
|
497
|
+
SWTProxy[*styles] rescue DNDProxy[*styles]
|
481
498
|
end
|
482
499
|
|
483
500
|
def default_style(underscored_widget_name)
|
484
|
-
|
485
|
-
SWTProxy[styles] rescue DNDProxy[styles]
|
501
|
+
DEFAULT_STYLES[underscored_widget_name] || [:none]
|
486
502
|
end
|
487
503
|
|
488
504
|
def ruby_attribute_setter(attribute_name)
|
@@ -0,0 +1,55 @@
|
|
1
|
+
include Glimmer
|
2
|
+
|
3
|
+
shell {
|
4
|
+
text "User Profile"
|
5
|
+
|
6
|
+
composite {
|
7
|
+
grid_layout 2, false
|
8
|
+
|
9
|
+
group {
|
10
|
+
text "Name"
|
11
|
+
grid_layout 2, false
|
12
|
+
layout_data :fill, :fill, true, true
|
13
|
+
label {text "First"}; text {text "Bullet"}
|
14
|
+
label {text "Last"}; text {text "Tooth"}
|
15
|
+
}
|
16
|
+
|
17
|
+
group {
|
18
|
+
layout_data :fill, :fill, true, true
|
19
|
+
text "Gender"
|
20
|
+
radio {text "Male"; selection true}
|
21
|
+
radio {text "Female"}
|
22
|
+
}
|
23
|
+
|
24
|
+
group {
|
25
|
+
layout_data :fill, :fill, true, true
|
26
|
+
text "Role"
|
27
|
+
check {text "Student"; selection true}
|
28
|
+
check {text "Employee"; selection true}
|
29
|
+
}
|
30
|
+
|
31
|
+
group {
|
32
|
+
text "Experience"
|
33
|
+
row_layout
|
34
|
+
layout_data :fill, :fill, true, true
|
35
|
+
spinner {selection 5}; label {text "years"}
|
36
|
+
}
|
37
|
+
|
38
|
+
button {
|
39
|
+
text "save"
|
40
|
+
layout_data :right, :center, true, true
|
41
|
+
on_widget_selected {
|
42
|
+
message_box {
|
43
|
+
text 'Profile Saved!'
|
44
|
+
message 'User profile has been saved!'
|
45
|
+
}.open
|
46
|
+
}
|
47
|
+
}
|
48
|
+
|
49
|
+
button {
|
50
|
+
text "close"
|
51
|
+
layout_data :left, :center, true, true
|
52
|
+
on_widget_selected { exit(0) }
|
53
|
+
}
|
54
|
+
}
|
55
|
+
}.open
|
metadata
CHANGED
@@ -1,21 +1,21 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: glimmer-dsl-swt
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.6.
|
4
|
+
version: 0.6.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- AndyMaleh
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-09-
|
11
|
+
date: 2020-09-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
15
15
|
requirements:
|
16
16
|
- - "~>"
|
17
17
|
- !ruby/object:Gem::Version
|
18
|
-
version: 0.10.
|
18
|
+
version: 0.10.4
|
19
19
|
name: glimmer
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
@@ -23,7 +23,7 @@ dependencies:
|
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.10.
|
26
|
+
version: 0.10.4
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
29
29
|
requirements:
|
@@ -57,7 +57,7 @@ dependencies:
|
|
57
57
|
requirements:
|
58
58
|
- - "~>"
|
59
59
|
- !ruby/object:Gem::Version
|
60
|
-
version: 0.10.
|
60
|
+
version: 0.10.1
|
61
61
|
name: puts_debuggerer
|
62
62
|
type: :runtime
|
63
63
|
prerelease: false
|
@@ -65,7 +65,21 @@ dependencies:
|
|
65
65
|
requirements:
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: 0.10.
|
68
|
+
version: 0.10.1
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: 0.2.1
|
75
|
+
name: rake-tui
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 0.2.1
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
84
|
requirement: !ruby/object:Gem::Requirement
|
71
85
|
requirements:
|
@@ -200,6 +214,26 @@ dependencies:
|
|
200
214
|
- - "<"
|
201
215
|
- !ruby/object:Gem::Version
|
202
216
|
version: 2.0.0
|
217
|
+
- !ruby/object:Gem::Dependency
|
218
|
+
requirement: !ruby/object:Gem::Requirement
|
219
|
+
requirements:
|
220
|
+
- - ">="
|
221
|
+
- !ruby/object:Gem::Version
|
222
|
+
version: 0.7.0
|
223
|
+
- - "<"
|
224
|
+
- !ruby/object:Gem::Version
|
225
|
+
version: 2.0.0
|
226
|
+
name: tty-markdown
|
227
|
+
type: :runtime
|
228
|
+
prerelease: false
|
229
|
+
version_requirements: !ruby/object:Gem::Requirement
|
230
|
+
requirements:
|
231
|
+
- - ">="
|
232
|
+
- !ruby/object:Gem::Version
|
233
|
+
version: 0.7.0
|
234
|
+
- - "<"
|
235
|
+
- !ruby/object:Gem::Version
|
236
|
+
version: 2.0.0
|
203
237
|
- !ruby/object:Gem::Dependency
|
204
238
|
requirement: !ruby/object:Gem::Requirement
|
205
239
|
requirements:
|
@@ -290,7 +324,7 @@ dependencies:
|
|
290
324
|
- - "~>"
|
291
325
|
- !ruby/object:Gem::Version
|
292
326
|
version: 0.7.0
|
293
|
-
description: Glimmer DSL for SWT (Desktop GUI)
|
327
|
+
description: Glimmer DSL for SWT (JRuby Desktop GUI)
|
294
328
|
email: andy.am@gmail.com
|
295
329
|
executables:
|
296
330
|
- glimmer
|
@@ -392,6 +426,7 @@ files:
|
|
392
426
|
- samples/elaborate/tic_tac_toe.rb
|
393
427
|
- samples/elaborate/tic_tac_toe/board.rb
|
394
428
|
- samples/elaborate/tic_tac_toe/cell.rb
|
429
|
+
- samples/elaborate/user_profile.rb
|
395
430
|
- samples/hello/hello_browser.rb
|
396
431
|
- samples/hello/hello_combo.rb
|
397
432
|
- samples/hello/hello_computed.rb
|