DirectEntryScroll.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. __all__ = ['DirectEntryScroll']
  2. from panda3d.core import *
  3. from . import DirectGuiGlobals as DGG
  4. from .DirectScrolledFrame import *
  5. from .DirectFrame import *
  6. from .DirectEntry import *
  7. class DirectEntryScroll(DirectFrame):
  8. def __init__(self, entry, parent = None, **kw):
  9. optiondefs = (
  10. ('pgFunc', PGVirtualFrame, None),
  11. ('relief', None, None),
  12. ('clipSize', (-1, 1, -1, 1), self.setClipSize),
  13. )
  14. self.defineoptions(kw, optiondefs)
  15. DirectFrame.__init__(self, parent, **kw)
  16. self.canvas = None
  17. self.visXMin = 0.0
  18. self.visXMax = 0.0
  19. self.clipXMin = 0.0
  20. self.clipXMax = 0.0
  21. self.initialiseoptions(DirectEntryScroll)
  22. # don't set a scale on the entry
  23. # instead make it the correct size, use something like:
  24. # text_scale = 0.035,
  25. # frameSize = (-0.006, 3.2, -0.015, 0.036),
  26. # if you need to scale the entry scale it's parent instead
  27. self.canvas = NodePath(self.guiItem.getCanvasNode())
  28. self.canvas.setPos(0,0,0)
  29. self.entry = None
  30. if entry is not None:
  31. self.entry = entry
  32. self.entry.reparentTo(self.canvas)
  33. self.entry.bind(DGG.CURSORMOVE, self.cursorMove)
  34. self.canvas.node().setBounds(OmniBoundingVolume())
  35. self.canvas.node().setFinal(1)
  36. self.resetCanvas()
  37. def setEntry(self, entry):
  38. """
  39. Sets a DirectEntry element for this scroll frame. A DirectEntryScroll
  40. can only hold one entry at a time, so make sure to not call this
  41. function twice or call clearEntry before to make sure no entry
  42. is already set.
  43. """
  44. assert self.entry is None, "An entry was already set for this DirectEntryScroll element"
  45. self.entry = entry
  46. self.entry.reparentTo(self.canvas)
  47. self.entry.bind(DGG.CURSORMOVE, self.cursorMove)
  48. def clearEntry(self):
  49. """
  50. detaches and unbinds the entry from the scroll frame and its
  51. events. You'll be responsible for destroying it.
  52. """
  53. if self.entry is None: return
  54. self.entry.unbind(DGG.CURSORMOVE)
  55. self.entry.detachNode()
  56. self.entry = None
  57. def cursorMove(self, cursorX, cursorY):
  58. cursorX = self.entry.guiItem.getCursorX() * self.entry['text_scale'][0]
  59. canvasX = self.canvas.getX()
  60. visXMin = self.clipXMin - canvasX
  61. visXMax = self.clipXMax - canvasX
  62. visXCenter = (visXMin + visXMax) * 0.5
  63. distanceToCenter = visXCenter - cursorX
  64. clipExtent = self.clipXMax - self.clipXMin
  65. entryExtent = self.entry['text_scale'][0] * self.entry['width']
  66. entryWiggle = entryExtent - clipExtent
  67. if abs(distanceToCenter) > (clipExtent * 0.5):
  68. self.moveToCenterCursor()
  69. def moveToCenterCursor(self):
  70. cursorX = self.entry.guiItem.getCursorX() * self.entry['text_scale'][0]
  71. canvasX = self.canvas.getX()
  72. visXMin = self.clipXMin - canvasX
  73. visXMax = self.clipXMax - canvasX
  74. visXCenter = (visXMin + visXMax) * 0.5
  75. distanceToCenter = visXCenter - cursorX
  76. newX = canvasX + distanceToCenter
  77. clipExtent = self.clipXMax - self.clipXMin
  78. entryExtent = self.entry['text_scale'][0] * self.entry['width']
  79. entryWiggle = entryExtent - clipExtent
  80. if self.entry.guiItem.getCursorPosition() <= 0: #deals with the cursor jump bug
  81. newX = 0.0
  82. elif newX > 0.0:
  83. newX = 0.0
  84. elif newX < (-entryWiggle):
  85. newX = -entryWiggle
  86. #print("CursorX %s CanvasX %s VisCenter %s Distance %s NewX %s Wiggle %s" % (cursorX, canvasX, visXCenter, distanceToCenter, newX, entryWiggle))
  87. self.canvas.setX(newX)
  88. def destroy(self):
  89. # Destroy children of the canvas
  90. for child in self.canvas.getChildren():
  91. childGui = self.guiDict.get(child.getName())
  92. if childGui:
  93. childGui.destroy()
  94. else:
  95. parts = child.getName().split('-')
  96. simpleChildGui = self.guiDict.get(parts[-1])
  97. if simpleChildGui:
  98. simpleChildGui.destroy()
  99. self.entry.destroy()
  100. self.entry = None
  101. DirectFrame.destroy(self)
  102. def getCanvas(self):
  103. return self.canvas
  104. def setClipSize(self):
  105. self.guiItem.setClipFrame(self['clipSize'])
  106. self.clipXMin = self['clipSize'][0]
  107. self.clipXMax = self['clipSize'][1]
  108. self.visXMin = self.clipXMin
  109. self.visXMax = self.clipXMax
  110. if self.canvas:
  111. self.resetCanvas()
  112. def resetCanvas(self):
  113. self.canvas.setPos(0,0,0)