blob: b9375a11a61ba3c8a4413140167bcbddc419f2e9 [file] [log] [blame]
/*
* Copyright (c) 2009, Tony Kohar. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.zest.envisage.tree;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.GridBagConstraints;
import java.awt.Insets;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.ResourceBundle;
import javax.swing.BorderFactory;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.*;
import org.apache.zest.tools.model.descriptor.ApplicationDetailDescriptor;
/**
* Application Model View as Swing Component.
* It support 2 view:
* <pre><code>
* - by Structure
* - by Type
* </code></pre>
*/
public final class TreeModelPane
extends JPanel
{
private static final String STRUCTURE_VIEW = "Structure";
private static final String TYPE_VIEW = "Type";
private static final ResourceBundle BUNDLE = ResourceBundle.getBundle( TreeModelPane.class.getName() );
private JPanel mainPane;
private CardLayout cardLayout;
private JTree structureTree;
private JTree typeTree;
private JComboBox viewAsCombo;
private boolean selectionInProgress;
public TreeModelPane()
{
setLayout( new BorderLayout() );
// init mainPane
structureTree = new JTree();
structureTree.setRootVisible( false );
structureTree.setShowsRootHandles( true );
structureTree.setExpandsSelectedPaths( true );
structureTree.setScrollsOnExpand( true );
structureTree.setName( STRUCTURE_VIEW );
structureTree.setCellRenderer( new TreeModelCellRenderer() );
typeTree = new JTree();
typeTree.setRootVisible( false );
typeTree.setShowsRootHandles( true );
typeTree.setExpandsSelectedPaths( true );
typeTree.setScrollsOnExpand( true );
typeTree.setName( TYPE_VIEW );
typeTree.setCellRenderer( new TreeModelCellRenderer() );
mainPane = new JPanel();
cardLayout = new CardLayout();
mainPane.setLayout( cardLayout );
mainPane.add( new JScrollPane( structureTree ), STRUCTURE_VIEW );
mainPane.add( new JScrollPane( typeTree ), TYPE_VIEW );
add( mainPane, BorderLayout.CENTER );
// init viewAsCombo
JPanel viewAsPane = new JPanel();
viewAsPane.setBorder( BorderFactory.createEmptyBorder( 3, 6, 3, 0 ) );
viewAsPane.setLayout( new java.awt.GridBagLayout() );
GridBagConstraints gridBagConstraints;
JLabel viewAsLabel = new JLabel( BUNDLE.getString( "CTL_ViewAs.Text" ) );
gridBagConstraints = new GridBagConstraints();
gridBagConstraints.anchor = GridBagConstraints.WEST;
gridBagConstraints.insets = new Insets( 0, 0, 0, 6 );
viewAsPane.add( viewAsLabel, gridBagConstraints );
viewAsCombo = new JComboBox( new DefaultComboBoxModel( new String[]
{
STRUCTURE_VIEW, TYPE_VIEW
} ) );
gridBagConstraints = new GridBagConstraints();
gridBagConstraints.fill = GridBagConstraints.HORIZONTAL;
gridBagConstraints.weightx = 1.0;
viewAsPane.add( viewAsCombo, gridBagConstraints );
viewAsCombo.addItemListener( new ItemListener()
{
@Override
public void itemStateChanged( ItemEvent evt )
{
if( evt.getStateChange() == ItemEvent.DESELECTED )
{
return;
}
cardLayout.show( mainPane, evt.getItem().toString() );
repaint();
}
} );
add( viewAsPane, BorderLayout.PAGE_START );
}
/**
* Initialize Qi4J for this component
*
* @param descriptor the Application descriptor
*/
public void initQi4J( ApplicationDetailDescriptor descriptor )
{
// traverse the model and build JTree representation
MutableTreeNode rootNode1 = StructureModelBuilder.build( descriptor );
MutableTreeNode rootNode2 = TypeModelBuilder.build( descriptor );
structureTree.setModel( new DefaultTreeModel( rootNode1 ) );
typeTree.setModel( new DefaultTreeModel( rootNode2 ) );
structureTree.addTreeSelectionListener( new TreeSelectionListener()
{
@Override
public void valueChanged( TreeSelectionEvent evt )
{
structureTreeValueChanged();
}
} );
typeTree.addTreeSelectionListener( new TreeSelectionListener()
{
@Override
public void valueChanged( TreeSelectionEvent evt )
{
typeTreeValueChanged();
}
} );
}
public Object getLastSelected()
{
Object obj = structureTree.getLastSelectedPathComponent();
if( obj != null )
{
return ( (DefaultMutableTreeNode) obj ).getUserObject();
}
return null;
}
public void setSelectedValue( Object obj )
{
if( obj == null )
{
return;
}
TreeNode node = findNode( structureTree, obj );
if( node != null )
{
DefaultTreeModel treeModel = (DefaultTreeModel) structureTree.getModel();
TreePath treePath = new TreePath( treeModel.getPathToRoot( node ) );
structureTree.setSelectionPath( treePath );
structureTree.scrollPathToVisible( treePath );
}
else
{
structureTree.clearSelection();
}
}
/**
* Just a helper method to find the node which contains the userObject
*
* @param tree the JTree to search into
* @param object the user object
*
* @return TreeNode or null
*/
protected TreeNode findNode( JTree tree, Object object )
{
DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree.getModel().getRoot();
return findNode( node, object );
}
/**
* Recurvice search or find node that contains the obj
*
* @param node DefaultMutableTreeNode
* @param obj userObject
*
* @return TreeNode or null if could not find
*/
private TreeNode findNode( DefaultMutableTreeNode node, Object obj )
{
if( obj instanceof String )
{
if( node.getUserObject().toString().equals( obj.toString() ) )
{
return node;
}
}
else if( node.getUserObject().equals( obj ) )
{
return node;
}
TreeNode foundNode = null;
for( int i = 0; i < node.getChildCount(); i++ )
{
DefaultMutableTreeNode childNode = (DefaultMutableTreeNode) node.getChildAt( i );
foundNode = findNode( childNode, obj );
if( foundNode != null )
{
break;
}
}
return foundNode;
}
public final void addTreeSelectionListener( TreeSelectionListener listener )
{
structureTree.addTreeSelectionListener( listener );
}
public final void removeTreeSelectionListener( TreeSelectionListener listener )
{
structureTree.removeTreeSelectionListener( listener );
}
protected void structureTreeValueChanged()
{
if( selectionInProgress )
{
return;
}
Object userObject = getLastSelected();
if( userObject == null )
{
return;
}
TreeNode node = findNode( typeTree, userObject );
if( node != null )
{
DefaultTreeModel treeModel = (DefaultTreeModel) typeTree.getModel();
TreePath treePath = new TreePath( treeModel.getPathToRoot( node ) );
typeTree.setSelectionPath( treePath );
typeTree.scrollPathToVisible( treePath );
}
}
protected void typeTreeValueChanged()
{
Object obj = typeTree.getLastSelectedPathComponent();
if( obj == null )
{
return;
}
Object userObject = ( (DefaultMutableTreeNode) obj ).getUserObject();
TreeNode node = findNode( structureTree, userObject );
if( node != null )
{
DefaultTreeModel treeModel = (DefaultTreeModel) structureTree.getModel();
TreePath treePath = new TreePath( treeModel.getPathToRoot( node ) );
selectionInProgress = true;
try
{
structureTree.setSelectionPath( treePath );
}
finally
{
selectionInProgress = false;
}
structureTree.scrollPathToVisible( treePath );
}
}
}