diff --git a/src/css/settings-export.css b/src/css/settings-export.css new file mode 100644 index 00000000..7d05dd7f --- /dev/null +++ b/src/css/settings-export.css @@ -0,0 +1,47 @@ + +/* Gif/Png Export Setting panel*/ +/*******************************/ +.gif-upload-button, +.gif-render-button { + /*float : right;*/ + margin-top : 10px; + margin-right : 10px; +} + +.gif-export-radio-group { + margin:10px 0; +} + +.gif-export-preview, +.png-export-preview { + margin-top:20px; + max-width:240px; + position:relative; +} + +.png-export-preview { + margin:10px 0; + overflow: hidden; +} + +.png-export-preview img { + float: left; +} + +.png-upload-status { + margin : 10px 0; +} + +.preview-upload-ongoing:before{ + content: "Upload ongoing ..."; + position: absolute; + display: block; + height: 100%; + width: 100%; + text-align: center; + padding-top: 45%; + box-sizing:border-box; + -moz-box-sizing:border-box; + background: rgba(0,0,0,0.5); + color: white; +} \ No newline at end of file diff --git a/src/css/settings.css b/src/css/settings.css index 31ee0af5..fe592471 100644 --- a/src/css/settings.css +++ b/src/css/settings.css @@ -21,9 +21,9 @@ margin-right: 0; } -/* - * Settings icons - */ +/********************************************************** *j* j** j*j j j j** *****************/ +/* Settings icons I I I I I\I \ */ +/********************************************************** *** *** *** * * '** *****************/ .tool-icon.gallery-icon { background-image: url(../img/gallery.png); @@ -104,6 +104,10 @@ border-left : 3px solid gold; } +/************************************************************************************************/ +/* Common settings classes */ +/************************************************************************************************/ + .settings-section { margin: 10px 20px; font-size: 12px; @@ -133,6 +137,10 @@ margin-bottom: 10px; } +/************************************************************************************************/ +/* Application settings */ +/************************************************************************************************/ + .background-picker-wrapper { overflow: hidden; padding: 10px 5px 20px 5px; @@ -166,11 +174,12 @@ border: gold 1px solid; } -/* Gif/Png Export Setting panel*/ -/*******************************/ +/************************************************************************************************/ +/* Gif/Png Export panel */ +/************************************************************************************************/ + .gif-upload-button, .gif-render-button { - /*float : right;*/ margin-top : 10px; margin-right : 10px; } @@ -179,6 +188,17 @@ margin:10px 0; } +.gif-export-progress-status { + margin-left: 5px; +} + +.gif-export-progress-bar { + margin-top:5px; + height:3px; + width: 0; + background:gold; +} + .gif-export-preview, .png-export-preview { margin-top:20px; @@ -213,7 +233,10 @@ color: white; } -/* Import panel */ +/************************************************************************************************/ +/* Import panel */ +/************************************************************************************************/ + .import-section, .resize-section { margin: 15px 0; @@ -291,6 +314,11 @@ vertical-align: middle; } + +/************************************************************************************************/ +/* Browse local piskels panel */ +/************************************************************************************************/ + .local-piskels-list { width: 100%; } diff --git a/src/js/Events.js b/src/js/Events.js index 23d4aa86..07d75b09 100644 --- a/src/js/Events.js +++ b/src/js/Events.js @@ -17,13 +17,6 @@ var Events = { PALETTE_LIST_UPDATED : 'PALETTE_LIST_UPDATED', - /** - * When this event is emitted, a request is sent to the localstorage - * Service to save the current framesheet. The storage service - * may not immediately store data (internal throttling of requests). - */ - LOCALSTORAGE_REQUEST: "LOCALSTORAGE_REQUEST", - /** * Fired each time a user setting change. * The payload will be: diff --git a/src/js/controller/DrawingController.js b/src/js/controller/DrawingController.js index ba98036a..1cb9dd7f 100644 --- a/src/js/controller/DrawingController.js +++ b/src/js/controller/DrawingController.js @@ -139,8 +139,6 @@ this.overlayFrame, event ); - - $.publish(Events.LOCALSTORAGE_REQUEST); } }; @@ -166,11 +164,6 @@ this.overlayFrame, event ); - - // TODO(vincz): Find a way to move that to the model instead of being at the interaction level. - // Eg when drawing, it may make sense to have it here. However for a non drawing tool, - // you don't need to draw anything when mousemoving and you request useless localStorage. - $.publish(Events.LOCALSTORAGE_REQUEST); } else { this.currentToolBehavior.moveUnactiveToolAt( diff --git a/src/js/controller/PreviewFilmController.js b/src/js/controller/PreviewFilmController.js index 8fdce874..8b9e90a1 100644 --- a/src/js/controller/PreviewFilmController.js +++ b/src/js/controller/PreviewFilmController.js @@ -1,5 +1,13 @@ (function () { var ns = $.namespace("pskl.controller"); + + var ACTION = { + SELECT : 'select', + CLONE : 'clone', + DELETE : 'delete', + NEW_FRAME : 'newframe' + }; + ns.PreviewFilmController = function (piskelController, container) { this.piskelController = piskelController; @@ -15,12 +23,7 @@ $.subscribe(Events.PISKEL_RESET, this.refreshZoom_.bind(this)); $('#preview-list-scroller').scroll(this.updateScrollerOverflows.bind(this)); - this.updateScrollerOverflows(); - }; - - ns.PreviewFilmController.prototype.addFrame = function () { - this.piskelController.addFrame(); - this.piskelController.setCurrentFrameIndex(this.piskelController.getFrameCount() - 1); + this.container.get(0).addEventListener('click', this.onContainerClick_.bind(this)); this.updateScrollerOverflows(); }; @@ -62,6 +65,29 @@ wrapper.toggleClass('bottom-overflow-visible', overflowBottom); }; + ns.PreviewFilmController.prototype.onContainerClick_ = function (event) { + var target = pskl.utils.Dom.getParentWithData(event.target, 'tileAction'); + if (!target) { + return; + } + var action = target.dataset.tileAction; + var index = target.dataset.tileNumber; + + if (action === ACTION.CLONE) { + this.piskelController.setCurrentFrameIndex(index + 1); + this.updateScrollerOverflows(); + } else if (action === ACTION.DELETE) { + this.piskelController.removeFrameAt(index); + this.updateScrollerOverflows(); + } else if (action === ACTION.SELECT) { + this.piskelController.setCurrentFrameIndex(index); + } else if (action === ACTION.NEW_FRAME) { + this.piskelController.addFrame(); + this.piskelController.setCurrentFrameIndex(this.piskelController.getFrameCount() - 1); + this.updateScrollerOverflows(); + } + }; + ns.PreviewFilmController.prototype.createPreviews_ = function () { this.container.html(""); @@ -77,11 +103,10 @@ var newFrameButton = document.createElement("div"); newFrameButton.id = "add-frame-action"; newFrameButton.className = "add-frame-action"; + newFrameButton.setAttribute('data-tile-action', ACTION.NEW_FRAME); newFrameButton.innerHTML = "

Add new frame

"; this.container.append(newFrameButton); - $(newFrameButton).click(this.addFrame.bind(this)); - var needDragndropBehavior = (frameCount > 1); if(needDragndropBehavior) { this.initDragndropBehavior_(); @@ -112,9 +137,6 @@ this.piskelController.moveFrame(originFrameId, targetInsertionId); this.piskelController.setCurrentFrameIndex(targetInsertionId); - - // TODO(grosbouddha): move localstorage request to the model layer? - $.publish(Events.LOCALSTORAGE_REQUEST); }; @@ -128,6 +150,7 @@ var previewTileRoot = document.createElement("li"); var classname = "preview-tile"; previewTileRoot.setAttribute("data-tile-number", tileNumber); + previewTileRoot.setAttribute('data-tile-action', ACTION.SELECT); if (this.piskelController.getCurrentFrame() == currentFrame) { classname += " selected"; @@ -141,15 +164,14 @@ canvasBackground.className = "canvas-background"; canvasContainer.appendChild(canvasBackground); - previewTileRoot.addEventListener('click', this.onPreviewClick_.bind(this, tileNumber)); - var cloneFrameButton = document.createElement("button"); cloneFrameButton.setAttribute('rel', 'tooltip'); cloneFrameButton.setAttribute('data-placement', 'right'); + cloneFrameButton.setAttribute('data-tile-number', tileNumber); + cloneFrameButton.setAttribute('data-tile-action', ACTION.CLONE); cloneFrameButton.setAttribute('title', 'Duplicate this frame'); cloneFrameButton.className = "tile-overlay duplicate-frame-action"; previewTileRoot.appendChild(cloneFrameButton); - cloneFrameButton.addEventListener('click', this.onAddButtonClick_.bind(this, tileNumber)); // TODO(vincz): Eventually optimize this part by not recreating a FrameRenderer. Note that the real optim // is to make this update function (#createPreviewTile) less aggressive. @@ -169,8 +191,9 @@ deleteButton.setAttribute('rel', 'tooltip'); deleteButton.setAttribute('data-placement', 'right'); deleteButton.setAttribute('title', 'Delete this frame'); + deleteButton.setAttribute('data-tile-number', tileNumber); + deleteButton.setAttribute('data-tile-action', ACTION.DELETE); deleteButton.className = "tile-overlay delete-frame-action"; - deleteButton.addEventListener('click', this.onDeleteButtonClick_.bind(this, tileNumber)); previewTileRoot.appendChild(deleteButton); // Add 'dragndrop handle'. @@ -183,30 +206,9 @@ tileCount.innerHTML = tileNumber + 1; previewTileRoot.appendChild(tileCount); - return previewTileRoot; }; - ns.PreviewFilmController.prototype.onPreviewClick_ = function (index, evt) { - // has not class tile-action: - if(!evt.target.classList.contains('tile-overlay')) { - this.piskelController.setCurrentFrameIndex(index); - } - }; - - ns.PreviewFilmController.prototype.onDeleteButtonClick_ = function (index, evt) { - this.piskelController.removeFrameAt(index); - $.publish(Events.LOCALSTORAGE_REQUEST); // Should come from model - this.updateScrollerOverflows(); - }; - - ns.PreviewFilmController.prototype.onAddButtonClick_ = function (index, evt) { - this.piskelController.duplicateFrameAt(index); - $.publish(Events.LOCALSTORAGE_REQUEST); // Should come from model - this.piskelController.setCurrentFrameIndex(index + 1); - this.updateScrollerOverflows(); - }; - /** * Calculate the preview zoom depending on the piskel size */ diff --git a/src/js/controller/settings/GifExportController.js b/src/js/controller/settings/GifExportController.js index 9a5bd75f..11de80f5 100644 --- a/src/js/controller/settings/GifExportController.js +++ b/src/js/controller/settings/GifExportController.js @@ -28,14 +28,17 @@ ns.GifExportController.prototype.init = function () { this.radioTemplate_ = pskl.utils.Template.get("gif-export-radio-template"); - this.uploadStatusContainerEl = document.querySelectorAll(".gif-upload-status")[0]; + this.uploadStatusContainerEl = document.querySelector(".gif-upload-status"); - this.previewContainerEl = document.querySelectorAll(".gif-export-preview")[0]; - this.radioGroupEl = document.querySelectorAll(".gif-export-radio-group")[0]; + this.previewContainerEl = document.querySelector(".gif-export-preview"); + this.radioGroupEl = document.querySelector(".gif-export-radio-group"); this.uploadForm = $("[name=gif-export-upload-form]"); this.uploadForm.submit(this.onUploadFormSubmit_.bind(this)); + this.exportProgressStatusEl = document.querySelector('.gif-export-progress-status'); + this.exportProgressBarEl = document.querySelector('.gif-export-progress-bar'); + this.createRadioElements_(); }; @@ -127,13 +130,29 @@ }); } + gif.on('progress', function(percentage) { + this.updateProgressStatus_((percentage*100).toFixed(2)); + }.bind(this)); + gif.on('finished', function(blob) { - this.blobToBase64_(blob, cb); + this.hideProgressStatus_(); + // this.blobToBase64_(blob, cb); }.bind(this)); gif.render(); }; + ns.GifExportController.prototype.updateProgressStatus_ = function (percentage) { + this.exportProgressStatusEl.innerHTML = percentage + '%'; + this.exportProgressBarEl.style.width = percentage + "%"; + + }; + + ns.GifExportController.prototype.hideProgressStatus_ = function () { + this.exportProgressStatusEl.innerHTML = ''; + this.exportProgressBarEl.style.width = "0"; + }; + // FIXME : HORRIBLE COPY/PASTA ns.GifExportController.prototype.updateStatus_ = function (imageUrl, error) { diff --git a/src/js/utils/Dom.js b/src/js/utils/Dom.js index 56818cea..5049ba3d 100644 --- a/src/js/utils/Dom.js +++ b/src/js/utils/Dom.js @@ -24,6 +24,16 @@ } } return false; + }, + + getParentWithData : function (node, data) { + while (node) { + if (node.dataset && typeof node.dataset[data] !== 'undefined') { + return node; + } + node = node.parentNode; + } + return null; } }; })(); \ No newline at end of file diff --git a/src/templates/settings/export-gif.html b/src/templates/settings/export-gif.html index 97feaf34..b95c991a 100644 --- a/src/templates/settings/export-gif.html +++ b/src/templates/settings/export-gif.html @@ -11,6 +11,8 @@
+ +