From 7f08766392027977d8e14452c5be04dcbf645b1e Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 22 Jun 2016 15:17:28 -0700 Subject: [PATCH] GUACAMOLE-55: Add image support to the guacClipboard directive. --- .../app/client/directives/guacClipboard.js | 87 ++++++++++++++++++- .../webapp/app/client/styles/clipboard.css | 51 +++++++++++ .../webapp/app/client/styles/guac-menu.css | 8 -- .../app/client/templates/guacClipboard.html | 10 ++- 4 files changed, 144 insertions(+), 12 deletions(-) create mode 100644 guacamole/src/main/webapp/app/client/styles/clipboard.css diff --git a/guacamole/src/main/webapp/app/client/directives/guacClipboard.js b/guacamole/src/main/webapp/app/client/directives/guacClipboard.js index bd050c923..745577ad9 100644 --- a/guacamole/src/main/webapp/app/client/directives/guacClipboard.js +++ b/guacamole/src/main/webapp/app/client/directives/guacClipboard.js @@ -51,7 +51,7 @@ angular.module('client').directive('guacClipboard', [function guacClipboard() { * field. Changes to this value will be rendered within the field and, * if possible, will be pushed to the local clipboard. * - * @type String + * @type String|Blob */ data : '=' @@ -85,6 +85,74 @@ angular.module('client').directive('guacClipboard', [function guacClipboard() { */ var clipboardDataFromKey = {}; + /** + * The URL of the image is currently stored within the clipboard. If + * the clipboard currently contains text, this will be null. + * + * @type String + */ + $scope.imageURL = null; + + // Intercept paste events, handling image data specifically + $element[0].addEventListener('paste', function dataPasted(e) { + + // For each item within the clipboard + var items = e.clipboardData.items; + for (var i = 0; i < items.length; i++) { + + // If the item is an image, attempt to read that image + if (items[i].kind === 'file' && /^image\//.exec(items[i].type)) { + + // Set clipboard data to contents + $scope.$apply(function setClipboardData() { + $scope.data = items[i].getAsFile(); + }); + + // Do not paste + e.preventDefault(); + return; + + } + + } // end for each item + + }); + + /** + * Returns whether the clipboard currently contains only an image, the + * URL of which is exposed via the imageURL property. + * + * @returns {Boolean} + * true if the current clipboard contains only an image, false + * otherwise. + */ + $scope.isImage = function isImage() { + return !!$scope.imageURL; + }; + + /** + * Returns whether the clipboard currently contains only text. + * + * @returns {Boolean} + * true if the clipboard currently contains only text, false + * otherwise. + */ + $scope.isText = function isText() { + return !$scope.isImage(); + }; + + /** + * Clears the current clipboard contents. If the clipboard currently + * displays an image, this will also return to a text-based clipboard + * display. + */ + $scope.resetClipboard = function resetClipboard() { + + // Reset to blank + $scope.data = ''; + + }; + // Watch clipboard for new data, associating it with any pressed keys $scope.$watch('data', function clipboardChanged(data) { @@ -92,8 +160,21 @@ angular.module('client').directive('guacClipboard', [function guacClipboard() { for (var keysym in keysCurrentlyPressed) clipboardDataFromKey[keysym] = data; - // Notify of updated clipboard data - $rootScope.$broadcast('guacClipboard', 'text/plain', data); + // Revoke old image URL, if any + if ($scope.imageURL) { + URL.revokeObjectURL($scope.imageURL); + $scope.imageURL = null; + } + + // If the copied data was an image, display it as such + if (data instanceof Blob) { + $scope.imageURL = URL.createObjectURL(data); + $rootScope.$broadcast('guacClipboard', data.type, data); + } + + // Otherwise, the data is simply text + else + $rootScope.$broadcast('guacClipboard', 'text/plain', data); }); diff --git a/guacamole/src/main/webapp/app/client/styles/clipboard.css b/guacamole/src/main/webapp/app/client/styles/clipboard.css new file mode 100644 index 000000000..cade1aecb --- /dev/null +++ b/guacamole/src/main/webapp/app/client/styles/clipboard.css @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +.clipboard .image-clipboard, +.clipboard .text-clipboard textarea { + position: relative; + border: 1px solid #AAA; + -moz-border-radius: 0.25em; + -webkit-border-radius: 0.25em; + -khtml-border-radius: 0.25em; + border-radius: 0.25em; + background: white; +} + +.clipboard .text-clipboard textarea { + width: 100%; + white-space: pre; +} + +.clipboard .image-clipboard { + text-align: center; +} + +.clipboard .image-clipboard .reset-button { + position: absolute; + left: 0; + top: 0; + font-size: 0.75em; + min-width: 0; +} + +.clipboard .image-clipboard img { + max-width: 100%; + max-height: 480px; +} diff --git a/guacamole/src/main/webapp/app/client/styles/guac-menu.css b/guacamole/src/main/webapp/app/client/styles/guac-menu.css index 3f5460e93..2ddb432d3 100644 --- a/guacamole/src/main/webapp/app/client/styles/guac-menu.css +++ b/guacamole/src/main/webapp/app/client/styles/guac-menu.css @@ -66,14 +66,6 @@ } #guac-menu #clipboard-settings textarea { - width: 100%; - border: 1px solid #AAA; - -moz-border-radius: 0.25em; - -webkit-border-radius: 0.25em; - -khtml-border-radius: 0.25em; - border-radius: 0.25em; - white-space: pre; - display: block; font-size: 1em; } diff --git a/guacamole/src/main/webapp/app/client/templates/guacClipboard.html b/guacamole/src/main/webapp/app/client/templates/guacClipboard.html index 8b56ac83c..af4501956 100644 --- a/guacamole/src/main/webapp/app/client/templates/guacClipboard.html +++ b/guacamole/src/main/webapp/app/client/templates/guacClipboard.html @@ -1 +1,9 @@ - +
+
+ +
+
+ + +
+