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.BorderFactory;
    29  import javax.swing.JPanel;
    30  import javax.swing.JPopupMenu;
    31  import javax.swing.JScrollPane;
    32  import javax.swing.JTree;
    33  import javax.swing.KeyStroke;
    34  import javax.swing.ToolTipManager;
    35  import javax.swing.event.TreeSelectionEvent;
    36  import javax.swing.event.TreeSelectionListener;
    37  import javax.swing.tree.TreePath;
    38  import javax.swing.tree.TreeSelectionModel;
    39
    40  import com.eviware.soapui.model.ModelItem;
    41  import com.eviware.soapui.model.project.Project;
    42  import com.eviware.soapui.model.tree.SoapUITreeModel;
    43  import com.eviware.soapui.model.tree.SoapUITreeNode;
    44  import com.eviware.soapui.model.tree.SoapUITreeNodeRenderer;
    45  import com.eviware.soapui.model.tree.nodes.ProjectTreeNode;
    46  import com.eviware.soapui.model.workspace.Workspace;
    47  import com.eviware.soapui.support.UISupport;
    48  import com.eviware.soapui.support.action.swing.ActionList;
    49
    50  /***
    51   * The soapUI navigator tree
    52   *
    53   * @author Ole.Matzura
    54   */
    55
    56  public class Navigator extends JPanel
    57  {
    58  	private Workspace workspace;
    59  	private JTree mainTree;
    60  	private SoapUITreeModel treeModel;
    61  	private Set<NavigatorListener> listeners = new HashSet<NavigatorListener>();
    62
    63  	public Navigator( Workspace workspace )
    64  	{
    65  		super( new BorderLayout() );
    66  		this.workspace = workspace;
    67
    68  		buildUI();
    69  	}
    70
    71  	private void buildUI()
    72  	{
    73  		treeModel = new SoapUITreeModel(workspace);
    74
    75        mainTree = new NavigatorTree( treeModel );
    76        mainTree.setRootVisible(true);
    77        mainTree.setExpandsSelectedPaths(true);
    78        mainTree.setToggleClickCount( 0 );
    79        mainTree.addMouseListener(new TreeMouseListener());
    80        mainTree.addTreeSelectionListener(new InternalTreeSelectionListener());
    81        mainTree.setCellRenderer( new SoapUITreeNodeRenderer() );
    82        mainTree.setBorder(null);
    83        mainTree.getSelectionModel().setSelectionMode( TreeSelectionModel.SINGLE_TREE_SELECTION );
    84        mainTree.addKeyListener( new TreeKeyListener() );
    85  //      mainTree.addTreeExpansionListener( new TreeExpansionListener() {
    86  //
    87  //			public void treeCollapsed( TreeExpansionEvent event )
    88  //			{
    89  //			}
    90  //
    91  //			public void treeExpanded( final TreeExpansionEvent event )
    92  //			{
    93  //				Object treeNode = event.getPath().getLastPathComponent();
    94  //				if( treeNode instanceof ProjectTreeNode )
    95  //				{
    96  //					ProjectTreeNode tn = ( ProjectTreeNode ) treeNode;
    97  //					if( !tn.getModelItem().isOpen() && !tn.getModelItem().isDisabled() )
    98  //					{
    99  //						try
    100 //						{
    101 //							UISupport.select( workspace.openProject( tn.getModelItem()));
    102 //						}
    103 //						catch( SoapUIException e )
    104 //						{
    105 //							UISupport.showErrorMessage( e );
    106 //						}
    107 //					}
    108 //				}
    109 //			}} );
    110 //
    111
    112       ToolTipManager.sharedInstance().registerComponent(mainTree);
    113
    114       add( new JScrollPane( mainTree ), BorderLayout.CENTER );
    115       setBorder( BorderFactory.createEmptyBorder( 2, 0, 0, 0 ));
    116 	}
    117
    118 	private static class NavigatorTree extends JTree implements Autoscroll
    119 	{
    120 		public NavigatorTree( SoapUITreeModel treeModel )
    121 		{
    122 			super( treeModel );
    123 		}
    124
    125 		private static final int AUTOSCROLL_MARGIN = 12;
    126
    127 		public void autoscroll( Point pt )
    128 		{
    129 			// Figure out which row we?re on.
    130 			int nRow = getRowForLocation( pt.x, pt.y );
    131
    132 			// If we are not on a row then ignore this autoscroll request
    133 			if( nRow < 0 )
    134 				return;
    135
    136 			Rectangle raOuter = getBounds();
    137 			// Now decide if the row is at the top of the screen or at the
    138 			// bottom. We do this to make the previous row (or the next
    139 			// row) visible as appropriate. If we?re at the absolute top or
    140 			// bottom, just return the first or last row respectively.
    141
    142 			nRow = ( pt.y + raOuter.y <= AUTOSCROLL_MARGIN ) // Is row at top of
    143 			// screen?
    144 			? ( nRow <= 0 ? 0 : nRow - 1 ) // Yes, scroll up one row
    145 						: ( nRow < getRowCount() - 1 ? nRow + 1 : nRow ); // No,
    146 			// scroll
    147 			// down one
    148 			// row
    149
    150 			scrollRowToVisible( nRow );
    151 		}
    152
    153 		// Calculate the insets for the *JTREE*, not the viewport
    154 		// the tree is in. This makes it a bit messy.
    155 		public Insets getAutoscrollInsets()
    156 		{
    157 			Rectangle raOuter = getBounds();
    158 			Rectangle raInner = getParent().getBounds();
    159 			return new Insets( raInner.y - raOuter.y + AUTOSCROLL_MARGIN, raInner.x - raOuter.x
    160 						+ AUTOSCROLL_MARGIN, raOuter.height - raInner.height - raInner.y + raOuter.y
    161 						+ AUTOSCROLL_MARGIN, raOuter.width - raInner.width - raInner.x + raOuter.x
    162 						+ AUTOSCROLL_MARGIN );
    163 		}
    164 	}
    165
    166 	public Project getCurrentProject()
    167    {
    168       TreePath path = mainTree.getSelectionPath();
    169       if( path == null )
    170       	return null;
    171
    172       Object node = (Object) path.getLastPathComponent();
    173       while (node != null && !(node instanceof ProjectTreeNode))
    174       {
    175          path = path.getParentPath();
    176          node = (path == null ? null : path.getLastPathComponent());
    177       }
    178
    179       if (node == null)
    180          return null;
    181
    182       return ((ProjectTreeNode) node).getProject();
    183    }
    184
    185 	public void addNavigatorListener( NavigatorListener listener )
    186 	{
    187 		listeners.add( listener );
    188 	}
    189
    190 	public void removeNavigatorListener( NavigatorListener listener )
    191 	{
    192 		listeners.remove( listener );
    193 	}
    194
    195 	public void selectModelItem(ModelItem modelItem)
    196    {
    197       TreePath path = treeModel.getPath( modelItem );
    198       mainTree.setSelectionPath( path );
    199      	mainTree.expandPath( path );
    200       mainTree.scrollPathToVisible( path );
    201    }
    202
    203 	public TreePath getTreePath( ModelItem modelItem )
    204 	{
    205 		return treeModel.getPath( modelItem );
    206 	}
    207
    208 	public JTree getMainTree()
    209 	{
    210 		return mainTree;
    211 	}
    212
    213 	public ModelItem getSelectedItem()
    214 	{
    215 		TreePath path = mainTree.getSelectionPath();
    216       if( path == null )
    217       	return null;
    218
    219      return ((SoapUITreeNode) path.getLastPathComponent()).getModelItem();
    220 	}
    221
    222 	private final class TreeKeyListener extends KeyAdapter
    223 	{
    224 		public void keyPressed(KeyEvent e)
    225 		{
    226 			TreePath selectionPath = mainTree.getSelectionPath();
    227 			if( selectionPath != null )
    228 			{
    229 				SoapUITreeNode lastPathComponent = (SoapUITreeNode) selectionPath.getLastPathComponent();
    230 				ActionList actions = lastPathComponent.getActions();
    231 				if( actions != null )
    232 				{
    233 					actions.dispatchKeyEvent( e );
    234 				}
    235
    236 				if( !e.isConsumed() )
    237 				{
    238 					KeyStroke ks = KeyStroke.getKeyStrokeForEvent( e );
    239 					if( ks.equals( UISupport.getKeyStroke( "alt C" )))
    240 					{
    241 						mainTree.collapsePath( selectionPath );
    242 						e.consume();
    243 					}
    244 					else if( ks.equals( UISupport.getKeyStroke( "alt E" )))
    245 					{
    246 						mainTree.collapsePath( selectionPath );
    247 						int row = mainTree.getSelectionRows()[0];
    248 						TreePath nextPath = mainTree.getPathForRow( row+1 );
    249
    250 						TreePath path = mainTree.getPathForRow( row );
    251 						while( path != null && !path.equals( nextPath ))
    252 						{
    253 							mainTree.expandRow( row );
    254 							path = mainTree.getPathForRow( ++row );
    255 						}
    256
    257 						e.consume();
    258 					}
    259 				}
    260 			}
    261 		}
    262 	}
    263
    264 	public class InternalTreeSelectionListener implements TreeSelectionListener
    265    {
    266       public void valueChanged(TreeSelectionEvent e)
    267       {
    268          Object obj = e.getPath().getLastPathComponent();
    269          if (obj instanceof SoapUITreeNode)
    270          {
    271             SoapUITreeNode treeNode = (SoapUITreeNode) obj;
    272
    273             if( !listeners.isEmpty() )
    274             {
    275             	TreePath newPath = e.getNewLeadSelectionPath();
    276 	            NavigatorListener[] array = listeners.toArray( new NavigatorListener[listeners.size()]);
    277 	            for( NavigatorListener listener : array )
    278 	            {
    279 	            	listener.nodeSelected( newPath == null ? null : treeNode );
    280 	            }
    281             }
    282          }
    283       }
    284    }
    285
    286 	public class TreeMouseListener extends MouseAdapter
    287    {
    288       public void mouseClicked(MouseEvent e)
    289       {
    290          if (e.isPopupTrigger())
    291             showPopup(e);
    292          else if (e.getClickCount() < 2)
    293             return;
    294          if (mainTree.getSelectionCount() != 1)
    295             return;
    296
    297          int row = mainTree.getRowForLocation( e.getX(), e.getY() );
    298          TreePath path = mainTree.getSelectionPath();
    299          if( path == null && row == -1 )
    300          	return;
    301
    302          if( path == null || mainTree.getRowForPath( path ) != row )
    303          	mainTree.setSelectionRow( row );
    304
    305          SoapUITreeNode node = (SoapUITreeNode) path.getLastPathComponent();
    306          ActionList actions = node.getActions();
    307          if( actions != null )
    308          	actions.performDefaultAction( new ActionEvent( mainTree, 0, null ));
    309       }
    310
    311       public void mousePressed(MouseEvent e)
    312       {
    313          if (e.isPopupTrigger())
    314             showPopup(e);
    315       }
    316
    317       public void mouseReleased(MouseEvent e)
    318       {
    319          if (e.isPopupTrigger())
    320             showPopup(e);
    321       }
    322
    323       private void showPopup(MouseEvent e)
    324       {
    325          TreePath path = mainTree.getPathForLocation((int) e.getPoint().getX(), (int) e.getPoint().getY());
    326          if (path == null)
    327             return;
    328          SoapUITreeNode node = (SoapUITreeNode) path.getLastPathComponent();
    329
    330          JPopupMenu popupMenu = node.getPopup();
    331          if (popupMenu == null)
    332             return;
    333
    334          mainTree.setSelectionPath(path);
    335
    336          popupMenu.show(mainTree, e.getX(), e.getY());
    337       }
    338    }
    339
    340 	public boolean isVisible( TreePath path )
    341 	{
    342 		return mainTree.isVisible( path );
    343 	}
    344
    345 	public boolean isExpanded( TreePath path )
    346 	{
    347 		return mainTree.isExpanded( path );
    348 	}
    349 }