diff options
Diffstat (limited to 'webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/event')
11 files changed, 4272 insertions, 0 deletions
diff --git a/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/event/handler/DragAndDropHandler.js b/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/event/handler/DragAndDropHandler.js new file mode 100644 index 0000000000..48b3cdf517 --- /dev/null +++ b/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/event/handler/DragAndDropHandler.js @@ -0,0 +1,952 @@ +/* ************************************************************************ + + qooxdoo - the new era of web development + + http://qooxdoo.org + + Copyright: + 2004-2007 1&1 Internet AG, Germany, http://www.1and1.org + + License: + LGPL: http://www.gnu.org/licenses/lgpl.html + EPL: http://www.eclipse.org/org/documents/epl-v10.php + See the LICENSE file in the project's top-level directory for details. + + Authors: + * Sebastian Werner (wpbasti) + * Andreas Ecker (ecker) + +************************************************************************ */ + +/* ************************************************************************ + +#module(ui_dragdrop) +#load(qx.html.ElementFromPoint) +#embed(qx.widgettheme/cursors/*) + +************************************************************************ */ + +/** + * This manager (singleton) manage all drag and drop handling of a qx.core.Init instance. + */ +qx.OO.defineClass("qx.event.handler.DragAndDropHandler", qx.manager.object.ObjectManager, +function() +{ + qx.core.Target.call(this); + + this._data = {}; + this._actions = {}; + this._cursors = {}; + + var vCursor; + for (var vAction in this._actionNames) + { + vCursor = this._cursors[vAction] = new qx.ui.basic.Image(this._cursorPath + vAction + "." + this._cursorFormat); + vCursor.setZIndex(1e8); + } +}); + +qx.OO.addProperty({ name : "sourceWidget", type : "object" }); +qx.OO.addProperty({ name : "destinationWidget", type : "object" }); +qx.OO.addProperty({ name : "cursor", type : "object" }); +qx.OO.addProperty({ name : "currentAction", type : "string" }); + +/** + * The default delta x of the cursor feedback. + * + * @see #setCursorPosition + */ +qx.OO.addProperty({ name : "defaultCursorDeltaX", type : "number", defaultValue : 5, allowNull : false }); + +/** + * The default delta y of the cursor feedback. + * + * @see #setCursorPosition + */ +qx.OO.addProperty({ name : "defaultCursorDeltaY", type : "number", defaultValue : 15, allowNull : false }); + +qx.Proto._actionNames = +{ + move : "move", + copy : "copy", + alias : "alias", + nodrop : "nodrop" +} + +qx.Proto._cursorPath = "widget/cursors/"; +qx.Proto._cursorFormat = "gif"; +qx.Proto._lastDestinationEvent = null; + + + + + +/* +--------------------------------------------------------------------------- + COMMON MODIFIER +--------------------------------------------------------------------------- +*/ + +qx.Proto._modifyDestinationWidget = function(propValue, propOldValue, propData) +{ + if (propValue) + { + propValue.dispatchEvent(new qx.event.type.DragEvent("dragdrop", this._lastDestinationEvent, propValue, this.getSourceWidget())); + this._lastDestinationEvent = null; + } + + return true; +} + + + + + + + + +/* +--------------------------------------------------------------------------- + DATA HANDLING +--------------------------------------------------------------------------- +*/ + +/*! +Add data of mimetype. + +#param vMimeType[String]: A valid mimetype +#param vData[Any]: Any value for the mimetype +*/ +qx.Proto.addData = function(vMimeType, vData) { + this._data[vMimeType] = vData; +} + +qx.Proto.getData = function(vMimeType) { + return this._data[vMimeType]; +} + +qx.Proto.clearData = function() { + this._data = {}; +} + + + + + + + + + +/* +--------------------------------------------------------------------------- + MIME TYPE HANDLING +--------------------------------------------------------------------------- +*/ + +qx.Proto.getDropDataTypes = function() +{ + var vDestination = this.getDestinationWidget(); + var vDropTypes = []; + + // If there is not any destination, simple return + if (!vDestination) { + return vDropTypes; + } + + // Search for matching mimetypes + var vDropDataTypes = vDestination.getDropDataTypes(); + + for (var i=0, l=vDropDataTypes.length; i<l; i++) { + if (vDropDataTypes[i] in this._data) { + vDropTypes.push(vDropDataTypes[i]); + } + } + + return vDropTypes; +} + + + + + + + +/* +--------------------------------------------------------------------------- + START DRAG +--------------------------------------------------------------------------- +*/ + +/*! +This needed be called from any "dragstart" event to really start drag session. +*/ +qx.Proto.startDrag = function() +{ + if (!this._dragCache) { + throw new Error("Invalid usage of startDrag. Missing dragInfo!"); + } + + // Update status flag + this._dragCache.dragHandlerActive = true; + + // Internal storage of source widget + this.setSourceWidget(this._dragCache.sourceWidget); + + // Add feedback widget + if (this._feedbackWidget) { + this._feedbackWidget.setVisibility(false); + + var doc = qx.ui.core.ClientDocument.getInstance(); + doc.add(this._feedbackWidget); + } +} + + + + + + + +/* +--------------------------------------------------------------------------- + FIRE IMPLEMENTATION FOR USER EVENTS +--------------------------------------------------------------------------- +*/ + +qx.Proto._fireUserEvents = function(fromWidget, toWidget, e) +{ + if (fromWidget && fromWidget != toWidget && fromWidget.hasEventListeners("dragout")) { + fromWidget.dispatchEvent(new qx.event.type.DragEvent("dragout", e, fromWidget, toWidget), true); + } + + if (toWidget) + { + if (fromWidget != toWidget && toWidget.hasEventListeners("dragover")) { + toWidget.dispatchEvent(new qx.event.type.DragEvent("dragover", e, toWidget, fromWidget), true); + } + + if (toWidget.hasEventListeners("dragmove")) { + toWidget.dispatchEvent(new qx.event.type.DragEvent("dragmove", e, toWidget, null), true); + } + } +} + + + + + + + + +/* +--------------------------------------------------------------------------- + HANDLER FOR MOUSE EVENTS +--------------------------------------------------------------------------- +*/ + +/*! +This wraps the mouse events to custom handlers. +*/ +qx.Proto.handleMouseEvent = function(e) +{ + switch (e.getType()) + { + case "mousedown": + return this._handleMouseDown(e); + + case "mouseup": + return this._handleMouseUp(e); + + case "mousemove": + return this._handleMouseMove(e); + } +} + +/*! +This starts the core drag and drop session. + +To really get drag and drop working you need to define +a function which you attach to "dragstart"-event, which +invokes at least this.startDrag() +*/ +qx.Proto._handleMouseDown = function(e) +{ + if (e.getDefaultPrevented() || ! e.isLeftButtonPressed()) { + return; + } + + // Store initial dragCache + this._dragCache = + { + startScreenX : e.getScreenX(), + startScreenY : e.getScreenY(), + + pageX : e.getPageX(), + pageY : e.getPageY(), + + sourceWidget : e.getTarget(), + sourceTopLevel : e.getTarget().getTopLevelWidget(), + + dragHandlerActive : false, + hasFiredDragStart : false + } +} + + +/*! +Handler for mouse move events +*/ + +qx.Proto._handleMouseMove = function(e) +{ + // Return if dragCache was not filled before + if (!this._dragCache) { + return; + } + + /* + Default handling if drag handler is activated + */ + + if (this._dragCache.dragHandlerActive) + { + // Update page coordinates + this._dragCache.pageX = e.getPageX(); + this._dragCache.pageY = e.getPageY(); + + // Get current target + var currentDropTarget = this.getDropTarget(e); + + // Update action + this.setCurrentAction(currentDropTarget ? this._evalNewAction(e.isShiftPressed(), e.isCtrlPressed(), e.isAltPressed()) : null); + + // Fire user events + this._fireUserEvents(this._dragCache.currentDropWidget, currentDropTarget, e); + + // Store current widget + this._dragCache.currentDropWidget = currentDropTarget; + + // Update cursor icon + this._renderCursor(); + + // Update user feedback + this._renderFeedbackWidget(); + } + + /* + Initial activation and fire of dragstart + */ + else if (!this._dragCache.hasFiredDragStart) + { + if (Math.abs(e.getScreenX() - this._dragCache.startScreenX) > 5 || Math.abs(e.getScreenY() - this._dragCache.startScreenY) > 5) + { + // Fire dragstart event to finally allow the above if to handle next events + this._dragCache.sourceWidget.dispatchEvent(new qx.event.type.DragEvent("dragstart", e, this._dragCache.sourceWidget), true); + + // Update status flag + this._dragCache.hasFiredDragStart = true; + + // Look if handler become active + if (this._dragCache.dragHandlerActive) + { + // Fire first user events + this._fireUserEvents(this._dragCache.currentDropWidget, this._dragCache.sourceWidget, e); + + // Update status flags + this._dragCache.currentDropWidget = this._dragCache.sourceWidget; + + // Activate capture for clientDocument + qx.ui.core.ClientDocument.getInstance().setCapture(true); + } + } + } +} + +/*! +Handle mouse up event. Normally this finalize the drag and drop event. +*/ +qx.Proto._handleMouseUp = function(e) +{ + // Return if dragCache was not filled before + if (!this._dragCache) { + return; + } + + if (this._dragCache.dragHandlerActive) + { + this._endDrag(this.getDropTarget(e), e); + } + else + { + // Clear drag cache + this._dragCache = null; + } +} + + + + + + + +/* +--------------------------------------------------------------------------- + HANDLER FOR KEY EVENTS +--------------------------------------------------------------------------- +*/ + +/*! +This wraps the key events to custom handlers. +*/ +qx.Proto.handleKeyEvent = function(e) +{ + if (!this._dragCache) { + return; + } + + switch (e.getType()) + { + case "keydown": + this._handleKeyDown(e); + return; + + case "keyup": + this._handleKeyUp(e); + return; + } +} + +qx.Proto._handleKeyDown = function(e) +{ + // Stop Drag on Escape + if (e.getKeyIdentifier() == "Escape") + { + this.cancelDrag(e); + } + + // Update cursor and action on press of modifier keys + else if (this.getCurrentAction() != null) + { + // TODO this doesn't work in WebKit because WebKit doesn't fire keyevents for modifier keys + switch(e.getKeyIdentifier()) + { + case "Shift": + case "Control": + case "Alt": + this.setAction(this._evalNewAction(e.isShiftPressed(), e.isCtrlPressed(), e.isAltPressed())); + this._renderCursor(); + + e.preventDefault(); + } + } +} + +qx.Proto._handleKeyUp = function(e) +{ + // TODO this doesn't work in WebKit because WebKit doesn't fire keyevents for modifier keys + var bShiftPressed = e.getKeyIdentifier() == "Shift"; + var bCtrlPressed = e.getKeyIdentifier() == "Control"; + var bAltPressed = e.getKeyIdentifier() == "Alt"; + + if (bShiftPressed || bCtrlPressed || bAltPressed) + { + if (this.getCurrentAction() != null) + { + this.setAction(this._evalNewAction(!bShiftPressed && e.isShiftPressed(), ! bCtrlPressed && e.isCtrlPressed(), !bAltPressed && e.isAltPressed())); + this._renderCursor(); + + e.preventDefault(); + } + } +} + + + + + + + + + +/* +--------------------------------------------------------------------------- + IMPLEMENTATION OF DRAG&DROP SESSION FINALISATION +--------------------------------------------------------------------------- +*/ + +/*! + Cancel current drag and drop session +*/ +qx.Proto.cancelDrag = function(e) { + // Return if dragCache was not filled before + if (!this._dragCache) { + return; + } + + if (this._dragCache.dragHandlerActive) + { + this._endDrag(null, e); + } + else + { + // Clear drag cache + this._dragCache = null; + } +} + +qx.Proto.globalCancelDrag = function() +{ + if (this._dragCache && this._dragCache.dragHandlerActive) { + this._endDragCore(); + } +} + +/*! + This will be called to the end of each drag and drop session +*/ +qx.Proto._endDrag = function(currentDestinationWidget, e) +{ + // Use given destination widget + if (currentDestinationWidget) + { + this._lastDestinationEvent = e; + this.setDestinationWidget(currentDestinationWidget); + } + + // Dispatch dragend event + this.getSourceWidget().dispatchEvent(new qx.event.type.DragEvent("dragend", e, this.getSourceWidget(), currentDestinationWidget), true); + + // Fire dragout event + this._fireUserEvents(this._dragCache && this._dragCache.currentDropWidget, null, e); + + // Call helper + this._endDragCore(); +} + +qx.Proto._endDragCore = function() +{ + // Cleanup feedback widget + if (this._feedbackWidget) { + var doc = qx.ui.core.ClientDocument.getInstance(); + doc.remove(this._feedbackWidget); + + if (this._feedbackAutoDispose) { + this._feedbackWidget.dispose(); + } + + this._feedbackWidget = null; + } + + // Remove cursor + var oldCursor = this.getCursor(); + if (oldCursor) + { + oldCursor._style.display = "none"; + this.forceCursor(null); + } + + this._cursorDeltaX = null; + this._cursorDeltaY = null; + + // Reset drag cache for next drag and drop session + if (this._dragCache) + { + this._dragCache.currentDropWidget = null; + this._dragCache = null; + } + + // Deactivate capture for clientDocument + qx.ui.core.ClientDocument.getInstance().setCapture(false); + + // Cleanup data and actions + this.clearData(); + this.clearActions(); + + // Cleanup widgets + this.setSourceWidget(null); + this.setDestinationWidget(null); +} + + + + + + + + + +/* +--------------------------------------------------------------------------- + IMPLEMENTATION OF CURSOR UPDATES +--------------------------------------------------------------------------- +*/ + +/** + * Sets the position of the cursor feedback (the icon showing whether dropping + * is allowed at the current position and which action a drop will do). + * + * @param deltaX {int} The number of pixels the top-left corner of the + * cursor feedback should be away from the mouse cursor in x direction. + * @param deltaY {int} The number of pixels the top-left corner of the + * cursor feedback should be away from the mouse cursor in y direction. + */ +qx.Proto.setCursorPosition = function(deltaX, deltaY) { + this._cursorDeltaX = deltaX; + this._cursorDeltaY = deltaY; +}; + +/*! + Select and setup the current used cursor +*/ +qx.Proto._renderCursor = function() +{ + var vNewCursor; + var vOldCursor = this.getCursor(); + + switch(this.getCurrentAction()) + { + case this._actionNames.move: + vNewCursor = this._cursors.move; + break; + + case this._actionNames.copy: + vNewCursor = this._cursors.copy; + break; + + case this._actionNames.alias: + vNewCursor = this._cursors.alias; + break; + + default: + vNewCursor = this._cursors.nodrop; + } + + // Hide old cursor + if (vNewCursor != vOldCursor && vOldCursor != null) { + vOldCursor._style.display = "none"; + } + + // Ensure that the cursor is created + if (!vNewCursor._initialLayoutDone) + { + qx.ui.core.ClientDocument.getInstance().add(vNewCursor); + qx.ui.core.Widget.flushGlobalQueues(); + } + + // Apply position with runtime style (fastest qooxdoo method) + vNewCursor._applyRuntimeLeft(this._dragCache.pageX + + ((this._cursorDeltaX != null) ? this._cursorDeltaX : this.getDefaultCursorDeltaX())); + vNewCursor._applyRuntimeTop(this._dragCache.pageY + + ((this._cursorDeltaY != null) ? this._cursorDeltaY : this.getDefaultCursorDeltaY())); + + // Finally show new cursor + if (vNewCursor != vOldCursor) { + vNewCursor._style.display = ""; + } + + // Store new cursor + this.forceCursor(vNewCursor); +} + + + + + + + + +/* +--------------------------------------------------------------------------- + IMPLEMENTATION OF DROP TARGET VALIDATION +--------------------------------------------------------------------------- +*/ + +qx.Proto.supportsDrop = function(vWidget) +{ + var vTypes = vWidget.getDropDataTypes(); + + if (!vTypes) { + return false; + } + + for (var i=0; i<vTypes.length; i++) + { + if (vTypes[i] in this._data) { + return true; + } + } + + return false; +} + +/*! +#param e[qx.event.type.MouseEvent]: Current MouseEvent for dragdrop action +*/ +if (qx.core.Client.getInstance().isGecko()) +{ + qx.Proto.getDropTarget = function(e) + { + var vCurrent = e.getTarget(); + + // work around gecko bug (all other browsers are correct) + // clicking on a free space and drag prohibit the get of + // a valid event target. The target is always the element + // which was the one with the mousedown event before. + if (vCurrent == this._dragCache.sourceWidget) + { + // vCurrent = qx.event.handler.EventHandler.getTargetObject(qx.html.ElementFromPoint.getElementFromPoint(e.getPageX(), e.getPageY())); + + // this is around 8-12 times faster as the above method + vCurrent = this._dragCache.sourceTopLevel.getWidgetFromPoint(e.getPageX(), e.getPageY()); + } + else + { + vCurrent = qx.event.handler.EventHandler.getTargetObject(null, vCurrent); + } + + while (vCurrent != null && vCurrent != this._dragCache.sourceWidget) + { + if (!vCurrent.supportsDrop(this._dragCache)) { + return null; + } + + if (this.supportsDrop(vCurrent)) { + return vCurrent; + } + + vCurrent = vCurrent.getParent(); + } + + return null; + } +} +else +{ + qx.Proto.getDropTarget = function(e) + { + var vCurrent = e.getTarget(); + + while (vCurrent != null) + { + if (!vCurrent.supportsDrop(this._dragCache)) { + return null; + } + + if (this.supportsDrop(vCurrent)) { + return vCurrent; + } + + vCurrent = vCurrent.getParent(); + } + + return null; + } +} + + + + + + + + + +/* +--------------------------------------------------------------------------- + ACTION HANDLING +--------------------------------------------------------------------------- +*/ + +qx.Proto.addAction = function(vAction, vForce) +{ + this._actions[vAction] = true; + + // Defaults to first added action + if (vForce || this.getCurrentAction() == null) { + this.setCurrentAction(vAction); + } +} + +qx.Proto.clearActions = function() +{ + this._actions = {}; + this.setCurrentAction(null); +} + +qx.Proto.removeAction = function(vAction) +{ + delete this._actions[vAction]; + + // Reset current action on remove + if (this.getCurrentAction() == vAction) { + this.setCurrentAction(null); + } +} + +qx.Proto.setAction = function(vAction) +{ + if (vAction != null && !(vAction in this._actions)) { + this.addAction(vAction, true); + } + else + { + this.setCurrentAction(vAction); + } +} + +qx.Proto._evalNewAction = function(vKeyShift, vKeyCtrl, vKeyAlt) +{ + if (vKeyShift && vKeyCtrl && this._actionNames.alias in this._actions) + { + return this._actionNames.alias; + } + else if (vKeyShift && vKeyAlt && this._actionNames.copy in this._actions) + { + return this._actionNames.copy; + } + else if (vKeyShift && this._actionNames.move in this._actions) + { + return this._actionNames.move; + } + else if (vKeyAlt && this._actionNames.alias in this._actions) + { + return this._actionNames.alias; + } + else if (vKeyCtrl && this._actionNames.copy in this._actions) + { + return this._actionNames.copy; + } + else + { + // Return the first action found + for (var vAction in this._actions) { + return vAction; + } + } + + return null; +} + + + + + + +/* +--------------------------------------------------------------------------- + USER FEEDBACK SUPPORT +--------------------------------------------------------------------------- +*/ + +/** + * Sets the widget to show as feedback for the user. This widget should + * represent the object(s) the user is dragging. + * + * @param widget {qx.ui.core.Widget} the feedback widget. + * @param deltaX {int ? 10} the number of pixels the top-left corner of the widget + * should be away from the mouse cursor in x direction. + * @param deltaY {int ? 10} the number of pixels the top-left corner of the widget + * should be away from the mouse cursor in y direction. + * @param autoDisposeWidget {boolean} whether the widget should be disposed when + * dragging is finished or cancelled. + */ +qx.Proto.setFeedbackWidget = function(widget, deltaX, deltaY, autoDisposeWidget) { + this._feedbackWidget = widget; + this._feedbackDeltaX = (deltaX != null) ? deltaX : 10; + this._feedbackDeltaY = (deltaY != null) ? deltaY : 10; + this._feedbackAutoDispose = autoDisposeWidget ? true : false; +}; + +/** + * Renders the user feedback widget at the correct location. + */ +qx.Proto._renderFeedbackWidget = function() { + if (this._feedbackWidget) { + this._feedbackWidget.setVisibility(true); + + // Apply position with runtime style (fastest qooxdoo method) + this._feedbackWidget._applyRuntimeLeft(this._dragCache.pageX + this._feedbackDeltaX); + this._feedbackWidget._applyRuntimeTop(this._dragCache.pageY + this._feedbackDeltaY); + } +}; + + + + + + +/* +--------------------------------------------------------------------------- + DISPOSER +--------------------------------------------------------------------------- +*/ + +qx.Proto.dispose = function() +{ + if (this.getDisposed()) { + return; + } + + // Reset drag cache for next drag and drop session + if (this._dragCache) + { + this._dragCache.currentDropWidget = null; + this._dragCache = null; + } + + // Cleanup data and actions + this._data = null; + this._actions = null; + this._actionNames = null; + + this._lastDestinationEvent = null; + + if (this._cursors) + { + if (this._cursors.move) + { + this._cursors.move.dispose(); + delete this._cursors.move; + } + + if (this._cursors.copy) + { + this._cursors.copy.dispose(); + delete this._cursors.copy; + } + + if (this._cursors.alias) + { + this._cursors.alias.dispose(); + delete this._cursors.alias; + } + + if (this._cursors.nodrop) + { + this._cursors.nodrop.dispose(); + delete this._cursors.nodrop; + } + + this._cursors = null; + } + + return qx.manager.object.ObjectManager.prototype.dispose.call(this); +} + + + + + + + + +/* +--------------------------------------------------------------------------- + DEFER SINGLETON INSTANCE +--------------------------------------------------------------------------- +*/ + +/** + * Singleton Instance Getter + */ +qx.Class.getInstance = qx.lang.Function.returnInstance; diff --git a/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/event/handler/EventHandler.js b/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/event/handler/EventHandler.js new file mode 100644 index 0000000000..858f8d6096 --- /dev/null +++ b/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/event/handler/EventHandler.js @@ -0,0 +1,1182 @@ +/* ************************************************************************ + + qooxdoo - the new era of web development + + http://qooxdoo.org + + Copyright: + 2004-2007 1&1 Internet AG, Germany, http://www.1and1.org + + License: + LGPL: http://www.gnu.org/licenses/lgpl.html + EPL: http://www.eclipse.org/org/documents/epl-v10.php + See the LICENSE file in the project's top-level directory for details. + + Authors: + * Sebastian Werner (wpbasti) + * Andreas Ecker (ecker) + +************************************************************************ */ + +/* ************************************************************************ + +#module(ui_core) +#require(qx.event.type.KeyEvent) +#require(qx.event.handler.KeyEventHandler) +#optional(qx.event.handler.DragAndDropHandler) +#optional(qx.manager.object.MenuManager) +#optional(qx.event.handler.FocusHandler) +#optional(qx.manager.object.PopupManager) +#optional(qx.manager.object.ToolTipManager) + +************************************************************************ */ + +/** + * This manager registers and manage all incoming key and mouse events. + * + * @event error {qx.event.type.DataEvent} Fired when an exception was thrown + * when dispatching the event to the listeners. The event's property + * "data" holds the exception. + */ +qx.OO.defineClass("qx.event.handler.EventHandler", qx.core.Target, +function() +{ + qx.core.Target.call(this); + + // Object Wrapper to Events (Needed for DOM-Events) + var o = this; + + // User Events + this.__onmouseevent = function(e) { return o._onmouseevent(e); }; + this.__ondragevent = function(e) { return o._ondragevent(e); }; + this.__onselectevent = function(e) { return o._onselectevent(e); }; + + // Window Events + this.__onwindowblur = function(e) { return o._onwindowblur(e); }; + this.__onwindowfocus = function(e) { return o._onwindowfocus(e); }; + this.__onwindowresize = function(e) { return o._onwindowresize(e); }; + + // Init Command Interface + this._commands = {}; +}); + + + + + + +qx.OO.addProperty({ name : "allowClientContextMenu", type : "boolean", defaultValue : false }); +qx.OO.addProperty({ name : "allowClientSelectAll", type : "boolean", defaultValue : false }); + +qx.OO.addProperty({ name : "captureWidget", type : "object", instance : "qx.ui.core.Widget", allowNull : true }); +qx.OO.addProperty({ name : "focusRoot", type : "object", instance : "qx.ui.core.Parent", allowNull : true }); + + + + + + +qx.Class.mouseEventTypes = [ "mouseover", "mousemove", "mouseout", "mousedown", "mouseup", "click", "dblclick", "contextmenu", qx.core.Client.getInstance().isMshtml() ? "mousewheel" : "DOMMouseScroll" ]; +qx.Class.keyEventTypes = [ "keydown", "keypress", "keyup" ]; + +if (qx.core.Client.getInstance().isGecko()) +{ + qx.Class.dragEventTypes = [ "dragdrop", "dragover", "dragenter", "dragexit", "draggesture" ]; +} +else if (qx.core.Client.getInstance().isMshtml()) +{ + qx.Class.dragEventTypes = [ "dragend", "dragover", "dragstart", "drag", "dragenter", "dragleave" ]; +} +else +{ + qx.Class.dragEventTypes = [ "dragstart", "dragdrop", "dragover", "drag", "dragleave", "dragenter", "dragexit", "draggesture" ]; +} + + + + + + + + + + +/* +--------------------------------------------------------------------------- + STATE FLAGS +--------------------------------------------------------------------------- +*/ + +qx.Proto._lastMouseEventType = null; +qx.Proto._lastMouseDown = false; +qx.Proto._lastMouseEventDate = 0; + + + + + + +/* +--------------------------------------------------------------------------- + MODIFIERS +--------------------------------------------------------------------------- +*/ + +qx.Proto._modifyCaptureWidget = function(propValue, propOldValue, propData) +{ + if (propOldValue) { + propOldValue.setCapture(false); + } + + if (propValue) { + propValue.setCapture(true); + } + + return true; +} + +qx.Proto._modifyFocusRoot = function(propValue, propOldValue, propData) +{ + // this.debug("FocusRoot: " + propValue + "(from:" + propOldValue + ")"); + + if (propOldValue) { + propOldValue.setFocusedChild(null); + } + + if (propValue) + { + if (propValue.getFocusedChild() == null) { + propValue.setFocusedChild(propValue); + } + } + + return true; +} + + + + + + +/* +--------------------------------------------------------------------------- + COMMAND INTERFACE +--------------------------------------------------------------------------- +*/ + +qx.Proto.addCommand = function(vCommand) { + this._commands[vCommand.toHashCode()] = vCommand; +} + +qx.Proto.removeCommand = function(vCommand) { + delete this._commands[vCommand.toHashCode()]; +} + +qx.Proto._checkKeyEventMatch = function(e) +{ + var vCommand; + + for (var vHash in this._commands) + { + vCommand = this._commands[vHash]; + + if (vCommand.getEnabled() && vCommand._matchesKeyEvent(e)) + { + // allow the user to stop the event + // through the execute event. + if (!vCommand.execute(e.getTarget())) { + e.preventDefault(); + } + + break; + } + } +} + + + + + + +/* +--------------------------------------------------------------------------- + EVENT-MAPPING +--------------------------------------------------------------------------- +*/ + +qx.Proto.attachEvents = function() +{ + // Register dom events + this.attachEventTypes(qx.event.handler.EventHandler.mouseEventTypes, this.__onmouseevent); + this.attachEventTypes(qx.event.handler.EventHandler.dragEventTypes, this.__ondragevent); + + // Unregister separate handler events + qx.event.handler.KeyEventHandler.getInstance()._attachEvents(); + + // Register window events + qx.html.EventRegistration.addEventListener(window, "blur", this.__onwindowblur); + qx.html.EventRegistration.addEventListener(window, "focus", this.__onwindowfocus); + qx.html.EventRegistration.addEventListener(window, "resize", this.__onwindowresize); + + // Register selection events + document.body.onselect = document.onselectstart = document.onselectionchange = this.__onselectevent; +} + +qx.Proto.detachEvents = function() +{ + // Unregister dom events + this.detachEventTypes(qx.event.handler.EventHandler.mouseEventTypes, this.__onmouseevent); + this.detachEventTypes(qx.event.handler.EventHandler.dragEventTypes, this.__ondragevent); + + // Unregister separate handler events + qx.event.handler.KeyEventHandler.getInstance()._detachEvents(); + + // Unregister window events + qx.html.EventRegistration.removeEventListener(window, "blur", this.__onwindowblur); + qx.html.EventRegistration.removeEventListener(window, "focus", this.__onwindowfocus); + qx.html.EventRegistration.removeEventListener(window, "resize", this.__onwindowresize); + + // Unregister selection events + document.body.onselect = document.onselectstart = document.onselectionchange = null; +} + + + + + + + +/* +--------------------------------------------------------------------------- + EVENT-MAPPING HELPER +--------------------------------------------------------------------------- +*/ + +qx.Proto.attachEventTypes = function(vEventTypes, vFunctionPointer) +{ + try + { + // Gecko is a bit buggy to handle key events on document if not previously focused + // I think they will fix this sometimes, and we should add a version check here. + // Internet Explorer has problems to use 'window', so there we use the 'body' element + // as previously. + var el = qx.core.Client.getInstance().isGecko() ? window : document.body; + + for (var i=0, l=vEventTypes.length; i<l; i++) { + qx.html.EventRegistration.addEventListener(el, vEventTypes[i], vFunctionPointer); + } + } + catch(ex) + { + throw new Error("qx.event.handler.EventHandler: Failed to attach window event types: " + vEventTypes + ": " + ex); + } +} + +qx.Proto.detachEventTypes = function(vEventTypes, vFunctionPointer) +{ + try + { + var el = qx.core.Client.getInstance().isGecko() ? window : document.body; + + for (var i=0, l=vEventTypes.length; i<l; i++) { + qx.html.EventRegistration.removeEventListener(el, vEventTypes[i], vFunctionPointer); + } + } + catch(ex) + { + throw new Error("qx.event.handler.EventHandler: Failed to detach window event types: " + vEventTypes + ": " + ex); + } +} + + + + + + +/* +--------------------------------------------------------------------------- + HELPER METHODS +--------------------------------------------------------------------------- +*/ + +// BUG: http://xscroll.mozdev.org/ +// If your Mozilla was built with an option `--enable-default-toolkit=gtk2', +// it can not return the correct event target for DOMMouseScroll. + +qx.Class.getOriginalTargetObject = function(vNode) +{ + // Events on the HTML element, when using absolute locations which + // are outside the HTML element. Opera does not seem to fire events + // on the HTML element. + if (vNode == document.documentElement) { + vNode = document.body; + } + + // Walk up the tree and search for an qx.ui.core.Widget + while(vNode != null && vNode.qx_Widget == null) + { + try { + vNode = vNode.parentNode; + } + catch(vDomEvent) + { + vNode = null; + } + } + + return vNode ? vNode.qx_Widget : null; +} + +if (qx.core.Client.getInstance().isWebkit()) +{ + /** + * extract the target node from a DOM event + * http://www.quirksmode.org/js/events_properties.html + * + * @param vDomEvent {Event} + * @return {Element} the target node + */ + qx.Class.getDomTarget = function(vDomEvent) + { + var vNode = vDomEvent.target || vDomEvent.srcElement; + + // Safari takes text nodes as targets for events + if (vNode && (vNode.nodeType == qx.dom.Node.TEXT)) { + vNode = vNode.parentNode; + } + + return vNode; + }; +} +else if (qx.core.Client.getInstance().isMshtml()) +{ + /** + * extract the target node from a DOM event + * http://www.quirksmode.org/js/events_properties.html + * + * @param vDomEvent {Event} + * @return {Element} the target node + */ + qx.Class.getDomTarget = function(vDomEvent) { + return vDomEvent.target || vDomEvent.srcElement; + }; +} +else +{ + /** + * extract the target node from a DOM event + * http://www.quirksmode.org/js/events_properties.html + * + * @param vDomEvent {Event} + * @return {Element} the target node + */ + qx.Class.getDomTarget = function(vDomEvent) { + return vDomEvent.target; + }; +} + + +qx.Class.getOriginalTargetObjectFromEvent = function(vDomEvent, vWindow) +{ + var vNode = qx.event.handler.EventHandler.getDomTarget(vDomEvent); + + // Especially to fix key events. + // 'vWindow' is the window reference then + if (vWindow) + { + var vDocument = vWindow.document; + + if (vNode == vWindow || vNode == vDocument || vNode == vDocument.documentElement || vNode == vDocument.body) { + return vDocument.body.qx_Widget; + } + } + + return qx.event.handler.EventHandler.getOriginalTargetObject(vNode); +} + +qx.Class.getRelatedOriginalTargetObjectFromEvent = function(vDomEvent) { + return qx.event.handler.EventHandler.getOriginalTargetObject(vDomEvent.relatedTarget || (vDomEvent.type == "mouseover" ? vDomEvent.fromElement : vDomEvent.toElement)); +} + + + + + + + +qx.Class.getTargetObject = function(vNode, vObject, allowDisabled) +{ + if (!vObject) + { + var vObject = qx.event.handler.EventHandler.getOriginalTargetObject(vNode); + + if (!vObject) { + return null; + } + } + + // Search parent tree + while(vObject) + { + // Break if current object is disabled - + // event should be ignored then. + if (!allowDisabled && !vObject.getEnabled()) { + return null; + } + + // If object is anonymous, search for + // first parent which is not anonymous + // and not disabled + if (!vObject.getAnonymous()) { + break; + } + + vObject = vObject.getParent(); + } + + return vObject; +}; + + +qx.Class.getTargetObjectFromEvent = function(vDomEvent) { + return qx.event.handler.EventHandler.getTargetObject(qx.event.handler.EventHandler.getDomTarget(vDomEvent)); +}; + + +qx.Class.getRelatedTargetObjectFromEvent = function(vDomEvent) { + var target = vDomEvent.relatedTarget; + if (!target) { + if (vDomEvent.type == "mouseover") { + target = vDomEvent.fromElement + } else { + target = vDomEvent.toElement + } + } + return qx.event.handler.EventHandler.getTargetObject(target); +}; + + +/** + * stops further propagation of the event + * + * @param vDomEvent {Element} DOM event object + */ +qx.Class.stopDomEvent = function(vDomEvent) {}; +if (qx.core.Client.getInstance().isMshtml()) +{ + qx.Class.stopDomEvent = function(vDomEvent) { + vDomEvent.returnValue = false; + } +} +else +{ + qx.Class.stopDomEvent = function(vDomEvent) + { + vDomEvent.preventDefault(); + vDomEvent.returnValue = false; + } +}; + + + + + + + +/* +--------------------------------------------------------------------------- + KEY EVENTS +--------------------------------------------------------------------------- +*/ + +qx.Proto._onkeyevent_post = function(vDomEvent, vType, vKeyCode, vCharCode, vKeyIdentifier) +{ + var vDomTarget = qx.event.handler.EventHandler.getDomTarget(vDomEvent); + + + // Find current active qooxdoo object + var vFocusRoot = this.getFocusRoot(); + var vTarget = this.getCaptureWidget() || (vFocusRoot == null ? null : vFocusRoot.getActiveChild()); + + if (vTarget == null || !vTarget.getEnabled()) { + return false; + } + + var vDomEventTarget = vTarget.getElement(); + + + + + // Hide Menus + switch(vKeyIdentifier) + { + case "Escape": + case "Tab": + if (qx.OO.isAvailable("qx.manager.object.MenuManager")) { + qx.manager.object.MenuManager.getInstance().update(vTarget, vType); + } + + break; + } + + + + + // TODO: Move this to KeyEvent? + + // Prohibit CTRL+A + if (!this.getAllowClientSelectAll()) + { + if (vDomEvent.ctrlKey && vKeyIdentifier == "A") + { + switch(vDomTarget.tagName.toLowerCase()) + { + case "input": + case "textarea": + case "iframe": + break; + + default: + qx.event.handler.EventHandler.stopDomEvent(vDomEvent); + } + } + } + + + + // Create Event Object + var vKeyEventObject = new qx.event.type.KeyEvent(vType, vDomEvent, vDomTarget, vTarget, null, vKeyCode, vCharCode, vKeyIdentifier); + + // Check for commands + if (vDomEvent.type == "keydown") { + this._checkKeyEventMatch(vKeyEventObject); + } + + try { + // Starting Objects Internal Event Dispatcher + // This handles the real event action + vTarget.dispatchEvent(vKeyEventObject); + + // Send event to qx.event.handler.DragAndDropHandler + if (qx.OO.isAvailable("qx.event.handler.DragAndDropHandler")) { + qx.event.handler.DragAndDropHandler.getInstance().handleKeyEvent(vKeyEventObject); + } + } catch (ex) { + this.error("Failed to dispatch key event", ex); + this.createDispatchDataEvent("error", ex); + } + + // Cleanup Event Object + vKeyEventObject.dispose(); + + // Flush Queues + qx.ui.core.Widget.flushGlobalQueues(); +} + + + + + + +/* +--------------------------------------------------------------------------- + MOUSE EVENTS +--------------------------------------------------------------------------- +*/ + +/*! + This one handle all mouse events + + When a user double clicks on a qx.ui.core.Widget the + order of the mouse events is the following: + + 1. mousedown + 2. mouseup + 3. click + 4. mousedown + 5. mouseup + 6. click + 7. dblclick +*/ + +if(qx.core.Client.getInstance().isMshtml()) +{ + qx.Proto._onmouseevent = function(vDomEvent) + { + qx.core.Init.getInstance().getComponent().preload(); + + if(!vDomEvent) { + vDomEvent = window.event; + } + + var vDomTarget = qx.event.handler.EventHandler.getDomTarget(vDomEvent); + var vType = vDomEvent.type; + + if(vType == "mousemove") + { + if (this._mouseIsDown && vDomEvent.button == 0) + { + this._onmouseevent_post(vDomEvent, "mouseup"); + this._mouseIsDown = false; + } + } + else + { + if(vType == "mousedown") + { + this._mouseIsDown = true; + } + else if(vType == "mouseup") + { + this._mouseIsDown = false; + } + + // Fix MSHTML Mouseup, should be after a normal click or contextmenu event, like Mozilla does this + if(vType == "mouseup" && !this._lastMouseDown && ((new Date).valueOf() - this._lastMouseEventDate) < 250) + { + this._onmouseevent_post(vDomEvent, "mousedown"); + } + // Fix MSHTML Doubleclick, should be after a normal click event, like Mozilla does this + else if(vType == "dblclick" && this._lastMouseEventType == "mouseup" && ((new Date).valueOf() - this._lastMouseEventDate) < 250) + { + this._onmouseevent_post(vDomEvent, "click"); + } + + switch(vType) + { + case "mousedown": + case "mouseup": + case "click": + case "dblclick": + case "contextmenu": + this._lastMouseEventType = vType; + this._lastMouseEventDate = (new Date).valueOf(); + this._lastMouseDown = vType == "mousedown"; + } + } + + this._onmouseevent_post(vDomEvent, vType, vDomTarget); + } +} +else +{ + qx.Proto._onmouseevent = function(vDomEvent) + { + qx.core.Init.getInstance().getComponent().preload(); + + var vDomTarget = qx.event.handler.EventHandler.getDomTarget(vDomEvent); + var vType = vDomEvent.type; + + switch(vType) + { + case "DOMMouseScroll": + // normalize mousewheel event + vType = "mousewheel"; + break; + + case "click": + case "dblclick": + // ignore click or dblclick events with other then the left mouse button + if (vDomEvent.which !== 1) { + return; + } + } + + this._onmouseevent_post(vDomEvent, vType, vDomTarget); + } +} + +/*! +Fixes browser quirks with 'click' detection + +Firefox 1.5.0.6: The DOM-targets are different. The click event only fires, if the target of the + mousedown is the same than with the mouseup. If the content moved away, the click isn't fired. + +Internet Explorer 6.0: The DOM-targets are identical and the click fires fine. + +Opera 9.01: The DOM-targets are different, but the click fires fine. Fires click successfull, + even if the content under the cursor was moved away. +*/ +if (qx.core.Client.getInstance().isGecko()) +{ + qx.Proto._onmouseevent_click_fix = function(vDomTarget, vType, vDispatchTarget) + { + var vReturn = false; + + switch(vType) + { + case "mousedown": + this._lastMouseDownDomTarget = vDomTarget; + this._lastMouseDownDispatchTarget = vDispatchTarget; + break; + + case "mouseup": + // Add additional click event if the dispatch target is the same, but the dom target is different + if (this._lastMouseDownDispatchTarget === vDispatchTarget && vDomTarget !== this._lastMouseDownDomTarget) + { + vReturn = true; + } + else + { + this._lastMouseDownDomTarget = null; + this._lastMouseDownDispatchTarget = null; + } + } + + return vReturn; + }; +} +else +{ + qx.Proto._onmouseevent_click_fix = function(vDomTarget, vDispatchTarget) { + return false; + } +}; + +/*! + This is the crossbrowser post handler for all mouse events. +*/ +qx.Proto._onmouseevent_post = function(vDomEvent, vType, vDomTarget) +{ + try + { + var vEventObject, vCaptureTarget, vDispatchTarget, vTarget, vOriginalTarget, vRelatedTarget, vFixClick, vTargetIsEnabled; + + + + // Check for capturing, if enabled the target is the captured widget. + vCaptureTarget = this.getCaptureWidget(); + + // Event Target Object + vOriginalTarget = qx.event.handler.EventHandler.getOriginalTargetObject(vDomTarget); + + // If capturing isn't active search for a valid target object + if (!vCaptureTarget) + { + // Get Target Object + vDispatchTarget = vTarget = qx.event.handler.EventHandler.getTargetObject(null, vOriginalTarget, true); + } + else + { + vDispatchTarget = vCaptureTarget; + vTarget = qx.event.handler.EventHandler.getTargetObject(null, vOriginalTarget, true); + } + + + + // If there is no target, we have nothing to do + if (!vTarget) { + return; + } + vTargetIsEnabled = vTarget.getEnabled(); + + // Fix click event + vFixClick = this._onmouseevent_click_fix(vDomTarget, vType, vDispatchTarget); + + + // Prevent the browser's native context menu + if (vType == "contextmenu" && !this.getAllowClientContextMenu()) { + qx.event.handler.EventHandler.stopDomEvent(vDomEvent); + } + + + // Update focus + if (vTargetIsEnabled && vType == "mousedown") { + qx.event.handler.FocusHandler.mouseFocus = true; + + var vRoot = vTarget.getFocusRoot(); + + if (vRoot) + { + this.setFocusRoot(vRoot); + + vRoot.setActiveChild(vTarget); + + // Active focus on element (if possible, else search up the parent tree) + var vFocusTarget = vTarget; + while (!vFocusTarget.isFocusable() && vFocusTarget != vRoot) { + vFocusTarget = vFocusTarget.getParent(); + } + + vRoot.setFocusedChild(vFocusTarget); + } + } + + + + + var vDomEventTarget = vTarget.getElement(); + + + + + // Find related target object + switch(vType) + { + case "mouseover": + case "mouseout": + vRelatedTarget = qx.event.handler.EventHandler.getRelatedTargetObjectFromEvent(vDomEvent); + + // Ignore events where the related target and + // the real target are equal - from our sight + if (vRelatedTarget == vTarget) { + return; + } + } + + + + try + { + + // Create Mouse Event Object + vEventObject = new qx.event.type.MouseEvent(vType, vDomEvent, vDomTarget, vTarget, vOriginalTarget, vRelatedTarget); + } + catch(ex) + { + return this.error("Failed to create mouse event", ex); + } + + + // Store last Event in MouseEvent Constructor + // Needed for Tooltips, ... + qx.event.type.MouseEvent._storeEventState(vEventObject); + + + if (vTargetIsEnabled) { + // Dispatch Event through target (eventtarget-)object + var vEventWasProcessed = false; + try { + vEventWasProcessed = vDispatchTarget ? vDispatchTarget.dispatchEvent(vEventObject) : true; + + // Handle Special Post Events + this._onmouseevent_special_post(vType, vTarget, vOriginalTarget, vDispatchTarget, vEventWasProcessed, vEventObject, vDomEvent); + } catch(ex) { + this.error("Failed to dispatch mouse event", ex); + this.createDispatchDataEvent("error", ex); + } + } else { + // target is disabled -> Pass the event only to the ToolTipManager + if (vType == "mouseover") { + if (qx.OO.isAvailable("qx.manager.object.ToolTipManager")) { + qx.manager.object.ToolTipManager.getInstance().handleMouseOver(vEventObject); + } + } + } + + + + // Dispose Event Object + vEventObject.dispose(); + vEventObject = null; + + + + + // Flush Queues + qx.ui.core.Widget.flushGlobalQueues(); + + + // Fix Click (Gecko Bug, see above) + if (vFixClick) + { + this._onmouseevent_post(vDomEvent, "click", this._lastMouseDownDomTarget); + + this._lastMouseDownDomTarget = null; + this._lastMouseDownDispatchTarget = null; + } + } + catch(ex) + { + return this.error("Failed to handle mouse event", ex); + } +} + + +qx.Proto._onmouseevent_special_post = function(vType, vTarget, vOriginalTarget, vDispatchTarget, vEventWasProcessed, vEventObject, vDomEvent) { + switch(vType) + { + case "mousedown": + if (qx.OO.isAvailable("qx.manager.object.PopupManager")) { + qx.manager.object.PopupManager.getInstance().update(vTarget); + } + + if (qx.OO.isAvailable("qx.manager.object.MenuManager")) { + qx.manager.object.MenuManager.getInstance().update(vTarget, vType); + } + + if (qx.OO.isAvailable("qx.manager.object.IframeManager")) { + qx.manager.object.IframeManager.getInstance().handleMouseDown(vEventObject); + } + + break; + + case "mouseup": + + // Mouseup event should always hide, independed of target, so don't send a target + if (qx.OO.isAvailable("qx.manager.object.MenuManager")) { + qx.manager.object.MenuManager.getInstance().update(vTarget, vType); + } + + if (qx.OO.isAvailable("qx.manager.object.IframeManager")) { + qx.manager.object.IframeManager.getInstance().handleMouseUp(vEventObject); + } + + break; + + case "mouseover": + if (qx.OO.isAvailable("qx.manager.object.ToolTipManager")) { + qx.manager.object.ToolTipManager.getInstance().handleMouseOver(vEventObject); + } + + break; + + case "mouseout": + if (qx.OO.isAvailable("qx.manager.object.ToolTipManager")) { + qx.manager.object.ToolTipManager.getInstance().handleMouseOut(vEventObject); + } + + break; + + case "mousewheel": + // priority for the real target not the (eventually captured) dispatch target + vEventWasProcessed ? this._onmousewheel(vOriginalTarget || vDispatchTarget, vEventObject) : qx.event.handler.EventHandler.stopDomEvent(vDomEvent); + + break; + } + + + + this._ignoreWindowBlur = vType === "mousedown"; + + + + + // Send Event Object to Drag&Drop Manager + if (qx.OO.isAvailable("qx.event.handler.DragAndDropHandler") && vTarget) { + qx.event.handler.DragAndDropHandler.getInstance().handleMouseEvent(vEventObject); + } +} + + +if (qx.core.Client.getInstance().isGecko()) +{ + qx.Proto._onmousewheel = function(vTarget, vEvent) + { + if(vTarget == null) { + return; + } + + // ingore if overflow is configured as hidden + // in this case send the event to the parent instead + if(vTarget.getOverflowY() == "hidden") { + return this._onmousewheel(vTarget.getParent(), vEvent); + } + + var vScrollTop = vTarget.getScrollTop(); + var vDelta = 20 * vEvent.getWheelDelta(); + + // if already at the top edge and the user scrolls up + // then send the event to the parent instead + if(vScrollTop == 0 && vDelta > 0) { + return this._onmousewheel(vTarget.getParent(), vEvent); + } + + var vScrollHeight = vTarget.getScrollHeight(); + var vClientHeight = vTarget.getClientHeight(); + + // if already at the bottom edge and the user scrolls down + // then send the event to the parent instead + if(vScrollTop + vClientHeight >= vScrollHeight && vDelta < 0) { + return this._onmousewheel(vTarget.getParent(), vEvent); + } + + // apply new scroll position + vTarget.setScrollTop(vScrollTop - vDelta); + + // stop default handling, that works sometimes, too + vEvent.preventDefault(); + } +} +else +{ + qx.Proto._onmousewheel = function() {}; +} + + + + + + + +/* +--------------------------------------------------------------------------- + DRAG EVENTS + + Currently only to stop non needed events +--------------------------------------------------------------------------- +*/ + +qx.Proto._ondragevent = function(vEvent) +{ + if (!vEvent) { + vEvent = window.event; + } + + qx.event.handler.EventHandler.stopDomEvent(vEvent); +} + + + + + + + +/* +--------------------------------------------------------------------------- + SELECT EVENTS +--------------------------------------------------------------------------- +*/ + +qx.Proto._onselectevent = function(e) +{ + if(!e) { + e = window.event; + } + + var vTarget = qx.event.handler.EventHandler.getOriginalTargetObjectFromEvent(e); + + if(vTarget && !vTarget.getSelectable()) { + qx.event.handler.EventHandler.stopDomEvent(e); + } +} + + + + + + +/* +--------------------------------------------------------------------------- + WINDOW EVENTS +--------------------------------------------------------------------------- +*/ + +qx.Proto._focused = false; + +qx.Proto._onwindowblur = function(e) +{ + // this.debug("Try Window blur..."); + + if (!this._focused || this._ignoreWindowBlur) { + return; + } + + this._focused = false; + + // this.debug("Window blur..."); + + // Disable capturing + this.setCaptureWidget(null); + + // Hide Popups, Tooltips, ... + if (qx.OO.isAvailable("qx.manager.object.PopupManager")) { + qx.manager.object.PopupManager.getInstance().update(); + } + + // Hide Menus + if (qx.OO.isAvailable("qx.manager.object.MenuManager")) { + qx.manager.object.MenuManager.getInstance().update(); + } + + // Cancel Drag Operations + if (qx.OO.isAvailable("qx.event.handler.DragAndDropHandler")) { + qx.event.handler.DragAndDropHandler.getInstance().globalCancelDrag(); + } + + // Send blur event to client document + qx.ui.core.ClientDocument.getInstance().createDispatchEvent("windowblur"); +} + +qx.Proto._onwindowfocus = function(e) +{ + // this.debug("Try Window focus..."); + + if (this._focused) { + return; + } + + this._focused = true; + + // this.debug("Window focus..."); + + // Send focus event to client document + qx.ui.core.ClientDocument.getInstance().createDispatchEvent("windowfocus"); +} + +qx.Proto._onwindowresize = function(e) +{ + // Send resize event to client document + qx.ui.core.ClientDocument.getInstance().createDispatchEvent("windowresize"); +} + + + + + +/* +--------------------------------------------------------------------------- + DISPOSE +--------------------------------------------------------------------------- +*/ + +qx.Proto.dispose = function() +{ + if (this.getDisposed()) { + return; + } + + // Detach mouse events + this.detachEvents(); + + // Reset functions + this.__onmouseevent = this.__ondragevent = this.__onselectevent = null; + this.__onwindowblur = this.__onwindowfocus = this.__onwindowresize = null; + + // Cleanup + this._lastMouseEventType = null; + this._lastMouseDown = null; + this._lastMouseEventDate = null; + + this._lastMouseDownDomTarget = null; + this._lastMouseDownDispatchTarget = null; + + if (this._commands) + { + for (var vHash in this._commands) + { + this._commands[vHash].dispose(); + delete this._commands[vHash]; + } + + this._commands = null; + } + + qx.core.Target.prototype.dispose.call(this); +} + + + + + + +/* +--------------------------------------------------------------------------- + DEFER SINGLETON INSTANCE +--------------------------------------------------------------------------- +*/ + +/** + * Singleton Instance Getter + */ +qx.Class.getInstance = qx.lang.Function.returnInstance; diff --git a/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/event/handler/FocusHandler.js b/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/event/handler/FocusHandler.js new file mode 100644 index 0000000000..d21639e3dd --- /dev/null +++ b/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/event/handler/FocusHandler.js @@ -0,0 +1,344 @@ +/* ************************************************************************ + + qooxdoo - the new era of web development + + http://qooxdoo.org + + Copyright: + 2004-2007 1&1 Internet AG, Germany, http://www.1and1.org + + License: + LGPL: http://www.gnu.org/licenses/lgpl.html + EPL: http://www.eclipse.org/org/documents/epl-v10.php + See the LICENSE file in the project's top-level directory for details. + + Authors: + * Sebastian Werner (wpbasti) + * Andreas Ecker (ecker) + +************************************************************************ */ + +/* ************************************************************************ + +#module(ui_core) +#optional(qx.ui.core.Parent) +#optional(qx.ui.basic.Terminator) + +************************************************************************ */ + +/*! + This object gets an instance in each focus root and manage the focus handling for it. +*/ +qx.OO.defineClass("qx.event.handler.FocusHandler", qx.core.Target, +function(vWidget) +{ + qx.core.Target.call(this); + + if (vWidget != null) { + this._attachedWidget = vWidget; + } +}); + +qx.event.handler.FocusHandler.mouseFocus = false; + + + + +/* +--------------------------------------------------------------------------- + UTILITIES +--------------------------------------------------------------------------- +*/ + +qx.Proto.getAttachedWidget = function() { + return this._attachedWidget; +} + + + + + + +/* +--------------------------------------------------------------------------- + TAB-EVENT HANDLING +--------------------------------------------------------------------------- +*/ + +// Check for TAB pressed +// * use keydown on mshtml +// * use keypress on vAll other (correct) browsers +// = same behaviour +qx.event.handler.FocusHandler.tabEventType = qx.core.Client.getInstance().isMshtml() ? "keydown" : "keypress"; + +qx.Proto._onkeyevent = function(vContainer, vEvent) +{ + if (vEvent.getKeyIdentifier() != "Tab") { + return; + } + + // Stop all key-events with a TAB keycode + vEvent.stopPropagation(); + vEvent.preventDefault(); + + // But only react on the one to use for this browser. + if (vEvent.getType() != qx.event.handler.FocusHandler.tabEventType) { + return; + } + + qx.event.handler.FocusHandler.mouseFocus = false; + + var vCurrent = this.getAttachedWidget().getFocusedChild(); + + // Support shift key to reverse widget detection order + if(!vEvent.isShiftPressed()) { + var vNext = vCurrent ? this.getWidgetAfter(vContainer, vCurrent) : this.getFirstWidget(vContainer); + } else { + var vNext = vCurrent ? this.getWidgetBefore(vContainer, vCurrent) : this.getLastWidget(vContainer); + } + + // If there was a widget found, focus it + if(vNext) + { + vNext.setFocused(true); + vNext._ontabfocus(); + } +} + +qx.Proto.compareTabOrder = function(c1, c2) +{ + // Sort-Check #1: Tab-Index + if(c1 == c2) { + return 0; + } + + var t1 = c1.getTabIndex(); + var t2 = c2.getTabIndex(); + + // The following are some ideas to handle focus after tabindex. + + // Sort-Check #2: Top-Position + if(t1 != t2) { + return t1 - t2; + } + + var y1 = qx.html.Location.getPageBoxTop(c1.getElement()); + var y2 = qx.html.Location.getPageBoxTop(c2.getElement()); + + if(y1 != y2) { + return y1 - y2; + } + + // Sort-Check #3: Left-Position + var x1 = qx.html.Location.getPageBoxLeft(c1.getElement()); + var x2 = qx.html.Location.getPageBoxLeft(c2.getElement()); + + if(x1 != x2) { + return x1 - x2; + } + + // Sort-Check #4: zIndex + var z1 = c1.getZIndex(); + var z2 = c2.getZIndex(); + + if(z1 != z2) { + return z1 - z2; + } + + return 0; +} + + + + + + +/* +--------------------------------------------------------------------------- + UTILITIES FOR TAB HANDLING +--------------------------------------------------------------------------- +*/ + +qx.Proto.getFirstWidget = function(vParentContainer) { + return this._getFirst(vParentContainer, null); +} + +qx.Proto.getLastWidget = function(vParentContainer) { + return this._getLast(vParentContainer, null); +} + +qx.Proto.getWidgetAfter = function(vParentContainer, vWidget) +{ + if(vParentContainer == vWidget) { + return this.getFirstWidget(vParentContainer); + } + + if(vWidget.getAnonymous()) { + vWidget = vWidget.getParent(); + } + + if(vWidget == null) { + return []; + } + + var vAll = []; + + this._getAllAfter(vParentContainer, vWidget, vAll); + + vAll.sort(this.compareTabOrder); + + return vAll.length > 0 ? vAll[0] : this.getFirstWidget(vParentContainer); +} + +qx.Proto.getWidgetBefore = function(vParentContainer, vWidget) +{ + if(vParentContainer == vWidget) { + return this.getLastWidget(vParentContainer); + } + + if(vWidget.getAnonymous()) { + vWidget = vWidget.getParent(); + } + + if(vWidget == null) { + return []; + } + + var vAll = []; + + this._getAllBefore(vParentContainer, vWidget, vAll); + + vAll.sort(this.compareTabOrder); + + var vChildrenLength = vAll.length; + return vChildrenLength > 0 ? vAll[vChildrenLength-1] : this.getLastWidget(vParentContainer); +} + +qx.Proto._getAllAfter = function(vParent, vWidget, vArray) +{ + var vChildren = vParent.getChildren(); + var vCurrentChild; + var vChildrenLength = vChildren.length; + + for (var i = 0; i < vChildrenLength; i++) + { + vCurrentChild = vChildren[i]; + + if(!(vCurrentChild instanceof qx.ui.core.Parent) && !(vCurrentChild instanceof qx.ui.basic.Terminator)) { + continue; + } + + if(vCurrentChild.isFocusable() && vCurrentChild.getTabIndex() > 0 && this.compareTabOrder(vWidget, vCurrentChild) < 0) { + vArray.push(vChildren[i]); + } + + if(!vCurrentChild.isFocusRoot() && vCurrentChild instanceof qx.ui.core.Parent) { + this._getAllAfter(vCurrentChild, vWidget, vArray); + } + } +} + +qx.Proto._getAllBefore = function(vParent, vWidget, vArray) +{ + var vChildren = vParent.getChildren(); + var vCurrentChild; + var vChildrenLength = vChildren.length; + + for (var i = 0; i < vChildrenLength; i++) + { + vCurrentChild = vChildren[i]; + + if(!(vCurrentChild instanceof qx.ui.core.Parent) && !(vCurrentChild instanceof qx.ui.basic.Terminator)) { + continue; + } + + if(vCurrentChild.isFocusable() && vCurrentChild.getTabIndex() > 0 && this.compareTabOrder(vWidget, vCurrentChild) > 0) { + vArray.push(vCurrentChild); + } + + if(!vCurrentChild.isFocusRoot() && vCurrentChild instanceof qx.ui.core.Parent) { + this._getAllBefore(vCurrentChild, vWidget, vArray); + } + } +} + +qx.Proto._getFirst = function(vParent, vFirstWidget) +{ + var vChildren = vParent.getChildren(); + var vCurrentChild; + var vChildrenLength = vChildren.length; + + for (var i = 0; i < vChildrenLength; i++) + { + vCurrentChild = vChildren[i]; + + if(!(vCurrentChild instanceof qx.ui.core.Parent) && !(vCurrentChild instanceof qx.ui.basic.Terminator)) { + continue; + } + + if(vCurrentChild.isFocusable() && vCurrentChild.getTabIndex() > 0) + { + if(vFirstWidget == null || this.compareTabOrder(vCurrentChild, vFirstWidget) < 0) { + vFirstWidget = vCurrentChild; + } + } + + if(!vCurrentChild.isFocusRoot() && vCurrentChild instanceof qx.ui.core.Parent) { + vFirstWidget = this._getFirst(vCurrentChild, vFirstWidget); + } + } + + return vFirstWidget; +} + +qx.Proto._getLast = function(vParent, vLastWidget) +{ + var vChildren = vParent.getChildren(); + var vCurrentChild; + var vChildrenLength = vChildren.length; + + for (var i = 0; i < vChildrenLength; i++) + { + vCurrentChild = vChildren[i]; + + if(!(vCurrentChild instanceof qx.ui.core.Parent) && !(vCurrentChild instanceof qx.ui.basic.Terminator)) { + continue; + } + + if(vCurrentChild.isFocusable() && vCurrentChild.getTabIndex() > 0) + { + if(vLastWidget == null || this.compareTabOrder(vCurrentChild, vLastWidget) > 0) { + vLastWidget = vCurrentChild; + } + } + + if(!vCurrentChild.isFocusRoot() && vCurrentChild instanceof qx.ui.core.Parent) { + vLastWidget = this._getLast(vCurrentChild, vLastWidget); + } + } + + return vLastWidget; +} + + + + + + + +/* +--------------------------------------------------------------------------- + DISPOSER +--------------------------------------------------------------------------- +*/ + +qx.Proto.dispose = function() +{ + if (this.getDisposed()) { + return; + } + + this._attachedWidget = null; + + qx.core.Target.prototype.dispose.call(this); +} diff --git a/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/event/handler/KeyEventHandler.js b/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/event/handler/KeyEventHandler.js new file mode 100644 index 0000000000..fd44b75c79 --- /dev/null +++ b/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/event/handler/KeyEventHandler.js @@ -0,0 +1,659 @@ +/* ************************************************************************ + + qooxdoo - the new era of web development + + http://qooxdoo.org + + Copyright: + 2004-2007 1&1 Internet AG, Germany, http://www.1and1.org + + License: + LGPL: http://www.gnu.org/licenses/lgpl.html + EPL: http://www.eclipse.org/org/documents/epl-v10.php + See the LICENSE file in the project's top-level directory for details. + + Authors: + * Sebastian Werner (wpbasti) + * Andreas Ecker (ecker) + * Fabian Jakobs (fjakobs) + +************************************************************************ */ + +/* ************************************************************************ + +#module(ui_core) +#require(qx.event.type.KeyEvent) +#require(qx.lang.Function); + +************************************************************************ */ + +/** + * This class provides unified key event handler for Internet Explorer, + * Firefox, Opera and Safari + */ +qx.OO.defineClass("qx.event.handler.KeyEventHandler", qx.core.Target, function() +{ + qx.core.Target.call(this); + + // Object Wrapper to Events (Needed for DOM-Events) + var o = this; + + /** + * private + * + * @param e {Event} event + */ + this.__onkeypress = function(e) { o._onkeypress(e); }; + + /** + * private + * + * @param e {Event} event + */ + this.__onkeyupdown = function(e) { o._onkeyupdown(e); }; +}); + + + + + + + + +/* +--------------------------------------------------------------------------- + EVENT-MAPPING +--------------------------------------------------------------------------- +*/ + +/** attach the key event handler to the DOM events */ +qx.Proto._attachEvents = function() +{ + var el = qx.core.Client.getInstance().isGecko() ? window : document.body; + + qx.html.EventRegistration.addEventListener(el, "keypress", this.__onkeypress); + qx.html.EventRegistration.addEventListener(el, "keyup", this.__onkeyupdown); + qx.html.EventRegistration.addEventListener(el, "keydown", this.__onkeyupdown); +}; + +/** detach the key event handler from the DOM events */ +qx.Proto._detachEvents = function() +{ + var el = qx.core.Client.getInstance().isGecko() ? window : document.body; + + // Unregister dom events + qx.html.EventRegistration.removeEventListener(el, "keypress", this.__onkeypress); + qx.html.EventRegistration.removeEventListener(el, "keyup", this.__onkeyupdown); + qx.html.EventRegistration.removeEventListener(el, "keydown", this.__onkeyupdown); +}; + + + + + + + + +/* +--------------------------------------------------------------------------- + KEY-MAPS +--------------------------------------------------------------------------- +*/ + +/** maps the charcodes of special printable keys to key identifiers */ +qx.Proto._specialCharCodeMap = +{ + 8 : "Backspace", // The Backspace (Back) key. + 9 : "Tab", // The Horizontal Tabulation (Tab) key. + 32 : "Space" // The Space (Spacebar) key. +}; + +/** maps the keycodes of non printable keys to key identifiers */ +qx.Proto._keyCodeToIdentifierMap = +{ + 13 : "Enter", // The Enter key. + // Note: This key identifier is also used for the + // Return (Macintosh numpad) key. + 16 : "Shift", // The Shift key. + 17 : "Control", // The Control (Ctrl) key. + 18 : "Alt", // The Alt (Menu) key. + 20 : "CapsLock", // The CapsLock key + 224 : "Meta", // The Meta key. (Apple Meta and Windows key) + + 27 : "Escape", // The Escape (Esc) key. + + 37 : "Left", // The Left Arrow key. + 38 : "Up", // The Up Arrow key. + 39 : "Right", // The Right Arrow key. + 40 : "Down", // The Down Arrow key. + + 33 : "PageUp", // The Page Up key. + 34 : "PageDown", // The Page Down (Next) key. + + 35 : "End", // The End key. + 36 : "Home", // The Home key. + 45 : "Insert", // The Insert (Ins) key. (Does not fire in Opera/Win) + 46 : "Delete", // The Delete (Del) Key. + + 112 : "F1", // The F1 key. + 113 : "F2", // The F2 key. + 114 : "F3", // The F3 key. + 115 : "F4", // The F4 key. + 116 : "F5", // The F5 key. + 117 : "F6", // The F6 key. + 118 : "F7", // The F7 key. + 119 : "F8", // The F8 key. + 120 : "F9", // The F9 key. + 121 : "F10", // The F10 key. + 122 : "F11", // The F11 key. + 123 : "F12", // The F12 key. + + 144 : "NumLock", // The Num Lock key. + 44 : "PrintScreen", // The Print Screen (PrintScrn, SnapShot) key. + 145 : "Scroll", // The scroll lock key + 19 : "Pause", // The pause/break key + + 91 : "Win", // The Windows Logo key + 93 : "Apps" // The Application key (Windows Context Menu) +}; + +/** maps the keycodes of the numpad keys to the right charcodes */ +qx.Proto._numpadToCharCode = +{ + 96 : "0".charCodeAt(0), + 97 : "1".charCodeAt(0), + 98 : "2".charCodeAt(0), + 99 : "3".charCodeAt(0), + 100 : "4".charCodeAt(0), + 101 : "5".charCodeAt(0), + 102 : "6".charCodeAt(0), + 103 : "7".charCodeAt(0), + 104 : "8".charCodeAt(0), + 105 : "9".charCodeAt(0), + + 106 : "*".charCodeAt(0), + 107 : "+".charCodeAt(0), + 109 : "-".charCodeAt(0), + 110 : ",".charCodeAt(0), + 111 : "/".charCodeAt(0) +}; + + +// construct invers of keyCodeToIdentifierMap +(function() +{ + if (!qx.Proto._identifierToKeyCodeMap) + { + qx.Proto._identifierToKeyCodeMap = {}; + + for (var key in qx.Proto._keyCodeToIdentifierMap) { + qx.Proto._identifierToKeyCodeMap[qx.Proto._keyCodeToIdentifierMap[key]] = parseInt(key); + } + + for (var key in qx.Proto._specialCharCodeMap) { + qx.Proto._identifierToKeyCodeMap[qx.Proto._specialCharCodeMap[key]] = parseInt(key); + } + } +})(); + + + + + + + +/* +--------------------------------------------------------------------------- + HELPER-METHODS +--------------------------------------------------------------------------- +*/ + +qx.Proto._charCodeA = "A".charCodeAt(0); +qx.Proto._charCodeZ = "Z".charCodeAt(0); +qx.Proto._charCode0 = "0".charCodeAt(0); +qx.Proto._charCode9 = "9".charCodeAt(0); + +/** + * Checks wether the keyCode represents a non printable key + * + * @param keyCode {String} + * @return {Boolean} + */ +qx.Proto._isNonPrintableKeyCode = function(keyCode) { + return this._keyCodeToIdentifierMap[keyCode] ? true : false; +}; + + +/** + * Check wether the keycode can be reliably detected in keyup/keydown events + * + * @param keyCode {String} + * @return {Boolean} + */ +qx.Proto._isIdentifiableKeyCode = function(keyCode) +{ + // A-Z + if (keyCode >= this._charCodeA && keyCode <= this._charCodeZ) { + return true; + } + + // 0-9 + if (keyCode >= this._charCode0 && keyCode <= this._charCode9) { + return true; + } + + // Enter, Space, Tab, Backspace + if (this._specialCharCodeMap[keyCode]) { + return true; + } + + // Numpad + if (this._numpadToCharCode[keyCode]) { + return true; + } + + // non printable keys + if (this._isNonPrintableKeyCode(keyCode)) { + return true; + } + + return false; +}; + + +/** + * Checks wether a given string is a valid keyIdentifier + * + * @param keyIdentifier {String} The key identifier. + * @return {Boolean} wether the given string is a valid keyIdentifier + */ +qx.Proto.isValidKeyIdentifier = function(keyIdentifier) +{ + if (this._identifierToKeyCodeMap[keyIdentifier]) { + return true; + } + + if (keyIdentifier.length != 1) { + return false; + } + + if (keyIdentifier >= "0" && keyIdentifier <= "9") { + return true; + } + + if (keyIdentifier >= "A" && keyIdentifier <= "Z") { + return true; + } + + switch (keyIdentifier) + { + case "+": + case "-": + case "*": + case "/": + return true; + + default: + return false; + } +}; + + +/** + * converts a keyboard code to the corresponding identifier + * + * @param keyCode {Integer} + * @return {String} key identifier + */ +qx.Proto._keyCodeToIdentifier = function(keyCode) +{ + if (this._isIdentifiableKeyCode(keyCode)) + { + var numPadKeyCode = this._numpadToCharCode[keyCode]; + if (numPadKeyCode) { + return String.fromCharCode(numPadKeyCode); + } + + return ( + this._keyCodeToIdentifierMap[keyCode] || + this._specialCharCodeMap[keyCode] || + String.fromCharCode(keyCode) + ); + } + else + { + return "Unidentified"; + } +}; + + +/** + * converts a character code to the corresponding identifier + * + * @param charCode {String} + * @return {String} key identifier + */ +qx.Proto._charCodeToIdentifier = function(charCode) { + return this._specialCharCodeMap[charCode] || String.fromCharCode(charCode).toUpperCase(); +}; + + +/** + * converts a key identifier back to a keycode + * + * @param keyIdentifier {String} + * @return {Integer} keyboard code + */ +qx.Proto._identifierToKeyCode = function(keyIdentifier) { + return this._identifierToKeyCodeMap[keyIdentifier] || keyIdentifier.charCodeAt(0); +}; + + + + + + + + +/* +--------------------------------------------------------------------------- + IDEALIZED-KEY-HANDLER +--------------------------------------------------------------------------- +*/ + +/** + * Key handler for an idealized browser. + * Runs after the browser specific key handlers have normalized the key events. + * + * @param keyCode {String} keyboard code + * @param charCode {String} character code + * @param eventType {String} type of the event (keydown, keypress, keyup) + * @param domEvent {Element} DomEvent + */ +qx.Proto._idealKeyHandler = function(keyCode, charCode, eventType, domEvent) +{ + if (!keyCode && !charCode) { + return; + } + + var keyIdentifier; + + // Use: keyCode + if (keyCode) + { + keyIdentifier = this._keyCodeToIdentifier(keyCode); + qx.event.handler.EventHandler.getInstance()._onkeyevent_post(domEvent, eventType, keyCode, charCode, keyIdentifier); + } + + // Use: charCode + else + { + keyIdentifier = this._charCodeToIdentifier(charCode); + qx.event.handler.EventHandler.getInstance()._onkeyevent_post(domEvent, "keypress", keyCode, charCode, keyIdentifier); + qx.event.handler.EventHandler.getInstance()._onkeyevent_post(domEvent, "keyinput", keyCode, charCode, keyIdentifier); + } +}; + + + + + + + + + +/* +--------------------------------------------------------------------------- + BROWSER-SPECIFIC-KEY-HANDLER: MSHTML +--------------------------------------------------------------------------- +*/ + +if (qx.core.Client.getInstance().isMshtml()) +{ + qx.Proto._lastUpDownType = {}; + + qx.Proto._charCode2KeyCode = + { + 13 : 13, + 27 : 27 + }; + + qx.Proto._onkeyupdown = function(domEvent) + { + domEvent = window.event || domEvent; + + var keyCode = domEvent.keyCode; + var charcode = 0; + var type = domEvent.type; + + // Ignore the down in such sequences dp dp dp + if (!(this._lastUpDownType[keyCode] == "keydown" && type == "keydown")) { + this._idealKeyHandler(keyCode, charcode, type, domEvent); + } + + // On non print-able character be sure to add a keypress event + if (this._isNonPrintableKeyCode(keyCode) && type == "keydown") { + this._idealKeyHandler(keyCode, charcode, "keypress", domEvent); + } + + // Store last type + this._lastUpDownType[keyCode] = type; + }; + + qx.Proto._onkeypress = function(domEvent) + { + domEvent = window.event || domEvent; + + if (this._charCode2KeyCode[domEvent.keyCode]) { + this._idealKeyHandler(this._charCode2KeyCode[domEvent.keyCode], 0, domEvent.type, domEvent); + } else { + this._idealKeyHandler(0, domEvent.keyCode, domEvent.type, domEvent); + } + }; +} + + + + + + +/* +--------------------------------------------------------------------------- + BROWSER-SPECIFIC-KEY-HANDLER: GECKO +--------------------------------------------------------------------------- +*/ + +else if (qx.core.Client.getInstance().isGecko()) +{ + qx.Proto._lastUpDownType = {}; + + qx.Proto._keyCodeFix = { + 12 : qx.Proto._identifierToKeyCode("NumLock") + }; + + /** + * key handler for Gecko + * + * @param domEvent {Element} DomEvent + */ + qx.Proto._onkeyupdown = qx.Proto._onkeypress = function(domEvent) + { + var keyCode = this._keyCodeFix[domEvent.keyCode] || domEvent.keyCode; + var charCode = domEvent.charCode; + var type = domEvent.type; + + // FF repeats under windows keydown events like IE + if (qx.core.Client.getInstance().runsOnWindows()) + { + var keyIdentifier = keyCode ? this._keyCodeToIdentifier(keyCode) : this._charCodeToIdentifier(charCode) + + if (!(this._lastUpDownType[keyIdentifier] == "keypress" && type == "keydown")) { + this._idealKeyHandler(keyCode, charCode, type, domEvent); + } + + // Store last type + this._lastUpDownType[keyIdentifier] = type; + } + + // all other OSes + else + { + this._idealKeyHandler(keyCode, charCode, type, domEvent); + } + }; +} + + + + + + +/* +--------------------------------------------------------------------------- + BROWSER-SPECIFIC-KEY-HANDLER: WEBKIT +--------------------------------------------------------------------------- +*/ + +else if (qx.core.Client.getInstance().isWebkit()) +{ + qx.Proto._charCode2KeyCode = + { + // Safari/Webkit Mappings + 63289 : qx.Proto._identifierToKeyCode("NumLock"), + 63276 : qx.Proto._identifierToKeyCode("PageUp"), + 63277 : qx.Proto._identifierToKeyCode("PageDown"), + 63275 : qx.Proto._identifierToKeyCode("End"), + 63273 : qx.Proto._identifierToKeyCode("Home"), + 63234 : qx.Proto._identifierToKeyCode("Left"), + 63232 : qx.Proto._identifierToKeyCode("Up"), + 63235 : qx.Proto._identifierToKeyCode("Right"), + 63233 : qx.Proto._identifierToKeyCode("Down"), + 63272 : qx.Proto._identifierToKeyCode("Delete"), + 63302 : qx.Proto._identifierToKeyCode("Insert"), + 63236 : qx.Proto._identifierToKeyCode("F1"), + 63237 : qx.Proto._identifierToKeyCode("F2"), + 63238 : qx.Proto._identifierToKeyCode("F3"), + 63239 : qx.Proto._identifierToKeyCode("F4"), + 63240 : qx.Proto._identifierToKeyCode("F5"), + 63241 : qx.Proto._identifierToKeyCode("F6"), + 63242 : qx.Proto._identifierToKeyCode("F7"), + 63243 : qx.Proto._identifierToKeyCode("F8"), + 63244 : qx.Proto._identifierToKeyCode("F9"), + 63245 : qx.Proto._identifierToKeyCode("F10"), + 63246 : qx.Proto._identifierToKeyCode("F11"), + 63247 : qx.Proto._identifierToKeyCode("F12"), + 63248 : qx.Proto._identifierToKeyCode("PrintScreen"), + + 3 : qx.Proto._identifierToKeyCode("Enter"), + 12 : qx.Proto._identifierToKeyCode("NumLock"), + 13 : qx.Proto._identifierToKeyCode("Enter") + }; + + qx.Proto._onkeyupdown = qx.Proto._onkeypress = function(domEvent) + { + var keyCode = 0; + var charCode = 0; + var type = domEvent.type; + + // prevent Safari from sending key signals twice + // This bug is fixed in recent Webkit builds so we need a revision check + // see http://trac.mochikit.com/ticket/182 for details + if (qx.core.Client.getInstance().getVersion() < 420) + { + if (!this._lastCharCodeForType) { + this._lastCharCodeForType = {}; + } + + var isSafariSpecialKey = this._lastCharCodeForType[type] > 63000; + + if (isSafariSpecialKey) { + this._lastCharCodeForType[type] = null; + return; + } + + this._lastCharCodeForType[type] = domEvent.charCode; + } + + if (type == "keyup" || type == "keydown") { + keyCode = this._charCode2KeyCode[domEvent.charCode] || domEvent.keyCode; + } + else + { + if (this._charCode2KeyCode[domEvent.charCode]) { + keyCode = this._charCode2KeyCode[domEvent.charCode]; + } else { + charCode = domEvent.charCode; + } + } + + this._idealKeyHandler(keyCode, charCode, type, domEvent); + }; +} + + + + + +/* +--------------------------------------------------------------------------- + BROWSER-SPECIFIC-KEY-HANDLER: OPERA +--------------------------------------------------------------------------- +*/ + +else if (qx.core.Client.getInstance().isOpera()) +{ + qx.Proto._onkeyupdown = function(domEvent) { + this._idealKeyHandler(domEvent.keyCode, 0, domEvent.type, domEvent); + }; + + qx.Proto._onkeypress = function(domEvent) + { + if (this._keyCodeToIdentifierMap[domEvent.keyCode]) { + this._idealKeyHandler(domEvent.keyCode, 0, domEvent.type, domEvent); + } else { + this._idealKeyHandler(0, domEvent.keyCode, domEvent.type, domEvent); + } + }; +} + + + + + + +/* +--------------------------------------------------------------------------- + DISPOSE +--------------------------------------------------------------------------- +*/ + +/** + * Destructor + */ +qx.Proto.dispose = function() +{ + if (this.getDisposed()) { + return; + } + + // Detach keyboard events + this._detachEvents(); + + return qx.core.Target.prototype.dispose.call(this); +}; + + + + + + +/* +--------------------------------------------------------------------------- + DEFER SINGLETON INSTANCE +--------------------------------------------------------------------------- +*/ + +/** + * Singleton Instance Getter + */ +qx.Class.getInstance = qx.lang.Function.returnInstance; diff --git a/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/event/type/DataEvent.js b/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/event/type/DataEvent.js new file mode 100644 index 0000000000..47e08a1771 --- /dev/null +++ b/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/event/type/DataEvent.js @@ -0,0 +1,50 @@ +/* ************************************************************************ + + qooxdoo - the new era of web development + + http://qooxdoo.org + + Copyright: + 2004-2007 1&1 Internet AG, Germany, http://www.1and1.org + + License: + LGPL: http://www.gnu.org/licenses/lgpl.html + EPL: http://www.eclipse.org/org/documents/epl-v10.php + See the LICENSE file in the project's top-level directory for details. + + Authors: + * Sebastian Werner (wpbasti) + * Andreas Ecker (ecker) + +************************************************************************ */ + +/* ************************************************************************ + +#module(core) + +************************************************************************ */ + +/*! + Event object for property changes. +*/ +qx.OO.defineClass("qx.event.type.DataEvent", qx.event.type.Event, +function(vType, vData) +{ + qx.event.type.Event.call(this, vType); + + this.setData(vData); +}); + +qx.OO.addFastProperty({ name : "propagationStopped", defaultValue : false }); +qx.OO.addFastProperty({ name : "data" }); + +qx.Proto.dispose = function() +{ + if(this.getDisposed()) { + return; + } + + this._valueData = null; + + return qx.event.type.Event.prototype.dispose.call(this); +} diff --git a/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/event/type/DomEvent.js b/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/event/type/DomEvent.js new file mode 100644 index 0000000000..b6fb710c7a --- /dev/null +++ b/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/event/type/DomEvent.js @@ -0,0 +1,229 @@ +/* ************************************************************************ + + qooxdoo - the new era of web development + + http://qooxdoo.org + + Copyright: + 2004-2007 1&1 Internet AG, Germany, http://www.1and1.org + + License: + LGPL: http://www.gnu.org/licenses/lgpl.html + EPL: http://www.eclipse.org/org/documents/epl-v10.php + See the LICENSE file in the project's top-level directory for details. + + Authors: + * Sebastian Werner (wpbasti) + * Andreas Ecker (ecker) + +************************************************************************ */ + +/* ************************************************************************ + +#module(ui_core) + +************************************************************************ */ + +qx.OO.defineClass("qx.event.type.DomEvent", qx.event.type.Event, +function(vType, vDomEvent, vDomTarget, vTarget, vOriginalTarget) +{ + qx.event.type.Event.call(this, vType); + + this.setDomEvent(vDomEvent); + this.setDomTarget(vDomTarget); + + this.setTarget(vTarget); + this.setOriginalTarget(vOriginalTarget); +}); + +qx.OO.addFastProperty({ name : "bubbles", defaultValue : true, noCompute : true }); +qx.OO.addFastProperty({ name : "propagationStopped", defaultValue : false, noCompute : true }); + +qx.OO.addFastProperty({ name : "domEvent", setOnlyOnce : true, noCompute : true }); +qx.OO.addFastProperty({ name : "domTarget", setOnlyOnce : true, noCompute : true }); + +/** + * The modifiers. A mask of the pressed modifier keys. This is an OR-combination of + * {@link #SHIFT_MASK}, {@link #CTRL_MASK}, {@link #ALT_MASK} and {@link #META_MASK}. + */ +qx.OO.addCachedProperty({ name : "modifiers", defaultValue : null }); + + +// property computer +qx.Proto._computeModifiers = function() { + var mask = 0; + var evt = this.getDomEvent(); + if (evt.shiftKey) mask |= qx.event.type.DomEvent.SHIFT_MASK; + if (evt.ctrlKey) mask |= qx.event.type.DomEvent.CTRL_MASK; + if (evt.altKey) mask |= qx.event.type.DomEvent.ALT_MASK; + if (evt.metaKey) mask |= qx.event.type.DomEvent.META_MASK; + return mask; +} + + + + + + +/* +--------------------------------------------------------------------------- + SPECIAL KEY SUPPORT +--------------------------------------------------------------------------- +*/ + +/** + * Returns whether the the ctrl key is pressed. + * + * @return {Boolean} whether the the ctrl key is pressed. + */ +qx.Proto.isCtrlPressed = function() { + return this.getDomEvent().ctrlKey; +} + +/** + * Returns whether the the ctrl key is pressed. + * + * @return {Boolean} whether the the ctrl key is pressed. + * @deprecated Use {@link #isCtrlPressed} instead. + */ +qx.Proto.getCtrlKey = qx.Proto.isCtrlPressed; + + +/** + * Returns whether the the shift key is pressed. + * + * @return {Boolean} whether the the shift key is pressed. + */ +qx.Proto.isShiftPressed = function() { + return this.getDomEvent().shiftKey; +} + +/** + * Returns whether the the shift key is pressed. + * + * @return {Boolean} whether the the shift key is pressed. + * @deprecated Use {@link #isShiftPressed} instead. + */ +qx.Proto.getShiftKey = qx.Proto.isShiftPressed; + + +/** + * Returns whether the the alt key is pressed. + * + * @return {Boolean} whether the the alt key is pressed. + */ +qx.Proto.isAltPressed = function() { + return this.getDomEvent().altKey; +} + +/** + * Returns whether the the alt key is pressed. + * + * @return {Boolean} whether the the alt key is pressed. + * @deprecated Use {@link #isAltPressed} instead. + */ +qx.Proto.getAltKey = qx.Proto.isAltPressed; + + +/** + * Returns whether the the meta key is pressed. + * + * @return {Boolean} whether the the meta key is pressed. + */ +qx.Proto.isMetaPressed = function() { + return this.getDomEvent().metaKey; +} + + +/** + * Returns whether the ctrl key or (on the Mac) the command key is pressed. + * + * @return {Boolean} <code>true</code> if the command key is pressed on the Mac + * or the ctrl key is pressed on another system. + */ +qx.Proto.isCtrlOrCommandPressed = function() { + if (qx.core.Client.getInstance().runsOnMacintosh()) { + return this.getDomEvent().metaKey; + } else { + return this.getDomEvent().ctrlKey; + } +} + + + + + + + +/* +--------------------------------------------------------------------------- + PREVENT DEFAULT +--------------------------------------------------------------------------- +*/ + +if(qx.core.Client.getInstance().isMshtml()) +{ + qx.Proto.setDefaultPrevented = function(vValue) + { + if (!vValue) { + return this.error("It is not possible to set preventDefault to false if it was true before!", "setDefaultPrevented"); + } + + this.getDomEvent().returnValue = false; + + qx.event.type.Event.prototype.setDefaultPrevented.call(this, vValue); + } +} +else +{ + qx.Proto.setDefaultPrevented = function(vValue) + { + if (!vValue) { + return this.error("It is not possible to set preventDefault to false if it was true before!", "setDefaultPrevented"); + } + + this.getDomEvent().preventDefault(); + this.getDomEvent().returnValue = false; + + qx.event.type.Event.prototype.setDefaultPrevented.call(this, vValue); + } +} + + + + + + + +/* +--------------------------------------------------------------------------- + DISPOSER +--------------------------------------------------------------------------- +*/ + +qx.Proto.dispose = function() +{ + if (this.getDisposed()) { + return; + } + + this._valueDomEvent = null; + this._valueDomTarget = null; + + return qx.event.type.Event.prototype.dispose.call(this); +} + + + + +/** {int} The modifier mask for the shift key. */ +qx.Class.SHIFT_MASK = 1; + +/** {int} The modifier mask for the control key. */ +qx.Class.CTRL_MASK = 2; + +/** {int} The modifier mask for the alt key. */ +qx.Class.ALT_MASK = 4; + +/** {int} The modifier mask for the meta key (e.g. apple key on Macs). */ +qx.Class.META_MASK = 8; diff --git a/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/event/type/DragEvent.js b/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/event/type/DragEvent.js new file mode 100644 index 0000000000..a6bd360bbe --- /dev/null +++ b/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/event/type/DragEvent.js @@ -0,0 +1,207 @@ +/* ************************************************************************ + + qooxdoo - the new era of web development + + http://qooxdoo.org + + Copyright: + 2004-2007 1&1 Internet AG, Germany, http://www.1and1.org + + License: + LGPL: http://www.gnu.org/licenses/lgpl.html + EPL: http://www.eclipse.org/org/documents/epl-v10.php + See the LICENSE file in the project's top-level directory for details. + + Authors: + * Sebastian Werner (wpbasti) + * Andreas Ecker (ecker) + +************************************************************************ */ + +/* ************************************************************************ + +#module(ui_dragdrop) + +************************************************************************ */ + +/*! + The event object for drag and drop sessions +*/ +qx.OO.defineClass("qx.event.type.DragEvent", qx.event.type.MouseEvent, +function(vType, vMouseEvent, vTarget, vRelatedTarget) +{ + this._mouseEvent = vMouseEvent; + + var vOriginalTarget = null; + + switch(vType) + { + case "dragstart": + case "dragover": + vOriginalTarget = vMouseEvent.getOriginalTarget(); + } + + qx.event.type.MouseEvent.call(this, vType, vMouseEvent.getDomEvent(), vTarget.getElement(), vTarget, vOriginalTarget, vRelatedTarget); +}); + + + + + +/* +--------------------------------------------------------------------------- + UTILITIY +--------------------------------------------------------------------------- +*/ + +qx.Proto.getMouseEvent = function() { + return this._mouseEvent; +} + + + + + + +/* +--------------------------------------------------------------------------- + APPLICATION CONNECTION +--------------------------------------------------------------------------- +*/ + +qx.Proto.startDrag = function() +{ + if (this.getType() != "dragstart") { + throw new Error("qx.event.type.DragEvent startDrag can only be called during the dragstart event: " + this.getType()); + } + + this.stopPropagation(); + qx.event.handler.DragAndDropHandler.getInstance().startDrag(); +} + + + + + + +/* +--------------------------------------------------------------------------- + DATA SUPPORT +--------------------------------------------------------------------------- +*/ + +qx.Proto.addData = function(sType, oData) { + qx.event.handler.DragAndDropHandler.getInstance().addData(sType, oData); +} + +qx.Proto.getData = function(sType) { + return qx.event.handler.DragAndDropHandler.getInstance().getData(sType); +} + +qx.Proto.clearData = function() { + qx.event.handler.DragAndDropHandler.getInstance().clearData(); +} + +qx.Proto.getDropDataTypes = function() { + return qx.event.handler.DragAndDropHandler.getInstance().getDropDataTypes(); +} + + + + + + +/* +--------------------------------------------------------------------------- + ACTION SUPPORT +--------------------------------------------------------------------------- +*/ + +qx.Proto.addAction = function(sAction) { + qx.event.handler.DragAndDropHandler.getInstance().addAction(sAction); +} + +qx.Proto.removeAction = function(sAction) { + qx.event.handler.DragAndDropHandler.getInstance().removeAction(sAction); +} + +qx.Proto.getAction = function() { + return qx.event.handler.DragAndDropHandler.getInstance().getCurrentAction(); +} + +qx.Proto.clearActions = function() { + qx.event.handler.DragAndDropHandler.getInstance().clearActions(); +} + + + + + + +/* +--------------------------------------------------------------------------- + USER FEEDBACK SUPPORT +--------------------------------------------------------------------------- +*/ + +/** + * Sets the widget to show as feedback for the user. This widget should + * represent the object(s) the user is dragging. + * + * @param widget {qx.ui.core.Widget} the feedback widget. + * @param deltaX {int ? 10} the number of pixels the top-left corner of the widget + * should be away from the mouse cursor in x direction. + * @param deltaY {int ? 10} the number of pixels the top-left corner of the widget + * should be away from the mouse cursor in y direction. + * @param autoDisposeWidget {boolean} whether the widget should be disposed when + * dragging is finished or cancelled. + */ +qx.Proto.setFeedbackWidget = function(widget, deltaX, deltaY, autoDisposeWidget) { + qx.event.handler.DragAndDropHandler.getInstance().setFeedbackWidget(widget, deltaX, deltaY, autoDisposeWidget); +}; + + + + + + +/* +--------------------------------------------------------------------------- + CURSPOR POSITIONING SUPPORT +--------------------------------------------------------------------------- +*/ + +/** + * Sets the position of the cursor feedback (the icon showing whether dropping + * is allowed at the current position and which action a drop will do). + * + * @param deltaX {int} The number of pixels the top-left corner of the + * cursor feedback should be away from the mouse cursor in x direction. + * @param deltaY {int} The number of pixels the top-left corner of the + * cursor feedback should be away from the mouse cursor in y direction. + */ +qx.Proto.setCursorPosition = function(deltaX, deltaY) { + qx.event.handler.DragAndDropHandler.getInstance().setCursorPosition(deltaX, deltaY); +}; + + + + + + +/* +--------------------------------------------------------------------------- + DISPOSER +--------------------------------------------------------------------------- +*/ + +qx.Proto.dispose = function() +{ + if (this.getDisposed()) { + return; + } + + this._mouseEvent = null; + + return qx.event.type.MouseEvent.prototype.dispose.call(this); +} diff --git a/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/event/type/Event.js b/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/event/type/Event.js new file mode 100644 index 0000000000..82798da893 --- /dev/null +++ b/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/event/type/Event.js @@ -0,0 +1,90 @@ +/* ************************************************************************ + + qooxdoo - the new era of web development + + http://qooxdoo.org + + Copyright: + 2004-2007 1&1 Internet AG, Germany, http://www.1and1.org + + License: + LGPL: http://www.gnu.org/licenses/lgpl.html + EPL: http://www.eclipse.org/org/documents/epl-v10.php + See the LICENSE file in the project's top-level directory for details. + + Authors: + * Sebastian Werner (wpbasti) + * Andreas Ecker (ecker) + +************************************************************************ */ + +/* ************************************************************************ + +#module(core) + +************************************************************************ */ + +/*! + The qooxdoo core event object. Each event object for qx.core.Targets should extend this class. +*/ +qx.OO.defineClass("qx.event.type.Event", qx.core.Object, +function(vType) +{ + qx.core.Object.call(this, false); + + this.setType(vType); +}); + +qx.OO.addFastProperty({ name : "type", setOnlyOnce : true }); + +qx.OO.addFastProperty({ name : "originalTarget", setOnlyOnce : true }); +qx.OO.addFastProperty({ name : "target", setOnlyOnce : true }); +qx.OO.addFastProperty({ name : "relatedTarget", setOnlyOnce : true }); +qx.OO.addFastProperty({ name : "currentTarget" }); + +qx.OO.addFastProperty({ name : "bubbles", defaultValue : false, noCompute : true }); +qx.OO.addFastProperty({ name : "propagationStopped", defaultValue : true, noCompute : true }); +qx.OO.addFastProperty({ name : "defaultPrevented", defaultValue : false, noCompute : true }); + +/** If the event object should automatically be disposed by the dispatcher */ +qx.OO.addFastProperty({ name : "autoDispose", defaultValue : false }); + + + + +/* +--------------------------------------------------------------------------- + SHORTCUTS +--------------------------------------------------------------------------- +*/ + +qx.Proto.preventDefault = function() { + this.setDefaultPrevented(true); +} + +qx.Proto.stopPropagation = function() { + this.setPropagationStopped(true); +} + + + + +/* +--------------------------------------------------------------------------- + DISPOSER +--------------------------------------------------------------------------- +*/ + +qx.Proto.dispose = function() +{ + if(this.getDisposed()) { + return; + } + + this._valueOriginalTarget = null; + this._valueTarget = null; + this._valueRelatedTarget = null; + this._valueCurrentTarget = null; + + return qx.core.Object.prototype.dispose.call(this); +} diff --git a/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/event/type/FocusEvent.js b/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/event/type/FocusEvent.js new file mode 100644 index 0000000000..d8b327cb78 --- /dev/null +++ b/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/event/type/FocusEvent.js @@ -0,0 +1,48 @@ +/* ************************************************************************ + + qooxdoo - the new era of web development + + http://qooxdoo.org + + Copyright: + 2004-2007 1&1 Internet AG, Germany, http://www.1and1.org + + License: + LGPL: http://www.gnu.org/licenses/lgpl.html + EPL: http://www.eclipse.org/org/documents/epl-v10.php + See the LICENSE file in the project's top-level directory for details. + + Authors: + * Sebastian Werner (wpbasti) + * Andreas Ecker (ecker) + +************************************************************************ */ + +/* ************************************************************************ + +#module(ui_core) + +************************************************************************ */ + +/*! + This event handles all focus events. + + The four supported types are: + 1+2: focus and blur also propagate the target object + 3+4: focusout and focusin are bubbling to the parent objects +*/ +qx.OO.defineClass("qx.event.type.FocusEvent", qx.event.type.Event, +function(vType, vTarget) +{ + qx.event.type.Event.call(this, vType); + + this.setTarget(vTarget); + + switch(vType) + { + case "focusin": + case "focusout": + this.setBubbles(true); + this.setPropagationStopped(false); + } +}); diff --git a/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/event/type/KeyEvent.js b/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/event/type/KeyEvent.js new file mode 100644 index 0000000000..eb69c51242 --- /dev/null +++ b/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/event/type/KeyEvent.js @@ -0,0 +1,200 @@ +/* ************************************************************************ + + qooxdoo - the new era of web development + + http://qooxdoo.org + + Copyright: + 2004-2007 1&1 Internet AG, Germany, http://www.1and1.org + + License: + LGPL: http://www.gnu.org/licenses/lgpl.html + EPL: http://www.eclipse.org/org/documents/epl-v10.php + See the LICENSE file in the project's top-level directory for details. + + Authors: + * Sebastian Werner (wpbasti) + * Andreas Ecker (ecker) + * Fabian Jakobs (fjakobs) + +************************************************************************ */ + +/* ************************************************************************ + +#module(ui_core) + +************************************************************************ */ + +/** + * A key event instance contains all data for each occured key event + * + * @param vType {String} event type (keydown, keypress, keyinput, keyup) + * @param vDomEvent {Element} DOM event object + * @param vDomTarget {Element} target element of the DOM event + * @param vTarget + * @param vOriginalTarget + * @param vKeyCode {Integer} emulated key code for compatibility with older qoodoo applications + * @param vCharCode {Integer} char code from the "keypress" event + * @param vKeyIdentifier {String} the key identifier + */ +qx.OO.defineClass("qx.event.type.KeyEvent", qx.event.type.DomEvent, +function(vType, vDomEvent, vDomTarget, vTarget, vOriginalTarget, vKeyCode, vCharCode, vKeyIdentifier) +{ + qx.event.type.DomEvent.call(this, vType, vDomEvent, vDomTarget, vTarget, vOriginalTarget); + + this.setKeyCode(vKeyCode); + this.setCharCode(vCharCode); + this.setKeyIdentifier(vKeyIdentifier); +}); + +/** + * Legacy keycode + * @deprecated Will be removed with qooxdoo 0.7 + */ +qx.OO.addFastProperty({ name : "keyCode", setOnlyOnce : true, noCompute : true }); + +/** + * Unicode number of the pressed character. + * Only valid in "keyinput" events + */ +qx.OO.addFastProperty({ name : "charCode", setOnlyOnce : true, noCompute : true }); + +/** + * Identifier of the pressed key. This property is modeled after the <em>KeyboardEvent.keyIdentifier</em> property + * of the W3C DOM 3 event specification (http://www.w3.org/TR/2003/NOTE-DOM-Level-3-Events-20031107/events.html#Events-KeyboardEvent-keyIdentifier). + * + * It is not valid in "keyinput" events" + * + * Printable keys are represented by a unicode string, non-printable keys have one of the following + * values: + * <br> + * <table> + * <tr><th>Backspace</th><td>The Backspace (Back) key.</td></tr> + * <tr><th>Tab</th><td>The Horizontal Tabulation (Tab) key.</td></tr> + * <tr><th>Space</th><td>The Space (Spacebar) key.</td></tr> + * <tr><th>Enter</th><td>The Enter key. Note: This key identifier is also used for the Return (Macintosh numpad) key.</td></tr> + * <tr><th>Shift</th><td>The Shift key.</td></tr> + * <tr><th>Control</th><td>The Control (Ctrl) key.</td></tr> + * <tr><th>Alt</th><td>The Alt (Menu) key.</td></tr> + * <tr><th>CapsLock</th><td>The CapsLock key</td></tr> + * <tr><th>Meta</th><td>The Meta key. (Apple Meta and Windows key)</td></tr> + * <tr><th>Escape</th><td>The Escape (Esc) key.</td></tr> + * <tr><th>Left</th><td>The Left Arrow key.</td></tr> + * <tr><th>Up</th><td>The Up Arrow key.</td></tr> + * <tr><th>Right</th><td>The Right Arrow key.</td></tr> + * <tr><th>Down</th><td>The Down Arrow key.</td></tr> + * <tr><th>PageUp</th><td>The Page Up key.</td></tr> + * <tr><th>PageDown</th><td>The Page Down (Next) key.</td></tr> + * <tr><th>End</th><td>The End key.</td></tr> + * <tr><th>Home</th><td>The Home key.</td></tr> + * <tr><th>Insert</th><td>The Insert (Ins) key. (Does not fire in Opera/Win)</td></tr> + * <tr><th>Delete</th><td>The Delete (Del) Key.</td></tr> + * <tr><th>F1</th><td>The F1 key.</td></tr> + * <tr><th>F2</th><td>The F2 key.</td></tr> + * <tr><th>F3</th><td>The F3 key.</td></tr> + * <tr><th>F4</th><td>The F4 key.</td></tr> + * <tr><th>F5</th><td>The F5 key.</td></tr> + * <tr><th>F6</th><td>The F6 key.</td></tr> + * <tr><th>F7</th><td>The F7 key.</td></tr> + * <tr><th>F8</th><td>The F8 key.</td></tr> + * <tr><th>F9</th><td>The F9 key.</td></tr> + * <tr><th>F10</th><td>The F10 key.</td></tr> + * <tr><th>F11</th><td>The F11 key.</td></tr> + * <tr><th>F12</th><td>The F12 key.</td></tr> + * <tr><th>NumLock</th><td>The Num Lock key.</td></tr> + * <tr><th>PrintScreen</th><td>The Print Screen (PrintScrn, SnapShot) key.</td></tr> + * <tr><th>Scroll</th><td>The scroll lock key</td></tr> + * <tr><th>Pause</th><td>The pause/break key</td></tr> + * <tr><th>Win</th><td>The Windows Logo key</td></tr> + * <tr><th>Apps</th><td>The Application key (Windows Context Menu)</td></tr> + * </table> + */ +qx.OO.addFastProperty({ name : "keyIdentifier", setOnlyOnce : true, noCompute : true }); + + + + + + + + +/* ************************************************************************ + Class data, properties and methods +************************************************************************ */ + +/* +--------------------------------------------------------------------------- + CLASS PROPERTIES AND METHODS +--------------------------------------------------------------------------- +*/ + +/** + * Mapping of the old key identifiers to the key codes + * @deprecated + */ +qx.event.type.KeyEvent.keys = +{ + esc : 27, + enter : 13, + tab : 9, + space : 32, + + up : 38, + down : 40, + left : 37, + right : 39, + + shift : 16, + ctrl : 17, + alt : 18, + + f1 : 112, + f2 : 113, + f3 : 114, + f4 : 115, + f5 : 116, + f6 : 117, + f7 : 118, + f8 : 119, + f9 : 120, + f10 : 121, + f11 : 122, + f12 : 123, + + print : 124, + + del : 46, + backspace : 8, + insert : 45, + home : 36, + end : 35, + + pageup : 33, + pagedown : 34, + + numlock : 144, + + numpad_0 : 96, + numpad_1 : 97, + numpad_2 : 98, + numpad_3 : 99, + numpad_4 : 100, + numpad_5 : 101, + numpad_6 : 102, + numpad_7 : 103, + numpad_8 : 104, + numpad_9 : 105, + + numpad_divide : 111, + numpad_multiply : 106, + numpad_minus : 109, + numpad_plus : 107 +}; + +// create dynamic codes copy +(function() { + qx.event.type.KeyEvent.codes = {}; + for (var i in qx.event.type.KeyEvent.keys) { + qx.event.type.KeyEvent.codes[qx.event.type.KeyEvent.keys[i]] = i; + } +})(); diff --git a/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/event/type/MouseEvent.js b/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/event/type/MouseEvent.js new file mode 100644 index 0000000000..053037b281 --- /dev/null +++ b/webapps/qooxdoo-0.6.5-sdk/frontend/framework/source/class/qx/event/type/MouseEvent.js @@ -0,0 +1,311 @@ +/* ************************************************************************ + + qooxdoo - the new era of web development + + http://qooxdoo.org + + Copyright: + 2004-2007 1&1 Internet AG, Germany, http://www.1and1.org + + License: + LGPL: http://www.gnu.org/licenses/lgpl.html + EPL: http://www.eclipse.org/org/documents/epl-v10.php + See the LICENSE file in the project's top-level directory for details. + + Authors: + * Sebastian Werner (wpbasti) + * Andreas Ecker (ecker) + +************************************************************************ */ + +/* ************************************************************************ + +#module(ui_core) + +************************************************************************ */ + +/*! + A mouse event instance contains all data for each occured mouse event +*/ +qx.OO.defineClass("qx.event.type.MouseEvent", qx.event.type.DomEvent, +function(vType, vDomEvent, vDomTarget, vTarget, vOriginalTarget, vRelatedTarget) +{ + qx.event.type.DomEvent.call(this, vType, vDomEvent, vDomTarget, vTarget, vOriginalTarget); + + if (vRelatedTarget) { + this.setRelatedTarget(vRelatedTarget); + } +}); + +qx.Class.C_BUTTON_LEFT = "left"; +qx.Class.C_BUTTON_MIDDLE = "middle"; +qx.Class.C_BUTTON_RIGHT = "right"; +qx.Class.C_BUTTON_NONE = "none"; + + + +/* ************************************************************************ + Class data, properties and methods +************************************************************************ */ + +/* +--------------------------------------------------------------------------- + CLASS PROPERTIES AND METHODS +--------------------------------------------------------------------------- +*/ + +qx.event.type.MouseEvent._screenX = qx.event.type.MouseEvent._screenY = qx.event.type.MouseEvent._clientX = qx.event.type.MouseEvent._clientY = qx.event.type.MouseEvent._pageX = qx.event.type.MouseEvent._pageY = 0; +qx.event.type.MouseEvent._button = null; + +qx.event.type.MouseEvent._storeEventState = function(e) +{ + qx.event.type.MouseEvent._screenX = e.getScreenX(); + qx.event.type.MouseEvent._screenY = e.getScreenY(); + qx.event.type.MouseEvent._clientX = e.getClientX(); + qx.event.type.MouseEvent._clientY = e.getClientY(); + qx.event.type.MouseEvent._pageX = e.getPageX(); + qx.event.type.MouseEvent._pageY = e.getPageY(); + qx.event.type.MouseEvent._button = e.getButton(); +} + +qx.event.type.MouseEvent.getScreenX = function() { return qx.event.type.MouseEvent._screenX; } +qx.event.type.MouseEvent.getScreenY = function() { return qx.event.type.MouseEvent._screenY; } +qx.event.type.MouseEvent.getClientX = function() { return qx.event.type.MouseEvent._clientX; } +qx.event.type.MouseEvent.getClientY = function() { return qx.event.type.MouseEvent._clientY; } +qx.event.type.MouseEvent.getPageX = function() { return qx.event.type.MouseEvent._pageX; } +qx.event.type.MouseEvent.getPageY = function() { return qx.event.type.MouseEvent._pageY; } +qx.event.type.MouseEvent.getButton = function() { return qx.event.type.MouseEvent._button; } + +if (qx.core.Client.getInstance().isMshtml()) +{ + qx.event.type.MouseEvent.buttons = { left : 1, right : 2, middle : 4 } +} +else +{ + qx.event.type.MouseEvent.buttons = { left : 0, right : 2, middle : 1 } +} + + + + + + +/* ************************************************************************ + Instance data, properties and methods +************************************************************************ */ + +/* +--------------------------------------------------------------------------- + SCREEN COORDINATES SUPPORT +--------------------------------------------------------------------------- +*/ + +qx.Proto.getScreenX = function() { + return this.getDomEvent().screenX; +} + +qx.Proto.getScreenY = function() { + return this.getDomEvent().screenY; +} + + + + + + + + +/* +--------------------------------------------------------------------------- + PAGE COORDINATES SUPPORT +--------------------------------------------------------------------------- +*/ + +if (qx.core.Client.getInstance().isMshtml()) +{ +qx.OO.addFastProperty({ name : "pageX", readOnly : true }); +qx.OO.addFastProperty({ name : "pageY", readOnly : true }); + + if (qx.core.Client.getInstance().isInQuirksMode()) + { + qx.Proto._computePageX = function() { + return this.getDomEvent().clientX + document.documentElement.scrollLeft; + } + + qx.Proto._computePageY = function() { + return this.getDomEvent().clientY + document.documentElement.scrollTop; + } + } + else + { + qx.Proto._computePageX = function() { + return this.getDomEvent().clientX + document.body.scrollLeft; + } + + qx.Proto._computePageY = function() { + return this.getDomEvent().clientY + document.body.scrollTop; + } + } +} +else if (qx.core.Client.getInstance().isGecko()) +{ + qx.Proto.getPageX = function() { + return this.getDomEvent().pageX; + } + + qx.Proto.getPageY = function() { + return this.getDomEvent().pageY; + } +} +else +{ + qx.Proto.getPageX = function() { + return this.getDomEvent().clientX; + } + + qx.Proto.getPageY = function() { + return this.getDomEvent().clientY; + } +} + + + + + + + +/* +--------------------------------------------------------------------------- + CLIENT COORDINATES SUPPORT +--------------------------------------------------------------------------- +*/ + +if (qx.core.Client.getInstance().isMshtml() || qx.core.Client.getInstance().isGecko()) +{ + qx.Proto.getClientX = function() { + return this.getDomEvent().clientX; + } + + qx.Proto.getClientY = function() { + return this.getDomEvent().clientY; + } +} +else +{ +qx.OO.addFastProperty({ name : "clientX", readOnly : true }); +qx.OO.addFastProperty({ name : "clientY", readOnly : true }); + + qx.Proto._computeClientX = function() { + return this.getDomEvent().clientX + (document.body && document.body.scrollLeft != null ? document.body.scrollLeft : 0); + } + + qx.Proto._computeClientY = function() { + return this.getDomEvent().clientY + (document.body && document.body.scrollTop != null ? document.body.scrollTop : 0); + } +} + + + + + + + +/* +--------------------------------------------------------------------------- + BUTTON SUPPORT +--------------------------------------------------------------------------- +*/ + +qx.OO.addFastProperty({ name : "button", readOnly : true }); + +// IE does not set e.button in click events +if (qx.core.Client.getInstance().isMshtml()) +{ + qx.Proto.isLeftButtonPressed = function() { + if (this.getType() == "click") { + return true; + } else { + return this.getButton() === qx.event.type.MouseEvent.C_BUTTON_LEFT; + } + } +} +else +{ + qx.Proto.isLeftButtonPressed = function() { + return this.getButton() === qx.event.type.MouseEvent.C_BUTTON_LEFT; + } +} + +qx.Proto.isMiddleButtonPressed = function() { + return this.getButton() === qx.event.type.MouseEvent.C_BUTTON_MIDDLE; +} + +qx.Proto.isRightButtonPressed = function() { + return this.getButton() === qx.event.type.MouseEvent.C_BUTTON_RIGHT; +} + +qx.Proto._computeButton = function() { + var e = this.getDomEvent(); + if (e.which) { + switch (e.which) { + case 1: + return qx.event.type.MouseEvent.C_BUTTON_LEFT; + + case 3: + return qx.event.type.MouseEvent.C_BUTTON_RIGHT; + + case 2: + return qx.event.type.MouseEvent.C_BUTTON_MIDDLE; + + default: + return qx.event.type.MouseEvent.C_BUTTON_NONE; + + } + } else { + switch(e.button) { + case 1: + return qx.event.type.MouseEvent.C_BUTTON_LEFT; + + case 2: + return qx.event.type.MouseEvent.C_BUTTON_RIGHT; + + case 4: + return qx.event.type.MouseEvent.C_BUTTON_MIDDLE; + + default: + return qx.event.type.MouseEvent.C_BUTTON_NONE; + } + } +} + + + + +/* +--------------------------------------------------------------------------- + WHEEL SUPPORT +--------------------------------------------------------------------------- +*/ + +// Implementation differences: http://ajaxian.com/archives/javascript-and-mouse-wheels + +qx.OO.addFastProperty({ name : "wheelDelta", readOnly : true }); + +if(qx.core.Client.getInstance().isMshtml()) +{ + qx.Proto._computeWheelDelta = function() { + return this.getDomEvent().wheelDelta / 120; + } +} +else if(qx.core.Client.getInstance().isOpera()) +{ + qx.Proto._computeWheelDelta = function() { + return -this.getDomEvent().wheelDelta / 120; + } +} +else +{ + qx.Proto._computeWheelDelta = function() { + return -this.getDomEvent().detail / 3; + } +} |