How to trigger ValueChangeListener on the vaadin table? - listener

The problem is, I cannot find listeners having been added to the table.
It seems the method getListeners doesn't work properly. It returns an empty collection.
My code:
table.addValueChangeListener(new MyListener());
System.out.println("ListenerCount="+table.getListeners(ValueChangeListener.class).size());
Console output:
ListenerCount=0
What is wrong? I expected it would return 1.

AbstractComponent.getListeners takes the event type class as an argument.
Pass it a Property.ValueChangeEvent or one of it's implementations, a Field.ValueChangeEvent or Label.ValueChangeEvent, depending on your use case.

If you read the API very carefully you'll see that you need to provide the event type of your listener:
java.util.Collection<?> getListeners(java.lang.Class<?> eventType)
Returns all listeners that are registered for the given event type
or one of its subclasses.
In your case:
table.getListeners(ValueChangeEvent.class);

Related

How to pass object, MouseEvent.CLICK and function to trigger

I want to pass to function object, const of type MouseEvent.CLICK and function to trigger. In my case:
my class Assistant:
public static function addEventListenerTo(obj:Object, MouseEventConst:String, functinToTrigger:Function) {
obj.addEventListener(MouseEventConst, functinToTrigger:Function);
}
and my class Engine which invokes
Assistant.addEventListenerTo(deck,"MouseEvent.CLICK",showObject);
Please give me advice how to make it work. Thanks.
In the code you provide there is one compiler error (the one Tahir Ahmed pointed to in his second comment).
Fixing this by removing the second :Function in the first code block:
public static function addEventListenerTo
(obj:Object, MouseEventConst:String, functinToTrigger:Function)
{
obj.addEventListener(MouseEventConst, functinToTrigger);
}
will let the code compile. (I wrapped the Method signature to avoid the scrollbar, this is not required to make it compile.)
The other major problem is a configuration error (or maybe a typo): the one about MouseEvent.CLICK. (the one Tahir Ahmed pointed to in his first comment)
Looking at the documentation it is defined to have the value "click" (a String literal following the AS3 convention of the lowercase constant name). So to pass it to your method you can either put in a reference to the constant by writing MouseEvent.CLICK (without the "s around it) or reach the same goal with passing its value by writing "click".
As using the reference will prevent mistyping because the compiler checks it, the first approach should be preferred.
So calling the Method should look like this:
Assistant.addEventListenerTo(deck, MouseEvent.CLICK, showObject);
If you want to know why your version didn't work you should read a simple introduction to AS3 Events and EventDispatchers. As a short hint: if deck would dispatch an Event that has its type property set to "MouseEvent.CLICK" your listener would get fired.
While you are at it, you could improve the quality of your code by to major things:
the first one is about avoiding getting runtime Errors and prefering compile time errors: Not every instance of type Object has a method called addEventListener. In your current code, when you pass an instance to Assistant.addEventListenerTo as first parameter, that doesn't have this method (e.g. {} or an instance of type Array), the error will get thrown while your swf is displayed and it might stop displaying anything and might show an error message to the user.
If the type of the parameter is IEventDispatcher instead, the compiler will already tell you that you passed an incompatible instance.
The second one is about names and conventions, which helps other developers to read your code (an having more fun helping you).
what you called MouseEventConst is called an event type in AS3, which provides a better name for a parameter, as it being a String nobody stops anybody from passing contants of other event types like Event
the functionToTrigger is what is called a listener (or event listener)
the first letter of parameter names should be lower case
So if I would have written the static method it would look like this:
import flash.events.*;
public class Assistent{
public static function addEventListenerTo
(dispatcher:IEventDispatcher, eventType:String, listener:Function)
{
dispatcher.addEventListener(eventType, listener);
}
}

In Scala, how can you check whether a specifc Component was clicked by pattern matching on the MouseEvent object?

This book seems to suggest every that an event is an instance of an event case class.
"For instance, pressing a button will create an event which is an instance of the following case class:
case class ButtonClicked(source: Button)"
1) Applyin this logic, does this mean that pressing the mouse will create an event which is an instance of the following case class?:
case class MousePressed(source: Component, point: java.awt.Point, modifiers: Modifiers, clicks: Int, triggersPopup: Boolean)(peer: java.awt.event.MouseEvent)
2) To do pattern matching on the object to detect whether a specific Component has been pressed by the mouse, is this code correct?:
listenTo(mouse.clicks)
reactions += {
case MousePressed(nameOfComponent,_,_,_,_) => //some code you want to execute in response to that component being pressed //
}
3) and am I also right in thinking that the other arguments can be checked as well, say for example
case MousePressed(nameOfComponent,point,modifier,3,true)
makes for a very specific pattern: a specific component at a specific point with a certain modifier, on its third click, and triggers pop up? (it's probably not very practical)
4) What does the Modifier argument do?
1) It will create an instance of scala.swing.event.MousePressed. As I said in the comment, it doesn't matter what constructor is used during initialization, it will be the same class with the same field. The only difference is that you have a pattern available that corresponds to the primary constructor, since it's a case class.
2) Yes, and no. Formally you're correct - specifically in this case you say:
"for this component",
"capture any MousePressed event, and give me access to the component field through nameOfComponent (I don't care about the rest)."
Practically your code won't work as you expect, since event handlers in Swing are registered per component, and it seems Scala Swing follows that pattern. That means unless you say explicitly, you will only get events from the components mouse module you've used listenTo on - and no other component, not even it's children.
So, if you would e.g. want to listen on the component itself and its direct children (not children of children), you would add:
contents.foreach(child => listenTo(child.mouse.clicks))
This is of course standard Scala code - I'll leave it to you to adapt it to your needs.
And finally for this point - usually it's best to define a pattern match for specific events for specific components, instead of a "general" handler - the latter solution is useful only in a minority of cases, like making custom components.
3) Correct, here you say "I want to match MousePressed, give me access to the component, point and modifier fields through variables nameOfComponent,point, and modifier, and I want the matched event to have clicks == 3 and triggersPopup == true". The last two are called constant patterns.
4) This is really a separate question, but I'll bite, this time. They're the same thing as in Java's Swing - it's a special field for storing flags related to the event. They're even the same type as in Java - Modifiers is a type alias for Int. Basically, those are numbers which convey additional info about the event. For example, if you want to check whether this was a left click, you would use:
import java.awt.event.{InputEvent => AWTEvent} //so that we don't confuse it with the Scala class
...
case MousePressed(_,_,AWTEvent.BUTTON1_DOWN_MASK,_,_) => ...
You can use the following code to print a line telling you where the mouse clicked.
listenTo(mouse.clicks)
reactions += {
case e:MousePressed => println("press "+e.point)
}

How much information should one pass through events?

Say, I have a datagrid with checkboxes, and each time a checkbox is marked I store the object in the data property of flex ResultEvent
public class MyItemRenderer extends ItemRenderer{
public static var CLICK:String = "CheckBoxClick";
protected function itemRendererClickListener(data:Object):void{
dispatchEvent(new ResultEvent(MyItemRenderer.CLICK, data))
}
}
I handle the result here.
protected function checkbox_clicked(event:ResultEvent):void{
//Here I do everything I want with the data.
Alert.show(event.result.toString());
}
This is what I've been using for months, but I never wondererd if this was a bad practice.
Or let alone bad practice, what is the optimal way to do this?
it's not really 'bad'. But it does create an additional reference to an object that can potentially keep that object in memory longer (or indefinitely if not managed well).
Generally speaking, you should only store data related to the event itself in the event instance. You can use the event.target and event.currentTarget properties to reference back to the object that dispatched the event and get data that way.
In your case, your event is a check box state change. The event itself (being checked) doesn't need any data associated with it besides the item being checked (which you can get with 'target' or 'currentTarget'). So it would be more appropriate in my opinion to do the following:
Alert.show(MyItemRenderer(event.currentTarget).data.toString());
This keeps your events more reusable
Best practice for Events with data is to use a custom event (see http://cookbooks.adobe.com/post_AS3__Creating_and_dispatching_Custom_Events-17609.html) for explanation
btw, another 'best practice' is to avoid the generic Object class in your code - instead, create a value object class

How to add one listener for all events?

EventDispatcher.addEventListener() expects first parameter for event type (parameter of String type).
But the current object can generate multiple types of events.
Is it possible to handle all of them in one handler? May be I can pass null for type parameter or something?
You should try to make way around and extend dispatchEvent function :
public override function dispatchEvent(evt:Event):Boolean {
trace(evt.type);
return super.dispatchEvent(evt);
}
You can put Your code here to handle all events dispatched in this object .
Yes, this is possible.
If you use getQualifiedClassName of the Event class, you could get the types using describeType. Then you know all types that could be added, assuming you are using a custom event with public static types as strings in same event class. Then you could loop through all types, and add listeners with all those types to the dispatcher.
This idea is included in the templelibrary (EventUtils.addAll), which I suggest to use.
See documentation: http://templelibrary.googlecode.com/svn/trunk/doc/temple/utils/types/EventUtils.html

Comparing MouseEvent

I have more than one Event Listener that calls a specific function, and I want to add if statements to check what event is being passed. How can I do that?
I tried a simple comparison like:
if(evt == MouseEvent.MOUSE_OVER)
But it will give an error because I comparing a MouseEvent object and a String.
You should use the type property of the event:
if(evt.type == MouseEvent.MOUSE_OVER)