From 4af7302b058c3ef083b09cb9fd5cddf8930019e6 Mon Sep 17 00:00:00 2001 From: Humberto Sanchez II Date: Thu, 27 Oct 2022 16:52:37 -0500 Subject: [PATCH] [update for Pyut]: [ * Additional options for IOPluginInterface * PluginManager was using .doAction instead of .executeTool on Tool Plugins (bug) * Update OglObjectType * Update several plugins with new options * Implement a couple more PluginAdapter methods to ensure the plugin code "as-is" works * Align UMLFrame more with the "real" UmlFrame; I really need a component here * Version update for Pyut ] [https://github.com/hasii2011/PyUt/issues/319] --- core/IOPluginInterface.py | 74 ++++++---- core/PluginManager.py | 17 ++- core/ToolPluginInterface.py | 1 + core/types/Types.py | 2 +- plugins/io/IOGML.py | 2 + plugins/io/IOPdf.py | 2 + plugins/io/IOWxImage.py | 35 +---- plugins/io/IOXml.py | 2 + setup.py | 2 +- tests/scaffoldv2/PluginAdapterV2.py | 2 +- tests/scaffoldv2/ScaffoldFrame.py | 38 +++++- tests/scaffoldv2/ScaffoldUI.py | 142 +++++++++++++++----- tests/scaffoldv2/eventengine/EventEngine.py | 20 +++ tests/scaffoldv2/eventengine/Events.py | 6 +- tests/scaffoldv2/umlframes/UmlFrame.py | 8 ++ 15 files changed, 245 insertions(+), 108 deletions(-) diff --git a/core/IOPluginInterface.py b/core/IOPluginInterface.py index cb9c532..399ca0f 100644 --- a/core/IOPluginInterface.py +++ b/core/IOPluginInterface.py @@ -43,47 +43,71 @@ def __init__(self, pluginAdapter: IPluginAdapter): self._selectedOglObjects: OglObjects = cast(OglObjects, None) # The selected Ogl Objects requested by .executeExport() self._frameInformation: FrameInformation = cast(FrameInformation, None) # The frame information requested by .executeExport() + # + # Input plugins that require an active frame or frame(s) should set this value to `True` + # Some output plugins may create their own frame or ever their own project and frame. These should set this value to `False` + # Plugins should set the value the need in their constructor + # + self._requireActiveFrame: bool = True + # + # Some Output plugins may offer the option of exporting only selected objects; Others may just export + # the entire project or the current frame + # + # Plugins should set the value the need in their constructor + self._requireSelection: bool = True + # + # + # prefs: PyutPreferences = PyutPreferences() + # if prefs.pyutIoPluginAutoSelectAll is True: TODO: Need plugin preferences + # self._autoSelectAll: bool = True + # else + self._autoSelectAll: bool = False + def executeImport(self): """ - Called by Pyut to begin the import process. Checks to see if an import format is - supported if not returns None; Checks to see if there are any import options; - If the method return True the import proceeds - - Returns: - None if cancelled, else a list of OglObjects + Called by Pyut to begin the import process. """ - if self.inputFormat is None: - self._oglObjects = None - else: - if self.setImportOptions() is True: - self._oglObjects = self.read() - else: - self._oglObjects = None + # TODO Fix later + # noinspection PyTypeChecker + self._pluginAdapter.getFrameInformation(callback=self._executeImport) # type ignore - return self._oglObjects + def _executeImport(self, frameInformation: FrameInformation): + """ + The callback necessary to start the import process; + Args: + frameInformation: + """ + assert self.inputFormat is not None, 'Developer error. We cannot import w/o an import format' + if self._requireActiveFrame is True: + if frameInformation.frameActive is False: + self.displayNoUmlFrame() + return + if self.setImportOptions() is True: + self.read() def executeExport(self): """ Called by Pyut to begin the export process. """ + if self._autoSelectAll is True: + self._pluginAdapter.selectAllOglObjects() self._pluginAdapter.getFrameInformation(callback=self._executeExport) def _executeExport(self, frameInformation: FrameInformation): - assert self.outputFormat is not None, 'Developer error. We cannot export w/o and output format' + assert self.outputFormat is not None, 'Developer error. We cannot export w/o an output format' + + self._frameInformation = frameInformation + if frameInformation.frameActive is False: self.displayNoUmlFrame() else: - if self.setExportOptions() is True: - self._frameInformation = frameInformation - self._selectedOglObjects = frameInformation.selectedOglObjects # syntactic sugar - # prefs: PyutPreferences = PyutPreferences() - # if prefs.pyutIoPluginAutoSelectAll is True: TODO: Need plugin preferences - # pluginAdapter.selectAllShapes() - - if len(self._selectedOglObjects) == 0: - self.displayNoSelectedOglObjects() - else: + self._selectedOglObjects = frameInformation.selectedOglObjects # syntactic sugar + + if len(self._selectedOglObjects) == 0: + self.displayNoSelectedOglObjects() + else: + if self.setExportOptions() is True: self.write(self._selectedOglObjects) self._pluginAdapter.deselectAllOglObjects() diff --git a/core/PluginManager.py b/core/PluginManager.py index d0cf090..2e5371c 100644 --- a/core/PluginManager.py +++ b/core/PluginManager.py @@ -152,15 +152,14 @@ def doToolAction(self, wxId: int): # Create a plugin instance pluginInstance: ToolPluginInterface = clazz(pluginAdapter=self._pluginAdapter) - if pluginInstance.setOptions() is True: - # Do plugin functionality - BeginBusyCursor() - try: - pluginInstance.doAction() - self.logger.debug(f"After tool plugin do action") - except (ValueError, Exception) as e: - self.logger.error(f'{e}') - EndBusyCursor() + # Do plugin functionality + BeginBusyCursor() + try: + pluginInstance.executeTool() + self.logger.debug(f"After tool plugin do action") + except (ValueError, Exception) as e: + self.logger.error(f'{e}') + EndBusyCursor() def doImport(self, wxId: int): """ diff --git a/core/ToolPluginInterface.py b/core/ToolPluginInterface.py index e003fd0..fdfb598 100644 --- a/core/ToolPluginInterface.py +++ b/core/ToolPluginInterface.py @@ -23,6 +23,7 @@ def executeTool(self): """ This is used by Pyut to invoke the tool. This should NOT be overridden + TODO: Check for active frame """ if self.setOptions() is True: self.doAction() diff --git a/core/types/Types.py b/core/types/Types.py index 73ed00e..4540b7b 100644 --- a/core/types/Types.py +++ b/core/types/Types.py @@ -39,7 +39,7 @@ OglSDInstances = NewType('OglSDInstances', Dict[int, OglSDInstance]) OglSDMessages = NewType('OglSDMessages', Dict[int, OglSDMessage]) -OglObjectType = Union[OglClass, OglLink, OglNote, OglText, OglActor, OglUseCase, OglInterface2] +OglObjectType = Union[OglClass, OglLink, OglNote, OglText, OglActor, OglUseCase, OglInterface2, OglSDMessage, OglSDInstance, OglUseCase, OglActor] OglObjects = NewType('OglObjects', List[OglObjectType]) PyutLinks = NewType('PyutLinks', List[PyutLink]) diff --git a/plugins/io/IOGML.py b/plugins/io/IOGML.py index 22a2ff2..b525457 100644 --- a/plugins/io/IOGML.py +++ b/plugins/io/IOGML.py @@ -47,6 +47,8 @@ def __init__(self, pluginAdapter: IPluginAdapter): self._inputFormat = cast(InputFormat, None) self._outputFormat = OutputFormat(formatName=FORMAT_NAME, extension=PLUGIN_EXTENSION, description=PLUGIN_DESCRIPTION) + self._autoSelectAll = False # Temp until we have plugin preferences + def setImportOptions(self) -> bool: """ Prepare the import. diff --git a/plugins/io/IOPdf.py b/plugins/io/IOPdf.py index 9a3b363..f3c7709 100644 --- a/plugins/io/IOPdf.py +++ b/plugins/io/IOPdf.py @@ -53,6 +53,8 @@ def __init__(self, pluginAdapter: IPluginAdapter): self._imageOptions.imageFormat = ImageFormat.PDF + self._autoSelectAll = True # we are taking a picture of the entire diagram + def setImportOptions(self) -> bool: return False diff --git a/plugins/io/IOWxImage.py b/plugins/io/IOWxImage.py index 9269ac3..00216e6 100644 --- a/plugins/io/IOWxImage.py +++ b/plugins/io/IOWxImage.py @@ -53,6 +53,8 @@ def __init__(self, pluginAdapter: IPluginAdapter): self._inputFormat = cast(InputFormat, None) self._outputFormat = OutputFormat(formatName=FORMAT_NAME, extension=PLUGIN_EXTENSION, description=PLUGIN_DESCRIPTION) + self._autoSelectAll = True # we are taking a picture of the entire diagram + def setImportOptions(self) -> bool: return False @@ -85,18 +87,15 @@ def write(self, oglObjects: OglObjects): Args: oglObjects: list of exported objects """ - # self._pluginAdapter.getFrameInformation(callback=self._gotFrameInfo) - mediator: IPluginAdapter = self._pluginAdapter + pluginAdapter: IPluginAdapter = self._pluginAdapter frameInformation: FrameInformation = self._frameInformation - mediator.deselectAllOglObjects() + pluginAdapter.deselectAllOglObjects() imageType: BitmapType = WxImageFormat.toWxBitMapType(self._imageFormat) - # window: ScrolledWindow = self._pluginAdapter.umlFrame context: ClientDC = frameInformation.clientDC memory: MemoryDC = MemoryDC() - # x, y = window.GetSize() x: int = frameInformation.frameSize.width y: int = frameInformation.frameSize.height emptyBitmap: Bitmap = Bitmap(x, y, -1) @@ -112,29 +111,3 @@ def write(self, oglObjects: OglObjects): status: bool = img.SaveFile(filename, imageType) if status is False: self.logger.error(f'Error on image write to {filename}') - - # def _gotFrameInfo(self, frameInformation: FrameInformation): - # - # x = frameInformation.frameSize.width - # y = frameInformation.frameSize.height - # context: ClientDC = frameInformation.clientDC - # imageType: BitmapType = WxImageFormat.toWxBitMapType(self._imageFormat) - # - # # window: ScrolledWindow = self._pluginAdapter.umlFrame - # # context: ClientDC = ClientDC(window) - # memory: MemoryDC = MemoryDC() - # - # # x, y = window.GetSize() - # emptyBitmap: Bitmap = Bitmap(x, y, -1) - # - # memory.SelectObject(emptyBitmap) - # memory.Blit(source=context, xsrc=0, height=y, xdest=0, ydest=0, ysrc=0, width=x) - # memory.SelectObject(NullBitmap) - # - # img: Image = emptyBitmap.ConvertToImage() - # extension: str = self._imageFormat.__str__() - # - # filename: str = f'{self._outputFileName}.{extension}' - # status: bool = img.SaveFile(filename, imageType) - # if status is False: - # self.logger.error(f'Error on image write to {filename}') diff --git a/plugins/io/IOXml.py b/plugins/io/IOXml.py index 72fb3ef..ad16c29 100644 --- a/plugins/io/IOXml.py +++ b/plugins/io/IOXml.py @@ -80,6 +80,8 @@ def __init__(self, pluginAdapter: IPluginAdapter): self._fileToExport: str = '' self._fileToImport: str = '' + self._requireActiveFrame = False + def setImportOptions(self) -> bool: """ We do need to ask for the input file names diff --git a/setup.py b/setup.py index 086eefe..21dd260 100644 --- a/setup.py +++ b/setup.py @@ -11,7 +11,7 @@ setup( name="pyutplugincore", - version="0.5.9", + version="0.5.10", author='Humberto A. Sanchez II', author_email='humberto.a.sanchez.ii@gmail.com', maintainer='Humberto A. Sanchez II', diff --git a/tests/scaffoldv2/PluginAdapterV2.py b/tests/scaffoldv2/PluginAdapterV2.py index 0d111e4..14ca8e2 100644 --- a/tests/scaffoldv2/PluginAdapterV2.py +++ b/tests/scaffoldv2/PluginAdapterV2.py @@ -65,7 +65,7 @@ def deselectAllOglObjects(self): wxYield() def addShape(self, shape: OglObjectType): - pass + self._eventEngine.sendEvent(EventType.AddShape, shapeToAdd=shape) def loadProject(self, pluginProject: PluginProject): """ diff --git a/tests/scaffoldv2/ScaffoldFrame.py b/tests/scaffoldv2/ScaffoldFrame.py index 1f2b875..04964c1 100644 --- a/tests/scaffoldv2/ScaffoldFrame.py +++ b/tests/scaffoldv2/ScaffoldFrame.py @@ -43,6 +43,7 @@ from core.types.PluginDataTypes import PluginIDMap from tests.scaffoldv2.PluginAdapterV2 import PluginAdapterV2 +from tests.scaffoldv2.PyutDiagramType import PyutDiagramType from tests.scaffoldv2.ScaffoldUI import ScaffoldUI from tests.scaffoldv2.eventengine.EventEngine import EventEngine from tests.scaffoldv2.eventengine.Events import EventType @@ -100,6 +101,11 @@ def loadXmlFile(self, fqFileName: str): def _createApplicationMenuBar(self): + self._loadXmlFileWxId: int = NewIdRef() + self._newClassDiagramWxId: int = NewIdRef() + self._newUseCaseDiagramWxId: int = NewIdRef() + self._newSequenceDiagramWxId: int = NewIdRef() + menuBar: MenuBar = MenuBar() fileMenu: Menu = Menu() editMenu: Menu = Menu() @@ -115,27 +121,34 @@ def _createApplicationMenuBar(self): self.SetMenuBar(menuBar) - self._loadXmlFileWxId: int = NewIdRef() - self.Bind(EVT_MENU, self.Close, id=ID_EXIT) def _makeFileMenu(self, fileMenu: Menu) -> Menu: fileMenu.Append(self._loadXmlFileWxId, 'Load Xml Diagram') - importSubMenu: Menu = self._makeImportSubMenu() - exportSubMenu: Menu = self._makeExportSubMenu() + newDiagramSubMenu: Menu = self._makeNewDiagramSubMenu() + importSubMenu: Menu = self._makeImportSubMenu() + exportSubMenu: Menu = self._makeExportSubMenu() + fileMenu.AppendSubMenu(newDiagramSubMenu, 'New') fileMenu.AppendSubMenu(importSubMenu, 'Import') fileMenu.AppendSubMenu(exportSubMenu, 'Export') self.Bind(EVT_MENU, self._onLoadXmlFile, id=self._loadXmlFileWxId) return fileMenu - # noinspection PyUnusedLocal - def _onLoadXmlFile(self, event: CommandEvent): + def _makeNewDiagramSubMenu(self) -> Menu: + subMenu: Menu = Menu() - self._displayError(message='Use the import plugin') + subMenu.Append(self._newClassDiagramWxId, 'Class Diagram') + subMenu.Append(self._newUseCaseDiagramWxId, 'Use Case Diagram') + subMenu.Append(self._newSequenceDiagramWxId, 'Sequence Diagram') + + self.Bind(EVT_MENU, self._onNewDiagram, id=self._newClassDiagramWxId) + self.Bind(EVT_MENU, self._onNewDiagram, id=self._newUseCaseDiagramWxId) + self.Bind(EVT_MENU, self._onNewDiagram, id=self._newSequenceDiagramWxId) + return subMenu def _makeToolsMenu(self, toolsMenu: Menu) -> Menu: """ @@ -220,6 +233,17 @@ def _onExport(self, event: CommandEvent): self.logger.info(f'Export: {wxId=}') self._pluginManager.doExport(wxId=wxId) + # noinspection PyUnusedLocal + def _onLoadXmlFile(self, event: CommandEvent): + + self._displayError(message='Use the import plugin') + + def _onNewDiagram(self, event: CommandEvent): + eventId: int = event.GetId() + + if eventId == self._newClassDiagramWxId: + self._eventEngine.sendEvent(EventType.NewDiagram, diagramType=PyutDiagramType.CLASS_DIAGRAM) + def _askForXMLFileToImport(self) -> RequestResponse: """ TODO: This belongs in another class diff --git a/tests/scaffoldv2/ScaffoldUI.py b/tests/scaffoldv2/ScaffoldUI.py index 4cc7b53..d7ba77f 100644 --- a/tests/scaffoldv2/ScaffoldUI.py +++ b/tests/scaffoldv2/ScaffoldUI.py @@ -7,9 +7,9 @@ from logging import Logger from logging import getLogger -from miniogl.SelectAnchorPoint import SelectAnchorPoint -from ogl.OglLink import OglLink -from ogl.OglObject import OglObject +from miniogl.Diagram import Diagram +from ogl.sd.OglSDInstance import OglSDInstance +from ogl.sd.OglSDMessage import OglSDMessage from wx import CLIP_CHILDREN from wx import ClientDC from wx import EVT_TREE_SEL_CHANGED @@ -32,7 +32,10 @@ from wx import Yield as wxYield from miniogl.DiagramFrame import DiagramFrame +from miniogl.SelectAnchorPoint import SelectAnchorPoint +from ogl.OglLink import OglLink +from ogl.OglObject import OglObject from ogl.OglInterface2 import OglInterface2 from core.types.Types import FrameInformation @@ -52,11 +55,14 @@ from tests.scaffoldv2.PyutProject import UmlFrameType from tests.scaffoldv2.eventengine.EventEngine import EventEngine +from tests.scaffoldv2.eventengine.Events import AddShapeEvent from tests.scaffoldv2.eventengine.Events import DeSelectAllShapesEvent -from tests.scaffoldv2.eventengine.Events import EVENT_DESELECT_ALL_SHAPES +from tests.scaffoldv2.eventengine.Events import EVENT_ADD_SHAPE +from tests.scaffoldv2.eventengine.Events import EVENT_DESELECT_ALL_SHAPES from tests.scaffoldv2.eventengine.Events import EVENT_FRAME_INFORMATION from tests.scaffoldv2.eventengine.Events import EVENT_FRAME_SIZE +from tests.scaffoldv2.eventengine.Events import EVENT_NEW_DIAGRAM from tests.scaffoldv2.eventengine.Events import EVENT_REFRESH_FRAME from tests.scaffoldv2.eventengine.Events import EVENT_SELECT_ALL_SHAPES from tests.scaffoldv2.eventengine.Events import EVENT_LOAD_PROJECT @@ -66,6 +72,7 @@ from tests.scaffoldv2.eventengine.Events import FrameSizeEvent from tests.scaffoldv2.eventengine.Events import FrameInformationEvent from tests.scaffoldv2.eventengine.Events import LoadProjectEvent +from tests.scaffoldv2.eventengine.Events import NewDiagramEvent from tests.scaffoldv2.eventengine.Events import NewProjectEvent from tests.scaffoldv2.eventengine.Events import RefreshFrameEvent from tests.scaffoldv2.eventengine.Events import SelectAllShapesEvent @@ -95,13 +102,14 @@ def __init__(self, topLevelFrame: Frame, createEmptyProject: bool = True): self._projectTree: TreeCtrl = cast(TreeCtrl, None) self._notebook: Notebook = cast(Notebook, None) - self._projectsRoot: TreeItemId = cast(TreeItemId, None) - self._projects: PyutProjects = PyutProjects([]) + self._projectsRoot: TreeItemId = cast(TreeItemId, None) + self._projects: PyutProjects = PyutProjects([]) self._initializeUIElements() - self._notebookCurrentPage: int = -1 - self._currentFrame: DiagramFrame = cast(DiagramFrame, None) + self._notebookCurrentPage: int = -1 + self._currentProject: PyutProject = cast(PyutProject, None) + self._currentFrame: UmlDiagramsFrame = cast(UmlDiagramsFrame, None) if createEmptyProject is True: self.createEmptyProject() @@ -131,6 +139,7 @@ def _setEventEngine(self, eventEngine: EventEngine): """ self._eventEngine = eventEngine self._eventEngine.registerListener(EVENT_NEW_PROJECT, self._onNewProject) + self._eventEngine.registerListener(EVENT_NEW_DIAGRAM, self._onNewDiagram) self._eventEngine.registerListener(EVENT_LOAD_PROJECT, self._onLoadProject) self._eventEngine.registerListener(EVENT_SELECT_ALL_SHAPES, self._onSelectAll) self._eventEngine.registerListener(EVENT_DESELECT_ALL_SHAPES, self._onDeSelectAll) @@ -138,6 +147,7 @@ def _setEventEngine(self, eventEngine: EventEngine): self._eventEngine.registerListener(EVENT_REFRESH_FRAME, self._onRefreshFrame) self._eventEngine.registerListener(EVENT_FRAME_SIZE, self._onFrameSize) self._eventEngine.registerListener(EVENT_FRAME_INFORMATION, self._onFrameInformation) + self._eventEngine.registerListener(EVENT_ADD_SHAPE, self._onAddShape) eventEngine = property(fset=_setEventEngine) @@ -206,29 +216,57 @@ def _onLoadProject(self, loadProjectEvent: LoadProjectEvent): pyutProject.projectTreeRoot = projectTreeRoot - # self._treeRoot = self._projectTree.AppendItem(parent=self._projectsRoot, text=projectName, data=pyutProject) - # Add the frames for pluginDocument in pluginProject.pluginDocuments.values(): # document.addToTree(self._tree, self._treeRoot) diagramType: PyutDiagramType = self._toPyutDiagramType(pluginDocument.documentType) - pyutDocument: PyutDocument = PyutDocument(diagramType=diagramType) - pyutDocument.title = pluginDocument.documentTitle - - umlClassDiagramsFrame: UmlClassDiagramsFrame = UmlClassDiagramsFrame(parent=self._notebook) - pyutDocument.diagramFrame = umlClassDiagramsFrame + pyutDocument: PyutDocument = self._newDiagram(diagramType=diagramType) itemId: TreeItemId = self._projectTree.AppendItem(parent=projectTreeRoot, text=pyutDocument.title, data=pyutDocument) self._projectTree.SelectItem(item=itemId, select=True) pyutProject.documents.append(pyutDocument) - self._layoutPluginDocument(pluginDocument=pluginDocument, umlFrame=umlClassDiagramsFrame) + self._layoutPluginDocument(pluginDocument=pluginDocument, umlFrame=pyutDocument.diagramFrame) self._projectTree.Expand(projectTreeRoot) self._addProjectToNotebook(project=pyutProject) self._projects.append(pyutProject) + def _onNewDiagram(self, newDiagramEvent: NewDiagramEvent): + + diagramType: PyutDiagramType = newDiagramEvent.diagramType + self.logger.info(f"{diagramType=}") + + pyutProject: PyutProject = self._currentProject + pyutDocument: PyutDocument = self._newDiagram(diagramType=diagramType) + + projectTreeRoot = pyutProject.projectTreeRoot + + itemId: TreeItemId = self._projectTree.AppendItem(parent=projectTreeRoot, text=pyutDocument.title, data=pyutDocument) + self._projectTree.SelectItem(item=itemId, select=True) + + self._notebook.AddPage(page=pyutDocument.diagramFrame, text=pyutDocument.title) + + pyutProject.documents.append(pyutDocument) + + def _newDiagram(self, diagramType: PyutDiagramType) -> PyutDocument: + """ + Create the appropriate PyutDocument + Args: + diagramType: + + Returns: The PyutDocument + """ + pyutDocument: PyutDocument = PyutDocument(diagramType=diagramType) + pyutDocument.title = 'New Diagram' + + umlClassDiagramsFrame: UmlClassDiagramsFrame = UmlClassDiagramsFrame(parent=self._notebook) + pyutDocument.diagramFrame = umlClassDiagramsFrame + + umlClassDiagramsFrame.Refresh() + return pyutDocument + def _onSelectedOglObjects(self, event: SelectedOglObjectsEvent): selectedObjects = self._currentFrame.GetSelectedShapes() @@ -279,6 +317,21 @@ def _onFrameInformation(self, event: FrameInformationEvent): callback(frameInformation) + def _onAddShape(self, event: AddShapeEvent): + shapeToAdd: OglObject = event.shapeToAdd + + umlFrame: UmlDiagramsFrame = self._currentFrame + + match shapeToAdd: + case OglLink() as shapeToAdd: + self._layoutOglLink(umlFrame=umlFrame, oglLink=cast(OglLink, shapeToAdd)) + case OglSDInstance() as shapeToAdd: + self._layoutOglSDInstance(diagram=umlFrame.getDiagram(), oglSDInstance=cast(OglSDInstance, shapeToAdd)) + case OglSDMessage() as shapeToAdd: + self._layoutOglSDMessage(diagram=umlFrame.getDiagram(), oglSDMessage=cast(OglSDMessage, shapeToAdd)) + case _: + self._layoutAnOglObject(umlFrame=umlFrame, oglObject=shapeToAdd) + def _addProjectToNotebook(self, project: PyutProject) -> bool: success: bool = True @@ -389,7 +442,7 @@ def __syncPageFrameAndNotebook(self, frame): self._notebook.SetSelection(i) break - def _layoutPluginDocument(self, pluginDocument: PluginDocument, umlFrame: UmlFrameShapeHandler): + def _layoutPluginDocument(self, pluginDocument: PluginDocument, umlFrame: UmlDiagramsFrame): """ Loads a plugin's Ogl Objects TODO: Not complete. No sequence diagrams or use cases or OglTexts @@ -420,21 +473,46 @@ def _layoutPluginDocument(self, pluginDocument: PluginDocument, umlFrame: UmlFra for oglSDMessage in pluginDocument.oglSDMessages.values(): self._layoutAnOglObject(umlFrame=umlFrame, oglObject=oglSDMessage) - def _layoutAnOglObject(self, umlFrame: UmlFrameShapeHandler, oglObject: Union[OglObject, OglInterface2, SelectAnchorPoint, OglLink]): - x, y = oglObject.GetPosition() - umlFrame.addShape(oglObject, x, y) - - def _layoutLinks(self, umlFrame: UmlFrameShapeHandler, oglLinks: OglLinks): + def _layoutLinks(self, umlFrame: UmlDiagramsFrame, oglLinks: OglLinks): - umlDiagram = umlFrame.GetDiagram() + # umlDiagram = umlFrame.GetDiagram() for oglLink in oglLinks: - x, y = oglLink.GetPosition() - umlFrame.addShape(oglLink, x=x, y=y) - - if isinstance(oglLink, OglInterface2) is False: - umlDiagram.AddShape(oglLink.sourceAnchor) - umlDiagram.AddShape(oglLink.destinationAnchor) - controlPoints = oglLink.GetControlPoints() - for controlPoint in controlPoints: - umlDiagram.AddShape(controlPoint) + self._layoutOglLink(umlFrame=umlFrame, oglLink=oglLink) + # x, y = oglLink.GetPosition() + # umlFrame.addShape(oglLink, x=x, y=y) + # + # if isinstance(oglLink, OglInterface2) is False: + # umlDiagram.AddShape(oglLink.sourceAnchor) + # umlDiagram.AddShape(oglLink.destinationAnchor) + # controlPoints = oglLink.GetControlPoints() + # for controlPoint in controlPoints: + # umlDiagram.AddShape(controlPoint) + + def _layoutOglLink(self, umlFrame: UmlDiagramsFrame, oglLink: OglLink): + + self._layoutAnOglObject(umlFrame=umlFrame, oglObject=oglLink) + # TODO: + # This is bad mooky here. The Ogl objects were created withing having a Diagram + # The legacy code deserialized the object while adding them to a frame. This + # new code deserializes w/o reference to a frame + # If we don't this the AnchorPoints are not on the diagram and lines ends are not + # movable. + if isinstance(oglLink, OglInterface2) is False: + umlDiagram = umlFrame.GetDiagram() + + umlDiagram.AddShape(oglLink.sourceAnchor) + umlDiagram.AddShape(oglLink.destinationAnchor) + controlPoints = oglLink.GetControlPoints() + for controlPoint in controlPoints: + umlDiagram.AddShape(controlPoint) + + def _layoutOglSDInstance(self, diagram: Diagram, oglSDInstance: OglSDInstance): + diagram.AddShape(oglSDInstance) + + def _layoutOglSDMessage(self, diagram: Diagram, oglSDMessage: OglSDMessage): + diagram.AddShape(oglSDMessage) + + def _layoutAnOglObject(self, umlFrame: UmlFrameShapeHandler, oglObject: Union[OglObject, OglInterface2, SelectAnchorPoint, OglLink]): + x, y = oglObject.GetPosition() + umlFrame.addShape(oglObject, x, y) diff --git a/tests/scaffoldv2/eventengine/EventEngine.py b/tests/scaffoldv2/eventengine/EventEngine.py index 93d43d5..9677b95 100644 --- a/tests/scaffoldv2/eventengine/EventEngine.py +++ b/tests/scaffoldv2/eventengine/EventEngine.py @@ -11,10 +11,14 @@ from core.types.Types import PluginProject from core.types.Types import SelectedOglObjectsCallback +from tests.scaffoldv2.PyutDiagramType import PyutDiagramType +from tests.scaffoldv2.eventengine.Events import AddShapeEvent + from tests.scaffoldv2.eventengine.Events import EventType from tests.scaffoldv2.eventengine.Events import FrameInformationEvent from tests.scaffoldv2.eventengine.Events import FrameSizeEvent from tests.scaffoldv2.eventengine.Events import LoadProjectEvent +from tests.scaffoldv2.eventengine.Events import NewDiagramEvent from tests.scaffoldv2.eventengine.Events import NewProjectEvent from tests.scaffoldv2.eventengine.Events import SelectedOglObjectsEvent from tests.scaffoldv2.eventengine.Events import UpdateTreeItemNameEvent @@ -25,6 +29,8 @@ TREE_ITEM_ID_PARAMETER: str = 'treeItemId' PLUGIN_PROJECT_PARAMETER: str = 'pluginProject' CALLBACK_PARAMETER: str = 'callback' +DIAGRAM_TYPE_PARAMETER: str = 'diagramType' +SHAPE_PARAMETER: str = 'shapeToAdd' class EventEngine(IEventEngine): @@ -53,10 +59,14 @@ def sendEvent(self, eventType: EventType, **kwargs): self._sendLoadProjectEvent(**kwargs) case EventType.NewProject: self._sendNewProjectEvent() + case EventType.NewDiagram: + self._sendNewDiagramEvent(**kwargs) case EventType.SelectAllShapes: self._simpleSendEvent(eventType=eventType) case EventType.DeSelectAllShapes: self._simpleSendEvent(eventType=eventType) + case EventType.AddShape: + self._sendAddShapeEvent(**kwargs) case EventType.RefreshFrame: self._simpleSendEvent(eventType=eventType) case EventType.SelectedOglObjects: @@ -79,6 +89,11 @@ def _sendNewProjectEvent(self): eventToPost: NewProjectEvent = NewProjectEvent() PostEvent(dest=self._listeningWindow, event=eventToPost) + def _sendNewDiagramEvent(self, **kwargs): + diagramType: PyutDiagramType = kwargs[DIAGRAM_TYPE_PARAMETER] + eventToPost: NewDiagramEvent = NewDiagramEvent(diagramType=diagramType) + PostEvent(dest=self._listeningWindow, event=eventToPost) + def _sendLoadProjectEvent(self, **kwargs): pluginProject: PluginProject = kwargs[PLUGIN_PROJECT_PARAMETER] @@ -102,6 +117,11 @@ def _sendFrameInformationEvent(self, **kwargs): eventToPost: FrameInformationEvent = FrameInformationEvent(callback=callback) PostEvent(dest=self._listeningWindow, event=eventToPost) + def _sendAddShapeEvent(self, **kwargs): + shapeToAdd = kwargs[SHAPE_PARAMETER] + eventToPost: AddShapeEvent = AddShapeEvent(shapeToAdd=shapeToAdd) + PostEvent(dest=self._listeningWindow, event=eventToPost) + def _simpleSendEvent(self, eventType: EventType): eventToPost = eventType.commandEvent PostEvent(dest=self._listeningWindow, event=eventToPost) diff --git a/tests/scaffoldv2/eventengine/Events.py b/tests/scaffoldv2/eventengine/Events.py index 0c0f14f..73e92ae 100644 --- a/tests/scaffoldv2/eventengine/Events.py +++ b/tests/scaffoldv2/eventengine/Events.py @@ -10,10 +10,12 @@ # The constructor returns a Tuple; First is the event, The second is the binder # NewProjectEvent, EVENT_NEW_PROJECT = NewEvent() +NewDiagramEvent, EVENT_NEW_DIAGRAM = NewEvent() LoadProjectEvent, EVENT_LOAD_PROJECT = NewEvent() UpdateTreeItemNameEvent, EVENT_UPDATE_TREE_ITEM_NAME = NewEvent() SelectAllShapesEvent, EVENT_SELECT_ALL_SHAPES = NewEvent() -DeSelectAllShapesEvent, EVENT_DESELECT_ALL_SHAPES = NewEvent() +DeSelectAllShapesEvent, EVENT_DESELECT_ALL_SHAPES = NewEvent() +AddShapeEvent, EVENT_ADD_SHAPE = NewEvent() SelectedOglObjectsEvent, EVENT_SELECTED_OGL_OBJECTS = NewEvent() RefreshFrameEvent, EVENT_REFRESH_FRAME = NewEvent() @@ -37,10 +39,12 @@ def __new__(cls, title: str, commandEvent: CommandEvent, binder: PyEventBinder) return obj NewProject = ('NewProject', NewProjectEvent(), EVENT_NEW_PROJECT) + NewDiagram = ('NewDiagram', NewDiagramEvent(), EVENT_NEW_DIAGRAM) LoadProjectEvent = ('LoadProjectEvent', LoadProjectEvent(), EVENT_NEW_PROJECT) UpdateTreeItemName = ('UpdateTreeItemName', UpdateTreeItemNameEvent(), EVENT_UPDATE_TREE_ITEM_NAME) SelectAllShapes = ('SelectAllShapes', SelectAllShapesEvent(), EVENT_SELECT_ALL_SHAPES) DeSelectAllShapes = ('DeSelectAllShapes', DeSelectAllShapesEvent(), EVENT_DESELECT_ALL_SHAPES) + AddShape = ('AddShape', AddShapeEvent(), EVENT_ADD_SHAPE) SelectedOglObjects = ('SelectedOglObjects', SelectedOglObjectsEvent(), EVENT_SELECTED_OGL_OBJECTS) RefreshFrame = ('RefreshFrame', RefreshFrameEvent(), EVENT_REFRESH_FRAME) FrameSize = ('FrameSize', FrameSizeEvent(), EVENT_FRAME_SIZE) diff --git a/tests/scaffoldv2/umlframes/UmlFrame.py b/tests/scaffoldv2/umlframes/UmlFrame.py index 05db495..5184d6e 100644 --- a/tests/scaffoldv2/umlframes/UmlFrame.py +++ b/tests/scaffoldv2/umlframes/UmlFrame.py @@ -27,3 +27,11 @@ def clearDiagram(self): """ self._diagram.DeleteAllShapes() self.Refresh() + + def getDiagram(self): + """ + Returns this frame's diagram + + Returns: wx.Diagram + """ + return self._diagram