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 @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 }