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: package org.netbeans.modules.form;
042:
043: import java.awt.*;
044: import java.beans.*;
045: import java.util.*;
046: import javax.swing.*;
047: import javax.swing.border.*;
048:
049: import org.openide.nodes.*;
050: import org.openide.actions.*;
051: import org.openide.explorer.*;
052: import org.openide.explorer.view.*;
053:
054: /**
055: * A component that displays non visual beans.
056: *
057: * @author Jan Stola
058: */
059: public class NonVisualTray extends JPanel implements
060: ExplorerManager.Provider {
061: /** The corresponding form model. */
062: private FormModel formModel;
063: /** List view used to display beans. */
064: private NonVisualView listView;
065: /** Explorer manager for the list view. */
066: private ExplorerManager manager;
067:
068: /**
069: * Creates new <code>NonVisualTray</code>.
070: *
071: * @param formModel the corresponding form model.
072: */
073: public NonVisualTray(FormModel formModel) {
074: this .formModel = formModel;
075: manager = new ExplorerManager();
076: Node othersNode = FormEditor.getFormEditor(formModel)
077: .getOthersContainerNode();
078: manager.setRootContext(new NonVisualNode(othersNode,
079: new NonVisualChildren(othersNode)));
080: Listener listener = new Listener();
081: manager.addPropertyChangeListener(listener);
082: ComponentInspector ci = ComponentInspector.getInstance();
083: ci.getExplorerManager().addPropertyChangeListener(listener);
084: listView = new NonVisualView();
085: setLayout(new BorderLayout());
086: add(listView, BorderLayout.CENTER);
087: }
088:
089: /**
090: * Returns explorer manager for the list view.
091: *
092: * @return explorer manager for the list view.
093: */
094: public ExplorerManager getExplorerManager() {
095: return manager;
096: }
097:
098: void updateVisualSettings() {
099: listView.updateVisualSettings();
100: }
101:
102: /**
103: * List view used in the non visual tray.
104: */
105: private static class NonVisualView extends ListView {
106:
107: /**
108: * Creates new <code>NonVisualView</code>.
109: */
110: public NonVisualView() {
111: list.setCellRenderer(new Renderer());
112: list.setLayoutOrientation(JList.HORIZONTAL_WRAP);
113: list.setVisibleRowCount(-1);
114: list.setBorder(BorderFactory.createEmptyBorder(0, 4, 4, 4));
115: updateVisualSettings();
116: setTraversalAllowed(false);
117: setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER);
118: setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
119: }
120:
121: @Override
122: public Dimension getPreferredSize() {
123: Dimension dim = super .getPreferredSize();
124: return new Dimension(1, (int) dim.getHeight());
125: }
126:
127: void updateVisualSettings() {
128: list.setBackground(FormLoaderSettings.getInstance()
129: .getFormDesignerBackgroundColor());
130: }
131:
132: }
133:
134: /**
135: * Renderer for the list view of the non visual tray.
136: */
137: private static class Renderer implements ListCellRenderer {
138: /** Button used as a renderer component. */
139: private JButton button;
140: /** Border for the selected rendered items. */
141: private Border selectedBorder;
142: /** Border for the unselected rendered items. */
143: private Border unselectedBorder;
144:
145: /**
146: * Creates new <code>Renderer</code>.
147: */
148: public Renderer() {
149: button = new JButton();
150: button.setUI(new javax.swing.plaf.basic.BasicButtonUI());
151: unselectedBorder = BorderFactory.createEmptyBorder(4, 4, 4,
152: 4);
153: Color selectionColor = FormLoaderSettings.getInstance()
154: .getSelectionBorderColor();
155: selectedBorder = BorderFactory.createCompoundBorder(
156: BorderFactory.createEmptyBorder(3, 3, 3, 3),
157: BorderFactory.createLineBorder(selectionColor));
158: button.setOpaque(false);
159: int fontSize = button.getFontMetrics(button.getFont())
160: .getHeight();
161: button.setPreferredSize(new Dimension(64 + 2 * 4,
162: 50 + fontSize));
163: }
164:
165: public Component getListCellRendererComponent(JList list,
166: Object value, int index, boolean isSelected,
167: boolean cellHasFocus) {
168: Node node = Visualizer.findNode(value);
169: ImageIcon icon = new ImageIcon(node
170: .getIcon(java.beans.BeanInfo.ICON_COLOR_32x32));
171: button.setIcon(icon);
172: String text = node.getShortDescription();
173: button.setText(text);
174: button.setHorizontalTextPosition(SwingConstants.CENTER);
175: button.setVerticalTextPosition(SwingConstants.BOTTOM);
176: button.setHorizontalAlignment(SwingConstants.CENTER);
177: button.setBorder(isSelected ? selectedBorder
178: : unselectedBorder);
179: return button;
180: }
181:
182: }
183:
184: /**
185: * Listener that synchronizes the selected nodes of the form designer
186: * and the non-visual tray.
187: */
188: private class Listener implements PropertyChangeListener {
189:
190: public void propertyChange(PropertyChangeEvent evt) {
191: if (ExplorerManager.PROP_SELECTED_NODES.equals(evt
192: .getPropertyName())) {
193: if (evt.getSource() == manager) {
194: Node[] newNodes = (Node[]) evt.getNewValue();
195: Node[] nodes = new Node[newNodes.length];
196: for (int i = 0; i < nodes.length; i++) {
197: nodes[i] = ((NonVisualNode) newNodes[i])
198: .getOriginal();
199: }
200: ComponentInspector ci = ComponentInspector
201: .getInstance();
202: Node[] ciNodes = ci.getSelectedNodes();
203: if (!Arrays.asList(ciNodes).containsAll(
204: Arrays.asList(nodes))) {
205: try {
206: ci.setSelectedNodes(nodes, FormEditor
207: .getFormEditor(formModel));
208: } catch (PropertyVetoException pvex) {
209: }
210: }
211: } else {
212: Node[] nodes = (Node[]) evt.getNewValue();
213: java.util.List<Node> list = new ArrayList<Node>();
214: Node node = ((NonVisualNode) manager
215: .getRootContext()).getOriginal();
216: for (int i = 0; i < nodes.length; i++) {
217: if (node == nodes[i].getParentNode()) {
218: list.add(findFilterNode(nodes[i]));
219: }
220: }
221: try {
222: manager.setSelectedNodes(list
223: .toArray(new Node[list.size()]));
224: } catch (PropertyVetoException pvex) {
225: }
226: }
227: }
228: }
229:
230: /**
231: * Finds a filter node (in the non-visual tray) that corresponds
232: * to the passed node (RADComponentNode).
233: */
234: private Node findFilterNode(Node original) {
235: Node root = manager.getRootContext();
236: Node[] nodes = root.getChildren().getNodes(false);
237: for (int i = 0; i < nodes.length; i++) {
238: NonVisualNode node = (NonVisualNode) nodes[i];
239: if (node.getOriginal() == original) {
240: return node;
241: }
242: }
243: return null;
244: }
245:
246: }
247:
248: /**
249: * Class that manages children of the <code>NonVisualNode</code>.
250: */
251: private class NonVisualChildren extends FilterNode.Children {
252:
253: /**
254: * Creates new <code>NonVisualChildren</code>.
255: *
256: * @param original the original node.
257: */
258: public NonVisualChildren(Node original) {
259: super (original);
260: }
261:
262: /**
263: * Creates a replacement for the original subnode.
264: *
265: * @return a replacement for the original subnode.
266: */
267: @Override
268: protected Node copyNode(Node node) {
269: return new NonVisualNode(node);
270: }
271:
272: }
273:
274: /**
275: * Nodes used in the non visual tray.
276: */
277: private static class NonVisualNode extends FilterNode {
278:
279: /**
280: * Creates new <code>NonVisualNode</code>.
281: *
282: * @param original the original node.
283: */
284: public NonVisualNode(Node original) {
285: super (original);
286: disableDelegation(DELEGATE_GET_SHORT_DESCRIPTION
287: | DELEGATE_GET_ACTIONS);
288: }
289:
290: /**
291: * Creates new <code>NonVisualNode</code>
292: *
293: * @param original the original node.
294: * @param children management of the subnodes.
295: */
296: public NonVisualNode(Node original, Children children) {
297: super (original, children);
298: }
299:
300: /**
301: * Returns short description of the node (used in tooltips by default).
302: *
303: * @return short description of the node.
304: */
305: @Override
306: public String getShortDescription() {
307: return getName();
308: }
309:
310: /**
311: * Returns the original node.
312: *
313: * @return the original node.
314: */
315: @Override
316: protected Node getOriginal() {
317: return super .getOriginal();
318: }
319:
320: /**
321: * Returns actions of the node.
322: *
323: * @param context determines whether context actions should be returned.
324: * @return actions of the node.
325: */
326: @Override
327: public Action[] getActions(boolean context) {
328: java.util.List forbiddenActions = Arrays
329: .asList(new Class[] { MoveUpAction.class,
330: MoveDownAction.class });
331: Action[] actions = getOriginal().getActions(context);
332: java.util.List<Action> actionList = new ArrayList<Action>(
333: Arrays.asList(actions));
334: for (int i = 0; i < actions.length; i++) {
335: Action action = actions[i];
336: if ((action != null)
337: && (forbiddenActions
338: .contains(action.getClass()))) {
339: actionList.remove(action);
340: }
341: }
342: return actionList.toArray(new Action[actionList.size()]);
343: }
344:
345: }
346:
347: }
|