jaxx.runtime.swing.navigation.NavigationTreeHandler Maven / Gradle / Ivy
/*
* *##%
* JAXX Runtime
* Copyright (C) 2008 - 2009 CodeLutin
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* .
* ##%*
*/
package jaxx.runtime.swing.navigation;
import java.awt.Component;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultTreeSelectionModel;
import javax.swing.tree.TreePath;
import jaxx.runtime.JAXXAction;
import jaxx.runtime.JAXXContext;
import jaxx.runtime.context.JAXXInitialContext;
import jaxx.runtime.JAXXObject;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* The handler of a navigation tree.
*
* This is also the selection model to use, since we must check before moving
* from a node we can not just listen selection model changed, we must control
* it.
*
* @author tony
* @since 1.7.2
*/
public abstract class NavigationTreeHandler extends DefaultTreeSelectionModel implements TreeSelectionListener{
private static final long serialVersionUID = 1L;
/**
* Logger
*/
static private final Log log = LogFactory.getLog(NavigationTreeHandler.class);
/**
* Strategy of instanciation of ui.
*
* For a given {@code node}, the method {@link #getId(NavigationTreeNode)}
* returns the id of ui to use.
*/
public enum Strategy {
/**
* instanciate a ui for a node
*/
PER_NODE {
@Override
public String getId(NavigationTreeNode node) {
return node.getFullPath();
}
},
/**
* instanciate only one a ui for a type,nodes will share the instanciation
*/
PER_UI_TYPE {
@Override
public String getId(NavigationTreeNode node) {
return node.getUIClass().getName();
}
};
public abstract String getId(NavigationTreeNode node);
}
/**
* UI which contains navigation tree
*/
protected JAXXContext context;
/**
* UI Instanciation strategy
*/
protected Strategy strategy;
/**
* JAXXContext access helper.
*
* @since 1.7.2
*/
protected NavigationTreeContextHelper contextHelper;
protected NavigationTreeHandler(String contextPrefix, JAXXObject context, Strategy strategy) {
this.contextHelper = new NavigationTreeContextHelper(contextPrefix);
this.context = context;
this.strategy = strategy;
addTreeSelectionListener(this);
}
@Override
public void valueChanged(TreeSelectionEvent event) {
if (log.isDebugEnabled()){
log.debug("Value changed for path : " + event.getPath());
log.debug("Old lead selection path : " + event.getOldLeadSelectionPath());
}
if (event.getOldLeadSelectionPath() != null && event.getOldLeadSelectionPath().equals(event.getPath())) {
// do not treate this if no path changed
return;
}
NavigationTreeNode node = (NavigationTreeNode) event.getPath().getLastPathComponent();
selectNodeUI(node);
}
/**
* @return le modèle de navigation associé
*/
protected abstract NavigationModel getNavigationTreeModel();
/**
* @return le composent actuellement visible associé au noeud courant ou
* au noeud précédent lors d'un changement de noeud.
*/
protected abstract Component getCurrentUI();
/**
* @param node le noeud associé à l'ui à retrouver
* @return l'ui associé au novueau noeud sélectionné
*/
protected abstract Component getUI(NavigationTreeNode node);
/**
* @param component le composent actuellement visible
* @return true
si le composent a bien été fermé, false
sinon
* @throws Exception if any
*/
protected abstract boolean closeUI(Component component) throws Exception;
/**
* Instancie une nouvelle ui associé à un noeud de l'arbre de navigation
*
* @param node le noeud associé à l'ui à créer
* @return la nouvelle ui associée au noeud
* @throws Exception if any
*/
protected abstract Component createUI(NavigationTreeNode node) throws Exception;
/**
* Ouvre l'ui associée au noeud sélectionné dans l'arbre de navigation.
*
* @param newUI l'ui associé au noeud sélectionné à ouvrir
* @param node le node de l'ui a ouvrir
* @throws Exception if any
*/
protected abstract void openUI(Component newUI, NavigationTreeNode node) throws Exception;
/**
* Traitement des exceptions.
*
* @param e l'erreur recontrée (ou null si pas d"erreur)
*/
protected abstract void treateError(Exception e);
public JAXXContext getContext() {
return context;
}
public NavigationTreeContextHelper getContextHelper() {
return contextHelper;
}
@Override
public void setSelectionPath(TreePath path) {
if (path.equals(getSelectionPath())) {
// stay on same node, can skip
if (log.isDebugEnabled()) {
log.debug("skip stay on path " + path);
}
return;
}
Component component = getCurrentUI();
try {
if (!closeUI(component)) {
if (log.isDebugEnabled()) {
log.debug("changing node canceled!");
}
// can not changed current node
return;
}
if (component instanceof NavigationContentUI) {
((NavigationContentUI) component).closeUI((NavigationTreeNode) path.getLastPathComponent());
}
} catch (Exception ex) {
treateError(ex);
return;
}
if (log.isDebugEnabled()) {
log.debug("will select path " + path);
}
// ok can safely select the new path
super.setSelectionPath(path);
}
@Override
public void setSelectionPaths(TreePath[] paths) {
if (paths.equals(getSelectionPaths())) {
// stay on same node, can skip
if (log.isDebugEnabled()) {
log.debug("skip stay on path " + paths);
}
return;
}
Component component = getCurrentUI();
try {
if (!closeUI(component)) {
if (log.isDebugEnabled()) {
log.debug("changing node canceled!");
}
// can not changed current node
return;
}
if (component instanceof NavigationMultiContentUI) {
if (paths.length == 1){
NavigationTreeContextHelper helper = getContextHelper();
((NavigationMultiContentUI) component).closeUI(helper.getSelectedNodes(getContext()));
}
}
} catch (Exception ex) {
treateError(ex);
return;
}
if (log.isDebugEnabled()) {
log.debug("will select " + paths.length + " paths");
}
// ok can safely select the new path
super.setSelectionPaths(paths);
}
protected void selectNodeUI(NavigationTreeNode node) {
try {
String path = node.getFullPath();
if (log.isTraceEnabled()) {
log.trace(path);
}
Component newUI = getUI(node);
// now, we are free to open the ui associated with the selected node in navigation
// get the bean associated with the node
Object data = getNavigationTreeModel().getBean(path);
// save it in context (must be done before init ui)
addSelectedBeanInContext(node, data);
if (newUI == null) {
// a new ui instance is required
newUI = createUI(node);
}
JAXXContext ctxt = getContext();
NavigationTreeContextHelper helper = getContextHelper();
// save in context current node context path
helper.setSelectedPath(ctxt, node.getFullPath());
// save in context current node
helper.setSelectedNode(ctxt, node);
// save in context current ui
// helper.setSelectedUI(ctxt, newUI);
// really open the ui associated with the selected node
// init ui before to be visible
if (newUI instanceof NavigationContentUI) {
((NavigationContentUI) newUI).openUI(node);
}
// set ui in content
openUI(newUI, node);
} catch (Exception e) {
// remove data from context
// if any error, go back to previvous node
treateError(e);
}
}
/**
* Prepare le context a utiliser pour initialiser une nouvelle ui.
*
* @param node le noeud associé à l'ui à créer
* @return le context à utiliser pour instancier l'ui
* @throws Exception if any
*/
protected JAXXContext createUIContext(NavigationTreeNode node) throws Exception {
if (node.getUIHandlerClass() == null) {
if (log.isWarnEnabled()) {
log.warn("no action associated with ui " + node.getUIClass());
}
// no action associated, just
return getContext();
}
JAXXAction action = node.getUIHandlerClass().newInstance();
// init context with
JAXXInitialContext uiContext = action.init(getContext());
return uiContext;
}
protected void addSelectedBeanInContext(NavigationTreeNode node, Object data) {
if (log.isDebugEnabled()) {
log.debug("find data for contextPath <" + node.getFullPath() + "> : " + (data == null ? null : data.getClass()));
}
JAXXContext ctxt = getContext();
NavigationTreeContextHelper helper = getContextHelper();
// remove previous selected bean
//TODO-TC-20091004 should have an automatic clean context method while
helper.setSelectedBean(ctxt, null);
if (data != null) {
helper.setSelectedBean(ctxt, data);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy