| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341 |
- from DirectGuiGlobals import *
- from DirectFrame import *
- from DirectButton import *
- class DirectDialog(DirectFrame):
- def __init__(self, parent = guiTop, **kw):
- """
- DirectDialog(kw)
- Creates a popup dialog to alert and/or interact with user.
- Some of the main keywords that can be used to customize the dialog:
- Keyword Definition
- ------- ----------
- text Text message/query displayed to user
- geom Geometry to be displayed in dialog
- buttonTextList List of text to show on each button
- buttonGeomList List of geometry to show on each button
- buttonImageList List of images to show on each button
- buttonValueList List of values sent to dialog command for
- each button. If value is [] then the
- ordinal rank of the button is used as
- its value
- buttonHotKeyList List of hotkeys to bind to each button.
- Typing hotkey is equivalent to pressing
- the corresponding button.
- supressKeys Set to true if you wish to supress keys
- (i.e. Dialog eats key event), false if
- you wish Dialog to pass along key event
- buttonSize 4-tuple used to specify custom size for
- each button (to make bigger then geom/text
- for example)
- pad Space between border and interior graphics
- topPad Extra space added above text/geom/image
- midPad Extra space added between text/buttons
- buttonPadSF Scale factor used to expand/contract
- button horizontal spacing
- command Callback command used when a button is
- pressed. Value supplied to command
- depends on values in buttonValueList
- Note: Number of buttons on the dialog depends upon the maximum
- length of any button[Text|Geom|Image|Value]List specified.
- Values of None are substituted for lists that are shorter
- than the max length
- """
-
- # Inherits from DirectFrame
- optiondefs = (
- # Define type of DirectGuiWidget
- ('pad', (0.1, 0.1), None),
- ('text', '', None),
- ('text_align', TMALIGNLEFT, None),
- ('text_scale', 0.06, None),
- ('image', getDefaultDialogGeom(), None),
- ('relief', None, None),
- ('buttonTextList', [], INITOPT),
- ('buttonGeomList', [], INITOPT),
- ('buttonImageList', [], INITOPT),
- ('buttonValueList', [], INITOPT),
- ('buttonHotKeyList', [], INITOPT),
- ('button_borderWidth',(.01,.01), None),
- ('button_pad', (.01,.01), None),
- ('button_relief', RAISED, None),
- ('button_text_scale' , 0.06, None),
- ('buttonSize', None, INITOPT),
- ('topPad', 0.06, INITOPT),
- ('midPad', 0.12, INITOPT),
- ('buttonPadSF', 1.05, INITOPT),
- ('command', None, None),
- ('extraArgs', [], None),
- )
- # Merge keyword options with default options
- self.defineoptions(kw, optiondefs, dynamicGroups = ("button",))
- # Initialize superclasses
- DirectFrame.__init__(self, parent)
- # Determine number of buttons
- self.numButtons = max(len(self['buttonTextList']),
- len(self['buttonGeomList']),
- len(self['buttonImageList']),
- len(self['buttonValueList']))
- # Create buttons
- self.buttonList = []
- index = 0
- for i in range(self.numButtons):
- name = 'Button' + `i`
- try:
- text = self['buttonTextList'][i]
- except IndexError:
- text = None
- try:
- geom = self['buttonGeomList'][i]
- except IndexError:
- geom = None
- try:
- image = self['buttonImageList'][i]
- except IndexError:
- image = None
- try:
- value = self['buttonValueList'][i]
- except IndexError:
- value = i
- self['buttonValueList'].append(i)
- try:
- hotKey = self['buttonHotKeyList'][i]
- except IndexError:
- hotKey = None
- button = self.createcomponent(
- name, (), "button",
- DirectButton, (self,),
- text = text,
- geom = geom,
- image = image,
- suppressKeys = self['suppressKeys'],
- frameSize = self['buttonSize'],
- command = lambda s = self, v = value: s.buttonCommand(v)
- )
- self.buttonList.append(button)
- # Update dialog when everything has been initialised
- self.postInitialiseFuncList.append(self.configureDialog)
- self.initialiseoptions(DirectDialog)
- def configureDialog(self):
- # Set up hot key bindings
- bindList = zip(self.buttonList, self['buttonHotKeyList'],
- self['buttonValueList'])
- for button, hotKey, value in bindList:
- if ((type(hotKey) == types.ListType) or
- (type(hotKey) == types.TupleType)):
- for key in hotKey:
- button.bind('press-' + key + '-', self.buttonCommand,
- extraArgs = [value])
- self.bind('press-' + key + '-', self.buttonCommand,
- extraArgs = [value])
-
- else:
- button.bind('press-' + hotKey + '-',self.buttonCommand,
- extraArgs = [value])
- self.bind('press-' + hotKey + '-', self.buttonCommand,
- extraArgs = [value])
- # Position buttons and text
- pad = self['pad']
- bpad = self['button_pad']
- image = self.component('image0')
- # Get size of text/geom without image (for state 0)
- if image:
- image.reparentTo(hidden)
- bounds = self.stateNodePath[0].getTightBounds()
- if image:
- image.reparentTo(self.stateNodePath[0])
- l = bounds[0][0]
- r = bounds[1][0]
- b = bounds[0][2]
- t = bounds[1][2]
- # Center text and geom around origin
- # How far is center of text from origin?
- xOffset = -(l+r)/2.0
- zOffset = -(b+t)/2.0
- # Update bounds to reflect text movement
- l += xOffset
- r += xOffset
- b += zOffset
- t += zOffset
- # Offset text and geom to center
- if self['text']:
- self['text_pos'] = (self['text_pos'][0] + xOffset,
- self['text_pos'][1] + zOffset)
- if self['geom']:
- self['geom_pos'] = Point3(self['geom_pos'][0] + xOffset,
- self['geom_pos'][1],
- self['geom_pos'][2] + zOffset)
- # Get button size
- if self['buttonSize']:
- # Either use given size
- buttonSize = self['buttonSize']
- bl = buttonSize[0]
- br = buttonSize[1]
- bb = buttonSize[2]
- bt = buttonSize[3]
- else:
- # Or get bounds of union of buttons
- bl = br = bb = bt = 0
- for button in self.buttonList:
- bounds = button.stateNodePath[0].getTightBounds()
- bl = min(bl, bounds[0][0])
- br = max(br, bounds[1][0])
- bb = min(bb, bounds[0][2])
- bt = max(bt, bounds[1][2])
- bl -= bpad[0]
- br += bpad[0]
- bb -= bpad[1]
- bt += bpad[1]
- # Now resize buttons to match largest
- for button in self.buttonList:
- button['frameSize'] = (bl,br,bb,bt)
- # Must compensate for scale
- scale = self['button_scale']
- # Can either be a Vec3 or a tuple of 3 values
- if (isinstance(scale, Vec3) or
- (type(scale) == types.ListType) or
- (type(scale) == types.TupleType)):
- sx = scale[0]
- sz = scale[2]
- elif ((type(scale) == types.IntType) or
- (type(scale) == types.FloatType)):
- sx = sz = scale
- else:
- sx = sz = 1
- bl *= sx
- br *= sx
- bb *= sz
- bt *= sz
- # Position buttons
- # Calc button width and height
- bHeight = bt - bb
- bWidth = br - bl
- # Add pad between buttons
- bSpacing = self['buttonPadSF'] * bWidth
- if self.numButtons != 0:
- bPos = -bSpacing * (self.numButtons - 1)/2.0
- index = 0
- for button in self.buttonList:
- button.setPos(bPos + index * bSpacing, 0,
- b - self['midPad'] - bpad[1] - bt)
- index += 1
- bMax = bPos + bSpacing * (self.numButtons - 1)
- else:
- bPos = 0
- bMax = 0
- # Resize frame to fit text and buttons
- l = min(bPos + bl, l) - pad[0]
- r = max(bMax + br, r) + pad[0]
- # reduce bottom by pad, button height and 2*button pad
- b = min(b - self['midPad'] - bpad[1] - bHeight - bpad[1], b) - pad[1]
- t = t + self['topPad'] + pad[1]
- self['image_scale'] = (r - l, 1, t - b)
- # Center frame about text and buttons
- self['image_pos'] = ((l+r)/2.0, 0.0,(b+t)/2.0)
- self.resetFrameSize()
- def buttonCommand(self, value, event = None):
- if self['command']:
- self['command'](value)
-
- def destroy(self):
- DirectFrame.destroy(self)
- class OKDialog(DirectDialog):
- def __init__(self, parent = guiTop, **kw):
- # Inherits from DirectFrame
- optiondefs = (
- # Define type of DirectGuiWidget
- ('buttonTextList', ['OK'], INITOPT),
- ('buttonValueList', [1], INITOPT),
- )
- # Merge keyword options with default options
- self.defineoptions(kw, optiondefs)
- DirectDialog.__init__(self, parent)
- self.initialiseoptions(OKDialog)
- class OKCancelDialog(DirectDialog):
- def __init__(self, parent = guiTop, **kw):
- # Inherits from DirectFrame
- optiondefs = (
- # Define type of DirectGuiWidget
- ('buttonTextList', ['OK','Cancel'], INITOPT),
- ('buttonValueList', [1,-1], INITOPT),
- )
- # Merge keyword options with default options
- self.defineoptions(kw, optiondefs)
- DirectDialog.__init__(self, parent)
- self.initialiseoptions(OKCancelDialog)
- class YesNoDialog(DirectDialog):
- def __init__(self, parent = guiTop, **kw):
- # Inherits from DirectFrame
- optiondefs = (
- # Define type of DirectGuiWidget
- ('buttonTextList', ['Yes', 'No'], INITOPT),
- ('buttonValueList', [1,0], INITOPT),
- )
- # Merge keyword options with default options
- self.defineoptions(kw, optiondefs)
- DirectDialog.__init__(self, parent)
- self.initialiseoptions(YesNoDialog)
- class YesNoCancelDialog(DirectDialog):
- def __init__(self, parent = guiTop, **kw):
- # Inherits from DirectFrame
- optiondefs = (
- # Define type of DirectGuiWidget
- ('buttonTextList', ['Yes', 'No', 'Cancel'], INITOPT),
- ('buttonValueList', [1,0,-1], INITOPT),
- )
- # Merge keyword options with default options
- self.defineoptions(kw, optiondefs)
- DirectDialog.__init__(self, parent)
- self.initialiseoptions(YesNoCancelDialog)
- class RetryCancelDialog(DirectDialog):
- def __init__(self, parent = guiTop, **kw):
- # Inherits from DirectFrame
- optiondefs = (
- # Define type of DirectGuiWidget
- ('buttonTextList', ['Retry','Cancel'], INITOPT),
- ('buttonValueList', [1,-1], INITOPT),
- )
- # Merge keyword options with default options
- self.defineoptions(kw, optiondefs)
- DirectDialog.__init__(self, parent)
- self.initialiseoptions(RetryCancelDialog)
- class TTOkCancelDialog(DirectDialog):
- def __init__(self, parent = guiTop, **kw):
- # Inherits from DirectDialog
- buttons = loader.loadModelOnce(
- 'phase_3/models/gui/dialog_box_buttons_gui')
- okImageList = (buttons.find('**/ChtBx_OKBtn_UP'),
- buttons.find('**/ChtBx_OKBtn_DN'),
- buttons.find('**/ChtBx_OKBtn_Rllvr'))
- okTextList = ('', 'OK', 'OK')
- cancelImageList = (buttons.find('**/CloseBtn_UP'),
- buttons.find('**/CloseBtn_DN'),
- buttons.find('**/CloseBtn_Rllvr'))
- cancelTextList = ('', 'Cancel', 'Cancel')
- optiondefs = (
- # Define type of DirectGuiWidget
- ('buttonTextList', [okTextList, cancelTextList], INITOPT),
- ('buttonImageList', [okImageList, cancelImageList], INITOPT),
- ('buttonValueList', [1,-1], INITOPT),
- ('button_pad', (0,0), None),
- ('button_relief', None, None),
- ('button_text_pos', (0,-0.1), None),
- ('buttonSize', (-.05,.05,-.05,.05), None),
- )
- # Merge keyword options with default options
- self.defineoptions(kw, optiondefs)
- DirectDialog.__init__(self, parent)
- self.initialiseoptions(TTOkCancelDialog)
- buttons.removeNode()
|