Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » Remote Application Platform (RAP) » Adding a MouseMove Listener to a Remote Object-based Custom Widget
Adding a MouseMove Listener to a Remote Object-based Custom Widget [message #1085395] Mon, 12 August 2013 17:49 Go to next message
Mark Leone is currently offline Mark Leone
Messages: 67
Registered: April 2012
Member
I'm porting an app from RAP 1.5 to 2.1, which had a custom widget dating back to RAP 1.3 days, using an LCA for client-server communication. The custom widget has mouseover and mouseout listeners that call respective methods on the server side widget when the mouse enters or leaves the widget. This communication was handled with an LCA in the RAP 1.5 version, and now I want to use the RemoteObject API.

I don't think ClientScripting can be used to implement this in RAP 2.1, since it doesn't support communication from client to server. So I'm trying to implement a Remote Object-based custom widget. I seem to be instantiating the widget on the client side, but I can't get the mouse events to fire.

Here's the client-side code:

(function() {
rap.registerTypeHandler( "my.package.TrackableLabel", {
  			factory : function( properties ) {
    			return new my.package.TrackableLabel();
 	 		},
 			properties : [ "mouseExit", "mouseEnter" ]
} );

rwt.qx.Class.define("my.package.TrackableLabel", {
	extend: rwt.widgets.base.Parent,

	construct: function() {
		this.base(arguments);
		console.log("construct");
		this.addEventListener("mousemove", this._onMouseMove, this);
		this.addEventListener("mouseout", this._onMouseOut, this);
	},
	
	destruct : function() {
    	this.removeEventListener( "mousemove", this._onMouseMove, this );
    	this.removeEventListener( "mouseout", this._onMouseOut, this );
  	},

	members: {
		_onMouseMove : function(e) {
			console.log('mouse move');
			var remoteObject = rap.getRemoteObject( this );
			remoteObject.set( "mouseEnter", "mouse enter" );
			remoteObject.notify( "Modify" );
		},

		_onMouseOut : function(e) {
			console.log('mouse out');
			var remoteObject = rap.getRemoteObject( this );
			remoteObject.set( "mouseExit", "mouse exit" );
			remoteObject.notify( "Modify" );
		},
	}
});
}());


And here's what I'm doing on the server side in the Java constructor of the widget

Connection connection = RWT.getUISession().getConnection();
RemoteObject remoteObject = connection.createRemoteObject( "my.domain.TrackableLabel" );
remoteObject.setHandler( new AbstractOperationHandler() {

public void handleNotify(String event, JsonObject properties) {
			
	System.err.println("JSON Object: " + properties.asString());
};


I see a console entry indicating that the JS widget constructor was called. But I don't see any console output indicating that the mouse listener functions were called. So it's not a problem with communication from the client widget to the remote object on the server. The listeners are never firing on the client side.

Maybe the problem is that the client side widget I create is not the one that the user is interacting with. I'm not really sure I understand how to associate the JS widget on the client side with the Java widget on the server.


[Updated on: Tue, 13 August 2013 11:15]

Report message to a moderator

Re: Adding a MoueMove Listener to a Remote Object-based Custom Widget [message #1085646 is a reply to message #1085395] Tue, 13 August 2013 03:09 Go to previous messageGo to next message
Ivan Furnadjiev is currently offline Ivan Furnadjiev
Messages: 1691
Registered: July 2009
Senior Member
Hi Mark,
the client-to-server "notify" operation is a pair with server-to-client
"listen" operation. If there is no listener attached on the server-side,
there is no sense to send a notify as nobody is listening for such
notify. In order to make it works you need
on server:
....
remoteObject.listen( "Modify", true );
....
on client:
....
listeners : [ "Modify" ],
listenerHandler : {
"Modify" : function( widget, value ) {
// execute a code when listeners is added/removed or simply set a
boolean flag _hasModifyListener
}
}
....
Or... you could use "call" instead of "notify" to trigger a request
without any additional code:
....
remoteObject.call( "Modify" );
....
On the server-side you must handle the "call" operation instead of "notify".
HTH,
Ivan

On 8/13/2013 12:49 AM, Mark Leone wrote:
> I'm porting an app from RAP 1.5 to 2.1, which had a custom widget
> dating back to RAP 1.3 days, using an LCA for client-server
> communication. The custom widget has mouseover and mouseout listeners
> that call respective methods on the server side widget when the mouse
> enters or leaves the widget. This communication was handled with an
> LCA in the RAP 1.5 version, and now I want to use the RemoteObject API.
>
> I don't think ClientScripting can be used to implement this in RAP
> 2.1, since it doesn't support communication from client to server. So
> I'm trying to implement a Remote Object-based custom widget. I seem to
> be instantiating the widget on the client side, but I can't get the
> mouse events to fire.
>
> Here's the client-side code:
>
> (function() {
> rap.registerTypeHandler( "my.package.TrackableLabel", {
> factory : function( properties ) {
> return new my.package.TrackableLabel();
> },
> properties : [ "mouseExit", "mouseEnter" ]
> } );
>
> rwt.qx.Class.define("my.package.TrackableLabel", {
> extend: rwt.widgets.base.Parent,
>
> construct: function() {
> this.base(arguments);
> console.log("construct");
> this.addEventListener("mousemove", this._onMouseMove, this);
> this.addEventListener("mouseout", this._onMouseOut, this);
> },
>
> destruct : function() {
> this.removeEventListener( "mousemove", this._onMouseMove, this );
> this.removeEventListener( "mouseout", this._onMouseOut, this );
> },
>
> members: {
> _onMouseMove : function(e) {
> console.log('mouse move');
> var remoteObject = rap.getRemoteObject( this );
> remoteObject.set( "mouseEnter", "mouse enter" );
> remoteObject.notify( "Modify" );
> },
>
> _onMouseOut : function(e) {
> console.log('mouse out');
> var remoteObject = rap.getRemoteObject( this );
> remoteObject.set( "mouseExit", "mouse exit" );
> remoteObject.notify( "Modify" );
> },
> }
> });
> }());
>
> And here's what I'm doing on the server side in the Java constructor
> of the widget
>
> Connection connection = RWT.getUISession().getConnection();
> RemoteObject remoteObject = connection.createRemoteObject(
> "my.domain.TrackableLabel" );
> remoteObject.setHandler( new AbstractOperationHandler() {
>
> public void handleNotify(String event, JsonObject properties) {
>
> System.err.println("JSON Object: " + properties.asString());
> };
>
> I see a console entry indicating that the JS widget constructor was
> called. But I don't see any console output indicating that the mouse
> listener functions were called. So it's not a problem with
> communication from the client widget to the remote object on the
> server. The listeners are never firing on the client side.
>
> Maybe the problem is that the client side widget I create is not the
> one that the user is interacting with. I'm not really sure I
> understand how to associate the JS widget on the client side with the
> Java widget on the server.
>
>
>

--
Ivan Furnadjiev

Twitter: @EclipseRAP
Blog: http://eclipsesource.com/blogs/

Professional services for RAP and RCP?
http://eclipsesource.com/services/rap/
Re: Adding a MoueMove Listener to a Remote Object-based Custom Widget [message #1085955 is a reply to message #1085646] Tue, 13 August 2013 11:38 Go to previous messageGo to next message
Mark Leone is currently offline Mark Leone
Messages: 67
Registered: April 2012
Member
Ivan,

Thanks for your response. I added the code you suggested, and I verified with console logging that the "Modify" listener handler you had me add is being invoked. But I still have the underlying problem, which seems to be antecedent to any client to server communication, that the client is not detecting any mouse movements. I added a mousemove and mouseout listner, but they never fire on the client. That is, I never even get the console log output indicating that the client has detected a mousemove or mouseout event.

Either I'm adding the listeners improperly, or the Javascript widget I've created is not what the user is interacting with. The Javascript widget is created by calling createRemoteObject() on the Connection, as I show in my code above. But does that mean it is creating a widget that is paired with the Java widget I created? I don't see how, since I didn't tell it to make any such association. Maybe I need to get the ID of the RemoteObject on the server side, and then use that with a call to rap.getObject() on the client side to get a proper reference to the client widget? Currently I create the client js file statically, but maybe I need to create it dynamically after getting the ID of the client remote object as created by the server?
Re: Adding a MoueMove Listener to a Remote Object-based Custom Widget [message #1085970 is a reply to message #1085955] Tue, 13 August 2013 12:07 Go to previous messageGo to next message
Ivan Furnadjiev is currently offline Ivan Furnadjiev
Messages: 1691
Registered: July 2009
Senior Member
Hi Mark,
did you set any bounds (top, left, width,heigth) to your widget? If you
didn't set the bounds, your widget is not visible (does not have any
space on the screen) and you can't hover it or move the mouse over it.
Best,
Ivan


On 8/13/2013 6:38 PM, Mark Leone wrote:
> Ivan,
>
> Thanks for your response. I added the code you suggested, and I
> verified with console logging that the "Modify" listener handler you
> had me add is being invoked. But I still have the underlying problem,
> which seems to be antecedent to any client to server communication,
> that the client is not detecting any mouse movements. I added a
> mousemove and mouseout listner, but they never fire on the client.
> That is, I never even get the console log output indicating that the
> client has detected a mousemove or mouseout event.
>
> Either I'm adding the listeners improperly, or the Javascript widget
> I've created is not what the user is interacting with. The Javascript
> widget is created by calling createRemoteObject() on the Connection,
> as I show in my code above. But does that mean it is creating a widget
> that is paired with the Java widget I created? I don't see how, since
> I didn't tell it to make any such association. Maybe I need to get the
> ID of the RemoteObject on the server side, and then use that with a
> call to rap.getObject() on the client side to get a proper reference
> to the client widget? Currently I create the client js file
> statically, but maybe I need to create it dynamically after getting
> the ID of the client remote object as created by the server?

--
Ivan Furnadjiev

Twitter: @EclipseRAP
Blog: http://eclipsesource.com/blogs/

Professional services for RAP and RCP?
http://eclipsesource.com/services/rap/
Re: Adding a MoueMove Listener to a Remote Object-based Custom Widget [message #1085978 is a reply to message #1085955] Tue, 13 August 2013 12:17 Go to previous messageGo to next message
Ivan Furnadjiev is currently offline Ivan Furnadjiev
Messages: 1691
Registered: July 2009
Senior Member
.... together with the bounds you have to set the parent of your widget.

On 8/13/2013 6:38 PM, Mark Leone wrote:
> Ivan,
>
> Thanks for your response. I added the code you suggested, and I
> verified with console logging that the "Modify" listener handler you
> had me add is being invoked. But I still have the underlying problem,
> which seems to be antecedent to any client to server communication,
> that the client is not detecting any mouse movements. I added a
> mousemove and mouseout listner, but they never fire on the client.
> That is, I never even get the console log output indicating that the
> client has detected a mousemove or mouseout event.
>
> Either I'm adding the listeners improperly, or the Javascript widget
> I've created is not what the user is interacting with. The Javascript
> widget is created by calling createRemoteObject() on the Connection,
> as I show in my code above. But does that mean it is creating a widget
> that is paired with the Java widget I created? I don't see how, since
> I didn't tell it to make any such association. Maybe I need to get the
> ID of the RemoteObject on the server side, and then use that with a
> call to rap.getObject() on the client side to get a proper reference
> to the client widget? Currently I create the client js file
> statically, but maybe I need to create it dynamically after getting
> the ID of the client remote object as created by the server?

--
Ivan Furnadjiev

Twitter: @EclipseRAP
Blog: http://eclipsesource.com/blogs/

Professional services for RAP and RCP?
http://eclipsesource.com/services/rap/
Re: Adding a MoueMove Listener to a Remote Object-based Custom Widget [message #1085994 is a reply to message #1085978] Tue, 13 August 2013 12:46 Go to previous messageGo to next message
Mark Leone is currently offline Mark Leone
Messages: 67
Registered: April 2012
Member
Ivan, I see the widget being displayed. So I just need to get a reference to it in javascript. For setting the parent, I have this in the server side code:

remoteObject.set( "parent", WidgetUtil.getId( this ) );


where "this" is the parent of the SWT widget for which I want to get the client counterpart.

I expect the javascript widget to be an RWT composite, but apparently it is not, since it has no method addListener, which I see in the RAP javascript API. It does, however, have a method addEventListener. Have I specified the base class properly (rwt.widgets.base.Parent)?
Re: Adding a MoueMove Listener to a Remote Object-based Custom Widget [message #1086040 is a reply to message #1085994] Tue, 13 August 2013 14:22 Go to previous messageGo to next message
Mark Leone is currently offline Mark Leone
Messages: 67
Registered: April 2012
Member
I tried creating javascript dynamically to get a reference to the client widget and set listeners on it, and that is not going well either. Here's my code:

Connection connection = RWT.getUISession().getConnection();
RemoteObject remoteObject = connection.createRemoteObject( "my.package.TrackableLabel" );
remoteObject.listen("Modify", true);
String remoteId = remoteObject.getId();
configureClientWidget(remoteId);


private void configureClientWidget(String remoteId) {
        JavaScriptExecutor executor = RWT.getClient().getService( JavaScriptExecutor.class );
	executor.execute(
			"var widget = rap.getObject('" + remoteId +"');" +
			"widget._onMouseMove = function(e){ console.log('mouse move detected');};" +
			"widget._onMouseOut = function(e){ console.log('mouse out detected');};" +
			"widget.addEventListener('mousemove', this._onMouseMove);" +
			"widget.addEventListener('mouseout', this._onMouseOut);" +
			"console.log('added mouse listeners');"
	 );
	}


I get the following error when this executes:

Error: Error: Operation "call" on target "rwt.client.JavaScriptExecutor" of type "[object Object]" failed:
Cannot read property '_hashCode' of undefined
Properties: 
content = var widget = rap.getObject('r80');widget._onMouseMove = function(){ console.log('mouse move detected');};widget._onMouseOut = function(){ console.log('mouse out detected');};widget.addEventListener('mousemove', this._onMouseMove);widget.addEventListener('mouseout', this._onMouseOut);console.log('added mouse listeners');


At this point I think I'm thrashing.

It seems I'm trying to do something basic, and I just haven't found a relevant example in all my searching. I just want to get a reference in javascript to the remote object corresponding to the widget created on the server side, and add mousemove and mouseout listeners to that javascript object. Does anyone know of an example that shows how to do this?

Re: Adding a MoueMove Listener to a Remote Object-based Custom Widget [message #1086461 is a reply to message #1085994] Wed, 14 August 2013 04:29 Go to previous messageGo to next message
Tim Buschtoens is currently offline Tim Buschtoens
Messages: 355
Registered: July 2009
Senior Member
Hi.

(I'm going to ignore that post using JavaScriptExecutor, thats
definitely the wrong direction.)

Am 13.08.2013 18:46, schrieb Mark Leone:
> Ivan, I see the widget being displayed. So I just need to get a

That's strange, according to your typeHandler the widget can not be
added to the parent.

(function() {
rap.registerTypeHandler( "my.package.TrackableLabel", {
factory : function( properties ) {
return new my.package.TrackableLabel();
},
properties : [ "mouseExit", "mouseEnter" ]
} );

You would have to implement something like this in the factory:

var result = new my.package.TrackableLabel();
rwt.remote.HandlerUtil.setParent( result, properties.parent );
return result;

> I expect the javascript widget to be an RWT composite, but apparently it
> is not, since it has no method addListener, which I see in the RAP
> javascript API. It does, however, have a method addEventListener. Have I
> specified the base class properly (rwt.widgets.base.Parent)?

Okay, you seem to confuse concepts of internal and public API (which is
totally not your fault, I admit it can be confusing if you are used to
1.x API, which was basically all internal).

- Everything that starts with "rwt." is internal API.
- Everything that starts with "rap." is public API.
- The (public) type "Composite" is a wrapper around the internal
rwt.widgets.Composite. It can *only* be used to add HTML elements (not
Widgets) and resize listener. It it can be obtained using rap.getObject(
"idOfAComposite" ).
- The "real" (INTERNAL!!) widget you can get from
rwt.remote.ObjectRegistry.getObject or
rwt.remote.HandlerUtil.callWithTarget/setParent.

Perhaps this helps?

By the way, you CAN use ClientScripting with a RemoteObject to
communicate with the server, though it's a bit of a strange mix and we
have never recommended or described it anywhere. If you only want to add
mousemove event handling to a label it might be the easier way to go. I
can give you details if you want.

Greetings,
Tim

--
Tim Buschtöns

Twitter: @EclipseRAP
Blog: http://eclipsesource.com/blogs/

Professional services for RAP and RCP?
http://eclipsesource.com/services/rap/
Re: Adding a MoueMove Listener to a Remote Object-based Custom Widget [message #1086697 is a reply to message #1086461] Wed, 14 August 2013 11:26 Go to previous messageGo to next message
Mark Leone is currently offline Mark Leone
Messages: 67
Registered: April 2012
Member
Thanks for your reply, Tim. I had already commented out the JavaScriptExecutor code, and now I've deleted it.

I tried to set the parent on the Javascript widget as you showed me, but the 'properties' argument is undefined when the factory function is called. I suspect there is something wrong with my Javascript constructor, or perhaps in the creation of the remote object.

Edit: Above paragraph is no longer true. I think that what fixed it was changing
remoteObject.set( "parent", WidgetUtil.getId( this.label ) );
to
remoteObject.set( "parent", WidgetUtil.getId( this ) )
; (which sets the parent of the Java widget instead of the Java widget itself)

However, I'm still wehre I was before. The mouse listeners are not firing on the client, but the widget is visible.

I understand your explanation on the difference between the internal widget class and the external wrapper, and that answers my question about the method for adding a listener. But what class should I extend in my widget definition? I tried rwt.widgets.base.Parent and rwt.widgets.base.Widget. My code is pasted below.

And yes, I'm interested in learning how to set a property value from client to server with ClientScripting. I'd like to make the remote object approach work as well, since I need to learn how to do it. But ClientScripting does sound like a better approach for this part of my app, since I just need to set a property for mouse enter and exit events.

Client Code:

(function() {
rwt.qx.Class.define("my.package.TrackableLabel", {
	extend: rwt.widgets.base.Parent,

	construct: function() {
		this.base(arguments);
		console.log("construct");
		this.addEventListener("mousemove", this._onMouseMove, this);
		this.addEventListener("mouseout", this._onMouseOut, this);
	},
	
	destruct : function() {
    	this.removeEventListener( "mousemove", this._onMouseMove, this );
    	this.removeEventListener( "mouseout", this._onMouseOut, this );
  	},

	members: {
		_onMouseMove : function(e) {
			console.log('mouse move');
			var remoteObject = rap.getRemoteObject( this );
			remoteObject.set( "mouseEnter", "mouse enter" );
			remoteObject.notify( "Modify" );
		},

		_onMouseOut : function(e) {
			console.log('mouse out');
			var remoteObject = rap.getRemoteObject( this );
			remoteObject.set( "mouseExit", "mouse exit" );
			remoteObject.notify( "Modify" );
		}
	}
});

rap.registerTypeHandler( "my.package.TrackableLabel", {
  			factory : function( properties ) {
    			var result = new my.package.TrackableLabel();
    			rwt.remote.HandlerUtil.setParent( result, properties.parent );
    			return result;
 	 		},
 			properties : [ "mouseExit", "mouseEnter" ],
 			listeners : ["Modify"],
 			listenerHandler : {
 				"Modify" : function(widget, value) {
 					console.log("listener added");
 				}
 			}
} );

}());




Server code:

Connection connection = RWT.getUISession().getConnection();
RemoteObject remoteObject = connection.createRemoteObject( "my.package.TrackableLabel" );
remoteObject.set( "parent", WidgetUtil.getId( this.label ) );
remoteObject.listen("Modify", true);
remoteObject.setHandler( new AbstractOperationHandler() {

     public void handleNotify(String event, JsonObject properties) {

          System.err.println("JSON Object: " + properties.asString());
     };
} );

[Updated on: Wed, 14 August 2013 11:31]

Report message to a moderator

Re: Adding a MoueMove Listener to a Remote Object-based Custom Widget [message #1086712 is a reply to message #1086697] Wed, 14 August 2013 11:53 Go to previous messageGo to next message
Mark Leone is currently offline Mark Leone
Messages: 67
Registered: April 2012
Member
Ivan mentioned previously that I need to set bounds on the widget. Where and how should I do that?

I tried this in the server-side code

remoteObject.set( "bounds","{0,0," + this.label.getSize().x + "," + this.label.getSize().y + "}" );


But the mouse listeners are still not firing.

[Updated on: Wed, 14 August 2013 12:17]

Report message to a moderator

Re: Adding a MoueMove Listener to a Remote Object-based Custom Widget [message #1087152 is a reply to message #1086712] Thu, 15 August 2013 03:50 Go to previous messageGo to next message
Ivan Furnadjiev is currently offline Ivan Furnadjiev
Messages: 1691
Registered: July 2009
Senior Member
Hi Mark,
server-side code:
....
remoteObject.set("bounds", new
JsonArray().add(left).add(top).add(width).add(height));
....
client-side code:
rap.registerTypeHandler( "my.package.TrackableLabel", {
....
properties : [ "bounds", "mouseExit", "mouseEnter" ],
propertyHandler : {
"bounds" : function( widget, value ) {
widget.setLeft( value[ 0 ] );
widget.setTop( value[ 1 ] );
widget.setWidth( value[ 2 ] );
widget.setHeight( value[ 3 ] );
}
}
....
HTH,
Ivan

On 8/14/2013 6:53 PM, Mark Leone wrote:
> Ivan mentioned previously that I need to set bounds on the widget.
> Where and how should I do that?
>
> The widget is defined in the Java code, and I think that's the widget
> I'm seeing on the display, without the mouse listeners added. I don't
> understand how, just by creating a remote object, the framework knows
> that the object I created is the client counterpart of this particular
> server-side widget, since there's nothing in the code that seems to
> specify that. So perhaps that's the step I'm missing. I'm trying to
> make javascript extensions on the client-side counterpart of the
> specific Java widget I'm concerned with, but it seems I'm just
> creating a custom widget and not telling the framework that it's the
> counterpart of this particular server-side widget.

--
Ivan Furnadjiev

Twitter: @EclipseRAP
Blog: http://eclipsesource.com/blogs/

Professional services for RAP and RCP?
http://eclipsesource.com/services/rap/
Re: Adding a MoueMove Listener to a Remote Object-based Custom Widget [message #1087170 is a reply to message #1086712] Thu, 15 August 2013 04:22 Go to previous messageGo to next message
Tim Buschtoens is currently offline Tim Buschtoens
Messages: 355
Registered: July 2009
Senior Member
Hi.

Am 14.08.2013 17:53, schrieb Mark Leone:

> The widget is defined in the Java code, and I think that's the widget
> I'm seeing on the display, without the mouse listeners added. I don't
> understand how, just by creating a remote object, the framework knows
> that the object I created is the client counterpart of this particular
> server-side widget, since there's nothing in the code that seems to
> specify that. So perhaps that's the step I'm missing. I'm trying to make

If you extend a Composite (you should not extend any other controls) in
Java the framework will still render it as such. With the new API, this
is what is wanted and the RemoteObject only controls the HTML that is
added to that Composite.

When mixing old way (extending an internal client widget) and new (using
remoteObject) like you do it gets a bit confusing. Either you add an
LCA that does nothing and render every single property yourself using
remoteObject, or the client widget you extend needs to be aware it's
parent is a Composite that it needs to fill completely by setting it's
bounds to 100% each.

I guess the morale of the story is, do not mix old and new custom widget
patterns unless your an absolute expert on RAP internals.

Greetings,
Tim




--
Tim Buschtöns

Twitter: @EclipseRAP
Blog: http://eclipsesource.com/blogs/

Professional services for RAP and RCP?
http://eclipsesource.com/services/rap/
Re: Adding a MoueMove Listener to a Remote Object-based Custom Widget [message #1087186 is a reply to message #1086697] Thu, 15 August 2013 04:50 Go to previous messageGo to next message
Tim Buschtoens is currently offline Tim Buschtoens
Messages: 355
Registered: July 2009
Senior Member
Am 14.08.2013 17:26, schrieb Mark Leone:
>
> I tried to set the parent on the Javascript widget as you showed me, but
> the 'properties' argument is undefined when the factory function is
> called. I suspect there is something wrong with my Javascript
> constructor, or perhaps in the creation of the remote object.

I don't think the properties argument can be undefined. Perhaps null, if
you do not set any properties, but not undefined.

> I understand your explanation on the difference between the internal
> widget class and the external wrapper, and that answers my question
> about the method for adding a listener. But what class should I extend
> in my widget definition? I tried rwt.widgets.base.Parent and
> rwt.widgets.base.Widget. My code is pasted below.

That completely depends on what you are trying to do. If you only add
HTML (and not other internal widgets) then Terminator would be the right
choice, otherwise Parent. But then again if you only add HTML you should
use only the new API. (You should do that anyway.)

>
> And yes, I'm interested in learning how to set a property value from
> client to server with ClientScripting. I'd like to make the remote
> object approach work as well, since I need to learn how to do it. But
> ClientScripting does sound like a better approach for this part of my
> app, since I just need to set a property for mouse enter and exit events.

Okay.

First, to prevent any further confusion (I think I should start a FAQ
for this stuff), ClientScripting is usually completely separated from
creating HTML/remoteObject-based custom widgets. It only adds some logic
to EXISTING widgets.

Usually the remoteObject is attached to a "real" object that renders
something, but it doesn't have to. You can write a nearly empty
typehandler that just returns {} in the factory, which allows you to
create a remoteObject of the type you registered. Now you can use that
RemoteObject to communicate.

This example code is theory (I havan't tried to run it), so it could
have typos and such:

Type Handler: (JS)

rap.registerTypeHandler( "my.dummyObject", {
factory : function( properties ) {
return {};
}
} );

Creating the RemoteObject: (Java)

Connection connection = RWT.getUISession().getConnection();
remoteObject = connection.createRemoteObject( "my.dummyObject" );
remoteObject.setHandler( ... ); // can handle notify, call, set...

Adding the RemoteObject id to the widget that you want to script: (Java)

WidgetDataWhiteList.addKey( "remoteObjectId" ); //do this only once
// in RAP 2.2 the above will be WidgetUtil.registerDataKeys
widget.setData( "remoteObjectId", remoteObject.getId() ); //since 2.1!
widget.addListener( SWT.XXX, new ClientListener( ... ) );

Getting the RemoteObject in the client Script: (JS)

function handleEvent( event ) {
var widget = event.widget;
// again, this is not the "real" widget, just a wrapper!
var remoteObjectId = widget.getData( "remoteObjectId" );
var dummyObj = rap.getObject( remoteObjectId );
var remoteObject = rap.getRemoteObject( dummyObj );
remoteObject.notify/set/call... etc
}

Remember that notify only works if the server-side renders a "listen"
for that event type, so use call or set if you don't want that limitation.

Also, this example works client->server, but you can easily make it work
the other way also.

Greetings,
Tim




--
Tim Buschtöns

Twitter: @EclipseRAP
Blog: http://eclipsesource.com/blogs/

Professional services for RAP and RCP?
http://eclipsesource.com/services/rap/
Re: Adding a MoueMove Listener to a Remote Object-based Custom Widget [message #1087226 is a reply to message #1087186] Thu, 15 August 2013 06:17 Go to previous messageGo to next message
Tim Buschtoens is currently offline Tim Buschtoens
Messages: 355
Registered: July 2009
Senior Member
> First, to prevent any further confusion (I think I should start a FAQ
> for this stuff),

I did just that: http://wiki.eclipse.org/RAP/Custom_Widgets_FAQ


--
Tim Buschtöns

Twitter: @EclipseRAP
Blog: http://eclipsesource.com/blogs/

Professional services for RAP and RCP?
http://eclipsesource.com/services/rap/
Re: Adding a MoueMove Listener to a Remote Object-based Custom Widget [message #1087469 is a reply to message #1087226] Thu, 15 August 2013 13:42 Go to previous messageGo to next message
Mark Leone is currently offline Mark Leone
Messages: 67
Registered: April 2012
Member
Thanks Ivan and Tim for such helpful responses. Tim, your FAQ entry is great to have. That's exactly the sort of big picture explanation I was looking for for the RAP 2.x approach.

I first applied Ivan's changes to the mixed approach I had already started, and that worked, including the property being set successfully from client to server via remote object when the mouse event occurred.

Then I applied Tim's instructions for removing the client code extending an internal widget and relying solely on the new API. That works to the point of the client detecting the mouse event, but for some reason the server does not respond when the client calls set on the remote object. In the javascript debugger I see that it is indeed an instance of rwt.remote.RemoteObject that I'm calling set on. But the notification is not received on the server. This part worked when I had the combined old-style/new API code, so I guess I'm missing that needs to be applied in the new API only. I compared my code with the CKEditor example, and I can't see anything missing.

Here's my code now. I think I have some extraneous things in there, added in my unsuccessful attempts to get the notifications working on the server.

Client:
rap.registerTypeHandler( "my.package.TrackableLabel", {
  			factory : function( properties ) {
    			var parent = rap.getObject( properties.parent );
   				var intWidget = rwt.remote.ObjectRegistry.getObject(properties.parent);
   				intWidget.addEventListener("mouseover", function(event) {
   					console.log('mouse enter');
   					var remoteObject = rap.getRemoteObject(intWidget);
   					remoteObject.set("mouseEnter", "mouse enter");
   				});
   				intWidget.addEventListener("mouseout", function(event) {
   					var remoteObject = rap.getRemoteObject(intWidget);
   					console.log('mouse exit');
   					remoteObject.set("mouseExit", "mouse exit");
   				});
    			return parent;
 	 		},
 			properties : [ "mouseExit", "mouseEnter" ],
 			listeners : ["Modify"],
 			listenerHandler : {
 				"Modify" : function(widget, value) {
 					console.log("listener added");
 				}
 			}
}


Server:
                RemoteObject remoteObject = connection.createRemoteObject( "my.package.TrackableLabel" );
		remoteObject.set( "parent", WidgetUtil.getId( this ) );
		remoteObject.listen("Modify", true);
		remoteObject.listen("Set", true);
		remoteObject.listen("Notify", true);
		remoteObject.listen("Call", true);
		remoteObject.setHandler( new AbstractOperationHandler() {

			public void handleNotify(String event, JsonObject properties) {
				System.err.println("Modify: " + properties);
			};
			
			public void handleCall(String method, JsonObject parameters) {};
			
			@Override
			public void handleSet(JsonObject properties) {
				System.err.println("Set moueEnter: " + properties.get("mouseEnter"));
				System.err.println("Set mouseExit: " + properties.get("mouseExit"));
			}
		} );
Re: Adding a MoueMove Listener to a Remote Object-based Custom Widget [message #1087553 is a reply to message #1087469] Thu, 15 August 2013 16:43 Go to previous messageGo to next message
Mark Leone is currently offline Mark Leone
Messages: 67
Registered: April 2012
Member
Found my problem. I was retrieving the remote object on the client using the internal widget as the key instead of the parent object.

rap.registerTypeHandler( "my.package.TrackableLabel", {
  			factory : function( properties ) {
    			var parent = rap.getObject( properties.parent );
   				var intWidget = rwt.remote.ObjectRegistry.getObject(properties.parent);
   				intWidget.addEventListener("mouseover", function(event) {
   					console.log('mouse enter');
   					var remoteObject = rap.getRemoteObject(parent); // <==== Incorrectly used intWidget here
   					remoteObject.set("mouseEnter", "mouse enter");
   					remoteObject.notify("Modify");
   				});
   				intWidget.addEventListener("mouseout", function(event) {
   					var remoteObject = rap.getRemoteObject(parent); // <==== Incorrectly used intWidget here
   					console.log('mouse exit');
   					remoteObject.set("mouseExit", "mouse exit");
   					remoteObject.notify("Modify");
   				});
    			return parent;
 	 		},
 			properties : [ "mouseExit", "mouseEnter" ],
 			listeners : ["Modify"],
 			listenerHandler : {
 				"Modify" : function(widget, value) {
 					console.log("listener added");
 				}
 			}
} );


Tim, thanks for the explanation of how to use the Remote Object API with RWT SCripting. I'll give that a try next.
Re: Adding a MoueMove Listener to a Remote Object-based Custom Widget [message #1087889 is a reply to message #1087553] Fri, 16 August 2013 04:28 Go to previous messageGo to next message
Tim Buschtoens is currently offline Tim Buschtoens
Messages: 355
Registered: July 2009
Senior Member
Hi.

Not to complain about success, but there still some strange... "things"
in your code:

> rap.registerTypeHandler( "my.package.TrackableLabel", {
> factory : function( properties ) {
> var parent = rap.getObject( properties.parent );
[...]
> var remoteObject = rap.getRemoteObject(parent);
// You are using the Composite wrapper as the client object that is
assigned to the remoteObject... that's technically possible, but
counter-intuitive, since the actual composite is internally registered
as a client object already.

> remoteObject.set("mouseEnter", "mouse enter");
// This also works more by accident than intention: remoteObject does
not check whether the property already has the value that is set here
before sending it, but it very well could. (I.e. you can semantically
only set a "mouseEnter" to "mosue enter" once.) This should be something
like
remoteObject.set("hover", true);
and down below:
remoteObject.set("hover", false);

> listeners : ["Modify"],
> listenerHandler : {
> "Modify" : function(widget, value) {
> console.log("listener added");
> }
> }

// These two fields are not API, and the way you use them makes no
sense. Use "events" as documented.


remoteObject.listen("Set", true);
remoteObject.listen("Notify", true);
remoteObject.listen("Call", true);
// You do not need to do that. "listen" is only used to tell the client
to send specific event types, not types of operations.

Greetings,
Tim


--
Tim Buschtöns

Twitter: @EclipseRAP
Blog: http://eclipsesource.com/blogs/

Professional services for RAP and RCP?
http://eclipsesource.com/services/rap/
Re: Adding a MoueMove Listener to a Remote Object-based Custom Widget [message #1088128 is a reply to message #1087889] Fri, 16 August 2013 12:20 Go to previous messageGo to next message
Mark Leone is currently offline Mark Leone
Messages: 67
Registered: April 2012
Member
Tim,

Thanks again. Wrong code that works is the worst kind of wrong code. So I'm glad for the additional comments.

However, to be honest, I really don't understand your comments. Could you tell me specifically what I need to change in my code to implement them?

1. For the remote object on the client, you seem to be saying I should use
var remoteObject = rap.getRemoteObject(intWidget);
instead of
var remoteObject = rap.getRemoteObject(parent);
, but I tried that and the listener on the remote object in the server code is never called.

2. You say
listeners : ["Modify"],
listenerHandler : {
 	"Modify" : function(widget, value) {
 		console.log("listener added");
 	}
}
is not API. Indeed, I only got it from Ivan (I guess he gave it to me since I was combining old and new APIs originally), but I can't make the code work without it. As I read the documentation, I'm supposed to set an operations handler on the remote object on the server, and then invoke set() and notify() on the client. That's all the CKEditor example does, and it's all I see in the documentation. But it doesn't work for me unless I insert the non-API code that Ivan game me.

3. I don't understand what I need to change about how I'm calling set() on the remote object on the client. Your example is the same as mine except you set a boolean value and I set a String value. But I think that's not what you;re getting at, so I don't understand what has to be changed.

Sorry to be so dense. I'm working hard to understand the documentation and examples, and I guess I'm just not getting it.
Re: Adding a MoueMove Listener to a Remote Object-based Custom Widget [message #1088136 is a reply to message #1088128] Fri, 16 August 2013 12:31 Go to previous messageGo to next message
Mark Leone is currently offline Mark Leone
Messages: 67
Registered: April 2012
Member
I figured out the answer to item 2.
I needed to replace the non-API code with

events : ["Modify"]


I see that in the API. but CKEditor doesn't have it in its type handler registration

[Updated on: Fri, 16 August 2013 12:32]

Report message to a moderator

Re: Adding a MoueMove Listener to a Remote Object-based Custom Widget [message #1089788 is a reply to message #1088128] Mon, 19 August 2013 04:44 Go to previous message
Tim Buschtoens is currently offline Tim Buschtoens
Messages: 355
Registered: July 2009
Senior Member
Hi.


>
> 1. For the remote object on the client, you seem to be saying I should
> use var remoteObject = rap.getRemoteObject(intWidget); instead of var
> remoteObject = rap.getRemoteObject(parent);, but I tried that and the
> listener on the remote object in the server code is never called.

It needs to be the object that the factory returns, which should
*neither* be the actual parent...

var intWidget = rwt.remote.ObjectRegistry.getObject(properties.parent);

*nor* the parent wrapper

var parent = rap.getObject( properties.parent );

but a new client side widget, which you are currently not creating.
It should be either something extending an qooxdoo widget and attached
to the actual parent, or (preferably) a wrapper around an HTMLElement
that is attached to the parent wrapper.

See also here:
http://wiki.eclipse.org/Image:CustomWidgetUML.png


>
> 3. I don't understand what I need to change about how I'm calling set()
> on the remote object on the client. Your example is the same as mine
> except you set a boolean value and I set a String value. But I think
> that's not what you;re getting at, so I don't understand what has to be
> changed.

* You have two properties (set two only one possible value) where only
one is needed. Either the mouse is in the widget or it isn't, which is a
state.
* Set operations represent states, not events, but "mouseEnter" and
"mouseExit" are, semantically, events.


--
Tim Buschtöns

Twitter: @EclipseRAP
Blog: http://eclipsesource.com/blogs/

Professional services for RAP and RCP?
http://eclipsesource.com/services/rap/
Previous Topic:Can't Revert from Rap 2.1 to RAP 1.5
Next Topic:chart tools for RAP
Goto Forum:
  


Current Time: Sun Apr 20 03:09:03 EDT 2014

Powered by FUDForum. Page generated in 0.07160 seconds