View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2008 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.support.components;
14  
15  import com.eviware.soapui.SoapUI;
16  import com.eviware.soapui.model.ModelItem;
17  import com.eviware.soapui.model.tree.SoapUITreeNode;
18  import com.eviware.soapui.model.tree.nodes.support.EmptyModelItem;
19  import com.eviware.soapui.support.ListDataListenerAdapter;
20  import com.eviware.soapui.support.UISupport;
21  import com.eviware.soapui.support.swing.ModelItemListMouseListener;
22  import com.eviware.soapui.support.types.StringList;
23  import com.eviware.soapui.ui.support.DefaultDesktopPanel;
24  
25  import javax.swing.*;
26  import javax.swing.event.*;
27  import javax.swing.tree.TreePath;
28  import java.awt.*;
29  import java.awt.event.ActionEvent;
30  import java.util.HashMap;
31  import java.util.Map;
32  
33  public class ModelItemListDesktopPanel extends DefaultDesktopPanel
34  {
35  	private final ModelItem[] modelItems;
36  	private JList list;
37  	private ItemsListModel listModel;
38  	private InternalTreeModelListener treeModelListener;
39  	private Map<ModelItem,StringList> detailInfo = new HashMap<ModelItem, StringList>();
40  	private JList detailList;
41  	private DetailsListModel detailListModel;
42  
43  	public ModelItemListDesktopPanel( String title, String description, ModelItem [] modelItems )
44  	{
45  		super( title, description, new JPanel( new BorderLayout() ) );
46  		this.modelItems = modelItems;
47  		
48  		buildUI();
49  		
50  		treeModelListener = new InternalTreeModelListener();
51  		SoapUI.getNavigator().getMainTree().getModel().addTreeModelListener( treeModelListener );
52  	}
53  	
54  	public void addDetails( ModelItem modelItem, String details )
55  	{
56  		if( !detailInfo.containsKey( modelItem ))
57  			detailInfo.put( modelItem, new StringList() );
58  		
59  		detailInfo.get( modelItem ).add( details );
60  	}
61  
62  	private void buildUI()
63  	{
64  		JPanel p = ( JPanel ) getComponent();
65  		
66  		p.add( UISupport.buildDescription( getTitle(), getDescription(), null ), BorderLayout.NORTH );
67  		p.add( buildModelItemList(), BorderLayout.CENTER );
68  	}
69  	
70  	@Override
71  	public boolean onClose( boolean canCancel )
72  	{
73  		SoapUI.getNavigator().getMainTree().getModel().removeTreeModelListener( treeModelListener );
74  		return super.onClose( canCancel );
75  	}
76  
77  	private Component buildModelItemList()
78  	{
79  		listModel = new ItemsListModel( modelItems );
80  		
81  		list = new JList( listModel);
82  		list.setCellRenderer( new ItemListCellRenderer() );
83  		ModelItemListMouseListener modelItemListMouseListener = new ModelItemListMouseListener();
84  		JPopupMenu popupMenu = new JPopupMenu();
85  		popupMenu.add( new RemoveAction() );
86  		popupMenu.add( new HighlightAction() );
87  		
88  		modelItemListMouseListener.setPopupMenu( popupMenu );
89  		list.addMouseListener( modelItemListMouseListener );
90  		listModel.addListDataListener( new ListDataListenerAdapter() {
91  
92  			@Override
93  			public void intervalRemoved( ListDataEvent e )
94  			{
95  				if( listModel.isEmpty() )
96  				{
97  					SwingUtilities.invokeLater( new Runnable() {
98  
99  						public void run()
100 						{
101 							SoapUI.getDesktop().closeDesktopPanel( ModelItemListDesktopPanel.this );
102 						}} );
103 				}
104 			}} );
105 		
106 		list.addListSelectionListener( new ListSelectionListener() {
107 
108 			public void valueChanged( ListSelectionEvent e )
109 			{
110 				detailListModel.refresh();
111 			}} );
112 		
113 		JInspectorPanelImpl inspectorPanel = new JInspectorPanelImpl( new JScrollPane( list ) );
114 		inspectorPanel.addInspector( new JComponentInspector<JComponent>( buildDetails(), "Details", 
115 					"Shows detailed information for the selected item", true ) );
116 		
117 		return inspectorPanel;
118 	}
119 	
120 	private JComponent buildDetails()
121 	{
122 		detailListModel = new DetailsListModel();
123 		detailList = new JList( detailListModel );
124 		return new JScrollPane( detailList );
125 	}
126 
127 	private class DetailsListModel extends AbstractListModel
128 	{
129 		public Object getElementAt( int index )
130 		{
131 			ModelItem modelItem = ( ModelItem ) list.getSelectedValue();
132 			if( modelItem == null || !detailInfo.containsKey( modelItem ))
133 				return null;
134 			else 
135 				return detailInfo.get( modelItem ).get( index );
136 		}
137 
138 		public void refresh()
139 		{
140 			fireIntervalAdded( this, 0, getSize()-1 );
141 		}
142 
143 		public int getSize()
144 		{
145 			ModelItem modelItem = ( ModelItem ) list.getSelectedValue();
146 			if( modelItem == null || !detailInfo.containsKey( modelItem ))
147 				return 0;
148 			else 
149 				return detailInfo.get( modelItem ).size();
150 		}
151 	}
152 	
153 	private class ItemsListModel extends DefaultListModel
154 	{
155 		public ItemsListModel( ModelItem[] modelItems )
156 		{
157 			for( ModelItem item : modelItems )
158 				addElement( item );
159 		}
160 
161 		public void nodesChanged()
162 		{
163 			fireContentsChanged( this, 0, getSize()-1 );
164 		}
165 	}
166 	
167 	private class RemoveAction extends AbstractAction
168 	{
169 		public RemoveAction()
170 		{
171 			super( "Remove" );
172 			putValue( SHORT_DESCRIPTION, "Removes this item from the list" );
173 		}
174 		
175 		public void actionPerformed( ActionEvent e )
176 		{
177 			int ix = list.getSelectedIndex();
178 			if( ix != -1 && UISupport.confirm( "Remove selected item from list?", "Remove Item" ))
179 				listModel.remove( ix );
180 		}
181 	}
182 	
183 	private class HighlightAction extends AbstractAction
184 	{
185 		public HighlightAction()
186 		{
187 			super( "Select in Tree" );
188 			putValue( SHORT_DESCRIPTION, "Selects this node in the Navigator Tree" );
189 		}
190 		
191 		public void actionPerformed( ActionEvent e )
192 		{
193 			int ix = list.getSelectedIndex();
194 			if( ix != -1 )
195 				UISupport.select( ( ModelItem ) listModel.getElementAt( ix ));
196 		}
197 	}
198 	
199 	private final class InternalTreeModelListener implements TreeModelListener
200 	{
201 		public void treeNodesChanged( TreeModelEvent e )
202 		{
203 			listModel.nodesChanged();
204 		}
205 
206 		public void treeNodesInserted( TreeModelEvent e )
207 		{
208 		}
209 
210 		public void treeNodesRemoved( TreeModelEvent e )
211 		{
212 			SwingUtilities.invokeLater( new Runnable() {
213 
214 				public void run()
215 				{
216 					for( int c = 0; c < listModel.getSize(); c++ )
217 					{
218 						if( SoapUI.getNavigator().getTreePath( ( ModelItem ) listModel.elementAt( c )) == null )
219 						{
220 							listModel.remove( c );
221 							c--;
222 						}
223 					}
224 				}} );
225 		}
226 
227 		public void treeStructureChanged( TreeModelEvent e )
228 		{
229 		}
230 	}
231 
232 	private class ItemListCellRenderer extends DefaultListCellRenderer
233 	{
234 		public Component getListCellRendererComponent( JList list, Object value, int index, boolean isSelected, boolean cellHasFocus )
235 		{
236 			JLabel label = ( JLabel ) super.getListCellRendererComponent( list, value, index, isSelected, cellHasFocus );
237 			
238 			if( value instanceof ModelItem )
239 			{
240 				ModelItem item = ( ModelItem ) value;
241 				TreePath treePath = SoapUI.getNavigator().getTreePath( item );
242 				
243 				if( treePath == null )
244 				{
245 					if( !(item instanceof EmptyModelItem))
246 					{
247 						//listModel.setElementAt( new EmptyModelItem( "<removed>", item.getIcon()), index );
248 					}
249 					
250 					label.setText( "<removed>" );
251 					label.setToolTipText( null );
252 				}
253 				else
254 				{
255 					String str = item.getName() + " [";
256 					
257 					for( int c = 1; c < treePath.getPathCount(); c++ )
258 					{
259 						SoapUITreeNode comp = ( SoapUITreeNode ) treePath.getPathComponent( c );
260 						if( comp.getModelItem() instanceof EmptyModelItem )
261 							continue;
262 						
263 						if( c > 1 )
264 							str += " - ";
265 						
266 						str += comp.toString();
267 					}
268 					
269 					str += "]";
270 				
271 					label.setText( str);
272 					label.setToolTipText( item.getDescription() );
273 				}
274 				
275 				label.setIcon( item.getIcon() );
276 				label.setBorder( BorderFactory.createEmptyBorder( 2, 2, 2, 2 ));
277 			}
278 			
279 			return label;
280 		}
281 	}
282 }