Langages de modélisation¶
Depuis la version 2.0, Gaphor supporte le concept de langages de modélisation. Cela permet de développer des langages de modélisation distincts de l’application principale de Gaphor.
Le langage principal était et reste UML. Gaphor prend désormais également en charge un sous-ensemble de SysML, RAAML et le modèle C4.
Un langage de modélisation dans Gaphor est défini par une classe implémentant la classe de base abstraite gaphor.abc.ModelingLanguage. Le langage de modélisation doit être enregistré en tant que point d’entrée gaphor.modelinglanguages.
L’interface ModelingLanguage (Langage de modélisation) est assez minimale. Elle permet à d’autres services de rechercher des éléments et des éléments de diagramme, ainsi qu’une boîte à outils et des types de diagramme. Cependant, les responsabilités d’un langage de modélisation ne s’arrêtent pas là. Certaines fonctionnalités seront mises en œuvre en enregistrant des gestionnaires pour un ensemble de fonctions génériques.
Mais n’allons pas trop vite en besogne. Quelles fonctionnalités une implémentation de langage de modélisation peut-elle offrir ?
Trois fonctionnalités sont exposées par une instance de ModelingLanguage :
Un modèle de données (éléments) et des éléments de diagramme
Types de diagrammes
Une définition de la boîte à outils
D’autres fonctionnalités peuvent être étendues en ajoutant des gestionnaires aux fonctions génériques correspondantes :
Connecteurs, permet de connecter des éléments de diagramme
Formater/analyser modéliser des éléments vers et à partir d’une représentation textuelle
Comportement de copier/coller lorsque la copie d’un élément n’est pas triviale, par exemple lorsque plusieurs éléments sont impliqués
Regroupement, permet d’imbriquer les éléments les uns dans les autres
Dropping, permet de faire glisser des éléments de l’arborescence sur un diagramme
Règles de nettoyage automatique pour maintenir la cohérence du modèle
Les langages de modélisation peuvent également fournir de nouveaux composants d’interface utilisateur. Ces composants ne sont pas chargés directement lors de l’importation d’un paquetage de langage de modélisation. Ils doivent être importés via le point d’entrée gaphor.modules.
Pages de l’éditeur, affichées dans le volet rétractable de droite
Fenêtres contextuelles instantanées de l’éditeur (de diagrammes)
Interactions avec les diagrammes spéciaux
Langue de modélisation¶
- class gaphor.abc.ModelingLanguage[source]¶
Un fournisseur de modèle est un service spécialisé qui fournit un point d’entrée pour l’implémentation d’un modèle, comme UML, SysML ou RAAML.
- abstract property diagram_types: Iterable[DiagramType]¶
Diagrammes types.
- abstract property element_types: Iterable[ElementCreateInfo]¶
Itérer les types d’éléments.
- abstractmethod lookup_element(name: str, ns: str | None = None) type[Base] | None[source]¶
Rechercher un élément de modèle par son nom de classe.
Un nom de domaine peut être fourni. Cela permettra au modèle d’être chargé uniquement à partir de ce langage de modélisation spécifique.
- abstract property model_browser_model: type[TreeModel]¶
Un modèle à utiliser dans le navigateur de modèles.
- abstract property toolbox_definition: ToolboxDefinition¶
Structurer la boîte à outils.
Par convention, le paquet contenant le langage de modélisation doit avoir un attribut __modeling_language__ dont la valeur est identique à celle du nom du langage de modélisation dans le point d’entrée.
En guise d’illustration :
Le fichier mytool/mylang/__init__.py contient une entrée :
__modeling_language__ = "MyLang"
pyproject.toml contient un point d’entrée :
[project.entry-points."gaphor.modelinglanguages"]
"MyLang" = "mytool.mylang.modelinglanguage:MyLangModelingLanguage"
Connecteurs¶
Les connecteurs sont utilisés pour relier un élément à un autre.
Les connecteurs doivent respecter le protocole ConnectorProtocol. Normalement, vous héritez de BaseConnector.
- class gaphor.diagram.connectors.BaseConnector(element: Presentation[Base], line: Presentation[Base])[source]¶
Adaptateur de connexion pour les éléments du diagramme Gaphor.
L’élément ligne
linese connecte avec une poignée à un élément connectableelement.- Paramètres:
line – élément de connexion
element – élément connectable
Par convention, les adaptateurs sont enregistrés par (élément, ligne) – dans cet ordre.
- allow(handle: Handle, port: Port) bool[source]¶
Détermine si les éléments peuvent être connectés.
La connexion est-elle toujours autorisée, par exemple lorsque la souris se déplace ?
Retourne
Truesi la connexion est autorisée.
- connect(handle: Handle, port: Port) bool[source]¶
Se connecter à un élément.
Établir une connexion entre l’élément et la ligne. Prend également en charge les déconnexions, si nécessaire (par exemple, pour les relations 1:1).
Notez qu’à ce stade, la ligne peut être connectée à un autre élément ou au même élément. La connexion au niveau du modèle reste valide.
Retourne
Truesi une connexion est établie.
Formater et analyser¶
Les éléments de modèle peuvent être représentés sous forme textuelle. Par exemple, le navigateur de modèles utilise cette fonctionnalité. Il ne s’agit toutefois pas d’une conversion complète de l’élément de modèle.
Dans certains cas, il peut être utile d’analyser le texte afin de le réintégrer dans un objet. C’est notamment le cas lorsque l’on modifie les attributs et les opérations d’une classe.
Chaque format() n’a pas besoin d’avoir une fonction parse() équivalente.
- gaphor.core.format.format(element: Element) str¶
Il renvoie une représentation lisible de l’élément de modèle. Dans la plupart des cas, il s’agit simplement du nom, mais les propriétés (attributs) et les opérations sont présentées de manière plus détaillée :
+ attr: str + format(element: Element): string
Copier et coller¶
Le copier-coller fonctionne immédiatement pour des éléments simples, comme un élément de diagramme avec un élément de modèle (le subject). Il s’appuie sur les méthodes load() et save() des éléments pour s’assurer que toutes les données pertinentes sont copiées.
Parfois, certains éléments ont besoin de plus d’un élément du modèle pour fonctionner. Une association, par exemple, a deux extrémités.
Dans ces cas spécifiques, vous devez implémenter vos propres fonctions de copier-coller. Pour ce faire, vous devez créer deux fonctions : l’une pour copier et l’autre pour coller.
- gaphor.diagram.copypaste.copy(obj: Base | Iterable) Iterator[tuple[Id, Opaque]]¶
Créer une copie d’un élément (ou d’une liste d’éléments). Le type de retour doit être distinct afin que la fonction
paste()puisse être correctement distribuée. Une fonction de copie ne copie normalement que l’élément et les éléments connexes obligatoires. Par exemple, une association a besoin de deux extrémités.
- gaphor.diagram.copypaste.paste(copy_data: Opaque, diagram: Diagram, lookup: Callable[[str], Base | None]) Iterator[Base]¶
Collez les données précédemment recopiées. Dupliquez les éléments copiés en fonction du type de données créé dans la fonction
copy(). Renvoie l’élément nouvellement créé.
Gaphor fournit quelques fonctions de confort :
- gaphor.diagram.copypaste.copy_full(items: Collection[Base], lookup: Callable[[Id], Base | None] | None = None) CopyData:¶
Copier
items. La fonctionlookupest utilisée pour rechercher les éléments possédés (affichés comme des noeuds enfants dans le navigateur de modèle).
Regroupement¶
Le regroupement s’effectue en faisant glisser un élément sur un autre, dans un diagramme ou dans l’arborescence.
- gaphor.diagram.group.owner(element: Base) Base | RootType | None¶
Retourne le propriétaire de l’élément. Il peut s’agir de
Root, indiquant que l’élément doit être placé à la racine de la hiérarchie de propriété. Si None est retourné, il n’y a pas de propriétaire.
- gaphor.diagram.group.owns(element: Base) list[Base]¶
Retourne tous les éléments appartenant à `element
- gaphor.diagram.group.group(parent: Base, element: Base) bool¶
Un élément peut être regroupé dans un élément parent. Ce regroupement peut être basé sur la propriété, mais d’autres types de regroupement sont également possibles.
Dépose¶
Le dépôt s’effectue en faisant glisser un élément de l’arborescence et en le déposant sur un diagramme. Il s’agit d’un moyen facile d’ajouter des éléments de modèle déjà existants à un diagramme.
Il est également possible de déposer un élément de présentation au-dessus d’un autre élément.
- gaphor.diagram.drop.drop(element: Base | Presentation, diagram: Diagram | Presentation, x: float, y: float) Presentation | None¶
La fonction « drop » crée une nouvelle présentation pour un élément du diagramme qui n’en est pas encore une. Pour les relations, un dépôt ne fonctionne que si les deux éléments connectés sont présents dans le même diagramme.
Alors que le regroupement permet d’articuler les éléments du modèle, le dépôt permet de créer et de placer les éléments de présentation au bon endroit dans un diagramme.
Nettoyage automatisé des modèles¶
Gaphor souhaite maintenir le modèle synchronisé avec les diagrammes.
Une petite fonction d’envoi permet de déterminer si un élément du modèle peut être retiré.
Pages de l’éditeur de propriétés¶
La page de l’éditeur est composée d’extraits. Par exemple, presque chaque élément a un nom, et un élément d’interface utilisateur vous permet donc d’éditer un nom.
Chaque page de propriété (snippet) doit hériter de PropertyPageBase.
Fenêtres contextuelles instantanées de l’éditeur (de diagrammes)¶
Lorsque vous double-cliquez sur un élément d’un diagramme, une fenêtre contextuelle peut s’afficher, ce qui vous permet de modifier facilement le nom.
Par défaut, cela fonctionne pour tout élément nommé. Vous pouvez enregistrer votre propre fonction d’édition en ligne si nécessaire.
- gaphor.diagram.instanteditors.instant_editor(item: Item, view, event_manager: EventManager, pos: tuple[int, int] | None = None) bool¶
Affiche une petite fenêtre d’édition dans le diagramme. Permet de faciliter l’édition sans avoir recours à l’éditeur d’éléments.
Dans le cas d’un clic de la souris, la position de la souris (par rapport à l’élément) est également fournie.