1 Commits

Author SHA1 Message Date
0cdfcfc94d release 0.8.3: fix safari zoom issue 2016-10-23 10:04:22 +02:00
307 changed files with 2890 additions and 15341 deletions

View File

@ -1,25 +0,0 @@
engines:
csslint:
enabled: true
duplication:
enabled: true
config:
languages:
- javascript
eslint:
enabled: true
checks:
wrap-iife:
enabled: false
fixme:
enabled: true
ratings:
paths:
- "**.css"
- "**.js"
exclude_paths:
- .github/
- bin/
- misc/
- src/js/lib/
- test/

View File

@ -1,2 +0,0 @@
# Exclude libs.
**/lib/**/*.js

View File

@ -1,19 +0,0 @@
Bug description
(this template is intended for bug reports, erase it when requesting features/enhancements)
### Steps to reproduce the bug
1. go to piskelapp.com
2. select a tool
3. ...
### Environment details
* operating system:
* browser (or offline application version):
### Sprite details
* number of frames:
* sprite resolution:
* session duration:
Feel free to include a screenshot of the bug, a .piskel file of the sprite or anything else that can help us investigate.

7
.gitignore vendored
View File

@ -1,4 +1,4 @@
# mac artifacts # mac artefacts
*.DS_Store *.DS_Store
# nodejs local installs # nodejs local installs
@ -15,12 +15,10 @@ cache
# netbeans project folder # netbeans project folder
nbproject nbproject
# vscode workspace folder
.vscode
# git stackdumps # git stackdumps
*.stackdump *.stackdump
# diffs # diffs
diff.txt diff.txt
@ -30,7 +28,6 @@ build/closure/closure_compiled_binary.js
# spriting artifacts # spriting artifacts
src/img/icons.png src/img/icons.png
src/img/icons@2x.png
src/css/icons.css src/css/icons.css
# plato report directory # plato report directory

75
.jscsrc Normal file
View File

@ -0,0 +1,75 @@
{
"requireCurlyBraces": [
"if",
"else",
"for",
"while",
"do",
"try",
"catch"
],
"requireOperatorBeforeLineBreak": true,
"requireCamelCaseOrUpperCaseIdentifiers": true,
"maximumLineLength": {
"value": 80,
"allExcept": ["comments", "regex"]
},
"validateIndentation": 2,
"validateQuoteMarks": "'",
"disallowMultipleLineStrings": true,
"disallowMixedSpacesAndTabs": true,
"disallowTrailingWhitespace": true,
"disallowSpaceAfterPrefixUnaryOperators": true,
"disallowMultipleVarDecl": true,
"disallowKeywordsOnNewLine": ["else"],
"requireSpaceAfterKeywords": [
"if",
"else",
"for",
"while",
"do",
"switch",
"return",
"try",
"catch"
],
"requireSpaceBeforeBinaryOperators": [
"=", "+=", "-=", "*=", "/=", "%=", "<<=", ">>=", ">>>=",
"&=", "|=", "^=", "+=",
"+", "-", "*", "/", "%", "<<", ">>", ">>>", "&",
"|", "^", "&&", "||", "===", "==", ">=",
"<=", "<", ">", "!=", "!=="
],
"requireSpaceAfterBinaryOperators": true,
"requireSpacesInConditionalExpression": true,
"requireSpaceBeforeBlockStatements": true,
"requireSpacesInForStatement": true,
"requireLineFeedAtFileEnd": true,
"requireSpacesInFunctionExpression": {
"beforeOpeningCurlyBrace": true
},
"disallowSpacesInAnonymousFunctionExpression": {
"beforeOpeningRoundBrace": false
},
"disallowSpacesInsideObjectBrackets": "all",
"disallowSpacesInsideArrayBrackets": "all",
"disallowSpacesInsideParentheses": true,
"disallowMultipleLineBreaks": true,
"disallowNewlineBeforeBlockStatements": true,
"disallowKeywords": ["with"],
"disallowSpacesInFunctionExpression": null,
"disallowSpacesInFunctionDeclaration": null,
"disallowSpacesInCallExpression": true,
"disallowSpaceAfterObjectKeys": false,
"requireSpaceBeforeObjectValues": true,
"requireCapitalizedConstructors": true,
"requireDotNotation": true,
"requireSemicolons": true,
"validateParameterSeparator": ", ",
"jsDoc": null
}

View File

@ -1,9 +1,14 @@
language: node_js language: node_js
node_js: node_js:
- "7.4.0" - "4.1"
before_install: before_install:
- npm update -g npm - npm update -g npm
- npm install -g grunt-cli - npm install -g grunt-cli
- git clone git://github.com/n1k0/casperjs.git ~/casperjs
- cd ~/casperjs
- git checkout tags/1.0.2
- export PATH=$PATH:`pwd`/bin
- cd -
before_script: before_script:
- phantomjs --version - phantomjs --version
- casperjs --version - casperjs --version

View File

@ -9,10 +9,11 @@ module.exports = function(grunt) {
TEST : 9991 TEST : 9991
}; };
var DEV_MODE = '?debug';
// create a version based on the build timestamp // create a version based on the build timestamp
var dateFormat = require('dateformat'); var dateFormat = require('dateformat');
var version = '-' + dateFormat(new Date(), "yyyy-mm-dd-hh-MM"); var version = '-' + dateFormat(new Date(), "yyyy-mm-dd-hh-MM");
var releaseVersion = require('./package.json').version;
/** /**
* Helper to prefix all strings in provided array with the provided path * Helper to prefix all strings in provided array with the provided path
@ -33,27 +34,37 @@ module.exports = function(grunt) {
var stylePaths = require('./src/piskel-style-list.js').styles; var stylePaths = require('./src/piskel-style-list.js').styles;
var piskelStyles = prefixPaths(stylePaths, "src/"); var piskelStyles = prefixPaths(stylePaths, "src/");
// Casper JS tests var getCasperConfig = function (suiteName, delay, host) {
var casperjsOptions = [ var testPaths = require('./test/casperjs/' + suiteName).tests;
'--baseUrl=http://' + hostname + ':' + PORT.TEST, var tests = prefixPaths(testPaths, "test/casperjs/");
'--mode=?debug',
'--verbose=false',
'--includes=test/casperjs/integration/include.js',
'--log-level=info',
'--print-command=false',
'--print-file-paths=true',
];
var integrationTestPaths = require('./test/casperjs/integration/IntegrationSuite.js').tests; return {
var integrationTests = prefixPaths(integrationTestPaths, "test/casperjs/integration/"); filesSrc : tests,
options : {
args : {
baseUrl : 'http://' + host + ':' + PORT.TEST,
mode : DEV_MODE,
delay : delay
},
async : false,
direct : false,
logLevel : 'info',
printCommand : false,
printFilePaths : true
}
};
};
var getConnectConfig = function (base, port, host) {
if (typeof base === 'string') {
base = [base];
}
var getConnectConfig = function (base, port, host, open) {
return { return {
options: { options: {
port: port, port: port,
hostname : host, hostname : host,
base: base, base: base
open: open
} }
}; };
}; };
@ -80,17 +91,33 @@ module.exports = function(grunt) {
css : ['src/css/**/*.css'] css : ['src/css/**/*.css']
}, },
eslint: { jscs : {
files: [ options : {
// Includes "config": ".jscsrc",
'src/js/**/*.js', "maximumLineLength": 120,
// Exludes "requireCamelCaseOrUpperCaseIdentifiers": "ignoreProperties",
// TODO: remove this (for now we still get warnings from the lib folder) "validateQuoteMarks": { "mark": "'", "escape": true },
'!src/js/**/lib/**/*.js' "disallowMultipleVarDecl": "exceptUndefined",
], "disallowSpacesInAnonymousFunctionExpression": null
},
js : [ 'src/js/**/*.js' , '!src/js/**/lib/**/*.js' ]
},
jshint: {
options: { options: {
fix: grunt.option('fix') // this will get params from the flags undef : true,
} latedef : true,
browser : true,
trailing : true,
curly : true,
globals : {'$':true, 'jQuery' : true, 'pskl':true, 'Events':true, 'Constants':true, 'console' : true, 'module':true, 'require':true, 'Q':true}
},
files: [
'Gruntfile.js',
'package.json',
'src/js/**/*.js',
'!src/js/**/lib/**/*.js' // Exclude lib folder (note the leading !)
]
}, },
/** /**
@ -98,9 +125,18 @@ module.exports = function(grunt) {
*/ */
connect: { connect: {
prod: getConnectConfig('dest/prod', PORT.PROD, hostname, true), prod: getConnectConfig('dest/prod', PORT.PROD, hostname),
test: getConnectConfig(['dest/dev', 'test'], PORT.TEST, hostname, false), test: getConnectConfig(['dest/dev', 'test'], PORT.TEST, hostname),
dev: getConnectConfig(['dest/dev', 'test'], PORT.DEV, hostname, 'http://' + hostname + ':' + PORT.DEV + '/?debug') dev: getConnectConfig(['dest/dev', 'test'], PORT.DEV, hostname)
},
open : {
prod : {
path : 'http://' + hostname + ':' + PORT.PROD + '/'
},
dev : {
path : 'http://' + hostname + ':' + PORT.DEV + '/' + DEV_MODE
}
}, },
watch: { watch: {
@ -144,7 +180,7 @@ module.exports = function(grunt) {
}, },
css : { css : {
src : piskelStyles, src : piskelStyles,
dest : 'dest/tmp/css/piskel-style-packaged' + version + '.css' dest : 'dest/prod/css/piskel-style-packaged' + version + '.css'
} }
}, },
@ -165,8 +201,7 @@ module.exports = function(grunt) {
dest: 'dest/tmp/index.html', dest: 'dest/tmp/index.html',
options : { options : {
globals : { globals : {
'version' : version, 'version' : version
'releaseVersion' : releaseVersion
} }
} }
} }
@ -196,18 +231,19 @@ module.exports = function(grunt) {
{src: ['dest/tmp/index.html'], dest: 'dest/prod/piskelapp-partials/main-partial.html'} {src: ['dest/tmp/index.html'], dest: 'dest/prod/piskelapp-partials/main-partial.html'}
] ]
}, },
// remove the fake header from the desktop build
css: { desktop: {
options: { options: {
patterns: [{ patterns: [{
match: /var\(--highlight-color\)/g, match: /<!--standalone-start-->(?:.|[\r\n])*<!--standalone-end-->/,
replacement: "gold", replacement: "",
}] description : "Remove everything between standalone-start & standalone-end"
}
]
}, },
files: [{ files: [
src: ['dest/tmp/css/piskel-style-packaged' + version + '.css'], {src: ['dest/prod/index.html'], dest: 'dest/prod/index.html'}
dest: 'dest/prod/css/piskel-style-packaged' + version + '.css' ]
}]
} }
}, },
@ -246,23 +282,9 @@ module.exports = function(grunt) {
} }
}, },
casperjs : { ghost : {
drawing : { 'travis' : getCasperConfig('TravisTestSuite.js', 10000, hostname),
files : { 'local' : getCasperConfig('LocalTestSuite.js', 50, hostname)
src: ['test/casperjs/DrawingTest.js']
},
options : {
casperjsOptions: casperjsOptions
}
},
integration : {
files : {
src: integrationTests
},
options : {
casperjsOptions: casperjsOptions
}
}
}, },
/** /**
@ -272,78 +294,57 @@ module.exports = function(grunt) {
nwjs: { nwjs: {
windows : { windows : {
options: { options: {
downloadUrl: 'https://dl.nwjs.io/', version : "0.15.4",
version : "0.19.4",
build_dir: './dest/desktop/', // destination folder of releases. build_dir: './dest/desktop/', // destination folder of releases.
win: true, win: true,
linux32: true, linux32: true,
linux64: true, linux64: true
flavor: "normal",
}, },
src: ['./dest/prod/**/*', "./package.json", "!./dest/desktop/"] src: ['./dest/prod/**/*', "./package.json", "!./dest/desktop/"]
}, },
macos : { macos : {
options: { options: {
downloadUrl: 'https://dl.nwjs.io/',
osx64: true, osx64: true,
version : "0.19.4", version : "0.15.4",
build_dir: './dest/desktop/', build_dir: './dest/desktop/'
flavor: "normal",
},
src: ['./dest/prod/**/*', "./package.json", "!./dest/desktop/"]
},
macos_old : {
options: {
downloadUrl: 'https://dl.nwjs.io/',
osx64: true,
version : "0.12.3",
build_dir: './dest/desktop/old',
flavor: "normal",
}, },
src: ['./dest/prod/**/*', "./package.json", "!./dest/desktop/"] src: ['./dest/prod/**/*', "./package.json", "!./dest/desktop/"]
} }
} }
}); });
// TEST TASKS // Validate
// Run linting grunt.registerTask('lint', ['jscs:js', 'leadingIndent:css', 'jshint']);
grunt.registerTask('lint', ['eslint', 'leadingIndent:css']);
// Run unit-tests // karma/unit-tests task
grunt.registerTask('unit-test', ['karma']); grunt.registerTask('unit-test', ['karma']);
// Run integration tests
grunt.registerTask('integration-test', ['build-dev', 'connect:test', 'casperjs:integration']);
// Run drawing tests
grunt.registerTask('drawing-test', ['build-dev', 'connect:test', 'casperjs:drawing']);
// Run linting, unit tests, drawing tests and integration tests
grunt.registerTask('test', ['lint', 'unit-test', 'build-dev', 'connect:test', 'casperjs:drawing', 'casperjs:integration']);
// Run the tests, even if the linting fails // Validate & Test
grunt.registerTask('test-nolint', ['unit-test', 'build-dev', 'connect:test', 'casperjs:drawing', 'casperjs:integration']); grunt.registerTask('test-travis', ['lint', 'unit-test', 'build-dev', 'connect:test', 'ghost:travis']);
// Validate & Test (faster version) will NOT work on travis !!
grunt.registerTask('test-local', ['lint', 'unit-test', 'build-dev', 'connect:test', 'ghost:local']);
grunt.registerTask('test-local-nolint', ['unit-test', 'build-dev', 'connect:test', 'ghost:local']);
// Used by optional precommit hook grunt.registerTask('test', ['test-travis']);
grunt.registerTask('precommit', ['test']); grunt.registerTask('precommit', ['test-local']);
// BUILD TASKS
grunt.registerTask('build-index.html', ['includereplace']); grunt.registerTask('build-index.html', ['includereplace']);
grunt.registerTask('merge-statics', ['concat:js', 'concat:css', 'uglify']); grunt.registerTask('merge-statics', ['concat:js', 'concat:css', 'uglify']);
grunt.registerTask('build', ['clean:prod', 'sprite', 'merge-statics', 'build-index.html', 'replace:mainPartial', 'replace:css', 'copy:prod']); grunt.registerTask('build', ['clean:prod', 'sprite', 'merge-statics', 'build-index.html', 'replace:mainPartial', 'copy:prod']);
grunt.registerTask('build-dev', ['clean:dev', 'sprite', 'build-index.html', 'copy:dev']); grunt.registerTask('build-dev', ['clean:dev', 'sprite', 'build-index.html', 'copy:dev']);
grunt.registerTask('desktop', ['clean:desktop', 'default', 'nwjs:windows']);
grunt.registerTask('desktop-mac', ['clean:desktop', 'default', 'nwjs:macos']);
grunt.registerTask('desktop-mac-old', ['clean:desktop', 'default', 'replace:desktop', 'nwjs:macos_old']);
// SERVER TASKS // Validate & Build
// Start webserver and watch for changes
grunt.registerTask('serve', ['build', 'connect:prod', 'watch:prod']);
// Start webserver on src folder, in debug mode
grunt.registerTask('play', ['build-dev', 'connect:dev', 'watch:dev']);
// ALIASES, kept for backward compatibility
grunt.registerTask('serve-debug', ['play']);
grunt.registerTask('serve-dev', ['play']);
grunt.registerTask('test-travis', ['test']);
grunt.registerTask('test-local', ['test']);
// Default task
grunt.registerTask('default', ['lint', 'build']); grunt.registerTask('default', ['lint', 'build']);
// Build stand alone app with nodewebkit
grunt.registerTask('desktop', ['clean:desktop', 'default', 'replace:desktop', 'nwjs:windows']);
grunt.registerTask('desktop-mac', ['clean:desktop', 'default', 'replace:desktop', 'nwjs:macos']);
// Start webserver and watch for changes
grunt.registerTask('serve', ['build', 'connect:prod', 'open:prod', 'watch:prod']);
// Start webserver on src folder, in debug mode
grunt.registerTask('serve-dev', ['build-dev', 'connect:dev', 'open:dev', 'watch:dev']);
grunt.registerTask('serve-debug', ['serve-dev']);
grunt.registerTask('play', ['serve-dev']);
}; };

View File

@ -1,61 +1,75 @@
Piskel Piskel
====== ======
[![Travis Status](https://api.travis-ci.org/piskelapp/piskel.png?branch=master)](https://travis-ci.org/piskelapp/piskel) [![Built with Grunt](https://cdn.gruntjs.com/builtwith.png)](https://gruntjs.com/) [![Travis Status](https://api.travis-ci.org/juliandescottes/piskel.png?branch=master)](https://travis-ci.org/juliandescottes/piskel) [![Built with Grunt](https://cdn.gruntjs.com/builtwith.png)](http://gruntjs.com/)
Piskel is an easy-to-use sprite editor. It can be used to create game sprites, animations, pixel-art... A simple web-based tool for Spriting and Pixel art.
It is the editor used in **[piskelapp.com](https://www.piskelapp.com)**.
<img ![Piskel editor screenshot](https://screenletstore.appspot.com/img/8f03e768-ac59-11e3-b2a1-7f5a1b97c420.jpeg "Piskel editor screenshot")
src="https://screenletstore.appspot.com/img/95aaa0f0-37a4-11e7-a652-7b8128ce3e3b.png"
title="Piskel editor screenshot"
width="500">
## About Piskel You can try the standalone editor at **http://juliandescottes.github.io/piskel** or see it integrated in **http://piskelapp.com**.
### Built with Piskel is mainly developped by :
The Piskel editor is purely built in **JavaScript, HTML and CSS**. * **[@juliandescottes](https://github.com/juliandescottes)**
* **[@grosbouddha](https://github.com/grosbouddha)**
## What's the point ?
You can use Piskel to do two things :
* **spriting** : create retro-style sprites for games
![Megaman spritesheet](http://piskel-imgstore-a.appspot.com/img/c8081287-ac58-11e3-bd8c-b3c4036c0eee.png "Megaman spritesheet")
* **pixelart** : create crazy/pretty pixelart animations for fun !
![Rabbit jumping](http://piskel-imgstore-a.appspot.com/img/947f2dab-ac58-11e3-949a-b3c4036c0eee.gif "Rabit jumping")
Integrated in **[piskelapp.com](http://piskelapp.com)**, you can share everything you work on with others as easily as you share a link.
## Requirements
Piskel supports the following browsers :
* **Chrome** (latest)
* **Firefox** (latest)
* **Internet Explorer** 11+
... and a fairly recent computer.
We don't plan/want/could be forced into supporting older IEs. For Opera and Safari, we've never tested them but the gap shouldn't be huge.
## Offline version
Offline builds are available. More details in the [dedicated wiki page](https://github.com/juliandescottes/piskel/wiki/Desktop-applications).
## Built with
The Piskel editor is purely built in **JavaScript, HTML and CSS**. It uses Canvas extensively for displaying all them pretty sprites.
We also use the following **libraries** : We also use the following **libraries** :
* [spectrum](https://github.com/bgrins/spectrum) : awesome standalone colorpicker * [spectrum](https://github.com/bgrins/spectrum) : awesome standalone colorpicker
* [gifjs](https://jnordberg.github.io/gif.js/) : generate animated GIFs in javascript, using webworkers * [gifjs](http://jnordberg.github.io/gif.js/) : generate animated GIFs in javascript, using webworkers
* [supergif](https://github.com/buzzfeed/libgif-js) : modified version of SuperGif to parse and import GIFs * [supergif](https://github.com/buzzfeed/libgif-js) : modified version of SuperGif to parse and import GIFs
* [jszip](https://github.com/Stuk/jszip) : create, read and edit .zip files with Javascript * [jszip](https://github.com/Stuk/jszip) : create, read and edit .zip files with Javascript
* [canvas-toBlob](https://github.com/eligrey/canvas-toBlob.js/) : shim for canvas toBlob * [canvas-toBlob](https://github.com/eligrey/canvas-toBlob.js/) : shim for canvas toBlob
* [jquery](https://jquery.com/) : used sporadically in the application * [jquery](http://jquery.com/) : used sporadically in the application
* [bootstrap-tooltip](https://getbootstrap.com/javascript/#tooltips) : nice tooltips * [bootstrap-tooltip](http://getbootstrap.com/javascript/#tooltips) : nice tooltips
As well as some **icons** from the [Noun Project](https://thenounproject.com/) : As well as some **icons** from the [Noun Project](http://thenounproject.com/) :
* Folder by Simple Icons from The Noun Project * Folder by Simple Icons from The Noun Project
* (and probably one or two others) * (and probably one or two others)
### Browser Support
Piskel supports the following browsers:
* **Chrome** (latest)
* **Firefox** (latest)
* **Edge** (latest)
* **Internet Explorer** 11
### Mobile/Tablets
There is no support for mobile.
### Offline builds
Offline builds are available. More details in the [dedicated wiki page](https://github.com/piskelapp/piskel/wiki/Desktop-applications).
## Contributing ? ## Contributing ?
Help is always welcome ! Help is always welcome !
* **Issues** : Found a problem when using the application, want to request a feature, [open an issue](https://github.com/piskelapp/piskel/issues). * **Issues** : Found a problem when using the application, want to request a feature, [open an issue](https://github.com/juliandescottes/piskel/issues).
* **Development** : Have a look at the [wiki](https://github.com/piskelapp/piskel/wiki) to set up the development environment * **Participate** : Have a look at the [wiki](https://github.com/juliandescottes/piskel/wiki) to set up the development environment
## License ## License
Copyright 2017 Julian Descottes Copyright 2016 Julian Descottes
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -69,3 +83,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
## Mobile/Tablets
There is no support for mobile for now.

View File

@ -1,32 +0,0 @@
# Release instructions
- retrieve source code and dependencies
- clone piskel `git clone https://github.com/piskelapp/piskel`
- clone piskel website `git clone https://github.com/piskelapp/piskel-website`
- download the appengine SDK for python at [this url](https://cloud.google.com/appengine/docs/standard/python/download). It seems recent versions don't work for me on Windows. [GoogleAppEngine-1.9.67.msi](https://storage.cloud.google.com/appengine-sdks/featured/GoogleAppEngine-1.9.67.msi?_ga=2.6838962.-1257793585.1543157659) looks ok...
- prepare the release
- in `piskel-website` clone, checkout the `master` branch, not the `release`. The release branch is similar to the master branch, except it doesn't ignore the statics files coming from the `piskel` project. The idea is that we can easily checkout the release branch to do a new release, without having to rebuild piskel, in case nothing changed in piskel itself. We will switch to the release branch when we perform the final release.
- in `piskel` clone, create a new branch for the release `git checkout -b vX.Y`
- build and copy piskel to piskel-website (assumes the clones are in the same folder) `grunt && node bin/copy-to-piskel-website.js`
- local test
- start piskel-website in the Google app engine launcher, test manually the update
- if any issue is detected create a commit to fix it (on the `vX.Y` branch) and push it.
- beta test
- check the version in app.yaml is set to 'beta'. For historical reasons, alpha is the "production" version, while beta is the ... beta version. Don't ask.
- in the google app engine launcher, deploy this version.
- go to https://beta-dot-piskel-app.appspot.com and test (while this is not production frontend, it shares the same database, so be careful with what you create and delete)
- if any issue is detected create a commit to fix it (on `master`) and push it.
- check caches...
- If any icon was modified or any script of piskel-website was modified, there's no nice way to clean the cache on each release... so we just put a time stamp in the requests. eg `background-image: url(../img/icons@2x.png?20181125);` or `<script type="text/javascript" src="/static/js/piskel-animated-preview.js?20181124"></script>`. Erk.
- finalize the release
- in `piskel` update version in package.json. Remove the "-SNAPSHOT" at the end and commit the change, with a commit message such as `release: bump version to vX.Y`.
- in `piskel-website` checkout the `release` branch. Rebase it on master (that's pretty bad, we should probably cherry pick all the changes between the two branches...)
- once again build and copy piskel to piskel-website
- in `piskel-website` run `git status` to check that there are a bunch of changes to commit. (test locally again if you are paranoid)
- in `piskel-website` commit the current changes with a commit message such as `update statics for release vX.Y`
- Check that the version in app.yaml is now set to alpha. Deploy. Pray.
- post release
- in piskel-website push the release branch to github
- in piskel add a last commit to update the version in package.json to update the version to `vX+1.0-SNAPSHOT`
- create a tag on github

View File

@ -1,84 +0,0 @@
const rmdir = require('rmdir');
const path = require('path');
const fs = require('fs');
const fse = require('fs-extra');
const PISKEL_PATH = path.resolve(__dirname, '..');
const PISKELAPP_PATH = path.resolve(__dirname, '../../piskel-website');
var pjson = require('../package.json');
// Callbacks sorted by call sequence.
function onCopy(err) {
if (err) {
console.error('Failed to copy static files...');
return console.error(err);
}
console.log('Copied static files to piskel-website...');
let previousPartialPath = path.resolve(PISKELAPP_PATH, 'templates/editor/main-partial.html');
fs.access(previousPartialPath, fs.constants.F_OK, function (err) {
if (err) {
// File does not exit, call next step directly.
console.error('Previous main partial doesn\'t exist yet.');
onDeletePreviousPartial();
} else {
// File exists, try to delete it before moving on.
fs.unlink(previousPartialPath, onDeletePreviousPartial);
}
})
}
function onDeletePreviousPartial(err) {
if (err) {
console.error('Failed to delete previous main partial...');
return console.error(err);
}
console.log('Previous main partial deleted...');
fse.copy(
path.resolve(PISKELAPP_PATH, "static/editor/piskelapp-partials/main-partial.html"),
path.resolve(PISKELAPP_PATH, "templates/editor/main-partial.html"),
onCopyNewPartial
);
}
function onCopyNewPartial(err) {
if (err) {
console.error('Failed to delete previous main partial...');
return console.error(err);
}
console.log('Main partial copied...');
rmdir(
path.resolve(PISKELAPP_PATH, "static/editor/piskelapp-partials/"),
onDeleteTempPartial
);
}
function onDeleteTempPartial(err) {
if (err) {
console.error('Failed to delete temporary main partial...');
return console.error(err);
}
console.log('Temporary main partial deleted...');
fs.writeFile(path.resolve(PISKELAPP_PATH, "static/editor/VERSION"), pjson.version, onVersionFileCreated);
}
function onVersionFileCreated(err) {
if (err) {
console.error('Failed to create temporary main partial...');
return console.error(err);
}
console.log('Version file created...');
console.log('Finished!');
}
fse.copy(
path.resolve(PISKEL_PATH, "dest/prod"),
path.resolve(PISKELAPP_PATH, "static/editor"),
onCopy
);

View File

@ -1,64 +0,0 @@
# Piskel CLI
Wraps the Piskel pixel editing application to enable similar export options via the command line.
## Installation
Option 1: Globally install Piskel
```
npm install -g https://github.com/piskelapp/piskel/tarball/master
```
Option 2: Clone and install Piskel normally and then run npm link inside the installation root
## Usage
**Export provided .piskel file as a png sprite sheet using app defaults**
```
piskel-cli snow-monster.piskel
```
**Export scaled sprite sheet**
```
piskel-cli snow-monster.piskel --scale 5
```
**Export scaled to specific (single frame) width value**
```
piskel-cli snow-monster.piskel --scaledWidth 435
```
**Export scaled to specific (single frame) height value**
```
piskel-cli snow-monster.piskel --scaledHeight 435
```
**Export sprite sheet as a single column**
```
piskel-cli snow-monster.piskel --columns 1
```
**Export sprite sheet as a single row**
```
piskel-cli snow-monster.piskel --rows 1
```
**Export a single frame (0 is first frame)**
```
piskel-cli snow-monster.piskel --frame 3
```
**Export a second file containing the data-uri for the exported png**
```
piskel-cli snow-monster.piskel --dataUri
```
**Export cropped**
```
piskel-cli snow-monster.piskel --crop
```
**Custom output path and/or filename**
```
piskel-cli snow-monster.piskel --dest ./output-folder/snah-monstah.png
```

View File

@ -1,130 +0,0 @@
const fs = require('fs');
function onPageEvaluate(window, options, piskel) {
console.log("\nPiskel name: " + piskel.descriptor.name);
// Setup piskelController
var piskelController = new pskl.controller.piskel.PiskelController(piskel);
pskl.app.piskelController = piskelController;
piskelController.init();
// Apply crop if enabled
if (options.crop) {
// Mock selection manager to avoid errors during crop
pskl.app.selectionManager = {};
// Setup crop tool
var crop = new pskl.tools.transform.Crop();
// Perform crop
crop.applyTransformation();
// Get cropped piskel
piskel = piskelController.getPiskel();
}
// Mock exportController to provide zoom value based on cli args
// and to avoid errors and/or unnecessary bootstrapping
var exportController = {
getExportZoom: function () {
var zoom = options.zoom;
if (options.scaledWidth) {
zoom = options.scaledWidth / piskel.getWidth();
} else if (options.scaledHeight) {
zoom = options.scaledHeight / piskel.getHeight();
}
return zoom;
}
};
// Setup pngExportController
var pngExportController = new pskl.controller.settings.exportimage.PngExportController(piskelController, exportController);
// Mock getColumns and getRows to use values from cli arguments
pngExportController.getColumns_ = function () {
if (options.columns) return options.columns;
if (options.rows) {
return Math.ceil(piskelController.getFrameCount() / pngExportController.getRows_());
} else {
return pngExportController.getBestFit_();
}
};
pngExportController.getRows_ = function () {
if (options.columns && !options.rows) {
return Math.ceil(piskelController.getFrameCount() / pngExportController.getColumns_());
}
return options.rows;
};
// Render to output canvas
var canvas;
if (options.frame > -1) {
// Render a single frame
canvas = piskelController.renderFrameAt(options.frame, true);
var zoom = exportController.getExportZoom();
if (zoom != 1) {
// Scale rendered frame
canvas = pskl.utils.ImageResizer.resize(canvas, canvas.width * zoom, canvas.height * zoom, false);
}
} else {
// Render the sprite sheet
canvas = pngExportController.createPngSpritesheet_();
}
// Add output canvas to DOM
window.document.body.appendChild(canvas);
// Prepare return data
const returnData = {
width: canvas.width,
height: canvas.height
};
// Wait a tick for things to wrap up
setTimeout(function () {
// Exit and pass data to parent process
window.callPhantom(returnData);
}, 0);
}
function onPageExit(page, options, data) {
// Set clip for output image
if (data.width && data.height) {
page.clipRect = { top: 0, left: 0, width: data.width, height: data.height };
}
console.log("\n" + 'Generated file(s):');
const dest = options.dest.replace('.png', '') + '.png';
// Render page to the output image
page.render(dest);
console.log(" " + dest);
if (options.dataUri) {
const dataUriPath = options.dest + '.datauri';
const dataUri = 'data:image/png;base64,' + page.renderBase64('PNG');
// Write data-uri to file
fs.write(dataUriPath, dataUri, 'w');
console.log(" " + dataUriPath);
}
}
module.exports = {
onPageEvaluate: onPageEvaluate,
onPageExit: onPageExit
};

View File

@ -1,93 +0,0 @@
#!/usr/bin/env node
const fs = require('fs');
const path = require('path');
const minimist = require('minimist');
const childProcess = require('child_process');
const phantomjs = require('phantomjs');
const binPath = phantomjs.path;
// Parse command args
let args = minimist(process.argv.slice(2), {
default: {
crop: false,
dataUri: false,
debug: false,
scale: 1
},
});
if (args.debug) console.log(args);
// Ensure a path for the src file was passed
if (!args._ || (args._ && !args._.length)) {
console.error('Path to a .piskel file is required');
return;
}
const src = args._[0];
// Ensure the src file exists
if (!fs.existsSync(src)) {
console.error('No such file: ' + src);
return;
}
// Read src piskel file
const piskelFile = fs.readFileSync(src, 'utf-8');
const dest = args.dest || path.basename(src, '.piskel');
console.log('Piskel CLI is exporting...');
// Get path to Piskel's app js bundle
let piskelAppJsDir = path.resolve(__dirname +'/../dest/prod/js/');
let minJsFiles = fs.readdirSync(piskelAppJsDir).filter(filename => filename.indexOf('min') > -1);
let piskelAppJsFileName = minJsFiles[0];
let piskelAppJsPath = (piskelAppJsFileName) ? path.join(piskelAppJsDir, piskelAppJsFileName) : '';
if (!fs.existsSync(piskelAppJsPath)) {
console.error(`Piskel's application JS file not found in: ${piskelAppJsDir}. Run prod build and try again.`);
return;
}
// Prepare args to pass to phantom script
const options = {
dest: dest,
zoom: args.scale,
crop: !!args.crop,
rows: args.rows,
columns: args.columns,
frame: args.frame,
dataUri: !!args.dataUri,
debug: args.debug,
piskelAppJsPath: piskelAppJsPath,
scaledWidth: args.scaledWidth,
scaledHeight: args.scaledHeight
};
const childArgs = [
path.join(__dirname, 'piskel-export.js'),
piskelFile,
JSON.stringify(options)
];
if (args.debug) {
childArgs.unshift(
'--remote-debugger-port=9035',
'--remote-debugger-autorun=yes'
);
}
// Run phantom script
childProcess.execFile(binPath, childArgs, function (err, stdout, stderr) {
// Print any output the from child process
if (err) console.log(err);
if (stderr) console.log(stderr);
if (stdout) console.log(stdout);
console.log('Export complete');
});

View File

@ -1,45 +0,0 @@
// PhantomJS system
const system = require('system');
// Exporter
const exporter = require('./export-png');
// Get passed args
const args = system.args;
// Parse input piskel file and options
const piskelFile = JSON.parse(args[1]);
const options = JSON.parse(args[2]);
// Create page w/ canvas
const page = require('webpage').create();
page.content = '<html><body></body></html>';
// Inject Piskel JS
page.injectJs(options.piskelAppJsPath);
// Listen for page console logs
page.onConsoleMessage = function (msg) {
console.log(msg);
};
// Run page logic
page.evaluate(function (piskelFile, options, onPageEvaluate) {
// Zero out default body margin
document.body.style.margin = 0;
// Deserialize piskel file and run exporter's page evaluate task
pskl.utils.serialization.Deserializer.deserialize(piskelFile, function (piskel) {
onPageEvaluate(window, options, piskel);
});
}, piskelFile, options, exporter.onPageEvaluate);
// Wait for page to trigger exit
page.onCallback = function (data) {
// Run exporter page exit task
exporter.onPageExit(page, options, data);
// Exit
phantom.exit(0);
};

View File

@ -8,10 +8,7 @@ module.exports = function(config) {
var piskelScripts = require('./src/piskel-script-list.js').scripts.map(mapToSrcFolder); var piskelScripts = require('./src/piskel-script-list.js').scripts.map(mapToSrcFolder);
piskelScripts.push('test/js/testutils/**/*.js'); piskelScripts.push('test/js/testutils/**/*.js');
piskelScripts.push('test/js/**/*.js'); piskelScripts.push('test/js/**/*.js');
// Polyfill for Object.assign (missing in PhantomJS)
piskelScripts.push('./node_modules/phantomjs-polyfill-object-assign/object-assign-polyfill.js');
config.set({ config.set({
// base path that will be used to resolve all patterns (eg. files, exclude) // base path that will be used to resolve all patterns (eg. files, exclude)
@ -24,9 +21,7 @@ module.exports = function(config) {
// list of files / patterns to load in the browser // list of files / patterns to load in the browser
files: piskelScripts.concat([ files: piskelScripts,
'./node_modules/promise-polyfill/promise.js'
]),
// list of files to exclude // list of files to exclude

View File

@ -1,80 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
id="Layer_1"
x="0px"
y="0px"
width="90"
height="90"
viewBox="0 0 89.999997 90"
enable-background="new 0 0 89.231 100"
xml:space="preserve"
inkscape:version="0.92.1 r15371"
sodipodi:docname="common-backup.svg"
inkscape:export-filename="C:\Development\git\piskel\misc\icons\source\tool-rotate.png"
inkscape:export-xdpi="45"
inkscape:export-ydpi="45"><metadata
id="metadata15"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs13" /><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1148"
id="namedview11"
showgrid="false"
inkscape:zoom="7.75"
inkscape:cx="13.031976"
inkscape:cy="43.272537"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="Layer_1" /><g
id="g3760"
transform="matrix(0,-0.97677741,0.97203982,0,-2.1261998,91.355253)"
style="fill:#ff00ff;fill-opacity:1"><path
style="fill:#ff00ff;fill-opacity:1"
inkscape:connector-curvature="0"
id="path3"
d="m 29.229405,55.37008 c -0.387431,-1.333059 -0.642506,-2.72161 -0.738881,-4.152895 h -8.675106 c 0.115651,2.460738 0.552554,4.838559 1.260594,7.099021 z" /><path
style="fill:#ff00ff;fill-opacity:1"
inkscape:connector-curvature="0"
id="path5"
d="m 29.023802,70.783821 5.579515,-6.601516 c -1.862622,-1.780814 -3.387929,-3.907969 -4.44999,-6.287065 l -8.152106,2.946124 c 1.604978,3.800815 4.017584,7.185766 7.022581,9.942457 z" /><path
style="fill:#ff00ff;fill-opacity:1"
inkscape:connector-curvature="0"
id="path7"
d="m 47.110967,69.703978 c -3.887799,-0.260871 -7.469766,-1.6322 -10.437498,-3.790608 l -5.577588,6.598963 c 4.487901,3.403448 10.011517,5.524225 16.015086,5.803594 z" /><path
style="fill:#ff00ff;fill-opacity:1;stroke:none"
inkscape:connector-curvature="0"
id="path9"
d="M 48.464084,21.400659 V 14.532532 L 28.981398,25.698341 48.464084,36.86415 v -6.867489 c 11.042093,0 20.024317,8.91683 20.024317,19.877897 0,10.509484 -8.258763,19.134189 -18.671845,19.828145 v 8.611948 c 15.190751,-0.703524 27.330245,-13.189635 27.330245,-28.440093 0,-15.700763 -12.86681,-28.473899 -28.682717,-28.473899 z" /></g><g
id="g4513"
transform="translate(0,-2)"><rect
y="32.516129"
x="42"
height="15.612903"
width="7.9999986"
id="rect4494"
style="fill:#ff00f7;fill-opacity:1;stroke:#ffffed;stroke-width:0;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:6.04534006;stroke-opacity:1" /><rect
transform="rotate(120)"
y="-76.050484"
x="12.680965"
height="15.612903"
width="7.9999986"
id="rect4494-7"
style="fill:#ff00f7;fill-opacity:1;stroke:#ffffed;stroke-width:0;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:6.04534006;stroke-opacity:1" /></g></svg>

Before

Width:  |  Height:  |  Size: 3.7 KiB

View File

@ -1,64 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generator: Adobe Illustrator 15.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
id="Layer_1"
x="0px"
y="0px"
width="42"
height="42"
viewBox="0 0 41.999999 41.999999"
enable-background="new 0 0 99.997 69.373"
xml:space="preserve"
inkscape:version="0.48.4 r9939"
sodipodi:docname="common-warning-red.svg"
inkscape:export-filename="C:\Development\git\piskel\misc\icons\source\tool-move.png"
inkscape:export-xdpi="45"
inkscape:export-ydpi="45"><metadata
id="metadata9"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs7" /><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1148"
id="namedview5"
showgrid="false"
inkscape:zoom="4"
inkscape:cx="85.612634"
inkscape:cy="3.0742543"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="Layer_1" />
<path
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;color:#000000;fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans"
d="m 21,4.2499995 c -0.868171,0 -1.517453,0.2705716 -2,1.03125 L 3.9999999,34.999999 c -0.6703157,1.211185 0.6156981,2.999959 2,3 l 29.9999991,0 c 1.377219,0.0098 2.645421,-1.78334 2,-3 l -15,-29.6874995 C 22.632848,4.6114627 21.868171,4.2499995 21,4.2499995 z m 0,6.2187495 11.999999,23.53125 -23.9999992,0 z"
id="rect3765"
inkscape:connector-curvature="0"
sodipodi:nodetypes="zcccccczcccc" /><path
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;color:#000000;fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans"
d="m 20.572432,16.003047 c -0.858253,0.109012 -1.577503,1.040604 -1.572402,2.036618 L 20,25.963381 c 9.2e-5,1.066342 -0.158856,2.036512 0.765534,2.036618 l 0.468961,0 c 0.92439,-1.06e-4 0.765412,-0.970276 0.765504,-2.036618 l 1,-7.923716 c -9.2e-5,-1.066342 -0.841114,-2.036512 -1.765504,-2.036618 l -0.468961,0 c -0.0643,-0.0041 -0.128799,-0.0041 -0.193102,0 z"
id="rect3772"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccccc" /><path
style="fill:#ff0000;fill-opacity:1;stroke:#00ffff;stroke-width:0;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:1.60000000000000010"
d="m 20.999298,29.000086 c 0.620953,-0.006 0.971639,0.298697 0.999273,1.499911 0.02763,1.201212 -0.347092,1.493936 -0.999273,1.499909 -0.65218,0.006 -1.002864,-0.275261 -0.999271,-1.499909 0.0036,-1.22465 0.378318,-1.493938 0.999271,-1.499911 z"
inkscape:connector-curvature="0"
sodipodi:nodetypes="zzzzz" /></svg>

Before

Width:  |  Height:  |  Size: 4.1 KiB

View File

@ -0,0 +1,21 @@
@ECHO off
SETLOCAL
SET PISKEL_PATH="C:\Development\git\piskel"
SET PISKELAPP_PATH="C:\Development\git\piskel-website"
ECHO "Copying files to piskelapp"
XCOPY "%PISKEL_PATH%\dest\prod" "%PISKELAPP_PATH%\static\editor" /e /i /h /y
ECHO "Delete previous partial"
DEL "%PISKELAPP_PATH%\templates\editor\main-partial.html"
ECHO "Copy new partial"
MOVE "%PISKELAPP_PATH%\static\editor\piskelapp-partials\main-partial.html" "%PISKELAPP_PATH%\templates\editor"
ECHO "Delete temp partial"
RMDIR "%PISKELAPP_PATH%\static\editor\piskelapp-partials\" /S /Q
PAUSE
explorer "%PISKELAPP_PATH%\"
ENDLOCAL

View File

@ -1,77 +1,63 @@
{ {
"name": "piskel", "name": "piskel",
"version": "0.15.2-SNAPSHOT", "version": "0.8.3",
"description": "Pixel art editor", "description": "Pixel art editor",
"author": "Julian Descottes <julian.descottes@gmail.com>", "author": "Julian Descottes <julian.descottes@gmail.com>",
"contributors": [ "contributors": [
"Vincent Renaudin" "Vincent Renaudin"
], ],
"homepage": "http://github.com/piskelapp/piskel", "homepage": "http://github.com/juliandescottes/piskel",
"license": "Apache-2.0", "license": "Apache-2.0",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "http://github.com/piskelapp/piskel.git" "url": "http://github.com/juliandescottes/piskel.git"
}, },
"files": [ "files": [
"dest/prod", "dest/prod",
"misc/scripts/piskel-root" "misc/scripts/piskel-root"
], ],
"bin": { "bin": {
"piskel-root": "./misc/scripts/piskel-root", "piskel-root": "./misc/scripts/piskel-root"
"piskel-cli": "./cli/index.js"
}, },
"main": "./dest/prod/index.html", "main": "./dest/prod/index.html",
"scripts": { "scripts": {
"test": "grunt test", "test": "grunt test",
"dev": "grunt play", "start": "nodewebkit",
"start": "grunt build && nw", "preversion": "grunt test-local build",
"preversion": "grunt test build", "postversion": "git push && git push --tags && npm publish"
"postversion": "git push && git push --tags && npm publish",
"release": "grunt && node ./bin/copy-to-piskel-website",
"build": "grunt desktop",
"build:mac": "grunt desktop-mac",
"format": "grunt eslint --fix"
}, },
"devDependencies": { "devDependencies": {
"dateformat": "4.5.1", "dateformat": "1.0.11",
"fs-extra": "10.0.0", "grunt": "^0.4.5",
"grunt": "1.4.1", "grunt-contrib-clean": "1.0.0",
"grunt-casperjs": "^2.2.1",
"grunt-cli": "^1.4.3",
"grunt-contrib-clean": "2.0.0",
"grunt-contrib-concat": "1.0.1", "grunt-contrib-concat": "1.0.1",
"grunt-contrib-connect": "3.0.0", "grunt-contrib-connect": "1.0.2",
"grunt-contrib-copy": "1.0.0", "grunt-contrib-copy": "1.0.0",
"grunt-contrib-jshint": "3.0.0", "grunt-contrib-jshint": "1.0.0",
"grunt-contrib-uglify": "5.0.1", "grunt-contrib-uglify": "1.0.1",
"grunt-contrib-watch": "^1.1.0", "grunt-contrib-watch": "1.0.0",
"grunt-eslint": "23.0.0", "grunt-ghost": "1.1.0",
"grunt-include-replace": "5.0.0", "grunt-include-replace": "4.0.1",
"grunt-jscs": "3.0.1", "grunt-jscs": "2.8.0",
"grunt-karma": "4.0.2", "grunt-karma": "1.0.0",
"grunt-leading-indent": "0.2.0", "grunt-leading-indent": "0.2.0",
"grunt-nw-builder": "3.1.0", "grunt-nw-builder": "2.0.3",
"grunt-replace": "2.0.2", "grunt-open": "0.2.3",
"grunt-spritesmith": "^6.9.0", "grunt-replace": "1.0.1",
"jasmine-core": "3.8.0", "grunt-spritesmith": "6.3.0",
"karma": "6.3.4", "jasmine-core": "2.1.0",
"karma-jasmine": "4.0.1", "karma": "0.13.21",
"karma-phantomjs-launcher": "1.0.4", "karma-chrome-launcher": "1.0.1",
"load-grunt-tasks": "5.1.0", "karma-jasmine": "1.0.2",
"nw": "0.54.0", "karma-phantomjs-launcher": "0.2.3",
"phantomjs": "2.1.7", "load-grunt-tasks": "3.5.0",
"phantomjs-polyfill-object-assign": "0.0.2", "phantomjs": "1.9.19"
"promise-polyfill": "8.2.0",
"rmdir": "1.2.0"
}, },
"window": { "window": {
"title": "Piskel", "title": "Piskel",
"icon": "dest/prod/logo.png", "icon": "dest/prod/logo.png",
"toolbar": false, "toolbar": false,
"width": 1000, "width": 1000,
"height": 700 "height": 500
},
"dependencies": {
"minimist": "^1.2.5"
} }
} }

View File

@ -1,9 +1,3 @@
@keyframes fade { @keyframes fade {
50% { opacity: 0.5; } 50% { opacity: 0.5; }
} }
@keyframes glow {
0% { opacity: 0.66; }
50% { opacity: 1; }
100% { opacity: 0.66; }
}

View File

@ -1,152 +0,0 @@
#dialog-container.browse-backups {
width: 700px;
height: 500px;
top : 50%;
left : 50%;
position : absolute;
margin-left: -350px;
}
.backups-step-container {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
}
.backups-step-content {
width: 100%;
height: 10px;
flex-grow: 1;
background: #444;
padding: 20px;
overflow: auto;
box-sizing: border-box;
}
.backups-step-actions {
flex-grow: 0;
flex-shrink: 1;
height: 60px;
display: flex;
align-items: center;
padding: 0 20px;
}
.show #dialog-container.browse-backups {
margin-top: -250px;
}
.browse-backups .browse-backups-disclaimer {
display: flex;
margin-bottom: 20px;
align-items: center;
}
.browse-backups .browse-backups-disclaimer-content {
padding: 0 20px;
font-size: 13px;
}
.browse-backups .browse-backups-disclaimer .backups-icon {
border: 1px solid gold;
flex-shrink: 0;
width: 90px;
height: 90px;
}
.browse-backups .centered-message {
position: absolute;
left: 50%;
width: 200px;
margin-top: 100px;
margin-left: -130px;
padding: 30px;
font-size: 16px;
text-align: center;
border: 1px solid;
}
.browse-backups .session-list-empty,
.browse-backups .snapshot-list-empty {
color: #bbb;
}
.browse-backups .session-list-error,
.browse-backups .snapshot-list-error {
color: white;
}
.browse-backups .session-item {
/* Transition duration should be kept in sync with SelectSession.DELETE_TRANSITION_DURATION */
transition: all 500ms;
}
/* Hide and slide up next sessions when deleting an item */
.browse-backups .session-item.deleting {
opacity: 0;
margin-bottom: -60px;
}
.browse-backups .session-item,
.browse-backups .snapshot-item {
display: flex;
align-items: center;
width: 100%;
height: 80px;
margin-bottom: 10px;
padding: 0 20px;
border: 1px solid #666;
box-sizing: border-box;
}
.browse-backups .snapshot-preview {
flex-grow: 0;
flex-shrink: 1;
/* Keep synced with SessionDetails.PREVIEW_SIZE */
height: 60px;
width: 60px;
margin-right: 20px;
}
.browse-backups .session-details,
.browse-backups .snapshot-details {
flex-grow: 1;
flex-shrink: 0;
display: flex;
flex-direction: column;
}
.browse-backups .session-details-title,
.browse-backups .snapshot-details-title {
font-size: 13px;
}
.browse-backups .session-details-info,
.browse-backups .snapshot-details-info {
font-size: 11px;
color: #bbb;
line-height: 1.5em;
}
.browse-backups .session-actions,
.browse-backups .snapshot-actions {
flex-grow: 0;
flex-shrink: 1;
display: flex;
}
.browse-backups .session-actions button,
.browse-backups .snapshot-actions button {
margin-left: 10px;
}
.browse-backups .session-item:last-child,
.browse-backups .snapshot-item:last-child {
margin-bottom: 0;
}

View File

@ -3,19 +3,6 @@
/* Browse local piskels panel */ /* Browse local piskels panel */
/************************************************************************************************/ /************************************************************************************************/
#dialog-container.browse-local {
width: 700px;
height: 500px;
top : 50%;
left : 50%;
position : absolute;
margin-left: -350px;
}
.show #dialog-container.browse-local {
margin-top: -250px;
}
.local-piskel-list { .local-piskel-list {
width: 100%; width: 100%;
} }
@ -42,7 +29,7 @@
.local-piskel-list-head { .local-piskel-list-head {
font-weight: bold; font-weight: bold;
color: var(--highlight-color); color: gold;
} }
.local-piskel-load-button, .local-piskel-load-button,

View File

@ -3,7 +3,7 @@
bottom: 10px; bottom: 10px;
left: 10px; left: 10px;
color : var(--highlight-color); color : gold;
font-weight: bold; font-weight: bold;
font-size : 1.25em; font-size : 1.25em;
line-height: 20px; line-height: 20px;
@ -97,7 +97,7 @@
border-radius: 2px; border-radius: 2px;
text-align: center; text-align: center;
font-family: monospace; font-family:Courier;
font-weight: bold; font-weight: bold;
font-size : 18px; font-size : 18px;
color: white; color: white;
@ -113,8 +113,8 @@
} }
.cheatsheet-shortcut-editable .cheatsheet-key { .cheatsheet-shortcut-editable .cheatsheet-key {
border-color: var(--highlight-color); border-color: gold;
color: var(--highlight-color); color: gold;
} }
.cheatsheet-shortcut-editing .cheatsheet-key { .cheatsheet-shortcut-editing .cheatsheet-key {
@ -140,7 +140,7 @@
padding : 10px; padding : 10px;
overflow: hidden; overflow: hidden;
background-color : var(--highlight-color); background-color : gold;
} }
.cheatsheet-helptext { .cheatsheet-helptext {

View File

@ -103,7 +103,7 @@
transition : border-color 0.2s; transition : border-color 0.2s;
} }
.create-palette-color:hover { .create-palette-color:hover {
border:1px solid var(--highlight-color); border:1px solid gold;
} }
.colors-list-drop-proxy { .colors-list-drop-proxy {
@ -111,17 +111,17 @@
} }
.create-palette-new-color { .create-palette-new-color {
border:2px dotted var(--highlight-color); border:2px dotted gold;
border-radius: 2px; border-radius: 2px;
line-height: 40px; line-height: 40px;
text-align: center; text-align: center;
font-size: 20px; font-size: 20px;
color: var(--highlight-color); color: gold;
} }
.create-palette-color.selected { .create-palette-color.selected {
border:2px solid var(--highlight-color); border:2px solid gold;
} }
.create-palette-remove-color { .create-palette-remove-color {

View File

@ -0,0 +1,101 @@
/************************************************************************************************/
/* Import dialog */
/************************************************************************************************/
#dialog-container.import-image {
width: 550px;
height: 360px;
top : 50%;
left : 50%;
position : absolute;
margin-left: -250px;
}
.show #dialog-container.import-image {
margin-top: -150px;
}
.import-subsection {
margin-left: 25px;
}
.import-section:not(.import-subsection) > .dialog-section-title {
width: 50px;
}
.import-section-preview-title {
position: absolute;
margin-left: 50%;
margin-top: -28px;
}
.import-section-preview {
position: absolute;
display: inline-block;
border: 1px dashed #999;
border-radius: 3px;
margin-left: 50%;
}
.import-section-preview img {
max-width: 220px;
max-height: 220px;
display: block;
}
.import-section-preview.no-border {
border-color: transparent;
}
.import-section-preview canvas {
position: absolute;
left: 0;
top: 0;
}
.dialog-section-title {
display : inline-block;
width: 80px;
}
.dialog-section-radio {
margin-top: 15px;
vertical-align: sub;
}
.import-size-field:nth-of-type(2) {
margin-left: 5px;
}
.import-image-file-name {
display: inline-block;
overflow: hidden;
width: 200px;
vertical-align: middle;
word-break : break-all;
white-space: nowrap;
text-overflow: ellipsis;
font-style: italic;
font-weight: normal;
text-shadow: none;
color: gold;
}
[name=smooth-resize-checkbox] {
margin : 0 8px;
}
.dialog-import-body {
padding: 10px 20px;
font-size:1.3em
}
.import-button {
font-size: 1em;
height: 28px;
padding: 0px 10px;
margin-top: 15px;
}

View File

@ -1,288 +0,0 @@
#dialog-container.import {
width: 500px;
height: 350px;
top : 50%;
left : 50%;
position : absolute;
margin-left: -250px;
margin-top: -175px;
}
.import .dialog-content {
font-size: 1.3em;
}
.import-step-container {
display: flex;
width: 100%;
height: 100%;
box-sizing: border-box;
box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.5);
background: #444;
}
.import-step-content {
padding: 10px;
}
.import-step-buttons {
position: absolute;
bottom: 10px;
right: 10px;
text-align: right;
}
.import-first-step .import-back-button {
display: none;
}
/**
* IMAGE IMPORT STEP
*/
.import-image-container {
padding: 10px;
}
.import-image-loading {
opacity: 0.3;
pointer-events: none;
}
.import-image-loading::after {
content: 'loading image';
position: absolute;
width: 100%;
top: 0;
left: 0;
margin-top: 110px;
text-align: center;
font-size: 3em;
color: white;
text-shadow: 0 0 60px black;
}
.import-subsection {
margin-left: 25px;
}
.import-section:not(.import-subsection) > .dialog-section-title {
width: 50px;
}
.import-section-preview-title {
position: absolute;
margin-left: 50%;
margin-top: -28px;
}
.import-section-preview {
position: absolute;
display: inline-block;
border: 1px dashed #999;
border-radius: 3px;
margin-left: 50%;
top: 10px;
width: 220px;
height: 220px;
display: flex;
align-items: center;
justify-content: center;
}
.import-section-preview img {
max-width: 100%;
max-height: 100%;
display: block;
}
.import-section-preview canvas {
position: absolute;
}
.dialog-section-title {
display : inline-block;
width: 80px;
}
.dialog-section-radio {
margin-top: 15px;
vertical-align: sub;
}
.import-size-field:nth-of-type(2) {
margin-left: 5px;
}
.import-image-file-name {
display: inline-block;
overflow: hidden;
width: 200px;
vertical-align: middle;
word-break : break-all;
white-space: nowrap;
text-overflow: ellipsis;
font-style: italic;
font-weight: normal;
text-shadow: none;
color: var(--highlight-color);
}
[name=smooth-resize-checkbox] {
margin : 0 8px;
}
.dialog-import-body {
padding: 10px 20px;
font-size:1.3em
}
/**
* SELECT MODE
*/
.import-info {
display: flex;
flex-direction: column;
height: 100%;
max-width: 178px;
box-sizing: border-box;
padding: 10px;
border-right: 3px solid gold;
}
.import-preview canvas {
max-width: 100%;
max-height: 100%;
}
.import-meta {
margin-top: 10px;
box-sizing: border-box;
/*center meta information horizontally*/
display: flex;
flex-direction: column;
justify-content: center;
}
.import-meta > div {
height: 22px;
display: flex;
margin-bottom: 5px;
}
.import-meta-value,
.import-meta-label {
padding: 2px 4px;
}
.import-meta-label {
border-radius: 2px 0 0 2px;
color: var(--highlight-color);
}
.import-meta-value {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.import-missing {
text-align: center;
line-height: 70px;
font-style: italic;
color: #aaa;
}
.import-mode-title {
margin-bottom: 10px
}
.import-mode-section {
display: flex;
border: 3px solid #666;
border-radius: 3px;
padding: 10px;
margin-bottom: 10px;
align-items: center;
}
.import-mode-section .button {
width: 75px;
height: 30px;
font-size: 14px;
margin-left: 10px;
flex-grow: 0;
flex-shrink: 0;
}
.import-mode-section-description {
flex-grow: 1;
}
.import-resize-option,
.insert-mode-option {
display: flex;
align-items: center;
margin: 5px 0;
}
.import-resize-option :checked + span,
.insert-mode-option :checked + span {
color: var(--highlight-color);
}
.import-resize-option input,
.insert-mode-option input {
margin: 5px;
}
/**
* ADJUST SIZE
*/
.import-resize-anchor-info {
margin-bottom: 10px;
}
.import-resize-section {
margin-bottom: 10px;
}
.import-resize-anchor {
margin-top: 20px;
}
.import-resize-option :checked + span {
color: var(--highlight-color);
}
.import-resize-warning {
color: var(--highlight-color);
}
/**
* INSERT LOCATION
*/
.insert-mode-container {
margin-top: 20px;
margin-bottom: 10px;
}
.insert-frame-preview {
margin: 10px 0;
}
.insert-frame-preview .frame-picker-wrapper {
height: 120px;
}

View File

@ -1,68 +0,0 @@
.performance-link {
display: none;
position: fixed;
bottom: 10px;
right: 10px;
z-index: 11000;
cursor: pointer;
opacity: 0;
transition : opacity 0.3s;
}
.performance-link.visible {
display: block;
opacity: 0.66;
animation: glow 2s infinite;
}
.performance-link.visible:hover {
opacity: 1;
animation: none;
}
#dialog-container.performance-info {
width: 500px;
height: 525px;
top : 50%;
left : 50%;
position : absolute;
margin-left: -250px;
margin-top: -260px;
}
.dialog-performance-info-body {
font-size: 13px;
letter-spacing: 1px;
padding: 10px 20px;
}
.dialog-performance-info-body ul {
border: 1px solid #666;
padding: 5px;
border-radius: 3px;
}
.dialog-performance-info-body li {
list-style-type: initial;
margin: 0 20px;
}
.dialog-performance-info-body sup {
color: var(--highlight-color);
cursor: pointer;
}
.show #dialog-container.performance-info {
margin-top: -300px;
}
.dialog-performance-info-body .warning-icon {
float: left;
margin-top: 10px;
}
.dialog-performance-info-body .warning-icon-info {
overflow: hidden;
margin-left: 30px;
}

View File

@ -1,32 +0,0 @@
/************************************************************************************************/
/* Unsupported browser dialog */
/************************************************************************************************/
#dialog-container.unsupported-browser {
width: 600px;
height: 260px;
top : 50%;
left : 50%;
position : absolute;
margin-top: -130px;
margin-left: -300px;
}
.unsupported-browser .dialog-content {
font-size:1.2em;
letter-spacing: 1px;
padding:10px 20px;
overflow: auto;
}
.unsupported-browser .supported-browser-list {
padding: 5px 20px;
}
.unsupported-browser .supported-browser-list li {
list-style-type: square;
}
#current-user-agent {
color: var(--highlight-color);
}

View File

@ -39,7 +39,7 @@
-moz-box-sizing : border-box; -moz-box-sizing : border-box;
border-radius: 3px; border-radius: 3px;
border : 3px solid var(--highlight-color); border : 3px solid gold;
background: #444; background: #444;
overflow: auto; overflow: auto;
} }
@ -48,6 +48,19 @@
margin-top: 0; margin-top: 0;
} }
#dialog-container.browse-local {
width: 700px;
height: 500px;
top : 50%;
left : 50%;
position : absolute;
margin-left: -350px;
}
.show #dialog-container.browse-local {
margin-top: -250px;
}
.dialog-wrapper { .dialog-wrapper {
height: 100%; height: 100%;
position : relative; position : relative;
@ -63,7 +76,7 @@
.dialog-head { .dialog-head {
width: 100%; width: 100%;
background: var(--highlight-color); background: gold;
margin: 0; margin: 0;
padding: 10px; padding: 10px;
color: black; color: black;

View File

@ -22,11 +22,6 @@
background : #3a3a3a; background : #3a3a3a;
} }
.textfield:focus {
border-color: var(--highlight-color);
outline: none;
}
.textfield-small { .textfield-small {
width : 50px; width : 50px;
} }
@ -34,13 +29,17 @@
.button { .button {
box-sizing: border-box; box-sizing: border-box;
height: 24px; height: 24px;
background-color: #666;
border-style: none; background-color: #3f3f3f;
border-radius: 2px; border: 1px solid #333;
border-top-color: #666;
border-bottom-color: #222;
cursor: pointer; cursor: pointer;
text-decoration: none; text-decoration: none;
color: white; color: white;
text-shadow: 0 -1px 0 black;
font-weight: bold; font-weight: bold;
font-size: 1rem; font-size: 1rem;
text-align: center; text-align: center;
@ -49,17 +48,25 @@
} }
.button:hover { .button:hover {
color: var(--highlight-color); text-decoration: none;
background-color: #484848;
color: gold;
} }
.button-primary { .button-primary {
background-color: var(--highlight-color); background-color: rgb(255,215,0); /* gold */
border-color: rgb(179, 164, 0);
border-top-color: white;
border-bottom-color: rgb(151, 133, 0);
color: black; color: black;
text-shadow: 0 1px 0 #fff;
} }
.button-primary:hover { .button-primary:hover {
background-color: white; background-color: rgb(255,235,20);
color: black; color: #333;
} }
.button[disabled], .button[disabled],
@ -67,6 +74,10 @@
cursor:default; cursor:default;
background-color: #aaa; background-color: #aaa;
color: #777; color: #777;
text-shadow: 0 1px 0 #bbb;
border-color: #666;
border-top-color: #999;
border-bottom-color: #555;
} }
.import-size-field, .import-size-field,

View File

@ -54,9 +54,6 @@
} }
.add-frame-action { .add-frame-action {
display: flex;
align-items: center;
margin-top: 8px; margin-top: 8px;
padding: 6px 0; padding: 6px 0;
overflow: hidden; overflow: hidden;
@ -74,7 +71,6 @@
.add-frame-action-icon { .add-frame-action-icon {
margin: 3px; margin: 3px;
float: left; float: left;
flex-shrink: 0;
} }
.add-frame-action .label { .add-frame-action .label {
@ -83,7 +79,7 @@
} }
.add-frame-action:hover { .add-frame-action:hover {
border-color: var(--highlight-color); border-color: gold;
} }
.preview-tile { .preview-tile {
@ -135,11 +131,6 @@
cursor: default; cursor: default;
} }
.preview-tile .tile-overlay.tile-count.toggled {
background-color: gold;
color: black;
}
.preview-tile .tile-overlay.delete-frame-action { .preview-tile .tile-overlay.delete-frame-action {
top: 0; top: 0;
right: 0; right: 0;
@ -162,7 +153,7 @@
} }
.preview-tile.selected { .preview-tile.selected {
border-color: var(--highlight-color); border-color: gold;
} }
.preview-tile.selected:after { .preview-tile.selected:after {
@ -171,7 +162,7 @@
top: 38px; top: 38px;
right: -9px; right: -9px;
border: transparent 4px solid; border: transparent 4px solid;
border-left-color: var(--highlight-color); border-left-color: gold;
border-width: 6px 0 6px 6px; border-width: 6px 0 6px 6px;
border-style: solid; border-style: solid;
} }
@ -182,6 +173,6 @@
*/ */
.preview-tile-drop-proxy { .preview-tile-drop-proxy {
border: 3px dashed var(--highlight-color); border: 3px dashed gold;
background-color: rgba(255, 215,0, 0.2); background-color: rgba(255, 215,0, 0.2);
} }

View File

@ -25,7 +25,7 @@
.left-column { .left-column {
vertical-align: top; vertical-align: top;
height: 100%; height: 100%;
padding-right: 7px; margin-right: 7px;
flex-shrink: 0; flex-shrink: 0;
} }
@ -44,8 +44,7 @@
flex-direction: column; flex-direction: column;
position: relative; position: relative;
/* Keep in sync with Constants.RIGHT_COLUMN_PADDING_LEFT */ margin-left: 10px;
padding-left: 10px;
/* Add some padding for the absolutely positioned .cursor-coordinates */ /* Add some padding for the absolutely positioned .cursor-coordinates */
padding-bottom: 20px; padding-bottom: 20px;
} }
@ -81,21 +80,10 @@
} }
.cursor-coordinates { .cursor-coordinates {
color: var(--highlight-color); color:#888;
font-size: 12px; font-size:12px;
font-weight: bold; font-weight:bold;
font-family: monospace; font-family:Courier;
}
.cursor-coordinates .drawing-zoom {
position: absolute;
top: -20px;
left: 1px;
}
.cursor-coordinates .frame-info {
line-height: 1.5;
text-align: left;
} }
/** /**
@ -169,4 +157,4 @@
.canvas.drawing-canvas {z-index: 8;} .canvas.drawing-canvas {z-index: 8;}
.canvas.canvas-overlay {z-index: 9;} .canvas.canvas-overlay {z-index: 9;}
.canvas.onion-skin-canvas {z-index: 10;} .canvas.onion-skin-canvas {z-index: 10;}
.canvas.layers-above-canvas {z-index: 11;} .canvas.layers-above-canvas {z-index: 11;}

View File

@ -1,8 +1,8 @@
.minimap-crop-frame { .minimap-crop-frame {
position: absolute; position:absolute;
border: 2px solid gold; border:1px solid rgba(255,255,255,0.5);
z-index: 100; z-index:100;
box-sizing: border-box; box-sizing : border-box;
-moz-box-sizing: border-box; -moz-box-sizing : border-box;
cursor: pointer; cursor : pointer;
} }

View File

@ -6,12 +6,12 @@
max-width: 300px; max-width: 300px;
border-top-left-radius: 7px; border-top-left-radius: 7px;
border: #e1a325 2px solid; border: #F0C36D 1px solid;
border-right: 0; border-right: 0;
border-bottom: 0; border-bottom: 0;
color: #222; color: #222;
background-color: var(--highlight-color); background-color: #F9EDBE;
font-weight: bold; font-weight: bold;
font-size: 13px; font-size: 13px;
@ -24,6 +24,8 @@
top: 6px; top: 6px;
right: 17px; right: 17px;
color: gray;
font-size: 18px; font-size: 18px;
font-weight: bold; font-weight: bold;
@ -41,7 +43,7 @@
padding: 10px; padding: 10px;
width: 360px; width: 360px;
border-top-right-radius: 2px; border-top-right-radius: 2px;
border: var(--highlight-color) 2px solid; border: gold 2px solid;
border-left: 0; border-left: 0;
border-bottom: 0; border-bottom: 0;
background-color: #444; background-color: #444;
@ -67,6 +69,6 @@
margin-top: 8px; margin-top: 8px;
height : 4px; height : 4px;
width : 300px; width : 300px;
background : linear-gradient(to left, var(--highlight-color), var(--highlight-color)) no-repeat -300px 0; background : linear-gradient(to left, gold, gold) no-repeat -300px 0;
background-color : black; background-color : black;
} }

49
src/css/pensize.css Normal file
View File

@ -0,0 +1,49 @@
.pen-size-container {
overflow: hidden;
padding: 5px 5px;
}
.pen-size-option {
float: left;
box-sizing: border-box;
width: 20px;
height: 20px;
margin-right: 2px;
border-style: solid;
border-width: 2px;
border-color: #444;
cursor: pointer;
}
.pen-size-option[data-size='1'] {
padding: 6px;
}
.pen-size-option[data-size='2'] {
padding: 5px;
}
.pen-size-option[data-size='3'] {
padding: 4px;
}
.pen-size-option[data-size='4'] {
padding: 3px;
}
.pen-size-option:before {
content: '';
width: 100%;
height: 100%;
background-color: white;
display: block;
}
.pen-size-option:hover {
border-color: #888;
}
.pen-size-option.selected:before {
background-color: gold;
}
.pen-size-option.selected {
border-color: gold;
}

View File

@ -5,7 +5,6 @@ html, body {
cursor : default; cursor : default;
font-family: Arial; font-family: Arial;
font-size: 11px; font-size: 11px;
line-height: 1.1;
-webkit-touch-callout: none; -webkit-touch-callout: none;
-webkit-user-select: none; -webkit-user-select: none;
-khtml-user-select: none; -khtml-user-select: none;
@ -48,5 +47,5 @@ input[type="range"] {
} }
a, a:visited { a, a:visited {
color: var(--highlight-color); color:gold;
} }

View File

@ -1,14 +1,6 @@
/********************************/ /*******************************/
/* Preferences Settings panel */ /* Application Setting panel */
/********************************/ /*******************************/
.settings-section-preferences {
height: 100%;
position: relative;
overflow: hidden;
margin: 0 20px;
height: 100%;
}
.background-picker-wrapper { .background-picker-wrapper {
display: inline-block; display: inline-block;
@ -35,20 +27,16 @@
} }
.background-picker.selected { .background-picker.selected {
border-color: var(--highlight-color); border-color: gold;
} }
.settings-opacity-input { .layer-opacity-input {
margin: 5px; margin: 5px;
vertical-align: middle; vertical-align: middle;
}
.layer-opacity-input,
.tile-mask-opacity-input {
width: 100px; width: 100px;
} }
.settings-opacity-text { .layer-opacity-text {
height: 31px; height: 31px;
display: inline-block; display: inline-block;
line-height: 30px; line-height: 30px;
@ -59,102 +47,11 @@
text-align: center; text-align: center;
} }
.settings-item-grid-size, .grid-width-select {
.settings-item-grid-spacing,
.settings-item-grid-color {
display: flex;
align-items: center;
}
.settings-item-grid-size > label,
.settings-item-grid-spacing > label,
.settings-item-grid-color > label {
width: 65px;
flex-shrink: 0;
}
.grid-spacing-container .size-picker-option[data-size='1'] {
padding: 7px;
}
.grid-spacing-container .size-picker-option[data-size='2'] {
padding: 6px;
}
.grid-spacing-container .size-picker-option[data-size='4'] {
padding: 5px;
}
.grid-spacing-container .size-picker-option[data-size='8'] {
padding: 4px;
}
.grid-spacing-container .size-picker-option[data-size='16'] {
padding: 3px;
}
.grid-spacing-container .size-picker-option[data-size='32'] {
padding: 2px;
}
.grid-spacing-container .size-picker-option[data-size='64'] {
padding: 1px;
}
.settings-item-grid-size .size-picker-option,
.settings-item-grid-spacing .size-picker-option {
border-color: #888;
}
.settings-item-grid-size .size-picker-option:not(.selected):hover,
.settings-item-grid-spacing .size-picker-option:not(.selected):hover {
border-color: white;
}
.grid-width-select,
.color-format-select {
margin: 5px 5px 0 5px; margin: 5px 5px 0 5px;
} }
.settings-section-application > .settings-title {
.grid-colors-list {
overflow: hidden;
padding: 0 5px;
}
.grid-colors-item {
float: left;
width: 20px;
height: 20px;
cursor: pointer;
border: 2px solid #888;
margin-right: 2px;
margin-bottom: 2px;
box-sizing: border-box;
}
.grid-colors-item:hover {
border-color: white;
}
.grid-colors-item.selected {
border-color: gold;
}
.settings-section-preferences > .settings-title {
/* Override the default 10px margin bottom for this panel */ /* Override the default 10px margin bottom for this panel */
margin-bottom: 15px; margin-bottom: 15px;
} }
.settings-section-preferences .button-primary {
margin-top: 10px;
}
.settings-version-info {
position: absolute;
bottom: 10px;
right: 10px;
color: #888;
}
/* Override default link styles for the release notes link
It doesn't need to popout too much */
.settings-version,
.settings-version:hover {
color: white !important;
text-decoration: none !important;
}

View File

@ -43,29 +43,8 @@
float : left; float : left;
} }
.gif-export-warning {
display: none;
}
.gif-export-warning.visible {
display: flex;
align-items: center;
border: 1px solid red;
padding: 5px;
margin: 5px 0;
}
.gif-export-warning-icon {
flex-shrink: 0;
margin-right: 5px;
}
.gif-export-warning-message {
font-weight: normal;
}
.preview-upload-ongoing:before{ .preview-upload-ongoing:before{
content: "Upload in progress..."; content: "Upload ongoing ...";
position: absolute; position: absolute;
display: block; display: block;
height: 100%; height: 100%;
@ -121,6 +100,43 @@
line-height: 23px; line-height: 23px;
} }
.export-tabs {
overflow: hidden;
position: relative;
}
.export-tabs:after {
content: "";
display: block;
position: absolute;
bottom: 0;
width: 100%;
height: 1px;
z-index: 0;
background-color: gold;
}
.export-tab {
float: left;
cursor: pointer;
padding: 5px;
border: 1px solid transparent;
/* Make sure the tab and its border are positioned above the :after element; */
position: relative;
z-index: 1;
}
.export-tab.selected,
.export-tab:hover {
color: gold;
}
.export-tab.selected {
border-color: gold gold #444 gold;
border-style: solid;
border-width: 1px;
}
.export-panel-header { .export-panel-header {
padding: 10px 5px 0px; padding: 10px 5px 0px;
} }
@ -144,8 +160,7 @@
overflow: hidden; overflow: hidden;
} }
.export-panel-gif .button, .export-panel-gif .button {
.export-panel-png .button {
margin-right: 5px; margin-right: 5px;
width: 75px; width: 75px;
flex-shrink: 0; flex-shrink: 0;
@ -155,6 +170,11 @@
width: 50px; width: 50px;
} }
.png-export-dimension-info,
.png-export-datauri-info {
margin-left: 5px;
}
#png-export-columns, #png-export-columns,
#png-export-rows { #png-export-rows {
/* Override default textfield padding-right to keep the number spinners /* Override default textfield padding-right to keep the number spinners

View File

@ -5,8 +5,103 @@
width: 25%; width: 25%;
} }
.resize-anchor-container { /*****************/
/* ANCHOR WIDGET */
/*****************/
.resize-origin-container {
overflow: hidden;
position: relative; position: relative;
width: 70px;
margin-top: 5px; margin-top: 5px;
display: inline-block; display: inline-block;
} }
.transition .resize-origin-option,
.transition .resize-origin-option:before {
transition: background-color 0.2s, border-color 0.2s;
}
.resize-origin-option {
float: left;
position: relative;
box-sizing: border-box;
margin: 0 1px 1px 0;
width: 20px;
height: 20px;
background : #888;
font-size: 8px;
text-align: center;
cursor: pointer;
}
.disabled .resize-origin-option {
cursor: default;
background : #555;
border-color: #555 !important;
}
.resize-origin-option:hover {
border : 3px solid white;
}
.resize-origin-option.selected {
border : 3px solid gold;
}
.resize-origin-option:before {
content: '';
position: absolute;
display: block;
top: 50%;
left: 50%;
margin: -2px;
}
.resize-origin-option.selected:before {
content: '';
width: 4px;
height: 4px;
background: gold;
}
.disabled .resize-origin-option.selected:before {
background: #555;
}
.disabled .resize-origin-option[data-neighbor]:before {
border-color: #555 !important;
}
.resize-origin-option[data-neighbor]:before {
width: 0;
height: 0;
border-width: 4px;
border-style: solid;
border-color: transparent;
}
.resize-origin-option[data-neighbor="bottom"]:before {
border-top-color: gold;
margin-left: -4px;
}
.resize-origin-option[data-neighbor="left"]:before {
border-right-color: gold;
margin-top: -4px;
margin-left: -6px;
}
.resize-origin-option[data-neighbor="top"]:before {
border-bottom-color: gold;
margin-top: -6px;
margin-left: -4px;
}
.resize-origin-option[data-neighbor="right"]:before {
border-left-color: gold;
margin-top: -4px;
}

View File

@ -24,13 +24,3 @@
color: white; color: white;
font-style: normal; font-style: normal;
} }
.save-status-warning-icon {
float: left;
margin-top: 5px;
}
.save-status-warning-icon {
overflow: hidden;
padding-left: 10px;
}

View File

@ -52,7 +52,7 @@
background-color: #444; background-color: #444;
margin-right: 0; margin-right: 0;
padding-right: 2px; padding-right: 2px;
border-left : 3px solid var(--highlight-color); border-left : 3px solid gold;
} }
/************************************************************************************************/ /************************************************************************************************/
@ -64,6 +64,7 @@
font-size: 12px; font-size: 12px;
font-weight: bold; font-weight: bold;
color: #ccc; color: #ccc;
text-shadow: 1px 1px #000;
} }
.settings-section .button { .settings-section .button {
@ -76,7 +77,7 @@
text-transform: uppercase; text-transform: uppercase;
border-bottom: 1px #aaa solid; border-bottom: 1px #aaa solid;
padding-bottom: 5px; padding-bottom: 5px;
color: var(--highlight-color); color: gold;
} }
.settings-description { .settings-description {

View File

@ -100,8 +100,8 @@
} }
.sp-palette .sp-thumb-el.sp-thumb-active { .sp-palette .sp-thumb-el.sp-thumb-active {
border-color: var(--highlight-color); border-color: gold;
box-shadow: 0 0 0px 1px var(--highlight-color); box-shadow: 0 0 0px 1px gold;
} }
.sp-input { .sp-input {
@ -110,7 +110,7 @@
background: #111; background: #111;
border-radius: 2px; border-radius: 2px;
color: #D3D3D3; color: #D3D3D3;
font-family: monospace!important; font-family: Courier!important;
} }
.sp-input.sp-validation-error { .sp-input.sp-validation-error {

113
src/css/sprites.css Normal file
View File

@ -0,0 +1,113 @@
/*
Icon classes can be used entirely standalone. They are named after their original file names.
```html
<!-- `display: block` sprite -->
<div class="icon-home"></div>
<!-- `display: inline-block` sprite -->
<img class="icon-home" />
```
*/
.icon-cloud_export {
background-image: url(../img/spritesheet.png);
background-position: -512px -276px;
width: 50px;
height: 47px;
}
.icon-dragndrop {
background-image: url(../img/spritesheet.png);
background-position: -564px -173px;
width: 48px;
height: 48px;
}
.icon-duplicate {
background-image: url(../img/spritesheet.png);
background-position: -512px -369px;
width: 16px;
height: 16px;
}
.icon-export {
background-image: url(../img/spritesheet.png);
background-position: -564px -225px;
width: 43px;
height: 42px;
}
.icon-favicon {
background-image: url(../img/spritesheet.png);
background-position: -582px -151px;
width: 16px;
height: 16px;
}
.icon-gallery {
background-image: url(../img/spritesheet.png);
background-position: -512px -225px;
width: 52px;
height: 51px;
}
.icon-garbage {
background-image: url(../img/spritesheet.png);
background-position: 0px 0px;
width: 512px;
height: 512px;
}
.icon-gear {
background-image: url(../img/spritesheet.png);
background-position: -563px -323px;
width: 38px;
height: 37px;
}
.icon-import-icon {
background-image: url(../img/spritesheet.png);
background-position: -576px -69px;
width: 28px;
height: 36px;
}
.icon-keyboard {
background-image: url(../img/spritesheet.png);
background-position: -512px -133px;
width: 70px;
height: 40px;
}
.icon-local-storage-icon {
background-image: url(../img/spritesheet.png);
background-position: -512px 0px;
width: 100px;
height: 69px;
}
.icon-merge-icon {
background-image: url(../img/spritesheet.png);
background-position: -512px -69px;
width: 64px;
height: 64px;
}
.icon-plus {
background-image: url(../img/spritesheet.png);
background-position: -512px -323px;
width: 51px;
height: 46px;
}
.icon-popup-preview-arrow-gold {
background-image: url(../img/spritesheet.png);
background-position: -576px -105px;
width: 24px;
height: 18px;
}
.icon-popup-preview-arrow-white {
background-image: url(../img/spritesheet.png);
background-position: -582px -133px;
width: 24px;
height: 18px;
}
.icon-resize-icon {
background-image: url(../img/spritesheet.png);
background-position: -512px -173px;
width: 52px;
height: 52px;
}
.icon-save {
background-image: url(../img/spritesheet.png);
background-position: -562px -276px;
width: 43px;
height: 42px;
}

View File

@ -17,11 +17,11 @@ body {
} }
.no-overflow { .no-overflow {
overflow: hidden; overflow : hidden;
} }
.highlight { .image-link {
color: var(--highlight-color); color : gold;
} }
.pull-top, .pull-top,
@ -52,23 +52,14 @@ body {
} }
.checkbox-fix { .checkbox-fix {
margin: 3px 3px 3px 0; margin-left: 0;
}
.checkbox-container {
display: flex;
align-items: center;
}
.hidden {
display: none;
} }
/** /**
* TOOLTIPS * TOOLTIPS
*/ */
.tooltip-shortcut { .tooltip-shortcut {
color: var(--highlight-color); color:gold;
} }
.tooltip-container { .tooltip-container {

View File

@ -79,7 +79,7 @@
.preview-toggle-onion-skin-enabled, .preview-toggle-onion-skin-enabled,
.preview-toggle-onion-skin-enabled:hover { .preview-toggle-onion-skin-enabled:hover {
color : var(--highlight-color); color : gold;
} }
.preview-contextual-actions { .preview-contextual-actions {
@ -98,9 +98,7 @@
opacity: 1; opacity: 1;
} }
.preview-contextual-action { .original-size-button {
float: left;
width : 18px; width : 18px;
height: 18px; height: 18px;
line-height: 18px; line-height: 18px;
@ -115,73 +113,14 @@
font-family: Tahoma; font-family: Tahoma;
} }
.preview-contextual-action-hidden { .original-size-button-enabled {
display: none;
}
.preview-contextual-action:hover {
color: var(--highlight-color);
border-color: var(--highlight-color);
}
/**
* If the icon represents an enabled state, the border should always be gold.
*/
.preview-contextual-action-enabled {
color: var(--highlight-color);
border-color: var(--highlight-color);
}
/**
* Drop-down in preview size selection
*/
.preview-drop-down {
float: left;
position: relative;
width : 22px;
min-height: 22px;
margin: 0 5px;
}
.preview-drop-down.preview-drop-down-disabled {
opacity: 0.5;
}
.preview-disable-overlay{
position: absolute;
width: 100%;
height: 100%;
display: none;
}
.preview-drop-down.preview-drop-down-disabled .preview-disable-overlay {
display: block;
z-index: 10;
}
.preview-drop-down .preview-contextual-action {
position: relative;
margin: 0 0 -100% 0;
opacity: 0;
transition: opacity linear .2s,
margin linear .2s;
transition-delay: 0s, .2s;
z-index: 1;
}
.preview-drop-down:hover .preview-contextual-action {
margin: 0 0 5px 0;
opacity: 1;
transition-delay: 0s, 0s;
}
.preview-drop-down .size-button-selected {
opacity: 1;
color: gold; color: gold;
border-color: gold; border-color: gold;
z-index: 5;
} }
.preview-contextual-action {
float: left;
}
.open-popup-preview-button { .open-popup-preview-button {
border : 2px solid white; border : 2px solid white;
@ -189,21 +128,13 @@
} }
.open-popup-preview-button:hover { .open-popup-preview-button:hover {
border-color: var(--highlight-color); border-color: gold;
} }
/** /**
* The regular image is provided by the sprite icons.png+icons.css * The regular image is provided bby the sprite icons.png+icons.css
*/ */
.icon-minimap-popup-preview-arrow-white:hover { .icon-minimap-popup-preview-arrow-white:hover {
background-image: url(../img/icons/minimap/minimap-popup-preview-arrow-gold.png); background-image: url(../img/icons/minimap/minimap-popup-preview-arrow-gold.png);
background-position: 0 0; background-position: 0 0;
background-size: 18px 18px;
}
@media (-webkit-min-device-pixel-ratio: 2),
(min-resolution: 192dpi) {
.icon-minimap-popup-preview-arrow-white:hover {
background-image: url(../img/icons/minimap/minimap-popup-preview-arrow-gold@2x.png);
}
} }

View File

@ -35,7 +35,7 @@
.layers-toggle-preview-enabled, .layers-toggle-preview-enabled,
.layers-toggle-preview-enabled:hover { .layers-toggle-preview-enabled:hover {
color : var(--highlight-color); color : gold;
} }
/** /**
@ -59,40 +59,24 @@
.layer-item { .layer-item {
position: relative; position: relative;
display: flex;
height:24px; height:24px;
line-height: 24px; line-height: 24px;
padding: 0 0 0 10px;
border-top: 1px solid #444; border-top: 1px solid #444;
cursor: pointer; cursor: pointer;
} }
.layer-item .layer-name,
.layer-item .layer-name-input {
padding: 0 0 0 10px;
flex: 1 auto;
white-space: nowrap;
}
.layer-item .layer-name-input {
width: 80%;
}
.layer-item .layer-name.overflowing-name {
overflow: hidden;
text-overflow: ellipsis;
}
.layer-item:hover { .layer-item:hover {
background : #222; background : #222;
} }
.layer-item-opacity { .layer-item-opacity {
padding: 0 8px 0 8px; position: absolute;
flex: 0 auto; right: 8px;
} }
.current-layer-item, .current-layer-item,
.current-layer-item:hover { .current-layer-item:hover {
background : #333; background : #333;
color: var(--highlight-color); color: gold;
} }

View File

@ -76,11 +76,6 @@
position: relative; position: relative;
} }
.palettes-list-colors.tiny > .palettes-list-color {
width: calc((100% - 35px) / 10);
height: 16px;
}
.palettes-list-color div { .palettes-list-color div {
height: 100%; height: 100%;
} }
@ -94,7 +89,7 @@
line-height: 35px; line-height: 35px;
width: 100%; width: 100%;
color: gray; color: gray;
font-size: 0.8em; font-size: 0.7em;
font-style: italic; font-style: italic;
text-align: center text-align: center
} }
@ -126,14 +121,13 @@
* Color index for the 9 first colors * Color index for the 9 first colors
*/ */
:not(.tiny) > .palettes-list-color:nth-child(-n+10):after { .palettes-list-color:nth-child(-n+10):after {
content: attr(data-color-index);
position: absolute; position: absolute;
top: 0; top: 0;
right: 0; right: 0;
background-color: black; background-color: black;
color: var(--highlight-color); color: gold;
font-family: Tahoma; font-family: Tahoma;
font-size: 0.5em; font-size: 0.5em;
@ -142,3 +136,39 @@
padding: 2px 3px 2px 3px; padding: 2px 3px 2px 3px;
border-radius: 0 0 0 2px; border-radius: 0 0 0 2px;
} }
.palettes-list-color:nth-child(1):after {
content: "1";
}
.palettes-list-color:nth-child(2):after {
content: "2";
}
.palettes-list-color:nth-child(3):after {
content: "3";
}
.palettes-list-color:nth-child(4):after {
content: "4";
}
.palettes-list-color:nth-child(5):after {
content: "5";
}
.palettes-list-color:nth-child(6):after {
content: "6";
}
.palettes-list-color:nth-child(7):after {
content: "7";
}
.palettes-list-color:nth-child(8):after {
content: "8";
}
.palettes-list-color:nth-child(9):after {
content: "9";
}

View File

@ -26,17 +26,7 @@
.toolbox-buttons .button { .toolbox-buttons .button {
/* Override border propery on .button elements from form.css */ /* Override border propery on .button elements from form.css */
border-style: solid;
border-color: #333;
border-width: 0 1px 0 0; border-width: 0 1px 0 0;
border-radius: 0;
background-color: #3f3f3f;
}
.toolbox-buttons .button[disabled],
.toolbox-buttons .button[disabled]:hover {
background-color: #aaa;
} }
.toolbox-buttons button:last-child { .toolbox-buttons button:last-child {

View File

@ -17,7 +17,7 @@
position : absolute; position : absolute;
height : 100%; height : 100%;
width : 100%; width : 100%;
border: 3px solid var(--highlight-color); border: 3px solid gold;
box-sizing: border-box; box-sizing: border-box;
} }

View File

@ -3,38 +3,5 @@
} }
.transformations-container .tool-icon { .transformations-container .tool-icon {
margin: 0 0 5px 0; float:left;
} }
.transformations-container .tools-wrapper {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
height: 46px;
/* Override the float:left set on tools-wrapper in layout.css; */
float: initial;
}
.transformations-container.show-more .tools-wrapper {
height: auto;
/* Compensate the 5px bottom-margin coming from the tool-icon */
margin-bottom: -5px;
}
.transformations-show-more-link {
position: absolute;
color: #999;
right: 10px;
font-weight: normal;
cursor: pointer;
transition: 0.2s linear;
}
.transformations-show-more-link:hover {
color: white;
}
.show-more .transformations-show-more-link {
color: gold;
}

View File

@ -1,3 +0,0 @@
html, body {
--highlight-color: gold;
}

View File

@ -1,98 +0,0 @@
/*****************/
/* ANCHOR WIDGET */
/*****************/
.anchor-wrapper {
overflow: hidden;
width: 70px;
}
/* When transitioning between enabled and disabled states */
.transition .anchor-option,
.transition .anchor-option:before {
transition: background-color 0.2s, border-color 0.2s;
}
.anchor-option {
float: left;
position: relative;
box-sizing: border-box;
margin: 0 1px 1px 0;
width: 20px;
height: 20px;
background : #888;
font-size: 8px;
text-align: center;
cursor: pointer;
}
.disabled .anchor-option {
cursor: default;
background : #555;
border-color: #555 !important;
}
.anchor-option:hover {
border : 3px solid white;
}
.anchor-option.selected {
border : 3px solid var(--highlight-color);
}
.anchor-option:before {
content: '';
position: absolute;
display: block;
top: 50%;
left: 50%;
margin: -2px;
}
.anchor-option.selected:before {
content: '';
width: 4px;
height: 4px;
background: var(--highlight-color);
}
.disabled .anchor-option.selected:before {
background: #555;
}
.disabled .anchor-option[data-neighbor]:before {
border-color: #555 !important;
}
.anchor-option[data-neighbor]:before {
width: 0;
height: 0;
border-width: 4px;
border-style: solid;
border-color: transparent;
}
.anchor-option[data-neighbor="bottom"]:before {
border-top-color: var(--highlight-color);
margin-left: -4px;
}
.anchor-option[data-neighbor="left"]:before {
border-right-color: var(--highlight-color);
margin-top: -4px;
margin-left: -6px;
}
.anchor-option[data-neighbor="top"]:before {
border-bottom-color: var(--highlight-color);
margin-top: -6px;
margin-left: -4px;
}
.anchor-option[data-neighbor="right"]:before {
border-left-color: var(--highlight-color);
margin-top: -4px;
}

View File

@ -1,55 +0,0 @@
/***********************/
/* FRAME PICKER WIDGET */
/***********************/
.frame-picker-wrapper {
width: 150px;
height: 150px;
border: 3px solid #666;
border-radius: 3px;
}
.frame-viewer {
width: 100%;
height: calc(100% - 25px);
display: flex;
align-items: center;
justify-content: center;
}
.frame-viewer > canvas,
.frame-viewer > img {
max-width: 100%;
max-height: 100%;
}
.frame-nav {
display: flex;
width: 100%;
height: 24px;
border-top: 1px solid #666;
}
.frame-nav .button {
flex-shrink: 0;
border-radius: 0;
height: 24px;
background-color: #3f3f3f;
}
.frame-nav .button[disabled],
.frame-nav .button[disabled]:hover {
background-color: #aaa;
}
.frame-nav .button + .button {
border-left: 1px solid #333;
}
.frame-nav-input {
min-width: 1px;
border-style: none;
height: 24px;
text-align: center;
}

View File

@ -1,61 +0,0 @@
/***********************/
/* SIZE PICKER WIDGET */
/***********************/
.size-picker-container {
overflow: hidden;
padding: 5px 5px;
}
.size-picker-option {
float: left;
box-sizing: border-box;
width: 20px;
height: 20px;
margin-right: 2px;
border-style: solid;
border-width: 2px;
border-color: #444;
cursor: pointer;
}
.size-picker-option[data-size='1'] {
padding: 5px;
}
.size-picker-option[data-size='2'] {
padding: 4px;
}
.size-picker-option[data-size='3'] {
padding: 3px;
}
.size-picker-option[data-size='4'] {
padding: 2px;
}
.size-picker-option:before {
content: '';
width: 100%;
height: 100%;
background-color: white;
display: block;
text-align: center;
line-height: 12px;
font-size: 90%;
}
.size-picker-option:hover {
border-color: #888;
}
.size-picker-option.selected:before {
background-color: var(--highlight-color);
}
.size-picker-option.selected {
border-color: var(--highlight-color);
}
.size-picker-option.labeled:before {
content: attr(real-size);
color: black;
}

View File

@ -1,42 +0,0 @@
/*****************/
/* TABS WIDGET */
/*****************/
.tab-list {
overflow: hidden;
position: relative;
}
.tab-list:after {
content: "";
display: block;
position: absolute;
bottom: 0;
width: 100%;
height: 1px;
z-index: 0;
background-color: var(--highlight-color);
}
.tab-item {
float: left;
cursor: pointer;
padding: 5px;
border: 1px solid transparent;
border-radius: 2px 2px 0 0;
/* Make sure the tab and its border are positioned above the :after element; */
position: relative;
z-index: 1;
}
.tab-item.selected,
.tab-item:hover {
color: var(--highlight-color);
}
.tab-item.selected {
border-color: var(--highlight-color);
border-bottom-color: #444;
border-style: solid;
border-width: 1px;
}

View File

@ -1,32 +0,0 @@
.wizard-wrapper {
z-index: 1;
position: relative;
width: 100%;
height: 100%;
overflow: hidden;
}
.wizard-step {
z-index: -1;
margin-left: calc(100% + 5px);
position: absolute;
}
.current-step {
z-index: 1;
margin-left: 0;
}
.current-step-in,
.current-step-out {
z-index: 10;
transition: margin-left 200ms;
}
.current-step-in {
margin-left: 0;
}
.current-step-out {
margin-left: 100%;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 446 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 851 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 135 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 192 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 135 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 186 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 393 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 693 B

BIN
src/img/icons@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View File

@ -22,7 +22,9 @@
color:white;"> color:white;">
<span style="top:45%">Loading Piskel ...</span> <span style="top:45%">Loading Piskel ...</span>
</div> </div>
<!--standalone-start-->
@@include('templates/debug-header.html', {}) @@include('templates/debug-header.html', {})
<!--standalone-end-->
<!-- the comment below indicates the beginning of markup reused by the editor integrated in piskelapp.com --> <!-- the comment below indicates the beginning of markup reused by the editor integrated in piskelapp.com -->
<!-- do not delete, do not move :) --> <!-- do not delete, do not move :) -->
@ -67,28 +69,18 @@
</div> </div>
@@include('templates/misc-templates.html', {}) @@include('templates/misc-templates.html', {})
@@include('templates/data-uri-export.html', {})
@@include('templates/popup-preview.html', {}) @@include('templates/popup-preview.html', {})
<span class="cheatsheet-link icon-common-keyboard-gold" <span class="cheatsheet-link icon-common-keyboard-gold" rel="tooltip" data-placement="right" title="Keyboard shortcuts">&nbsp;</span>
rel="tooltip" data-placement="right" title="Keyboard shortcuts">&nbsp;</span>
<div class="performance-link icon-common-warning-red"
rel="tooltip" data-placement="left" title="Performance problem detected, learn more.">&nbsp;</div>
<!-- dialogs partials --> <!-- dialogs partials -->
@@include('templates/dialogs/browse-backups.html', {}) @@include('templates/dialogs/create-palette.html', {})
@@include('templates/dialogs/import-image.html', {})
@@include('templates/dialogs/browse-local.html', {}) @@include('templates/dialogs/browse-local.html', {})
@@include('templates/dialogs/cheatsheet.html', {}) @@include('templates/dialogs/cheatsheet.html', {})
@@include('templates/dialogs/create-palette.html', {})
@@include('templates/dialogs/import.html', {})
@@include('templates/dialogs/performance-info.html', {})
@@include('templates/dialogs/unsupported-browser.html', {})
<!-- settings-panel partials --> <!-- settings-panel partials -->
@@include('templates/settings/preferences.html', {}) @@include('templates/settings/application.html', {})
@@include('templates/settings/preferences/grid.html', {})
@@include('templates/settings/preferences/misc.html', {})
@@include('templates/settings/preferences/tile.html', {})
@@include('templates/settings/resize.html', {}) @@include('templates/settings/resize.html', {})
@@include('templates/settings/save.html', {}) @@include('templates/settings/save.html', {})
@@include('templates/settings/import.html', {}) @@include('templates/settings/import.html', {})

View File

@ -1,99 +0,0 @@
{
"env": {
"es6": true,
"browser": true
},
"globals": {
"$": true,
"jQuery": true,
"pskl": true,
"Events": true,
"Constants": true,
"console": true,
"module": true,
"require": true,
"Q": true,
"Promise": true
},
"rules": {
"no-undef": 2,
"no-use-before-define": [
2,
{
"functions": false
}
],
"curly": [
2,
"all"
],
"operator-linebreak": [
2,
"after"
],
"camelcase": [
2,
{
"properties": "never"
}
],
"max-len": [
2,
120
],
"indent": [
2,
2,
{
"SwitchCase": 1
}
],
"quotes": [
2,
"single"
],
"no-multi-str": 2,
"no-mixed-spaces-and-tabs": 2,
"no-trailing-spaces": 2,
"space-unary-ops": [
2,
{
"nonwords": false,
"overrides": {}
}
],
"one-var": [
2,
"never"
],
"brace-style": [
2,
"1tbs",
{
"allowSingleLine": true
}
],
"keyword-spacing": [
2,
{}
],
"space-infix-ops": 2,
"space-before-blocks": [
2,
"always"
],
"eol-last": 2,
"space-in-parens": [
2,
"never"
],
"no-multiple-empty-lines": 2,
"no-with": 2,
"no-spaced-func": 2,
"dot-notation": 2,
"semi": [
2,
"always"
]
}
}

View File

@ -12,19 +12,14 @@ var Constants = {
MAX_HEIGHT : 1024, MAX_HEIGHT : 1024,
MAX_WIDTH : 1024, MAX_WIDTH : 1024,
MAX_PALETTE_COLORS : 256, MAX_PALETTE_COLORS : 100,
// allow current colors service to get up to 256 colors.
// GIF generation is different if the color count goes over 256.
MAX_WORKER_COLORS : 256,
PREVIEW_FILM_SIZE : 96, PREVIEW_FILM_SIZE : 96,
ANIMATED_PREVIEW_WIDTH : 200, ANIMATED_PREVIEW_WIDTH : 200,
// Keep in sync with padding-left: 10px in layout.css
RIGHT_COLUMN_PADDING_LEFT : 10,
DEFAULT_PEN_COLOR : '#000000', DEFAULT_PEN_COLOR : '#000000',
TRANSPARENT_COLOR : 'rgba(0, 0, 0, 0)', TRANSPARENT_COLOR : 'rgba(0, 0, 0, 0)',
SEAMLESS_MODE_OVERLAY_COLOR : 'rgba(255, 255, 255, 0)', SEAMLESS_MODE_OVERLAY_COLOR : 'rgba(255, 255, 255, 0.5)',
CURRENT_COLORS_PALETTE_ID : '__current-colors', CURRENT_COLORS_PALETTE_ID : '__current-colors',
@ -54,17 +49,8 @@ var Constants = {
// TESTS // TESTS
DRAWING_TEST_FOLDER : 'drawing', DRAWING_TEST_FOLDER : 'drawing',
// Maximum size of a sprite that can be saved on piskelapp datastore.
// This size will be compared to the length of the stringified serialization of the sprite.
// This is an approximation at best but gives correct results in most cases.
// The datastore limit is 1 MiB, which we roughly approximate to 1 million characters.
APPENGINE_SAVE_LIMIT : 1 * 1024 * 1024,
// Message displayed when an action will lead to erase the current animation.
CONFIRM_OVERWRITE: 'This will replace your current animation, are you sure you want to continue?',
// SERVICE URLS // SERVICE URLS
APPENGINE_SAVE_URL : 'save', APPENGINE_SAVE_URL : 'save',
IMAGE_SERVICE_UPLOAD_URL : '{{protocol}}://piskel-imgstore-b.appspot.com/__/upload', IMAGE_SERVICE_UPLOAD_URL : 'http://piskel-imgstore-b.appspot.com/__/upload',
IMAGE_SERVICE_GET_URL : '{{protocol}}://piskel-imgstore-b.appspot.com/img/' IMAGE_SERVICE_GET_URL : 'http://piskel-imgstore-b.appspot.com/img/'
}; };

View File

@ -15,7 +15,7 @@ var Events = {
DRAG_START : 'DRAG_START', DRAG_START : 'DRAG_START',
DRAG_END : 'DRAG_END', DRAG_END : 'DRAG_END',
DIALOG_SHOW : 'DIALOG_SHOW', DIALOG_DISPLAY : 'DIALOG_DISPLAY',
DIALOG_HIDE : 'DIALOG_HIDE', DIALOG_HIDE : 'DIALOG_HIDE',
PALETTE_LIST_UPDATED : 'PALETTE_LIST_UPDATED', PALETTE_LIST_UPDATED : 'PALETTE_LIST_UPDATED',
@ -59,15 +59,13 @@ var Events = {
AFTER_SAVING_PISKEL: 'AFTER_SAVING_PISKEL', AFTER_SAVING_PISKEL: 'AFTER_SAVING_PISKEL',
FRAME_SIZE_CHANGED : 'FRAME_SIZE_CHANGED', FRAME_SIZE_CHANGED : 'FRAME_SIZE_CHANGED',
FPS_CHANGED : 'FPS_CHANGED',
SELECTION_CREATED: 'SELECTION_CREATED', SELECTION_CREATED: 'SELECTION_CREATED',
SELECTION_MOVE_REQUEST: 'SELECTION_MOVE_REQUEST', SELECTION_MOVE_REQUEST: 'SELECTION_MOVE_REQUEST',
SELECTION_DISMISSED: 'SELECTION_DISMISSED', SELECTION_DISMISSED: 'SELECTION_DISMISSED',
SELECTION_COPY: 'SELECTION_COPY',
CLIPBOARD_COPY: 'CLIPBOARD_COPY', SELECTION_CUT: 'SELECTION_CUT',
CLIPBOARD_CUT: 'CLIPBOARD_CUT', SELECTION_PASTE: 'SELECTION_PASTE',
CLIPBOARD_PASTE: 'CLIPBOARD_PASTE',
SHOW_NOTIFICATION: 'SHOW_NOTIFICATION', SHOW_NOTIFICATION: 'SHOW_NOTIFICATION',
HIDE_NOTIFICATION: 'HIDE_NOTIFICATION', HIDE_NOTIFICATION: 'HIDE_NOTIFICATION',
@ -81,10 +79,6 @@ var Events = {
CURRENT_COLORS_UPDATED : 'CURRENT_COLORS_UPDATED', CURRENT_COLORS_UPDATED : 'CURRENT_COLORS_UPDATED',
PERFORMANCE_REPORT_CHANGED : 'PERFORMANCE_REPORT_CHANGED',
PISKEL_FILE_IMPORT_FAILED : 'PISKEL_FILE_IMPORT_FAILED',
// Tests // Tests
MOUSE_EVENT : 'MOUSE_EVENT', MOUSE_EVENT : 'MOUSE_EVENT',
KEYBOARD_EVENT : 'KEYBOARD_EVENT', KEYBOARD_EVENT : 'KEYBOARD_EVENT',

View File

@ -15,16 +15,12 @@
*/ */
this.isAppEngineVersion = !!pskl.appEngineToken_; this.isAppEngineVersion = !!pskl.appEngineToken_;
// This id is used to keep track of sessions in the BackupService.
this.sessionId = pskl.utils.Uuid.generate();
this.shortcutService = new pskl.service.keyboard.ShortcutService(); this.shortcutService = new pskl.service.keyboard.ShortcutService();
this.shortcutService.init(); this.shortcutService.init();
var size = pskl.UserSettings.get(pskl.UserSettings.DEFAULT_SIZE); var size = pskl.UserSettings.get(pskl.UserSettings.DEFAULT_SIZE);
var fps = Constants.DEFAULT.FPS;
var descriptor = new pskl.model.piskel.Descriptor('New Piskel', ''); var descriptor = new pskl.model.piskel.Descriptor('New Piskel', '');
var piskel = new pskl.model.Piskel(size.width, size.height, fps, descriptor); var piskel = new pskl.model.Piskel(size.width, size.height, descriptor);
var layer = new pskl.model.Layer('Layer 1'); var layer = new pskl.model.Layer('Layer 1');
var frame = new pskl.model.Frame(size.width, size.height); var frame = new pskl.model.Frame(size.width, size.height);
@ -39,8 +35,6 @@
this.piskelController.init(); this.piskelController.init();
this.paletteImportService = new pskl.service.palette.PaletteImportService(); this.paletteImportService = new pskl.service.palette.PaletteImportService();
this.paletteImportService.init();
this.paletteService = new pskl.service.palette.PaletteService(); this.paletteService = new pskl.service.palette.PaletteService();
this.paletteService.addDynamicPalette(new pskl.service.palette.CurrentColorsPalette()); this.paletteService.addDynamicPalette(new pskl.service.palette.CurrentColorsPalette());
@ -64,24 +58,25 @@
this.drawingController = new pskl.controller.DrawingController( this.drawingController = new pskl.controller.DrawingController(
this.piskelController, this.piskelController,
document.querySelector('#drawing-canvas-container')); this.paletteController,
$('#drawing-canvas-container'));
this.drawingController.init(); this.drawingController.init();
this.previewController = new pskl.controller.preview.PreviewController( this.previewController = new pskl.controller.preview.PreviewController(
this.piskelController, this.piskelController,
document.querySelector('#animated-preview-canvas-container')); $('#animated-preview-canvas-container'));
this.previewController.init(); this.previewController.init();
this.minimapController = new pskl.controller.MinimapController( this.minimapController = new pskl.controller.MinimapController(
this.piskelController, this.piskelController,
this.previewController, this.previewController,
this.drawingController, this.drawingController,
document.querySelector('.minimap-container')); $('.minimap-container'));
this.minimapController.init(); this.minimapController.init();
this.framesListController = new pskl.controller.FramesListController( this.framesListController = new pskl.controller.FramesListController(
this.piskelController, this.piskelController,
document.querySelector('#preview-list-wrapper')); $('#preview-list'));
this.framesListController.init(); this.framesListController.init();
this.layersListController = new pskl.controller.LayersListController(this.piskelController); this.layersListController = new pskl.controller.LayersListController(this.piskelController);
@ -99,7 +94,7 @@
this.selectionManager = new pskl.selection.SelectionManager(this.piskelController); this.selectionManager = new pskl.selection.SelectionManager(this.piskelController);
this.selectionManager.init(); this.selectionManager.init();
this.historyService = new pskl.service.HistoryService(this.piskelController); this.historyService = new pskl.service.HistoryService(this.corePiskelController);
this.historyService.init(); this.historyService.init();
this.notificationController = new pskl.controller.NotificationController(); this.notificationController = new pskl.controller.NotificationController();
@ -114,9 +109,6 @@
this.canvasBackgroundController = new pskl.controller.CanvasBackgroundController(); this.canvasBackgroundController = new pskl.controller.CanvasBackgroundController();
this.canvasBackgroundController.init(); this.canvasBackgroundController.init();
this.indexedDbStorageService = new pskl.service.storage.IndexedDbStorageService(this.piskelController);
this.indexedDbStorageService.init();
this.localStorageService = new pskl.service.storage.LocalStorageService(this.piskelController); this.localStorageService = new pskl.service.storage.LocalStorageService(this.piskelController);
this.localStorageService.init(); this.localStorageService.init();
@ -132,15 +124,12 @@
this.storageService = new pskl.service.storage.StorageService(this.piskelController); this.storageService = new pskl.service.storage.StorageService(this.piskelController);
this.storageService.init(); this.storageService.init();
this.importService = new pskl.service.ImportService(this.piskelController); this.importService = new pskl.service.ImportService(this.piskelController, this.previewController);
this.importService.init();
this.imageUploadService = new pskl.service.ImageUploadService(); this.imageUploadService = new pskl.service.ImageUploadService();
this.imageUploadService.init(); this.imageUploadService.init();
this.savedStatusService = new pskl.service.SavedStatusService( this.savedStatusService = new pskl.service.SavedStatusService(this.piskelController, this.historyService);
this.piskelController,
this.historyService);
this.savedStatusService.init(); this.savedStatusService.init();
this.backupService = new pskl.service.BackupService(this.piskelController); this.backupService = new pskl.service.BackupService(this.piskelController);
@ -149,9 +138,7 @@
this.beforeUnloadService = new pskl.service.BeforeUnloadService(this.piskelController); this.beforeUnloadService = new pskl.service.BeforeUnloadService(this.piskelController);
this.beforeUnloadService.init(); this.beforeUnloadService.init();
this.headerController = new pskl.controller.HeaderController( this.headerController = new pskl.controller.HeaderController(this.piskelController, this.savedStatusService);
this.piskelController,
this.savedStatusService);
this.headerController.init(); this.headerController.init();
this.penSizeService = new pskl.service.pensize.PenSizeService(); this.penSizeService = new pskl.service.pensize.PenSizeService();
@ -160,29 +147,20 @@
this.penSizeController = new pskl.controller.PenSizeController(); this.penSizeController = new pskl.controller.PenSizeController();
this.penSizeController.init(); this.penSizeController.init();
this.fileDropperService = new pskl.service.FileDropperService(this.piskelController); this.fileDropperService = new pskl.service.FileDropperService(
this.piskelController,
document.querySelector('#drawing-canvas-container'));
this.fileDropperService.init(); this.fileDropperService.init();
this.userWarningController = new pskl.controller.UserWarningController(this.piskelController); var drawingLoop = new pskl.rendering.DrawingLoop();
this.userWarningController.init(); drawingLoop.addCallback(this.render, this);
drawingLoop.start();
this.performanceReportService = new pskl.service.performance.PerformanceReportService(
this.piskelController,
this.currentColorsService);
this.performanceReportService.init();
this.clipboardService = new pskl.service.ClipboardService(this.piskelController);
this.clipboardService.init();
this.drawingLoop = new pskl.rendering.DrawingLoop();
this.drawingLoop.addCallback(this.render, this);
this.drawingLoop.start();
this.initTooltips_(); this.initTooltips_();
var piskelData = this.getPiskelInitData_(); var piskelData = this.getPiskelInitData_();
if (piskelData && piskelData.piskel) { if (piskelData && piskelData.piskel) {
this.loadPiskel_(piskelData); this.loadPiskel_(piskelData.piskel, piskelData.descriptor, piskelData.fps);
} }
if (pskl.devtools) { if (pskl.devtools) {
@ -195,28 +173,13 @@
mb.createMacBuiltin('Piskel'); mb.createMacBuiltin('Piskel');
gui.Window.get().menu = mb; gui.Window.get().menu = mb;
} }
if (!pskl.utils.Environment.isIntegrationTest() && pskl.utils.UserAgent.isUnsupported()) {
$.publish(Events.DIALOG_SHOW, {
dialogId : 'unsupported-browser'
});
}
if (pskl.utils.Environment.isDebug()) {
pskl.app.shortcutService.registerShortcut(pskl.service.keyboard.Shortcuts.DEBUG.RELOAD_STYLES,
window.reloadStyles);
}
}, },
loadPiskel_ : function (piskelData) { loadPiskel_ : function (serializedPiskel, descriptor, fps) {
var serializedPiskel = piskelData.piskel;
pskl.utils.serialization.Deserializer.deserialize(serializedPiskel, function (piskel) { pskl.utils.serialization.Deserializer.deserialize(serializedPiskel, function (piskel) {
piskel.setDescriptor(descriptor);
pskl.app.piskelController.setPiskel(piskel); pskl.app.piskelController.setPiskel(piskel);
$.publish(Events.PISKEL_SAVED); pskl.app.previewController.setFPS(fps);
if (piskelData.descriptor) {
// Backward compatibility for v2 or older
piskel.setDescriptor(piskelData.descriptor);
}
}); });
}, },

View File

@ -17,8 +17,6 @@
$.subscribe(Events.DRAG_START, this.onDragStart_.bind(this)); $.subscribe(Events.DRAG_START, this.onDragStart_.bind(this));
$.subscribe(Events.DRAG_END, this.onDragEnd_.bind(this)); $.subscribe(Events.DRAG_END, this.onDragEnd_.bind(this));
$.subscribe(Events.FRAME_SIZE_CHANGED, this.redraw.bind(this)); $.subscribe(Events.FRAME_SIZE_CHANGED, this.redraw.bind(this));
$.subscribe(Events.ZOOM_CHANGED, this.redraw.bind(this));
$.subscribe(Events.PISKEL_RESET, this.redraw.bind(this));
this.redraw(); this.redraw();
}; };
@ -41,18 +39,7 @@
} }
} }
if (pskl.app.drawingController) { this.coordinatesContainer.innerHTML = this.getFrameSizeHTML_() + html;
var zoom = pskl.app.drawingController.compositeRenderer.getZoom().toFixed(2);
html += '<div class="drawing-zoom">x' + zoom + '</div>';
}
this.coordinatesContainer.innerHTML = this.getFrameSizeHTML_() + html + this.getCurrentFrameIndexHTML_();
};
ns.CursorCoordinatesController.prototype.getCurrentFrameIndexHTML_ = function () {
var currentFrameIndex = this.piskelController.getCurrentFrameIndex() + 1;
var frameCount = this.piskelController.getFrameCount();
return '<div class="frame-info">' + currentFrameIndex + '/' + frameCount + '</div>';
}; };
ns.CursorCoordinatesController.prototype.getFrameSizeHTML_ = function () { ns.CursorCoordinatesController.prototype.getFrameSizeHTML_ = function () {

View File

@ -2,12 +2,14 @@
var ns = $.namespace('pskl.controller'); var ns = $.namespace('pskl.controller');
ns.DrawingController = function (piskelController, container) { ns.DrawingController = function (piskelController, paletteController, container) {
/** /**
* @public * @public
*/ */
this.piskelController = piskelController; this.piskelController = piskelController;
this.paletteController = paletteController;
this.dragHandler = new ns.drawing.DragHandler(this); this.dragHandler = new ns.drawing.DragHandler(this);
/** /**
@ -22,7 +24,7 @@
var cfg = { var cfg = {
'zoom': this.calculateZoom_(), 'zoom': this.calculateZoom_(),
'supportGridRendering' : false, 'supportGridRendering' : true,
'height' : this.getContainerHeight_(), 'height' : this.getContainerHeight_(),
'width' : this.getContainerWidth_(), 'width' : this.getContainerWidth_(),
'xOffset' : 0, 'xOffset' : 0,
@ -30,10 +32,9 @@
}; };
this.overlayRenderer = new pskl.rendering.frame.CachedFrameRenderer(this.container, cfg, ['canvas-overlay']); this.overlayRenderer = new pskl.rendering.frame.CachedFrameRenderer(this.container, cfg, ['canvas-overlay']);
this.renderer = new pskl.rendering.frame.CachedFrameRenderer(this.container, cfg, ['drawing-canvas']);
this.onionSkinRenderer = pskl.rendering.OnionSkinRenderer.createInContainer(this.container, cfg, piskelController); this.onionSkinRenderer = pskl.rendering.OnionSkinRenderer.createInContainer(this.container, cfg, piskelController);
this.layersRenderer = new pskl.rendering.layer.LayersRenderer(this.container, cfg, piskelController); this.layersRenderer = new pskl.rendering.layer.LayersRenderer(this.container, cfg, piskelController);
cfg.supportGridRendering = true;
this.renderer = new pskl.rendering.frame.CachedFrameRenderer(this.container, cfg, ['drawing-canvas']);
this.compositeRenderer = new pskl.rendering.CompositeRenderer(); this.compositeRenderer = new pskl.rendering.CompositeRenderer();
this.compositeRenderer this.compositeRenderer
@ -51,12 +52,12 @@
ns.DrawingController.prototype.init = function () { ns.DrawingController.prototype.init = function () {
this.initMouseBehavior(); this.initMouseBehavior();
$.subscribe(Events.TOOL_SELECTED, (function(evt, toolBehavior) { $.subscribe(Events.TOOL_SELECTED, $.proxy(function(evt, toolBehavior) {
this.currentToolBehavior = toolBehavior; this.currentToolBehavior = toolBehavior;
this.overlayFrame.clear(); this.overlayFrame.clear();
}).bind(this)); }, this));
window.addEventListener('resize', this.startResizeTimer_.bind(this)); $(window).resize($.proxy(this.startResizeTimer_, this));
$.subscribe(Events.USER_SETTINGS_CHANGED, this.onUserSettingsChange_.bind(this)); $.subscribe(Events.USER_SETTINGS_CHANGED, this.onUserSettingsChange_.bind(this));
$.subscribe(Events.FRAME_SIZE_CHANGED, this.onFrameSizeChange_.bind(this)); $.subscribe(Events.FRAME_SIZE_CHANGED, this.onFrameSizeChange_.bind(this));
@ -65,10 +66,6 @@
pskl.app.shortcutService.registerShortcut(shortcuts.MISC.RESET_ZOOM, this.resetZoom_.bind(this)); pskl.app.shortcutService.registerShortcut(shortcuts.MISC.RESET_ZOOM, this.resetZoom_.bind(this));
pskl.app.shortcutService.registerShortcut(shortcuts.MISC.INCREASE_ZOOM, this.updateZoom_.bind(this, 1)); pskl.app.shortcutService.registerShortcut(shortcuts.MISC.INCREASE_ZOOM, this.updateZoom_.bind(this, 1));
pskl.app.shortcutService.registerShortcut(shortcuts.MISC.DECREASE_ZOOM, this.updateZoom_.bind(this, -1)); pskl.app.shortcutService.registerShortcut(shortcuts.MISC.DECREASE_ZOOM, this.updateZoom_.bind(this, -1));
pskl.app.shortcutService.registerShortcut(shortcuts.MISC.OFFSET_UP, this.updateOffset_.bind(this, 'up'));
pskl.app.shortcutService.registerShortcut(shortcuts.MISC.OFFSET_RIGHT, this.updateOffset_.bind(this, 'right'));
pskl.app.shortcutService.registerShortcut(shortcuts.MISC.OFFSET_DOWN, this.updateOffset_.bind(this, 'down'));
pskl.app.shortcutService.registerShortcut(shortcuts.MISC.OFFSET_LEFT, this.updateOffset_.bind(this, 'left'));
window.setTimeout(function () { window.setTimeout(function () {
this.afterWindowResize_(); this.afterWindowResize_();
@ -77,12 +74,13 @@
}; };
ns.DrawingController.prototype.initMouseBehavior = function() { ns.DrawingController.prototype.initMouseBehavior = function() {
this.container.addEventListener('mousedown', this.onMousedown_.bind(this)); var body = $('body');
this.container.mousedown($.proxy(this.onMousedown_, this));
if (pskl.utils.UserAgent.isChrome || pskl.utils.UserAgent.isIE11) { if (pskl.utils.UserAgent.isChrome || pskl.utils.UserAgent.isIE11) {
this.container.addEventListener('mousewheel', this.onMousewheel_.bind(this)); this.container.on('mousewheel', $.proxy(this.onMousewheel_, this));
} else { } else {
this.container.addEventListener('wheel', this.onMousewheel_.bind(this)); this.container.on('wheel', $.proxy(this.onMousewheel_, this));
} }
window.addEventListener('mouseup', this.onMouseup_.bind(this)); window.addEventListener('mouseup', this.onMouseup_.bind(this));
@ -93,20 +91,22 @@
window.addEventListener('touchend', this.onTouchend_.bind(this)); window.addEventListener('touchend', this.onTouchend_.bind(this));
// Deactivate right click: // Deactivate right click:
document.body.addEventListener('contextmenu', this.onCanvasContextMenu_.bind(this)); body.contextmenu(this.onCanvasContextMenu_);
}; };
ns.DrawingController.prototype.startResizeTimer_ = function () { ns.DrawingController.prototype.startResizeTimer_ = function () {
if (this.resizeTimer) { if (this.resizeTimer) {
window.clearInterval(this.resizeTimer); window.clearInterval(this.resizeTimer);
} }
this.resizeTimer = window.setTimeout(this.afterWindowResize_.bind(this), 200); this.resizeTimer = window.setTimeout($.proxy(this.afterWindowResize_, this), 200);
}; };
ns.DrawingController.prototype.afterWindowResize_ = function () { ns.DrawingController.prototype.afterWindowResize_ = function () {
var initialWidth = this.compositeRenderer.getDisplaySize().width; var initialWidth = this.compositeRenderer.getDisplaySize().width;
this.compositeRenderer.setDisplaySize(this.getContainerWidth_(), this.getContainerHeight_()); this.compositeRenderer.setDisplaySize(this.getContainerWidth_(), this.getContainerHeight_());
this.centerColumnWrapperHorizontally_();
var ratio = this.compositeRenderer.getDisplaySize().width / initialWidth; var ratio = this.compositeRenderer.getDisplaySize().width / initialWidth;
var newZoom = ratio * this.compositeRenderer.getZoom(); var newZoom = ratio * this.compositeRenderer.getZoom();
this.compositeRenderer.setZoom(newZoom); this.compositeRenderer.setZoom(newZoom);
@ -131,6 +131,7 @@
ns.DrawingController.prototype.onFrameSizeChange_ = function () { ns.DrawingController.prototype.onFrameSizeChange_ = function () {
this.compositeRenderer.setDisplaySize(this.getContainerWidth_(), this.getContainerHeight_()); this.compositeRenderer.setDisplaySize(this.getContainerWidth_(), this.getContainerHeight_());
this.centerColumnWrapperHorizontally_();
this.compositeRenderer.setZoom(this.calculateZoom_()); this.compositeRenderer.setZoom(this.calculateZoom_());
this.compositeRenderer.setOffset(0, 0); this.compositeRenderer.setOffset(0, 0);
$.publish(Events.ZOOM_CHANGED); $.publish(Events.ZOOM_CHANGED);
@ -164,9 +165,6 @@
if (event.button === Constants.MIDDLE_BUTTON) { if (event.button === Constants.MIDDLE_BUTTON) {
this.dragHandler.startDrag(event.clientX, event.clientY); this.dragHandler.startDrag(event.clientX, event.clientY);
} else if (event.altKey && !this.currentToolBehavior.supportsAlt()) {
this.currentToolBehavior.hideHighlightedPixel(this.overlayFrame);
this.isPickingColor = true;
} else { } else {
this.currentToolBehavior.hideHighlightedPixel(this.overlayFrame); this.currentToolBehavior.hideHighlightedPixel(this.overlayFrame);
$.publish(Events.TOOL_PRESSED); $.publish(Events.TOOL_PRESSED);
@ -214,8 +212,6 @@
if (this.isClicked) { if (this.isClicked) {
if (pskl.app.mouseStateService.isMiddleButtonPressed()) { if (pskl.app.mouseStateService.isMiddleButtonPressed()) {
this.dragHandler.updateDrag(x, y); this.dragHandler.updateDrag(x, y);
} else if (this.isPickingColor) {
// Nothing to do on mousemove when picking a color with ALT+click.
} else { } else {
$.publish(Events.MOUSE_EVENT, [event, this]); $.publish(Events.MOUSE_EVENT, [event, this]);
this.currentToolBehavior.moveToolAt( this.currentToolBehavior.moveToolAt(
@ -238,7 +234,8 @@
$.publish(Events.CURSOR_MOVED, [coords.x, coords.y]); $.publish(Events.CURSOR_MOVED, [coords.x, coords.y]);
}; };
ns.DrawingController.prototype.onMousewheel_ = function (evt) { ns.DrawingController.prototype.onMousewheel_ = function (jQueryEvent) {
var evt = jQueryEvent.originalEvent;
// Ratio between wheelDeltaY (mousewheel event) and deltaY (wheel event) is -40 // Ratio between wheelDeltaY (mousewheel event) and deltaY (wheel event) is -40
var delta; var delta;
if (pskl.utils.UserAgent.isIE11) { if (pskl.utils.UserAgent.isIE11) {
@ -262,29 +259,6 @@
this.updateZoom_(modifier, coords); this.updateZoom_(modifier, coords);
}; };
/**
* Update the current viewport offset of 1 pixel in the provided direction.
* Direction can be one of 'up', 'right', 'down', 'left'.
* Callback for the OFFSET_${DIR} shortcuts.
*/
ns.DrawingController.prototype.updateOffset_ = function (direction) {
var off = this.getOffset();
if (direction === 'up') {
off.y -= 1;
} else if (direction === 'right') {
off.x += 1;
} else if (direction === 'down') {
off.y += 1;
} else if (direction === 'left') {
off.x -= 1;
}
this.setOffset(
off.x,
off.y
);
};
/** /**
* Update the current zoom level by a given multiplier. * Update the current zoom level by a given multiplier.
* *
@ -322,75 +296,38 @@
* @private * @private
*/ */
ns.DrawingController.prototype.onMouseup_ = function (event) { ns.DrawingController.prototype.onMouseup_ = function (event) {
if (!this.isClicked) { var frame = this.piskelController.getCurrentFrame();
return;
}
var coords = this.getSpriteCoordinates(event.clientX, event.clientY); var coords = this.getSpriteCoordinates(event.clientX, event.clientY);
if (event.changedTouches && event.changedTouches[0]) { if (event.changedTouches && event.changedTouches[0]) {
coords = this.getSpriteCoordinates(event.changedTouches[0].clientX, event.changedTouches[0].clientY); coords = this.getSpriteCoordinates(event.changedTouches[0].clientX, event.changedTouches[0].clientY);
} }
if (this.isClicked) {
// A mouse button was clicked on the drawing canvas before this mouseup event,
// the user was probably drawing on the canvas.
// Note: The mousemove movement (and the mouseup) may end up outside
// of the drawing canvas.
// A mouse button was clicked on the drawing canvas before this mouseup event, this.isClicked = false;
// the user was probably drawing on the canvas.
// Note: The mousemove movement (and the mouseup) may end up outside
// of the drawing canvas.
this.isClicked = false; if (pskl.app.mouseStateService.isMiddleButtonPressed()) {
if (this.dragHandler.isDragging()) {
this.dragHandler.stopDrag();
} else if (frame.containsPixel(coords.x, coords.y)) {
$.publish(Events.SELECT_PRIMARY_COLOR, [frame.getPixel(coords.x, coords.y)]);
}
} else {
this.currentToolBehavior.releaseToolAt(
coords.x,
coords.y,
this.piskelController.getCurrentFrame(),
this.overlayFrame,
event
);
var isMiddleButton = pskl.app.mouseStateService.isMiddleButtonPressed(); $.publish(Events.TOOL_RELEASED);
var isMiddleClick = isMiddleButton && !this.dragHandler.isDragging(); }
var isMiddleDrag = isMiddleButton && this.dragHandler.isDragging(); $.publish(Events.MOUSE_EVENT, [event, this]);
if (this.isPickingColor || isMiddleClick) {
// Picking color after ALT+click or middle mouse button click.
this.pickColorAt_(coords);
this.isPickingColor = false;
// Flash the cursor to briefly show the colorpicker cursor.
this.flashColorPicker_();
} else if (isMiddleDrag) {
// Stop the drag handler after a middle button drag action.
this.dragHandler.stopDrag();
} else {
// Regular tool click, release the current tool.
this.currentToolBehavior.releaseToolAt(
coords.x,
coords.y,
this.piskelController.getCurrentFrame(),
this.overlayFrame,
event
);
$.publish(Events.TOOL_RELEASED);
} }
$.publish(Events.MOUSE_EVENT, [event, this]);
};
/**
* Send a COLOR selection event for the color contained at the provided coordinates.
* No-op if the coordinate is outside of the drawing canvas.
* @param {Object} coords {x: Number, y: Number}
*/
ns.DrawingController.prototype.pickColorAt_ = function (coords) {
var frame = this.piskelController.getCurrentFrame();
if (!frame.containsPixel(coords.x, coords.y)) {
return;
}
var color = pskl.utils.intToColor(frame.getPixel(coords.x, coords.y));
var isRightButton = pskl.app.mouseStateService.isRightButtonPressed();
var evt = isRightButton ? Events.SELECT_SECONDARY_COLOR : Events.SELECT_PRIMARY_COLOR;
$.publish(evt, [color]);
};
ns.DrawingController.prototype.flashColorPicker_ = function () {
document.body.classList.add('tool-colorpicker');
document.body.classList.remove(this.currentToolBehavior.toolId);
window.clearTimeout(this.flashColorPickerTimer);
this.flashColorPickerTimer = window.setTimeout(function () {
document.body.classList.remove('tool-colorpicker');
document.body.classList.add(this.currentToolBehavior.toolId);
}.bind(this), 200);
}; };
/** /**
@ -411,8 +348,7 @@
* @private * @private
*/ */
ns.DrawingController.prototype.onCanvasContextMenu_ = function (event) { ns.DrawingController.prototype.onCanvasContextMenu_ = function (event) {
// closest() not really available everywhere yet, just skip if missing. if ($(event.target).closest('#drawing-canvas-container').length) {
if (event.target.closest && event.target.closest('#drawing-canvas-container')) {
// Deactivate right click on drawing canvas only. // Deactivate right click on drawing canvas only.
event.preventDefault(); event.preventDefault();
event.stopPropagation(); event.stopPropagation();
@ -450,21 +386,17 @@
}; };
ns.DrawingController.prototype.getAvailableHeight_ = function () { ns.DrawingController.prototype.getAvailableHeight_ = function () {
return document.querySelector('#main-wrapper').getBoundingClientRect().height; return $('#main-wrapper').height();
};
ns.DrawingController.prototype.getSelectorWidth_ = function (selector) {
return document.querySelector(selector).getBoundingClientRect().width;
}; };
ns.DrawingController.prototype.getAvailableWidth_ = function () { ns.DrawingController.prototype.getAvailableWidth_ = function () {
var leftSectionWidth = this.getSelectorWidth_('.left-column'); var leftSectionWidth = $('.left-column').outerWidth(true);
var rightSectionWidth = this.getSelectorWidth_('.right-column'); var rightSectionWidth = $('.right-column').outerWidth(true);
var toolsContainerWidth = this.getSelectorWidth_('#tool-section'); var toolsContainerWidth = $('#tool-section').outerWidth(true);
var settingsContainerWidth = this.getSelectorWidth_('#application-action-section'); var settingsContainerWidth = $('#application-action-section').outerWidth(true);
var usedWidth = leftSectionWidth + rightSectionWidth + toolsContainerWidth + settingsContainerWidth; var usedWidth = leftSectionWidth + rightSectionWidth + toolsContainerWidth + settingsContainerWidth;
var availableWidth = this.getSelectorWidth_('#main-wrapper') - usedWidth; var availableWidth = $('#main-wrapper').width() - usedWidth;
var comfortMargin = 10; var comfortMargin = 10;
return availableWidth - comfortMargin; return availableWidth - comfortMargin;
@ -478,6 +410,17 @@
return this.getAvailableWidth_(); return this.getAvailableWidth_();
}; };
/**
* @private
*/
ns.DrawingController.prototype.centerColumnWrapperHorizontally_ = function() {
var containerHeight = this.getContainerHeight_();
var verticalGapInPixel = Math.floor(($('#main-wrapper').height() - containerHeight) / 2);
$('#column-wrapper').css({
'top': verticalGapInPixel + 'px'
});
};
ns.DrawingController.prototype.getRenderer = function () { ns.DrawingController.prototype.getRenderer = function () {
return this.compositeRenderer; return this.compositeRenderer;
}; };

View File

@ -5,46 +5,35 @@
SELECT : 'select', SELECT : 'select',
CLONE : 'clone', CLONE : 'clone',
DELETE : 'delete', DELETE : 'delete',
NEW_FRAME : 'newframe', NEW_FRAME : 'newframe'
TOGGLE: 'toggle'
}; };
ns.FramesListController = function (piskelController, container) { ns.FramesListController = function (piskelController, container) {
this.piskelController = piskelController; this.piskelController = piskelController;
this.container = container; this.container = container;
this.previewList = container.querySelector('#preview-list');
this.refreshZoom_(); this.refreshZoom_();
this.redrawFlag = true; this.redrawFlag = true;
this.regenerateDomFlag = true;
this.justDropped = false;
this.cachedFrameProcessor = new pskl.model.frame.CachedFrameProcessor(); this.cachedFrameProcessor = new pskl.model.frame.CachedFrameProcessor();
this.cachedFrameProcessor.setFrameProcessor(this.frameToPreviewCanvas_.bind(this)); this.cachedFrameProcessor.setFrameProcessor(this.frameToPreviewCanvas_.bind(this));
this.cachedFrameProcessor.setOutputCloner(this.clonePreviewCanvas_.bind(this)); this.cachedFrameProcessor.setOutputCloner(this.clonePreviewCanvas_.bind(this));
this.initDragndropBehavior_();
}; };
ns.FramesListController.prototype.init = function() { ns.FramesListController.prototype.init = function() {
$.subscribe(Events.TOOL_RELEASED, this.flagForRedraw_.bind(this)); $.subscribe(Events.TOOL_RELEASED, this.flagForRedraw_.bind(this));
$.subscribe(Events.PISKEL_RESET, this.flagForRedraw_.bind(this, true)); $.subscribe(Events.PISKEL_RESET, this.flagForRedraw_.bind(this));
$.subscribe(Events.USER_SETTINGS_CHANGED, this.flagForRedraw_.bind(this)); $.subscribe(Events.USER_SETTINGS_CHANGED, this.flagForRedraw_.bind(this));
$.subscribe(Events.PISKEL_RESET, this.refreshZoom_.bind(this)); $.subscribe(Events.PISKEL_RESET, this.refreshZoom_.bind(this));
this.previewListScroller = document.querySelector('#preview-list-scroller'); $('#preview-list-scroller').scroll(this.updateScrollerOverflows.bind(this));
this.previewListScroller.addEventListener('scroll', this.updateScrollerOverflows.bind(this)); this.container.get(0).addEventListener('click', this.onContainerClick_.bind(this));
this.container.addEventListener('click', this.onContainerClick_.bind(this));
this.updateScrollerOverflows(); this.updateScrollerOverflows();
}; };
ns.FramesListController.prototype.flagForRedraw_ = function (regenerateDom) { ns.FramesListController.prototype.flagForRedraw_ = function () {
this.redrawFlag = true; this.redrawFlag = true;
if (regenerateDom) {
this.regenerateDomFlag = true;
}
}; };
ns.FramesListController.prototype.refreshZoom_ = function () { ns.FramesListController.prototype.refreshZoom_ = function () {
@ -53,25 +42,17 @@
ns.FramesListController.prototype.render = function () { ns.FramesListController.prototype.render = function () {
if (this.redrawFlag) { if (this.redrawFlag) {
if (this.regenerateDomFlag) { this.createPreviews_();
this.tiles = [];
this.addFrameTile = null;
this.createPreviews_();
this.regenerateDomFlag = false;
}
this.updatePreviews_();
this.redrawFlag = false; this.redrawFlag = false;
} }
}; };
ns.FramesListController.prototype.updateScrollerOverflows = function () { ns.FramesListController.prototype.updateScrollerOverflows = function () {
var scroller = this.previewListScroller; var scroller = $('#preview-list-scroller');
var scrollerHeight = scroller.offsetHeight; var scrollerHeight = scroller.height();
var scrollTop = scroller.scrollTop; var scrollTop = scroller.scrollTop();
var scrollerContentHeight = this.previewList.offsetHeight; var scrollerContentHeight = $('#preview-list').height();
var treshold = this.container.querySelector('.top-overflow').offsetHeight; var treshold = $('.top-overflow').height();
var overflowTop = false; var overflowTop = false;
var overflowBottom = false; var overflowBottom = false;
@ -84,8 +65,9 @@
overflowBottom = true; overflowBottom = true;
} }
} }
this.container.classList.toggle('top-overflow-visible', overflowTop); var wrapper = $('#preview-list-wrapper');
this.container.classList.toggle('bottom-overflow-visible', overflowBottom); wrapper.toggleClass('top-overflow-visible', overflowTop);
wrapper.toggleClass('bottom-overflow-visible', overflowBottom);
}; };
ns.FramesListController.prototype.onContainerClick_ = function (event) { ns.FramesListController.prototype.onContainerClick_ = function (event) {
@ -98,92 +80,27 @@
if (action === ACTION.CLONE) { if (action === ACTION.CLONE) {
this.piskelController.duplicateFrameAt(index); this.piskelController.duplicateFrameAt(index);
var clonedTile = this.createPreviewTile_(index + 1);
this.previewList.insertBefore(clonedTile, this.tiles[index].nextSibling);
this.tiles.splice(index, 0, clonedTile);
this.updateScrollerOverflows(); this.updateScrollerOverflows();
} else if (action === ACTION.DELETE) { } else if (action === ACTION.DELETE) {
this.piskelController.removeFrameAt(index); this.piskelController.removeFrameAt(index);
this.previewList.removeChild(this.tiles[index]);
this.tiles.splice(index, 1);
this.updateScrollerOverflows(); this.updateScrollerOverflows();
} else if (action === ACTION.SELECT && !this.justDropped) { } else if (action === ACTION.SELECT) {
this.piskelController.setCurrentFrameIndex(index); this.piskelController.setCurrentFrameIndex(index);
} else if (action === ACTION.NEW_FRAME) { } else if (action === ACTION.NEW_FRAME) {
this.piskelController.addFrame(); this.piskelController.addFrame();
var newtile = this.createPreviewTile_(this.tiles.length);
this.tiles.push(newtile);
this.previewList.insertBefore(newtile, this.addFrameTile);
this.updateScrollerOverflows(); this.updateScrollerOverflows();
} else if (action == ACTION.TOGGLE) {
this.piskelController.toggleFrameVisibilityAt(index);
} }
this.flagForRedraw_();
};
ns.FramesListController.prototype.updatePreviews_ = function () {
var i;
var length;
for (i = 0, length = this.tiles.length; i < length; i++) {
// Remove selected class
this.tiles[i].classList.remove('selected');
// Remove toggle class
this.tiles[i].querySelector('.tile-count').classList.remove('toggled');
// Update tile numbers
this.tiles[i].setAttribute('data-tile-number', i);
this.tiles[i].querySelector('.tile-count').innerHTML = (i + 1);
// Update visibility
if (this.piskelController.hasVisibleFrameAt(i)) {
this.tiles[i].querySelector('.tile-count').classList.add('toggled');
}
// Check if any tile is updated
var hash = this.piskelController.getCurrentLayer().getFrameAt(i).getHash();
if (this.tiles[i].getAttribute('data-tile-hash') !== hash) {
if (this.tiles[i].querySelector('canvas')) {
this.tiles[i].querySelector('.canvas-container').replaceChild(
this.getCanvasForFrame(this.piskelController.getCurrentLayer().getFrameAt(i)),
this.tiles[i].querySelector('canvas')
);
} else {
this.tiles[i].querySelector('.canvas-container').appendChild(
this.getCanvasForFrame(this.piskelController.getCurrentLayer().getFrameAt(i))
);
}
}
}
// Hide/Show buttons if needed
var buttons = this.container.querySelectorAll('.delete-frame-action, .dnd-action');
var display = (this.piskelController.getFrameCount() > 1) ? 'block' : 'none';
for (i = 0, length = buttons.length; i < length; i++) {
buttons[i].style.display = display;
}
// Add selected class
this.tiles[this.piskelController.getCurrentFrameIndex()].classList.add('selected');
}; };
ns.FramesListController.prototype.createPreviews_ = function () { ns.FramesListController.prototype.createPreviews_ = function () {
this.previewList.innerHTML = ''; this.container.html('');
// Manually remove tooltips since mouseout events were shortcut by the DOM refresh: // Manually remove tooltips since mouseout events were shortcut by the DOM refresh:
var tooltips = document.querySelectorAll('.tooltip'); $('.tooltip').remove();
Array.prototype.forEach.call(tooltips, function (tooltip) {
tooltip.parentNode.removeChild(tooltip);
});
var frameCount = this.piskelController.getFrameCount(); var frameCount = this.piskelController.getFrameCount();
for (var i = 0 ; i < frameCount ; i++) { for (var i = 0 ; i < frameCount ; i++) {
var tile = this.createPreviewTile_(i); this.container.append(this.createPreviewTile_(i));
this.previewList.appendChild(tile);
this.tiles[i] = tile;
} }
// Append 'new empty frame' button // Append 'new empty frame' button
var newFrameButton = document.createElement('div'); var newFrameButton = document.createElement('div');
@ -192,9 +109,12 @@
newFrameButton.setAttribute('data-tile-action', ACTION.NEW_FRAME); newFrameButton.setAttribute('data-tile-action', ACTION.NEW_FRAME);
newFrameButton.innerHTML = '<div class="add-frame-action-icon icon-frame-plus-white">' + newFrameButton.innerHTML = '<div class="add-frame-action-icon icon-frame-plus-white">' +
'</div><div class="label">Add new frame</div>'; '</div><div class="label">Add new frame</div>';
this.previewList.appendChild(newFrameButton); this.container.append(newFrameButton);
this.addFrameTile = newFrameButton;
var needDragndropBehavior = (frameCount > 1);
if (needDragndropBehavior) {
this.initDragndropBehavior_();
}
this.updateScrollerOverflows(); this.updateScrollerOverflows();
}; };
@ -202,54 +122,37 @@
* @private * @private
*/ */
ns.FramesListController.prototype.initDragndropBehavior_ = function () { ns.FramesListController.prototype.initDragndropBehavior_ = function () {
$(this.previewList).sortable({
$('#preview-list').sortable({
placeholder: 'preview-tile preview-tile-drop-proxy', placeholder: 'preview-tile preview-tile-drop-proxy',
update: this.onUpdate_.bind(this), update: $.proxy(this.onUpdate_, this),
stop: this.onSortableStop_.bind(this),
items: '.preview-tile', items: '.preview-tile',
axis: 'y', axis: 'y',
tolerance: 'pointer' tolerance: 'pointer'
}); });
$(this.previewList).disableSelection(); $('#preview-list').disableSelection();
}; };
/** /**
* @private * @private
*/ */
ns.FramesListController.prototype.onUpdate_ = function (event, ui) { ns.FramesListController.prototype.onUpdate_ = function (event, ui) {
var movedItem = ui.item.get(0); var originFrameId = parseInt(ui.item.data('tile-number'), 10);
var originFrameId = parseInt(movedItem.dataset.tileNumber, 10); var targetInsertionId = $('.preview-tile').index(ui.item);
var tiles = document.querySelectorAll('.preview-tile');
var targetInsertionId = Array.prototype.indexOf.call(tiles, movedItem);
this.piskelController.moveFrame(originFrameId, targetInsertionId); this.piskelController.moveFrame(originFrameId, targetInsertionId);
this.piskelController.setCurrentFrameIndex(targetInsertionId); this.piskelController.setCurrentFrameIndex(targetInsertionId);
var tile = this.tiles.splice(originFrameId, 1)[0];
this.tiles.splice(targetInsertionId, 0, tile);
this.flagForRedraw_();
};
/**
* @private
*/
ns.FramesListController.prototype.onSortableStop_ = function (event, ui) {
this.justDropped = true;
this.resizeTimer = window.setTimeout((function() {
this.justDropped = false;
}).bind(this), 200);
}; };
/** /**
* @private * @private
* TODO(vincz): clean this giant rendering function & remove listeners.
*/ */
ns.FramesListController.prototype.createPreviewTile_ = function(tileNumber) { ns.FramesListController.prototype.createPreviewTile_ = function(tileNumber) {
var currentFrame = this.piskelController.getCurrentLayer().getFrameAt(tileNumber); var currentFrame = this.piskelController.getCurrentLayer().getFrameAt(tileNumber);
var previewTileRoot = document.createElement('li'); var previewTileRoot = document.createElement('li');
previewTileRoot.setAttribute('data-tile-number', tileNumber); previewTileRoot.setAttribute('data-tile-number', tileNumber);
previewTileRoot.setAttribute('data-tile-hash', currentFrame.getHash());
previewTileRoot.setAttribute('data-tile-action', ACTION.SELECT); previewTileRoot.setAttribute('data-tile-action', ACTION.SELECT);
previewTileRoot.classList.add('preview-tile'); previewTileRoot.classList.add('preview-tile');
if (this.piskelController.getCurrentFrame() == currentFrame) { if (this.piskelController.getCurrentFrame() == currentFrame) {
@ -268,14 +171,10 @@
canvasContainer.style.marginLeft = verticalMargin + 'px'; canvasContainer.style.marginLeft = verticalMargin + 'px';
canvasContainer.style.marginRight = verticalMargin + 'px'; canvasContainer.style.marginRight = verticalMargin + 'px';
// Add canvas background and canvas
var canvasBackground = document.createElement('div'); var canvasBackground = document.createElement('div');
canvasBackground.className = 'canvas-background'; canvasBackground.className = 'canvas-background';
canvasContainer.appendChild(canvasBackground); canvasContainer.appendChild(canvasBackground);
canvasContainer.appendChild(this.getCanvasForFrame(currentFrame));
previewTileRoot.appendChild(canvasContainer);
// Add clone button
var cloneFrameButton = document.createElement('button'); var cloneFrameButton = document.createElement('button');
cloneFrameButton.setAttribute('rel', 'tooltip'); cloneFrameButton.setAttribute('rel', 'tooltip');
cloneFrameButton.setAttribute('data-placement', 'right'); cloneFrameButton.setAttribute('data-placement', 'right');
@ -285,28 +184,27 @@
cloneFrameButton.className = 'tile-overlay duplicate-frame-action icon-frame-duplicate-white'; cloneFrameButton.className = 'tile-overlay duplicate-frame-action icon-frame-duplicate-white';
previewTileRoot.appendChild(cloneFrameButton); previewTileRoot.appendChild(cloneFrameButton);
// Add delete button canvasContainer.appendChild(this.getCanvasForFrame(currentFrame));
var deleteButton = document.createElement('button'); previewTileRoot.appendChild(canvasContainer);
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 icon-frame-recyclebin-white';
previewTileRoot.appendChild(deleteButton);
// Add 'dragndrop handle'. if (tileNumber > 0 || this.piskelController.getFrameCount() > 1) {
var dndHandle = document.createElement('div'); // Add 'remove frame' button.
dndHandle.className = 'tile-overlay dnd-action icon-frame-dragndrop-white' ; var deleteButton = document.createElement('button');
previewTileRoot.appendChild(dndHandle); 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 icon-frame-recyclebin-white';
previewTileRoot.appendChild(deleteButton);
// Add tile count // Add 'dragndrop handle'.
var tileCount = document.createElement('button'); var dndHandle = document.createElement('div');
tileCount.setAttribute('rel', 'tooltip'); dndHandle.className = 'tile-overlay dnd-action icon-frame-dragndrop-white' ;
tileCount.setAttribute('title', 'Toggle for preview'); previewTileRoot.appendChild(dndHandle);
tileCount.setAttribute('data-tile-number', tileNumber); }
tileCount.setAttribute('data-tile-action', ACTION.TOGGLE); var tileCount = document.createElement('div');
tileCount.className = 'tile-overlay tile-count toggle-frame-action'; tileCount.className = 'tile-overlay tile-count';
tileCount.innerHTML = tileNumber + 1; tileCount.innerHTML = tileNumber + 1;
previewTileRoot.appendChild(tileCount); previewTileRoot.appendChild(tileCount);

View File

@ -31,7 +31,7 @@
} }
if (this.piskelName_) { if (this.piskelName_) {
this.piskelName_.textContent = name; this.piskelName_.innerHTML = name;
} }
} catch (e) { } catch (e) {
console.warn('Could not update header : ' + e.message); console.warn('Could not update header : ' + e.message);

View File

@ -1,18 +1,15 @@
(function () { (function () {
var ns = $.namespace('pskl.controller'); var ns = $.namespace('pskl.controller');
var TOGGLE_LAYER_SHORTCUT = 'alt+L';
ns.LayersListController = function (piskelController) { ns.LayersListController = function (piskelController) {
this.piskelController = piskelController; this.piskelController = piskelController;
this.layerPreviewShortcut = pskl.service.keyboard.Shortcuts.MISC.LAYER_PREVIEW; this.layerPreviewShortcut = pskl.service.keyboard.Shortcuts.MISC.LAYER_PREVIEW ;
this.startRenamingCurrentLayer_ = this.startRenamingCurrentLayer_.bind(this);
this.onRenameInput_ = this.onRenameInput_.bind(this);
}; };
ns.LayersListController.prototype.init = function () { ns.LayersListController.prototype.init = function () {
this.isRenaming = false;
this.layerItemTemplate_ = pskl.utils.Template.get('layer-item-template'); this.layerItemTemplate_ = pskl.utils.Template.get('layer-item-template');
this.layerNameInputTemplate_ = pskl.utils.Template.get('layer-name-input-template');
this.rootEl = document.querySelector('.layers-list-container'); this.rootEl = document.querySelector('.layers-list-container');
this.layersListEl = document.querySelector('.layers-list'); this.layersListEl = document.querySelector('.layers-list');
this.toggleLayerPreviewEl = document.querySelector('.layers-toggle-preview'); this.toggleLayerPreviewEl = document.querySelector('.layers-toggle-preview');
@ -20,55 +17,28 @@
this.rootEl.addEventListener('click', this.onClick_.bind(this)); this.rootEl.addEventListener('click', this.onClick_.bind(this));
this.toggleLayerPreviewEl.addEventListener('click', this.toggleLayerPreview_.bind(this)); this.toggleLayerPreviewEl.addEventListener('click', this.toggleLayerPreview_.bind(this));
this.createButtonTooltips_();
this.initToggleLayerPreview_(); this.initToggleLayerPreview_();
this.renderLayerList_(); this.renderLayerList_();
this.updateToggleLayerPreview_(); this.updateToggleLayerPreview_();
$.subscribe(Events.PISKEL_RESET, this.renderLayerList_.bind(this)); $.subscribe(Events.PISKEL_RESET, this.renderLayerList_.bind(this));
$.subscribe(Events.USER_SETTINGS_CHANGED, this.onUserSettingsChange_.bind(this)); $.subscribe(Events.USER_SETTINGS_CHANGED, $.proxy(this.onUserSettingsChange_, this));
}; };
ns.LayersListController.prototype.renderLayerList_ = function () { ns.LayersListController.prototype.renderLayerList_ = function () {
// Backup scroll before refresh.
var scrollTop = this.layersListEl.scrollTop;
this.layersListEl.innerHTML = ''; this.layersListEl.innerHTML = '';
var layers = this.piskelController.getLayers(); var layers = this.piskelController.getLayers();
layers.forEach(this.addLayerItem.bind(this)); layers.forEach(this.addLayerItem.bind(this));
this.updateButtonStatus_(); this.updateButtonStatus_();
// Restore scroll
this.layersListEl.scrollTop = scrollTop;
// Ensure the currently the selected layer is visible. // Ensure the currently the selected layer is visible.
var currentLayerEl = this.layersListEl.querySelector('.current-layer-item'); var currentLayerEl = this.layersListEl.querySelector('.current-layer-item');
if (currentLayerEl) { if (currentLayerEl) {
currentLayerEl.scrollIntoViewIfNeeded(false); currentLayerEl.scrollIntoView();
} }
}; };
ns.LayersListController.prototype.createButtonTooltips_ = function () {
var addTooltip = pskl.utils.TooltipFormatter.format('Create a layer', null, [
{key : 'shift', description : 'Clone current layer'}
]);
var addButton = this.rootEl.querySelector('[data-action="add"]');
addButton.setAttribute('title', addTooltip);
var moveDownTooltip = pskl.utils.TooltipFormatter.format('Move layer down', null, [
{key : 'shift', description : 'Move to the bottom'}
]);
var moveDownButton = this.rootEl.querySelector('[data-action="down"]');
moveDownButton.setAttribute('title', moveDownTooltip);
var moveUpTooltip = pskl.utils.TooltipFormatter.format('Move layer up', null, [
{key : 'shift', description : 'Move to the top'}
]);
var moveUpButton = this.rootEl.querySelector('[data-action="up"]');
moveUpButton.setAttribute('title', moveUpTooltip);
};
ns.LayersListController.prototype.initToggleLayerPreview_ = function () { ns.LayersListController.prototype.initToggleLayerPreview_ = function () {
var descriptors = [{description : 'Opacity defined in PREFERENCES'}]; var descriptors = [{description : 'Opacity defined in PREFERENCES'}];
var helpText = 'Preview all layers'; var helpText = 'Preview all layers';
@ -80,6 +50,7 @@
ns.LayersListController.prototype.updateButtonStatus_ = function () { ns.LayersListController.prototype.updateButtonStatus_ = function () {
var layers = this.piskelController.getLayers(); var layers = this.piskelController.getLayers();
var currentLayer = this.piskelController.getCurrentLayer();
var index = this.piskelController.getCurrentLayerIndex(); var index = this.piskelController.getCurrentLayerIndex();
var isLast = index === 0; var isLast = index === 0;
@ -120,62 +91,24 @@
ns.LayersListController.prototype.addLayerItem = function (layer, index) { ns.LayersListController.prototype.addLayerItem = function (layer, index) {
var isSelected = this.piskelController.getCurrentLayer() === layer; var isSelected = this.piskelController.getCurrentLayer() === layer;
var isRenaming = isSelected && this.isRenaming;
var layerItemHtml = pskl.utils.Template.replace(this.layerItemTemplate_, { var layerItemHtml = pskl.utils.Template.replace(this.layerItemTemplate_, {
'layername' : layer.getName(), 'layername' : layer.getName(),
'layerindex' : index, 'layerindex' : index,
'isselected:current-layer-item' : isSelected, 'isselected:current-layer-item' : isSelected,
'opacity' : layer.getOpacity() 'opacity': layer.getOpacity()
}); });
var layerItem = pskl.utils.Template.createFromHTML(layerItemHtml); var layerItem = pskl.utils.Template.createFromHTML(layerItemHtml);
this.layersListEl.insertBefore(layerItem, this.layersListEl.firstChild); this.layersListEl.insertBefore(layerItem, this.layersListEl.firstChild);
if (layerItem.offsetWidth < layerItem.scrollWidth) {
var layerNameEl = layerItem.querySelector('.layer-name');
layerNameEl.classList.add('overflowing-name');
layerNameEl.setAttribute('title', layer.getName());
layerNameEl.setAttribute('rel', 'tooltip');
}
if (isSelected) {
layerItem.removeEventListener('dblclick', this.startRenamingCurrentLayer_);
layerItem.addEventListener('dblclick', this.startRenamingCurrentLayer_);
}
if (isRenaming) {
var layerNameInputHtml = pskl.utils.Template.replace(this.layerNameInputTemplate_, {
'layername' : layer.getName()
});
var layerNameInput = pskl.utils.Template.createFromHTML(layerNameInputHtml);
var layerNameEl = layerItem.querySelector('.layer-name');
layerItem.replaceChild(layerNameInput, layerNameEl);
layerNameInput.removeEventListener('blur', this.onRenameInput_);
layerNameInput.removeEventListener('keydown', this.onRenameInput_);
layerNameInput.addEventListener('blur', this.onRenameInput_);
layerNameInput.addEventListener('keydown', this.onRenameInput_);
layerNameInput.focus();
layerNameInput.select();
}
var opacity = layer.getOpacity();
if (opacity == 1) {
layerItem.querySelector('.layer-item-opacity').style.color = '#ffd700';
} else if (opacity == 0) {
layerItem.querySelector('.layer-item-opacity').style.color = '#969696';
} else {
layerItem.querySelector('.layer-item-opacity').style.color = '#ffffff';
}
}; };
ns.LayersListController.prototype.onClick_ = function (evt) { ns.LayersListController.prototype.onClick_ = function (evt) {
var el = evt.target || evt.srcElement; var el = evt.target || evt.srcElement;
var index; var index;
if (el.classList.contains('button')) { if (el.classList.contains('button')) {
this.onButtonClick_(el, evt); this.onButtonClick_(el);
} else if (el.classList.contains('layer-name')) { } else if (el.classList.contains('layer-item')) {
var currentIndex = this.piskelController.getCurrentLayerIndex(); index = el.dataset.layerIndex;
index = pskl.utils.Dom.getData(el, 'layerIndex'); this.piskelController.setCurrentLayerIndex(parseInt(index, 10));
if (index != currentIndex) {
var currentItem = el.parentElement.parentElement.querySelector('.current-layer-item');
currentItem.removeEventListener('dblclick', this.startRenamingCurrentLayer_);
this.piskelController.setCurrentLayerIndex(parseInt(index, 10));
}
} else if (el.classList.contains('layer-item-opacity')) { } else if (el.classList.contains('layer-item-opacity')) {
index = pskl.utils.Dom.getData(el, 'layerIndex'); index = pskl.utils.Dom.getData(el, 'layerIndex');
var layer = this.piskelController.getLayerAt(parseInt(index, 10)); var layer = this.piskelController.getLayerAt(parseInt(index, 10));
@ -184,29 +117,14 @@
} }
}; };
ns.LayersListController.prototype.startRenamingCurrentLayer_ = function () { ns.LayersListController.prototype.renameCurrentLayer_ = function () {
this.isRenaming = true; var layer = this.piskelController.getCurrentLayer();
this.renderLayerList_(); var name = window.prompt('Please enter the layer name', layer.getName());
}; if (name) {
ns.LayersListController.prototype.onRenameInput_ = function (evt) {
var el = evt.target || evt.srcElement;
if (evt.key === 'Enter') {
this.finishRenamingCurrentLayer_(el, el.value);
} else if (!evt.key || evt.key === 'Escape') {
this.finishRenamingCurrentLayer_(el);
}
};
ns.LayersListController.prototype.finishRenamingCurrentLayer_ = function (input, newName) {
if (newName) {
var index = this.piskelController.getCurrentLayerIndex(); var index = this.piskelController.getCurrentLayerIndex();
this.piskelController.renameLayerAt(index, newName); this.piskelController.renameLayerAt(index, name);
this.renderLayerList_();
} }
input.removeEventListener('blur', this.onRenameInput_);
input.removeEventListener('keydown', this.onRenameInput_);
this.isRenaming = false;
this.renderLayerList_();
}; };
ns.LayersListController.prototype.mergeDownCurrentLayer_ = function () { ns.LayersListController.prototype.mergeDownCurrentLayer_ = function () {
@ -215,24 +133,20 @@
this.renderLayerList_(); this.renderLayerList_();
}; };
ns.LayersListController.prototype.onButtonClick_ = function (button, evt) { ns.LayersListController.prototype.onButtonClick_ = function (button) {
var action = button.getAttribute('data-action'); var action = button.getAttribute('data-action');
if (action == 'up') { if (action == 'up') {
this.piskelController.moveLayerUp(evt.shiftKey); this.piskelController.moveLayerUp();
} else if (action == 'down') { } else if (action == 'down') {
this.piskelController.moveLayerDown(evt.shiftKey); this.piskelController.moveLayerDown();
} else if (action == 'add') { } else if (action == 'add') {
if (evt.shiftKey) { this.piskelController.createLayer();
this.piskelController.duplicateCurrentLayer();
} else {
this.piskelController.createLayer();
}
} else if (action == 'delete') { } else if (action == 'delete') {
this.piskelController.removeCurrentLayer(); this.piskelController.removeCurrentLayer();
} else if (action == 'merge') { } else if (action == 'merge') {
this.mergeDownCurrentLayer_(); this.mergeDownCurrentLayer_();
} else if (action == 'edit') { } else if (action == 'edit') {
this.startRenamingCurrentLayer_(); this.renameCurrentLayer_();
} }
}; };

View File

@ -16,14 +16,14 @@
this.minimapEl = document.createElement('DIV'); this.minimapEl = document.createElement('DIV');
this.minimapEl.className = 'minimap-crop-frame'; this.minimapEl.className = 'minimap-crop-frame';
this.minimapEl.style.display = 'none'; this.minimapEl.style.display = 'none';
this.container.appendChild(this.minimapEl); $(this.container).append(this.minimapEl);
// Init mouse events // Init mouse events
this.container.addEventListener('mousedown', this.onMinimapMousedown_.bind(this)); $(this.container).mousedown(this.onMinimapMousedown_.bind(this));
document.body.addEventListener('mousemove', this.onMinimapMousemove_.bind(this)); $('body').mousemove(this.onMinimapMousemove_.bind(this));
document.body.addEventListener('mouseup', this.onMinimapMouseup_.bind(this)); $('body').mouseup(this.onMinimapMouseup_.bind(this));
$.subscribe(Events.ZOOM_CHANGED, this.renderMinimap_.bind(this)); $.subscribe(Events.ZOOM_CHANGED, $.proxy(this.renderMinimap_, this));
}; };
ns.MinimapController.prototype.renderMinimap_ = function () { ns.MinimapController.prototype.renderMinimap_ = function () {
@ -40,9 +40,8 @@
var minimapSize = this.getMinimapSize_(); var minimapSize = this.getMinimapSize_();
var previewSize = this.getPreviewSize_(); var previewSize = this.getPreviewSize_();
var containerRect = this.container.getBoundingClientRect(); var containerHeight = this.container.height();
var containerHeight = containerRect.height; var containerWidth = this.container.width();
var containerWidth = containerRect.width;
// offset(x, y) in frame pixels // offset(x, y) in frame pixels
var offset = this.drawingController.getRenderer().getOffset(); var offset = this.drawingController.getRenderer().getOffset();
@ -61,7 +60,7 @@
this.minimapEl.style.display = 'block'; this.minimapEl.style.display = 'block';
this.minimapEl.style.width = Math.min(minimapSize.width, containerWidth) + 'px'; this.minimapEl.style.width = Math.min(minimapSize.width, containerWidth) + 'px';
this.minimapEl.style.height = Math.min(minimapSize.height, containerHeight) + 'px'; this.minimapEl.style.height = Math.min(minimapSize.height, containerHeight) + 'px';
this.minimapEl.style.left = (Math.max(0, left) + Constants.RIGHT_COLUMN_PADDING_LEFT) + 'px'; this.minimapEl.style.left = Math.max(0, left) + 'px';
this.minimapEl.style.top = Math.max(0, top) + 'px'; this.minimapEl.style.top = Math.max(0, top) + 'px';
this.isVisible = true; this.isVisible = true;

View File

@ -7,8 +7,8 @@
* @public * @public
*/ */
ns.NotificationController.prototype.init = function() { ns.NotificationController.prototype.init = function() {
$.subscribe(Events.SHOW_NOTIFICATION, this.displayMessage_.bind(this)); $.subscribe(Events.SHOW_NOTIFICATION, $.proxy(this.displayMessage_, this));
$.subscribe(Events.HIDE_NOTIFICATION, this.removeMessage_.bind(this)); $.subscribe(Events.HIDE_NOTIFICATION, $.proxy(this.removeMessage_, this));
}; };
/** /**
@ -35,9 +35,9 @@
* @private * @private
*/ */
ns.NotificationController.prototype.removeMessage_ = function (evt) { ns.NotificationController.prototype.removeMessage_ = function (evt) {
var message = document.querySelector('#user-message'); var message = $('#user-message');
if (message) { if (message.length) {
message.parentNode.removeChild(message); message.remove();
} }
}; };
})(); })();

View File

@ -1,10 +1,6 @@
(function () { (function () {
var ns = $.namespace('pskl.controller'); var ns = $.namespace('pskl.controller');
/**
* The PaletteController is responsible for handling the two color picker
* widgets found in the left column, below the tools.
*/
ns.PaletteController = function () {}; ns.PaletteController = function () {};
/** /**
@ -35,24 +31,24 @@
// Initialize colorpickers: // Initialize colorpickers:
var colorPicker = $('#color-picker'); var colorPicker = $('#color-picker');
colorPicker.spectrum($.extend({color: Constants.DEFAULT_PEN_COLOR}, spectrumCfg)); colorPicker.spectrum($.extend({color: Constants.DEFAULT_PEN_COLOR}, spectrumCfg));
colorPicker.change({isPrimary : true}, this.onPickerChange_.bind(this)); colorPicker.change({isPrimary : true}, $.proxy(this.onPickerChange_, this));
this.setTitleOnPicker_(Constants.DEFAULT_PEN_COLOR, colorPicker.get(0)); this.setTitleOnPicker_(Constants.DEFAULT_PEN_COLOR, colorPicker);
var secondaryColorPicker = $('#secondary-color-picker'); var secondaryColorPicker = $('#secondary-color-picker');
secondaryColorPicker.spectrum($.extend({color: Constants.TRANSPARENT_COLOR}, spectrumCfg)); secondaryColorPicker.spectrum($.extend({color: Constants.TRANSPARENT_COLOR}, spectrumCfg));
secondaryColorPicker.change({isPrimary : false}, this.onPickerChange_.bind(this)); secondaryColorPicker.change({isPrimary : false}, $.proxy(this.onPickerChange_, this));
this.setTitleOnPicker_(Constants.TRANSPARENT_COLOR, secondaryColorPicker.get(0)); this.setTitleOnPicker_(Constants.TRANSPARENT_COLOR, secondaryColorPicker);
var swapColorsIcon = document.querySelector('.swap-colors-button'); var swapColorsIcon = $('.swap-colors-button');
swapColorsIcon.addEventListener('click', this.swapColors.bind(this)); swapColorsIcon.click(this.swapColors.bind(this));
}; };
/** /**
* @private * @private
*/ */
ns.PaletteController.prototype.onPickerChange_ = function(evt) { ns.PaletteController.prototype.onPickerChange_ = function(evt, isPrimary) {
var inputPicker = evt.target; var inputPicker = $(evt.target);
var color = inputPicker.value; var color = inputPicker.val();
if (color != Constants.TRANSPARENT_COLOR) { if (color != Constants.TRANSPARENT_COLOR) {
// Unless the color is TRANSPARENT_COLOR, format it to hexstring, as // Unless the color is TRANSPARENT_COLOR, format it to hexstring, as
@ -71,6 +67,7 @@
* @private * @private
*/ */
ns.PaletteController.prototype.onColorSelected_ = function(args, evt, color) { ns.PaletteController.prototype.onColorSelected_ = function(args, evt, color) {
var inputPicker = $(evt.target);
if (args.isPrimary) { if (args.isPrimary) {
this.setPrimaryColor_(color); this.setPrimaryColor_(color);
} else { } else {
@ -79,12 +76,12 @@
}; };
ns.PaletteController.prototype.setPrimaryColor_ = function (color) { ns.PaletteController.prototype.setPrimaryColor_ = function (color) {
this.updateColorPicker_(color, document.querySelector('#color-picker')); this.updateColorPicker_(color, $('#color-picker'));
$.publish(Events.PRIMARY_COLOR_SELECTED, [color]); $.publish(Events.PRIMARY_COLOR_SELECTED, [color]);
}; };
ns.PaletteController.prototype.setSecondaryColor_ = function (color) { ns.PaletteController.prototype.setSecondaryColor_ = function (color) {
this.updateColorPicker_(color, document.querySelector('#secondary-color-picker')); this.updateColorPicker_(color, $('#secondary-color-picker'));
$.publish(Events.SECONDARY_COLOR_SELECTED, [color]); $.publish(Events.SECONDARY_COLOR_SELECTED, [color]);
}; };
@ -95,15 +92,13 @@
}; };
ns.PaletteController.prototype.resetColors = function () { ns.PaletteController.prototype.resetColors = function () {
this.setPrimaryColor_(Constants.DEFAULT_PEN_COLOR); pskl.app.selectedColorsService.reset();
this.setSecondaryColor_(Constants.TRANSPARENT_COLOR);
}; };
/** /**
* @private * @private
*/ */
ns.PaletteController.prototype.updateColorPicker_ = function (color, colorPicker) { ns.PaletteController.prototype.updateColorPicker_ = function (color, colorPicker) {
var jqueryColorPicker = $(colorPicker);
if (color == Constants.TRANSPARENT_COLOR) { if (color == Constants.TRANSPARENT_COLOR) {
// We can set the current palette color to transparent. // We can set the current palette color to transparent.
// You can then combine this transparent color with an advanced // You can then combine this transparent color with an advanced
@ -114,17 +109,17 @@
// The colorpicker can't be set to a transparent state. // The colorpicker can't be set to a transparent state.
// We set its background to white and insert the // We set its background to white and insert the
// string "TRANSPARENT" to mimic this state: // string "TRANSPARENT" to mimic this state:
jqueryColorPicker.spectrum('set', Constants.TRANSPARENT_COLOR); colorPicker.spectrum('set', Constants.TRANSPARENT_COLOR);
colorPicker.value = Constants.TRANSPARENT_COLOR; colorPicker.val(Constants.TRANSPARENT_COLOR);
} else { } else {
jqueryColorPicker.spectrum('set', color); colorPicker.spectrum('set', color);
} }
this.setTitleOnPicker_(color, colorPicker); this.setTitleOnPicker_(color, colorPicker);
}; };
ns.PaletteController.prototype.setTitleOnPicker_ = function (title, colorPicker) { ns.PaletteController.prototype.setTitleOnPicker_ = function (title, colorPicker) {
var parent = colorPicker.parentNode; var parent = colorPicker.parent();
title = parent.dataset.initialTitle + '<br/>' + title; title = parent.data('initial-title') + '<br/>' + title;
parent.dataset.originalTitle = title; parent.attr('data-original-title', title);
}; };
})(); })();

View File

@ -29,7 +29,7 @@
$.subscribe(Events.CURRENT_COLORS_UPDATED, this.fillColorListContainer.bind(this)); $.subscribe(Events.CURRENT_COLORS_UPDATED, this.fillColorListContainer.bind(this));
$.subscribe(Events.PRIMARY_COLOR_SELECTED, this.highlightSelectedColors.bind(this)); $.subscribe(Events.PRIMARY_COLOR_SELECTED, this.highlightSelectedColors.bind(this));
$.subscribe(Events.SECONDARY_COLOR_SELECTED, this.highlightSelectedColors.bind(this)); $.subscribe(Events.SECONDARY_COLOR_SELECTED, this.highlightSelectedColors.bind(this));
$.subscribe(Events.USER_SETTINGS_CHANGED, this.onUserSettingsChange_.bind(this)); $.subscribe(Events.USER_SETTINGS_CHANGED, $.proxy(this.onUserSettingsChange_, this));
var shortcuts = pskl.service.keyboard.Shortcuts; var shortcuts = pskl.service.keyboard.Shortcuts;
pskl.app.shortcutService.registerShortcut(shortcuts.COLOR.PREVIOUS_COLOR, this.selectPreviousColor_.bind(this)); pskl.app.shortcutService.registerShortcut(shortcuts.COLOR.PREVIOUS_COLOR, this.selectPreviousColor_.bind(this));
@ -51,17 +51,12 @@
}; };
ns.PalettesListController.prototype.fillColorListContainer = function () { ns.PalettesListController.prototype.fillColorListContainer = function () {
var colors = this.getSelectedPaletteColors_(); var colors = this.getSelectedPaletteColors_();
if (colors.length > 0) { if (colors.length > 0) {
var html = colors.filter(function (color) { var html = colors.map(function (color, index) {
return !!color; return pskl.utils.Template.replace(this.paletteColorTemplate_, {color : color, index : index});
}).map(function (color, index) {
return pskl.utils.Template.replace(this.paletteColorTemplate_, {
color : color,
index : index + 1,
title : color.toUpperCase()
});
}.bind(this)).join(''); }.bind(this)).join('');
this.colorListContainer_.innerHTML = html; this.colorListContainer_.innerHTML = html;
@ -69,10 +64,6 @@
} else { } else {
this.colorListContainer_.innerHTML = pskl.utils.Template.get('palettes-list-no-colors-partial'); this.colorListContainer_.innerHTML = pskl.utils.Template.get('palettes-list-no-colors-partial');
} }
// If we have more than 10 colors, use tiny mode, where 10 colors will fit on the same
// line.
this.colorListContainer_.classList.toggle('tiny', colors.length > 10);
}; };
ns.PalettesListController.prototype.selectPalette = function (paletteId) { ns.PalettesListController.prototype.selectPalette = function (paletteId) {
@ -109,8 +100,8 @@
ns.PalettesListController.prototype.getCurrentColorIndex_ = function () { ns.PalettesListController.prototype.getCurrentColorIndex_ = function () {
var currentIndex = 0; var currentIndex = 0;
var selectedColor = document.querySelector('.' + PRIMARY_COLOR_CLASSNAME); var selectedColor = document.querySelector('.' + PRIMARY_COLOR_CLASSNAME);
if (selectedColor) { if (selectedColor) {
currentIndex = parseInt(selectedColor.dataset.colorIndex, 10) - 1; currentIndex = parseInt(selectedColor.dataset.colorIndex, 10);
} }
return currentIndex; return currentIndex;
}; };
@ -148,14 +139,14 @@
}; };
ns.PalettesListController.prototype.onCreatePaletteClick_ = function (evt) { ns.PalettesListController.prototype.onCreatePaletteClick_ = function (evt) {
$.publish(Events.DIALOG_SHOW, { $.publish(Events.DIALOG_DISPLAY, {
dialogId : 'create-palette' dialogId : 'create-palette'
}); });
}; };
ns.PalettesListController.prototype.onEditPaletteClick_ = function (evt) { ns.PalettesListController.prototype.onEditPaletteClick_ = function (evt) {
var paletteId = this.colorPaletteSelect_.value; var paletteId = this.colorPaletteSelect_.value;
$.publish(Events.DIALOG_SHOW, { $.publish(Events.DIALOG_DISPLAY, {
dialogId : 'create-palette', dialogId : 'create-palette',
initArgs : paletteId initArgs : paletteId
}); });

View File

@ -1,19 +1,23 @@
(function () { (function () {
var ns = $.namespace('pskl.controller'); var ns = $.namespace('pskl.controller');
ns.PenSizeController = function () { ns.PenSizeController = function () {};
this.sizePicker = new pskl.widgets.SizePicker(this.onSizePickerChanged_.bind(this));
};
ns.PenSizeController.prototype.init = function () { ns.PenSizeController.prototype.init = function () {
this.sizePicker.init(document.querySelector('.pen-size-container')); this.container = document.querySelector('.pen-size-container');
pskl.utils.Event.addEventListener(this.container, 'click', this.onPenSizeOptionClick_, this);
$.subscribe(Events.PEN_SIZE_CHANGED, this.onPenSizeChanged_.bind(this)); $.subscribe(Events.PEN_SIZE_CHANGED, this.onPenSizeChanged_.bind(this));
this.updateSelectedOption_(); this.updateSelectedOption_();
}; };
ns.PenSizeController.prototype.onSizePickerChanged_ = function (size) { ns.PenSizeController.prototype.onPenSizeOptionClick_ = function (e) {
pskl.app.penSizeService.setPenSize(size); var size = e.target.dataset.size;
if (!isNaN(size)) {
size = parseInt(size, 10);
pskl.app.penSizeService.setPenSize(size);
}
}; };
ns.PenSizeController.prototype.onPenSizeChanged_ = function (e) { ns.PenSizeController.prototype.onPenSizeChanged_ = function (e) {
@ -21,7 +25,11 @@
}; };
ns.PenSizeController.prototype.updateSelectedOption_ = function () { ns.PenSizeController.prototype.updateSelectedOption_ = function () {
pskl.utils.Dom.removeClass('selected', this.container);
var size = pskl.app.penSizeService.getPenSize(); var size = pskl.app.penSizeService.getPenSize();
this.sizePicker.setSize(size); var selectedOption = this.container.querySelector('[data-size="' + size + '"]');
if (selectedOption) {
selectedOption.classList.add('selected');
}
}; };
})(); })();

View File

@ -10,9 +10,9 @@
}; };
ns.ProgressBarController.prototype.init = function () { ns.ProgressBarController.prototype.init = function () {
$.subscribe(Events.SHOW_PROGRESS, this.showProgress_.bind(this)); $.subscribe(Events.SHOW_PROGRESS, $.proxy(this.showProgress_, this));
$.subscribe(Events.UPDATE_PROGRESS, this.updateProgress_.bind(this)); $.subscribe(Events.UPDATE_PROGRESS, $.proxy(this.updateProgress_, this));
$.subscribe(Events.HIDE_PROGRESS, this.hideProgress_.bind(this)); $.subscribe(Events.HIDE_PROGRESS, $.proxy(this.hideProgress_, this));
}; };
ns.ProgressBarController.prototype.showProgress_ = function (event, progressInfo) { ns.ProgressBarController.prototype.showProgress_ = function (event, progressInfo) {

View File

@ -35,8 +35,7 @@
// Set SimplePen as default selected tool: // Set SimplePen as default selected tool:
this.selectTool_(this.tools[0]); this.selectTool_(this.tools[0]);
// Activate listener on tool panel: // Activate listener on tool panel:
var toolSection = document.querySelector('#tool-section'); $('#tool-section').mousedown($.proxy(this.onToolIconClicked_, this));
toolSection.addEventListener('mousedown', this.onToolIconClicked_.bind(this));
$.subscribe(Events.SELECT_TOOL, this.onSelectToolEvent_.bind(this)); $.subscribe(Events.SELECT_TOOL, this.onSelectToolEvent_.bind(this));
$.subscribe(Events.SHORTCUTS_CHANGED, this.createToolsDom_.bind(this)); $.subscribe(Events.SHORTCUTS_CHANGED, this.createToolsDom_.bind(this));
@ -46,14 +45,14 @@
* @private * @private
*/ */
ns.ToolController.prototype.activateToolOnStage_ = function(tool) { ns.ToolController.prototype.activateToolOnStage_ = function(tool) {
var stage = document.body; var stage = $('body');
var previousSelectedToolClass = stage.dataset.selectedToolClass; var previousSelectedToolClass = stage.data('selected-tool-class');
if (previousSelectedToolClass) { if (previousSelectedToolClass) {
stage.classList.remove(previousSelectedToolClass); stage.removeClass(previousSelectedToolClass);
stage.classList.remove(pskl.tools.drawing.Move.TOOL_ID); stage.removeClass(pskl.tools.drawing.Move.TOOL_ID);
} }
stage.classList.add(tool.toolId); stage.addClass(tool.toolId);
stage.dataset.selectedToolClass = tool.toolId; stage.data('selected-tool-class', tool.toolId);
}; };
ns.ToolController.prototype.onSelectToolEvent_ = function(event, toolId) { ns.ToolController.prototype.onSelectToolEvent_ = function(event, toolId) {
@ -70,13 +69,11 @@
this.currentSelectedTool = tool; this.currentSelectedTool = tool;
this.activateToolOnStage_(this.currentSelectedTool); this.activateToolOnStage_(this.currentSelectedTool);
var selectedToolElement = document.querySelector('#tool-section .tool-icon.selected'); var selectedToolElement = $('#tool-section .tool-icon.selected');
if (selectedToolElement) { var toolElement = $('[data-tool-id=' + tool.toolId + ']');
selectedToolElement.classList.remove('selected');
}
var toolElement = document.querySelector('[data-tool-id=' + tool.toolId + ']'); selectedToolElement.removeClass('selected');
toolElement.classList.add('selected'); toolElement.addClass('selected');
$.publish(Events.TOOL_SELECTED, [tool]); $.publish(Events.TOOL_SELECTED, [tool]);
}; };
@ -85,11 +82,11 @@
* @private * @private
*/ */
ns.ToolController.prototype.onToolIconClicked_ = function(evt) { ns.ToolController.prototype.onToolIconClicked_ = function(evt) {
var target = evt.target; var target = $(evt.target);
var clickedTool = pskl.utils.Dom.getParentWithData(target, 'toolId'); var clickedTool = target.closest('.tool-icon');
if (clickedTool) { if (clickedTool.length) {
var toolId = clickedTool.dataset.toolId; var toolId = clickedTool.data().toolId;
var tool = this.getToolById_(toolId); var tool = this.getToolById_(toolId);
if (tool) { if (tool) {
this.selectTool_(tool); this.selectTool_(tool);
@ -119,7 +116,7 @@
var tool = this.tools[i]; var tool = this.tools[i];
html += this.toolIconBuilder.createIcon(tool); html += this.toolIconBuilder.createIcon(tool);
} }
document.querySelector('#tools-container').innerHTML = html; $('#tools-container').html(html);
}; };
ns.ToolController.prototype.addKeyboardShortcuts_ = function () { ns.ToolController.prototype.addKeyboardShortcuts_ = function () {

View File

@ -1,30 +1,22 @@
(function () { (function () {
var ns = $.namespace('pskl.controller'); var ns = $.namespace('pskl.controller');
var SHOW_MORE_CLASS = 'show-more';
ns.TransformationsController = function () { ns.TransformationsController = function () {
this.tools = [ this.tools = [
new pskl.tools.transform.Flip(), new pskl.tools.transform.Flip(),
new pskl.tools.transform.Rotate(), new pskl.tools.transform.Rotate(),
new pskl.tools.transform.Clone(), new pskl.tools.transform.Clone(),
new pskl.tools.transform.Center(), new pskl.tools.transform.Center()
new pskl.tools.transform.Crop(),
]; ];
this.toolIconBuilder = new pskl.tools.ToolIconBuilder(); this.toolIconBuilder = new pskl.tools.ToolIconBuilder();
}; };
ns.TransformationsController.prototype.init = function () { ns.TransformationsController.prototype.init = function () {
this.container = document.querySelector('.transformations-container'); var container = document.querySelector('.transformations-container');
this.container.addEventListener('click', this.onTransformationClick_.bind(this)); this.toolsContainer = container.querySelector('.tools-wrapper');
container.addEventListener('click', this.onTransformationClick_.bind(this));
this.showMoreLink = this.container.querySelector('.transformations-show-more-link');
this.showMoreLink.addEventListener('click', this.toggleShowMoreTools_.bind(this));
this.createToolsDom_(); this.createToolsDom_();
this.updateShowMoreLink_();
$.subscribe(Events.USER_SETTINGS_CHANGED, this.onUserSettingsChange_.bind(this));
}; };
ns.TransformationsController.prototype.applyTool = function (toolId, evt) { ns.TransformationsController.prototype.applyTool = function (toolId, evt) {
@ -38,35 +30,13 @@
ns.TransformationsController.prototype.onTransformationClick_ = function (evt) { ns.TransformationsController.prototype.onTransformationClick_ = function (evt) {
var toolId = evt.target.dataset.toolId; var toolId = evt.target.dataset.toolId;
if (toolId) { this.applyTool(toolId, evt);
this.applyTool(toolId, evt);
}
};
ns.TransformationsController.prototype.toggleShowMoreTools_ = function (evt) {
var showMore = pskl.UserSettings.get(pskl.UserSettings.TRANSFORM_SHOW_MORE);
pskl.UserSettings.set(pskl.UserSettings.TRANSFORM_SHOW_MORE, !showMore);
};
ns.TransformationsController.prototype.onUserSettingsChange_ = function (evt, settingName) {
if (settingName == pskl.UserSettings.TRANSFORM_SHOW_MORE) {
this.updateShowMoreLink_();
}
};
ns.TransformationsController.prototype.updateShowMoreLink_ = function () {
var showMoreEnabled = pskl.UserSettings.get(pskl.UserSettings.TRANSFORM_SHOW_MORE);
this.container.classList.toggle(SHOW_MORE_CLASS, showMoreEnabled);
// Hide the link in case there are 4 or less tools available.
this.showMoreLink.classList.toggle('hidden', this.tools.length < 5);
}; };
ns.TransformationsController.prototype.createToolsDom_ = function() { ns.TransformationsController.prototype.createToolsDom_ = function() {
var html = this.tools.reduce(function (p, tool) { var html = this.tools.reduce(function (p, tool) {
return p + this.toolIconBuilder.createIcon(tool, 'left'); return p + this.toolIconBuilder.createIcon(tool, 'left');
}.bind(this), ''); }.bind(this), '');
var toolsContainer = this.container.querySelector('.tools-wrapper'); this.toolsContainer.innerHTML = html;
toolsContainer.innerHTML = html;
}; };
})(); })();

View File

@ -1,59 +0,0 @@
(function () {
var ns = $.namespace('pskl.controller');
ns.UserWarningController = function (piskelController, currentColorsService) {
this.piskelController = piskelController;
this.currentColorsService = currentColorsService;
};
// This method is not attached to the prototype because we want to trigger it
// from markup generated for a notification message.
ns.UserWarningController.showPerformanceInfoDialog = function () {
$.publish(Events.DIALOG_SHOW, {
dialogId: 'performance-info'
});
};
ns.UserWarningController.prototype.init = function () {
$.subscribe(Events.PERFORMANCE_REPORT_CHANGED, this.onPerformanceReportChanged_.bind(this));
this.performanceLinkEl = document.querySelector('.performance-link');
pskl.utils.Event.addEventListener(
this.performanceLinkEl,
'click',
ns.UserWarningController.showPerformanceInfoDialog,
this
);
};
ns.UserWarningController.prototype.destroy = function () {
pskl.utils.Event.removeAllEventListeners(this);
this.performanceLinkEl = null;
};
ns.UserWarningController.prototype.onPerformanceReportChanged_ = function (event, report) {
var shouldDisplayWarning = report.hasProblem();
// Check if a performance warning is already displayed.
var isWarningDisplayed = this.performanceLinkEl.classList.contains('visible');
// Show/hide the performance warning link depending on the received report.
if (shouldDisplayWarning) {
this.performanceLinkEl.classList.add('visible');
} else {
this.performanceLinkEl.classList.remove('visible');
}
// Show a notification message if the new report indicates a performance issue
// and we were not displaying a warning before.
if (shouldDisplayWarning && !isWarningDisplayed) {
$.publish(Events.SHOW_NOTIFICATION, [{
'content': 'Performance problem detected, ' +
'<a href="#" style="color:red;"' +
'onclick="pskl.controller.UserWarningController.showPerformanceInfoDialog()">' +
'learn more?</a>',
'hideDelay' : 5000
}]);
}
};
})();

View File

@ -4,19 +4,14 @@
ns.AbstractDialogController = function () {}; ns.AbstractDialogController = function () {};
ns.AbstractDialogController.prototype.init = function () { ns.AbstractDialogController.prototype.init = function () {
var closeButton = document.querySelector('.dialog-close'); this.closeButton = document.querySelector('.dialog-close');
this.addEventListener(closeButton, 'click', this.closeDialog); this.closeButton.addEventListener('click', this.closeDialog.bind(this));
}; };
ns.AbstractDialogController.prototype.addEventListener = function (el, type, cb) { ns.AbstractDialogController.prototype.destroy = function () {};
pskl.utils.Event.addEventListener(el, type, cb, this);
};
ns.AbstractDialogController.prototype.destroy = function () {
pskl.utils.Event.removeAllEventListeners(this);
};
ns.AbstractDialogController.prototype.closeDialog = function () { ns.AbstractDialogController.prototype.closeDialog = function () {
this.destroy();
$.publish(Events.DIALOG_HIDE); $.publish(Events.DIALOG_HIDE);
}; };

View File

@ -1,7 +1,8 @@
(function () { (function () {
var ns = $.namespace('pskl.controller.dialogs'); var ns = $.namespace('pskl.controller.dialogs');
ns.BrowseLocalController = function (piskelController) {}; ns.BrowseLocalController = function (piskelController) {
};
pskl.utils.inherit(ns.BrowseLocalController, ns.AbstractDialogController); pskl.utils.inherit(ns.BrowseLocalController, ns.AbstractDialogController);
@ -10,12 +11,13 @@
this.localStorageItemTemplate_ = pskl.utils.Template.get('local-storage-item-template'); this.localStorageItemTemplate_ = pskl.utils.Template.get('local-storage-item-template');
this.service_ = pskl.app.indexedDbStorageService; this.service_ = pskl.app.localStorageService;
this.piskelList = document.querySelector('.local-piskel-list'); this.piskelList = $('.local-piskel-list');
this.prevSessionContainer = $('.previous-session');
this.fillLocalPiskelsList_(); this.fillLocalPiskelsList_();
this.piskelList.addEventListener('click', this.onPiskelsListClick_.bind(this)); this.piskelList.click(this.onPiskelsListClick_.bind(this));
}; };
ns.BrowseLocalController.prototype.onPiskelsListClick_ = function (evt) { ns.BrowseLocalController.prototype.onPiskelsListClick_ = function (evt) {
@ -35,24 +37,21 @@
}; };
ns.BrowseLocalController.prototype.fillLocalPiskelsList_ = function () { ns.BrowseLocalController.prototype.fillLocalPiskelsList_ = function () {
this.service_.getKeys().then(function (keys) { var html = '';
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) { keys.sort(function (k1, k2) {
var date = pskl.utils.DateUtils.format(key.date, '{{Y}}/{{M}}/{{D}} {{H}}:{{m}}'); if (k1.date < k2.date) {return 1;}
html += pskl.utils.Template.replace(this.localStorageItemTemplate_, { if (k1.date > k2.date) {return -1;}
name : key.name, return 0;
date : date });
});
}).bind(this));
var tableBody_ = this.piskelList.tBodies[0]; keys.forEach((function (key) {
tableBody_.innerHTML = html; var date = pskl.utils.DateUtils.format(key.date, '{{Y}}/{{M}}/{{D}} {{H}}:{{m}}');
}.bind(this)); html += pskl.utils.Template.replace(this.localStorageItemTemplate_, {name : key.name, date : date});
}).bind(this));
var tableBody_ = this.piskelList.get(0).tBodies[0];
tableBody_.innerHTML = html;
}; };
})(); })();

View File

@ -13,12 +13,11 @@
this.cheatsheetEl = document.getElementById('cheatsheetContainer'); this.cheatsheetEl = document.getElementById('cheatsheetContainer');
this.eventTrapInput = document.getElementById('cheatsheetEventTrap'); this.eventTrapInput = document.getElementById('cheatsheetEventTrap');
this.addEventListener('.cheatsheet-restore-defaults', 'click', this.onRestoreDefaultsClick_); pskl.utils.Event.addEventListener('.cheatsheet-restore-defaults', 'click', this.onRestoreDefaultsClick_, this);
this.addEventListener(this.cheatsheetEl, 'click', this.onCheatsheetClick_); pskl.utils.Event.addEventListener(this.cheatsheetEl, 'click', this.onCheatsheetClick_, this);
this.addEventListener(this.eventTrapInput, 'keydown', this.onEventTrapKeydown_); pskl.utils.Event.addEventListener(this.eventTrapInput, 'keydown', this.onEventTrapKeydown_, this);
this.onShortcutsChanged_ = this.onShortcutsChanged_.bind(this); $.subscribe(Events.SHORTCUTS_CHANGED, this.onShortcutsChanged_.bind(this));
$.subscribe(Events.SHORTCUTS_CHANGED, this.onShortcutsChanged_);
this.initMarkup_(); this.initMarkup_();
document.querySelector('.cheatsheet-helptext').setAttribute('title', this.getHelptextTitle_()); document.querySelector('.cheatsheet-helptext').setAttribute('title', this.getHelptextTitle_());
@ -26,11 +25,8 @@
ns.CheatsheetController.prototype.destroy = function () { ns.CheatsheetController.prototype.destroy = function () {
this.eventTrapInput.blur(); this.eventTrapInput.blur();
pskl.utils.Event.removeAllEventListeners();
$.unsubscribe(Events.SHORTCUTS_CHANGED, this.onShortcutsChanged_);
this.cheatsheetEl = null; this.cheatsheetEl = null;
this.superclass.destroy.call(this);
}; };
ns.CheatsheetController.prototype.onRestoreDefaultsClick_ = function () { ns.CheatsheetController.prototype.onRestoreDefaultsClick_ = function () {
@ -144,8 +140,7 @@
title : title, title : title,
icon : descriptor.iconClass, icon : descriptor.iconClass,
description : description, description : description,
// Avoid sanitization key : this.formatKey_(shortcut.getDisplayKey()),
'!key!' : this.formatKey_(shortcut.getDisplayKey()),
className : shortcutClasses.join(' ') className : shortcutClasses.join(' ')
}); });
@ -157,10 +152,10 @@
key = key.replace('ctrl', 'cmd'); key = key.replace('ctrl', 'cmd');
key = key.replace('alt', 'option'); key = key.replace('alt', 'option');
} }
key = key.replace(/left/i, '&larr;'); key = key.replace(/left/i, '&#65513;');
key = key.replace(/up/i, '&uarr;'); key = key.replace(/up/i, '&#65514;');
key = key.replace(/right/i, '&rarr;'); key = key.replace(/right/i, '&#65515;');
key = key.replace(/down/i, '&darr;'); key = key.replace(/down/i, '&#65516;');
key = key.replace(/>/g, '&gt;'); key = key.replace(/>/g, '&gt;');
key = key.replace(/</g, '&lt;'); key = key.replace(/</g, '&lt;');
// add spaces around '+' delimiters // add spaces around '+' delimiters

View File

@ -19,12 +19,12 @@
var downloadButton = document.querySelector('.create-palette-download-button'); var downloadButton = document.querySelector('.create-palette-download-button');
var importFileButton = document.querySelector('.create-palette-import-button'); var importFileButton = document.querySelector('.create-palette-import-button');
this.addEventListener(this.nameInput, 'input', this.onNameInputChange_); this.nameInput.addEventListener('input', this.onNameInputChange_.bind(this));
this.addEventListener(this.hiddenFileInput, 'change', this.onFileInputChange_); this.hiddenFileInput.addEventListener('change', this.onFileInputChange_.bind(this));
this.addEventListener(buttonsContainer, 'click', this.onButtonClick_); buttonsContainer.addEventListener('click', this.onButtonClick_.bind(this));
this.addEventListener(downloadButton, 'click', this.onDownloadButtonClick_); downloadButton.addEventListener('click', this.onDownloadButtonClick_.bind(this));
this.addEventListener(importFileButton, 'click', this.onImportFileButtonClick_); importFileButton.addEventListener('click', this.onImportFileButtonClick_.bind(this));
var colorsListContainer = document.querySelector('.colors-container'); var colorsListContainer = document.querySelector('.colors-container');
this.colorsListWidget = new pskl.widgets.ColorsList(colorsListContainer); this.colorsListWidget = new pskl.widgets.ColorsList(colorsListContainer);
@ -66,10 +66,7 @@
ns.CreatePaletteController.prototype.destroy = function () { ns.CreatePaletteController.prototype.destroy = function () {
this.colorsListWidget.destroy(); this.colorsListWidget.destroy();
this.superclass.destroy.call(this);
this.nameInput = null; this.nameInput = null;
this.hiddenFileInput = null;
}; };
ns.CreatePaletteController.prototype.onButtonClick_ = function (evt) { ns.CreatePaletteController.prototype.onButtonClick_ = function (evt) {

View File

@ -14,21 +14,9 @@
template : 'templates/dialogs/browse-local.html', template : 'templates/dialogs/browse-local.html',
controller : ns.BrowseLocalController controller : ns.BrowseLocalController
}, },
'import' : { 'import-image' : {
template : 'templates/dialogs/import.html', template : 'templates/dialogs/import-image.html',
controller : ns.importwizard.ImportWizard controller : ns.ImportImageController
},
'performance-info' : {
template : 'templates/dialogs/performance-info.html',
controller : ns.PerformanceInfoController
},
'unsupported-browser' : {
template : 'templates/dialogs/unsupported-browser.html',
controller : ns.UnsupportedBrowserController
},
'browse-backups' : {
template : 'templates/dialogs/browse-backups.html',
controller : ns.backups.BrowseBackups
} }
}; };
@ -42,7 +30,7 @@
this.dialogContainer_ = document.getElementById('dialog-container'); this.dialogContainer_ = document.getElementById('dialog-container');
this.dialogWrapper_ = document.getElementById('dialog-container-wrapper'); this.dialogWrapper_ = document.getElementById('dialog-container-wrapper');
$.subscribe(Events.DIALOG_SHOW, this.onDialogDisplayEvent_.bind(this)); $.subscribe(Events.DIALOG_DISPLAY, this.onDialogDisplayEvent_.bind(this));
$.subscribe(Events.DIALOG_HIDE, this.hideDialog.bind(this)); $.subscribe(Events.DIALOG_HIDE, this.hideDialog.bind(this));
var createPaletteShortcut = pskl.service.keyboard.Shortcuts.COLOR.CREATE_PALETTE; var createPaletteShortcut = pskl.service.keyboard.Shortcuts.COLOR.CREATE_PALETTE;
@ -54,7 +42,6 @@
// adding the .animated class here instead of in the markup to avoid an animation during app startup // adding the .animated class here instead of in the markup to avoid an animation during app startup
this.dialogWrapper_.classList.add('animated'); this.dialogWrapper_.classList.add('animated');
pskl.utils.Event.addEventListener(this.dialogWrapper_, 'click', this.onWrapperClicked_, this);
}; };
ns.DialogsController.prototype.onCreatePaletteShortcut_ = function () { ns.DialogsController.prototype.onCreatePaletteShortcut_ = function () {
@ -82,12 +69,6 @@
this.showDialog(args.dialogId, args.initArgs); this.showDialog(args.dialogId, args.initArgs);
}; };
ns.DialogsController.prototype.onWrapperClicked_ = function (evt) {
if (evt.target === this.dialogWrapper_) {
this.hideDialog();
}
};
ns.DialogsController.prototype.showDialog = function (dialogId, initArgs) { ns.DialogsController.prototype.showDialog = function (dialogId, initArgs) {
if (this.isDisplayingDialog_()) { if (this.isDisplayingDialog_()) {
return; return;

View File

@ -0,0 +1,261 @@
(function () {
var ns = $.namespace('pskl.controller.dialogs');
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.importType = $('[name=import-type]');
this.resizeWidth = $('[name=resize-width]');
this.resizeHeight = $('[name=resize-height]');
this.smoothResize = $('[name=smooth-resize-checkbox]');
this.frameSizeX = $('[name=frame-size-x]');
this.frameSizeY = $('[name=frame-size-y]');
this.frameOffsetX = $('[name=frame-offset-x]');
this.frameOffsetY = $('[name=frame-offset-y]');
this.importType.change(this.onImportTypeChange_.bind(this));
this.resizeWidth.keyup(this.onResizeInputKeyUp_.bind(this, 'width'));
this.resizeHeight.keyup(this.onResizeInputKeyUp_.bind(this, 'height'));
this.frameSizeX.keyup(this.onFrameInputKeyUp_.bind(this, 'frameSizeX'));
this.frameSizeY.keyup(this.onFrameInputKeyUp_.bind(this, 'frameSizeY'));
this.frameOffsetX.keyup(this.onFrameInputKeyUp_.bind(this, 'frameOffsetX'));
this.frameOffsetY.keyup(this.onFrameInputKeyUp_.bind(this, 'frameOffsetY'));
this.importImageForm = $('[name=import-image-form]');
this.importImageForm.submit(this.onImportFormSubmit_.bind(this));
pskl.utils.FileUtils.readImageFile(this.file_, this.onImageLoaded_.bind(this));
};
ns.ImportImageController.prototype.onImportTypeChange_ = function (evt) {
if (this.getImportType_() === 'single') {
// Using single image, so remove the frame grid
this.hideFrameGrid_();
} else {
// Using spritesheet import, so draw the frame grid in the preview
var x = this.sanitizeInputValue_(this.frameOffsetX, 0);
var y = this.sanitizeInputValue_(this.frameOffsetY, 0);
var w = this.sanitizeInputValue_(this.frameSizeX, 1);
var h = this.sanitizeInputValue_(this.frameSizeY, 1);
this.drawFrameGrid_(x, y, w, h);
}
};
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.onFrameInputKeyUp_ = function (from, evt) {
if (this.importedImage_) {
this.synchronizeFrameFields_(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;
var width = this.importedImage_.width;
// Select single image import type since the user changed a value here
this.importType.filter('[value="single"]').attr('checked', 'checked');
if (from === 'width') {
this.resizeHeight.val(Math.round(value * height / width));
} else {
this.resizeWidth.val(Math.round(value * width / height));
}
};
ns.ImportImageController.prototype.synchronizeFrameFields_ = function (value, from) {
value = parseInt(value, 10);
if (isNaN(value)) {
value = 0;
}
// Parse the frame input values
var frameSizeX = this.sanitizeInputValue_(this.frameSizeX, 1);
var frameSizeY = this.sanitizeInputValue_(this.frameSizeY, 1);
var frameOffsetX = this.sanitizeInputValue_(this.frameOffsetX, 0);
var frameOffsetY = this.sanitizeInputValue_(this.frameOffsetY, 0);
// Select spritesheet import type since the user changed a value here
this.importType.filter('[value="sheet"]').attr('checked', 'checked');
// Draw the grid
this.drawFrameGrid_(frameOffsetX, frameOffsetY, frameSizeX, frameSizeY);
};
ns.ImportImageController.prototype.sanitizeInputValue_ = function(input, minValue) {
var value = parseInt(input.val(), 10);
if (value <= minValue || isNaN(value)) {
input.val(minValue);
value = minValue;
}
return value;
};
ns.ImportImageController.prototype.getImportType_ = function () {
return this.importType.filter(':checked').val();
};
ns.ImportImageController.prototype.onImageLoaded_ = function (image) {
this.importedImage_ = image;
var w = this.importedImage_.width;
var 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.fileNameContainer.attr('title', fileName);
this.resizeWidth.val(w);
this.resizeHeight.val(h);
this.frameSizeX.val(w);
this.frameSizeY.val(h);
this.frameOffsetX.val(0);
this.frameOffsetY.val(0);
this.importPreview.width('auto');
this.importPreview.height('auto');
this.importPreview.html('');
this.importPreview.append(this.createImagePreview_());
};
ns.ImportImageController.prototype.createImagePreview_ = function () {
var image = document.createElement('IMG');
image.src = this.importedImage_.src;
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 () {
if (this.importedImage_) {
if (window.confirm('You are about to create a new Piskel, unsaved changes will be lost.')) {
pskl.app.importService.newPiskelFromImage(
this.importedImage_,
{
importType: this.getImportType_(),
frameSizeX: this.getImportType_() === 'single' ?
this.resizeWidth.val() : this.sanitizeInputValue_(this.frameSizeX, 1),
frameSizeY: this.getImportType_() === 'single' ?
this.resizeHeight.val() : this.sanitizeInputValue_(this.frameSizeY, 1),
frameOffsetX: this.sanitizeInputValue_(this.frameOffsetX, 0),
frameOffsetY: this.sanitizeInputValue_(this.frameOffsetY, 0),
smoothing: !!this.smoothResize.prop('checked')
},
this.closeDialog.bind(this)
);
}
}
};
ns.ImportImageController.prototype.drawFrameGrid_ = function (frameX, frameY, frameW, frameH) {
if (!this.importedImage_) {
return;
}
// Grab the sizes of the source and preview images
var width = this.importedImage_.width;
var height = this.importedImage_.height;
var previewWidth = this.importPreview.width();
var previewHeight = this.importPreview.height();
var canvasWrapper = this.importPreview.children('canvas');
var canvas = canvasWrapper.get(0);
if (!canvasWrapper.length) {
// Create a new canvas for the grid
canvas = pskl.utils.CanvasUtils.createCanvas(
previewWidth + 1,
previewHeight + 1);
this.importPreview.append(canvas);
canvasWrapper = $(canvas);
}
var context = canvas.getContext('2d');
context.clearRect(0, 0, canvas.width, canvas.height);
context.beginPath();
// Calculate the number of whole frames
var countX = Math.floor((width - frameX) / frameW);
var countY = Math.floor((height - frameY) / frameH);
if (countX > 0 && countY > 0) {
var scaleX = previewWidth / width;
var scaleY = previewHeight / height;
var maxWidth = countX * frameW + frameX;
var maxHeight = countY * frameH + frameY;
// Draw the vertical lines
for (var x = frameX + 0.5; x < maxWidth + 1 && x < width + 1; x += frameW) {
context.moveTo(x * scaleX, frameY * scaleY);
context.lineTo(x * scaleX, maxHeight * scaleY);
}
// Draw the horizontal lines
for (var y = frameY + 0.5; y < maxHeight + 1 && y < height + 1; y += frameH) {
context.moveTo(frameX * scaleX, y * scaleY);
context.lineTo(maxWidth * scaleX, y * scaleY);
}
// Set the line style to dashed
context.lineWidth = 1;
context.setLineDash([2, 1]);
context.strokeStyle = '#000000';
context.stroke();
// Show the canvas
canvasWrapper.show();
this.importPreview.addClass('no-border');
} else {
this.hideFrameGrid_();
}
};
ns.ImportImageController.prototype.hideFrameGrid_ = function() {
this.importPreview.children('canvas').hide();
this.importPreview.removeClass('no-border');
};
})();

View File

@ -1,11 +0,0 @@
(function () {
var ns = $.namespace('pskl.controller.dialogs');
ns.PerformanceInfoController = function () {};
pskl.utils.inherit(ns.PerformanceInfoController, ns.AbstractDialogController);
ns.PerformanceInfoController.prototype.init = function () {
this.superclass.init.call(this);
};
})();

View File

@ -1,13 +0,0 @@
(function () {
var ns = $.namespace('pskl.controller.dialogs');
ns.UnsupportedBrowserController = function () {};
pskl.utils.inherit(ns.UnsupportedBrowserController, ns.AbstractDialogController);
ns.UnsupportedBrowserController.prototype.init = function () {
this.superclass.init.call(this);
var currentUserAgentElement = document.querySelector('#current-user-agent');
currentUserAgentElement.innerText = pskl.utils.UserAgent.getDisplayName();
};
})();

View File

@ -1,81 +0,0 @@
(function () {
var ns = $.namespace('pskl.controller.dialogs.backups');
var stepDefinitions = {
'SELECT_SESSION' : {
controller : ns.steps.SelectSession,
template : 'backups-select-session'
},
'SESSION_DETAILS' : {
controller : ns.steps.SessionDetails,
template : 'backups-session-details'
},
};
ns.BrowseBackups = function (piskelController, args) {
this.piskelController = piskelController;
// Backups data object used by steps to communicate and share their
// results.
this.backupsData = {
sessions: [],
selectedSession : null
};
};
pskl.utils.inherit(ns.BrowseBackups, pskl.controller.dialogs.AbstractDialogController);
ns.BrowseBackups.prototype.init = function () {
this.superclass.init.call(this);
// Prepare wizard steps.
this.steps = this.createSteps_();
// Start wizard widget.
var wizardContainer = document.querySelector('.backups-wizard-container');
this.wizard = new pskl.widgets.Wizard(this.steps, wizardContainer);
this.wizard.init();
this.wizard.goTo('SELECT_SESSION');
};
ns.BrowseBackups.prototype.back = function () {
this.wizard.back();
this.wizard.getCurrentStep().instance.onShow();
};
ns.BrowseBackups.prototype.next = function () {
var step = this.wizard.getCurrentStep();
if (step.name === 'SELECT_SESSION') {
this.wizard.goTo('SESSION_DETAILS');
}
};
ns.BrowseBackups.prototype.destroy = function (file) {
Object.keys(this.steps).forEach(function (stepName) {
var step = this.steps[stepName];
step.instance.destroy();
step.instance = null;
step.el = null;
}.bind(this));
this.superclass.destroy.call(this);
};
ns.BrowseBackups.prototype.createSteps_ = function () {
var steps = {};
Object.keys(stepDefinitions).forEach(function (stepName) {
var definition = stepDefinitions[stepName];
var el = pskl.utils.Template.getAsHTML(definition.template);
var instance = new definition.controller(this.piskelController, this, el);
instance.init();
steps[stepName] = {
name: stepName,
el: el,
instance: instance
};
}.bind(this));
return steps;
};
})();

View File

@ -1,101 +0,0 @@
(function () {
var ns = $.namespace('pskl.controller.dialogs.backups.steps');
// Should match the transition duration for.session-item defined in dialogs-browse-backups.css
var DELETE_TRANSITION_DURATION = 500;
/**
* Helper that returns a promise that will resolve after waiting for a
* given time (in ms).
*
* @param {Number} time
* The time to wait.
* @return {Promise} promise that resolves after time.
*/
var wait = function (time) {
var deferred = Q.defer();
setTimeout(function () {
deferred.resolve();
}, time);
return deferred.promise;
};
ns.SelectSession = function (piskelController, backupsController, container) {
this.piskelController = piskelController;
this.backupsController = backupsController;
this.container = container;
};
ns.SelectSession.prototype.addEventListener = function (el, type, cb) {
pskl.utils.Event.addEventListener(el, type, cb, this);
};
ns.SelectSession.prototype.init = function () {
this.addEventListener(this.container, 'click', this.onContainerClick_);
};
ns.SelectSession.prototype.onShow = function () {
this.update();
};
ns.SelectSession.prototype.update = function () {
pskl.app.backupService.list().then(function (sessions) {
var html = this.getMarkupForSessions_(sessions);
this.container.querySelector('.session-list').innerHTML = html;
}.bind(this)).catch(function () {
var html = pskl.utils.Template.get('session-list-error');
this.container.querySelector('.session-list').innerHTML = html;
}.bind(this));
};
ns.SelectSession.prototype.getMarkupForSessions_ = function (sessions) {
if (sessions.length === 0) {
return pskl.utils.Template.get('session-list-empty');
}
var sessionItemTemplate = pskl.utils.Template.get('session-list-item');
return sessions.reduce(function (previous, session) {
if (session.id === pskl.app.sessionId) {
// Do not show backups for the current session.
return previous;
}
var view = {
id: session.id,
name: session.name,
description: session.description ? '- ' + session.description : '',
date: pskl.utils.DateUtils.format(session.endDate, 'the {{Y}}/{{M}}/{{D}} at {{H}}:{{m}}'),
count: session.count === 1 ? '1 snapshot' : session.count + ' snapshots'
};
return previous + pskl.utils.Template.replace(sessionItemTemplate, view);
}, '');
};
ns.SelectSession.prototype.destroy = function () {
pskl.utils.Event.removeAllEventListeners(this);
};
ns.SelectSession.prototype.onContainerClick_ = function (evt) {
var sessionId = evt.target.dataset.sessionId;
if (!sessionId) {
return;
}
var action = evt.target.dataset.action;
if (action == 'view') {
this.backupsController.backupsData.selectedSession = sessionId;
this.backupsController.next();
} else if (action == 'delete') {
if (window.confirm('Are you sure you want to delete this session?')) {
evt.target.closest('.session-item').classList.add('deleting');
Q.all([
pskl.app.backupService.deleteSession(sessionId),
// Wait for 500ms for the .hide opacity transition.
wait(DELETE_TRANSITION_DURATION)
]).then(function () {
// Refresh the list of sessions
this.update();
}.bind(this));
}
}
};
})();

View File

@ -1,102 +0,0 @@
(function () {
var ns = $.namespace('pskl.controller.dialogs.backups.steps');
// Should match the preview dimensions defined in dialogs-browse-backups.css
var PREVIEW_SIZE = 60;
ns.SessionDetails = function (piskelController, backupsController, container) {
this.piskelController = piskelController;
this.backupsController = backupsController;
this.container = container;
};
ns.SessionDetails.prototype.init = function () {
this.backButton = this.container.querySelector('.back-button');
this.addEventListener(this.backButton, 'click', this.onBackClick_);
this.addEventListener(this.container, 'click', this.onContainerClick_);
};
ns.SessionDetails.prototype.destroy = function () {
pskl.utils.Event.removeAllEventListeners(this);
};
ns.SessionDetails.prototype.addEventListener = function (el, type, cb) {
pskl.utils.Event.addEventListener(el, type, cb, this);
};
ns.SessionDetails.prototype.onShow = function () {
var sessionId = this.backupsController.backupsData.selectedSession;
pskl.app.backupService.getSnapshotsBySessionId(sessionId).then(function (snapshots) {
var html = this.getMarkupForSnapshots_(snapshots);
this.container.querySelector('.snapshot-list').innerHTML = html;
// Load the image of the first frame for each sprite and update the list.
snapshots.forEach(function (snapshot) {
this.updateSnapshotPreview_(snapshot);
}.bind(this));
}.bind(this)).catch(function () {
var html = pskl.utils.Template.get('snapshot-list-error');
this.container.querySelector('.snapshot-list').innerHTML = html;
}.bind(this));
};
ns.SessionDetails.prototype.getMarkupForSnapshots_ = function (snapshots) {
if (snapshots.length === 0) {
// This should normally never happen, all sessions have at least one snapshot and snapshots
// can not be individually deleted.
console.warn('Could not retrieve snapshots for a session');
return pskl.utils.Template.get('snapshot-list-empty');
}
var sessionItemTemplate = pskl.utils.Template.get('snapshot-list-item');
return snapshots.reduce(function (previous, snapshot) {
var view = {
id: snapshot.id,
name: snapshot.name,
description: snapshot.description ? '- ' + snapshot.description : '',
date: pskl.utils.DateUtils.format(snapshot.date, 'the {{Y}}/{{M}}/{{D}} at {{H}}:{{m}}'),
frames: snapshot.frames === 1 ? '1 frame' : snapshot.frames + ' frames',
resolution: pskl.utils.StringUtils.formatSize(snapshot.width, snapshot.height),
fps: snapshot.fps
};
return previous + pskl.utils.Template.replace(sessionItemTemplate, view);
}, '');
};
ns.SessionDetails.prototype.updateSnapshotPreview_ = function (snapshot) {
pskl.utils.serialization.Deserializer.deserialize(
JSON.parse(snapshot.serialized),
function (piskel) {
var selector = '.snapshot-item[data-snapshot-id="' + snapshot.id + '"] .snapshot-preview';
var previewContainer = this.container.querySelector(selector);
if (!previewContainer) {
return;
}
var image = this.getFirstFrameAsImage_(piskel);
previewContainer.appendChild(image);
}.bind(this)
);
};
ns.SessionDetails.prototype.getFirstFrameAsImage_ = function (piskel) {
var frame = pskl.utils.LayerUtils.mergeFrameAt(piskel.getLayers(), 0);
var wZoom = PREVIEW_SIZE / piskel.width;
var hZoom = PREVIEW_SIZE / piskel.height;
var zoom = Math.min(hZoom, wZoom);
return pskl.utils.FrameUtils.toImage(frame, zoom);
};
ns.SessionDetails.prototype.onBackClick_ = function () {
this.backupsController.back(this);
};
ns.SessionDetails.prototype.onContainerClick_ = function (evt) {
var action = evt.target.dataset.action;
if (action == 'load' && window.confirm(Constants.CONFIRM_OVERWRITE)) {
var snapshotId = evt.target.dataset.snapshotId * 1;
pskl.app.backupService.loadSnapshotById(snapshotId).then(function () {
$.publish(Events.DIALOG_HIDE);
});
}
};
})();

View File

@ -1,202 +0,0 @@
(function () {
var ns = $.namespace('pskl.controller.dialogs.importwizard');
var stepDefinitions = {
'IMAGE_IMPORT' : {
controller : ns.steps.ImageImport,
template : 'import-image-import'
},
'ADJUST_SIZE' : {
controller : ns.steps.AdjustSize,
template : 'import-adjust-size'
},
'INSERT_LOCATION' : {
controller : ns.steps.InsertLocation,
template : 'import-insert-location'
},
'SELECT_MODE' : {
controller : ns.steps.SelectMode,
template : 'import-select-mode'
}
};
ns.ImportWizard = function (piskelController, args) {
this.piskelController = piskelController;
// Merge data object used by steps to communicate and share their
// results.
this.mergeData = {
rawFiles : [],
mergePiskel: null,
origin: null,
resize: null,
insertIndex: null,
insertMode: null
};
};
pskl.utils.inherit(ns.ImportWizard, pskl.controller.dialogs.AbstractDialogController);
ns.ImportWizard.prototype.init = function (initArgs) {
this.superclass.init.call(this);
// Prepare mergeData object and wizard steps.
this.mergeData.rawFiles = initArgs.rawFiles;
this.steps = this.createSteps_();
// Start wizard widget.
var wizardContainer = document.querySelector('.import-wizard-container');
this.wizard = new pskl.widgets.Wizard(this.steps, wizardContainer);
this.wizard.init();
if (this.hasSingleImage_()) {
this.wizard.goTo('IMAGE_IMPORT');
} else if (this.hasSinglePiskelFile_()) {
// If a piskel file was provided we can directly go to
pskl.utils.PiskelFileUtils.loadFromFile(this.mergeData.rawFiles[0],
// onSuccess
function (piskel) {
this.mergeData.mergePiskel = piskel;
this.wizard.goTo('SELECT_MODE');
}.bind(this),
// onError
function (reason) {
this.closeDialog();
$.publish(Events.PISKEL_FILE_IMPORT_FAILED, [reason]);
}.bind(this)
);
} else {
console.error('Unsupported import. Only single piskel or single image are supported at the moment.');
this.closeDialog();
}
};
ns.ImportWizard.prototype.back = function () {
this.wizard.back();
this.wizard.getCurrentStep().instance.onShow();
};
ns.ImportWizard.prototype.next = function () {
var step = this.wizard.getCurrentStep();
if (step.name === 'IMAGE_IMPORT') {
if (this.piskelController.isEmpty()) {
// If the current sprite is empty finalize immediately and replace the current sprite.
this.mergeData.importMode = ns.steps.SelectMode.MODES.REPLACE;
this.finalizeImport_();
} else {
this.wizard.goTo('SELECT_MODE');
}
} else if (step.name === 'SELECT_MODE') {
if (this.mergeData.importMode === ns.steps.SelectMode.MODES.REPLACE) {
this.finalizeImport_();
} else if (this.hasSameSize_()) {
this.wizard.goTo('INSERT_LOCATION');
} else {
this.wizard.goTo('ADJUST_SIZE');
}
} else if (step.name === 'ADJUST_SIZE') {
this.wizard.goTo('INSERT_LOCATION');
} else if (step.name === 'INSERT_LOCATION') {
this.finalizeImport_();
}
};
ns.ImportWizard.prototype.destroy = function (file) {
Object.keys(this.steps).forEach(function (stepName) {
var step = this.steps[stepName];
step.instance.destroy();
step.instance = null;
step.el = null;
}.bind(this));
this.superclass.destroy.call(this);
};
ns.ImportWizard.prototype.createSteps_ = function () {
// The IMAGE_IMPORT step is used only if there is a single image file
// being imported.
var hasSingleImage = this.hasSingleImage_();
var steps = {};
Object.keys(stepDefinitions).forEach(function (stepName) {
if (stepName === 'IMAGE_IMPORT' && !hasSingleImage) {
return;
}
var definition = stepDefinitions[stepName];
var el = pskl.utils.Template.getAsHTML(definition.template);
var instance = new definition.controller(this.piskelController, this, el);
instance.init();
steps[stepName] = {
name: stepName,
el: el,
instance: instance
};
}.bind(this));
if (hasSingleImage) {
steps.IMAGE_IMPORT.el.classList.add('import-first-step');
} else {
steps.SELECT_MODE.el.classList.add('import-first-step');
}
return steps;
};
ns.ImportWizard.prototype.finalizeImport_ = function () {
var piskel = this.mergeData.mergePiskel;
var mode = this.mergeData.importMode;
if (mode === ns.steps.SelectMode.MODES.REPLACE) {
// Replace the current piskel and close the dialog.
if (window.confirm(Constants.CONFIRM_OVERWRITE)) {
this.piskelController.setPiskel(piskel);
this.closeDialog();
}
} else if (mode === ns.steps.SelectMode.MODES.MERGE) {
var merge = pskl.utils.MergeUtils.merge(this.piskelController.getPiskel(), piskel, {
insertIndex: this.mergeData.insertIndex,
insertMode: this.mergeData.insertMode,
origin: this.mergeData.origin,
resize: this.mergeData.resize
});
this.piskelController.setPiskel(merge);
// Set the first imported layer as selected.
var importedLayers = piskel.getLayers().length;
var currentLayers = this.piskelController.getLayers().length;
this.piskelController.setCurrentLayerIndex(currentLayers - importedLayers);
this.closeDialog();
}
};
ns.ImportWizard.prototype.hasSameSize_ = function () {
var piskel = this.mergeData.mergePiskel;
if (!piskel) {
return false;
}
return piskel.width === this.piskelController.getWidth() &&
piskel.height === this.piskelController.getHeight();
};
ns.ImportWizard.prototype.hasSingleImage_ = function () {
if (this.mergeData.rawFiles.length !== 1) {
return false;
}
var file = this.mergeData.rawFiles[0];
return file.type.indexOf('image') === 0;
};
ns.ImportWizard.prototype.hasSinglePiskelFile_ = function () {
if (this.mergeData.rawFiles.length !== 1) {
return false;
}
var file = this.mergeData.rawFiles[0];
return (/\.piskel$/).test(file.name);
};
})();

View File

@ -1,65 +0,0 @@
(function () {
var ns = $.namespace('pskl.controller.dialogs.importwizard.steps');
ns.AbstractImportStep = function (piskelController, importController, container) {
this.piskelController = piskelController;
this.container = container;
this.importController = importController;
this.mergeData = this.importController.mergeData;
};
ns.AbstractImportStep.prototype.init = function () {
this.nextButton = this.container.querySelector('.import-next-button');
this.backButton = this.container.querySelector('.import-back-button');
this.addEventListener(this.nextButton, 'click', this.onNextClick);
this.addEventListener(this.backButton, 'click', this.onBackClick);
};
ns.AbstractImportStep.prototype.addEventListener = function (el, type, cb) {
pskl.utils.Event.addEventListener(el, type, cb, this);
};
ns.AbstractImportStep.prototype.destroy = function () {
if (this.framePickerWidget) {
this.framePickerWidget.destroy();
}
pskl.utils.Event.removeAllEventListeners(this);
};
ns.AbstractImportStep.prototype.onNextClick = function () {
this.importController.next(this);
};
ns.AbstractImportStep.prototype.onBackClick = function () {
this.importController.back(this);
};
ns.AbstractImportStep.prototype.onShow = function () {
var mergePiskel = this.mergeData.mergePiskel;
if (!mergePiskel) {
return;
}
if (!this.framePickerWidget) {
var framePickerContainer = this.container.querySelector('.import-preview');
this.framePickerWidget = new pskl.widgets.FramePicker(mergePiskel, framePickerContainer);
this.framePickerWidget.init();
} else if (this.framePickerWidget.piskel != mergePiskel) {
// If the piskel displayed by the frame picker is different from the previous one,
// refresh the widget.
this.framePickerWidget.piskel = mergePiskel;
this.framePickerWidget.setFrameIndex(1);
}
var metaHtml = pskl.utils.Template.getAndReplace('import-meta-content', {
name : mergePiskel.getDescriptor().name,
dimensions : pskl.utils.StringUtils.formatSize(mergePiskel.getWidth(), mergePiskel.getHeight()),
frames : mergePiskel.getFrameCount(),
layers : mergePiskel.getLayers().length
});
this.container.querySelector('.import-meta').innerHTML = metaHtml;
};
})();

View File

@ -1,109 +0,0 @@
(function () {
var ns = $.namespace('pskl.controller.dialogs.importwizard.steps');
ns.AdjustSize = function (piskelController, importController, container) {
this.superclass.constructor.apply(this, arguments);
};
ns.AdjustSize.OPTIONS = {
KEEP: 'keep',
EXPAND: 'expand'
};
pskl.utils.inherit(ns.AdjustSize, ns.AbstractImportStep);
ns.AdjustSize.prototype.init = function () {
this.superclass.init.call(this);
// Create anchor widget
var anchorContainer = this.container.querySelector('.import-resize-anchor-container');
this.anchorWidget = new pskl.widgets.AnchorWidget(anchorContainer, this.onAnchorChange_.bind(this));
this.anchorWidget.setOrigin('TOPLEFT');
this.resizeInfoContainer = this.container.querySelector('.import-resize-info');
this.addEventListener(this.resizeInfoContainer, 'change', this.onResizeOptionChange_);
// By default, set the mode to expand to avoid losing any image content.
this.mergeData.resize = ns.AdjustSize.OPTIONS.EXPAND;
};
ns.AdjustSize.prototype.destroy = function () {
this.anchorWidget.destroy();
this.superclass.destroy.call(this);
};
ns.AdjustSize.prototype.onShow = function () {
this.refresh_();
this.superclass.onShow.call(this);
};
ns.AdjustSize.prototype.refresh_ = function () {
var isBigger = this.isImportedPiskelBigger_();
var keep = this.mergeData.resize === ns.AdjustSize.OPTIONS.KEEP;
// Refresh resize partial
var size = this.formatPiskelSize_(this.piskelController.getPiskel());
var newSize = this.formatPiskelSize_(this.mergeData.mergePiskel);
var markup;
if (isBigger) {
markup = pskl.utils.Template.getAndReplace('import-resize-bigger-partial', {
size : size,
newSize : newSize,
keepChecked : keep ? 'checked="checked"' : '',
expandChecked : keep ? '' : 'checked="checked"'
});
} else {
markup = pskl.utils.Template.getAndReplace('import-resize-smaller-partial', {
size : size,
newSize : newSize
});
}
this.resizeInfoContainer.innerHTML = markup;
// Update anchor widget
if (this.mergeData.origin) {
this.anchorWidget.setOrigin(this.mergeData.origin);
}
// Update anchor widget info
var anchorInfo = this.container.querySelector('.import-resize-anchor-info');
if (isBigger && keep) {
anchorInfo.innerHTML = [
'<div class="import-resize-warning">',
' Imported content will be cropped!',
'</div>',
'Select crop anchor:'
].join('');
} else if (isBigger) {
anchorInfo.innerHTML = 'Select resize anchor:';
} else {
anchorInfo.innerHTML = 'Select position anchor:';
}
};
ns.AdjustSize.prototype.onAnchorChange_ = function (origin) {
this.mergeData.origin = origin;
};
ns.AdjustSize.prototype.onResizeOptionChange_ = function () {
var value = this.resizeInfoContainer.querySelector(':checked').value;
if (this.mergeData.resize != value) {
this.mergeData.resize = value;
this.refresh_();
}
};
ns.AdjustSize.prototype.isImportedPiskelBigger_ = function () {
var piskel = this.mergeData.mergePiskel;
if (!piskel) {
return false;
}
return piskel.width > this.piskelController.getWidth() ||
piskel.height > this.piskelController.getHeight();
};
ns.AdjustSize.prototype.formatPiskelSize_ = function (piskel) {
return pskl.utils.StringUtils.formatSize(piskel.width, piskel.height);
};
})();

Some files were not shown because too many files have changed in this diff Show More