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-2006 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.vmd.midp.propertyeditors.eventhandler;
043:
044: import java.awt.Component;
045: import java.awt.GridBagConstraints;
046: import java.awt.GridBagLayout;
047: import java.awt.Insets;
048: import java.lang.ref.WeakReference;
049: import java.util.ArrayList;
050: import java.util.Collection;
051: import java.util.Iterator;
052: import java.util.List;
053: import javax.swing.ButtonGroup;
054: import javax.swing.JPanel;
055: import javax.swing.JRadioButton;
056: import org.netbeans.modules.vmd.api.model.DesignComponent;
057: import org.netbeans.modules.vmd.api.model.PropertyValue;
058: import org.netbeans.modules.vmd.api.model.TypeID;
059: import org.netbeans.modules.vmd.api.model.common.DocumentSupport;
060: import org.netbeans.modules.vmd.api.model.presenters.InfoPresenter;
061: import org.netbeans.modules.vmd.api.properties.DesignPropertyEditor;
062: import org.netbeans.modules.vmd.midp.components.MidpDocumentSupport;
063: import org.netbeans.modules.vmd.midp.components.categories.DisplayablesCategoryCD;
064: import org.netbeans.modules.vmd.midp.components.categories.PointsCategoryCD;
065: import org.netbeans.modules.vmd.midp.components.displayables.AlertCD;
066: import org.netbeans.modules.vmd.midp.components.displayables.DisplayableCD;
067: import org.netbeans.modules.vmd.midp.components.points.CallPointCD;
068: import org.netbeans.modules.vmd.midp.components.points.MethodPointCD;
069: import org.netbeans.modules.vmd.midp.components.points.MobileDeviceCD;
070: import org.netbeans.modules.vmd.midp.general.AcceptContextResolver;
071: import org.netbeans.modules.vmd.midp.propertyeditors.element.PropertyEditorEventHandlerElement;
072: import org.netbeans.modules.vmd.midp.propertyeditors.element.PropertyEditorElementFactory;
073: import org.openide.awt.Mnemonics;
074: import org.openide.util.Lookup;
075: import org.openide.util.NbBundle;
076:
077: /**
078: *
079: * @author Anton Chechel
080: */
081: public final class PropertyEditorEventHandler extends
082: DesignPropertyEditor {
083:
084: private static final String DO_NOTHING = NbBundle.getMessage(
085: PropertyEditorEventHandler.class, "LBL_NOTHING_ACTION"); // NOI18N
086: private final CustomEditor customEditor;
087: private WeakReference<DesignComponent> component;
088: private boolean initialized;
089:
090: @SuppressWarnings(value="unchecked")
091: // NOI18N
092: private PropertyEditorEventHandler() {
093: Collection<PropertyEditorElementFactory> factories = Lookup
094: .getDefault().lookup(
095: new Lookup.Template(
096: PropertyEditorElementFactory.class))
097: .allInstances();
098: Collection<PropertyEditorEventHandlerElement> elements = new ArrayList<PropertyEditorEventHandlerElement>(
099: factories.size());
100: for (PropertyEditorElementFactory factory : factories) {
101: elements.add(factory.createElement());
102: }
103:
104: customEditor = new CustomEditor(elements);
105: }
106:
107: public static final PropertyEditorEventHandler createInstance() {
108: return new PropertyEditorEventHandler();
109: }
110:
111: @Override
112: public void init(DesignComponent component) {
113: if (component != null) {
114: this .component = new WeakReference<DesignComponent>(
115: component);
116: }
117: }
118:
119: @Override
120: public Component getCustomEditor() {
121: if (initialized) {
122: initCustomEditor();
123: }
124: return customEditor;
125: }
126:
127: private void initCustomEditor() {
128: if (component != null && component.get() != null) {
129: final DesignComponent _component = component.get();
130: _component.getDocument().getTransactionManager()
131: .readAccess(new Runnable() {
132:
133: public void run() {
134: PropertyValue value = null;
135: Iterator<DesignComponent> iterator = _component
136: .getComponents().iterator();
137: if (iterator.hasNext()) {
138: DesignComponent eventHandler = iterator
139: .next();
140: value = PropertyValue
141: .createComponentReference(eventHandler);
142: }
143:
144: DesignComponent displayableCategory = MidpDocumentSupport
145: .getCategoryComponent(
146: _component.getDocument(),
147: DisplayablesCategoryCD.TYPEID);
148: DesignComponent pointsCategory = MidpDocumentSupport
149: .getCategoryComponent(_component
150: .getDocument(),
151: PointsCategoryCD.TYPEID);
152: List<DesignComponent> displayables = DocumentSupport
153: .gatherAllComponentsOfTypeID(
154: displayableCategory,
155: DisplayableCD.TYPEID);
156: customEditor
157: .updateModels(
158: displayables,
159: PropertyEditorEventHandlerElement.MODEL_TYPE_DISPLAYABLES,
160: value);
161:
162: List<DesignComponent> alerts = DocumentSupport
163: .gatherAllComponentsOfTypeID(
164: displayableCategory,
165: AlertCD.TYPEID);
166: List<DesignComponent> displExceptAlerts = new ArrayList<DesignComponent>(
167: displayables.size() - alerts.size());
168: displExceptAlerts.addAll(displayables);
169: displExceptAlerts.removeAll(alerts);
170: customEditor
171: .updateModels(
172: displExceptAlerts,
173: PropertyEditorEventHandlerElement.MODEL_TYPE_DISPLAYABLES_WITHOUT_ALERTS,
174: value);
175:
176: List<DesignComponent> points = DocumentSupport
177: .gatherAllComponentsOfTypeID(
178: pointsCategory,
179: CallPointCD.TYPEID);
180: List<DesignComponent> methods = DocumentSupport
181: .gatherAllComponentsOfTypeID(
182: pointsCategory,
183: MethodPointCD.TYPEID);
184: List<DesignComponent> pointsAndMethods = new ArrayList<DesignComponent>(
185: points.size() + methods.size());
186: pointsAndMethods.addAll(points);
187: pointsAndMethods.addAll(methods);
188: customEditor
189: .updateModels(
190: pointsAndMethods,
191: PropertyEditorEventHandlerElement.MODEL_TYPE_POINTS,
192: value);
193:
194: List<DesignComponent> mobileDevices = DocumentSupport
195: .gatherSubComponentsOfType(
196: pointsCategory,
197: MobileDeviceCD.TYPEID);
198: customEditor
199: .setExitMidletEnabled(mobileDevices
200: .size() == 1);
201: }
202: });
203: }
204: }
205:
206: @Override
207: public Boolean canEditAsText() {
208: return false;
209: }
210:
211: @Override
212: public String getAsText() {
213: final String[] string = new String[1];
214: if (component != null && component.get() != null) {
215: final DesignComponent _component = component.get();
216: _component.getDocument().getTransactionManager()
217: .readAccess(new Runnable() {
218:
219: public void run() {
220: Iterator<DesignComponent> iterator = _component
221: .getComponents().iterator();
222: if (!iterator.hasNext()) {
223: string[0] = DO_NOTHING;
224: } else {
225: DesignComponent eventHandler = iterator
226: .next();
227: InfoPresenter presenter = eventHandler
228: .getPresenter(InfoPresenter.class);
229: if (presenter != null) {
230: string[0] = presenter
231: .getDisplayName(InfoPresenter.NameType.PRIMARY);
232: } else {
233: throw new IllegalStateException(
234: "No infoPresenter for "
235: + eventHandler); // NOI18N
236: }
237: }
238: }
239: });
240: }
241: return string[0];
242: }
243:
244: @Override
245: public boolean executeInsideWriteTransaction() {
246: if (initialized && component != null && component.get() != null) {
247: customEditor.createEventHandler(component.get());
248: }
249: return false;
250: }
251:
252: @Override
253: public boolean isDefaultValue() {
254: return true;
255: }
256:
257: private class CustomEditor extends JPanel {
258:
259: private Collection<PropertyEditorEventHandlerElement> elements;
260: private JRadioButton doNothingRadioButton;
261:
262: public CustomEditor(
263: Collection<PropertyEditorEventHandlerElement> elements) {
264: this .elements = elements;
265: }
266:
267: private void initComponents(
268: Collection<PropertyEditorEventHandlerElement> elements) {
269: if (component == null || component.get() == null) {
270: return;
271: }
272:
273: setLayout(new GridBagLayout());
274: ButtonGroup buttonGroup = new ButtonGroup();
275: GridBagConstraints constraints = new GridBagConstraints();
276: boolean wasSelected = false;
277:
278: final DesignComponent _component = component.get();
279: for (PropertyEditorEventHandlerElement element : elements) {
280: final Collection<TypeID> types = element.getTypes();
281: final boolean[] acceptable = new boolean[] { true };
282: _component.getDocument().getTransactionManager()
283: .readAccess(new Runnable() {
284:
285: public void run() {
286: for (TypeID typeID : types) {
287: if (!AcceptContextResolver
288: .resolveAcceptAllowance(
289: _component, typeID)) {
290: acceptable[0] = false;
291: break;
292: }
293: }
294: }
295: });
296: if (!acceptable[0]) {
297: continue;
298: }
299:
300: JRadioButton rb = element.getRadioButton();
301: if (element.isInitiallySelected()) {
302: rb.setSelected(true);
303: wasSelected = true;
304: }
305: buttonGroup.add(rb);
306:
307: constraints.insets = new Insets(12, 12, 6, 12);
308: constraints.anchor = GridBagConstraints.NORTHWEST;
309: constraints.gridx = GridBagConstraints.REMAINDER;
310: constraints.gridy = GridBagConstraints.RELATIVE;
311: constraints.weightx = 1.0;
312: constraints.weighty = 0.0;
313: constraints.fill = GridBagConstraints.HORIZONTAL;
314: add(rb, constraints);
315:
316: Component component = element
317: .getCustomEditorComponent();
318: if (component != null) {
319: constraints.insets = new Insets(0, 32, 12, 12);
320: constraints.anchor = GridBagConstraints.NORTHWEST;
321: constraints.gridx = GridBagConstraints.REMAINDER;
322: constraints.gridy = GridBagConstraints.RELATIVE;
323: constraints.weightx = 1.0;
324: constraints.weighty = element
325: .isVerticallyResizable() ? 1.0 : 0.0;
326: constraints.fill = GridBagConstraints.BOTH;
327: add(component, constraints);
328: }
329: }
330:
331: doNothingRadioButton = new JRadioButton();
332: Mnemonics.setLocalizedText(doNothingRadioButton, NbBundle
333: .getMessage(PropertyEditorEventHandler.class,
334: "LBL_NOTHING")); // NOI18N
335: doNothingRadioButton.setSelected(!wasSelected);
336: buttonGroup.add(doNothingRadioButton);
337:
338: constraints.insets = new Insets(12, 12, 6, 12);
339: constraints.anchor = GridBagConstraints.NORTHWEST;
340: constraints.gridx = GridBagConstraints.REMAINDER;
341: constraints.gridy = GridBagConstraints.RELATIVE;
342: constraints.weightx = 1.0;
343: constraints.weighty = 0.0;
344: constraints.fill = GridBagConstraints.HORIZONTAL;
345: add(doNothingRadioButton, constraints);
346:
347: JPanel spacer = new JPanel();
348: constraints.insets = new Insets(0, 0, 0, 0);
349: constraints.anchor = GridBagConstraints.NORTHWEST;
350: constraints.gridx = GridBagConstraints.REMAINDER;
351: constraints.gridy = GridBagConstraints.RELATIVE;
352: constraints.weightx = 1.0;
353: constraints.weighty = 1.0;
354: constraints.fill = GridBagConstraints.BOTH;
355: add(spacer, constraints);
356: }
357:
358: public void updateModels(List<DesignComponent> components,
359: int modelType, PropertyValue value) {
360: for (PropertyEditorEventHandlerElement element : elements) {
361: element.updateModel(components, modelType);
362: element.updateState(value);
363: checkDoNothing(value);
364: }
365: }
366:
367: public void setExitMidletEnabled(boolean enabled) {
368: for (PropertyEditorEventHandlerElement element : elements) {
369: if (element instanceof ExitMidletElement) {
370: element.setElementEnabled(enabled);
371: break;
372: }
373: }
374: }
375:
376: private void checkDoNothing(PropertyValue value) {
377: if (value == null || value.getComponent() == null) {
378: doNothingRadioButton.setSelected(true);
379: }
380: }
381:
382: private void resetEventHandler(DesignComponent eventSource) {
383: MidpDocumentSupport.updateEventHandlerWithNew(eventSource,
384: null);
385: }
386:
387: public void createEventHandler(DesignComponent eventSource) {
388: if (doNothingRadioButton.isSelected()) {
389: resetEventHandler(eventSource);
390: } else {
391: for (PropertyEditorEventHandlerElement element : elements) {
392: if (eventSource != null) {
393: element.createEventHandler(eventSource);
394: }
395: }
396: }
397: }
398:
399: @Override
400: public void addNotify() {
401: if (!initialized) {
402: initComponents(elements);
403: initCustomEditor();
404: initialized = true;
405: }
406: super.addNotify();
407: }
408: }
409: }
|