* @constructor
* @extends {WebInspector.Object}
* @param {!Element} element
+ * @param {boolean=} disableRotate
*/
-WebInspector.TransformController = function(element)
+WebInspector.TransformController = function(element, disableRotate)
{
+ this._shortcuts = {};
this.element = element;
- element.addEventListener("mousemove", this._onMouseMove.bind(this), false);
- element.addEventListener("mousedown", this._onMouseDown.bind(this), false);
- element.addEventListener("mouseup", this._onMouseUp.bind(this), false);
+ if (this.element.tabIndex < 0)
+ this.element.tabIndex = 0;
+ this._registerShortcuts();
+ WebInspector.installDragHandle(element, this._onDragStart.bind(this), this._onDrag.bind(this), this._onDragEnd.bind(this), "move", null);
+ element.addEventListener("keydown", this._onKeyDown.bind(this), false);
+ element.addEventListener("keyup", this._onKeyUp.bind(this), false);
element.addEventListener("mousewheel", this._onMouseWheel.bind(this), false);
+ this._disableRotate = disableRotate;
+ this._minScale = 0;
+ this._maxScale = Infinity;
+
+ this._controlPanelElement = createElement("div");
+ this._controlPanelElement.classList.add("transform-control-panel");
+
+ this._modeButtons = {};
+ if (!disableRotate) {
+ var panModeButton = new WebInspector.StatusBarButton(WebInspector.UIString("Pan mode (X)"), "transform-mode-pan");
+ panModeButton.addEventListener("click", this._setMode.bind(this, WebInspector.TransformController.Modes.Pan));
+ this._modeButtons[WebInspector.TransformController.Modes.Pan] = panModeButton;
+ this._controlPanelElement.appendChild(panModeButton.element);
+ var rotateModeButton = new WebInspector.StatusBarButton(WebInspector.UIString("Rotate mode (V)"), "transform-mode-rotate");
+ rotateModeButton.addEventListener("click", this._setMode.bind(this, WebInspector.TransformController.Modes.Rotate));
+ this._modeButtons[WebInspector.TransformController.Modes.Rotate] = rotateModeButton;
+ this._controlPanelElement.appendChild(rotateModeButton.element);
+ }
+ this._setMode(WebInspector.TransformController.Modes.Pan);
+
+ var resetButton = new WebInspector.StatusBarButton(WebInspector.UIString("Reset transform (0)"), "transform-reset");
+ resetButton.addEventListener("click", this.resetAndNotify.bind(this, undefined));
+ this._controlPanelElement.appendChild(resetButton.element);
+
this._reset();
}
TransformChanged: "TransformChanged"
}
+/**
+ * @enum {string}
+ */
+WebInspector.TransformController.Modes = {
+ Pan: "Pan",
+ Rotate: "Rotate",
+}
+
WebInspector.TransformController.prototype = {
/**
- * @param {function(!Array.<!WebInspector.KeyboardShortcut.Descriptor>, function(?Event=))} registerShortcutDelegate
+ * @return {!Element}
*/
- registerShortcuts: function(registerShortcutDelegate)
+ controlPanelElement: function()
+ {
+ return this._controlPanelElement;
+ },
+
+ _onKeyDown: function(event)
+ {
+ if (event.keyCode === WebInspector.KeyboardShortcut.Keys.Shift.code) {
+ this._toggleMode();
+ return;
+ }
+
+ var shortcutKey = WebInspector.KeyboardShortcut.makeKeyFromEventIgnoringModifiers(event);
+ var handler = this._shortcuts[shortcutKey];
+ if (handler && handler(event))
+ event.consume();
+ },
+
+ _onKeyUp: function(event)
{
- registerShortcutDelegate(WebInspector.ShortcutsScreen.LayersPanelShortcuts.ResetView, this._resetAndNotify.bind(this));
+ if (event.keyCode === WebInspector.KeyboardShortcut.Keys.Shift.code)
+ this._toggleMode();
+ },
+
+ _addShortcuts: function(keys, handler)
+ {
+ for (var i = 0; i < keys.length; ++i)
+ this._shortcuts[keys[i].key] = handler;
+ },
+
+ _registerShortcuts: function()
+ {
+ this._addShortcuts(WebInspector.ShortcutsScreen.LayersPanelShortcuts.ResetView, this.resetAndNotify.bind(this));
+ this._addShortcuts(WebInspector.ShortcutsScreen.LayersPanelShortcuts.PanMode, this._setMode.bind(this, WebInspector.TransformController.Modes.Pan));
+ this._addShortcuts(WebInspector.ShortcutsScreen.LayersPanelShortcuts.RotateMode, this._setMode.bind(this, WebInspector.TransformController.Modes.Rotate));
var zoomFactor = 1.1;
- registerShortcutDelegate(WebInspector.ShortcutsScreen.LayersPanelShortcuts.ZoomIn, this._onKeyboardZoom.bind(this, zoomFactor));
- registerShortcutDelegate(WebInspector.ShortcutsScreen.LayersPanelShortcuts.ZoomOut, this._onKeyboardZoom.bind(this, 1 / zoomFactor));
- var panDistanceInPixels = 6;
- registerShortcutDelegate(WebInspector.ShortcutsScreen.LayersPanelShortcuts.PanUp, this._onPan.bind(this, 0, -panDistanceInPixels));
- registerShortcutDelegate(WebInspector.ShortcutsScreen.LayersPanelShortcuts.PanDown, this._onPan.bind(this, 0, panDistanceInPixels));
- registerShortcutDelegate(WebInspector.ShortcutsScreen.LayersPanelShortcuts.PanLeft, this._onPan.bind(this, -panDistanceInPixels, 0));
- registerShortcutDelegate(WebInspector.ShortcutsScreen.LayersPanelShortcuts.PanRight, this._onPan.bind(this, panDistanceInPixels, 0));
- var rotateDegrees = 5;
- registerShortcutDelegate(WebInspector.ShortcutsScreen.LayersPanelShortcuts.RotateCWX, this._onKeyboardRotate.bind(this, rotateDegrees, 0));
- registerShortcutDelegate(WebInspector.ShortcutsScreen.LayersPanelShortcuts.RotateCCWX, this._onKeyboardRotate.bind(this, -rotateDegrees, 0));
- registerShortcutDelegate(WebInspector.ShortcutsScreen.LayersPanelShortcuts.RotateCWY, this._onKeyboardRotate.bind(this, 0, -rotateDegrees));
- registerShortcutDelegate(WebInspector.ShortcutsScreen.LayersPanelShortcuts.RotateCCWY, this._onKeyboardRotate.bind(this, 0, rotateDegrees));
+ this._addShortcuts(WebInspector.ShortcutsScreen.LayersPanelShortcuts.ZoomIn, this._onKeyboardZoom.bind(this, zoomFactor));
+ this._addShortcuts(WebInspector.ShortcutsScreen.LayersPanelShortcuts.ZoomOut, this._onKeyboardZoom.bind(this, 1 / zoomFactor));
+ this._addShortcuts(WebInspector.ShortcutsScreen.LayersPanelShortcuts.Up, this._onKeyboardPanOrRotate.bind(this, 0, -1));
+ this._addShortcuts(WebInspector.ShortcutsScreen.LayersPanelShortcuts.Down, this._onKeyboardPanOrRotate.bind(this, 0, 1));
+ this._addShortcuts(WebInspector.ShortcutsScreen.LayersPanelShortcuts.Left, this._onKeyboardPanOrRotate.bind(this, -1, 0));
+ this._addShortcuts(WebInspector.ShortcutsScreen.LayersPanelShortcuts.Right, this._onKeyboardPanOrRotate.bind(this, 1, 0));
},
_postChangeEvent: function()
this._rotateY = 0;
},
+ _toggleMode: function()
+ {
+ this._setMode(this._mode === WebInspector.TransformController.Modes.Pan ? WebInspector.TransformController.Modes.Rotate : WebInspector.TransformController.Modes.Pan);
+ },
+
/**
- * @param {?Event=} event
+ * @param {!WebInspector.TransformController.Modes} mode
*/
- _resetAndNotify: function(event)
+ _setMode: function(mode)
+ {
+ if (this._mode === mode)
+ return;
+ this._mode = mode;
+ this._updateModeButtons();
+ this.element.focus();
+ },
+
+ _updateModeButtons: function()
+ {
+ for (var mode in this._modeButtons)
+ this._modeButtons[mode].toggled = (mode === this._mode);
+ },
+
+ /**
+ * @param {!Event=} event
+ */
+ resetAndNotify: function(event)
{
this._reset();
this._postChangeEvent();
if (event)
event.preventDefault();
+ this.element.focus();
+ },
+
+ /**
+ * @param {number} minScale
+ * @param {number} maxScale
+ */
+ setScaleConstraints: function(minScale, maxScale)
+ {
+ this._minScale = minScale;
+ this._maxScale = maxScale;
+ this._scale = Number.constrain(this._scale, minScale, maxScale);
+ },
+
+ /**
+ * @param {number} minX
+ * @param {number} maxX
+ * @param {number} minY
+ * @param {number} maxY
+ */
+ clampOffsets: function(minX, maxX, minY, maxY)
+ {
+ this._offsetX = Number.constrain(this._offsetX, minX, maxX);
+ this._offsetY = Number.constrain(this._offsetY, minY, maxY);
},
/**
*/
_onScale: function(scaleFactor, x, y)
{
+ scaleFactor = Number.constrain(this._scale * scaleFactor, this._minScale, this._maxScale) / this._scale;
this._scale *= scaleFactor;
this._offsetX -= (x - this._offsetX) * (scaleFactor - 1);
this._offsetY -= (y - this._offsetY) * (scaleFactor - 1);
},
/**
- * @param {number} rotateX
- * @param {number} rotateY
+ * @param {number} xMultiplier
+ * @param {number} yMultiplier
*/
- _onKeyboardRotate: function(rotateX, rotateY)
+ _onKeyboardPanOrRotate: function(xMultiplier, yMultiplier)
{
- this._onRotate(this._rotateX + rotateX, this._rotateY + rotateY);
+ var panStepInPixels = 6;
+ var rotateStepInDegrees = 5;
+
+ if (this._mode === WebInspector.TransformController.Modes.Rotate) {
+ // Sic! _onRotate treats X and Y as "rotate around X" and "rotate around Y", so swap X/Y multiplers.
+ this._onRotate(this._rotateX + yMultiplier * rotateStepInDegrees, this._rotateY + xMultiplier * rotateStepInDegrees);
+ } else {
+ this._onPan(xMultiplier * panStepInPixels, yMultiplier * panStepInPixels);
+ }
},
/**
- * @param {?Event} event
+ * @param {!Event} event
*/
_onMouseWheel: function(event)
{
- if (!event.altKey) {
- /** @const */
- var zoomFactor = 1.1;
- /** @const */
- var mouseWheelZoomSpeed = 1 / 120;
- var scaleFactor = Math.pow(zoomFactor, event.wheelDeltaY * mouseWheelZoomSpeed);
- this._onScale(scaleFactor, event.clientX - this.element.totalOffsetLeft(), event.clientY - this.element.totalOffsetTop());
- } else {
- /** @const */
- var moveFactor = 1 / 20;
- this._onPan(event.wheelDeltaX * moveFactor, event.wheelDeltaY * moveFactor);
- }
+ /** @const */
+ var zoomFactor = 1.1;
+ /** @const */
+ var mouseWheelZoomSpeed = 1 / 120;
+ var scaleFactor = Math.pow(zoomFactor, event.wheelDeltaY * mouseWheelZoomSpeed);
+ this._onScale(scaleFactor, event.clientX - this.element.totalOffsetLeft(), event.clientY - this.element.totalOffsetTop());
},
/**
- * @param {?Event} event
+ * @param {!Event} event
*/
- _onMouseMove: function(event)
+ _onDrag: function(event)
{
- if (event.which !== 1 || typeof this._originX !== "number")
- return;
- this._onRotate(this._oldRotateX + (this._originY - event.clientY) / this.element.clientHeight * 180, this._oldRotateY - (this._originX - event.clientX) / this.element.clientWidth * 180);
+ if (this._mode === WebInspector.TransformController.Modes.Rotate) {
+ this._onRotate(this._oldRotateX + (this._originY - event.clientY) / this.element.clientHeight * 180, this._oldRotateY - (this._originX - event.clientX) / this.element.clientWidth * 180);
+ } else {
+ this._onPan(event.clientX - this._originX, event.clientY - this._originY);
+ this._originX = event.clientX;
+ this._originY = event.clientY;
+ }
},
/**
- * @param {?Event} event
+ * @param {!MouseEvent} event
*/
- _setReferencePoint: function(event)
+ _onDragStart: function(event)
{
+ this.element.focus();
this._originX = event.clientX;
this._originY = event.clientY;
this._oldRotateX = this._rotateX;
this._oldRotateY = this._rotateY;
+ return true;
},
- _resetReferencePoint: function()
+ _onDragEnd: function()
{
delete this._originX;
delete this._originY;
delete this._oldRotateY;
},
- /**
- * @param {?Event} event
- */
- _onMouseDown: function(event)
- {
- if (event.which !== 1)
- return;
- this._setReferencePoint(event);
- },
-
- /**
- * @param {?Event} event
- */
- _onMouseUp: function(event)
- {
- if (event.which !== 1)
- return;
- this._resetReferencePoint();
- },
-
__proto__: WebInspector.Object.prototype
}