glimmer-dsl-swt 0.6.1 → 0.6.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +3 -2
- data/VERSION +1 -1
- data/bin/girb +1 -1
- data/bin/glimmer +5 -1
- data/icons/scaffold_app.png +0 -0
- data/lib/ext/glimmer/config.rb +13 -1
- data/lib/glimmer-dsl-swt.rb +5 -9
- data/lib/glimmer/Rakefile +5 -0
- data/lib/glimmer/data_binding/table_items_binding.rb +4 -1
- data/lib/glimmer/dsl/swt/cursor_expression.rb +1 -4
- data/lib/glimmer/dsl/swt/dsl.rb +1 -0
- data/lib/glimmer/dsl/swt/font_expression.rb +3 -1
- data/lib/glimmer/dsl/swt/image_expression.rb +21 -0
- data/lib/glimmer/dsl/swt/message_box_expression.rb +9 -1
- data/lib/glimmer/dsl/swt/widget_expression.rb +7 -7
- data/lib/glimmer/launcher.rb +59 -20
- data/lib/glimmer/package.rb +26 -9
- data/lib/glimmer/rake_task.rb +115 -5
- data/lib/glimmer/scaffold.rb +65 -32
- data/lib/glimmer/swt/display_proxy.rb +13 -2
- data/lib/glimmer/swt/image_proxy.rb +16 -23
- data/lib/glimmer/swt/layout_proxy.rb +2 -0
- data/lib/glimmer/swt/message_box_proxy.rb +23 -5
- data/lib/glimmer/swt/scrolled_composite_proxy.rb +6 -11
- data/lib/glimmer/swt/shell_proxy.rb +0 -1
- data/lib/glimmer/swt/table_proxy.rb +60 -2
- data/lib/glimmer/swt/widget_proxy.rb +72 -18
- data/samples/elaborate/contact_manager.rb +121 -0
- data/samples/elaborate/contact_manager/contact.rb +11 -0
- data/samples/elaborate/contact_manager/contact_manager_presenter.rb +26 -0
- data/samples/elaborate/contact_manager/contact_repository.rb +244 -0
- data/samples/elaborate/login.rb +108 -0
- data/samples/elaborate/tic_tac_toe.rb +55 -0
- data/samples/elaborate/tic_tac_toe/board.rb +124 -0
- data/samples/elaborate/tic_tac_toe/cell.rb +27 -0
- data/samples/elaborate/user_profile.rb +55 -0
- data/samples/hello/hello_browser.rb +8 -0
- data/samples/hello/hello_combo.rb +38 -0
- data/samples/hello/hello_computed.rb +69 -0
- data/samples/hello/hello_computed/contact.rb +21 -0
- data/samples/hello/hello_drag_and_drop.rb +29 -0
- data/samples/hello/hello_list_multi_selection.rb +48 -0
- data/samples/hello/hello_list_single_selection.rb +37 -0
- data/samples/hello/hello_menu_bar.rb +64 -0
- data/samples/hello/hello_message_box.rb +15 -0
- data/samples/hello/hello_pop_up_context_menu.rb +36 -0
- data/samples/hello/hello_tab.rb +24 -0
- data/samples/hello/hello_world.rb +8 -0
- metadata +66 -8
@@ -0,0 +1,108 @@
|
|
1
|
+
require "java"
|
2
|
+
require "observer"
|
3
|
+
|
4
|
+
#Presents login screen data
|
5
|
+
class LoginPresenter
|
6
|
+
|
7
|
+
attr_accessor :user_name
|
8
|
+
attr_accessor :password
|
9
|
+
attr_accessor :status
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
@user_name = ""
|
13
|
+
@password = ""
|
14
|
+
@status = "Logged Out"
|
15
|
+
end
|
16
|
+
|
17
|
+
def status=(status)
|
18
|
+
@status = status
|
19
|
+
|
20
|
+
#TODO add feature to bind dependent properties to master property (2017-07-25 nested data binding)
|
21
|
+
notify_observers("logged_in")
|
22
|
+
notify_observers("logged_out")
|
23
|
+
end
|
24
|
+
|
25
|
+
def valid?
|
26
|
+
!@user_name.to_s.strip.empty? && !@password.to_s.strip.empty?
|
27
|
+
end
|
28
|
+
|
29
|
+
def logged_in
|
30
|
+
self.status == "Logged In"
|
31
|
+
end
|
32
|
+
|
33
|
+
def logged_out
|
34
|
+
!self.logged_in
|
35
|
+
end
|
36
|
+
|
37
|
+
def login
|
38
|
+
return unless valid?
|
39
|
+
self.status = "Logged In"
|
40
|
+
end
|
41
|
+
|
42
|
+
def logout
|
43
|
+
self.user_name = ""
|
44
|
+
self.password = ""
|
45
|
+
self.status = "Logged Out"
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
#Login screen
|
51
|
+
class Login
|
52
|
+
include Glimmer
|
53
|
+
|
54
|
+
def launch
|
55
|
+
presenter = LoginPresenter.new
|
56
|
+
@shell = shell {
|
57
|
+
text "Login"
|
58
|
+
composite {
|
59
|
+
grid_layout 2, false #two columns with differing widths
|
60
|
+
|
61
|
+
label { text "Username:" } # goes in column 1
|
62
|
+
@user_name_text = text { # goes in column 2
|
63
|
+
text bind(presenter, :user_name)
|
64
|
+
enabled bind(presenter, :logged_out)
|
65
|
+
on_key_pressed { |event|
|
66
|
+
@password_text.set_focus if event.keyCode == swt(:cr)
|
67
|
+
}
|
68
|
+
}
|
69
|
+
|
70
|
+
label { text "Password:" }
|
71
|
+
@password_text = text(:password, :border) {
|
72
|
+
text bind(presenter, :password)
|
73
|
+
enabled bind(presenter, :logged_out)
|
74
|
+
on_key_pressed { |event|
|
75
|
+
presenter.login if event.keyCode == swt(:cr)
|
76
|
+
}
|
77
|
+
}
|
78
|
+
|
79
|
+
label { text "Status:" }
|
80
|
+
label { text bind(presenter, :status) }
|
81
|
+
|
82
|
+
button {
|
83
|
+
text "Login"
|
84
|
+
enabled bind(presenter, :logged_out)
|
85
|
+
on_widget_selected { presenter.login }
|
86
|
+
on_key_pressed { |event|
|
87
|
+
presenter.login if event.keyCode == swt(:cr)
|
88
|
+
}
|
89
|
+
}
|
90
|
+
|
91
|
+
button {
|
92
|
+
text "Logout"
|
93
|
+
enabled bind(presenter, :logged_in)
|
94
|
+
on_widget_selected { presenter.logout }
|
95
|
+
on_key_pressed { |event|
|
96
|
+
if event.keyCode == swt(:cr)
|
97
|
+
presenter.logout
|
98
|
+
@user_name_text.set_focus
|
99
|
+
end
|
100
|
+
}
|
101
|
+
}
|
102
|
+
}
|
103
|
+
}
|
104
|
+
@shell.open
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
Login.new.launch
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require_relative "tic_tac_toe/board"
|
2
|
+
|
3
|
+
class TicTacToe
|
4
|
+
include Glimmer
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@tic_tac_toe_board = Board.new
|
8
|
+
@shell = shell {
|
9
|
+
text "Tic-Tac-Toe"
|
10
|
+
minimum_size 150, 178
|
11
|
+
composite {
|
12
|
+
grid_layout 3, true
|
13
|
+
(1..3).each { |row|
|
14
|
+
(1..3).each { |column|
|
15
|
+
button {
|
16
|
+
layout_data :fill, :fill, true, true
|
17
|
+
text bind(@tic_tac_toe_board[row, column], :sign)
|
18
|
+
enabled bind(@tic_tac_toe_board[row, column], :empty)
|
19
|
+
font style: :bold, height: 20
|
20
|
+
on_widget_selected {
|
21
|
+
@tic_tac_toe_board.mark(row, column)
|
22
|
+
}
|
23
|
+
}
|
24
|
+
}
|
25
|
+
}
|
26
|
+
}
|
27
|
+
}
|
28
|
+
observe(@tic_tac_toe_board, :game_status) { |game_status|
|
29
|
+
display_win_message if game_status == Board::WIN
|
30
|
+
display_draw_message if game_status == Board::DRAW
|
31
|
+
}
|
32
|
+
end
|
33
|
+
|
34
|
+
def display_win_message
|
35
|
+
display_game_over_message("Player #{@tic_tac_toe_board.winning_sign} has won!")
|
36
|
+
end
|
37
|
+
|
38
|
+
def display_draw_message
|
39
|
+
display_game_over_message("Draw!")
|
40
|
+
end
|
41
|
+
|
42
|
+
def display_game_over_message(message_text)
|
43
|
+
message_box(@shell) {
|
44
|
+
text 'Game Over'
|
45
|
+
message message_text
|
46
|
+
}.open
|
47
|
+
@tic_tac_toe_board.reset
|
48
|
+
end
|
49
|
+
|
50
|
+
def open
|
51
|
+
@shell.open
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
TicTacToe.new.open
|
@@ -0,0 +1,124 @@
|
|
1
|
+
require_relative 'cell'
|
2
|
+
|
3
|
+
class TicTacToe
|
4
|
+
class Board
|
5
|
+
DRAW = :draw
|
6
|
+
IN_PROGRESS = :in_progress
|
7
|
+
WIN = :win
|
8
|
+
attr :winning_sign
|
9
|
+
attr_accessor :game_status
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
@sign_state_machine = {nil => "X", "X" => "O", "O" => "X"}
|
13
|
+
build_grid
|
14
|
+
@winning_sign = Cell::EMPTY
|
15
|
+
@game_status = IN_PROGRESS
|
16
|
+
end
|
17
|
+
|
18
|
+
#row and column numbers are 1-based
|
19
|
+
def mark(row, column)
|
20
|
+
self[row, column].mark(current_sign)
|
21
|
+
game_over? #updates winning sign
|
22
|
+
end
|
23
|
+
|
24
|
+
def current_sign
|
25
|
+
@current_sign = @sign_state_machine[@current_sign]
|
26
|
+
end
|
27
|
+
|
28
|
+
def [](row, column)
|
29
|
+
@grid[row-1][column-1]
|
30
|
+
end
|
31
|
+
|
32
|
+
def game_over?
|
33
|
+
win? or draw?
|
34
|
+
end
|
35
|
+
|
36
|
+
def win?
|
37
|
+
win = (row_win? or column_win? or diagonal_win?)
|
38
|
+
self.game_status=WIN if win
|
39
|
+
win
|
40
|
+
end
|
41
|
+
|
42
|
+
def reset
|
43
|
+
(1..3).each do |row|
|
44
|
+
(1..3).each do |column|
|
45
|
+
self[row, column].reset
|
46
|
+
end
|
47
|
+
end
|
48
|
+
@winning_sign = Cell::EMPTY
|
49
|
+
@current_sign = nil
|
50
|
+
self.game_status=IN_PROGRESS
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def build_grid
|
56
|
+
@grid = []
|
57
|
+
3.times do |row_index| #0-based
|
58
|
+
@grid << []
|
59
|
+
3.times { @grid[row_index] << Cell.new }
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def row_win?
|
64
|
+
(1..3).each do |row|
|
65
|
+
if row_has_same_sign(row)
|
66
|
+
@winning_sign = self[row, 1].sign
|
67
|
+
return true
|
68
|
+
end
|
69
|
+
end
|
70
|
+
false
|
71
|
+
end
|
72
|
+
|
73
|
+
def column_win?
|
74
|
+
(1..3).each do |column|
|
75
|
+
if column_has_same_sign(column)
|
76
|
+
@winning_sign = self[1, column].sign
|
77
|
+
return true
|
78
|
+
end
|
79
|
+
end
|
80
|
+
false
|
81
|
+
end
|
82
|
+
|
83
|
+
#needs refactoring if we ever decide to make the board size dynamic
|
84
|
+
def diagonal_win?
|
85
|
+
if (self[1, 1].sign == self[2, 2].sign) and (self[2, 2].sign == self[3, 3].sign) and self[1, 1].marked
|
86
|
+
@winning_sign = self[1, 1].sign
|
87
|
+
return true
|
88
|
+
end
|
89
|
+
if (self[3, 1].sign == self[2, 2].sign) and (self[2, 2].sign == self[1, 3].sign) and self[3, 1].marked
|
90
|
+
@winning_sign = self[3, 1].sign
|
91
|
+
return true
|
92
|
+
end
|
93
|
+
false
|
94
|
+
end
|
95
|
+
|
96
|
+
def draw?
|
97
|
+
@board_full = true
|
98
|
+
3.times do |x|
|
99
|
+
3.times do |y|
|
100
|
+
@board_full = false if self[x, y].empty
|
101
|
+
end
|
102
|
+
end
|
103
|
+
self.game_status = DRAW if @board_full
|
104
|
+
@board_full
|
105
|
+
end
|
106
|
+
|
107
|
+
def row_has_same_sign(number)
|
108
|
+
row_sign = self[number, 1].sign
|
109
|
+
[2, 3].each do |column|
|
110
|
+
return false unless row_sign == (self[number, column].sign)
|
111
|
+
end
|
112
|
+
true if self[number, 1].marked
|
113
|
+
end
|
114
|
+
|
115
|
+
def column_has_same_sign(number)
|
116
|
+
column_sign = self[1, number].sign
|
117
|
+
[2, 3].each do |row|
|
118
|
+
return false unless column_sign == (self[row, number].sign)
|
119
|
+
end
|
120
|
+
true if self[1, number].marked
|
121
|
+
end
|
122
|
+
|
123
|
+
end
|
124
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
class TicTacToe
|
2
|
+
class Cell
|
3
|
+
EMPTY = ""
|
4
|
+
attr_accessor :sign, :empty
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
reset
|
8
|
+
end
|
9
|
+
|
10
|
+
def mark(sign)
|
11
|
+
self.sign = sign
|
12
|
+
end
|
13
|
+
|
14
|
+
def reset
|
15
|
+
self.sign = EMPTY
|
16
|
+
end
|
17
|
+
|
18
|
+
def sign=(sign_symbol)
|
19
|
+
@sign = sign_symbol
|
20
|
+
self.empty = sign == EMPTY
|
21
|
+
end
|
22
|
+
|
23
|
+
def marked
|
24
|
+
!empty
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -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
|
@@ -0,0 +1,38 @@
|
|
1
|
+
class Person
|
2
|
+
attr_accessor :country, :country_options
|
3
|
+
|
4
|
+
def initialize
|
5
|
+
self.country_options=["", "Canada", "US", "Mexico"]
|
6
|
+
self.country = "Canada"
|
7
|
+
end
|
8
|
+
|
9
|
+
def reset_country
|
10
|
+
self.country = "Canada"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class HelloCombo
|
15
|
+
include Glimmer
|
16
|
+
def launch
|
17
|
+
person = Person.new
|
18
|
+
|
19
|
+
shell {
|
20
|
+
fill_layout :vertical
|
21
|
+
text 'Hello, Combo!'
|
22
|
+
|
23
|
+
combo(:read_only) {
|
24
|
+
selection bind(person, :country)
|
25
|
+
}
|
26
|
+
|
27
|
+
button {
|
28
|
+
text "Reset Selection"
|
29
|
+
|
30
|
+
on_widget_selected do
|
31
|
+
person.reset_country
|
32
|
+
end
|
33
|
+
}
|
34
|
+
}.open
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
HelloCombo.new.launch
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require_relative 'hello_computed/contact'
|
2
|
+
|
3
|
+
class HelloComputed
|
4
|
+
include Glimmer
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@contact = Contact.new(
|
8
|
+
first_name: 'Barry',
|
9
|
+
last_name: 'McKibbin',
|
10
|
+
year_of_birth: 1985
|
11
|
+
)
|
12
|
+
end
|
13
|
+
|
14
|
+
def launch
|
15
|
+
shell {
|
16
|
+
text 'Hello, Computed!'
|
17
|
+
composite {
|
18
|
+
grid_layout {
|
19
|
+
num_columns 2
|
20
|
+
make_columns_equal_width true
|
21
|
+
horizontal_spacing 20
|
22
|
+
vertical_spacing 10
|
23
|
+
}
|
24
|
+
label {text 'First &Name: '}
|
25
|
+
text {
|
26
|
+
text bind(@contact, :first_name)
|
27
|
+
layout_data {
|
28
|
+
horizontal_alignment :fill
|
29
|
+
grab_excess_horizontal_space true
|
30
|
+
}
|
31
|
+
}
|
32
|
+
label {text '&Last Name: '}
|
33
|
+
text {
|
34
|
+
text bind(@contact, :last_name)
|
35
|
+
layout_data {
|
36
|
+
horizontal_alignment :fill
|
37
|
+
grab_excess_horizontal_space true
|
38
|
+
}
|
39
|
+
}
|
40
|
+
label {text '&Year of Birth: '}
|
41
|
+
text {
|
42
|
+
text bind(@contact, :year_of_birth)
|
43
|
+
layout_data {
|
44
|
+
horizontal_alignment :fill
|
45
|
+
grab_excess_horizontal_space true
|
46
|
+
}
|
47
|
+
}
|
48
|
+
label {text 'Name: '}
|
49
|
+
label {
|
50
|
+
text bind(@contact, :name, computed_by: [:first_name, :last_name])
|
51
|
+
layout_data {
|
52
|
+
horizontal_alignment :fill
|
53
|
+
grab_excess_horizontal_space true
|
54
|
+
}
|
55
|
+
}
|
56
|
+
label {text 'Age: '}
|
57
|
+
label {
|
58
|
+
text bind(@contact, :age, on_write: :to_i, computed_by: [:year_of_birth])
|
59
|
+
layout_data {
|
60
|
+
horizontal_alignment :fill
|
61
|
+
grab_excess_horizontal_space true
|
62
|
+
}
|
63
|
+
}
|
64
|
+
}
|
65
|
+
}.open
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
HelloComputed.new.launch
|