Issue #287 : Shortcuts now rely on Shortcut instances. Shortcut key can be changed dynamically.
This commit is contained in:
parent
8081d5e232
commit
ca3bbf1c57
35 changed files with 597 additions and 185 deletions
|
@ -62,9 +62,10 @@
|
|||
$.subscribe(Events.USER_SETTINGS_CHANGED, this.onUserSettingsChange_.bind(this));
|
||||
$.subscribe(Events.FRAME_SIZE_CHANGED, this.onFrameSizeChange_.bind(this));
|
||||
|
||||
pskl.app.shortcutService.registerShortcut('0', this.resetZoom_.bind(this));
|
||||
pskl.app.shortcutService.registerShortcut('+', this.increaseZoom_.bind(this, 1));
|
||||
pskl.app.shortcutService.registerShortcut('-', this.decreaseZoom_.bind(this, 1));
|
||||
var shortcuts = pskl.service.keyboard.Shortcuts;
|
||||
pskl.app.shortcutService.registerShortcut(shortcuts.MISC.RESET_ZOOM, this.resetZoom_.bind(this));
|
||||
pskl.app.shortcutService.registerShortcut(shortcuts.MISC.INCREASE_ZOOM, this.increaseZoom_.bind(this, 1));
|
||||
pskl.app.shortcutService.registerShortcut(shortcuts.MISC.DECREASE_ZOOM, this.decreaseZoom_.bind(this, 1));
|
||||
|
||||
window.setTimeout(function () {
|
||||
this.afterWindowResize_();
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
ns.LayersListController = function (piskelController) {
|
||||
this.piskelController = piskelController;
|
||||
this.layerPreviewShortcut = pskl.service.keyboard.Shortcuts.MISC.LAYER_PREVIEW ;
|
||||
};
|
||||
|
||||
ns.LayersListController.prototype.init = function () {
|
||||
|
@ -36,10 +37,9 @@
|
|||
var descriptors = [{description : 'Opacity defined in PREFERENCES'}];
|
||||
var helpText = 'Preview all layers';
|
||||
|
||||
var toggleLayerPreviewTooltip = pskl.utils.TooltipFormatter.format(helpText, TOGGLE_LAYER_SHORTCUT, descriptors);
|
||||
this.toggleLayerPreviewEl.setAttribute('title', toggleLayerPreviewTooltip);
|
||||
|
||||
pskl.app.shortcutService.registerShortcut(TOGGLE_LAYER_SHORTCUT, this.toggleLayerPreview_.bind(this));
|
||||
pskl.app.shortcutService.registerShortcut(this.layerPreviewShortcut, this.toggleLayerPreview_.bind(this));
|
||||
var tooltip = pskl.utils.TooltipFormatter.format(helpText, this.layerPreviewShortcut, descriptors);
|
||||
this.toggleLayerPreviewEl.setAttribute('title', tooltip);
|
||||
};
|
||||
|
||||
ns.LayersListController.prototype.updateButtonStatus_ = function () {
|
||||
|
|
|
@ -10,8 +10,9 @@
|
|||
$.subscribe(Events.SELECT_PRIMARY_COLOR, this.onColorSelected_.bind(this, {isPrimary:true}));
|
||||
$.subscribe(Events.SELECT_SECONDARY_COLOR, this.onColorSelected_.bind(this, {isPrimary:false}));
|
||||
|
||||
pskl.app.shortcutService.registerShortcut('X', this.swapColors.bind(this));
|
||||
pskl.app.shortcutService.registerShortcut('D', this.resetColors.bind(this));
|
||||
var shortcuts = pskl.service.keyboard.Shortcuts;
|
||||
pskl.app.shortcutService.registerShortcut(shortcuts.COLOR.SWAP, this.swapColors.bind(this));
|
||||
pskl.app.shortcutService.registerShortcut(shortcuts.COLOR.RESET, this.resetColors.bind(this));
|
||||
|
||||
var spectrumCfg = {
|
||||
showPalette: true,
|
||||
|
|
|
@ -37,9 +37,10 @@
|
|||
$.subscribe(Events.SECONDARY_COLOR_SELECTED, this.highlightSelectedColors.bind(this));
|
||||
$.subscribe(Events.USER_SETTINGS_CHANGED, $.proxy(this.onUserSettingsChange_, this));
|
||||
|
||||
pskl.app.shortcutService.registerShortcuts(['>', 'shift+>'], this.selectNextColor_.bind(this));
|
||||
pskl.app.shortcutService.registerShortcuts('123465789'.split(''), this.selectColorForKey_.bind(this));
|
||||
pskl.app.shortcutService.registerShortcut('<', this.selectPreviousColor_.bind(this));
|
||||
var shortcuts = pskl.service.keyboard.Shortcuts;
|
||||
pskl.app.shortcutService.registerShortcut(shortcuts.COLOR.PREVIOUS_COLOR, this.selectPreviousColor_.bind(this));
|
||||
pskl.app.shortcutService.registerShortcut(shortcuts.COLOR.NEXT_COLOR, this.selectNextColor_.bind(this));
|
||||
pskl.app.shortcutService.registerShortcut(shortcuts.COLOR.SELECT_COLOR, this.selectColorForKey_.bind(this));
|
||||
|
||||
this.fillPaletteList();
|
||||
this.updateFromUserSettings();
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
new pskl.tools.drawing.ColorPicker()
|
||||
];
|
||||
|
||||
this.toolIconRenderer = new pskl.tools.IconMarkupRenderer();
|
||||
this.iconMarkupRenderer = new pskl.tools.IconMarkupRenderer();
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -93,12 +93,10 @@
|
|||
}
|
||||
};
|
||||
|
||||
ns.ToolController.prototype.onKeyboardShortcut_ = function(charkey) {
|
||||
for (var i = 0 ; i < this.tools.length ; i++) {
|
||||
var tool = this.tools[i];
|
||||
if (tool.shortcut.toLowerCase() === charkey.toLowerCase()) {
|
||||
this.selectTool_(tool);
|
||||
}
|
||||
ns.ToolController.prototype.onKeyboardShortcut_ = function(toolId, charkey) {
|
||||
var tool = this.getToolById_(toolId);
|
||||
if (tool !== null) {
|
||||
this.selectTool_(tool);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -115,14 +113,15 @@
|
|||
var html = '';
|
||||
for (var i = 0 ; i < this.tools.length ; i++) {
|
||||
var tool = this.tools[i];
|
||||
html += this.toolIconRenderer.render(tool, tool.shortcut);
|
||||
html += this.iconMarkupRenderer.render(tool);
|
||||
}
|
||||
$('#tools-container').html(html);
|
||||
};
|
||||
|
||||
ns.ToolController.prototype.addKeyboardShortcuts_ = function () {
|
||||
for (var i = 0 ; i < this.tools.length ; i++) {
|
||||
pskl.app.shortcutService.registerShortcut(this.tools[i].shortcut, this.onKeyboardShortcut_.bind(this));
|
||||
var tool = this.tools[i];
|
||||
pskl.app.shortcutService.registerShortcut(tool.shortcut, this.onKeyboardShortcut_.bind(this, tool.toolId));
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
ns.DialogsController = function (piskelController) {
|
||||
this.piskelController = piskelController;
|
||||
this.closePopupShortcut = pskl.service.keyboard.Shortcuts.MISC.CLOSE_POPUP;
|
||||
this.currentDialog_ = null;
|
||||
};
|
||||
|
||||
|
@ -28,11 +29,16 @@
|
|||
$.subscribe(Events.DIALOG_HIDE, this.onDialogHideEvent_.bind(this));
|
||||
|
||||
// TODO : JD : should be moved to a main controller
|
||||
pskl.app.shortcutService.registerShortcut('alt+P', this.onDialogDisplayEvent_.bind(this, null, 'create-palette'));
|
||||
var createPaletteShortcut = pskl.service.keyboard.Shortcuts.COLOR.CREATE_PALETTE;
|
||||
pskl.app.shortcutService.registerShortcut(createPaletteShortcut, this.onCreatePaletteShortcut_.bind(this));
|
||||
|
||||
this.dialogWrapper_.classList.add('animated');
|
||||
};
|
||||
|
||||
ns.DialogsController.prototype.onCreatePaletteShortcut_ = function () {
|
||||
this.onDialogDisplayEvent_(null, 'create-palette');
|
||||
};
|
||||
|
||||
ns.DialogsController.prototype.onDialogDisplayEvent_ = function (evt, args) {
|
||||
var dialogId, initArgs;
|
||||
if (typeof args === 'string') {
|
||||
|
@ -66,7 +72,7 @@
|
|||
};
|
||||
|
||||
ns.DialogsController.prototype.showDialogWrapper_ = function () {
|
||||
pskl.app.shortcutService.registerShortcut('ESC', this.hideDialog.bind(this));
|
||||
pskl.app.shortcutService.registerShortcut(this.closePopupShortcut, this.hideDialog.bind(this));
|
||||
this.dialogWrapper_.classList.add('show');
|
||||
};
|
||||
|
||||
|
@ -85,7 +91,7 @@
|
|||
};
|
||||
|
||||
ns.DialogsController.prototype.hideDialogWrapper_ = function () {
|
||||
pskl.app.shortcutService.unregisterShortcut('ESC');
|
||||
pskl.app.shortcutService.unregisterShortcut(this.closePopupShortcut);
|
||||
this.dialogWrapper_.classList.remove('show');
|
||||
};
|
||||
|
||||
|
|
|
@ -30,10 +30,11 @@
|
|||
this.saveWrap_('moveLayerDown', true);
|
||||
this.saveWrap_('removeCurrentLayer', true);
|
||||
|
||||
pskl.app.shortcutService.registerShortcut('up', this.selectPreviousFrame.bind(this));
|
||||
pskl.app.shortcutService.registerShortcut('down', this.selectNextFrame.bind(this));
|
||||
pskl.app.shortcutService.registerShortcut('n', this.addFrameAtCurrentIndex.bind(this));
|
||||
pskl.app.shortcutService.registerShortcut('shift+n', this.duplicateCurrentFrame.bind(this));
|
||||
var shortcuts = pskl.service.keyboard.Shortcuts;
|
||||
pskl.app.shortcutService.registerShortcut(shortcuts.MISC.PREVIOUS_FRAME, this.selectPreviousFrame.bind(this));
|
||||
pskl.app.shortcutService.registerShortcut(shortcuts.MISC.NEXT_FRAME, this.selectNextFrame.bind(this));
|
||||
pskl.app.shortcutService.registerShortcut(shortcuts.MISC.NEW_FRAME, this.addFrameAtCurrentIndex.bind(this));
|
||||
pskl.app.shortcutService.registerShortcut(shortcuts.MISC.DUPLICATE_FRAME, this.duplicateCurrentFrame.bind(this));
|
||||
};
|
||||
|
||||
ns.PublicPiskelController.prototype.setPiskel = function (piskel, preserveState) {
|
||||
|
|
|
@ -14,6 +14,9 @@
|
|||
this.elapsedTime = 0;
|
||||
this.currentIndex = 0;
|
||||
|
||||
this.onionSkinShortcut = pskl.service.keyboard.Shortcuts.MISC.ONION_SKIN;
|
||||
this.originalSizeShortcut = pskl.service.keyboard.Shortcuts.MISC.X1_PREVIEW;
|
||||
|
||||
this.renderFlag = true;
|
||||
|
||||
/**
|
||||
|
@ -47,8 +50,8 @@
|
|||
pskl.utils.Event.addEventListener(this.openPopupPreview, 'click', this.onOpenPopupPreviewClick_, this);
|
||||
pskl.utils.Event.addEventListener(this.originalSizeButton, 'click', this.onOriginalSizeButtonClick_, this);
|
||||
|
||||
pskl.app.shortcutService.registerShortcut(ONION_SKIN_SHORTCUT, this.toggleOnionSkin_.bind(this));
|
||||
pskl.app.shortcutService.registerShortcut(ORIGINAL_SIZE_SHORTCUT, this.onOriginalSizeButtonClick_.bind(this));
|
||||
pskl.app.shortcutService.registerShortcut(this.onionSkinShortcut, this.toggleOnionSkin_.bind(this));
|
||||
pskl.app.shortcutService.registerShortcut(this.originalSizeShortcut, this.onOriginalSizeButtonClick_.bind(this));
|
||||
|
||||
$.subscribe(Events.FRAME_SIZE_CHANGED, this.onFrameSizeChange_.bind(this));
|
||||
$.subscribe(Events.USER_SETTINGS_CHANGED, $.proxy(this.onUserSettingsChange_, this));
|
||||
|
@ -66,9 +69,9 @@
|
|||
};
|
||||
|
||||
ns.PreviewController.prototype.initTooltips_ = function () {
|
||||
var onionSkinTooltip = pskl.utils.TooltipFormatter.format('Toggle onion skin', ONION_SKIN_SHORTCUT);
|
||||
var onionSkinTooltip = pskl.utils.TooltipFormatter.format('Toggle onion skin', this.onionSkinShortcut);
|
||||
this.toggleOnionSkinButton.setAttribute('title', onionSkinTooltip);
|
||||
var originalSizeTooltip = pskl.utils.TooltipFormatter.format('Original size preview', ORIGINAL_SIZE_SHORTCUT);
|
||||
var originalSizeTooltip = pskl.utils.TooltipFormatter.format('Original size preview', this.originalSizeShortcut);
|
||||
this.originalSizeButton.setAttribute('title', originalSizeTooltip);
|
||||
};
|
||||
|
||||
|
|
|
@ -18,11 +18,11 @@
|
|||
$.subscribe(Events.SELECTION_DISMISSED, $.proxy(this.onSelectionDismissed_, this));
|
||||
$.subscribe(Events.SELECTION_MOVE_REQUEST, $.proxy(this.onSelectionMoved_, this));
|
||||
|
||||
pskl.app.shortcutService.registerShortcut('ctrl+V', this.paste.bind(this));
|
||||
pskl.app.shortcutService.registerShortcut('ctrl+X', this.cut.bind(this));
|
||||
pskl.app.shortcutService.registerShortcut('ctrl+C', this.copy.bind(this));
|
||||
pskl.app.shortcutService.registerShortcut('del', this.erase.bind(this));
|
||||
pskl.app.shortcutService.registerShortcut('back', this.onBackPressed_.bind(this));
|
||||
var shortcuts = pskl.service.keyboard.Shortcuts;
|
||||
pskl.app.shortcutService.registerShortcut(shortcuts.SELECTION.PASTE, this.paste.bind(this));
|
||||
pskl.app.shortcutService.registerShortcut(shortcuts.SELECTION.CUT, this.cut.bind(this));
|
||||
pskl.app.shortcutService.registerShortcut(shortcuts.SELECTION.COPY, this.copy.bind(this));
|
||||
pskl.app.shortcutService.registerShortcut(shortcuts.SELECTION.DELETE, this.onDeleteShortcut_.bind(this));
|
||||
|
||||
$.subscribe(Events.TOOL_SELECTED, $.proxy(this.onToolSelected_, this));
|
||||
};
|
||||
|
@ -54,7 +54,7 @@
|
|||
this.cleanSelection_();
|
||||
};
|
||||
|
||||
ns.SelectionManager.prototype.onBackPressed_ = function(evt) {
|
||||
ns.SelectionManager.prototype.onDeleteShortcut_ = function(evt) {
|
||||
if (this.currentSelection) {
|
||||
this.erase();
|
||||
} else {
|
||||
|
|
|
@ -26,8 +26,9 @@
|
|||
ns.HistoryService.prototype.init = function () {
|
||||
$.subscribe(Events.PISKEL_SAVE_STATE, this.onSaveStateEvent.bind(this));
|
||||
|
||||
this.shortcutService.registerShortcut('ctrl+Z', this.undo.bind(this));
|
||||
this.shortcutService.registerShortcuts(['ctrl+Y', 'ctrl+shift+Z'] , this.redo.bind(this));
|
||||
var shortcuts = pskl.service.keyboard.Shortcuts;
|
||||
this.shortcutService.registerShortcut(shortcuts.MISC.UNDO, this.undo.bind(this));
|
||||
this.shortcutService.registerShortcut(shortcuts.MISC.REDO, this.redo.bind(this));
|
||||
|
||||
this.saveState({
|
||||
type : ns.HistoryService.SNAPSHOT
|
||||
|
|
|
@ -1,8 +1,13 @@
|
|||
(function () {
|
||||
var ns = $.namespace('pskl.service.keyboard');
|
||||
|
||||
/**
|
||||
* TODO : JD : This is not a service, but a controller
|
||||
* Moreover this should be handled by the DialogsController
|
||||
*/
|
||||
ns.CheatsheetService = function () {
|
||||
this.isDisplayed = false;
|
||||
this.closePopupShortcut = pskl.service.keyboard.Shortcuts.MISC.CLOSE_POPUP;
|
||||
};
|
||||
|
||||
ns.CheatsheetService.prototype.init = function () {
|
||||
|
@ -13,7 +18,9 @@
|
|||
}
|
||||
|
||||
this.initMarkup_();
|
||||
pskl.app.shortcutService.registerShortcuts(['?', 'shift+?'], this.toggleCheatsheet_.bind(this));
|
||||
|
||||
var cheatsheetShortcut = pskl.service.keyboard.Shortcuts.MISC.CHEATSHEET;
|
||||
pskl.app.shortcutService.registerShortcut(cheatsheetShortcut, this.toggleCheatsheet_.bind(this));
|
||||
|
||||
pskl.utils.Event.addEventListener(document.body, 'click', this.onBodyClick_, this);
|
||||
|
||||
|
@ -46,13 +53,13 @@
|
|||
};
|
||||
|
||||
ns.CheatsheetService.prototype.showCheatsheet_ = function () {
|
||||
pskl.app.shortcutService.registerShortcut('ESC', this.hideCheatsheet_.bind(this));
|
||||
pskl.app.shortcutService.registerShortcut(this.closePopupShortcut, this.hideCheatsheet_.bind(this));
|
||||
this.cheatsheetEl.style.display = 'block';
|
||||
this.isDisplayed = true;
|
||||
};
|
||||
|
||||
ns.CheatsheetService.prototype.hideCheatsheet_ = function () {
|
||||
pskl.app.shortcutService.unregisterShortcut('ESC');
|
||||
pskl.app.shortcutService.unregisterShortcut(this.closePopupShortcut);
|
||||
this.cheatsheetEl.style.display = 'none';
|
||||
this.isDisplayed = false;
|
||||
};
|
||||
|
@ -65,71 +72,56 @@
|
|||
};
|
||||
|
||||
ns.CheatsheetService.prototype.initMarkupForTools_ = function () {
|
||||
var descriptors = pskl.app.toolController.tools.map(function (tool) {
|
||||
return this.toDescriptor_(tool.shortcut, tool.getHelpText(), 'tool-icon ' + tool.toolId);
|
||||
}.bind(this));
|
||||
var descriptors = this.createShortcutDescriptors_(ns.Shortcuts.TOOL, this.getToolShortcutClassname_);
|
||||
this.initMarkupForDescriptors_(descriptors, '.cheatsheet-tool-shortcuts');
|
||||
};
|
||||
|
||||
var container = this.cheatsheetEl.querySelector('.cheatsheet-tool-shortcuts');
|
||||
this.initMarkupForDescriptors_(descriptors, container);
|
||||
ns.CheatsheetService.prototype.getToolShortcutClassname_ = function (shortcut) {
|
||||
return 'tool-icon ' + shortcut.getId();
|
||||
};
|
||||
|
||||
ns.CheatsheetService.prototype.initMarkupForMisc_ = function () {
|
||||
var descriptors = [
|
||||
this.toDescriptor_('0', 'Reset zoom level'),
|
||||
this.toDescriptor_('+/-', 'Zoom in/Zoom out'),
|
||||
this.toDescriptor_('ctrl + Z', 'Undo'),
|
||||
this.toDescriptor_('ctrl + Y', 'Redo'),
|
||||
this.toDescriptor_('↑', 'Select previous frame'), /* ASCII for up-arrow */
|
||||
this.toDescriptor_('↓', 'Select next frame'), /* ASCII for down-arrow */
|
||||
this.toDescriptor_('N', 'Create new frame'),
|
||||
this.toDescriptor_('shift + N', 'Duplicate selected frame'),
|
||||
this.toDescriptor_('shift + ?', 'Open/Close this popup'),
|
||||
this.toDescriptor_('alt + 1', 'Toggle original size preview'),
|
||||
this.toDescriptor_('alt + O', 'Toggle Onion Skin'),
|
||||
this.toDescriptor_('alt + L', 'Toggle Layer Preview')
|
||||
];
|
||||
|
||||
var container = this.cheatsheetEl.querySelector('.cheatsheet-misc-shortcuts');
|
||||
this.initMarkupForDescriptors_(descriptors, container);
|
||||
var descriptors = this.createShortcutDescriptors_(ns.Shortcuts.MISC);
|
||||
this.initMarkupForDescriptors_(descriptors, '.cheatsheet-misc-shortcuts');
|
||||
};
|
||||
|
||||
ns.CheatsheetService.prototype.initMarkupForColors_ = function () {
|
||||
var descriptors = [
|
||||
this.toDescriptor_('X', 'Swap primary/secondary colors'),
|
||||
this.toDescriptor_('D', 'Reset default colors'),
|
||||
this.toDescriptor_('alt + P', 'Create a Palette'),
|
||||
this.toDescriptor_('</>', 'Select prev/next palette color'),
|
||||
this.toDescriptor_('1 to 9', 'Select palette color at index')
|
||||
];
|
||||
|
||||
var container = this.cheatsheetEl.querySelector('.cheatsheet-colors-shortcuts');
|
||||
this.initMarkupForDescriptors_(descriptors, container);
|
||||
var descriptors = this.createShortcutDescriptors_(ns.Shortcuts.COLOR);
|
||||
this.initMarkupForDescriptors_(descriptors, '.cheatsheet-colors-shortcuts');
|
||||
};
|
||||
|
||||
ns.CheatsheetService.prototype.initMarkupForSelection_ = function () {
|
||||
var descriptors = [
|
||||
this.toDescriptor_('ctrl + X', 'Cut selection'),
|
||||
this.toDescriptor_('ctrl + C', 'Copy selection'),
|
||||
this.toDescriptor_('ctrl + V', 'Paste selection'),
|
||||
this.toDescriptor_('del', 'Delete selection')
|
||||
];
|
||||
|
||||
var container = this.cheatsheetEl.querySelector('.cheatsheet-selection-shortcuts');
|
||||
this.initMarkupForDescriptors_(descriptors, container);
|
||||
var descriptors = this.createShortcutDescriptors_(ns.Shortcuts.SELECTION);
|
||||
this.initMarkupForDescriptors_(descriptors, '.cheatsheet-selection-shortcuts');
|
||||
};
|
||||
|
||||
ns.CheatsheetService.prototype.toDescriptor_ = function (shortcut, description, icon) {
|
||||
ns.CheatsheetService.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.getKey(), shortcut.getDescription(), classname);
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
ns.CheatsheetService.prototype.toDescriptor_ = function (key, description, icon) {
|
||||
if (pskl.utils.UserAgent.isMac) {
|
||||
shortcut = shortcut.replace('ctrl', 'cmd');
|
||||
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');
|
||||
|
||||
return {
|
||||
'shortcut' : shortcut,
|
||||
'key' : key,
|
||||
'description' : description,
|
||||
'icon' : icon
|
||||
};
|
||||
};
|
||||
|
||||
ns.CheatsheetService.prototype.initMarkupForDescriptors_ = function (descriptors, container) {
|
||||
ns.CheatsheetService.prototype.initMarkupForDescriptors_ = function (descriptors, containerSelector) {
|
||||
var container = this.cheatsheetEl.querySelector(containerSelector);
|
||||
descriptors.forEach(function (descriptor) {
|
||||
var shortcut = this.getDomFromDescriptor_(descriptor);
|
||||
container.appendChild(shortcut);
|
||||
|
@ -141,7 +133,7 @@
|
|||
var markup = pskl.utils.Template.replace(shortcutTemplate, {
|
||||
shortcutIcon : descriptor.icon,
|
||||
shortcutDescription : descriptor.description,
|
||||
shortcutKey : descriptor.shortcut
|
||||
shortcutKey : descriptor.key
|
||||
});
|
||||
|
||||
return pskl.utils.Template.createFromHTML(markup);
|
||||
|
|
60
src/js/service/keyboard/Shortcut.js
Normal file
60
src/js/service/keyboard/Shortcut.js
Normal file
|
@ -0,0 +1,60 @@
|
|||
(function () {
|
||||
var ns = $.namespace('pskl.service.keyboard');
|
||||
|
||||
/**
|
||||
* Keyboard shortcut wrapper, use it to register on the ShortcutService.
|
||||
*
|
||||
* @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)
|
||||
* 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) {
|
||||
this.id_ = id;
|
||||
this.description_ = description;
|
||||
this.defaultKey_ = defaultKey;
|
||||
this.displayKey_ = displayKey;
|
||||
};
|
||||
|
||||
ns.Shortcut.USER_SETTINGS_PREFIX = 'shortcut.';
|
||||
|
||||
ns.Shortcut.prototype.getId = function () {
|
||||
return this.id_;
|
||||
};
|
||||
|
||||
ns.Shortcut.prototype.getDescription = function () {
|
||||
return this.description_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve the array of String keys that match this shortcut
|
||||
* @return {Array<String>} array of keys
|
||||
*/
|
||||
ns.Shortcut.prototype.getKeys = function () {
|
||||
var keys = pskl.UserSettings.get(ns.Shortcut.USER_SETTINGS_PREFIX + this.id_) || this.defaultKey_;
|
||||
if (typeof keys === 'string') {
|
||||
keys = [keys];
|
||||
}
|
||||
|
||||
return keys;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the key to be displayed for this shortcut, if
|
||||
* @return {[type]} [description]
|
||||
*/
|
||||
ns.Shortcut.prototype.getKey = function () {
|
||||
if (this.displayKey_) {
|
||||
return this.displayKey_;
|
||||
}
|
||||
|
||||
var keys = this.getKeys();
|
||||
if (Array.isArray(keys) && keys.length > 0) {
|
||||
return keys[0];
|
||||
}
|
||||
|
||||
return '';
|
||||
};
|
||||
|
||||
})();
|
|
@ -2,7 +2,7 @@
|
|||
var ns = $.namespace('pskl.service.keyboard');
|
||||
|
||||
ns.ShortcutService = function () {
|
||||
this.shortcuts_ = {};
|
||||
this.shortcuts_ = [];
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -14,43 +14,34 @@
|
|||
|
||||
/**
|
||||
* Add a keyboard shortcut
|
||||
* @param {String} rawKey (case insensitive) a key is a combination of modifiers + ([a-z0-9] or
|
||||
* a special key) (check list of supported special keys in KeycodeTranslator)
|
||||
* eg. 'ctrl+A',
|
||||
* 'del'
|
||||
* 'ctrl+shift+S'
|
||||
* @param {pskl.service.keyboard.Shortcut} shortcut
|
||||
* @param {Function} callback should return true to let the original event perform its default action
|
||||
*/
|
||||
ns.ShortcutService.prototype.registerShortcut = function (rawKey, callback) {
|
||||
var parsedKey = this.parseKey_(rawKey.toLowerCase());
|
||||
|
||||
var key = parsedKey.key;
|
||||
var meta = parsedKey.meta;
|
||||
|
||||
this.shortcuts_[key] = this.shortcuts_[key] || {};
|
||||
|
||||
if (this.shortcuts_[key][meta]) {
|
||||
var keyStr = (meta !== 'normal' ? meta + ' + ' : '') + key;
|
||||
console.error('[ShortcutService] >>> Shortcut [' + keyStr + '] already registered');
|
||||
} else {
|
||||
this.shortcuts_[key][meta] = callback;
|
||||
ns.ShortcutService.prototype.registerShortcut = function (shortcut, callback) {
|
||||
if (!(shortcut instanceof ns.Shortcut)) {
|
||||
throw 'Invalid shortcut argument, please use instances of pskl.service.keyboard.Shortcut';
|
||||
}
|
||||
|
||||
if (typeof callback != 'function') {
|
||||
throw 'Invalid callback argument, please provide a function';
|
||||
}
|
||||
|
||||
this.shortcuts_.push({
|
||||
shortcut : shortcut,
|
||||
callback : callback
|
||||
});
|
||||
};
|
||||
|
||||
ns.ShortcutService.prototype.registerShortcuts = function (keys, callback) {
|
||||
keys.forEach(function (key) {
|
||||
this.registerShortcut(key, callback);
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
ns.ShortcutService.prototype.unregisterShortcut = function (rawKey) {
|
||||
var parsedKey = this.parseKey_(rawKey.toLowerCase());
|
||||
var key = parsedKey.key;
|
||||
var meta = parsedKey.meta;
|
||||
|
||||
this.shortcuts_[key] = this.shortcuts_[key] || {};
|
||||
|
||||
this.shortcuts_[key][meta] = null;
|
||||
ns.ShortcutService.prototype.unregisterShortcut = function (shortcut) {
|
||||
var index = -1;
|
||||
this.shortcuts_.forEach(function (s, i) {
|
||||
if (s.shortcut === shortcut) {
|
||||
index = i;
|
||||
}
|
||||
});
|
||||
if (index != -1) {
|
||||
this.shortcuts_.splice(index, 1);
|
||||
}
|
||||
};
|
||||
|
||||
ns.ShortcutService.prototype.parseKey_ = function (key) {
|
||||
|
@ -62,51 +53,58 @@
|
|||
|
||||
var parts = key.split(/\+(?!$)/);
|
||||
key = parts[parts.length - 1];
|
||||
return {meta : meta, key : key};
|
||||
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 = [];
|
||||
['alt', 'ctrl', 'shift'].forEach(function (metaKey) {
|
||||
if (meta[metaKey]) {
|
||||
keyBuffer.push(metaKey);
|
||||
}
|
||||
});
|
||||
|
||||
if (keyBuffer.length > 0) {
|
||||
return keyBuffer.join('+');
|
||||
} else {
|
||||
return 'normal';
|
||||
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)) {
|
||||
// jquery names FTW ...
|
||||
var keycode = evt.which;
|
||||
var charkey = pskl.service.keyboard.KeycodeTranslator.toChar(keycode);
|
||||
|
||||
var keyShortcuts = this.shortcuts_[charkey];
|
||||
if (keyShortcuts) {
|
||||
var meta = this.getMetaKey_({
|
||||
alt : this.isAltKeyPressed_(evt),
|
||||
shift : this.isShiftKeyPressed_(evt),
|
||||
ctrl : this.isCtrlKeyPressed_(evt)
|
||||
});
|
||||
var cb = keyShortcuts[meta];
|
||||
|
||||
if (cb) {
|
||||
var bubble = cb(charkey);
|
||||
if (bubble !== true) {
|
||||
evt.preventDefault();
|
||||
}
|
||||
$.publish(Events.KEYBOARD_EVENT, [evt]);
|
||||
}
|
||||
}
|
||||
if (this.isInInput_(evt)) {
|
||||
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)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var bubble = shortcutInfo.callback(eventKey);
|
||||
if (bubble !== true) {
|
||||
evt.preventDefault();
|
||||
}
|
||||
$.publish(Events.KEYBOARD_EVENT, [evt]);
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
ns.ShortcutService.prototype.isInInput_ = function (evt) {
|
||||
|
@ -114,15 +112,12 @@
|
|||
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;
|
||||
};
|
||||
|
||||
ns.ShortcutService.prototype.isShiftKeyPressed_ = function (evt) {
|
||||
return evt.shiftKey;
|
||||
};
|
||||
|
||||
ns.ShortcutService.prototype.isAltKeyPressed_ = function (evt) {
|
||||
return evt.altKey;
|
||||
};
|
||||
})();
|
||||
|
|
70
src/js/service/keyboard/Shortcuts.js
Normal file
70
src/js/service/keyboard/Shortcuts.js
Normal file
|
@ -0,0 +1,70 @@
|
|||
(function () {
|
||||
var ns = $.namespace('pskl.service.keyboard');
|
||||
|
||||
var createShortcut = function (id, description, defaultKey, displayKey) {
|
||||
return new ns.Shortcut(id, description, defaultKey, displayKey);
|
||||
};
|
||||
|
||||
ns.Shortcuts = {
|
||||
/**
|
||||
* Syntax : createShortcut(id, description, default key(s))
|
||||
*/
|
||||
TOOL : {
|
||||
PEN : createShortcut('tool-pen', 'Pen tool', 'P'),
|
||||
MIRROR_PEN : createShortcut('tool-vertical-mirror-pen', 'Vertical mirror pen tool', 'V'),
|
||||
PAINT_BUCKET : createShortcut('tool-paint-bucket', 'Paint bucket tool', 'B'),
|
||||
COLORSWAP : createShortcut('tool-colorswap', 'Magic bucket tool', 'A'),
|
||||
ERASER : createShortcut('tool-eraser', 'Eraser pen tool', 'E'),
|
||||
STROKE : createShortcut('tool-stroke', 'Stroke tool', 'L'),
|
||||
RECTANGLE : createShortcut('tool-rectangle', 'Rectangle tool', 'R'),
|
||||
CIRCLE : createShortcut('tool-circle', 'Circle tool', 'C'),
|
||||
MOVE : createShortcut('tool-move', 'Move tool', 'M'),
|
||||
SHAPE_SELECT : createShortcut('tool-shape-select', 'Shape selection', 'Z'),
|
||||
RECTANGLE_SELECT : createShortcut('tool-rectangle-select', 'Rectangle selection', 'S'),
|
||||
LASSO_SELECT : createShortcut('tool-lasso-select', 'Lasso selection', 'H'),
|
||||
LIGHTEN : createShortcut('tool-lighten', 'Lighten tool', 'U'),
|
||||
DITHERING : createShortcut('tool-dithering', 'Dithering tool', 'T'),
|
||||
COLORPICKER : createShortcut('tool-colorpicker', 'Color picker', 'O')
|
||||
},
|
||||
|
||||
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'),
|
||||
DELETE : createShortcut('selection-delete', 'Delete selection', ['del', 'back'])
|
||||
},
|
||||
|
||||
MISC : {
|
||||
RESET_ZOOM : createShortcut('reset-zoom', 'Reset zoom level', '0'),
|
||||
INCREASE_ZOOM : createShortcut('increase-zoom', 'Increase zoom level', '+'),
|
||||
DECREASE_ZOOM : createShortcut('decrease-zoom', 'Decrease zoom level', '-'),
|
||||
UNDO : createShortcut('undo', 'Undo', 'ctrl+Z'),
|
||||
REDO : createShortcut('redo', 'Redo', ['ctrl+Y', 'ctrl+shift+Z']),
|
||||
PREVIOUS_FRAME : createShortcut('previous-frame', 'Select previous frame', 'up'),
|
||||
NEXT_FRAME : createShortcut('next-frame', 'Select next frame', 'down'),
|
||||
NEW_FRAME : createShortcut('new-frame', 'Create new empty frame', 'N'),
|
||||
DUPLICATE_FRAME : createShortcut('duplicate-frame', 'Duplicate selected frame', 'shift+N'),
|
||||
CHEATSHEET : createShortcut('cheatsheet', 'Open the keyboard shortcut cheatsheet', 'shift+?'),
|
||||
X1_PREVIEW : createShortcut('x1-preview', 'Toggle original size preview', 'alt+1'),
|
||||
ONION_SKIN : createShortcut('onion-skin', 'Toggle onion skin', 'alt+O'),
|
||||
LAYER_PREVIEW : createShortcut('layer-preview', 'Toggle layer preview', 'alt+L'),
|
||||
CLOSE_POPUP : createShortcut('close-popup', 'Close an opened popup', 'ESC')
|
||||
},
|
||||
|
||||
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')
|
||||
},
|
||||
|
||||
COLOR : {
|
||||
SWAP : createShortcut('swap-colors', 'Swap primary/secondary colors', 'X'),
|
||||
RESET : createShortcut('reset-colors', 'Reset default colors', 'D'),
|
||||
CREATE_PALETTE : createShortcut('create-palette', 'Open the palette creation popup', 'alt+P'),
|
||||
PREVIOUS_COLOR : createShortcut('previous-color', 'Select the previous color in the current palette', '<'),
|
||||
NEXT_COLOR : createShortcut('next-color', 'Select the next color in the current palette', '>'),
|
||||
SELECT_COLOR : createShortcut('select-color', 'Select a palette color in the current palette',
|
||||
'123456789'.split(''), '1 to 9')
|
||||
}
|
||||
};
|
||||
})();
|
|
@ -10,9 +10,10 @@
|
|||
};
|
||||
|
||||
ns.StorageService.prototype.init = function () {
|
||||
pskl.app.shortcutService.registerShortcut('ctrl+o', this.onOpenKey_.bind(this));
|
||||
pskl.app.shortcutService.registerShortcut('ctrl+s', this.onSaveKey_.bind(this));
|
||||
pskl.app.shortcutService.registerShortcut('ctrl+shift+s', this.onSaveAsKey_.bind(this));
|
||||
var shortcuts = pskl.service.keyboard.Shortcuts;
|
||||
pskl.app.shortcutService.registerShortcut(shortcuts.STORAGE.OPEN, this.onOpenKey_.bind(this));
|
||||
pskl.app.shortcutService.registerShortcut(shortcuts.STORAGE.SAVE, this.onSaveKey_.bind(this));
|
||||
pskl.app.shortcutService.registerShortcut(shortcuts.STORAGE.SAVE_AS, this.onSaveAsKey_.bind(this));
|
||||
|
||||
$.subscribe(Events.BEFORE_SAVING_PISKEL, this.setSavingFlag_.bind(this, true));
|
||||
$.subscribe(Events.AFTER_SAVING_PISKEL, this.setSavingFlag_.bind(this, false));
|
||||
|
|
|
@ -3,19 +3,19 @@
|
|||
|
||||
ns.IconMarkupRenderer = function () {};
|
||||
|
||||
ns.IconMarkupRenderer.prototype.render = function (tool, shortcut, tooltipPosition) {
|
||||
ns.IconMarkupRenderer.prototype.render = function (tool, tooltipPosition) {
|
||||
tooltipPosition = tooltipPosition || 'right';
|
||||
var tpl = pskl.utils.Template.get('drawingTool-item-template');
|
||||
return pskl.utils.Template.replace(tpl, {
|
||||
cssclass : ['tool-icon', tool.toolId].join(' '),
|
||||
toolid : tool.toolId,
|
||||
title : this.getTooltipText(tool, shortcut),
|
||||
title : this.getTooltipText(tool),
|
||||
tooltipposition : tooltipPosition
|
||||
});
|
||||
};
|
||||
|
||||
ns.IconMarkupRenderer.prototype.getTooltipText = function(tool, shortcut) {
|
||||
ns.IconMarkupRenderer.prototype.getTooltipText = function(tool) {
|
||||
var descriptors = tool.tooltipDescriptors;
|
||||
return pskl.utils.TooltipFormatter.format(tool.getHelpText(), shortcut, descriptors);
|
||||
return pskl.utils.TooltipFormatter.format(tool.getHelpText(), tool.shortcut, descriptors);
|
||||
};
|
||||
})();
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
this.toolId = 'tool-circle';
|
||||
this.helpText = 'Circle tool';
|
||||
this.shortcut = 'C';
|
||||
this.shortcut = pskl.service.keyboard.Shortcuts.TOOL.CIRCLE;
|
||||
};
|
||||
|
||||
pskl.utils.inherit(ns.Circle, ns.ShapeTool);
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
ns.ColorPicker = function() {
|
||||
this.toolId = 'tool-colorpicker';
|
||||
this.helpText = 'Color picker';
|
||||
this.shortcut = 'O';
|
||||
this.shortcut = pskl.service.keyboard.Shortcuts.TOOL.COLORPICKER;
|
||||
};
|
||||
|
||||
pskl.utils.inherit(ns.ColorPicker, ns.BaseTool);
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
ns.ColorSwap = function() {
|
||||
this.toolId = 'tool-colorswap';
|
||||
this.helpText = 'Paint all pixels of the same color';
|
||||
this.shortcut = 'A';
|
||||
this.shortcut = pskl.service.keyboard.Shortcuts.TOOL.COLORSWAP;
|
||||
|
||||
this.tooltipDescriptors = [
|
||||
{key : 'ctrl', description : 'Apply to all layers'},
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
ns.SimplePen.call(this);
|
||||
this.toolId = 'tool-dithering';
|
||||
this.helpText = 'Dithering tool';
|
||||
this.shortcut = 'T';
|
||||
this.shortcut = pskl.service.keyboard.Shortcuts.TOOL.DITHERING;
|
||||
};
|
||||
pskl.utils.inherit(ns.DitheringTool, ns.SimplePen);
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
this.toolId = 'tool-eraser';
|
||||
this.helpText = 'Eraser tool';
|
||||
this.shortcut = 'E';
|
||||
this.shortcut = pskl.service.keyboard.Shortcuts.TOOL.ERASER;
|
||||
};
|
||||
|
||||
pskl.utils.inherit(ns.Eraser, ns.SimplePen);
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
this.toolId = 'tool-lighten';
|
||||
this.helpText = 'Lighten';
|
||||
this.shortcut = 'U';
|
||||
this.shortcut = pskl.service.keyboard.Shortcuts.TOOL.LIGHTEN;
|
||||
|
||||
this.tooltipDescriptors = [
|
||||
{key : 'ctrl', description : 'Darken'},
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
ns.Move = function() {
|
||||
this.toolId = ns.Move.TOOL_ID;
|
||||
this.helpText = 'Move tool';
|
||||
this.shortcut = 'M';
|
||||
this.shortcut = pskl.service.keyboard.Shortcuts.TOOL.MOVE;
|
||||
|
||||
this.tooltipDescriptors = [
|
||||
{key : 'ctrl', description : 'Apply to all layers'},
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
ns.PaintBucket = function() {
|
||||
this.toolId = 'tool-paint-bucket';
|
||||
this.helpText = 'Paint bucket tool';
|
||||
this.shortcut = 'B';
|
||||
this.shortcut = pskl.service.keyboard.Shortcuts.TOOL.PAINT_BUCKET;
|
||||
};
|
||||
|
||||
pskl.utils.inherit(ns.PaintBucket, ns.BaseTool);
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
this.toolId = 'tool-rectangle';
|
||||
this.helpText = 'Rectangle tool';
|
||||
this.shortcut = 'R';
|
||||
this.shortcut = pskl.service.keyboard.Shortcuts.TOOL.RECTANGLE;
|
||||
};
|
||||
|
||||
pskl.utils.inherit(ns.Rectangle, ns.ShapeTool);
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
ns.SimplePen = function() {
|
||||
this.toolId = 'tool-pen';
|
||||
this.helpText = 'Pen tool';
|
||||
this.shortcut = 'P';
|
||||
this.shortcut = pskl.service.keyboard.Shortcuts.TOOL.PEN;
|
||||
|
||||
this.previousCol = null;
|
||||
this.previousRow = null;
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
ns.Stroke = function() {
|
||||
this.toolId = 'tool-stroke';
|
||||
this.helpText = 'Stroke tool';
|
||||
this.shortcut = 'L';
|
||||
this.shortcut = pskl.service.keyboard.Shortcuts.TOOL.STROKE;
|
||||
|
||||
// Stroke's first point coordinates (set in applyToolAt)
|
||||
this.startCol = null;
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
this.toolId = 'tool-vertical-mirror-pen';
|
||||
this.helpText = 'Vertical Mirror pen';
|
||||
this.shortcut = 'V';
|
||||
this.shortcut = pskl.service.keyboard.Shortcuts.TOOL.MIRROR_PEN;
|
||||
|
||||
this.tooltipDescriptors = [
|
||||
{key : 'ctrl', description : 'Use horizontal axis'},
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
this.toolId = 'tool-lasso-select';
|
||||
this.helpText = 'Lasso selection';
|
||||
this.shortcut = 'H';
|
||||
this.shortcut = pskl.service.keyboard.Shortcuts.TOOL.LASSO_SELECT;
|
||||
};
|
||||
|
||||
pskl.utils.inherit(ns.LassoSelect, ns.AbstractDragSelect);
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
this.toolId = 'tool-rectangle-select';
|
||||
this.helpText = 'Rectangle selection';
|
||||
this.shortcut = 'S';
|
||||
this.shortcut = pskl.service.keyboard.Shortcuts.TOOL.RECTANGLE_SELECT;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
this.toolId = 'tool-shape-select';
|
||||
this.helpText = 'Shape selection';
|
||||
this.shortcut = 'Z';
|
||||
this.shortcut = pskl.service.keyboard.Shortcuts.TOOL.SHAPE_SELECT;
|
||||
};
|
||||
|
||||
pskl.utils.inherit(ns.ShapeSelect, ns.BaseSelect);
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
ns.TooltipFormatter.format = function(helpText, shortcut, descriptors) {
|
||||
var tpl = pskl.utils.Template.get('tooltip-container-template');
|
||||
shortcut = shortcut ? '(' + shortcut + ')' : '';
|
||||
shortcut = shortcut ? '(' + shortcut.getKey() + ')' : '';
|
||||
return pskl.utils.Template.replace(tpl, {
|
||||
helptext : helpText,
|
||||
shortcut : shortcut,
|
||||
|
|
|
@ -91,6 +91,10 @@
|
|||
* @private
|
||||
*/
|
||||
checkKeyValidity_ : function(key) {
|
||||
if (key.indexOf(pskl.service.keyboard.Shortcut.USER_SETTINGS_PREFIX) === 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
var isValidKey = key in this.KEY_TO_DEFAULT_VALUE_MAP_;
|
||||
if (!isValidKey) {
|
||||
console.error('UserSettings key <' + key + '> not found in supported keys.');
|
||||
|
|
|
@ -157,6 +157,8 @@
|
|||
"js/service/palette/reader/PaletteTxtReader.js",
|
||||
"js/service/palette/PaletteImportService.js",
|
||||
"js/service/SavedStatusService.js",
|
||||
"js/service/keyboard/Shortcut.js",
|
||||
"js/service/keyboard/Shortcuts.js",
|
||||
"js/service/keyboard/ShortcutService.js",
|
||||
"js/service/keyboard/KeycodeTranslator.js",
|
||||
"js/service/keyboard/CheatsheetService.js",
|
||||
|
|
275
test/js/service/keyboard/ShortcutServiceTest.js
Normal file
275
test/js/service/keyboard/ShortcutServiceTest.js
Normal file
|
@ -0,0 +1,275 @@
|
|||
describe("ShortcutService test suite", function() {
|
||||
|
||||
var A_KEY = 'A';
|
||||
var B_KEY = 'B';
|
||||
var A_KEYCODE = 65;
|
||||
var B_KEYCODE = 66;
|
||||
|
||||
var service;
|
||||
|
||||
beforeEach(function() {
|
||||
service = new pskl.service.keyboard.ShortcutService();
|
||||
});
|
||||
|
||||
var createEvent = function (keycode) {
|
||||
return {
|
||||
which : keycode,
|
||||
altKey : false,
|
||||
withAltKey : function () {
|
||||
this.altKey = true;
|
||||
return this;
|
||||
},
|
||||
ctrlKey : false,
|
||||
withCtrlKey : function () {
|
||||
this.ctrlKey = true;
|
||||
return this;
|
||||
},
|
||||
shiftKey : false,
|
||||
withShiftKey : function () {
|
||||
this.shiftKey = true;
|
||||
return this;
|
||||
},
|
||||
preventDefaultCalled : false,
|
||||
preventDefault : function () {
|
||||
this.preventDefaultCalled = true;
|
||||
},
|
||||
target : {
|
||||
nodeName : 'div'
|
||||
},
|
||||
setNodeName : function (nodeName) {
|
||||
this.target.nodeName = nodeName;
|
||||
return this;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
var setTargetName = function (evt, targetName) {
|
||||
evt.target = {
|
||||
nodeName : targetName
|
||||
};
|
||||
};
|
||||
|
||||
it("accepts only shortcut instances", function() {
|
||||
console.log('[ShortcutService] accepts only shortcut instances');
|
||||
|
||||
console.log('[ShortcutService] ... fails for missing shortcut');
|
||||
expect(function () {
|
||||
service.registerShortcut();
|
||||
}).toThrow('Invalid shortcut argument, please use instances of pskl.service.keyboard.Shortcut');
|
||||
|
||||
console.log('[ShortcutService] ... fails for shortcut as empty object');
|
||||
expect(function () {
|
||||
service.registerShortcut({});
|
||||
}).toThrow('Invalid shortcut argument, please use instances of pskl.service.keyboard.Shortcut');
|
||||
|
||||
console.log('[ShortcutService] ... fails for shortcut as a string');
|
||||
expect(function () {
|
||||
service.registerShortcut('alt+F4');
|
||||
}).toThrow('Invalid shortcut argument, please use instances of pskl.service.keyboard.Shortcut');
|
||||
|
||||
var shortcut = new pskl.service.keyboard.Shortcut('shortcut-id', '', A_KEY);
|
||||
|
||||
console.log('[ShortcutService] ... fails for missing callback');
|
||||
expect(function () {
|
||||
service.registerShortcut(shortcut);
|
||||
}).toThrow('Invalid callback argument, please provide a function');
|
||||
|
||||
console.log('[ShortcutService] ... fails for invalid callback');
|
||||
expect(function () {
|
||||
service.registerShortcut(shortcut, {callback : function () {}});
|
||||
}).toThrow('Invalid callback argument, please provide a function');
|
||||
|
||||
console.log('[ShortcutService] ... is ok for valid arguments');
|
||||
service.registerShortcut(shortcut, function () {});
|
||||
});
|
||||
|
||||
it ("triggers shortcut", function () {
|
||||
console.log('[ShortcutService] triggers shortcut');
|
||||
var callbackCalled = false;
|
||||
|
||||
console.log('[ShortcutService] ... register shortcut for A');
|
||||
var shortcutA = new pskl.service.keyboard.Shortcut('shortcut-a', '', A_KEY);
|
||||
service.registerShortcut(shortcutA, function () {
|
||||
callbackCalled = true;
|
||||
});
|
||||
|
||||
console.log('[ShortcutService] ... verify shortcut is called');
|
||||
service.onKeyUp_(createEvent(A_KEYCODE));
|
||||
expect(callbackCalled).toBe(true);
|
||||
});
|
||||
|
||||
it ("triggers shortcuts independently", function () {
|
||||
console.log('[ShortcutService] registers shortcuts');
|
||||
|
||||
var shortcutA = new pskl.service.keyboard.Shortcut('shortcut-a', '', A_KEY);
|
||||
var shortcutB = new pskl.service.keyboard.Shortcut('shortcut-b', '', B_KEY);
|
||||
var shortcutA_B = new pskl.service.keyboard.Shortcut('shortcut-a&b', '', [A_KEY, B_KEY]);
|
||||
|
||||
var counters = {
|
||||
a : 0,
|
||||
b : 0,
|
||||
a_b : 0
|
||||
};
|
||||
|
||||
console.log('[ShortcutService] ... register separate shortcuts for A and B');
|
||||
service.registerShortcut(shortcutA, function () {
|
||||
counters.a++;
|
||||
});
|
||||
service.registerShortcut(shortcutB, function () {
|
||||
counters.b++;
|
||||
});
|
||||
service.registerShortcut(shortcutA_B, function () {
|
||||
counters.a_b++;
|
||||
});
|
||||
|
||||
console.log('[ShortcutService] ... trigger A, expect counter A at 1, B at 0, A_B at 1');
|
||||
service.onKeyUp_(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));
|
||||
expect(counters.a).toBe(1);
|
||||
expect(counters.b).toBe(1);
|
||||
expect(counters.a_b).toBe(2);
|
||||
});
|
||||
|
||||
it ("unregisters shortcut", function () {
|
||||
console.log('[ShortcutService] unregisters shortcut');
|
||||
var callbackCalled = false;
|
||||
|
||||
console.log('[ShortcutService] ... register shortcut for A');
|
||||
var shortcutA = new pskl.service.keyboard.Shortcut('shortcut-a', '', A_KEY);
|
||||
service.registerShortcut(shortcutA, function () {
|
||||
callbackCalled = true;
|
||||
});
|
||||
|
||||
console.log('[ShortcutService] ... unregister shortcut A');
|
||||
service.unregisterShortcut(shortcutA);
|
||||
|
||||
console.log('[ShortcutService] ... verify shortcut callback is not called');
|
||||
service.onKeyUp_(createEvent(A_KEYCODE));
|
||||
expect(callbackCalled).toBe(false);
|
||||
});
|
||||
|
||||
it ("unregisters shortcut without removing other shortcuts", function () {
|
||||
console.log('[ShortcutService] unregisters shortcut');
|
||||
var callbackCalled = false;
|
||||
|
||||
console.log('[ShortcutService] ... register shortcut for A & B');
|
||||
var shortcutA = new pskl.service.keyboard.Shortcut('shortcut-a', '', A_KEY);
|
||||
var shortcutB = new pskl.service.keyboard.Shortcut('shortcut-b', '', B_KEY);
|
||||
service.registerShortcut(shortcutA, function () {});
|
||||
service.registerShortcut(shortcutB, function () {
|
||||
callbackCalled = true;
|
||||
});
|
||||
|
||||
console.log('[ShortcutService] ... unregister shortcut A');
|
||||
service.unregisterShortcut(shortcutA);
|
||||
|
||||
console.log('[ShortcutService] ... verify shortcut callback for B can still be called');
|
||||
service.onKeyUp_(createEvent(B_KEYCODE));
|
||||
expect(callbackCalled).toBe(true);
|
||||
});
|
||||
|
||||
it ("supports unregistering unknown shortcuts", function () {
|
||||
console.log('[ShortcutService] unregisters shortcut');
|
||||
var callbackCalled = false;
|
||||
|
||||
console.log('[ShortcutService] ... register shortcut for A');
|
||||
var shortcutA = new pskl.service.keyboard.Shortcut('shortcut-a', '', A_KEY);
|
||||
service.registerShortcut(shortcutA, function () {
|
||||
callbackCalled = true;
|
||||
});
|
||||
|
||||
console.log('[ShortcutService] ... unregister shortcut B, which was not registered in the first place');
|
||||
var shortcutB = new pskl.service.keyboard.Shortcut('shortcut-b', '', B_KEY);
|
||||
service.unregisterShortcut(shortcutB);
|
||||
|
||||
console.log('[ShortcutService] ... verify shortcut callback for A can still be called');
|
||||
callbackCalled = false;
|
||||
service.onKeyUp_(createEvent(A_KEYCODE));
|
||||
expect(callbackCalled).toBe(true);
|
||||
});
|
||||
|
||||
it ("does not trigger shortcuts from INPUT or TEXTAREA", function () {
|
||||
console.log('[ShortcutService] triggers shortcut');
|
||||
var callbackCalled = false;
|
||||
|
||||
console.log('[ShortcutService] ... register shortcut for A');
|
||||
var shortcutA = new pskl.service.keyboard.Shortcut('shortcut-a', '', A_KEY);
|
||||
service.registerShortcut(shortcutA, function () {
|
||||
callbackCalled = true;
|
||||
});
|
||||
|
||||
console.log('[ShortcutService] ... verify shortcut is not called from event on INPUT');
|
||||
service.onKeyUp_(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'));
|
||||
expect(callbackCalled).toBe(false);
|
||||
|
||||
console.log('[ShortcutService] ... verify shortcut is called from event on LINK');
|
||||
service.onKeyUp_(createEvent(A_KEYCODE).setNodeName('A'));
|
||||
expect(callbackCalled).toBe(true);
|
||||
});
|
||||
|
||||
it ("supports meta modifiers", function () {
|
||||
console.log('[ShortcutService] triggers shortcut');
|
||||
var callbackCalled = false;
|
||||
|
||||
console.log('[ShortcutService] ... create various A shortcuts with modifiers');
|
||||
var shortcuts = [
|
||||
new pskl.service.keyboard.Shortcut('a', '', A_KEY),
|
||||
new pskl.service.keyboard.Shortcut('a_ctrl', '', 'ctrl+' + A_KEY),
|
||||
new pskl.service.keyboard.Shortcut('a_ctrl_shift', '', 'ctrl+shift+' + A_KEY),
|
||||
new pskl.service.keyboard.Shortcut('a_ctrl_shift_alt', '', 'ctrl+shift+alt+' + A_KEY),
|
||||
new pskl.service.keyboard.Shortcut('a_alt', '', 'alt+' + A_KEY)
|
||||
];
|
||||
|
||||
var counters = {
|
||||
a : 0,
|
||||
a_ctrl : 0,
|
||||
a_ctrl_shift : 0,
|
||||
a_ctrl_shift_alt : 0,
|
||||
a_alt : 0,
|
||||
};
|
||||
|
||||
shortcuts.forEach(function (shortcut) {
|
||||
service.registerShortcut(shortcut, function () {
|
||||
counters[shortcut.getId()]++;
|
||||
});
|
||||
});
|
||||
|
||||
var verifyCounters = function (a, a_c, a_cs, a_csa, a_a) {
|
||||
expect(counters.a).toBe(a);
|
||||
expect(counters.a_ctrl).toBe(a_c);
|
||||
expect(counters.a_ctrl_shift).toBe(a_cs);
|
||||
expect(counters.a_ctrl_shift_alt).toBe(a_csa);
|
||||
expect(counters.a_alt).toBe(a_a);
|
||||
};
|
||||
|
||||
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));
|
||||
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());
|
||||
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());
|
||||
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());
|
||||
verifyCounters(1,1,1,1,0);
|
||||
|
||||
console.log('[ShortcutService] ... trigger CTRL+A, expect all counters at 1');
|
||||
service.onKeyUp_(createEvent(A_KEYCODE).withAltKey());
|
||||
verifyCounters(1,1,1,1,1);
|
||||
});
|
||||
|
||||
});
|
Loading…
Reference in a new issue