Custom event listeners

120 views
Skip to first unread message

Omar Wagih

unread,
Sep 11, 2012, 12:40:43 AM9/11/12
to cytoscap...@googlegroups.com
From the 3.0 cookbook, its states that if you want to create a custom event listener you do the following:

// Define a class, which implements a listener interface
public class MyListenerClass implements NetworkAddedListener {
....
 public void handleEvent(NetworkAddedEvent e){
 // do something here
 }
}
and
// Register the listener in the CyActivator class
registerService(bc,myListenerClass, NetworkAddedListener.class, new Properties());
 
However, I have a custom object I would like to update when a network is added. How do I do that if my listener class has to be instantiated inside my CyActivator class..?
In other words, is there a way to register a listener class outside the CyActivator class?

Thanks,
Omar 

Jason Montojo

unread,
Sep 11, 2012, 10:24:43 AM9/11/12
to cytoscap...@googlegroups.com
Hi Omar,

You can (un)register OSGi services dynamically using a CyServiceRegistrar.  It's available as an OSGi service so you can fetch it in CyActivator.  Just hold on to a reference so you can use it later.

Hope this helps,
Jason

--
You received this message because you are subscribed to the Google Groups "cytoscape-discuss" group.
To view this discussion on the web visit https://groups.google.com/d/msg/cytoscape-discuss/-/GktsG6btVRAJ.
To post to this group, send email to cytoscap...@googlegroups.com.
To unsubscribe from this group, send email to cytoscape-disc...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/cytoscape-discuss?hl=en.

Scooter Morris

unread,
Sep 11, 2012, 10:57:36 AM9/11/12
to cytoscap...@googlegroups.com, Jason Montojo
Hi Omar,
    The other question is why don't you hand your custom object to the listener in CyActivator?

MyClass myObject = new MyClass();
MyListenerClass listener = new MyListenerClass(myObject);
registerService(bc, listener, NetworkAddedListener.class, new Properties());

That way, all of your services are in the CyActivator, which makes them easier to find, and you can still pass around your status object.  In your listener class, you could call methods to update your object.  Another option is just to have MyClass implement NetworkAddedListener and advertise that service...

Of course, you can, as Jason suggested also pass the CyServiceRegistrar object down and register your services from there, but I don't really see how that helps.  You still need to instantiate your object and the CyActivator is the easiest place to do that...

-- scooter
Message has been deleted

Omar Wagih

unread,
Sep 12, 2012, 1:26:03 AM9/12/12
to cytoscap...@googlegroups.com, Jason Montojo
There are too many custom objects and I would rather not move things around.
In future apps, I will know to have a reference for everything in CyActivator Thanks!

Now, I used CyServiceRegistrar to register my listener (which implements several listeners) like this:

//Create listener object
 NetworkViewListeners networkViewListeners = new NetworkViewListeners();
        
        //Register them
        CyActivator.serviceRegistrar.registerService(networkViewListeners, 
                NetworkViewAddedListener.class, new Properties());
        CyActivator.serviceRegistrar.registerService(networkViewListeners, 
                NetworkViewAboutToBeDestroyedListener.class, new Properties());
        CyActivator.serviceRegistrar.registerService(networkViewListeners, 
                RowsSetListener.class, new Properties());

However, when for example a view is created, the handleEvent method for the NetworkViewAddedListener is called more than once
I am positive I am adding the network view only once..

Is there something I am missing?

Omar

Jason Montojo

unread,
Sep 12, 2012, 11:09:46 AM9/12/12
to Omar Wagih, cytoscap...@googlegroups.com
Hi Omar,

I tried Jason's suggestion

1) Set CyServiceRegistrar reference in CyActivator class

//Service regisrar

 public static CyServiceRegistrar serviceRegistrar; 

Non-final public static variables are almost always a terrible idea.  They invite weird code coupling and negatively impact modularity.  To clarify what I suggested, I meant you should get a service reference in CyActivator and pass that reference either via the constructor or some other method call to the class that needs it.  In this case, passing via constructor is probably the most elegant approach.  For example:

CyServiceRegistrar registrar = getService(bc, CyServiceRegistrar.class);
MyListener listener = new MyListener(registrar);

Hopes this helps,
Jason

Jason Montojo

unread,
Sep 12, 2012, 11:14:04 AM9/12/12
to Omar Wagih, cytoscap...@googlegroups.com
Hi Omar,

However, when for example a view is created, the handleEvent method for the NetworkViewAddedListener is called more than once
I am positive I am adding the network view only once..

Is there something I am missing?

Are you sure handleEvent is being called multiple times for the exact same network view?  Cytoscape creates multiple network views when the first view is created.  One of them is the main network view that shows up in your workspace.  The other is the birds eye view (which is the little network overview in the Network tab).  Apart from that, Cytoscape creates a network view to display the visual style preview in the VizMapper tab.  It's possible your listener is being called for those network views too.  Can you verify whether this is the case in the debugger?

Thanks,
Jason

Omar Wagih

unread,
Sep 14, 2012, 9:50:23 PM9/14/12
to cytoscap...@googlegroups.com, Omar Wagih
Hello!
Sorry for the late response!

Everything magically worked when I passed in CyServicerRegistrar as an argument to my constructors rather than using a static non-final!
@scooter the main reason I am using CyServicerRegistrar is that I have too many managers/factories which I would have to pass through my constructors at least twice or 3 times so it gets messy

Thanks guys!
Reply all
Reply to author
Forward
0 new messages