mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 10:54:24 -04:00
*** empty log message ***
This commit is contained in:
parent
1408f36fc0
commit
d98d9cc244
@ -989,7 +989,5 @@ class DirectSessionPanel(AppShell):
|
|||||||
|
|
||||||
def onDestroy(self, event):
|
def onDestroy(self, event):
|
||||||
# Remove hooks
|
# Remove hooks
|
||||||
print 'here'
|
|
||||||
for event, method in self.actionEvents:
|
for event, method in self.actionEvents:
|
||||||
self.ignore(event)
|
self.ignore(event)
|
||||||
print 'there'
|
|
||||||
|
@ -1,13 +1,11 @@
|
|||||||
from Tkinter import *
|
from Tkinter import *
|
||||||
from tkSimpleDialog import askfloat
|
|
||||||
from PandaModules import ClockObject
|
from PandaModules import ClockObject
|
||||||
import Task
|
from WidgetPropertiesDialog import *
|
||||||
import Pmw
|
import Pmw
|
||||||
import tkMessageBox
|
import Task
|
||||||
import math
|
import math
|
||||||
import string
|
import string
|
||||||
import operator
|
import operator
|
||||||
import types
|
|
||||||
|
|
||||||
TWO_PI = 2.0 * math.pi
|
TWO_PI = 2.0 * math.pi
|
||||||
ONEPOINTFIVE_PI = 1.5 * math.pi
|
ONEPOINTFIVE_PI = 1.5 * math.pi
|
||||||
@ -25,187 +23,6 @@ globalClock = ClockObject.getGlobalClock()
|
|||||||
|
|
||||||
from tkSimpleDialog import Dialog
|
from tkSimpleDialog import Dialog
|
||||||
|
|
||||||
class WidgetPropertiesDialog(Toplevel):
|
|
||||||
"""Class to open dialogs to adjust widget properties."""
|
|
||||||
def __init__(self, widget, propertyList, title = None, parent = None):
|
|
||||||
"""Initialize a dialog.
|
|
||||||
Arguments:
|
|
||||||
propertyList -- a list of properties to be edited
|
|
||||||
parent -- a parent window (the application window)
|
|
||||||
title -- the dialog title
|
|
||||||
"""
|
|
||||||
# Record widget and property list
|
|
||||||
self.widget = widget
|
|
||||||
self.propertyList = propertyList
|
|
||||||
# Use default parent if none specified
|
|
||||||
if not parent:
|
|
||||||
import Tkinter
|
|
||||||
parent = Tkinter._default_root
|
|
||||||
# Create toplevel window
|
|
||||||
Toplevel.__init__(self, parent)
|
|
||||||
self.transient(parent)
|
|
||||||
# Set title
|
|
||||||
if title:
|
|
||||||
self.title(title)
|
|
||||||
# Record parent
|
|
||||||
self.parent = parent
|
|
||||||
# Initialize result
|
|
||||||
self.result = None
|
|
||||||
# Create body
|
|
||||||
body = Frame(self)
|
|
||||||
self.initial_focus = self.body(body)
|
|
||||||
body.pack(padx=5, pady=5)
|
|
||||||
# Create OK Cancel button
|
|
||||||
self.buttonbox()
|
|
||||||
# Initialize window state
|
|
||||||
self.grab_set()
|
|
||||||
self.protocol("WM_DELETE_WINDOW", self.cancel)
|
|
||||||
self.geometry("+%d+%d" % (parent.winfo_rootx()+50,
|
|
||||||
parent.winfo_rooty()+50))
|
|
||||||
self.initial_focus.focus_set()
|
|
||||||
self.wait_window(self)
|
|
||||||
|
|
||||||
def destroy(self):
|
|
||||||
"""Destroy the window"""
|
|
||||||
self.propertyList = []
|
|
||||||
self.entryList = []
|
|
||||||
self.initial_focus = None
|
|
||||||
Toplevel.destroy(self)
|
|
||||||
|
|
||||||
#
|
|
||||||
# construction hooks
|
|
||||||
def body(self, master):
|
|
||||||
"""create dialog body.
|
|
||||||
return widget that should have initial focus.
|
|
||||||
This method should be overridden, and is called
|
|
||||||
by the __init__ method.
|
|
||||||
"""
|
|
||||||
self.labelList = []
|
|
||||||
self.entryList = []
|
|
||||||
count = 0
|
|
||||||
for propertySet in self.propertyList:
|
|
||||||
# Make singletons into lists
|
|
||||||
if type(propertySet) is not types.ListType:
|
|
||||||
propertySet = [propertySet]
|
|
||||||
# Name of widget property
|
|
||||||
property = propertySet[0]
|
|
||||||
initialvalue = self.widget[property]
|
|
||||||
try:
|
|
||||||
entryType = propertySet[1]
|
|
||||||
except IndexError:
|
|
||||||
entryType = 'float'
|
|
||||||
try:
|
|
||||||
fAllowNone = propertySet[2]
|
|
||||||
except IndexError:
|
|
||||||
fAllowNone = 0
|
|
||||||
# Create label
|
|
||||||
label = Label(master, text=property, justify=LEFT)
|
|
||||||
label.grid(row=count, col = 0, padx=5, sticky=W)
|
|
||||||
self.labelList.append(label)
|
|
||||||
# Create entry
|
|
||||||
entry = Entry(master)
|
|
||||||
entry.grid(row=count, col = 1, padx=5, sticky=W+E)
|
|
||||||
if initialvalue is None:
|
|
||||||
entry.insert(0, 'None')
|
|
||||||
else:
|
|
||||||
entry.insert(0, initialvalue)
|
|
||||||
if entryType == 'float':
|
|
||||||
validateFunc = self.validateFloat
|
|
||||||
elif entryType == 'int':
|
|
||||||
validateFunc = self.validateInt
|
|
||||||
else:
|
|
||||||
validateFunc = self.validateString
|
|
||||||
callback = (lambda event, vf = validateFunc,
|
|
||||||
e=entry,p=property,fn = fAllowNone,: vf(e, p, fn))
|
|
||||||
entry.bind('<Return>', callback)
|
|
||||||
self.entryList.append(entry)
|
|
||||||
count += 1
|
|
||||||
# Set initial focus
|
|
||||||
if len(self.entryList) > 0:
|
|
||||||
entry = self.entryList[0]
|
|
||||||
entry.select_range(0, END)
|
|
||||||
# Set initial focus to first entry in the list
|
|
||||||
return self.entryList[0]
|
|
||||||
else:
|
|
||||||
# Just set initial focus to self
|
|
||||||
return self
|
|
||||||
|
|
||||||
def buttonbox(self):
|
|
||||||
"""add standard button box buttons.
|
|
||||||
"""
|
|
||||||
box = Frame(self)
|
|
||||||
# Create buttons
|
|
||||||
w = Button(box, text="OK", width=10, command=self.ok, default=ACTIVE)
|
|
||||||
w.pack(side=LEFT, padx=5, pady=5)
|
|
||||||
w = Button(box, text="Cancel", width=10, command=self.cancel)
|
|
||||||
w.pack(side=LEFT, padx=5, pady=5)
|
|
||||||
# Bind commands
|
|
||||||
self.bind("<Escape>", self.cancel)
|
|
||||||
# Pack
|
|
||||||
box.pack()
|
|
||||||
|
|
||||||
#
|
|
||||||
# standard button semantics
|
|
||||||
def ok(self, event=None):
|
|
||||||
self.withdraw()
|
|
||||||
self.update_idletasks()
|
|
||||||
self.apply()
|
|
||||||
self.cancel()
|
|
||||||
|
|
||||||
def cancel(self, event=None):
|
|
||||||
# put focus back to the parent window
|
|
||||||
self.parent.focus_set()
|
|
||||||
self.destroy()
|
|
||||||
|
|
||||||
def validateFloat(self, entry, property, fAllowNone):
|
|
||||||
value = entry.get()
|
|
||||||
errormsg = "Please enter a floating point value"
|
|
||||||
if fAllowNone:
|
|
||||||
errormsg += "\nor the string 'None'"
|
|
||||||
try:
|
|
||||||
value = string.atof(value)
|
|
||||||
except ValueError:
|
|
||||||
if fAllowNone and (value == 'None'):
|
|
||||||
value = None
|
|
||||||
else:
|
|
||||||
tkMessageBox.showwarning(
|
|
||||||
"Illegal value", errormsg, parent = self)
|
|
||||||
return 0
|
|
||||||
self.widget[property] = value
|
|
||||||
return 1
|
|
||||||
|
|
||||||
def validateInt(self, entry, property, fAllowNone):
|
|
||||||
value = entry.get()
|
|
||||||
errormsg = "Please enter an integer value"
|
|
||||||
if fAllowNone:
|
|
||||||
errormsg += "\nor the string 'None'"
|
|
||||||
try:
|
|
||||||
value = string.atoi(value)
|
|
||||||
except ValueError:
|
|
||||||
if fAllowNone and (value == 'None'):
|
|
||||||
value = None
|
|
||||||
else:
|
|
||||||
tkMessageBox.showwarning(
|
|
||||||
"Illegal value", errormsg, parent = self)
|
|
||||||
return 0
|
|
||||||
self.widget[property] = value
|
|
||||||
return 1
|
|
||||||
|
|
||||||
def validateString(self, entry, property, fAllowNone):
|
|
||||||
value = entry.get()
|
|
||||||
if fAllowNone and (value == 'None'):
|
|
||||||
value = None
|
|
||||||
self.widget[property] = value
|
|
||||||
|
|
||||||
def apply(self):
|
|
||||||
"""process the data
|
|
||||||
|
|
||||||
This method is called automatically to process the data, *after*
|
|
||||||
the dialog is destroyed. By default, it does nothing.
|
|
||||||
"""
|
|
||||||
pass # override
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Dial(Pmw.MegaWidget):
|
class Dial(Pmw.MegaWidget):
|
||||||
@ -254,12 +71,20 @@ class Dial(Pmw.MegaWidget):
|
|||||||
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')
|
||||||
|
|
||||||
# The Label
|
# The Label
|
||||||
self._label = self.createcomponent('label', (), None,
|
self._label = self.createcomponent('label', (), None,
|
||||||
Label, (interior,),
|
Label, (interior,),
|
||||||
text = self['text'],
|
text = self['text'],
|
||||||
font = ('MS Sans Serif',12,'bold'),
|
font = ('MS Sans Serif',12,'bold'),
|
||||||
anchor = CENTER)
|
anchor = CENTER)
|
||||||
|
self._label.bind('<ButtonPress-3>', self._dial.popupDialMenu)
|
||||||
|
|
||||||
# The entry
|
# The entry
|
||||||
self._entryVal = StringVar()
|
self._entryVal = StringVar()
|
||||||
@ -269,6 +94,7 @@ class Dial(Pmw.MegaWidget):
|
|||||||
width = 12,
|
width = 12,
|
||||||
textvariable = self._entryVal)
|
textvariable = self._entryVal)
|
||||||
self._entry.bind('<Return>', self.validateEntryInput)
|
self._entry.bind('<Return>', self.validateEntryInput)
|
||||||
|
self._entry.bind('<ButtonPress-3>', self._dial.popupDialMenu)
|
||||||
self._entryBackground = self._entry.cget('background')
|
self._entryBackground = self._entry.cget('background')
|
||||||
|
|
||||||
if self['style'] == DIAL_FULL:
|
if self['style'] == DIAL_FULL:
|
||||||
@ -374,6 +200,7 @@ class AngleDial(Dial):
|
|||||||
class DialWidget(Pmw.MegaWidget):
|
class DialWidget(Pmw.MegaWidget):
|
||||||
sfBase = 3.0
|
sfBase = 3.0
|
||||||
sfDist = 15
|
sfDist = 15
|
||||||
|
deadband = 10
|
||||||
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
|
||||||
@ -396,7 +223,7 @@ class DialWidget(Pmw.MegaWidget):
|
|||||||
('min', None, None),
|
('min', None, None),
|
||||||
('max', None, None),
|
('max', None, None),
|
||||||
('resolution', None, None),
|
('resolution', None, None),
|
||||||
('numDigits', 2, None),
|
('numDigits', 2, self.setNumDigits),
|
||||||
# Value dial jumps to on reset
|
# Value dial jumps to on reset
|
||||||
('resetValue', 0.0, None),
|
('resetValue', 0.0, None),
|
||||||
## Behavior
|
## Behavior
|
||||||
@ -435,6 +262,31 @@ 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,),
|
||||||
@ -625,8 +477,11 @@ class DialWidget(Pmw.MegaWidget):
|
|||||||
def computeKnobSF(self, event):
|
def computeKnobSF(self, event):
|
||||||
x = self._canvas.canvasx(event.x)
|
x = self._canvas.canvasx(event.x)
|
||||||
y = self._canvas.canvasy(event.y)
|
y = self._canvas.canvasy(event.y)
|
||||||
minExp = math.floor(-self['numDigits']/math.log10(DialWidget.sfBase))
|
offset = max(0, abs(x) - DialWidget.deadband)
|
||||||
sf = math.pow(DialWidget.sfBase, minExp + (abs(x) / DialWidget.sfDist))
|
if offset == 0:
|
||||||
|
return 0
|
||||||
|
sf = math.pow(DialWidget.sfBase,
|
||||||
|
self.minExp + offset/DialWidget.sfDist)
|
||||||
if x > 0:
|
if x > 0:
|
||||||
return sf
|
return sf
|
||||||
else:
|
else:
|
||||||
@ -674,6 +529,11 @@ class DialWidget(Pmw.MegaWidget):
|
|||||||
def setBorderwidth(self):
|
def setBorderwidth(self):
|
||||||
self.interior()['borderwidth'] = self['borderwidth']
|
self.interior()['borderwidth'] = self['borderwidth']
|
||||||
|
|
||||||
|
def setNumDigits(self):
|
||||||
|
# Set minimum exponent to use in velocity task
|
||||||
|
self.minExp = math.floor(-self['numDigits']/
|
||||||
|
math.log10(DialWidget.sfBase))
|
||||||
|
|
||||||
# The following methods are used to handle the popup menu
|
# The following methods are used to handle the popup menu
|
||||||
def popupDialMenu(self,event):
|
def popupDialMenu(self,event):
|
||||||
self._popupMenu.post(event.widget.winfo_pointerx(),
|
self._popupMenu.post(event.widget.winfo_pointerx(),
|
||||||
@ -690,55 +550,11 @@ class DialWidget(Pmw.MegaWidget):
|
|||||||
# This handles the popup dial min dialog
|
# This handles the popup dial min dialog
|
||||||
def getProperties(self):
|
def getProperties(self):
|
||||||
# Popup dialog to adjust widget properties
|
# Popup dialog to adjust widget properties
|
||||||
WidgetPropertiesDialog(self, [
|
WidgetPropertiesDialog(
|
||||||
['min', 'float', 1],
|
self.propertyDict,
|
||||||
['min', 'float', 1],
|
propertyList = self.propertyList,
|
||||||
['base', 'float', 1],
|
title = 'Dial Widget Properties',
|
||||||
['delta', 'float', 0],
|
parent = self._canvas)
|
||||||
['resetValue', 'float', 0]])
|
|
||||||
|
|
||||||
def getMin(self):
|
|
||||||
newMin = askfloat('Dial Min', 'Min:',
|
|
||||||
initialvalue = `self['min']`,
|
|
||||||
parent = self.interior())
|
|
||||||
if newMin is not None:
|
|
||||||
self['min'] = newMin
|
|
||||||
self.updateIndicator(self.value)
|
|
||||||
|
|
||||||
# This handles the popup dial base value dialog
|
|
||||||
def getBase(self):
|
|
||||||
newBase = askfloat('Dial Base Value', 'Base:',
|
|
||||||
initialvalue = `self['base']`,
|
|
||||||
parent = self.interior())
|
|
||||||
if newBase is not None:
|
|
||||||
self['base'] = newBase
|
|
||||||
self.updateIndicator(self.value)
|
|
||||||
|
|
||||||
# This handles the popup dial delta dialog
|
|
||||||
def getDelta(self):
|
|
||||||
newDelta = askfloat('Delta Per Revolution', 'Delta:',
|
|
||||||
initialvalue = `self['delta']`,
|
|
||||||
parent = self.interior())
|
|
||||||
if newDelta is not None:
|
|
||||||
self['delta'] = newDelta
|
|
||||||
self.updateIndicator(self.value)
|
|
||||||
|
|
||||||
# This handles the popup dial max dialog
|
|
||||||
def getMax(self):
|
|
||||||
newMax = askfloat('Dial Max', 'Max:',
|
|
||||||
initialvalue = `self['max']`,
|
|
||||||
parent = self.interior())
|
|
||||||
if newMax is not None:
|
|
||||||
self['max'] = newMax
|
|
||||||
self.updateIndicator(self.value)
|
|
||||||
|
|
||||||
# This handles the popup dial resetValue dialog
|
|
||||||
def getResetValue(self):
|
|
||||||
newResetValue = askfloat('Dial ResetValue', 'ResetValue:',
|
|
||||||
initialvalue = `self['resetValue']`,
|
|
||||||
parent = self.interior())
|
|
||||||
if newResetValue is not None:
|
|
||||||
self['resetValue'] = newResetValue
|
|
||||||
|
|
||||||
# User callbacks
|
# User callbacks
|
||||||
def _onButtonPress(self, *args):
|
def _onButtonPress(self, *args):
|
||||||
|
221
direct/src/tkwidgets/WidgetPropertiesDialog.py
Normal file
221
direct/src/tkwidgets/WidgetPropertiesDialog.py
Normal file
@ -0,0 +1,221 @@
|
|||||||
|
from Tkinter import *
|
||||||
|
import Pmw
|
||||||
|
import types
|
||||||
|
import string
|
||||||
|
|
||||||
|
"""
|
||||||
|
TODO:
|
||||||
|
Checkboxes for None?
|
||||||
|
Floaters to adjust float values
|
||||||
|
OK and Cancel to allow changes to be delayed
|
||||||
|
Something other than Return to accept a new value
|
||||||
|
"""
|
||||||
|
|
||||||
|
class WidgetPropertiesDialog(Toplevel):
|
||||||
|
"""Class to open dialogs to adjust widget properties."""
|
||||||
|
def __init__(self, propertyDict, propertyList = None, parent = None,
|
||||||
|
title = 'Widget Properties'):
|
||||||
|
"""Initialize a dialog.
|
||||||
|
Arguments:
|
||||||
|
propertyDict -- a dictionary of properties to be edited
|
||||||
|
parent -- a parent window (the application window)
|
||||||
|
title -- the dialog title
|
||||||
|
"""
|
||||||
|
# Record property list
|
||||||
|
self.propertyDict = propertyDict
|
||||||
|
self.propertyList = propertyList
|
||||||
|
if self.propertyList is None:
|
||||||
|
self.propertyList = self.propertyDict.keys()
|
||||||
|
self.propertyList.sort()
|
||||||
|
# Use default parent if none specified
|
||||||
|
if not parent:
|
||||||
|
import Tkinter
|
||||||
|
parent = Tkinter._default_root
|
||||||
|
# Create toplevel window
|
||||||
|
Toplevel.__init__(self, parent)
|
||||||
|
self.transient(parent)
|
||||||
|
# Set title
|
||||||
|
if title:
|
||||||
|
self.title(title)
|
||||||
|
# Record parent
|
||||||
|
self.parent = parent
|
||||||
|
# Initialize modifications
|
||||||
|
self.modifiedDict = {}
|
||||||
|
# Create body
|
||||||
|
body = Frame(self)
|
||||||
|
self.initial_focus = self.body(body)
|
||||||
|
body.pack(padx=5, pady=5)
|
||||||
|
# Create OK Cancel button
|
||||||
|
self.buttonbox()
|
||||||
|
# Initialize window state
|
||||||
|
self.grab_set()
|
||||||
|
self.protocol("WM_DELETE_WINDOW", self.cancel)
|
||||||
|
self.geometry("+%d+%d" % (parent.winfo_rootx()+50,
|
||||||
|
parent.winfo_rooty()+50))
|
||||||
|
self.initial_focus.focus_set()
|
||||||
|
self.wait_window(self)
|
||||||
|
|
||||||
|
def destroy(self):
|
||||||
|
"""Destroy the window"""
|
||||||
|
self.propertyDict = {}
|
||||||
|
self.initial_focus = None
|
||||||
|
# Clean up balloons!
|
||||||
|
for balloon in self.balloonList:
|
||||||
|
balloon.withdraw()
|
||||||
|
Toplevel.destroy(self)
|
||||||
|
|
||||||
|
#
|
||||||
|
# construction hooks
|
||||||
|
def body(self, master):
|
||||||
|
"""create dialog body.
|
||||||
|
return entry that should have initial focus.
|
||||||
|
This method should be overridden, and is called
|
||||||
|
by the __init__ method.
|
||||||
|
"""
|
||||||
|
count = 0
|
||||||
|
entryList = []
|
||||||
|
self.balloonList = []
|
||||||
|
for property in self.propertyList:
|
||||||
|
propertySet = self.propertyDict[property]
|
||||||
|
# Widget
|
||||||
|
widget = propertySet.get('widget', None)
|
||||||
|
# Get initial value
|
||||||
|
initialvalue = widget[property]
|
||||||
|
# Type of entry
|
||||||
|
entryType = propertySet.get('type', 'real')
|
||||||
|
# Is None an allowable value?
|
||||||
|
fAllowNone = propertySet.get('fNone', 0)
|
||||||
|
# Help string specified?
|
||||||
|
helpString = propertySet.get('help', None)
|
||||||
|
# Create label
|
||||||
|
label = Label(master, text=property, justify=LEFT)
|
||||||
|
label.grid(row=count, col = 0, padx=5, sticky=W)
|
||||||
|
|
||||||
|
# Create entry
|
||||||
|
entry = Pmw.EntryField(master, entry_justify = 'right')
|
||||||
|
entry.grid(row=count, col = 1, padx=5, sticky=W+E)
|
||||||
|
if initialvalue is None:
|
||||||
|
entry.insert(0, 'None')
|
||||||
|
else:
|
||||||
|
entry.insert(0, initialvalue)
|
||||||
|
|
||||||
|
# Create balloon for help
|
||||||
|
balloon = Pmw.Balloon(state = 'balloon')
|
||||||
|
self.balloonList.append(balloon)
|
||||||
|
# extra info if None is allowed value
|
||||||
|
if helpString is None:
|
||||||
|
if fAllowNone:
|
||||||
|
extra = ' or None'
|
||||||
|
else:
|
||||||
|
extra = ''
|
||||||
|
# Set up help string and validator based upon type
|
||||||
|
if entryType == 'real':
|
||||||
|
entry['validate'] = { 'validator' : self.realOrNone }
|
||||||
|
if helpString is None:
|
||||||
|
helpString = 'Enter a floating point number' + extra + '.'
|
||||||
|
elif entryType == 'integer':
|
||||||
|
entry['validate'] = { 'validator' : self.intOrNone }
|
||||||
|
if helpString is None:
|
||||||
|
helpString = 'Enter an integer' + extra + '.'
|
||||||
|
else:
|
||||||
|
entry['validate'] = { 'validator' : 'alphanumeric' }
|
||||||
|
if helpString is None:
|
||||||
|
helpString = 'Enter a string' + extra + '.'
|
||||||
|
# Bind balloon with help string to entry
|
||||||
|
balloon.bind(entry, helpString)
|
||||||
|
# Create callback to execute whenever a value is changed
|
||||||
|
modifiedCallback = (lambda f=self.modified, w=widget, e=entry,
|
||||||
|
p=property, t=entryType,fn=fAllowNone:
|
||||||
|
f(w,e,p,t, fn))
|
||||||
|
entry['modifiedcommand'] = modifiedCallback
|
||||||
|
# Keep track of the entrys
|
||||||
|
entryList.append(entry)
|
||||||
|
count += 1
|
||||||
|
# Set initial focus
|
||||||
|
if len(entryList) > 0:
|
||||||
|
entry = entryList[0]
|
||||||
|
entry.select_range(0, END)
|
||||||
|
# Set initial focus to first entry in the list
|
||||||
|
return entryList[0]
|
||||||
|
else:
|
||||||
|
# Just set initial focus to self
|
||||||
|
return self
|
||||||
|
|
||||||
|
def modified(self, widget, entry, property, type, fNone):
|
||||||
|
self.modifiedDict[property] = (widget,entry,type,fNone)
|
||||||
|
|
||||||
|
def buttonbox(self):
|
||||||
|
"""add standard button box buttons.
|
||||||
|
"""
|
||||||
|
box = Frame(self)
|
||||||
|
# Create buttons
|
||||||
|
w = Button(box, text="OK", width=10, command=self.ok)
|
||||||
|
w.pack(side=LEFT, padx=5, pady=5)
|
||||||
|
# Create buttons
|
||||||
|
w = Button(box, text="Cancel", width=10, command=self.cancel)
|
||||||
|
w.pack(side=LEFT, padx=5, pady=5)
|
||||||
|
# Bind commands
|
||||||
|
self.bind("<Return>", self.ok)
|
||||||
|
self.bind("<Escape>", self.cancel)
|
||||||
|
# Pack
|
||||||
|
box.pack()
|
||||||
|
|
||||||
|
def realOrNone(self, val):
|
||||||
|
val = string.lower(val)
|
||||||
|
if string.find('none', val) != -1:
|
||||||
|
if val == 'none':
|
||||||
|
return Pmw.OK
|
||||||
|
else:
|
||||||
|
return Pmw.PARTIAL
|
||||||
|
return Pmw.realvalidator(val)
|
||||||
|
|
||||||
|
def intOrNone(self, val):
|
||||||
|
val = string.lower(val)
|
||||||
|
if string.find('none', val) != -1:
|
||||||
|
if val == 'none':
|
||||||
|
return Pmw.OK
|
||||||
|
else:
|
||||||
|
return Pmw.PARTIAL
|
||||||
|
return Pmw.integervalidator(val)
|
||||||
|
|
||||||
|
#
|
||||||
|
# standard button semantics
|
||||||
|
def ok(self, event=None):
|
||||||
|
self.withdraw()
|
||||||
|
self.update_idletasks()
|
||||||
|
self.validateChanges()
|
||||||
|
self.apply()
|
||||||
|
self.cancel()
|
||||||
|
|
||||||
|
def cancel(self, event=None):
|
||||||
|
# put focus back to the parent window
|
||||||
|
self.parent.focus_set()
|
||||||
|
self.destroy()
|
||||||
|
|
||||||
|
def validateChanges(self):
|
||||||
|
for property in self.modifiedDict.keys():
|
||||||
|
tuple = self.modifiedDict[property]
|
||||||
|
widget = tuple[0]
|
||||||
|
entry = tuple[1]
|
||||||
|
type = tuple[2]
|
||||||
|
fNone = tuple[3]
|
||||||
|
value = entry.get()
|
||||||
|
lValue = string.lower(value)
|
||||||
|
if (string.find('none', lValue) != -1):
|
||||||
|
if fNone and (lValue == 'none'):
|
||||||
|
widget[property] = None
|
||||||
|
else:
|
||||||
|
if type == 'real':
|
||||||
|
value = string.atof(value)
|
||||||
|
elif type == 'integer':
|
||||||
|
value = string.atoi(value)
|
||||||
|
widget[property] = value
|
||||||
|
|
||||||
|
def apply(self):
|
||||||
|
"""process the data
|
||||||
|
|
||||||
|
This method is called automatically to process the data, *after*
|
||||||
|
the dialog is destroyed. By default, it does nothing.
|
||||||
|
"""
|
||||||
|
pass # override
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user