KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > xml > wsdl > ui > view > grapheditor > widget > AbstractWidget


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19 /*
20  * AbstractWidget.java
21  *
22  * Created on August 15, 2006, 11:23 PM
23  *
24  * To change this template, choose Tools | Template Manager
25  * and open the template in the editor.
26  */

27
28 package org.netbeans.modules.xml.wsdl.ui.view.grapheditor.widget;
29
30 import java.awt.EventQueue JavaDoc;
31 import java.awt.Graphics2D JavaDoc;
32 import java.awt.Paint JavaDoc;
33 import java.awt.Point JavaDoc;
34 import java.awt.Rectangle JavaDoc;
35 import java.awt.RenderingHints JavaDoc;
36 import java.awt.Shape JavaDoc;
37 import java.awt.geom.Rectangle2D JavaDoc;
38 import java.util.ArrayList JavaDoc;
39 import java.util.Collections JavaDoc;
40 import java.util.HashSet JavaDoc;
41 import java.util.List JavaDoc;
42 import java.util.ListIterator JavaDoc;
43 import java.util.Set JavaDoc;
44
45 import javax.swing.Action JavaDoc;
46 import javax.swing.JPopupMenu JavaDoc;
47 import javax.swing.SwingUtilities JavaDoc;
48
49 import org.netbeans.api.visual.action.ActionFactory;
50 import org.netbeans.api.visual.action.PopupMenuProvider;
51 import org.netbeans.api.visual.model.ObjectState;
52 import org.netbeans.api.visual.widget.Scene;
53 import org.netbeans.api.visual.widget.Widget;
54 import org.netbeans.modules.xml.wsdl.model.WSDLComponent;
55 import org.netbeans.modules.xml.wsdl.model.WSDLModel;
56 import org.netbeans.modules.xml.wsdl.ui.view.treeeditor.NodesFactory;
57 import org.netbeans.modules.xml.xam.ComponentEvent;
58 import org.netbeans.modules.xml.xam.ComponentListener;
59 import org.netbeans.modules.xml.xam.Model;
60 import org.openide.actions.ReorderAction;
61 import org.openide.nodes.AbstractNode;
62 import org.openide.nodes.Children;
63 import org.openide.nodes.Node;
64 import org.openide.util.Lookup;
65 import org.openide.util.Utilities;
66 import org.openide.util.WeakListeners;
67 import org.openide.util.lookup.AbstractLookup;
68 import org.openide.util.lookup.InstanceContent;
69 import org.openide.util.lookup.ProxyLookup;
70 import org.openide.windows.TopComponent;
71
72 /**
73  * Class AbstractWidget is the base class for all widgets that represent
74  * a WSDL component.
75  *
76  * @author radval
77  * @author Nathan Fiedler
78  */

79 public abstract class AbstractWidget<T extends WSDLComponent> extends Widget
80         implements ComponentListener, PopupMenuProvider {
81     
82     /** The WSDL component this widget represents; may be null. */
83     private T wsdlComponent;
84     /** The Lookup for this widget. */
85     private Lookup widgetLookup;
86     /** The content of our customized Lookup. */
87     private InstanceContent lookupContent;
88     /** The Node for the WSDLComponent, if it has been created. */
89     private Node componentNode;
90     /** Used to weakly listen to the component model. */
91     private ComponentListener weakComponentListener;
92     /** store the WSDLModel representing the wsdl being edited **/
93     private WSDLModel model;
94     
95     
96     /**
97      * Creates a new instance of AbstractWidget.
98      *
99      * @param scene the widget Scene.
100      * @param component the corresponding WSDL component.
101      * @param lookup the Lookup for this widget.
102      */

103     public AbstractWidget(Scene scene, T component, Lookup lookup) {
104         super(scene);
105         model = ((PartnerScene)scene).getModel();
106         lookupContent = new InstanceContent();
107         widgetLookup = new ProxyLookup(new Lookup[] {
108             new AbstractLookup(lookupContent),
109             lookup
110         });
111         if (component != null) {
112             lookupContent.add(component);
113         }
114         setWSDLComponent(component);
115         getActions().addAction(ActionFactory.createPopupMenuAction(this));
116     }
117
118     /**
119      * Deletes the model component. Subclasses should in general avoid
120      * overriding this method and creating another transaction, as that
121      * will create another undoable edit on the undo/redo queue. Instead,
122      * override the postDeleteComponent(Model) method, which is invoked
123      * during the transaction, so any changes to the model will be
124      * captured in a single undoable edit.
125      */

126     protected void deleteComponent() {
127         if (wsdlComponent == null) {
128             return;
129         }
130         // Remove our compopnent listener.
131
registerListener(null);
132         try {
133             if (model.startTransaction()) {
134                 model.removeChildComponent(wsdlComponent);
135                 postDeleteComponent(model);
136             }
137         } finally {
138             model.endTransaction();
139         }
140         model = null;
141     }
142
143     public WSDLModel getModel() {
144         return model;
145     }
146     
147     /**
148      * Subclasses may override this method to make additional changes to
149      * the model within the same transaction as the one used to delete
150      * the model component.
151      *
152      * @param model the model that is in transaction.
153      */

154     protected void postDeleteComponent(@SuppressWarnings JavaDoc("unused")
155     Model model) {
156         // Do nothing here, as this is exclusively for subclasses to override.
157
}
158
159     /**
160      * Locates the TopComponent parent of the view containing the Scene
161      * that owns this widget, if possible.
162      *
163      * @return the parent TopComponent, or null if not found.
164      */

165     protected TopComponent findTopComponent() {
166         return (TopComponent) SwingUtilities.getAncestorOfClass(
167                 TopComponent.class, getScene().getView());
168     }
169
170     @Override JavaDoc
171     public Lookup getLookup() {
172         return widgetLookup;
173     }
174
175     /**
176      * Return the content of this widget's custom Lookup. Subclasses may
177      * add objects to this content, thereby altering the contents of the
178      * Lookup associated with this widget.
179      *
180      * @return Lookup content.
181      */

182     protected InstanceContent getLookupContent() {
183         return lookupContent;
184     }
185
186     /**
187      * Returns a Node for the WSDL component that this widget represents.
188      * If this widget does not have an assigned WSDL component, then this
189      * returns an AbstractNode with no interesting properties.
190      */

191     public synchronized Node getNode() {
192         if (componentNode == null) {
193             if (wsdlComponent == null) {
194                 // No component? Then supply a dummy node.
195
componentNode = new AbstractNode(Children.LEAF);
196             } else {
197                 // Use the factory to construct the Node.
198
NodesFactory factory = NodesFactory.getInstance();
199                 componentNode = factory.create(wsdlComponent);
200             }
201             componentNode = getNodeFilter(componentNode);
202         }
203         return componentNode;
204     }
205
206     /**
207      * Method for subclasses to have an opportunity to wrap the original
208      * Node in a FilterNode, which can then be customized to suit the
209      * individual widget (e.g. to filter the NewType list).
210      *
211      * the current widget is passed so that delete can work.
212      * @param original the Node to be filtered.
213      * @return the filtered node.
214      */

215     protected Node getNodeFilter(Node original) {
216         return new WidgetFilterNode(original, this);
217     }
218
219     public JPopupMenu JavaDoc getPopupMenu(Widget widget, Point JavaDoc point) {
220         Node node = getNode();
221         if (node != null && wsdlComponent != null) {
222             Set JavaDoc<WSDLComponent> set = new HashSet JavaDoc<WSDLComponent>();
223             set.add(getWSDLComponent());
224             ((PartnerScene) getScene()).setSelectedObjects(set);
225             TopComponent tc = findTopComponent();
226             Lookup lookup;
227             if (tc != null) {
228                 // Activate the node just as any explorer view would do.
229
tc.setActivatedNodes(new Node[] { node });
230                 // To get the explorer actions enabled, must have the
231
// lookup from the parent TopComponent.
232
lookup = tc.getLookup();
233             } else {
234                 lookup = Lookup.EMPTY;
235             }
236             // Remove the actions that we do not want to support in this view.
237
Action JavaDoc[] actions = node.getActions(true);
238             List JavaDoc<Action JavaDoc> list = new ArrayList JavaDoc<Action JavaDoc>();
239             Collections.addAll(list, actions);
240             updateActions(list);
241             actions = list.toArray(new Action JavaDoc[list.size()]);
242             return Utilities.actionsToPopup(actions, lookup);
243         }
244         return null;
245     }
246
247     /**
248      * Return the WSDL component this widget represents.
249      *
250      * @return WSDL component for this widget; may be null.
251      */

252     public T getWSDLComponent() {
253         return wsdlComponent;
254     }
255
256     @Override JavaDoc
257     protected void notifyStateChanged(ObjectState previousState, ObjectState state) {
258         super.notifyStateChanged(previousState, state);
259         //add delete action only if the widget is selected.
260
if (state.isSelected()) {
261             TopComponent tc = findTopComponent();
262             if (tc != null) {
263                 Node node = getNode();
264                 tc.setActivatedNodes(new Node[] { node });
265             }
266             
267         }
268         repaint();
269     }
270
271     /**
272      * Manage the listener registration with the component model. If the
273      * current component is non-null, removes this widget as a listener
274      * from that component's model. If the new component is non-null, adds
275      * a weak component listener to that component's model.
276      *
277      * @param component the component to listen to.
278      */

279     protected void registerListener(T component) {
280         if (wsdlComponent != null) {
281             wsdlComponent.getModel().removeComponentListener(weakComponentListener);
282             weakComponentListener = null;
283         }
284         if (component != null) {
285             weakComponentListener = (ComponentListener) WeakListeners.create(
286                     ComponentListener.class, this, model);
287             model.addComponentListener(weakComponentListener);
288         }
289     }
290
291     /**
292      * Change the WSDL component that this widget is associated with.
293      * Only a new component of the same type can be assigned. This manages
294      * the listener registration with the component model.
295      *
296      * @param component the new WSDL component.
297      */

298     protected void setWSDLComponent(T component) {
299         registerListener(component);
300         wsdlComponent = component;
301     }
302
303     @Override JavaDoc
304     protected void paintChildren() {
305         super.paintChildren();
306         
307         if (getState().isSelected()) {
308             Graphics2D JavaDoc g2 = getGraphics();
309
310             Object JavaDoc oldStrokeControl = g2.getRenderingHint(RenderingHints
311                     .KEY_STROKE_CONTROL);
312             Paint JavaDoc oldPaint = g2.getPaint();
313             
314             g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,
315                     RenderingHints.VALUE_STROKE_PURE);
316
317             g2.setPaint(WidgetConstants.SELECTION_COLOR);
318             
319             g2.draw(createSelectionShape());
320
321             g2.setPaint(oldPaint);
322             
323             g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,
324                     oldStrokeControl);
325         }
326     }
327     
328     /**
329      * Return the shape to be used to show the selection of this widget.
330      *
331      * @return selection shape.
332      */

333     protected Shape JavaDoc createSelectionShape() {
334         Rectangle JavaDoc rect = getBounds();
335         return new Rectangle2D.Double JavaDoc(rect.x + 1, rect.y + 1, rect.width - 2,
336                 rect.height - 2);
337     }
338
339     /**
340      * Add/remove actions from the given list, as needed for each type
341      * of widget. For instance, the default implementation removes the
342      * ReorderAction instance from the list provided by the backing Node.
343      * Subclasses may add or remove additional actions. To prevent removing
344      * the default actions, override without calling this superclass method.
345      *
346      * @param actions list of Action instances to be updated.
347      */

348     protected void updateActions(List JavaDoc<Action JavaDoc> actions) {
349         ListIterator JavaDoc<Action JavaDoc> liter = actions.listIterator();
350         while (liter.hasNext()) {
351             Action JavaDoc action = liter.next();
352             if (action instanceof ReorderAction) {
353                 liter.remove();
354             }
355         }
356     }
357
358     /**
359      * Invoked when the model component has changed in some way (either
360      * values changed, children were added, or children were removed).
361      * Subclasses should override this method to update their content.
362      */

363     protected void updateContent() {
364     }
365
366     /**
367      * Check if this widget should update its content based on the given
368      * component event. If so, the contents and scene validation will be
369      * performed on the event dispatching thread.
370      *
371      * @param event component event.
372      */

373     private void checkUpdate(ComponentEvent event) {
374         Object JavaDoc src = event.getSource();
375         if (src.equals(wsdlComponent)) {
376             Runnable JavaDoc updater = new Runnable JavaDoc() {
377                 public void run() {
378                     updateContent();
379                     getScene().validate();
380                 }
381             };
382             if (EventQueue.isDispatchThread()) {
383                 updater.run();
384             } else {
385                 EventQueue.invokeLater(updater);
386             }
387         }
388     }
389
390     public void childrenAdded(ComponentEvent event) {
391         checkUpdate(event);
392     }
393
394     public void childrenDeleted(ComponentEvent event) {
395         checkUpdate(event);
396     }
397
398     public void valueChanged(ComponentEvent event) {
399         checkUpdate(event);
400     }
401 }
402
Popular Tags