Spec-Zone .ru
спецификации, руководства, описания, API
001/*
002 * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation.  Oracle designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Oracle in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
022 * or visit www.oracle.com if you need additional information or have any
023 * questions.
024 */
025
026package javafx.scene.input;
027
028import java.io.File;
029import java.security.AccessControlContext;
030import java.security.AccessController;
031import java.util.List;
032import java.util.Map;
033import java.util.Set;
034
035import javafx.scene.image.Image;
036import javafx.util.Pair;
037
038import com.sun.javafx.tk.TKClipboard;
039import com.sun.javafx.tk.Toolkit;
040
041/**
042 * Represents an operating system clipboard, on which data may be placed during, for
043 * example, cut, copy, and paste operations.
044 * <p>
045 * To access the general system clipboard, use the following code:
046 * <pre><code>
047 *     Clipboard clipboard = Clipboard.getSystemClipboard();
048 * </code></pre>
049 * <p>
050 * There is only ever one instance of the system clipboard in the application, so it is
051 * perfectly acceptable to stash a reference to it somewhere handy if you so choose.
052 * <p>
053 * The Clipboard operates on the concept of having a single conceptual item on the
054 * clipboard at any one time -- though it may be placed on the clipboard in different
055 * formats. For example, the user might select text in an HTML editor and press the
056 * ctrl+c or cmd+c to copy it. In this case, the same text might be available on the
057 * clipboard both as HTML and as plain text. There are two copies of the data on the
058 * clipboard, but they both represent the same data.
059 * <p>
060 * Content is specified on the Clipboard by using the {@link #setContent}
061 * method. First, construct a ClipboardContent object, then invoke setContent. Every time
062 * setContent is called, any previous data on the clipboard is cleared and replaced with
063 * this new content.
064 * <pre><code>
065 *     final Clipboard clipboard = Clipboard.getSystemClipboard();
066 *     final ClipboardContent content = new ClipboardContent();
067 *     content.putString("Some text");
068 *     content.putHtml("&lt;b&gt;Some&lt;/b&gt; text");
069 *     clipboard.setContent(content);
070 * </code></pre>
071 * <p>
072 * The {@link ClipboardContent} class is simply a map with convenience methods for dealing
073 * with common data types added to a clipboard.
074 * <p>
075 * Because multiple representations of the same data may exist on the clipboard, and because
076 * different applications have different capabilities for handling different content types,
077 * it is important to place as many data representations on the clipboard as is practical to
078 * facilitate external applications. Note that sometimes the operating system might be
079 * helpful in some cases and add multiple types for you. For example, the Mac might set the
080 * plain text string for you when you specify the RTF type. How and under what circumstances
081 * this occurs is outside the realm of this specification, consult your OS documentation.
082 * <p>
083 * When reading data off the clipboard, it is important to look for the richest
084 * supported type first. For example, if I have a text document which supports embedding of
085 * images and media formats, when pasting content from the clipboard I should first check to
086 * see if the content can be represented as media or as an image. If not, then I might check
087 * for RTF or HTML or whatever rich text format is supported by my document type. If not,
088 * then I might just take a String.
089 * <p>
090 * Or for example, if I have a plain text document, then I would simple get a String
091 * representation and use that, if available. I can check to see if the clipboard "hasHtml"
092 * or "hasString".
093 * <pre><code>
094 *     if (clipboard.hasString()) { ... }
095 * </pre></code>
096 * <p>
097 * In addition to the common or built in types, you may put any arbitrary data onto the
098 * clipboard (assuming it is serializable).
099 * <p>
100 * Content types are defined by the DataFormat objects.
101 * The DataFormat class defines an immutable object, and there are a number of static final
102 * fields for common DataFormat types. Of course application specific DataFormat types can also be
103 * declared and used. The following two methods are equivalent (and the second call
104 * will override the first!)
105 * <pre><code>
106 *     ClipboardContent content = new ClipboardContent();
107 *     content.putString("some text");
108 *     content.put(DataFormat.PLAIN_TEXT, "other text");
109 * </pre></code>
110 * <p>
111 * On embedded platforms that do not have their own windowing system, the
112 * Clipboard returned from Clipboard.getSystemClipboard() might not be
113 * accessible from outside the JavaFX application. In this case, the clipboard
114 * returned by Clipboard.getSystemClipboard() can be used for exchange of data
115 * between different parts of one JavaFX application but cannot be used to
116 * exchange data between multiple applications.
117 */
118public class Clipboard {
119
120    /**
121     * Whether user has put something on this clipboard. Needed for DnD.
122     */
123    private boolean contentPut = false;
124
125    // future:
126    /*
127     * JavaFX supports the concept of multiple independently named clipboards. There is a
128     * predefined clipboard which represents the main system clipboard, but it is possible
129     * to create custom clipboards if you so desire. Some platforms, such as Mac OS X,
130     * define a number of different named clipboards. You can access these from JavaFX by
131     * simply creating a Clipboard with the correct name. Typically there is no need to do
132     * so in your applications since the UI Controls will use the correct System clipboards,
133     * if applicable.
134     * <p>
135     *
136     * Sometimes you may want to put a reference to a data representation on the clipboard
137     *
138     * rather than the data itself. For example, the user may have selected a large block of
139     * text, and wants to copy this to the clipboard. Instead of having to actually produce
140     * multiple copies of this text, a reference can be placed on the clipboard instead. When
141     * the developer subsequently attempts to read the value off the clipboard, this reference
142     * is resolved. Or suppose that I want to put a Node on the clipboard, such that the
143     * representation of that Node on the clipboard is as an image.
144     * <pre><code>
145     *     final Node node = ...;
146     *     ClipboardReference ref = new ClipboardReference() {
147     *         @Override public InputStream get() {
148     *             // convert the node to an image
149     *             // return an input stream to the image
150     *             ...
151     *         }
152     *     };
153     *     clipboard.putReference(DataFormat.IMAGE_TIFF, ref);
154     * </pre></code>
155     * <p>
156     * At the appropriate time, a client reading off the clipboard will ask for the data and
157     * the system will invoke the provided callback to stream the image data over to the client.
158     */
159
160    private static Clipboard systemClipboard = null;
161
162    private final AccessControlContext acc = AccessController.getContext();
163    
164    /**
165     * Gets the current system clipboard, through which data can be stored and
166     * retrieved. There is ever only one system clipboard for a JavaFX application.
167     * @return The single system clipboard, used for cut / copy / paste operations
168     */
169    public static Clipboard getSystemClipboard() {
170        if (systemClipboard == null) {
171            systemClipboard = new Clipboard(Toolkit.getToolkit().getSystemClipboard());
172        }
173        return systemClipboard;
174    }
175
176    TKClipboard peer;
177
178    // Only allow Dragboard to extend from this
179    Clipboard(TKClipboard peer) {
180        Toolkit.getToolkit().checkFxUserThread();
181        if (peer == null) {
182            throw new NullPointerException();
183        }
184        peer.setSecurityContext(acc);
185        this.peer = peer;
186    }
187
188    /**
189     * Clears the clipboard of any and all content. Any subsequent call to
190     * {@link #getContentTypes} before putting more content on the clipboard
191     * will result in an empty set being returned.
192     */
193    public final void clear() {
194        setContent(null);
195    }
196
197    /**
198     * Gets the set of DataFormat types on this Clipboard instance which have
199     * associated data registered on the clipboard. This set will always
200     * be non-null and immutable. If the Clipboard is subsequently modifed,
201     * this returned set is not updated.
202     *
203     * @return A non-null immutable set of content types.
204     */
205    public final Set<DataFormat> getContentTypes() {
206        return peer.getContentTypes();
207    }
208
209    /**
210     * Puts content onto the clipboard. This call will always result in
211     * clearing all previous content from the clipboard, and replacing
212     * it with whatever content is specified in the supplied
213     * ClipboardContent map.
214     *
215     * @param content The content to put on the clipboard. If null, the
216     *        clipboard is simply cleared and no new content added.
217     * @return True if successful, false if the content fails to be added.
218     * @throws NullPointerException if null data reference is passed for any 
219     *                              format
220     */
221//    public abstract boolean setContent(DataFormat uti, Object content);
222    public final boolean setContent(Map<DataFormat, Object> content) {
223        Toolkit.getToolkit().checkFxUserThread();
224        if (content == null) {
225            contentPut = false;
226            peer.putContent(new Pair[0]);
227            return true;
228        } else {
229            Pair<DataFormat, Object>[] data = new Pair[content.size()];
230            int index = 0;
231            for (Map.Entry<DataFormat, Object> entry : content.entrySet()) {
232                data[index++] = new Pair<DataFormat, Object>(entry.getKey(), entry.getValue());
233            }
234            contentPut = peer.putContent(data);
235            return contentPut;
236        }
237    }
238
239    /**
240     * Returns the content stored in this clipboard of the given type, or null
241     * if there is no content with this type.
242     * @return The content associated with this type, or null if there is none
243     */
244    public final Object getContent(DataFormat dataFormat) {
245        Toolkit.getToolkit().checkFxUserThread();
246        return peer.getContent(dataFormat);
247    }
248
249    /**
250     * Tests whether there is any content on this clipboard of the given DataFormat type.
251     * @return true if there is content on this clipboard for this type
252     */
253    public final boolean hasContent(DataFormat dataFormat) {
254        Toolkit.getToolkit().checkFxUserThread();
255        return peer.hasContent(dataFormat);
256    }
257
258    /**
259     * Gets whether a plain text String (DataFormat.PLAIN_TEXT) has been registered
260     * on this Clipboard.
261     * @return true if <code>hasContent(DataFormat.PLAIN_TEXT)</code> returns true, false otherwise
262     */
263    public final boolean hasString() {
264        return hasContent(DataFormat.PLAIN_TEXT);
265    }
266
267    /**
268     * Gets the plain text String from the clipboard which had previously
269     * been registered. This is equivalent to invoking
270     * <code>getContent(DataFormat.PLAIN_TEXT)</code>. If no such entry exists,
271     * null is returned.
272     * @return The String on the clipboard associated with DataFormat.PLAIN_TEXT,
273     * or null if there is not one.
274     */
275    public final String getString() {
276        return (String) getContent(DataFormat.PLAIN_TEXT);
277    }
278
279    /**
280     * Gets whether a url String (DataFormat.URL) has been registered
281     * on this Clipboard.
282     * @return true if hasContent(DataFormat.URL) returns true, false otherwise
283     */
284    public final boolean hasUrl() {
285        return hasContent(DataFormat.URL);
286    }
287
288    /**
289     * Gets the URL String from the clipboard which had previously
290     * been registered. This is equivalent to invoking
291     * <code>getContent(DataFormat.URL)</code>. If no such entry exists,
292     * null is returned.
293     * @return The String on the clipboard associated with DataFormat.URL,
294     * or null if there is not one.
295     */
296    public final String getUrl() {
297        return (String) getContent(DataFormat.URL);
298    }
299
300    /**
301     * Gets whether an HTML text String (DataFormat.HTML) has been registered
302     * on this Clipboard.
303     * @return true if <code>hasContent(DataFormat.HTML)</code> returns true, false otherwise
304     */
305    public final boolean hasHtml() {
306        return hasContent(DataFormat.HTML);
307    }
308
309    /**
310     * Gets the HTML text String from the clipboard which had previously
311     * been registered. This is equivalent to invoking
312     * <code>getContent(DataFormat.HTML)</code>. If no such entry exists,
313     * null is returned.
314     * @return The String on the clipboard associated with DataFormat.HTML,
315     * or null if there is not one.
316     */
317    public final String getHtml() {
318        return (String) getContent(DataFormat.HTML);
319    }
320
321    /**
322     * Gets whether an RTF String (DataFormat.RTF) has been registered
323     * on this Clipboard.
324     * @return true if hasContent(DataFormat.RTF) returns true, false otherwise
325     */
326    public final boolean hasRtf() {
327        return hasContent(DataFormat.RTF);
328    }
329
330    /**
331     * Gets the RTF text String from the clipboard which had previously
332     * been registered. This is equivalent to invoking
333     * <code>getContent(DataFormat.RTF)</code>. If no such entry exists,
334     * null is returned.
335     * @return The String on the clipboard associated with DataFormat.RTF,
336     * or null if there is not one.
337     */
338    public final String getRtf() {
339        return (String) getContent(DataFormat.RTF);
340    }
341
342    /**
343     * Gets whether an Image (DataFormat.IMAGE) has been registered
344     * on this Clipboard.
345     * @return true if hasContent(DataFormat.IMAGE) returns true, false otherwise
346     */
347    public final boolean hasImage() {
348        return hasContent(DataFormat.IMAGE);
349    };
350
351    /**
352     * Gets the Image from the clipboard which had previously
353     * been registered. This is equivalent to invoking
354     * <code>getContent(DataFormat.IMAGE)</code>. If no such entry exists,
355     * null is returned.
356     * @return The Image on the clipboard associated with DataFormat.IMAGE,
357     * or null if there is not one.
358     */
359    public final Image getImage() {
360        return (Image) getContent(DataFormat.IMAGE);
361    }
362
363    /**
364     * Gets whether an List of Files (DataFormat.FILES) has been registered
365     * on this Clipboard.
366     * @return true if hasContent(DataFormat.FILES) returns true, false otherwise
367     */
368    public final boolean hasFiles() {
369        return hasContent(DataFormat.FILES);
370    }
371
372    /**
373     * Gets the List of Files from the clipboard which had previously
374     * been registered. This is equivalent to invoking
375     * <code>getContent(DataFormat.FILES)</code>. If no such entry exists,
376     * null is returned.
377     * @return The List of Files on the clipboard associated with DataFormat.FILES,
378     * or null if there is not one.
379     */
380    public final List<File> getFiles() {
381        return (List<File>) getContent(DataFormat.FILES);
382    }
383
384    /**
385     * @treatAsPrivate implementation detail
386     * @deprecated This is an internal API that is not intended for use and will be removed in the next version
387     */
388    @Deprecated
389    public boolean impl_contentPut() {
390        return contentPut;
391    }
392}