NavigationModel
WARNING : certaines parties de la documentation ne sont pas à jour...
Présentation
Ajout d'un modèle d'arbre de navigation.
Le but de cette fonctionnalité est de pouvoir créer un arbre de navigation lié au context de JAXX, de définir des UI rattachés à chaque noeud.
Le développement est effectué dans le paquetage jaxx.runtime.swing.navigation.
jaxx.runtime.swing.navigation.NavigationModel
Contrat representant le model de l'arbre de navigation.
Les noeuds présents dans se modèle sont aussi typés en jaxx.runtime.swing.navigation.tree.NavigationTreeModel.NavigationTreeNode.
L'idée principale est de pouvoir associer à un noeud précis un chemin depuis la racine, ce que l'on appele chemin de navigation.
Pour obtenir le chemin de navigation d'un noeud donné, on récupère l'enmseble des neoud depuis la racine vers ce noeud et les concatène en suffixant par le caractère séparateur défini.
Tout les models suivants implémantent cette interface.
jaxx.runtime.swing.navigation.tree.NavigationTreeModel
Il s'agit du modèle de l'arbre utilisé, c'est une extension d'un javax.swing.tree.DefaultTreeModel.
jaxx.runtime.swing.navigation.treetable.NavigationTreeTableModel
Il s'agit du modèle de l'arbre tableau (org.jdesktop.swingx.JXTreeTable), c'est une extension d'un org.jdesktop.swingx.treetable.DefaultTreeTableModel.
Les noeuds présents dans se modèle sont typés en jaxx.runtime.swing.navigation.tree.NavigationTreeModel.NavigationTreeTableNode qui étend jaxx.runtime.swing.navigation.tree.NavigationTreeModel.NavigationTreeNode.
NavigationTreeTableNode est abstaite, l'instance doit donc être crée en implementant la méthode createNavigationTreeTableNode du builder (jaxx.runtime.swing.navigation.treetable.NavigationTreeTableModelBuilder).
Les builders
jaxx.runtime.swing.navigation.NavigationModelBuilder
Les builders sont des classes utilitaires permétant de construire le model et les rendus de l'arbre simplement.
Tous les builders implémentent cette interface.
jaxx.runtime.swing.navigation.tree.NavigationTreeModelBuilder
Classe utilitaire pour construire le model (ici un jaxx.runtime.swing.navigation.tree.NavigationTreeModel) et décorer un arbre.
jaxx.runtime.swing.navigation.treetable.NavigationTreeTableModelBuilder
Classe utilitaire pour construire le model (ici un jaxx.runtime.swing.navigation.treetable.NavigationTreeTableModel) et décorer un arbre tableau.
Les Handlers
jaxx.runtime.swing.navigation.handler.AbstractNavigationHandler
Cette classe est une implémentation d'un model de sélection pour les arbres de navigations.
Il y a 2 façons de l'utiliser, soit l'on associe une ui par noeud (Strategy.PER_NODE) soit on associe une ui par type de noeud (Strategy.PER_UI_TYPE).
jaxx.runtime.swing.navigation.handler.NavigationTreeHandlerWithCardLayout
Extension de jaxx.runtime.swing.navigation.handler.AbstractNavigationHandler pour l'utilisation de CardLayout (jaxx.runtime.swing.CardLayout2).
jaxx.runtime.swing.navigation.handler.NavigationMultiTreeHandler
TODO ajouter la strategie de la multiselection
Extension de jaxx.runtime.swing.navigation.handler.AbstractNavigationHandler pour ajouter la possibilité d'utiliser la multisélection.
jaxx.runtime.swing.navigation.handler.NavigationOneClicSelectionHandler
Extension de jaxx.runtime.swing.navigation.handler.NavigationMultiTreeHandler pour activer le simple clic lors de la multi-selection.
Définition d'un noeud
Le noeud (jaxx.runtime.swing.navigation.tree.NavigationTreeModel.NavigationTreeNode) est une extension d'un javax.swing.tree.DefaultMutableTreeNode.
Il apporte les nouvelles propriétés suivantes :
- navigationPath : nom de chemin de navigation de ce noeud.
- jaxxClass : nom qualifié de la classe d'ui associé à ce noeud (doit être obligatoirement un JAXXObject)
- jaxxActionClass : nom qualifié de la classe d'handler d'ui associé à ce noeud (doit être obligatoirement un JAXXAction).
- jaxxContextEntryDef : définition de l'entrée dans le context JAXX associé à ce noeud.
- jaxxContextEntryJXPath : définition d'une expression JXPath à appliquer sur le bean associé au noeud.
Retrouver un noeud à partir du chemin de navigation
Il est possible en connaissant le chemin de navigation d'un noeud de récupérer le noeud dans l'arbre via la méthode
model.findNode("chemin.de.navigation")
Trouver la valeur associée dans le context JAXX à partir du chemin de navigation
Il est possible en connaissant le chemin de navigation d'un noeud de récupérer la valeur associée dans le context JAXX.
model.getJAXXContextValue(myJAXXContext, "chemin.de.navigation")* .
L'algrotihme est le suivant :
- récupération du noeud associé au chemin de navigation
- recherche du premier noeud (dans les noeuds qui remontent vers la racine de l'arbre) dont la propriété jaxxContextEntry est non nulle, il s'agit du point d'entré dans le context JAXX.
- redescendre à partir de ce noeud vers le noeud d'origine (si ce noeud était différent) et en descendant conjointement dans l'objet du context JAXX :
- on utilise l'expression JXPath pour obtenir l'objet associé au noeud
Exemple :
"$root" + <-- la racine de l'abre | + "string" <-- attaché au context JAXX <java.lang.String,"string"> | + "liste" + <-- attaché au context JAXX <java.util.List.class,"liste"> | | | + "0" <-- le premier élément de la liste | | | + "1" <-- le second élément de la liste | | | + "2" <-- le troisième élément de la liste | + "locale" + <-- attaché au context JAXX <java.util.Locale> | + country | + language // preparation du context java.util.List myList = java.util.Arrays.asList("one","two","three"); java.util.Locale myLocale = java.util.Locale.FRENCH; context.setContextValue(myList, "liste"); context.setContextValue("stringValue","string"); context.setContextValue(myLocale); // récupération des valeurs dans le context à partir de chemin de navigation assert model.getJAXXContextValue(context, "$root") == null; assert model.getJAXXContextValue(context, "$root.string") == "stringValue"; assert model.getJAXXContextValue(context, "$root.liste") == myList; assert model.getJAXXContextValue(context, "$root.liste.0") == "one"; assert model.getJAXXContextValue(context, "$root.liste.1") == "two"; assert model.getJAXXContextValue(context, "$root.liste.2") == "three"; assert model.getJAXXContextValue(context, "$root.locale") == myLocale; assert model.getJAXXContextValue(context, "$root.locale.country") == myLocale.getCountry(); assert model.getJAXXContextValue(context, "$root.locale.language") == myLocale.getLanguage();
TODO mettre à jour cet exemple suite à l'utilisation de JXPath pour naviguer dans les objets.
A noter qu'une seconde méthode de récupération de valeur du context JAXX est disponible pour pouvoir récupérer cette valeur en connaissant le noeud :
model.getJAXXContextValue(context, myNode);
jaxx.runtime.swing.navigation.NavigationTreeSelectionAdapter
Il s'agit d'un listener sur la sélection d'un noeud dans l'arbre de navigation basé sur notre modèle de navigation. Il étend javax.swing.event.TreeSelectionListener.
Ce listener contient la gestion de passage d'un noeud à un autre avec interaction avec le context JAXX et affichage automatique de l'ui associé au noeud sélectionné.
Attention : la mécanique ne fonctionne que pour un arbre à selection unique.
Algorithme
Voici l'algorithme utilisé lors de la sélection d'un nouveau noeud :
- closeUI : tentative de fermeture de l'ui lié au noeud précédemment selectionné, si cela n'aboutit pas on retourne sur le noeud précédent.
- attachBeanFromNodeToContext : injection dans le context JAXX de la valeur associée au nouveau noeud
- createUI : création de la nouvelle ui (si elle n'existe pas)
- openUI : ouverture de la nouvelle ui
Si une erreur survient lors de ces opérations, on entre dans la méthode goBackToPreviousNode qui est abstraite et permet de notifier les erreur de retourner au noeud précdent.
jaxx.runtime.swing.navigation.NavigationTreeSelectionAdapterWithCardLayout
Il s'agit d'une implantation du listener précédent qui suppose que les uis associées aux noeuds sont affichées dans un unique container en utilisant le layout jaxx.runtime.swing.CardLayout2.
La contrainte de chaque ui sera extactement le chemin de navigation du noeud associé.
Il possède deux méthodes abstraites :
- getContentContainer : qui indique le container d'ui.
- getContentLayout : qui indique le layout utilisé.
Pour pouvoir utilisé cet adapter, il vous suffit de définir la méthode suivante (en plus des deux méthodes abstraites) :
- goBackToPreviousNode : comment gérer les erreurs et retourner au noeud précedent.