ソースを参照

*** empty log message ***

Mark Mine 24 年 前
コミット
235cd02cb7

+ 31 - 21
direct/src/leveleditor/LevelEditor.py

@@ -4435,7 +4435,7 @@ class LevelEditorPanel(Pmw.MegaToplevel):
         self.fUpdateSelected = 1
         self.fUpdateSelected = 1
         # Handle to the toplevels hull
         # Handle to the toplevels hull
         hull = self.component('hull')
         hull = self.component('hull')
-        hull.geometry('400x550')
+        hull.geometry('400x515')
         
         
         balloon = self.balloon = Pmw.Balloon(hull)
         balloon = self.balloon = Pmw.Balloon(hull)
         # Start with balloon help disabled
         # Start with balloon help disabled
@@ -4737,63 +4737,73 @@ class LevelEditorPanel(Pmw.MegaToplevel):
         self.addKernFloater = Floater.Floater(
         self.addKernFloater = Floater.Floater(
             gridFrame, 
             gridFrame, 
             text='Kern',
             text='Kern',
-            maxVelocity=1.0,
+            #maxVelocity=1.0,
             command=self.setSignBaselineKern)
             command=self.setSignBaselineKern)
-        self.addKernFloater.grid(row=4, column=0, rowspan=2, columnspan=3)
+        self.addKernFloater.grid(row=4, column=0, rowspan=2, columnspan=3,
+                                 sticky = EW)
         self.addWiggleFloater = Floater.Floater(
         self.addWiggleFloater = Floater.Floater(
             gridFrame, 
             gridFrame, 
             text='Wiggle',
             text='Wiggle',
-            maxVelocity=10.0,
+            #maxVelocity=10.0,
             command=self.setSignBaselineWiggle)
             command=self.setSignBaselineWiggle)
-        self.addWiggleFloater.grid(row=6, column=0, rowspan=2, columnspan=3)
+        self.addWiggleFloater.grid(row=6, column=0, rowspan=2, columnspan=3,
+                                 sticky = EW)
         self.addStumbleFloater = Floater.Floater(
         self.addStumbleFloater = Floater.Floater(
             gridFrame, 
             gridFrame, 
             text='Stumble',
             text='Stumble',
-            maxVelocity=1.0,
+            #maxVelocity=1.0,
             command=self.setSignBaselineStumble)
             command=self.setSignBaselineStumble)
-        self.addStumbleFloater.grid(row=8, column=0, rowspan=2, columnspan=3)
+        self.addStumbleFloater.grid(row=8, column=0, rowspan=2, columnspan=3,
+                                 sticky = EW)
         self.addStompFloater = Floater.Floater(
         self.addStompFloater = Floater.Floater(
             gridFrame, 
             gridFrame, 
             text='Stomp',
             text='Stomp',
-            maxVelocity=1.0,
+            #maxVelocity=1.0,
             command=self.setSignBaselineStomp)
             command=self.setSignBaselineStomp)
-        self.addStompFloater.grid(row=10, column=0, rowspan=2, columnspan=3)
+        self.addStompFloater.grid(row=10, column=0, rowspan=2, columnspan=3,
+                                 sticky = EW)
         self.addCurveFloater = Floater.Floater(
         self.addCurveFloater = Floater.Floater(
             gridFrame, 
             gridFrame, 
             text='Curve',
             text='Curve',
-            maxVelocity = 1.0,
+            #maxVelocity = 1.0,
             command=self.setSignBaselineCurve)
             command=self.setSignBaselineCurve)
-        self.addCurveFloater.grid(row=12, column=0, rowspan=2, columnspan=3)
+        self.addCurveFloater.grid(row=12, column=0, rowspan=2, columnspan=3,
+                                 sticky = EW)
         self.addXFloater = Floater.Floater(
         self.addXFloater = Floater.Floater(
             gridFrame, 
             gridFrame, 
             text='X',
             text='X',
-            maxVelocity=1.0,
+            #maxVelocity=1.0,
             command=self.setDNATargetX)
             command=self.setDNATargetX)
-        self.addXFloater.grid(row=4, column=3, rowspan=2, columnspan=3)
+        self.addXFloater.grid(row=4, column=3, rowspan=2, columnspan=3,
+                                 sticky = EW)
         self.addZFloater = Floater.Floater(
         self.addZFloater = Floater.Floater(
             gridFrame, 
             gridFrame, 
             text='Z',
             text='Z',
-            maxVelocity=1.0,
+            #maxVelocity=1.0,
             command=self.setDNATargetZ)
             command=self.setDNATargetZ)
-        self.addZFloater.grid(row=6, column=3, rowspan=2, columnspan=3)
+        self.addZFloater.grid(row=6, column=3, rowspan=2, columnspan=3,
+                                 sticky = EW)
         self.addScaleXFloater = Floater.Floater(
         self.addScaleXFloater = Floater.Floater(
             gridFrame, 
             gridFrame, 
             text='Scale X',
             text='Scale X',
-            maxVelocity=1.0,
+            #maxVelocity=1.0,
             command=self.setDNATargetScaleX)
             command=self.setDNATargetScaleX)
-        self.addScaleXFloater.grid(row=8, column=3, rowspan=2, columnspan=3)
+        self.addScaleXFloater.grid(row=8, column=3, rowspan=2, columnspan=3,
+                                 sticky = EW)
         self.addScaleZFloater = Floater.Floater(
         self.addScaleZFloater = Floater.Floater(
             gridFrame, 
             gridFrame, 
             text='Scale Z',
             text='Scale Z',
-            maxVelocity=1.0,
+            #maxVelocity=1.0,
             command=self.setDNATargetScaleZ)
             command=self.setDNATargetScaleZ)
-        self.addScaleZFloater.grid(row=10, column=3, rowspan=2, columnspan=3)
+        self.addScaleZFloater.grid(row=10, column=3, rowspan=2, columnspan=3,
+                                 sticky = EW)
         self.addRollFloater = Floater.Floater(
         self.addRollFloater = Floater.Floater(
             gridFrame, 
             gridFrame, 
             text='Roll',
             text='Roll',
-            maxVelocity=10.0,
+            #maxVelocity=10.0,
             command=self.setDNATargetRoll)
             command=self.setDNATargetRoll)
-        self.addRollFloater.grid(row=12, column=3, rowspan=2, columnspan=3)
+        self.addRollFloater.grid(row=12, column=3, rowspan=2, columnspan=3,
+                                 sticky = EW)
 
 
         gridFrame.pack(fill=BOTH)
         gridFrame.pack(fill=BOTH)
 
 

+ 12 - 11
direct/src/tkpanels/DirectSessionPanel.py

@@ -369,7 +369,7 @@ class DirectSessionPanel(AppShell):
         self.pConstantAttenuation = EntryScale.EntryScale(
         self.pConstantAttenuation = EntryScale.EntryScale(
             pointPage,
             pointPage,
             text = 'Constant Attenuation',
             text = 'Constant Attenuation',
-            min = 0.0, max = 1.0, initialValue = 1.0)
+            min = 0.0, max = 1.0, value = 1.0)
         self.pConstantAttenuation['command'] = self.setConstantAttenuation
         self.pConstantAttenuation['command'] = self.setConstantAttenuation
         self.pConstantAttenuation.pack(fill = X, expand = 0)
         self.pConstantAttenuation.pack(fill = X, expand = 0)
         self.bind(self.pConstantAttenuation,
         self.bind(self.pConstantAttenuation,
@@ -378,7 +378,7 @@ class DirectSessionPanel(AppShell):
         self.pLinearAttenuation = EntryScale.EntryScale(
         self.pLinearAttenuation = EntryScale.EntryScale(
             pointPage,
             pointPage,
             text = 'Linear Attenuation',
             text = 'Linear Attenuation',
-            min = 0.0, max = 1.0, initialValue = 0.0)
+            min = 0.0, max = 1.0, value = 0.0)
         self.pLinearAttenuation['command'] = self.setLinearAttenuation
         self.pLinearAttenuation['command'] = self.setLinearAttenuation
         self.pLinearAttenuation.pack(fill = X, expand = 0)
         self.pLinearAttenuation.pack(fill = X, expand = 0)
         self.bind(self.pLinearAttenuation,
         self.bind(self.pLinearAttenuation,
@@ -387,7 +387,7 @@ class DirectSessionPanel(AppShell):
         self.pQuadraticAttenuation = EntryScale.EntryScale(
         self.pQuadraticAttenuation = EntryScale.EntryScale(
             pointPage,
             pointPage,
             text = 'Quadratic Attenuation',
             text = 'Quadratic Attenuation',
-            min = 0.0, max = 1.0, initialValue = 0.0)
+            min = 0.0, max = 1.0, value = 0.0)
         self.pQuadraticAttenuation['command'] = self.setQuadraticAttenuation
         self.pQuadraticAttenuation['command'] = self.setQuadraticAttenuation
         self.pQuadraticAttenuation.pack(fill = X, expand = 0)
         self.pQuadraticAttenuation.pack(fill = X, expand = 0)
         self.bind(self.pQuadraticAttenuation,
         self.bind(self.pQuadraticAttenuation,
@@ -404,7 +404,7 @@ class DirectSessionPanel(AppShell):
         self.sConstantAttenuation = EntryScale.EntryScale(
         self.sConstantAttenuation = EntryScale.EntryScale(
             spotPage,
             spotPage,
             text = 'Constant Attenuation',
             text = 'Constant Attenuation',
-            min = 0.0, max = 1.0, initialValue = 1.0)
+            min = 0.0, max = 1.0, value = 1.0)
         self.sConstantAttenuation['command'] = self.setConstantAttenuation
         self.sConstantAttenuation['command'] = self.setConstantAttenuation
         self.sConstantAttenuation.pack(fill = X, expand = 0)
         self.sConstantAttenuation.pack(fill = X, expand = 0)
         self.bind(self.sConstantAttenuation,
         self.bind(self.sConstantAttenuation,
@@ -413,7 +413,7 @@ class DirectSessionPanel(AppShell):
         self.sLinearAttenuation = EntryScale.EntryScale(
         self.sLinearAttenuation = EntryScale.EntryScale(
             spotPage,
             spotPage,
             text = 'Linear Attenuation',
             text = 'Linear Attenuation',
-            min = 0.0, max = 1.0, initialValue = 0.0)
+            min = 0.0, max = 1.0, value = 0.0)
         self.sLinearAttenuation['command'] = self.setLinearAttenuation
         self.sLinearAttenuation['command'] = self.setLinearAttenuation
         self.sLinearAttenuation.pack(fill = X, expand = 0)
         self.sLinearAttenuation.pack(fill = X, expand = 0)
         self.bind(self.sLinearAttenuation,
         self.bind(self.sLinearAttenuation,
@@ -422,7 +422,7 @@ class DirectSessionPanel(AppShell):
         self.sQuadraticAttenuation = EntryScale.EntryScale(
         self.sQuadraticAttenuation = EntryScale.EntryScale(
             spotPage,
             spotPage,
             text = 'Quadratic Attenuation',
             text = 'Quadratic Attenuation',
-            min = 0.0, max = 1.0, initialValue = 0.0)
+            min = 0.0, max = 1.0, value = 0.0)
         self.sQuadraticAttenuation['command'] = self.setQuadraticAttenuation
         self.sQuadraticAttenuation['command'] = self.setQuadraticAttenuation
         self.sQuadraticAttenuation.pack(fill = X, expand = 0)
         self.sQuadraticAttenuation.pack(fill = X, expand = 0)
         self.bind(self.sQuadraticAttenuation,
         self.bind(self.sQuadraticAttenuation,
@@ -431,7 +431,7 @@ class DirectSessionPanel(AppShell):
         self.sExponent = EntryScale.EntryScale(
         self.sExponent = EntryScale.EntryScale(
             spotPage,
             spotPage,
             text = 'Exponent',
             text = 'Exponent',
-            min = 0.0, max = 1.0, initialValue = 0.0)
+            min = 0.0, max = 1.0, value = 0.0)
         self.sExponent['command'] = self.setExponent
         self.sExponent['command'] = self.setExponent
         self.sExponent.pack(fill = X, expand = 0)
         self.sExponent.pack(fill = X, expand = 0)
         self.bind(self.sExponent,
         self.bind(self.sExponent,
@@ -478,7 +478,7 @@ class DirectSessionPanel(AppShell):
             gridPage,
             gridPage,
             text = 'Grid Spacing',
             text = 'Grid Spacing',
             min = 0.1,
             min = 0.1,
-            initialValue = direct.grid.getGridSpacing())
+            value = direct.grid.getGridSpacing())
         self.gridSpacing['command'] = direct.grid.setGridSpacing
         self.gridSpacing['command'] = direct.grid.setGridSpacing
         self.gridSpacing.pack(fill = X, expand = 0)
         self.gridSpacing.pack(fill = X, expand = 0)
         
         
@@ -486,13 +486,14 @@ class DirectSessionPanel(AppShell):
             gridPage,
             gridPage,
             text = 'Grid Size',
             text = 'Grid Size',
             min = 1.0,
             min = 1.0,
-            initialValue = direct.grid.getGridSize())
+            value = direct.grid.getGridSize())
         self.gridSize['command'] = direct.grid.setGridSize
         self.gridSize['command'] = direct.grid.setGridSize
         self.gridSize.pack(fill = X, expand = 0)
         self.gridSize.pack(fill = X, expand = 0)
 
 
         self.gridSnapAngle = Dial.AngleDial(
         self.gridSnapAngle = Dial.AngleDial(
             gridPage,
             gridPage,
             text = 'Snap Angle',
             text = 'Snap Angle',
+            style = Dial.DIAL_MINI,
             value = direct.grid.getSnapAngle())
             value = direct.grid.getSnapAngle())
         self.gridSnapAngle['command'] = direct.grid.setSnapAngle
         self.gridSnapAngle['command'] = direct.grid.setSnapAngle
         self.gridSnapAngle.pack(fill = X, expand = 0)
         self.gridSnapAngle.pack(fill = X, expand = 0)
@@ -544,7 +545,7 @@ class DirectSessionPanel(AppShell):
             self.jbXyzSF = EntryScale.EntryScale(
             self.jbXyzSF = EntryScale.EntryScale(
                 joyboxFrame,
                 joyboxFrame,
                 text = 'XYZ Scale Factor',
                 text = 'XYZ Scale Factor',
-                initialValue = 1.0,
+                value = 1.0,
                 hull_relief = RIDGE, hull_borderwidth = 2,
                 hull_relief = RIDGE, hull_borderwidth = 2,
                 min = 1.0, max = 100.0)
                 min = 1.0, max = 100.0)
             self.jbXyzSF['command'] = (
             self.jbXyzSF['command'] = (
@@ -555,7 +556,7 @@ class DirectSessionPanel(AppShell):
             self.jbHprSF = EntryScale.EntryScale(
             self.jbHprSF = EntryScale.EntryScale(
                 joyboxFrame,
                 joyboxFrame,
                 text = 'HPR Scale Factor',
                 text = 'HPR Scale Factor',
-                initialValue = 1.0,
+                value = 1.0,
                 hull_relief = RIDGE, hull_borderwidth = 2,
                 hull_relief = RIDGE, hull_borderwidth = 2,
                 min = 1.0, max = 100.0)
                 min = 1.0, max = 100.0)
             self.jbHprSF['command'] = (
             self.jbHprSF['command'] = (

+ 23 - 25
direct/src/tkpanels/MopathRecorder.py

@@ -370,7 +370,7 @@ class MopathRecorder(AppShell, PandaObject):
             'Number of samples in resampled curve',
             'Number of samples in resampled curve',
             resolution = 1, min = 2, max = 1000, command = self.setNumSamples)
             resolution = 1, min = 2, max = 1000, command = self.setNumSamples)
         widget.component('hull')['relief'] = RIDGE
         widget.component('hull')['relief'] = RIDGE
-        widget.onRelease = widget.onReturnRelease = self.sampleCurve
+        widget['preCallback'] = widget['postCallback'] = self.sampleCurve
 
 
         frame = Frame(resampleFrame)
         frame = Frame(resampleFrame)
         self.createButton(
         self.createButton(
@@ -395,7 +395,7 @@ class MopathRecorder(AppShell, PandaObject):
             min = 1, max = 100, resolution = 1,
             min = 1, max = 100, resolution = 1,
             command = self.setDesampleFrequency)
             command = self.setDesampleFrequency)
         widget.component('hull')['relief'] = RIDGE
         widget.component('hull')['relief'] = RIDGE
-        widget.onRelease = widget.onReturnRelease = self.desampleCurve
+        widget['postCallback'] = self.desampleCurve
         desampleFrame.pack(fill = X, expand = 0, pady = 2)
         desampleFrame.pack(fill = X, expand = 0, pady = 2)
 
 
         ## REFINE PAGE ##
         ## REFINE PAGE ##
@@ -410,29 +410,28 @@ class MopathRecorder(AppShell, PandaObject):
                                        'Begin time of refine pass',
                                        'Begin time of refine pass',
                                        resolution = 0.01,
                                        resolution = 0.01,
                                        command = self.setRecordStart)
                                        command = self.setRecordStart)
-        widget.onPress = self.setRefineMode
-        widget.onRelease = widget.onReturnRelease = (
-            lambda s = self: s.getPrePoints('Refine'))
+        widget['preCallback'] = self.setRefineMode
+        widget['postCallback'] = lambda s = self: s.getPrePoints('Refine')
         widget = self.createEntryScale(
         widget = self.createEntryScale(
             refineFrame, 'Refine Page',
             refineFrame, 'Refine Page',
             'Control Start',
             'Control Start',
             'Time when full control of node path is given during refine pass',
             'Time when full control of node path is given during refine pass',
             resolution = 0.01,
             resolution = 0.01,
             command = self.setControlStart)
             command = self.setControlStart)
-        widget.onPress = widget.onReturn = self.setRefineMode
+        widget['preCallback'] = self.setRefineMode
         widget = self.createEntryScale(
         widget = self.createEntryScale(
             refineFrame, 'Refine Page',
             refineFrame, 'Refine Page',
             'Control Stop',
             'Control Stop',
             'Time when node path begins transition back to original curve',
             'Time when node path begins transition back to original curve',
             resolution = 0.01,
             resolution = 0.01,
             command = self.setControlStop)
             command = self.setControlStop)
-        widget.onPress = widget.onReturn = self.setRefineMode
+        widget['preCallback'] = self.setRefineMode
         widget = self.createEntryScale(refineFrame, 'Refine Page', 'Refine To',
         widget = self.createEntryScale(refineFrame, 'Refine Page', 'Refine To',
                                        'Stop time of refine pass',
                                        'Stop time of refine pass',
                                        resolution = 0.01,
                                        resolution = 0.01,
                                        command = self.setRefineStop)
                                        command = self.setRefineStop)
-        widget.onPress = self.setRefineMode
-        widget.onRelease = widget.onReturnRelease = self.getPostPoints
+        widget['preCallback'] = self.setRefineMode
+        widget['postCallback'] = self.getPostPoints
         refineFrame.pack(fill = X)
         refineFrame.pack(fill = X)
 
 
         ## EXTEND PAGE ##
         ## EXTEND PAGE ##
@@ -447,16 +446,15 @@ class MopathRecorder(AppShell, PandaObject):
                                        'Begin time of extend pass',
                                        'Begin time of extend pass',
                                        resolution = 0.01,
                                        resolution = 0.01,
                                        command = self.setRecordStart)
                                        command = self.setRecordStart)
-        widget.onPress = self.setExtendMode
-        widget.onRelease = widget.onReturnRelease = (
-            lambda s = self: s.getPrePoints('Extend'))
+        widget['preCallback'] = self.setExtendMode
+        widget['postCallback'] = lambda s = self: s.getPrePoints('Extend')
         widget = self.createEntryScale(
         widget = self.createEntryScale(
             extendFrame, 'Extend Page',
             extendFrame, 'Extend Page',
             'Control Start',
             'Control Start',
             'Time when full control of node path is given during extend pass',
             'Time when full control of node path is given during extend pass',
             resolution = 0.01,
             resolution = 0.01,
             command = self.setControlStart)
             command = self.setControlStart)
-        widget.onPress = widget.onReturn = self.setExtendMode
+        widget['preCallback'] = self.setExtendMode
         extendFrame.pack(fill = X)
         extendFrame.pack(fill = X)
 
 
         ## CROP PAGE ##
         ## CROP PAGE ##
@@ -529,48 +527,48 @@ class MopathRecorder(AppShell, PandaObject):
             sfFrame, 'Style', 'Num Segs',
             sfFrame, 'Style', 'Num Segs',
             'Set number of segments used to approximate each parametric unit',
             'Set number of segments used to approximate each parametric unit',
             min = 1.0, max = 400, resolution = 1.0,
             min = 1.0, max = 400, resolution = 1.0,
-            initialValue = 40, 
+            value = 40, 
             command = self.setNumSegs, side = TOP)
             command = self.setNumSegs, side = TOP)
         widget.component('hull')['relief'] = RIDGE
         widget.component('hull')['relief'] = RIDGE
         widget = self.createEntryScale(
         widget = self.createEntryScale(
             sfFrame, 'Style', 'Num Ticks',
             sfFrame, 'Style', 'Num Ticks',
             'Set number of tick marks drawn for each unit of time',
             'Set number of tick marks drawn for each unit of time',
             min = 0.0, max = 10.0, resolution = 1.0,
             min = 0.0, max = 10.0, resolution = 1.0,
-            initialValue = 0.0,
+            value = 0.0,
             command = self.setNumTicks, side = TOP)
             command = self.setNumTicks, side = TOP)
         widget.component('hull')['relief'] = RIDGE
         widget.component('hull')['relief'] = RIDGE
         widget = self.createEntryScale(
         widget = self.createEntryScale(
             sfFrame, 'Style', 'Tick Scale',
             sfFrame, 'Style', 'Tick Scale',
             'Set visible size of time tick marks',
             'Set visible size of time tick marks',
             min = 0.01, max = 100.0, resolution = 0.01,
             min = 0.01, max = 100.0, resolution = 0.01,
-            initialValue = 5.0,
+            value = 5.0,
             command = self.setTickScale, side = TOP)
             command = self.setTickScale, side = TOP)
         widget.component('hull')['relief'] = RIDGE
         widget.component('hull')['relief'] = RIDGE
         self.createColorEntry(
         self.createColorEntry(
             sfFrame, 'Style', 'Path Color',
             sfFrame, 'Style', 'Path Color',
             'Color of curve',
             'Color of curve',
             command = self.setPathColor,
             command = self.setPathColor,
-            initialValue = [255.0,255.0,255.0,255.0])
+            value = [255.0,255.0,255.0,255.0])
         self.createColorEntry(
         self.createColorEntry(
             sfFrame, 'Style', 'Knot Color',
             sfFrame, 'Style', 'Knot Color',
             'Color of knots',
             'Color of knots',
             command = self.setKnotColor,
             command = self.setKnotColor,
-            initialValue = [0,0,255.0,255.0])
+            value = [0,0,255.0,255.0])
         self.createColorEntry(
         self.createColorEntry(
             sfFrame, 'Style', 'CV Color',
             sfFrame, 'Style', 'CV Color',
             'Color of CVs',
             'Color of CVs',
             command = self.setCvColor,
             command = self.setCvColor,
-            initialValue = [255.0,0,0,255.0])
+            value = [255.0,0,0,255.0])
         self.createColorEntry(
         self.createColorEntry(
             sfFrame, 'Style', 'Tick Color',
             sfFrame, 'Style', 'Tick Color',
             'Color of Ticks',
             'Color of Ticks',
             command = self.setTickColor,
             command = self.setTickColor,
-            initialValue = [255.0,0,0,255.0])
+            value = [255.0,0,0,255.0])
         self.createColorEntry(
         self.createColorEntry(
             sfFrame, 'Style', 'Hull Color',
             sfFrame, 'Style', 'Hull Color',
             'Color of Hull',
             'Color of Hull',
             command = self.setHullColor,
             command = self.setHullColor,
-            initialValue = [255.0,128.0,128.0,255.0])
+            value = [255.0,128.0,128.0,255.0])
 
 
         #drawFrame.pack(fill = X)
         #drawFrame.pack(fill = X)
 
 
@@ -585,7 +583,7 @@ class MopathRecorder(AppShell, PandaObject):
         widget = self.createLabeledEntry(
         widget = self.createLabeledEntry(
             frame, 'Recording', 'Record Hook',
             frame, 'Recording', 'Record Hook',
             'Hook used to start/stop recording',
             'Hook used to start/stop recording',
-            initialValue = self.startStopHook,
+            value = self.startStopHook,
             command = self.setStartStopHook)[0]
             command = self.setStartStopHook)[0]
         label = self.getWidget('Recording', 'Record Hook-Label')
         label = self.getWidget('Recording', 'Record Hook-Label')
         label.configure(width = 16, anchor = W)
         label.configure(width = 16, anchor = W)
@@ -593,7 +591,7 @@ class MopathRecorder(AppShell, PandaObject):
         widget = self.createLabeledEntry(
         widget = self.createLabeledEntry(
             frame, 'Recording', 'Keyframe Hook',
             frame, 'Recording', 'Keyframe Hook',
             'Hook used to add a new keyframe',
             'Hook used to add a new keyframe',
-            initialValue = self.keyframeHook,
+            value = self.keyframeHook,
             command = self.setKeyframeHook)[0]
             command = self.setKeyframeHook)[0]
         label = self.getWidget('Recording', 'Keyframe Hook-Label')
         label = self.getWidget('Recording', 'Keyframe Hook-Label')
         label.configure(width = 16, anchor = W)
         label.configure(width = 16, anchor = W)
@@ -1678,12 +1676,12 @@ class MopathRecorder(AppShell, PandaObject):
         return self.variableDict[category + '-' + text]
         return self.variableDict[category + '-' + text]
 
 
     def createLabeledEntry(self, parent, category, text, balloonHelp,
     def createLabeledEntry(self, parent, category, text, balloonHelp,
-                           initialValue = '', command = None,
+                           value = '', command = None,
                            relief = 'sunken', side = LEFT,
                            relief = 'sunken', side = LEFT,
                            expand = 1, width = 12):
                            expand = 1, width = 12):
         frame = Frame(parent)
         frame = Frame(parent)
         variable = StringVar()
         variable = StringVar()
-        variable.set(initialValue)
+        variable.set(value)
         label = Label(frame, text = text)
         label = Label(frame, text = text)
         label.pack(side = LEFT, fill = X)
         label.pack(side = LEFT, fill = X)
         self.bind(label, balloonHelp)
         self.bind(label, balloonHelp)

+ 15 - 16
direct/src/tkpanels/ParticlePanel.py

@@ -20,7 +20,7 @@ class ParticlePanel(AppShell):
     # Override class variables
     # Override class variables
     appname = 'Particle Panel'
     appname = 'Particle Panel'
     frameWidth  = 375
     frameWidth  = 375
-    frameHeight = 775
+    frameHeight = 575
     usecommandarea = 0
     usecommandarea = 0
     usestatusarea  = 0
     usestatusarea  = 0
     balloonState = 'both'
     balloonState = 'both'
@@ -374,7 +374,7 @@ class ParticlePanel(AppShell):
         self.createVector3Entry(boxPage, 'Box Emitter', 'Max',
         self.createVector3Entry(boxPage, 'Box Emitter', 'Max',
                                 'Max point defining emitter box',
                                 'Max point defining emitter box',
                                 command = self.setEmitterBoxPoint2,
                                 command = self.setEmitterBoxPoint2,
-                                initialValue = (1.0, 1.0, 1.0))
+                                value = (1.0, 1.0, 1.0))
         # Disc page #
         # Disc page #
         discPage = self.emitterNotebook.add('DiscEmitter')
         discPage = self.emitterNotebook.add('DiscEmitter')
         self.createFloater(discPage, 'Disc Emitter', 'Radius',
         self.createFloater(discPage, 'Disc Emitter', 'Radius',
@@ -408,7 +408,7 @@ class ParticlePanel(AppShell):
         self.createVector3Entry(linePage, 'Line Emitter', 'Max',
         self.createVector3Entry(linePage, 'Line Emitter', 'Max',
                                 'Max point defining emitter line',
                                 'Max point defining emitter line',
                                 command = self.setEmitterLinePoint2,
                                 command = self.setEmitterLinePoint2,
-                                initialValue = (1.0, 0.0, 0.0))
+                                value = (1.0, 0.0, 0.0))
         # Point page #
         # Point page #
         emitterPointPage = self.emitterNotebook.add('PointEmitter')
         emitterPointPage = self.emitterNotebook.add('PointEmitter')
         self.createVector3Entry(emitterPointPage, 'Point Emitter', 'Position',
         self.createVector3Entry(emitterPointPage, 'Point Emitter', 'Position',
@@ -736,13 +736,11 @@ class ParticlePanel(AppShell):
 
 
     def createFloater(self, parent, category, text, balloonHelp,
     def createFloater(self, parent, category, text, balloonHelp,
                       command = None, min = 0.0, resolution = None,
                       command = None, min = 0.0, resolution = None,
-                      significantDigits = 3,
-                      maxVelocity = 10.0, **kw):
+                      numDigits = 3, **kw):
         kw['text'] = text
         kw['text'] = text
         kw['min'] = min
         kw['min'] = min
-        kw['maxVelocity'] = maxVelocity
-        kw['resolution'] = resolution
-        kw['significantDigits'] = significantDigits
+        kw['floater_resolution'] = resolution
+        kw['numDigits'] = numDigits
         widget = apply(Floater.Floater, (parent,), kw)
         widget = apply(Floater.Floater, (parent,), kw)
         # Do this after the widget so command isn't called on creation
         # Do this after the widget so command isn't called on creation
         widget['command'] = command
         widget['command'] = command
@@ -754,6 +752,7 @@ class ParticlePanel(AppShell):
     def createAngleDial(self, parent, category, text, balloonHelp,
     def createAngleDial(self, parent, category, text, balloonHelp,
                         command = None, **kw):
                         command = None, **kw):
         kw['text'] = text
         kw['text'] = text
+        kw['style'] = Dial.DIAL_MINI
         widget = apply(Dial.AngleDial,(parent,), kw)
         widget = apply(Dial.AngleDial,(parent,), kw)
         # Do this after the widget so command isn't called on creation
         # Do this after the widget so command isn't called on creation
         widget['command'] = command
         widget['command'] = command
@@ -1771,7 +1770,7 @@ class ParticlePanel(AppShell):
         self.createFloater(frame, pageName, forceName + ' Amplitude',
         self.createFloater(frame, pageName, forceName + ' Amplitude',
                            'Force amplitude multiplier',
                            'Force amplitude multiplier',
                            command = setAmplitude,
                            command = setAmplitude,
-                           initialValue = force.getAmplitude())
+                           value = force.getAmplitude())
         cbf = Frame(frame, relief = FLAT)
         cbf = Frame(frame, relief = FLAT)
         self.createCheckbutton(cbf, pageName, forceName + ' Mass Dependent',
         self.createCheckbutton(cbf, pageName, forceName + ' Mass Dependent',
                                ('On: force depends on mass; ' +
                                ('On: force depends on mass; ' +
@@ -1808,7 +1807,7 @@ class ParticlePanel(AppShell):
         self.createVector3Entry(frame, pageName, forceName,
         self.createVector3Entry(frame, pageName, forceName,
                                 'Set force direction and magnitude',
                                 'Set force direction and magnitude',
                                 command = setVec,
                                 command = setVec,
-                                initialValue = [vec[0], vec[1], vec[2]])
+                                value = [vec[0], vec[1], vec[2]])
         self.createForceActiveWidget(frame, pageName, forceName, force)
         self.createForceActiveWidget(frame, pageName, forceName, force)
 
 
     def createLinearRandomForceWidget(self, forcePage, pageName, count,
     def createLinearRandomForceWidget(self, forcePage, pageName, count,
@@ -1828,7 +1827,7 @@ class ParticlePanel(AppShell):
         self.createFloater(frame, pageName, forceName + ' Coef',
         self.createFloater(frame, pageName, forceName + ' Coef',
                            'Set linear friction force',
                            'Set linear friction force',
                            command = setCoef, min = None,
                            command = setCoef, min = None,
-                           initialValue = force.getCoef())
+                           value = force.getCoef())
         self.createForceActiveWidget(frame, pageName, forceName, force)
         self.createForceActiveWidget(frame, pageName, forceName, force)
 
 
     def createLinearCylinderVortexForceWidget(self, forcePage, pageName,
     def createLinearCylinderVortexForceWidget(self, forcePage, pageName,
@@ -1845,15 +1844,15 @@ class ParticlePanel(AppShell):
         self.createFloater(frame, pageName, forceName + ' Coef',
         self.createFloater(frame, pageName, forceName + ' Coef',
                            'Set linear cylinder vortex coefficient',
                            'Set linear cylinder vortex coefficient',
                            command = setCoef,
                            command = setCoef,
-                           initialValue = force.getCoef())
+                           value = force.getCoef())
         self.createFloater(frame, pageName, forceName + ' Length',
         self.createFloater(frame, pageName, forceName + ' Length',
                            'Set linear cylinder vortex length',
                            'Set linear cylinder vortex length',
                            command = setLength,
                            command = setLength,
-                           initialValue = force.getLength())
+                           value = force.getLength())
         self.createFloater(frame, pageName, forceName + ' Radius',
         self.createFloater(frame, pageName, forceName + ' Radius',
                            'Set linear cylinder vortex radius',
                            'Set linear cylinder vortex radius',
                            command = setRadius,
                            command = setRadius,
-                           initialValue = force.getRadius())
+                           value = force.getRadius())
         self.createForceActiveWidget(frame, pageName, forceName, force)
         self.createForceActiveWidget(frame, pageName, forceName, force)
 
 
     def createLinearDistanceForceWidget(self, forcePage, pageName,
     def createLinearDistanceForceWidget(self, forcePage, pageName,
@@ -1896,12 +1895,12 @@ class ParticlePanel(AppShell):
                                 'Set center of force',
                                 'Set center of force',
                                 command = setForceCenter,
                                 command = setForceCenter,
                                 label_width = 16,
                                 label_width = 16,
-                                initialValue = [vec[0], vec[1], vec[2]])
+                                value = [vec[0], vec[1], vec[2]])
         self.createFloater(frame, pageName, forceName + ' Radius',
         self.createFloater(frame, pageName, forceName + ' Radius',
                            'Set falloff radius',
                            'Set falloff radius',
                            command = setRadius,
                            command = setRadius,
                            min = 0.01,
                            min = 0.01,
-                           initialValue = force.getRadius())
+                           value = force.getRadius())
         self.createForceActiveWidget(frame, pageName, forceName, force)
         self.createForceActiveWidget(frame, pageName, forceName, force)
 
 
 ######################################################################
 ######################################################################

+ 60 - 90
direct/src/tkpanels/Placer.py

@@ -18,8 +18,8 @@ class Placer(AppShell):
     # Override class variables here
     # Override class variables here
     appname = 'Placer Panel'
     appname = 'Placer Panel'
     frameWidth      = 625
     frameWidth      = 625
-    frameHeight     = 290
-    usecommandarea = 1
+    frameHeight     = 215
+    usecommandarea = 0
     usestatusarea  = 0
     usestatusarea  = 0
 
 
     def __init__(self, parent = None, **kw):
     def __init__(self, parent = None, **kw):
@@ -82,6 +82,7 @@ class Placer(AppShell):
     def createInterface(self):
     def createInterface(self):
         # The interior of the toplevel panel
         # The interior of the toplevel panel
         interior = self.interior()
         interior = self.interior()
+        interior['relief'] = FLAT
         # Add placer commands to menubar
         # Add placer commands to menubar
         self.menuBar.addmenu('Placer', 'Placer Panel Operations')
         self.menuBar.addmenu('Placer', 'Placer Panel Operations')
         self.menuBar.addmenuitem('Placer', 'command',
         self.menuBar.addmenuitem('Placer', 'command',
@@ -159,20 +160,16 @@ class Placer(AppShell):
         self.redoButton.pack(side = 'left', expand = 0)
         self.redoButton.pack(side = 'left', expand = 0)
         self.bind(self.redoButton, 'Redo last operation')
         self.bind(self.redoButton, 'Redo last operation')
 
 
-        # The master frame for the dials
-        dialFrame = Frame(interior)
-        dialFrame.pack(fill = 'both', expand = 1)
-        
         # Create and pack the Pos Controls
         # Create and pack the Pos Controls
-        posGroup = Pmw.Group(dialFrame,
+        posGroup = Pmw.Group(interior,
                              tag_pyclass = Menubutton,
                              tag_pyclass = Menubutton,
                              tag_text = 'Position',
                              tag_text = 'Position',
-                             tag_font=('MSSansSerif', 14, 'bold'),
+                             tag_font=('MSSansSerif', 14),
                              tag_activebackground = '#909090',
                              tag_activebackground = '#909090',
-                             ring_relief = 'flat')
+                             ring_relief = RIDGE)
         posMenubutton = posGroup.component('tag')
         posMenubutton = posGroup.component('tag')
         self.bind(posMenubutton, 'Position menu operations')
         self.bind(posMenubutton, 'Position menu operations')
-        posMenu = Menu(posMenubutton)
+        posMenu = Menu(posMenubutton, tearoff = 0)
         posMenu.add_command(label = 'Set to zero', command = self.zeroPos)
         posMenu.add_command(label = 'Set to zero', command = self.zeroPos)
         posMenu.add_command(label = 'Reset initial',
         posMenu.add_command(label = 'Reset initial',
                             command = self.resetPos)
                             command = self.resetPos)
@@ -183,56 +180,50 @@ class Placer(AppShell):
         # Create the dials
         # Create the dials
         self.posX = self.createcomponent('posX', (), None,
         self.posX = self.createcomponent('posX', (), None,
                                          Floater.Floater, (posInterior,),
                                          Floater.Floater, (posInterior,),
-                                         text = 'X',
-                                         initialValue = 0.0,
+                                         text = 'X', relief = FLAT,
+                                         value = 0.0,
                                          label_foreground = 'Red')
                                          label_foreground = 'Red')
         self.posX['command'] = self.xform
         self.posX['command'] = self.xform
         self.posX['commandData'] = ['x']
         self.posX['commandData'] = ['x']
+        self.posX['preCallback'] = self.xformStart
+        self.posX['postCallback'] = self.xformStop
         self.posX['callbackData'] = ['x']
         self.posX['callbackData'] = ['x']
-        self.posX.onReturn = self.xformStart
-        self.posX.onReturnRelease = self.xformStop
-        self.posX.onPress = self.xformStart
-        self.posX.onRelease = self.xformStop
         self.posX.pack(expand=1,fill='both')
         self.posX.pack(expand=1,fill='both')
         
         
         self.posY = self.createcomponent('posY', (), None,
         self.posY = self.createcomponent('posY', (), None,
                                          Floater.Floater, (posInterior,),
                                          Floater.Floater, (posInterior,),
-                                         text = 'Y',
-                                         initialValue = 0.0,
+                                         text = 'Y', relief = FLAT,
+                                         value = 0.0,
                                          label_foreground = '#00A000')
                                          label_foreground = '#00A000')
         self.posY['command'] = self.xform
         self.posY['command'] = self.xform
         self.posY['commandData'] = ['y']
         self.posY['commandData'] = ['y']
+        self.posY['preCallback'] = self.xformStart
+        self.posY['postCallback'] = self.xformStop
         self.posY['callbackData'] = ['y']
         self.posY['callbackData'] = ['y']
-        self.posY.onReturn = self.xformStart
-        self.posY.onReturnRelease = self.xformStop
-        self.posY.onPress = self.xformStart
-        self.posY.onRelease = self.xformStop
         self.posY.pack(expand=1,fill='both')
         self.posY.pack(expand=1,fill='both')
         
         
         self.posZ = self.createcomponent('posZ', (), None,
         self.posZ = self.createcomponent('posZ', (), None,
                                          Floater.Floater, (posInterior,),
                                          Floater.Floater, (posInterior,),
-                                         text = 'Z',
-                                         initialValue = 0.0,
+                                         text = 'Z', relief = FLAT,
+                                         value = 0.0,
                                          label_foreground = 'Blue')
                                          label_foreground = 'Blue')
         self.posZ['command'] = self.xform
         self.posZ['command'] = self.xform
         self.posZ['commandData'] = ['z']
         self.posZ['commandData'] = ['z']
+        self.posZ['preCallback'] = self.xformStart
+        self.posZ['postCallback'] = self.xformStop
         self.posZ['callbackData'] = ['z']
         self.posZ['callbackData'] = ['z']
-        self.posZ.onReturn = self.xformStart
-        self.posZ.onReturnRelease = self.xformStop
-        self.posZ.onPress = self.xformStart
-        self.posZ.onRelease = self.xformStop
         self.posZ.pack(expand=1,fill='both')
         self.posZ.pack(expand=1,fill='both')
 
 
         # Create and pack the Hpr Controls
         # Create and pack the Hpr Controls
-        hprGroup = Pmw.Group(dialFrame,
+        hprGroup = Pmw.Group(interior,
                              tag_pyclass = Menubutton,
                              tag_pyclass = Menubutton,
                              tag_text = 'Orientation',
                              tag_text = 'Orientation',
-                             tag_font=('MSSansSerif', 14, 'bold'),
+                             tag_font=('MSSansSerif', 14),
                              tag_activebackground = '#909090',
                              tag_activebackground = '#909090',
-                             ring_relief = 'flat')
+                             ring_relief = RIDGE)
         hprMenubutton = hprGroup.component('tag')
         hprMenubutton = hprGroup.component('tag')
         self.bind(hprMenubutton, 'Orientation menu operations')
         self.bind(hprMenubutton, 'Orientation menu operations')
-        hprMenu = Menu(hprMenubutton)
+        hprMenu = Menu(hprMenubutton, tearoff = 0)
         hprMenu.add_command(label = 'Set to zero', command = self.zeroHpr)
         hprMenu.add_command(label = 'Set to zero', command = self.zeroHpr)
         hprMenu.add_command(label = 'Reset initial', command = self.resetHpr)
         hprMenu.add_command(label = 'Reset initial', command = self.resetHpr)
         hprMenubutton['menu'] = hprMenu
         hprMenubutton['menu'] = hprMenu
@@ -242,41 +233,41 @@ class Placer(AppShell):
         # Create the dials
         # Create the dials
         self.hprH = self.createcomponent('hprH', (), None,
         self.hprH = self.createcomponent('hprH', (), None,
                                          Dial.AngleDial, (hprInterior,),
                                          Dial.AngleDial, (hprInterior,),
+                                         style = Dial.DIAL_MINI,
                                          text = 'H', value = 0.0,
                                          text = 'H', value = 0.0,
+                                         relief = FLAT,
                                          label_foreground = 'blue')
                                          label_foreground = 'blue')
         self.hprH['command'] = self.xform
         self.hprH['command'] = self.xform
         self.hprH['commandData'] = ['h']
         self.hprH['commandData'] = ['h']
+        self.hprH['preCallback'] = self.xformStart
+        self.hprH['postCallback'] = self.xformStop
         self.hprH['callbackData'] = ['h']
         self.hprH['callbackData'] = ['h']
-        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.hprH.pack(expand=1,fill='both')
         
         
         self.hprP = self.createcomponent('hprP', (), None,
         self.hprP = self.createcomponent('hprP', (), None,
                                          Dial.AngleDial, (hprInterior,),
                                          Dial.AngleDial, (hprInterior,),
+                                         style = Dial.DIAL_MINI,
                                          text = 'P', value = 0.0,
                                          text = 'P', value = 0.0,
+                                         relief = FLAT,
                                          label_foreground = 'red')
                                          label_foreground = 'red')
         self.hprP['command'] = self.xform
         self.hprP['command'] = self.xform
         self.hprP['commandData'] = ['p']
         self.hprP['commandData'] = ['p']
+        self.hprP['preCallback'] = self.xformStart
+        self.hprP['postCallback'] = self.xformStop
         self.hprP['callbackData'] = ['p']
         self.hprP['callbackData'] = ['p']
-        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.hprP.pack(expand=1,fill='both')
         
         
         self.hprR = self.createcomponent('hprR', (), None,
         self.hprR = self.createcomponent('hprR', (), None,
                                          Dial.AngleDial, (hprInterior,),
                                          Dial.AngleDial, (hprInterior,),
+                                         style = Dial.DIAL_MINI,
                                          text = 'R', value = 0.0,
                                          text = 'R', value = 0.0,
+                                         relief = FLAT,
                                          label_foreground = '#00A000')
                                          label_foreground = '#00A000')
         self.hprR['command'] = self.xform
         self.hprR['command'] = self.xform
         self.hprR['commandData'] = ['r']
         self.hprR['commandData'] = ['r']
+        self.hprR['preCallback'] = self.xformStart
+        self.hprR['postCallback'] = self.xformStop
         self.hprR['callbackData'] = ['r']
         self.hprR['callbackData'] = ['r']
-        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')
         self.hprR.pack(expand=1,fill='both')
 
 
         # Create and pack the Scale Controls
         # Create and pack the Scale Controls
@@ -284,18 +275,18 @@ class Placer(AppShell):
         self.scalingMode = StringVar()
         self.scalingMode = StringVar()
         self.scalingMode.set('Scale Uniform')
         self.scalingMode.set('Scale Uniform')
         # The scaling widgets
         # The scaling widgets
-        scaleGroup = Pmw.Group(dialFrame,
+        scaleGroup = Pmw.Group(interior,
                                tag_text = 'Scale Uniform',
                                tag_text = 'Scale Uniform',
                                tag_pyclass = Menubutton,
                                tag_pyclass = Menubutton,
-                               tag_font=('MSSansSerif', 14, 'bold'),
+                               tag_font=('MSSansSerif', 14),
                                tag_activebackground = '#909090',
                                tag_activebackground = '#909090',
-                               ring_relief = 'flat')
+                               ring_relief = RIDGE)
         self.scaleMenubutton = scaleGroup.component('tag')
         self.scaleMenubutton = scaleGroup.component('tag')
         self.bind(self.scaleMenubutton, 'Scale menu operations')
         self.bind(self.scaleMenubutton, 'Scale menu operations')
         self.scaleMenubutton['textvariable'] = self.scalingMode
         self.scaleMenubutton['textvariable'] = self.scalingMode
 
 
         # Scaling menu
         # Scaling menu
-        scaleMenu = Menu(self.scaleMenubutton)
+        scaleMenu = Menu(self.scaleMenubutton, tearoff = 0)
         scaleMenu.add_command(label = 'Set to unity',
         scaleMenu.add_command(label = 'Set to unity',
                               command = self.unitScale)
                               command = self.unitScale)
         scaleMenu.add_command(label = 'Reset initial',
         scaleMenu.add_command(label = 'Reset initial',
@@ -313,48 +304,45 @@ class Placer(AppShell):
         
         
         # Create the dials
         # Create the dials
         self.scaleX = self.createcomponent('scaleX', (), None,
         self.scaleX = self.createcomponent('scaleX', (), None,
-                                           Dial.Dial, (scaleInterior,),
+                                           Floater.Floater, (scaleInterior,),
                                            text = 'X Scale',
                                            text = 'X Scale',
+                                           relief = FLAT,
                                            min = 0.0001, value = 1.0,
                                            min = 0.0001, value = 1.0,
                                            resetValue = 1.0,
                                            resetValue = 1.0,
                                            label_foreground = 'Red')
                                            label_foreground = 'Red')
         self.scaleX['command'] = self.xform
         self.scaleX['command'] = self.xform
         self.scaleX['commandData'] = ['sx']
         self.scaleX['commandData'] = ['sx']
         self.scaleX['callbackData'] = ['sx']
         self.scaleX['callbackData'] = ['sx']
-        self.scaleX['onReturnPress'] = self.xformStart
-        self.scaleX['onReturnRelease'] = self.xformStop
-        self.scaleX['onButtonPress'] = self.xformStart
-        self.scaleX['onButtonRelease'] = self.xformStop
+        self.scaleX['preCallback'] = self.xformStart
+        self.scaleX['postCallback'] = self.xformStop
         self.scaleX.pack(expand=1,fill='both')
         self.scaleX.pack(expand=1,fill='both')
         
         
         self.scaleY = self.createcomponent('scaleY', (), None,
         self.scaleY = self.createcomponent('scaleY', (), None,
-                                           Dial.Dial, (scaleInterior,),
+                                           Floater.Floater, (scaleInterior,),
                                            text = 'Y Scale',
                                            text = 'Y Scale',
+                                           relief = FLAT,
                                            min = 0.0001, value = 1.0,
                                            min = 0.0001, value = 1.0,
                                            resetValue = 1.0,
                                            resetValue = 1.0,
                                            label_foreground = '#00A000')
                                            label_foreground = '#00A000')
         self.scaleY['command'] = self.xform
         self.scaleY['command'] = self.xform
         self.scaleY['commandData'] = ['sy']
         self.scaleY['commandData'] = ['sy']
         self.scaleY['callbackData'] = ['sy']
         self.scaleY['callbackData'] = ['sy']
-        self.scaleY['onReturnPress'] = self.xformStart
-        self.scaleY['onReturnRelease'] = self.xformStop
-        self.scaleY['onButtonPress'] = self.xformStart
-        self.scaleY['onButtonRelease'] = self.xformStop
+        self.scaleY['preCallback'] = self.xformStart
+        self.scaleY['postCallback'] = self.xformStop
         self.scaleY.pack(expand=1,fill='both')
         self.scaleY.pack(expand=1,fill='both')
         
         
         self.scaleZ = self.createcomponent('scaleZ', (), None,
         self.scaleZ = self.createcomponent('scaleZ', (), None,
-                                           Dial.Dial, (scaleInterior,),
+                                           Floater.Floater, (scaleInterior,),
                                            text = 'Z Scale',
                                            text = 'Z Scale',
+                                           relief = FLAT,
                                            min = 0.0001, value = 1.0,
                                            min = 0.0001, value = 1.0,
                                            resetValue = 1.0,
                                            resetValue = 1.0,
                                            label_foreground = 'Blue')
                                            label_foreground = 'Blue')
         self.scaleZ['command'] = self.xform
         self.scaleZ['command'] = self.xform
         self.scaleZ['commandData'] = ['sz']
         self.scaleZ['commandData'] = ['sz']
         self.scaleZ['callbackData'] = ['sz']
         self.scaleZ['callbackData'] = ['sz']
-        self.scaleZ['onReturnPress'] = self.xformStart
-        self.scaleZ['onReturnRelease'] = self.xformStop
-        self.scaleZ['onButtonPress'] = self.xformStart
-        self.scaleZ['onButtonRelease'] = self.xformStop
+        self.scaleZ['preCallback'] = self.xformStart
+        self.scaleZ['postCallback'] = self.xformStop
         self.scaleZ.pack(expand=1,fill='both')
         self.scaleZ.pack(expand=1,fill='both')
 
 
         # Make sure appropriate labels are showing
         # Make sure appropriate labels are showing
@@ -363,33 +351,6 @@ class Placer(AppShell):
         self.selectNodePathNamed('init')
         self.selectNodePathNamed('init')
         self.selectRefNodePathNamed('parent')
         self.selectRefNodePathNamed('parent')
 
 
-        self.createButtons()
-
-    def createButtons(self):
-        self.buttonAdd('Zero All',
-                       helpMessage='Zero Node Path',
-                       statusMessage='Zero Node Path',
-                       command=self.zeroAll)
-        self.buttonAdd('Reset All',
-                       helpMessage='Reset Node Path',
-                       statusMessage='Reset Node Path',
-                       command=self.resetAll)
-        self.buttonAdd('Print Info',
-                       helpMessage='Print Node Path Info',
-                       statusMessage='Print Node Path Info',
-                       command=self.printNodePathInfo)
-        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()
 
 
     ### WIDGET OPERATIONS ###
     ### WIDGET OPERATIONS ###
     def setMovementMode(self, movementMode):
     def setMovementMode(self, movementMode):
@@ -715,8 +676,17 @@ class Placer(AppShell):
 
 
     def updateResetValues(self, nodePath):
     def updateResetValues(self, nodePath):
         self.initPos.assign(nodePath.getPos())
         self.initPos.assign(nodePath.getPos())
+        self.posX['resetValue'] = self.initPos[0]
+        self.posY['resetValue'] = self.initPos[1]
+        self.posZ['resetValue'] = self.initPos[2]
         self.initHpr.assign(nodePath.getHpr())
         self.initHpr.assign(nodePath.getHpr())
+        self.hprH['resetValue'] = self.initHpr[0]
+        self.hprP['resetValue'] = self.initHpr[1]
+        self.hprR['resetValue'] = self.initHpr[2]
         self.initScale.assign(nodePath.getScale())
         self.initScale.assign(nodePath.getScale())
+        self.scaleX['resetValue'] = self.initScale[0]
+        self.scaleY['resetValue'] = self.initScale[1]
+        self.scaleZ['resetValue'] = self.initScale[2]
 
 
     def resetAll(self):
     def resetAll(self):
         if self['nodePath']:
         if self['nodePath']:

+ 2 - 2
direct/src/tkwidgets/AppShell.py

@@ -328,14 +328,14 @@ class AppShell(Pmw.MegaWidget, PandaObject):
         return widget
         return widget
 
 
     def newCreateLabeledEntry(self, parent, category, text, help = '', 
     def newCreateLabeledEntry(self, parent, category, text, help = '', 
-                              command = None, initialValue = '',
+                              command = None, value = '',
                               width = 12, relief = SUNKEN,
                               width = 12, relief = SUNKEN,
                               side = LEFT, fill = X, expand = 0):
                               side = LEFT, fill = X, expand = 0):
         """ createLabeledEntry(parent, category, text, [options]) """
         """ createLabeledEntry(parent, category, text, [options]) """
         # Create labeled entry
         # Create labeled entry
         frame = Frame(parent)
         frame = Frame(parent)
         variable = StringVar()
         variable = StringVar()
-        variable.set(initialValue)
+        variable.set(value)
         label = Label(frame, text = text)
         label = Label(frame, text = text)
         label.pack(side = LEFT, fill = X, expand = 0)
         label.pack(side = LEFT, fill = X, expand = 0)
         entry = Entry(frame, width = width, relief = relief,
         entry = Entry(frame, width = width, relief = relief,

+ 96 - 65
direct/src/tkwidgets/Dial.py

@@ -1,6 +1,6 @@
 from Tkinter import *
 from Tkinter import *
 from PandaModules import ClockObject
 from PandaModules import ClockObject
-from WidgetPropertiesDialog import *
+import WidgetPropertiesDialog
 import Pmw
 import Pmw
 import Task
 import Task
 import math
 import math
@@ -17,7 +17,7 @@ DIAL_FULL = 'full'
 DIAL_MINI = 'mini'
 DIAL_MINI = 'mini'
 
 
 DIAL_FULL_SIZE = 45
 DIAL_FULL_SIZE = 45
-DIAL_MINI_SIZE = 20
+DIAL_MINI_SIZE = 30
 
 
 globalClock = ClockObject.getGlobalClock()
 globalClock = ClockObject.getGlobalClock()
 
 
@@ -29,13 +29,8 @@ class Dial(Pmw.MegaWidget):
     def __init__(self, parent = None, **kw):
     def __init__(self, parent = None, **kw):
         #define the megawidget options
         #define the megawidget options
         INITOPT = Pmw.INITOPT
         INITOPT = Pmw.INITOPT
-        if 'full' == kw.get('style', DIAL_FULL):
-            DIAL_SIZE = DIAL_FULL_SIZE
-        else:
-            DIAL_SIZE = DIAL_MINI_SIZE
         optiondefs = (
         optiondefs = (
             ('style',             DIAL_FULL,      INITOPT),
             ('style',             DIAL_FULL,      INITOPT),
-            ('dial_size',         DIAL_SIZE,      None),
             # Widget relief
             # Widget relief
             ('relief',            GROOVE,         None),
             ('relief',            GROOVE,         None),
             # Widget borderwidth
             # Widget borderwidth
@@ -46,21 +41,30 @@ class Dial(Pmw.MegaWidget):
             ('numDigits',         2,              self.setEntryFormat),
             ('numDigits',         2,              self.setEntryFormat),
             ('command',           None,           None),
             ('command',           None,           None),
             ('commandData',       [],             None),
             ('commandData',       [],             None),
-            ('callbackData',      [],             self.setCallbackData),
             ('min',               None,           self.setMin),
             ('min',               None,           self.setMin),
             ('max',               None,           self.setMax),
             ('max',               None,           self.setMax),
             ('base',              0.0,            self.setBase),
             ('base',              0.0,            self.setBase),
             ('delta',             1.0,            self.setDelta),
             ('delta',             1.0,            self.setDelta),
-            ('onReturnPress',     None,           None),
-            ('onReturnRelease',   None,           None),
-            ('onButtonPress',     None,           self.setButtonPressCmd),
-            ('onButtonRelease',   None,           self.setButtonReleaseCmd),
+            # Callbacks to execute when updating widget's value
+            ('preCallback',       None,           self.setPreCallbackCmd),
+            ('postCallback',      None,           self.setPostCallbackCmd),
+            # Extra data to be passed to callback function, needs to be a list
+            ('callbackData',      [],             self.setCallbackData),
             )
             )
         self.defineoptions(kw, optiondefs)
         self.defineoptions(kw, optiondefs)
         
         
         # Initialize the superclass
         # Initialize the superclass
         Pmw.MegaWidget.__init__(self, parent)
         Pmw.MegaWidget.__init__(self, parent)
 
 
+        # Override size if style specified by size is not
+        if not kw.has_key('dial_size'):
+            if self['style'] == DIAL_FULL:
+                dialSize = DIAL_FULL_SIZE
+            else:
+                dialSize = DIAL_MINI_SIZE
+        else:
+            dialSize = DIAL_FULL_SIZE
+
         # Create the components
         # Create the components
         interior = self.interior()
         interior = self.interior()
         interior.configure(relief = self['relief'], bd = self['borderwidth'])
         interior.configure(relief = self['relief'], bd = self['borderwidth'])
@@ -68,15 +72,24 @@ class Dial(Pmw.MegaWidget):
         # The Dial 
         # The Dial 
         self._dial = self.createcomponent('dial', (), None,
         self._dial = self.createcomponent('dial', (), None,
                                           DialWidget, (interior,),
                                           DialWidget, (interior,),
+                                          size = dialSize,
                                           command = self.setEntry,
                                           command = self.setEntry,
                                           value = self['value'])
                                           value = self['value'])
 
 
-        self._dial.propertyDict['numDigits'] = {
-            'widget' : self,
-            'type' : 'integer',
-            'help' : 'Enter number of digits after decimal point.'
-            }
-        self._dial.propertyList.append('numDigits')
+        self._dial.addPropertyToDialog(
+            'text',
+            {'widget' : self,
+             'type' : 'string',
+             'help' : 'Enter label text for Dial.'
+             }
+            )
+        self._dial.addPropertyToDialog(
+            'numDigits',
+            {'widget' : self,
+             'type' : 'integer',
+             'help' : 'Enter number of digits after decimal point.'
+             }
+            )
 
 
         # The Label
         # The Label
         self._label = self.createcomponent('label', (), None,
         self._label = self.createcomponent('label', (), None,
@@ -99,14 +112,14 @@ class Dial(Pmw.MegaWidget):
 
 
         if self['style'] == DIAL_FULL:
         if self['style'] == DIAL_FULL:
             # Attach dial to entry
             # Attach dial to entry
-            self._dial.grid(rowspan = 2, columnspan = 2)
+            self._dial.grid(rowspan = 2, columnspan = 2, padx = 2, pady = 2)
             self._label.grid(row = 0, col = 2, sticky = EW)
             self._label.grid(row = 0, col = 2, sticky = EW)
             self._entry.grid(row = 1, col = 2, sticky = EW)
             self._entry.grid(row = 1, col = 2, sticky = EW)
             interior.columnconfigure(2, weight = 1)
             interior.columnconfigure(2, weight = 1)
         else:
         else:
             self._label.grid(row=0,col=0, sticky = EW)
             self._label.grid(row=0,col=0, sticky = EW)
             self._entry.grid(row=0,col=1, sticky = EW)
             self._entry.grid(row=0,col=1, sticky = EW)
-            self._dial.grid(row=0,col=2)
+            self._dial.grid(row=0,col=2, padx = 2, pady = 2)
             interior.columnconfigure(0, weight = 1)
             interior.columnconfigure(0, weight = 1)
 
 
         # Make sure input variables processed 
         # Make sure input variables processed 
@@ -144,13 +157,13 @@ class Dial(Pmw.MegaWidget):
 
 
     def _onReturnPress(self, *args):
     def _onReturnPress(self, *args):
         """ User redefinable callback executed on <Return> in entry """
         """ User redefinable callback executed on <Return> in entry """
-        if self['onReturnPress']:
-            apply(self['onReturnPress'], self['callbackData'])
+        if self['preCallback']:
+            apply(self['preCallback'], self['callbackData'])
 
 
     def _onReturnRelease(self, *args):
     def _onReturnRelease(self, *args):
         """ User redefinable callback executed on <Return> release in entry """
         """ User redefinable callback executed on <Return> release in entry """
-        if self['onReturnRelease']:
-            apply(self['onReturnRelease'], self['callbackData'])
+        if self['postCallback']:
+            apply(self['postCallback'], self['callbackData'])
 
 
     # Pass settings down to dial
     # Pass settings down to dial
     def setCallbackData(self):
     def setCallbackData(self):
@@ -175,11 +188,12 @@ class Dial(Pmw.MegaWidget):
     def setLabel(self):
     def setLabel(self):
         self._label['text'] = self['text']
         self._label['text'] = self['text']
 
 
-    def setButtonPressCmd(self):
-        self._dial['onButtonPress'] = self['onButtonPress']
+    def setPreCallbackCmd(self):
+        self._dial['preCallback'] = self['preCallback']
+
+    def setPostCallbackCmd(self):
+        self._dial['postCallback'] = self['postCallback']
 
 
-    def setButtonReleaseCmd(self):
-        self._dial['onButtonRelease'] = self['onButtonRelease']
 
 
 class AngleDial(Dial):
 class AngleDial(Dial):
     def __init__(self, parent = None, **kw):
     def __init__(self, parent = None, **kw):
@@ -237,10 +251,11 @@ class DialWidget(Pmw.MegaWidget):
             ('command',         None,           None),
             ('command',         None,           None),
             # Extra data to be passed to command function
             # Extra data to be passed to command function
             ('commandData',     [],             None),
             ('commandData',     [],             None),
-            # Extra data to be passed to callback function
+            # 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),
             ('callbackData',    [],             None),
-            ('onButtonPress',   None,           None),
-            ('onButtonRelease', None,           None),
             )
             )
         self.defineoptions(kw, optiondefs)
         self.defineoptions(kw, optiondefs)
         
         
@@ -262,31 +277,6 @@ class DialWidget(Pmw.MegaWidget):
         # Radius of the inner knob
         # Radius of the inner knob
         inner_radius = max(3,radius * INNER_SF)
         inner_radius = max(3,radius * INNER_SF)
 
 
-        # A Dictionary of dictionaries
-        self.propertyDict = {
-            'min' : { 'widget' : self,
-                      'type' : 'real',
-                      'fNone' : 1,
-                      'help' : 'Minimum allowable dial value, Enter None for no minimum'},
-            'max' : { 'widget' : self,
-                      'type' : 'real',
-                      'fNone' : 1,
-                      'help' : 'Maximum allowable dial value, Enter None for no maximum'},
-            'base' : { 'widget' : self,
-                       'type' : 'real',
-                       'help' : 'Dial value = base + delta * numRevs'},
-            'delta' : { 'widget' : self,
-                        'type' : 'real',
-                        'help' : 'Dial value = base + delta * numRevs'},
-            'numSegments' : { 'widget' : self,
-                              'type' : 'integer',
-                              'help' : 'Number of segments to divide dial into'},
-            'resetValue' : { 'widget' : self,
-                             'type' : 'real',
-                             'help' : 'Enter value to set dial to on reset.'}
-            }
-        self.propertyList = ['min', 'max', 'base', 'delta', 'numSegments', 'resetValue']
-
         # The canvas 
         # The canvas 
         self._canvas = self.createcomponent('canvas', (), None,
         self._canvas = self.createcomponent('canvas', (), None,
                                             Canvas, (interior,),
                                             Canvas, (interior,),
@@ -312,6 +302,32 @@ class DialWidget(Pmw.MegaWidget):
                                  fill = '#A0A0A0',
                                  fill = '#A0A0A0',
                                  tags = ('knob',))
                                  tags = ('knob',))
 
 
+        # A Dictionary of dictionaries used for the popup property dialog
+        self.propertyDict = {
+            'min' : { 'widget' : self,
+                      'type' : 'real',
+                      'fNone' : 1,
+                      'help' : 'Minimum allowable dial value, Enter None for no minimum'},
+            'max' : { 'widget' : self,
+                      'type' : 'real',
+                      'fNone' : 1,
+                      'help' : 'Maximum allowable dial value, Enter None for no maximum'},
+            'base' : { 'widget' : self,
+                       'type' : 'real',
+                       'help' : 'Dial value = base + delta * numRevs'},
+            'delta' : { 'widget' : self,
+                        'type' : 'real',
+                        'help' : 'Dial value = base + delta * numRevs'},
+            'numSegments' : { 'widget' : self,
+                              'type' : 'integer',
+                              'help' : 'Number of segments to divide dial into'},
+            'resetValue' : { 'widget' : self,
+                             'type' : 'real',
+                             'help' : 'Enter value to set dial to on reset.'}
+            }
+        self.propertyList = ['min', 'max', 'base', 'delta',
+                             'resetValue', 'numSegments']
+
         # The popup menu
         # The popup menu
         self._popupMenu = Menu(interior, tearoff = 0)
         self._popupMenu = Menu(interior, tearoff = 0)
         self._fSnap = IntVar()
         self._fSnap = IntVar()
@@ -325,8 +341,11 @@ class DialWidget(Pmw.MegaWidget):
             self._popupMenu.add_checkbutton(label = 'Rollover',
             self._popupMenu.add_checkbutton(label = 'Rollover',
                                             variable = self._fRollover,
                                             variable = self._fRollover,
                                             command = self.setRollover)
                                             command = self.setRollover)
-            self._popupMenu.add_command(label = 'Properties...',
-                                        command = self.getProperties)
+            self._popupMenu.add_command(
+                label = 'Properties...',
+                command = self.popupPropertiesDialog)
+        self._popupMenu.add_command(label = 'Zero Dial',
+                                    command = self.zero)
         self._popupMenu.add_command(label = 'Reset Dial',
         self._popupMenu.add_command(label = 'Reset Dial',
                                     command = self.reset)
                                     command = self.reset)
 
 
@@ -375,6 +394,14 @@ class DialWidget(Pmw.MegaWidget):
         # Record value
         # Record value
         self.value = value
         self.value = value
     
     
+    # Set floater to zero
+    def zero(self):
+        """
+        self.reset()
+        Set dial to zero
+        """
+        self.set(0.0)
+
     # Reset dial to reset value
     # Reset dial to reset value
     def reset(self):
     def reset(self):
         """
         """
@@ -384,6 +411,7 @@ class DialWidget(Pmw.MegaWidget):
         self.set(self['resetValue'])
         self.set(self['resetValue'])
 
 
     def mouseReset(self,event):
     def mouseReset(self,event):
+        # If not over any canvas item
         if not self._canvas.find_withtag(CURRENT):
         if not self._canvas.find_withtag(CURRENT):
             self.reset()
             self.reset()
         
         
@@ -465,7 +493,6 @@ class DialWidget(Pmw.MegaWidget):
         # Update value
         # Update value
         currT = globalClock.getFrameTime()
         currT = globalClock.getFrameTime()
         dt = currT - state.lastTime
         dt = currT - state.lastTime
-        #self.set(self.value + self['delta'] * self.knobSF * dt)
         self.set(self.value + self.knobSF * dt)
         self.set(self.value + self.knobSF * dt)
         state.lastTime = currT
         state.lastTime = currT
         return Task.cont
         return Task.cont
@@ -548,24 +575,28 @@ class DialWidget(Pmw.MegaWidget):
         self['fRollover'] = self._fRollover.get()
         self['fRollover'] = self._fRollover.get()
 
 
     # This handles the popup dial min dialog
     # This handles the popup dial min dialog
-    def getProperties(self):
+    def popupPropertiesDialog(self):
         # Popup dialog to adjust widget properties
         # Popup dialog to adjust widget properties
-        WidgetPropertiesDialog(
+        WidgetPropertiesDialog.WidgetPropertiesDialog(
             self.propertyDict,
             self.propertyDict,
             propertyList = self.propertyList,
             propertyList = self.propertyList,
             title = 'Dial Widget Properties',
             title = 'Dial Widget Properties',
             parent = self._canvas)
             parent = self._canvas)
+
+    def addPropertyToDialog(self, property, pDict):
+        self.propertyDict[property] = pDict
+        self.propertyList.append(property)
             
             
     # User callbacks
     # User callbacks
     def _onButtonPress(self, *args):
     def _onButtonPress(self, *args):
         """ User redefinable callback executed on button press """
         """ User redefinable callback executed on button press """
-        if self['onButtonPress']:
-            apply(self['onButtonPress'], self['callbackData'])
+        if self['preCallback']:
+            apply(self['preCallback'], self['callbackData'])
 
 
     def _onButtonRelease(self, *args):
     def _onButtonRelease(self, *args):
         """ User redefinable callback executed on button release """
         """ User redefinable callback executed on button release """
-        if self['onButtonRelease']:
-            apply(self['onButtonRelease'], self['callbackData'])
+        if self['postCallback']:
+            apply(self['postCallback'], self['callbackData'])
 
 
   
   
 if __name__ == '__main__':
 if __name__ == '__main__':

+ 29 - 21
direct/src/tkwidgets/EntryScale.py

@@ -19,14 +19,16 @@ class EntryScale(Pmw.MegaWidget):
 
 
         # Define the megawidget options.
         # Define the megawidget options.
         optiondefs = (
         optiondefs = (
-            ('initialValue',        0.0,           Pmw.INITOPT),
+            ('value',        0.0,           Pmw.INITOPT),
             ('resolution',          0.001,         None),
             ('resolution',          0.001,         None),
             ('command',             None,          None),
             ('command',             None,          None),
+            ('preCallback',         None,          None),
+            ('postCallback',        None,          None),
             ('callbackData',        [],            None),
             ('callbackData',        [],            None),
             ('min',                 0.0,           self._updateValidate),
             ('min',                 0.0,           self._updateValidate),
             ('max',                 100.0,         self._updateValidate),
             ('max',                 100.0,         self._updateValidate),
             ('text',                'EntryScale',  self._updateLabelText),
             ('text',                'EntryScale',  self._updateLabelText),
-            ('significantDigits',   2,             self._setSigDigits),
+            ('numDigits',   2,             self._setSigDigits),
             )
             )
         self.defineoptions(kw, optiondefs)
         self.defineoptions(kw, optiondefs)
  
  
@@ -34,7 +36,7 @@ class EntryScale(Pmw.MegaWidget):
         Pmw.MegaWidget.__init__(self, parent)
         Pmw.MegaWidget.__init__(self, parent)
 
 
         # Initialize some class variables
         # Initialize some class variables
-        self.value = self['initialValue']
+        self.value = self['value']
         self.entryFormat = '%.2f'
         self.entryFormat = '%.2f'
         self.fScaleCommand = 0
         self.fScaleCommand = 0
 
 
@@ -49,7 +51,7 @@ class EntryScale(Pmw.MegaWidget):
                                                Frame, interior)
                                                Frame, interior)
         # Create an entry field to display and validate the entryScale's value
         # Create an entry field to display and validate the entryScale's value
         self.entryValue = StringVar()
         self.entryValue = StringVar()
-        self.entryValue.set(self['initialValue'])
+        self.entryValue.set(self['value'])
         self.entry = self.createcomponent('entryField',
         self.entry = self.createcomponent('entryField',
                                           # Access widget's entry using "entry"
                                           # Access widget's entry using "entry"
                                           (('entry', 'entryField_entry'),),
                                           (('entry', 'entryField_entry'),),
@@ -105,7 +107,7 @@ class EntryScale(Pmw.MegaWidget):
                                           showvalue = 0)
                                           showvalue = 0)
         self.scale.pack(side = 'left', expand = 1, fill = 'x')
         self.scale.pack(side = 'left', expand = 1, fill = 'x')
         # Set scale to the middle of its range
         # Set scale to the middle of its range
-        self.scale.set(self['initialValue'])
+        self.scale.set(self['value'])
         self.scale.bind('<Button-1>', self.__onPress)
         self.scale.bind('<Button-1>', self.__onPress)
         self.scale.bind('<ButtonRelease-1>', self.__onRelease)
         self.scale.bind('<ButtonRelease-1>', self.__onRelease)
         self.scale.bind('<Button-3>', self.askForResolution)
         self.scale.bind('<Button-3>', self.askForResolution)
@@ -218,7 +220,7 @@ class EntryScale(Pmw.MegaWidget):
             pass
             pass
 
 
     def _setSigDigits(self):
     def _setSigDigits(self):
-        sd = self['significantDigits']
+        sd = self['numDigits']
         self.entryFormat = '%.' + '%d' % sd + 'f'
         self.entryFormat = '%.' + '%d' % sd + 'f'
         # And reset value to reflect change
         # And reset value to reflect change
         self.entryValue.set( self.entryFormat % self.value )
         self.entryValue.set( self.entryFormat % self.value )
@@ -260,7 +262,8 @@ class EntryScale(Pmw.MegaWidget):
 
 
     def __onPress(self, event):
     def __onPress(self, event):
         # First execute onpress callback
         # First execute onpress callback
-        apply(self.onPress, self['callbackData'])
+        if self['preCallback']:
+            apply(self['preCallback'], self['callbackData'])
         # Now enable slider command
         # Now enable slider command
         self.fScaleCommand = 1
         self.fScaleCommand = 1
 
 
@@ -272,7 +275,8 @@ class EntryScale(Pmw.MegaWidget):
         # Now disable slider command
         # Now disable slider command
         self.fScaleCommand = 0
         self.fScaleCommand = 0
         # First execute onpress callback
         # First execute onpress callback
-        apply(self.onRelease, self['callbackData'])
+        if self['postCallback']:
+            apply(self['postCallback'], self['callbackData'])
 
 
     def onRelease(self, *args):
     def onRelease(self, *args):
         """ User redefinable callback executed on button release """
         """ User redefinable callback executed on button release """
@@ -295,9 +299,11 @@ class EntryScaleGroup(Pmw.MegaToplevel):
             ('side',            TOP,                    INITOPT),
             ('side',            TOP,                    INITOPT),
             ('title',           'Group',                None),
             ('title',           'Group',                None),
             # A tuple of initial values, one for each entryScale
             # A tuple of initial values, one for each entryScale
-            ('initialValue',    DEFAULT_VALUE,          INITOPT),
+            ('value',    DEFAULT_VALUE,          INITOPT),
             # The command to be executed any time one of the entryScales is updated
             # The command to be executed any time one of the entryScales is updated
             ('command',         None,                   None),
             ('command',         None,                   None),
+            ('preCallback',     None,                   None),
+            ('postCallback',    None,                   None),
             # A tuple of labels, one for each entryScale
             # A tuple of labels, one for each entryScale
             ('labels',          DEFAULT_LABELS,         self._updateLabels),
             ('labels',          DEFAULT_LABELS,         self._updateLabels),
             # Destroy or withdraw
             # Destroy or withdraw
@@ -311,7 +317,7 @@ class EntryScaleGroup(Pmw.MegaToplevel):
         # Create the components
         # Create the components
         interior = self.interior()
         interior = self.interior()
         # Get a copy of the initial value (making sure its a list)
         # Get a copy of the initial value (making sure its a list)
-        self._value = list(self['initialValue'])
+        self._value = list(self['value'])
 
 
         # The Menu Bar
         # The Menu Bar
         self.balloon = Pmw.Balloon()
         self.balloon = Pmw.Balloon()
@@ -349,7 +355,7 @@ class EntryScaleGroup(Pmw.MegaToplevel):
             #   fg.configure(Valuator_XXX = YYY)
             #   fg.configure(Valuator_XXX = YYY)
             f = self.createcomponent(
             f = self.createcomponent(
                 'entryScale%d' % index, (), 'Valuator', EntryScale,
                 'entryScale%d' % index, (), 'Valuator', EntryScale,
-                (interior,), initialValue = self._value[index],
+                (interior,), value = self._value[index],
                 text = self['labels'][index])
                 text = self['labels'][index])
             # Do this separately so command doesn't get executed during construction
             # Do this separately so command doesn't get executed during construction
             f['command'] = lambda val, s=self, i=index: s._entryScaleSetAt(i, val)
             f['command'] = lambda val, s=self, i=index: s._entryScaleSetAt(i, val)
@@ -357,13 +363,13 @@ class EntryScaleGroup(Pmw.MegaToplevel):
             # Callbacks
             # Callbacks
             f.onReturn = self.__onReturn
             f.onReturn = self.__onReturn
             f.onReturnRelease = self.__onReturnRelease
             f.onReturnRelease = self.__onReturnRelease
-            f.onPress = self.__onPress
-            f.onRelease = self.__onRelease
+            f['preCallback'] = self.__onPress
+            f['postCallback'] = self.__onRelease
             f.pack(side = self['side'], expand = 1, fill = X)
             f.pack(side = self['side'], expand = 1, fill = X)
             self.entryScaleList.append(f)
             self.entryScaleList.append(f)
 
 
         # Make sure entryScales are initialized
         # Make sure entryScales are initialized
-        self.set(self['initialValue'])
+        self.set(self['value'])
         
         
         # Make sure input variables processed 
         # Make sure input variables processed 
         self.initialiseoptions(EntryScaleGroup)
         self.initialiseoptions(EntryScaleGroup)
@@ -405,7 +411,7 @@ class EntryScaleGroup(Pmw.MegaToplevel):
             self['command'](self._value)
             self['command'](self._value)
 
 
     def reset(self):
     def reset(self):
-        self.set(self['initialValue'])
+        self.set(self['value'])
 
 
     def __onReturn(self, esg):
     def __onReturn(self, esg):
         # Execute onReturn callback
         # Execute onReturn callback
@@ -425,7 +431,8 @@ class EntryScaleGroup(Pmw.MegaToplevel):
 
 
     def __onPress(self, esg):
     def __onPress(self, esg):
         # Execute onPress callback
         # Execute onPress callback
-        apply(self.onPress, esg.get())
+        if self['preCallback']:
+            apply(self['preCallback'], esg.get())
 
 
     def onPress(self, *args):
     def onPress(self, *args):
         """ User redefinable callback executed on button press """
         """ User redefinable callback executed on button press """
@@ -433,7 +440,8 @@ class EntryScaleGroup(Pmw.MegaToplevel):
 
 
     def __onRelease(self, esg):
     def __onRelease(self, esg):
         # Execute onRelease callback
         # Execute onRelease callback
-        apply(self.onRelease, esg.get())
+        if self['postCallback']:
+            apply(self['postCallback'], esg.get())
 
 
     def onRelease(self, *args):
     def onRelease(self, *args):
         """ User redefinable callback executed on button release """
         """ User redefinable callback executed on button release """
@@ -455,7 +463,7 @@ def rgbPanel(nodePath, callback = None):
     esg = EntryScaleGroup(title = 'RGBA Panel: ' + nodePath.getName(),
     esg = EntryScaleGroup(title = 'RGBA Panel: ' + nodePath.getName(),
                           dim = 4,
                           dim = 4,
                           labels = ['R','G','B','A'],
                           labels = ['R','G','B','A'],
-                          initialValue = [int(initColor[0]),
+                          value = [int(initColor[0]),
                                           int(initColor[1]),
                                           int(initColor[1]),
                                           int(initColor[2]),
                                           int(initColor[2]),
                                           int(initColor[3])],
                                           int(initColor[3])],
@@ -499,7 +507,7 @@ def rgbPanel(nodePath, callback = None):
     # Set callback
     # Set callback
     def onRelease(r,g,b,a, nodePath = nodePath):
     def onRelease(r,g,b,a, nodePath = nodePath):
         messenger.send('RGBPanel_setColor', [nodePath, r,g,b,a])
         messenger.send('RGBPanel_setColor', [nodePath, r,g,b,a])
-    esg.onRelease = onRelease
+    esg['postCallback'] = onRelease
     return esg
     return esg
 
 
 ## SAMPLE CODE
 ## SAMPLE CODE
@@ -519,7 +527,7 @@ if __name__ == '__main__':
     """
     """
     # These are things you can set/configure
     # These are things you can set/configure
     # Starting value for entryScale    
     # Starting value for entryScale    
-    mega1['initialValue'] = 123.456
+    mega1['value'] = 123.456
     mega1['text'] = 'Drive delta X'
     mega1['text'] = 'Drive delta X'
     mega1['min'] = 0.0
     mega1['min'] = 0.0
     mega1['max'] = 1000.0
     mega1['max'] = 1000.0
@@ -530,7 +538,7 @@ if __name__ == '__main__':
     # To have really fine control, for example
     # To have really fine control, for example
     # mega1['maxVelocity'] = 0.1
     # mega1['maxVelocity'] = 0.1
     # Number of digits to the right of the decimal point, default = 2
     # Number of digits to the right of the decimal point, default = 2
-    # mega1['significantDigits'] = 5
+    # mega1['numDigits'] = 5
     """
     """
 
 
     # To create a entryScale group to set an RGBA value:
     # To create a entryScale group to set an RGBA value:

+ 404 - 187
direct/src/tkwidgets/Floater.py

@@ -5,214 +5,431 @@ Floater Class: Velocity style controller for floating point values with
 from PandaObject import *
 from PandaObject import *
 from Tkinter import *
 from Tkinter import *
 import Pmw
 import Pmw
+import WidgetPropertiesDialog
 import string
 import string
 
 
-class Floater(Pmw.MegaWidget):
-    "Velocity style floating point controller"
- 
-    def __init__(self, parent = None, **kw):
+globalClock = ClockObject.getGlobalClock()
+
+
+FLOATER_FULL = 'full'
+FLOATER_MINI = 'mini'
+
+FLOATER_WIDTH = 25
+FLOATER_HEIGHT = 20
 
 
-        # Define the megawidget options.
+class FloaterWidget(Pmw.MegaWidget):
+    sfBase = 3.0
+    sfDist = 15
+    deadband = 10
+    def __init__(self, parent = None, **kw):
+        #define the megawidget options
+        INITOPT = Pmw.INITOPT
         optiondefs = (
         optiondefs = (
-            ('initialValue',        0.0,        Pmw.INITOPT),
-            ('resolution',          None,       None),
-            ('command',             None,       None),
-            ('commandData',         [],         None),
-            ('callbackData',        [],         None),
-            ('maxVelocity',         10.0,       None),
-            ('min',                 None,       self._updateValidate),
-            ('max',                 None,       self._updateValidate),
-            ('text',                'Floater',  self._updateLabelText),
-            ('significantDigits',   2,          self._setSigDigits),
+            ## Appearance
+            # Edge size of the floater
+            ('width',           FLOATER_WIDTH,  INITOPT),
+            ('height',          FLOATER_HEIGHT, INITOPT),
+            # Color
+            ('background',      'white',        INITOPT),
+            # Widget relief
+            ('relief',          SUNKEN,         self.setRelief),
+            # Widget borderwidth
+            ('borderwidth',     2,              self.setBorderwidth),
+            ## Values
+            # Initial value of floater, use self.set to change value
+            ('value',           0.0,            INITOPT),
+            ('min',             None,           None),
+            ('max',             None,           None),
+            ('resolution',      None,           None),
+            ('numDigits',       2,              self.setNumDigits),
+            # Value floater jumps to on reset
+            ('resetValue',      0.0,            None),
+            ## Behavior
+            # Able to adjust max/min
+            ('fAdjustable',     1,              None),
+            # Command to execute on floater 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)
         self.defineoptions(kw, optiondefs)
- 
-        # Initialise superclass
-        Pmw.MegaWidget.__init__(self, parent)
-
-        # Initialize some class variables
-        self.value = self['initialValue']
-        self.velocity = 0.0
-        self.entryFormat = '%.2f'
 
 
-        # Create the components.
-
-        # Setup up container
-        interior = self.interior()
-        interior.configure(relief = GROOVE, borderwidth = 2)
-
-        # Create a label and an entry
-        self.labelFrame = self.createcomponent('frame', (), None,
-                                               Frame, interior)
-        # Create an entry field to display and validate the floater's value
-        self.entryValue = StringVar()
-        self.entryValue.set(self['initialValue'])
-        self.entry = self.createcomponent('entryField',
-                                          # Access floaters entry using "entry"
-                                          (('entry', 'entryField_entry'),),
-                                          None,
-                                          Pmw.EntryField, self.labelFrame,
-                                          entry_width = 10,
-                                          validate = { 'validator' : 'real',
-                                                       'min' : self['min'],
-                                                       'max' : self['max'],
-                                                       'minstrict' : 0,
-                                                       'maxstrict' : 0},
-                                          entry_justify = 'right',
-                                          entry_textvar = self.entryValue,
-                                          command = self._entryCommand)
-        self.entry.pack(side='left',padx = 4)
-                                          
-        # Create the Floater's label
-        self.label = self.createcomponent('label', (), None,
-                                          Label, self.labelFrame,
-                                          text = self['text'],
-                                          width = 12,
-                                          anchor = 'center',
-                                          font = "Arial 10 bold")
-        self.label.pack(side='left', expand = 1, fill = 'x')
-
-        # Now pack the frame
-        self.labelFrame.pack(expand = 1, fill = 'both')
-
-        # Create the scale component.
-        self.scale = self.createcomponent('scale', (), None,
-                                          Scale, interior,
-                                          command = self._scaleToVelocity,
-                                          orient = 'horizontal',
-                                          length = 150,
-                                          from_ = -1.0,
-                                          to = 1.0,
-                                          resolution = 0.001,
-                                          showvalue = 0)
-        self.scale.pack(expand = 1, fill = 'x')
-        # Set scale to the middle of its range
-        self.scale.set(0.0)
+        #print 'FLOATER WIDGET', self['resetValue']
         
         
-        # Add scale bindings: When interacting with mouse:
-        self.scale.bind('<Button-1>', self._startFloaterTask)
-        self.scale.bind('<ButtonRelease-1>', self._floaterReset)
-        # In case you wish to interact using keys
-        self.scale.bind('<KeyPress-Right>', self._floaterKeyCommand)
-        self.scale.bind('<KeyRelease-Right>', self._floaterReset)
-        self.scale.bind('<KeyPress-Left>', self._floaterKeyCommand)
-        self.scale.bind('<KeyRelease-Left>', self._floaterReset)
- 
-        # Check keywords and initialise options based on input values.
-        self.initialiseoptions(Floater)
+        # Initialize the superclass
+        Pmw.MegaWidget.__init__(self, parent)
 
 
-    def label(self):
-        return self.label
-    def scale(self):
-        return self.scale
-    def entry(self):
-        return self.entry
-    
-    def _updateLabelText(self):
-        self.label['text'] = self['text']
-
-    def _updateValidate(self):
-        self.configure(entryField_validate = {
-            'validator' : 'real',
-            'min' : self['min'],
-            'max' : self['max'],
-            'minstrict' : 0,
-            'maxstrict' : 0})
-
-    def _scaleToVelocity(self, strVal):
-        # convert scale val to float
-        val = string.atof(strVal)
-        # Square val, but retain sign of velocity by only calling abs once
-        self.velocity = self['maxVelocity'] * val * abs(val)
-
-    def _startFloaterTask(self,event):
-        self._fFloaterTask = 1
-        apply(self.onPress,self['callbackData'])
-        taskMgr.add(self._floaterTask, 'floaterTask')
-
-    def _floaterTask(self, state):
-        if self.velocity != 0.0:
-            self.set( self.value + self.velocity )
-        return Task.cont
+        # Set up some local and instance variables        
+        # Current value
+        self.value = self['value']
 
 
-    def _floaterReset(self, event):
-        taskMgr.remove('floaterTask')
-        self.velocity = 0.0
-        self.scale.set(0.0)
-        apply(self.onRelease, self['callbackData'])
+        # Create the components
+        interior = self.interior()
 
 
-    def _floaterKeyCommand(self, event):
-        if self.velocity != 0.0:
-            self.set( self.value + self.velocity )
+        # The canvas
+        width = self['width']
+        height = self['height']
+        self._canvas = self.createcomponent('canvas', (), None,
+                                            Canvas, (interior,),
+                                            width = self['width'],
+                                            height = self['height'],
+                                            background = self['background'],
+                                            highlightthickness = 0,
+                                            scrollregion = (-width/2.0,
+                                                            -height/2.0,
+                                                            width/2.0,
+                                                            height/2.0))
+        self._canvas.pack(expand = 1, fill = BOTH)
+
+        # The floater icon
+        self._canvas.create_polygon(-width/2.0, 0, -2.0, -height/2.0,
+                                    -2.0, height/2.0,
+                                    fill = '#A0A0A0',
+                                    tags = ('floater',))
+        self._canvas.create_polygon(width/2.0, 0, 2.0, height/2.0,
+                                    2.0, -height/2.0,
+                                    fill = '#A0A0A0',
+                                    tags = ('floater',))
+
+        # A Dictionary of dictionaries for the popup property dialog
+        self.propertyDict = {
+            'min' : { 'widget' : self,
+                      'type' : 'real',
+                      'fNone' : 1,
+                      'help' : 'Minimum allowable floater value, Enter None for no minimum'},
+            'max' : { 'widget' : self,
+                      'type' : 'real',
+                      'fNone' : 1,
+                      'help' : 'Maximum allowable floater value, Enter None for no maximum'},
+            'resetValue' : { 'widget' : self,
+                             'type' : 'real',
+                             'help' : 'Enter value to set floater to on reset.'}
+            }
+        self.propertyList = ['min', 'max', 'resetValue']
+
+        # The popup menu
+        self._popupMenu = Menu(interior, tearoff = 0)
+
+        if self['fAdjustable']:
+            self._popupMenu.add_command(
+                label = 'Properties...',
+                command = self.popupPropertiesDialog)
+        self._popupMenu.add_command(label = 'Zero Floater',
+                                    command = self.zero)
+        self._popupMenu.add_command(label = 'Reset Floater',
+                                    command = self.reset)
+
+        # Add event bindings
+        self._canvas.bind('<ButtonPress-1>', self.mouseDown)
+        self._canvas.bind('<B1-Motion>', self.mouseMotion)
+        self._canvas.bind('<ButtonRelease-1>', self.mouseUp)
+        self._canvas.bind('<ButtonPress-3>', self.popupFloaterMenu)
+        self._canvas.bind('<Double-ButtonPress-1>', self.mouseReset)
+        self._canvas.bind('<ButtonPress-3>', self.popupFloaterMenu)
+        self._canvas.bind('<Enter>', self.highlightIcon)
+        self._canvas.bind('<Leave>', self.restoreIcon)
+        self._canvas.tag_bind('floater', '<ButtonPress-1>', self.mouseDown)
+        self._canvas.tag_bind('floater', '<B1-Motion>', self.mouseMotion)
+        self._canvas.tag_bind('floater', '<ButtonRelease-1>', self.mouseUp)
 
 
-    def _entryCommand(self, event = None):
-        try:
-            val = string.atof( self.entryValue.get() )
-            apply(self.onReturn,self['callbackData'])
-            self.set( val )
-            apply(self.onReturnRelease,self['callbackData'])
-        except ValueError:
-            pass
-
-    def _setSigDigits(self):
-        sd = self['significantDigits']
-        self.entryFormat = '%.' + '%d' % sd + 'f'
-        # And reset value to reflect change
-        self.entryValue.set( self.entryFormat % self.value )
+        # Make sure input variables processed 
+        self.initialiseoptions(FloaterWidget)
 
 
-    def get(self):
-        return self.value
-    
-    def set(self, newVal, fCommand = 1):
+    def set(self, value, fCommand = 1):
+        """
+        self.set(value, fCommand = 1)
+        Set floater to new value, execute command if fCommand == 1
+        """
         # Clamp value
         # Clamp value
         if self['min'] is not None:
         if self['min'] is not None:
-            if newVal < self['min']:
-                newVal = self['min']
+            if value < self['min']:
+                value = self['min']
         if self['max'] is not None:
         if self['max'] is not None:
-            if newVal > self['max']:
-                newVal = self['max']
+            if value > self['max']:
+                value = self['max']
         # Round by resolution
         # Round by resolution
         if self['resolution'] is not None:
         if self['resolution'] is not None:
-            newVal = round(newVal / self['resolution']) * self['resolution']
+            value = round(value / self['resolution']) * self['resolution']
+
+        # Send command if any
+        if fCommand and (self['command'] != None):
+            apply(self['command'], [value] + self['commandData'])
+        # Record value
+        self.value = value
+    
+    # Set floater to zero
+    def zero(self):
+        """
+        self.reset()
+        Set floater to zero
+        """
+        self.set(0.0)
+
+    # Reset floater to reset value
+    def reset(self):
+        """
+        self.reset()
+        Reset floater to reset value
+        """
+        self.set(self['resetValue'])
+
+    def mouseReset(self,event):
+        # If not over any canvas item
+        #if not self._canvas.find_withtag(CURRENT):
+        self.reset()
         
         
-        # Update floater's value
-        self.value = newVal
-        # Update entry to reflect formatted value
-        self.entryValue.set( self.entryFormat % self.value )
-        self.entry.checkentry()
+    def get(self):
+        """
+        self.get()
+        Get current floater value
+        """
+        return self.value
+
+    ## Canvas callback functions
+    # Floater velocity controller
+    def mouseDown(self,event):
+        self._onButtonPress()
+        self.velocitySF = 0.0
+        t = taskMgr.add(self.computeVelocity, 'cv')
+        t.lastTime = globalClock.getFrameTime()
+
+    def computeVelocity(self, state):
+        # Update value
+        currT = globalClock.getFrameTime()
+        dt = currT - state.lastTime
+        self.set(self.value + self.velocitySF * dt)
+        state.lastTime = currT
+        return Task.cont
+
+    def mouseMotion(self, event):
+        # What is the current knob angle
+        self.velocitySF = self.computeVelocitySF(event)
+
+    def computeVelocitySF(self, event):
+        x = self._canvas.canvasx(event.x)
+        y = self._canvas.canvasy(event.y)
+        offset = max(0, abs(x) - FloaterWidget.deadband)
+        if offset == 0:
+            return 0
+        sf = math.pow(FloaterWidget.sfBase,
+                      self.minExp + offset/FloaterWidget.sfDist)
+        if x > 0:
+            return sf
+        else:
+            return -sf
+
+    def mouseUp(self, event):
+        taskMgr.remove('cv')
+        self.velocitySF = 0.0
+        self._onButtonRelease()
+
+    def highlightIcon(self, event):
+        self._canvas.itemconfigure('floater', fill = 'black')
+
+    def restoreIcon(self, event):
+        self._canvas.itemconfigure('floater', fill = '#A0A0A0')
+
+    # Methods to modify floater characteristics    
+    def setRelief(self):
+        self.interior()['relief'] = self['relief']
+
+    def setBorderwidth(self):
+        self.interior()['borderwidth'] = self['borderwidth']
+
+    def setNumDigits(self):
+        # Set minimum exponent to use in velocity task
+        self.minExp = math.floor(-self['numDigits']/
+                                 math.log10(FloaterWidget.sfBase))        
+
+    # The following methods are used to handle the popup menu
+    def popupFloaterMenu(self,event):
+        self._popupMenu.post(event.widget.winfo_pointerx(),
+                             event.widget.winfo_pointery())
+
+    # Popup dialog to adjust widget properties
+    def popupPropertiesDialog(self):
+        WidgetPropertiesDialog.WidgetPropertiesDialog(
+            self.propertyDict,
+            propertyList = self.propertyList,
+            title = 'Floater Widget Properties',
+            parent = self._canvas)
+
+    def addPropertyToDialog(self, property, pDict):
+        self.propertyDict[property] = pDict
+        self.propertyList.append(property)
+            
+    # User callbacks
+    def _onButtonPress(self, *args):
+        """ User redefinable callback executed on button press """
+        if self['preCallback']:
+            apply(self['preCallback'], self['callbackData'])
+
+    def _onButtonRelease(self, *args):
+        """ User redefinable callback executed on button release """
+        if self['postCallback']:
+            apply(self['postCallback'], self['callbackData'])
+
+
+class Floater(Pmw.MegaWidget):
+    def __init__(self, parent = None, **kw):
+        #define the megawidget options
+        INITOPT = Pmw.INITOPT
+        optiondefs = (
+            # Widget relief
+            ('relief',            GROOVE,         None),
+            # Widget borderwidth
+            ('borderwidth',       2,              None),
+            ('value',             0.0,            INITOPT),
+            ('resetValue',        0.0,            self.setResetValue),
+            ('text',              'Floater',      self.setLabel),
+            ('numDigits',         2,              self.setEntryFormat),
+            ('command',           None,           None),
+            ('commandData',       [],             None),
+            ('min',               None,           self.setMin),
+            ('max',               None,           self.setMax),
+            # Callbacks to execute when updating widget's value
+            ('preCallback',     None,           self.setButtonPressCmd),
+            ('postCallback',   None,           self.setButtonReleaseCmd),
+            # Extra data to be passed to callback function, needs to be a list
+            ('callbackData',      [],             self.setCallbackData),
+            )
+        self.defineoptions(kw, optiondefs)
         
         
-        # execute command
-        if fCommand and (self['command'] is not None):
-            apply(self['command'], [newVal] + self['commandData'])
+        # Initialize the superclass
+        Pmw.MegaWidget.__init__(self, parent)
 
 
-    def reset(self):
-        self.set(self['initialValue'])
+        # Create the components
+        interior = self.interior()
+        interior.configure(relief = self['relief'], bd = self['borderwidth'])
+        
+        # The Floater
+        #print self['text'], self['value'], self['resetValue']
+        self._floater = self.createcomponent('floater', (), None,
+                                             FloaterWidget, (interior,),
+                                             command = self.setEntry,
+                                             resetValue = self['value'],
+                                             value = self['value'])
+
+        if not kw.has_key('resetValue'):
+            self['resetValue'] = self['value']
+        self._floater.addPropertyToDialog(
+            'text',
+            {'widget' : self,
+             'type' : 'string',
+             'help' : 'Enter label text for Floater.'
+             }
+            )
+        self._floater.addPropertyToDialog(
+            'numDigits',
+            {'widget' : self,
+             'type' : 'integer',
+             'help' : 'Enter number of digits after decimal point.'
+             }
+            )
 
 
-    def disable(self):
-        self.scale['state'] = 'disabled'
-        self.label['state'] = 'disabled'
-        self.component('entry')['state'] = 'disabled'
+        # The Label
+        self._label = self.createcomponent('label', (), None,
+                                           Label, (interior,),
+                                           text = self['text'],
+                                           font = ('MS Sans Serif',12,'bold'),
+                                           anchor = CENTER)
+        self._label.bind('<ButtonPress-3>', self._floater.popupFloaterMenu)
+
+        # The entry
+        self._entryVal = StringVar()
+        self._entry = self.createcomponent('entry', (), None,
+                                           Entry, (interior,),
+                                           justify = RIGHT,
+                                           width = 12,
+                                           textvariable = self._entryVal)
+        self._entry.bind('<Return>', self.validateEntryInput)
+        self._entry.bind('<ButtonPress-3>', self._floater.popupFloaterMenu)
+        self._entryBackground = self._entry.cget('background')
+
+        # Position components
+        self._label.grid(row=0,col=0, sticky = EW)
+        self._entry.grid(row=0,col=1, sticky = EW)
+        self._floater.grid(row=0,col=2, padx = 2, pady = 2)
+        interior.columnconfigure(0, weight = 1)
+
+        # Make sure input variables processed
+        self.fInit = 0
+        self.initialiseoptions(Floater)
+        self.fInit = 1
+
+    def set(self, value, fCommand = 1):
+        # Pass fCommand to user specified data (to control if command
+        # is executed or not) to floater which will return it to self.setEntry
+        self._floater['commandData'] = [fCommand]
+        self._floater.set(value)
+        # Restore commandData to 1 so that interaction via floater widget
+        # will result in command being executed, otherwise a set with
+        # commandData == 0 will stick and commands will not be executed
+        self._floater['commandData'] = [1]
+        
+    def get(self):
+        return self._floater.get()
 
 
-    def enable(self):
-        self.scale['state'] = 'normal'
-        self.label['state'] = 'normal'
-        self.component('entry')['state'] = 'normal'
+    def setEntry(self, value, fCommand = 1):
+        self._entryVal.set(self.entryFormat % value)
+        # Execute command
+        if self.fInit and fCommand and (self['command'] != None):
+            apply(self['command'], [value] + self['commandData'])
+
+    def setEntryFormat(self):
+        self.entryFormat = "%." + "%df" % self['numDigits']
+        self.setEntry(self.get())
+        self._floater['numDigits'] = self['numDigits']
+
+    def validateEntryInput(self, event):
+        input = self._entryVal.get()
+        try:
+            self._onReturnPress()
+            self._entry.configure(background = self._entryBackground)
+            newValue = string.atof(input)
+            self.set(newValue)
+            self._onReturnRelease()
+        except ValueError:
+            self._entry.configure(background = 'Pink')
 
 
-    def onReturn(self, *args):
+    def _onReturnPress(self, *args):
         """ User redefinable callback executed on <Return> in entry """
         """ User redefinable callback executed on <Return> in entry """
-        pass
+        if self['preCallback']:
+            apply(self['preCallback'], self['callbackData'])
 
 
-    def onReturnRelease(self, *args):
+    def _onReturnRelease(self, *args):
         """ User redefinable callback executed on <Return> release in entry """
         """ User redefinable callback executed on <Return> release in entry """
-        pass
+        if self['postCallback']:
+            apply(self['postCallback'], self['callbackData'])
 
 
-    def onPress(self, *args):
-        """ User redefinable callback executed on button press """
-        pass
+    # Pass settings down to floater
+    def setCallbackData(self):
+        # Pass callback data down to floater
+        self._floater['callbackData'] = self['callbackData']
+
+    def setResetValue(self):
+        self._floater['resetValue'] = self['resetValue']
+
+    def setMin(self):
+        self._floater['min'] = self['min']
+
+    def setMax(self):
+        self._floater['max'] = self['max']
+
+    def setLabel(self):
+        self._label['text'] = self['text']
+
+    def setButtonPressCmd(self):
+        self._floater['preCallback'] = self['preCallback']
+
+    def setButtonReleaseCmd(self):
+        self._floater['postCallback'] = self['postCallback']
 
 
-    def onRelease(self, *args):
-        """ User redefinable callback executed on button release """
-        pass
 
 
 class FloaterGroup(Pmw.MegaToplevel):
 class FloaterGroup(Pmw.MegaToplevel):
     def __init__(self, parent = None, **kw):
     def __init__(self, parent = None, **kw):
@@ -231,7 +448,7 @@ class FloaterGroup(Pmw.MegaToplevel):
             ('side',            TOP,                    INITOPT),
             ('side',            TOP,                    INITOPT),
             ('title',           'Floater Group',        None),
             ('title',           'Floater Group',        None),
             # A tuple of initial values, one for each floater
             # A tuple of initial values, one for each floater
-            ('initialValue',    DEFAULT_VALUE,          INITOPT),
+            ('value',    DEFAULT_VALUE,          INITOPT),
             # The command to be executed any time one of the floaters is updated
             # The command to be executed any time one of the floaters is updated
             ('command',         None,                   None),
             ('command',         None,                   None),
             # A tuple of labels, one for each floater
             # A tuple of labels, one for each floater
@@ -245,7 +462,7 @@ class FloaterGroup(Pmw.MegaToplevel):
         # Create the components
         # Create the components
         interior = self.interior()
         interior = self.interior()
         # Get a copy of the initial value (making sure its a list)
         # Get a copy of the initial value (making sure its a list)
-        self._value = list(self['initialValue'])
+        self._value = list(self['value'])
 
 
         # The Menu Bar
         # The Menu Bar
         self.balloon = Pmw.Balloon()
         self.balloon = Pmw.Balloon()
@@ -279,7 +496,7 @@ class FloaterGroup(Pmw.MegaToplevel):
             #   fg.configure(Valuator_XXX = YYY)
             #   fg.configure(Valuator_XXX = YYY)
             f = self.createcomponent(
             f = self.createcomponent(
                 'floater%d' % index, (), 'Valuator', Floater,
                 'floater%d' % index, (), 'Valuator', Floater,
-                (interior,), initialValue = self._value[index],
+                (interior,), value = self._value[index],
                 text = self['labels'][index])
                 text = self['labels'][index])
             # Do this separately so command doesn't get executed during construction
             # Do this separately so command doesn't get executed during construction
             f['command'] = lambda val, s=self, i=index: s._floaterSetAt(i, val)
             f['command'] = lambda val, s=self, i=index: s._floaterSetAt(i, val)
@@ -287,7 +504,7 @@ class FloaterGroup(Pmw.MegaToplevel):
             self.floaterList.append(f)
             self.floaterList.append(f)
 
 
         # Make sure floaters are initialized
         # Make sure floaters are initialized
-        self.set(self['initialValue'])
+        self.set(self['value'])
         
         
         # Make sure input variables processed 
         # Make sure input variables processed 
         self.initialiseoptions(FloaterGroup)
         self.initialiseoptions(FloaterGroup)
@@ -329,9 +546,9 @@ class FloaterGroup(Pmw.MegaToplevel):
             self['command'](self._value)
             self['command'](self._value)
 
 
     def reset(self):
     def reset(self):
-        self.set(self['initialValue'])
-
+        self.set(self['value'])
 
 
+  
 ## SAMPLE CODE
 ## SAMPLE CODE
 if __name__ == '__main__':
 if __name__ == '__main__':
     # Initialise Tkinter and Pmw.
     # Initialise Tkinter and Pmw.
@@ -349,7 +566,7 @@ if __name__ == '__main__':
     """
     """
     # These are things you can set/configure
     # These are things you can set/configure
     # Starting value for floater    
     # Starting value for floater    
-    mega1['initialValue'] = 123.456
+    mega1['value'] = 123.456
     mega1['text'] = 'Drive delta X'
     mega1['text'] = 'Drive delta X'
     mega1['min'] = 0.0
     mega1['min'] = 0.0
     mega1['max'] = 1000.0
     mega1['max'] = 1000.0
@@ -360,7 +577,7 @@ if __name__ == '__main__':
     # To have really fine control, for example
     # To have really fine control, for example
     # mega1['maxVelocity'] = 0.1
     # mega1['maxVelocity'] = 0.1
     # Number of digits to the right of the decimal point, default = 2
     # Number of digits to the right of the decimal point, default = 2
-    # mega1['significantDigits'] = 5
+    # mega1['numDigits'] = 5
     """
     """
 
 
     # To create a floater group to set an RGBA value:
     # To create a floater group to set an RGBA value:

+ 12 - 8
direct/src/tkwidgets/VectorWidgets.py

@@ -20,7 +20,7 @@ class VectorEntry(Pmw.MegaWidget):
         INITOPT = Pmw.INITOPT
         INITOPT = Pmw.INITOPT
         optiondefs = (
         optiondefs = (
             ('dim',                 DEFAULT_DIM,    INITOPT),
             ('dim',                 DEFAULT_DIM,    INITOPT),
-            ('initialValue',        DEFAULT_VALUE,  INITOPT),
+            ('value',        DEFAULT_VALUE,  INITOPT),
             ('resetValue',          DEFAULT_VALUE,  None),
             ('resetValue',          DEFAULT_VALUE,  None),
             ('label_width',         12,             None),
             ('label_width',         12,             None),
             ('command',             None,           None),
             ('command',             None,           None),
@@ -30,7 +30,7 @@ class VectorEntry(Pmw.MegaWidget):
             ('text',                'Vector:',      self._updateText),
             ('text',                'Vector:',      self._updateText),
             ('min',                 None,           self._updateValidate),
             ('min',                 None,           self._updateValidate),
             ('max',                 None,           self._updateValidate),
             ('max',                 None,           self._updateValidate),
-            ('significantDigits',   2,              self._setSigDigits),
+            ('numDigits',   2,              self._setSigDigits),
             ('valuatorType',        VALUATOR,       None),
             ('valuatorType',        VALUATOR,       None),
             ('state',               'normal',       self._setState),
             ('state',               'normal',       self._setState),
             )
             )
@@ -41,8 +41,8 @@ class VectorEntry(Pmw.MegaWidget):
 
 
         # Initialize value
         # Initialize value
         # Make sure its a list (and as a byproduct, make a distinct copy)
         # Make sure its a list (and as a byproduct, make a distinct copy)
-        self._value = list(self['initialValue'])
-        self['resetValue'] = self['initialValue']
+        self._value = list(self['value'])
+        self['resetValue'] = self['value']
         self._floaters = None
         self._floaters = None
         self.entryFormat = '%.2f'
         self.entryFormat = '%.2f'
 
 
@@ -103,7 +103,7 @@ class VectorEntry(Pmw.MegaWidget):
                                              
                                              
 
 
         # Make sure entries are updated
         # Make sure entries are updated
-        self.set(self['initialValue'])
+        self.set(self['value'])
 
 
         # Record entry color
         # Record entry color
         self.entryBackground = self.cget('Entry_entry_background')
         self.entryBackground = self.cget('Entry_entry_background')
@@ -142,9 +142,9 @@ class VectorEntry(Pmw.MegaWidget):
         self['Entry_entry_width'] = self['entryWidth']
         self['Entry_entry_width'] = self['entryWidth']
 
 
     def _setSigDigits(self):
     def _setSigDigits(self):
-        sd = self['significantDigits']
+        sd = self['numDigits']
         self.entryFormat = '%.' + '%d' % sd + 'f'
         self.entryFormat = '%.' + '%d' % sd + 'f'
-        self.configure(Valuator_significantDigits = sd)
+        self.configure(Valuator_numDigits = sd)
         # And refresh value to reflect change
         # And refresh value to reflect change
         for index in range(self['dim']):
         for index in range(self['dim']):
             self._refreshEntry(index)
             self._refreshEntry(index)
@@ -232,8 +232,10 @@ class VectorEntry(Pmw.MegaWidget):
             self.configure(Entry_entry_state = 'disabled')
             self.configure(Entry_entry_state = 'disabled')
             self.configure(Entry_entry_background = '#C0C0C0')
             self.configure(Entry_entry_background = '#C0C0C0')
             # Disable floater Group scale
             # Disable floater Group scale
+            """
             self.component('fGroup').configure(
             self.component('fGroup').configure(
                 Valuator_scale_state = 'disabled')
                 Valuator_scale_state = 'disabled')
+            """
             # Disable floater group entry
             # Disable floater group entry
             self.component('fGroup').configure(
             self.component('fGroup').configure(
                 Valuator_entry_state = 'disabled')
                 Valuator_entry_state = 'disabled')
@@ -244,8 +246,10 @@ class VectorEntry(Pmw.MegaWidget):
             self.configure(Entry_entry_state = 'normal')
             self.configure(Entry_entry_state = 'normal')
             self.configure(Entry_entry_background = self.entryBackground)
             self.configure(Entry_entry_background = self.entryBackground)
             # Disable floater Group scale
             # Disable floater Group scale
+            """
             self.component('fGroup').configure(
             self.component('fGroup').configure(
                 Valuator_scale_state = 'normal')
                 Valuator_scale_state = 'normal')
+            """
             # Disable floater group entry
             # Disable floater group entry
             self.component('fGroup').configure(
             self.component('fGroup').configure(
                 Valuator_entry_state = 'normal')
                 Valuator_entry_state = 'normal')
@@ -302,7 +306,7 @@ class ColorEntry(VectorEntry):
             ('fGroup_labels',           ('R','G','B','A'),  None),
             ('fGroup_labels',           ('R','G','B','A'),  None),
             ('min',                     0.0,                None),
             ('min',                     0.0,                None),
             ('max',                     255.0,              None),
             ('max',                     255.0,              None),
-            ('significantDigits',       0,                  None),
+            ('nuDigits',       0,                  None),
             ('Valuator_resolution',     1.0,                None),
             ('Valuator_resolution',     1.0,                None),
             )
             )
         self.defineoptions(kw, optiondefs)
         self.defineoptions(kw, optiondefs)

+ 3 - 1
direct/src/tkwidgets/WidgetPropertiesDialog.py

@@ -110,15 +110,17 @@ class WidgetPropertiesDialog(Toplevel):
                     extra = ''
                     extra = ''
             # Set up help string and validator based upon type
             # Set up help string and validator based upon type
             if entryType == 'real':
             if entryType == 'real':
+                # Only allow real numbers
                 entry['validate'] = { 'validator' : self.realOrNone }
                 entry['validate'] = { 'validator' : self.realOrNone }
                 if helpString is None:
                 if helpString is None:
                     helpString = 'Enter a floating point number' + extra + '.'
                     helpString = 'Enter a floating point number' + extra + '.'
             elif entryType == 'integer':
             elif entryType == 'integer':
+                # Only allow integer values
                 entry['validate'] = { 'validator' : self.intOrNone }
                 entry['validate'] = { 'validator' : self.intOrNone }
                 if helpString is None:
                 if helpString is None:
                     helpString = 'Enter an integer' + extra + '.'
                     helpString = 'Enter an integer' + extra + '.'
             else:
             else:
-                entry['validate'] = { 'validator' : 'alphanumeric' }
+                # Anything goes with a string widget
                 if helpString is None:
                 if helpString is None:
                     helpString = 'Enter a string' + extra + '.'
                     helpString = 'Enter a string' + extra + '.'
             # Bind balloon with help string to entry
             # Bind balloon with help string to entry