Skip to content

Commit

Permalink
Add Slider.sensitivity (#5145)
Browse files Browse the repository at this point in the history
* Add Slider.sensitivity

* Update slider.py

* Add test for Slider

* Compute coords from handles

* Update slider.py

* Remove obvious comments
  • Loading branch information
KeyWeeUsr committed May 15, 2017
1 parent 19d9d9d commit 873427d
Show file tree
Hide file tree
Showing 3 changed files with 170 additions and 4 deletions.
8 changes: 4 additions & 4 deletions kivy/data/style.kv
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,10 @@
points: self.center_x, self.y + self.padding, self.center_x, self.value_pos[1]
Color:
rgb: 1, 1, 1
Rectangle:
pos: (self.value_pos[0] - self.cursor_width / 2, self.center_y - self.cursor_height / 2) if self.orientation == 'horizontal' else (self.center_x - self.cursor_width / 2, self.value_pos[1] - self.cursor_height / 2)
size: self.cursor_size
source: self.cursor_disabled_image if self.disabled else self.cursor_image
Image:
pos: (root.value_pos[0] - root.cursor_width / 2, root.center_y - root.cursor_height / 2) if root.orientation == 'horizontal' else (root.center_x - root.cursor_width / 2, root.value_pos[1] - root.cursor_height / 2)
size: root.cursor_size
source: root.cursor_disabled_image if root.disabled else root.cursor_image

<ProgressBar>:
canvas:
Expand Down
153 changes: 153 additions & 0 deletions kivy/tests/test_uix_slider.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
from kivy.tests.common import GraphicUnitTest

from kivy.input.motionevent import MotionEvent
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.slider import Slider
from kivy.base import EventLoop


class UTMotionEvent(MotionEvent):
def depack(self, args):
self.is_touch = True
self.sx = args['x']
self.sy = args['y']
self.profile = ['pos']
super(UTMotionEvent, self).depack(args)


class TestSliderHandle(Slider):
def __init__(self, **kwargs):
super(TestSliderHandle, self).__init__(**kwargs)
self.sensitivity = 'handle'


class TestSliderAll(Slider):
def __init__(self, **kwargs):
super(TestSliderAll, self).__init__(**kwargs)
self.sensitivity = 'all'


class SliderMoveTestCase(GraphicUnitTest):
framecount = 0

# debug with
# def tearDown(self, *a): pass
# def setUp(self): pass

def test_slider_move(self):
EventLoop.ensure_window()
win = EventLoop.window
layout = BoxLayout(orientation='vertical')

s_handle = TestSliderHandle()
s_all = TestSliderAll()
layout.add_widget(s_handle)
layout.add_widget(s_all)
win.add_widget(layout)

# get widgets ready
EventLoop.idle()

cur1 = s_handle.children[0]
cur2 = s_all.children[0]

h1 = cur1.to_window(*cur1.center)[1]
h2 = h1 - s_handle.cursor_height
h3 = cur2.to_window(*cur2.center)[1]
h4 = h3 - s_all.cursor_height

w1 = cur1.to_window(*cur1.center)[0]
w2 = cur2.to_window(*cur2.center)[0]
wh = win.width / 2.0
dt = 2

# default pos, new pos, slider ID
points = [
[w1, h1, wh, h1, 'handle'],
[w1, h2, wh, h2, 'handle'],
[w2, h3, wh, h3, 'all'],
[w2, h4, wh, h4, 'all'],
]

for point in points:
x, y, nx, ny, id = point

# custom touch
touch = UTMotionEvent("unittest", 1, {
"x": x / float(win.width),
"y": y / float(win.height),
})

# touch down
EventLoop.post_dispatch_input("begin", touch)

if id == 'handle':
# touch on handle
if x == w1 and y == h1:
self.assertAlmostEqual(
s_handle.value, 0.0,
delta=dt
)
# touch in widget area (ignored, previous value)
elif x == w1 and y == h2:
self.assertAlmostEqual(
s_handle.value, 50.0,
delta=dt
)
elif id == 'all':
# touch on handle:
if x == w1 and y == h3:
self.assertAlmostEqual(
s_all.value, 0.0,
delta=dt
)
# touch in widget area
elif x == w1 and y == h4:
self.assertAlmostEqual(
s_all.value, 0.0,
delta=dt
)

# move from default to new pos
touch.move({
"x": nx / float(win.width),
"y": ny / float(win.height)
})
EventLoop.post_dispatch_input("update", touch)

if id == 'handle':
# move from handle to center
if nx == wh and ny == h1:
self.assertAlmostEqual(
s_handle.value, 50.0,
delta=dt
)
# move to center (ignored, previous value)
elif nx == wh and ny == h2:
self.assertAlmostEqual(
s_handle.value, 50.0,
delta=dt
)
elif id == 'all':
# touch on handle:
if nx == wh and ny == h3:
self.assertAlmostEqual(
s_all.value, 50.0,
delta=dt
)
# touch in widget area
elif nx == wh and ny == h4:
self.assertAlmostEqual(
s_all.value, 50.0,
delta=dt
)

# touch up
EventLoop.post_dispatch_input("end", touch)

self.render(layout)


if __name__ == '__main__':
import unittest
unittest.main()
13 changes: 13 additions & 0 deletions kivy/uix/slider.py
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,16 @@ class Slider(Widget):
and defaults to 3dp.
"""

sensitivity = OptionProperty('all', options=('all', 'handle'))
"""Whether the touch collides with the whole body of the widget
or with the slider button part only.
.. versionadded:: 1.10.1
:attr:`sensitivity` is a :class:`~kivy.properties.OptionProperty`
and defaults to 'all'.
"""

# The following two methods constrain the slider's value
# to range(min,max). Otherwise it may happen that self.value < self.min
# at init.
Expand Down Expand Up @@ -357,6 +367,9 @@ def on_touch_down(self, touch):
self.value = max(
self.min,
self.value - (self.max - self.min) / 20)
elif self.sensitivity == 'handle':
if self.children[0].collide_point(*touch.pos):
touch.grab(self)
else:
touch.grab(self)
self.value_pos = touch.pos
Expand Down

0 comments on commit 873427d

Please sign in to comment.