__all__ = ['DirectEntryScroll']
from panda3d.core import *
from . import DirectGuiGlobals as DGG
from .DirectScrolledFrame import *
from .DirectFrame import *
from .DirectEntry import *
[docs]class DirectEntryScroll(DirectFrame):
[docs] def __init__(self, entry, parent = None, **kw):
optiondefs = (
('pgFunc', PGVirtualFrame, None),
('relief', None, None),
('clipSize', (-1, 1, -1, 1), self.setClipSize),
)
self.defineoptions(kw, optiondefs)
DirectFrame.__init__(self, parent, **kw)
self.canvas = None
self.visXMin = 0.0
self.visXMax = 0.0
self.clipXMin = 0.0
self.clipXMax = 0.0
self.initialiseoptions(DirectEntryScroll)
# don't set a scale on the entry
# instead make it the correct size, use something like:
# text_scale = 0.035,
# frameSize = (-0.006, 3.2, -0.015, 0.036),
# if you need to scale the entry scale it's parent instead
self.canvas = NodePath(self.guiItem.getCanvasNode())
self.canvas.setPos(0,0,0)
self.entry = None
if entry is not None:
self.entry = entry
self.entry.reparentTo(self.canvas)
self.entry.bind(DGG.CURSORMOVE, self.cursorMove)
self.canvas.node().setBounds(OmniBoundingVolume())
self.canvas.node().setFinal(1)
self.resetCanvas()
[docs] def setEntry(self, entry):
"""
Sets a DirectEntry element for this scroll frame. A DirectEntryScroll
can only hold one entry at a time, so make sure to not call this
function twice or call clearEntry before to make sure no entry
is already set.
"""
assert self.entry is None, "An entry was already set for this DirectEntryScroll element"
self.entry = entry
self.entry.reparentTo(self.canvas)
self.entry.bind(DGG.CURSORMOVE, self.cursorMove)
[docs] def clearEntry(self):
"""
detaches and unbinds the entry from the scroll frame and its
events. You'll be responsible for destroying it.
"""
if self.entry is None:
return
self.entry.unbind(DGG.CURSORMOVE)
self.entry.detachNode()
self.entry = None
[docs] def cursorMove(self, cursorX, cursorY):
cursorX = self.entry.guiItem.getCursorX() * self.entry['text_scale'][0]
canvasX = self.canvas.getX()
visXMin = self.clipXMin - canvasX
visXMax = self.clipXMax - canvasX
visXCenter = (visXMin + visXMax) * 0.5
distanceToCenter = visXCenter - cursorX
clipExtent = self.clipXMax - self.clipXMin
entryExtent = self.entry['text_scale'][0] * self.entry['width']
entryWiggle = entryExtent - clipExtent
if abs(distanceToCenter) > (clipExtent * 0.5):
self.moveToCenterCursor()
[docs] def moveToCenterCursor(self):
cursorX = self.entry.guiItem.getCursorX() * self.entry['text_scale'][0]
canvasX = self.canvas.getX()
visXMin = self.clipXMin - canvasX
visXMax = self.clipXMax - canvasX
visXCenter = (visXMin + visXMax) * 0.5
distanceToCenter = visXCenter - cursorX
newX = canvasX + distanceToCenter
clipExtent = self.clipXMax - self.clipXMin
entryExtent = self.entry['text_scale'][0] * self.entry['width']
entryWiggle = entryExtent - clipExtent
if self.entry.guiItem.getCursorPosition() <= 0: #deals with the cursor jump bug
newX = 0.0
elif newX > 0.0:
newX = 0.0
elif newX < (-entryWiggle):
newX = -entryWiggle
#print("CursorX %s CanvasX %s VisCenter %s Distance %s NewX %s Wiggle %s" % (cursorX, canvasX, visXCenter, distanceToCenter, newX, entryWiggle))
self.canvas.setX(newX)
[docs] def destroy(self):
# Destroy children of the canvas
for child in self.canvas.getChildren():
childGui = self.guiDict.get(child.getName())
if childGui:
childGui.destroy()
else:
parts = child.getName().split('-')
simpleChildGui = self.guiDict.get(parts[-1])
if simpleChildGui:
simpleChildGui.destroy()
self.entry.destroy()
self.entry = None
DirectFrame.destroy(self)
[docs] def getCanvas(self):
return self.canvas
[docs] def setClipSize(self):
self.guiItem.setClipFrame(self['clipSize'])
self.clipXMin = self['clipSize'][0]
self.clipXMax = self['clipSize'][1]
self.visXMin = self.clipXMin
self.visXMax = self.clipXMax
if self.canvas:
self.resetCanvas()
[docs] def resetCanvas(self):
self.canvas.setPos(0,0,0)