simple_tk 0.1.0
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 +7 -0
- data/.gitignore +9 -0
- data/.travis.yml +5 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +84 -0
- data/Rakefile +10 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/simple_tk/errors.rb +16 -0
- data/lib/simple_tk/get_set_helper.rb +79 -0
- data/lib/simple_tk/version.rb +3 -0
- data/lib/simple_tk/widget_helpers.rb +30 -0
- data/lib/simple_tk/window.rb +667 -0
- data/lib/simple_tk.rb +44 -0
- metadata +114 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 688f0fe3a07729c95ffe968c6d1bb55a846ef7d9
|
4
|
+
data.tar.gz: b96b21a78f9c6244bc66cb07018c5f356c003473
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 524e8e9e20024a885938ea049b292c04a393c5ebbfe7acdcc1600d1fc5a3f48ac313a257a858cee2ae287f95a2fe72b939411338f2bc2545417493ddb55f5de1
|
7
|
+
data.tar.gz: 656d163a645705cf9964754a7c96a510d75de50616c190a38b21ff06887817ecbd0cf9cd2e5df00cf27674d639a5232c60d00c7e390ba3e37e9d0ec591bb15a4
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2017 Beau Barker
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
# SimpleTk
|
2
|
+
|
3
|
+
I wanted a really simple GUI library for Ruby. Not because I think Ruby should be used for GUI
|
4
|
+
applications, but because I think it should be able to tbe used for GUI applications.
|
5
|
+
|
6
|
+
Really I wanted something to make a quick configuration app using an existing Ruby gem I had
|
7
|
+
written. I started out with a simple console app, but I decided I wanted something even simpler
|
8
|
+
for the eventual day when somebody else has to use it.
|
9
|
+
|
10
|
+
So I searched. First I found Shoes. Which would be acceptable except Shoes 3 does not have a gem
|
11
|
+
and Shoes 4 requires JRuby. Ok moving on, we have several other libraries that interface with other
|
12
|
+
libraries. And then Tk, which is from the Ruby code base. So time to learn Tk, which turns out has
|
13
|
+
a lot of repeated steps and code. Well that's easy enough to correct. I wrote a quick wrapper and
|
14
|
+
built my config app.
|
15
|
+
|
16
|
+
I extracted that wrapper and built it up to support more than just labels, entries, and buttons.
|
17
|
+
This gem is the end result of that action.
|
18
|
+
|
19
|
+
## Installation
|
20
|
+
|
21
|
+
Add this line to your application's Gemfile:
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
gem 'simple_tk'
|
25
|
+
```
|
26
|
+
|
27
|
+
And then execute:
|
28
|
+
|
29
|
+
$ bundle
|
30
|
+
|
31
|
+
Or install it yourself as:
|
32
|
+
|
33
|
+
$ gem install simple_tk
|
34
|
+
|
35
|
+
## Usage
|
36
|
+
|
37
|
+
You can build windows using either a block passed to a window constructor or by calling the methods
|
38
|
+
on the created window. Call `SimpleTk.run` to run your application. You can use `SimpleTk.alert` and
|
39
|
+
`SimpleTk.ask` for basic message boxes. In all cases, the Tk library is available if you need more
|
40
|
+
advanced options.
|
41
|
+
|
42
|
+
```ruby
|
43
|
+
require 'simple_tk'
|
44
|
+
|
45
|
+
win = SimpleTk::Window.new(title: "My Program", window_geometry: "400x300") do
|
46
|
+
add_label :label1, "Hello World!", :column => 0, :row => 0
|
47
|
+
add_frame(:frame1, :column => 0, :row => 1) do
|
48
|
+
add_button(:btn1, "Button 1", :position => [ 0, 0 ]) do
|
49
|
+
SimpleTk.alert "You clicked Button 1!"
|
50
|
+
end
|
51
|
+
add_button :btn2,
|
52
|
+
"Button 2",
|
53
|
+
:position => { x: 1, y: 0 },
|
54
|
+
:command => ->{ SimpleTk.alert "You clicked Button 2!" }
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
win.add_label :label2, "Goodby World!", :column => 0, :row => 2
|
59
|
+
|
60
|
+
win.config_column 0, weight: 1
|
61
|
+
|
62
|
+
(0..win.row_count).each do |row|
|
63
|
+
win.config_row row, weight: 1
|
64
|
+
end
|
65
|
+
|
66
|
+
# Use the Tk 'bind' method on the :btn2 object.
|
67
|
+
win.object[:frame1].object[:btn2].bind("3") do
|
68
|
+
SimpleTk.alert "You right-clicked on Button 2!"
|
69
|
+
end
|
70
|
+
|
71
|
+
SimpleTk.run
|
72
|
+
```
|
73
|
+
|
74
|
+
|
75
|
+
|
76
|
+
## Contributing
|
77
|
+
|
78
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/barkerest/simple_tk.
|
79
|
+
|
80
|
+
|
81
|
+
## License
|
82
|
+
|
83
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
84
|
+
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "simple_tk"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
module SimpleTk
|
2
|
+
##
|
3
|
+
# A helper class to make hash instance variables more accessible.
|
4
|
+
class GetSetHelper
|
5
|
+
|
6
|
+
##
|
7
|
+
# Creates a helper for a specific hash in a parent object.
|
8
|
+
#
|
9
|
+
# This helper does not support adding items to the connected hash.
|
10
|
+
#
|
11
|
+
# Parameters:
|
12
|
+
# parent::
|
13
|
+
# The parent object this helper accesses.
|
14
|
+
# hash_ivar::
|
15
|
+
# The name (as a symbol) of the instance variable in the parent object to access.
|
16
|
+
# (eg - :@data)
|
17
|
+
# auto_symbol::
|
18
|
+
# Should names be converted to symbols in the accessors, defaults to true.
|
19
|
+
# getter::
|
20
|
+
# The method or proc to call when getting a value.
|
21
|
+
# If this is a Symbol then it defines the method name of the retrieved value to call.
|
22
|
+
# If this is a Proc then it will be called with the retrieved value as an argument.
|
23
|
+
# If this is nil then the retrieved value is returned.
|
24
|
+
# setter::
|
25
|
+
# The method or proc to call when setting a value.
|
26
|
+
# If this is a Symbol then it defines the method name of the retrieved value to call with the new value.
|
27
|
+
# If this ia a Proc then it will be called with the retrieved value and the new value as arguments.
|
28
|
+
# If this is nil then the hash value is replaced with the new value.
|
29
|
+
#
|
30
|
+
# GetSetHelper.new(my_obj, :@data)
|
31
|
+
# GetSetHelper.new(my_obj, :@data, true, :value, :value=)
|
32
|
+
# GetSetHelper.new(my_obj, :@data, true, ->(v){ v.value }, ->(i,v){ i.value = v })
|
33
|
+
def initialize(parent, hash_ivar, auto_symbol = true, getter = nil, setter = nil)
|
34
|
+
@parent = parent
|
35
|
+
@hash_ivar = hash_ivar
|
36
|
+
@auto_symbol = auto_symbol
|
37
|
+
@getter = getter
|
38
|
+
@setter = setter
|
39
|
+
end
|
40
|
+
|
41
|
+
##
|
42
|
+
# Gets the value for the given name.
|
43
|
+
def [](name)
|
44
|
+
name = name.to_sym if @auto_symbol
|
45
|
+
h = @parent.instance_variable_get(@hash_ivar)
|
46
|
+
if h.include?(name)
|
47
|
+
v = h[name]
|
48
|
+
if @getter.is_a?(Symbol)
|
49
|
+
v.send @getter
|
50
|
+
elsif @getter.is_a?(Proc)
|
51
|
+
@getter.call v
|
52
|
+
else
|
53
|
+
v
|
54
|
+
end
|
55
|
+
else
|
56
|
+
raise IndexError
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
##
|
61
|
+
# Sets the value for the given name.
|
62
|
+
def []=(name, value)
|
63
|
+
name = name.to_sym if @auto_symbol
|
64
|
+
h = @parent.instance_variable_get(@hash_ivar)
|
65
|
+
if h.include?(name)
|
66
|
+
if @setter.is_a?(Symbol)
|
67
|
+
h[name].send @setter, value
|
68
|
+
elsif @setter.is_a?(Proc)
|
69
|
+
@setter.call h[name], value
|
70
|
+
else
|
71
|
+
h[name] = value
|
72
|
+
end
|
73
|
+
else
|
74
|
+
raise IndexError
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
|
2
|
+
module SimpleTk
|
3
|
+
|
4
|
+
##
|
5
|
+
# Provides :disable, :disabled?, and :enable methods to widgets.
|
6
|
+
module DisableHelpers
|
7
|
+
|
8
|
+
##
|
9
|
+
# Disables this widget.
|
10
|
+
def disable
|
11
|
+
self.state('disabled')
|
12
|
+
end
|
13
|
+
|
14
|
+
##
|
15
|
+
# Is this widget disabled?
|
16
|
+
def disabled?
|
17
|
+
self.instate('disabled')
|
18
|
+
end
|
19
|
+
|
20
|
+
##
|
21
|
+
# Enables this widget.
|
22
|
+
def enable
|
23
|
+
self.state('!disabled')
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,667 @@
|
|
1
|
+
require 'simple_tk/errors'
|
2
|
+
require 'simple_tk/get_set_helper'
|
3
|
+
require 'simple_tk/widget_helpers'
|
4
|
+
|
5
|
+
require 'tk'
|
6
|
+
|
7
|
+
module SimpleTk
|
8
|
+
##
|
9
|
+
# A class representing a window that all the other controls get piled into.
|
10
|
+
#
|
11
|
+
# We use the "grid" layout manager. Each widget gets assigned to the grid
|
12
|
+
# using specific column and row settings.
|
13
|
+
#
|
14
|
+
# To simplify things the Window class allows either "free" mode or "flow"
|
15
|
+
# mode placement. In "free" mode, you must specify the :column and :row
|
16
|
+
# option for each widget you add. In "flow" mode, the :column and :row
|
17
|
+
# are computed for you automatically.
|
18
|
+
#
|
19
|
+
# There are multiple ways to give the Window the grid coordinates for the
|
20
|
+
# new widget.
|
21
|
+
#
|
22
|
+
# You can explicitly set the :column, :row, :columnspan, and :rowspan options.
|
23
|
+
# The :col option is equivalent to :column and the :colspan option is equivalent
|
24
|
+
# to the :columnspan option. The :columnspan and :rowspan options default to
|
25
|
+
# a value of 1 if you do not specify them.
|
26
|
+
# add_label :xyz, 'XYZ', :column => 1, :row => 2, :columnspan => 1, :rowspan => 1
|
27
|
+
# add_label :xyz, 'XYZ', :col => 1, :row => 2, :colspan => 1, :rowspan => 1
|
28
|
+
#
|
29
|
+
# You can also set the :position option. The :pos option is equivalent to the
|
30
|
+
# :position option. The argument to this option is either an Array or a Hash.
|
31
|
+
# If an Array is specified, it should have either 2 or 4 values.
|
32
|
+
class Window
|
33
|
+
|
34
|
+
##
|
35
|
+
# Allows you to get or set the linked object for this window.
|
36
|
+
#
|
37
|
+
# A linked object can be used to provide command callbacks.
|
38
|
+
attr_accessor :linked_object
|
39
|
+
|
40
|
+
##
|
41
|
+
# Creates a new window.
|
42
|
+
#
|
43
|
+
# Some valid options:
|
44
|
+
# title::
|
45
|
+
# The title to put on the window.
|
46
|
+
# Defaults to "My Application".
|
47
|
+
# parent::
|
48
|
+
# The parent window for this window.
|
49
|
+
# Use your main window for any popup windows you create.
|
50
|
+
# Defaults to nil.
|
51
|
+
# padding::
|
52
|
+
# The padding for the content frame.
|
53
|
+
# This can be a single value to have the same padding all around.
|
54
|
+
# It can also be two numbers to specify horizontal and vertical padding.
|
55
|
+
# If you specify four numbers, they are for left, top, right, and bottom padding.
|
56
|
+
# Defaults to "3".
|
57
|
+
# sticky::
|
58
|
+
# The stickiness for the content frame.
|
59
|
+
# This defaults to "nsew" and most likely you don't want to change it, but the
|
60
|
+
# option is available.
|
61
|
+
#
|
62
|
+
# Window options can be prefixed with 'window_' or put into a hash under a 'window' option.
|
63
|
+
# SimpleTk::Window.new(window: { geometry: '300x300' })
|
64
|
+
# SimpleTk::Window.new(window_geometry: '300x300')
|
65
|
+
#
|
66
|
+
# Any options not listed above or explicitly assigned to the window are applied to the
|
67
|
+
# content frame.
|
68
|
+
#
|
69
|
+
# If you provide a block it will be executed in the scope of the window.
|
70
|
+
def initialize(options = {}, &block)
|
71
|
+
@stkw_object_list = {}
|
72
|
+
@stkw_var_list = {}
|
73
|
+
|
74
|
+
options = {
|
75
|
+
title: 'My Application',
|
76
|
+
padding: '3',
|
77
|
+
sticky: 'nsew'
|
78
|
+
}.merge(options.inject({}) { |m,(k,v)| m[k.to_sym] = v; m})
|
79
|
+
|
80
|
+
title = options.delete(:title) || 'My Application'
|
81
|
+
parent = options.delete(:parent)
|
82
|
+
is_frame = options.delete(:stk___frame)
|
83
|
+
|
84
|
+
win_opt, options = split_window_content_options(options)
|
85
|
+
|
86
|
+
@stkw_object_list[:stk___root] =
|
87
|
+
if is_frame
|
88
|
+
parent
|
89
|
+
elsif parent
|
90
|
+
TkToplevel.new(parent)
|
91
|
+
else
|
92
|
+
TkRoot.new
|
93
|
+
end
|
94
|
+
|
95
|
+
unless is_frame
|
96
|
+
root.title title
|
97
|
+
TkGrid.columnconfigure root, 0, weight: 1
|
98
|
+
TkGrid.rowconfigure root, 0, weight: 1
|
99
|
+
apply_options root, win_opt
|
100
|
+
end
|
101
|
+
|
102
|
+
@stkw_object_list[:stk___content] = Tk::Tile::Frame.new(root)
|
103
|
+
apply_options content, options
|
104
|
+
|
105
|
+
@stkw_config = {
|
106
|
+
placement: :free,
|
107
|
+
row_start: -1,
|
108
|
+
col_start: -1,
|
109
|
+
col_count: -1,
|
110
|
+
cur_col: -1,
|
111
|
+
cur_row: -1,
|
112
|
+
base_opt: { },
|
113
|
+
max_col: 0,
|
114
|
+
max_row: 0
|
115
|
+
}
|
116
|
+
|
117
|
+
if block_given?
|
118
|
+
instance_eval &block
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
##
|
123
|
+
# Gets the number of columns in use.
|
124
|
+
def column_count
|
125
|
+
@stkw_config[:max_col]
|
126
|
+
end
|
127
|
+
|
128
|
+
##
|
129
|
+
# Gets the number of rows in use.
|
130
|
+
def row_count
|
131
|
+
@stkw_config[:max_row]
|
132
|
+
end
|
133
|
+
|
134
|
+
##
|
135
|
+
# Allows you to configure the grid options for all cells in a column.
|
136
|
+
def config_column(col, options = {})
|
137
|
+
TkGrid.columnconfigure content, col, options
|
138
|
+
end
|
139
|
+
|
140
|
+
##
|
141
|
+
# Allows you to configure the grid options for all cells in a row.
|
142
|
+
def config_row(row, options = {})
|
143
|
+
TkGrid.rowconfigure content, row, options
|
144
|
+
end
|
145
|
+
|
146
|
+
##
|
147
|
+
# Gets all of the children on this window.
|
148
|
+
def children
|
149
|
+
TkWinfo.children(content)
|
150
|
+
end
|
151
|
+
|
152
|
+
##
|
153
|
+
# Gets objects from the window.
|
154
|
+
def object
|
155
|
+
@object_helper ||= SimpleTk::GetSetHelper.new(self, :@stkw_object_list, true, nil, ->(i,v) { } )
|
156
|
+
end
|
157
|
+
|
158
|
+
##
|
159
|
+
# Gets or sets variable values for this window.
|
160
|
+
def var
|
161
|
+
@var_helper ||= SimpleTk::GetSetHelper.new(self, :@stkw_var_list, true, :value, :value=)
|
162
|
+
end
|
163
|
+
|
164
|
+
##
|
165
|
+
# Binds a method or Proc to a window event.
|
166
|
+
#
|
167
|
+
# event::
|
168
|
+
# The event to bind to (eg - "1", "Return", "Shift-2")
|
169
|
+
# proc::
|
170
|
+
# A predefined proc to bind to the event, only used if no block is provided.
|
171
|
+
#
|
172
|
+
# If a block is provided it will be bound, otherwise the +proc+ argument is looked at.
|
173
|
+
# If the proc argument specifies a Proc it will be bound. If the proc argument is a Symbol
|
174
|
+
# and the Window or +linked_object+ responds to the proc, then the method from the Window
|
175
|
+
# or +linked_object+ will be bound.
|
176
|
+
def on(event, proc = nil, &block)
|
177
|
+
cmd = get_command proc, &block
|
178
|
+
root.bind(event) { cmd.call }
|
179
|
+
end
|
180
|
+
|
181
|
+
##
|
182
|
+
# Adds a new label to the window.
|
183
|
+
#
|
184
|
+
# name::
|
185
|
+
# A unique label for this item, cannot be nil.
|
186
|
+
# label_text::
|
187
|
+
# The text to put in the label.
|
188
|
+
# If this is a Symbol, then a variable will be created with this value as its name.
|
189
|
+
# Otherwise the label will be given the string value as a static label.
|
190
|
+
# options::
|
191
|
+
# Options for the label. Common options are :column, :row, and :sticky.
|
192
|
+
def add_label(name, label_text, options = {})
|
193
|
+
add_widget Tk::Tile::Label, name, label_text, options
|
194
|
+
end
|
195
|
+
|
196
|
+
##
|
197
|
+
# Adds a new image to the window.
|
198
|
+
#
|
199
|
+
# name::
|
200
|
+
# A unique label for this item, cannot be nil.
|
201
|
+
# image_path::
|
202
|
+
# The path to the image, can be relative or absolute.
|
203
|
+
# options::
|
204
|
+
# Options for the image. Common options are :column, :row, and :sticky.
|
205
|
+
def add_image(name, image_path, options = {})
|
206
|
+
image = TkPhotoImage.new(file: image_path)
|
207
|
+
add_widget Tk::Tile::Label, name, nil, options.merge(image: image)
|
208
|
+
end
|
209
|
+
|
210
|
+
##
|
211
|
+
# Adds a new button to the window.
|
212
|
+
#
|
213
|
+
# name::
|
214
|
+
# A unique label for this item, cannot be nil.
|
215
|
+
# label_text::
|
216
|
+
# The text to put in the button.
|
217
|
+
# If this is a Symbol, then a variable will be created with this value as its name.
|
218
|
+
# Otherwise the button will be given the string value as a static label.
|
219
|
+
# options::
|
220
|
+
# Options for the button. Common options are :column, :row, :sticky, and :command.
|
221
|
+
#
|
222
|
+
# If a block is provided, it will be used for the button command. Otherwise the :command option
|
223
|
+
# will be used. This can be a Proc or Symbol. If it is a Symbol it should reference a method in
|
224
|
+
# the current Window object or in the +linked_object+.
|
225
|
+
#
|
226
|
+
# If no block or proc is provided, a default proc that prints to $stderr is created.
|
227
|
+
def add_button(name, label_text, options = {}, &block)
|
228
|
+
options = options.dup
|
229
|
+
proc = get_command(options.delete(:command), &block) || ->{ $stderr.puts "Button '#{name}' does nothing when clicked." }
|
230
|
+
add_widget Tk::Tile::Button, name, label_text, options, &proc
|
231
|
+
end
|
232
|
+
|
233
|
+
##
|
234
|
+
# Adds a new image button to the window.
|
235
|
+
#
|
236
|
+
# name::
|
237
|
+
# A unique label for this item, cannot be nil.
|
238
|
+
# image_path::
|
239
|
+
# The path to the image, can be relative or absolute.
|
240
|
+
# options::
|
241
|
+
# Options for the image button. Common options are :column, :row, :sticky, and :command.
|
242
|
+
#
|
243
|
+
# If a block is provided, it will be used for the button command. Otherwise the :command option
|
244
|
+
# will be used. This can be a Proc or Symbol. If it is a Symbol it should reference a method in
|
245
|
+
# the current Window object or in the +linked_object+.
|
246
|
+
#
|
247
|
+
# If no block or proc is provided, a default proc that prints to $stderr is created.
|
248
|
+
def add_image_button(name, image_path, options = {}, &block)
|
249
|
+
options = options.dup
|
250
|
+
image = TkPhotoImage.new(file: image_path)
|
251
|
+
proc = get_command(options.delete(:command), &block) || ->{ $stderr.puts "Button '#{name}' does nothing when clicked." }
|
252
|
+
add_widget Tk::Tile::Button, name, nil, options.merge(image: image), &proc
|
253
|
+
end
|
254
|
+
|
255
|
+
##
|
256
|
+
# Adds a new text box to the window.
|
257
|
+
#
|
258
|
+
# name::
|
259
|
+
# A unique label for this item, cannot be nil.
|
260
|
+
# options::
|
261
|
+
# Options for the text box. Common options are :column, :row, :sticky, :width, :value, and :password.
|
262
|
+
#
|
263
|
+
# Accepts a block or command the same as a button. Unlike the button there is no default proc assigned.
|
264
|
+
# The proc, if specified, will be called for each keypress. It should return 1 (success) or 0 (failure).
|
265
|
+
def add_text_box(name, options = {}, &block)
|
266
|
+
options = options.dup
|
267
|
+
if options.delete(:password)
|
268
|
+
options[:show] = '*'
|
269
|
+
end
|
270
|
+
proc = get_command(options.delete(:command), &block)
|
271
|
+
item = add_widget Tk::Tile::Entry, name, nil, options.merge(create_var: :textvariable)
|
272
|
+
# FIXME: Should the command be processed for validation or bound to a specific event?
|
273
|
+
if proc
|
274
|
+
item.send :validate, 'key'
|
275
|
+
item.send(:validatecommand) { proc.call }
|
276
|
+
end
|
277
|
+
item
|
278
|
+
end
|
279
|
+
|
280
|
+
##
|
281
|
+
# Adds a new check box to the window
|
282
|
+
#
|
283
|
+
# name::
|
284
|
+
# A unique label for this item, cannot be nil.
|
285
|
+
# label_text::
|
286
|
+
# The text to put in the button.
|
287
|
+
# If this is a Symbol, then a variable will be created with this value as its name.
|
288
|
+
# Otherwise the button will be given the string value as a static label.
|
289
|
+
# options::
|
290
|
+
# Options for the check box. Common options are :column, :row, :sticky, and :value.
|
291
|
+
#
|
292
|
+
# Accepts a block or command the same as a button. Unlike a button there is no default proc assigned.
|
293
|
+
def add_check_box(name, label_text, options = {}, &block)
|
294
|
+
options = options.dup
|
295
|
+
proc = get_command(options.delete(:command), &block)
|
296
|
+
add_widget Tk::Tile::Checkbutton, name, label_text, options.merge(create_var: :variable), &proc
|
297
|
+
end
|
298
|
+
|
299
|
+
##
|
300
|
+
# Adds a new image check box to the window
|
301
|
+
#
|
302
|
+
# name::
|
303
|
+
# A unique label for this item, cannot be nil.
|
304
|
+
# image_path::
|
305
|
+
# The path to the image, can be relative or absolute.
|
306
|
+
# options::
|
307
|
+
# Options for the check box. Common options are :column, :row, :sticky, and :value.
|
308
|
+
#
|
309
|
+
# Accepts a block or command the same as a button. Unlike a button there is no default proc assigned.
|
310
|
+
def add_image_check_box(name, image_path, options = {}, &block)
|
311
|
+
options = options.dup
|
312
|
+
image = TkPhotoImage.new(file: image_path)
|
313
|
+
proc = get_command(options.delete(:command), &block)
|
314
|
+
add_widget Tk::Tile::Checkbutton, name, nil, options.merge(image: image, create_var: :variable), &proc
|
315
|
+
end
|
316
|
+
|
317
|
+
##
|
318
|
+
# Adds a new radio button to the window.
|
319
|
+
#
|
320
|
+
# name::
|
321
|
+
# A unique label for this item, cannot be nil.
|
322
|
+
# group::
|
323
|
+
# The name of the variable this radio button uses.
|
324
|
+
# label_text::
|
325
|
+
# The text to put in the button.
|
326
|
+
# If this is a Symbol, then a variable will be created with this value as its name.
|
327
|
+
# Otherwise the button will be given the string value as a static label.
|
328
|
+
# options::
|
329
|
+
# Options for the check box. Common options are :column, :row, :sticky, :value, and :selected.
|
330
|
+
#
|
331
|
+
# Accepts a block or command the same as a button. Unlike a button there is no default proc assigned.
|
332
|
+
def add_radio_button(name, group, label_text, options = {}, &block)
|
333
|
+
raise ArgumentError, 'group cannot be blank' if group.to_s.strip == ''
|
334
|
+
options = options.dup
|
335
|
+
group = group.to_sym
|
336
|
+
@stkw_var_list[group] ||= TkVariable.new
|
337
|
+
options[:variable] = @stkw_var_list[group]
|
338
|
+
options[:value] ||= name.to_s.strip
|
339
|
+
if options.delete(:selected)
|
340
|
+
@stkw_var_list[group] = options[:value]
|
341
|
+
end
|
342
|
+
proc = get_command(options.delete(:command), &block)
|
343
|
+
add_widget Tk::Tile::Radiobutton, name, label_text, options, &proc
|
344
|
+
end
|
345
|
+
|
346
|
+
##
|
347
|
+
# Adds a new radio button to the window.
|
348
|
+
#
|
349
|
+
# name::
|
350
|
+
# A unique label for this item, cannot be nil.
|
351
|
+
# group::
|
352
|
+
# The name of the variable this radio button uses.
|
353
|
+
# image_path::
|
354
|
+
# The path to the image, can be relative or absolute.
|
355
|
+
# options::
|
356
|
+
# Options for the check box. Common options are :column, :row, :sticky, :value, and :selected.
|
357
|
+
#
|
358
|
+
# Accepts a block or command the same as a button. Unlike a button there is no default proc assigned.
|
359
|
+
def add_image_radio_button(name, group, image_path, options = {}, &block)
|
360
|
+
raise ArgumentError, 'group cannot be blank' if group.to_s.strip == ''
|
361
|
+
options = options.dup
|
362
|
+
group = group.to_sym
|
363
|
+
@stkw_var_list[group] ||= TkVariable.new
|
364
|
+
options[:variable] = @stkw_var_list[group]
|
365
|
+
options[:value] ||= name.to_s.strip
|
366
|
+
if options.delete(:selected)
|
367
|
+
@stkw_var_list[group] = options[:value]
|
368
|
+
end
|
369
|
+
proc = get_command(options.delete(:command), &block)
|
370
|
+
image = TkPhotoImage.new(file: image_path)
|
371
|
+
add_widget Tk::Tile::Radiobutton, name, nil, options.merge(image: image), &proc
|
372
|
+
end
|
373
|
+
|
374
|
+
##
|
375
|
+
# Adds a new combo box to the window.
|
376
|
+
#
|
377
|
+
# name::
|
378
|
+
# A unique label for this item, cannot be nil.
|
379
|
+
# options::
|
380
|
+
# Options for the check box. Common options are :column, :row, :sticky, :value, and :values.
|
381
|
+
#
|
382
|
+
# The :values option will define the items in the combo box, the :value option sets the selected option if set.
|
383
|
+
#
|
384
|
+
# Accepts a block or command the same as a button. Unlike a button there is no default proc assigned.
|
385
|
+
def add_combo_box(name, options = {}, &block)
|
386
|
+
options = options.dup
|
387
|
+
proc = get_command(options.delete(:command), &block)
|
388
|
+
item = add_widget TK::Tile::Combobox, name, nil, options.merge(create_var: :textvariable)
|
389
|
+
if proc
|
390
|
+
item.bind('<ComboboxSelected>') { proc.call }
|
391
|
+
end
|
392
|
+
item
|
393
|
+
end
|
394
|
+
|
395
|
+
##
|
396
|
+
# Adds a new frame to the window.
|
397
|
+
#
|
398
|
+
# name::
|
399
|
+
# A unique label for this item, cannot be nil.
|
400
|
+
# options::
|
401
|
+
# Options for the frame. Common options are :column, :row, and :padding.
|
402
|
+
#
|
403
|
+
# A frame can be used as a sub-window. The returned object has all of the same methods as a Window
|
404
|
+
# so you can add other widgets to it and use it as a grid within the parent grid.
|
405
|
+
#
|
406
|
+
# If you provide a block, it will be executed in the scope of the frame.
|
407
|
+
def add_frame(name, options = {}, &block)
|
408
|
+
name = name.to_sym
|
409
|
+
raise DuplicateNameError if @stkw_object_list.include?(name)
|
410
|
+
options = fix_position(options.dup)
|
411
|
+
@stkw_object_list[name] = SimpleTk::Window.new(options.merge(parent: content, stk___frame: true), &block)
|
412
|
+
end
|
413
|
+
|
414
|
+
##
|
415
|
+
# Sets the placement mode for this window.
|
416
|
+
#
|
417
|
+
# mode::
|
418
|
+
# This can be either :free or :flow.
|
419
|
+
# The default mode for a new window is :free.
|
420
|
+
# Frames do not inherit this setting from the parent window.
|
421
|
+
# In free placement mode, you must provide the :column and :row for every widget.
|
422
|
+
# In flow placement mode, you must not provide the :column or :row for any widget.
|
423
|
+
# Flow placement will add each widget to the next column moving to the next row as
|
424
|
+
# needed.
|
425
|
+
# options::
|
426
|
+
# Options are ignored in free placement mode.
|
427
|
+
# In flow placement mode, you must provide :first_column, :first_row, and either
|
428
|
+
# :last_column or :column_count. If you specify both :last_column and :column_count
|
429
|
+
# then :last_column will be used. The :first_column and :first_row must be greater
|
430
|
+
# than or equal to zero. The :last_column can be equal to the first column but
|
431
|
+
# the computed :column_count must be at least 1.
|
432
|
+
def set_placement_mode(mode, options = {})
|
433
|
+
raise ArgumentError, 'mode must be :free or :flow' unless [ :free, :flow ].include?(mode)
|
434
|
+
if mode == :flow
|
435
|
+
first_col = options[:first_column]
|
436
|
+
col_count =
|
437
|
+
if (val = options[:last_column])
|
438
|
+
val - first_col + 1
|
439
|
+
elsif (val = options[:column_count])
|
440
|
+
val
|
441
|
+
else
|
442
|
+
nil
|
443
|
+
end
|
444
|
+
first_row = options[:first_row]
|
445
|
+
raise ArgumentError, ':first_column must be provided for flow placement' unless first_col
|
446
|
+
raise ArgumentError, ':first_row must be provided for flow placement' unless first_row
|
447
|
+
raise ArgumentError, ':last_column or :column_count must be provided for flow placement' unless col_count
|
448
|
+
raise ArgumentError, ':first_column must be >= 0' unless first_col >= 0
|
449
|
+
raise ArgumentError, ':first_row must be >= 0' unless first_row >= 0
|
450
|
+
raise ArgumentError, ':column_count must be > 0' unless col_count > 0
|
451
|
+
|
452
|
+
@stkw_config.merge!(
|
453
|
+
placement: :flow,
|
454
|
+
col_start: first_col,
|
455
|
+
row_start: first_row,
|
456
|
+
col_count: col_count,
|
457
|
+
cur_row: first_row,
|
458
|
+
cur_col: first_col
|
459
|
+
)
|
460
|
+
elsif mode == :free
|
461
|
+
@stkw_config.merge!(
|
462
|
+
placement: :free,
|
463
|
+
col_start: -1,
|
464
|
+
row_start: -1,
|
465
|
+
col_count: -1,
|
466
|
+
cur_row: -1,
|
467
|
+
cur_col: -1
|
468
|
+
)
|
469
|
+
end
|
470
|
+
end
|
471
|
+
|
472
|
+
##
|
473
|
+
# Executes a block with the specified options preset.
|
474
|
+
def with_options(options = {}, &block)
|
475
|
+
return unless block
|
476
|
+
backup_options = @stkw_config[:base_opt]
|
477
|
+
@stkw_config[:base_opt] = @stkw_config[:base_opt].merge(options)
|
478
|
+
begin
|
479
|
+
instance_eval &block
|
480
|
+
ensure
|
481
|
+
@stkw_config[:base_opt] = backup_options
|
482
|
+
end
|
483
|
+
end
|
484
|
+
|
485
|
+
private
|
486
|
+
|
487
|
+
def root
|
488
|
+
@stkw_object_list[:stk___root]
|
489
|
+
end
|
490
|
+
|
491
|
+
def content
|
492
|
+
@stkw_object_list[:stk___content]
|
493
|
+
end
|
494
|
+
|
495
|
+
def fix_position(options)
|
496
|
+
col = options.delete(:column) || options.delete(:col)
|
497
|
+
row = options.delete(:row)
|
498
|
+
width = options.delete(:columnspan) || options.delete(:colspan) || options.delete(:columns) || 1
|
499
|
+
height = options.delete(:rowspan) || options.delete(:rows) || 1
|
500
|
+
pos = options.delete(:position) || options.delete(:pos)
|
501
|
+
skip = options.delete(:skip)
|
502
|
+
|
503
|
+
if pos.is_a?(Array)
|
504
|
+
col = pos[0] || col
|
505
|
+
row = pos[1] || row
|
506
|
+
width = pos[2] || width
|
507
|
+
height = pos[3] || height
|
508
|
+
elsif pos.is_a?(Hash)
|
509
|
+
col = pos[:column] || pos[:col] || pos[:x] || col
|
510
|
+
row = pos[:row] || pos[:y] || row
|
511
|
+
width = pos[:width] || pos[:w] || pos[:columnspan] || pos[:colspan] || width
|
512
|
+
height = pos[:height] || pos[:h] || pos[:rowspan] || height
|
513
|
+
end
|
514
|
+
|
515
|
+
if @stkw_config[:placement] == :free
|
516
|
+
raise ArgumentError, ':column must be set for free placement mode' unless col
|
517
|
+
raise ArgumentError, ':row must be set for free placement mode' unless row
|
518
|
+
raise ArgumentError, ':skip must not be set for free placement mode' if skip
|
519
|
+
elsif @stkw_config[:placement] == :flow
|
520
|
+
raise ArgumentError, ':column cannot be set for flow placement mode' if col
|
521
|
+
raise ArgumentError, ':row cannot be set for flow placement mode' if row
|
522
|
+
raise ArgumentError, ":columnspan cannot be more than #{@stkw_config[:col_count]} in flow placement mode" if width > @stkw_config[:col_count]
|
523
|
+
raise ArgumentError, ':rowspan cannot be more than 1 in flow placement mode' if height > 1
|
524
|
+
|
525
|
+
# skip cells if the user requested it.
|
526
|
+
if skip
|
527
|
+
@stkw_config[:cur_col] += skip
|
528
|
+
while @stkw_config[:cur_col] >= @stkw_config[:col_start] + @stkw_config[:col_count]
|
529
|
+
@stkw_config[:cur_row] += 1
|
530
|
+
@stkw_config[:cur_col] -= @stkw_config[:col_count]
|
531
|
+
end
|
532
|
+
end
|
533
|
+
|
534
|
+
if width > @stkw_config[:col_count] - @stkw_config[:cur_col] + 1
|
535
|
+
@stkw_config[:cur_row] += 1
|
536
|
+
@stkw_config[:cur_col] = @stkw_config[:col_start]
|
537
|
+
end
|
538
|
+
col = @stkw_config[:cur_col]
|
539
|
+
row = @stkw_config[:cur_row]
|
540
|
+
@stkw_config[:cur_col] += width
|
541
|
+
if @stkw_config[:cur_col] >= @stkw_config[:col_start] + @stkw_config[:col_count]
|
542
|
+
@stkw_config[:cur_col] = @stkw_config[:col_start]
|
543
|
+
@stkw_config[:cur_row] += 1
|
544
|
+
end
|
545
|
+
end
|
546
|
+
|
547
|
+
options[:column] = col
|
548
|
+
options[:row] = row
|
549
|
+
options[:columnspan] = width
|
550
|
+
options[:rowspan] = height
|
551
|
+
|
552
|
+
end_col = options[:column] + options[:columnspan] - 1
|
553
|
+
end_row = options[:row] + options[:rowspan] - 1
|
554
|
+
|
555
|
+
# track the columns and rows.
|
556
|
+
@stkw_config[:max_col] = end_col if end_col > @stkw_config[:max_col]
|
557
|
+
@stkw_config[:max_row] = end_row if end_row > @stkw_config[:max_row]
|
558
|
+
|
559
|
+
options
|
560
|
+
end
|
561
|
+
|
562
|
+
def add_widget(klass, name, label_text, options = {}, &block)
|
563
|
+
raise ArgumentError, 'name cannot be blank' if name.to_s.strip == ''
|
564
|
+
name = name.to_sym
|
565
|
+
raise DuplicateNameError if @stkw_object_list.include?(name)
|
566
|
+
options = options.dup
|
567
|
+
cmd = get_command options.delete(:command), &block
|
568
|
+
if cmd
|
569
|
+
options[:command] = cmd
|
570
|
+
end
|
571
|
+
|
572
|
+
options = fix_position(options)
|
573
|
+
|
574
|
+
if (attrib = options.delete(:create_var))
|
575
|
+
@stkw_var_list[name] ||= TkVariable.new
|
576
|
+
if attrib.is_a?(Symbol)
|
577
|
+
options[attrib] = @stkw_var_list[name]
|
578
|
+
end
|
579
|
+
init_val = options.delete(:value)
|
580
|
+
var[name] = init_val if init_val
|
581
|
+
end
|
582
|
+
|
583
|
+
@stkw_object_list[name] = klass.new(content)
|
584
|
+
if label_text
|
585
|
+
set_text @stkw_object_list[name], label_text
|
586
|
+
end
|
587
|
+
apply_options @stkw_object_list[name], options
|
588
|
+
|
589
|
+
# add disable, disabled?, and enable methods.
|
590
|
+
@stkw_object_list[name].extend SimpleTk::DisableHelpers
|
591
|
+
|
592
|
+
# return the object after creation
|
593
|
+
@stkw_object_list[name]
|
594
|
+
end
|
595
|
+
|
596
|
+
def get_command(proc, &block)
|
597
|
+
if block
|
598
|
+
block
|
599
|
+
elsif proc.is_a?(Proc)
|
600
|
+
proc
|
601
|
+
elsif proc.is_a?(Symbol) && self.respond_to?(proc, true)
|
602
|
+
self.method(proc)
|
603
|
+
elsif linked_object && proc.is_a?(Symbol) && linked_object.respond_to?(proc, true)
|
604
|
+
linked_object.method(proc)
|
605
|
+
else
|
606
|
+
nil
|
607
|
+
end
|
608
|
+
end
|
609
|
+
|
610
|
+
def set_text(object, label_text)
|
611
|
+
if label_text.is_a?(Symbol)
|
612
|
+
@stkw_var_list[label_text] ||= TkVariable.new
|
613
|
+
object.textvariable @stkw_var_list[label_text]
|
614
|
+
else
|
615
|
+
object.text label_text
|
616
|
+
end
|
617
|
+
end
|
618
|
+
|
619
|
+
def apply_options(object, options)
|
620
|
+
widget_opt, grid_opt = split_widget_grid_options(options)
|
621
|
+
widget_opt.each do |key,val|
|
622
|
+
if val.is_a?(Proc)
|
623
|
+
object.send key, &val
|
624
|
+
else
|
625
|
+
object.send key, val
|
626
|
+
end
|
627
|
+
end
|
628
|
+
object.grid(grid_opt) unless grid_opt.empty?
|
629
|
+
end
|
630
|
+
|
631
|
+
def split_widget_grid_options(options)
|
632
|
+
wopt = options.dup
|
633
|
+
gopt = {}
|
634
|
+
|
635
|
+
[
|
636
|
+
:row, :column, :columnspan, :rowspan,
|
637
|
+
:padx, :pady, :ipadx, :ipady,
|
638
|
+
:sticky,
|
639
|
+
].each do |attr|
|
640
|
+
val = wopt.delete(attr)
|
641
|
+
if val
|
642
|
+
gopt[attr] = val
|
643
|
+
end
|
644
|
+
end
|
645
|
+
|
646
|
+
[ wopt, gopt ]
|
647
|
+
end
|
648
|
+
|
649
|
+
def split_window_content_options(options)
|
650
|
+
options = options.dup
|
651
|
+
wopt = options.delete(:window) || { }
|
652
|
+
copt = { }
|
653
|
+
|
654
|
+
options.each do |k,v|
|
655
|
+
ks = k.to_s
|
656
|
+
if ks =~ /^window_/
|
657
|
+
wopt[ks[7..-1].to_sym] = v
|
658
|
+
else
|
659
|
+
copt[k] = v
|
660
|
+
end
|
661
|
+
end
|
662
|
+
|
663
|
+
[ wopt, copt ]
|
664
|
+
end
|
665
|
+
|
666
|
+
end
|
667
|
+
end
|
data/lib/simple_tk.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'simple_tk/version'
|
2
|
+
require 'simple_tk/get_set_helper'
|
3
|
+
require 'simple_tk/window'
|
4
|
+
|
5
|
+
##
|
6
|
+
# A real cheap wrapper around the Ruby Tk bindings.
|
7
|
+
module SimpleTk
|
8
|
+
|
9
|
+
##
|
10
|
+
# Runs the Tk application.
|
11
|
+
def self.run
|
12
|
+
Tk.mainloop
|
13
|
+
end
|
14
|
+
|
15
|
+
##
|
16
|
+
# Creates a basic alert message box.
|
17
|
+
#
|
18
|
+
# message::
|
19
|
+
# The message to display.
|
20
|
+
# icon::
|
21
|
+
# The icon to display (one of :info, :error, :question, or :warning).
|
22
|
+
#
|
23
|
+
# Returns true.
|
24
|
+
def self.alert(message, icon = :info)
|
25
|
+
Tk::messageBox message: message, icon: icon.to_s
|
26
|
+
true
|
27
|
+
end
|
28
|
+
|
29
|
+
##
|
30
|
+
# Creates a basic yes/no message box.
|
31
|
+
#
|
32
|
+
# message::
|
33
|
+
# The message to display.
|
34
|
+
# icon::
|
35
|
+
# The icon to display (one of :info, :error, :question, or :warning).
|
36
|
+
# ok_cancel::
|
37
|
+
# Set to true to make the buttons OK and Cancel instead of Yes and No.
|
38
|
+
#
|
39
|
+
# Returns true for 'Yes' (or 'OK') or false for 'No' (or 'Cancel').
|
40
|
+
def self.ask(message, icon = :question, ok_cancel = false)
|
41
|
+
%w(ok yes).include?(Tk::messageBox(message: message, type: ok_cancel ? 'okcancel' : 'yesno', icon: icon))
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
metadata
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: simple_tk
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Beau Barker
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-04-22 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: tk
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.1.2
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.1.2
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.14'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.14'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '10.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '10.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: minitest
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '5.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '5.0'
|
69
|
+
description:
|
70
|
+
email:
|
71
|
+
- beau@barkerest.com
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- ".gitignore"
|
77
|
+
- ".travis.yml"
|
78
|
+
- Gemfile
|
79
|
+
- LICENSE.txt
|
80
|
+
- README.md
|
81
|
+
- Rakefile
|
82
|
+
- bin/console
|
83
|
+
- bin/setup
|
84
|
+
- lib/simple_tk.rb
|
85
|
+
- lib/simple_tk/errors.rb
|
86
|
+
- lib/simple_tk/get_set_helper.rb
|
87
|
+
- lib/simple_tk/version.rb
|
88
|
+
- lib/simple_tk/widget_helpers.rb
|
89
|
+
- lib/simple_tk/window.rb
|
90
|
+
homepage: http://www.barkerest.com/
|
91
|
+
licenses:
|
92
|
+
- MIT
|
93
|
+
metadata: {}
|
94
|
+
post_install_message:
|
95
|
+
rdoc_options: []
|
96
|
+
require_paths:
|
97
|
+
- lib
|
98
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0'
|
103
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
104
|
+
requirements:
|
105
|
+
- - ">="
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
version: '0'
|
108
|
+
requirements: []
|
109
|
+
rubyforge_project:
|
110
|
+
rubygems_version: 2.6.11
|
111
|
+
signing_key:
|
112
|
+
specification_version: 4
|
113
|
+
summary: A simple interface to the Ruby Tk bindings.
|
114
|
+
test_files: []
|