1 from __future__ import absolute_import
2 from __future__ import division
10 from wx import glcanvas
12 OpenGL.ERROR_CHECKING = False
13 from OpenGL.GL import *
15 from Cura.gui.util import opengl
17 class animation(object):
18 def __init__(self, gui, start, end, runTime):
21 self._startTime = time.time()
22 self._runTime = runTime
23 gui._animationList.append(self)
26 return time.time() > self._startTime + self._runTime
28 def getPosition(self):
31 f = (time.time() - self._startTime) / self._runTime
34 #f = 6*tc*ts + -15*ts*ts + 10*tc
36 return self._start + (self._end - self._start) * f
38 class glGuiControl(object):
39 def __init__(self, parent, pos):
41 self._base = parent._base
43 self._size = (0,0, 1, 1)
44 self._parent.add(self)
46 def setSize(self, x, y, w, h):
47 self._size = (x, y, w, h)
55 def updateLayout(self):
59 for n in xrange(self._parent._glGuiControlList.index(self) + 1, len(self._parent._glGuiControlList)):
60 if self._parent._glGuiControlList[n].setFocus():
62 for n in xrange(0, self._parent._glGuiControlList.index(self)):
63 if self._parent._glGuiControlList[n].setFocus():
66 def focusPrevious(self):
67 for n in xrange(self._parent._glGuiControlList.index(self) -1, -1, -1):
68 if self._parent._glGuiControlList[n].setFocus():
70 for n in xrange(len(self._parent._glGuiControlList) - 1, self._parent._glGuiControlList.index(self), -1):
71 if self._parent._glGuiControlList[n].setFocus():
78 return self._base._focus == self
80 def OnMouseUp(self, x, y):
83 def OnKeyChar(self, key):
86 class glGuiContainer(glGuiControl):
87 def __init__(self, parent, pos):
88 self._glGuiControlList = []
89 glGuiLayoutButtons(self)
90 super(glGuiContainer, self).__init__(parent, pos)
93 self._glGuiControlList.append(ctrl)
96 def OnMouseDown(self, x, y, button):
97 for ctrl in self._glGuiControlList:
98 if ctrl.OnMouseDown(x, y, button):
102 def OnMouseUp(self, x, y):
103 for ctrl in self._glGuiControlList:
104 if ctrl.OnMouseUp(x, y):
108 def OnMouseMotion(self, x, y):
110 for ctrl in self._glGuiControlList:
111 if ctrl.OnMouseMotion(x, y):
116 for ctrl in self._glGuiControlList:
119 def updateLayout(self):
120 self._layout.update()
121 for ctrl in self._glGuiControlList:
124 class glGuiPanel(glcanvas.GLCanvas):
125 def __init__(self, parent):
126 attribList = (glcanvas.WX_GL_RGBA, glcanvas.WX_GL_DOUBLEBUFFER, glcanvas.WX_GL_DEPTH_SIZE, 32, glcanvas.WX_GL_STENCIL_SIZE, 8)
127 glcanvas.GLCanvas.__init__(self, parent, style=wx.WANTS_CHARS, attribList = attribList)
130 self._container = None
131 self._container = glGuiContainer(self, (0,0))
132 self._shownError = False
134 self._context = glcanvas.GLContext(self)
135 self._glButtonsTexture = None
136 self._glRobotTexture = None
137 self._buttonSize = 64
139 self._animationList = []
140 self.glReleaseList = []
142 wx.EVT_PAINT(self, self._OnGuiPaint)
143 wx.EVT_SIZE(self, self._OnSize)
144 wx.EVT_ERASE_BACKGROUND(self, self._OnEraseBackground)
145 wx.EVT_LEFT_DOWN(self, self._OnGuiMouseDown)
146 wx.EVT_LEFT_DCLICK(self, self._OnGuiMouseDown)
147 wx.EVT_LEFT_UP(self, self._OnGuiMouseUp)
148 wx.EVT_RIGHT_DOWN(self, self._OnGuiMouseDown)
149 wx.EVT_RIGHT_DCLICK(self, self._OnGuiMouseDown)
150 wx.EVT_RIGHT_UP(self, self._OnGuiMouseUp)
151 wx.EVT_MIDDLE_DOWN(self, self._OnGuiMouseDown)
152 wx.EVT_MIDDLE_DCLICK(self, self._OnGuiMouseDown)
153 wx.EVT_MIDDLE_UP(self, self._OnGuiMouseUp)
154 wx.EVT_MOTION(self, self._OnGuiMouseMotion)
155 wx.EVT_CHAR(self, self._OnGuiKeyChar)
156 wx.EVT_KILL_FOCUS(self, self.OnFocusLost)
157 wx.EVT_IDLE(self, self._OnIdle)
159 def _OnIdle(self, e):
160 if len(self._animationList) > 0:
161 for anim in self._animationList:
163 self._animationList.remove(anim)
166 def _OnGuiKeyChar(self, e):
167 if self._focus is not None:
168 self._focus.OnKeyChar(e.GetKeyCode())
171 self.OnKeyChar(e.GetKeyCode())
173 def OnFocusLost(self, e):
177 def _OnGuiMouseDown(self,e):
179 if self._container.OnMouseDown(e.GetX(), e.GetY(), e.GetButton()):
184 def _OnGuiMouseUp(self, e):
185 if self._container.OnMouseUp(e.GetX(), e.GetY()):
190 def _OnGuiMouseMotion(self,e):
192 if not self._container.OnMouseMotion(e.GetX(), e.GetY()):
193 self.OnMouseMotion(e)
195 def _OnGuiPaint(self, e):
196 h = self.GetSize().GetHeight()
197 w = self.GetSize().GetWidth()
198 oldButtonSize = self._buttonSize
202 self._buttonSize = 32
204 self._buttonSize = 48
206 self._buttonSize = 64
208 self._buttonSize = 80
210 self._buttonSize = 96
211 if self._buttonSize != oldButtonSize:
212 self._container.updateLayout()
214 dc = wx.PaintDC(self)
216 self.SetCurrent(self._context)
217 for obj in self.glReleaseList:
219 del self.glReleaseList[:]
225 errStr = 'An error has occurred during the 3D view drawing.'
226 tb = traceback.extract_tb(sys.exc_info()[2])
227 errStr += "\n%s: '%s'" % (str(sys.exc_info()[0].__name__), str(sys.exc_info()[1]))
228 for n in xrange(len(tb)-1, -1, -1):
230 errStr += "\n @ %s:%s:%d" % (os.path.basename(locationInfo[0]), locationInfo[2], locationInfo[1])
231 if not self._shownError:
232 wx.CallAfter(wx.MessageBox, errStr, '3D window error', wx.OK | wx.ICON_EXCLAMATION)
233 self._shownError = True
236 if self._glButtonsTexture is None:
237 self._glButtonsTexture = opengl.loadGLTexture('glButtons.png')
238 self._glRobotTexture = opengl.loadGLTexture('UltimakerRobot.png')
240 glDisable(GL_DEPTH_TEST)
242 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
243 glDisable(GL_LIGHTING)
244 glColor4ub(255,255,255,255)
246 glMatrixMode(GL_PROJECTION)
248 size = self.GetSize()
249 glOrtho(0, size.GetWidth()-1, size.GetHeight()-1, 0, -1000.0, 1000.0)
250 glMatrixMode(GL_MODELVIEW)
253 self._container.draw()
254 glBindTexture(GL_TEXTURE_2D, self._glRobotTexture)
255 glEnable(GL_TEXTURE_2D)
258 glTranslate(size.GetWidth() - 8,size.GetHeight() - 16,0)
259 s = self._buttonSize * 1.4
271 glDisable(GL_TEXTURE_2D)
274 def _OnEraseBackground(self,event):
275 #Workaround for windows background redraw flicker.
279 self._container.setSize(0, 0, self.GetSize().GetWidth(), self.GetSize().GetHeight())
280 self._container.updateLayout()
283 def OnMouseDown(self,e):
285 def OnMouseUp(self,e):
287 def OnMouseMotion(self, e):
289 def OnKeyChar(self, keyCode):
291 def OnPaint(self, e):
295 if self._container is not None:
296 self._container.add(ctrl)
298 class glGuiLayoutButtons(object):
299 def __init__(self, parent):
300 self._parent = parent
301 self._parent._layout = self
304 bs = self._parent._base._buttonSize
305 x0, y0, w, h = self._parent.getSize()
307 for ctrl in self._parent._glGuiControlList:
310 x = w + pos[0] * gridSize - bs * 0.2
312 x = pos[0] * gridSize + bs * 0.2
314 y = h + pos[1] * gridSize * 1.2 - bs * 0.2
316 y = pos[1] * gridSize * 1.2 + bs * 0.2
317 ctrl.setSize(x, y, gridSize, gridSize)
319 def getLayoutSize(self):
320 _, _, w, h = self._parent.getSize()
323 class glGuiLayoutGrid(object):
324 def __init__(self, parent):
325 self._parent = parent
326 self._parent._layout = self
328 self._alignBottom = True
331 borderSize = self._parent._base._buttonSize * 0.2
332 x0, y0, w, h = self._parent.getSize()
337 for ctrl in self._parent._glGuiControlList:
339 w, h = ctrl.getMinSize()
343 widths[x] = max(widths[x], w)
347 heights[y] = max(heights[y], h)
348 self._size = sum(widths.values()) + borderSize * 2, sum(heights.values()) + borderSize * 2
349 if self._alignBottom:
350 y0 -= self._size[1] - self._parent.getSize()[3]
351 self._parent.setSize(x0 - borderSize, y0 - borderSize, self._size[0], self._size[1])
352 for ctrl in self._parent._glGuiControlList:
356 for n in xrange(0, x):
360 for n in xrange(0, y):
364 ctrl.setSize(x1, y1, widths[x], heights[y])
366 def getLayoutSize(self):
369 class glButton(glGuiControl):
370 def __init__(self, parent, imageID, tooltip, pos, callback):
371 super(glButton, self).__init__(parent, pos)
372 self._tooltip = tooltip
373 self._parent = parent
374 self._imageID = imageID
375 self._callback = callback
376 self._selected = False
379 self._disabled = False
380 self._showExpandArrow = False
381 self._progressBar = 0.0
383 def setSelected(self, value):
384 self._selected = value
386 def setExpandArrow(self, value):
387 self._showExpandArrow = value
389 def setHidden(self, value):
392 def setDisabled(self, value):
393 self._disabled = value
395 def setProgressBar(self, value):
396 self._progressBar = value
398 def getSelected(self):
399 return self._selected
401 def getMinSize(self):
402 return self._base._buttonSize, self._base._buttonSize
404 def _getPixelPos(self):
405 x0, y0, w, h = self.getSize()
406 return x0 + w / 2, y0 + h / 2
412 cx = (self._imageID % 4) / 4
413 cy = int(self._imageID / 4) / 4
414 bs = self._base._buttonSize
415 pos = self._getPixelPos()
417 glBindTexture(GL_TEXTURE_2D, self._base._glButtonsTexture)
424 glColor4ub(128,128,128,128)
426 glColor4ub(255,255,255,255)
427 opengl.glDrawTexturedQuad(pos[0]-bs*scale/2, pos[1]-bs*scale/2, bs*scale, bs*scale, 0)
428 opengl.glDrawTexturedQuad(pos[0]-bs*scale/2, pos[1]-bs*scale/2, bs*scale, bs*scale, self._imageID)
429 if self._showExpandArrow:
431 opengl.glDrawTexturedQuad(pos[0]+bs*scale/2-bs*scale/4*1.2, pos[1]-bs*scale/2*1.2, bs*scale/4, bs*scale/4, 1)
433 opengl.glDrawTexturedQuad(pos[0]+bs*scale/2-bs*scale/4*1.2, pos[1]-bs*scale/2*1.2, bs*scale/4, bs*scale/4, 1, 2)
435 glTranslatef(pos[0], pos[1], 0)
436 glDisable(GL_TEXTURE_2D)
438 glTranslatef(0, -0.55*bs*scale, 0)
441 glColor4ub(60,60,60,255)
442 glTranslatef(-1, -1, 0)
443 opengl.glDrawStringCenter(self._tooltip)
444 glTranslatef(0, 2, 0)
445 opengl.glDrawStringCenter(self._tooltip)
446 glTranslatef(2, 0, 0)
447 opengl.glDrawStringCenter(self._tooltip)
448 glTranslatef(0, -2, 0)
449 opengl.glDrawStringCenter(self._tooltip)
452 glColor4ub(255,255,255,255)
453 opengl.glDrawStringCenter(self._tooltip)
455 if 0.0 < self._progressBar < 1.0:
456 glColor4ub(255,255,255,192)
458 opengl.glDrawTexturedQuad(pos[0]-bs/2, pos[1]+bs/2, bs, bs / 4, 0)
459 opengl.glDrawTexturedQuad(pos[0]-bs/2, pos[1]+bs/2, bs * self._progressBar, bs / 4, 0)
462 def _checkHit(self, x, y):
463 if self._hidden or self._disabled:
465 bs = self.getMinSize()[0]
466 pos = self._getPixelPos()
467 return -bs * 0.5 <= x - pos[0] <= bs * 0.5 and -bs * 0.5 <= y - pos[1] <= bs * 0.5
469 def OnMouseMotion(self, x, y):
470 if self._checkHit(x, y):
476 def OnMouseDown(self, x, y, button):
477 if self._checkHit(x, y):
478 self._callback(button)
482 class glRadioButton(glButton):
483 def __init__(self, parent, imageID, tooltip, pos, group, callback):
484 super(glRadioButton, self).__init__(parent, imageID, tooltip, pos, self._onRadioSelect)
486 self._radioCallback = callback
487 self._group.append(self)
489 def setSelected(self, value):
490 self._selected = value
492 def _onRadioSelect(self, button):
493 self._base._focus = None
494 for ctrl in self._group:
496 ctrl.setSelected(False)
497 if self.getSelected():
498 self.setSelected(False)
500 self.setSelected(True)
501 self._radioCallback(button)
503 class glComboButton(glButton):
504 def __init__(self, parent, tooltip, imageIDs, tooltips, pos, callback):
505 super(glComboButton, self).__init__(parent, imageIDs[0], tooltip, pos, self._onComboOpenSelect)
506 self._imageIDs = imageIDs
507 self._tooltips = tooltips
508 self._comboCallback = callback
511 def _onComboOpenSelect(self):
513 self._base._focus = None
515 self._base._focus = self
520 self._selected = self.hasFocus()
521 super(glComboButton, self).draw()
523 bs = self._base._buttonSize / 2
524 pos = self._getPixelPos()
526 if not self._selected:
530 glTranslatef(pos[0]+bs*0.5, pos[1] + bs*0.5, 0)
531 glBindTexture(GL_TEXTURE_2D, self._base._glButtonsTexture)
532 for n in xrange(0, len(self._imageIDs)):
533 glTranslatef(0, bs, 0)
534 glColor4ub(255,255,255,255)
535 opengl.glDrawTexturedQuad(-0.5*bs,-0.5*bs,bs,bs, 0)
536 opengl.glDrawTexturedQuad(-0.5*bs,-0.5*bs,bs,bs, self._imageIDs[n])
537 glDisable(GL_TEXTURE_2D)
540 glTranslatef(-0.55*bs, 0.1*bs, 0)
543 glColor4ub(60,60,60,255)
544 glTranslatef(-1, -1, 0)
545 opengl.glDrawStringRight(self._tooltips[n])
546 glTranslatef(0, 2, 0)
547 opengl.glDrawStringRight(self._tooltips[n])
548 glTranslatef(2, 0, 0)
549 opengl.glDrawStringRight(self._tooltips[n])
550 glTranslatef(0, -2, 0)
551 opengl.glDrawStringRight(self._tooltips[n])
554 glColor4ub(255,255,255,255)
555 opengl.glDrawStringRight(self._tooltips[n])
560 return self._selection
562 def setValue(self, value):
563 self._selection = value
564 self._imageID = self._imageIDs[self._selection]
565 self._comboCallback()
567 def OnMouseDown(self, x, y, button):
568 if self._hidden or self._disabled:
571 bs = self._base._buttonSize / 2
572 pos = self._getPixelPos()
573 if 0 <= x - pos[0] <= bs and 0 <= y - pos[1] - bs <= bs * len(self._imageIDs):
574 self._selection = int((y - pos[1] - bs) / bs)
575 self._imageID = self._imageIDs[self._selection]
576 self._base._focus = None
577 self._comboCallback()
579 return super(glComboButton, self).OnMouseDown(x, y, button)
581 class glFrame(glGuiContainer):
582 def __init__(self, parent, pos):
583 super(glFrame, self).__init__(parent, pos)
584 self._selected = False
588 def setSelected(self, value):
589 self._selected = value
591 def setHidden(self, value):
594 def getSelected(self):
595 return self._selected
597 def getMinSize(self):
598 return self._base._buttonSize, self._base._buttonSize
600 def _getPixelPos(self):
601 x0, y0, w, h = self.getSize()
608 bs = self._parent._buttonSize
609 pos = self._getPixelPos()
611 size = self._layout.getLayoutSize()
612 glColor4ub(255,255,255,255)
613 opengl.glDrawStretchedQuad(pos[0], pos[1], size[0], size[1], bs/2, 0)
614 #Draw the controls on the frame
615 super(glFrame, self).draw()
617 def _checkHit(self, x, y):
620 pos = self._getPixelPos()
621 w, h = self._layout.getLayoutSize()
622 return 0 <= x - pos[0] <= w and 0 <= y - pos[1] <= h
624 def OnMouseMotion(self, x, y):
625 super(glFrame, self).OnMouseMotion(x, y)
626 if self._checkHit(x, y):
632 def OnMouseDown(self, x, y, button):
633 if self._checkHit(x, y):
634 super(glFrame, self).OnMouseDown(x, y, button)
638 class glLabel(glGuiControl):
639 def __init__(self, parent, label, pos):
641 super(glLabel, self).__init__(parent, pos)
643 def getMinSize(self):
644 w, h = opengl.glGetStringSize(self._label)
647 def _getPixelPos(self):
648 x0, y0, w, h = self.getSize()
652 x, y, w, h = self.getSize()
655 glTranslatef(x, y, 0)
657 # glColor4ub(255,255,255,128)
669 glTranslate(5, h - 5, 0)
670 glColor4ub(255,255,255,255)
671 opengl.glDrawStringLeft(self._label)
674 def _checkHit(self, x, y):
677 def OnMouseMotion(self, x, y):
680 def OnMouseDown(self, x, y, button):
683 class glNumberCtrl(glGuiControl):
684 def __init__(self, parent, value, pos, callback):
685 self._callback = callback
686 self._value = str(value)
689 self._inCallback = False
690 super(glNumberCtrl, self).__init__(parent, pos)
692 def setValue(self, value):
695 self._value = str(value)
697 def getMinSize(self):
698 w, h = opengl.glGetStringSize("VALUES")
701 def _getPixelPos(self):
702 x0, y0, w, h = self.getSize()
706 x, y, w, h = self.getSize()
709 glTranslatef(x, y, 0)
712 glColor4ub(255,255,255,255)
714 glColor4ub(255,255,255,192)
726 glTranslate(5, h - 5, 0)
727 glColor4ub(0,0,0,255)
728 opengl.glDrawStringLeft(self._value)
730 glTranslate(opengl.glGetStringSize(self._value[0:self._selectPos])[0] - 2, -1, 0)
731 opengl.glDrawStringLeft('|')
734 def _checkHit(self, x, y):
735 x1, y1, w, h = self.getSize()
736 return 0 <= x - x1 <= w and 0 <= y - y1 <= h
738 def OnMouseMotion(self, x, y):
741 def OnMouseDown(self, x, y, button):
742 if self._checkHit(x, y):
747 def OnKeyChar(self, c):
748 self._inCallback = True
751 self._selectPos = max(0, self._selectPos)
752 if c == wx.WXK_RIGHT:
754 self._selectPos = min(self._selectPos, len(self._value))
757 value = float(self._value)
762 self._value = str(value)
763 self._callback(self._value)
766 value = float(self._value)
772 self._value = str(value)
773 self._callback(self._value)
774 if c == wx.WXK_BACK and self._selectPos > 0:
775 self._value = self._value[0:self._selectPos - 1] + self._value[self._selectPos:]
777 self._callback(self._value)
778 if c == wx.WXK_DELETE:
779 self._value = self._value[0:self._selectPos] + self._value[self._selectPos + 1:]
780 self._callback(self._value)
781 if c == wx.WXK_TAB or c == wx.WXK_NUMPAD_ENTER or c == wx.WXK_RETURN:
782 if wx.GetKeyState(wx.WXK_SHIFT):
786 if (ord('0') <= c <= ord('9') or c == ord('.')) and len(self._value) < self._maxLen:
787 self._value = self._value[0:self._selectPos] + chr(c) + self._value[self._selectPos:]
789 self._callback(self._value)
790 self._inCallback = False
793 self._base._focus = self
794 self._selectPos = len(self._value)
797 class glCheckbox(glGuiControl):
798 def __init__(self, parent, value, pos, callback):
799 self._callback = callback
803 self._inCallback = False
804 super(glCheckbox, self).__init__(parent, pos)
806 def setValue(self, value):
809 self._value = str(value)
814 def getMinSize(self):
817 def _getPixelPos(self):
818 x0, y0, w, h = self.getSize()
822 x, y, w, h = self.getSize()
825 glTranslatef(x, y, 0)
827 glColor3ub(255,255,255)
829 opengl.glDrawTexturedQuad(w/2-h/2,0, h, h, 28)
831 opengl.glDrawTexturedQuad(w/2-h/2,0, h, h, 29)
835 def _checkHit(self, x, y):
836 x1, y1, w, h = self.getSize()
837 return 0 <= x - x1 <= w and 0 <= y - y1 <= h
839 def OnMouseMotion(self, x, y):
842 def OnMouseDown(self, x, y, button):
843 if self._checkHit(x, y):
844 self._value = not self._value
848 class glSlider(glGuiControl):
849 def __init__(self, parent, value, minValue, maxValue, pos, callback):
850 super(glSlider, self).__init__(parent, pos)
851 self._callback = callback
855 self._minValue = minValue
856 self._maxValue = maxValue
858 def setValue(self, value):
860 self._value = max(self._minValue, self._value)
861 self._value = min(self._maxValue, self._value)
866 def setRange(self, minValue, maxValue):
867 if maxValue < minValue:
869 self._minValue = minValue
870 self._maxValue = maxValue
871 self._value = max(minValue, self._value)
872 self._value = min(maxValue, self._value)
874 def getMinValue(self):
875 return self._minValue
877 def getMaxValue(self):
878 return self._maxValue
880 def setHidden(self, value):
883 def getMinSize(self):
884 return self._base._buttonSize * 0.2, self._base._buttonSize * 4
886 def _getPixelPos(self):
887 x0, y0, w, h = self.getSize()
888 minSize = self.getMinSize()
889 return x0 + w / 2 - minSize[0] / 2, y0 + h / 2 - minSize[1] / 2
895 w, h = self.getMinSize()
896 pos = self._getPixelPos()
899 glTranslatef(pos[0], pos[1], 0)
900 glDisable(GL_TEXTURE_2D)
902 glColor4ub(60,60,60,255)
904 glColor4ub(60,60,60,192)
906 glVertex2f( w/2,-h/2)
907 glVertex2f(-w/2,-h/2)
908 glVertex2f(-w/2, h/2)
909 glVertex2f( w/2, h/2)
912 glTranslate(0.0,scrollLength/2,0)
914 glColor4ub(0,0,0,255)
916 glTranslate(-w/2,opengl.glGetStringSize(str(self._minValue))[1]/2,0)
917 opengl.glDrawStringRight(str(self._minValue))
918 glTranslate(0,-scrollLength,0)
919 opengl.glDrawStringRight(str(self._maxValue))
920 if self._maxValue-self._minValue > 0:
921 glTranslate(w,scrollLength-scrollLength*((self._value-self._minValue)/(self._maxValue-self._minValue)),0)
922 opengl.glDrawStringLeft(str(self._value))
924 glColor4ub(255,255,255,240)
925 if self._maxValue - self._minValue != 0:
926 glTranslate(0.0,-scrollLength*((self._value-self._minValue)/(self._maxValue-self._minValue)),0)
928 glVertex2f( w/2,-w/2)
929 glVertex2f(-w/2,-w/2)
930 glVertex2f(-w/2, w/2)
931 glVertex2f( w/2, w/2)
935 def _checkHit(self, x, y):
938 pos = self._getPixelPos()
939 w, h = self.getMinSize()
940 return -w/2 <= x - pos[0] <= w/2 and -h/2 <= y - pos[1] <= h/2
943 self._base._focus = self
946 def OnMouseMotion(self, x, y):
948 w, h = self.getMinSize()
950 pos = self._getPixelPos()
951 self.setValue(int(self._minValue + (self._maxValue - self._minValue) * -(y - pos[1] - scrollLength/2) / scrollLength))
954 if self._checkHit(x, y):
960 def OnMouseDown(self, x, y, button):
961 if self._checkHit(x, y):
963 self.OnMouseMotion(x, y)
967 def OnMouseUp(self, x, y):
969 self._base._focus = None