diff --git a/Viewer/features/app.js b/Viewer/features/app.js index 3769dc2e..3dcc4e74 100755 --- a/Viewer/features/app.js +++ b/Viewer/features/app.js @@ -333,6 +333,29 @@ var ElectronHostActions = actions.Actions({ splash.destroy() } }], + + // XXX should this support resizing??? + copy: ['Image|Edit/Copy image', + core.doc`Copy image + + Copy current image (original ref)... + .copy() + + Copy best matching preview of current image... + .copy(size) + + `, + function(size){ + var url = this.images.getBestPreview(this.current, size, true).url + electron.clipboard.write({ + title: this.images.getImageFileName(), + text: url, + image: electron.nativeImage.createFromPath(url), + }) }], + paste: ['- Image|Edit/Paste image', + function(){ + // XXX + }], }) var ElectronHost = @@ -400,6 +423,46 @@ var BrowserHostActions = actions.Actions({ that.dom[0].style.visibility = '' }, 150) } })], + + + // XXX these do not work from file:// + // XXX should this support resizing??? + copy: ['Image|Edit/Copy image', + core.doc`Copy image + + Copy current image (original ref)... + .copy() + + Copy best matching preview of current image... + .copy(size) + + NOTE: this must be called from within an event handler... + NOTE: this will not work with file:// paths... + `, + function(size){ + var img = new Image; + var c = document.createElement("canvas"); + var ctx = c.getContext("2d"); + + img.onload = function(){ + c.width = this.naturalWidth + c.height = this.naturalHeight + ctx.drawImage(this, 0, 0) + c.toBlob(function(blob){ + // copy... + // XXX would be nice to add a path/title here... + navigator.clipboard.write([ + new ClipboardItem({ + [blob.type]: blob, + }) ]) }, + "image/png") } + img.crossOrigin = '' + img.src = this.images.getBestPreview(this.current, size, true).url + }], + paste: ['- Image|Edit/Paste image', + function(){ + // XXX + }], }) // NOTE: keep this defined last as a fallback... @@ -626,8 +689,7 @@ module.WindowedAppControl = core.ImageGridFeatures.Feature({ this.size = [w, h] cfg.devtools - && this.showDevTools() - } + && this.showDevTools() } // restore actual window state... this.restoreWindowGeometry() diff --git a/Viewer/features/filesystem.js b/Viewer/features/filesystem.js index 843d5d4f..7ab1a710 100755 --- a/Viewer/features/filesystem.js +++ b/Viewer/features/filesystem.js @@ -3132,6 +3132,9 @@ var FileSystemWriterUIActions = actions.Actions({ // Export presets... // + // XXX would be nice to be able to "export" (copy) single images as well... + // ...and it would be logical to have separate presets for single + // images and lists... (???) // XXX UI: // - element format: // TITLE diff --git a/Viewer/features/keyboard.js b/Viewer/features/keyboard.js index 9744c9b9..7a95cde7 100755 --- a/Viewer/features/keyboard.js +++ b/Viewer/features/keyboard.js @@ -434,9 +434,13 @@ module.GLOBAL_KEYBOARD = { // do the default copy thing... // NOTE: this stops the default: handler from getting the ctrl: // key case... - ctrl_C: 'NEXT', + //ctrl_C: 'NEXT', ctrl_V: 'NEXT', + // copy/paste image... + ctrl_C: 'copy', + //ctrl_V: 'paste', + // sort... //shift_S: 'sortImages: "Date" -- Sort images by date', diff --git a/Viewer/features/meta.js b/Viewer/features/meta.js index 1d45a1ac..2a278c3f 100755 --- a/Viewer/features/meta.js +++ b/Viewer/features/meta.js @@ -43,7 +43,7 @@ core.ImageGridFeatures.Feature('imagegrid-ui-minimal', [ 'keyboard', 'ui-cursor', 'ui-control', - 'ui-copy-image', + //'ui-copy-image', 'ui-drag-n-drop', // XXX use one... diff --git a/Viewer/features/ui-widgets.js b/Viewer/features/ui-widgets.js index ffeb119a..060a7c61 100755 --- a/Viewer/features/ui-widgets.js +++ b/Viewer/features/ui-widgets.js @@ -2199,6 +2199,8 @@ var BrowseActionsActions = actions.Actions({ '99:$Edit', 'Edit/90:Undo', 'Edit/90:Redo', + 'Edit/85:.*copy.*', + 'Edit/85:.*paste.*', 'Edit/85:.*base.*', 'Edit/80:.*sort.*', 'Edit/80:.*order.*', @@ -2212,6 +2214,8 @@ var BrowseActionsActions = actions.Actions({ 'Navigate/80:.*screen.*', 'Navigate/70:.*ribbon.*', '$Image', + 'Image/98:.*copy.*', + 'Image/98:.*paste.*', 'Image/98:.*editor.*', 'Image/98:.*folder.*', 'Image/95:.*metadata.*', diff --git a/Viewer/features/ui.js b/Viewer/features/ui.js index 2cba0626..c4df7561 100755 --- a/Viewer/features/ui.js +++ b/Viewer/features/ui.js @@ -1149,6 +1149,36 @@ module.Cursor = core.ImageGridFeatures.Feature({ +/*********************************************************************/ +// Copy... + +// XXX implement internal copy/paste... +var CopyImiage = +module.CopyImiage = core.ImageGridFeatures.Feature({ + title: '', + doc: '', + + tag: 'ui-copy-image', + depends: [ + 'ui' + ], + + actions: actions.Actions({ + // XXX mark copied image(s)... + copy: ['- Image|Edit/Copy image', + function(size){ + // XXX + }], + // XXX if pasted image(s) is the one(s) marked by copy, do a shift action... + paste: ['- Image|Edit/Paste image', + function(){ + // XXX + }], + }), +}) + + + /*********************************************************************/ // Touch/Control... // diff --git a/Viewer/imagegrid/images.js b/Viewer/imagegrid/images.js index ed00d638..ddf0f502 100755 --- a/Viewer/imagegrid/images.js +++ b/Viewer/imagegrid/images.js @@ -554,8 +554,7 @@ module.ImagesPrototype = { : '') + url, size: preview_size, - } - }, + } }, // Get image filename... // @@ -563,14 +562,11 @@ module.ImagesPrototype = { getImageFileName: function(gid, do_unescape){ do_unescape = do_unescape == null ? true : do_unescape if(!this[gid] || !this[gid].path){ - return gid - } + return gid } if(do_unescape){ return unescape(this[gid].path.split('/').pop()) } else { - return this[gid].path.split('/').pop() - } - }, + return this[gid].path.split('/').pop() } }, // Get the first sequence of numbers in the file name... // // NOTE: if no filenmae (.path) is set, this will return gid... (???)