mirror of
https://github.com/piskelapp/piskel.git
synced 2023-08-10 21:12:52 +03:00
Merge pull request #143 from juliandescottes/add-keyboard-shortcuts
Add keyboard shortcuts
This commit is contained in:
@@ -7,8 +7,9 @@
|
||||
ns.HistoryService.prototype.init = function () {
|
||||
|
||||
$.subscribe(Events.TOOL_RELEASED, this.saveState.bind(this));
|
||||
$.subscribe(Events.UNDO, this.undo.bind(this));
|
||||
$.subscribe(Events.REDO, this.redo.bind(this));
|
||||
|
||||
pskl.app.shortcutService.addShortcut('ctrl+Z', this.undo.bind(this));
|
||||
pskl.app.shortcutService.addShortcut('ctrl+Y', this.redo.bind(this));
|
||||
};
|
||||
|
||||
ns.HistoryService.prototype.saveState = function () {
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
(function () {
|
||||
var ns = $.namespace("pskl.service");
|
||||
|
||||
ns.KeyboardEventService = function () {};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.KeyboardEventService.prototype.KeyboardActions_ = {
|
||||
|
||||
"ctrl" : {
|
||||
"z" : Events.UNDO,
|
||||
"y" : Events.REDO,
|
||||
"x" : Events.CUT,
|
||||
"c" : Events.COPY,
|
||||
"v" : Events.PASTE
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.KeyboardEventService.prototype.CharCodeToKeyCodeMap_ = {
|
||||
|
||||
90 : "z",
|
||||
89 : "y",
|
||||
88 : "x",
|
||||
67 : "c",
|
||||
86 : "v"
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.KeyboardEventService.prototype.onKeyUp_ = function(evt) {
|
||||
var isMac = false;
|
||||
if (navigator.appVersion.indexOf("Mac")!=-1) {
|
||||
// Welcome in mac world where vowels are consons and meta used instead of ctrl:
|
||||
isMac = true;
|
||||
}
|
||||
|
||||
if (isMac ? evt.metaKey : evt.ctrlKey) {
|
||||
// Get key pressed:
|
||||
var letter = this.CharCodeToKeyCodeMap_[evt.which];
|
||||
if(letter) {
|
||||
var eventToTrigger = this.KeyboardActions_.ctrl[letter];
|
||||
if(eventToTrigger) {
|
||||
$.publish(eventToTrigger);
|
||||
|
||||
evt.preventDefault();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
ns.KeyboardEventService.prototype.init = function() {
|
||||
$(document.body).keydown($.proxy(this.onKeyUp_, this));
|
||||
};
|
||||
|
||||
})();
|
||||
104
js/service/keyboard/CheatsheetService.js
Normal file
104
js/service/keyboard/CheatsheetService.js
Normal file
@@ -0,0 +1,104 @@
|
||||
(function () {
|
||||
var ns = $.namespace('pskl.service.keyboard');
|
||||
|
||||
ns.CheatsheetService = function () {
|
||||
this.isDisplayed_ = false;
|
||||
};
|
||||
|
||||
ns.CheatsheetService.prototype.init = function () {
|
||||
this.cheatsheetEl_ = document.getElementById('cheatsheet-wrapper');
|
||||
if (!this.cheatsheetEl_) {
|
||||
throw 'cheatsheetEl_ DOM element could not be retrieved';
|
||||
}
|
||||
this.initMarkup_();
|
||||
pskl.app.shortcutService.addShortcut('shift+?', this.toggleCheatsheet_.bind(this));
|
||||
pskl.app.shortcutService.addShortcut('?', this.toggleCheatsheet_.bind(this));
|
||||
$.subscribe(Events.TOGGLE_HELP, this.toggleCheatsheet_.bind(this));
|
||||
$.subscribe(Events.ESCAPE, this.onEscape_.bind(this));
|
||||
};
|
||||
|
||||
ns.CheatsheetService.prototype.toggleCheatsheet_ = function () {
|
||||
if (this.isDisplayed_) {
|
||||
this.hideCheatsheet_();
|
||||
} else {
|
||||
this.showCheatsheet_();
|
||||
}
|
||||
};
|
||||
|
||||
ns.CheatsheetService.prototype.onEscape_ = function () {
|
||||
if (this.isDisplayed_) {
|
||||
this.hideCheatsheet_();
|
||||
}
|
||||
};
|
||||
|
||||
ns.CheatsheetService.prototype.showCheatsheet_ = function () {
|
||||
pskl.app.shortcutService.addShortcut('ESC', this.hideCheatsheet_.bind(this));
|
||||
this.cheatsheetEl_.style.display = 'block';
|
||||
this.isDisplayed_ = true;
|
||||
};
|
||||
|
||||
|
||||
ns.CheatsheetService.prototype.hideCheatsheet_ = function () {
|
||||
pskl.app.shortcutService.removeShortcut('ESC');
|
||||
this.cheatsheetEl_.style.display = 'none';
|
||||
this.isDisplayed_ = false;
|
||||
};
|
||||
|
||||
ns.CheatsheetService.prototype.initMarkup_ = function () {
|
||||
this.initMarkupForTools_();
|
||||
this.initMarkupForMisc_();
|
||||
};
|
||||
|
||||
ns.CheatsheetService.prototype.initMarkupForTools_ = function () {
|
||||
var shortcutTemplate = pskl.utils.Template.get('cheatsheet-shortcut-template');
|
||||
|
||||
var toolShortcutsContainer = $('.cheatsheet-tool-shortcuts', this.cheatsheetEl_).get(0);
|
||||
var tools = pskl.app.toolController.tools;
|
||||
for (var i = 0 ; i < tools.length ; i++) {
|
||||
var tool = tools[i];
|
||||
var shortcutEl = pskl.utils.Template.createFromHTML(
|
||||
pskl.utils.Template.replace(shortcutTemplate, {
|
||||
shortcutIcon : 'tool-icon ' + tool.instance.toolId,
|
||||
shortcutDescription : tool.instance.helpText,
|
||||
shortcutKey : tool.shortcut
|
||||
})
|
||||
);
|
||||
toolShortcutsContainer.appendChild(shortcutEl);
|
||||
}
|
||||
};
|
||||
|
||||
ns.CheatsheetService.prototype.initMarkupForMisc_ = function () {
|
||||
var shortcutTemplate = pskl.utils.Template.get('cheatsheet-shortcut-template');
|
||||
|
||||
var miscShortcutsContainer = $('.cheatsheet-misc-shortcuts', this.cheatsheetEl_).get(0);
|
||||
var toDescriptor = function (shortcut, description) {
|
||||
return {shortcut:shortcut, description:description};
|
||||
};
|
||||
var miscKeys = [
|
||||
toDescriptor('X', 'Swap primary/secondary colors'),
|
||||
toDescriptor('D', 'Reset default colors'),
|
||||
toDescriptor('ctrl + X', 'Cut selection'),
|
||||
toDescriptor('ctrl + C', 'Copy selection'),
|
||||
toDescriptor('ctrl + V', 'Paste selection'),
|
||||
toDescriptor('ctrl + Z', 'Undo'),
|
||||
toDescriptor('ctrl + Y', 'Redo'),
|
||||
toDescriptor('↑', 'Select previous frame'), /* ASCII for up-arrow */
|
||||
toDescriptor('↓', 'Select next frame'), /* ASCII for down-arrow */
|
||||
toDescriptor('N', 'Create new frame'),
|
||||
toDescriptor('shift + N', 'Duplicate selected frame'),
|
||||
toDescriptor('shift + ?', 'Open/Close this popup')
|
||||
];
|
||||
for (var i = 0 ; i < miscKeys.length ; i++) {
|
||||
var key = miscKeys[i];
|
||||
var shortcutEl = pskl.utils.Template.createFromHTML(
|
||||
pskl.utils.Template.replace(shortcutTemplate, {
|
||||
shortcutIcon : '',
|
||||
shortcutDescription : key.description,
|
||||
shortcutKey : key.shortcut
|
||||
})
|
||||
);
|
||||
miscShortcutsContainer.appendChild(shortcutEl);
|
||||
}
|
||||
};
|
||||
|
||||
})();
|
||||
24
js/service/keyboard/KeycodeTranslator.js
Normal file
24
js/service/keyboard/KeycodeTranslator.js
Normal file
@@ -0,0 +1,24 @@
|
||||
(function () {
|
||||
var specialKeys = {
|
||||
191 : "?",
|
||||
27 : "esc",
|
||||
38 : "up",
|
||||
40 : "down"
|
||||
};
|
||||
|
||||
var ns = $.namespace('pskl.service.keyboard');
|
||||
|
||||
ns.KeycodeTranslator= {
|
||||
toChar : function (keycode) {
|
||||
if (keycode >= 48 && keycode <= 57) {
|
||||
// key is 0-9
|
||||
return (keycode - 48) + "";
|
||||
} else if (keycode >= 65 && keycode <= 90) {
|
||||
// key is a-z, use base 36 to get the string representation
|
||||
return (keycode - 65 + 10).toString(36);
|
||||
} else {
|
||||
return specialKeys[keycode];
|
||||
}
|
||||
}
|
||||
};
|
||||
})();
|
||||
90
js/service/keyboard/ShortcutService.js
Normal file
90
js/service/keyboard/ShortcutService.js
Normal file
@@ -0,0 +1,90 @@
|
||||
(function () {
|
||||
var ns = $.namespace('pskl.service.keyboard');
|
||||
|
||||
ns.ShortcutService = function () {
|
||||
this.shortcuts_ = {};
|
||||
};
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
ns.ShortcutService.prototype.init = function() {
|
||||
$(document.body).keydown($.proxy(this.onKeyUp_, this));
|
||||
};
|
||||
|
||||
ns.ShortcutService.prototype.addShortcut = function (rawKey, callback) {
|
||||
var parsedKey = this.parseKey_(rawKey.toLowerCase());
|
||||
|
||||
var key = parsedKey.key,
|
||||
meta = parsedKey.meta;
|
||||
|
||||
this.shortcuts_[key] = this.shortcuts_[key] || {};
|
||||
|
||||
if (this.shortcuts_[key][meta]) {
|
||||
throw 'Shortcut ' + meta + ' + ' + key + ' already registered';
|
||||
} else {
|
||||
this.shortcuts_[key][meta] = callback;
|
||||
}
|
||||
};
|
||||
|
||||
ns.ShortcutService.prototype.removeShortcut = function (rawKey) {
|
||||
var parsedKey = this.parseKey_(rawKey.toLowerCase());
|
||||
|
||||
var key = parsedKey.key,
|
||||
meta = parsedKey.meta;
|
||||
|
||||
this.shortcuts_[key] = this.shortcuts_[key] || {};
|
||||
|
||||
this.shortcuts_[key][meta] = null;
|
||||
};
|
||||
|
||||
ns.ShortcutService.prototype.parseKey_ = function (key) {
|
||||
var meta = 'normal';
|
||||
if (key.indexOf('ctrl+') === 0) {
|
||||
meta = 'ctrl';
|
||||
key = key.replace('ctrl+', '');
|
||||
} else if (key.indexOf('shift+') === 0) {
|
||||
meta = 'shift';
|
||||
key = key.replace('shift+', '');
|
||||
}
|
||||
return {meta : meta, key : key};
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.ShortcutService.prototype.onKeyUp_ = function(evt) {
|
||||
// jquery names FTW ...
|
||||
var keycode = evt.which;
|
||||
var charkey = pskl.service.keyboard.KeycodeTranslator.toChar(keycode);
|
||||
|
||||
var keyShortcuts = this.shortcuts_[charkey];
|
||||
if(keyShortcuts) {
|
||||
var cb;
|
||||
if (this.isCtrlKeyPressed_(evt)) {
|
||||
cb = keyShortcuts.ctrl;
|
||||
} else if (this.isShiftKeyPressed_(evt)) {
|
||||
cb = keyShortcuts.shift;
|
||||
} else {
|
||||
cb = keyShortcuts.normal;
|
||||
}
|
||||
|
||||
if(cb) {
|
||||
cb(charkey);
|
||||
evt.preventDefault();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ns.ShortcutService.prototype.isCtrlKeyPressed_ = function (evt) {
|
||||
return this.isMac_() ? evt.metaKey : evt.ctrlKey;
|
||||
};
|
||||
|
||||
ns.ShortcutService.prototype.isShiftKeyPressed_ = function (evt) {
|
||||
return evt.shiftKey;
|
||||
};
|
||||
|
||||
ns.ShortcutService.prototype.isMac_ = function () {
|
||||
return navigator.appVersion.indexOf("Mac") != -1;
|
||||
};
|
||||
})();
|
||||
Reference in New Issue
Block a user