tk-doubleslider 0.1.1

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 7f2017932a98ff943f05066b9e8e77c6f0d998d5
4
+ data.tar.gz: 1b7aedd78ff5f2f85bc664ab70dc3db2873834f0
5
+ SHA512:
6
+ metadata.gz: 26cd45d3211fc4b549ea1d0cb8f3386c04528e2bd53db992f559eb4561599812238aafa082a2516ff68746c0103a28480b25cc2d1832ca6fbac952f39fb82ed2
7
+ data.tar.gz: 78446d42e156067ac7982faad07352dcabeac9244582d46287e6e7446e7c757b4f901d87fa872b6e8175b76943467d7ceda5ca055baca7b499176c8e489e5563
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ .ruby-*
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in tk-doubleslider.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 chrislee35
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,126 @@
1
+ # Tk::Doubleslider
2
+
3
+ A double-headed slider widget allows for a range to be specified. This implementation works for Ruby Tk and provides ways to provide customized formatting of values, non-linear values, and log-based sliders (i.e., lots of accuracy for low values, but not for high values).
4
+
5
+ This has been tested in:
6
+ * ruby-1.8.7-p371
7
+ * ruby-1.9.3-p392
8
+ * ruby-2.0.0-p0
9
+
10
+ RVM install command example (rvm doesn't install with tk or tcl by default):
11
+
12
+ rvm reinstall 1.9.3 --enable-shared --enable-pthread --with-tk --with-tcl
13
+
14
+ ## Installation
15
+
16
+ Add this line to your application's Gemfile:
17
+
18
+ gem 'tk-doubleslider'
19
+
20
+ And then execute:
21
+
22
+ $ bundle
23
+
24
+ Or install it yourself as:
25
+
26
+ $ gem install tk-doubleslider
27
+
28
+ ## Usage
29
+
30
+ Within a Tk project, you'll need to have a Window with a Frame to place the Doubleslider within. Here is a minimalistic example:
31
+
32
+ require 'tk'
33
+
34
+ def minimal_example()
35
+ # create the root window for this Tk app
36
+ root = TkRoot.new() {
37
+ title "Tk::DoubleSlider Test"
38
+ protocol('WM_DELETE_WINDOW', proc{ exit })
39
+ }
40
+ # bind ctrl-c to exit
41
+ root.bind('Control-c', proc{ exit })
42
+ # create a frame to place the Doubleslider within
43
+ left_frame = TkFrame.new(root)
44
+ left_frame.grid(:row=>0,:column=>0,:sticky=>'new')
45
+ # create a "time window" from 7 days ago until now
46
+ time_min = Time.now.to_i - (7*24*60*60)
47
+ time_max = Time.now.to_i
48
+ # create a "time slider" with a value formatter in HH:MM format and a delta formatter of 0.00 hours.
49
+ timeslide = Tk::Doubleslider.new( left_frame,
50
+ :min=>time_min, # what's the minimal possible value
51
+ :max=>time_max, # what's the maximum possible value
52
+ :low=>time_min, # what's the current minimum value
53
+ :high=>time_max, # what's the current max
54
+ :snap => 300, # when you slide the slider, by what increments (for this example, it's every 5 minutes)
55
+ :label=>'Time', # what do you call this slider
56
+ :valuefmt => proc { |x| Time.at(x).strftime("%H:%M") }, # how shall we format the values
57
+ :deltafmt => proc { |x| sprintf("%0.2f hours", (x/3600.0)) } # how shall we format the delta
58
+ )
59
+ # pack everything together
60
+ timeslide.pack()
61
+ # enter the main loop
62
+ Tk.mainloop()
63
+ end
64
+
65
+
66
+ Great, so what options can Tk::Doubleslider take and what are their defaults?
67
+
68
+ height = 36.0 # height in pixels
69
+ width = 360.0 # width in pixel
70
+ min = 0.0 # minimum possible value
71
+ max = 0.0 # maximum possible value
72
+ low = 0.0 # the current minimum value
73
+ high = 0.0 # the current high value
74
+ ballsize = 5 # the size in pixels of the header (the knob)
75
+ snap = false # snap increments in value
76
+ logbase = false # use logirithms to scale the slider (pretty cool stuff)
77
+ # colors for the slider
78
+ colors = {
79
+ :background => 'grey20',
80
+ :line => 'grey75',
81
+ :low_head => '#996666',
82
+ :high_head => '#996666',
83
+ :text => 'white',
84
+ :delta => 'white',
85
+ }
86
+ # margins
87
+ left_margin = 10.0
88
+ right_margin = 20.0
89
+ top_margin = 6.0
90
+ bottom_margin = 4.0
91
+ change_cb = nil # callback to call when a selection has changed, object must have a method called, "call", which must accept a low and high value (see example below)
92
+ # how to format the value
93
+ valuefmt = proc { |x| sprintf "%d", x }
94
+ # how to format the delta (defaults to valuefmt)
95
+ deltafmt = nil
96
+ # the label to display on the slider, a string
97
+ label = nil
98
+
99
+ Now, how about that callback that I promised you?
100
+
101
+ class TkDS_Callback
102
+ def call(low, high)
103
+ puts "#{low} #{high}"
104
+ if low < 90
105
+ puts "Maybe you should reconsider your answer"
106
+ end
107
+ end
108
+ end
109
+
110
+ timeslide = Tk::Doubleslider.new( left_frame, :min => 0, :max => 100, :low => 90, :high => 100,
111
+ :cb => TkDS_Callback.new, :label => 'your love for TkDS')
112
+
113
+
114
+
115
+ ## Contributing
116
+
117
+ 1. Fork it
118
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
119
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
120
+ 4. Push to the branch (`git push origin my-new-feature`)
121
+ 5. Create new Pull Request
122
+
123
+ ## Copyright
124
+
125
+ Copyright (c) 2011 Chris Lee, PhD. See LICENSE.txt for
126
+ further details.
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+
4
+ require 'rake/testtask'
5
+
6
+ Rake::TestTask.new do |t|
7
+ t.libs << 'lib'
8
+ t.test_files = FileList['test/test_*.rb']
9
+ t.verbose = true
10
+ end
11
+
12
+ task :default => :test
@@ -0,0 +1,174 @@
1
+ #require "tk/doubleslider/version"
2
+ # DESCRIPTION: provides a TK widget with two "heads", a high and a low.
3
+ # Copyright (C) 2007 Christopher Lee
4
+ #
5
+ # This program is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+ module Tk
18
+ class Doubleslider
19
+ VERSION = "0.1.1"
20
+
21
+ def pack(*args)
22
+ @canvas.pack(*args)
23
+ end
24
+
25
+ def redraw
26
+ @canvas.delete('all');
27
+ x1 = value2x(@low)
28
+ x2 = value2x(@high)
29
+ y = @height/2
30
+ TkcText.new(@canvas, 2, @height - 2, :text=>@label, :anchor=>'sw', :fill => @colors[:text]) if @label
31
+ TkcLine.new(@canvas, @left_margin, y, @width - @right_margin, y, :fill => @colors[:line], :width => 1, :tags => ['track'])
32
+ TkcLine.new(@canvas, @left_margin, y, @width - @right_margin, y, :fill => @colors[:line], :width => 4, :tags => ['selection'])
33
+ TkcOval.new(@canvas, x1 - @ballsize, y - @ballsize, x1 + @ballsize, y + @ballsize, :fill => @colors[:low_head], :width => 1, :tags => ['low'])
34
+ TkcOval.new(@canvas, x2 - @ballsize, y - @ballsize, x2 + @ballsize, y + @ballsize, :fill => @colors[:high_head], :width => 1, :tags => ['high'])
35
+ if @valuefmt
36
+ TkcText.new(@canvas, x1, @top_margin, :text => @valuefmt.call(@low), :tags => ['lowvalue'], :fill => @colors[:text])
37
+ TkcText.new(@canvas, x2, @height - @bottom_margin, :text => @valuefmt.call(@high), :tags => ['highvalue'], :fill => @colors[:text])
38
+ fmt = @deltafmt || @valuefmt # use delta format instead of value format if it is defined
39
+ TkcText.new(@canvas, (x1+x2)/2, y, :text => fmt.call(@high - @low), :tags => ['delta'], :fill => @colors[:delta])
40
+ coords = @canvas.bbox('delta')
41
+ TkcRectangle.new(@canvas,coords[0], coords[1], coords[2], coords[3], :fill => @colors[:background], :tags => ['deltabg'], :outline => @colors[:background]) if coords.length > 0
42
+ @canvas.raise('delta','all')
43
+ end
44
+ @canvas.itembind('low', 'ButtonPress-1', proc { @sel = 'low' })
45
+ @canvas.itembind('high', 'ButtonPress-1', proc { @sel = 'high' })
46
+ @canvas.itembind('all', 'ButtonRelease-1', proc { @sel = nil })
47
+ @canvas.itembind('low||high', 'Button1-Motion', proc { |x,y| move(@sel,x,y) }, "%x %y")
48
+ end
49
+
50
+ def move(tag, x, y)
51
+ return unless @sel
52
+ @canvas.raise @sel, 'all'
53
+ x = @left_margin if x < @left_margin
54
+ x = @width - @right_margin if x > @width - @right_margin
55
+ x = value2x(snap(x2value(x)))
56
+ y = @height/2
57
+ # don't update the text and deltas unless they need to be updated
58
+ return if instance_variable_get("@#{@sel}") == x2value(x)
59
+ instance_variable_set("@#{@sel}",x2value(x))
60
+ @canvas.coords(@sel, x - @ballsize, y - @ballsize, x + @ballsize, y + @ballsize)
61
+ if @sel == 'low' and @low > @high
62
+ @high = @low
63
+ @canvas.coords('high', x - @ballsize, y - @ballsize, x + @ballsize, y + @ballsize)
64
+ elsif @sel == 'high' and @high < @low
65
+ @low = @high
66
+ @canvas.coords('low', x - @ballsize, y - @ballsize, x + @ballsize, y + @ballsize)
67
+ end
68
+ lx = value2x(@low)
69
+ hx = value2x(@high)
70
+ @canvas.coords('selection', lx, y, hx, y)
71
+ if @valuefmt
72
+ @canvas.coords('lowvalue', lx, @top_margin)
73
+ @canvas.coords('highvalue', hx, @height - @bottom_margin)
74
+ @canvas.coords('delta', (lx+hx)/2, y)
75
+ @canvas.itemconfigure('lowvalue', :text => @valuefmt.call(@low))
76
+ @canvas.itemconfigure('highvalue', :text => @valuefmt.call(@high))
77
+ fmt = @deltafmt || @valuefmt # use delta format instead of value format if it is defined
78
+ @canvas.itemconfigure('delta', :text => fmt.call(@high - @low))
79
+ coords = @canvas.bbox('delta')
80
+ w1 = coords[2] - coords[0]
81
+ if coords[0] < lx +5
82
+ if lx < @width/2
83
+ coords2 = @canvas.bbox('lowvalue')
84
+ ox = coords2[2] + 10 + (w1/2)
85
+ oy = @top_margin
86
+ @canvas.coords('delta',ox,oy)
87
+ else
88
+ coords2 = @canvas.bbox('highvalue')
89
+ ox = coords2[0] - 10 - (w1/2)
90
+ oy = @height - @bottom_margin
91
+ @canvas.coords('delta',ox,oy)
92
+ end
93
+ end
94
+ coords = @canvas.bbox('delta')
95
+ @canvas.coords('deltabg', coords[0], coords[1], coords[2], coords[3])
96
+ end
97
+ @change_cb.call(@low,@high) if @change_cb
98
+ end
99
+
100
+ def snap(x)
101
+ return x unless @snap
102
+ return @max if x > @max - @snap
103
+ x = (x - (x % @snap)).to_i
104
+ return x
105
+ end
106
+
107
+ def x2value(x)
108
+ x = @left_margin if x < @left_margin
109
+ r = @width - @right_margin
110
+ x = r if x > r
111
+ l = @left_margin
112
+ o = (x - l).to_f
113
+ dx = (r - l).to_f
114
+ frac = o/dx
115
+ if @logbase
116
+ return @max**(o/dx)
117
+ else
118
+ return @min+((o/dx)*(@max - @min))
119
+ end
120
+ end
121
+
122
+ def value2x(v)
123
+ v = @max if v > @max
124
+ v = @min if v < @min
125
+ w = @width - @left_margin - @right_margin
126
+ if @logbase
127
+ return @left_margin + (Math.log(v)*w/Math.log(@max))
128
+ else
129
+ return @left_margin + (((v - @min).to_f/(@max - @min).to_f)*w)
130
+ end
131
+ end
132
+
133
+ attr_accessor :change_cb, :valuefmt, :colors
134
+ def initialize(parent,*args)
135
+ @height = 36.0
136
+ @width = 360.0
137
+ @min = @max = @low = @high = 0.0
138
+ @ballsize = 5
139
+ @snap = false
140
+ @logbase = false
141
+ @colors = {
142
+ :background => 'grey20',
143
+ :line => 'grey75',
144
+ :low_head => '#996666',
145
+ :high_head => '#996666',
146
+ :text => 'white',
147
+ :delta => 'white',
148
+ }
149
+ @left_margin = 10.0
150
+ @right_margin = 20.0
151
+ @top_margin = 6.0
152
+ @bottom_margin = 4.0
153
+ @selection = nil
154
+ @change_cb = nil
155
+ @valuefmt = proc { |x| sprintf "%d", x }
156
+ @deltafmt = nil
157
+ @label = nil
158
+ if args.length > 0
159
+ args[0].each do |k,v|
160
+ if instance_variable_defined?("@#{k}")
161
+ if v =~ /^[\d\.]+$/
162
+ instance_variable_set("@#{k}", v.to_f)
163
+ else
164
+ instance_variable_set("@#{k}", v)
165
+ end
166
+ end
167
+ end
168
+ end
169
+ @canvas = TkCanvas.new(parent, :width => @width, :height => @height, :scrollregion => [0, 0, @width, @height])
170
+ @canvas.configure('background', @colors[:background]) if @colors[:background]
171
+ redraw
172
+ end
173
+ end
174
+ end
@@ -0,0 +1,5 @@
1
+ module Tk
2
+ module Doubleslider
3
+ VERSION = "0.1.1"
4
+ end
5
+ end
@@ -0,0 +1,3 @@
1
+ require 'test/unit'
2
+ require 'tk'
3
+ require File.expand_path('../../lib/tk/doubleslider.rb', __FILE__)
@@ -0,0 +1,42 @@
1
+ unless Kernel.respond_to?(:require_relative)
2
+ module Kernel
3
+ def require_relative(path)
4
+ require File.join(File.dirname(caller[0]), path.to_str)
5
+ end
6
+ end
7
+ end
8
+
9
+ require_relative 'helper'
10
+
11
+ class TestDoubleslider < Test::Unit::TestCase
12
+ def test_display_double_headed_slider_with_linear_scale_and_custom_value_and_delta_formatters
13
+ # create the root window for this Tk app
14
+ root = TkRoot.new() {
15
+ title "Tk::DoubleSlider Test"
16
+ protocol('WM_DELETE_WINDOW', proc{ exit })
17
+ }
18
+ # bind ctrl-c to exit
19
+ root.bind('Control-c', proc{ exit })
20
+ # create a frame to place the Doubleslider within
21
+ left_frame = TkFrame.new(root)
22
+ left_frame.grid(:row=>0,:column=>0,:sticky=>'new')
23
+ # create a "time window" from 7 days ago until now
24
+ time_min = Time.now.to_i - (7*24*60*60)
25
+ time_max = Time.now.to_i
26
+ # create a "time slider" with a value formatter in HH:MM format and a delta formatter of 0.00 hours.
27
+ timeslide = Tk::Doubleslider.new( left_frame,
28
+ :min=>time_min, # what's the minimal possible value
29
+ :max=>time_max, # what's the maximum possible value
30
+ :low=>time_min, # what's the current minimum value
31
+ :high=>time_max, # what's the current max
32
+ :snap => 300, # when you slide the slider, by what increments (for this example, it's every 5 minutes)
33
+ :label=>'Time', # what do you call this slider
34
+ :valuefmt => proc { |x| Time.at(x).strftime("%H:%M") }, # how shall we format the values
35
+ :deltafmt => proc { |x| sprintf("%0.2f hours", (x/3600.0)) } # how shall we format the delta
36
+ )
37
+ # pack everything together
38
+ timeslide.pack()
39
+ # enter the main loop
40
+ Tk.mainloop()
41
+ end
42
+ end
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'tk/doubleslider/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "tk-doubleslider"
8
+ spec.version = Tk::Doubleslider::VERSION
9
+ spec.authors = ["chrislee35"]
10
+ spec.email = ["rubygems@chrislee.dhs.org"]
11
+ spec.description = %q{This provides an advanced, double-headed slider widget that allows selection of a range of values on a linear, log, square root, or cube root axis.}
12
+ spec.summary = %q{A double headed slider widget for Tk}
13
+ spec.homepage = "https://rubygems.org/gems/tk-doubleslider"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+
24
+ #spec.add_runtime_dependency "tk"
25
+
26
+ spec.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
27
+ end
metadata ADDED
@@ -0,0 +1,85 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tk-doubleslider
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - chrislee35
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-05-10 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: This provides an advanced, double-headed slider widget that allows selection
42
+ of a range of values on a linear, log, square root, or cube root axis.
43
+ email:
44
+ - rubygems@chrislee.dhs.org
45
+ executables: []
46
+ extensions: []
47
+ extra_rdoc_files: []
48
+ files:
49
+ - .gitignore
50
+ - Gemfile
51
+ - LICENSE.txt
52
+ - README.md
53
+ - Rakefile
54
+ - lib/tk/doubleslider.rb
55
+ - lib/tk/doubleslider/version.rb
56
+ - test/helper.rb
57
+ - test/test_tk-doubleslider.rb
58
+ - tk-doubleslider.gemspec
59
+ homepage: https://rubygems.org/gems/tk-doubleslider
60
+ licenses:
61
+ - MIT
62
+ metadata: {}
63
+ post_install_message:
64
+ rdoc_options: []
65
+ require_paths:
66
+ - lib
67
+ required_ruby_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - '>='
70
+ - !ruby/object:Gem::Version
71
+ version: '0'
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ requirements: []
78
+ rubyforge_project:
79
+ rubygems_version: 2.0.3
80
+ signing_key:
81
+ specification_version: 4
82
+ summary: A double headed slider widget for Tk
83
+ test_files:
84
+ - test/helper.rb
85
+ - test/test_tk-doubleslider.rb