def __init__(self,
                 fileName,
                 guiElementsDict,
                 getEditorFrame,
                 usePixel2D,
                 exceptionSave=False,
                 autosave=False,
                 tooltip=None):
        self.guiElementsDict = guiElementsDict
        self.getEditorFrame = getEditorFrame
        self.usePixel2D = usePixel2D
        self.isAutosave = False

        if exceptionSave:
            self.excSave()
            return

        if autosave:
            self.isAutosave = True
            self.autoSave(fileName)
            return

        self.dlgPathSelect = PathSelect(self.save, "Save Project File",
                                        "Save file path", "Save", fileName,
                                        tooltip)
Exemplo n.º 2
0
 def __init__(self,
              filePath,
              visualEditorInfo,
              elementHandler,
              customWidgetHandler,
              getEditorPlacer,
              exceptionLoading=False,
              tooltip=None,
              newProjectCall=None):
     self.newProjectCall = newProjectCall
     self.extraOptions = [
         "borderWidth", "frameColor", "initialText", "clipSize"
     ]
     self.parentMap = {}
     self.radiobuttonOthersDict = {}
     self.elementDict = {}
     self.elementHandler = elementHandler
     self.customWidgetHandler = customWidgetHandler
     self.visualEditorInfo = visualEditorInfo
     self.visualEditor = visualEditorInfo.element
     self.getEditorPlacer = getEditorPlacer
     self.hasErrors = False
     if exceptionLoading:
         self.excLoad()
     else:
         self.dlgPathSelect = PathSelect(self.Load, "Load Project File",
                                         "Load file path", "Load", filePath,
                                         tooltip)
Exemplo n.º 3
0
class PyScriptLoader:
    def __init__(self, visualEditor, tooltip):
        self.visualEditor = visualEditor
        self.dlgPathSelect = PathSelect(
            self.Load, "Load Python File", "Load file path", "Load", "~/export.py", tooltip)

    def Load(self, doLoad):
        if doLoad:
            path = self.dlgPathSelect.getPath()
            path = os.path.expanduser(path)
            path = os.path.expandvars(path)

            spec = importlib.util.spec_from_file_location("loadedGUI", path)
            guiModule = importlib.util.module_from_spec(spec)
            spec.loader.exec_module(guiModule)
            guiModule.GUI(self.visualEditor.getCanvas())

        self.dlgPathSelect.destroy()
        del self.dlgPathSelect
class ExporterProject:
    def __init__(self,
                 fileName,
                 guiElementsDict,
                 getEditorFrame,
                 usePixel2D,
                 exceptionSave=False,
                 autosave=False,
                 tooltip=None):
        self.guiElementsDict = guiElementsDict
        self.getEditorFrame = getEditorFrame
        self.usePixel2D = usePixel2D
        self.isAutosave = False

        if exceptionSave:
            self.excSave()
            return

        if autosave:
            self.isAutosave = True
            self.autoSave(fileName)
            return

        self.dlgPathSelect = PathSelect(self.save, "Save Project File",
                                        "Save file path", "Save", fileName,
                                        tooltip)

    def excSave(self):
        self.dlgOverwrite = None
        self.dlgOverwriteShadow = None

        tmpPath = os.path.join(tempfile.gettempdir(), "DGDExceptionSave.json")
        self.__executeSave(True, tmpPath)
        logging.info("Wrote crash session file to {}".format(tmpPath))

    def autoSave(self, fileName=""):
        self.dlgOverwrite = None
        self.dlgOverwriteShadow = None
        if fileName == "":
            fileName = os.path.join(tempfile.gettempdir(), "DGDAutosave.json")
        self.__executeSave(True, fileName)
        logging.info("Wrote autosave file to {}".format(fileName))

    def save(self, doSave):
        if doSave:
            self.dlgOverwrite = None
            self.dlgOverwriteShadow = None
            path = self.dlgPathSelect.getPath()
            path = os.path.expanduser(path)
            path = os.path.expandvars(path)
            if os.path.exists(path):
                self.dlgOverwrite = YesNoDialog(
                    text="File already Exist.\nOverwrite?",
                    relief=DGG.RIDGE,
                    frameColor=(1, 1, 1, 1),
                    frameSize=(-0.5, 0.5, -0.3, 0.2),
                    sortOrder=1,
                    button_relief=DGG.FLAT,
                    button_frameColor=(0.8, 0.8, 0.8, 1),
                    command=self.__executeSave,
                    extraArgs=[path],
                    scale=300,
                    pos=(base.getSize()[0] / 2, 0, -base.getSize()[1] / 2),
                    parent=base.pixel2d)
                self.dlgOverwriteShadow = DirectFrame(
                    pos=(base.getSize()[0] / 2 + 10, 0,
                         -base.getSize()[1] / 2 - 10),
                    sortOrder=0,
                    frameColor=(0, 0, 0, 0.5),
                    frameSize=self.dlgOverwrite.bounds,
                    scale=300,
                    parent=base.pixel2d)
            else:
                self.__executeSave(True, path)
            base.messenger.send("setLastPath", [path])
        self.dlgPathSelect.destroy()
        del self.dlgPathSelect

    def __executeSave(self, overwrite, path):
        if self.dlgOverwrite is not None: self.dlgOverwrite.destroy()
        if self.dlgOverwriteShadow is not None:
            self.dlgOverwriteShadow.destroy()
        if not overwrite: return

        jsonTools = JSONTools()
        jsonElements = jsonTools.getProjectJSON(self.guiElementsDict,
                                                self.getEditorFrame,
                                                self.usePixel2D)
        with open(path, 'w') as outfile:
            json.dump(jsonElements, outfile, indent=2)

        if not self.isAutosave:
            base.messenger.send("clearDirtyFlag")
Exemplo n.º 5
0
class ProjectLoader(DirectObject):
    funcMap = {"initialText": "set"}
    # This prioList will be walked through if all other options not in
    # this list have already been set
    prioList = ["frameSize"]
    setAsOption = [
        "frameSize", "canvasSize", "indicatorValue", "frameColor", "barColor",
        "barRelief", "range", "value", "relief", "borderWidth", "clipSize",
        "scrollBarWidth", "state"
    ]
    ignoreMap = []  #"state"]
    ignoreComponentSplit = ["text", "image"]

    def __init__(self,
                 filePath,
                 visualEditorInfo,
                 elementHandler,
                 customWidgetHandler,
                 getEditorPlacer,
                 exceptionLoading=False,
                 tooltip=None,
                 newProjectCall=None):
        self.newProjectCall = newProjectCall
        self.extraOptions = [
            "borderWidth", "frameColor", "initialText", "clipSize"
        ]
        self.parentMap = {}
        self.radiobuttonOthersDict = {}
        self.elementDict = {}
        self.elementHandler = elementHandler
        self.customWidgetHandler = customWidgetHandler
        self.visualEditorInfo = visualEditorInfo
        self.visualEditor = visualEditorInfo.element
        self.getEditorPlacer = getEditorPlacer
        self.hasErrors = False
        if exceptionLoading:
            self.excLoad()
        else:
            self.dlgPathSelect = PathSelect(self.Load, "Load Project File",
                                            "Load file path", "Load", filePath,
                                            tooltip)

    def excLoad(self):
        tmpPath = os.path.join(tempfile.gettempdir(), "DGDExceptionSave.json")
        self.__executeLoad(tmpPath)

    def get(self):
        return self.elementDict

    def Load(self, doLoad):
        if doLoad:
            path = self.dlgPathSelect.getPath()
            path = os.path.expanduser(path)
            path = os.path.expandvars(path)

            if not os.path.exists(path):
                base.messenger.send(
                    "showWarning",
                    ["File \"{}\" does not exist.".format(path)])
                return

            if self.newProjectCall():
                self.__executeLoad(path)
            else:
                self.accept("clearDirtyFlag", self.__executeLoad, [path])

        self.dlgPathSelect.destroy()
        del self.dlgPathSelect

    def __executeLoad(self, path):
        fileContent = None
        with open(path, 'r') as infile:
            try:
                fileContent = json.load(infile)
            except Exception as e:
                logging.error("Couldn't load project file {}".format(infile))
                logging.exception(e)
                base.messenger.send("showWarning", [
                    "Error while loading Project!\nPlease check output logs for more information."
                ])
                return
        if fileContent is None:
            logging.error("Problems reading Project file: {}".format(infile))
            return

        self.canvasParents = [
            "a2dTopCenter", "a2dBottomCenter", "a2dLeftCenter",
            "a2dRightCenter", "a2dTopLeft", "a2dTopRight", "a2dBottomLeft",
            "a2dBottomRight"
        ]
        self.createdParents = ["root"] + self.canvasParents
        self.postponedElements = {}
        if fileContent["ProjectVersion"] != "0.2a":
            logging.warning("Unsupported Project Version")
            base.messenger.send("showWarning", ["Unsupported Project Version"])
            return
        base.messenger.send("setVisualEditorParent",
                            [fileContent["EditorConfig"]["usePixel2D"]])
        base.messenger.send("setVisualEditorCanvasSize",
                            [eval(fileContent["EditorConfig"]["canvasSize"])])
        for name, elementInfo in fileContent["ComponentList"].items():
            self.__createElement(name, elementInfo)

        for elementInfo, option in self.radiobuttonOthersDict.items():
            elementList = []
            for elementId, info in self.elementDict.items():
                if info.name in option:
                    elementList.append(info.element)
            elementInfo.element["others"] = elementList

        if self.hasErrors:
            base.messenger.send("showWarning", [
                "Errors occured while loading the project!\nProject may not be fully loaded\nSee output log for more information."
            ])
            return

        base.messenger.send("setLastPath", [path])
        base.messenger.send("updateElementDict-afterLoad", [self.elementDict])

    def __createElement(self, name, info):
        if info["parent"] not in self.createdParents:
            self.postponedElements[name] = info
            return

        # create the element
        self.__createControl(name, info)
        self.createdParents.append(name)

        if name in self.postponedElements.keys():
            del self.postponedElements[name]

        # check if we can create postponed elements
        for elementName, elementInfo in self.postponedElements.copy().items():
            if elementName in self.createdParents: continue
            if elementInfo["parent"] in self.createdParents:
                self.__createElement(elementName, elementInfo)

    def __createControl(self, jsonElementName, jsonElementInfo):
        funcName = "create{}".format(jsonElementInfo["type"])
        if hasattr(self.elementHandler, funcName):
            parentName = jsonElementInfo["parent"]
            parent = None
            if parentName in self.parentMap.keys():
                parent = self.elementDict[self.parentMap[parentName]]
            widget = self.customWidgetHandler.getWidget(
                jsonElementInfo["type"])
            if funcName == "createDirectEntryScroll":
                elementInfo = getattr(self.elementHandler, funcName)(
                    parent.element if parent is not None else None, False)
            elif widget is not None:
                # Custom widget add
                elementInfo = getattr(self.elementHandler, funcName)(
                    widget, parent.element if parent is not None else None)
            else:
                elementInfo = getattr(
                    self.elementHandler,
                    funcName)(parent.element if parent is not None else None)

            if elementInfo is None: return

            if parentName in self.canvasParents:
                elementInfo.element.reparentTo(
                    self.getEditorPlacer(parentName))

            # load the extra definitions of the element info
            elementInfo.command = jsonElementInfo["command"]
            elementInfo.extraArgs = jsonElementInfo["extraArgs"]
            elementInfo.extraOptions = jsonElementInfo["extraOptions"]
            elementInfo.name = jsonElementName
            if "transparency" in jsonElementInfo:
                elementInfo.element.setTransparency(
                    eval(jsonElementInfo["transparency"]))

            if type(elementInfo) is tuple:
                if parent is not None and "DirectScrolledList" == parent.type:
                    parent.element.addItem(elementInfo[0].element)
                elif parent is not None and "DirectEntryScroll" == parent.type:
                    parent.element.setEntry(elementInfo[0].element)
                    parent.extraOptions[
                        "entry"] = "self." + elementInfo[0].name
                parentWidget = self.customWidgetHandler.getWidget(
                    parent.type if parent is not None else "")
                if parentWidget is not None:
                    if parentWidget.addItemFunction is not None:
                        # call custom widget add function
                        getattr(parent.element, parentWidget.addItemFunction)(
                            elementInfo[0].element)

                for entry in elementInfo:
                    entry.parent = parent
                    # TODO: Check how this works! ESP. Saving TOO
                    self.__setProperties(entry, jsonElementInfo)
                    self.elementDict[entry.element.guiId] = entry
                    self.parentMap[jsonElementName] = entry.element.guiId
            else:
                elementInfo.parent = parent
                if parent is not None and "DirectScrolledList" == parent.type:
                    parent.element.addItem(elementInfo.element)
                elif parent is not None and "DirectEntryScroll" == parent.type:
                    parent.element.setEntry(elementInfo.element)
                    parent.extraOptions["entry"] = "self." + elementInfo.name
                parentWidget = self.customWidgetHandler.getWidget(
                    parent.type if parent is not None else "")
                if parentWidget is not None:
                    if parentWidget.addItemFunction is not None:
                        # call custom widget add function
                        getattr(parent.element, parentWidget.addItemFunction)(
                            elementInfo.element)
                self.__setProperties(elementInfo, jsonElementInfo)
                if elementInfo.type == "DirectScrolledFrame":
                    elementInfo.element.setScrollBarWidth()
                self.elementDict[elementInfo.element.guiId] = elementInfo
                self.parentMap[jsonElementName] = elementInfo.element.guiId
            base.messenger.send("refreshStructureTree")

    def __setProperties(self, elementInfo, jsonElementInfo):
        tempOptionDict = {}
        for name, value in jsonElementInfo["element"].items():
            if name == "others":
                self.radiobuttonOthersDict[elementInfo] = value
                continue
            if name in self.prioList:
                tempOptionDict[name] = value
            else:
                self.__setProp(elementInfo, name, value)

        for name, value in tempOptionDict.items():
            self.__setProp(elementInfo, name, value)

        if "frameSize" not in tempOptionDict.keys():
            elementInfo.element.resetFrameSize()

    def __setProp(self, elementInfo, name, value):
        try:
            options = self.extraOptions + elementInfo.element.options()
            if name in self.ignoreMap: return
            if name in options:
                self.__setPropValue(name, elementInfo.element, value)
            else:
                components = name.split("_")
                found = False
                for comp in components:
                    if comp in self.ignoreComponentSplit:
                        found = True
                if len(components) > 1 and not found:
                    componentName = components[0]
                    if elementInfo.element.hascomponent(componentName):
                        component = elementInfo.element.component(
                            componentName)
                        optionName = components[-1]
                        self.__setPropValue(optionName, component, value)
                    else:
                        try:
                            self.__setPropValue(name, elementInfo.element,
                                                value)
                        except Exception as e:
                            logging.exception(
                                "Unsupported Property or item {}".format(name))
                else:
                    self.__setPropValue(name, elementInfo.element, value)
        except Exception as e:
            logging.exception(
                "Couldn't set Property with Name '{}' to {}".format(
                    name, value))
            self.hasErrors = True

    def __setPropValue(self, optionName, component, value):
        funcName = "set{}{}".format(optionName[0].upper(), optionName[1:])
        if optionName in self.setAsOption:
            component[optionName] = eval(value)
        elif optionName in self.funcMap.keys():
            funcName = self.funcMap[optionName]
            getattr(component, funcName)(eval(value))
        elif hasattr(component, funcName):
            getattr(component, funcName)(eval(value))
        else:
            component[optionName] = eval(value)
    def __init__(self, saveFile, guiElementsDict, customWidgetHandler, getEditorFrame, tooltip, usePixel2D):
        self.guiElementsDict = guiElementsDict
        self.customWidgetHandler = customWidgetHandler

        jsonTools = JSONTools()
        self.jsonFileContent = jsonTools.getProjectJSON(self.guiElementsDict, getEditorFrame, usePixel2D)
        self.jsonElements = self.jsonFileContent["ComponentList"]

        self.createdParents = ["root"]
        self.postponedElements = {}
        self.postSetupCalling = []
        self.radiobuttonDict = {}
        self.customWidgetAddDict = {}

        importStatements = {
            "DirectButton":"from direct.gui.DirectButton import DirectButton",
            "DirectEntry":"from direct.gui.DirectEntry import DirectEntry",
            "DirectEntryScroll":"from direct.gui.DirectEntryScroll import DirectEntryScroll",
            "DirectCheckBox":"from direct.gui.DirectCheckBox import DirectCheckBox",
            "DirectCheckButton":"from direct.gui.DirectCheckButton import DirectCheckButton",
            "DirectOptionMenu":"from direct.gui.DirectOptionMenu import DirectOptionMenu",
            "DirectRadioButton":"from direct.gui.DirectRadioButton import DirectRadioButton",
            "DirectSlider":"from direct.gui.DirectSlider import DirectSlider",
            "DirectScrollBar":"from direct.gui.DirectScrollBar import DirectScrollBar",
            "DirectScrolledList":"from direct.gui.DirectScrolledList import DirectScrolledList",
            "DirectScrolledListItem":"from direct.gui.DirectScrolledList import DirectScrolledListItem",
            "DirectLabel":"from direct.gui.DirectLabel import DirectLabel",
            "DirectWaitBar":"from direct.gui.DirectWaitBar import DirectWaitBar",
            "OkDialog":"from direct.gui.DirectDialog import OkDialog",
            "OkCancelDialog":"from direct.gui.DirectDialog import OkCancelDialog",
            "YesNoDialog":"from direct.gui.DirectDialog import YesNoDialog",
            "YesNoCancelDialog":"from direct.gui.DirectDialog import YesNoCancelDialog",
            "RetryCancelDialog":"from direct.gui.DirectDialog import RetryCancelDialog",
            "DirectFrame":"from direct.gui.DirectFrame import DirectFrame",
            "DirectScrolledFrame":"from direct.gui.DirectScrolledFrame import DirectScrolledFrame",
        }

        self.content = """#!/usr/bin/python
# -*- coding: utf-8 -*-

# This file was created using the DirectGUI Designer

from direct.gui import DirectGuiGlobals as DGG
"""
        usedImports = []
        for name, elementInfo in self.guiElementsDict.items():
            if elementInfo.type not in usedImports:
                if elementInfo.type in importStatements:
                    self.content = "{}\n{}".format(self.content, importStatements[elementInfo.type])
                else:
                    self.content = "{}\n{}".format(self.content, elementInfo.customImportPath)
                usedImports.append(elementInfo.type)
        self.content += """
from panda3d.core import (
    LPoint3f,
    LVecBase3f,
    LVecBase4f,
    TextNode
)"""
        if ConfigVariableBool("create-executable-scripts", False).getValue():
            self.content += """
# We need showbase to make this script directly runnable
from direct.showbase.ShowBase import ShowBase"""
        self.content += """

class GUI:
    def __init__(self, rootParent=None):
        """

        #self.__createStructuredElements("root", visualEditor.getCanvas())

        for name, elementInfo in self.jsonElements.items():
            self.content += self.__createElement(name, elementInfo)


        self.content += "\n"
        for line in self.postSetupCalling:
            self.content += line + "\n"

        for radioButton, others in self.radiobuttonDict.items():
            self.content += " "*8 + "{}.setOthers([".format(radioButton)
            for other in others:
                self.content += other + ","
            self.content += "])\n"

        topLevelItems = []
        for name, elementInfo in self.jsonElements.items():
            widget = self.customWidgetHandler.getWidget(elementInfo["type"])
            if widget is not None:
                if name not in self.customWidgetAddDict: continue
                for element in self.customWidgetAddDict[name]:
                    if widget.addItemFunction is not None:
                        self.content += " "*8 + "self.{}.{}({})\n".format(name, widget.addItemFunction, element)

            if elementInfo["parent"] == "root":
                topLevelItems.append(name)

        # Create helper functions for toplevel elements
        if len(topLevelItems) > 0:
            self.content += "\n"
            self.content += " "*4 + "def show(self):\n"
            for name in topLevelItems:
                self.content += " "*8 + "self.{}.show()\n".format(name)

            self.content += "\n"
            self.content += " "*4 + "def hide(self):\n"
            for name in topLevelItems:
                self.content += " "*8 + "self.{}.hide()\n".format(name)

            self.content += "\n"
            self.content += " "*4 + "def destroy(self):\n"
            for name in topLevelItems:
                self.content += " "*8 + "self.{}.destroy()\n".format(name)

        # Make script executable if desired
        if ConfigVariableBool("create-executable-scripts", False).getValue():
            self.content += """
# Create a ShowBase instance to make this gui directly runnable
app = ShowBase()\n"""
            if usePixel2D:
                self.content += "GUI(app.pixel2d)\n"
            else:
                self.content += "GUI()\n"
            self.content += "app.run()\n"

        self.dlgPathSelect = PathSelect(
            self.save, "Save Python File", "Save file path", "Save", saveFile, tooltip)
class ExporterPy:
    functionMapping = {
        "base":{"initialText":"get"},
        "text":{"align":"align", "scale":"scale", "pos":"pos", "fg":"fg", "bg":"bg"}}

    # list of control names starting with the following will be ignored
    ignoreControls = ["item", "cancelframe", "popupMarker", "popupMenu"]
    # list of control names staritng with the following will always be included
    explIncludeControls = ["itemFrame"]

    def __init__(self, saveFile, guiElementsDict, customWidgetHandler, getEditorFrame, tooltip, usePixel2D):
        self.guiElementsDict = guiElementsDict
        self.customWidgetHandler = customWidgetHandler

        jsonTools = JSONTools()
        self.jsonFileContent = jsonTools.getProjectJSON(self.guiElementsDict, getEditorFrame, usePixel2D)
        self.jsonElements = self.jsonFileContent["ComponentList"]

        self.createdParents = ["root"]
        self.postponedElements = {}
        self.postSetupCalling = []
        self.radiobuttonDict = {}
        self.customWidgetAddDict = {}

        importStatements = {
            "DirectButton":"from direct.gui.DirectButton import DirectButton",
            "DirectEntry":"from direct.gui.DirectEntry import DirectEntry",
            "DirectEntryScroll":"from direct.gui.DirectEntryScroll import DirectEntryScroll",
            "DirectCheckBox":"from direct.gui.DirectCheckBox import DirectCheckBox",
            "DirectCheckButton":"from direct.gui.DirectCheckButton import DirectCheckButton",
            "DirectOptionMenu":"from direct.gui.DirectOptionMenu import DirectOptionMenu",
            "DirectRadioButton":"from direct.gui.DirectRadioButton import DirectRadioButton",
            "DirectSlider":"from direct.gui.DirectSlider import DirectSlider",
            "DirectScrollBar":"from direct.gui.DirectScrollBar import DirectScrollBar",
            "DirectScrolledList":"from direct.gui.DirectScrolledList import DirectScrolledList",
            "DirectScrolledListItem":"from direct.gui.DirectScrolledList import DirectScrolledListItem",
            "DirectLabel":"from direct.gui.DirectLabel import DirectLabel",
            "DirectWaitBar":"from direct.gui.DirectWaitBar import DirectWaitBar",
            "OkDialog":"from direct.gui.DirectDialog import OkDialog",
            "OkCancelDialog":"from direct.gui.DirectDialog import OkCancelDialog",
            "YesNoDialog":"from direct.gui.DirectDialog import YesNoDialog",
            "YesNoCancelDialog":"from direct.gui.DirectDialog import YesNoCancelDialog",
            "RetryCancelDialog":"from direct.gui.DirectDialog import RetryCancelDialog",
            "DirectFrame":"from direct.gui.DirectFrame import DirectFrame",
            "DirectScrolledFrame":"from direct.gui.DirectScrolledFrame import DirectScrolledFrame",
        }

        self.content = """#!/usr/bin/python
# -*- coding: utf-8 -*-

# This file was created using the DirectGUI Designer

from direct.gui import DirectGuiGlobals as DGG
"""
        usedImports = []
        for name, elementInfo in self.guiElementsDict.items():
            if elementInfo.type not in usedImports:
                if elementInfo.type in importStatements:
                    self.content = "{}\n{}".format(self.content, importStatements[elementInfo.type])
                else:
                    self.content = "{}\n{}".format(self.content, elementInfo.customImportPath)
                usedImports.append(elementInfo.type)
        self.content += """
from panda3d.core import (
    LPoint3f,
    LVecBase3f,
    LVecBase4f,
    TextNode
)"""
        if ConfigVariableBool("create-executable-scripts", False).getValue():
            self.content += """
# We need showbase to make this script directly runnable
from direct.showbase.ShowBase import ShowBase"""
        self.content += """

class GUI:
    def __init__(self, rootParent=None):
        """

        #self.__createStructuredElements("root", visualEditor.getCanvas())

        for name, elementInfo in self.jsonElements.items():
            self.content += self.__createElement(name, elementInfo)


        self.content += "\n"
        for line in self.postSetupCalling:
            self.content += line + "\n"

        for radioButton, others in self.radiobuttonDict.items():
            self.content += " "*8 + "{}.setOthers([".format(radioButton)
            for other in others:
                self.content += other + ","
            self.content += "])\n"

        topLevelItems = []
        for name, elementInfo in self.jsonElements.items():
            widget = self.customWidgetHandler.getWidget(elementInfo["type"])
            if widget is not None:
                if name not in self.customWidgetAddDict: continue
                for element in self.customWidgetAddDict[name]:
                    if widget.addItemFunction is not None:
                        self.content += " "*8 + "self.{}.{}({})\n".format(name, widget.addItemFunction, element)

            if elementInfo["parent"] == "root":
                topLevelItems.append(name)

        # Create helper functions for toplevel elements
        if len(topLevelItems) > 0:
            self.content += "\n"
            self.content += " "*4 + "def show(self):\n"
            for name in topLevelItems:
                self.content += " "*8 + "self.{}.show()\n".format(name)

            self.content += "\n"
            self.content += " "*4 + "def hide(self):\n"
            for name in topLevelItems:
                self.content += " "*8 + "self.{}.hide()\n".format(name)

            self.content += "\n"
            self.content += " "*4 + "def destroy(self):\n"
            for name in topLevelItems:
                self.content += " "*8 + "self.{}.destroy()\n".format(name)

        # Make script executable if desired
        if ConfigVariableBool("create-executable-scripts", False).getValue():
            self.content += """
# Create a ShowBase instance to make this gui directly runnable
app = ShowBase()\n"""
            if usePixel2D:
                self.content += "GUI(app.pixel2d)\n"
            else:
                self.content += "GUI()\n"
            self.content += "app.run()\n"

        self.dlgPathSelect = PathSelect(
            self.save, "Save Python File", "Save file path", "Save", saveFile, tooltip)

    def save(self, doSave):
        if doSave:
            self.dlgOverwrite = None
            self.dlgOverwriteShadow = None
            path = self.dlgPathSelect.getPath()
            path = os.path.expanduser(path)
            path = os.path.expandvars(path)
            if os.path.exists(path):
                self.dlgOverwrite = YesNoDialog(
                    text="File already Exist.\nOverwrite?",
                    relief=DGG.RIDGE,
                    frameColor=(1,1,1,1),
                    frameSize=(-0.5,0.5,-0.3,0.2),
                    sortOrder=1,
                    button_relief=DGG.FLAT,
                    button_frameColor=(0.8, 0.8, 0.8, 1),
                    command=self.__executeSave,
                    extraArgs=[path],
                    scale=300,
                    pos=(base.getSize()[0]/2, 0, -base.getSize()[1]/2),
                    parent=base.pixel2d)
                self.dlgOverwriteShadow = DirectFrame(
                    pos=(base.getSize()[0]/2 + 10, 0, -base.getSize()[1]/2 - 10),
                    sortOrder=0,
                    frameColor=(0,0,0,0.5),
                    frameSize=self.dlgOverwrite.bounds,
                    scale=300,
                    parent=base.pixel2d)
            else:
                self.__executeSave(True, path)
            base.messenger.send("setLastPath", [path])
        self.dlgPathSelect.destroy()
        del self.dlgPathSelect

    def __executeSave(self, overwrite, path):
        if self.dlgOverwrite is not None: self.dlgOverwrite.destroy()
        if self.dlgOverwriteShadow is not None: self.dlgOverwriteShadow.destroy()
        if not overwrite: return
        with open(path, 'w') as outfile:
            outfile.write(self.content)

    def __createElement(self, name, elementInfo):
        extraOptions = ""
        for optionName, optionValue in elementInfo["extraOptions"].items():
            extraOptions += " "*12 + "{}={},\n".format(optionName, optionValue)
        elementCode = """
        self.{} = {}(
{}{}{}{}        )\n""".format(
            name,
            elementInfo["type"],
            self.__writeElementOptions(name, elementInfo),
            " "*12 + "command={},\n".format(elementInfo["command"]) if elementInfo["command"] is not None else "",
            " "*12 + "extraArgs=[{}],\n".format(elementInfo["extraArgs"]) if elementInfo["extraArgs"] is not None else "",
            extraOptions,
            )
        if elementInfo["element"]["transparency"] != "M_none":
            elementCode += " "*8 +"self.{}.setTransparency({})\n".format(name, elementInfo["element"]["transparency"])

        if elementInfo["type"] == "DirectScrolledListItem":
            self.postSetupCalling.append(" "*8 + "self.{}.addItem(self.{})".format(elementInfo["parent"], name))

        return elementCode

    def __writeElementOptions(self, name, elementInfo):
        elementOptions = ""
        indent = " "*12

        if elementInfo["type"] == "DirectOptionMenu":
            elementOptions += indent + "items=['item1'],\n"

        for optionKey, optionValue in elementInfo["element"].items():
            if optionKey == "others":
                others = []
                for other in optionValue:
                    others.append("self.{}".format(other))
                self.radiobuttonDict["self.{}".format(name)] = others
                continue
            elif optionKey == "transparency":
                continue

            elementOptions += indent + optionKey + "=" + optionValue + ",\n"

        if elementInfo["parent"] != "root":
            self.canvasParents = [
                "a2dTopCenter","a2dBottomCenter","a2dLeftCenter","a2dRightCenter",
                "a2dTopLeft","a2dTopRight","a2dBottomLeft","a2dBottomRight"]

            if elementInfo["parent"] in self.jsonElements and self.jsonElements[elementInfo["parent"]]["type"] == "DirectScrollFrame":
                # use the canvas as parent
                elementOptions += indent + "parent=self." + elementInfo["parent"] + ".getCanvas(),\n"
            elif elementInfo["parent"] in self.jsonElements and self.customWidgetHandler.getWidget(self.jsonElements[elementInfo["parent"]]["type"]) is not None:
                widget = self.customWidgetHandler.getWidget(self.jsonElements[elementInfo["parent"]]["type"])
                if widget.addItemFunction is not None:
                    if elementInfo["parent"] in self.customWidgetAddDict:
                        self.customWidgetAddDict[elementInfo["parent"]].append("self.{}".format(name))
                    else:
                        self.customWidgetAddDict[elementInfo["parent"]] = ["self.{}".format(name)]
            elif elementInfo["parent"] in self.canvasParents:
                elementOptions += indent + "parent=base." + elementInfo["parent"] + ",\n"
            else:
                elementOptions += indent + "parent=self." + elementInfo["parent"] + ",\n"
        else:
            # use the parent passed to the class
            elementOptions += indent + "parent=rootParent,\n"

        return elementOptions
Exemplo n.º 8
0
 def __init__(self, visualEditor, tooltip):
     self.visualEditor = visualEditor
     self.dlgPathSelect = PathSelect(
         self.Load, "Load Python File", "Load file path", "Load", "~/export.py", tooltip)