glimmer-dsl-tk 0.0.4 → 0.0.8

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.
@@ -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