View Javadoc

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