Lenguajes de modelado

Desde la versión 2.0, Gaphor soporta el concepto de lenguajes de modelado. Esto permite el desarrollo de lenguajes de modelado independientes de la aplicación central de Gaphor.

El lenguaje principal era y será UML. Ahora Gaphor también admite un subconjunto de SysML, RAAML y el modelo C4.

A modeling language in Gaphor is defined by a class implementing the gaphor.abc.ModelingLanguage abstract base class. The modeling language should be registered as a gaphor.modelinglanguages entry point.

La interfaz ModelingLanguage es bastante mínima. Permite que otros servicios busquen elementos y elementos de diagramas, así como una caja de herramientas y tipos de diagramas. Sin embargo, las responsabilidades de un lenguaje de modelado no terminan ahí. Partes de la funcionalidad se implementarán mediante el registro de manejadores a un conjunto de funciones genéricas.

Pero no nos adelantemos. ¿Cuál es la funcionalidad que puede ofrecer la aplicación de un lenguaje de modelado?

Three functionalities are exposed by a ModelingLanguage instance:

  • Un modelo de dato (elementos) y elementos de esquema

  • Tipos de diagramas

  • Una definición de caja de herramientas

Other functionalities can be extended by adding handlers to the respective generic functions:

  • Conectores, permite conectar elementos del diagrama

  • Format/parse model elements to and from a textual representation

  • Comportamiento Copiar/pegar cuando la copia de elementos no es trivial, por ejemplo, cuando hay más de un elemento implicado

  • Agrupación, permite anidar elementos entre sí

  • Dropping, permitir que los elementos se arrastren desde la vista de árbol a un diagrama

  • Reglas de limpieza automática para mantener la coherencia del modelo

Modeling languages can also provide new UI components. Those components are not loaded directly when you import a modeling language package. Instead, they should be imported via the gaphor.modules entrypoint.

Modeling language

class gaphor.abc.ModelingLanguage[fuente]

Un proveedor de modelos es un servicio especial que proporciona un punto de entrada a una implementación de modelo, como UML, SysML, RAAML.

abstract property diagram_types: Iterable[DiagramType]

Iterar tipos de diagramas.

abstract property element_types: Iterable[ElementCreateInfo]

Iterate element types.

abstractmethod lookup_element(name: str, ns: str | None = None) type[Base] | None[fuente]

Buscar un tipo de elemento del modelo por nombre (de clase).

A namespace may be provided. This will allow the model to be loaded from that specific modeling language only.

abstract property model_browser_model: type[TreeModel]

A model for use in the Model Browser.

abstract property name: str

Nombre legible del lenguaje de modelado.

abstract property toolbox_definition: ToolboxDefinition

Obtener estructura para la caja de herramientas.

As a convention, the package containing the modeling language should have an attribute __modeling_language__ that has the same value as the modeling language name in the entry point.

To illustrate:

The file mytool/mylang/__init__.py contains an entry:

__modeling_language__ = "MyLang"

pyproject.toml contains an entry point:

[project.entry-points."gaphor.modelinglanguages"]
"MyLang" = "mytool.mylang.modelinglanguage:MyLangModelingLanguage"

Conectores

Los conectores sirven para unir un elemento con otro.

Los conectores deben adherirse al ConnectorProtocol. Normalmente se hereda de BaseConnector.

class gaphor.diagram.connectors.BaseConnector(element: Presentation[Base], line: Presentation[Base])[fuente]

Adaptador de conexión para elementos del diagrama Gaphor.

El elemento de línea line se conecta con un manejador a un elemento conectable element.

Parámetros:
  • line – elemento de conexión

  • element – elemento conectable

Por convención, los adaptadores se registran por (elemento, línea) – en ese orden.

allow(handle: Handle, port: Port) bool[fuente]

Determina si los elementos pueden conectarse.

Is the connection allowed at all (during mouse movement for example)?

Devuelve True si la conexión está permitida.

connect(handle: Handle, port: Port) bool[fuente]

Connect to an element.

Establish a connection between element and line. Also takes care of disconnects, if required (e.g. 1:1 relationships).

Note that at this point the line may be connected to some other, or the same element. The connection at model level also still exists.

Devuelve True si se ha establecido una conexión.

disconnect(handle: Handle) None[fuente]

Desconecte las conexiones de nivel de modelo.

Break connection, called when dropping a handle on a point where it can not connect.

get_connected(handle: Handle) Presentation[Base] | None[fuente]

Obtener elemento conectado a un manejador.

Format and parse

Model elements can be formatted to a simple text representation. For example, This is used in the Model Browser. It isn’t a full serialization of the model element.

In some cases it’s useful to parse a text back into an object. This is done when you edit attributes and operations on a class.

Not every format() needs to have an equivalent parse() function.

gaphor.core.format.format(element: Element) str

Returns a human readable representation of the model element. In most cases this is just the name, however, properties (attributes) and operations are formatted more extensively:

+ attr: str
+ format(element: Element): string
gaphor.core.format.parse(element: Element, text: str) None

Parse text and populate element. The element is populated with elements from the text. This may mean that new model elements are created as part of the parse process.

Copiar y pegar

Copy and paste works out of the box for simple items: one diagram item with one model element (the subject). It leverages the load() and save() methods of the elements to ensure all relevant data is copied.

A veces los elementos necesitan más de un elemento del modelo para funcionar. Por ejemplo una asociación: tiene dos extremos de asociación.

En esos casos específicos necesita implementar sus propias funciones de copiar y pegar. Para crear algo así necesitará crear dos funciones: una para copiar y otra para pegar.

gaphor.diagram.copypaste.copy(obj: Base | Iterable) Iterator[tuple[Id, Opaque]]

Create a copy of an element (or list of elements). The returned type should be distinct, so the paste() function can properly dispatch. A copy function normally copies only the element and mandatory related elements. E.g. an Association needs two association ends.

gaphor.diagram.copypaste.paste(copy_data: Opaque, diagram: Diagram, lookup: Callable[[str], Base | None]) Iterator[Base]

Paste previously copied data. Based on the data type created in the copy() function, try to duplicate the copied elements. Returns the newly created item or element.

Gaphor provides some convenience functions:

gaphor.diagram.copypaste.copy_full(items: Collection[Base], lookup: Callable[[Id], Base | None] | None = None) CopyData:

Copy items. The lookup function is used to look up owned elements (shown as child nodes in the Model Browser).

Paste a copy of the Presentation element to the diagram, but try to link the underlying model element. A shallow copy.

gaphor.diagram.copypaste.paste_full(copy_data: CopyData, diagram: Diagram) set[~gaphor.core.modeling.Presentation]:

Paste a copy of both Presentation and model element. A deep copy.

Agrupación

La agrupación se realiza arrastrando un elemento sobre otro, en un diagrama o en la vista en árbol.

gaphor.diagram.group.owner(element: Base) Base | RootType | None

Return the owner for element. The owner may be Root, denoting the element should be placed in the root of the ownership hierarchy. If None is returned, there is no owner.

gaphor.diagram.group.owns(element: Base) list[Base]

Returns all elements owned by `element

gaphor.diagram.group.group(parent: Base, element: Base) bool

Agrupa un elemento en un elemento padre. La agrupación puede basarse en la propiedad, pero también son posibles otros tipos de agrupación.

gaphor.diagram.group.ungroup(parent: Base, element: Base) bool

Elimina la agrupación de un elemento. La función necesita comprobar si el nodo parent proporcionado es el correcto.

gaphor.diagram.group.can_group(parent_type: type[Base], element_or_type: type[Base] | Base) bool

Esta función intenta determinar si la agrupación es posible, sin realizar realmente una operación de agrupación. Esto no es 100% preciso.

Soltando

El soltado se realiza arrastrando un elemento desde la vista de árbol y soltándolo en un diagrama. Se trata de una forma sencilla de ampliar un diagrama con elementos de modelo ya existentes.

Alternatively, a presentation item can be dropped on top of another element.

gaphor.diagram.drop.drop(element: Base | Presentation, diagram: Diagram | Presentation, x: float, y: float) Presentation | None

The drop function creates a new presentation for an element on the diagram, if the element is not a presentation yet. For relationships, a drop only works if both connected elements are present in the same diagram.

While grouping deals with connecting model elements, dropping deals with creating and placing presentation elements on the right item in a diagram.

Limpieza automática de modelos

Gaphor quiere mantener el modelo sincronizado con los diagramas.

Se usa una pequeña función de envío para determinar si se puede eliminar un elemento del modelo.

gaphor.diagram.deletable.deletable(element: Base) bool

Determina si un elemento del modelo puede eliminarse con seguridad.

Property Editor pages

La página del editor se construye a partir de fragmentos. Por ejemplo: casi todos los elementos tienen un nombre, por lo que hay un fragmento de IU que permite editar un nombre.

Cada página de propiedades (fragmento) debe heredar de PropertyPageBase.

class gaphor.diagram.propertypages.PropertyPageBase[fuente]

Una página de propiedades que puede mostrarse en un cuaderno.

close() None[fuente]

Called when a property page is removed.

This allows us to clean up.

abstractmethod construct() Gtk.Widget | None[fuente]

Crea la página (Gtk.Widget) que pertenece a la página propiedad.

Devuelve el widget de nivel superior de la página (Gtk.Widget).

Ventanas emergentes instantáneas del editor (de diagramas)

When you double-click on an item in a diagram, a popup can show up, so you can easily change the name.

By default, this works for any named element. You can register your own inline editor function if you need to.

gaphor.diagram.instanteditors.instant_editor(item: Item, view, event_manager: EventManager, pos: tuple[int, int] | None = None) bool

Muestra una pequeña ventana emergente del editor en el diagrama. Facilita la edición sin recurrir al editor de elementos.

En el caso de un evento de pulsación del ratón, también se proporciona la posición del ratón (relativa al elemento).