001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.modules.visualweb.designer.jsf.action;
043:
044: import com.sun.rave.designtime.DesignBean;
045: import com.sun.rave.designtime.DesignContext;
046: import java.awt.Component;
047: import java.awt.event.ActionEvent;
048: import java.beans.PropertyChangeListener;
049: import java.beans.PropertyChangeSupport;
050: import java.util.Collection;
051: import javax.swing.AbstractAction;
052: import javax.swing.Action;
053: import javax.swing.JButton;
054: import javax.swing.JMenuItem;
055: import org.netbeans.modules.visualweb.designer.jsf.JsfForm;
056: import org.openide.ErrorManager;
057: import org.openide.awt.Actions;
058: import org.openide.nodes.Node;
059: import org.openide.util.ContextAwareAction;
060: import org.openide.util.Lookup;
061: import org.openide.util.LookupEvent;
062: import org.openide.util.LookupListener;
063: import org.openide.util.WeakListeners;
064: import org.openide.util.actions.Presenter;
065:
066: /**
067: * An action which operates on <code>JsfForm</code> context. The subclasses
068: * need to implement the <code>isEnabled</code>, <code>perfomAction</code>
069: * and also <code>getDisplayName</code> and <code>getIconBase</code> methods
070: * taking the <code>JsfForm</code> as an argument.
071: * If they wish to implement different than standard menu, toolbar or popup
072: * presenter, they can just override the corresponding method
073: * <code>getMenuPresenter</code>, <code>getPopupPresenter</code>
074: * or <code>getToolbarPresenter</code>.
075: *
076: * @author Peter Zavadsky
077: */
078: abstract class AbstractJsfFormAction extends AbstractAction implements
079: ContextAwareAction {
080:
081: /** Name of property designBeans. */
082: protected static final String PROP_JSF_FORM = "jsfForm"; // NOI18N
083:
084: /** Creates a new instance of AbstractDesignBeanAction */
085: public AbstractJsfFormAction() {
086: // #6485313 To show the display name in the options dialog.
087: putValue(NAME, getDisplayName(null));
088: }
089:
090: /** This method is not used, only the context aware instance are in the game,
091: * this instance is only a placeholder in layer (or nodes). */
092: public final void actionPerformed(ActionEvent evt) {
093: ErrorManager
094: .getDefault()
095: .notify(
096: ErrorManager.INFORMATIONAL,
097: new IllegalStateException(
098: "This can't be called directly, it is just a placeholder," // NOI18N
099: + " the context aware instance has to be used.")); // NOI18N
100: }
101:
102: /** Creates the context aware instance working in the specific context. */
103: public final Action createContextAwareInstance(Lookup context) {
104: return new DelegateAction(this , context);
105: }
106:
107: /** Gets action display name based on provided beans. */
108: protected abstract String getDisplayName(JsfForm jsfForm);
109:
110: /** Gets icon base based on provided beans, in the form "com/mycompany/myIcon.gif".
111: * @see org.openide.awt.Actions#connect(AbstractButton, Action) */
112: protected abstract String getIconBase(JsfForm jsfForm);
113:
114: /** Implement in order to enable/disable the action based on provided beans. */
115: protected abstract boolean isEnabled(JsfForm jsfForm);
116:
117: /** Implement to perform the action based on provided beans. */
118: protected abstract void performAction(JsfForm jsfForm);
119:
120: // Presenters
121: /** Override if you wish to change the default presenter of the context aware action. */
122: protected JMenuItem getMenuPresenter(Action contextAwareAction,
123: Lookup.Result<Node> result) {
124: return new Actions.MenuItem(contextAwareAction, true);
125: }
126:
127: /** Override if you wish to change the default presenter of the context aware action. */
128: protected JMenuItem getPopupPresenter(Action contextAwareAction,
129: Lookup.Result<Node> result) {
130: return new Actions.MenuItem(contextAwareAction, false);
131: }
132:
133: /** Override if you wish to change the default presenter of the context aware action. */
134: protected Component getToolbarPresenter(Action contextAwareAction,
135: Lookup.Result<Node> result) {
136: // return new Actions.ToolbarButton(contextAwareAction);
137: JButton toolbarButton = new JButton();
138: Actions.connect(toolbarButton, contextAwareAction);
139: return toolbarButton;
140: }
141:
142: protected static final JsfForm getJsfForm(Lookup.Result<Node> result) {
143: Node[] nodes = getNodes(result);
144:
145: for (Node node : nodes) {
146: DesignBean designBean = node.getLookup().lookup(
147: DesignBean.class);
148: if (designBean == null) {
149: continue;
150: }
151: DesignContext designContext = designBean.getDesignContext();
152: if (designContext == null) {
153: continue;
154: }
155: JsfForm jsfForm = JsfForm.findJsfForm(designContext);
156: if (jsfForm != null) {
157: return jsfForm;
158: }
159: }
160: return null;
161: }
162:
163: private static final Node[] getNodes(Lookup.Result<Node> result) {
164: Collection<? extends Node> col = result.allInstances();
165: return col.toArray(new Node[col.size()]);
166: }
167:
168: /** Context aware implementation. */
169: private static class DelegateAction implements Action,
170: LookupListener, Presenter.Menu, Presenter.Popup,
171: Presenter.Toolbar {
172:
173: /** <code>AbstractDesignBeanAction</code> to delegate to. */
174: private final AbstractJsfFormAction delegate;
175:
176: /** <code>Lookup.Result</code> we are associated with. */
177: private final Lookup.Result<Node> result;
178:
179: /** State of enabled. */
180: private boolean enabled = true;
181:
182: /** Support for listeners */
183: private final PropertyChangeSupport support = new PropertyChangeSupport(
184: this );
185:
186: public DelegateAction(AbstractJsfFormAction delegate,
187: Lookup actionContext) {
188: this .delegate = delegate;
189:
190: this .result = actionContext
191: .lookup(new Lookup.Template<Node>(Node.class));
192: this .result.addLookupListener(WeakListeners.create(
193: LookupListener.class, this , this .result));
194: resultChanged(null);
195: }
196:
197: /** Overrides superclass method, adds delegate description. */
198: public String toString() {
199: return super .toString() + "[delegate=" + delegate + "]"; // NOI18N
200: }
201:
202: /** Invoked when an action occurs. */
203: public void actionPerformed(ActionEvent evt) {
204: delegate.performAction(getJsfForm(result));
205: }
206:
207: public void addPropertyChangeListener(
208: PropertyChangeListener listener) {
209: support.addPropertyChangeListener(listener);
210: }
211:
212: public void removePropertyChangeListener(
213: PropertyChangeListener listener) {
214: support.removePropertyChangeListener(listener);
215: }
216:
217: public void putValue(String key, Object object) {
218: delegate.putValue(key, object);
219: }
220:
221: public Object getValue(String key) {
222: // XXX Delegating display name and icon base to the
223: // context sensitive methods.
224: if (Action.NAME.equals(key)) {
225: return delegate.getDisplayName(getJsfForm(result));
226: } else if ("iconBase".equals(key)) { // NOI18N
227: return delegate.getIconBase(getJsfForm(result));
228: } else {
229: return delegate.getValue(key);
230: }
231: }
232:
233: public boolean isEnabled() {
234: return enabled;
235: }
236:
237: public void setEnabled(boolean enabled) {
238: if (this .enabled == enabled) {
239: return;
240: }
241:
242: this .enabled = enabled;
243: support.firePropertyChange("enabled", !enabled, enabled); // NOI18N
244: }
245:
246: public void resultChanged(LookupEvent evt) {
247: JsfForm jsfForm = getJsfForm(result);
248:
249: setEnabled(delegate.isEnabled(jsfForm));
250:
251: support.firePropertyChange(PROP_JSF_FORM, null, jsfForm);
252: }
253:
254: public JMenuItem getMenuPresenter() {
255: return delegate.getMenuPresenter(this , result);
256: }
257:
258: public JMenuItem getPopupPresenter() {
259: return delegate.getPopupPresenter(this , result);
260: }
261:
262: public Component getToolbarPresenter() {
263: return delegate.getToolbarPresenter(this , result);
264: }
265: } // End of DelegateAction.
266:
267: }
|