feature : add keyboard shortcuts : initial impl

+ added shortcuts for all tools in ToolController
+ modified structure of tools in Controller to Array of descriptors to
allow to declare shortcuts directly when setting up the tool controller
This commit is contained in:
jdescottes 2013-11-17 22:07:26 +01:00
parent 25e6470499
commit f0ef016309
4 changed files with 64 additions and 36 deletions

View File

@ -40,9 +40,11 @@ var Events = {
SHOW_NOTIFICATION: "SHOW_NOTIFICATION", SHOW_NOTIFICATION: "SHOW_NOTIFICATION",
HIDE_NOTIFICATION: "HIDE_NOTIFICATION", HIDE_NOTIFICATION: "HIDE_NOTIFICATION",
// Events triggered by keyboard
UNDO: "UNDO", UNDO: "UNDO",
REDO: "REDO", REDO: "REDO",
CUT: "CUT", CUT: "CUT",
COPY: "COPY", COPY: "COPY",
PASTE: "PASTE" PASTE: "PASTE",
SELECT_TOOL : "SELECT_TOOL"
}; };

View File

@ -1,25 +1,28 @@
(function () { (function () {
var ns = $.namespace("pskl.controller"); var ns = $.namespace("pskl.controller");
ns.ToolController = function () { ns.ToolController = function () {
var toDescriptor = function (id, shortcut, instance) {
this.toolInstances = { return {id:id, shortcut:shortcut, instance:instance};
"simplePen" : new pskl.drawingtools.SimplePen(),
"verticalMirrorPen" : new pskl.drawingtools.VerticalMirrorPen(),
"eraser" : new pskl.drawingtools.Eraser(),
"paintBucket" : new pskl.drawingtools.PaintBucket(),
"stroke" : new pskl.drawingtools.Stroke(),
"rectangle" : new pskl.drawingtools.Rectangle(),
"circle" : new pskl.drawingtools.Circle(),
"move" : new pskl.drawingtools.Move(),
"rectangleSelect" : new pskl.drawingtools.RectangleSelect(),
"shapeSelect" : new pskl.drawingtools.ShapeSelect(),
"colorPicker" : new pskl.drawingtools.ColorPicker()
}; };
this.currentSelectedTool = this.toolInstances.simplePen; this.tools = [
this.previousSelectedTool = this.toolInstances.simplePen; toDescriptor('simplePen', 'P', new pskl.drawingtools.SimplePen()),
toDescriptor('verticalMirrorPen', 'V', new pskl.drawingtools.VerticalMirrorPen()),
toDescriptor('eraser', 'E', new pskl.drawingtools.Eraser()),
toDescriptor('paintBucket', 'B', new pskl.drawingtools.PaintBucket()),
toDescriptor('stroke', 'L', new pskl.drawingtools.Stroke()),
toDescriptor('rectangle', 'R', new pskl.drawingtools.Rectangle()),
toDescriptor('circle', 'C', new pskl.drawingtools.Circle()),
toDescriptor('move', 'M', new pskl.drawingtools.Move()),
toDescriptor('rectangleSelect', 'S', new pskl.drawingtools.RectangleSelect()),
toDescriptor('shapeSelect', 'Z', new pskl.drawingtools.ShapeSelect()),
toDescriptor('colorPicker', 'O', new pskl.drawingtools.ColorPicker())
];
this.currentSelectedTool = this.tools[0];
this.previousSelectedTool = this.tools[0];
}; };
/** /**
@ -30,9 +33,11 @@
// Initialize tool: // Initialize tool:
// Set SimplePen as default selected tool: // Set SimplePen as default selected tool:
this.selectTool_(this.toolInstances.simplePen); this.selectTool_(this.tools[0]);
// Activate listener on tool panel: // Activate listener on tool panel:
$("#tool-section").click($.proxy(this.onToolIconClicked_, this)); $("#tool-section").click($.proxy(this.onToolIconClicked_, this));
$.subscribe(Events.SELECT_TOOL, $.proxy(this.onKeyboardShortcut_, this));
}; };
/** /**
@ -44,18 +49,18 @@
if(previousSelectedToolClass) { if(previousSelectedToolClass) {
stage.removeClass(previousSelectedToolClass); stage.removeClass(previousSelectedToolClass);
} }
stage.addClass(tool.toolId); stage.addClass(tool.instance.toolId);
stage.data("selected-tool-class", tool.toolId); stage.data("selected-tool-class", tool.instance.toolId);
}; };
/** /**
* @private * @private
*/ */
ns.ToolController.prototype.selectTool_ = function(tool) { ns.ToolController.prototype.selectTool_ = function(tool) {
console.log("Selecting Tool:" , this.currentSelectedTool); console.log("Selecting Tool:" , this.currentSelectedTool.name);
this.currentSelectedTool = tool; this.currentSelectedTool = tool;
this.activateToolOnStage_(this.currentSelectedTool); this.activateToolOnStage_(this.currentSelectedTool);
$.publish(Events.TOOL_SELECTED, [tool]); $.publish(Events.TOOL_SELECTED, [tool.instance]);
}; };
/** /**
@ -78,10 +83,20 @@
} }
}; };
ns.ToolController.prototype.onKeyboardShortcut_ = function(evt, 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.getToolById_ = function (toolId) { ns.ToolController.prototype.getToolById_ = function (toolId) {
for(var key in this.toolInstances) { for(var i = 0 ; i < this.tools.length ; i++) {
if (this.toolInstances[key].toolId == toolId) { var tool = this.tools[i];
return this.toolInstances[key]; if (tool.instance.toolId == toolId) {
return tool;
} }
} }
return null; return null;
@ -93,14 +108,16 @@
ns.ToolController.prototype.createToolMarkup_ = function() { ns.ToolController.prototype.createToolMarkup_ = function() {
var currentTool, toolMarkup = '', extraClass; var currentTool, toolMarkup = '', extraClass;
// TODO(vincz): Tools rendering order is not enforced by the data stucture (this.toolInstances), fix that. // TODO(vincz): Tools rendering order is not enforced by the data stucture (this.toolInstances), fix that.
for (var toolKey in this.toolInstances) { for(var i = 0 ; i < this.tools.length ; i++) {
currentTool = this.toolInstances[toolKey]; var tool = this.tools[i];
extraClass = currentTool.toolId; var instance = tool.instance;
if (this.currentSelectedTool == currentTool) {
extraClass = instance.toolId;
if (this.currentSelectedTool == tool) {
extraClass = extraClass + " selected"; extraClass = extraClass + " selected";
} }
toolMarkup += '<li rel="tooltip" data-placement="right" class="tool-icon ' + extraClass + '" data-tool-id="' + currentTool.toolId + toolMarkup += '<li rel="tooltip" data-placement="right" class="tool-icon ' + extraClass + '" data-tool-id="' + instance.toolId +
'" title="' + currentTool.helpText + '"></li>'; '" title="' + instance.helpText + '"></li>';
} }
$('#tools-container').html(toolMarkup); $('#tools-container').html(toolMarkup);
}; };

View File

@ -11,6 +11,13 @@
"v" : Events.PASTE "v" : Events.PASTE
} }
}; };
// See ToolController
// TODO : Allow for other classes to register new shortcuts
var toolKeys = 'pveblrcmzso'.split('');
toolKeys.forEach(function (key) {
this.keyboardActions_[key] = Events.SELECT_TOOL;
}.bind(this));
}; };
@ -34,12 +41,14 @@
if(charkey) { if(charkey) {
if (this.isCtrlKeyPressed_(evt)) { if (this.isCtrlKeyPressed_(evt)) {
eventToTrigger = this.keyboardActions_.ctrl[charkey]; eventToTrigger = this.keyboardActions_.ctrl[charkey];
} else {
eventToTrigger = this.keyboardActions_[charkey];
} }
}
if(eventToTrigger) { if(eventToTrigger) {
$.publish(eventToTrigger); $.publish(eventToTrigger, charkey);
evt.preventDefault(); evt.preventDefault();
}
} }
}; };

View File

@ -1,7 +1,7 @@
(function () { (function () {
var specialKeys = {}; var specialKeys = {};
var ns = $.namespace('service.keyboard'); var ns = $.namespace('pskl.service.keyboard');
ns.KeycodeTranslator= { ns.KeycodeTranslator= {
toChar : function (keycode) { toChar : function (keycode) {