*** empty log message ***
This commit is contained in:
parent
f2bd33cd7c
commit
c6178a4d81
|
|
@ -12,7 +12,7 @@ from ClusterServer import *
|
|||
from ClusterConfig import *
|
||||
from tkSimpleDialog import askstring
|
||||
import Placer
|
||||
import EntryScale
|
||||
import Slider
|
||||
import SceneGraphExplorer
|
||||
import OnscreenText
|
||||
import types
|
||||
|
|
@ -149,7 +149,7 @@ class DirectSession(PandaObject):
|
|||
['SGE_Show All', self.showAllDescendants],
|
||||
['SGE_Fit', self.fitOnNodePath],
|
||||
['SGE_Place', Placer.place],
|
||||
['SGE_Set Color', EntryScale.rgbPanel],
|
||||
['SGE_Set Color', Slider.rgbPanel],
|
||||
['SGE_Explore', SceneGraphExplorer.explore],
|
||||
['SGE_Delete', self.removeNodePath],
|
||||
['SGE_Set Name', self.getAndSetName],
|
||||
|
|
|
|||
|
|
@ -803,8 +803,8 @@
|
|||
base.wantTk = 1
|
||||
base.wantDIRECT = 1
|
||||
import TkGlobal
|
||||
import EntryScale
|
||||
return EntryScale.rgbPanel(self, cb)
|
||||
import Slider
|
||||
return Slider.rgbPanel(self, cb)
|
||||
|
||||
def select(self):
|
||||
base.wantTk = 1
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ from tkFileDialog import *
|
|||
from whrandom import *
|
||||
import Pmw
|
||||
import Floater
|
||||
import EntryScale
|
||||
import VectorWidgets
|
||||
import string
|
||||
import os
|
||||
|
|
|
|||
|
|
@ -276,7 +276,7 @@ def adjust(command = None, parent = None, **kw):
|
|||
adjust(command = None, parent = None, **kw)
|
||||
Popup and entry scale to adjust a parameter
|
||||
|
||||
Accepts any EntryScale keyword argument. Typical arguments include:
|
||||
Accepts any Slider keyword argument. Typical arguments include:
|
||||
command: The one argument command to execute
|
||||
min: The min value of the slider
|
||||
max: The max value of the slider
|
||||
|
|
@ -294,7 +294,7 @@ def adjust(command = None, parent = None, **kw):
|
|||
# Make sure we enable Tk
|
||||
import TkGlobal
|
||||
import Tkinter
|
||||
import EntryScale
|
||||
import Slider
|
||||
import Pmw
|
||||
# Create toplevel if needed
|
||||
if not parent:
|
||||
|
|
@ -303,7 +303,7 @@ def adjust(command = None, parent = None, **kw):
|
|||
# Set command if specified
|
||||
if command:
|
||||
kw['command'] = command
|
||||
es = apply(EntryScale.EntryScale, (parent,), kw)
|
||||
es = apply(Slider.Slider, (parent,), kw)
|
||||
es.pack(expand = 1, fill = 'x')
|
||||
es.parent = parent
|
||||
return es
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import string
|
|||
import Pmw
|
||||
import Dial
|
||||
import Floater
|
||||
import EntryScale
|
||||
import Slider
|
||||
import VectorWidgets
|
||||
import SceneGraphExplorer
|
||||
from TaskManagerPanel import TaskManagerWidget
|
||||
|
|
@ -24,8 +24,8 @@ class DirectSessionPanel(AppShell):
|
|||
# Override class variables here
|
||||
appname = 'Direct Session Panel'
|
||||
frameWidth = 600
|
||||
frameHeight = 502
|
||||
usecommandarea = 1
|
||||
frameHeight = 365
|
||||
usecommandarea = 0
|
||||
usestatusarea = 0
|
||||
|
||||
def __init__(self, parent = None, **kw):
|
||||
|
|
@ -102,6 +102,17 @@ class DirectSessionPanel(AppShell):
|
|||
label = 'Enable Grid',
|
||||
variable = self.directGridEnabled,
|
||||
command = self.toggleDirectGrid)
|
||||
|
||||
self.menuBar.addmenuitem('DIRECT', 'command',
|
||||
'Toggle Object Handles Visability',
|
||||
label = 'Toggle Widget Viz',
|
||||
command = direct.toggleWidgetVis)
|
||||
|
||||
self.menuBar.addmenuitem(
|
||||
'DIRECT', 'command',
|
||||
'Toggle Widget Move/COA Mode',
|
||||
label = 'Toggle Widget Mode',
|
||||
command = direct.manipulationControl.toggleObjectHandlesMode)
|
||||
|
||||
# Get a handle to the menu frame
|
||||
menuFrame = self.menuFrame
|
||||
|
|
@ -150,7 +161,7 @@ class DirectSessionPanel(AppShell):
|
|||
self.SGE = SceneGraphExplorer.SceneGraphExplorer(
|
||||
sgeFrame, nodePath = render,
|
||||
scrolledCanvas_hull_width = 250,
|
||||
scrolledCanvas_hull_height = 400)
|
||||
scrolledCanvas_hull_height = 300)
|
||||
self.SGE.pack(fill = BOTH, expand = 0)
|
||||
sgeFrame.pack(side = LEFT, fill = 'both', expand = 0)
|
||||
|
||||
|
|
@ -212,7 +223,7 @@ class DirectSessionPanel(AppShell):
|
|||
|
||||
fovFrame = Frame(drFrame)
|
||||
fovFloaterFrame = Frame(fovFrame)
|
||||
self.hFov = EntryScale.EntryScale(
|
||||
self.hFov = Slider.Slider(
|
||||
fovFloaterFrame,
|
||||
text = 'Horizontal FOV',
|
||||
min = 0.01, max = 170.0)
|
||||
|
|
@ -220,7 +231,7 @@ class DirectSessionPanel(AppShell):
|
|||
self.hFov.pack(fill = X, expand = 0)
|
||||
self.bind(self.hFov, 'Set horizontal field of view')
|
||||
|
||||
self.vFov = EntryScale.EntryScale(
|
||||
self.vFov = Slider.Slider(
|
||||
fovFloaterFrame,
|
||||
text = 'Vertical FOV',
|
||||
min = 0.01, max = 170.0)
|
||||
|
|
@ -366,7 +377,7 @@ class DirectSessionPanel(AppShell):
|
|||
self.bind(self.pSpecularColor,
|
||||
'Set point light specular color')
|
||||
|
||||
self.pConstantAttenuation = EntryScale.EntryScale(
|
||||
self.pConstantAttenuation = Slider.Slider(
|
||||
pointPage,
|
||||
text = 'Constant Attenuation',
|
||||
min = 0.0, max = 1.0, value = 1.0)
|
||||
|
|
@ -375,7 +386,7 @@ class DirectSessionPanel(AppShell):
|
|||
self.bind(self.pConstantAttenuation,
|
||||
'Set point light constant attenuation')
|
||||
|
||||
self.pLinearAttenuation = EntryScale.EntryScale(
|
||||
self.pLinearAttenuation = Slider.Slider(
|
||||
pointPage,
|
||||
text = 'Linear Attenuation',
|
||||
min = 0.0, max = 1.0, value = 0.0)
|
||||
|
|
@ -384,7 +395,7 @@ class DirectSessionPanel(AppShell):
|
|||
self.bind(self.pLinearAttenuation,
|
||||
'Set point light linear attenuation')
|
||||
|
||||
self.pQuadraticAttenuation = EntryScale.EntryScale(
|
||||
self.pQuadraticAttenuation = Slider.Slider(
|
||||
pointPage,
|
||||
text = 'Quadratic Attenuation',
|
||||
min = 0.0, max = 1.0, value = 0.0)
|
||||
|
|
@ -401,7 +412,7 @@ class DirectSessionPanel(AppShell):
|
|||
self.bind(self.sSpecularColor,
|
||||
'Set spot light specular color')
|
||||
|
||||
self.sConstantAttenuation = EntryScale.EntryScale(
|
||||
self.sConstantAttenuation = Slider.Slider(
|
||||
spotPage,
|
||||
text = 'Constant Attenuation',
|
||||
min = 0.0, max = 1.0, value = 1.0)
|
||||
|
|
@ -410,7 +421,7 @@ class DirectSessionPanel(AppShell):
|
|||
self.bind(self.sConstantAttenuation,
|
||||
'Set spot light constant attenuation')
|
||||
|
||||
self.sLinearAttenuation = EntryScale.EntryScale(
|
||||
self.sLinearAttenuation = Slider.Slider(
|
||||
spotPage,
|
||||
text = 'Linear Attenuation',
|
||||
min = 0.0, max = 1.0, value = 0.0)
|
||||
|
|
@ -419,7 +430,7 @@ class DirectSessionPanel(AppShell):
|
|||
self.bind(self.sLinearAttenuation,
|
||||
'Set spot light linear attenuation')
|
||||
|
||||
self.sQuadraticAttenuation = EntryScale.EntryScale(
|
||||
self.sQuadraticAttenuation = Slider.Slider(
|
||||
spotPage,
|
||||
text = 'Quadratic Attenuation',
|
||||
min = 0.0, max = 1.0, value = 0.0)
|
||||
|
|
@ -428,7 +439,7 @@ class DirectSessionPanel(AppShell):
|
|||
self.bind(self.sQuadraticAttenuation,
|
||||
'Set spot light quadratic attenuation')
|
||||
|
||||
self.sExponent = EntryScale.EntryScale(
|
||||
self.sExponent = Slider.Slider(
|
||||
spotPage,
|
||||
text = 'Exponent',
|
||||
min = 0.0, max = 1.0, value = 0.0)
|
||||
|
|
@ -493,7 +504,7 @@ class DirectSessionPanel(AppShell):
|
|||
self.gridSnapAngle = Dial.AngleDial(
|
||||
gridPage,
|
||||
text = 'Snap Angle',
|
||||
style = Dial.DIAL_MINI,
|
||||
style = 'mini',
|
||||
value = direct.grid.getSnapAngle())
|
||||
self.gridSnapAngle['command'] = direct.grid.setSnapAngle
|
||||
self.gridSnapAngle.pack(fill = X, expand = 0)
|
||||
|
|
@ -542,7 +553,7 @@ class DirectSessionPanel(AppShell):
|
|||
self.bind(self.jbNodePathMenu,
|
||||
'Select node path to manipulate using the joybox')
|
||||
|
||||
self.jbXyzSF = EntryScale.EntryScale(
|
||||
self.jbXyzSF = Slider.Slider(
|
||||
joyboxFrame,
|
||||
text = 'XYZ Scale Factor',
|
||||
value = 1.0,
|
||||
|
|
@ -553,7 +564,7 @@ class DirectSessionPanel(AppShell):
|
|||
self.jbXyzSF.pack(fill = X, expand = 0)
|
||||
self.bind(self.jbXyzSF, 'Set joybox XYZ speed multiplier')
|
||||
|
||||
self.jbHprSF = EntryScale.EntryScale(
|
||||
self.jbHprSF = Slider.Slider(
|
||||
joyboxFrame,
|
||||
text = 'HPR Scale Factor',
|
||||
value = 1.0,
|
||||
|
|
@ -568,31 +579,13 @@ class DirectSessionPanel(AppShell):
|
|||
Label(tasksPage, text = 'TASKS',
|
||||
font=('MSSansSerif', 14, 'bold')).pack(expand = 0)
|
||||
self.taskMgrPanel = TaskManagerWidget(tasksPage, taskMgr)
|
||||
self.taskMgrPanel.taskListBox['listbox_height'] = 10
|
||||
|
||||
notebook.setnaturalsize()
|
||||
|
||||
framePane.pack(expand = 1, fill = BOTH)
|
||||
mainFrame.pack(fill = 'both', expand = 1)
|
||||
|
||||
# Create some buttons in the bottom tray
|
||||
self.createButtons()
|
||||
|
||||
def createButtons(self):
|
||||
# Grid: enable/disable, xyz/hpr snap, snap to plane
|
||||
# Render mode: wireframe, lights, texture
|
||||
self.buttonAdd('Toggle Widget Viz',
|
||||
helpMessage='Toggle Object Handles Visability',
|
||||
statusMessage='Toggle Object Handles Visability',
|
||||
command=direct.toggleWidgetVis)
|
||||
self.buttonAdd(
|
||||
'Toggle Widget Mode',
|
||||
helpMessage='Toggle Widget Move/COA Mode',
|
||||
statusMessage='Toggle Widget Move/COA Mode',
|
||||
command=direct.manipulationControl.toggleObjectHandlesMode)
|
||||
|
||||
# Make all buttons as wide as widest
|
||||
self.alignbuttons()
|
||||
|
||||
def toggleDirect(self):
|
||||
if self.directEnabled.get():
|
||||
direct.enable()
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import string
|
|||
import Pmw
|
||||
import Dial
|
||||
import Floater
|
||||
import Slider
|
||||
import EntryScale
|
||||
import VectorWidgets
|
||||
import __builtin__
|
||||
|
|
@ -365,7 +366,7 @@ class MopathRecorder(AppShell, PandaObject):
|
|||
self.resamplePage, relief = SUNKEN, borderwidth = 2)
|
||||
label = Label(resampleFrame, text = 'RESAMPLE CURVE',
|
||||
font=('MSSansSerif', 12, 'bold')).pack()
|
||||
widget = self.createEntryScale(
|
||||
widget = self.createSlider(
|
||||
resampleFrame, 'Resample', 'Num. Samples',
|
||||
'Number of samples in resampled curve',
|
||||
resolution = 1, min = 2, max = 1000, command = self.setNumSamples)
|
||||
|
|
@ -389,7 +390,7 @@ class MopathRecorder(AppShell, PandaObject):
|
|||
self.resamplePage, relief = SUNKEN, borderwidth = 2)
|
||||
Label(desampleFrame, text = 'DESAMPLE CURVE',
|
||||
font=('MSSansSerif', 12, 'bold')).pack()
|
||||
widget = self.createEntryScale(
|
||||
widget = self.createSlider(
|
||||
desampleFrame, 'Resample', 'Points Between Samples',
|
||||
'Specify number of points to skip between samples',
|
||||
min = 1, max = 100, resolution = 1,
|
||||
|
|
@ -405,28 +406,28 @@ class MopathRecorder(AppShell, PandaObject):
|
|||
font=('MSSansSerif', 12, 'bold'))
|
||||
label.pack(fill = X)
|
||||
|
||||
widget = self.createEntryScale(refineFrame,
|
||||
widget = self.createSlider(refineFrame,
|
||||
'Refine Page', 'Refine From',
|
||||
'Begin time of refine pass',
|
||||
resolution = 0.01,
|
||||
command = self.setRecordStart)
|
||||
widget['preCallback'] = self.setRefineMode
|
||||
widget['postCallback'] = lambda s = self: s.getPrePoints('Refine')
|
||||
widget = self.createEntryScale(
|
||||
widget = self.createSlider(
|
||||
refineFrame, 'Refine Page',
|
||||
'Control Start',
|
||||
'Time when full control of node path is given during refine pass',
|
||||
resolution = 0.01,
|
||||
command = self.setControlStart)
|
||||
widget['preCallback'] = self.setRefineMode
|
||||
widget = self.createEntryScale(
|
||||
widget = self.createSlider(
|
||||
refineFrame, 'Refine Page',
|
||||
'Control Stop',
|
||||
'Time when node path begins transition back to original curve',
|
||||
resolution = 0.01,
|
||||
command = self.setControlStop)
|
||||
widget['preCallback'] = self.setRefineMode
|
||||
widget = self.createEntryScale(refineFrame, 'Refine Page', 'Refine To',
|
||||
widget = self.createSlider(refineFrame, 'Refine Page', 'Refine To',
|
||||
'Stop time of refine pass',
|
||||
resolution = 0.01,
|
||||
command = self.setRefineStop)
|
||||
|
|
@ -441,14 +442,14 @@ class MopathRecorder(AppShell, PandaObject):
|
|||
font=('MSSansSerif', 12, 'bold'))
|
||||
label.pack(fill = X)
|
||||
|
||||
widget = self.createEntryScale(extendFrame,
|
||||
widget = self.createSlider(extendFrame,
|
||||
'Extend Page', 'Extend From',
|
||||
'Begin time of extend pass',
|
||||
resolution = 0.01,
|
||||
command = self.setRecordStart)
|
||||
widget['preCallback'] = self.setExtendMode
|
||||
widget['postCallback'] = lambda s = self: s.getPrePoints('Extend')
|
||||
widget = self.createEntryScale(
|
||||
widget = self.createSlider(
|
||||
extendFrame, 'Extend Page',
|
||||
'Control Start',
|
||||
'Time when full control of node path is given during extend pass',
|
||||
|
|
@ -464,14 +465,14 @@ class MopathRecorder(AppShell, PandaObject):
|
|||
font=('MSSansSerif', 12, 'bold'))
|
||||
label.pack(fill = X)
|
||||
|
||||
widget = self.createEntryScale(
|
||||
widget = self.createSlider(
|
||||
cropFrame,
|
||||
'Crop Page', 'Crop From',
|
||||
'Delete all curve points before this time',
|
||||
resolution = 0.01,
|
||||
command = self.setCropFrom)
|
||||
|
||||
widget = self.createEntryScale(
|
||||
widget = self.createSlider(
|
||||
cropFrame,
|
||||
'Crop Page', 'Crop To',
|
||||
'Delete all curve points after this time',
|
||||
|
|
@ -523,21 +524,21 @@ class MopathRecorder(AppShell, PandaObject):
|
|||
side = LEFT, fill = X, expand = 1)
|
||||
frame.pack(fill = X, expand = 1)
|
||||
# Sliders
|
||||
widget = self.createEntryScale(
|
||||
widget = self.createSlider(
|
||||
sfFrame, 'Style', 'Num Segs',
|
||||
'Set number of segments used to approximate each parametric unit',
|
||||
min = 1.0, max = 400, resolution = 1.0,
|
||||
value = 40,
|
||||
command = self.setNumSegs, side = TOP)
|
||||
widget.component('hull')['relief'] = RIDGE
|
||||
widget = self.createEntryScale(
|
||||
widget = self.createSlider(
|
||||
sfFrame, 'Style', 'Num Ticks',
|
||||
'Set number of tick marks drawn for each unit of time',
|
||||
min = 0.0, max = 10.0, resolution = 1.0,
|
||||
value = 0.0,
|
||||
command = self.setNumTicks, side = TOP)
|
||||
widget.component('hull')['relief'] = RIDGE
|
||||
widget = self.createEntryScale(
|
||||
widget = self.createSlider(
|
||||
sfFrame, 'Style', 'Tick Scale',
|
||||
'Set visible size of time tick marks',
|
||||
min = 0.01, max = 100.0, resolution = 0.01,
|
||||
|
|
@ -1760,6 +1761,24 @@ class MopathRecorder(AppShell, PandaObject):
|
|||
self.widgetDict[category + '-' + text] = widget
|
||||
return widget
|
||||
|
||||
def createSlider(self, parent, category, text, balloonHelp,
|
||||
command = None, min = 0.0, max = 1.0,
|
||||
resolution = None,
|
||||
side = TOP, fill = X, expand = 1, **kw):
|
||||
kw['text'] = text
|
||||
kw['min'] = min
|
||||
kw['max'] = max
|
||||
kw['resolution'] = resolution
|
||||
#widget = apply(EntryScale.EntryScale, (parent,), kw)
|
||||
import Slider
|
||||
widget = apply(Slider.Slider, (parent,), kw)
|
||||
# Do this after the widget so command isn't called on creation
|
||||
widget['command'] = command
|
||||
widget.pack(side = side, fill = fill, expand = expand)
|
||||
self.bind(widget, balloonHelp)
|
||||
self.widgetDict[category + '-' + text] = widget
|
||||
return widget
|
||||
|
||||
def createEntryScale(self, parent, category, text, balloonHelp,
|
||||
command = None, min = 0.0, max = 1.0,
|
||||
resolution = None,
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import os
|
|||
import Pmw
|
||||
import Dial
|
||||
import Floater
|
||||
import EntryScale
|
||||
import Slider
|
||||
import VectorWidgets
|
||||
import Placer
|
||||
import ForceGroup
|
||||
|
|
@ -279,23 +279,23 @@ class ParticlePanel(AppShell):
|
|||
zSpinPage = self.factoryNotebook.add('ZSpinParticleFactory')
|
||||
self.createAngleDial(zSpinPage, 'Z Spin Factory', 'Initial Angle',
|
||||
'Starting angle in degrees',
|
||||
dial_fRollover = 1,
|
||||
fRollover = 1,
|
||||
command = self.setFactoryZSpinInitialAngle)
|
||||
self.createAngleDial(
|
||||
zSpinPage, 'Z Spin Factory',
|
||||
'Initial Angle Spread',
|
||||
'Spread of the initial angle',
|
||||
dial_fRollover = 1,
|
||||
fRollover = 1,
|
||||
command = self.setFactoryZSpinInitialAngleSpread)
|
||||
self.createAngleDial(zSpinPage, 'Z Spin Factory', 'Final Angle',
|
||||
'Final angle in degrees',
|
||||
dial_fRollover = 1,
|
||||
fRollover = 1,
|
||||
command = self.setFactoryZSpinFinalAngle)
|
||||
self.createAngleDial(
|
||||
zSpinPage, 'Z Spin Factory',
|
||||
'Final Angle Spread',
|
||||
'Spread of the final angle',
|
||||
dial_fRollover = 1,
|
||||
fRollover = 1,
|
||||
command = self.setFactoryZSpinFinalAngleSpread)
|
||||
# Oriented page #
|
||||
orientedPage = self.factoryNotebook.add('OrientedParticleFactory')
|
||||
|
|
@ -472,7 +472,7 @@ class ParticlePanel(AppShell):
|
|||
('NO_ALPHA','ALPHA_OUT','ALPHA_IN','ALPHA_USER'),
|
||||
self.setRendererAlphaMode)
|
||||
|
||||
self.createEntryScale(
|
||||
self.createSlider(
|
||||
rendererPage, 'Renderer', 'User Alpha',
|
||||
'alpha value for ALPHA_USER alpha mode',
|
||||
command = self.setRendererUserAlpha)
|
||||
|
|
@ -739,7 +739,7 @@ class ParticlePanel(AppShell):
|
|||
numDigits = 3, **kw):
|
||||
kw['text'] = text
|
||||
kw['min'] = min
|
||||
kw['floater_resolution'] = resolution
|
||||
kw['resolution'] = resolution
|
||||
kw['numDigits'] = numDigits
|
||||
widget = apply(Floater.Floater, (parent,), kw)
|
||||
# Do this after the widget so command isn't called on creation
|
||||
|
|
@ -752,7 +752,7 @@ class ParticlePanel(AppShell):
|
|||
def createAngleDial(self, parent, category, text, balloonHelp,
|
||||
command = None, **kw):
|
||||
kw['text'] = text
|
||||
kw['style'] = Dial.DIAL_MINI
|
||||
kw['style'] = 'mini'
|
||||
widget = apply(Dial.AngleDial,(parent,), kw)
|
||||
# Do this after the widget so command isn't called on creation
|
||||
widget['command'] = command
|
||||
|
|
@ -761,14 +761,14 @@ class ParticlePanel(AppShell):
|
|||
self.widgetDict[category + '-' + text] = widget
|
||||
return widget
|
||||
|
||||
def createEntryScale(self, parent, category, text, balloonHelp,
|
||||
command = None, min = 0.0, max = 1.0,
|
||||
resolution = 0.001, **kw):
|
||||
def createSlider(self, parent, category, text, balloonHelp,
|
||||
command = None, min = 0.0, max = 1.0,
|
||||
resolution = 0.001, **kw):
|
||||
kw['text'] = text
|
||||
kw['min'] = min
|
||||
kw['max'] = max
|
||||
kw['resolution'] = resolution
|
||||
widget = apply(EntryScale.EntryScale, (parent,), kw)
|
||||
widget = apply(Slider.Slider, (parent,), kw)
|
||||
# Do this after the widget so command isn't called on creation
|
||||
widget['command'] = command
|
||||
widget.pack(fill = X)
|
||||
|
|
|
|||
|
|
@ -233,7 +233,7 @@ class Placer(AppShell):
|
|||
# Create the dials
|
||||
self.hprH = self.createcomponent('hprH', (), None,
|
||||
Dial.AngleDial, (hprInterior,),
|
||||
style = Dial.DIAL_MINI,
|
||||
style = 'mini',
|
||||
text = 'H', value = 0.0,
|
||||
relief = FLAT,
|
||||
label_foreground = 'blue')
|
||||
|
|
@ -246,7 +246,7 @@ class Placer(AppShell):
|
|||
|
||||
self.hprP = self.createcomponent('hprP', (), None,
|
||||
Dial.AngleDial, (hprInterior,),
|
||||
style = Dial.DIAL_MINI,
|
||||
style = 'mini',
|
||||
text = 'P', value = 0.0,
|
||||
relief = FLAT,
|
||||
label_foreground = 'red')
|
||||
|
|
@ -259,7 +259,7 @@ class Placer(AppShell):
|
|||
|
||||
self.hprR = self.createcomponent('hprR', (), None,
|
||||
Dial.AngleDial, (hprInterior,),
|
||||
style = Dial.DIAL_MINI,
|
||||
style = 'mini',
|
||||
text = 'R', value = 0.0,
|
||||
relief = FLAT,
|
||||
label_foreground = '#00A000')
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ from tkFileDialog import *
|
|||
import Pmw
|
||||
import Dial
|
||||
import Floater
|
||||
import Slider
|
||||
import EntryScale
|
||||
import VectorWidgets
|
||||
import sys, string
|
||||
|
|
@ -411,6 +412,15 @@ class AppShell(Pmw.MegaWidget, PandaObject):
|
|||
help, command, side, fill, expand, kw)
|
||||
return widget
|
||||
|
||||
def newCreateSider(self, parent, category, text,
|
||||
help = '', command = None,
|
||||
side = LEFT, fill = X, expand = 0, **kw):
|
||||
# Create the widget
|
||||
widget = self.createWidget(parent, category, text,
|
||||
Slider.Slider,
|
||||
help, command, side, fill, expand, kw)
|
||||
return widget
|
||||
|
||||
def newCreateEntryScale(self, parent, category, text,
|
||||
help = '', command = None,
|
||||
side = LEFT, fill = X, expand = 0, **kw):
|
||||
|
|
|
|||
|
|
@ -16,15 +16,11 @@ ONEPOINTFIVE_PI = 1.5 * math.pi
|
|||
POINTFIVE_PI = 0.5 * math.pi
|
||||
INNER_SF = 0.2
|
||||
|
||||
DIAL_FULL = 'full'
|
||||
DIAL_MINI = 'mini'
|
||||
|
||||
DIAL_FULL_SIZE = 45
|
||||
DIAL_MINI_SIZE = 30
|
||||
|
||||
globalClock = ClockObject.getGlobalClock()
|
||||
|
||||
|
||||
class Dial(Valuator):
|
||||
"""
|
||||
Valuator widget which includes an angle dial and an entry for setting
|
||||
|
|
@ -33,7 +29,7 @@ class Dial(Valuator):
|
|||
def __init__(self, parent = None, **kw):
|
||||
INITOPT = Pmw.INITOPT
|
||||
optiondefs = (
|
||||
('style', DIAL_FULL, INITOPT),
|
||||
('style', VALUATOR_FULL, INITOPT),
|
||||
('base', 0.0, self.setBase),
|
||||
('delta', 1.0, self.setDelta),
|
||||
('fSnap', 0, self.setSnap),
|
||||
|
|
@ -56,7 +52,7 @@ class Dial(Valuator):
|
|||
self._valuator._canvas.bind('<Double-ButtonPress-1>', self.mouseReset)
|
||||
|
||||
def packValuator(self):
|
||||
if self['style'] == DIAL_FULL:
|
||||
if self['style'] == VALUATOR_FULL:
|
||||
self._valuator.grid(rowspan = 2, columnspan = 2,
|
||||
padx = 2, pady = 2)
|
||||
if self._label:
|
||||
|
|
@ -155,7 +151,7 @@ class DialWidget(Pmw.MegaWidget):
|
|||
INITOPT = Pmw.INITOPT
|
||||
optiondefs = (
|
||||
# Appearance
|
||||
('style', DIAL_FULL, INITOPT),
|
||||
('style', VALUATOR_FULL, INITOPT),
|
||||
('size', None, INITOPT),
|
||||
('relief', SUNKEN, self.setRelief),
|
||||
('borderwidth', 2, self.setBorderwidth),
|
||||
|
|
@ -200,7 +196,7 @@ class DialWidget(Pmw.MegaWidget):
|
|||
|
||||
# Base dial size on style, if size not specified,
|
||||
if not self['size']:
|
||||
if self['style'] == DIAL_FULL:
|
||||
if self['style'] == VALUATOR_FULL:
|
||||
size = DIAL_FULL_SIZE
|
||||
else:
|
||||
size = DIAL_MINI_SIZE
|
||||
|
|
|
|||
|
|
@ -17,7 +17,10 @@ FLOATER_HEIGHT = 18
|
|||
|
||||
class Floater(Valuator):
|
||||
def __init__(self, parent = None, **kw):
|
||||
optiondefs = ()
|
||||
INITOPT = Pmw.INITOPT
|
||||
optiondefs = (
|
||||
('style', VALUATOR_MINI, INITOPT),
|
||||
)
|
||||
self.defineoptions(kw, optiondefs)
|
||||
# Initialize the superclass
|
||||
Valuator.__init__(self, parent)
|
||||
|
|
|
|||
|
|
@ -11,18 +11,8 @@ import string
|
|||
import operator
|
||||
from PandaModules import ClockObject
|
||||
|
||||
SLIDER_FULL = 'full'
|
||||
SLIDER_MINI = 'mini'
|
||||
|
||||
SLIDER_FULL_WIDTH = 50
|
||||
SLIDER_FULL_HEIGHT = 25
|
||||
|
||||
SLIDER_MINI_WIDTH = 16
|
||||
SLIDER_MINI_HEIGHT = 16
|
||||
|
||||
globalClock = ClockObject.getGlobalClock()
|
||||
|
||||
|
||||
class Slider(Valuator):
|
||||
"""
|
||||
Valuator widget which includes an min/max slider and an entry for setting
|
||||
|
|
@ -31,10 +21,17 @@ class Slider(Valuator):
|
|||
def __init__(self, parent = None, **kw):
|
||||
INITOPT = Pmw.INITOPT
|
||||
optiondefs = (
|
||||
('style', SLIDER_FULL, INITOPT),
|
||||
('min', 0.0, self.setMin),
|
||||
('max', 100.0, self.setMax),
|
||||
('style', VALUATOR_MINI, INITOPT),
|
||||
)
|
||||
self.defineoptions(kw, optiondefs)
|
||||
Valuator.__init__(self, parent)
|
||||
# Can not enter none for min or max
|
||||
self.propertyDict['min']['fNone'] = 0
|
||||
self.propertyDict['min']['help'] = 'Minimum allowable value.'
|
||||
self.propertyDict['max']['fNone'] = 0
|
||||
self.propertyDict['max']['help'] = 'Maximum allowable value.'
|
||||
self.initialiseoptions(Slider)
|
||||
|
||||
def createValuator(self):
|
||||
|
|
@ -49,13 +46,24 @@ class Slider(Valuator):
|
|||
value = self['value'])
|
||||
self._valuator._canvas.bind('<Double-ButtonPress-1>', self.mouseReset)
|
||||
|
||||
# Add popup bindings to slider widget
|
||||
try:
|
||||
self._valuator._arrowBtn.bind(
|
||||
'<ButtonPress-3>', self._popupValuatorMenu)
|
||||
except AttributeError:
|
||||
pass
|
||||
self._valuator._minLabel.bind(
|
||||
'<ButtonPress-3>', self._popupValuatorMenu)
|
||||
self._valuator._maxLabel.bind(
|
||||
'<ButtonPress-3>', self._popupValuatorMenu)
|
||||
|
||||
def packValuator(self):
|
||||
if self['style'] == SLIDER_FULL:
|
||||
if self['style'] == VALUATOR_FULL:
|
||||
if self._label:
|
||||
self._label.grid(row = 0, col = 0, sticky = EW)
|
||||
self._entry.grid(row = 0, col = 1, sticky = EW)
|
||||
self._valuator.grid(row = 1, columnspan = 2,
|
||||
padx = 2, pady = 2)
|
||||
padx = 2, pady = 2, sticky = 'ew')
|
||||
self.interior().columnconfigure(0, weight = 1)
|
||||
else:
|
||||
if self._label:
|
||||
|
|
@ -64,351 +72,35 @@ class Slider(Valuator):
|
|||
self._valuator.grid(row=0,col=2, padx = 2, pady = 2)
|
||||
self.interior().columnconfigure(0, weight = 1)
|
||||
|
||||
def setMin(self):
|
||||
if self['min'] is not None:
|
||||
self._valuator['min'] = self['min']
|
||||
|
||||
class SliderWidget(Pmw.MegaWidget):
|
||||
def __init__(self, parent = None, **kw):
|
||||
#define the megawidget options
|
||||
INITOPT = Pmw.INITOPT
|
||||
optiondefs = (
|
||||
# Appearance
|
||||
('style', SLIDER_MINI, INITOPT),
|
||||
('width', SLIDER_MINI_WIDTH, INITOPT),
|
||||
('height', SLIDER_MINI_HEIGHT, INITOPT),
|
||||
('relief', SUNKEN, self.setRelief),
|
||||
('borderwidth', 2, self.setBorderwidth),
|
||||
('background', 'white', self.setBackground),
|
||||
# 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)
|
||||
|
||||
# Initialize the superclass
|
||||
Pmw.MegaWidget.__init__(self, parent)
|
||||
|
||||
# Set up some local and instance variables
|
||||
# Create the components
|
||||
interior = self.interior()
|
||||
|
||||
# Current value
|
||||
self.value = self['value']
|
||||
|
||||
# Base slider size on style, if size not specified,
|
||||
if not self['width']:
|
||||
if self['style'] == SLIDER_FULL_SIZE:
|
||||
width = SLIDER_FULL_WIDTH
|
||||
else:
|
||||
width = SLIDER_MINI_WIDTH
|
||||
else:
|
||||
width = self['width']
|
||||
|
||||
if not self['height']:
|
||||
if self['style'] == SLIDER_FULL_SIZE:
|
||||
height = SLIDER_FULL_HEIGHT
|
||||
else:
|
||||
height = SLIDER_MINI_HEIGHT
|
||||
else:
|
||||
height = self['height']
|
||||
|
||||
halfWidth = width/2.0
|
||||
halfHeight = height/2.0
|
||||
left = -(halfWidth - 2)
|
||||
right = halfWidth - 2
|
||||
top = -(halfHeight - 2)
|
||||
bottom = halfHeight - 2
|
||||
|
||||
# The canvas
|
||||
self._canvas = self.createcomponent('canvas', (), None,
|
||||
Canvas, (interior,),
|
||||
width = width,
|
||||
height = height,
|
||||
background = self['background'],
|
||||
highlightthickness = 0,
|
||||
scrollregion = (-halfWidth,
|
||||
-halfHeight,
|
||||
halfWidth,
|
||||
halfHeight))
|
||||
self._canvas.pack(expand = 1, fill = BOTH)
|
||||
|
||||
self._canvas.create_polygon(left,top,
|
||||
0, bottom,
|
||||
right, top,
|
||||
fill = '#A0A0A0',
|
||||
tags = ('slider',))
|
||||
|
||||
# The indicator
|
||||
self._canvas.create_line(left, bottom,
|
||||
right, bottom,
|
||||
width = 2)
|
||||
|
||||
# Add event bindings
|
||||
self._canvas.bind('<ButtonPress-1>', self.mouseDown)
|
||||
self._canvas.bind('<B1-Motion>', self.updateSliderSF)
|
||||
self._canvas.bind('<ButtonRelease-1>', self.mouseUp)
|
||||
self._canvas.bind('<Enter>', self.highlightWidget)
|
||||
self._canvas.bind('<Leave>', self.restoreWidget)
|
||||
|
||||
# Make sure input variables processed
|
||||
self.initialiseoptions(SliderWidget)
|
||||
|
||||
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
|
||||
|
||||
## Canvas callback functions
|
||||
# Slider velocity controller
|
||||
def mouseDown(self,event):
|
||||
""" Begin mouse interaction """
|
||||
# Exectute user redefinable callback function (if any)
|
||||
if self['preCallback']:
|
||||
apply(self['preCallback'], self['callbackData'])
|
||||
self.velocitySF = 0.0
|
||||
self.updateTask = taskMgr.add(self.updateSliderTask,
|
||||
'updateSlider')
|
||||
self.updateTask.lastTime = globalClock.getFrameTime()
|
||||
|
||||
def updateSliderTask(self, state):
|
||||
"""
|
||||
Update sliderWidget value based on current scaleFactor
|
||||
Adjust for time to compensate for fluctuating frame rates
|
||||
"""
|
||||
currT = globalClock.getFrameTime()
|
||||
dt = currT - state.lastTime
|
||||
self.set(self.value + self.velocitySF * dt)
|
||||
state.lastTime = currT
|
||||
return Task.cont
|
||||
|
||||
def updateSliderSF(self, event):
|
||||
"""
|
||||
Update velocity scale factor based of mouse distance from origin
|
||||
"""
|
||||
x = self._canvas.canvasx(event.x)
|
||||
y = self._canvas.canvasy(event.y)
|
||||
offset = max(0, abs(x) - Valuator.deadband)
|
||||
if offset == 0:
|
||||
return 0
|
||||
sf = math.pow(Valuator.sfBase,
|
||||
self.minExp + offset/Valuator.sfDist)
|
||||
if x > 0:
|
||||
self.velocitySF = sf
|
||||
else:
|
||||
self.velocitySF = -sf
|
||||
|
||||
def mouseUp(self, event):
|
||||
taskMgr.remove(self.updateTask)
|
||||
self.velocitySF = 0.0
|
||||
# Execute user redefinable callback function (if any)
|
||||
if self['postCallback']:
|
||||
apply(self['postCallback'], self['callbackData'])
|
||||
|
||||
def setNumDigits(self):
|
||||
"""
|
||||
Adjust minimum exponent to use in velocity task based
|
||||
upon the number of digits to be displayed in the result
|
||||
"""
|
||||
self.minExp = math.floor(-self['numDigits']/
|
||||
math.log10(Valuator.sfBase))
|
||||
|
||||
# Methods to modify slider characteristics
|
||||
def setRelief(self):
|
||||
self.interior()['relief'] = self['relief']
|
||||
|
||||
def setBorderwidth(self):
|
||||
self.interior()['borderwidth'] = self['borderwidth']
|
||||
|
||||
def setBackground(self):
|
||||
self._canvas['background'] = self['background']
|
||||
|
||||
def highlightWidget(self, event):
|
||||
self._canvas.itemconfigure('slider', fill = 'black')
|
||||
|
||||
def restoreWidget(self, event):
|
||||
self._canvas.itemconfigure('slider', fill = '#A0A0A0')
|
||||
|
||||
if __name__ == '__main__':
|
||||
tl = Toplevel()
|
||||
d = Slider(tl)
|
||||
d2 = Slider(tl, slider_numSegments = 12, max = 360,
|
||||
slider_fRollover = 0, value = 180)
|
||||
d3 = Slider(tl, slider_numSegments = 12, max = 90, min = -90,
|
||||
slider_fRollover = 0)
|
||||
d4 = Slider(tl, slider_numSegments = 16, max = 256,
|
||||
slider_fRollover = 0)
|
||||
d.pack(expand = 1, fill = X)
|
||||
d2.pack(expand = 1, fill = X)
|
||||
d3.pack(expand = 1, fill = X)
|
||||
d4.pack(expand = 1, fill = X)
|
||||
|
||||
|
||||
|
||||
class PopupSliderWidget(Pmw.MegaToplevel):
|
||||
def __init__(self, parent = None, **kw):
|
||||
optiondefs = (
|
||||
('width', 150, None),
|
||||
('height', 25, None),
|
||||
('xoffset', 0, None), # pixels
|
||||
('yoffset', 1, None), # pixels
|
||||
)
|
||||
self.defineoptions(kw, optiondefs)
|
||||
Pmw.MegaToplevel.__init__(self, parent)
|
||||
interior = self.interior()
|
||||
self.withdraw()
|
||||
self.overrideredirect(1)
|
||||
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.pack()
|
||||
self.initialiseoptions(PopupSliderWidget)
|
||||
|
||||
def showPopup(self, widget):
|
||||
x = widget.winfo_rootx() + widget.winfo_width() - self['width']
|
||||
y = widget.winfo_rooty() + widget.winfo_height()
|
||||
Pmw.setgeometryanddeiconify(self, '%dx%d+%d+%d' %
|
||||
(self['width'], self['height'],x,y))
|
||||
|
||||
"""
|
||||
|
||||
pw = PopupSliderWidget()
|
||||
tl = Toplevel()
|
||||
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)
|
||||
|
||||
|
||||
"""
|
||||
def setMax(self):
|
||||
if self['max'] is not None:
|
||||
self._valuator['max'] = self['max']
|
||||
|
||||
|
||||
# Based on Pmw ComboBox code.
|
||||
class PopupSlider(Pmw.MegaWidget):
|
||||
class SliderWidget(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),
|
||||
# Appearance
|
||||
('relief', RAISED, self.setRelief),
|
||||
('borderwidth', 2, self.setBorderwidth),
|
||||
('background', 'SystemButtonFace', self.setBackground),
|
||||
('fliparrow', 0, INITOPT),
|
||||
# Behavior
|
||||
('style', VALUATOR_MINI, INITOPT),
|
||||
# Bounds
|
||||
('min', 0.0, self.setMin),
|
||||
('max', 100.0, self.setMax),
|
||||
# Initial value of slider, use self.set to change value
|
||||
('value', 0.0, INITOPT),
|
||||
('numDigits', 2, self._setNumDigits),
|
||||
('numDigits', 2, self.setNumDigits),
|
||||
# Command to execute on slider updates
|
||||
('command', None, None),
|
||||
# Extra data to be passed to command function
|
||||
|
|
@ -429,47 +121,95 @@ class PopupSlider(Pmw.MegaWidget):
|
|||
|
||||
# Current value
|
||||
self.value = self['value']
|
||||
self.formatString = '%2f'
|
||||
self.increment = 0.01
|
||||
|
||||
# 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')
|
||||
self._isPosted = 0
|
||||
if self['style'] == VALUATOR_MINI:
|
||||
self._firstPress = 1
|
||||
else:
|
||||
self._firstPress = 0
|
||||
|
||||
# Slider dimensions
|
||||
width = 100
|
||||
xPad = 10
|
||||
self.xPad = 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
|
||||
self.top = top = -5
|
||||
self.bottom = bottom = top + height
|
||||
|
||||
def _createSlider(parent):
|
||||
# Create the canvas inside the dropdown window.
|
||||
# Min label
|
||||
self._minLabel = Label(parent, text = self['min'], width = 8,
|
||||
anchor = E)
|
||||
self._minLabel.pack(side = LEFT)
|
||||
# Slider
|
||||
self._canvas = self.createcomponent(
|
||||
'canvas', (), None,
|
||||
Canvas, (parent,),
|
||||
width = canvasWidth,
|
||||
height = height,
|
||||
bd = 2,
|
||||
highlightthickness = 0,
|
||||
scrollregion = (left - xPad, top, right + xPad, bottom))
|
||||
self._canvas.pack(side = LEFT, expand=1, fill=X)
|
||||
if self['style'] == VALUATOR_FULL:
|
||||
self._canvas.configure(relief = SUNKEN, bd = 2)
|
||||
# Max label
|
||||
self._maxLabel = Label(parent, text = self['max'], width = 8,
|
||||
anchor = W)
|
||||
self._maxLabel.pack(side = LEFT)
|
||||
|
||||
# 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,
|
||||
tags = ('line',))
|
||||
|
||||
self._canvas.bind('<Left>', self._decrementValue)
|
||||
self._canvas.bind('<Right>', self._incrementValue)
|
||||
self._canvas.bind('<Shift-Left>', self._bigDecrementValue)
|
||||
self._canvas.bind('<Shift-Right>', self._bigIncrementValue)
|
||||
self._canvas.bind('<Home>', self._goToMin)
|
||||
self._canvas.bind('<End>', self._goToMax)
|
||||
|
||||
|
||||
# Create slider
|
||||
if self['dropdown']:
|
||||
if self['style'] == VALUATOR_MINI:
|
||||
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)
|
||||
Canvas, (interior,), borderwidth = 0,
|
||||
relief = FLAT, width = 14, height = 14)
|
||||
self._arrowBtn.pack(expand = 1, fill = BOTH)
|
||||
self._arrowBtn.create_polygon(2.5, 4.5, 12.5, 4.5, 7.5, 12.5,
|
||||
tags = 'arrow')
|
||||
self._arrowRelief = self._arrowBtn.cget('relief')
|
||||
|
||||
# Create the label.
|
||||
self.createlabel(interior, childCols=2)
|
||||
|
||||
# Create the dropdown window.
|
||||
self._popup = self.createcomponent(
|
||||
'popup',
|
||||
|
|
@ -479,87 +219,41 @@ class PopupSlider(Pmw.MegaWidget):
|
|||
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)
|
||||
|
||||
_createSlider(self._popup)
|
||||
|
||||
# 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:
|
||||
self._arrowBtn.bind('<Enter>', self.highlightWidget)
|
||||
self._arrowBtn.bind('<Leave>', self.restoreWidget)
|
||||
# Need to unpost the popup if the arrow Button is unmapped (eg:
|
||||
# its toplevel window is withdrawn) while the popup canvas is
|
||||
# displayed.
|
||||
self._entryWidget.bind('<Unmap>', self._unpostCanvas)
|
||||
self._arrowBtn.bind('<Unmap>', self._unpostCanvas)
|
||||
|
||||
# Bind events to the dropdown window.
|
||||
self._popup.bind('<Escape>', self._unpostCanvas)
|
||||
self._popup.bind('<ButtonRelease-1>', self._sliderBtnRelease)
|
||||
self._popup.bind('<ButtonPress-1>', self._sliderBtnPress)
|
||||
self._popup.bind('<Motion>', self._sliderMove)
|
||||
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)
|
||||
# Create the slider directly in the interior
|
||||
_createSlider(interior)
|
||||
self._canvas.bind('<ButtonRelease-1>', self._sliderBtnRelease)
|
||||
self._canvas.bind('<ButtonPress-1>', self._sliderBtnPress)
|
||||
self._canvas.bind('<Motion>', self._sliderMove)
|
||||
self._canvas.bind('<Configure>', self._changeConfiguration)
|
||||
|
||||
|
||||
# Check keywords and initialise options.
|
||||
self.initialiseoptions(PopupSlider)
|
||||
self.initialiseoptions(SliderWidget)
|
||||
|
||||
# Adjust relief
|
||||
if not kw.has_key('relief'):
|
||||
if self['style'] == VALUATOR_FULL:
|
||||
self['relief'] = FLAT
|
||||
|
||||
def destroy(self):
|
||||
if self['dropdown'] and self._isPosted:
|
||||
if (self['style'] == VALUATOR_MINI) and self._isPosted:
|
||||
Pmw.popgrab(self._popup)
|
||||
Pmw.MegaWidget.destroy(self)
|
||||
|
||||
|
|
@ -578,10 +272,6 @@ class PopupSlider(Pmw.MegaWidget):
|
|||
# Record value
|
||||
self.value = value
|
||||
|
||||
def updateIndicator(self, value):
|
||||
# Nothing visible to update on this type of widget
|
||||
pass
|
||||
|
||||
def get(self):
|
||||
"""
|
||||
self.get()
|
||||
|
|
@ -589,50 +279,42 @@ class PopupSlider(Pmw.MegaWidget):
|
|||
"""
|
||||
return self.value
|
||||
|
||||
def updateIndicator(self, value):
|
||||
# Get current marker position
|
||||
markerX = self._getMarkerX()
|
||||
percentX = (value - self['min'])/(self['max'] - self['min'])
|
||||
newX = percentX * (self.right - self.left) + self.left
|
||||
dx = newX - markerX
|
||||
self._canvas.move('slider', dx, 0)
|
||||
|
||||
#======================================================================
|
||||
|
||||
# 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')
|
||||
# Private methods for slider.
|
||||
|
||||
def _postCanvas(self, event = None):
|
||||
self._isPosted = 1
|
||||
self._fUpdate = 0
|
||||
self._drawArrow(sunken=1)
|
||||
if self['style'] == VALUATOR_MINI:
|
||||
self.interior()['relief'] = SUNKEN
|
||||
|
||||
# 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()
|
||||
x = self._arrowBtn.winfo_rootx() + self._arrowBtn.winfo_width()/2.0
|
||||
y = self._arrowBtn.winfo_rooty() + self._arrowBtn.winfo_height()
|
||||
minW = self._minLabel.winfo_width()
|
||||
cw = self._canvas.winfo_width()
|
||||
maxW = self._maxLabel.winfo_width()
|
||||
pw = minW + cw + maxW
|
||||
#pw = minW + cw + maxW
|
||||
pw = maxW + cw/2.0
|
||||
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
|
||||
y = self._arrowBtn.winfo_rooty() - ch
|
||||
|
||||
Pmw.setgeometryanddeiconify(self._popup, '+%d+%d' % (x + w - pw, y))
|
||||
Pmw.setgeometryanddeiconify(self._popup, '+%d+%d' % (x - pw, y))
|
||||
|
||||
# Grab the popup, so that all events are delivered to it, and
|
||||
# set focus to the canvas, to make keyboard navigation
|
||||
|
|
@ -640,8 +322,6 @@ class PopupSlider(Pmw.MegaWidget):
|
|||
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
|
||||
|
|
@ -650,23 +330,37 @@ class PopupSlider(Pmw.MegaWidget):
|
|||
self._fPressInsde = 0
|
||||
|
||||
def _updateValue(self,event):
|
||||
canvasX = self._canvas.canvasx(
|
||||
mouseX = 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)
|
||||
if mouseX < self.left:
|
||||
mouseX = self.left
|
||||
if mouseX > self.right:
|
||||
mouseX = self.right
|
||||
# Update value
|
||||
sf = (mouseX - self.left)/(self.right - self.left)
|
||||
newVal = sf * (self['max'] - self['min']) + self['min']
|
||||
self.set(newVal)
|
||||
|
||||
def _dropdownBtnPress(self, event):
|
||||
self._fUpdate = 1
|
||||
self._fPressInside = 1
|
||||
self._updateValue(event)
|
||||
def _sliderBtnPress(self, event):
|
||||
# Check behavior for this button press
|
||||
if self['style'] == VALUATOR_MINI:
|
||||
widget = self._popup
|
||||
xPos = event.x_root - widget.winfo_rootx()
|
||||
yPos = event.y_root - widget.winfo_rooty()
|
||||
fInside = ((xPos > 0) and (xPos < widget.winfo_width()) and
|
||||
(yPos > 0) and (yPos < widget.winfo_height()))
|
||||
else:
|
||||
fInside = 1
|
||||
# Set flags based upon result
|
||||
if fInside:
|
||||
self._fPressInside = 1
|
||||
self._fUpdate = 1
|
||||
self._updateValue(event)
|
||||
else:
|
||||
self._fPressInside = 0
|
||||
self._fUpdate = 0
|
||||
|
||||
def _dropdownMove(self, event):
|
||||
def _sliderMove(self, event):
|
||||
if self._firstPress and not self._fUpdate:
|
||||
canvasY = self._canvas.canvasy(
|
||||
event.y_root - self._canvas.winfo_rooty())
|
||||
|
|
@ -676,7 +370,7 @@ class PopupSlider(Pmw.MegaWidget):
|
|||
elif self._fUpdate:
|
||||
self._updateValue(event)
|
||||
|
||||
def _dropdownBtnRelease(self, event):
|
||||
def _sliderBtnRelease(self, event):
|
||||
if (self._fUnpost or
|
||||
(not (self._firstPress or self._fPressInside))):
|
||||
self._unpostCanvas()
|
||||
|
|
@ -688,14 +382,6 @@ class PopupSlider(Pmw.MegaWidget):
|
|||
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
|
||||
|
|
@ -714,12 +400,66 @@ class PopupSlider(Pmw.MegaWidget):
|
|||
self._popup.withdraw()
|
||||
|
||||
self._isPosted = 0
|
||||
self._drawArrow()
|
||||
|
||||
if self['style'] == VALUATOR_MINI:
|
||||
self.interior()['relief'] = RAISED
|
||||
|
||||
def _incrementValue(self, event):
|
||||
self.set(self.value + self.increment)
|
||||
def _bigIncrementValue(self, event):
|
||||
self.set(self.value + self.increment * 10.0)
|
||||
def _decrementValue(self, event):
|
||||
self.set(self.value - self.increment)
|
||||
def _bigDecrementValue(self, event):
|
||||
self.set(self.value - self.increment * 10.0)
|
||||
def _goToMin(self, event):
|
||||
self.set(self['min'])
|
||||
def _goToMax(self, event):
|
||||
self.set(self['max'])
|
||||
|
||||
# Methods to modify floater characteristics
|
||||
def setMin(self):
|
||||
self._minLabel['text'] = self.formatString % self['min']
|
||||
self.updateIndicator(self.value)
|
||||
|
||||
def setMax(self):
|
||||
self._maxLabel['text'] = self.formatString % self['max']
|
||||
self.updateIndicator(self.value)
|
||||
|
||||
def setNumDigits(self):
|
||||
self.formatString = '%0.' + ('%d' % self['numDigits']) + 'f'
|
||||
self._minLabel['text'] = self.formatString % self['min']
|
||||
self._maxLabel['text'] = self.formatString % self['max']
|
||||
self.updateIndicator(self.value)
|
||||
self.increment = pow(10, -self['numDigits'])
|
||||
|
||||
def _changeConfiguration(self, event):
|
||||
newWidth = self._canvas.winfo_width()
|
||||
self.left = -newWidth/2.0 + self.xPad
|
||||
self.right = newWidth/2.0 - self.xPad
|
||||
self._canvas.configure(scrollregion = (-newWidth/2.0, self.top,
|
||||
newWidth/2.0, self.bottom))
|
||||
self._canvas.coords('line', self.left, 0, self.right, 0)
|
||||
self.updateIndicator(self.value)
|
||||
|
||||
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')
|
||||
|
||||
def setRelief(self):
|
||||
self.interior()['relief'] = self['relief']
|
||||
|
||||
def setBorderwidth(self):
|
||||
self.interior()['borderwidth'] = self['borderwidth']
|
||||
|
||||
def setBackground(self):
|
||||
self._canvas['background'] = self['background']
|
||||
|
||||
def highlightWidget(self, event):
|
||||
self._arrowBtn.itemconfigure('arrow', fill = 'black')
|
||||
|
||||
def restoreWidget(self, event):
|
||||
self._arrowBtn.itemconfigure('arrow', fill = '#A0A0A0')
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,9 @@ import Pmw
|
|||
import WidgetPropertiesDialog
|
||||
import string
|
||||
|
||||
VALUATOR_MINI = 'mini'
|
||||
VALUATOR_FULL = 'full'
|
||||
|
||||
class Valuator(Pmw.MegaWidget):
|
||||
sfBase = 3.0
|
||||
sfDist = 7
|
||||
|
|
@ -357,6 +360,11 @@ class ValuatorGroup(Pmw.MegaWidget):
|
|||
('labels', DEFAULT_LABELS, self._updateLabels),
|
||||
# The command to be executed when one of the valuators is updated
|
||||
('command', None, None),
|
||||
# Callbacks to execute when updating widget's value
|
||||
('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)
|
||||
|
||||
|
|
@ -376,6 +384,9 @@ class ValuatorGroup(Pmw.MegaWidget):
|
|||
if self['type'] == DIAL:
|
||||
import Dial
|
||||
valuatorType = Dial.Dial
|
||||
elif self['type'] == SLIDER:
|
||||
import Slider
|
||||
valuatorType = Slider.Slider
|
||||
else:
|
||||
import Floater
|
||||
valuatorType = Floater.Floater
|
||||
|
|
@ -383,7 +394,10 @@ class ValuatorGroup(Pmw.MegaWidget):
|
|||
'valuator%d' % index, (), 'valuator', valuatorType,
|
||||
(interior,), value = self._value[index],
|
||||
text = self['labels'][index],
|
||||
command = lambda val, i = index: self._valuatorSetAt(i, val)
|
||||
command = lambda val, i = index: self._valuatorSetAt(i, val),
|
||||
preCallback = self._preCallback,
|
||||
postCallback = self._postCallback,
|
||||
callbackData = [self],
|
||||
)
|
||||
f.pack(side = self['side'], expand = 1, fill = X)
|
||||
self._valuatorList.append(f)
|
||||
|
|
@ -428,6 +442,16 @@ class ValuatorGroup(Pmw.MegaWidget):
|
|||
for index in range(self['dim']):
|
||||
self._valuatorList[index]['text'] = self['labels'][index]
|
||||
|
||||
def _preCallback(self, valGroup):
|
||||
# Execute pre callback
|
||||
if self['preCallback']:
|
||||
apply(self['preCallback'], valGroup.get())
|
||||
|
||||
def _postCallback(self, valGroup):
|
||||
# Execute post callback
|
||||
if self['postCallback']:
|
||||
apply(self['postCallback'], valGroup.get())
|
||||
|
||||
def __len__(self):
|
||||
return self['dim']
|
||||
|
||||
|
|
@ -464,6 +488,13 @@ class ValuatorGroupPanel(Pmw.MegaToplevel):
|
|||
('numDigits', 2, self._setNumDigits),
|
||||
# The command to be executed when one of the floaters is updated
|
||||
('command', None, self._setCommand),
|
||||
# Callbacks to execute when updating widget's value
|
||||
('preCallback', None, self._setPreCallback),
|
||||
('postCallback', None, self._setPostCallback),
|
||||
# Extra data to be passed to callback function, needs to be a list
|
||||
('callbackData', [], self._setCallbackData),
|
||||
# Destroy or withdraw
|
||||
('fDestroy', 0, INITOPT)
|
||||
)
|
||||
self.defineoptions(kw, optiondefs)
|
||||
|
||||
|
|
@ -486,9 +517,15 @@ class ValuatorGroupPanel(Pmw.MegaToplevel):
|
|||
'Valuator Group', 'command', 'Reset the Valuator Group panel',
|
||||
label = 'Reset',
|
||||
command = lambda s = self: s.reset())
|
||||
|
||||
if self['fDestroy']:
|
||||
dismissCommand = self.destroy
|
||||
else:
|
||||
dismissCommand = self.withdraw
|
||||
|
||||
menubar.addmenuitem(
|
||||
'Valuator Group', 'command', 'Dismiss Valuator Group panel',
|
||||
label = 'Dismiss', command = self.withdraw)
|
||||
label = 'Dismiss', command = dismissCommand)
|
||||
|
||||
menubar.addmenu('Help', 'Valuator Group Help Operations')
|
||||
self.toggleBalloonVar = IntVar()
|
||||
|
|
@ -530,7 +567,85 @@ class ValuatorGroupPanel(Pmw.MegaToplevel):
|
|||
def _setCommand(self):
|
||||
self.valuatorGroup['command'] = self['command']
|
||||
|
||||
def _setPreCallback(self):
|
||||
self.valuatorGroup['preCallback'] = self['preCallback']
|
||||
|
||||
def _setPostCallback(self):
|
||||
self.valuatorGroup['postCallback'] = self['postCallback']
|
||||
|
||||
def _setCallbackData(self):
|
||||
self.valuatorGroup['callbackData'] = self['callbackData']
|
||||
|
||||
def reset(self):
|
||||
self.set(self['value'])
|
||||
|
||||
Pmw.forwardmethods(ValuatorGroupPanel, ValuatorGroup, 'valuatorGroup')
|
||||
|
||||
|
||||
def rgbPanel(nodePath, callback = None, style = 'full'):
|
||||
def setNodePathColor(color, np = nodePath, cb = callback):
|
||||
np.setColor(color[0]/255.0, color[1]/255.0,
|
||||
color[2]/255.0, color[3]/255.0)
|
||||
# Execute callback to pass along color info
|
||||
if cb:
|
||||
cb(color)
|
||||
# Check init color
|
||||
if nodePath.hasColor():
|
||||
initColor = nodePath.getColor() * 255.0
|
||||
else:
|
||||
initColor = Vec4(255)
|
||||
# Create entry scale group
|
||||
esg = ValuatorGroupPanel(title = 'RGBA Panel: ' + nodePath.getName(),
|
||||
dim = 4,
|
||||
labels = ['R','G','B','A'],
|
||||
value = [int(initColor[0]),
|
||||
int(initColor[1]),
|
||||
int(initColor[2]),
|
||||
int(initColor[3])],
|
||||
type = 'slider',
|
||||
valuator_style = style,
|
||||
valuator_min = 0,
|
||||
valuator_max = 255,
|
||||
valuator_resolution = 1,
|
||||
# Destroy not withdraw panel on dismiss
|
||||
fDestroy = 1,
|
||||
command = setNodePathColor)
|
||||
# Update menu button
|
||||
esg.component('menubar').component('Valuator Group-button')['text'] = (
|
||||
'RGBA Panel')
|
||||
# Update menu
|
||||
menu = esg.component('menubar').component('Valuator Group-menu')
|
||||
# Some helper functions
|
||||
# Clear color
|
||||
menu.insert_command(index = 1, label = 'Clear Color',
|
||||
command = lambda np = nodePath: np.clearColor())
|
||||
# Set Clear Transparency
|
||||
menu.insert_command(index = 2, label = 'Set Transparency',
|
||||
command = lambda np = nodePath: np.setTransparency(1))
|
||||
menu.insert_command(
|
||||
index = 3, label = 'Clear Transparency',
|
||||
command = lambda np = nodePath: np.clearTransparency())
|
||||
|
||||
# System color picker
|
||||
def popupColorPicker(esg = esg):
|
||||
# Can pass in current color with: color = (255, 0, 0)
|
||||
color = tkColorChooser.askcolor(
|
||||
parent = esg.interior(),
|
||||
# Initialize it to current color
|
||||
initialcolor = tuple(esg.get()[:3]))[0]
|
||||
if color:
|
||||
esg.set((color[0], color[1], color[2], esg.getAt(3)))
|
||||
menu.insert_command(index = 4, label = 'Popup Color Picker',
|
||||
command = popupColorPicker)
|
||||
def printToLog(nodePath=nodePath):
|
||||
c=nodePath.getColor()
|
||||
print "Vec4(%.3f, %.3f, %.3f, %.3f)"%(c[0], c[1], c[2], c[3])
|
||||
menu.insert_command(index = 5, label = 'Print to log',
|
||||
command = printToLog)
|
||||
|
||||
# Set callback
|
||||
def onRelease(r,g,b,a, nodePath = nodePath):
|
||||
messenger.send('RGBPanel_setColor', [nodePath, r,g,b,a])
|
||||
esg['postCallback'] = onRelease
|
||||
return esg
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ from Tkinter import *
|
|||
import Pmw
|
||||
import Valuator
|
||||
import Floater
|
||||
import EntryScale
|
||||
import Slider
|
||||
import string
|
||||
import tkColorChooser
|
||||
|
||||
|
|
@ -15,7 +15,6 @@ class VectorEntry(Pmw.MegaWidget):
|
|||
DEFAULT_VALUE = [0.0] * kw.get('dim', DEFAULT_DIM)
|
||||
DEFAULT_LABELS = map(lambda x: 'v[%d]' % x,
|
||||
range(kw.get('dim', DEFAULT_DIM)))
|
||||
VALUATOR = kw.get('valuatorType', Floater.FloaterGroup)
|
||||
|
||||
# Process options
|
||||
INITOPT = Pmw.INITOPT
|
||||
|
|
@ -31,8 +30,8 @@ class VectorEntry(Pmw.MegaWidget):
|
|||
('text', 'Vector:', self._updateText),
|
||||
('min', None, self._updateValidate),
|
||||
('max', None, self._updateValidate),
|
||||
('numDigits', 2, self._setSigDigits),
|
||||
('valuatorType', VALUATOR, None),
|
||||
('numDigits', 2, self._setSigDigits),
|
||||
('type', 'floater', None),
|
||||
('state', 'normal', self._setState),
|
||||
)
|
||||
self.defineoptions(kw, optiondefs)
|
||||
|
|
@ -92,9 +91,11 @@ class VectorEntry(Pmw.MegaWidget):
|
|||
self._floaters = self.createcomponent(
|
||||
'floaterGroup',
|
||||
(('fGroup', 'floaterGroup'),
|
||||
('Valuator', 'floaterGroup_Valuator'),), None,
|
||||
self['valuatorType'], (self.interior(),),
|
||||
dim = self['dim'], title = self['text'],
|
||||
('valuator', 'floaterGroup_valuator'),), None,
|
||||
Valuator.ValuatorGroupPanel, (self.interior(),),
|
||||
dim = self['dim'],
|
||||
#title = self['text'],
|
||||
type = self['type'],
|
||||
command = self.set)
|
||||
# Note: This means the 'X' on the menu bar doesn't really destroy
|
||||
# the panel, just withdraws it. This is to avoid problems which occur
|
||||
|
|
@ -145,7 +146,7 @@ class VectorEntry(Pmw.MegaWidget):
|
|||
def _setSigDigits(self):
|
||||
sd = self['numDigits']
|
||||
self.entryFormat = '%.' + '%d' % sd + 'f'
|
||||
self.configure(Valuator_numDigits = sd)
|
||||
self.configure(valuator_numDigits = sd)
|
||||
# And refresh value to reflect change
|
||||
for index in range(self['dim']):
|
||||
self._refreshEntry(index)
|
||||
|
|
@ -159,8 +160,8 @@ class VectorEntry(Pmw.MegaWidget):
|
|||
'minstrict' : 0,
|
||||
'maxstrict' : 0})
|
||||
# Reflect changes in floaters
|
||||
self.configure(Valuator_min = self['min'],
|
||||
Valuator_max = self['max'])
|
||||
self.configure(valuator_min = self['min'],
|
||||
valuator_max = self['max'])
|
||||
|
||||
def get(self):
|
||||
return self._value
|
||||
|
|
@ -234,24 +235,24 @@ class VectorEntry(Pmw.MegaWidget):
|
|||
self.configure(Entry_entry_background = '#C0C0C0')
|
||||
# Disable floater Group scale
|
||||
self.component('fGroup').configure(
|
||||
Valuator_state = 'disabled')
|
||||
valuator_state = 'disabled')
|
||||
# Disable floater group entry
|
||||
self.component('fGroup').configure(
|
||||
Valuator_entry_state = 'disabled')
|
||||
valuator_entry_state = 'disabled')
|
||||
self.component('fGroup').configure(
|
||||
Valuator_entry_background = '#C0C0C0')
|
||||
valuator_entry_background = '#C0C0C0')
|
||||
else:
|
||||
# Disable entry
|
||||
self.configure(Entry_entry_state = 'normal')
|
||||
self.configure(Entry_entry_background = self.entryBackground)
|
||||
# Disable floater Group scale
|
||||
self.component('fGroup').configure(
|
||||
Valuator_state = 'normal')
|
||||
valuator_state = 'normal')
|
||||
# Disable floater group entry
|
||||
self.component('fGroup').configure(
|
||||
Valuator_entry_state = 'normal')
|
||||
valuator_entry_state = 'normal')
|
||||
self.component('fGroup').configure(
|
||||
Valuator_entry_background = self.entryBackground)
|
||||
valuator_entry_background = self.entryBackground)
|
||||
|
||||
class Vector2Entry(VectorEntry):
|
||||
def __init__(self, parent = None, **kw):
|
||||
|
|
@ -300,18 +301,17 @@ class ColorEntry(VectorEntry):
|
|||
# Initialize options for the class (overriding some superclass options)
|
||||
optiondefs = (
|
||||
('dim', 4, Pmw.INITOPT),
|
||||
('type', 'slider', Pmw.INITOPT),
|
||||
('fGroup_labels', ('R','G','B','A'), None),
|
||||
('min', 0.0, None),
|
||||
('max', 255.0, None),
|
||||
('nuDigits', 0, None),
|
||||
('Valuator_resolution', 1.0, None),
|
||||
('nuDigits', 0, None),
|
||||
('valuator_resolution', 1.0, None),
|
||||
)
|
||||
self.defineoptions(kw, optiondefs)
|
||||
#kw['valuatorType'] = EntryScale.EntryScaleGroup
|
||||
#kw['dim'] = self['dim']
|
||||
|
||||
# Initialize the superclass, make sure dim makes it to superclass
|
||||
VectorEntry.__init__(self, parent, dim = self['dim'],
|
||||
valuatorType = EntryScale.EntryScaleGroup)
|
||||
VectorEntry.__init__(self, parent, dim = self['dim'])
|
||||
# Add menu item to popup color picker
|
||||
self.addMenuItem(
|
||||
'Popup color picker',
|
||||
|
|
|
|||
|
|
@ -111,12 +111,18 @@ class WidgetPropertiesDialog(Toplevel):
|
|||
# Set up help string and validator based upon type
|
||||
if entryType == 'real':
|
||||
# Only allow real numbers
|
||||
entry['validate'] = { 'validator' : self.realOrNone }
|
||||
if fAllowNone:
|
||||
entry['validate'] = { 'validator' : self.realOrNone }
|
||||
else:
|
||||
entry['validate'] = { 'validator' : 'real' }
|
||||
if helpString is None:
|
||||
helpString = 'Enter a floating point number' + extra + '.'
|
||||
elif entryType == 'integer':
|
||||
# Only allow integer values
|
||||
entry['validate'] = { 'validator' : self.intOrNone }
|
||||
if fAllowNone:
|
||||
entry['validate'] = { 'validator' : self.intOrNone }
|
||||
else:
|
||||
entry['validate'] = { 'validator' : 'integer' }
|
||||
if helpString is None:
|
||||
helpString = 'Enter an integer' + extra + '.'
|
||||
else:
|
||||
|
|
|
|||
Loading…
Reference in New Issue