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.palette.ui;
043:
044: import java.awt.Dialog;
045: import javax.swing.*;
046: import javax.swing.text.DefaultEditorKit;
047: import java.beans.*;
048: import java.util.logging.Level;
049: import java.util.logging.Logger;
050: import org.netbeans.spi.palette.PaletteActions;
051: import org.netbeans.spi.palette.PaletteController;
052: import org.openide.awt.Mnemonics;
053: import org.openide.util.*;
054: import org.openide.explorer.*;
055: import org.openide.explorer.view.BeanTreeView;
056: import org.openide.*;
057: import org.openide.nodes.*;
058: import org.netbeans.modules.palette.*;
059:
060: /**
061: * This class provides the UI for managing palette content (adding components
062: * etc). Shown to the user as "Palette Customizer" window.
063: *
064: * @author Tomas Pavek, S. Aubrecht
065: */
066:
067: public class Customizer extends JPanel implements
068: ExplorerManager.Provider, Lookup.Provider {
069: private ExplorerManager explorerManager;
070: private Lookup lookup;
071:
072: private Node root;
073: private PaletteController controller;
074: private Settings settings;
075:
076: private JButton[] customButtons;
077:
078: // ------------
079:
080: /**
081: * Opens the manager window.
082: *
083: * @param paletteRoot Palette root node.
084: */
085: public static void show(Node paletteRoot,
086: PaletteController controller, Settings settings) {
087: JButton closeButton = new JButton();
088: org.openide.awt.Mnemonics.setLocalizedText(closeButton, Utils
089: .getBundleString("CTL_Close_Button")); // NOI18N
090: closeButton.getAccessibleContext().setAccessibleDescription(
091: Utils.getBundleString("ACSD_Close"));
092: DialogDescriptor dd = new DialogDescriptor(new Customizer(
093: paletteRoot, controller, settings),
094: Utils.getBundleString("CTL_Customizer_Title"), // NOI18N
095: false, new Object[] { closeButton }, closeButton,
096: DialogDescriptor.DEFAULT_ALIGN, null, null);
097: Dialog dialog = DialogDisplayer.getDefault().createDialog(dd);
098: dialog.setVisible(true);
099: }
100:
101: /** Creates new Customizer */
102: public Customizer(Node paletteRoot, PaletteController controller,
103: Settings settings) {
104: this .root = paletteRoot;
105: this .controller = controller;
106: this .settings = settings;
107: explorerManager = new ExplorerManager();
108:
109: ActionMap map = getActionMap();
110: map.put(DefaultEditorKit.copyAction, ExplorerUtils
111: .actionCopy(explorerManager));
112: map.put(DefaultEditorKit.cutAction, ExplorerUtils
113: .actionCut(explorerManager));
114: map.put(DefaultEditorKit.pasteAction, ExplorerUtils
115: .actionPaste(explorerManager));
116: map.put("delete", ExplorerUtils.actionDelete(explorerManager,
117: true)); // NOI18N
118:
119: lookup = ExplorerUtils.createLookup(explorerManager, map);
120:
121: explorerManager.setRootContext(paletteRoot);
122:
123: initComponents();
124:
125: createCustomButtons();
126:
127: CheckTreeView treeView = new CheckTreeView(settings);
128: treeView.getAccessibleContext().setAccessibleName(
129: Utils.getBundleString("ACSN_PaletteContentsTree")); // NOI18N
130: treeView.getAccessibleContext().setAccessibleDescription(
131: Utils.getBundleString("ACSD_PaletteContentsTree")); // NOI18N
132: treePanel.add(treeView, java.awt.BorderLayout.CENTER);
133: captionLabel.setLabelFor(treeView);
134:
135: explorerManager
136: .addPropertyChangeListener(new PropertyChangeListener() {
137: public void propertyChange(PropertyChangeEvent ev) {
138: if (ExplorerManager.PROP_SELECTED_NODES
139: .equals(ev.getPropertyName())) {
140: updateInfoLabel(explorerManager
141: .getSelectedNodes());
142: updateButtons();
143: }
144: }
145: });
146: updateButtons();
147: }
148:
149: public void addNotify() {
150: super .addNotify();
151: ExplorerUtils.activateActions(explorerManager, true);
152: }
153:
154: public void removeNotify() {
155: ExplorerUtils.activateActions(explorerManager, false);
156: super .removeNotify();
157: }
158:
159: // ExplorerManager.Provider
160: public ExplorerManager getExplorerManager() {
161: return explorerManager;
162: }
163:
164: // Lookup.Provider from TopComponent
165: public Lookup getLookup() {
166: return lookup;
167: }
168:
169: private void updateButtons() {
170: Node[] selNodes = explorerManager.getSelectedNodes();
171: boolean canRemove = null != selNodes && selNodes.length > 0;
172: boolean canMoveUp = null != selNodes && selNodes.length == 1;
173: boolean canMoveDown = null != selNodes && selNodes.length == 1;
174:
175: for (int i = 0; null != selNodes && i < selNodes.length; i++) {
176: Node node = selNodes[i];
177: if (!node.canDestroy())
178: canRemove = false;
179:
180: Node parent = node.getParentNode();
181: if (null == parent || movePossible(node, parent, true) < 0)
182: canMoveUp = false;
183: if (null == parent || movePossible(node, parent, false) < 0)
184: canMoveDown = false;
185: }
186: removeButton.setEnabled(canRemove);
187: moveUpButton.setEnabled(canMoveUp);
188: moveDownButton.setEnabled(canMoveDown);
189: }
190:
191: // -------
192:
193: /** This method is called from within the constructor to
194: * initialize the form.
195: * WARNING: Do NOT modify this code. The content of this method is
196: * always regenerated by the Form Editor.
197: */
198: // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
199: private void initComponents() {
200: java.awt.GridBagConstraints gridBagConstraints;
201:
202: captionLabel = new javax.swing.JLabel();
203: treePanel = new javax.swing.JPanel();
204: infoLabel = new javax.swing.JLabel();
205: moveUpButton = new javax.swing.JButton();
206: moveDownButton = new javax.swing.JButton();
207: removeButton = new javax.swing.JButton();
208: newCategoryButton = new javax.swing.JButton();
209: customActionsPanel = new javax.swing.JPanel();
210: resetButton = new javax.swing.JButton();
211:
212: setLayout(new java.awt.GridBagLayout());
213:
214: org.openide.awt.Mnemonics.setLocalizedText(captionLabel, Utils
215: .getBundleString("CTL_Caption")); // NOI18N
216: gridBagConstraints = new java.awt.GridBagConstraints();
217: gridBagConstraints.gridwidth = 2;
218: gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
219: gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
220: gridBagConstraints.insets = new java.awt.Insets(6, 10, 0, 10);
221: add(captionLabel, gridBagConstraints);
222:
223: treePanel.setBorder(javax.swing.BorderFactory
224: .createEtchedBorder());
225: treePanel.setPreferredSize(new java.awt.Dimension(288, 336));
226: treePanel.setLayout(new java.awt.BorderLayout());
227: gridBagConstraints = new java.awt.GridBagConstraints();
228: gridBagConstraints.gridx = 0;
229: gridBagConstraints.gridy = 1;
230: gridBagConstraints.gridheight = 7;
231: gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
232: gridBagConstraints.weightx = 1.0;
233: gridBagConstraints.weighty = 1.0;
234: gridBagConstraints.insets = new java.awt.Insets(6, 10, 0, 0);
235: add(treePanel, gridBagConstraints);
236:
237: infoLabel.setText(" ");
238: gridBagConstraints = new java.awt.GridBagConstraints();
239: gridBagConstraints.gridx = 0;
240: gridBagConstraints.gridy = 8;
241: gridBagConstraints.gridwidth = 2;
242: gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
243: gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
244: gridBagConstraints.insets = new java.awt.Insets(10, 10, 0, 10);
245: add(infoLabel, gridBagConstraints);
246:
247: org.openide.awt.Mnemonics.setLocalizedText(moveUpButton, Utils
248: .getBundleString("CTL_MoveUp_Button")); // NOI18N
249: moveUpButton
250: .addActionListener(new java.awt.event.ActionListener() {
251: public void actionPerformed(
252: java.awt.event.ActionEvent evt) {
253: moveUpButtonActionPerformed(evt);
254: }
255: });
256: gridBagConstraints = new java.awt.GridBagConstraints();
257: gridBagConstraints.gridx = 1;
258: gridBagConstraints.gridy = 2;
259: gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
260: gridBagConstraints.insets = new java.awt.Insets(28, 12, 0, 10);
261: add(moveUpButton, gridBagConstraints);
262: moveUpButton.getAccessibleContext().setAccessibleDescription(
263: Utils.getBundleString("ACSD_MoveUp")); // NOI18N
264:
265: org.openide.awt.Mnemonics.setLocalizedText(moveDownButton,
266: Utils.getBundleString("CTL_MoveDown_Button")); // NOI18N
267: moveDownButton
268: .addActionListener(new java.awt.event.ActionListener() {
269: public void actionPerformed(
270: java.awt.event.ActionEvent evt) {
271: moveDownButtonActionPerformed(evt);
272: }
273: });
274: gridBagConstraints = new java.awt.GridBagConstraints();
275: gridBagConstraints.gridx = 1;
276: gridBagConstraints.gridy = 3;
277: gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
278: gridBagConstraints.insets = new java.awt.Insets(5, 12, 0, 10);
279: add(moveDownButton, gridBagConstraints);
280: moveDownButton.getAccessibleContext().setAccessibleDescription(
281: Utils.getBundleString("ACSD_MoveDown")); // NOI18N
282:
283: org.openide.awt.Mnemonics.setLocalizedText(removeButton, Utils
284: .getBundleString("CTL_Remove_Button")); // NOI18N
285: removeButton
286: .addActionListener(new java.awt.event.ActionListener() {
287: public void actionPerformed(
288: java.awt.event.ActionEvent evt) {
289: removeButtonActionPerformed(evt);
290: }
291: });
292: gridBagConstraints = new java.awt.GridBagConstraints();
293: gridBagConstraints.gridx = 1;
294: gridBagConstraints.gridy = 4;
295: gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
296: gridBagConstraints.insets = new java.awt.Insets(5, 12, 0, 10);
297: add(removeButton, gridBagConstraints);
298: removeButton.getAccessibleContext().setAccessibleDescription(
299: Utils.getBundleString("ACSD_Remove")); // NOI18N
300:
301: org.openide.awt.Mnemonics.setLocalizedText(newCategoryButton,
302: Utils.getBundleString("CTL_NewCategory_Button")); // NOI18N
303: newCategoryButton
304: .addActionListener(new java.awt.event.ActionListener() {
305: public void actionPerformed(
306: java.awt.event.ActionEvent evt) {
307: newCategoryButtonActionPerformed(evt);
308: }
309: });
310: gridBagConstraints = new java.awt.GridBagConstraints();
311: gridBagConstraints.gridx = 1;
312: gridBagConstraints.gridy = 5;
313: gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
314: gridBagConstraints.insets = new java.awt.Insets(5, 12, 0, 10);
315: add(newCategoryButton, gridBagConstraints);
316: newCategoryButton.getAccessibleContext()
317: .setAccessibleDescription(
318: Utils.getBundleString("ACSD_NewCategory")); // NOI18N
319:
320: customActionsPanel.setLayout(new java.awt.GridBagLayout());
321: gridBagConstraints = new java.awt.GridBagConstraints();
322: gridBagConstraints.gridx = 1;
323: gridBagConstraints.gridy = 1;
324: gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
325: add(customActionsPanel, gridBagConstraints);
326:
327: org.openide.awt.Mnemonics.setLocalizedText(resetButton, Utils
328: .getBundleString("CTL_ResetPalette")); // NOI18N
329: resetButton.setActionCommand("Reset Palette");
330: resetButton
331: .addActionListener(new java.awt.event.ActionListener() {
332: public void actionPerformed(
333: java.awt.event.ActionEvent evt) {
334: resetButtonActionPerformed(evt);
335: }
336: });
337: gridBagConstraints = new java.awt.GridBagConstraints();
338: gridBagConstraints.gridx = 1;
339: gridBagConstraints.gridy = 6;
340: gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
341: gridBagConstraints.insets = new java.awt.Insets(28, 12, 0, 10);
342: add(resetButton, gridBagConstraints);
343: resetButton.getAccessibleContext().setAccessibleName(
344: Utils.getBundleString("ASCN_ResetPalette")); // NOI18N
345: resetButton.getAccessibleContext().setAccessibleDescription(
346: Utils.getBundleString("ASCD_ResetPalette")); // NOI18N
347:
348: getAccessibleContext().setAccessibleDescription(
349: Utils.getBundleString("ACSD_PaletteCustomizer")); // NOI18N
350: }// </editor-fold>//GEN-END:initComponents
351:
352: private void resetButtonActionPerformed(
353: java.awt.event.ActionEvent evt) {//GEN-FIRST:event_resetButtonActionPerformed
354: Utils.resetPalette(controller, settings);
355: }//GEN-LAST:event_resetButtonActionPerformed
356:
357: private void removeButtonActionPerformed(
358: java.awt.event.ActionEvent evt) {//GEN-FIRST:event_removeButtonActionPerformed
359: Node[] selected = explorerManager.getSelectedNodes();
360: if (selected.length == 0)
361: return;
362:
363: if (selected.length == 1 && !selected[0].canDestroy())
364: return;
365:
366: // first user confirmation...
367: NotifyDescriptor desc = new NotifyDescriptor.Confirmation(Utils
368: .getBundleString("MSG_ConfirmPaletteDelete"), // NOI18N
369: Utils.getBundleString("CTL_ConfirmDeleteTitle"), // NOI18N
370: NotifyDescriptor.YES_NO_OPTION);
371:
372: if (NotifyDescriptor.YES_OPTION.equals(DialogDisplayer
373: .getDefault().notify(desc))) {
374: try {
375: for (int i = 0; i < selected.length; i++) {
376: if (selected[i].canDestroy())
377: selected[i].destroy();
378: }
379: } catch (java.io.IOException e) {
380: Logger.getLogger(getClass().getName()).log(Level.INFO,
381: null, e);
382: }
383: }
384: }//GEN-LAST:event_removeButtonActionPerformed
385:
386: private void moveDownButtonActionPerformed(
387: java.awt.event.ActionEvent evt) {//GEN-FIRST:event_moveDownButtonActionPerformed
388: moveNode(false);
389: }//GEN-LAST:event_moveDownButtonActionPerformed
390:
391: private void moveUpButtonActionPerformed(
392: java.awt.event.ActionEvent evt) {//GEN-FIRST:event_moveUpButtonActionPerformed
393: moveNode(true);
394: }//GEN-LAST:event_moveUpButtonActionPerformed
395:
396: private void newCategoryButtonActionPerformed(
397: java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newCategoryButtonActionPerformed
398: new Utils.NewCategoryAction(root).actionPerformed(evt);
399: }//GEN-LAST:event_newCategoryButtonActionPerformed
400:
401: // Variables declaration - do not modify//GEN-BEGIN:variables
402: private javax.swing.JLabel captionLabel;
403: private javax.swing.JPanel customActionsPanel;
404: private javax.swing.JLabel infoLabel;
405: private javax.swing.JButton moveDownButton;
406: private javax.swing.JButton moveUpButton;
407: private javax.swing.JButton newCategoryButton;
408: private javax.swing.JButton removeButton;
409: private javax.swing.JButton resetButton;
410: private javax.swing.JPanel treePanel;
411:
412: // End of variables declaration//GEN-END:variables
413:
414: private void moveNode(boolean up) {
415: Node[] selected = explorerManager.getSelectedNodes();
416: if (selected.length != 1)
417: return;
418:
419: Node node = selected[0];
420: Node parent = node.getParentNode();
421: if (parent == null)
422: return;
423:
424: Index indexCookie = parent.getCookie(Index.class);
425: if (indexCookie == null)
426: return;
427:
428: int index = movePossible(node, parent, up);
429: if (index != -1) {
430: if (up) {
431: indexCookie.moveUp(index);
432: } else {
433: indexCookie.moveDown(index);
434: }
435: }
436: }
437:
438: private static int movePossible(Node node, Node parentNode,
439: boolean up) {
440: if (parentNode == null)
441: return -1;
442:
443: Node[] nodes = parentNode.getChildren().getNodes();
444: for (int i = 0; i < nodes.length; i++)
445: if (nodes[i].getName().equals(node.getName()))
446: return (up && i > 0) || (!up && i + 1 < nodes.length) ? i
447: : -1;
448:
449: return -1;
450: }
451:
452: private void updateInfoLabel(org.openide.nodes.Node[] nodes) {
453: String text = " "; // NOI18N
454: if (nodes.length == 1) {
455: Item item = nodes[0].getCookie(Item.class);
456: if (item != null)
457: text = item.getShortDescription(); //TODO revisit PaletteSupport.getItemComponentDescription(item);
458: }
459: infoLabel.setText(text);
460: }
461:
462: private void createCustomButtons() {
463: PaletteActions customActions = root.getLookup().lookup(
464: PaletteActions.class);
465: if (null == customActions)
466: return;
467:
468: Action[] actions = customActions.getImportActions();
469: if (null == actions || actions.length == 0)
470: return;
471:
472: customButtons = new JButton[actions.length];
473: for (int i = 0; i < actions.length; i++) {
474: customButtons[i] = new JButton(actions[i]);
475: if (null != actions[i].getValue(Action.NAME))
476: Mnemonics.setLocalizedText(customButtons[i], actions[i]
477: .getValue(Action.NAME).toString());
478: if (null != actions[i].getValue(Action.LONG_DESCRIPTION))
479: customButtons[i].getAccessibleContext()
480: .setAccessibleDescription(
481: actions[i].getValue(
482: Action.LONG_DESCRIPTION)
483: .toString());
484: java.awt.GridBagConstraints gridBagConstraints = new java.awt.GridBagConstraints();
485: gridBagConstraints.gridx = 0;
486: gridBagConstraints.gridy = i;
487: gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
488: gridBagConstraints.insets = new java.awt.Insets(5, 12, 0,
489: 10);
490: customActionsPanel
491: .add(customButtons[i], gridBagConstraints);
492: }
493: }
494:
495: private static class CheckTreeView extends BeanTreeView {
496: /** Creates a new instance of CheckTreeView */
497: public CheckTreeView(Settings settings) {
498: if (settings instanceof DefaultSettings) {
499: CheckListener l = new CheckListener(
500: (DefaultSettings) settings);
501: tree.addMouseListener(l);
502: tree.addKeyListener(l);
503:
504: CheckRenderer check = new CheckRenderer(
505: (DefaultSettings) settings);
506: tree.setCellRenderer(check);
507: }
508: }
509: }
510: }
|