glimmer-dsl-tk 0.0.4 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,5 @@
1
- # Copyright (c) 2020 Andy Maleh
2
- #
1
+ # Copyright (c) 2020-2021 Andy Maleh
2
+ #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
5
5
  # "Software"), to deal in the Software without restriction, including
@@ -7,10 +7,10 @@
7
7
  # distribute, sublicense, and/or sell copies of the Software, and to
8
8
  # permit persons to whom the Software is furnished to do so, subject to
9
9
  # the following conditions:
10
- #
10
+ #
11
11
  # The above copyright notice and this permission notice shall be
12
12
  # included in all copies or substantial portions of the Software.
13
- #
13
+ #
14
14
  # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
15
  # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
16
  # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
@@ -22,7 +22,7 @@
22
22
  require 'glimmer/tk/widget_proxy'
23
23
 
24
24
  module Glimmer
25
- module Tk
25
+ module Tk
26
26
  # Custom list widget implementation
27
27
  class ListProxy < WidgetProxy
28
28
  def initialize(underscored_widget_name, parent_proxy, args)
@@ -35,16 +35,16 @@ module Glimmer
35
35
  ::Tk::Tile::Treeview => {
36
36
  'items' => {
37
37
  getter: {name: 'items', invoker: lambda { |widget, args| tk.children('').map(&:text) }},
38
- setter: {name: 'items=', invoker: lambda { |widget, args|
38
+ setter: {name: 'items=', invoker: lambda { |widget, args|
39
39
  @tk.delete @tk.children('')
40
40
  args.first.each do |child|
41
41
  @tk.insert('', 'end', :text => child)
42
- end
42
+ end
43
43
  }},
44
44
  },
45
45
  'selection' => {
46
46
  getter: {name: 'selection', invoker: lambda { |widget, args| @tk.selection.map(&:text) }},
47
- setter: {name: 'selection=', invoker: lambda { |widget, args|
47
+ setter: {name: 'selection=', invoker: lambda { |widget, args|
48
48
  selection_args = args.first.is_a?(Array) ? args.first : [args.first]
49
49
  selection_items = selection_args.map do |arg|
50
50
  @tk.children('').detect {|item| item.text == arg}
@@ -1,5 +1,5 @@
1
- # Copyright (c) 2020 Andy Maleh
2
- #
1
+ # Copyright (c) 2020-2021 Andy Maleh
2
+ #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
5
5
  # "Software"), to deal in the Software without restriction, including
@@ -7,10 +7,10 @@
7
7
  # distribute, sublicense, and/or sell copies of the Software, and to
8
8
  # permit persons to whom the Software is furnished to do so, subject to
9
9
  # the following conditions:
10
- #
10
+ #
11
11
  # The above copyright notice and this permission notice shall be
12
12
  # included in all copies or substantial portions of the Software.
13
- #
13
+ #
14
14
  # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
15
  # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
16
  # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
@@ -22,7 +22,7 @@
22
22
  require 'glimmer/tk/widget_proxy'
23
23
 
24
24
  module Glimmer
25
- module Tk
25
+ module Tk
26
26
  # Proxy for Tk::Tile::Notebook
27
27
  #
28
28
  # Follows the Proxy Design Pattern
@@ -1,5 +1,5 @@
1
- # Copyright (c) 2020 Andy Maleh
2
- #
1
+ # Copyright (c) 2020-2021 Andy Maleh
2
+ #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
5
5
  # "Software"), to deal in the Software without restriction, including
@@ -7,10 +7,10 @@
7
7
  # distribute, sublicense, and/or sell copies of the Software, and to
8
8
  # permit persons to whom the Software is furnished to do so, subject to
9
9
  # the following conditions:
10
- #
10
+ #
11
11
  # The above copyright notice and this permission notice shall be
12
12
  # included in all copies or substantial portions of the Software.
13
- #
13
+ #
14
14
  # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
15
  # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
16
  # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
@@ -27,11 +27,14 @@ module Glimmer
27
27
  #
28
28
  # Follows the Proxy Design Pattern
29
29
  class RootProxy < WidgetProxy
30
-
31
30
  def initialize(*args)
32
31
  @tk = ::TkRoot.new
33
32
  end
34
33
 
34
+ def post_add_content
35
+ set_attribute('iconphoto', File.expand_path('../../../icons/glimmer.png', __dir__)) if @tk.iconphoto.nil?
36
+ end
37
+
35
38
  def open
36
39
  start_event_loop
37
40
  end
@@ -39,6 +42,17 @@ module Glimmer
39
42
  def content(&block)
40
43
  Glimmer::DSL::Engine.add_content(self, Glimmer::DSL::Tk::RootExpression.new, &block)
41
44
  end
45
+
46
+ def set_attribute(attribute, *args)
47
+ if attribute.to_s == 'iconphoto'
48
+ if args.size == 1 && args.first.is_a?(String)
49
+ args[0] = ::TkPhotoImage.new(file: args.first)
50
+ end
51
+ super
52
+ else
53
+ super
54
+ end
55
+ end
42
56
 
43
57
  # Starts Tk mainloop
44
58
  def start_event_loop
@@ -1,5 +1,5 @@
1
- # Copyright (c) 2020 Andy Maleh
2
- #
1
+ # Copyright (c) 2020-2021 Andy Maleh
2
+ #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
5
5
  # "Software"), to deal in the Software without restriction, including
@@ -7,10 +7,10 @@
7
7
  # distribute, sublicense, and/or sell copies of the Software, and to
8
8
  # permit persons to whom the Software is furnished to do so, subject to
9
9
  # the following conditions:
10
- #
10
+ #
11
11
  # The above copyright notice and this permission notice shall be
12
12
  # included in all copies or substantial portions of the Software.
13
- #
13
+ #
14
14
  # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
15
  # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
16
  # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
@@ -29,7 +29,13 @@ module Glimmer
29
29
 
30
30
  DEFAULT_INITIALIZERS = {
31
31
  'combobox' => lambda do |tk|
32
- tk.textvariable = ::TkVariable.new
32
+ tk.textvariable = ::TkVariable.new
33
+ end,
34
+ 'label' => lambda do |tk|
35
+ tk.textvariable = ::TkVariable.new
36
+ end,
37
+ 'entry' => lambda do |tk|
38
+ tk.textvariable = ::TkVariable.new
33
39
  end,
34
40
  }
35
41
 
@@ -44,17 +50,17 @@ module Glimmer
44
50
  Glimmer::Tk.const_get(class_name)
45
51
  rescue
46
52
  Glimmer::Tk::WidgetProxy
47
- end
53
+ end
48
54
  end
49
55
 
50
56
  # This supports widgets in and out of basic Tk
51
57
  def tk_widget_class_for(underscored_widget_name)
52
58
  tk_widget_class_basename = underscored_widget_name.camelcase(:upper)
53
59
  potential_tk_widget_class_names = [
54
- "::Tk::Tile::#{tk_widget_class_basename}",
55
- "::Tk::#{tk_widget_class_basename}",
56
- "::Tk#{tk_widget_class_basename}",
57
- "::Glimmer::Tk::#{tk_widget_class_basename}Proxy",
60
+ "::Tk::Tile::#{tk_widget_class_basename}",
61
+ "::Tk::#{tk_widget_class_basename}",
62
+ "::Tk#{tk_widget_class_basename}",
63
+ "::Glimmer::Tk::#{tk_widget_class_basename}Proxy",
58
64
  ]
59
65
  tk_widget_class = nil
60
66
  potential_tk_widget_class_names.each do |tk_widget_name|
@@ -63,11 +69,11 @@ module Glimmer
63
69
  break
64
70
  rescue RuntimeError, SyntaxError, NameError => e
65
71
  Glimmer::Config.logger.debug e.full_message
66
- end
72
+ end
67
73
  end
68
74
  tk_widget_class
69
75
  end
70
- end
76
+ end
71
77
 
72
78
  # Initializes a new Tk Widget
73
79
  #
@@ -79,7 +85,7 @@ module Glimmer
79
85
  @tk = tk_widget_class.new(@parent_proxy.tk, *args)
80
86
  # a common widget initializer
81
87
  @tk.grid
82
- DEFAULT_INITIALIZERS[underscored_widget_name]&.call(@tk)
88
+ DEFAULT_INITIALIZERS[underscored_widget_name]&.call(@tk)
83
89
  @parent_proxy.post_initialize_child(self)
84
90
  end
85
91
 
@@ -97,21 +103,26 @@ module Glimmer
97
103
  !!tk_widget_class_for(underscored_widget_name)
98
104
  end
99
105
 
100
- def tk_widget_has_attribute?(attribute)
106
+ def tk_widget_has_attribute_setter?(attribute)
101
107
  result = nil
102
- begin
103
- # TK Widget currently doesn't support respond_to? properly, so I have to resort to this trick for now
108
+ begin
109
+ # TK Widget currently doesn't support respond_to? properly, so I have to resort to this trick for now
104
110
  @tk.send(attribute_setter(attribute), @tk.send(attribute))
105
111
  result = true
106
112
  rescue => e
107
113
  result = false
108
114
  end
109
- result
115
+ result
116
+ end
117
+
118
+ def tk_widget_has_attribute_getter_setter?(attribute)
119
+ @tk.respond_to?(attribute)
110
120
  end
111
121
 
112
122
  def has_attribute?(attribute, *args)
113
- (widget_custom_attribute_mapping[tk.class] && widget_custom_attribute_mapping[tk.class][attribute.to_s]) ||
114
- tk_widget_has_attribute?(attribute) ||
123
+ (widget_custom_attribute_mapping[tk.class] && widget_custom_attribute_mapping[tk.class][attribute.to_s]) ||
124
+ tk_widget_has_attribute_setter?(attribute) ||
125
+ tk_widget_has_attribute_getter_setter?(attribute) ||
115
126
  respond_to?(attribute_setter(attribute), args)
116
127
  end
117
128
 
@@ -119,8 +130,10 @@ module Glimmer
119
130
  widget_custom_attribute = widget_custom_attribute_mapping[tk.class] && widget_custom_attribute_mapping[tk.class][attribute.to_s]
120
131
  if widget_custom_attribute
121
132
  widget_custom_attribute[:setter][:invoker].call(@tk, args)
122
- elsif tk_widget_has_attribute?(attribute)
133
+ elsif tk_widget_has_attribute_setter?(attribute)
123
134
  @tk.send(attribute_setter(attribute), *args) unless @tk.send(attribute) == args.first
135
+ elsif tk_widget_has_attribute_getter_setter?(attribute)
136
+ @tk.send(attribute, *args) unless @tk.send(attribute) == args.first
124
137
  else
125
138
  send(attribute_setter(attribute), args)
126
139
  end
@@ -130,7 +143,7 @@ module Glimmer
130
143
  widget_custom_attribute = widget_custom_attribute_mapping[tk.class] && widget_custom_attribute_mapping[tk.class][attribute.to_s]
131
144
  if widget_custom_attribute
132
145
  widget_custom_attribute[:getter][:invoker].call(@tk, args)
133
- elsif tk_widget_has_attribute?(attribute)
146
+ elsif tk_widget_has_attribute_getter_setter?(attribute)
134
147
  @tk.send(attribute)
135
148
  else
136
149
  send(attribute)
@@ -149,6 +162,18 @@ module Glimmer
149
162
  setter: {name: 'text=', invoker: lambda { |widget, args| @tk.textvariable&.value = args.first }},
150
163
  },
151
164
  },
165
+ ::Tk::Tile::TLabel => {
166
+ 'text' => {
167
+ getter: {name: 'text', invoker: lambda { |widget, args| @tk.textvariable&.value }},
168
+ setter: {name: 'text=', invoker: lambda { |widget, args| @tk.textvariable&.value = args.first }},
169
+ },
170
+ },
171
+ ::Tk::Tile::TEntry => {
172
+ 'text' => {
173
+ getter: {name: 'text', invoker: lambda { |widget, args| @tk.textvariable&.value }},
174
+ setter: {name: 'text=', invoker: lambda { |widget, args| @tk.textvariable&.value = args.first unless @text_variable_edit }},
175
+ },
176
+ },
152
177
  }
153
178
  end
154
179
 
@@ -166,6 +191,21 @@ module Glimmer
166
191
  }
167
192
  end,
168
193
  },
194
+ ::Tk::Tile::TEntry => {
195
+ 'text' => lambda do |observer|
196
+ tk.validate = 'key'
197
+ tk.validatecommand { |new_tk_variable|
198
+ @text_variable_edit = new_tk_variable.value != @tk.textvariable.value
199
+ if @text_variable_edit
200
+ observer.call(new_tk_variable.value)
201
+ @text_variable_edit = nil
202
+ true
203
+ else
204
+ false
205
+ end
206
+ }
207
+ end,
208
+ },
169
209
  }
170
210
  end
171
211
 
@@ -173,7 +213,7 @@ module Glimmer
173
213
  attribute_listener_installers = @tk.class.ancestors.map {|ancestor| widget_attribute_listener_installers[ancestor]}.compact
174
214
  widget_listener_installers = attribute_listener_installers.map{|installer| installer[attribute.to_s]}.compact if !attribute_listener_installers.empty?
175
215
  widget_listener_installers.to_a.first&.call(observer)
176
- end
216
+ end
177
217
 
178
218
  def content(&block)
179
219
  Glimmer::DSL::Engine.add_content(self, Glimmer::DSL::Tk::WidgetExpression.new, &block)
@@ -194,7 +234,7 @@ module Glimmer
194
234
  end
195
235
 
196
236
  def respond_to?(method, *args, &block)
197
- super ||
237
+ super ||
198
238
  tk.respond_to?(method, *args, &block)
199
239
  end
200
240
  end
@@ -1,5 +1,5 @@
1
- # Copyright (c) 2020 Andy Maleh
2
- #
1
+ # Copyright (c) 2020-2021 Andy Maleh
2
+ #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
5
5
  # "Software"), to deal in the Software without restriction, including
@@ -7,10 +7,10 @@
7
7
  # distribute, sublicense, and/or sell copies of the Software, and to
8
8
  # permit persons to whom the Software is furnished to do so, subject to
9
9
  # the following conditions:
10
- #
10
+ #
11
11
  # The above copyright notice and this permission notice shall be
12
12
  # included in all copies or substantial portions of the Software.
13
- #
13
+ #
14
14
  # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
15
  # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
16
  # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
@@ -1,5 +1,5 @@
1
- # Copyright (c) 2020 Andy Maleh
2
- #
1
+ # Copyright (c) 2020-2021 Andy Maleh
2
+ #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
5
5
  # "Software"), to deal in the Software without restriction, including
@@ -7,10 +7,10 @@
7
7
  # distribute, sublicense, and/or sell copies of the Software, and to
8
8
  # permit persons to whom the Software is furnished to do so, subject to
9
9
  # the following conditions:
10
- #
10
+ #
11
11
  # The above copyright notice and this permission notice shall be
12
12
  # included in all copies or substantial portions of the Software.
13
- #
13
+ #
14
14
  # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
15
  # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
16
  # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
@@ -21,10 +21,10 @@
21
21
 
22
22
  require 'glimmer-dsl-tk'
23
23
 
24
- class Person
24
+ class Person
25
25
  attr_accessor :country, :country_options
26
26
 
27
- def initialize
27
+ def initialize
28
28
  self.country_options=["", "Canada", "US", "Mexico"]
29
29
  self.country = "Canada"
30
30
  end
@@ -43,12 +43,12 @@ class HelloCombo
43
43
  root {
44
44
  title 'Hello, Combo!'
45
45
 
46
- combobox { |proxy|
47
- state 'readonly'
46
+ combobox {
47
+ state 'readonly'
48
48
  text bind(person, :country)
49
49
  }
50
50
 
51
- button { |proxy|
51
+ button {
52
52
  text "Reset Selection"
53
53
  command {
54
54
  person.reset_country
@@ -0,0 +1,21 @@
1
+ class HelloComputed
2
+ class Contact
3
+ attr_accessor :first_name, :last_name, :year_of_birth
4
+
5
+ def initialize(attribute_map)
6
+ @first_name = attribute_map[:first_name]
7
+ @last_name = attribute_map[:last_name]
8
+ @year_of_birth = attribute_map[:year_of_birth]
9
+ end
10
+
11
+ def name
12
+ "#{last_name}, #{first_name}"
13
+ end
14
+
15
+ def age
16
+ Time.now.year - year_of_birth.to_i
17
+ rescue
18
+ 0
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,96 @@
1
+ # Copyright (c) 2020-2021 Andy Maleh
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining
4
+ # a copy of this software and associated documentation files (the
5
+ # "Software"), to deal in the Software without restriction, including
6
+ # without limitation the rights to use, copy, modify, merge, publish,
7
+ # distribute, sublicense, and/or sell copies of the Software, and to
8
+ # permit persons to whom the Software is furnished to do so, subject to
9
+ # the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be
12
+ # included in all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
22
+ require 'glimmer-dsl-tk'
23
+
24
+ require_relative 'hello_computed/contact'
25
+
26
+ class HelloComputed
27
+ include Glimmer
28
+
29
+ def initialize
30
+ @contact = Contact.new(
31
+ first_name: 'Barry',
32
+ last_name: 'McKibbin',
33
+ year_of_birth: 1985
34
+ )
35
+ end
36
+
37
+ def launch
38
+ root {
39
+ title 'Hello, Computed!'
40
+
41
+ frame {
42
+ grid column: 0, row: 0, padx: 5, pady: 5
43
+
44
+ label {
45
+ grid column: 0, row: 0, sticky: 'w'
46
+ text 'First Name: '
47
+ }
48
+ entry {
49
+ grid column: 1, row: 0
50
+ width 15
51
+ text bind(@contact, :first_name)
52
+ }
53
+
54
+ label {
55
+ grid column: 0, row: 1, sticky: 'w'
56
+ text 'Last Name: '
57
+ }
58
+ entry {
59
+ grid column: 1, row: 1
60
+ width 15
61
+ text bind(@contact, :last_name)
62
+ }
63
+
64
+ label {
65
+ grid column: 0, row: 2, sticky: 'w'
66
+ text 'Year of Birth: '
67
+ }
68
+ entry {
69
+ grid column: 1, row: 2
70
+ width 15
71
+ text bind(@contact, :year_of_birth)
72
+ }
73
+
74
+ label {
75
+ grid column: 0, row: 3, sticky: 'w'
76
+ text 'Name: '
77
+ }
78
+ label {
79
+ grid column: 1, row: 3, sticky: 'w'
80
+ text bind(@contact, :name, computed_by: [:first_name, :last_name])
81
+ }
82
+
83
+ label {
84
+ grid column: 0, row: 4, sticky: 'w'
85
+ text 'Age: '
86
+ }
87
+ label {
88
+ grid column: 1, row: 4, sticky: 'w'
89
+ text bind(@contact, :age, on_write: :to_i, computed_by: [:year_of_birth])
90
+ }
91
+ }
92
+ }.open
93
+ end
94
+ end
95
+
96
+ HelloComputed.new.launch