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.options;
043:
044: import java.awt.Component;
045: import java.awt.Dialog;
046: import java.awt.event.ActionEvent;
047: import java.awt.event.ActionListener;
048: import java.awt.event.WindowEvent;
049: import java.awt.event.WindowListener;
050: import java.beans.PropertyChangeEvent;
051: import java.beans.PropertyChangeListener;
052: import java.lang.ref.WeakReference;
053: import java.util.logging.Logger;
054: import javax.swing.AbstractButton;
055: import javax.swing.JButton;
056: import javax.swing.JLabel;
057: import javax.swing.SwingUtilities;
058: import org.netbeans.api.options.OptionsDisplayer;
059: import org.netbeans.spi.options.OptionsPanelController;
060:
061: import org.openide.DialogDescriptor;
062: import org.openide.DialogDisplayer;
063: import org.openide.NotifyDescriptor;
064: import org.openide.NotifyDescriptor.Confirmation;
065: import org.openide.awt.Mnemonics;
066: import org.openide.util.Exceptions;
067: import org.openide.util.Lookup;
068: import org.openide.util.LookupEvent;
069: import org.openide.util.LookupListener;
070: import org.openide.util.NbBundle;
071: import org.openide.util.RequestProcessor;
072: import org.openide.util.Utilities;
073: import org.openide.util.actions.CallableSystemAction;
074: import org.openide.util.actions.SystemAction;
075:
076: public class OptionsDisplayerImpl {
077: /** Link to dialog, if its opened. */
078: private static Dialog dialog;
079: /** weak link to options dialog DialogDescriptor. */
080: private static WeakReference<DialogDescriptor> descriptorRef = new WeakReference<DialogDescriptor>(
081: null);
082: private static String title = loc("CTL_Options_Dialog_Title");
083: private static Logger log = Logger
084: .getLogger(OptionsDisplayerImpl.class.getName());
085: private boolean modal;
086: static final LookupListener lookupListener = new LookupListenerImpl();
087:
088: public OptionsDisplayerImpl(boolean modal) {
089: this .modal = modal;
090: }
091:
092: public boolean isOpen() {
093: return dialog != null;
094: }
095:
096: public void showOptionsDialog(String categoryID) {
097: if (isOpen()) {
098: // dialog already opened
099: dialog.setVisible(true);
100: dialog.toFront();
101: log.fine("Front Options Dialog"); //NOI18N
102: return;
103: }
104:
105: DialogDescriptor descriptor = null;
106: synchronized (lookupListener) {
107: descriptor = (DialogDescriptor) descriptorRef.get();
108: }
109:
110: OptionsPanel optionsPanel = null;
111: if (descriptor == null) {
112: optionsPanel = categoryID == null ? new OptionsPanel()
113: : new OptionsPanel(categoryID);
114: JButton bOK = (JButton) loc(new JButton(), "CTL_OK");//NOI18N
115: bOK.getAccessibleContext().setAccessibleDescription(
116: loc("ACS_OKButton"));//NOI18N
117: JButton bClassic = (JButton) loc(new JButton(),
118: "CTL_Classic");//NOI18N
119: bClassic.getAccessibleContext().setAccessibleDescription(
120: loc("ACS_ClassicButton"));//NOI18N
121: boolean isMac = Utilities.isMac();
122: Object[] options = new Object[2];
123: options[0] = isMac ? DialogDescriptor.CANCEL_OPTION : bOK;
124: options[1] = isMac ? bOK : DialogDescriptor.CANCEL_OPTION;
125: descriptor = new DialogDescriptor(optionsPanel, title,
126: modal, options, DialogDescriptor.OK_OPTION,
127: DialogDescriptor.DEFAULT_ALIGN, null, null, false);
128: descriptor.setAdditionalOptions(new Object[] { bClassic });
129: descriptor.setHelpCtx(optionsPanel.getHelpCtx());
130: OptionsPanelListener listener = new OptionsPanelListener(
131: descriptor, optionsPanel, bOK, bClassic);
132: descriptor.setButtonListener(listener);
133: optionsPanel.addPropertyChangeListener(listener);
134: synchronized (lookupListener) {
135: descriptorRef = new WeakReference<DialogDescriptor>(
136: descriptor);
137: }
138: log.fine("Create new Options Dialog"); //NOI18N
139: } else {
140: optionsPanel = (OptionsPanel) descriptor.getMessage();
141: //TODO:
142: //just in case that switched from advanced
143: optionsPanel.update();
144: log.fine("Reopen Options Dialog"); //NOI18N
145: }
146:
147: dialog = DialogDisplayer.getDefault().createDialog(descriptor);
148: optionsPanel.initCurrentCategory(categoryID);
149: dialog.addWindowListener(new MyWindowListener(optionsPanel));
150: dialog.setVisible(true);
151: }
152:
153: private static String loc(String key) {
154: return NbBundle.getMessage(OptionsDisplayerImpl.class, key);
155: }
156:
157: private static Component loc(Component c, String key) {
158: if (c instanceof AbstractButton)
159: Mnemonics.setLocalizedText((AbstractButton) c, loc(key));
160: else
161: Mnemonics.setLocalizedText((JLabel) c, loc(key));
162: return c;
163: }
164:
165: private class OptionsPanelListener implements
166: PropertyChangeListener, ActionListener {
167: private DialogDescriptor descriptor;
168: private OptionsPanel optionsPanel;
169: private JButton bOK;
170: private JButton bClassic;
171:
172: OptionsPanelListener(DialogDescriptor descriptor,
173: OptionsPanel optionsPanel, JButton bOK, JButton bClassic) {
174: this .descriptor = descriptor;
175: this .optionsPanel = optionsPanel;
176: this .bOK = bOK;
177: this .bClassic = bClassic;
178: }
179:
180: public void propertyChange(PropertyChangeEvent ev) {
181: if (ev.getPropertyName().equals(
182: "buran" + OptionsPanelController.PROP_HELP_CTX)) { //NOI18N
183: descriptor.setHelpCtx(optionsPanel.getHelpCtx());
184: } else if (ev.getPropertyName().equals(
185: "buran" + OptionsPanelController.PROP_VALID)) { //NOI18N
186: bOK.setEnabled(optionsPanel.dataValid());
187: }
188: }
189:
190: @SuppressWarnings("unchecked")
191: public void actionPerformed(ActionEvent e) {
192: if (!isOpen())
193: return; //WORKARROUND for some bug in NbPresenter
194: // listener is called twice ...
195: if (e.getSource() == bOK) {
196: log.fine("Options Dialog - Ok pressed."); //NOI18N
197: Dialog d = dialog;
198: dialog = null;
199: optionsPanel.save();
200: d.dispose();
201: } else if (e.getSource() == DialogDescriptor.CANCEL_OPTION
202: || e.getSource() == DialogDescriptor.CLOSED_OPTION) {
203: log.fine("Options Dialog - Cancel pressed."); //NOI18N
204: Dialog d = dialog;
205: dialog = null;
206: optionsPanel.cancel();
207: d.dispose();
208: } else if (e.getSource() == bClassic) {
209: log.fine("Options Dialog - Classic pressed."); //NOI18N
210: Dialog d = dialog;
211: dialog = null;
212: if (optionsPanel.isChanged()) {
213: Confirmation confirmationDescriptor = new Confirmation(
214: loc("CTL_Some_values_changed"),
215: NotifyDescriptor.YES_NO_CANCEL_OPTION,
216: NotifyDescriptor.QUESTION_MESSAGE);
217: Object result = DialogDisplayer.getDefault()
218: .notify(confirmationDescriptor);
219: if (result == NotifyDescriptor.YES_OPTION) {
220: optionsPanel.save();
221: d.dispose();
222: } else if (result == NotifyDescriptor.NO_OPTION) {
223: optionsPanel.cancel();
224: d.dispose();
225: } else {
226: dialog = d;
227: return;
228: }
229: } else {
230: d.dispose();
231: optionsPanel.cancel();
232: }
233: try {
234: ClassLoader cl = (ClassLoader) Lookup.getDefault()
235: .lookup(ClassLoader.class);
236: Class<CallableSystemAction> clz = (Class<CallableSystemAction>) cl
237: .loadClass("org.netbeans.core.actions.OptionsAction");
238: CallableSystemAction a = SystemAction.findObject(
239: clz, true);
240: a.putValue("additionalActionName",
241: loc("CTL_Modern"));
242: a.putValue("optionsDialogTitle",
243: loc("CTL_Classic_Title"));
244: a.putValue("additionalActionListener",
245: new OpenOptionsListener());
246: a.performAction();
247: } catch (Exception ex) {
248: Exceptions.printStackTrace(ex);
249: }
250: } // classic
251: }
252: }
253:
254: private class MyWindowListener implements WindowListener {
255: private OptionsPanel optionsPanel;
256: private Dialog originalDialog;
257:
258: MyWindowListener(OptionsPanel optionsPanel) {
259: this .optionsPanel = optionsPanel;
260: this .originalDialog = dialog;
261: }
262:
263: public void windowClosing(WindowEvent e) {
264: if (dialog == null)
265: return;
266: log.fine("Options Dialog - windowClosing "); //NOI18N
267: optionsPanel.cancel();
268: if (this .originalDialog == dialog) {
269: dialog = null;
270: }
271: }
272:
273: public void windowClosed(WindowEvent e) {
274: optionsPanel.storeUserSize();
275: if (optionsPanel.needsReinit()) {
276: synchronized (lookupListener) {
277: descriptorRef = new WeakReference<DialogDescriptor>(
278: null);
279: }
280: }
281: if (this .originalDialog == dialog) {
282: dialog = null;
283: }
284: log.fine("Options Dialog - windowClosed"); //NOI18N
285: }
286:
287: public void windowDeactivated(WindowEvent e) {
288: }
289:
290: public void windowOpened(WindowEvent e) {
291: }
292:
293: public void windowIconified(WindowEvent e) {
294: }
295:
296: public void windowDeiconified(WindowEvent e) {
297: }
298:
299: public void windowActivated(WindowEvent e) {
300: }
301: }
302:
303: class OpenOptionsListener implements ActionListener {
304: public void actionPerformed(ActionEvent e) {
305: RequestProcessor.getDefault().post(new Runnable() {
306: public void run() {
307: SwingUtilities.invokeLater(new Runnable() {
308: public void run() {
309: log
310: .fine("Options Dialog - Back to modern."); //NOI18N
311: //OptionsDisplayerImpl.this.showOptionsDialog(null);
312: OptionsDisplayer.getDefault().open();
313: }
314: });
315: }
316: });
317: }
318: }
319:
320: private static class LookupListenerImpl implements LookupListener {
321: public void resultChanged(LookupEvent ev) {
322: synchronized (lookupListener) {
323: descriptorRef = new WeakReference<DialogDescriptor>(
324: null);
325: }
326: }
327:
328: }
329: }
|