Skip to content

Pyut Plugin Development

Humberto Sanchez II edited this page Jan 15, 2025 · 2 revisions

Pyut Plugin Development

Introduction

Developing a plugin is the easiest way to enhance Pyut functionality. Developers can extend the types of data Pyut can export and the types of data or documents it can produce. Additionally, Pyut plugins can extend the functionality and behavior of the editor.

Plugin Types

Developers implement a particular interface depending on the type behavior or input/output that a developer wishes to implement.

Plugin Adapter

In order to keep the plugins loosely coupled from the Pyut internals, plugins request information and data from Pyut via a Plugin Adapter. The following diagram shows the class diagram depiction.

Notice that various methods require a callback. Again in order to loosely couple the plugins from Pyut the PluginManager sends request events to Pyut. Pyut responds by supplying the information via a parameter on the callback.

classDiagram
    direction RL
    %% Links follow
    IPluginAdapter  --  ScreenMetrics : 
    class ScreenMetrics { 
        +int screenWidth
        +int screenHeight
        +int dpiX
        +int dpiY
    }
    class IPluginAdapter { 
        +str pyutVersion
        +ScreenMetrics screenMetrics
        +str currentDirectory
        + __init__()
        + getFrameSize(callback)
        + getFrameInformation(callback)
        + getSelectedOglObjects(callback)
        + getObjectBoundaries(callback)
        + refreshFrame()
        + selectAllOglObjects()
        + deselectAllOglObjects()
        + addShape(shape)
        + loadProject(pluginProject)
        + requestCurrentProject(callback)
        + indicatePluginModifiedProject()
        + deleteLink(oglLink)
        + createLink(linkInformation, callback)
    }
Loading

Tool Plugins

Tool plugins are the simplest to write. Essentally, they manipulate the current UML frame.

Developers implement a Pyut Tool by creating a class that implements ToolPluginInterface. The developer fills in the code in the .doAction() method. If the plugin requires some intervention prior to executing the developer implements that code in the .setOptions() method. For example, the plugin may ask a question or present a dialog of options to set prior to execution. If the method returns False the PluginManager assumes the request was cancelled.

classDiagram
    direction RL
    %% Links follow
    BasePluginInterface<|--ToolPluginInterface
    class ToolPluginInterface { 
        +str menuTitle
        + __init__(pluginAdapter)
        + executeTool()
        +bool setOptions()
        + doAction()
    }
    class BasePluginInterface { 
        +PluginName name
        +str author
        +str version
        +InputFormat inputFormat
        +OutputFormat outputFormat
        + __init__(pluginAdapter)
        + displayNoUmlFrame(cls)
        + displayNoSelectedOglObjects(cls)
        +SingleFileRequestResponse askForFileToImport(startDirectory)
        +MultipleFileRequestResponse askToImportMultipleFiles(startDirectory)
        +SingleFileRequestResponse askForFileToExport(defaultFileName, defaultPath)
        +ImportDirectoryResponse askForImportDirectoryName()
        +ExportDirectoryResponse askForExportDirectoryName(preferredDefaultPath)
        # _layoutUmlClasses(oglClasses)
        # _layoutLinks(oglLinks)
        -str __composeWildCardSpecification()
    }
Loading

Input/Output Plugins

I/O plugins are more complex to author. Their purpose is to allow import of external data that can be transformed into a UML diagram. Conversely, the plugin may export Pyut UML diagrams into an external format.

To export Pyut UML objects to a different format the developer implements the .write() method. To import some external data and create Pyut UML objects the developer implements the .read() method. If the developer needs additional information from the end user prior to the .write() method he should implement the .setExportOptions() method. Conversely, implement the .setImportOptions() method to get additional information prior to the .read() method.

The developer can choose to implement either of the methods or both if appropriate. Note that the .write() and .read() methods return a boolean value that indicates success or failure. The Plugin Manager determines what type of plugin the developer implemented based on whether the .inputFormat or .outputFormat properties return non-null values.

classDiagram
    direction RL
    %% Links follow
    BasePluginInterface<|--IOPluginInterface
    class BasePluginInterface { 
        +PluginName name
        +str author
        +str version
        +InputFormat inputFormat
        +OutputFormat outputFormat
        + __init__(pluginAdapter)
        + displayNoUmlFrame(cls)
        + displayNoSelectedOglObjects(cls)
        +SingleFileRequestResponse askForFileToImport(startDirectory)
        +MultipleFileRequestResponse askToImportMultipleFiles(startDirectory)
        +SingleFileRequestResponse askForFileToExport(defaultFileName, defaultPath)
        +ImportDirectoryResponse askForImportDirectoryName()
        +ExportDirectoryResponse askForExportDirectoryName(preferredDefaultPath)
        # _layoutUmlClasses(oglClasses)
        # _layoutLinks(oglLinks)
        -str __composeWildCardSpecification()
    }
    class IOPluginInterface { 
        + __init__(pluginAdapter)
        + executeImport()
        # _executeImport(frameInformation)
        + executeExport()
        # _executeExport(frameInformation)
        +bool setImportOptions()
        +bool setExportOptions()
        +bool read()
        + write(oglObjects)
    }
Loading