1
2
3
4
5
6
7
8
9
10
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
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 }