glimmer-dsl-libui 0.3.5 → 0.4.3
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/CHANGELOG.md +38 -0
- data/README.md +4364 -3406
- data/VERSION +1 -1
- data/examples/basic_entry.rb +27 -24
- data/examples/basic_entry2.rb +31 -0
- data/examples/button_counter.rb +27 -0
- data/examples/color_the_circles.rb +2 -2
- data/examples/form.rb +42 -30
- data/examples/form2.rb +37 -0
- data/examples/form_table.rb +100 -85
- data/examples/form_table2.rb +95 -0
- data/examples/login.rb +45 -39
- data/examples/login2.rb +55 -0
- data/examples/login3.rb +65 -0
- data/examples/login4.rb +61 -0
- data/examples/login5.rb +43 -0
- data/examples/meta_example.rb +10 -7
- data/examples/method_based_custom_keyword.rb +8 -15
- data/examples/method_based_custom_keyword2.rb +97 -0
- data/examples/midi_player.rb +2 -6
- data/examples/snake/model/game.rb +2 -2
- data/examples/snake/presenter/grid.rb +5 -3
- data/examples/snake.rb +11 -21
- data/examples/tetris.rb +12 -12
- data/examples/tic_tac_toe.rb +3 -12
- data/examples/timer.rb +2 -6
- data/glimmer-dsl-libui.gemspec +0 -0
- data/lib/glimmer/dsl/libui/bind_expression.rb +36 -0
- data/lib/glimmer/dsl/libui/data_binding_expression.rb +45 -0
- data/lib/glimmer/dsl/libui/dsl.rb +3 -0
- data/lib/glimmer/dsl/libui/observe_expression.rb +35 -0
- data/lib/glimmer/dsl/libui/shine_data_binding_expression.rb +42 -0
- data/lib/glimmer/dsl/libui/string_expression.rb +4 -5
- data/lib/glimmer/libui/attributed_string.rb +19 -6
- data/lib/glimmer/libui/control_proxy/area_proxy.rb +52 -46
- data/lib/glimmer/libui/control_proxy/entry_proxy.rb +5 -0
- data/lib/glimmer/libui/control_proxy/image_proxy.rb +4 -5
- data/lib/glimmer/libui/control_proxy/multiline_entry_proxy.rb +5 -0
- data/lib/glimmer/libui/control_proxy/table_proxy.rb +1 -1
- data/lib/glimmer/libui/control_proxy.rb +16 -1
- data/lib/glimmer/libui/shape.rb +6 -3
- metadata +17 -4
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.3
|
1
|
+
0.4.3
|
data/examples/basic_entry.rb
CHANGED
@@ -2,30 +2,33 @@
|
|
2
2
|
|
3
3
|
require 'glimmer-dsl-libui'
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
5
|
+
class BasicEntry
|
6
|
+
include Glimmer
|
7
|
+
|
8
|
+
attr_accessor :entry_text
|
9
|
+
|
10
|
+
def launch
|
11
|
+
window('Basic Entry', 300, 50) {
|
12
|
+
horizontal_box {
|
13
|
+
entry {
|
14
|
+
# stretchy true # Smart default option for appending to horizontal_box
|
15
|
+
text <=> [self, :entry_text, after_write: ->(text) {puts text; $stdout.flush}] # bidirectional data-binding between text property and entry_text attribute, printing after write to model.
|
16
|
+
}
|
17
|
+
|
18
|
+
button('Button') {
|
19
|
+
stretchy false # stretchy property is available when control is nested under horizontal_box
|
20
|
+
|
21
|
+
on_clicked do
|
22
|
+
msg_box('You entered', entry_text)
|
23
|
+
end
|
24
|
+
}
|
25
|
+
}
|
20
26
|
|
21
|
-
|
22
|
-
|
23
|
-
msg_box('You entered', text)
|
27
|
+
on_closing do
|
28
|
+
puts 'Bye Bye'
|
24
29
|
end
|
25
|
-
}
|
26
|
-
}
|
27
|
-
|
28
|
-
on_closing do
|
29
|
-
puts 'Bye Bye'
|
30
|
+
}.show
|
30
31
|
end
|
31
|
-
|
32
|
+
end
|
33
|
+
|
34
|
+
BasicEntry.new.launch
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'glimmer-dsl-libui'
|
4
|
+
|
5
|
+
include Glimmer
|
6
|
+
|
7
|
+
window('Basic Entry', 300, 50) {
|
8
|
+
horizontal_box {
|
9
|
+
e = entry {
|
10
|
+
# stretchy true # Smart default option for appending to horizontal_box
|
11
|
+
|
12
|
+
on_changed do
|
13
|
+
puts e.text
|
14
|
+
$stdout.flush # For Windows
|
15
|
+
end
|
16
|
+
}
|
17
|
+
|
18
|
+
button('Button') {
|
19
|
+
stretchy false # stretchy property is available when control is nested under horizontal_box
|
20
|
+
|
21
|
+
on_clicked do
|
22
|
+
text = e.text
|
23
|
+
msg_box('You entered', text)
|
24
|
+
end
|
25
|
+
}
|
26
|
+
}
|
27
|
+
|
28
|
+
on_closing do
|
29
|
+
puts 'Bye Bye'
|
30
|
+
end
|
31
|
+
}.show
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'glimmer-dsl-libui'
|
2
|
+
|
3
|
+
class ButtonCounter
|
4
|
+
include Glimmer
|
5
|
+
|
6
|
+
attr_accessor :count
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@count = 0
|
10
|
+
end
|
11
|
+
|
12
|
+
def launch
|
13
|
+
window('Hello, Button!', 190, 20) {
|
14
|
+
vertical_box {
|
15
|
+
button {
|
16
|
+
text <= [self, :count, on_read: ->(count) {"Count: #{count}"}] # data-bind button text to self count, converting to string on read.
|
17
|
+
|
18
|
+
on_clicked do
|
19
|
+
self.count += 1
|
20
|
+
end
|
21
|
+
}
|
22
|
+
}
|
23
|
+
}.show
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
ButtonCounter.new.launch
|
@@ -26,7 +26,8 @@ class ColorTheCircles
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def register_observers
|
29
|
-
|
29
|
+
# observe automatically enhances self to become Glimmer::DataBinding::ObservableModel and notify observer block of score attribute changes
|
30
|
+
observe(self, :score) do |new_score|
|
30
31
|
Glimmer::LibUI.queue_main do
|
31
32
|
@score_label.text = new_score.to_s
|
32
33
|
if new_score == -20
|
@@ -40,7 +41,6 @@ class ColorTheCircles
|
|
40
41
|
end
|
41
42
|
end
|
42
43
|
end
|
43
|
-
observer.observe(self, :score) # automatically enhances self to become Glimmer::DataBinding::ObservableModel and notify observer on score attribute changes
|
44
44
|
end
|
45
45
|
|
46
46
|
def setup_circle_factory
|
data/examples/form.rb
CHANGED
@@ -2,36 +2,48 @@
|
|
2
2
|
|
3
3
|
require 'glimmer-dsl-libui'
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
window('Form') {
|
8
|
-
margined true
|
5
|
+
class Form
|
6
|
+
include Glimmer
|
9
7
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
@last_name_entry = entry {
|
17
|
-
label 'Last Name' # label property is available when control is nested under form
|
18
|
-
}
|
19
|
-
|
20
|
-
@phone_entry = entry {
|
21
|
-
label 'Phone' # label property is available when control is nested under form
|
22
|
-
}
|
8
|
+
attr_accessor :first_name, :last_name, :phone, :email
|
9
|
+
|
10
|
+
def launch
|
11
|
+
window('Form') {
|
12
|
+
margined true
|
23
13
|
|
24
|
-
|
25
|
-
|
14
|
+
vertical_box {
|
15
|
+
form {
|
16
|
+
entry {
|
17
|
+
label 'First Name' # label property is available when control is nested under form
|
18
|
+
text <=> [self, :first_name] # bidirectional data-binding of entry text property to self first_name attribute
|
19
|
+
}
|
20
|
+
|
21
|
+
entry {
|
22
|
+
label 'Last Name' # label property is available when control is nested under form
|
23
|
+
text <=> [self, :last_name]
|
24
|
+
}
|
25
|
+
|
26
|
+
entry {
|
27
|
+
label 'Phone' # label property is available when control is nested under form
|
28
|
+
text <=> [self, :phone]
|
29
|
+
}
|
30
|
+
|
31
|
+
entry {
|
32
|
+
label 'Email' # label property is available when control is nested under form
|
33
|
+
text <=> [self, :email]
|
34
|
+
}
|
35
|
+
}
|
36
|
+
|
37
|
+
button('Display Info') {
|
38
|
+
stretchy false
|
39
|
+
|
40
|
+
on_clicked do
|
41
|
+
msg_box('Info', "#{first_name} #{last_name} has phone #{phone} and email #{email}")
|
42
|
+
end
|
43
|
+
}
|
26
44
|
}
|
27
|
-
}
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
on_clicked do
|
33
|
-
msg_box('Info', "#{@first_name_entry.text} #{@last_name_entry.text} has phone #{@phone_entry.text} and email #{@email_entry.text}")
|
34
|
-
end
|
35
|
-
}
|
36
|
-
}
|
37
|
-
}.show
|
45
|
+
}.show
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
Form.new.launch
|
data/examples/form2.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'glimmer-dsl-libui'
|
4
|
+
|
5
|
+
include Glimmer
|
6
|
+
|
7
|
+
window('Form') {
|
8
|
+
margined true
|
9
|
+
|
10
|
+
vertical_box {
|
11
|
+
form {
|
12
|
+
@first_name_entry = entry {
|
13
|
+
label 'First Name' # label property is available when control is nested under form
|
14
|
+
}
|
15
|
+
|
16
|
+
@last_name_entry = entry {
|
17
|
+
label 'Last Name' # label property is available when control is nested under form
|
18
|
+
}
|
19
|
+
|
20
|
+
@phone_entry = entry {
|
21
|
+
label 'Phone' # label property is available when control is nested under form
|
22
|
+
}
|
23
|
+
|
24
|
+
@email_entry = entry {
|
25
|
+
label 'Email' # label property is available when control is nested under form
|
26
|
+
}
|
27
|
+
}
|
28
|
+
|
29
|
+
button('Display Info') {
|
30
|
+
stretchy false
|
31
|
+
|
32
|
+
on_clicked do
|
33
|
+
msg_box('Info', "#{@first_name_entry.text} #{@last_name_entry.text} has phone #{@phone_entry.text} and email #{@email_entry.text}")
|
34
|
+
end
|
35
|
+
}
|
36
|
+
}
|
37
|
+
}.show
|
data/examples/form_table.rb
CHANGED
@@ -2,94 +2,109 @@
|
|
2
2
|
|
3
3
|
require 'glimmer-dsl-libui'
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
data = [
|
8
|
-
['Lisa Sky', 'lisa@sky.com', '720-523-4329', 'Denver', 'CO', '80014'],
|
9
|
-
['Jordan Biggins', 'jordan@biggins.com', '617-528-5399', 'Boston', 'MA', '02101'],
|
10
|
-
['Mary Glass', 'mary@glass.com', '847-589-8788', 'Elk Grove Village', 'IL', '60007'],
|
11
|
-
['Darren McGrath', 'darren@mcgrath.com', '206-539-9283', 'Seattle', 'WA', '98101'],
|
12
|
-
['Melody Hanheimer', 'melody@hanheimer.com', '213-493-8274', 'Los Angeles', 'CA', '90001'],
|
13
|
-
]
|
14
|
-
|
15
|
-
window('Contacts', 600, 600) { |w|
|
16
|
-
margined true
|
5
|
+
class FormTable
|
6
|
+
include Glimmer
|
17
7
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
@
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
@
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
@city_entry = entry {
|
35
|
-
label 'City'
|
36
|
-
}
|
37
|
-
|
38
|
-
@state_entry = entry {
|
39
|
-
label 'State'
|
40
|
-
}
|
41
|
-
}
|
42
|
-
|
43
|
-
button('Save Contact') {
|
44
|
-
stretchy false
|
45
|
-
|
46
|
-
on_clicked do
|
47
|
-
new_row = [@name_entry.text, @email_entry.text, @phone_entry.text, @city_entry.text, @state_entry.text]
|
48
|
-
if new_row.include?('')
|
49
|
-
msg_box_error(w, 'Validation Error!', 'All fields are required! Please make sure to enter a value for all fields.')
|
50
|
-
else
|
51
|
-
data << new_row # automatically inserts a row into the table due to implicit data-binding
|
52
|
-
@unfiltered_data = data.dup
|
53
|
-
@name_entry.text = ''
|
54
|
-
@email_entry.text = ''
|
55
|
-
@phone_entry.text = ''
|
56
|
-
@city_entry.text = ''
|
57
|
-
@state_entry.text = ''
|
58
|
-
end
|
59
|
-
end
|
60
|
-
}
|
61
|
-
|
62
|
-
search_entry { |se|
|
63
|
-
stretchy false
|
8
|
+
attr_accessor :name, :email, :phone, :city, :state, :filter_value
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@data = [
|
12
|
+
['Lisa Sky', 'lisa@sky.com', '720-523-4329', 'Denver', 'CO', '80014'],
|
13
|
+
['Jordan Biggins', 'jordan@biggins.com', '617-528-5399', 'Boston', 'MA', '02101'],
|
14
|
+
['Mary Glass', 'mary@glass.com', '847-589-8788', 'Elk Grove Village', 'IL', '60007'],
|
15
|
+
['Darren McGrath', 'darren@mcgrath.com', '206-539-9283', 'Seattle', 'WA', '98101'],
|
16
|
+
['Melody Hanheimer', 'melody@hanheimer.com', '213-493-8274', 'Los Angeles', 'CA', '90001'],
|
17
|
+
]
|
18
|
+
end
|
19
|
+
|
20
|
+
def launch
|
21
|
+
window('Contacts', 600, 600) { |w|
|
22
|
+
margined true
|
64
23
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
24
|
+
vertical_box {
|
25
|
+
form {
|
26
|
+
stretchy false
|
27
|
+
|
28
|
+
entry {
|
29
|
+
label 'Name'
|
30
|
+
text <=> [self, :name]
|
31
|
+
}
|
32
|
+
|
33
|
+
entry {
|
34
|
+
label 'Email'
|
35
|
+
text <=> [self, :email]
|
36
|
+
}
|
37
|
+
|
38
|
+
entry {
|
39
|
+
label 'Phone'
|
40
|
+
text <=> [self, :phone]
|
41
|
+
}
|
42
|
+
|
43
|
+
entry {
|
44
|
+
label 'City'
|
45
|
+
text <=> [self, :city]
|
46
|
+
}
|
47
|
+
|
48
|
+
entry {
|
49
|
+
label 'State'
|
50
|
+
text <=> [self, :state]
|
51
|
+
}
|
52
|
+
}
|
53
|
+
|
54
|
+
button('Save Contact') {
|
55
|
+
stretchy false
|
56
|
+
|
57
|
+
on_clicked do
|
58
|
+
new_row = [name, email, phone, city, state]
|
59
|
+
if new_row.include?('')
|
60
|
+
msg_box_error(w, 'Validation Error!', 'All fields are required! Please make sure to enter a value for all fields.')
|
61
|
+
else
|
62
|
+
@data << new_row # automatically inserts a row into the table due to implicit data-binding
|
63
|
+
@unfiltered_data = @data.dup
|
64
|
+
self.name = '' # automatically clears name entry through explicit data-binding
|
65
|
+
self.email = ''
|
66
|
+
self.phone = ''
|
67
|
+
self.city = ''
|
68
|
+
self.state = ''
|
75
69
|
end
|
76
70
|
end
|
77
|
-
|
78
|
-
|
79
|
-
|
71
|
+
}
|
72
|
+
|
73
|
+
search_entry {
|
74
|
+
stretchy false
|
75
|
+
text <=> [self, :filter_value, # bidirectional data-binding of text to self.filter_value with after_write option
|
76
|
+
after_write: ->(filter_value) { # execute after write to self.filter_value
|
77
|
+
@unfiltered_data ||= @data.dup
|
78
|
+
# Unfilter first to remove any previous filters
|
79
|
+
@data.replace(@unfiltered_data) # affects table indirectly through implicit data-binding
|
80
|
+
# Now, apply filter if entered
|
81
|
+
unless filter_value.empty?
|
82
|
+
@data.filter! do |row_data| # affects table indirectly through implicit data-binding
|
83
|
+
row_data.any? do |cell|
|
84
|
+
cell.to_s.downcase.include?(filter_value.downcase)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
}
|
89
|
+
]
|
90
|
+
}
|
91
|
+
|
92
|
+
table {
|
93
|
+
text_column('Name')
|
94
|
+
text_column('Email')
|
95
|
+
text_column('Phone')
|
96
|
+
text_column('City')
|
97
|
+
text_column('State')
|
80
98
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
99
|
+
cell_rows @data # implicit data-binding
|
100
|
+
|
101
|
+
on_changed do |row, type, row_data|
|
102
|
+
puts "Row #{row} #{type}: #{row_data}"
|
103
|
+
end
|
104
|
+
}
|
105
|
+
}
|
106
|
+
}.show
|
107
|
+
end
|
108
|
+
end
|
87
109
|
|
88
|
-
|
89
|
-
|
90
|
-
on_changed do |row, type, row_data|
|
91
|
-
puts "Row #{row} #{type}: #{row_data}"
|
92
|
-
end
|
93
|
-
}
|
94
|
-
}
|
95
|
-
}.show
|
110
|
+
FormTable.new.launch
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'glimmer-dsl-libui'
|
4
|
+
|
5
|
+
include Glimmer
|
6
|
+
|
7
|
+
data = [
|
8
|
+
['Lisa Sky', 'lisa@sky.com', '720-523-4329', 'Denver', 'CO', '80014'],
|
9
|
+
['Jordan Biggins', 'jordan@biggins.com', '617-528-5399', 'Boston', 'MA', '02101'],
|
10
|
+
['Mary Glass', 'mary@glass.com', '847-589-8788', 'Elk Grove Village', 'IL', '60007'],
|
11
|
+
['Darren McGrath', 'darren@mcgrath.com', '206-539-9283', 'Seattle', 'WA', '98101'],
|
12
|
+
['Melody Hanheimer', 'melody@hanheimer.com', '213-493-8274', 'Los Angeles', 'CA', '90001'],
|
13
|
+
]
|
14
|
+
|
15
|
+
window('Contacts', 600, 600) { |w|
|
16
|
+
margined true
|
17
|
+
|
18
|
+
vertical_box {
|
19
|
+
form {
|
20
|
+
stretchy false
|
21
|
+
|
22
|
+
@name_entry = entry {
|
23
|
+
label 'Name'
|
24
|
+
}
|
25
|
+
|
26
|
+
@email_entry = entry {
|
27
|
+
label 'Email'
|
28
|
+
}
|
29
|
+
|
30
|
+
@phone_entry = entry {
|
31
|
+
label 'Phone'
|
32
|
+
}
|
33
|
+
|
34
|
+
@city_entry = entry {
|
35
|
+
label 'City'
|
36
|
+
}
|
37
|
+
|
38
|
+
@state_entry = entry {
|
39
|
+
label 'State'
|
40
|
+
}
|
41
|
+
}
|
42
|
+
|
43
|
+
button('Save Contact') {
|
44
|
+
stretchy false
|
45
|
+
|
46
|
+
on_clicked do
|
47
|
+
new_row = [@name_entry.text, @email_entry.text, @phone_entry.text, @city_entry.text, @state_entry.text]
|
48
|
+
if new_row.include?('')
|
49
|
+
msg_box_error(w, 'Validation Error!', 'All fields are required! Please make sure to enter a value for all fields.')
|
50
|
+
else
|
51
|
+
data << new_row # automatically inserts a row into the table due to implicit data-binding
|
52
|
+
@unfiltered_data = data.dup
|
53
|
+
@name_entry.text = ''
|
54
|
+
@email_entry.text = ''
|
55
|
+
@phone_entry.text = ''
|
56
|
+
@city_entry.text = ''
|
57
|
+
@state_entry.text = ''
|
58
|
+
end
|
59
|
+
end
|
60
|
+
}
|
61
|
+
|
62
|
+
search_entry { |se|
|
63
|
+
stretchy false
|
64
|
+
|
65
|
+
on_changed do
|
66
|
+
filter_value = se.text
|
67
|
+
@unfiltered_data ||= data.dup
|
68
|
+
# Unfilter first to remove any previous filters
|
69
|
+
data.replace(@unfiltered_data) # affects table indirectly through implicit data-binding
|
70
|
+
# Now, apply filter if entered
|
71
|
+
unless filter_value.empty?
|
72
|
+
data.filter! do |row_data| # affects table indirectly through implicit data-binding
|
73
|
+
row_data.any? do |cell|
|
74
|
+
cell.to_s.downcase.include?(filter_value.downcase)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
}
|
80
|
+
|
81
|
+
table {
|
82
|
+
text_column('Name')
|
83
|
+
text_column('Email')
|
84
|
+
text_column('Phone')
|
85
|
+
text_column('City')
|
86
|
+
text_column('State')
|
87
|
+
|
88
|
+
cell_rows data # implicit data-binding
|
89
|
+
|
90
|
+
on_changed do |row, type, row_data|
|
91
|
+
puts "Row #{row} #{type}: #{row_data}"
|
92
|
+
end
|
93
|
+
}
|
94
|
+
}
|
95
|
+
}.show
|
data/examples/login.rb
CHANGED
@@ -1,45 +1,51 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
1
|
require 'glimmer-dsl-libui'
|
4
2
|
|
5
|
-
|
6
|
-
|
7
|
-
window('Login') {
|
8
|
-
margined true
|
3
|
+
class Login
|
4
|
+
include Glimmer
|
9
5
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
@password_entry = password_entry {
|
17
|
-
label 'Password:'
|
18
|
-
}
|
19
|
-
}
|
20
|
-
|
21
|
-
horizontal_box {
|
22
|
-
@login_button = button('Login') {
|
23
|
-
on_clicked do
|
24
|
-
@username_entry.enabled = false
|
25
|
-
@password_entry.enabled = false
|
26
|
-
@login_button.enabled = false
|
27
|
-
@logout_button.enabled = true
|
28
|
-
end
|
29
|
-
}
|
6
|
+
attr_accessor :username, :password, :logged_in
|
7
|
+
|
8
|
+
def launch
|
9
|
+
window('Login') {
|
10
|
+
margined true
|
30
11
|
|
31
|
-
|
32
|
-
|
12
|
+
vertical_box {
|
13
|
+
form {
|
14
|
+
entry {
|
15
|
+
label 'Username:'
|
16
|
+
text <=> [self, :username]
|
17
|
+
enabled <= [self, :logged_in, on_read: :!] # `on_read: :!` negates read value
|
18
|
+
}
|
19
|
+
|
20
|
+
password_entry {
|
21
|
+
label 'Password:'
|
22
|
+
text <=> [self, :password]
|
23
|
+
enabled <= [self, :logged_in, on_read: :!]
|
24
|
+
}
|
25
|
+
}
|
33
26
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
27
|
+
horizontal_box {
|
28
|
+
button('Login') {
|
29
|
+
enabled <= [self, :logged_in, on_read: :!]
|
30
|
+
|
31
|
+
on_clicked do
|
32
|
+
self.logged_in = true
|
33
|
+
end
|
34
|
+
}
|
35
|
+
|
36
|
+
button('Logout') {
|
37
|
+
enabled <= [self, :logged_in]
|
38
|
+
|
39
|
+
on_clicked do
|
40
|
+
self.logged_in = false
|
41
|
+
self.username = ''
|
42
|
+
self.password = ''
|
43
|
+
end
|
44
|
+
}
|
45
|
+
}
|
42
46
|
}
|
43
|
-
}
|
44
|
-
|
45
|
-
|
47
|
+
}.show
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
Login.new.launch
|