| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232 |
- """Undocumented Module"""
- __all__ = ['WidgetPropertiesDialog']
- from direct.showbase.TkGlobal import *
- from Tkinter import *
- import types, string, Pmw
- """
- 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, column = 0, padx=5, sticky=W)
- # Create entry
- entry = Pmw.EntryField(master, entry_justify = 'right')
- entry.grid(row=count, column = 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':
- # Only allow real numbers
- if fAllowNone:
- entry['validate'] = { 'validator': self.realOrNone }
- else:
- entry['validate'] = { 'validator': 'real' }
- if helpString is None:
- helpString = 'Enter a floating point number' + extra + '.'
- elif entryType == 'integer':
- # Only allow integer values
- if fAllowNone:
- entry['validate'] = { 'validator': self.intOrNone }
- else:
- entry['validate'] = { 'validator': 'integer' }
- if helpString is None:
- helpString = 'Enter an integer' + extra + '.'
- else:
- # Anything goes with a string widget
- 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
|