dgui: refactor code common to DirectFrame setGeom, setImage, setText

Closes #776

Co-authored-by: rdb <git@rdb.name>
This commit is contained in:
max 2019-12-11 17:57:15 +01:00 committed by rdb
parent 49f423822d
commit 2ca37b8c97

View File

@ -23,6 +23,7 @@ from . import DirectGuiGlobals as DGG
from .DirectGuiBase import * from .DirectGuiBase import *
from .OnscreenImage import OnscreenImage from .OnscreenImage import OnscreenImage
from .OnscreenGeom import OnscreenGeom from .OnscreenGeom import OnscreenGeom
from .OnscreenText import OnscreenText
import sys import sys
if sys.version_info >= (3, 0): if sys.version_info >= (3, 0):
@ -33,7 +34,8 @@ else:
class DirectFrame(DirectGuiWidget): class DirectFrame(DirectGuiWidget):
DefDynGroups = ('text', 'geom', 'image') DefDynGroups = ('text', 'geom', 'image')
def __init__(self, parent = None, **kw):
def __init__(self, parent=None, **kw):
# Inherits from DirectGuiWidget # Inherits from DirectGuiWidget
optiondefs = ( optiondefs = (
# Define type of DirectGuiWidget # Define type of DirectGuiWidget
@ -50,10 +52,10 @@ class DirectFrame(DirectGuiWidget):
# Change default value of text mayChange flag from 0 # Change default value of text mayChange flag from 0
# (OnscreenText.py) to 1 # (OnscreenText.py) to 1
('textMayChange', 1, None), ('textMayChange', 1, None),
) )
# Merge keyword options with default options # Merge keyword options with default options
self.defineoptions(kw, optiondefs, self.defineoptions(kw, optiondefs,
dynamicGroups = DirectFrame.DefDynGroups) dynamicGroups=DirectFrame.DefDynGroups)
# Initialize superclasses # Initialize superclasses
DirectGuiWidget.__init__(self, parent) DirectGuiWidget.__init__(self, parent)
@ -61,8 +63,37 @@ class DirectFrame(DirectGuiWidget):
# Call option initialization functions # Call option initialization functions
self.initialiseoptions(DirectFrame) self.initialiseoptions(DirectFrame)
def destroy(self): def __reinitComponent(self, name, component_class, states, **kwargs):
DirectGuiWidget.destroy(self) """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): def clearText(self):
self['text'] = None self['text'] = None
@ -70,45 +101,18 @@ class DirectFrame(DirectGuiWidget):
def setText(self, text=None): def setText(self, text=None):
if text is not None: if text is not None:
self['text'] = text self["text"] = text
# Determine if user passed in single string or a sequence text = self["text"]
if self['text'] == None: if text is None or isinstance(text, stringType):
textList = (None,) * self['numStates'] text_list = (text,) * self['numStates']
elif isinstance(self['text'], stringType):
# If just passing in a single string, make a tuple out of it
textList = (self['text'],) * self['numStates']
else: else:
# Otherwise, hope that the user has passed in a tuple/list text_list = text
textList = self['text']
# Create/destroy components
for i in range(self['numStates']):
component = 'text' + repr(i)
# If fewer items specified than numStates,
# just repeat last item
try:
text = textList[i]
except IndexError:
text = textList[-1]
if self.hascomponent(component): self.__reinitComponent("text", OnscreenText, text_list,
if text == None: scale=1,
# Destroy component mayChange=self['textMayChange'],
self.destroycomponent(component) sort=DGG.TEXT_SORT_INDEX)
else:
self[component + '_text'] = text
else:
if text == None:
return
else:
from .OnscreenText import OnscreenText
self.createcomponent(
component, (), 'text',
OnscreenText,
(), parent = self.stateNodePath[i],
text = text, scale = 1, mayChange = self['textMayChange'],
sort = DGG.TEXT_SORT_INDEX,
)
def clearGeom(self): def clearGeom(self):
self['geom'] = None self['geom'] = None
@ -116,48 +120,19 @@ class DirectFrame(DirectGuiWidget):
def setGeom(self, geom=None): def setGeom(self, geom=None):
if geom is not None: if geom is not None:
self['geom'] = geom self["geom"] = geom
# Determine argument type geom = self["geom"]
geom = self['geom'] if geom is None or \
isinstance(geom, NodePath) or \
if geom == None: isinstance(geom, stringType):
# Passed in None geom_list = (geom,) * self['numStates']
geomList = (None,) * self['numStates']
elif isinstance(geom, NodePath) or \
isinstance(geom, stringType):
# Passed in a single node path, make a tuple out of it
geomList = (geom,) * self['numStates']
else: else:
# Otherwise, hope that the user has passed in a tuple/list geom_list = geom
geomList = geom
# Create/destroy components self.__reinitComponent("geom", OnscreenGeom, geom_list,
for i in range(self['numStates']): scale=1,
component = 'geom' + repr(i) sort=DGG.GEOM_SORT_INDEX)
# If fewer items specified than numStates,
# just repeat last item
try:
geom = geomList[i]
except IndexError:
geom = geomList[-1]
if self.hascomponent(component):
if geom == None:
# Destroy component
self.destroycomponent(component)
else:
self[component + '_geom'] = geom
else:
if geom == None:
return
else:
self.createcomponent(
component, (), 'geom',
OnscreenGeom,
(), parent = self.stateNodePath[i],
geom = geom, scale = 1,
sort = DGG.GEOM_SORT_INDEX)
def clearImage(self): def clearImage(self):
self['image'] = None self['image'] = None
@ -165,51 +140,21 @@ class DirectFrame(DirectGuiWidget):
def setImage(self, image=None): def setImage(self, image=None):
if image is not None: if image is not None:
self['image'] = image self["image"] = image
# Determine argument type image = self["image"]
arg = self['image'] if image is None or \
if arg == None: isinstance(image, NodePath) or \
# Passed in None isinstance(image, Texture) or \
imageList = (None,) * self['numStates'] isinstance(image, stringType) or \
elif isinstance(arg, NodePath) or \ isinstance(image, Filename) or \
isinstance(arg, Texture) or \ (len(image) == 2 and \
isinstance(arg, stringType): isinstance(image[0], stringType) and \
# Passed in a single node path, make a tuple out of it isinstance(image[1], stringType)):
imageList = (arg,) * self['numStates'] image_list = (image,) * self['numStates']
else: else:
# Otherwise, hope that the user has passed in a tuple/list image_list = image
if ((len(arg) == 2) and
isinstance(arg[0], stringType) and
isinstance(arg[1], stringType)):
# Its a model/node pair of strings
imageList = (arg,) * self['numStates']
else:
# Assume its a list of node paths
imageList = arg
# Create/destroy components
for i in range(self['numStates']):
component = 'image' + repr(i)
# If fewer items specified than numStates,
# just repeat last item
try:
image = imageList[i]
except IndexError:
image = imageList[-1]
if self.hascomponent(component): self.__reinitComponent("image", OnscreenImage, image_list,
if image == None: scale=1,
# Destroy component sort=DGG.IMAGE_SORT_INDEX)
self.destroycomponent(component)
else:
self[component + '_image'] = image
else:
if image == None:
return
else:
self.createcomponent(
component, (), 'image',
OnscreenImage,
(), parent = self.stateNodePath[i],
image = image, scale = 1,
sort = DGG.IMAGE_SORT_INDEX)