glimmer 0.8.1 → 0.8.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0c6aff23e9890326138ca130e2e7bb80d2ff62d9586d3ff9e62cfcb97dab0c18
4
- data.tar.gz: '038211b85b37a102b05006b5961ec60ad20c62eca31bd15f833065170d9b6b20'
3
+ metadata.gz: fbe97823fd25586221485191db661a4cb6fe71d8d9be9e89b60d617d5f496540
4
+ data.tar.gz: d81b11d52ce3f0fe1fdb46d9f1a6c286ccd95c3021118f71b4f72d7724cd0f41
5
5
  SHA512:
6
- metadata.gz: 7fea559224aa5069c03dfebdcbd4981ed7c6296d171098077164019e9c3fa8fd053fcfe0fcaf7161b03d0ad3a1dbda0af4c719629fd55a9af9868760a9b398e4
7
- data.tar.gz: 2abec0e6d750fc5ed6417ea79c18aa102c8d2d75ee3c253a2ecec1f0e01c22793e03dc7ff25b10a99c4b81d1a907712e7f558e85158ffa675bcfe24928ec7ff7
6
+ metadata.gz: 930a0914fc83db952df2eba9321779ee34a3d2819a0dabb05a31615b97b1eb57ff222321bd9db9fa4d6950e0f4e68f6455a66223ac1a1126a1c72be75a8a8b46
7
+ data.tar.gz: 5ab308d9b3403a9876d8f40f8a51d277cf0c88527f257977f87a21fc530a95a0d3e92d64a6b4025a56b2ed857f3d6b1c4d0d3df10bed7999c25cf90e589d6934
data/README.md CHANGED
@@ -1,7 +1,6 @@
1
- # Glimmer 0.8.1 Beta (Ruby Desktop Development GUI Library)
1
+ # Glimmer 0.8.2 Beta (Ruby Desktop Development GUI Library)
2
2
  [![Gem Version](https://badge.fury.io/rb/glimmer.svg)](http://badge.fury.io/rb/glimmer)
3
3
  [![Travis CI](https://travis-ci.com/AndyObtiva/glimmer.svg?branch=master)](https://travis-ci.com/github/AndyObtiva/glimmer)
4
- [![Test Coverage](https://api.codeclimate.com/v1/badges/38fbc278022862794414/test_coverage)](https://codeclimate.com/github/AndyObtiva/glimmer/test_coverage)
5
4
  [![Maintainability](https://api.codeclimate.com/v1/badges/38fbc278022862794414/maintainability)](https://codeclimate.com/github/AndyObtiva/glimmer/maintainability)
6
5
 
7
6
  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.
@@ -71,11 +70,11 @@ Glimmer app:
71
70
 
72
71
  ![Tic Tac Toe](images/glimmer-tic-tac-toe.png)
73
72
 
74
- NOTE: Glimmer is in beta mode. Please help make better by adopting for small or low risk projects and providing feedback.
73
+ NOTE: Glimmer is in beta mode. Please help make better by [contributing](#contributing), adopting for small or low risk projects, and providing feedback.
75
74
 
76
75
  ## Table of contents
77
76
 
78
- - [Glimmer 0.8.1 Beta (Ruby Desktop Development GUI Library)](#glimmer-081-beta-ruby-desktop-development-gui-library)
77
+ - [Glimmer 0.8.2 Beta (Ruby Desktop Development GUI Library)](#glimmer-082-beta-ruby-desktop-development-gui-library)
79
78
  - [Examples](#examples)
80
79
  - [Hello, World!](#hello-world)
81
80
  - [Tic Tac Toe](#tic-tac-toe)
@@ -89,23 +88,55 @@ NOTE: Glimmer is in beta mode. Please help make better by adopting for small or
89
88
  - [Basic Usage](#basic-usage)
90
89
  - [Advanced Usage](#advanced-usage)
91
90
  - [Scaffolding](#scaffolding)
91
+ - [App](#app)
92
+ - [Custom Shell](#custom-shell)
93
+ - [Custom Widget](#custom-widget)
94
+ - [Custom Shell Gem](#custom-shell-gem)
95
+ - [Custom Widget Gem](#custom-widget-gem)
92
96
  - [Girb (Glimmer irb) Command](#girb-glimmer-irb-command)
93
97
  - [Glimmer DSL Syntax](#glimmer-dsl-syntax)
94
98
  - [Widgets](#widgets)
99
+ - [Display](#display)
100
+ - [SWT Proxies](#swt-proxies)
101
+ - [Dialog](#dialog)
102
+ - [Menus](#menus)
95
103
  - [Widget Styles](#widget-styles)
104
+ - [Explicit SWT Style Bit](#explicit-swt-style-bit)
105
+ - [Negative SWT Style Bits](#negative-swt-style-bits)
106
+ - [Extra SWT Styles](#extra-swt-styles)
96
107
  - [Widget Properties](#widget-properties)
108
+ - [Colors](#colors)
109
+ - [Fonts](#fonts)
97
110
  - [Layouts](#layouts)
98
111
  - [Layout Data](#layout-data)
99
112
  - [Data-Binding](#data-binding)
113
+ - [General Examples](#general-examples)
114
+ - [Combo](#combo)
115
+ - [List](#list)
116
+ - [Table](#table)
117
+ - [Tree](#tree)
100
118
  - [Observer](#observer)
119
+ - [Observing Widgets](#observing-widgets)
120
+ - [Observing Models](#observing-models)
101
121
  - [Custom Widgets](#custom-widgets)
122
+ - [Simple Example](#simple-example)
123
+ - [Hook Example](#hook-example)
124
+ - [Content/Options Example](#contentoptions-example)
125
+ - [Gotcha](#gotcha)
102
126
  - [Custom Shells](#custom-shells)
103
127
  - [Miscellaneous](#miscellaneous)
128
+ - [Application Menu Items (About/Preferences)](#application-menu-items-aboutpreferences)
129
+ - [App Name and Version](#app-name-and-version)
130
+ - [Multi-DSL Support](#multi-dsl-support)
131
+ - [Video Widget](#video-widget)
132
+ - [Browser Widget](#browser-widget)
104
133
  - [Glimmer Style Guide](#glimmer-style-guide)
105
134
  - [Samples](#samples)
106
135
  - [Hello Samples](#hello-samples)
107
136
  - [Elaborate Samples](#elaborate-samples)
108
137
  - [External Samples](#external-samples)
138
+ - [Glimmer Calculator](#glimmer-calculator)
139
+ - [Gladiator](#gladiator)
109
140
  - [In Production](#in-production)
110
141
  - [SWT Reference](#swt-reference)
111
142
  - [SWT Packages](#swt-packages)
@@ -154,7 +185,7 @@ https://www.eclipse.org/swt/faq.php
154
185
 
155
186
  - SWT 4.15 (comes included in Glimmer gem)
156
187
  - JRuby 9.2.11.1 (supporting Ruby 2.5.x syntax) (find at [https://www.jruby.org/download](https://www.jruby.org/download))
157
- - Java SE Runtime Environment 7 or higher (find at [https://www.oracle.com/java/technologies/javase-downloads.html](https://www.oracle.com/java/technologies/javase-downloads.html))
188
+ - JDK 8 - 10 (find at [https://www.oracle.com/java/technologies/javase-downloads.html](https://www.oracle.com/java/technologies/javase-downloads.html))
158
189
  - (Optional) RVM is needed for [Scaffolding](#scaffolding) only (find at [https://rvm.io/](https://rvm.io/))
159
190
 
160
191
  On **Mac** and **Linux**, an easy way to obtain JRuby is through [RVM](http://rvm.io) by running:
@@ -173,7 +204,7 @@ Please follow these instructions to make the `glimmer` command available on your
173
204
 
174
205
  Run this command to install directly:
175
206
  ```
176
- jgem install glimmer -v 0.8.1
207
+ jgem install glimmer -v 0.8.2
177
208
  ```
178
209
 
179
210
  `jgem` is JRuby's version of `gem` command.
@@ -184,7 +215,7 @@ Otherwise, you may also run `jruby -S gem install ...`
184
215
 
185
216
  Add the following to `Gemfile`:
186
217
  ```
187
- gem 'glimmer', '~> 0.8.1'
218
+ gem 'glimmer', '~> 0.8.2'
188
219
  ```
189
220
 
190
221
  And, then run:
@@ -1099,7 +1130,7 @@ https://help.eclipse.org/2019-12/nftopic/org.eclipse.platform.doc.isv/reference/
1099
1130
 
1100
1131
  Data-binding is done with `bind` command following widget property to bind and taking model and bindable attribute as arguments.
1101
1132
 
1102
- #### General data-binding examples:
1133
+ #### General Examples
1103
1134
 
1104
1135
  `text bind(contact, :first_name)`
1105
1136
 
@@ -1270,7 +1301,62 @@ The Glimmer code is not much different from above except for passing the `:multi
1270
1301
 
1271
1302
  Note that in all the data-binding examples above, there was also an observer attached to the `button` widget to trigger an action on the model, which in turn triggers a data-binding update on the `list` or `combo`. Observers will be discussed in more details in the [next section](#observer).
1272
1303
 
1273
- You may learn more about Glimmer's data-binding syntax by reading the [Eclipse Zone Tutorial](http://eclipse.dzone.com/articles/an-introduction-glimmer) mentioned in resources and opening up the samples under the [samples](samples) directory.
1304
+ You may learn more about Glimmer's data-binding syntax by reading the code under the [samples](samples) directory.
1305
+
1306
+ #### Table
1307
+
1308
+ The SWT Tree widget renders a multi-column data table, such as a contact listing or a sales report.
1309
+
1310
+ To data-bind a Table, you need the main model, the collection property, and the text display attribute for each table column.
1311
+
1312
+ This involves using the `bind` keyword mentioned above in addition to a special `column_properties` keyword that takes the table column text attribute methods.
1313
+
1314
+ It assumes you have defined the table columns via `table_column` widget.
1315
+
1316
+ Example:
1317
+
1318
+ ```ruby
1319
+ shell {
1320
+ @table = table {
1321
+ table_column {
1322
+ text "Name"
1323
+ width 120
1324
+ }
1325
+ table_column {
1326
+ text "Age"
1327
+ width 120
1328
+ }
1329
+ table_column {
1330
+ text "Adult"
1331
+ width 120
1332
+ }
1333
+ items bind(group, :people), column_properties(:name, :age, :adult)
1334
+ selection bind(group, :selected_person)
1335
+ }
1336
+ }
1337
+ ```
1338
+
1339
+ The code above includes two data-bindings:
1340
+ - Table `items`, which first bind to the model collection property (group.people), and then maps each column property (name, age, adult) for displaying each table item column.
1341
+ - Table `selection`, which binds the single table item selected by the user to the attribute denoted by the `bind` keyword (or binds multiple table items selected for a table with `:multi` SWT style)
1342
+
1343
+ Additionally, Table `items` data-binding automatically stores each node model unto the SWT TableItem object via `setData` method. This enables things like searchability.
1344
+
1345
+ The table widget in Glimmer is represented by a subclass of `WidgetProxy` called `TableProxy`.
1346
+ TableProxy includes a `search` method that takes a block to look for a table item.
1347
+
1348
+ Example:
1349
+
1350
+ ```ruby
1351
+ found_array = @table.search { |table_item| table_item.getData == company.owner }
1352
+ ```
1353
+
1354
+ This finds a person. The array is a Java array. This enables easy passing of it to SWT `Table#setSelection` method, which expects a Java array of `TableItem` objects.
1355
+
1356
+ To edit a table, you must invoke `TableProxy#edit_selected_table_item(column_index, before_write: nil, after_write: nil, after_cancel: nil)` or `TableProxy#edit_table_item(table_item, column_index, before_write: nil, after_write: nil, after_cancel: nil)`.
1357
+ This automatically leverages the SWT TableEditor custom class behind the scenes, displaying a text widget to the user to change the selected or
1358
+ passed table item text into something else.
1359
+ It automatically persists the change to `items` data-bound model on ENTER/FOCUS-OUT or cancels on ESC/NO-CHANGE.
1274
1360
 
1275
1361
  #### Tree
1276
1362
 
@@ -1486,7 +1572,9 @@ Glimmer supports creating custom widgets with minimal code, which automatically
1486
1572
 
1487
1573
  Simply create a new class that includes `Glimmer::UI::CustomWidget` and put Glimmer DSL code in its `#body` block (its return value is stored in `#body_root` attribute). Glimmer will then automatically recognize this class by convention when it encounters a keyword matching the class name converted to underscored lowercase (and namespace double-colons `::` replaced with double-underscores `__`)
1488
1574
 
1489
- #### Example (you may copy/paste in [`girb`](#girb-glimmer-irb-command)):
1575
+ #### Simple Example
1576
+
1577
+ (you may copy/paste in [`girb`](#girb-glimmer-irb-command))
1490
1578
 
1491
1579
  Definition:
1492
1580
  ```ruby
@@ -1512,7 +1600,9 @@ shell {
1512
1600
 
1513
1601
  As you can see, `RedLabel` became Glimmer DSL keyword: `red_label`
1514
1602
 
1515
- #### Another Example (you may copy/paste in [`girb`](#girb-glimmer-irb-command)):
1603
+ #### Hook Example
1604
+
1605
+ (you may copy/paste in [`girb`](#girb-glimmer-irb-command))
1516
1606
 
1517
1607
  Definition:
1518
1608
  ```ruby
@@ -1561,7 +1651,9 @@ Additionally, custom widgets can call the following class methods:
1561
1651
  - `::options(*option_names)`: declares a list of options by taking an option name array (symbols/strings). This generates option attribute accessors (e.g. `options :orientation, :bg_color` generates `#orientation`, `#orientation=(v)`, `#bg_color`, and `#bg_color=(v)` attribute accessors)
1562
1652
  - `::option(option_name, default: nil)`: declares a single option taking option name and default value as arguments (also generates attribute accessors just like `::options`)
1563
1653
 
1564
- #### Content/Options Example (you may copy/paste in [`girb`](#girb-glimmer-irb-command)):
1654
+ #### Content/Options Example
1655
+
1656
+ (you may copy/paste in [`girb`](#girb-glimmer-irb-command))
1565
1657
 
1566
1658
  Definition:
1567
1659
  ```ruby
@@ -2007,15 +2099,15 @@ glimmer samples/elaborate/tic_tac_toe.rb # demonstrates a full MVC application
2007
2099
 
2008
2100
  ### External Samples
2009
2101
 
2010
- #### [Glimmer Calculator](https://github.com/AndyObtiva/glimmer-cs-calculator)
2102
+ #### Glimmer Calculator
2011
2103
 
2012
- ![Glimmer Calculator](https://raw.githubusercontent.com/AndyObtiva/glimmer-cs-calculator/v1.0.0/glimmer-cs-calculator-screenshot.png)
2104
+ [<img src="https://raw.githubusercontent.com/AndyObtiva/glimmer-cs-calculator/v1.0.0/glimmer-cs-calculator-screenshot.png" />](https://github.com/AndyObtiva/glimmer-cs-calculator)
2013
2105
 
2014
2106
  [Glimmer Calculator](https://github.com/AndyObtiva/glimmer-cs-calculator) is a basic calculator sample project demonstrating data-binding and TDD (test-driven-development) with Glimmer following the MVP pattern (Model-View-Presenter).
2015
2107
 
2016
- #### [Gladiator](https://github.com/AndyObtiva/glimmer-cs-gladiator)
2108
+ #### Gladiator
2017
2109
 
2018
- ![Gladiator](https://raw.githubusercontent.com/AndyObtiva/glimmer-cs-gladiator/v0.1.5/images/glimmer-gladiator.png)
2110
+ [<img src="https://raw.githubusercontent.com/AndyObtiva/glimmer-cs-gladiator/v0.1.5/images/glimmer-gladiator.png" />](https://github.com/AndyObtiva/glimmer-cs-gladiator)
2019
2111
 
2020
2112
  [Gladiator](https://github.com/AndyObtiva/glimmer-cs-gladiator) (short for Glimmer Editor) is a Glimmer sample project under on-going development.
2021
2113
  You may check it out to learn how to build a Glimmer Custom Shell gem.
@@ -2200,6 +2292,8 @@ The Glimmer rake task allows passing extra options to javapackager via:
2200
2292
  Example (Rakefile):
2201
2293
 
2202
2294
  ```ruby
2295
+ require 'glimmer/rake_task'
2296
+
2203
2297
  Glimmer::Package.javapackager_extra_args = '-BlicenseType="MIT" -Bmac.category="public.app-category.business" -Bmac.signing-key-developer-id-app="Andy Maleh"'
2204
2298
  ```
2205
2299
 
@@ -2283,10 +2377,11 @@ Exec failed with code 2 command [[/usr/bin/SetFile, -c, icnC, /var/folders/4_/g1
2283
2377
  ## Resources
2284
2378
 
2285
2379
  * [Code Master Blog](http://andymaleh.blogspot.com/search/label/Glimmer)
2286
- * [Eclipse Zone Tutorial](http://eclipse.dzone.com/articles/an-introduction-glimmer)
2287
- * [InfoQ Article](http://www.infoq.com/news/2008/02/glimmer-jruby-swt)
2288
- * [RubyConf 2008 Video](https://confreaks.tv/videos/rubyconf2008-desktop-development-with-glimmer)
2289
2380
  * [JRuby Cookbook by Justin Edelson & Henry Liu](http://shop.oreilly.com/product/9780596519650.do)
2381
+ * [MountainWest RubyConf 2011 Video](https://confreaks.tv/videos/mwrc2011-whatever-happened-to-desktop-development-in-ruby)
2382
+ * [RubyConf 2008 Video](https://confreaks.tv/videos/rubyconf2008-desktop-development-with-glimmer)
2383
+ * [InfoQ Article](http://www.infoq.com/news/2008/02/glimmer-jruby-swt)
2384
+ * [DZone Tutorial](https://dzone.com/articles/an-introduction-glimmer)
2290
2385
 
2291
2386
  ## Help
2292
2387
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.8.1
1
+ 0.8.2
@@ -16,6 +16,11 @@ module Glimmer
16
16
  @table = parent
17
17
  @model_binding = model_binding
18
18
  @column_properties = column_properties
19
+ if @table.respond_to?(:column_properties=)
20
+ @table.column_properties = @column_properties
21
+ else # assume custom widget
22
+ @table.body_root.column_properties = @column_properties
23
+ end
19
24
  call(@model_binding.evaluate_property)
20
25
  model = model_binding.base_model
21
26
  observe(model, model_binding.property_name_expression)
@@ -24,23 +29,27 @@ module Glimmer
24
29
  end
25
30
  end
26
31
 
27
- def call(model_collection=nil)
28
- if model_collection and model_collection.is_a?(Array)
29
- # TODO clean observer registrations
30
- observe(model_collection, @column_properties)
31
- @model_collection = model_collection
32
+ def call(new_model_collection=nil)
33
+ if new_model_collection and new_model_collection.is_a?(Array)
34
+ observe(new_model_collection, @column_properties)
35
+ @model_collection = new_model_collection
32
36
  end
33
37
  populate_table(@model_collection, @table, @column_properties)
34
38
  end
35
39
 
36
40
  def populate_table(model_collection, parent, column_properties)
41
+ selected_table_item_models = parent.swt_widget.getSelection.map(&:getData)
37
42
  parent.swt_widget.removeAll
38
43
  model_collection.each do |model|
39
44
  table_item = TableItem.new(parent.swt_widget, SWT::SWTProxy[:none])
40
45
  for index in 0..(column_properties.size-1)
41
46
  table_item.setText(index, model.send(column_properties[index]).to_s)
42
47
  end
48
+ table_item.setData(model)
43
49
  end
50
+ selected_table_items = parent.search {|item| selected_table_item_models.include?(item.getData) }
51
+ selected_table_items = [parent.swt_widget.getItems.first].to_java(TableItem) if selected_table_items.empty? && !parent.swt_widget.getItems.empty?
52
+ parent.swt_widget.setSelection(selected_table_items) unless selected_table_items.empty?
44
53
  end
45
54
  end
46
55
  end
@@ -0,0 +1,29 @@
1
+ require 'glimmer/dsl/static_expression'
2
+ require 'glimmer/dsl/parent_expression'
3
+ require 'glimmer/dsl/top_level_expression'
4
+ require 'glimmer/swt/shell_proxy'
5
+ require 'glimmer/swt/message_box_proxy'
6
+ require 'glimmer/swt/swt_proxy'
7
+
8
+ module Glimmer
9
+ module DSL
10
+ module SWT
11
+ class MessageBoxExpression < StaticExpression
12
+ include TopLevelExpression
13
+ include ParentExpression
14
+
15
+ include_package 'org.eclipse.swt.widgets'
16
+
17
+ def can_interpret?(parent, keyword, *args, &block)
18
+ keyword == 'message_box'
19
+ end
20
+
21
+ def interpret(parent, keyword, *args, &block)
22
+ potential_parent = args.first
23
+ parent = args.shift if potential_parent.is_a?(Shell) || (potential_parent.respond_to?(:swt_widget) && potential_parent.swt_widget.is_a?(Shell))
24
+ Glimmer::SWT::MessageBoxProxy.new(parent, Glimmer::SWT::SWTProxy[args])
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -32,3 +32,4 @@ end
32
32
 
33
33
  require 'glimmer/swt/widget_proxy'
34
34
  require 'glimmer/swt/tree_proxy'
35
+ require 'glimmer/swt/table_proxy'
@@ -2,6 +2,54 @@ module Glimmer
2
2
  module Package
3
3
  class << self
4
4
  attr_accessor :javapackager_extra_args
5
+
6
+ def config
7
+ project_name = File.basename(File.expand_path('.'))
8
+ if !File.exists?('config/warble.rb')
9
+ puts 'Generating JAR configuration (config/warble.rb) to use with Warbler...'
10
+ system('mkdir -p config')
11
+ system('warble config')
12
+ new_config = File.read('config/warble.rb').split("\n").inject('') do |output, line|
13
+ if line.include?('config.dirs =')
14
+ line = line.sub('# ', '').sub(/=[^=\n]+$/, '= %w(app config db lib script bin docs fonts icons images sounds videos)')
15
+ end
16
+ if line.include?('config.includes =')
17
+ line = line.sub('# ', '').sub(/=[^=\n]+$/, "= FileList['LICENSE.txt', 'VERSION']")
18
+ end
19
+ if line.include?('config.autodeploy_dir =')
20
+ line = line.sub('# ', '')
21
+ end
22
+ output + "\n" + line
23
+ end
24
+ File.write('config/warble.rb', new_config)
25
+ end
26
+ end
27
+
28
+ def jar
29
+ system('mkdir -p dist')
30
+ puts "Generating JAR with Warbler..."
31
+ system('warble')
32
+ end
33
+
34
+ def native
35
+ require 'facets/string/titlecase'
36
+ require 'facets/string/underscore'
37
+ project_name = File.basename(File.expand_path('.'))
38
+ version_file = File.expand_path('./VERSION')
39
+ version = (File.read(version_file).strip if File.exists?(version_file) && File.file?(version_file)) rescue nil
40
+ license_file = File.expand_path('./LICENSE.txt')
41
+ license = (File.read(license_file).strip if File.exists?(license_file) && File.file?(license_file)) rescue nil
42
+ human_name = project_name.underscore.titlecase
43
+ command = "javapackager -deploy -native -outdir packages -outfile \"#{project_name}\" -srcfiles \"dist/#{project_name}.jar\" -appclass JarMain -name \"#{human_name}\" -title \"#{human_name}\" -Bmac.CFBundleName=\"#{human_name}\" -Bmac.CFBundleIdentifier=\"org.#{project_name}.application.#{project_name}\" -Bmac.category=\"public.app-category.business\" "
44
+ command += " -BjvmOptions=-XstartOnFirstThread " if OS.mac?
45
+ command += " -BappVersion=#{version} -Bmac.CFBundleVersion=#{version} " if version
46
+ command += " -srcfiles LICENSE.txt -BlicenseFile=LICENSE.txt " if license
47
+ command += " #{javapackager_extra_args} " if javapackager_extra_args
48
+ command += " #{ENV['JAVAPACKAGER_EXTRA_ARGS']} " if ENV['JAVAPACKAGER_EXTRA_ARGS']
49
+ puts "Generating DMG/PKG/APP/JNLP with javapackager..."
50
+ puts command
51
+ system command
52
+ end
5
53
  end
6
54
  end
7
55
  end
@@ -7,57 +7,26 @@ namespace :glimmer do
7
7
  namespace :package do
8
8
  desc 'Generate JAR config file'
9
9
  task :config do
10
- project_name = File.basename(File.expand_path('.'))
11
- if !File.exists?('config/warble.rb')
12
- puts 'Generating JAR configuration (config/warble.rb) to use with Warbler...'
13
- system('mkdir -p config')
14
- system('warble config')
15
- new_config = File.read('config/warble.rb').split("\n").inject('') do |output, line|
16
- if line.include?('config.dirs =')
17
- line = line.sub('# ', '').sub(/=[^=\n]+$/, '= %w(app config db lib script bin docs fonts icons images sounds videos)')
18
- end
19
- if line.include?('config.includes =')
20
- line = line.sub('# ', '').sub(/=[^=\n]+$/, "= FileList['LICENSE.txt', 'VERSION']")
21
- end
22
- if line.include?('config.autodeploy_dir =')
23
- line = line.sub('# ', '')
24
- end
25
- output + "\n" + line
26
- end
27
- File.write('config/warble.rb', new_config)
28
- end
10
+ Glimmer::Package.config
29
11
  end
30
12
 
31
13
  desc 'Generate JAR file'
32
- task :jar => 'package:config' do
33
- system('mkdir -p dist')
34
- puts "Generating JAR with Warbler..."
35
- system('warble')
14
+ task :jar do
15
+ Glimmer::Package.jar
36
16
  end
37
17
 
38
- desc 'Generate Native files (DMG/PKG/APP on the Mac)'
39
- task :native => 'package:jar' do
40
- require 'facets/string/titlecase'
41
- require 'facets/string/underscore'
42
- project_name = File.basename(File.expand_path('.'))
43
- version_file = File.expand_path('./VERSION')
44
- version = (File.read(version_file).strip if File.exists?(version_file) && File.file?(version_file)) rescue nil
45
- license_file = File.expand_path('./LICENSE.txt')
46
- license = (File.read(license_file).strip if File.exists?(license_file) && File.file?(license_file)) rescue nil
47
- human_name = project_name.underscore.titlecase
48
- command = "javapackager -deploy -native -outdir packages -outfile \"#{project_name}\" -srcfiles \"dist/#{project_name}.jar\" -appclass JarMain -name \"#{human_name}\" -title \"#{human_name}\" -BjvmOptions=-XstartOnFirstThread -Bmac.CFBundleName=\"#{human_name}\" -Bmac.CFBundleIdentifier=\"org.#{project_name}.application.#{project_name}\" -Bmac.category=\"public.app-category.business\" "
49
- command += " -BappVersion=#{version} -Bmac.CFBundleVersion=#{version} " if version
50
- command += " -srcfiles LICENSE.txt -BlicenseFile=LICENSE.txt " if license
51
- command += " #{Glimmer::Package.javapackager_extra_args} " if Glimmer::Package.javapackager_extra_args
52
- command += " #{ENV['JAVAPACKAGER_EXTRA_ARGS']} " if ENV['JAVAPACKAGER_EXTRA_ARGS']
53
- puts "Generating DMG/PKG/APP/JNLP with javapackager..."
54
- puts command
55
- system command
18
+ desc 'Generate Native files (DMG/PKG/APP on the Mac, EXE on Windows, RPM/DEB on Linux)'
19
+ task :native do
20
+ Glimmer::Package.native
56
21
  end
57
22
  end
58
23
 
59
24
  desc 'Package app for distribution (generating config, jar, and native files)'
60
- task :package => 'package:native'
25
+ task :package do
26
+ Rake::Task['glimmer:package:config'].execute
27
+ Rake::Task['glimmer:package:jar'].execute
28
+ Rake::Task['glimmer:package:native'].execute
29
+ end
61
30
 
62
31
 
63
32
  desc 'Scaffold a Glimmer application directory structure to begin building a new app'
@@ -0,0 +1,48 @@
1
+ require 'glimmer/swt/swt_proxy'
2
+ require 'glimmer/swt/widget_proxy'
3
+ require 'glimmer/swt/display_proxy'
4
+ require 'glimmer/swt/shell_proxy'
5
+
6
+ module Glimmer
7
+ module SWT
8
+ # Proxy for org.eclipse.swt.widgets.Shell
9
+ #
10
+ # Follows the Proxy Design Pattern
11
+ class MessageBoxProxy
12
+ include_package 'org.eclipse.swt.widgets'
13
+
14
+ attr_reader :swt_widget
15
+
16
+ def initialize(parent, style)
17
+ parent = parent.swt_widget if parent.respond_to?(:swt_widget) && parent.swt_widget.is_a?(Shell)
18
+ @swt_widget = MessageBox.new(parent, style)
19
+ end
20
+
21
+ def open
22
+ @swt_widget.open
23
+ end
24
+
25
+ # TODO refactor the following methods to put in a JavaBean mixin or somethin (perhaps contribute to OSS project too)
26
+
27
+ def attribute_setter(attribute_name)
28
+ "set#{attribute_name.to_s.camelcase(:upper)}"
29
+ end
30
+
31
+ def attribute_getter(attribute_name)
32
+ "get#{attribute_name.to_s.camelcase(:upper)}"
33
+ end
34
+
35
+ def has_attribute?(attribute_name, *args)
36
+ @swt_widget.respond_to?(attribute_setter(attribute_name), args)
37
+ end
38
+
39
+ def set_attribute(attribute_name, *args)
40
+ @swt_widget.send(attribute_setter(attribute_name), *args) unless @swt_widget.send(attribute_getter(attribute_name)) == args.first
41
+ end
42
+
43
+ def get_attribute(attribute_name)
44
+ @swt_widget.send(attribute_getter(attribute_name))
45
+ end
46
+ end
47
+ end
48
+ end
@@ -102,24 +102,19 @@ module Glimmer
102
102
 
103
103
  def pack_same_size
104
104
  bounds = @swt_widget.getBounds
105
- width = @swt_widget.getBounds.width
106
- height = @swt_widget.getBounds.height
107
- x = @swt_widget.getBounds.x
108
- y = @swt_widget.getBounds.y
109
- if OS.windows?
105
+ if OS.mac?
106
+ @swt_widget.pack
107
+ @swt_widget.setBounds(bounds)
108
+ elsif OS.windows? || OS::Underlying.windows?
110
109
  minimum_size = @swt_widget.getMinimumSize
111
110
  @swt_widget.setMinimumSize(bounds.width, bounds.height)
112
- listener = on_control_resized {
113
- @swt_widget.setSize(bounds.width, bounds.height)
114
- @swt_widget.setLocation(bounds.x, bounds.y)
115
- }
111
+ listener = on_control_resized { @swt_widget.setBounds(bounds) }
116
112
  @swt_widget.pack
117
113
  @swt_widget.removeControlListener(listener.swt_listener)
118
114
  @swt_widget.setMinimumSize(minimum_size)
119
- else
120
- @swt_widget.pack
121
- @swt_widget.setSize(width, height)
122
- @swt_widget.setLocation(x, y)
115
+ elsif OS.linux?
116
+ @swt_widget.layout(true, true)
117
+ @swt_widget.setBounds(bounds)
123
118
  end
124
119
  end
125
120
 
@@ -0,0 +1,150 @@
1
+ require 'glimmer/swt/widget_proxy'
2
+
3
+ module Glimmer
4
+ module SWT
5
+ class TableProxy < Glimmer::SWT::WidgetProxy
6
+ include Glimmer
7
+
8
+ module TableListenerEvent
9
+ def table_item
10
+ table_item_and_column_index[:table_item]
11
+ end
12
+
13
+ def column_index
14
+ table_item_and_column_index[:column_index]
15
+ end
16
+
17
+ private
18
+
19
+ def table_item_and_column_index
20
+ @table_item_and_column_index ||= find_table_item_and_column_index
21
+ end
22
+
23
+ def find_table_item_and_column_index
24
+ {}.tap do |result|
25
+ if respond_to?(:x) && respond_to?(:y)
26
+ result[:table_item] = widget.getItems.detect do |ti|
27
+ result[:column_index] = widget.getColumnCount.times.to_a.detect do |ci|
28
+ ti.getBounds(ci).contains(x, y)
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+
36
+ attr_reader :table_editor, :table_editor_text_proxy
37
+ attr_accessor :column_properties
38
+
39
+ def initialize(underscored_widget_name, parent, args)
40
+ super
41
+ @table_editor = TableEditor.new(swt_widget)
42
+ @table_editor.horizontalAlignment = SWTProxy[:left]
43
+ @table_editor.grabHorizontal = true
44
+ @table_editor.minimumHeight = 20
45
+ end
46
+
47
+ # Performs a search for table items matching block condition
48
+ # If no condition block is passed, returns all table items
49
+ # Returns a Java TableItem array to easily set as selection on org.eclipse.swt.Table if needed
50
+ def search(&condition)
51
+ swt_widget.getItems.select {|item| condition.nil? || condition.call(item)}.to_java(TableItem)
52
+ end
53
+
54
+ # Returns all table items including descendants
55
+ def all_table_items
56
+ search
57
+ end
58
+
59
+ def widget_property_listener_installers
60
+ super.merge({
61
+ Java::OrgEclipseSwtWidgets::Table => {
62
+ selection: lambda do |observer|
63
+ on_widget_selected { |selection_event|
64
+ observer.call(@swt_widget.getSelection)
65
+ }
66
+ end
67
+ },
68
+ })
69
+ end
70
+
71
+ def edit_in_progress?
72
+ !!@edit_in_progress
73
+ end
74
+
75
+ def edit_selected_table_item(column_index, before_write: nil, after_write: nil, after_cancel: nil)
76
+ edit_table_item(swt_widget.getSelection.first, column_index, before_write: before_write, after_write: after_write, after_cancel: after_cancel)
77
+ end
78
+
79
+ def edit_table_item(table_item, column_index, before_write: nil, after_write: nil, after_cancel: nil)
80
+ return if table_item.nil?
81
+ content {
82
+ @table_editor_text_proxy = text {
83
+ focus true
84
+ text table_item.getText(column_index)
85
+ action_taken = false
86
+ cancel = lambda {
87
+ @table_editor_text_proxy.swt_widget.dispose
88
+ @table_editor_text_proxy = nil
89
+ after_cancel&.call
90
+ @edit_in_progress = false
91
+ }
92
+ action = lambda { |event|
93
+ if !action_taken && !@edit_in_progress
94
+ action_taken = true
95
+ @edit_in_progress = true
96
+ new_text = @table_editor_text_proxy.swt_widget.getText
97
+ if new_text == table_item.getText(column_index)
98
+ cancel.call
99
+ else
100
+ before_write&.call
101
+ table_item.setText(column_index, new_text)
102
+ model = table_item.getData
103
+ model.send("#{column_properties[column_index]}=", new_text) # makes table update itself, so must search for selected table item again
104
+ edited_table_item = search { |ti| ti.getData == model }.first
105
+ swt_widget.showItem(edited_table_item)
106
+ @table_editor_text_proxy.swt_widget.dispose
107
+ @table_editor_text_proxy = nil
108
+ after_write&.call(edited_table_item)
109
+ @edit_in_progress = false
110
+ end
111
+ end
112
+ }
113
+ on_focus_lost(&action)
114
+ on_key_pressed { |key_event|
115
+ if key_event.keyCode == swt(:cr)
116
+ action.call(key_event)
117
+ elsif key_event.keyCode == swt(:esc)
118
+ cancel.call
119
+ end
120
+ }
121
+ }
122
+ @table_editor_text_proxy.swt_widget.selectAll
123
+ }
124
+ @table_editor.setEditor(@table_editor_text_proxy.swt_widget, table_item, column_index)
125
+ end
126
+
127
+ def add_listener(underscored_listener_name, &block)
128
+ enhanced_block = lambda do |event|
129
+ event.extend(TableListenerEvent)
130
+ block.call(event)
131
+ end
132
+ super(underscored_listener_name, &enhanced_block)
133
+ end
134
+
135
+ private
136
+
137
+ def property_type_converters
138
+ super.merge({
139
+ selection: lambda do |value|
140
+ if value.is_a?(Array)
141
+ search {|ti| value.include?(ti.getData) }
142
+ else
143
+ search {|ti| ti.getData == value}
144
+ end
145
+ end,
146
+ })
147
+ end
148
+ end
149
+ end
150
+ end
@@ -95,7 +95,7 @@ module Glimmer
95
95
  }
96
96
  @tree_editor_text_proxy.swt_widget.selectAll
97
97
  }
98
- @tree_editor.setEditor(@tree_editor_text_proxy.swt_widget, tree_item);
98
+ @tree_editor.setEditor(@tree_editor_text_proxy.swt_widget, tree_item)
99
99
  end
100
100
 
101
101
  private
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: glimmer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.1
4
+ version: 0.8.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - AndyMaleh
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-06-03 00:00:00.000000000 Z
11
+ date: 2020-06-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement
@@ -164,7 +164,10 @@ dependencies:
164
164
  - - "~>"
165
165
  - !ruby/object:Gem::Version
166
166
  version: 0.8.1
167
- description: Ruby Desktop Development GUI Library
167
+ description: "Ruby Desktop Development GUI Library (JRuby on SWT). \n\nChanges: \n\
168
+ - `message_box` DSL keyword\n- Table single/multi selection databinding\n- Table\
169
+ \ cell editing databinding\n- Enhance table listener events with table_item and\
170
+ \ column_index methods\n- Fix `Glimmer::SWT::ShellProxy#pack_same_size` for Linux\n"
168
171
  email: andy.am@gmail.com
169
172
  executables:
170
173
  - glimmer
@@ -225,6 +228,7 @@ files:
225
228
  - lib/glimmer/dsl/swt/list_selection_data_binding_expression.rb
226
229
  - lib/glimmer/dsl/swt/menu_bar_expression.rb
227
230
  - lib/glimmer/dsl/swt/menu_expression.rb
231
+ - lib/glimmer/dsl/swt/message_box_expression.rb
228
232
  - lib/glimmer/dsl/swt/observe_expression.rb
229
233
  - lib/glimmer/dsl/swt/property_expression.rb
230
234
  - lib/glimmer/dsl/swt/rgb_expression.rb
@@ -259,10 +263,12 @@ files:
259
263
  - lib/glimmer/swt/layout_data_proxy.rb
260
264
  - lib/glimmer/swt/layout_proxy.rb
261
265
  - lib/glimmer/swt/menu_proxy.rb
266
+ - lib/glimmer/swt/message_box_proxy.rb
262
267
  - lib/glimmer/swt/packages.rb
263
268
  - lib/glimmer/swt/shell_proxy.rb
264
269
  - lib/glimmer/swt/swt_proxy.rb
265
270
  - lib/glimmer/swt/tab_item_proxy.rb
271
+ - lib/glimmer/swt/table_proxy.rb
266
272
  - lib/glimmer/swt/tree_proxy.rb
267
273
  - lib/glimmer/swt/widget_listener_proxy.rb
268
274
  - lib/glimmer/swt/widget_proxy.rb