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.model.tree;
14  
15  import java.awt.Component;
16  import java.awt.Rectangle;
17  import java.beans.PropertyChangeEvent;
18  import java.beans.PropertyChangeListener;
19  import java.util.Collections;
20  import java.util.Comparator;
21  import java.util.List;
22  
23  import javax.swing.JPopupMenu;
24  import javax.swing.JTree;
25  import javax.swing.event.TreeModelEvent;
26  import javax.swing.tree.TreePath;
27  
28  import com.eviware.soapui.SoapUI;
29  import com.eviware.soapui.model.ModelItem;
30  import com.eviware.soapui.model.settings.SettingsListener;
31  import com.eviware.soapui.model.testsuite.TestStep;
32  import com.eviware.soapui.model.util.PanelBuilderRegistry;
33  import com.eviware.soapui.support.action.swing.ActionList;
34  import com.eviware.soapui.support.action.swing.ActionListBuilder;
35  import com.eviware.soapui.support.action.swing.ActionSupport;
36  
37  /***
38   * Abstract base class for SoapUITreeNode implementations
39   * 
40   * @author Ole.Matzura
41   */
42  
43  public abstract class AbstractModelItemTreeNode<T extends ModelItem> implements SoapUITreeNode, PropertyChangeListener
44  {
45     private final T modelItem;
46  	private final ModelItem parentItem;
47  	private final SoapUITreeModel treeModel;
48  	private List<? extends SoapUITreeNode> orderItems;
49  	private String orderSetting;
50  	private InternalSettingsListener internalSettingsListener;
51  
52     protected AbstractModelItemTreeNode( T modelItem, ModelItem parentItem, SoapUITreeModel treeModel )
53     {
54        this.modelItem = modelItem;
55  		this.parentItem = parentItem;
56  		this.treeModel = treeModel;
57        
58        modelItem.addPropertyChangeListener( this );
59     }
60     
61     public SoapUITreeModel getTreeModel()
62     {
63        return treeModel;
64     }
65  
66     public Component getOverviewPanel()
67     {
68     	return PanelBuilderRegistry.getPanelBuilder( modelItem ).buildOverviewPanel( modelItem );
69     }
70     
71     public T getModelItem()
72     {
73        return modelItem;
74     }
75  
76     public boolean valueChanged(Object newValue)
77     {
78        return false;
79     }
80  
81     public boolean isLeaf()
82     {
83        return getChildCount() == 0;
84     }
85  
86     public int getChildCount()
87     {
88        return orderItems == null ? 0 : orderItems.size();
89     }
90  
91     public SoapUITreeNode getChildNode(int index)
92     {
93     	return orderItems == null ? null : orderItems.get( index );
94     }
95  
96     public int getIndexOfChild(Object child)
97     {
98     	return orderItems == null ? -1 : orderItems.indexOf( child );
99     }
100    
101    public String toString()
102    {
103       return modelItem instanceof TestStep ? ((TestStep)modelItem).getLabel() : modelItem.getName();
104    }
105    
106    public JPopupMenu getPopup()
107    {
108    	return ActionSupport.buildPopup( getActions() );
109    }
110 
111 	public ActionList getActions()
112 	{
113 		return ActionListBuilder.buildActions( modelItem );
114 	}
115    
116    public SoapUITreeNode getParentTreeNode()
117    {
118       return treeModel.getTreeNode( parentItem );
119    }
120 
121    public void propertyChange(PropertyChangeEvent evt)
122    {
123    	String propertyName = evt.getPropertyName();
124    	if( propertyName.equals( ModelItem.NAME_PROPERTY ) || propertyName.equals( TestStep.LABEL_PROPERTY ))
125    	{
126    		// use this since length has probably changed
127    		getTreeModel().notifyNodeChanged( this );
128    	}
129    	else if( propertyName.equals( ModelItem.ICON_PROPERTY ))
130    	{
131    		// hack to improve rendering performance
132    		JTree mainTree = SoapUI.getNavigator().getMainTree();
133 			TreePath nodePath = getTreeModel().getPath( this );
134    		Rectangle rowBounds = mainTree.getPathBounds( nodePath );
135    		if( rowBounds != null )
136    		{
137    			mainTree.repaint( rowBounds );
138    		}
139    	}
140    }
141    
142    public void release()
143    {
144    	modelItem.removePropertyChangeListener( this );
145    	
146    	if( internalSettingsListener != null )
147    		SoapUI.getSettings().removeSettingsListener( internalSettingsListener );
148    	
149    	getTreeModel().unmapModelItem( modelItem );
150    }
151 
152    public <T2 extends SoapUITreeNode> void initOrdering( List<T2> items, String setting )
153 	{
154 		this.orderItems = items;
155 		this.orderSetting = setting;
156 		
157 		internalSettingsListener = new InternalSettingsListener( this, setting);
158 		SoapUI.getSettings().addSettingsListener( internalSettingsListener );
159 		sortModelItems( items, setting );
160 	}
161 	
162 	private final class InternalSettingsListener implements SettingsListener
163 	{
164 		private final AbstractModelItemTreeNode node;
165 		private final String setting;
166 
167 		public InternalSettingsListener(AbstractModelItemTreeNode node, String setting)
168 		{
169 			this.node = node;
170 			this.setting = setting;
171 		}
172 
173 		public void settingChanged(String name, String newValue, String oldValue)
174 		{
175 			if( name.equals( setting ))
176 			{
177 				if( oldValue == null )
178 					oldValue = "false";
179 				
180 				if( newValue == null )
181 					newValue = "false";
182 				
183 				if( !oldValue.equals( newValue ))
184 				{
185 					TreePath path = getTreeModel().getPath( AbstractModelItemTreeNode.this );
186 					node.reorder( SoapUI.getNavigator().isVisible( path ) && SoapUI.getNavigator().isExpanded( path ));
187 				}
188 			}
189 		}}
190 	
191 	public void reorder( boolean notify )
192 	{
193 		if( orderItems != null )
194 		{
195 			sortModelItems( orderItems, orderSetting );
196 			
197 			if( notify )
198 			{
199 				getTreeModel().notifyStructureChanged( new TreeModelEvent( this, getTreeModel().getPath( this )));
200 			}
201 		}
202 	}
203 	
204 	public <T2 extends SoapUITreeNode> void sortModelItems( List<T2> modelItems, final String setting )
205 	{
206 		Collections.sort( modelItems, new Comparator<T2>() 
207 				{
208 					public int compare(T2 o1, T2 o2)
209 					{
210 						String name1 = o1.getModelItem().getName();
211 						String name2 = o2.getModelItem().getName();
212 						
213 						if( name1 == null && name2 == null )
214 						{
215 							return 0;
216 						}
217 						else if( name1 == null )
218 						{
219 							return -1;
220 						}
221 						else if( name2 == null )
222 						{
223 							return 1;
224 						}
225 						else if( setting != null && SoapUI.getSettings().getBoolean( setting ))
226 						{
227 							return name1.compareToIgnoreCase( name2 );
228 						}
229 						else
230 						{
231 							return name1.compareTo( name2 );
232 						}
233 					}} );
234 	}
235 	
236 	public class ReorderPropertyChangeListener implements PropertyChangeListener
237 	{
238 		public void propertyChange( PropertyChangeEvent arg0 )
239 		{
240 			reorder( true );
241 			SoapUI.getNavigator().selectModelItem( (ModelItem)arg0.getSource() );
242 		}
243 	}
244 }