*** empty log message ***
This commit is contained in:
parent
9b5a3a0eb0
commit
60313b33fa
|
|
@ -7,7 +7,8 @@ import string
|
|||
# For mono-modelcave-pipe0, I decided to set the offsets in the
|
||||
# actual configuration for the display.
|
||||
|
||||
ClientConfigs = {'mono-modelcave-pipe0': [ [Vec3(0,0,0),Vec3(0,0,0)] ] }
|
||||
ClientConfigs = {'mono-modelcave-pipe0': [ [Vec3(0,0,0),Vec3(0,0,0)] ],
|
||||
'single': [ [Vec3(0,0,0),Vec3(0,0,0)] ]}
|
||||
|
||||
# The following is a fake configuration to show an example with two servers.
|
||||
# 'two-server' : [ [Vec3(0,0,0),Vec3(-60,0,0)],
|
||||
|
|
|
|||
|
|
@ -490,13 +490,10 @@ class DirectSessionPanel(AppShell):
|
|||
self.gridSize['command'] = direct.grid.setGridSize
|
||||
self.gridSize.pack(fill = X, expand = 0)
|
||||
|
||||
self.gridSnapAngle = Dial.Dial(
|
||||
self.gridSnapAngle = Dial.AngleDial(
|
||||
gridPage,
|
||||
text = 'Snap Angle',
|
||||
min = 0.0, max = 360.0,
|
||||
numTicks = 12,
|
||||
fRollover = 0,
|
||||
initialValue = direct.grid.getSnapAngle())
|
||||
value = direct.grid.getSnapAngle())
|
||||
self.gridSnapAngle['command'] = direct.grid.setSnapAngle
|
||||
self.gridSnapAngle.pack(fill = X, expand = 0)
|
||||
|
||||
|
|
|
|||
|
|
@ -279,23 +279,23 @@ class ParticlePanel(AppShell):
|
|||
zSpinPage = self.factoryNotebook.add('ZSpinParticleFactory')
|
||||
self.createAngleDial(zSpinPage, 'Z Spin Factory', 'Initial Angle',
|
||||
'Starting angle in degrees',
|
||||
fRollover = 1,
|
||||
dial_fRollover = 1,
|
||||
command = self.setFactoryZSpinInitialAngle)
|
||||
self.createAngleDial(
|
||||
zSpinPage, 'Z Spin Factory',
|
||||
'Initial Angle Spread',
|
||||
'Spread of the initial angle',
|
||||
fRollover = 1,
|
||||
dial_fRollover = 1,
|
||||
command = self.setFactoryZSpinInitialAngleSpread)
|
||||
self.createAngleDial(zSpinPage, 'Z Spin Factory', 'Final Angle',
|
||||
'Final angle in degrees',
|
||||
fRollover = 1,
|
||||
dial_fRollover = 1,
|
||||
command = self.setFactoryZSpinFinalAngle)
|
||||
self.createAngleDial(
|
||||
zSpinPage, 'Z Spin Factory',
|
||||
'Final Angle Spread',
|
||||
'Spread of the final angle',
|
||||
fRollover = 1,
|
||||
dial_fRollover = 1,
|
||||
command = self.setFactoryZSpinFinalAngleSpread)
|
||||
# Oriented page #
|
||||
orientedPage = self.factoryNotebook.add('OrientedParticleFactory')
|
||||
|
|
|
|||
|
|
@ -241,48 +241,42 @@ class Placer(AppShell):
|
|||
|
||||
# Create the dials
|
||||
self.hprH = self.createcomponent('hprH', (), None,
|
||||
Dial.Dial, (hprInterior,),
|
||||
text = 'H', fRollover = 0,
|
||||
max = 360.0, numTicks = 12,
|
||||
initialValue = 0.0,
|
||||
Dial.AngleDial, (hprInterior,),
|
||||
text = 'H', value = 0.0,
|
||||
label_foreground = 'blue')
|
||||
self.hprH['command'] = self.xform
|
||||
self.hprH['commandData'] = ['h']
|
||||
self.hprH['callbackData'] = ['h']
|
||||
self.hprH.onReturn = self.xformStart
|
||||
self.hprH.onReturnRelease = self.xformStop
|
||||
self.hprH.onPress = self.xformStart
|
||||
self.hprH.onRelease = self.xformStop
|
||||
self.hprH['onReturnPress'] = self.xformStart
|
||||
self.hprH['onReturnRelease'] = self.xformStop
|
||||
self.hprH['onButtonPress'] = self.xformStart
|
||||
self.hprH['onButtonRelease'] = self.xformStop
|
||||
self.hprH.pack(expand=1,fill='both')
|
||||
|
||||
self.hprP = self.createcomponent('hprP', (), None,
|
||||
Dial.Dial, (hprInterior,),
|
||||
text = 'P', fRollover = 0,
|
||||
max = 360.0, numTicks = 12,
|
||||
initialValue = 0.0,
|
||||
Dial.AngleDial, (hprInterior,),
|
||||
text = 'P', value = 0.0,
|
||||
label_foreground = 'red')
|
||||
self.hprP['command'] = self.xform
|
||||
self.hprP['commandData'] = ['p']
|
||||
self.hprP['callbackData'] = ['p']
|
||||
self.hprP.onReturn = self.xformStart
|
||||
self.hprP.onReturnRelease = self.xformStop
|
||||
self.hprP.onPress = self.xformStart
|
||||
self.hprP.onRelease = self.xformStop
|
||||
self.hprP['onReturnPress'] = self.xformStart
|
||||
self.hprP['onReturnRelease'] = self.xformStop
|
||||
self.hprP['onButtonPress'] = self.xformStart
|
||||
self.hprP['onButtonRelease'] = self.xformStop
|
||||
self.hprP.pack(expand=1,fill='both')
|
||||
|
||||
self.hprR = self.createcomponent('hprR', (), None,
|
||||
Dial.Dial, (hprInterior,),
|
||||
text = 'R', fRollover = 0,
|
||||
max = 360.0, numTicks = 12,
|
||||
initialValue = 0.0,
|
||||
Dial.AngleDial, (hprInterior,),
|
||||
text = 'R', value = 0.0,
|
||||
label_foreground = '#00A000')
|
||||
self.hprR['command'] = self.xform
|
||||
self.hprR['commandData'] = ['r']
|
||||
self.hprR['callbackData'] = ['r']
|
||||
self.hprR.onReturn = self.xformStart
|
||||
self.hprR.onReturnRelease = self.xformStop
|
||||
self.hprR.onPress = self.xformStart
|
||||
self.hprR.onRelease = self.xformStop
|
||||
self.hprR['onReturnPress'] = self.xformStart
|
||||
self.hprR['onReturnRelease'] = self.xformStop
|
||||
self.hprR['onButtonPress'] = self.xformStart
|
||||
self.hprR['onButtonRelease'] = self.xformStop
|
||||
self.hprR.pack(expand=1,fill='both')
|
||||
|
||||
# Create and pack the Scale Controls
|
||||
|
|
@ -321,43 +315,46 @@ class Placer(AppShell):
|
|||
self.scaleX = self.createcomponent('scaleX', (), None,
|
||||
Dial.Dial, (scaleInterior,),
|
||||
text = 'X Scale',
|
||||
initialValue = 1.0,
|
||||
min = 0.0001, value = 1.0,
|
||||
resetValue = 1.0,
|
||||
label_foreground = 'Red')
|
||||
self.scaleX['command'] = self.xform
|
||||
self.scaleX['commandData'] = ['sx']
|
||||
self.scaleX['callbackData'] = ['sx']
|
||||
self.scaleX.onReturn = self.xformStart
|
||||
self.scaleX.onReturnRelease = self.xformStop
|
||||
self.scaleX.onPress = self.xformStart
|
||||
self.scaleX.onRelease = self.xformStop
|
||||
self.scaleX['onReturnPress'] = self.xformStart
|
||||
self.scaleX['onReturnRelease'] = self.xformStop
|
||||
self.scaleX['onButtonPress'] = self.xformStart
|
||||
self.scaleX['onButtonRelease'] = self.xformStop
|
||||
self.scaleX.pack(expand=1,fill='both')
|
||||
|
||||
self.scaleY = self.createcomponent('scaleY', (), None,
|
||||
Dial.Dial, (scaleInterior,),
|
||||
text = 'Y Scale',
|
||||
initialValue = 1.0,
|
||||
min = 0.0001, value = 1.0,
|
||||
resetValue = 1.0,
|
||||
label_foreground = '#00A000')
|
||||
self.scaleY['command'] = self.xform
|
||||
self.scaleY['commandData'] = ['sy']
|
||||
self.scaleY['callbackData'] = ['sy']
|
||||
self.scaleY.onReturn = self.xformStart
|
||||
self.scaleY.onReturnRelease = self.xformStop
|
||||
self.scaleY.onPress = self.xformStart
|
||||
self.scaleY.onRelease = self.xformStop
|
||||
self.scaleY['onReturnPress'] = self.xformStart
|
||||
self.scaleY['onReturnRelease'] = self.xformStop
|
||||
self.scaleY['onButtonPress'] = self.xformStart
|
||||
self.scaleY['onButtonRelease'] = self.xformStop
|
||||
self.scaleY.pack(expand=1,fill='both')
|
||||
|
||||
self.scaleZ = self.createcomponent('scaleZ', (), None,
|
||||
Dial.Dial, (scaleInterior,),
|
||||
text = 'Z Scale',
|
||||
initialValue = 1.0,
|
||||
min = 0.0001, value = 1.0,
|
||||
resetValue = 1.0,
|
||||
label_foreground = 'Blue')
|
||||
self.scaleZ['command'] = self.xform
|
||||
self.scaleZ['commandData'] = ['sz']
|
||||
self.scaleZ['callbackData'] = ['sz']
|
||||
self.scaleZ.onReturn = self.xformStart
|
||||
self.scaleZ.onReturnRelease = self.xformStop
|
||||
self.scaleZ.onPress = self.xformStart
|
||||
self.scaleZ.onRelease = self.xformStop
|
||||
self.scaleZ['onReturnPress'] = self.xformStart
|
||||
self.scaleZ['onReturnRelease'] = self.xformStop
|
||||
self.scaleZ['onButtonPress'] = self.xformStart
|
||||
self.scaleZ['onButtonRelease'] = self.xformStop
|
||||
self.scaleZ.pack(expand=1,fill='both')
|
||||
|
||||
# Make sure appropriate labels are showing
|
||||
|
|
|
|||
|
|
@ -7,11 +7,6 @@ import math
|
|||
import string
|
||||
import operator
|
||||
|
||||
# TODO:
|
||||
# More standardized use of 'max' and 'min'
|
||||
# Better floater style action
|
||||
# New option? 'delta'? 'repeatVal'? 'modulus'
|
||||
|
||||
TWO_PI = 2.0 * math.pi
|
||||
ONEPOINTFIVE_PI = 1.5 * math.pi
|
||||
POINTFIVE_PI = 0.5 * math.pi
|
||||
|
|
@ -26,89 +21,45 @@ class Dial(Pmw.MegaWidget):
|
|||
INITOPT = Pmw.INITOPT
|
||||
optiondefs = (
|
||||
# Widget relief
|
||||
('relief', GROOVE, INITOPT),
|
||||
('relief', GROOVE, None),
|
||||
# Widget borderwidth
|
||||
('borderwidth', 2, INITOPT),
|
||||
# Relief of dial inset
|
||||
('canvas_relief', GROOVE, INITOPT),
|
||||
# Borderwidth of dial inset
|
||||
('canvas_bd', 2, INITOPT),
|
||||
# Size of edge of dial inset
|
||||
('edgeLength', 50, INITOPT),
|
||||
('initialValue', 0.0, INITOPT),
|
||||
# Snap to angle on/off
|
||||
('fSnap', 0, None),
|
||||
# Do values rollover (i.e. accumulate) with multiple revolutions
|
||||
('fRollover', 1, None),
|
||||
('command', None, None),
|
||||
('commandData', [], None),
|
||||
('callbackData', [], None),
|
||||
('text', 'Dial Widget', self.updateLabel),
|
||||
('numTicks', 10, self.createTicks),
|
||||
('numDigits', 2, self.updateEntryFormat),
|
||||
('min', 0.0, self.setScaleFactor),
|
||||
('max', 1.0, self.setScaleFactor),
|
||||
('borderwidth', 2, None),
|
||||
('value', 0.0, INITOPT),
|
||||
('resetValue', 0.0, self.setResetValue),
|
||||
('text', 'Dial Widget', self.setLabel),
|
||||
('numDigits', 2, self.setEntryFormat),
|
||||
('command', None, None),
|
||||
('commandData', [], None),
|
||||
('callbackData', [], self.setCallbackData),
|
||||
('min', 0.0, self.setMin),
|
||||
('max', 1.0, self.setMax),
|
||||
('onReturnPress', None, None),
|
||||
('onReturnRelease', None, None),
|
||||
('onButtonPress', None, self.setButtonPressCmd),
|
||||
('onButtonRelease', None, self.setButtonReleaseCmd),
|
||||
)
|
||||
self.defineoptions(kw, optiondefs)
|
||||
|
||||
# Initialize the superclass
|
||||
Pmw.MegaWidget.__init__(self, parent)
|
||||
|
||||
# Set up some local and instance variables
|
||||
dim = self['edgeLength']
|
||||
self.sfGridDelta = dim / 10
|
||||
half = self.half = int(dim/2.0)
|
||||
radius = self.radius = half - 4
|
||||
|
||||
# Running total which increments/decrements every time around dial
|
||||
self.baseVal = 0.0
|
||||
# Determines value of one dial revolution
|
||||
self.scaleFactor = 1.0
|
||||
self.dialAngle = None
|
||||
# Current value
|
||||
self.value = self['initialValue']
|
||||
|
||||
# Create the components
|
||||
interior = self.interior()
|
||||
interior.configure(relief = self['relief'], bd = self['borderwidth'])
|
||||
|
||||
# The canvas
|
||||
self._canvas = self.createcomponent('canvas', (), None,
|
||||
Canvas, (interior,),
|
||||
width = dim + 12, height = dim,
|
||||
scrollregion = ((- half),(- half),
|
||||
half, half))
|
||||
self._canvas.grid(rowspan = 2, columnspan = 2)
|
||||
# The Dial
|
||||
self._dial = self.createcomponent('dial', (), None,
|
||||
MiniDial, (interior,),
|
||||
value = self['value'])
|
||||
# Attach dial to entry
|
||||
self._dial['command'] = self.setEntry
|
||||
self._dial.grid(rowspan = 2, columnspan = 2)
|
||||
|
||||
# The shuttle ring
|
||||
self._canvas.create_oval(-half, -half, half, half,
|
||||
fill = 'white', tags = ('ring',))
|
||||
|
||||
# The dial face
|
||||
self._canvas.create_oval(-radius, -radius, radius, radius,
|
||||
fill = 'white', tags = ('dial',))
|
||||
self.createTicks()
|
||||
|
||||
# The velocity knob
|
||||
self._canvas.create_oval(-radius * INNER_SF, -radius * INNER_SF,
|
||||
radius * INNER_SF, radius * INNER_SF,
|
||||
fill = '#909090', tags = ('velocityKnob',))
|
||||
|
||||
# The indicator
|
||||
self._canvas.create_line(0, 0, 0, (- radius), width = 2,
|
||||
tags = ('indicator', 'dial'))
|
||||
|
||||
# The Scale Factor marker
|
||||
self._canvas.create_polygon( half + 4, - 4, half + 12, 0,
|
||||
half + 4, + 4, fill = '#A0A0A0',
|
||||
tags = ('sfMarker',))
|
||||
self.sfy = 0
|
||||
|
||||
# The Dial's label
|
||||
# The Label
|
||||
self._label = self.createcomponent('label', (), None,
|
||||
Label, (interior,),
|
||||
text = self['text'],
|
||||
font = ('MS Sans Serif', 12, 'bold'),
|
||||
font = ('MS Sans Serif',12,'bold'),
|
||||
anchor = CENTER)
|
||||
self._label.grid(row = 0, col = 2, sticky = EW)
|
||||
|
||||
|
|
@ -123,404 +74,78 @@ class Dial(Pmw.MegaWidget):
|
|||
self._entryBackground = self._entry.cget('background')
|
||||
interior.columnconfigure(2, weight = 1)
|
||||
|
||||
# The popup menu
|
||||
self._popupMenu = Menu(interior, tearoff = 0)
|
||||
self._fAngleSnap = IntVar()
|
||||
self._fAngleSnap.set(self['fSnap'])
|
||||
self._popupMenu.add_checkbutton(label = 'Angle snap',
|
||||
variable = self._fAngleSnap,
|
||||
command = self.setAngleSnap)
|
||||
self._fRollover = IntVar()
|
||||
self._fRollover.set(self['fRollover'])
|
||||
self._popupMenu.add_checkbutton(label = 'Rollover',
|
||||
variable = self._fRollover,
|
||||
command = self.setRollover)
|
||||
|
||||
sfMenu = Menu(interior, tearoff = 1)
|
||||
self.expVar = DoubleVar()
|
||||
self.expVar.set(0)
|
||||
for exp in range (MAX_EXP, -(MAX_EXP + 1), -1):
|
||||
sf = "%g" % math.pow(10, exp)
|
||||
sfMenu.add_radiobutton(label = sf, value = exp,
|
||||
variable = self.expVar,
|
||||
command = self.setScaleFactor)
|
||||
sfMenu.add_command(label = 'Scale Factor...',
|
||||
command = self.getScaleFactor)
|
||||
self._popupMenu.add_cascade(label = 'Scale Factor',
|
||||
menu = sfMenu)
|
||||
self._popupMenu.add_command(label = 'Reset Dial',
|
||||
command = self.reset)
|
||||
|
||||
# Add event bindings
|
||||
self._canvas.tag_bind('ring', '<Enter>', self.highlightRing)
|
||||
self._canvas.tag_bind('ring', '<Leave>', self.restoreRing)
|
||||
self._canvas.tag_bind('ring', '<ButtonPress-1>', self.ringMouseDown)
|
||||
self._canvas.tag_bind('ring', '<B1-Motion>', self.ringMouseMotion)
|
||||
self._canvas.tag_bind('ring', '<ButtonRelease-1>', self.ringMouseUp)
|
||||
self._canvas.tag_bind('dial', '<ButtonPress-1>', self.mouseDown)
|
||||
self._canvas.tag_bind('dial', '<B1-Motion>', self.mouseMotion)
|
||||
self._canvas.tag_bind('dial', '<Shift-B1-Motion>', self.shiftMouseMotion)
|
||||
self._canvas.tag_bind('dial', '<ButtonRelease-1>', self.mouseUp)
|
||||
self._canvas.tag_bind('sfMarker', '<Enter>', self.highlightSFMarker)
|
||||
self._canvas.tag_bind('sfMarker', '<Leave>', self.restoreSFMarker)
|
||||
self._canvas.tag_bind('velocityKnob', '<Enter>', self.highlightKnob)
|
||||
self._canvas.tag_bind('velocityKnob', '<Leave>', self.restoreKnob)
|
||||
self._canvas.tag_bind('sfMarker', '<ButtonPress-1>', self.sfMouseDown)
|
||||
self._canvas.tag_bind('sfMarker', '<B1-Motion>', self.sfMouseMotion)
|
||||
self._canvas.tag_bind('sfMarker', '<ButtonRelease-1>', self.sfMouseUp)
|
||||
self._canvas.tag_bind('velocityKnob', '<ButtonPress-1>', self.knobMouseDown)
|
||||
self._canvas.tag_bind('velocityKnob', '<B1-Motion>', self.knobMouseMotion)
|
||||
self._canvas.tag_bind('velocityKnob', '<ButtonRelease-1>', self.knobMouseUp)
|
||||
self._canvas.bind('<ButtonPress-3>', self.popupDialMenu)
|
||||
self._canvas.bind('<Double-ButtonPress-1>', self.mouseReset)
|
||||
self._canvas.bind('<Up>', self.expUp)
|
||||
self._canvas.bind('<Down>', self.expDown)
|
||||
|
||||
# Make sure input variables processed
|
||||
self.initialiseoptions(Dial)
|
||||
|
||||
def updateLabel(self):
|
||||
self._label['text'] = self['text']
|
||||
|
||||
def createTicks(self):
|
||||
self._canvas.delete('ticks')
|
||||
# Based upon input snap angle, how many ticks
|
||||
numTicks = self['numTicks']
|
||||
# Compute snapAngle (radians)
|
||||
self.snapAngle = snapAngle = TWO_PI / numTicks
|
||||
# Create the ticks at the snap angles
|
||||
for ticknum in range(numTicks):
|
||||
angle = snapAngle * ticknum
|
||||
# convert to canvas coords
|
||||
angle = angle - POINTFIVE_PI
|
||||
# Compute tick endpoints
|
||||
startx = math.cos(angle) * self.radius
|
||||
starty = math.sin(angle) * self.radius
|
||||
# Elongate ticks at 90 degree points
|
||||
if (angle % POINTFIVE_PI) == 0.0:
|
||||
sf = 0.6
|
||||
else:
|
||||
sf = 0.8
|
||||
endx = startx * sf
|
||||
endy = starty * sf
|
||||
self._canvas.create_line(startx, starty, endx, endy,
|
||||
tags = ('ticks','dial'))
|
||||
|
||||
def mouseDown(self,event):
|
||||
apply(self.onPress, self['callbackData'])
|
||||
self.lastAngle = dialAngle = self.computeDialAngle(event)
|
||||
self.computeValueFromAngle(dialAngle)
|
||||
|
||||
def mouseUp(self,event):
|
||||
apply(self.onRelease, self['callbackData'])
|
||||
|
||||
def shiftMouseMotion(self,event):
|
||||
self.mouseMotion(event, 1)
|
||||
|
||||
def mouseMotion(self, event, fShift = 0):
|
||||
dialAngle = self.computeDialAngle(event, fShift)
|
||||
self.computeValueFromAngle(dialAngle)
|
||||
|
||||
def computeDialAngle(self,event, fShift = 0):
|
||||
x = self._canvas.canvasx(event.x)
|
||||
y = self._canvas.canvasy(event.y)
|
||||
rawAngle = math.atan2(y,x)
|
||||
# Snap to grid
|
||||
# Convert to dial coords to do snapping
|
||||
dialAngle = rawAngle + POINTFIVE_PI
|
||||
if operator.xor(self['fSnap'], fShift):
|
||||
dialAngle = round(dialAngle / self.snapAngle) * self.snapAngle
|
||||
return dialAngle
|
||||
|
||||
def computeValueFromAngle(self, dialAngle):
|
||||
delta = self.delta
|
||||
dialAngle = dialAngle % TWO_PI
|
||||
# Check for rollover, if necessary
|
||||
if (self.lastAngle > ONEPOINTFIVE_PI) and (dialAngle < POINTFIVE_PI):
|
||||
self.baseVal = self.baseVal + delta
|
||||
elif (self.lastAngle < POINTFIVE_PI) and (dialAngle > ONEPOINTFIVE_PI):
|
||||
self.baseVal = self.baseVal - delta
|
||||
self.lastAngle = dialAngle
|
||||
# Update value and entry
|
||||
newValue = self['min'] + self.baseVal + delta * (dialAngle / TWO_PI)
|
||||
self.dialAngle = dialAngle
|
||||
self.set(newValue)
|
||||
|
||||
def get(self):
|
||||
return self.value
|
||||
|
||||
def set(self, value, fCommand = 1):
|
||||
if not self['fRollover']:
|
||||
if value > self['max']:
|
||||
self.baseVal = 0.0
|
||||
value = ((value - self['min']) %
|
||||
(self['max'] - self['min'])) + self['min']
|
||||
self.updateEntry(value)
|
||||
if self.dialAngle:
|
||||
self.updateIndicatorRadians(self.dialAngle)
|
||||
self.dialAngle = None
|
||||
else:
|
||||
self.updateIndicator(value)
|
||||
# Pass fCommand to dial which will return it to self.setEntry
|
||||
self._dial['commandData'] = [fCommand]
|
||||
self._dial.set(value)
|
||||
|
||||
def get(self):
|
||||
return self._dial.get()
|
||||
|
||||
def setEntry(self, value, fCommand = 1):
|
||||
self._entryVal.set(self.entryFormat % value)
|
||||
# Execute command
|
||||
if fCommand and (self['command'] != None):
|
||||
apply(self['command'], [value] + self['commandData'])
|
||||
|
||||
def updateIndicator(self, value):
|
||||
# compute new indicator angle
|
||||
delta = self.delta
|
||||
factors = divmod(value - self['min'], delta)
|
||||
self.baseVal = factors[0] * delta
|
||||
self.updateIndicatorRadians( (factors[1]/delta) * TWO_PI )
|
||||
|
||||
def updateIndicatorDegrees(self, degAngle):
|
||||
self.updateIndicatorRadians(degAngle * (math.pi/180.0))
|
||||
|
||||
def updateIndicatorRadians(self,dialAngle):
|
||||
rawAngle = dialAngle - POINTFIVE_PI
|
||||
# Compute end points
|
||||
endx = math.cos(rawAngle) * self.radius
|
||||
endy = math.sin(rawAngle) * self.radius
|
||||
# Draw new indicator
|
||||
self._canvas.coords('indicator', endx * INNER_SF, endy * INNER_SF,
|
||||
endx, endy)
|
||||
|
||||
def updateEntry(self, value):
|
||||
self._entryVal.set(self.entryFormat % value)
|
||||
|
||||
def updateEntryFormat(self):
|
||||
def setEntryFormat(self):
|
||||
self.entryFormat = "%." + "%df" % self['numDigits']
|
||||
self.updateEntry(self.value)
|
||||
self.setEntry(self.get())
|
||||
|
||||
def validateEntryInput(self, event):
|
||||
input = self._entryVal.get()
|
||||
try:
|
||||
self._onReturnPress()
|
||||
self._entry.configure(background = self._entryBackground)
|
||||
newValue = string.atof(input)
|
||||
apply(self.onReturn, self['callbackData'])
|
||||
self.set(newValue)
|
||||
apply(self.onReturnRelease, self['callbackData'])
|
||||
self._onReturnRelease()
|
||||
except ValueError:
|
||||
self._entry.configure(background = 'Pink')
|
||||
|
||||
def sfMouseDown(self, event):
|
||||
# Record marker starting position
|
||||
self.starty = self.sfy
|
||||
# Record mouse starting position (convert to canvas coords)
|
||||
self.lasty = self._canvas.canvasy(event.y)
|
||||
|
||||
def sfMouseMotion(self, event):
|
||||
# How far did the mouse move?
|
||||
dy = self._canvas.canvasy(event.y) - self.lasty
|
||||
# Apply this delta to the marker
|
||||
newy = self.starty + dy
|
||||
# Compute new exponent based upon current position
|
||||
exp = self.sfComputeExp(newy)
|
||||
# Set resulting scale factor
|
||||
self.setScaleFactorExp(exp)
|
||||
|
||||
def sfMouseUp(self, event):
|
||||
self._canvas.delete('sfText')
|
||||
|
||||
# Compute exponent based on current marker position
|
||||
def sfComputeExp(self, y, fSnap = 1):
|
||||
# Force marker to stay visible
|
||||
newy = max( -self.half, min( self.half, y ) )
|
||||
# Snap it
|
||||
gridDelta = self.sfGridDelta
|
||||
if fSnap:
|
||||
newy = round( newy / gridDelta ) * gridDelta
|
||||
# Compute resulting exponent
|
||||
return (-(newy / gridDelta))
|
||||
|
||||
def setScaleFactorExp(self, exp, showText = 1, fUpdateIndicator = 1):
|
||||
self.exp = exp
|
||||
# Update popup scale factor menu to nearest exponent
|
||||
self.expVar.set(int(round(exp)))
|
||||
# Compute new scale factor
|
||||
self.scaleFactor = math.pow(10, exp)
|
||||
# Compute resulting delta
|
||||
self.delta = self.scaleFactor * (self['max'] - self['min'])
|
||||
# Update indicator to reflect new scale factor
|
||||
if fUpdateIndicator:
|
||||
self.updateIndicator(self.value)
|
||||
# Move marker to correct position
|
||||
self.updateScaleFactorMarker(-exp*self.sfGridDelta, showText)
|
||||
|
||||
def expUp(self,event):
|
||||
self.setScaleFactorExp(min(MAX_EXP, self.exp + 1), 0)
|
||||
|
||||
def expDown(self,event):
|
||||
self.setScaleFactorExp(max(-MAX_EXP, self.exp - 1), 0)
|
||||
|
||||
def ringMouseDown(self,event):
|
||||
apply(self.onPress, self['callbackData'])
|
||||
self.startRingAngle = self.computeRingAngle(event)
|
||||
self.deltaRingAngle = 0.0
|
||||
self.velocityTask = self.after(100, self.ringComputeVelocity)
|
||||
|
||||
def ringMouseMotion(self, event):
|
||||
# What is the current ring angle
|
||||
ringAngle = self.computeRingAngle(event)
|
||||
self.deltaRingAngle = ringAngle - self.startRingAngle
|
||||
|
||||
def ringComputeVelocity(self):
|
||||
# Compute new exponent based upon current ring position
|
||||
exp = self.deltaRingAngle/POINTFIVE_PI
|
||||
# Set resulting scale factor
|
||||
self.setScaleFactorExp(exp, fUpdateIndicator = 1)
|
||||
# Update value and entry
|
||||
delta = self.delta
|
||||
self.value = newValue = self.value + delta * self.deltaRingAngle
|
||||
self.set(newValue)
|
||||
self.updateIndicator(self.value)
|
||||
self.velocityTask = self.after(100, self.ringComputeVelocity)
|
||||
|
||||
def computeRingAngle(self, event):
|
||||
x = self._canvas.canvasx(event.x)
|
||||
y = self._canvas.canvasy(event.y)
|
||||
rawAngle = math.atan2(y,x)
|
||||
# Convert to dial coords
|
||||
dialAngle = rawAngle + TWO_PI
|
||||
return dialAngle
|
||||
|
||||
def ringMouseUp(self, event):
|
||||
self.after_cancel(self.velocityTask)
|
||||
# reset indicator
|
||||
self.updateIndicator(self.value)
|
||||
apply(self.onRelease, self['callbackData'])
|
||||
|
||||
def knobMouseDown(self,event):
|
||||
apply(self.onPress, self['callbackData'])
|
||||
self.lasty = self._canvas.canvasy(event.y)
|
||||
self.updateIndicatorRadians(0.0)
|
||||
self.velocityTask = self.after(100, self.computeVelocity)
|
||||
|
||||
def knobMouseMotion(self, event):
|
||||
# How far is the mouse from the origin?
|
||||
dx = self._canvas.canvasx(event.x)
|
||||
self.lasty = self._canvas.canvasy(event.y)
|
||||
exp = -5 + dx/20.0
|
||||
exp = max( -5, min( 5, exp ) )
|
||||
# Set resulting scale factor
|
||||
self.setScaleFactorExp(exp, 0, fUpdateIndicator = 0)
|
||||
|
||||
def knobMouseUp(self, event):
|
||||
self.after_cancel(self.velocityTask)
|
||||
# reset indicator
|
||||
self.updateIndicator(self.value)
|
||||
apply(self.onRelease, self['callbackData'])
|
||||
|
||||
def computeVelocity(self):
|
||||
if self.lasty < 0:
|
||||
sign = -1.0
|
||||
else:
|
||||
sign = 1.0
|
||||
lasty = abs(self.lasty)
|
||||
if lasty > 5:
|
||||
lasty = lasty - 5
|
||||
sf = min(100, lasty)/100.0
|
||||
sf = pow(sf, 3.0)
|
||||
newVal = self.value - sign * sf * self.delta
|
||||
self.dialAngle = - sign * sf * POINTFIVE_PI
|
||||
self.set(newVal)
|
||||
self.velocityTask = self.after(100, self.computeVelocity)
|
||||
|
||||
def updateScaleFactorMarker(self, newy, showText = 1):
|
||||
# Move marker
|
||||
self._canvas.move('sfMarker', 0, newy - self.sfy)
|
||||
self.sfy = newy
|
||||
|
||||
# Show current scaling factor
|
||||
if showText:
|
||||
sfText = '%g' % (self.delta / 10.0,)
|
||||
self._canvas.delete('sfText')
|
||||
self._canvas.create_rectangle( self.half - 40, newy - 6,
|
||||
self.half, newy + 7,
|
||||
fill = 'white',
|
||||
tags = ('sfText',))
|
||||
self._canvas.create_text( self.half, newy,
|
||||
justify = RIGHT,
|
||||
anchor = E,
|
||||
text = sfText,
|
||||
fill = 'Red',
|
||||
tags = ('sfText',))
|
||||
|
||||
# The following routines are used to handle the popup menu
|
||||
def popupDialMenu(self,event):
|
||||
self._popupMenu.post(event.widget.winfo_pointerx(),
|
||||
event.widget.winfo_pointery())
|
||||
|
||||
# This is called by the scale factor popup menu and when the user
|
||||
# changes the dial 'delta' value
|
||||
def setScaleFactor(self):
|
||||
exp = self.expVar.get()
|
||||
self.setScaleFactorExp(exp, showText = 0)
|
||||
|
||||
# This handles the popup scale factor dialog
|
||||
def getScaleFactor(self):
|
||||
sf = askfloat('Dial Scale Factor', 'Scale Factor:',
|
||||
parent = self.interior())
|
||||
if sf:
|
||||
self.setScaleFactorExp(math.log10(sf), showText = 0)
|
||||
|
||||
# Turn angle snap on/off
|
||||
def setAngleSnap(self):
|
||||
self['fSnap'] = self._fAngleSnap.get()
|
||||
|
||||
# Turn rollover (accumulation of a sum) on/off
|
||||
def setRollover(self):
|
||||
self['fRollover'] = self._fRollover.get()
|
||||
|
||||
def highlightSFMarker(self, event):
|
||||
self._canvas.itemconfigure('sfMarker', fill = '#252525')
|
||||
|
||||
def restoreSFMarker(self, event):
|
||||
self._canvas.itemconfigure('sfMarker', fill = '#A0A0A0')
|
||||
|
||||
def highlightRing(self, event):
|
||||
self._canvas.itemconfigure('ring', fill = '#A0A0A0')
|
||||
|
||||
def restoreRing(self, event):
|
||||
self._canvas.itemconfigure('ring', fill = 'white')
|
||||
|
||||
def highlightKnob(self, event):
|
||||
self._canvas.itemconfigure('velocityKnob', fill = '#252525')
|
||||
|
||||
def restoreKnob(self, event):
|
||||
self._canvas.itemconfigure('velocityKnob', fill = '#A0A0A0')
|
||||
|
||||
# Reset dial to zero
|
||||
def mouseReset(self,event):
|
||||
if not self._canvas.find_withtag(CURRENT):
|
||||
self.reset()
|
||||
|
||||
def reset(self):
|
||||
self.set(self['initialValue'])
|
||||
# Should we do this?
|
||||
self.setScaleFactorExp(0, showText = 0)
|
||||
|
||||
def onReturn(self, *args):
|
||||
def _onReturnPress(self, *args):
|
||||
""" User redefinable callback executed on <Return> in entry """
|
||||
pass
|
||||
if self['onReturnPress']:
|
||||
apply(self['onReturnPress'], self['callbackData'])
|
||||
|
||||
def onReturnRelease(self, *args):
|
||||
def _onReturnRelease(self, *args):
|
||||
""" User redefinable callback executed on <Return> release in entry """
|
||||
pass
|
||||
if self['onReturnRelease']:
|
||||
apply(self['onReturnRelease'], self['callbackData'])
|
||||
|
||||
def onPress(self, *args):
|
||||
""" User redefinable callback executed on button press """
|
||||
pass
|
||||
# Pass settings down to dial
|
||||
def setCallbackData(self):
|
||||
# Pass callback data down to dial
|
||||
self._dial['callbackData'] = self['callbackData']
|
||||
|
||||
def onRelease(self, *args):
|
||||
""" User redefinable callback executed on button release """
|
||||
pass
|
||||
def setResetValue(self):
|
||||
self._dial['resetValue'] = self['resetValue']
|
||||
|
||||
def setMin(self):
|
||||
self._dial['min'] = self['min']
|
||||
|
||||
def setMax(self):
|
||||
self._dial['max'] = self['max']
|
||||
|
||||
def setLabel(self):
|
||||
self._label['text'] = self['text']
|
||||
|
||||
def setButtonPressCmd(self):
|
||||
self._dial['onButtonPress'] = self['onButtonPress']
|
||||
|
||||
def setButtonReleaseCmd(self):
|
||||
self._dial['onButtonRelease'] = self['onButtonRelease']
|
||||
|
||||
class AngleDial(Dial):
|
||||
def __init__(self, parent = None, **kw):
|
||||
# Set the typical defaults for a 360 degree angle dial
|
||||
optiondefs = (
|
||||
('fRollover', 0, None),
|
||||
('numTicks', 12, None),
|
||||
('max', 360.0, None),
|
||||
('max', 360.0, None),
|
||||
('dial_fRollover', 0, None),
|
||||
('dial_numSegments', 12, None),
|
||||
)
|
||||
self.defineoptions(kw, optiondefs)
|
||||
# Initialize the superclass
|
||||
|
|
@ -539,7 +164,7 @@ class MiniDial(Pmw.MegaWidget):
|
|||
optiondefs = (
|
||||
## Appearance
|
||||
# Edge size of the dial
|
||||
('size', 50, INITOPT),
|
||||
('size', 40, INITOPT),
|
||||
# Widget relief
|
||||
('relief', GROOVE, self.setRelief),
|
||||
# Widget borderwidth
|
||||
|
|
@ -566,6 +191,8 @@ class MiniDial(Pmw.MegaWidget):
|
|||
('commandData', [], None),
|
||||
# Extra data to be passed to callback function
|
||||
('callbackData', [], None),
|
||||
('onButtonPress', None, None),
|
||||
('onButtonRelease', None, None),
|
||||
)
|
||||
self.defineoptions(kw, optiondefs)
|
||||
|
||||
|
|
@ -693,12 +320,12 @@ class MiniDial(Pmw.MegaWidget):
|
|||
## Canvas callback functions
|
||||
# Dial
|
||||
def mouseDown(self,event):
|
||||
apply(self.onPress, self['callbackData'])
|
||||
self._onButtonPress()
|
||||
self.lastAngle = dialAngle = self.computeDialAngle(event)
|
||||
self.computeValueFromAngle(dialAngle)
|
||||
|
||||
def mouseUp(self,event):
|
||||
apply(self.onRelease, self['callbackData'])
|
||||
self._onButtonRelease()
|
||||
|
||||
def shiftMouseMotion(self,event):
|
||||
self.mouseMotion(event, 1)
|
||||
|
|
@ -753,7 +380,7 @@ class MiniDial(Pmw.MegaWidget):
|
|||
|
||||
# Knob velocity controller
|
||||
def knobMouseDown(self,event):
|
||||
apply(self.onPress, self['callbackData'])
|
||||
self._onButtonPress()
|
||||
self.knobSF = 0.0
|
||||
t = taskMgr.spawnMethodNamed(self.knobComputeVelocity, 'cv')
|
||||
t.lastTime = globalClock.getFrameTime()
|
||||
|
|
@ -782,7 +409,7 @@ class MiniDial(Pmw.MegaWidget):
|
|||
def knobMouseUp(self, event):
|
||||
taskMgr.removeTasksNamed('cv')
|
||||
self.knobSF = 0.0
|
||||
apply(self.onRelease, self['callbackData'])
|
||||
self._onButtonRelease()
|
||||
|
||||
def highlightKnob(self, event):
|
||||
self._canvas.itemconfigure('knob', fill = 'black')
|
||||
|
|
@ -864,13 +491,15 @@ class MiniDial(Pmw.MegaWidget):
|
|||
self['resetValue'] = newResetValue
|
||||
|
||||
# User callbacks
|
||||
def onPress(self, *args):
|
||||
def _onButtonPress(self, *args):
|
||||
""" User redefinable callback executed on button press """
|
||||
pass
|
||||
if self['onButtonPress']:
|
||||
apply(self['onButtonPress'], self['callbackData'])
|
||||
|
||||
def onRelease(self, *args):
|
||||
def _onButtonRelease(self, *args):
|
||||
""" User redefinable callback executed on button release """
|
||||
pass
|
||||
if self['onButtonRelease']:
|
||||
apply(self['onButtonRelease'], self['callbackData'])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
|||
Loading…
Reference in New Issue