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 threaddemo.views;
043:
044: import java.awt.BorderLayout;
045: import java.awt.Component;
046: import java.beans.PropertyVetoException;
047: import javax.swing.ActionMap;
048: import javax.swing.InputMap;
049: import javax.swing.JComponent;
050: import javax.swing.JPanel;
051: import javax.swing.JScrollPane;
052: import javax.swing.JTree;
053: import javax.swing.KeyStroke;
054: import javax.swing.text.DefaultEditorKit;
055: import javax.swing.tree.TreeModel;
056: import threaddemo.views.looktree.LookTreeView;
057: import org.openide.explorer.view.BeanTreeView;
058: import org.openide.nodes.Node;
059: import threaddemo.model.Phadhail;
060: import org.netbeans.api.nodes2looks.Nodes;
061: import org.netbeans.spi.looks.Selectors;
062: import org.openide.explorer.ExplorerManager;
063: import org.openide.explorer.ExplorerUtils;
064: import org.openide.nodes.Children;
065: import org.openide.nodes.FilterNode;
066: import org.openide.nodes.NodeMemberEvent;
067: import org.openide.nodes.NodeReorderEvent;
068: import org.openide.util.Lookup;
069: import org.openide.util.Mutex;
070: import org.openide.util.lookup.Lookups;
071: import threaddemo.locking.LockAction;
072: import threaddemo.locking.Locks;
073:
074: /**
075: * Factory for views over Phadhail.
076: * All views are automatically scrollable; you do not need to wrap them in JScrollPane.
077: * @author Jesse Glick
078: */
079: public class PhadhailViews {
080:
081: private PhadhailViews() {
082: }
083:
084: private static Component nodeBasedView(Node root) {
085: Node root2;
086: if (Children.MUTEX == Mutex.EVENT) {
087: // #35833 branch.
088: root2 = root;
089: } else {
090: root2 = new EQReplannedNode(root);
091: }
092: ExpPanel p = new ExpPanel();
093: p.setLayout(new BorderLayout());
094: JComponent tree = new BeanTreeView();
095: p.add(tree, BorderLayout.CENTER);
096: p.getExplorerManager().setRootContext(root2);
097: try {
098: p.getExplorerManager().setSelectedNodes(
099: new Node[] { root2 });
100: } catch (PropertyVetoException pve) {
101: pve.printStackTrace();
102: }
103: Object key = "org.openide.actions.PopupAction";
104: KeyStroke ks = KeyStroke.getKeyStroke("shift F10");
105: tree.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
106: .put(ks, key);
107: return p;
108: }
109:
110: /** use Nodes API with an Explorer view */
111: public static Component nodeView(Phadhail root) {
112: return nodeBasedView(new PhadhailNode(root));
113: }
114:
115: /** use Looks and Nodes API with an Explorer view */
116: public static Component lookNodeView(Phadhail root) {
117: return nodeBasedView(Nodes.node(root, null, Selectors
118: .selector(new PhadhailLookProvider())));
119: }
120:
121: /** use raw Looks API with a JTree */
122: public static Component lookView(Phadhail root) {
123: // XXX pending a stable API...
124: return new JScrollPane(new LookTreeView(root, Selectors
125: .selector(new PhadhailLookProvider())));
126: }
127:
128: /** use Phadhail directly in a JTree */
129: public static Component rawView(Phadhail root) {
130: TreeModel model = new PhadhailTreeModel(root);
131: JTree tree = new JTree(model) {
132: // Could also use a custom TreeCellRenderer, but this is a bit simpler for now.
133: public String convertValueToText(Object value,
134: boolean selected, boolean expanded, boolean leaf,
135: int row, boolean hasFocus) {
136: Phadhail ph = (Phadhail) value;
137: return ph.getPath();
138: }
139: };
140: tree.setLargeModel(true);
141: return new JScrollPane(tree);
142: }
143:
144: /**
145: * Workaround for the fact that Node/Look currently do not run only in AWT.
146: */
147: private static final class EQReplannedNode extends FilterNode {
148: public EQReplannedNode(Node n) {
149: super (n, n.isLeaf() ? Children.LEAF
150: : new EQReplannedChildren(n));
151: }
152:
153: public String getName() {
154: return Locks.event().read(new LockAction<String>() {
155: public String run() {
156: return EQReplannedNode.super .getName();
157: }
158: });
159: }
160:
161: public String getDisplayName() {
162: return Locks.event().read(new LockAction<String>() {
163: public String run() {
164: return EQReplannedNode.super .getDisplayName();
165: }
166: });
167: }
168: // XXX any other methods could also be replanned as needed
169: }
170:
171: private static final class EQReplannedChildren extends
172: FilterNode.Children {
173: public EQReplannedChildren(Node n) {
174: super (n);
175: }
176:
177: protected Node copyNode(Node n) {
178: return new EQReplannedNode(n);
179: }
180:
181: public Node findChild(final String name) {
182: return Locks.event().read(new LockAction<Node>() {
183: public Node run() {
184: return EQReplannedChildren.super .findChild(name);
185: }
186: });
187: }
188:
189: public Node[] getNodes(final boolean optimalResult) {
190: return Locks.event().read(new LockAction<Node[]>() {
191: public Node[] run() {
192: return EQReplannedChildren.super
193: .getNodes(optimalResult);
194: }
195: });
196: }
197:
198: protected void filterChildrenAdded(final NodeMemberEvent ev) {
199: Locks.event().readLater(new Runnable() {
200: public void run() {
201: EQReplannedChildren.super .filterChildrenAdded(ev);
202: }
203: });
204: }
205:
206: protected void filterChildrenRemoved(final NodeMemberEvent ev) {
207: Locks.event().readLater(new Runnable() {
208: public void run() {
209: EQReplannedChildren.super .filterChildrenRemoved(ev);
210: }
211: });
212: }
213:
214: protected void filterChildrenReordered(final NodeReorderEvent ev) {
215: Locks.event().readLater(new Runnable() {
216: public void run() {
217: EQReplannedChildren.super
218: .filterChildrenReordered(ev);
219: }
220: });
221: }
222: }
223:
224: /**
225: * Replacement for ExplorerPanel, which is deprecated (and uses Filesystems!).
226: * @see "#36315"
227: */
228: private static final class ExpPanel extends JPanel implements
229: ExplorerManager.Provider, Lookup.Provider {
230:
231: private final ExplorerManager manager;
232: private final Lookup lookup;
233:
234: public ExpPanel() {
235: manager = new ExplorerManager();
236: ActionMap map = getActionMap();
237: map.put(DefaultEditorKit.copyAction, ExplorerUtils
238: .actionCopy(manager));
239: map.put(DefaultEditorKit.cutAction, ExplorerUtils
240: .actionCut(manager));
241: map.put(DefaultEditorKit.pasteAction, ExplorerUtils
242: .actionPaste(manager));
243: map
244: .put("delete", ExplorerUtils.actionDelete(manager,
245: true));
246: lookup = ExplorerUtils.createLookup(manager, map);
247: InputMap keys = getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
248: keys.put(KeyStroke.getKeyStroke("control c"),
249: DefaultEditorKit.copyAction);
250: keys.put(KeyStroke.getKeyStroke("control x"),
251: DefaultEditorKit.cutAction);
252: keys.put(KeyStroke.getKeyStroke("control v"),
253: DefaultEditorKit.pasteAction);
254: keys.put(KeyStroke.getKeyStroke("DELETE"), "delete");
255: }
256:
257: public void addNotify() {
258: super .addNotify();
259: ExplorerUtils.activateActions(manager, true);
260: }
261:
262: public void removeNotify() {
263: ExplorerUtils.activateActions(manager, false);
264: super .removeNotify();
265: }
266:
267: public ExplorerManager getExplorerManager() {
268: return manager;
269: }
270:
271: public Lookup getLookup() {
272: return lookup;
273: }
274:
275: }
276:
277: }
|