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