DirectCheckButton.py 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. """Undocumented Module"""
  2. __all__ = ['DirectCheckButton']
  3. from pandac.PandaModules import *
  4. import DirectGuiGlobals as DGG
  5. from DirectButton import *
  6. from DirectLabel import *
  7. class DirectCheckButton(DirectButton):
  8. """
  9. DirectCheckButton(parent) - Create a DirectGuiWidget which responds
  10. to mouse clicks by setting a state of on or off and execute a callback
  11. function (passing that state through) if defined
  12. """
  13. def __init__(self, parent = None, **kw):
  14. # Inherits from DirectButton
  15. # A Direct Frame can have:
  16. # - A background texture (pass in path to image, or Texture Card)
  17. # - A midground geometry item (pass in geometry)
  18. # - A foreground text Node (pass in text string or Onscreen Text)
  19. # For a direct button:
  20. # Each button has 4 states (ready, press, rollover, disabled)
  21. # The same image/geom/text can be used for all four states or each
  22. # state can have a different text/geom/image
  23. # State transitions happen automatically based upon mouse interaction
  24. # Responds to click event and calls command if None
  25. self.colors = None
  26. optiondefs = (
  27. ('indicatorValue', 0, self.setIndicatorValue),
  28. # boxBorder defines the space created around the check box
  29. ('boxBorder', 0, None),
  30. # boxPlacement maps left, above, right, below
  31. ('boxPlacement', 'left', None),
  32. ('boxImage', None, None),
  33. ('boxImageScale', 1, None),
  34. ('boxImageColor', None, None),
  35. ('boxRelief', 'sunken', None),
  36. )
  37. # Merge keyword options with default options
  38. self.defineoptions(kw, optiondefs)
  39. # Initialize superclasses
  40. DirectButton.__init__(self, parent)
  41. self.indicator = self.createcomponent("indicator", (), None,
  42. DirectLabel, (self,),
  43. numStates = 2,
  44. image = self['boxImage'],
  45. image_scale = self['boxImageScale'],
  46. image_color = self['boxImageColor'],
  47. state = 'disabled',
  48. text = ('X', 'X'),
  49. relief = self['boxRelief'],
  50. )
  51. # Call option initialization functions
  52. self.initialiseoptions(DirectCheckButton)
  53. # After initialization with X giving it the correct size, put back space
  54. if self['boxImage'] == None:
  55. self.indicator['text'] = (' ', '*')
  56. self.indicator['text_pos'] = (0, -.2)
  57. else:
  58. self.indicator['text'] = (' ', ' ')
  59. if self['boxImageColor'] != None and self['boxImage'] != None:
  60. self.colors = [VBase4(0, 0, 0, 0), self['boxImageColor']]
  61. self.component('indicator')['image_color'] = VBase4(0, 0, 0, 0)
  62. # Override the resetFrameSize of DirectGuiWidget inorder to provide space for label
  63. def resetFrameSize(self):
  64. self.setFrameSize(fClearFrame = 1)
  65. def setFrameSize(self, fClearFrame = 0):
  66. if self['frameSize']:
  67. # Use user specified bounds
  68. self.bounds = self['frameSize']
  69. frameType = self.frameStyle[0].getType()
  70. ibw = self.indicator['borderWidth']
  71. else:
  72. # Use ready state to compute bounds
  73. frameType = self.frameStyle[0].getType()
  74. if fClearFrame and (frameType != PGFrameStyle.TNone):
  75. self.frameStyle[0].setType(PGFrameStyle.TNone)
  76. self.guiItem.setFrameStyle(0, self.frameStyle[0])
  77. # To force an update of the button
  78. self.guiItem.getStateDef(0)
  79. # Clear out frame before computing bounds
  80. self.getBounds()
  81. # Restore frame style if necessary
  82. if (frameType != PGFrameStyle.TNone):
  83. self.frameStyle[0].setType(frameType)
  84. self.guiItem.setFrameStyle(0, self.frameStyle[0])
  85. # Ok, they didn't set specific bounds,
  86. # let's add room for the label indicator
  87. # get the difference in height
  88. ibw = self.indicator['borderWidth']
  89. indicatorWidth = (self.indicator.getWidth() + (2*ibw[0]))
  90. indicatorHeight = (self.indicator.getHeight() + (2*ibw[1]))
  91. diff = (indicatorHeight + (2*self['boxBorder']) -
  92. (self.bounds[3] - self.bounds[2]))
  93. # If background is smaller then indicator, enlarge background
  94. if diff > 0:
  95. if self['boxPlacement'] == 'left': #left
  96. self.bounds[0] += -(indicatorWidth + (2*self['boxBorder']))
  97. self.bounds[3] += diff/2
  98. self.bounds[2] -= diff/2
  99. elif self['boxPlacement'] == 'below': #below
  100. self.bounds[2] += -(indicatorHeight+(2*self['boxBorder']))
  101. elif self['boxPlacement'] == 'right': #right
  102. self.bounds[1] += indicatorWidth + (2*self['boxBorder'])
  103. self.bounds[3] += diff/2
  104. self.bounds[2] -= diff/2
  105. else: #above
  106. self.bounds[3] += indicatorHeight + (2*self['boxBorder'])
  107. # Else make space on correct side for indicator
  108. else:
  109. if self['boxPlacement'] == 'left': #left
  110. self.bounds[0] += -(indicatorWidth + (2*self['boxBorder']))
  111. elif self['boxPlacement'] == 'below': #below
  112. self.bounds[2] += -(indicatorHeight + (2*self['boxBorder']))
  113. elif self['boxPlacement'] == 'right': #right
  114. self.bounds[1] += indicatorWidth + (2*self['boxBorder'])
  115. else: #above
  116. self.bounds[3] += indicatorHeight + (2*self['boxBorder'])
  117. # Set frame to new dimensions
  118. if ((frameType != PGFrameStyle.TNone) and
  119. (frameType != PGFrameStyle.TFlat)):
  120. bw = self['borderWidth']
  121. else:
  122. bw = (0, 0)
  123. # Set frame to new dimensions
  124. self.guiItem.setFrame(
  125. self.bounds[0] - bw[0],
  126. self.bounds[1] + bw[0],
  127. self.bounds[2] - bw[1],
  128. self.bounds[3] + bw[1])
  129. # If they didn't specify a position, put it in the center of new area
  130. if not self.indicator['pos']:
  131. bbounds = self.bounds
  132. lbounds = self.indicator.bounds
  133. newpos = [0, 0, 0]
  134. if self['boxPlacement'] == 'left': #left
  135. newpos[0] += bbounds[0]-lbounds[0] + self['boxBorder'] + ibw[0]
  136. dropValue = (bbounds[3]-bbounds[2]-lbounds[3]+lbounds[2])/2 + self['boxBorder']
  137. newpos[2] += (bbounds[3]-lbounds[3] + self['boxBorder'] -
  138. dropValue)
  139. elif self['boxPlacement'] == 'right': #right
  140. newpos[0] += bbounds[1]-lbounds[1] - self['boxBorder'] - ibw[0]
  141. dropValue = (bbounds[3]-bbounds[2]-lbounds[3]+lbounds[2])/2 + self['boxBorder']
  142. newpos[2] += (bbounds[3]-lbounds[3] + self['boxBorder']
  143. - dropValue)
  144. elif self['boxPlacement'] == 'above': #above
  145. newpos[2] += bbounds[3]-lbounds[3] - self['boxBorder'] - ibw[1]
  146. else: #below
  147. newpos[2] += bbounds[2]-lbounds[2] + self['boxBorder'] + ibw[1]
  148. self.indicator.setPos(newpos[0], newpos[1], newpos[2])
  149. def commandFunc(self, event):
  150. self['indicatorValue'] = 1 - self['indicatorValue']
  151. if self.colors != None:
  152. self.component('indicator')['image_color'] = self.colors[self['indicatorValue']]
  153. if self['command']:
  154. # Pass any extra args to command
  155. apply(self['command'], [self['indicatorValue']] + self['extraArgs'])
  156. def setIndicatorValue(self):
  157. self.component('indicator').guiItem.setState(self['indicatorValue'])
  158. if self.colors != None:
  159. self.component('indicator')['image_color'] = self.colors[self['indicatorValue']]