-
-
Notifications
You must be signed in to change notification settings - Fork 780
/
DirectSlider.py
156 lines (129 loc) · 5.99 KB
/
DirectSlider.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
"""Defines the DirectSlider class.
See the :ref:`directslider` page in the programming manual for a more
in-depth explanation and an example of how to use this class.
"""
__all__ = ['DirectSlider']
from panda3d.core import PGSliderBar, Vec3
from . import DirectGuiGlobals as DGG
from .DirectFrame import DirectFrame
from .DirectButton import DirectButton
from math import isnan
class DirectSlider(DirectFrame):
"""
DirectSlider -- a widget which represents a slider that the
user can pull left and right to represent a continuous value.
"""
def __init__(self, parent = None, **kw):
optiondefs = (
# Define type of DirectGuiWidget
('pgFunc', PGSliderBar, None),
('state', DGG.NORMAL, None),
('frameColor', (0.6, 0.6, 0.6, 1), None),
('range', (0, 1), self.setRange),
('value', 0, self.__setValue),
('scrollSize', 0.01, self.setScrollSize),
('pageSize', 0.1, self.setPageSize),
('orientation', DGG.HORIZONTAL, self.setOrientation),
# Function to be called repeatedly as slider is moved
('command', None, None),
('extraArgs', [], None),
)
if kw.get('orientation') in (DGG.VERTICAL, DGG.VERTICAL_INVERTED):
# These are the default options for a vertical layout.
optiondefs += (
('frameSize', (-0.08, 0.08, -1, 1), None),
('frameVisibleScale', (0.25, 1), None),
)
else:
# These are the default options for a horizontal layout.
optiondefs += (
('frameSize', (-1, 1, -0.08, 0.08), None),
('frameVisibleScale', (1, 0.25), None),
)
# Merge keyword options with default options
self.defineoptions(kw, optiondefs)
# Initialize superclasses
DirectFrame.__init__(self, parent)
self.thumb = self.createcomponent("thumb", (), None,
DirectButton, (self,),
borderWidth = self['borderWidth'])
if self.thumb['frameSize'] is None:
# Compute a default frameSize for the thumb.
f = self['frameSize']
if self['orientation'] == DGG.HORIZONTAL:
self.thumb['frameSize'] = (f[0]*0.05, f[1]*0.05, f[2], f[3])
else:
self.thumb['frameSize'] = (f[0], f[1], f[2]*0.05, f[3]*0.05)
self._lastOrientation = self['orientation']
self.guiItem.setThumbButton(self.thumb.guiItem)
# Bind command function
self.bind(DGG.ADJUST, self.commandFunc)
# Call option initialization functions
self.initialiseoptions(DirectSlider)
def setRange(self):
# Try to preserve the value across a setRange call.
v = self['value']
r = self['range']
self.guiItem.setRange(r[0], r[1])
self['value'] = v
def __setValue(self):
# This is the internal function that is called when
# self['value'] is directly assigned.
value = self['value']
assert not isnan(value)
self.guiItem.setValue(value)
def setValue(self, value):
# This is the public function that is meant to be called by a
# user that doesn't like to use (or doesn't understand) the
# preferred interface of self['value'].
assert not isnan(value)
self['value'] = value
def getValue(self):
return self.guiItem.getValue()
def getRatio(self):
return self.guiItem.getRatio()
def setScrollSize(self):
self.guiItem.setScrollSize(self['scrollSize'])
def setPageSize(self):
self.guiItem.setPageSize(self['pageSize'])
def setOrientation(self):
if self['orientation'] == DGG.HORIZONTAL:
if self._lastOrientation in (DGG.VERTICAL, DGG.VERTICAL_INVERTED):
fpre = self['frameSize']
# swap frameSize width and height to keep custom frameSizes
self['frameSize'] = (fpre[2], fpre[3], fpre[0], fpre[1])
tf = self.thumb['frameSize']
self.thumb['frameSize'] = (tf[2], tf[3], tf[0], tf[1])
self.guiItem.setAxis(Vec3(1, 0, 0))
self['frameVisibleScale'] = (1, 0.25)
elif self['orientation'] == DGG.VERTICAL:
if self._lastOrientation == DGG.HORIZONTAL:
fpre = self['frameSize']
# swap frameSize width and height to keep custom frameSizes
self['frameSize'] = (fpre[2], fpre[3], fpre[0], fpre[1])
tf = self.thumb['frameSize']
self.thumb['frameSize'] = (tf[2], tf[3], tf[0], tf[1])
self.guiItem.setAxis(Vec3(0, 0, 1))
self['frameVisibleScale'] = (0.25, 1)
elif self['orientation'] == DGG.VERTICAL_INVERTED:
if self._lastOrientation == DGG.HORIZONTAL:
fpre = self['frameSize']
# swap frameSize width and height to keep custom frameSizes
self['frameSize'] = (fpre[2], fpre[3], fpre[0], fpre[1])
tf = self.thumb['frameSize']
self.thumb['frameSize'] = (tf[2], tf[3], tf[0], tf[1])
self.guiItem.setAxis(Vec3(0, 0, -1))
self['frameVisibleScale'] = (0.25, 1)
else:
raise ValueError('Invalid value for orientation: %s' % (self['orientation']))
self._lastOrientation = self['orientation']
def destroy(self):
if hasattr(self, 'thumb'):
self.thumb.destroy() # ow!
del self.thumb
DirectFrame.destroy(self)
def commandFunc(self):
# Store the updated value in self['value']
self._optionInfo['value'][DGG._OPT_VALUE] = self.guiItem.getValue()
if self['command']:
self['command'](*self['extraArgs'])