blob: d966f1a407861dac43a772c062410c9aad62c70d [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2012, 2013 EclipseSource and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* EclipseSource - initial API and implementation
******************************************************************************/
(function() {
rwt.qx.Class.createNamespace( "org.eclipse.rap.clientscripting", {} );
var ObjectRegistry = rwt.remote.ObjectRegistry;
org.eclipse.rap.clientscripting.ClientScriptingUtil = {
_wrapperHelper : function(){},
_getterMapping : {
"rwt.widgets.Text" : {
"getText" : function( widget ) { return function() { return widget.getValue(); }; },
"getSelection" : function( widget ) { return function() { return widget.getSelection(); }; },
"getEditable" : function( widget ) { return function() { return !widget.getReadOnly(); }; }
},
"rwt.widgets.List" : {
"getSelection" : function( widget ) {
return function() {
var items = widget.getSelectedItems();
var result = [];
for( var i = 0; i < items.length; i++ ) {
result[ i ] = rwt.util.Encoding.unescape( items[ i ].getLabel() );
}
return result;
};
}
}
},
_eventTypeMapping : {
"*" : {
"KeyDown" : "keypress",
"KeyUp" : "keyup",
"MouseDown" : "mousedown",
"MouseUp" : "mouseup",
"MouseMove" : "mousemove",
"MouseEnter" : "mouseover",
"MouseExit" : "mouseout",
"MouseDoubleClick" : "dblclick",
"Paint" : "paint",
"FocusIn" : "focus",
"FocusOut" : "blur",
"Show" : "appear",
"Hide" : "disappear"
},
"rwt.widgets.List" : {
"Selection" : "changeSelection",
"DefaultSelection" : "dblclick"
},
"rwt.widgets.Text" : {
"Verify" : "input", // TODO [tb] : does currently not react on programatic changes
"Modify" : "changeValue"
}
},
isPublicObject : function( obj ) {
return ObjectRegistry.getEntry( ObjectRegistry.getId( obj ) ).handler.isPublic === true;
},
getNativeEventSource : function( source, eventType ) {
var SWT = org.eclipse.rap.clientscripting.SWT;
var result;
if( source.classname === "rwt.widgets.List" && eventType === "Selection" ) {
result = source.getManager();
} else {
result = source;
}
return result;
},
getNativeEventType : function( source, eventType ) {
var map = this._eventTypeMapping;
var result;
if( map[ source.classname ] && map[ source.classname ][ eventType ] ) {
result = map[ source.classname ][ eventType ];
} else {
result = map[ "*" ][ eventType ];
}
return result;
},
wrapAsProto : function( object ) {
this._wrapperHelper.prototype = object;
var result = new this._wrapperHelper();
this._wrapperHelper.prototype = null;
return result;
},
disposeObject : function( object ) {
for( var key in object ) {
if( object.hasOwnProperty( key ) ) {
object[ key ] = null;
}
}
},
postProcessEvent : function( event, wrappedEvent, originalEvent ) {
var SWT = org.eclipse.rap.clientscripting.SWT;
switch( event.type ) {
case SWT.Verify:
this._postProcessVerifyEvent( event, wrappedEvent, originalEvent );
break;
case SWT.KeyDown:
case SWT.KeyUp:
this._postProcessKeyEvent( event, wrappedEvent, originalEvent );
break;
}
},
attachSetter : function( proxy, source ) {
var id = ObjectRegistry.getId( source );
var handler = id ? ObjectRegistry.getEntry( id ).handler : null;
if( handler ) {
var properties = handler.properties;
for( var i = 0; i < properties.length; i++ ) {
var property = properties[ i ];
proxy[ "set" + rwt.util.Strings.toFirstUp( property ) ] =
this._createSetter( id, property );
}
}
},
attachGetter : function( proxy, source ) {
if( source.classname ) {
var getterMap = this._getterMapping[ source.classname ];
for( var key in getterMap ) {
proxy[ key ] = getterMap[ key ]( source );
}
}
},
attachUserData : function( proxy, source ) {
var setter = this._setUserData;
var getter = this._getUserData;
proxy.setData = function( property, value ) {
setter( source, arguments );
};
proxy.getData = function( property ) {
return getter( source, arguments );
};
},
attachControlMethods : function( proxy, source ) {
var id = ObjectRegistry.getId( source );
var ClientScriptingUtil = org.eclipse.rap.clientscripting.ClientScriptingUtil;
proxy.redraw = function() {
ClientScriptingUtil._initGC( source );
};
proxy.forceFocus = function() {
var result = false;
if( source.getEnabled() && ClientScriptingUtil._isVisible( source ) ) {
rwt.widgets.Display.getCurrent().setFocusControl( id );
result = true;
}
return result;
};
},
addDisposeListener : function( widget, listener ) {
var orgDestroy = widget.destroy;
widget.destroy = function() {
listener( this );
orgDestroy.call( widget );
};
},
initEvent : function( event, type, target, originalEvent ) {
var SWT = org.eclipse.rap.clientscripting.SWT;
event.widget = org.eclipse.rap.clientscripting.WidgetProxy.getInstance( target );
event.type = type;
switch( type ) {
case SWT.KeyDown:
case SWT.KeyUp:
this._initKeyEvent( event, originalEvent );
break;
case SWT.MouseDown:
case SWT.MouseUp:
case SWT.MouseMove:
case SWT.MouseEnter:
case SWT.MouseExit:
case SWT.MouseDoubleClick:
this._initMouseEvent( event, originalEvent );
break;
case SWT.Verify:
this._initVerifyEvent( event, originalEvent );
break;
case SWT.Paint:
this._initPaintEvent( event, target );
break;
}
},
_createSetter : function( id, property ) {
var setProperty = this._setProperty;
var result = function( value ) {
setProperty( id, property, value );
};
return result;
},
_setProperty : function( id, property, value ) {
var props = {};
props[ property ] = value;
rwt.remote.MessageProcessor.processOperation( {
"target" : id,
"action" : "set",
"properties" : props
} );
},
_setUserData : function( source, args ) {
if( args.length !== 2 ) {
var msg = "Wrong number of arguments in SetData: Expected 2, found " + args.length;
throw new Error( msg );
}
var property = args[ 0 ];
var value = args[ 1 ];
var USERDATA_KEY = org.eclipse.rap.clientscripting.WidgetProxy._USERDATA_KEY;
var data = rwt.remote.HandlerUtil.getServerData( source );
data[ property ] = value;
},
_getUserData : function( source, args ) {
if( args.length !== 1 ) {
var msg = "Wrong number of arguments in SetData: Expected 1, found " + args.length;
throw new Error( msg );
}
var property = args[ 0 ];
var result = null;
var data = rwt.remote.HandlerUtil.getServerData( source );
if( typeof data[ property ] !== "undefined" ) {
result = data[ property ];
}
return result;
},
_initKeyEvent : function( event, originalEvent ) {
var charCode = originalEvent.getCharCode();
var SWT = org.eclipse.rap.clientscripting.SWT;
if( charCode !== 0 ) {
event.character = String.fromCharCode( charCode );
// TODO [tb] : keyCode will be off when character is not a-z
event.keyCode = event.character.toLowerCase().charCodeAt( 0 );
} else {
var keyCode = this._getLastKeyCode();
switch( keyCode ) {
case 16:
event.keyCode = SWT.SHIFT;
break;
case 17:
event.keyCode = SWT.CTRL;
break;
case 18:
event.keyCode = SWT.ALT;
break;
case 224:
event.keyCode = SWT.COMMAND;
break;
default:
event.keyCode = keyCode;
break;
}
}
this._setStateMask( event, originalEvent );
},
_initMouseEvent : function( event, originalEvent ) {
var target = originalEvent.getTarget()._getTargetNode();
var offset = rwt.html.Location.get( target, "scroll" );
event.x = originalEvent.getPageX() - offset.left;
event.y = originalEvent.getPageY() - offset.top;
if( originalEvent.isLeftButtonPressed() ) {
event.button = 1;
} else if( originalEvent.isRightButtonPressed() ) {
event.button = 3;
} if( originalEvent.isMiddleButtonPressed() ) {
event.button = 2;
}
this._setStateMask( event, originalEvent );
},
_initPaintEvent : function( event, target ) {
var gc = this._getGCFor( target );
event.gc = gc.getNativeContext();
},
_getGCFor : function( widget ) {
var gc = widget.getUserData( org.eclipse.rap.clientscripting.WidgetProxy._GC_KEY );
if( gc == null ) {
gc = this._findExistingGC( widget );
if( gc == null ) {
gc = new rwt.widgets.GC( widget );
}
widget.setUserData( org.eclipse.rap.clientscripting.WidgetProxy._GC_KEY, gc );
}
return gc;
},
_initGC : function( widget ) {
var gc = this._getGCFor( widget );
var width = widget.getInnerWidth();
var height = widget.getInnerHeight();
var fillStyle = widget.getBackgroundColor();
var strokeStyle = widget.getTextColor();
var font = [[]];
if( widget.getFont() ) {
font[ 0 ] = widget.getFont().getFamily();
font[ 1 ] = widget.getFont().getSize();
font[ 2 ] = widget.getFont().getBold();
font[ 3 ] = widget.getFont().getItalic();
}
gc.init(
width,
height,
font,
rwt.util.Colors.stringToRgb( fillStyle ? fillStyle : "#000000" ),
rwt.util.Colors.stringToRgb( strokeStyle ? strokeStyle : "#000000" )
);
},
_findExistingGC : function( widget ) {
var children = widget._getTargetNode().childNodes;
var result = null;
for( var i = 0; i < children.length && result == null; i++ ) {
if( children[ i ].rwtObject instanceof rwt.widgets.GC ) {
result = children[ i ].rwtObject;
}
}
return result;
},
_isVisible : function( widget ) {
var result = true;
var current = widget;
while( current && result ) {
result = current.getVisibility();
current = current.getParent();
}
return result;
},
_initVerifyEvent : function( event, originalEvent ) {
var text = originalEvent.getTarget();
if( text.classname === "rwt.widgets.Text" ) {
var keyCode = this._getLastKeyCode();
var newValue = text.getComputedValue();
var oldValue = text.getValue();
var oldSelection = text.getSelection();
var diff = this._getDiff( newValue, oldValue, oldSelection, keyCode );
if( diff[ 0 ].length === 1
&& diff[ 1 ] === diff[ 2 ]
&& diff[ 0 ] === originalEvent.getData()
) {
event.keyCode = keyCode;
event.character = diff[ 0 ];
}
event.text = diff[ 0 ];
event.start = diff[ 1 ];
event.end = diff[ 2 ];
}
},
_postProcessVerifyEvent : function( event, wrappedEvent, originalEvent ) {
var widget = originalEvent.getTarget();
if( wrappedEvent.doit !== false ) {
if( event.text !== wrappedEvent.text && event.text !== "" ) {
// insert replacement text
originalEvent.preventDefault();
var currentText = widget.getValue();
var textLeft = currentText.slice( 0, event.start );
var textRight = currentText.slice( event.end, currentText.length );
var carret = textLeft.length + wrappedEvent.text.length;
widget.setValue( textLeft + wrappedEvent.text + textRight );
widget.setSelection( [ carret, carret ] );
}
} else {
// undo any change
originalEvent.preventDefault();
widget._renderValue();
widget._renderSelection();
}
},
_postProcessKeyEvent : function( event, wrappedEvent, originalEvent ) {
if( wrappedEvent.doit === false ) {
originalEvent.preventDefault();
}
},
_setStateMask : function( event, originalEvent ) {
var SWT = org.eclipse.rap.clientscripting.SWT;
event.stateMask |= originalEvent.isShiftPressed() ? SWT.SHIFT : 0;
event.stateMask |= originalEvent.isCtrlPressed() ? SWT.CTRL : 0;
event.stateMask |= originalEvent.isAltPressed() ? SWT.ALT : 0;
event.stateMask |= originalEvent.isMetaPressed() ? SWT.COMMAND : 0;
},
_getLastKeyCode : function() {
// NOTE : While this is a private field, this mechanism must be integrated with
// KeyEventSupport anyway to support the doit flag better.
return rwt.remote.KeyEventSupport.getInstance()._currentKeyCode;
},
_getDiff : function( newValue, oldValue, oldSel, keyCode ) {
var start;
var end;
var text;
if( newValue.length >= oldValue.length || oldSel[ 0 ] !== oldSel[ 1 ] ) {
start = oldSel[ 0 ];
end = oldSel[ 1 ];
text = newValue.slice( start, newValue.length - ( oldValue.length - oldSel[ 1 ] ) );
} else {
text = "";
if( oldSel[ 0 ] === oldSel[ 1 ]
&& keyCode === 8 // backspace
&& ( oldValue.length - 1 ) === newValue.length
) {
start = oldSel[ 0 ] - 1;
end = oldSel[ 0 ];
} else {
start = oldSel[ 0 ];
end = start + oldValue.length - newValue.length;
}
}
return [ text, start, end ];
}
};
}());