mirror of
https://github.com/piskelapp/piskel.git
synced 2023-08-10 21:12:52 +03:00
Create 2 new dialog controllers
Image import is now triggering a popup after selecting the file. Same for local saves. Drag and drop of .piskel files opens the piskel immediately ! Remains to do : - redesign the dialog for import image and browse local - create dialog for recover session - improve recover session to handle more than the last session
This commit is contained in:
parent
18ff6f88a7
commit
ad3dd935e0
@ -40,6 +40,7 @@
|
||||
-moz-box-sizing : border-box;
|
||||
|
||||
border-radius: 3px;
|
||||
border : 3px solid gold;
|
||||
background: rgba(0,0,0,1);
|
||||
overflow: auto;
|
||||
}
|
||||
@ -48,3 +49,27 @@
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.dialog-wrapper {
|
||||
position : relative;
|
||||
}
|
||||
|
||||
.dialog-head {
|
||||
width: 100%;
|
||||
background: gold;
|
||||
margin: 0;
|
||||
padding: 10px;
|
||||
color: black;
|
||||
font-size: 1.8em;
|
||||
box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
}
|
||||
|
||||
.dialog-close {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
line-height: 45px;
|
||||
margin-right: 10px;
|
||||
font-size: 1.3em;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
@ -314,7 +314,7 @@
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.file-input-status {
|
||||
.import-image-file-name {
|
||||
display: inline-block;
|
||||
width: 130px;
|
||||
overflow: hidden;
|
||||
|
@ -69,6 +69,8 @@
|
||||
<div id="dialog-container-wrapper">
|
||||
<div id="dialog-container">
|
||||
<iframe src="templates/dialogs/manage-palettes.html" onload="iframeloader.onLoad(event)" data-iframe-loader="store"></iframe>
|
||||
<iframe src="templates/dialogs/import-image.html" onload="iframeloader.onLoad(event)" data-iframe-loader="store"></iframe>
|
||||
<iframe src="templates/dialogs/browse-local.html" onload="iframeloader.onLoad(event)" data-iframe-loader="store"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -105,8 +105,8 @@
|
||||
this.beforeUnloadService = new pskl.service.BeforeUnloadService(this.piskelController);
|
||||
this.beforeUnloadService.init();
|
||||
|
||||
this.imageDropperService = new pskl.service.ImageDropperService(this.piskelController, $('#drawing-canvas-container').get(0));
|
||||
this.imageDropperService.init();
|
||||
this.fileDropperService = new pskl.service.FileDropperService(this.piskelController, $('#drawing-canvas-container').get(0));
|
||||
this.fileDropperService.init();
|
||||
|
||||
|
||||
if (this.isAppEngineVersion) {
|
||||
|
18
src/js/controller/dialogs/AbstractDialogController.js
Normal file
18
src/js/controller/dialogs/AbstractDialogController.js
Normal file
@ -0,0 +1,18 @@
|
||||
(function () {
|
||||
var ns = $.namespace('pskl.controller.dialogs');
|
||||
|
||||
ns.AbstractDialogController = function () {};
|
||||
|
||||
|
||||
ns.AbstractDialogController.prototype.init = function () {
|
||||
this.closeButton = document.querySelector('.dialog-close');
|
||||
this.closeButton.addEventListener('click', this.closeDialog.bind(this));
|
||||
};
|
||||
|
||||
ns.AbstractDialogController.prototype.destroy = function () {};
|
||||
|
||||
ns.AbstractDialogController.prototype.closeDialog = function () {
|
||||
$.publish(Events.DIALOG_HIDE);
|
||||
};
|
||||
|
||||
})();
|
57
src/js/controller/dialogs/BrowseLocalController.js
Normal file
57
src/js/controller/dialogs/BrowseLocalController.js
Normal file
@ -0,0 +1,57 @@
|
||||
(function () {
|
||||
var ns = $.namespace('pskl.controller.dialogs');
|
||||
|
||||
ns.BrowseLocalController = function (piskelController) {
|
||||
};
|
||||
|
||||
pskl.utils.inherit(ns.BrowseLocalController, ns.AbstractDialogController);
|
||||
|
||||
ns.BrowseLocalController.prototype.init = function () {
|
||||
this.superclass.init.call(this);
|
||||
|
||||
this.localStorageItemTemplate_ = pskl.utils.Template.get("local-storage-item-template");
|
||||
|
||||
this.service_ = pskl.app.localStorageService;
|
||||
this.piskelsList = $('.local-piskels-list');
|
||||
this.prevSessionContainer = $('.previous-session');
|
||||
|
||||
this.fillLocalPiskelsList_();
|
||||
|
||||
this.piskelsList.click(this.onPiskelsListClick_.bind(this));
|
||||
};
|
||||
|
||||
ns.BrowseLocalController.prototype.onPiskelsListClick_ = function (evt) {
|
||||
var action = evt.target.getAttribute('data-action');
|
||||
var name = evt.target.getAttribute('data-name');
|
||||
if (action === 'load') {
|
||||
if (window.confirm('This will erase your current piskel. Continue ?')) {
|
||||
this.service_.load(name);
|
||||
this.closeDialog();
|
||||
}
|
||||
} else if (action === 'delete') {
|
||||
if (window.confirm('This will permanently DELETE this piskel from your computer. Continue ?')) {
|
||||
this.service_.remove(name);
|
||||
this.fillLocalPiskelsList_();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ns.BrowseLocalController.prototype.fillLocalPiskelsList_ = function () {
|
||||
var html = "";
|
||||
var keys = this.service_.getKeys();
|
||||
|
||||
keys.sort(function (k1, k2) {
|
||||
if (k1.date < k2.date) {return 1;}
|
||||
if (k1.date > k2.date) {return -1;}
|
||||
return 0;
|
||||
});
|
||||
|
||||
keys.forEach((function (key) {
|
||||
var date = pskl.utils.DateUtils.format(key.date, "{{Y}}/{{M}}/{{D}} {{H}}:{{m}}");
|
||||
html += pskl.utils.Template.replace(this.localStorageItemTemplate_, {name : key.name, date : date});
|
||||
}).bind(this));
|
||||
|
||||
var tableBody_ = this.piskelsList.get(0).tBodies[0];
|
||||
tableBody_.innerHTML = html;
|
||||
};
|
||||
})();
|
@ -5,6 +5,14 @@
|
||||
'manage-palettes' : {
|
||||
template : 'templates/dialogs/manage-palettes.html',
|
||||
controller : ns.PaletteManagerController
|
||||
},
|
||||
'browse-local' : {
|
||||
template : 'templates/dialogs/browse-local.html',
|
||||
controller : ns.BrowseLocalController
|
||||
},
|
||||
'import-image' : {
|
||||
template : 'templates/dialogs/import-image.html',
|
||||
controller : ns.ImportImageController
|
||||
}
|
||||
};
|
||||
|
||||
@ -22,13 +30,20 @@
|
||||
pskl.app.shortcutService.addShortcut('alt+P', this.onDialogDisplayEvent_.bind(this, null, 'manage-palettes'));
|
||||
};
|
||||
|
||||
ns.DialogsController.prototype.onDialogDisplayEvent_ = function (evt, dialogId) {
|
||||
ns.DialogsController.prototype.onDialogDisplayEvent_ = function (evt, args) {
|
||||
var dialogId, initArgs;
|
||||
if (typeof args === 'string') {
|
||||
dialogId = args;
|
||||
} else {
|
||||
dialogId = args.dialogId;
|
||||
initArgs = args.initArgs;
|
||||
}
|
||||
if (!this.isDisplayed()) {
|
||||
var config = dialogs[dialogId];
|
||||
if (config) {
|
||||
this.dialogContainer_.innerHTML = pskl.utils.Template.get(config.template);
|
||||
var controller = new config.controller(this.piskelController);
|
||||
controller.init();
|
||||
controller.init(initArgs);
|
||||
|
||||
this.showDialogWrapper_();
|
||||
this.currentDialog_ = {
|
||||
|
154
src/js/controller/dialogs/ImportImageController.js
Normal file
154
src/js/controller/dialogs/ImportImageController.js
Normal file
@ -0,0 +1,154 @@
|
||||
(function () {
|
||||
var ns = $.namespace('pskl.controller.dialogs');
|
||||
var PREVIEW_HEIGHT = 60;
|
||||
|
||||
ns.ImportImageController = function (piskelController) {
|
||||
this.importedImage_ = null;
|
||||
this.file_ = null;
|
||||
};
|
||||
|
||||
pskl.utils.inherit(ns.ImportImageController, ns.AbstractDialogController);
|
||||
|
||||
ns.ImportImageController.prototype.init = function (file) {
|
||||
this.superclass.init.call(this);
|
||||
|
||||
this.file_ = file;
|
||||
|
||||
this.importPreview = $('.import-section-preview');
|
||||
|
||||
this.fileNameContainer = $('.import-image-file-name');
|
||||
|
||||
this.resizeWidth = $('[name=resize-width]');
|
||||
this.resizeHeight = $('[name=resize-height]');
|
||||
this.smoothResize = $('[name=smooth-resize-checkbox]');
|
||||
|
||||
this.resizeWidth.keyup(this.onResizeInputKeyUp_.bind(this, 'width'));
|
||||
this.resizeHeight.keyup(this.onResizeInputKeyUp_.bind(this, 'height'));
|
||||
|
||||
this.importImageForm = $('[name=import-image-form]');
|
||||
this.importImageForm.submit(this.onImportFormSubmit_.bind(this));
|
||||
|
||||
pskl.utils.FileUtils.readFile(this.file_, this.processImageSource_.bind(this));
|
||||
};
|
||||
|
||||
ns.ImportImageController.prototype.onImportFormSubmit_ = function (evt) {
|
||||
evt.originalEvent.preventDefault();
|
||||
this.importImageToPiskel_();
|
||||
};
|
||||
|
||||
ns.ImportImageController.prototype.onResizeInputKeyUp_ = function (from, evt) {
|
||||
if (this.importedImage_) {
|
||||
this.synchronizeResizeFields_(evt.target.value, from);
|
||||
}
|
||||
};
|
||||
|
||||
ns.ImportImageController.prototype.synchronizeResizeFields_ = function (value, from) {
|
||||
value = parseInt(value, 10);
|
||||
if (isNaN(value)) {
|
||||
value = 0;
|
||||
}
|
||||
var height = this.importedImage_.height, width = this.importedImage_.width;
|
||||
if (from === 'width') {
|
||||
this.resizeHeight.val(Math.round(value * height / width));
|
||||
} else {
|
||||
this.resizeWidth.val(Math.round(value * width / height));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Create an image from the given source (url or data-url), and onload forward to onImageLoaded
|
||||
* TODO : should be a generic utility method, should take a callback
|
||||
* @param {String} imageSource url or data-url, will be used as src for the image
|
||||
*/
|
||||
ns.ImportImageController.prototype.processImageSource_ = function (imageSource) {
|
||||
this.importedImage_ = new Image();
|
||||
this.importedImage_.onload = this.onImageLoaded_.bind(this);
|
||||
this.importedImage_.src = imageSource;
|
||||
};
|
||||
|
||||
ns.ImportImageController.prototype.onImageLoaded_ = function (evt) {
|
||||
var w = this.importedImage_.width,
|
||||
h = this.importedImage_.height;
|
||||
|
||||
// FIXME : We remove the onload callback here because JsGif will insert
|
||||
// the image again and we want to avoid retriggering the image onload
|
||||
this.importedImage_.onload = function () {};
|
||||
|
||||
var fileName = this.extractFileNameFromPath_(this.file_.name);
|
||||
this.fileNameContainer.html(fileName);
|
||||
|
||||
this.resizeWidth.val(w);
|
||||
this.resizeHeight.val(h);
|
||||
|
||||
this.importPreview.width('auto');
|
||||
this.importPreview.html('');
|
||||
this.importPreview.append(this.createImagePreview_());
|
||||
};
|
||||
|
||||
ns.ImportImageController.prototype.createImagePreview_ = function () {
|
||||
var image = document.createElement('IMG');
|
||||
image.src = this.importedImage_.src;
|
||||
image.setAttribute('height', PREVIEW_HEIGHT);
|
||||
return image;
|
||||
};
|
||||
|
||||
ns.ImportImageController.prototype.extractFileNameFromPath_ = function (path) {
|
||||
var parts = [];
|
||||
if (path.indexOf('/') !== -1) {
|
||||
parts = path.split('/');
|
||||
} else if (path.indexOf('\\') !== -1) {
|
||||
parts = path.split('\\');
|
||||
} else {
|
||||
parts = [path];
|
||||
}
|
||||
return parts[parts.length-1];
|
||||
};
|
||||
|
||||
ns.ImportImageController.prototype.importImageToPiskel_ = function () {
|
||||
var image = this.importedImage_;
|
||||
if (image) {
|
||||
if (window.confirm('You are about to create a new Piskel, unsaved changes will be lost.')) {
|
||||
var gifLoader = new window.SuperGif({
|
||||
gif : image
|
||||
});
|
||||
|
||||
gifLoader.load({
|
||||
success : function(){
|
||||
var images = gifLoader.getFrames().map(function (frame) {
|
||||
return pskl.CanvasUtils.createFromImageData(frame.data);
|
||||
});
|
||||
this.createPiskelFromImages_(images);
|
||||
this.closeDialog();
|
||||
}.bind(this),
|
||||
error : function () {
|
||||
this.createPiskelFromImages_([image]);
|
||||
this.closeDialog();
|
||||
}.bind(this)
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ns.ImportImageController.prototype.createFramesFromImages_ = function (images) {
|
||||
var w = this.resizeWidth.val();
|
||||
var h = this.resizeHeight.val();
|
||||
var smoothing = !!this.smoothResize.prop('checked');
|
||||
|
||||
var frames = images.map(function (image) {
|
||||
var resizedImage = pskl.utils.ImageResizer.resize(image, w, h, smoothing);
|
||||
return pskl.utils.FrameUtils.createFromImage(resizedImage);
|
||||
});
|
||||
return frames;
|
||||
};
|
||||
|
||||
ns.ImportImageController.prototype.createPiskelFromImages_ = function (images) {
|
||||
var frames = this.createFramesFromImages_(images);
|
||||
var layer = pskl.model.Layer.fromFrames('Layer 1', frames);
|
||||
var descriptor = new pskl.model.piskel.Descriptor('Imported piskel', '');
|
||||
var piskel = pskl.model.Piskel.fromLayers([layer], descriptor);
|
||||
|
||||
pskl.app.piskelController.setPiskel(piskel);
|
||||
pskl.app.animationController.setFPS(Constants.DEFAULT.FPS);
|
||||
};
|
||||
})();
|
@ -18,13 +18,16 @@
|
||||
this.spectrumContainers = [];
|
||||
};
|
||||
|
||||
pskl.utils.inherit(ns.PaletteManagerController, ns.AbstractDialogController);
|
||||
|
||||
ns.PaletteManagerController.prototype.init = function () {
|
||||
this.superclass.init.call(this);
|
||||
|
||||
this.palettesList = document.querySelector('.palette-manager-list');
|
||||
this.paletteBody = document.querySelector('.palette-manager-details-body');
|
||||
this.paletteHead = document.querySelector('.palette-manager-details-head');
|
||||
this.createButton = document.querySelector('.palette-manager-actions-button[data-action="create"]');
|
||||
this.saveAllButton = document.querySelector('.palette-manager-actions-button[data-action="save-all"]');
|
||||
this.closeButton = document.querySelector('.palette-manager-close');
|
||||
|
||||
this.colorCardTemplate = pskl.utils.Template.get('palette-color-card-template');
|
||||
this.newColorTemplate = pskl.utils.Template.get('palette-new-color-template');
|
||||
@ -37,7 +40,6 @@
|
||||
this.paletteHead.addEventListener('click', this.delegatedPaletteHeadClick.bind(this));
|
||||
this.createButton.addEventListener('click', this.onCreateClick_.bind(this));
|
||||
this.saveAllButton.addEventListener('click', this.saveAll.bind(this));
|
||||
this.closeButton.addEventListener('click', this.closeDialog.bind(this));
|
||||
|
||||
// Init markup
|
||||
this.createPaletteListMarkup();
|
||||
@ -52,10 +54,6 @@
|
||||
this.destroySpectrumPickers();
|
||||
};
|
||||
|
||||
ns.PaletteManagerController.prototype.closeDialog = function () {
|
||||
$.publish(Events.DIALOG_HIDE);
|
||||
};
|
||||
|
||||
ns.PaletteManagerController.prototype.onCreateClick_ = function (evt) {
|
||||
this.createPalette();
|
||||
};
|
||||
|
@ -1,7 +1,5 @@
|
||||
(function () {
|
||||
var ns = $.namespace('pskl.controller.settings');
|
||||
var DEFAULT_FILE_STATUS = '';
|
||||
var PREVIEW_HEIGHT = 60;
|
||||
|
||||
ns.ImportController = function (piskelController) {
|
||||
this.piskelController = piskelController;
|
||||
@ -12,61 +10,22 @@
|
||||
this.hiddenOpenPiskelInput = $('[name=open-piskel-input]');
|
||||
this.openPiskelInputButton = $('.open-piskel-button');
|
||||
|
||||
this.importForm = $('[name=import-form]');
|
||||
this.hiddenFileInput = $('[name=file-upload-input]');
|
||||
this.fileInputButton = $('.file-input-button');
|
||||
this.fileInputStatus = $('.file-input-status');
|
||||
this.fileInputStatus.html(DEFAULT_FILE_STATUS);
|
||||
|
||||
this.importPreview = $('.import-section-preview');
|
||||
this.browseLocalButton = document.querySelector('.browse-local-button');
|
||||
this.browseLocalButton.addEventListener('click', this.onBrowseLocalClick_.bind(this));
|
||||
|
||||
this.resizeWidth = $('[name=resize-width]');
|
||||
this.resizeHeight = $('[name=resize-height]');
|
||||
this.smoothResize = $('[name=smooth-resize-checkbox]');
|
||||
|
||||
$('.import-options').hide();
|
||||
|
||||
this.importForm.submit(this.onImportFormSubmit_.bind(this));
|
||||
this.hiddenFileInput.change(this.onFileUploadChange_.bind(this));
|
||||
this.fileInputButton.click(this.onFileInputClick_.bind(this));
|
||||
|
||||
this.hiddenOpenPiskelInput.change(this.onOpenPiskelChange_.bind(this));
|
||||
this.openPiskelInputButton.click(this.onOpenPiskelClick_.bind(this));
|
||||
|
||||
this.resizeWidth.keyup(this.onResizeInputKeyUp_.bind(this, 'width'));
|
||||
this.resizeHeight.keyup(this.onResizeInputKeyUp_.bind(this, 'height'));
|
||||
};
|
||||
|
||||
ns.ImportController.prototype.reset_ = function () {
|
||||
this.importForm.get(0).reset();
|
||||
this.fileInputStatus.html(DEFAULT_FILE_STATUS);
|
||||
ns.ImportController.prototype.closeDrawer_ = function () {
|
||||
$.publish(Events.CLOSE_SETTINGS_DRAWER);
|
||||
};
|
||||
|
||||
ns.ImportController.prototype.onResizeInputKeyUp_ = function (from, evt) {
|
||||
if (this.importedImage_) {
|
||||
this.synchronizeResizeFields_(evt.target.value, from);
|
||||
}
|
||||
};
|
||||
|
||||
ns.ImportController.prototype.synchronizeResizeFields_ = function (value, from) {
|
||||
value = parseInt(value, 10);
|
||||
if (isNaN(value)) {
|
||||
value = 0;
|
||||
}
|
||||
var height = this.importedImage_.height, width = this.importedImage_.width;
|
||||
if (from === 'width') {
|
||||
this.resizeHeight.val(Math.round(value * height / width));
|
||||
} else {
|
||||
this.resizeWidth.val(Math.round(value * width / height));
|
||||
}
|
||||
};
|
||||
|
||||
ns.ImportController.prototype.onImportFormSubmit_ = function (evt) {
|
||||
evt.originalEvent.preventDefault();
|
||||
this.importImageToPiskel_();
|
||||
};
|
||||
|
||||
ns.ImportController.prototype.onFileUploadChange_ = function (evt) {
|
||||
this.importPictureFromFile_();
|
||||
};
|
||||
@ -83,40 +42,39 @@
|
||||
this.hiddenOpenPiskelInput.click();
|
||||
};
|
||||
|
||||
ns.ImportController.prototype.onBrowseLocalClick_ = function (evt) {
|
||||
$.publish(Events.DIALOG_DISPLAY, 'browse-local');
|
||||
this.closeDrawer_();
|
||||
};
|
||||
|
||||
ns.ImportController.prototype.openPiskelFile_ = function () {
|
||||
var files = this.hiddenOpenPiskelInput.get(0).files;
|
||||
if (files.length == 1) {
|
||||
|
||||
var file = files[0];
|
||||
if (this.isPiskel_(file)){
|
||||
pskl.utils.FileUtils.readFile(file, function (content) {
|
||||
var rawPiskel = window.atob(content.replace('data:;base64,',''));
|
||||
var serializedPiskel = JSON.parse(rawPiskel);
|
||||
var name = serializedPiskel.piskel.name;
|
||||
var description = serializedPiskel.piskel.description;
|
||||
var fps = serializedPiskel.piskel.fps;
|
||||
|
||||
pskl.utils.serialization.Deserializer.deserialize(serializedPiskel, function (piskel) {
|
||||
piskel.setDescriptor(new pskl.model.piskel.Descriptor(name, description, true));
|
||||
pskl.app.piskelController.setPiskel(piskel);
|
||||
pskl.app.animationController.setFPS(fps);
|
||||
});
|
||||
pskl.utils.PiskelFileUtils.loadFromFile(file, function (piskel, descriptor, fps) {
|
||||
piskel.setDescriptor(descriptor);
|
||||
pskl.app.piskelController.setPiskel(piskel);
|
||||
pskl.app.animationController.setFPS(fps);
|
||||
});
|
||||
this.reset_();
|
||||
this.closeDrawer_();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
ns.ImportController.prototype.importPictureFromFile_ = function () {
|
||||
var files = this.hiddenFileInput.get(0).files;
|
||||
if (files.length == 1) {
|
||||
var file = files[0];
|
||||
if (this.isImage_(file)) {
|
||||
this.readImageFile_(file);
|
||||
this.enableDisabledSections_();
|
||||
$.publish(Events.DIALOG_DISPLAY, {
|
||||
dialogId : 'import-image',
|
||||
initArgs : file
|
||||
});
|
||||
this.closeDrawer_();
|
||||
} else {
|
||||
this.reset_();
|
||||
this.closeDrawer_();
|
||||
throw 'File is not an image : ' + file.type;
|
||||
}
|
||||
}
|
||||
@ -128,108 +86,6 @@
|
||||
$('.import-options').show();
|
||||
};
|
||||
|
||||
ns.ImportController.prototype.readImageFile_ = function (imageFile) {
|
||||
pskl.utils.FileUtils.readFile(imageFile, this.processImageSource_.bind(this));
|
||||
};
|
||||
|
||||
/**
|
||||
* Create an image from the given source (url or data-url), and onload forward to onImageLoaded
|
||||
* TODO : should be a generic utility method, should take a callback
|
||||
* @param {String} imageSource url or data-url, will be used as src for the image
|
||||
*/
|
||||
ns.ImportController.prototype.processImageSource_ = function (imageSource) {
|
||||
this.importedImage_ = new Image();
|
||||
this.importedImage_.onload = this.onImageLoaded_.bind(this);
|
||||
this.importedImage_.src = imageSource;
|
||||
};
|
||||
|
||||
ns.ImportController.prototype.onImageLoaded_ = function (evt) {
|
||||
var w = this.importedImage_.width,
|
||||
h = this.importedImage_.height;
|
||||
|
||||
// FIXME : We remove the onload callback here because JsGif will insert
|
||||
// the image again and we want to avoid retriggering the image onload
|
||||
this.importedImage_.onload = function () {};
|
||||
|
||||
var filePath = this.hiddenFileInput.val();
|
||||
var fileName = this.extractFileNameFromPath_(filePath);
|
||||
this.fileInputStatus.html(fileName);
|
||||
|
||||
this.resizeWidth.val(w);
|
||||
this.resizeHeight.val(h);
|
||||
|
||||
this.importPreview.width('auto');
|
||||
this.importPreview.html('');
|
||||
this.importPreview.append(this.createImagePreview_());
|
||||
};
|
||||
|
||||
ns.ImportController.prototype.createImagePreview_ = function () {
|
||||
var image = document.createElement('IMG');
|
||||
image.src = this.importedImage_.src;
|
||||
image.setAttribute('height', PREVIEW_HEIGHT);
|
||||
return image;
|
||||
};
|
||||
|
||||
ns.ImportController.prototype.extractFileNameFromPath_ = function (path) {
|
||||
var parts = [];
|
||||
if (path.indexOf('/') !== -1) {
|
||||
parts = path.split('/');
|
||||
} else if (path.indexOf('\\') !== -1) {
|
||||
parts = path.split('\\');
|
||||
} else {
|
||||
parts = [path];
|
||||
}
|
||||
return parts[parts.length-1];
|
||||
};
|
||||
|
||||
ns.ImportController.prototype.importImageToPiskel_ = function () {
|
||||
var image = this.importedImage_;
|
||||
if (image) {
|
||||
if (window.confirm('You are about to create a new Piskel, unsaved changes will be lost.')) {
|
||||
var gifLoader = new window.SuperGif({
|
||||
gif : image
|
||||
});
|
||||
|
||||
gifLoader.load({
|
||||
success : function(){
|
||||
var images = gifLoader.getFrames().map(function (frame) {
|
||||
return pskl.CanvasUtils.createFromImageData(frame.data);
|
||||
});
|
||||
this.createPiskelFromImages_(images);
|
||||
}.bind(this),
|
||||
error : function () {
|
||||
this.createPiskelFromImages_([image]);
|
||||
}.bind(this)
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ns.ImportController.prototype.createFramesFromImages_ = function (images) {
|
||||
var w = this.resizeWidth.val();
|
||||
var h = this.resizeHeight.val();
|
||||
var smoothing = !!this.smoothResize.prop('checked');
|
||||
|
||||
var frames = images.map(function (image) {
|
||||
var resizedImage = pskl.utils.ImageResizer.resize(image, w, h, smoothing);
|
||||
return pskl.utils.FrameUtils.createFromImage(resizedImage);
|
||||
});
|
||||
return frames;
|
||||
};
|
||||
|
||||
ns.ImportController.prototype.createPiskelFromImages_ = function (images) {
|
||||
var frames = this.createFramesFromImages_(images);
|
||||
var layer = pskl.model.Layer.fromFrames('Layer 1', frames);
|
||||
var descriptor = new pskl.model.piskel.Descriptor('Imported piskel', '');
|
||||
var piskel = pskl.model.Piskel.fromLayers([layer], descriptor);
|
||||
|
||||
pskl.app.piskelController.setPiskel(piskel);
|
||||
pskl.app.animationController.setFPS(Constants.DEFAULT.FPS);
|
||||
|
||||
this.reset_();
|
||||
};
|
||||
|
||||
ns.ImportController.prototype.isImage_ = function (file) {
|
||||
return file.type.indexOf('image') === 0;
|
||||
};
|
||||
|
@ -1,17 +1,23 @@
|
||||
(function () {
|
||||
var ns = $.namespace('pskl.service');
|
||||
|
||||
ns.ImageDropperService = function (piskelController, drawingAreaContainer) {
|
||||
ns.FileDropperService = function (piskelController, drawingAreaContainer) {
|
||||
this.piskelController = piskelController;
|
||||
this.drawingAreaContainer = drawingAreaContainer;
|
||||
};
|
||||
|
||||
ns.ImageDropperService.prototype.init = function () {
|
||||
ns.FileDropperService.prototype.init = function () {
|
||||
document.body.addEventListener('drop', this.onFileDrop.bind(this), false);
|
||||
document.body.addEventListener('dragover', this.onFileDragOver.bind(this), false);
|
||||
};
|
||||
|
||||
ns.ImageDropperService.prototype.onFileDrop = function (event) {
|
||||
ns.FileDropperService.prototype.onFileDragOver = function (event) {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
event.dataTransfer.dropEffect = 'copy';
|
||||
};
|
||||
|
||||
ns.FileDropperService.prototype.onFileDrop = function (event) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
@ -25,28 +31,31 @@
|
||||
var isImage = file.type.indexOf('image') === 0;
|
||||
if (isImage) {
|
||||
this.readImageFile_(file);
|
||||
} else if (/\.piskel$/i.test(file.name)) {
|
||||
pskl.utils.PiskelFileUtils.loadFromFile(file, this.onPiskelFileLoaded_);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ns.ImageDropperService.prototype.onFileDragOver = function (event) {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
event.dataTransfer.dropEffect = 'Copy image on the frame'; // Explicitly show this is a copy.
|
||||
ns.FileDropperService.prototype.onPiskelFileLoaded_ = function (piskel, descriptor, fps) {
|
||||
if (window.confirm('This will replace your current animation')) {
|
||||
piskel.setDescriptor(descriptor);
|
||||
pskl.app.piskelController.setPiskel(piskel);
|
||||
pskl.app.animationController.setFPS(fps);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
ns.ImageDropperService.prototype.readImageFile_ = function (imageFile) {
|
||||
ns.FileDropperService.prototype.readImageFile_ = function (imageFile) {
|
||||
pskl.utils.FileUtils.readFile(imageFile, this.processImageSource_.bind(this));
|
||||
};
|
||||
|
||||
ns.ImageDropperService.prototype.processImageSource_ = function (imageSource) {
|
||||
ns.FileDropperService.prototype.processImageSource_ = function (imageSource) {
|
||||
this.importedImage_ = new Image();
|
||||
this.importedImage_.onload = this.onImageLoaded_.bind(this);
|
||||
this.importedImage_.src = imageSource;
|
||||
};
|
||||
|
||||
ns.ImageDropperService.prototype.onImageLoaded_ = function () {
|
||||
ns.FileDropperService.prototype.onImageLoaded_ = function () {
|
||||
var frame = pskl.utils.FrameUtils.createFromImage(this.importedImage_);
|
||||
var currentFrame = this.piskelController.getCurrentFrame();
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
ns.DateUtils = {
|
||||
format : function (date, format) {
|
||||
date = new Date(date);
|
||||
return pskl.utils.Template.replace(format, {
|
||||
Y : date.getFullYear(),
|
||||
M : pad(date.getMonth() + 1),
|
||||
|
17
src/js/utils/PiskelFileUtils.js
Normal file
17
src/js/utils/PiskelFileUtils.js
Normal file
@ -0,0 +1,17 @@
|
||||
(function () {
|
||||
var ns = $.namespace('pskl.utils');
|
||||
|
||||
ns.PiskelFileUtils = {
|
||||
loadFromFile : function (file, onSuccess, onError) {
|
||||
pskl.utils.FileUtils.readFile(file, function (content) {
|
||||
var rawPiskel = window.atob(content.replace('data:;base64,',''));
|
||||
var serializedPiskel = JSON.parse(rawPiskel);
|
||||
var fps = serializedPiskel.piskel.fps;
|
||||
var descriptor = new pskl.model.piskel.Descriptor(serializedPiskel.piskel.name, serializedPiskel.piskel.description, true);
|
||||
pskl.utils.serialization.Deserializer.deserialize(serializedPiskel, function (piskel) {
|
||||
onSuccess(piskel, descriptor, fps);
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
})();
|
@ -23,6 +23,7 @@
|
||||
"js/utils/LayerUtils.js",
|
||||
"js/utils/ImageResizer.js",
|
||||
"js/utils/PixelUtils.js",
|
||||
"js/utils/PiskelFileUtils.js",
|
||||
"js/utils/Template.js",
|
||||
"js/utils/UserSettings.js",
|
||||
"js/utils/serialization/Serializer.js",
|
||||
@ -97,7 +98,10 @@
|
||||
"js/controller/settings/SettingsController.js",
|
||||
|
||||
// Dialogs sub-controllers
|
||||
"js/controller/dialogs/AbstractDialogController.js",
|
||||
"js/controller/dialogs/PaletteManagerController.js",
|
||||
"js/controller/dialogs/ImportImageController.js",
|
||||
"js/controller/dialogs/BrowseLocalController.js",
|
||||
|
||||
// Dialogs controller
|
||||
"js/controller/dialogs/DialogsController.js",
|
||||
@ -115,7 +119,7 @@
|
||||
"js/service/keyboard/CheatsheetService.js",
|
||||
"js/service/ImageUploadService.js",
|
||||
"js/service/CurrentColorsService.js",
|
||||
"js/service/ImageDropperService.js",
|
||||
"js/service/FileDropperService.js",
|
||||
|
||||
// Tools
|
||||
"js/drawingtools/BaseTool.js",
|
||||
|
27
src/templates/dialogs/browse-local.html
Normal file
27
src/templates/dialogs/browse-local.html
Normal file
@ -0,0 +1,27 @@
|
||||
<div class="dialog-wrapper">
|
||||
<h3 class="dialog-head">
|
||||
Browse Local Piskels
|
||||
<span class="palette-manager-close dialog-close">X</span>
|
||||
</h3>
|
||||
<div>
|
||||
<table class="local-piskels-list">
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
</div>
|
||||
<script type="text/template" id="local-storage-item-template">
|
||||
<tr class="local-piskel-item">
|
||||
<td class="local-piskel-name">{{name}}</td>
|
||||
<td class="local-piskel-save-date">{{date}}</td>
|
||||
<td><a class="local-piskel-load-link" data-action="load" data-name="{{name}}" href="javascript:void(0);">load</a></td>
|
||||
<td><a class="local-piskel-delete-link" data-action="delete" data-name="{{name}}" href="javascript:void(0);">x</a></td>
|
||||
</tr>
|
||||
</script>
|
||||
<script type="text/template" id="previous-session-info-template">
|
||||
<div>
|
||||
Restore a backup of <span style="color:gold">{{name}}</span>, saved at <span style="color:white">{{date}}</span> ?
|
||||
<div style="margin-top:10px;">
|
||||
<button type="button" class="button button-primary restore-session-button">Restore</button>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
</div>
|
27
src/templates/dialogs/import-image.html
Normal file
27
src/templates/dialogs/import-image.html
Normal file
@ -0,0 +1,27 @@
|
||||
<div class="dialog-wrapper">
|
||||
<h3 class="dialog-head">
|
||||
Import Image
|
||||
<span class="palette-manager-close dialog-close">X</span>
|
||||
</h3>
|
||||
<div class="import-options">
|
||||
<form action="" method="POST" name="import-image-form">
|
||||
<div class="import-section">
|
||||
<span class="import-image-file-name"></span>
|
||||
</div>
|
||||
<div class="import-section">
|
||||
<span class="import-section-title import-section-title-small" style="vertical-align:top">Info :</span>
|
||||
<div class="import-section-preview"></div>
|
||||
</div>
|
||||
<div class="import-section">
|
||||
<span class="import-section-title import-section-title-small">Size :</span>
|
||||
<input type="text" class="textfield import-size-field" name="resize-width"/>x
|
||||
<input type="text" class="textfield import-size-field" name="resize-height"/>
|
||||
</div>
|
||||
<div class="import-section">
|
||||
<span class="import-section-title">Smooth resize :</span>
|
||||
<input type="checkbox" checked="checked" name="smooth-resize-checkbox" value="1"/>
|
||||
</div>
|
||||
<input type="submit" name="import-submit" class="button button-primary import-button" value="Import" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
@ -1,7 +1,7 @@
|
||||
<div class="palette-manager-wrapper">
|
||||
<h3 class="palette-manager-head">
|
||||
<h3 class="palette-manager-head dialog-head">
|
||||
Palette manager
|
||||
<span class="palette-manager-close">X</span>
|
||||
<span class="palette-manager-close dialog-close">X</span>
|
||||
</h3>
|
||||
<div class="palette-manager-body">
|
||||
<div class="palette-manager-drawer">
|
||||
|
@ -22,19 +22,26 @@
|
||||
rel="tooltip" data-placement="left" >
|
||||
</div>
|
||||
|
||||
<div
|
||||
data-setting="png"
|
||||
class="tool-icon import-icon"
|
||||
title="Export"
|
||||
rel="tooltip" data-placement="left">
|
||||
</div>
|
||||
|
||||
<div
|
||||
data-setting="import"
|
||||
class="tool-icon local-storage-icon"
|
||||
title="Import piskel"
|
||||
rel="tooltip" data-placement="left">
|
||||
</div>
|
||||
|
||||
<!--
|
||||
<div
|
||||
data-setting="localstorage"
|
||||
class="tool-icon local-storage-icon"
|
||||
title="Browse piskels saved locally"
|
||||
rel="tooltip" data-placement="left">
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
<!-- <div
|
||||
data-setting="gif"
|
||||
@ -43,11 +50,4 @@
|
||||
rel="tooltip" data-placement="left">
|
||||
<span class="label">ANIM</span>
|
||||
</div> -->
|
||||
|
||||
<div
|
||||
data-setting="png"
|
||||
class="tool-icon import-icon"
|
||||
title="Export"
|
||||
rel="tooltip" data-placement="left">
|
||||
</div>
|
||||
</div>
|
@ -5,57 +5,34 @@
|
||||
<div class="settings-item">
|
||||
<span>Load a <span style="font-weight:bold;color:white">local piskel</span> saved in this Browser</span>
|
||||
<div class="import-section">
|
||||
<button type="button" class="button button-primary load-browser-button">Browse local saves</button>
|
||||
<button type="button" class="button button-primary browse-local-button">Browse local saves</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="settings-title">
|
||||
Load .piskel file
|
||||
</div>
|
||||
<div class="settings-item">
|
||||
<form action="" method="POST" name="open-piskel-form">
|
||||
<span>Load a <span style="font-weight:bold;color:white">.piskel</span> file from your computer</span>
|
||||
<span>Load a <span style="font-weight:bold;color:white">.piskel</span> file from your computer</span>
|
||||
|
||||
<div class="import-section">
|
||||
<button type="button" class="button button-primary open-piskel-button">Browse .piskel files</button>
|
||||
<span class="file-input-open-piskel-status"></span>
|
||||
<input style="display:none"
|
||||
type="file" name="open-piskel-input"
|
||||
value="file" accept=".piskel"/>
|
||||
</div>
|
||||
</form>
|
||||
<div class="import-section">
|
||||
<button type="button" class="button button-primary open-piskel-button">Browse .piskel files</button>
|
||||
<span class="file-input-open-piskel-status"></span>
|
||||
<input style="display:none"
|
||||
type="file" name="open-piskel-input"
|
||||
value="file" accept=".piskel"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="settings-title">
|
||||
Import From Picture
|
||||
</div>
|
||||
<div class="settings-item">
|
||||
<form action="" method="POST" name="import-form">
|
||||
<div style="margin-top:5px;margin-bottom:5px;">Supports : <span style="font-weight:bold;color:white">PNG, JPG, BMP, Animated GIF ...</span></div>
|
||||
<div class="import-section">
|
||||
<button type="button" class="button button-primary file-input-button">Browse images</button>
|
||||
<span class="file-input-status"></span>
|
||||
<input style="display:none"
|
||||
type="file" name="file-upload-input"
|
||||
value="file" accept="image/*"/>
|
||||
</div>
|
||||
|
||||
<div class="import-options">
|
||||
<div class="import-section">
|
||||
<span class="import-section-title import-section-title-small" style="vertical-align:top">Info :</span>
|
||||
<div class="import-section-preview"></div>
|
||||
</div>
|
||||
<div class="import-section">
|
||||
<span class="import-section-title import-section-title-small">Size :</span>
|
||||
<input type="text" class="textfield import-size-field" name="resize-width"/>x
|
||||
<input type="text" class="textfield import-size-field" name="resize-height"/>
|
||||
</div>
|
||||
<div class="import-section">
|
||||
<span class="import-section-title">Smooth resize :</span>
|
||||
<input type="checkbox" checked="checked" name="smooth-resize-checkbox" value="1"/>
|
||||
</div>
|
||||
<input type="submit" name="import-submit" class="button button-primary import-button" value="Import" />
|
||||
</div>
|
||||
|
||||
</form>
|
||||
<div style="margin-top:5px;margin-bottom:5px;">Supports : <span style="font-weight:bold;color:white">PNG, JPG, BMP, Animated GIF ...</span></div>
|
||||
<div class="import-section">
|
||||
<button type="button" class="button button-primary file-input-button">Browse images</button>
|
||||
<input style="display:none"
|
||||
type="file" name="file-upload-input"
|
||||
value="file" accept="image/*"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="settings-title">
|
||||
Recover recent sessions
|
||||
|
@ -22,7 +22,7 @@
|
||||
</div>
|
||||
<div class="settings-title">Save offline in Browser</div>
|
||||
<div class="settings-item">
|
||||
<div id="save-browser-status" class="save-status">Your piskel will be saved in the browser and will only be accessible from this browser.</div>
|
||||
<div id="save-browser-status" class="save-status">Your piskel will be saved locally and will only be accessible from this browser.</div>
|
||||
<input type="submit" class="button button-primary" id="save-browser-button" value="Save in Browser" />
|
||||
</div>
|
||||
<div class="settings-title">Save offline as File</div>
|
||||
|
Loading…
Reference in New Issue
Block a user