| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250 |
- """Undocumented Module"""
- __all__ = ['DirectEntry']
- from pandac.PandaModules import *
- import DirectGuiGlobals as DGG
- from DirectFrame import *
- from OnscreenText import OnscreenText
- import string,types
- # DirectEntry States:
- ENTRY_FOCUS_STATE = PGEntry.SFocus # 0
- ENTRY_NO_FOCUS_STATE = PGEntry.SNoFocus # 1
- ENTRY_INACTIVE_STATE = PGEntry.SInactive # 2
- class DirectEntry(DirectFrame):
- """
- DirectEntry(parent) - Create a DirectGuiWidget which responds
- to keyboard buttons
- """
- directWtext = ConfigVariableBool('direct-wtext', 1)
- def __init__(self, parent = None, **kw):
- # Inherits from DirectFrame
- # A Direct Frame can have:
- # - A background texture (pass in path to image, or Texture Card)
- # - A midground geometry item (pass in geometry)
- # - A foreground text Node (pass in text string or Onscreen Text)
- # For a direct entry:
- # Each button has 3 states (focus, noFocus, disabled)
- # The same image/geom/text can be used for all three states or each
- # state can have a different text/geom/image
- # State transitions happen automatically based upon mouse interaction
- optiondefs = (
- # Define type of DirectGuiWidget
- ('pgFunc', PGEntry, None),
- ('numStates', 3, None),
- ('state', DGG.NORMAL, None),
- ('entryFont', None, DGG.INITOPT),
- ('width', 10, self.setup),
- ('numLines', 1, self.setup),
- ('focus', 0, self.setFocus),
- ('cursorKeys', 1, self.setCursorKeysActive),
- ('obscured', 0, self.setObscureMode),
- # Setting backgroundFocus allows the entry box to get keyboard
- # events that are not handled by other things (i.e. events that
- # fall through to the background):
- ('backgroundFocus', 0, self.setBackgroundFocus),
- # Text used for the PGEntry text node
- # NOTE: This overrides the DirectFrame text option
- ('initialText', '', DGG.INITOPT),
- # Command to be called on hitting Enter
- ('command', None, None),
- ('extraArgs', [], None),
- # Command to be called when enter is hit but we fail to submit
- ('failedCommand', None, None),
- ('failedExtraArgs',[], None),
- # commands to be called when focus is gained or lost
- ('focusInCommand', None, None),
- ('focusInExtraArgs', [], None),
- ('focusOutCommand', None, None),
- ('focusOutExtraArgs', [], None),
- # Sounds to be used for button events
- ('rolloverSound', DGG.getDefaultRolloverSound(), self.setRolloverSound),
- ('clickSound', DGG.getDefaultClickSound(), self.setClickSound),
- )
- # Merge keyword options with default options
- self.defineoptions(kw, optiondefs)
- # Initialize superclasses
- DirectFrame.__init__(self, parent)
- if self['entryFont'] == None:
- font = DGG.getDefaultFont()
- else:
- font = self['entryFont']
- # Create Text Node Component
- self.onscreenText = self.createcomponent(
- 'text', (), None,
- OnscreenText,
- (), parent = hidden,
- # Pass in empty text to avoid extra work, since its really
- # The PGEntry which will use the TextNode to generate geometry
- text = '',
- align = TextNode.ALeft,
- font = font,
- scale = 1,
- # Don't get rid of the text node
- mayChange = 1)
- # We can get rid of the node path since we're just using the
- # onscreenText as an easy way to access a text node as a
- # component
- self.onscreenText.removeNode()
- # Bind command function
- self.bind(DGG.ACCEPT, self.commandFunc)
- self.bind(DGG.ACCEPTFAILED, self.failedCommandFunc)
- self.accept(self.guiItem.getFocusInEvent(), self.focusInCommandFunc)
- self.accept(self.guiItem.getFocusOutEvent(), self.focusOutCommandFunc)
- # Call option initialization functions
- self.initialiseoptions(DirectEntry)
- # Update TextNodes for each state
- for i in range(self['numStates']):
- self.guiItem.setTextDef(i, self.onscreenText.textNode)
- # Update initial text
- self.unicodeText = 0
- if self['initialText']:
- self.set(self['initialText'])
- def destroy(self):
- self.ignore(self.guiItem.getFocusInEvent())
- self.ignore(self.guiItem.getFocusOutEvent())
- DirectFrame.destroy(self)
- def setup(self):
- self.node().setup(self['width'], self['numLines'])
- def setFocus(self):
- PGEntry.setFocus(self.guiItem, self['focus'])
- def setCursorKeysActive(self):
- PGEntry.setCursorKeysActive(self.guiItem, self['cursorKeys'])
- def setObscureMode(self):
- PGEntry.setObscureMode(self.guiItem, self['obscured'])
- def setBackgroundFocus(self):
- PGEntry.setBackgroundFocus(self.guiItem, self['backgroundFocus'])
- def setRolloverSound(self):
- rolloverSound = self['rolloverSound']
- if rolloverSound:
- self.guiItem.setSound(DGG.ENTER + self.guiId, rolloverSound)
- else:
- self.guiItem.clearSound(DGG.ENTER + self.guiId)
- def setClickSound(self):
- clickSound = self['clickSound']
- if clickSound:
- self.guiItem.setSound(DGG.ACCEPT + self.guiId, clickSound)
- else:
- self.guiItem.clearSound(DGG.ACCEPT + self.guiId)
- def commandFunc(self, event):
- if self['command']:
- # Pass any extra args to command
- apply(self['command'], [self.get()] + self['extraArgs'])
- def failedCommandFunc(self, event):
- if self['failedCommand']:
- # Pass any extra args
- apply(self['failedCommand'], [self.get()] + self['failedExtraArgs'])
- def focusInCommandFunc(self):
- if self['focusInCommand']:
- apply(self['focusInCommand'], self['focusInExtraArgs'])
- def focusOutCommandFunc(self):
- if self['focusOutCommand']:
- apply(self['focusOutCommand'], self['focusOutExtraArgs'])
- def set(self, text):
- """ Changes the text currently showing in the typable region;
- does not change the current cursor position. Also see
- enterText(). """
-
- self.unicodeText = isinstance(text, types.UnicodeType)
- if self.unicodeText:
- self.guiItem.setWtext(text)
- else:
- self.guiItem.setText(text)
- def get(self, plain = False):
- """ Returns the text currently showing in the typable region.
- If plain is True, the returned text will not include any
- formatting characters like nested color-change codes. """
- wantWide = self.unicodeText or self.guiItem.isWtext()
- if not self.directWtext.getValue():
- # If the user has configured wide-text off, then always
- # return an 8-bit string. This will be encoded if
- # necessary, according to Panda's default encoding.
- wantWide = False
- if plain:
- if wantWide:
- return self.guiItem.getPlainWtext()
- else:
- return self.guiItem.getPlainText()
- else:
- if wantWide:
- return self.guiItem.getWtext()
- else:
- return self.guiItem.getText()
- def setCursorPosition(self, pos):
- if (pos < 0):
- self.guiItem.setCursorPosition(self.guiItem.getNumCharacters() + pos)
- else:
- self.guiItem.setCursorPosition(pos)
- def enterText(self, text):
- """ sets the entry's text, and moves the cursor to the end """
- self.set(text)
- self.setCursorPosition(self.guiItem.getNumCharacters())
- def getBounds(self, state = 0):
- # Compute the width and height for the entry itself, ignoring
- # geometry etc.
- tn = self.onscreenText.textNode
- mat = tn.getTransform()
- align = tn.getAlign()
- lineHeight = tn.getLineHeight()
- numLines = self['numLines']
- width = self['width']
- if align == TextNode.ALeft:
- left = 0.0
- right = width
- elif align == TextNode.ACenter:
- left = -width / 2.0
- right = width / 2.0
- elif align == TextNode.ARight:
- left = -width
- right = 0.0
- bottom = -0.3 * lineHeight - (lineHeight * (numLines - 1))
- top = lineHeight
- self.ll.set(left, 0.0, bottom)
- self.ur.set(right, 0.0, top)
- self.ll = mat.xformPoint(self.ll)
- self.ur = mat.xformPoint(self.ur)
- # Scale bounds to give a pad around graphics. We also want to
- # scale around the border width.
- pad = self['pad']
- borderWidth = self['borderWidth']
- self.bounds = [self.ll[0] - pad[0] - borderWidth[0],
- self.ur[0] + pad[0] + borderWidth[0],
- self.ll[2] - pad[1] - borderWidth[1],
- self.ur[2] + pad[1] + borderWidth[1]]
- return self.bounds
|