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