1 /* 2 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package com.sun.glass.ui; 26 27 import com.sun.glass.ui.delegate.ClipboardDelegate; 28 29 import java.util.HashMap; 30 import java.util.HashSet; 31 import java.util.Map; 32 import java.util.Set; 33 34 import java.nio.ByteBuffer; 35 36 public class Clipboard { 37 /** 38 * predefined mime types 39 * Have to be synchronized with native realization. 40 */ 41 public final static String TEXT_TYPE = "text/plain"; 42 public final static String HTML_TYPE = "text/html"; 43 public final static String RTF_TYPE = "text/rtf"; 44 public final static String URI_TYPE = "text/uri-list";//http://www.ietf.org/rfc/rfc2483.txt 45 public final static String FILE_LIST_TYPE = "application/x-java-file-list"; 46 public final static String RAW_IMAGE_TYPE = "application/x-java-rawimage"; 47 public final static String DRAG_IMAGE = "application/x-java-drag-image"; 48 public final static String DRAG_IMAGE_OFFSET = "application/x-java-drag-image-offset"; 49 public final static String IE_URL_SHORTCUT_FILENAME = "text/ie-shortcut-filename"; 50 51 /** 52 * predefined drop-effect actions and combinations. 53 */ 54 public final static int ACTION_NONE = 0x0; 55 public final static int ACTION_COPY = 0x1; 56 public final static int ACTION_MOVE = 0x2; 57 public final static int ACTION_REFERENCE = 0x40000000; 58 public final static int ACTION_COPY_OR_MOVE = ACTION_COPY | ACTION_MOVE; 59 public final static int ACTION_ANY = 0x4FFFFFFF; 60 61 /** 62 * predefined clipboard name for system shared buffers 63 */ 64 public final static String DND = "DND"; 65 public final static String SYSTEM = "SYSTEM"; 66 public final static String SELECTION = "SELECTION"; 67 68 private final static Map <String, Clipboard> clipboards = new HashMap <String, Clipboard> (); 69 private final static ClipboardDelegate delegate = PlatformFactory.getPlatformFactory().createClipboardDelegate(); 70 71 private final HashSet <ClipboardAssistance> assistants = new HashSet <ClipboardAssistance> (); 72 private final String name; 73 private final Object localDataProtector = new Object(); 74 private HashMap <String, Object> localSharedData; 75 private ClipboardAssistance dataSource; 76 77 /** 78 * combination of ACTION_XXXX constants 79 */ 80 protected int supportedActions = ACTION_COPY; 81 82 protected Clipboard (String name) { 83 Application.checkEventThread(); 84 this.name = name; 85 } 86 87 public void add (ClipboardAssistance assistant) { 88 Application.checkEventThread(); 89 synchronized(assistants) { 90 assistants.add(assistant); 91 } 92 } 93 94 public void remove (ClipboardAssistance assistant) { 95 Application.checkEventThread(); 96 synchronized(localDataProtector) { 97 if (assistant==dataSource) { 98 dataSource = null; 99 } 100 } 101 boolean needClose; 102 synchronized(assistants) { 103 assistants.remove(assistant); 104 needClose = assistants.isEmpty(); 105 } 106 107 if (needClose) { 108 synchronized(clipboards) { 109 clipboards.remove(name); 110 } 111 close(); 112 } 113 } 114 115 protected void setSharedData ( 116 ClipboardAssistance dataSource, 117 HashMap<String, Object> cacheData, 118 int supportedActions) 119 { 120 Application.checkEventThread(); 121 synchronized(localDataProtector) { 122 localSharedData = (HashMap<String, Object>) cacheData.clone(); 123 this.supportedActions = supportedActions; 124 this.dataSource = dataSource; 125 } 126 } 127 128 /** 129 * 130 * @param cacheData 131 * @param supportedActions combination of ACTION_XXXX consts 132 */ 133 public void flush( 134 ClipboardAssistance dataSource, 135 HashMap<String, Object> cacheData, 136 int supportedActions) 137 { 138 Application.checkEventThread(); 139 setSharedData(dataSource, cacheData, supportedActions); 140 contentChanged(); 141 } 142 143 public int getSupportedSourceActions() { 144 Application.checkEventThread(); 145 return this.supportedActions; 146 } 147 148 public void setTargetAction(int actionDone) { 149 Application.checkEventThread(); 150 actionPerformed(actionDone); 151 } 152 153 public void contentChanged() { 154 Application.checkEventThread(); 155 final HashSet <ClipboardAssistance> _assistants; 156 synchronized(assistants) { 157 _assistants = (HashSet <ClipboardAssistance>)assistants.clone(); 158 } 159 for (ClipboardAssistance assistant : _assistants) { 160 assistant.contentChanged(); 161 } 162 } 163 164 /** 165 * Called by system and notifies about successful data transfer. 166 * Delete-on-move functionality should be implemented here. 167 * @param action Clipboard.ACTION_COPY, or Clipboard.ACTION_MOVE, or Clipboard.ACTION_REFERENCE 168 */ 169 public void actionPerformed(int action) { 170 Application.checkEventThread(); 171 synchronized(localDataProtector) { 172 if (null!=dataSource) { 173 dataSource.actionPerformed(action); 174 } 175 } 176 } 177 178 179 public Object getData (String mimeType) { 180 Application.checkEventThread(); 181 synchronized(localDataProtector) { 182 if (localSharedData == null) { 183 return null; 184 } 185 Object ret = localSharedData.get(mimeType); 186 return (ret instanceof DelayedCallback) 187 ? ((DelayedCallback)ret).providedData() 188 : ret; 189 } 190 } 191 192 public String[] getMimeTypes () { 193 Application.checkEventThread(); 194 synchronized(localDataProtector) { 195 if (localSharedData == null) { 196 return null; 197 } 198 Set<String> mimes = localSharedData.keySet(); 199 String [] ret = new String[mimes.size()]; 200 int i = 0; 201 for (String mime : mimes) { 202 ret[i++] = mime; 203 } 204 return ret; 205 } 206 } 207 208 /* We have only one clipboard for each name. 209 * but it can be used by several @code{ClipboardAssistance}s 210 */ 211 protected static Clipboard get (String clipboardName) { 212 Application.checkEventThread(); 213 /* return apropriate one*/ 214 synchronized(clipboards) { 215 if (!clipboards.keySet().contains(clipboardName)) { 216 Clipboard newClipboard = delegate.createClipboard(clipboardName); 217 if (newClipboard == null) { 218 newClipboard = new Clipboard(clipboardName); 219 } 220 clipboards.put(clipboardName, newClipboard); 221 } 222 return clipboards.get(clipboardName); 223 } 224 } 225 226 public Pixels getPixelsForRawImage(byte rawimage[]) { 227 Application.checkEventThread(); 228 ByteBuffer size = ByteBuffer.wrap(rawimage, 0, 8); 229 int width = size.getInt(); 230 int height = size.getInt(); 231 232 ByteBuffer pixels = ByteBuffer.wrap(rawimage, 8, rawimage.length - 8); // drop width+height 233 return Application.GetApplication().createPixels(width, height, pixels.slice()); 234 } 235 236 @Override public String toString () { 237 return "Clipboard: " + name + "@" + hashCode(); 238 } 239 240 protected void close() { 241 Application.checkEventThread(); 242 synchronized(localDataProtector) { 243 dataSource = null; 244 } 245 } 246 247 public String getName() { 248 Application.checkEventThread(); 249 return name; 250 } 251 252 public static String getActionString (int action) { 253 Application.checkEventThread(); 254 StringBuilder ret = new StringBuilder(""); 255 int[] test = { 256 ACTION_COPY, 257 ACTION_MOVE, 258 ACTION_REFERENCE}; 259 String[] canDo = { 260 "copy", 261 "move", 262 "link"}; 263 for (int i =0; i < 3; ++i) { 264 if ((test[i] & action) > 0) { 265 if (ret.length() > 0) { 266 ret.append(","); 267 } 268 ret.append(canDo[i]); 269 } 270 } 271 return ret.toString(); 272 } 273 }