PickList.py 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. """PickList module: contains the PickList class"""
  2. from ShowBaseGlobal import *
  3. from GuiGlobals import *
  4. import PandaObject
  5. import Frame
  6. import Button
  7. class PickList(PandaObject.PandaObject):
  8. """PickList class: display a menu of choices and report users
  9. choice (via mouse or keyboard) as an event with the choice as
  10. an extra argument
  11. """
  12. # special methods
  13. def __init__(self, name, choiceList,
  14. scale = 0.1,
  15. width = None,
  16. drawOrder = getDefaultDrawOrder(),
  17. font = getDefaultFont()):
  18. self.name = name
  19. self.frame = Frame.Frame(name)
  20. # initialization
  21. self.choice = -1
  22. self.choiceList = []
  23. self.eventName = self.name
  24. self.frame.setOffset(0.015)
  25. # display the menu
  26. self.__displayChoices(choiceList, scale, width, drawOrder, font)
  27. self.isClean = 0
  28. return None
  29. def owns(self, item):
  30. for x in self.choiceList:
  31. if (x.button == item):
  32. return 1
  33. return None
  34. def cleanup(self):
  35. """cleanup(self)
  36. """
  37. if self.isClean == 0:
  38. self.isClean = 1
  39. self.disable()
  40. self.frame.unmanage()
  41. self.frame = None
  42. self.choiceList = []
  43. return None
  44. # accessing
  45. def getName(self):
  46. return self.name
  47. def getEventName(self):
  48. return self.eventName
  49. def setEventName(self, eventName):
  50. self.eventName = eventName
  51. # actions
  52. def __displayChoices(self, choiceList,
  53. scale, width, drawOrder, font):
  54. """__displayChoices(self, string[])
  55. Display the list of choices
  56. """
  57. if width == None:
  58. # First, compute the maximum width of the buttons. We do this
  59. # ahead of time so the Gui code doesn't have to do it and take
  60. # forever about it.
  61. width = 0
  62. text = TextNode()
  63. text.setFont(font)
  64. for choice in choiceList:
  65. w = text.calcWidth(choice) + 0.2
  66. width = max(width, w)
  67. # Now create all the buttons.
  68. for choice in choiceList:
  69. # create a button for each choice
  70. button = Button.Button(choice, scale = scale, width = width,
  71. drawOrder = drawOrder, font = font,
  72. event = "choose")
  73. choiceIndex = choiceList.index(choice)
  74. button.setBehaviorEventParameter(choiceIndex)
  75. # set the rollover-up event
  76. eventName = self.name + "-up"
  77. button.button.setUpRolloverEvent(eventName)
  78. # set exit event
  79. eventName = self.name + "-exit"
  80. button.button.setUpEvent(eventName)
  81. # keep a list of the choice buttons
  82. self.frame.addItem(button)
  83. self.choiceList.append(button)
  84. # set up the frame
  85. self.frame.makeVertical()
  86. return None
  87. def manage(self):
  88. self.enable()
  89. self.frame.manage()
  90. for x in self.choiceList:
  91. x.startBehavior()
  92. return None
  93. def unmanage(self):
  94. self.disable()
  95. self.frame.unmanage()
  96. return None
  97. def enable(self):
  98. # turn the buttons on
  99. self.activate()
  100. # listen for keyboard events
  101. self.accept("up-up", self.__decrementChoice)
  102. self.accept("down-up", self.__incrementChoice)
  103. self.accept("enter-up", self.__makeChoice, [1, None, None])
  104. self.accept(self.name + "-up", self.__updateButtonChoice)
  105. self.accept(self.name + "-exit", self.__exitChoice)
  106. self.accept("choose", self.__makeChoice, [0])
  107. def disable(self, button=None):
  108. # turn the buttons off
  109. self.deactivate(button)
  110. # ignore all hooks
  111. self.ignore("up-up")
  112. self.ignore("down-up")
  113. self.ignore("enter-up")
  114. self.ignore(self.name + "-up")
  115. self.ignore(self.name + "-exit")
  116. self.ignore("choose")
  117. def activate(self):
  118. # make sure items are active
  119. for choice in self.choiceList:
  120. choice.getGuiItem().up()
  121. def deactivate(self, button=None):
  122. # make sure all items are inactive, if a button
  123. # is passed in do NOT deactivate it.
  124. for choice in self.choiceList:
  125. if (choice.getGuiItem().isActive()):
  126. if not (button == None):
  127. if not (self.choiceList.index(choice) == button):
  128. choice.getGuiItem().inactive()
  129. else:
  130. choice.getGuiItem().inactive()
  131. def recompute(self):
  132. self.frame.recompute()
  133. def setPos(self, x, y):
  134. self.frame.setPos(x, y)
  135. # event handlers
  136. def __incrementChoice(self):
  137. # handle the up arrow
  138. choice = self.choice + 1
  139. if (choice > len(self.choiceList) - 1):
  140. choice = 0
  141. # enter the new choice
  142. self.choiceList[choice].getGuiItem().enter()
  143. def __decrementChoice(self):
  144. # handle the down arrow
  145. choice = self.choice - 1
  146. if (choice < 0):
  147. choice = len(self.choiceList) - 1
  148. # enter this choice
  149. self.choiceList[choice].getGuiItem().enter()
  150. def __updateButtonChoice(self, item):
  151. # handle the mouse rollovers
  152. if self.owns(item):
  153. if (self.choice == -1):
  154. self.choice = item.getBehaviorEventParameter()
  155. if (self.choice != item.getBehaviorEventParameter()):
  156. self.choice = item.getBehaviorEventParameter()
  157. # make sure all the other buttons have exited
  158. for choice in self.choiceList:
  159. if (choice.button != item):
  160. choice.getGuiItem().exit()
  161. # throw event
  162. messenger.send(self.name + "-rollover")
  163. def __exitChoice(self, item):
  164. # reset choice when mouse exits a button
  165. if self.owns(item):
  166. if (self.choice == item.getBehaviorEventParameter()):
  167. self.choice = -1
  168. def __makeChoice(self, button, item, whichOne):
  169. # handle the enter key
  170. if (self.choice == -1):
  171. # nothing selected yet
  172. return None
  173. else:
  174. # if the keyboard was used, update the button manually
  175. if (button):
  176. self.choiceList[self.choice].getGuiItem().down()
  177. def buttonUp(state):
  178. state.choice.getGuiItem().up()
  179. return Task.done
  180. task = Task.Task(buttonUp)
  181. task.choice = self.choiceList[self.choice]
  182. taskMgr.spawnTaskNamed(Task.doLater(0.035, task,
  183. "buttonUp-later"),
  184. "doLater-buttonUp-later")
  185. else:
  186. # let everyone know a choice was made
  187. if self.owns(item):
  188. messenger.send(self.eventName, [self.choice])
  189. self.disable(self.choice)