|
@@ -17,8 +17,8 @@ SLIDER_MINI = 'mini'
|
|
|
SLIDER_FULL_WIDTH = 50
|
|
SLIDER_FULL_WIDTH = 50
|
|
|
SLIDER_FULL_HEIGHT = 25
|
|
SLIDER_FULL_HEIGHT = 25
|
|
|
|
|
|
|
|
-SLIDER_MINI_WIDTH = 22
|
|
|
|
|
-SLIDER_MINI_HEIGHT = 18
|
|
|
|
|
|
|
+SLIDER_MINI_WIDTH = 16
|
|
|
|
|
+SLIDER_MINI_HEIGHT = 16
|
|
|
|
|
|
|
|
globalClock = ClockObject.getGlobalClock()
|
|
globalClock = ClockObject.getGlobalClock()
|
|
|
|
|
|
|
@@ -121,14 +121,12 @@ class SliderWidget(Pmw.MegaWidget):
|
|
|
height = self['height']
|
|
height = self['height']
|
|
|
|
|
|
|
|
halfWidth = width/2.0
|
|
halfWidth = width/2.0
|
|
|
|
|
+ halfHeight = height/2.0
|
|
|
left = -(halfWidth - 2)
|
|
left = -(halfWidth - 2)
|
|
|
right = halfWidth - 2
|
|
right = halfWidth - 2
|
|
|
- halfHeight = height/2.0
|
|
|
|
|
top = -(halfHeight - 2)
|
|
top = -(halfHeight - 2)
|
|
|
bottom = halfHeight - 2
|
|
bottom = halfHeight - 2
|
|
|
|
|
|
|
|
- print left, right,bottom,top
|
|
|
|
|
-
|
|
|
|
|
# The canvas
|
|
# The canvas
|
|
|
self._canvas = self.createcomponent('canvas', (), None,
|
|
self._canvas = self.createcomponent('canvas', (), None,
|
|
|
Canvas, (interior,),
|
|
Canvas, (interior,),
|
|
@@ -275,30 +273,453 @@ class PopupSliderWidget(Pmw.MegaToplevel):
|
|
|
def __init__(self, parent = None, **kw):
|
|
def __init__(self, parent = None, **kw):
|
|
|
optiondefs = (
|
|
optiondefs = (
|
|
|
('width', 150, None),
|
|
('width', 150, None),
|
|
|
- ('height', 30, None),
|
|
|
|
|
|
|
+ ('height', 25, None),
|
|
|
('xoffset', 0, None), # pixels
|
|
('xoffset', 0, None), # pixels
|
|
|
('yoffset', 1, None), # pixels
|
|
('yoffset', 1, None), # pixels
|
|
|
)
|
|
)
|
|
|
self.defineoptions(kw, optiondefs)
|
|
self.defineoptions(kw, optiondefs)
|
|
|
Pmw.MegaToplevel.__init__(self, parent)
|
|
Pmw.MegaToplevel.__init__(self, parent)
|
|
|
|
|
+ interior = self.interior()
|
|
|
self.withdraw()
|
|
self.withdraw()
|
|
|
self.overrideredirect(1)
|
|
self.overrideredirect(1)
|
|
|
- self.interior()['relief'] = RAISED
|
|
|
|
|
- self.interior()['borderwidth'] = 3
|
|
|
|
|
- self.b = Button(self.interior(), text = 'hello')
|
|
|
|
|
|
|
+ interior['relief'] = RAISED
|
|
|
|
|
+ interior['borderwidth'] = 2
|
|
|
|
|
+ left = -self['width']/2.0
|
|
|
|
|
+ right = self['width']/2.0
|
|
|
|
|
+ top = -10
|
|
|
|
|
+ bottom = top + self['height']
|
|
|
|
|
+ self._canvas = self.createcomponent('canvas', (), None,
|
|
|
|
|
+ Canvas, (interior,),
|
|
|
|
|
+ relief = FLAT,
|
|
|
|
|
+ width = self['width'],
|
|
|
|
|
+ height = self['height'],
|
|
|
|
|
+ highlightthickness = 0,
|
|
|
|
|
+ scrollregion = (left, top,
|
|
|
|
|
+ right, bottom)
|
|
|
|
|
+ )
|
|
|
|
|
+ self._canvas.pack(expand = 1, fill = BOTH)
|
|
|
|
|
+ self.marker = self._canvas.create_polygon(-6.9 + 1,12,
|
|
|
|
|
+ 6.9+1,12,
|
|
|
|
|
+ 1, 0,
|
|
|
|
|
+ fill = 'black',
|
|
|
|
|
+ tags = ('slider',))
|
|
|
|
|
+ self._canvas.create_polygon(-5.75,10,
|
|
|
|
|
+ 5.75,10,
|
|
|
|
|
+ 0, 0,
|
|
|
|
|
+ fill = 'grey85',
|
|
|
|
|
+ outline = 'black',
|
|
|
|
|
+ tags = ('slider',))
|
|
|
|
|
+ # The indicator
|
|
|
|
|
+ self.lineLeft = lineLeft = left + 10
|
|
|
|
|
+ self.lineRight = lineRight = right -10
|
|
|
|
|
+ self._canvas.create_line(lineLeft, 1,
|
|
|
|
|
+ lineRight, 1,
|
|
|
|
|
+ width = 2)
|
|
|
|
|
+
|
|
|
|
|
+ self.b = Button(interior, text = 'hello')
|
|
|
self.b['command'] = self.withdraw
|
|
self.b['command'] = self.withdraw
|
|
|
self.b.pack()
|
|
self.b.pack()
|
|
|
self.initialiseoptions(PopupSliderWidget)
|
|
self.initialiseoptions(PopupSliderWidget)
|
|
|
|
|
+
|
|
|
def showPopup(self, widget):
|
|
def showPopup(self, widget):
|
|
|
x = widget.winfo_rootx() + widget.winfo_width() - self['width']
|
|
x = widget.winfo_rootx() + widget.winfo_width() - self['width']
|
|
|
y = widget.winfo_rooty() + widget.winfo_height()
|
|
y = widget.winfo_rooty() + widget.winfo_height()
|
|
|
Pmw.setgeometryanddeiconify(self, '%dx%d+%d+%d' %
|
|
Pmw.setgeometryanddeiconify(self, '%dx%d+%d+%d' %
|
|
|
(self['width'], self['height'],x,y))
|
|
(self['width'], self['height'],x,y))
|
|
|
|
|
+
|
|
|
"""
|
|
"""
|
|
|
|
|
+
|
|
|
pw = PopupSliderWidget()
|
|
pw = PopupSliderWidget()
|
|
|
tl = Toplevel()
|
|
tl = Toplevel()
|
|
|
-b = Button(tl, text = 'hello')
|
|
|
|
|
-b.pack(expand = 1, fill = X)
|
|
|
|
|
-b.bind('<ButtonPress-1>', lambda event, s = b: pw.showPopup(b))
|
|
|
|
|
-#b.bind('<ButtonRelease-1>', lambda event: pw.withdraw())
|
|
|
|
|
|
|
+b = Button(tl, text = 'V')
|
|
|
|
|
+b.pack()
|
|
|
|
|
+
|
|
|
|
|
+fCrossedLine = 0
|
|
|
|
|
+def move(event):
|
|
|
|
|
+ global fCrossedLine
|
|
|
|
|
+ if fCrossedLine:
|
|
|
|
|
+ newX = pw._canvas.canvasx(event.x_root) - pw.winfo_rootx()
|
|
|
|
|
+ if newX < pw.lineLeft:
|
|
|
|
|
+ newX = pw.lineLeft
|
|
|
|
|
+ elif newX > pw.lineRight:
|
|
|
|
|
+ newX = pw.lineRight
|
|
|
|
|
+ print (newX - pw.lineLeft)/(pw.lineRight - pw.lineLeft)
|
|
|
|
|
+ startX = getX()
|
|
|
|
|
+ dx = newX - startX
|
|
|
|
|
+ pw._canvas.move('slider', dx, 0)
|
|
|
|
|
+ else:
|
|
|
|
|
+ if event.y_root >= pw.winfo_rooty() + 10:
|
|
|
|
|
+ fCrossedLine = 1
|
|
|
|
|
+
|
|
|
|
|
+def getX():
|
|
|
|
|
+ c = pw._canvas.coords(pw.marker)
|
|
|
|
|
+ return c[4]
|
|
|
|
|
+
|
|
|
|
|
+def press(event):
|
|
|
|
|
+ global fCrossedLine
|
|
|
|
|
+ print 'press'
|
|
|
|
|
+ fCrossedLine = 0
|
|
|
|
|
+ pw.showPopup(b)
|
|
|
|
|
+ b.bind('<Motion>', move)
|
|
|
|
|
+
|
|
|
|
|
+def unpostCanvas(event):
|
|
|
|
|
+ print 'unpostCanvas', event.x_root, pw._canvas.winfo_rootx()
|
|
|
|
|
+ if event.x_root < pw._canvas.winfo_rootx():
|
|
|
|
|
+ print 'blah'
|
|
|
|
|
+ Pmw.popgrab(pw._canvas)
|
|
|
|
|
+ pw._canvas.withdraw()
|
|
|
|
|
+
|
|
|
|
|
+def popupPress(event):
|
|
|
|
|
+ global fCrossedLine
|
|
|
|
|
+ print 'popupPress'
|
|
|
|
|
+ fCrossedLine = 1
|
|
|
|
|
+ pw._canvas.bind('<Motion>', move)
|
|
|
|
|
+
|
|
|
|
|
+def release(event):
|
|
|
|
|
+ if fCrossedLine:
|
|
|
|
|
+ pw.withdraw()
|
|
|
|
|
+ b.unbind('<Motion>')
|
|
|
|
|
+ pw._canvas.unbind('<Motion>')
|
|
|
|
|
+ else:
|
|
|
|
|
+ Pmw.pushgrab(pw._canvas, 1, unpostCanvas)
|
|
|
|
|
+ pw._canvas.focus_set()
|
|
|
|
|
+
|
|
|
|
|
+b.bind('<ButtonPress-1>', press)
|
|
|
|
|
+b.bind('<ButtonRelease-1>', release)
|
|
|
|
|
+pw._canvas.bind('<ButtonPress-1>', popupPress)
|
|
|
|
|
+pw._canvas.bind('<ButtonRelease-1>', release)
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
"""
|
|
"""
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+# Based on Pmw ComboBox code.
|
|
|
|
|
+class PopupSlider(Pmw.MegaWidget):
|
|
|
|
|
+ def __init__(self, parent = None, **kw):
|
|
|
|
|
+
|
|
|
|
|
+ # Define the megawidget options.
|
|
|
|
|
+ INITOPT = Pmw.INITOPT
|
|
|
|
|
+ optiondefs = (
|
|
|
|
|
+ ('dropdown', 1, INITOPT),
|
|
|
|
|
+ ('buttonaspect', 1.0, INITOPT),
|
|
|
|
|
+ ('fliparrow', 0, INITOPT),
|
|
|
|
|
+ ('labelmargin', 0, INITOPT),
|
|
|
|
|
+ ('labelpos', None, INITOPT),
|
|
|
|
|
+ # Behavior
|
|
|
|
|
+ # Initial value of slider, use self.set to change value
|
|
|
|
|
+ ('value', 0.0, INITOPT),
|
|
|
|
|
+ ('numDigits', 2, self._setNumDigits),
|
|
|
|
|
+ # Command to execute on slider updates
|
|
|
|
|
+ ('command', None, None),
|
|
|
|
|
+ # Extra data to be passed to command function
|
|
|
|
|
+ ('commandData', [], None),
|
|
|
|
|
+ # Callback's to execute during mouse interaction
|
|
|
|
|
+ ('preCallback', None, None),
|
|
|
|
|
+ ('postCallback', None, None),
|
|
|
|
|
+ # Extra data to be passed to callback function, needs to be a list
|
|
|
|
|
+ ('callbackData', [], None),
|
|
|
|
|
+ )
|
|
|
|
|
+ self.defineoptions(kw, optiondefs)
|
|
|
|
|
+
|
|
|
|
|
+ # Initialise the base class (after defining the options).
|
|
|
|
|
+ Pmw.MegaWidget.__init__(self, parent)
|
|
|
|
|
+
|
|
|
|
|
+ # Create the components.
|
|
|
|
|
+ interior = self.interior()
|
|
|
|
|
+
|
|
|
|
|
+ # Current value
|
|
|
|
|
+ self.value = self['value']
|
|
|
|
|
+
|
|
|
|
|
+ # Interaction flags
|
|
|
|
|
+ self._fUpdate = 0
|
|
|
|
|
+ self._fUnpost = 0
|
|
|
|
|
+ self._firstPress = 1
|
|
|
|
|
+ self._fPressInsde = 0
|
|
|
|
|
+
|
|
|
|
|
+ self._entryfield = self.createcomponent('entryfield',
|
|
|
|
|
+ (('entry', 'entryfield_entry'),), None,
|
|
|
|
|
+ Pmw.EntryField, (interior,))
|
|
|
|
|
+ self._entryfield.grid(column=2, row=2, sticky='nsew')
|
|
|
|
|
+ interior.grid_columnconfigure(2, weight = 1)
|
|
|
|
|
+ self._entryWidget = self._entryfield.component('entry')
|
|
|
|
|
+
|
|
|
|
|
+ # Slider dimensions
|
|
|
|
|
+ width = 100
|
|
|
|
|
+ xPad = 10
|
|
|
|
|
+ canvasWidth = width + 2 * xPad
|
|
|
|
|
+ height = 20
|
|
|
|
|
+ self.left = left = -(width/2.0)
|
|
|
|
|
+ self.right = right = (width/2.0)
|
|
|
|
|
+ top = -5
|
|
|
|
|
+ bottom = top + height
|
|
|
|
|
+
|
|
|
|
|
+ # Create slider
|
|
|
|
|
+ if self['dropdown']:
|
|
|
|
|
+ self._isPosted = 0
|
|
|
|
|
+ interior.grid_rowconfigure(2, weight = 1)
|
|
|
|
|
+
|
|
|
|
|
+ # Create the arrow button.
|
|
|
|
|
+ self._arrowBtn = self.createcomponent('arrowbutton',
|
|
|
|
|
+ (), None,
|
|
|
|
|
+ Canvas, (interior,), borderwidth = 2,
|
|
|
|
|
+ relief = 'raised',
|
|
|
|
|
+ width = 16, height = 16)
|
|
|
|
|
+ self._arrowBtn.grid(column=3, row=2)
|
|
|
|
|
+ self._arrowRelief = self._arrowBtn.cget('relief')
|
|
|
|
|
+
|
|
|
|
|
+ # Create the label.
|
|
|
|
|
+ self.createlabel(interior, childCols=2)
|
|
|
|
|
+
|
|
|
|
|
+ # Create the dropdown window.
|
|
|
|
|
+ self._popup = self.createcomponent(
|
|
|
|
|
+ 'popup',
|
|
|
|
|
+ (), None,
|
|
|
|
|
+ Toplevel, (interior,),
|
|
|
|
|
+ relief = RAISED, borderwidth = 2)
|
|
|
|
|
+ self._popup.withdraw()
|
|
|
|
|
+ self._popup.overrideredirect(1)
|
|
|
|
|
+
|
|
|
|
|
+ # Create the canvas inside the dropdown window.
|
|
|
|
|
+ # Min label
|
|
|
|
|
+ self._minLabel = Label(self._popup, text = 'MINAAAAAA')
|
|
|
|
|
+ self._minLabel.pack(side = LEFT)
|
|
|
|
|
+ # Slider
|
|
|
|
|
+ self._canvas = self.createcomponent(
|
|
|
|
|
+ 'canvas', (), None,
|
|
|
|
|
+ Canvas, (self._popup,),
|
|
|
|
|
+ width = canvasWidth,
|
|
|
|
|
+ height = height,
|
|
|
|
|
+ bd = 3,
|
|
|
|
|
+ highlightthickness = 0,
|
|
|
|
|
+ scrollregion = (left - xPad, top, right + xPad, bottom))
|
|
|
|
|
+ self._canvas.pack(side = LEFT, expand=1, fill='both')
|
|
|
|
|
+ # Max label
|
|
|
|
|
+ self._maxLabel = Label(self._popup, text = 'MAX')
|
|
|
|
|
+ self._maxLabel.pack(side = LEFT)
|
|
|
|
|
+
|
|
|
|
|
+ # Bind events to the arrow button.
|
|
|
|
|
+ self._arrowBtn.bind('<1>', self._postCanvas)
|
|
|
|
|
+ self._arrowBtn.bind('<Configure>', self._drawArrow)
|
|
|
|
|
+
|
|
|
|
|
+ # Bind events to the dropdown window.
|
|
|
|
|
+ self._popup.bind('<Escape>', self._unpostCanvas)
|
|
|
|
|
+ self._popup.bind('<ButtonRelease-1>', self._dropdownBtnRelease)
|
|
|
|
|
+ self._popup.bind('<ButtonPress-1>', self._dropdownBtnPress)
|
|
|
|
|
+ self._popup.bind('<Motion>', self._dropdownMove)
|
|
|
|
|
+
|
|
|
|
|
+ # Bind events to the Tk listbox.
|
|
|
|
|
+ #self._canvas.bind('<Enter>', self._unpostOnNextRelease)
|
|
|
|
|
+
|
|
|
|
|
+ # Bind events to the Tk entry widget.
|
|
|
|
|
+ self._entryWidget.bind('<Configure>', self._resizeArrow)
|
|
|
|
|
+
|
|
|
|
|
+ # Need to unpost the popup if the entryfield is unmapped (eg:
|
|
|
|
|
+ # its toplevel window is withdrawn) while the popup canvas is
|
|
|
|
|
+ # displayed.
|
|
|
|
|
+ self._entryWidget.bind('<Unmap>', self._unpostCanvas)
|
|
|
|
|
+ else:
|
|
|
|
|
+ # Create the slider below the entry field.
|
|
|
|
|
+ self._canvas = self.createcomponent(
|
|
|
|
|
+ 'canvas', (), None,
|
|
|
|
|
+ Canvas, (interior,),
|
|
|
|
|
+ width = canvasWidth,
|
|
|
|
|
+ height = height,
|
|
|
|
|
+ highlightthickness = 0,
|
|
|
|
|
+ scrollregion = (left - xPad, top, right + xPad, bottom))
|
|
|
|
|
+ self._canvas.grid(column=2, row=3, sticky='nsew')
|
|
|
|
|
+
|
|
|
|
|
+ # The scrolled canvas should expand vertically.
|
|
|
|
|
+ interior.grid_rowconfigure(3, weight = 1)
|
|
|
|
|
+
|
|
|
|
|
+ # Create the label.
|
|
|
|
|
+ self.createlabel(interior, childRows=2)
|
|
|
|
|
+
|
|
|
|
|
+ # Interaction marker
|
|
|
|
|
+ xShift = 1
|
|
|
|
|
+ # Shadow arrow
|
|
|
|
|
+ self._marker = self._canvas.create_polygon(-7 + xShift, 12,
|
|
|
|
|
+ 7 + xShift, 12,
|
|
|
|
|
+ xShift, 0,
|
|
|
|
|
+ fill = 'black',
|
|
|
|
|
+ tags = ('slider',))
|
|
|
|
|
+ # Arrow
|
|
|
|
|
+ self._canvas.create_polygon(-6.0, 10,
|
|
|
|
|
+ 6.0, 10,
|
|
|
|
|
+ 0, 0,
|
|
|
|
|
+ fill = 'grey85',
|
|
|
|
|
+ outline = 'black',
|
|
|
|
|
+ tags = ('slider',))
|
|
|
|
|
+ # The indicator
|
|
|
|
|
+ self._canvas.create_line(left, 0,
|
|
|
|
|
+ right, 0,
|
|
|
|
|
+ width = 2)
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ # Check keywords and initialise options.
|
|
|
|
|
+ self.initialiseoptions(PopupSlider)
|
|
|
|
|
+
|
|
|
|
|
+ def destroy(self):
|
|
|
|
|
+ if self['dropdown'] and self._isPosted:
|
|
|
|
|
+ Pmw.popgrab(self._popup)
|
|
|
|
|
+ Pmw.MegaWidget.destroy(self)
|
|
|
|
|
+
|
|
|
|
|
+ #======================================================================
|
|
|
|
|
+
|
|
|
|
|
+ # Public methods
|
|
|
|
|
+
|
|
|
|
|
+ def set(self, value, fCommand = 1):
|
|
|
|
|
+ """
|
|
|
|
|
+ self.set(value, fCommand = 1)
|
|
|
|
|
+ Set slider to new value, execute command if fCommand == 1
|
|
|
|
|
+ """
|
|
|
|
|
+ # Send command if any
|
|
|
|
|
+ if fCommand and (self['command'] != None):
|
|
|
|
|
+ apply(self['command'], [value] + self['commandData'])
|
|
|
|
|
+ # Record value
|
|
|
|
|
+ self.value = value
|
|
|
|
|
+
|
|
|
|
|
+ def updateIndicator(self, value):
|
|
|
|
|
+ # Nothing visible to update on this type of widget
|
|
|
|
|
+ pass
|
|
|
|
|
+
|
|
|
|
|
+ def get(self):
|
|
|
|
|
+ """
|
|
|
|
|
+ self.get()
|
|
|
|
|
+ Get current slider value
|
|
|
|
|
+ """
|
|
|
|
|
+ return self.value
|
|
|
|
|
+
|
|
|
|
|
+ #======================================================================
|
|
|
|
|
+
|
|
|
|
|
+ # Private methods for dropdown canvas.
|
|
|
|
|
+
|
|
|
|
|
+ def _setNumDigits(self):
|
|
|
|
|
+ pass
|
|
|
|
|
+
|
|
|
|
|
+ def _drawArrow(self, event=None, sunken=0):
|
|
|
|
|
+ arrow = self._arrowBtn
|
|
|
|
|
+ if sunken:
|
|
|
|
|
+ self._arrowRelief = arrow.cget('relief')
|
|
|
|
|
+ arrow.configure(relief = 'sunken')
|
|
|
|
|
+ else:
|
|
|
|
|
+ arrow.configure(relief = self._arrowRelief)
|
|
|
|
|
+
|
|
|
|
|
+ if self._isPosted and self['fliparrow']:
|
|
|
|
|
+ direction = 'up'
|
|
|
|
|
+ else:
|
|
|
|
|
+ direction = 'down'
|
|
|
|
|
+ Pmw.drawarrow(arrow, self['entry_foreground'], direction, 'arrow')
|
|
|
|
|
+
|
|
|
|
|
+ def _postCanvas(self, event = None):
|
|
|
|
|
+ self._isPosted = 1
|
|
|
|
|
+ self._fUpdate = 0
|
|
|
|
|
+ self._drawArrow(sunken=1)
|
|
|
|
|
+
|
|
|
|
|
+ # Make sure that the arrow is displayed sunken.
|
|
|
|
|
+ self.update_idletasks()
|
|
|
|
|
+
|
|
|
|
|
+ x = self._entryfield.winfo_rootx()
|
|
|
|
|
+ y = self._entryfield.winfo_rooty() + self._entryfield.winfo_height()
|
|
|
|
|
+ w = self._entryfield.winfo_width() + self._arrowBtn.winfo_width()
|
|
|
|
|
+ minW = self._minLabel.winfo_width()
|
|
|
|
|
+ cw = self._canvas.winfo_width()
|
|
|
|
|
+ maxW = self._maxLabel.winfo_width()
|
|
|
|
|
+ pw = minW + cw + maxW
|
|
|
|
|
+ ch = self._canvas.winfo_height()
|
|
|
|
|
+ sh = self.winfo_screenheight()
|
|
|
|
|
+
|
|
|
|
|
+ # Compensate if too close to edge of screen
|
|
|
|
|
+ if y + ch > sh and y > sh / 2:
|
|
|
|
|
+ y = self._entryfield.winfo_rooty() - ch
|
|
|
|
|
+
|
|
|
|
|
+ Pmw.setgeometryanddeiconify(self._popup, '+%d+%d' % (x + w - pw, y))
|
|
|
|
|
+
|
|
|
|
|
+ # Grab the popup, so that all events are delivered to it, and
|
|
|
|
|
+ # set focus to the canvas, to make keyboard navigation
|
|
|
|
|
+ # easier.
|
|
|
|
|
+ Pmw.pushgrab(self._popup, 1, self._unpostCanvas)
|
|
|
|
|
+ self._canvas.focus_set()
|
|
|
|
|
+
|
|
|
|
|
+ self._drawArrow()
|
|
|
|
|
+
|
|
|
|
|
+ # Ignore the first release of the mouse button after posting the
|
|
|
|
|
+ # dropdown canvas, unless the mouse enters the dropdown canvas.
|
|
|
|
|
+ self._fUpdate = 0
|
|
|
|
|
+ self._fUnpost = 0
|
|
|
|
|
+ self._firstPress = 1
|
|
|
|
|
+ self._fPressInsde = 0
|
|
|
|
|
+
|
|
|
|
|
+ def _updateValue(self,event):
|
|
|
|
|
+ canvasX = self._canvas.canvasx(
|
|
|
|
|
+ event.x_root - self._canvas.winfo_rootx())
|
|
|
|
|
+ if canvasX < self.left:
|
|
|
|
|
+ canvasX = self.left
|
|
|
|
|
+ if canvasX > self.right:
|
|
|
|
|
+ canvasX = self.right
|
|
|
|
|
+ # Get current marker position
|
|
|
|
|
+ currX = self._getMarkerX()
|
|
|
|
|
+ dx = canvasX - currX
|
|
|
|
|
+ self._canvas.move('slider', dx, 0)
|
|
|
|
|
+
|
|
|
|
|
+ def _dropdownBtnPress(self, event):
|
|
|
|
|
+ self._fUpdate = 1
|
|
|
|
|
+ self._fPressInside = 1
|
|
|
|
|
+ self._updateValue(event)
|
|
|
|
|
+
|
|
|
|
|
+ def _dropdownMove(self, event):
|
|
|
|
|
+ if self._firstPress and not self._fUpdate:
|
|
|
|
|
+ canvasY = self._canvas.canvasy(
|
|
|
|
|
+ event.y_root - self._canvas.winfo_rooty())
|
|
|
|
|
+ if canvasY > 0:
|
|
|
|
|
+ self._fUpdate = 1
|
|
|
|
|
+ self._unpostOnNextRelease()
|
|
|
|
|
+ elif self._fUpdate:
|
|
|
|
|
+ self._updateValue(event)
|
|
|
|
|
+
|
|
|
|
|
+ def _dropdownBtnRelease(self, event):
|
|
|
|
|
+ if (self._fUnpost or
|
|
|
|
|
+ (not (self._firstPress or self._fPressInside))):
|
|
|
|
|
+ self._unpostCanvas()
|
|
|
|
|
+ # Otherwise, continue
|
|
|
|
|
+ self._fUpdate = 0
|
|
|
|
|
+ self._firstPress = 0
|
|
|
|
|
+ self._fPressInside = 0
|
|
|
|
|
+
|
|
|
|
|
+ def _unpostOnNextRelease(self, event = None):
|
|
|
|
|
+ self._fUnpost = 1
|
|
|
|
|
+
|
|
|
|
|
+ def _resizeArrow(self, event):
|
|
|
|
|
+ bw = (string.atoi(self._arrowBtn['borderwidth']) +
|
|
|
|
|
+ string.atoi(self._arrowBtn['highlightthickness']))
|
|
|
|
|
+ newHeight = self._entryfield.winfo_reqheight() - 2 * bw
|
|
|
|
|
+ newWidth = int(newHeight * self['buttonaspect'])
|
|
|
|
|
+ self._arrowBtn.configure(width=newWidth, height=newHeight)
|
|
|
|
|
+ self._drawArrow()
|
|
|
|
|
+
|
|
|
|
|
+ def _unpostCanvas(self, event=None):
|
|
|
|
|
+ if not self._isPosted:
|
|
|
|
|
+ # It is possible to get events on an unposted popup. For
|
|
|
|
|
+ # example, by repeatedly pressing the space key to post
|
|
|
|
|
+ # and unpost the popup. The <space> event may be
|
|
|
|
|
+ # delivered to the popup window even though
|
|
|
|
|
+ # Pmw.popgrab() has set the focus away from the
|
|
|
|
|
+ # popup window. (Bug in Tk?)
|
|
|
|
|
+ return
|
|
|
|
|
+
|
|
|
|
|
+ # Restore the focus before withdrawing the window, since
|
|
|
|
|
+ # otherwise the window manager may take the focus away so we
|
|
|
|
|
+ # can't redirect it. Also, return the grab to the next active
|
|
|
|
|
+ # window in the stack, if any.
|
|
|
|
|
+ Pmw.popgrab(self._popup)
|
|
|
|
|
+ self._popup.withdraw()
|
|
|
|
|
+
|
|
|
|
|
+ self._isPosted = 0
|
|
|
|
|
+ self._drawArrow()
|
|
|
|
|
+
|
|
|
|
|
+ def _getMarkerX(self):
|
|
|
|
|
+ # Get marker triangle coordinates
|
|
|
|
|
+ c = self._canvas.coords(self._marker)
|
|
|
|
|
+ # Marker postion defined as X position of third vertex
|
|
|
|
|
+ return c[4]
|
|
|
|
|
+
|
|
|
|
|
+Pmw.forwardmethods(PopupSlider, Pmw.EntryField, '_entryfield')
|