001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package java.awt.datatransfer;
019:
020: import java.awt.EventQueue;
021: import java.io.IOException;
022: import java.util.HashSet;
023: import java.util.Iterator;
024: import java.util.Set;
025: import org.apache.harmony.awt.ContextStorage;
026: import org.apache.harmony.awt.ListenerList;
027: import org.apache.harmony.awt.wtk.Synchronizer;
028:
029: public class Clipboard {
030:
031: protected ClipboardOwner owner;
032:
033: protected Transferable contents;
034:
035: private final String name;
036: private final FlavorEventProcessor processor;
037: private final ListenerList<FlavorListener> listeners;
038: private Set<DataFlavor> flavors;
039: private final Synchronizer awtSynchronizer;
040:
041: public Clipboard(String name) {
042: this .name = name;
043: listeners = new ListenerList<FlavorListener>();
044: processor = new FlavorEventProcessor();
045: flavors = new HashSet<DataFlavor>();
046: awtSynchronizer = ContextStorage.getSynchronizer();
047: }
048:
049: public String getName() {
050: return name;
051: }
052:
053: public Transferable getContents(Object requestor) {
054: awtSynchronizer.lock();
055: try {
056: return contents;
057: } finally {
058: awtSynchronizer.unlock();
059: }
060: }
061:
062: public void setContents(Transferable contents, ClipboardOwner owner) {
063: awtSynchronizer.lock();
064: try {
065: boolean ownershipLost = (this .owner != owner);
066: boolean flavorsChanged;
067: HashSet<DataFlavor> newFlavorsSet = new HashSet<DataFlavor>();
068:
069: if (contents != null) {
070: DataFlavor[] newFlavorsArray = contents
071: .getTransferDataFlavors();
072:
073: for (DataFlavor element : newFlavorsArray) {
074: newFlavorsSet.add(element);
075: }
076: flavorsChanged = !flavors.equals(newFlavorsSet);
077: } else {
078: flavorsChanged = (flavors == null) ? false : true;
079: }
080:
081: if (flavorsChanged || ownershipLost) {
082: processor.setProcessingParams(
083: ownershipLost ? this .owner : null,
084: this .contents, flavorsChanged);
085: EventQueue.invokeLater(processor);
086: }
087:
088: this .contents = contents;
089: this .owner = owner;
090: flavors = newFlavorsSet;
091: } finally {
092: awtSynchronizer.unlock();
093: }
094: }
095:
096: public DataFlavor[] getAvailableDataFlavors() {
097: awtSynchronizer.lock();
098: try {
099: return (contents == null) ? new DataFlavor[0] : contents
100: .getTransferDataFlavors();
101: } finally {
102: awtSynchronizer.unlock();
103: }
104: }
105:
106: public boolean isDataFlavorAvailable(DataFlavor flavor) {
107: awtSynchronizer.lock();
108: try {
109: return (contents == null) ? false : contents
110: .isDataFlavorSupported(flavor);
111: } finally {
112: awtSynchronizer.unlock();
113: }
114: }
115:
116: public Object getData(DataFlavor flavor)
117: throws UnsupportedFlavorException, IOException {
118: awtSynchronizer.lock();
119: try {
120: if (contents == null) {
121: throw new UnsupportedFlavorException(flavor);
122: }
123: return contents.getTransferData(flavor);
124: } finally {
125: awtSynchronizer.unlock();
126: }
127: }
128:
129: public void addFlavorListener(FlavorListener listener) {
130: listeners.addUserListener(listener);
131: }
132:
133: public void removeFlavorListener(FlavorListener listener) {
134: listeners.removeUserListener(listener);
135: }
136:
137: public FlavorListener[] getFlavorListeners() {
138: return listeners.getUserListeners(new FlavorListener[0]);
139: }
140:
141: private void processFlavorEvent(FlavorEvent e) {
142: for (Iterator<?> i = listeners.getUserIterator(); i.hasNext();) {
143: ((FlavorListener) i.next()).flavorsChanged(e);
144: }
145: }
146:
147: private class FlavorEventProcessor implements Runnable {
148:
149: private Transferable oldContents;
150: private ClipboardOwner oldOwner;
151: private boolean flavorsChanged;
152:
153: void setProcessingParams(ClipboardOwner oldOwner,
154: Transferable oldContents, boolean flavorsChanged) {
155: this .oldContents = oldContents;
156: this .oldOwner = oldOwner;
157: this .flavorsChanged = flavorsChanged;
158: }
159:
160: public void run() {
161: if (oldOwner != null) {
162: oldOwner.lostOwnership(Clipboard.this , oldContents);
163: }
164: if (flavorsChanged) {
165: processFlavorEvent(new FlavorEvent(Clipboard.this));
166: }
167: }
168:
169: }
170:
171: }
|