mirror of
https://github.com/piskelapp/piskel.git
synced 2023-08-10 21:12:52 +03:00
Issue #287 : Edit shortcuts from cheatsheet window (WIP)
This commit is contained in:
parent
2e3558ef08
commit
676cbd17ea
3
src/css/animations.css
Normal file
3
src/css/animations.css
Normal file
@ -0,0 +1,3 @@
|
||||
@keyframes fade {
|
||||
50% { opacity: 0.5; }
|
||||
}
|
@ -14,6 +14,7 @@
|
||||
background-image:url('../img/keyboard.png');
|
||||
background-size:35px 20px;
|
||||
background-repeat:no-repeat;
|
||||
|
||||
opacity: 0.5;
|
||||
z-index: 11000;
|
||||
transition : opacity 0.3s;
|
||||
@ -25,68 +26,78 @@
|
||||
|
||||
.cheatsheet-container {
|
||||
box-sizing: border-box;
|
||||
-moz-box-sizing : border-box;
|
||||
|
||||
padding: 20px 3%;
|
||||
border-radius: 3px;
|
||||
background: rgba(0,0,0,0.9);
|
||||
background-color: rgba(0,0,0,0.9);
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.cheatsheet-container .cheatsheet-title {
|
||||
font-size:24px;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.cheatsheet-container .cheatsheet-title:nth-of-type(2) {
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
.cheatsheet-container .cheatsheet-title:nth-of-type(1) {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.cheatsheet-section {
|
||||
float: left;
|
||||
width : 33%;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
padding : 0 20px;
|
||||
}
|
||||
|
||||
.cheatsheet-shortcut {
|
||||
overflow: hidden;
|
||||
margin: 10px 0;
|
||||
cursor : pointer;
|
||||
}
|
||||
|
||||
.cheatsheet-icon.tool-icon {
|
||||
float: left;
|
||||
display: inline-block;
|
||||
|
||||
height: 30px;
|
||||
width: 30px;
|
||||
margin: 0 20px 0 0;
|
||||
margin: 0 10px 0 0;
|
||||
|
||||
background-size: 20px 20px;
|
||||
background-position: 5px 5px;
|
||||
}
|
||||
|
||||
.cheatsheet-description {
|
||||
font-family:Courier;
|
||||
color: white;
|
||||
font-size : 13px;
|
||||
margin-left: 20px;
|
||||
font-size : 14px;
|
||||
margin-left: 10px;
|
||||
line-height : 30px;
|
||||
}
|
||||
|
||||
.cheatsheet-key {
|
||||
box-sizing: border-box;
|
||||
display : inline-block;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
line-height: 26px;
|
||||
padding: 0 10px;
|
||||
|
||||
border : 1px solid gold;
|
||||
border : 2px solid gold;
|
||||
border-radius: 2px;
|
||||
|
||||
box-sizing: border-box;
|
||||
-moz-box-sizing : border-box;
|
||||
|
||||
text-align: center;
|
||||
font-family:Courier;
|
||||
font-weight: bold;
|
||||
font-size : 18px;
|
||||
color: gold;
|
||||
}
|
||||
|
||||
.cheatsheet-shorcut-conflict .cheatsheet-key {
|
||||
border-color: red;
|
||||
color: red;
|
||||
}
|
||||
|
||||
.cheatsheet-shortcut-editing .cheatsheet-key{
|
||||
animation: fade .5s infinite;
|
||||
}
|
||||
.cheatsheet-shortcut-undefined .cheatsheet-key{
|
||||
border-color: red;
|
||||
color: red;
|
||||
}
|
@ -38,6 +38,7 @@
|
||||
$('#tool-section').mousedown($.proxy(this.onToolIconClicked_, this));
|
||||
|
||||
$.subscribe(Events.SELECT_TOOL, this.onSelectToolEvent_.bind(this));
|
||||
$.subscribe(Events.SHORTCUTS_CHANGED, this.createToolsDom_.bind(this));
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1,94 +1,96 @@
|
||||
(function () {
|
||||
var ns = $.namespace('pskl.controller.dialogs');
|
||||
|
||||
ns.CheatsheetController = function () {
|
||||
this.shortcuts = pskl.service.keyboard.Shortcuts;
|
||||
};
|
||||
ns.CheatsheetController = function () {};
|
||||
|
||||
pskl.utils.inherit(ns.CheatsheetController, ns.AbstractDialogController);
|
||||
|
||||
ns.CheatsheetController.prototype.init = function () {
|
||||
this.cheatsheetEl = document.getElementById('cheatsheetContainer');
|
||||
if (!this.cheatsheetEl) {
|
||||
throw 'cheatsheetEl DOM element could not be retrieved';
|
||||
}
|
||||
this.superclass.init.call(this);
|
||||
|
||||
this.cheatsheetEl = document.getElementById('cheatsheetContainer');
|
||||
this.eventTrapInput = document.getElementById('cheatsheet-event-trap');
|
||||
|
||||
pskl.utils.Event.addEventListener('.cheatsheet-restore-defaults', 'click', this.onRestoreDefaultsClick_, this);
|
||||
pskl.utils.Event.addEventListener(this.cheatsheetEl, 'click', this.onCheatsheetClick_, this);
|
||||
pskl.utils.Event.addEventListener(this.eventTrapInput, 'keydown', this.onEventTrapKeydown_, this);
|
||||
|
||||
$.subscribe(Events.SHORTCUTS_CHANGED, this.onShortcutsChanged_.bind(this));
|
||||
|
||||
this.initMarkup_();
|
||||
};
|
||||
|
||||
ns.CheatsheetController.prototype.destroy = function () {
|
||||
this.eventTrapInput.blur();
|
||||
pskl.utils.Event.removeAllEventListeners();
|
||||
this.cheatsheetEl = null;
|
||||
};
|
||||
|
||||
ns.CheatsheetController.prototype.onRestoreDefaultsClick_ = function () {
|
||||
pskl.service.keyboard.Shortcuts.restoreDefaultShortcuts();
|
||||
};
|
||||
|
||||
ns.CheatsheetController.prototype.onShortcutsChanged_ = function () {
|
||||
this.initMarkup_();
|
||||
};
|
||||
|
||||
ns.CheatsheetController.prototype.onCheatsheetClick_ = function (evt) {
|
||||
var shortcutId = pskl.utils.Dom.getData(evt.target, 'shortcutId');
|
||||
if (!shortcutId) {
|
||||
pskl.utils.Dom.removeClass('cheatsheet-shortcut-editing');
|
||||
|
||||
var shortcutEl = pskl.utils.Dom.getParentWithData(evt.target, 'shortcutId');
|
||||
if (!shortcutEl) {
|
||||
return;
|
||||
}
|
||||
|
||||
shortcutEl.classList.add('cheatsheet-shortcut-editing');
|
||||
this.eventTrapInput.focus();
|
||||
};
|
||||
|
||||
ns.CheatsheetController.prototype.onEventTrapKeydown_ = function (evt) {
|
||||
var editedShortcutEl = document.querySelector('.cheatsheet-shortcut-editing');
|
||||
if (!editedShortcutEl) {
|
||||
return;
|
||||
}
|
||||
|
||||
var shortcutKeyObject = pskl.service.keyboard.KeyUtils.createKeyFromEvent(evt);
|
||||
var shortcutKeyString = pskl.service.keyboard.KeyUtils.stringify(shortcutKeyObject);
|
||||
|
||||
var shortcutId = editedShortcutEl.dataset.shortcutId;
|
||||
var shortcut = pskl.service.keyboard.Shortcuts.getShortcutById(shortcutId);
|
||||
var newKeys = window.prompt('Please enter the new key', shortcut.getKeys().join(', '));
|
||||
shortcut.updateKeys(newKeys);
|
||||
pskl.service.keyboard.Shortcuts.updateShortcut(shortcut, shortcutKeyString);
|
||||
|
||||
this.eventTrapInput.blur();
|
||||
|
||||
evt.preventDefault();
|
||||
};
|
||||
|
||||
ns.CheatsheetController.prototype.initMarkup_ = function () {
|
||||
this.initMarkupForTools_();
|
||||
this.initMarkupForMisc_();
|
||||
this.initMarkupForColors_();
|
||||
this.initMarkupForSelection_();
|
||||
this.initMarkupForCategory_('TOOL', '.cheatsheet-tool-shortcuts', this.getToolIconClass_);
|
||||
this.initMarkupForCategory_('MISC', '.cheatsheet-misc-shortcuts');
|
||||
this.initMarkupForCategory_('COLOR', '.cheatsheet-color-shortcuts');
|
||||
this.initMarkupForCategory_('SELECTION', '.cheatsheet-selection-shortcuts');
|
||||
this.initMarkupForCategory_('STORAGE', '.cheatsheet-storage-shortcuts');
|
||||
};
|
||||
|
||||
ns.CheatsheetController.prototype.initMarkupForTools_ = function () {
|
||||
var descriptors = this.createShortcutDescriptors_(this.shortcuts.TOOL, this.getToolShortcutClassname_);
|
||||
this.initMarkupForDescriptors_(descriptors, '.cheatsheet-tool-shortcuts');
|
||||
};
|
||||
|
||||
ns.CheatsheetController.prototype.getToolShortcutClassname_ = function (shortcut) {
|
||||
ns.CheatsheetController.prototype.getToolIconClass_ = function (shortcut) {
|
||||
return 'tool-icon ' + shortcut.getId();
|
||||
};
|
||||
|
||||
ns.CheatsheetController.prototype.initMarkupForMisc_ = function () {
|
||||
var descriptors = this.createShortcutDescriptors_(this.shortcuts.MISC);
|
||||
this.initMarkupForDescriptors_(descriptors, '.cheatsheet-misc-shortcuts');
|
||||
};
|
||||
ns.CheatsheetController.prototype.initMarkupForCategory_ = function (category, container, iconClassProvider) {
|
||||
var shortcutMap = pskl.service.keyboard.Shortcuts[category];
|
||||
|
||||
ns.CheatsheetController.prototype.initMarkupForColors_ = function () {
|
||||
var descriptors = this.createShortcutDescriptors_(this.shortcuts.COLOR);
|
||||
this.initMarkupForDescriptors_(descriptors, '.cheatsheet-colors-shortcuts');
|
||||
};
|
||||
|
||||
ns.CheatsheetController.prototype.initMarkupForSelection_ = function () {
|
||||
var descriptors = this.createShortcutDescriptors_(this.shortcuts.SELECTION);
|
||||
this.initMarkupForDescriptors_(descriptors, '.cheatsheet-selection-shortcuts');
|
||||
};
|
||||
|
||||
ns.CheatsheetController.prototype.createShortcutDescriptors_ = function (shortcutMap, classnameProvider) {
|
||||
return Object.keys(shortcutMap).map(function (shortcutKey) {
|
||||
var shortcut = shortcutMap[shortcutKey];
|
||||
var classname = typeof classnameProvider == 'function' ? classnameProvider(shortcut) : '';
|
||||
return this.toDescriptor_(shortcut, classname);
|
||||
var descriptors = Object.keys(shortcutMap).map(function (shortcutKey) {
|
||||
return this.toDescriptor_(shortcutMap[shortcutKey], iconClassProvider);
|
||||
}.bind(this));
|
||||
|
||||
this.initMarkupForDescriptors_(descriptors, container);
|
||||
};
|
||||
|
||||
ns.CheatsheetController.prototype.toDescriptor_ = function (shortcut, icon) {
|
||||
var key = shortcut.getKey();
|
||||
if (pskl.utils.UserAgent.isMac) {
|
||||
key = key.replace('ctrl', 'cmd');
|
||||
}
|
||||
key = key.replace('up', '↑');
|
||||
key = key.replace('down', '↓');
|
||||
key = key.replace(/>/g, '>');
|
||||
key = key.replace(/</g, '<');
|
||||
key = key.replace(/^(.*[^ ])\+([^ ].*)$/g, '$1 + $2');
|
||||
|
||||
ns.CheatsheetController.prototype.toDescriptor_ = function (shortcut, iconClassProvider) {
|
||||
var iconClass = typeof iconClassProvider == 'function' ? iconClassProvider(shortcut) : '';
|
||||
return {
|
||||
'key' : key,
|
||||
'id' : shortcut.getId(),
|
||||
'description' : shortcut.getDescription(),
|
||||
'icon' : icon
|
||||
'shortcut' : shortcut,
|
||||
'iconClass' : iconClass
|
||||
};
|
||||
};
|
||||
|
||||
@ -97,19 +99,37 @@
|
||||
if (!container) {
|
||||
return;
|
||||
}
|
||||
var markupArray = descriptors.map(this.getMarkupForDescriptor_);
|
||||
var markupArray = descriptors.map(this.getMarkupForDescriptor_.bind(this));
|
||||
container.innerHTML = markupArray.join('');
|
||||
};
|
||||
|
||||
ns.CheatsheetController.prototype.getMarkupForDescriptor_ = function (descriptor) {
|
||||
var shortcutTemplate = pskl.utils.Template.get('cheatsheet-shortcut-template');
|
||||
var shortcut = descriptor.shortcut;
|
||||
var description = shortcut.isCustom() ? shortcut.getDescription() + ' *' : shortcut.getDescription();
|
||||
|
||||
var shortcutClass = shortcut.isUndefined() ? 'cheatsheet-shortcut-undefined' : '';
|
||||
var markup = pskl.utils.Template.replace(shortcutTemplate, {
|
||||
shortcutId : descriptor.id,
|
||||
shortcutIcon : descriptor.icon,
|
||||
shortcutDescription : descriptor.description,
|
||||
shortcutKey : descriptor.key
|
||||
shortcutId : shortcut.getId(),
|
||||
shortcutIcon : descriptor.iconClass,
|
||||
shortcutDescription : description,
|
||||
shortcutKey : this.formatKey_(shortcut.getDisplayKey()),
|
||||
shortcutClass : shortcutClass
|
||||
});
|
||||
|
||||
return markup;
|
||||
};
|
||||
|
||||
ns.CheatsheetController.prototype.formatKey_ = function (key) {
|
||||
if (pskl.utils.UserAgent.isMac) {
|
||||
key = key.replace('ctrl', 'cmd');
|
||||
}
|
||||
key = key.replace(/up/i, '↑');
|
||||
key = key.replace(/down/i, '↓');
|
||||
key = key.replace(/>/g, '>');
|
||||
key = key.replace(/</g, '<');
|
||||
// add spaces around '+' delimiters
|
||||
key = key.replace(/([^ ])\+([^ ])/g, '$1 + $2');
|
||||
return key;
|
||||
};
|
||||
})();
|
||||
|
@ -129,7 +129,7 @@
|
||||
}
|
||||
|
||||
event.preventDefault = function () {};
|
||||
pskl.app.shortcutService.onKeyUp_(event);
|
||||
pskl.app.shortcutService.onKeyDown_(event);
|
||||
};
|
||||
|
||||
ns.DrawingTestPlayer.prototype.playColorEvent_ = function (recordEvent) {
|
||||
|
@ -1 +0,0 @@
|
||||
|
80
src/js/service/keyboard/KeyUtils.js
Normal file
80
src/js/service/keyboard/KeyUtils.js
Normal file
@ -0,0 +1,80 @@
|
||||
(function () {
|
||||
var ns = $.namespace('pskl.service.keyboard');
|
||||
|
||||
ns.KeyUtils = {
|
||||
createKeyFromString : function (shortcutKeyString) {
|
||||
shortcutKeyString = shortcutKeyString.toLowerCase();
|
||||
var modifiers = {
|
||||
alt : shortcutKeyString.indexOf('alt+') != -1,
|
||||
shift : shortcutKeyString.indexOf('shift+') != -1,
|
||||
ctrl : shortcutKeyString.indexOf('ctrl+') != -1
|
||||
};
|
||||
|
||||
var parts = shortcutKeyString.split(/\+(?!$)/);
|
||||
var key = parts[parts.length - 1];
|
||||
|
||||
return {
|
||||
key : key.toUpperCase(),
|
||||
modifiers : modifiers
|
||||
};
|
||||
},
|
||||
|
||||
createKeyFromEvent : function (evt) {
|
||||
var keycode = evt.which;
|
||||
var key = ns.KeycodeTranslator.toChar(keycode);
|
||||
if (!key) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
key : key.toUpperCase(),
|
||||
modifiers : {
|
||||
alt : evt.altKey,
|
||||
shift : evt.shiftKey,
|
||||
ctrl : ns.KeyUtils.isCtrlKeyPressed_(evt)
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
equals : function (key1, key2) {
|
||||
key1 = typeof key1 === 'string' ? ns.KeyUtils.createKeyFromString(key1) : key1;
|
||||
key2 = typeof key2 === 'string' ? ns.KeyUtils.createKeyFromString(key2) : key2;
|
||||
|
||||
var isKeyMatching = key1.key === key2.key &&
|
||||
key1.modifiers.alt === key2.modifiers.alt &&
|
||||
key1.modifiers.shift === key2.modifiers.shift &&
|
||||
key1.modifiers.ctrl === key2.modifiers.ctrl;
|
||||
|
||||
return isKeyMatching;
|
||||
},
|
||||
|
||||
stringify : function (shortcutKeyObject) {
|
||||
var modifierString = ns.KeyUtils.getModifiersString(shortcutKeyObject.modifiers);
|
||||
if (modifierString) {
|
||||
return modifierString + '+' + shortcutKeyObject.key;
|
||||
}
|
||||
|
||||
return shortcutKeyObject.key;
|
||||
},
|
||||
|
||||
getModifiersString : function (modifiers) {
|
||||
var keyBuffer = [];
|
||||
|
||||
if (modifiers.alt) {
|
||||
keyBuffer.push('alt');
|
||||
}
|
||||
if (modifiers.ctrl) {
|
||||
keyBuffer.push('ctrl');
|
||||
}
|
||||
if (modifiers.shift) {
|
||||
keyBuffer.push('shift');
|
||||
}
|
||||
|
||||
return keyBuffer.join('+');
|
||||
},
|
||||
|
||||
isCtrlKeyPressed_ : function (evt) {
|
||||
return pskl.utils.UserAgent.isMac ? evt.metaKey : evt.ctrlKey;
|
||||
}
|
||||
};
|
||||
})();
|
@ -6,14 +6,17 @@
|
||||
*
|
||||
* @param {String} id Shortcut identifier
|
||||
* @param {String} description Shortcut description
|
||||
* @param {String|Array<String>} defaultKey combination of modifiers + ([a-z0-9] or a special key)
|
||||
* @param {String|Array<String>} defaultKeys combination of modifiers + ([a-z0-9] or a special key)
|
||||
* Special keys are defined in KeycodeTranslator. If the shortcut supports several keys,
|
||||
* use an array of String keys
|
||||
*/
|
||||
ns.Shortcut = function (id, description, defaultKey, displayKey) {
|
||||
ns.Shortcut = function (id, description, defaultKeys, displayKey) {
|
||||
this.id_ = id;
|
||||
this.description_ = description;
|
||||
this.defaultKey_ = defaultKey;
|
||||
if (typeof defaultKeys === 'string') {
|
||||
defaultKeys = [defaultKeys];
|
||||
}
|
||||
this.defaultKeys_ = defaultKeys;
|
||||
this.displayKey_ = displayKey;
|
||||
};
|
||||
|
||||
@ -32,34 +35,75 @@
|
||||
* @return {Array<String>} array of keys
|
||||
*/
|
||||
ns.Shortcut.prototype.getKeys = function () {
|
||||
var keys = pskl.UserSettings.get(this.getLocalStorageKey_()) || this.defaultKey_;
|
||||
var keys = pskl.UserSettings.get(this.getLocalStorageKey_()) || this.defaultKeys_;
|
||||
|
||||
if (typeof keys === 'string') {
|
||||
keys = [keys];
|
||||
return [keys];
|
||||
}
|
||||
|
||||
if (!Array.isArray(keys)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return keys;
|
||||
};
|
||||
|
||||
ns.Shortcut.prototype.isCustom = function () {
|
||||
var keys = this.getKeys();
|
||||
if (keys.length !== this.defaultKeys_.length) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// for some default keys
|
||||
return this.defaultKeys_.some(function (defaultKey) {
|
||||
// no match can be found in the current keys
|
||||
return !keys.some(function (key) {
|
||||
return ns.KeyUtils.equals(key, defaultKey);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
ns.Shortcut.prototype.isUndefined = function () {
|
||||
return this.getKeys().length === 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the key to be displayed for this shortcut, if
|
||||
* @return {[type]} [description]
|
||||
*/
|
||||
ns.Shortcut.prototype.getKey = function () {
|
||||
ns.Shortcut.prototype.getDisplayKey = function () {
|
||||
if (this.isUndefined()) {
|
||||
return '???';
|
||||
}
|
||||
|
||||
if (this.displayKey_) {
|
||||
return this.displayKey_;
|
||||
}
|
||||
|
||||
var keys = this.getKeys();
|
||||
if (Array.isArray(keys) && keys.length > 0) {
|
||||
return keys[0];
|
||||
}
|
||||
return this.getKeys()[0];
|
||||
};
|
||||
|
||||
return '';
|
||||
ns.Shortcut.prototype.restoreDefault = function (keys) {
|
||||
pskl.UserSettings.set(this.getLocalStorageKey_(), '');
|
||||
};
|
||||
|
||||
ns.Shortcut.prototype.updateKeys = function (keys) {
|
||||
pskl.UserSettings.set(this.getLocalStorageKey_(), keys.split(', '));
|
||||
$.publish(Events.SHORTCUTS_CHANGED);
|
||||
pskl.UserSettings.set(this.getLocalStorageKey_(), keys);
|
||||
};
|
||||
|
||||
ns.Shortcut.prototype.removeKeys = function (keysToRemove) {
|
||||
var keys = this.getKeys();
|
||||
var updatedKeys = keys.filter(function (key) {
|
||||
return !keysToRemove.some(function (keyToRemove) {
|
||||
return ns.KeyUtils.equals(key, keyToRemove);
|
||||
});
|
||||
});
|
||||
|
||||
if (updatedKeys.length !== keys.length) {
|
||||
this.updateKeys(updatedKeys);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
ns.Shortcut.prototype.getLocalStorageKey_ = function () {
|
||||
|
@ -9,7 +9,7 @@
|
||||
* @public
|
||||
*/
|
||||
ns.ShortcutService.prototype.init = function() {
|
||||
$(document.body).keydown($.proxy(this.onKeyUp_, this));
|
||||
$(document.body).keydown($.proxy(this.onKeyDown_, this));
|
||||
};
|
||||
|
||||
/**
|
||||
@ -44,61 +44,22 @@
|
||||
}
|
||||
};
|
||||
|
||||
ns.ShortcutService.prototype.parseKey_ = function (key) {
|
||||
var meta = this.getMetaKey_({
|
||||
alt : key.indexOf('alt+') != -1,
|
||||
shift : key.indexOf('shift+') != -1,
|
||||
ctrl : key.indexOf('ctrl+') != -1
|
||||
});
|
||||
|
||||
var parts = key.split(/\+(?!$)/);
|
||||
key = parts[parts.length - 1];
|
||||
return {meta : meta, key : key.toLowerCase()};
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve a comparable representation of a meta information for a key
|
||||
* 'alt' 'ctrl' and 'shift' will always be in the same order for the same meta
|
||||
*/
|
||||
ns.ShortcutService.prototype.getMetaKey_ = function (meta) {
|
||||
var keyBuffer = [];
|
||||
|
||||
if (meta.alt) {
|
||||
keyBuffer.push('alt');
|
||||
}
|
||||
if (meta.ctrl) {
|
||||
keyBuffer.push('ctrl');
|
||||
}
|
||||
if (meta.shift) {
|
||||
keyBuffer.push('shift');
|
||||
}
|
||||
|
||||
return keyBuffer.join('+') || 'normal';
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.ShortcutService.prototype.onKeyUp_ = function(evt) {
|
||||
if (this.isInInput_(evt)) {
|
||||
ns.ShortcutService.prototype.onKeyDown_ = function(evt) {
|
||||
var eventKey = ns.KeyUtils.createKeyFromEvent(evt);
|
||||
if (this.isInInput_(evt) || !eventKey) {
|
||||
return;
|
||||
}
|
||||
|
||||
var keycode = evt.which;
|
||||
var eventKey = pskl.service.keyboard.KeycodeTranslator.toChar(keycode);
|
||||
var eventMeta = this.getMetaKey_({
|
||||
alt : evt.altKey,
|
||||
shift : evt.shiftKey,
|
||||
ctrl : this.isCtrlKeyPressed_(evt)
|
||||
});
|
||||
|
||||
this.shortcuts_.forEach(function (shortcutInfo) {
|
||||
shortcutInfo.shortcut.getKeys().forEach(function (key) {
|
||||
if (!this.isKeyMatching_(key, eventKey, eventMeta)) {
|
||||
shortcutInfo.shortcut.getKeys().forEach(function (shortcutKey) {
|
||||
if (!ns.KeyUtils.equals(shortcutKey, eventKey)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var bubble = shortcutInfo.callback(eventKey);
|
||||
var bubble = shortcutInfo.callback(eventKey.key);
|
||||
if (bubble !== true) {
|
||||
evt.preventDefault();
|
||||
}
|
||||
@ -111,13 +72,4 @@
|
||||
var targetTagName = evt.target.nodeName.toUpperCase();
|
||||
return targetTagName === 'INPUT' || targetTagName === 'TEXTAREA';
|
||||
};
|
||||
|
||||
ns.ShortcutService.prototype.isKeyMatching_ = function (key, eventKey, eventMeta) {
|
||||
var parsedKey = this.parseKey_(key);
|
||||
return parsedKey.key === eventKey && parsedKey.meta === eventMeta;
|
||||
};
|
||||
|
||||
ns.ShortcutService.prototype.isCtrlKeyPressed_ = function (evt) {
|
||||
return pskl.utils.UserAgent.isMac ? evt.metaKey : evt.ctrlKey;
|
||||
};
|
||||
})();
|
||||
|
@ -30,7 +30,7 @@
|
||||
SELECTION : {
|
||||
CUT : createShortcut('selection-cut', 'Cut selection', 'ctrl+X'),
|
||||
COPY : createShortcut('selection-copy', 'Copy selection', 'ctrl+C'),
|
||||
PASTE : createShortcut('selection-cut', 'Paste selection', 'ctrl+V'),
|
||||
PASTE : createShortcut('selection-paste', 'Paste selection', 'ctrl+V'),
|
||||
DELETE : createShortcut('selection-delete', 'Delete selection', ['del', 'back'])
|
||||
},
|
||||
|
||||
@ -52,9 +52,9 @@
|
||||
},
|
||||
|
||||
STORAGE : {
|
||||
OPEN : createShortcut('open', '(Desktop only) Open a .piskel file', 'ctrl+O'),
|
||||
SAVE : createShortcut('save', 'Save the current sprite', 'ctrl+S'),
|
||||
SAVE_AS : createShortcut('save-as', '(Desktop only) Save as a new .piskel file', 'ctrl+shift+S')
|
||||
OPEN : createShortcut('open', '(desktop) Open a .piskel file', 'ctrl+O'),
|
||||
SAVE_AS : createShortcut('save-as', '(desktop) Save as new', 'ctrl+shift+S')
|
||||
},
|
||||
|
||||
COLOR : {
|
||||
@ -70,18 +70,43 @@
|
||||
CATEGORIES : ['TOOL', 'SELECTION', 'MISC', 'STORAGE', 'COLOR'],
|
||||
|
||||
getShortcutById : function (id) {
|
||||
var shortcut = null;
|
||||
return pskl.utils.Array.find(ns.Shortcuts.getShortcuts(), function (shortcut) {
|
||||
return shortcut.getId() === id;
|
||||
});
|
||||
},
|
||||
|
||||
getShortcuts : function () {
|
||||
var shortcuts = [];
|
||||
ns.Shortcuts.CATEGORIES.forEach(function (category) {
|
||||
var shortcuts = ns.Shortcuts[category];
|
||||
Object.keys(shortcuts).forEach(function (shortcutKey) {
|
||||
if (shortcuts[shortcutKey].getId() === id) {
|
||||
shortcut = shortcuts[shortcutKey];
|
||||
}
|
||||
var shortcutMap = ns.Shortcuts[category];
|
||||
Object.keys(shortcutMap).forEach(function (shortcutKey) {
|
||||
shortcuts.push(shortcutMap[shortcutKey]);
|
||||
});
|
||||
});
|
||||
return shortcuts;
|
||||
},
|
||||
|
||||
return shortcut;
|
||||
updateShortcut : function (shortcut, keysString) {
|
||||
keysString = keysString.replace(/\s/g, '');
|
||||
var keys = keysString.split(',');
|
||||
ns.Shortcuts.getShortcuts().forEach(function (s) {
|
||||
if (s === shortcut) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (s.removeKeys(keys)) {
|
||||
$.publish(Events.SHOW_NOTIFICATION, [{'content': 'Shortcut key removed for ' + s.getId()}]);
|
||||
}
|
||||
});
|
||||
shortcut.updateKeys(keys);
|
||||
$.publish(Events.SHORTCUTS_CHANGED);
|
||||
},
|
||||
|
||||
restoreDefaultShortcuts : function () {
|
||||
ns.Shortcuts.getShortcuts().forEach(function (shortcut) {
|
||||
shortcut.restoreDefault();
|
||||
});
|
||||
$.publish(Events.SHORTCUTS_CHANGED);
|
||||
}
|
||||
|
||||
};
|
||||
})();
|
||||
|
@ -41,6 +41,14 @@
|
||||
if (parent !== null) {
|
||||
return parent.dataset[dataName];
|
||||
}
|
||||
},
|
||||
|
||||
removeClass : function (className, container) {
|
||||
container = container || document;
|
||||
var elements = container.querySelectorAll('.' + className);
|
||||
for (var i = 0 ; i < elements.length ; i++) {
|
||||
elements[i].classList.remove(className);
|
||||
}
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
ns.TooltipFormatter.format = function(helpText, shortcut, descriptors) {
|
||||
var tpl = pskl.utils.Template.get('tooltip-container-template');
|
||||
shortcut = shortcut ? '(' + shortcut.getKey() + ')' : '';
|
||||
shortcut = shortcut ? '(' + shortcut.getDisplayKey() + ')' : '';
|
||||
return pskl.utils.Template.replace(tpl, {
|
||||
helptext : helpText,
|
||||
shortcut : shortcut,
|
||||
|
@ -28,8 +28,8 @@
|
||||
"js/utils/FileUtils.js",
|
||||
"js/utils/FileUtilsDesktop.js",
|
||||
"js/utils/FrameUtils.js",
|
||||
"js/utils/LayerUtils.js",
|
||||
"js/utils/ImageResizer.js",
|
||||
"js/utils/LayerUtils.js",
|
||||
"js/utils/PixelUtils.js",
|
||||
"js/utils/PiskelFileUtils.js",
|
||||
"js/utils/Template.js",
|
||||
@ -158,10 +158,11 @@
|
||||
"js/service/palette/reader/PaletteTxtReader.js",
|
||||
"js/service/palette/PaletteImportService.js",
|
||||
"js/service/SavedStatusService.js",
|
||||
"js/service/keyboard/KeycodeTranslator.js",
|
||||
"js/service/keyboard/KeyUtils.js",
|
||||
"js/service/keyboard/Shortcut.js",
|
||||
"js/service/keyboard/Shortcuts.js",
|
||||
"js/service/keyboard/ShortcutService.js",
|
||||
"js/service/keyboard/KeycodeTranslator.js",
|
||||
"js/service/ImageUploadService.js",
|
||||
"js/service/CurrentColorsService.js",
|
||||
"js/service/FileDropperService.js",
|
||||
|
@ -3,6 +3,7 @@
|
||||
(typeof exports != "undefined" ? exports : pskl_exports).styles = [
|
||||
"css/reset.css",
|
||||
"css/style.css",
|
||||
"css/animations.css",
|
||||
"css/layout.css",
|
||||
"css/font-icon.css",
|
||||
"css/forms.css",
|
||||
|
@ -16,12 +16,20 @@
|
||||
<h3 class="cheatsheet-title">Selection shortcuts</h3>
|
||||
<ul class="cheatsheet-selection-shortcuts"></ul>
|
||||
<h3 class="cheatsheet-title">Color shortcuts</h3>
|
||||
<ul class="cheatsheet-colors-shortcuts"></ul>
|
||||
<ul class="cheatsheet-color-shortcuts"></ul>
|
||||
<h3 class="cheatsheet-title">Storage shortcuts</h3>
|
||||
<ul class="cheatsheet-storage-shortcuts"></ul>
|
||||
</div>
|
||||
<div class="cheatsheet-actions">
|
||||
<button type="button" name="cheatsheet-restore-defaults" data-action="restore-defaults" class="button cheatsheet-restore-defaults">Restore default shortcuts</button>
|
||||
</div>
|
||||
<div style="position:relative;overflow:hidden; width:1px; height:1px">
|
||||
<input type="text" id="cheatsheet-event-trap" style="position:absolute; top:-1000px;" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/template" id="cheatsheet-shortcut-template">
|
||||
<li class="cheatsheet-shortcut" data-shortcut-id="{{shortcutId}}">
|
||||
<li class="cheatsheet-shortcut {{shortcutClass}}" data-shortcut-id="{{shortcutId}}">
|
||||
<div class="cheatsheet-icon {{shortcutIcon}}"></div>
|
||||
<span class="cheatsheet-key">{{shortcutKey}}</span>
|
||||
<span class="cheatsheet-description">{{shortcutDescription}}</span>
|
||||
|
@ -94,7 +94,7 @@ describe("ShortcutService test suite", function() {
|
||||
});
|
||||
|
||||
console.log('[ShortcutService] ... verify shortcut is called');
|
||||
service.onKeyUp_(createEvent(A_KEYCODE));
|
||||
service.onKeyDown_(createEvent(A_KEYCODE));
|
||||
expect(callbackCalled).toBe(true);
|
||||
});
|
||||
|
||||
@ -123,13 +123,13 @@ describe("ShortcutService test suite", function() {
|
||||
});
|
||||
|
||||
console.log('[ShortcutService] ... trigger A, expect counter A at 1, B at 0, A_B at 1');
|
||||
service.onKeyUp_(createEvent(A_KEYCODE));
|
||||
service.onKeyDown_(createEvent(A_KEYCODE));
|
||||
expect(counters.a).toBe(1);
|
||||
expect(counters.b).toBe(0);
|
||||
expect(counters.a_b).toBe(1);
|
||||
|
||||
console.log('[ShortcutService] ... trigger A, expect counter A at 1, B at 1, A_B at 2');
|
||||
service.onKeyUp_(createEvent(B_KEYCODE));
|
||||
service.onKeyDown_(createEvent(B_KEYCODE));
|
||||
expect(counters.a).toBe(1);
|
||||
expect(counters.b).toBe(1);
|
||||
expect(counters.a_b).toBe(2);
|
||||
@ -149,7 +149,7 @@ describe("ShortcutService test suite", function() {
|
||||
service.unregisterShortcut(shortcutA);
|
||||
|
||||
console.log('[ShortcutService] ... verify shortcut callback is not called');
|
||||
service.onKeyUp_(createEvent(A_KEYCODE));
|
||||
service.onKeyDown_(createEvent(A_KEYCODE));
|
||||
expect(callbackCalled).toBe(false);
|
||||
});
|
||||
|
||||
@ -169,7 +169,7 @@ describe("ShortcutService test suite", function() {
|
||||
service.unregisterShortcut(shortcutA);
|
||||
|
||||
console.log('[ShortcutService] ... verify shortcut callback for B can still be called');
|
||||
service.onKeyUp_(createEvent(B_KEYCODE));
|
||||
service.onKeyDown_(createEvent(B_KEYCODE));
|
||||
expect(callbackCalled).toBe(true);
|
||||
});
|
||||
|
||||
@ -189,7 +189,7 @@ describe("ShortcutService test suite", function() {
|
||||
|
||||
console.log('[ShortcutService] ... verify shortcut callback for A can still be called');
|
||||
callbackCalled = false;
|
||||
service.onKeyUp_(createEvent(A_KEYCODE));
|
||||
service.onKeyDown_(createEvent(A_KEYCODE));
|
||||
expect(callbackCalled).toBe(true);
|
||||
});
|
||||
|
||||
@ -204,15 +204,15 @@ describe("ShortcutService test suite", function() {
|
||||
});
|
||||
|
||||
console.log('[ShortcutService] ... verify shortcut is not called from event on INPUT');
|
||||
service.onKeyUp_(createEvent(A_KEYCODE).setNodeName('INPUT'));
|
||||
service.onKeyDown_(createEvent(A_KEYCODE).setNodeName('INPUT'));
|
||||
expect(callbackCalled).toBe(false);
|
||||
|
||||
console.log('[ShortcutService] ... verify shortcut is not called from event on TEXTAREA');
|
||||
service.onKeyUp_(createEvent(A_KEYCODE).setNodeName('TEXTAREA'));
|
||||
service.onKeyDown_(createEvent(A_KEYCODE).setNodeName('TEXTAREA'));
|
||||
expect(callbackCalled).toBe(false);
|
||||
|
||||
console.log('[ShortcutService] ... verify shortcut is called from event on LINK');
|
||||
service.onKeyUp_(createEvent(A_KEYCODE).setNodeName('A'));
|
||||
service.onKeyDown_(createEvent(A_KEYCODE).setNodeName('A'));
|
||||
expect(callbackCalled).toBe(true);
|
||||
});
|
||||
|
||||
@ -252,23 +252,23 @@ describe("ShortcutService test suite", function() {
|
||||
};
|
||||
|
||||
console.log('[ShortcutService] ... trigger A, expect counters CTRL+A, CTRL+SHIFT+A, CTRL+SHIFT+ALT+A, ALT+A to remain at 0');
|
||||
service.onKeyUp_(createEvent(A_KEYCODE));
|
||||
service.onKeyDown_(createEvent(A_KEYCODE));
|
||||
verifyCounters(1,0,0,0,0);
|
||||
|
||||
console.log('[ShortcutService] ... trigger CTRL+A, expect counters CTRL+SHIFT+A, CTRL+SHIFT+ALT+A, ALT+A to remain at 0');
|
||||
service.onKeyUp_(createEvent(A_KEYCODE).withCtrlKey());
|
||||
service.onKeyDown_(createEvent(A_KEYCODE).withCtrlKey());
|
||||
verifyCounters(1,1,0,0,0);
|
||||
|
||||
console.log('[ShortcutService] ... trigger CTRL+A, expect counters CTRL+SHIFT+ALT+A, ALT+A to remain at 0');
|
||||
service.onKeyUp_(createEvent(A_KEYCODE).withCtrlKey().withShiftKey());
|
||||
service.onKeyDown_(createEvent(A_KEYCODE).withCtrlKey().withShiftKey());
|
||||
verifyCounters(1,1,1,0,0);
|
||||
|
||||
console.log('[ShortcutService] ... trigger CTRL+A, expect counter ALT+A to remain at 0');
|
||||
service.onKeyUp_(createEvent(A_KEYCODE).withCtrlKey().withShiftKey().withAltKey());
|
||||
service.onKeyDown_(createEvent(A_KEYCODE).withCtrlKey().withShiftKey().withAltKey());
|
||||
verifyCounters(1,1,1,1,0);
|
||||
|
||||
console.log('[ShortcutService] ... trigger CTRL+A, expect all counters at 1');
|
||||
service.onKeyUp_(createEvent(A_KEYCODE).withAltKey());
|
||||
service.onKeyDown_(createEvent(A_KEYCODE).withAltKey());
|
||||
verifyCounters(1,1,1,1,1);
|
||||
});
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user