View Javadoc

1   /*
2    *  soapUI, copyright (C) 2006 eviware.com 
3    *
4    *  soapUI is free software; you can redistribute it and/or modify it under the 
5    *  terms of the GNU Lesser General Public License as published by the Free Software Foundation; 
6    *  either version 2.1 of the License, or (at your option) any later version.
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.impl.wsdl.panels.request.components.editor;
14  
15  import java.awt.BorderLayout;
16  import java.awt.CardLayout;
17  import java.awt.Color;
18  import java.awt.event.ActionEvent;
19  import java.beans.PropertyChangeEvent;
20  import java.beans.PropertyChangeListener;
21  import java.util.ArrayList;
22  import java.util.HashMap;
23  import java.util.List;
24  import java.util.Map;
25  
26  import javax.swing.AbstractAction;
27  import javax.swing.JComponent;
28  import javax.swing.JPanel;
29  import javax.swing.JSplitPane;
30  import javax.swing.JTabbedPane;
31  import javax.swing.JToggleButton;
32  import javax.swing.event.ChangeEvent;
33  import javax.swing.event.ChangeListener;
34  
35  import com.eviware.soapui.support.UISupport;
36  import com.eviware.soapui.support.components.JXToolBar;
37  import com.eviware.soapui.support.components.VTextIcon;
38  import com.eviware.soapui.support.components.VerticalTabbedPaneUI;
39  
40  @SuppressWarnings("serial")
41  public class XmlEditor extends JPanel implements PropertyChangeListener, XmlLocationListener
42  {
43  	private static final float DEFAULT_DIVIDER_LOCATION = 0.7F;
44  	private JTabbedPane inputTabs;
45  	private List<XmlEditorView> views = new ArrayList<XmlEditorView>();
46  	private XmlEditorView currentView;
47  	private XmlDocument xmlDocument;
48  	private List<XmlInspector> inspectors = new ArrayList<XmlInspector>();
49  	protected JSplitPane mainSplit;
50  	private JXToolBar inspectToolbar;
51  	private Map<XmlInspector,JToggleButton> inspectorButtons = new HashMap<XmlInspector,JToggleButton>();
52  	private XmlInspector currentInspector;
53  	private JPanel inspectorPanel;
54  	private int lastDividerLocation = 0;
55  
56  	public XmlEditor( XmlDocument xmlDocument )
57  	{
58  		super( new BorderLayout() );
59  		this.xmlDocument = xmlDocument;
60  		
61  		setBackground(Color.LIGHT_GRAY);
62  	   inputTabs = new JTabbedPane(JTabbedPane.LEFT, JTabbedPane.SCROLL_TAB_LAYOUT);
63     	inputTabs.setUI(new VerticalTabbedPaneUI());
64  	   
65  		inputTabs.setFont(inputTabs.getFont().deriveFont(8));
66  		
67  		inputTabs.addChangeListener( new ChangeListener() 
68  		{
69  			public void stateChanged( ChangeEvent e )
70  			{
71  				int currentViewIndex = views.indexOf( currentView );
72  				
73  				if( currentView != null )
74  				{
75  					if( inputTabs.getSelectedIndex() == currentViewIndex)
76  						return;
77  					
78  					if( !currentView.deactivate() )
79  					{
80  						inputTabs.setSelectedIndex( currentViewIndex );
81  						return;
82  					}
83  				}
84  				
85  				XmlEditorView previousView = currentView;
86  				int selectedIndex = inputTabs.getSelectedIndex();
87  				if( selectedIndex == -1 )
88  				{
89  					currentView = null;
90  					return;
91  				}
92  				
93  				currentView = views.get( selectedIndex );
94  				
95  				if( currentView != null && !currentView.activate( previousView == null ? null : previousView.getLocation() ))
96  				{
97  					inputTabs.setSelectedIndex( currentViewIndex );
98  					if( currentViewIndex == -1 )
99  						return;
100 					
101 					currentView.getComponent().requestFocus();
102 				}
103 				
104 				if( !currentView.isInspectable() && currentInspector != null )
105 					lastDividerLocation = mainSplit.getDividerLocation();
106 				
107 				inspectorPanel.setVisible( currentView.isInspectable() && currentInspector != null );
108 				inspectToolbar.setVisible( currentView.isInspectable()  );
109 				
110 				if( currentView.isInspectable() && currentInspector != null )
111 				{
112 					if( lastDividerLocation == 0 )
113 						mainSplit.setDividerLocation( DEFAULT_DIVIDER_LOCATION );
114 					else
115 						mainSplit.setDividerLocation( lastDividerLocation );
116 				}
117 			}
118 		} );
119 		
120 		inspectorPanel = new JPanel(new CardLayout());
121 		inspectorPanel.setVisible( false );
122 		
123 		mainSplit = new JSplitPane( JSplitPane.VERTICAL_SPLIT, inputTabs, inspectorPanel );
124 		mainSplit.setDividerSize( 10 );
125 		mainSplit.setBorder( null );
126 		mainSplit.setOneTouchExpandable( false );
127 		
128 		add(mainSplit, BorderLayout.CENTER);
129 		add( createInspectButtons(), BorderLayout.PAGE_END  );
130 		
131 		mainSplit.setResizeWeight( 0.8 );
132 	}
133 	
134 	private JComponent createInspectButtons()
135 	{
136 		inspectToolbar = UISupport.createToolbar();
137 		inspectToolbar.addSpace( 10 );
138 		inspectToolbar.setBackground( Color.WHITE );
139 		inspectToolbar.setOpaque( true );
140 		return inspectToolbar;
141 	}
142 
143 	public void addInspector( XmlInspector inspector )
144 	{
145 		if( inspectors.size() > 0 )
146 		{
147 			inspectToolbar.addSeparator();
148 		}
149 		
150 		inspectors.add( inspector );
151 		inspectorPanel.add( inspector.getComponent(), inspector.getClass().getName() );
152 
153 		JToggleButton button = new JToggleButton( new SelectInspectorAction( inspector ));
154 		
155 		button.setToolTipText( inspector.getDescription() );
156 		button.setOpaque( true );
157 		
158 		inspectorButtons.put( inspector, button );
159 		inspectToolbar.add( button );
160 		inspectToolbar.addRelatedGap();
161 	}
162 	
163 	public void addEditorView( XmlEditorView editorView )
164 	{
165 		views.add( editorView );
166 		
167 		inputTabs.addTab( null, new VTextIcon(inputTabs, editorView.getTitle(), VTextIcon.ROTATE_LEFT ),
168 				editorView.getComponent() );
169 
170 		editorView.addPropertyChangeListener( XmlEditorView.TITLE_PROPERTY, this );
171 		editorView.addLocationListener( this );
172 		
173 		editorView.setXmlDocument( xmlDocument );
174 	}
175 
176 	public void propertyChange(PropertyChangeEvent evt)
177 	{
178 		int ix = views.indexOf( evt.getSource() );
179 		if( ix == -1 )
180 			return;
181 		
182 		inputTabs.setTitleAt( ix, (String) evt.getNewValue() );
183 	}
184 	
185 	public void selectView( int viewIndex )
186 	{
187 		inputTabs.setSelectedIndex( viewIndex );
188 	}
189 	
190 	public void requestFocus()
191 	{
192 		if( currentView != null )
193 			currentView.getComponent().requestFocus();
194 	}
195 
196 	public final XmlDocument getXmlDocument()
197 	{
198 		return xmlDocument;
199 	}
200 	
201 	public boolean hasFocus()
202 	{
203 		return currentView == null ? false : currentView.getComponent().hasFocus();
204 	}
205 
206 	public final void setXmlDocument(XmlDocument xmlDocument)
207 	{
208 		this.xmlDocument = xmlDocument;
209 		
210 		for( XmlEditorView view : views )
211 		{
212 			view.setXmlDocument( xmlDocument );
213 		}
214 	}
215 
216 	public final XmlEditorView getCurrentView()
217 	{
218 		return currentView;
219 	}
220 
221 	public final JTabbedPane getInputTabs()
222 	{
223 		return inputTabs;
224 	}
225 
226 	public final List<XmlEditorView> getViews()
227 	{
228 		return views;
229 	}
230 	
231 	public XmlEditorView getView( String viewId )
232 	{
233 		for( XmlEditorView view : views )
234 		{
235 			if( view.getViewId().equals( viewId ))
236 				return view;
237 		}
238 		
239 		return null;
240 	}
241 	
242 	public XmlInspector getInspector( String inspectorId  )
243 	{
244 		for( XmlInspector inspector : inspectors )
245 		{
246 			if( inspector.getInspectorId().equals( inspectorId ))
247 				return inspector;
248 		}
249 		
250 		return null;
251 	}
252 
253 	public void locationChanged(XmlLocation location)
254 	{
255 		if( location != null )
256 		{
257 			for( XmlInspector inspector : inspectors )
258 			{
259 				inspector.locationChanged( location );
260 			}
261 		}
262 	}
263 	
264 	public void setEditable( boolean enabled )
265 	{
266 		for( XmlEditorView view : views )
267 		{
268 			view.setEditable( enabled );
269 		}
270 	}
271 	
272 	public class SelectInspectorAction extends AbstractAction implements PropertyChangeListener
273 	{
274 		private final XmlInspector inspector;
275 
276 		public SelectInspectorAction( XmlInspector inspector )
277 		{
278 			super( inspector.getTitle());
279 			this.inspector = inspector;
280 			inspector.addPropertyChangeListener( this );
281 		}
282 
283 		public void actionPerformed( ActionEvent arg0 )
284 		{
285 			JToggleButton button = inspectorButtons.get( inspector );
286 			if( !button.isSelected() )
287 			{
288 				currentInspector = null;
289 				button.setBackground( inspectToolbar.getBackground() );
290 				lastDividerLocation = mainSplit.getDividerLocation();
291 				inspectorPanel.setVisible( false );
292 			}
293 			else
294 			{
295 				if( currentInspector != null )
296 					inspectorButtons.get( currentInspector ).setSelected( false );
297 				
298 				currentInspector = inspector;
299 				button.setBackground( Color.WHITE );
300 				
301 				if( !inspectorPanel.isVisible() )
302 				{
303 					inspectorPanel.setVisible( true );
304 					if( lastDividerLocation == 0 )
305 						mainSplit.setDividerLocation( DEFAULT_DIVIDER_LOCATION );
306 					else
307 						mainSplit.setDividerLocation( lastDividerLocation );
308 				}
309 				
310 				CardLayout cards = ( CardLayout ) inspectorPanel.getLayout();
311 				cards.show( inspectorPanel, inspector.getClass().getName() );
312 			}
313 		}
314 
315 		public void propertyChange( PropertyChangeEvent evt )
316 		{
317 			if( evt.getPropertyName().equals( XmlInspector.TITLE_PROPERTY ))
318 				putValue( AbstractAction.NAME, evt.getNewValue() );
319 			else if( evt.getPropertyName().equals( XmlInspector.DESCRIPTION_PROPERTY ))
320 				putValue( AbstractAction.SHORT_DESCRIPTION, evt.getNewValue() );
321 			else if( evt.getPropertyName().equals( XmlInspector.ENABLED_PROPERTY ))
322 			{
323 				boolean enable = ((Boolean)evt.getNewValue()).booleanValue();
324 				setEnabled( enable );
325 				
326 				if( !enable && currentInspector == inspector )
327 				{
328 					inspectorButtons.get( currentInspector ).setSelected( false );
329 				}
330 			}
331 		}
332 	}
333 }