panda3d/direct/src/gui/DirectFrame.py
2019-12-11 17:57:15 +01:00

161 lines
5.1 KiB
Python

"""A DirectFrame is a basic DirectGUI component that acts as the base
class for various other components, and can also serve as a basic
container to hold other DirectGUI components.
A DirectFrame can have:
* A background texture (pass in path to image, or Texture Card)
* A midground geometry item (pass in geometry)
* A foreground text Node (pass in text string or OnscreenText)
Each of these has 1 or more states. The same object can be used for
all states or each state can have a different text/geom/image (for
radio button and check button indicators, for example).
See the :ref:`directframe` page in the programming manual for a more in-depth
explanation and an example of how to use this class.
"""
__all__ = ['DirectFrame']
from panda3d.core import *
from . import DirectGuiGlobals as DGG
from .DirectGuiBase import *
from .OnscreenImage import OnscreenImage
from .OnscreenGeom import OnscreenGeom
from .OnscreenText import OnscreenText
import sys
if sys.version_info >= (3, 0):
stringType = str
else:
stringType = basestring
class DirectFrame(DirectGuiWidget):
DefDynGroups = ('text', 'geom', 'image')
def __init__(self, parent=None, **kw):
# Inherits from DirectGuiWidget
optiondefs = (
# Define type of DirectGuiWidget
('pgFunc', PGItem, None),
('numStates', 1, None),
('state', self.inactiveInitState, None),
# Frame can have:
# A background texture
('image', None, self.setImage),
# A midground geometry item
('geom', None, self.setGeom),
# A foreground text node
('text', None, self.setText),
# Change default value of text mayChange flag from 0
# (OnscreenText.py) to 1
('textMayChange', 1, None),
)
# Merge keyword options with default options
self.defineoptions(kw, optiondefs,
dynamicGroups=DirectFrame.DefDynGroups)
# Initialize superclasses
DirectGuiWidget.__init__(self, parent)
# Call option initialization functions
self.initialiseoptions(DirectFrame)
def __reinitComponent(self, name, component_class, states, **kwargs):
"""Recreates the given component using the given keyword args."""
assert name in ("geom", "image", "text")
if len(states) != self['numStates']:
raise ValueError
# constants should be local to or default arguments of constructors
for c in range(self['numStates']):
component_name = name + str(c)
state = states[c]
if self.hascomponent(component_name):
if state is None:
self.destroycomponent(component_name)
else:
self[component_name + "_" + name] = state
else:
if state is None:
return
kwargs[name] = state
self.createcomponent(
component_name,
(),
name,
component_class,
(),
parent=self.stateNodePath[c],
**kwargs
)
def clearText(self):
self['text'] = None
self.setText()
def setText(self, text=None):
if text is not None:
self["text"] = text
text = self["text"]
if text is None or isinstance(text, stringType):
text_list = (text,) * self['numStates']
else:
text_list = text
self.__reinitComponent("text", OnscreenText, text_list,
scale=1,
mayChange=self['textMayChange'],
sort=DGG.TEXT_SORT_INDEX)
def clearGeom(self):
self['geom'] = None
self.setGeom()
def setGeom(self, geom=None):
if geom is not None:
self["geom"] = geom
geom = self["geom"]
if geom is None or \
isinstance(geom, NodePath) or \
isinstance(geom, stringType):
geom_list = (geom,) * self['numStates']
else:
geom_list = geom
self.__reinitComponent("geom", OnscreenGeom, geom_list,
scale=1,
sort=DGG.GEOM_SORT_INDEX)
def clearImage(self):
self['image'] = None
self.setImage()
def setImage(self, image=None):
if image is not None:
self["image"] = image
image = self["image"]
if image is None or \
isinstance(image, NodePath) or \
isinstance(image, Texture) or \
isinstance(image, stringType) or \
isinstance(image, Filename) or \
(len(image) == 2 and \
isinstance(image[0], stringType) and \
isinstance(image[1], stringType)):
image_list = (image,) * self['numStates']
else:
image_list = image
self.__reinitComponent("image", OnscreenImage, image_list,
scale=1,
sort=DGG.IMAGE_SORT_INDEX)