Quick links: Tutorial - Examples - Files - Symbols.
Classes: Hierarchy - Index - List - Members.
Namespaces: Index - base - cs - display.

Graph drawing

This section has not been translated yet, but graph drawing operations of Cogitant has been superseded by CoGui.

Les classes de dessin (espace de nom cogitantdisplay) permettent de dessiner les objets du modèle et d'éditer ces objets. Ces classes ne sont pas spécifiques à l'édition de graphes conceptuels avec une bibliothèque graphique donnée. Au contraire, elles peuvent permettre de dessiner / éditer différents objets tels que des supports, des graphes, des règles, en utilisant plusieurs bibliothèques (QT, wxWidgets, Java, etc.). Pour l'instant seul le dessin / édition de graphes conceptuels est disponible, en utilisant la bibliothèque Java (testé avec le J2SDK 1.5.0 et 1.6.0 sous Linux et Windows) (http://java.sun.com), wxWidgets (testé avec la version 2.6.1 sous Linux et Windows) (http://www.wxwidgets.org).

Il est à noter que ces classes n'ont pas pour objectif de fournir un éditeur "complet", mais simplement de pouvoir intégrer facilement des fonctions d'affichage et d'édition de graphes conceptuels dans une application développée à l'aide de Cogitant. Pour disposer d'un éditeur beaucoup plus complet, permettant d'éditer supports, graphes et règles, il est conseillé de regarder du côté de CoGui (http://www.lirmm.fr/cogui).

Compilation

Cette section détaille la compilation de la bibiliothèque pour utiliser les classes de dessin. Il est à noter que pour utiliser l'interfacage Java, le J2SDK doit être installé (et non pas uniquement une machine virtuelle) car la compilation de Cogitant requiert des fichiers header fournis avec le J2SDK qui permettent l'interfacage entre C++ et Java. La bibliothèque doit être compilée avec des options particulières afin que les fonctions de dessin soient disponibles.

Avec un script configure (Unix, Cygwin, Mingw)

Dans le cas où la bibliothèque est compilée suite à un appel au script configure, il est nécessaire de passer l'option –enable-dp au script de configuration (classes génériques de dessin). Ensuite, selon la bibliothèque graphique utilisée, il faut utiliser des options différentes :

La configuration de Cogitant pourra se faire avec une commande du type :

./configure --enable-dp --enable-dpjava --with-jdk=/usr/local/jdk1.5.0

ou

./configure --enable-dp --enable-wx

Il est évidemment possible de compiler Cogitant en utilisant Java et wxWidgets. Quand le script de configuration a terminé son travail, lancer la compilation de la façon habituelle par un simple make. Il est à noter que sous Debian, le j2sdk n'est pas installé dans /opt ou dans /usr/local mais dans un répertoire particulier de /usr/lib. On lancera alors la configuration de Cogitant avec un paramètre du type –with-jdk=/usr/lib/jvm/java-6-sun.

Avec Cmake (MS Windows, Unix)

Dans le cas où Cogitant est compilée avec Cmake, que ce soit sous Unix ou sous Windows, il suffit de définir les variables de configuration Cmake WithDisplay et withDisplay_wxWidgets à ON dans l'interface de Cmake (ou en ligne de commande, sous Unix). Pour l'instant seule l'utilisation de wxWidgets est possible dans le cas où Cogitant est compilée par Cmake. Vous pouvez aussi consulter la documentation de wxWidgets pour plus d'informations.

Exemple

Afin de vérifier si la compilation s'est correctement déroulée, il est possible d'exécuter l'exemple d'affichage d'un graphe dans une fenêtre gérée par Java. Cet exemple réside dans samples/javadisplay. Sous Unix, il est compilé par défaut. Sous Windows, taper make -fmakefile.b32 dans ce répertoire pour lancer la compilation. Notez que le source de cet exemple est un simple fichier Java. Avant d'exécuter cet exemple, sous Windows, il faut s'assurer que les bibliothèques indispensables sont accessibles (copiez cogitant.dll et cc32x0mt.dll dans samples/javadisplay). Pour exécuter l'exemple, tapez make run sous Unix et make -fmakefile.b32 run sous Windows.

Pour tester les classes d'interfacage avec wxWidgets, vous pouvez utiliser l'exemple situé dans samples/wxdisplay, qui est un mini éditeur de graphes conceptuels.

Dessin

L'objectif lors du développement de ces classes de dessin était de concevoir une méthode la plus générique possible, afin de réutiliser les classes pour afficher autre chose que des graphes conceptuels (supports, projection, ou tout à fait autre chose) de différentes façons (en utilisant qt, gtk+, l'api Java, ou d'autres bibliothèques graphiques, ou divers formats de fichiers graphiques). L'architecture qui a été conçue est donc composée de plusieurs classes, chacune de ces classes étant affectée à une partie du mécanisme de dessin. Ces classes sont ensuite spécialisées pour fournir un dessin de graphes conceptuels, en utilisant l'API Java.

Objets pouvant être dessinés

Les fonctions de dessin ont pour objectif d'être génériques. C'est pourquoi ce n'est pas directement un cogitant::Graph qui peut être parcouru pour être dessiné, mais une autre classe offrant des fonctions de parcours. En effet, quel que soit l'objet à dessiner, il est toujours nécessaire de parcourir les différents éléments de cet objet et d'afficher chacun de ces éléments (sommets d'un graphe, types d'un support, sommets et liens de coréference d'une règle, etc.). Ainsi, un dessin se fait toujours à partir d'une instance de la classe cogitantdisplay::Drawing. Cette classe abstraite est une interface permettant d'avoir une vue sur un objet pouvant être dessiné. Plus précisément, cette classe offre des méthodes permettant de parcourir les différents éléments (cogitantdisplay::Drawing::Element) qui composent un objet pouvant être dessiné. Dans le cas du dessin d'un graphe conceptuel, ces éléments seront les sommets et les arêtes du graphe (ainsi que les emboîtements et graphes internes, selon une structuration semblable à celle de cogitant::Graph). Plus précisément, le parcours s'effectue à l'aide d'itérateurs (cogitantdisplay::Drawing::Iterator) qui permettent de parcourir les éléments, de différentes façons (fils d'un élément donné, parents, etc.). Pour chaque élément, des méthodes permettent à l'opération de dessin de déterminer la figure qui doit être affichée (cogitantdisplay::Drawing::getStyle(), cogitantdisplay::Drawing::getLabel(), etc.). Pour définir le dessin d'un nouveau type d'objets, il est donc nécessaire de définir une sous-classe de cogitantdisplay::Drawing et de redéfinir les méthodes de parcours (pour obtenir une structure correspondant à celle de l'objet à dessiner) et les méthodes de détermination de la figure à afficher. La classe cogitantdisplay::DrawingGraph, dont le constructeur prend comme paramètre un (pointeur sur un) cogitant::Graph, permet de dessiner un graphe conceptuel. Plus précisément, les fonctions de parcours ont été redéfinies et permettent de parcourir les cogitant::GraphObject composant le graphe, et les méthodes de détermination de la figure correspondant à un élément donné ont été adaptées (un rectangle doit être affiché pour un sommet concept, etc.)
Dans le cas de graphes conceptuels, les coordonnées des sommets sont stockées dans les propriétés des cogitant::GraphObject. Cependant, dans certains cas, ces coordonnées sont absentes (graphe généré automatiquement, ou sans coordonnées). Une classe est fournie avec Cogitant et offre une opération de "rangement" des éléments d'un dessin. Là encore, cette classe, cogitantdisplay::OperationLayout, est générique et peut être spécialisée de différentes façons, selon le dessin à ranger. Une sous-classe adaptée aux graphes conceptuels (cogitantdisplay::OperationGraphLayout) est fournie. Cette classe se contente d'utiliser la bipartition des graphes conceptuels pour ranger les sommets (les sommets concepts sont rangés les uns sous les autres, idem pour les sommets relations).

Primitives d'affichage

Pour dessiner des objets quelconques (graphes conceptuels par exemple), il est nécessaire, à partir des objets à dessiner, de déterminer quelles figures élémentaires (ligne, texte, rectangle, etc.) doivent être dessinées, à quels emplacements elles doivent être dessinées, avec quels attributs (couleur, police, etc.) et quelles sont les relations entre ces figures (lien entre une ligne (arête) et un rectangle (sommet concept), appartenance entre un rectangle (sommet concept) et un rectangle (emboîtement contenant le sommet concept)). Toutes les primitives permettant de créer ces figures élémentaires sont dans la classe représentant un contexte d'affichage cogitantdisplay::Context. Cette classe contient aussi des méthodes générales pour calculer l'intersection entre un segment et un rectangle, un segment et une ellipse et autres méthodes du même ordre. Mais les principales méthodes pour le dessin sont celles qui permettent de rajouter à un contexte d'affichage des figures. Ainsi, une opération de dessin consistera à créer des figures associées au contexte par cogitantdisplay::Context::newFigure() et à modifier ces figures à l'aide de la méthode cogitantdisplay::Context::figure(). Pour cela, on utilisera la valeur de retour de newFigure() qui est un entier identifiant de façon unique une figure. La méthode figure() permet elle d'accéder à une figure à partir de son identificateur. Une figure est en fait une instance de la classe cogitantdisplay::Figure. Cette classe contient des membres permettant de représenter les coordonnées (cogitantdisplay::Figure::m_coords), le style (cogitantdisplay::Figure::m_style : rectangle, ligne, ellipse, texte), le pinceau utilisé pour le dessin (couleur, épaisseur et style du trait), la brosse (motif et couleur du fond), et la police (couleur, taille, style) dans le cas d'un texte.

C'est la classe cogitantdisplay::OperationDraw qui se charge d'interroger un cogitantdisplay::Drawing pour récupérer toutes les informations correspondant à un élément pour créer une Figure dans un Context, et modifier les différents attributs de la figure pour représenter l'élément.

Affichage de bas niveau

Une fois que les figures ont été déterminées, et stockées dans le Context, il est nécessaire de les afficher. L'objectif étant d'écrire des classes génériques, ces fonctions d'affichage de bas niveau ont été isolées dans une classe spécifique : cogitantdisplay::Output. De cette façon, pour utiliser une nouvelle bibliothèque graphique, il suffit d'écrire une sous-classe de Output, et de redéfinir les méthodes abstraites cogitantdisplay::Output::drawSimpleFigure() (dessin d'un rectangle ou d'une ellipse), cogitantdisplay::Output::drawSimpleLine() et cogitantdisplay::Output::drawSimpleText(). Ainsi les fonctions génériques d'affichage sont dans cogitantdisplay::Context et les fonctions spécifiques à une bibliothèque d'affichage dans cogitantdisplay::Output. La classe cogitantdisplay::Output_Java est justement une sous classe de Output et se charge d'afficher les figures en utilisant les primitives d'affichage de l'API Java à l'aide de JNI. À partir des figures associées à un contexte, il est possible de lancer l'affichage en utilisant la méthode cogitantdisplay::Context::drawFigures(). Cette méthode prend comme paramètre un pointeur sur une instance (d'une sous classe) de Output, et appelle les bonnes méthodes de Output pour dessiner les éléments graphiques correspondant aux figures.

Les classes et opérations décrites ci-dessus constituent le coeur des fonctions de dessin de Cogitant. Cependant, dans certains cas, il est préférable de disposer de fonctions de plus haut niveau pour plus de simplicité. C'est pourquoi d'autres classes ont été rajoutées pour simplifier l'utilisation des fonctions de dessin. Ainsi la classe cogitantdisplay::DisplayHandler manipule différentes instances de cogitantdisplay::OperationDraw et cogitantdisplay::OperationLayout. En utilisant un DisplayHandler pour dessiner ou ranger les éléments d'un dessin, on est assuré que l'opération adaptée au Drawing est utilisée. Cette classe est en fait semblable à cogitant::IOHandler qui gère des opérations d'entrées/sorties en différents formats et choisit celle qui est adaptée en fonction de l'extension du nom de fichier passé. Ici, DisplayHandler (et plus précisément cogitantdisplay::DrawHandler et cogitantdisplay::LayoutHandler) choisit l'opération adaptée en fonction du type du Drawing passé.
cogitantdisplay::Panel est une classe permettant de gérer un composant graphique (widget) contenant un dessin. Plus précisément, le constructeur de cette classe prend comme paramètre un Drawing et se charge du dessin de cet objet à l'écran (en ne redessinant que ce qui est nécessaire lors d'un rafraîchissement, en récupérant les évènements souris ou clavier, etc.). Évidemment, cette classe doit être adaptée selon la bibliothèque graphique utilisée. Ainsi la classe cogitantdisplay::Panel_Java gère l'affichage dans un javax.swing.JPanel Java, et la classe cogitantdisplay::Panel_Wx gère l'affichage dans un wxScrolledWindow.

Édition

Les fonctions d'édition sont basées sur les fonctions de dessin. Plus précisément, pour fournir les fonctions d'édition, un cogitantdisplay::Panel récupère les évènements produits par l'utilisateur (clavier et souris). Par défaut, un Panel n'effectue aucun traitement avec ces actions. Mais il est possible d'associer à un Panel un cogitantdisplay::PanelEventHandler. Dans ce cas, le Panel appellera automatiquement les méthodes

Il suffit alors d'associer des traitements particuliers à ces méthodes pour fournir des fonctions d'édition. C'est justement ce que fait la classe cogitantdisplay::Editor (qui est donc une sous-classe de PanelEventHandler). Cette classe fournit en fait des fonctions de plus haut niveau que le clic / déplacement / appui sur une touche. En fait, elle traduit les évènements primitifs en évènements de haut niveau. Ces évènements de haut niveau sont des instances de cogitantdisplay::Editor::Command. Ils représentent par exemple l'ajout d'un sommet, la suppression des éléments sélectionnés, l'ajout d'un élément à la sélection, etc. Certains évènements peuvent être produits directement par l'éditeur, suite à la réception d'évènements du Panel. D'autres évènements peuvent être d'une autre origine, par exemple une barre d'outils ou barre de menus. La classe Editor fournit justement une gestion simplifiée des "producteurs de commandes" (cogitantdisplay::EditorCommandProducer), qui permet la gestion d'une barre d'outils. En utilisant de tels objets, l'exécution de commandes lors d'un clic sur un outil de la barre d'outils ou le passage en grisé d'un outil selon l'état de l'éditeur est automatique.

Les classes d'édition sont évidemment génériques et permettent d'éditer tout type d'objet. Toutefois, certaines fonctions sont spécifiques à l'édition de graphes conceptuels (ajout d'un sommet concept, etc.). Toutes ces fonctions sont dans la classe cogitantdisplay::EditorGraph, qui est une sous-classe de Editor.

Interfaçage avec Java

Un certain nombre de fonctions de Cogitant sont disponibles à partir de Java. Ces fonctions concernent principalement l'affichage et l'édition de graphes conceptuels. L'interfaçage se fait à travers JNI (Java Native Interface). Le code compilé C++ est ainsi appelé à partir d'une application Java, à travers des classes Java qui font le lien entre le code Java et le code C++. Pour utiliser Cogitant dans une application Java, la bibliothèque doit être compilée en bibliothèque dynamique (i.e. so ou dll) et être accessible dans le chemin courant contenant l'application Java.

Le répertoire dp_java contient le source des classes java permettant l'accès aux classes C++. Toutes ces classes figurent dans le paquetage cogitant, et après compilation, elles sont regroupées dans le fichier cogitantdp.jar dans le répertoire lib. La plupart du temps, la classe Java porte le même nom que la classe C++ à laquelle elle donne accès, et les méthodes s'utilisent de la même façon, même si les classes Java ne contiennent que les fonctions "minimum" pour l'affichage de graphes.

Ces classes, qui permettent d'incorporer Cogitant dans une application Java permettant l'affichage et l'édition ne doivent pas être confondues avec les classes Java du répertoire java qui offrent l'accès aux opérations de Cogitant depuis une application Java.