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