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.EventQueue;
045: import java.io.IOException;
046: import java.util.Collection;
047: import java.util.Collections;
048: import java.util.IdentityHashMap;
049: import java.util.List;
050: import java.util.Map;
051: import java.util.logging.Logger;
052: import javax.swing.Action;
053: import javax.swing.event.ChangeEvent;
054: import javax.swing.event.ChangeListener;
055: import org.netbeans.spi.looks.Look;
056: import org.openide.actions.DeleteAction;
057: import org.openide.actions.NewAction;
058: import org.openide.actions.OpenAction;
059: import org.openide.actions.RenameAction;
060: import org.openide.actions.SaveAction;
061: import org.openide.util.Lookup;
062: import org.openide.util.LookupEvent;
063: import org.openide.util.LookupListener;
064: import org.openide.util.actions.SystemAction;
065: import org.openide.util.datatransfer.NewType;
066: import threaddemo.data.DomProvider;
067: import threaddemo.data.PhadhailLookups;
068: import threaddemo.data.PhadhailNewType;
069: import threaddemo.locking.Locks;
070: import threaddemo.model.Phadhail;
071: import threaddemo.model.PhadhailEvent;
072: import threaddemo.model.PhadhailListener;
073: import threaddemo.model.PhadhailNameEvent;
074:
075: /**
076: * A look which wraps phadhails.
077: * @author Jesse Glick
078: */
079: final class PhadhailLook extends Look<Phadhail> implements
080: PhadhailListener, LookupListener, ChangeListener {
081:
082: private static final Logger logger = Logger
083: .getLogger(PhadhailLook.class.getName());
084:
085: private static final Map<Phadhail, Lookup.Result<Object>> phadhails2Results = new IdentityHashMap<Phadhail, Lookup.Result<Object>>();
086: private static final Map<Lookup.Result, Phadhail> results2Phadhails = new IdentityHashMap<Lookup.Result, Phadhail>();
087: private static final Map<Phadhail, DomProvider> phadhails2DomProviders = new IdentityHashMap<Phadhail, DomProvider>();
088: private static final Map<DomProvider, Phadhail> domProviders2Phadhails = new IdentityHashMap<DomProvider, Phadhail>();
089:
090: PhadhailLook() {
091: super ("PhadhailLook");
092: }
093:
094: public String getDisplayName() {
095: return "Phadhails";
096: }
097:
098: protected void attachTo(Phadhail ph) {
099: ph.addPhadhailListener(this );
100: }
101:
102: protected void detachFrom(Phadhail ph) {
103: ph.removePhadhailListener(this );
104: Lookup.Result<Object> r = phadhails2Results.remove(ph);
105: if (r != null) {
106: r.removeLookupListener(this );
107: assert results2Phadhails.containsKey(r);
108: results2Phadhails.remove(r);
109: }
110: DomProvider p = phadhails2DomProviders.remove(ph);
111: if (p != null) {
112: p.removeChangeListener(this );
113: assert domProviders2Phadhails.containsKey(p);
114: domProviders2Phadhails.remove(p);
115: }
116: }
117:
118: public boolean isLeaf(Phadhail ph, Lookup e) {
119: assert EventQueue.isDispatchThread();
120: return !ph.hasChildren()
121: && PhadhailLookups.getLookup(ph).lookup(
122: DomProvider.class) == null;
123: }
124:
125: public List getChildObjects(final Phadhail ph, Lookup e) {
126: assert EventQueue.isDispatchThread();
127: if (ph.hasChildren()) {
128: return ph.getChildren();
129: } else {
130: DomProvider p = PhadhailLookups.getLookup(ph).lookup(
131: DomProvider.class);
132: if (p != null) {
133: if (!phadhails2DomProviders.containsKey(ph)) {
134: phadhails2DomProviders.put(ph, p);
135: assert !domProviders2Phadhails.containsKey(p);
136: domProviders2Phadhails.put(p, ph);
137: p.addChangeListener(this );
138: p.start();
139: }
140: if (p.isReady()) {
141: logger
142: .finer("DOM tree is ready, will ask for its document element");
143: // XXX do this block atomically in a lock?
144: try {
145: return Collections.singletonList(p
146: .getDocument().getDocumentElement());
147: } catch (IOException x) {
148: assert false : x;
149: }
150: } else {
151: logger.finer("DOM tree is not ready");
152: p.start();
153: // Cf. PhadhailLookSelector.StringLook:
154: return Collections.singletonList("Please wait...");
155: }
156: }
157: return null;
158: }
159: }
160:
161: public String getName(Phadhail ph, Lookup e) {
162: assert EventQueue.isDispatchThread();
163: return ph.getName();
164: }
165:
166: public String getDisplayName(Phadhail ph, Lookup e) {
167: assert EventQueue.isDispatchThread();
168: return ph.getPath();
169: }
170:
171: public boolean canRename(Phadhail ph, Lookup e) {
172: return true;
173: }
174:
175: public void rename(Phadhail ph, String newName, Lookup e)
176: throws IOException {
177: ph.rename(newName);
178: }
179:
180: public boolean canDestroy(Phadhail ph, Lookup e) {
181: return true;
182: }
183:
184: public void destroy(Phadhail ph, Lookup e) throws IOException {
185: ph.delete();
186: // XXX since this fires no changes of its own...
187: fireChange(ph, Look.DESTROY);
188: }
189:
190: public Action[] getActions(Phadhail ph, Lookup e) {
191: return new Action[] { SystemAction.get(OpenAction.class),
192: SystemAction.get(SaveAction.class), null,
193: SystemAction.get(NewAction.class), null,
194: SystemAction.get(DeleteAction.class),
195: SystemAction.get(RenameAction.class),
196: //SystemAction.get(ToolsAction.class),
197: };
198: }
199:
200: public NewType[] getNewTypes(Phadhail ph, Lookup e) {
201: if (ph.hasChildren()) {
202: return new NewType[] { new PhadhailNewType(ph, false),
203: new PhadhailNewType(ph, true), };
204: } else {
205: return new NewType[0];
206: }
207: }
208:
209: public Collection getLookupItems(Phadhail ph, Lookup env) {
210: assert EventQueue.isDispatchThread();
211: Lookup.Result<Object> r = phadhails2Results.get(ph);
212: if (r == null) {
213: Lookup l = PhadhailLookups.getLookup(ph);
214: r = l.lookupResult(Object.class);
215: assert r != null : "Null lookup from " + l + " in " + ph;
216: phadhails2Results.put(ph, r);
217: assert !results2Phadhails.containsKey(r);
218: results2Phadhails.put(r, ph);
219: r.addLookupListener(this );
220: }
221: return r.allItems();
222: }
223:
224: public void resultChanged(LookupEvent ev) {
225: // XXX #33372: should be able to do ev.getResult()
226: Lookup.Result r = (Lookup.Result) ev.getSource();
227: final Phadhail ph = results2Phadhails.get(r);
228: assert ph != null;
229: Locks.event().readLater(new Runnable() {
230: public void run() {
231: fireChange(ph, Look.GET_LOOKUP_ITEMS);
232: }
233: });
234: }
235:
236: public void childrenChanged(final PhadhailEvent ev) {
237: assert ev.getPhadhail().lock().canRead();
238: Locks.event().readLater(new Runnable() {
239: public void run() {
240: fireChange(ev.getPhadhail(), Look.GET_CHILD_OBJECTS);
241: }
242: });
243: }
244:
245: public void nameChanged(final PhadhailNameEvent ev) {
246: assert ev.getPhadhail().lock().canRead();
247: Locks.event().readLater(new Runnable() {
248: public void run() {
249: fireChange(ev.getPhadhail(), Look.GET_NAME
250: | Look.GET_DISPLAY_NAME);
251: }
252: });
253: }
254:
255: public void stateChanged(ChangeEvent e) {
256: logger.finer("got change");
257: DomProvider p = (DomProvider) e.getSource();
258: final Phadhail ph = domProviders2Phadhails.get(p);
259: assert ph != null;
260: Locks.event().readLater(new Runnable() {
261: public void run() {
262: fireChange(ph, Look.GET_CHILD_OBJECTS);
263: }
264: });
265: }
266:
267: }
|