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.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 			@Override
110 			public void intervalRemoved( ListDataEvent e )
111 			{
112 				if( listModel.isEmpty() )
113 				{
114 					SwingUtilities.invokeLater( new Runnable() {
115 
116 						public void run()
117 						{
118 							SoapUI.getDesktop().closeDesktopPanel( ModelItemListDesktopPanel.this );
119 						}} );
120 				}
121 			}} );
122 		
123 		list.addListSelectionListener( new ListSelectionListener() {
124 
125 			public void valueChanged( ListSelectionEvent e )
126 			{
127 				detailListModel.refresh();
128 			}} );
129 		
130 		JInspectorPanel inspectorPanel = new JInspectorPanel( new JScrollPane( list ) );
131 		inspectorPanel.addInspector( new JComponentInspector( buildDetails(), "Details", 
132 					"Shows detailed information for the selected item", true ) );
133 		
134 		return inspectorPanel;
135 	}
136 	
137 	private JComponent buildDetails()
138 	{
139 		detailListModel = new DetailsListModel();
140 		detailList = new JList( detailListModel );
141 		return new JScrollPane( detailList );
142 	}
143 
144 	private class DetailsListModel extends AbstractListModel
145 	{
146 		public Object getElementAt( int index )
147 		{
148 			ModelItem modelItem = ( ModelItem ) list.getSelectedValue();
149 			if( modelItem == null || !detailInfo.containsKey( modelItem ))
150 				return null;
151 			else 
152 				return detailInfo.get( modelItem ).get( index );
153 		}
154 
155 		public void refresh()
156 		{
157 			fireIntervalAdded( this, 0, getSize()-1 );
158 		}
159 
160 		public int getSize()
161 		{
162 			ModelItem modelItem = ( ModelItem ) list.getSelectedValue();
163 			if( modelItem == null || !detailInfo.containsKey( modelItem ))
164 				return 0;
165 			else 
166 				return detailInfo.get( modelItem ).size();
167 		}
168 	}
169 	
170 	private class ItemsListModel extends DefaultListModel
171 	{
172 		public ItemsListModel( ModelItem[] modelItems )
173 		{
174 			for( ModelItem item : modelItems )
175 				addElement( item );
176 		}
177 
178 		public void nodesChanged()
179 		{
180 			fireContentsChanged( this, 0, getSize()-1 );
181 		}
182 	}
183 	
184 	private class RemoveAction extends AbstractAction
185 	{
186 		public RemoveAction()
187 		{
188 			super( "Remove" );
189 			putValue( SHORT_DESCRIPTION, "Removes this item from the list" );
190 		}
191 		
192 		public void actionPerformed( ActionEvent e )
193 		{
194 			int ix = list.getSelectedIndex();
195 			if( ix != -1 && UISupport.confirm( "Remove selected item from list?", "Remove Item" ))
196 				listModel.remove( ix );
197 		}
198 	}
199 	
200 	private class HighlightAction extends AbstractAction
201 	{
202 		public HighlightAction()
203 		{
204 			super( "Select in Tree" );
205 			putValue( SHORT_DESCRIPTION, "Selects this node in the Navigator Tree" );
206 		}
207 		
208 		public void actionPerformed( ActionEvent e )
209 		{
210 			int ix = list.getSelectedIndex();
211 			if( ix != -1 )
212 				UISupport.select( ( ModelItem ) listModel.getElementAt( ix ));
213 		}
214 	}
215 	
216 	private final class InternalTreeModelListener implements TreeModelListener
217 	{
218 		public void treeNodesChanged( TreeModelEvent e )
219 		{
220 			listModel.nodesChanged();
221 		}
222 
223 		public void treeNodesInserted( TreeModelEvent e )
224 		{
225 		}
226 
227 		public void treeNodesRemoved( TreeModelEvent e )
228 		{
229 			SwingUtilities.invokeLater( new Runnable() {
230 
231 				public void run()
232 				{
233 					for( int c = 0; c < listModel.getSize(); c++ )
234 					{
235 						if( SoapUI.getNavigator().getTreePath( ( ModelItem ) listModel.elementAt( c )) == null )
236 						{
237 							listModel.remove( c );
238 							c--;
239 						}
240 					}
241 				}} );
242 		}
243 
244 		public void treeStructureChanged( TreeModelEvent e )
245 		{
246 		}
247 	}
248 
249 	private class ItemListCellRenderer extends DefaultListCellRenderer
250 	{
251 		public Component getListCellRendererComponent( JList list, Object value, int index, boolean isSelected, boolean cellHasFocus )
252 		{
253 			JLabel label = ( JLabel ) super.getListCellRendererComponent( list, value, index, isSelected, cellHasFocus );
254 			
255 			if( value instanceof ModelItem )
256 			{
257 				ModelItem item = ( ModelItem ) value;
258 				TreePath treePath = SoapUI.getNavigator().getTreePath( item );
259 				
260 				if( treePath == null )
261 				{
262 					if( !(item instanceof EmptyModelItem))
263 					{
264 						//listModel.setElementAt( new EmptyModelItem( "<removed>", item.getIcon()), index );
265 					}
266 					
267 					label.setText( "<removed>" );
268 					label.setToolTipText( null );
269 				}
270 				else
271 				{
272 					String str = item.getName() + " [";
273 					
274 					for( int c = 1; c < treePath.getPathCount(); c++ )
275 					{
276 						SoapUITreeNode comp = ( SoapUITreeNode ) treePath.getPathComponent( c );
277 						if( comp.getModelItem() instanceof EmptyModelItem )
278 							continue;
279 						
280 						if( c > 1 )
281 							str += " - ";
282 						
283 						str += comp.toString();
284 					}
285 					
286 					str += "]";
287 				
288 					label.setText( str);
289 					label.setToolTipText( item.getDescription() );
290 				}
291 				
292 				label.setIcon( item.getIcon() );
293 				label.setBorder( BorderFactory.createEmptyBorder( 2, 2, 2, 2 ));
294 			}
295 			
296 			return label;
297 		}
298 	}
299 }