View Javadoc

    1   /*
    2    *  soapUI, copyright (C) 2004-2007 eviware.com
    3    *
    4    *  soapUI is free software; you can redistribute it and/or modify it under the
    5    *  terms of version 2.1 of the GNU Lesser General Public License as published by
    6    *  the Free Software Foundation.
    7    *
    8    *  soapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
    9    *  even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    10   *  See the GNU Lesser General Public License for more details at gnu.org.
    11   */
    12
    13  package com.eviware.soapui.ui;
    14
    15  import java.awt.BorderLayout;
    16  import java.awt.Insets;
    17  import java.awt.Point;
    18  import java.awt.Rectangle;
    19  import java.awt.dnd.Autoscroll;
    20  import java.awt.event.ActionEvent;
    21  import java.awt.event.KeyAdapter;
    22  import java.awt.event.KeyEvent;
    23  import java.awt.event.MouseAdapter;
    24  import java.awt.event.MouseEvent;
    25  import java.util.HashSet;
    26  import java.util.Set;
    27
    28  import javax.swing.JPanel;
    29  import javax.swing.JPopupMenu;
    30  import javax.swing.JScrollPane;
    31  import javax.swing.JTree;
    32  import javax.swing.ToolTipManager;
    33  import javax.swing.event.TreeSelectionEvent;
    34  import javax.swing.event.TreeSelectionListener;
    35  import javax.swing.tree.TreePath;
    36  import javax.swing.tree.TreeSelectionModel;
    37
    38  import com.eviware.soapui.model.ModelItem;
    39  import com.eviware.soapui.model.project.Project;
    40  import com.eviware.soapui.model.tree.SoapUITreeModel;
    41  import com.eviware.soapui.model.tree.SoapUITreeNode;
    42  import com.eviware.soapui.model.tree.SoapUITreeNodeRenderer;
    43  import com.eviware.soapui.model.tree.nodes.ProjectTreeNode;
    44  import com.eviware.soapui.model.workspace.Workspace;
    45  import com.eviware.soapui.support.action.swing.ActionList;
    46
    47  /***
    48   * The soapUI navigator tree
    49   *
    50   * @author Ole.Matzura
    51   */
    52
    53  public class Navigator extends JPanel
    54  {
    55  	private Workspace workspace;
    56  	private JTree mainTree;
    57  	private SoapUITreeModel treeModel;
    58  	private Set<NavigatorListener> listeners = new HashSet<NavigatorListener>();
    59
    60  	public Navigator( Workspace workspace )
    61  	{
    62  		super( new BorderLayout() );
    63  		this.workspace = workspace;
    64
    65  		buildUI();
    66  	}
    67
    68  	private void buildUI()
    69  	{
    70  		treeModel = new SoapUITreeModel(workspace);
    71
    72        mainTree = new NavigatorTree( treeModel );
    73        mainTree.setRootVisible(true);
    74        mainTree.setExpandsSelectedPaths(true);
    75        mainTree.setToggleClickCount( 0 );
    76        mainTree.addMouseListener(new TreeMouseListener());
    77        mainTree.addTreeSelectionListener(new InternalTreeSelectionListener());
    78        mainTree.setCellRenderer( new SoapUITreeNodeRenderer() );
    79        mainTree.setBorder(null);
    80        mainTree.getSelectionModel().setSelectionMode( TreeSelectionModel.SINGLE_TREE_SELECTION );
    81
    82        mainTree.addKeyListener( new TreeKeyListener() );
    83
    84        ToolTipManager.sharedInstance().registerComponent(mainTree);
    85
    86        add( new JScrollPane( mainTree ), BorderLayout.CENTER );
    87  	}
    88
    89  	private static class NavigatorTree extends JTree implements Autoscroll
    90  	{
    91  		public NavigatorTree( SoapUITreeModel treeModel )
    92  		{
    93  			super( treeModel );
    94  		}
    95
    96  		private static final int AUTOSCROLL_MARGIN = 12;
    97
    98  		public void autoscroll( Point pt )
    99  		{
    100 			// Figure out which row we?re on.
    101 			int nRow = getRowForLocation( pt.x, pt.y );
    102
    103 			// If we are not on a row then ignore this autoscroll request
    104 			if( nRow < 0 )
    105 				return;
    106
    107 			Rectangle raOuter = getBounds();
    108 			// Now decide if the row is at the top of the screen or at the
    109 			// bottom. We do this to make the previous row (or the next
    110 			// row) visible as appropriate. If we?re at the absolute top or
    111 			// bottom, just return the first or last row respectively.
    112
    113 			nRow = ( pt.y + raOuter.y <= AUTOSCROLL_MARGIN ) // Is row at top of
    114 			// screen?
    115 			? ( nRow <= 0 ? 0 : nRow - 1 ) // Yes, scroll up one row
    116 						: ( nRow < getRowCount() - 1 ? nRow + 1 : nRow ); // No,
    117 			// scroll
    118 			// down one
    119 			// row
    120
    121 			scrollRowToVisible( nRow );
    122 		}
    123
    124 		// Calculate the insets for the *JTREE*, not the viewport
    125 		// the tree is in. This makes it a bit messy.
    126 		public Insets getAutoscrollInsets()
    127 		{
    128 			Rectangle raOuter = getBounds();
    129 			Rectangle raInner = getParent().getBounds();
    130 			return new Insets( raInner.y - raOuter.y + AUTOSCROLL_MARGIN, raInner.x - raOuter.x
    131 						+ AUTOSCROLL_MARGIN, raOuter.height - raInner.height - raInner.y + raOuter.y
    132 						+ AUTOSCROLL_MARGIN, raOuter.width - raInner.width - raInner.x + raOuter.x
    133 						+ AUTOSCROLL_MARGIN );
    134 		}
    135 	}
    136
    137 	public Project getCurrentProject()
    138    {
    139       TreePath path = mainTree.getSelectionPath();
    140       if( path == null )
    141       	return null;
    142
    143       Object node = (Object) path.getLastPathComponent();
    144       while (node != null && !(node instanceof ProjectTreeNode))
    145       {
    146          path = path.getParentPath();
    147          node = (path == null ? null : path.getLastPathComponent());
    148       }
    149
    150       if (node == null)
    151          return null;
    152
    153       return ((ProjectTreeNode) node).getProject();
    154    }
    155
    156 	public void addNavigatorListener( NavigatorListener listener )
    157 	{
    158 		listeners.add( listener );
    159 	}
    160
    161 	public void removeNavigatorListener( NavigatorListener listener )
    162 	{
    163 		listeners.remove( listener );
    164 	}
    165
    166 	public void selectModelItem(ModelItem modelItem)
    167    {
    168       TreePath path = treeModel.getPath( modelItem );
    169       mainTree.setSelectionPath( path );
    170      	mainTree.expandPath( path );
    171       mainTree.scrollPathToVisible( path );
    172    }
    173
    174 	public TreePath getTreePath( ModelItem modelItem )
    175 	{
    176 		return treeModel.getPath( modelItem );
    177 	}
    178
    179 	public JTree getMainTree()
    180 	{
    181 		return mainTree;
    182 	}
    183
    184 	private final class TreeKeyListener extends KeyAdapter
    185 	{
    186 		public void keyPressed(KeyEvent e)
    187 		{
    188 			TreePath selectionPath = mainTree.getSelectionPath();
    189 			if( selectionPath != null )
    190 			{
    191 				SoapUITreeNode lastPathComponent = (SoapUITreeNode) selectionPath.getLastPathComponent();
    192 				ActionList actions = lastPathComponent.getActions();
    193 				if( actions != null )
    194 				{
    195 					actions.dispatchKeyEvent( e );
    196 				}
    197 			}
    198 		}
    199 	}
    200
    201 	public class InternalTreeSelectionListener implements TreeSelectionListener
    202    {
    203       public void valueChanged(TreeSelectionEvent e)
    204       {
    205          Object obj = e.getPath().getLastPathComponent();
    206          if (obj instanceof SoapUITreeNode)
    207          {
    208             SoapUITreeNode treeNode = (SoapUITreeNode) obj;
    209
    210             if( !listeners.isEmpty() )
    211             {
    212             	TreePath newPath = e.getNewLeadSelectionPath();
    213 	            NavigatorListener[] array = listeners.toArray( new NavigatorListener[listeners.size()]);
    214 	            for( NavigatorListener listener : array )
    215 	            {
    216 	            	listener.nodeSelected( newPath == null ? null : treeNode );
    217 	            }
    218             }
    219          }
    220       }
    221    }
    222
    223 	public class TreeMouseListener extends MouseAdapter
    224    {
    225       public void mouseClicked(MouseEvent e)
    226       {
    227          if (e.isPopupTrigger())
    228             showPopup(e);
    229          else if (e.getClickCount() < 2)
    230             return;
    231          if (mainTree.getSelectionCount() != 1)
    232             return;
    233
    234          TreePath path = mainTree.getSelectionPath();
    235          if( path == null )
    236          	return;
    237
    238          SoapUITreeNode node = (SoapUITreeNode) path.getLastPathComponent();
    239          ActionList actions = node.getActions();
    240          if( actions != null )
    241          	actions.performDefaultAction( new ActionEvent( mainTree, 0, null ));
    242       }
    243
    244       public void mousePressed(MouseEvent e)
    245       {
    246          if (e.isPopupTrigger())
    247             showPopup(e);
    248       }
    249
    250       public void mouseReleased(MouseEvent e)
    251       {
    252          if (e.isPopupTrigger())
    253             showPopup(e);
    254       }
    255
    256       private void showPopup(MouseEvent e)
    257       {
    258          TreePath path = mainTree.getPathForLocation((int) e.getPoint().getX(), (int) e.getPoint().getY());
    259          if (path == null)
    260             return;
    261          SoapUITreeNode node = (SoapUITreeNode) path.getLastPathComponent();
    262
    263          JPopupMenu popupMenu = node.getPopup();
    264          if (popupMenu == null)
    265             return;
    266
    267          mainTree.setSelectionPath(path);
    268
    269          popupMenu.show(mainTree, e.getX(), e.getY());
    270       }
    271    }
    272
    273 	public boolean isVisible( TreePath path )
    274 	{
    275 		return mainTree.isVisible( path );
    276 	}
    277
    278 	public boolean isExpanded( TreePath path )
    279 	{
    280 		return mainTree.isExpanded( path );
    281 	}
    282 }