I am new developer in Panda-3D and I vritten this FileDialog class.
## Imports --------------------------------------------------------------------
import sys, os
if sys.platform == 'darwin':
sys.path.insert(0, "/Developer/Panda3D/lib")
#import logging
import direct.directbase.DirectStart
from pandac.PandaModules import TextNode
from direct.gui.DirectGui import DirectFrame, DirectLabel, DirectSlider
from direct.gui.DirectGui import DirectButton, DirectScrolledList, DGG
from direct.showbase.DirectObject import DirectObject
## Logging configuration ------------------------------------------------------
#log = logging.getLogger(__name__) #: the module level logger
#log.setLevel(logging.DEBUG)
#
# -----------------------------------------------------------------------------
#
class FileDialog():
""" File dialog handler
This class open a semi-transparent dialog window on the 'aspect2d' renderer.
The user can also navigate in the specified directory and select a file or
a directory; files can be filtered by there extention. If a directory is
selected, it is explored recursively; if a file is selected the dialog
window is closed and the absolute file path is returned in the callback
function. A "Cancel" button closes the dialog window returning 'None'.
"""
cmtt12 = loader.loadFont('cmtt12.egg')
def __init__(self, title, basePath, ext, command):
""" Constructor: launch the dialog window
@param title (string) : title of the dialog
@param basePath : path of the root directory to explore
@param ext : extension used to filter file names (no filtering if it is
'None')
@param command : callback function called at close time; this function
muss have an argument to get the selected file path.
"""
self.command = command
self.path = os.path.abspath(basePath)
self.first = os.path.basename(self.path)
self.ext = ext
self.curDir = self.first
self.frm = DirectFrame(frameSize = (0, 1.5, -1, 1),
frameColor = (0.4, 0.9, 0.9, 0.3),
relief = DGG.GROOVE,
borderWidth = (0.02, 0.02))
self.frm.setPos(-1.3, 0, 0)
self.frm.reparentTo(aspect2d)
titleLabel = DirectLabel(text = title,
scale = 0.09,
pos= (0.08, 0, 0.9),
frameSize = (-0.2, 10, -0.2, 0.8),
frameColor = (0.4, 0.9, 0.9, 0.4),
text_align = TextNode.ALeft)
titleLabel.reparentTo(self.frm)
btnCancel = DirectButton(text = "Cancel", scale = 0.07,
pos = (1.326, 0, .9),
frameSize = (-1.58, 1.75, -0.3, 0.9),
frameColor = (0.4, 0.9, 0.9, 0.3),
command = self._cancel)
btnCancel.reparentTo(self.frm)
self.dirFrame = None
self._handleADir()
def _handleADir(self):
""" Handle a directory, displays the scrolled list of dir and files.
"""
print self.curDir, self.path
files = sorted(filter(lambda x: os.path.isfile(os.path.join(self.path,
x)),
os.listdir(self.path)))
if self.ext != None:
files = filter(lambda x: x.endswith(self.ext), files)
dirs = sorted(filter(lambda x: os.path.isdir(os.path.join(self.path,
x)),
os.listdir(self.path)))
self.dirFrame = DirectFrame(frameSize = (0.05, 1.45, -0.97, 0.85),
frameColor = (0.4, 0.9, 0.9, 0.2),
)
self.dirFrame.reparentTo(self.frm)
dirId = DirectLabel(text = "> " + self.curDir,
scale = 0.075,
pos= (0.085, 0, 0.76),
frameSize = (-0.2, 17.9, -0.3, 0.85),
frameColor = (0.4, 0.9, 0.9, 0.3),
text_align = TextNode.ALeft)
dirId.reparentTo(self.dirFrame)
dirItems = []
if self.curDir != self.first:
aDir = '..'
b = DirectButton(text = (aDir, aDir, aDir, aDir),
frameColor = (0, 0, 0, 0),
text_scale = 0.07, borderWidth = (0.005, 0.005),
relief=2,
command = self._dirSelected,
extraArgs = [aDir])
dirItems.append(b)
for aDir in dirs:
b = DirectButton(text = (aDir, aDir, aDir, aDir),
frameColor = (0, 0, 0, 0),
text_scale = 0.07, borderWidth = (0.005, 0.005),
relief=2,
command = self._dirSelected,
extraArgs = [aDir])
dirItems.append(b)
for aFile in files:
b = DirectButton(text = (aFile, aFile, aFile, aFile),
frameColor = (0, 0, 0, 0),
text_scale = 0.07,
command = self._fileSelected,
extraArgs = [aFile])
dirItems.append(b)
print len(dirItems), dirItems
scList = DirectScrolledList(
pos = (0.07, 0, -0.95),
frameSize = (0.0, 1.36, 0.0, 1.67),
frameColor = (0.4, 0.9, 0.9, 0.3),
decButton_pos= (0.68, 0, 1.60),
decButton_text = "Previous",
decButton_text_scale = 0.04,
decButton_borderWidth = (0.005, 0.005),
decButton_frameColor = (0.4, 0.9, 0.9, 0.3),
incButton_pos= (0.68, 0, 0.04),
incButton_text = "Next",
incButton_text_scale = 0.04,
incButton_borderWidth = (0.005, 0.005),
incButton_frameColor = (0.4, 0.9, 0.9, 0.3),
itemFrame_frameSize = (-0.68, 0.68, -1.45, 0),
itemFrame_pos = (0.68, 0, 1.5),
itemFrame_frameColor = (0, 0, 0, 0),
items = dirItems,
numItemsVisible = 15,
forceHeight = 0.09
)
scList.reparentTo(self.dirFrame)
def _dirSelected(self, arg):
""" Callback method called at directory selection
@param arg : local name of the selected directory
"""
# print "Directory selected: ", os.path.join(curDir, arg)
self.dirFrame.removeNode()
if arg == '..':
self.curDir = os.path.dirname(self.curDir)
self.path = os.path.dirname(self.path)
else:
self.curDir = os.path.join(self.curDir, arg)
self.path = os.path.join(self.path, arg)
self._handleADir()
def _fileSelected(self, arg):
""" Callback method called at file selection.
This method close the dialog window and call the callback function that
has been passed to the constructor with the absolute path of the
selected file as argument.
@param arg : local name of the selected directory
"""
print "File selected: ", arg
self.frm.removeNode()
self.command(os.path.join(self.path, arg))
def _cancel(self):
""" Callback method called at file selection.
This method close the dialog window and call the callback function that
has been passed to the constructor with 'None' as argument.
"""
# print "Canceled"
self.frm.removeNode()
self.command(None)
#
# Testing function -----------------------------------------------------------
#
class TestDialog(DirectObject):
def __init__(self):
""" Test class constructor: executes the test
"""
from direct.actor.Actor import Actor # only used by test
# A Pando only to have a active display
base.disableMouse()
base.camera.setPos(0, -10, 0)
base.setBackgroundColor(0,0,0)
self.pandaActor = Actor("models/panda-model",
{"walk": "models/panda-walk4"})
self.pandaActor.setScale(0.003)
self.pandaActor.setPos(0, 0, -1)
self.pandaActor.setTwoSided(True)
self.pandaActor.loop("walk")
self.pandaActor.reparentTo(render)
# Always use 'Esc' to quit
self.accept("escape", sys.exit, [0])
# Connect the file dialog to "F9" key
self.accept('f9', self.callDialog)
def callDialog(self):
""" Callback method to open the file dialog
"""
frmDialog = FileDialog("Scripts loader", 'conf/default/scripts',
'.iscr', self.dialogCallback)
def dialogCallback(self, aPath):
""" Callback function connected to FileDialog
@param aPath : the full path of the choosed file or 'None' if cancelled.
"""
if aPath == None:
print "Cancelled"
else:
print "Selected file: ", aPath
if __name__ == '__main__':
w = TestDialog()
run()
# -----------------------------------------------------------------------------
It seem to work fine, but the mouse selection in the DirectScrolledList does not return the selected item, but the next in the list. If you have an idea on the origin of this problem, I am interested.
Sorry for my bad english.
Daniel