I am using yFiles library and I am handling a Graph2DView object named view. To activate mouseWheel scroll for this object, I have to add a listener in registerViewListeners function. However, I also want to be notified also in myClass mouseWheelMoved function when mouseweel
public class MyClass extends MyBaseClass implements MouseWheelListener {
Graph2DView view;
// .....
#Override
protected void registerViewListeners()
{
Graph2DViewMouseWheelScrollListener wheelListener = new Graph2DViewMouseWheelScrollListener();
wheelListener.addToCanvas(view);
// The two precedent instruction is equivalent to
// view.getCanvasComponent().addMouseWheelListener(this);
}
#Override
public void mouseWheelMoved(MouseWheelEvent e)
{
// some work ...
}
}
Problem:
If i register my view object through registerViewListeners
#Override
protected void registerViewListeners()
{
Graph2DViewMouseWheelScrollListener wheelListener = new Graph2DViewMouseWheelScrollListener();
wheelListener.addToCanvas(view);
}
My mouseWheelMoved function is no longer notified:
#Override
public void mouseWheelMoved(MouseWheelEvent e)
{
// not called
}
Your description sounds as if you have simply removed the registration for your event listener.
In the place where you instantiate MyClass, please also add:
view.getCanvasComponent().addMouseWheelListener(myClassInstance); // register listener
If you don't register your listener, it will not be called, of course. Only instantiating it will not suffice.
Related
I'm trying to add a custom user action to my media session so that it shows up on the android auto action card, but I can't seem to get it to work. I've looked around, but didn't find much on how to explicitly add a custom action. I've included all the relevant code that is a part of my implementation of the only custom action I am trying to implement.
I would like to know what is it I'm missing and/or is doing wrong. Thank you.
public class MyMediaBrowserService extends MediaBrowserServiceCompat{
//Variables Declared here ...
#Override
public void onCreate(){
mediaSession = new MediaSessionCompat(this, TAG);
mediaSessionCallback = new MyMediaSessionCallback();
mediaSession.setCallback(mediaSessionCallback);
// Enable callbacks from MediaButtons and TransportControls
mediaSession.setFlags(
MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS |
MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
MediaSessionCompat.Token token = mediaSession.getSessionToken();
setSessionToken(token);
mediaNotificationManager = new MediaNotificationManager(this);
// Set an initial PlaybackState with ACTION_PLAY, so media
buttons can start the player
mStateBuilder = new PlaybackStateCompat.Builder()
.setActions(
PlaybackStateCompat.ACTION_PLAY |
PlaybackStateCompat.ACTION_PAUSE |
PlaybackStateCompat.ACTION_SKIP_TO_NEXT |
PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS)
.addCustomAction(CUSTOM_ACTION_REPEAT, "Repeat Mode",
R.drawable.ic_repeat_none);
mediaSession.setPlaybackState(mStateBuilder.build());
mediaSession.setActive(true);
mediaPlayer = new DefaultMediaPlayer(this,
new DefaultMediaPlaybackListener());
}
...
public class MyMediaSessionCallback extends
MediaSessionCompat.Callback {
//Variables Declared here ...
// The following methods are actually implemented in the
// project, and functions as they are supposed to.
// They are mentioned here for the sake of showing their
// existence with relations to the PlaybackStateCompat set
// above.
#Override public void onAddQueueItem(MediaDescriptionCompat
description) { ... }
#Override public void onRemoveQueueItem(MediaDescriptionCompat
description) { ... }
#Override public void onPlayFromMediaId(String mediaId,
Bundle extras) { .... }
#Override public void onPlay() { ... }
#Override public void onPause() { ... }
#Override public void onStop() { ... }
#Override public void onSkipToNext() { ... }
#Override public void onSkipToPrevious() { ... }
#Override public void onSeekTo(long pos) { ... }
// This is the actual implement of the onCustomAction method
// I never got it working so I figured I'll start by logging it
// first before spending time coding it
#Override
public void onCustomAction(String action,
Bundle extras) {
if(action.equals(CUSTOM_ACTION_REPEAT))
Log.e(TAG, "Custom action is REPEAT");
}
...
}
}
In order to add a custom action and given a PlayBackStateCompat.Builder you can add a custom action as follows:
mStateBuilder.addCustomAction(
new PlaybackStateCompat.CustomAction.Builder(
CUSTOM_ACTION_REPLAY,
getString(R.string.custom_action_replay),
R.drawable.ic_replay).build()
);
Then you must add the code to handle the custom action as you already did.
The code above should work, and correctly display the actions on Android Auto, i use this to display the custom action. Hope this helps even if i am little late
I'm writing a simple solution for uploading files in GWT and recently encountered a tiny, but quite annoying problem. I'm using a standard GWT FileUpload widget inside a FormPanel. Everything works just fine (form is submitted and the file is being sent to the servlet) only if user clicks "physically" a button related to form, with an attached click handler (inside there is this form.submit() fired).
Unfortunately, I have to submit a form from the other place in a FormPanel's parent widget (another class). I tried to implement click simulation with this particular code and a button with Visible attribute set to "false":
public void buttonClick()
{
NativeEvent event = Document.get().createClickEvent(0, 0, 0, 0, 0, false, false, false, false);
DomEvent.fireNativeEvent(event, saveFileBtn);
}
saveFileBtn.addClickHandler(new ClickHandler()
{
#Override
public void onClick(ClickEvent event)
{
if(fileUpload.getFilename().isEmpty())
return;
else {
form.submit();
}
}
});
After calling the buttonClick() method the click event is fired, but the form doesn't submit (just nothing happens). Are there any differences between those two approaches to firing a click event?
If so, what would be the best alternative approach instead? I thought about making my own widget performing similar operations to the standard GWT FormPanel, but encode a file in a base64 format and send to server using the RequestBuilder mechanism. Does it make sense?
EDIT:
According to #Pedro Pedruzzi answer, I've implemented an event:
public interface FormToSubmitEventHandler extends EventHandler {
void onFormToSubmit(FormToSubmitEvent event);
}
public class FormToSubmitEvent extends GwtEvent<FormToSubmitEventHandler> {
public static final Type<FormToSubmitEventHandler> TYPE = new Type<FormToSubmitEventHandler>();
public FormToSubmitEvent() {
super();
}
#Override
public Type<FormToSubmitEventHandler> getAssociatedType()
{
return TYPE;
}
#Override
protected void dispatch(FormToSubmitEventHandler handler)
{
handler.onFormToSubmit(this);
}
public static HandlerRegistration register(EventBus eventBus, FormToSubmitEventHandler handler)
{
return eventBus.addHandler(TYPE, handler);
}
}
In a widget class (implementing the interface above) added:
#Override
public void onFormToSubmit(FormToSubmitEvent event)
{
if(fileUpload.getFilename().isEmpty())
return;
else {
form.submit();
}
}
And then:
FormToSubmitEvent event = new FormToSubmitEvent();
Events.getTactinEventBus().fireEvent(event);
Unfortunately - it still doesn't work. I'm completely confused about what is going on.
EDIT 2
Whole class with registered handler:
public class FileLinkPropertyControl implements FormToSubmitEventHandler
{
private FileUpload fileUpload;
protected FormPanel form;;
protected HorizontalPanel hPanel;
public FileLinkPropertyControl() {
fileUpload = new FileUpload();
FormToSubmitEvent.register(Events.getTactinEventBus(), this);
fileUpload.setName("fileUploadFormElement");
fileUpload.addChangeHandler(new ChangeHandler()
{
#Override
public void onChange(ChangeEvent event)
{
setValue(fileUpload.getFilename(), true);
}
});
form.setEncoding(FormPanel.ENCODING_MULTIPART);
form.setMethod(FormPanel.METHOD_POST);
form.setAction(GWT.getModuleBaseURL() + "fileUploadServlet");
form.setWidget(hPanel);
hPanel.add(fileUpload);
}
#Override
public void onFormToSubmit(FormToSubmitEvent event)
{
if(fileUpload.getFilename().isEmpty())
return;
else {
form.submit();
}
}
}
Don't try to simulate the click or to make the request manually. You have to reach form.submit() some way. If the widget hierarchy is too complex to have a simple call chain aproach, you should use an event (see http://www.gwtproject.org/doc/latest/DevGuideUiHandlers.html).
I'm trying to model my small project off the MVC design pattern. As such I am trying to assign the ActionListener for my JButton(submit) (in the UI class) to the evaluate method in the model class, I'm doing all this in a third class (controller) code is below.
public class ExpressionController implements ActionListener {
ExpressionModel model;
ExpressionUI view;
public ExpressionController(ExpressionModel m, ExpressionUI v) {
model = m;
view = v;
//ERROR: The method is undefined for the type Expression Controller
actionListenerComponenets(this);
}
#Override
public void actionPerformed(ActionEvent e) {
try {
double result;
result = model.evaluate(Double.parseDouble(view.input.getText()));
view.result.setText(String.valueOf(result));
}catch (Exception ex) {
ex.printStackTrace();
}
}
public void actionListenerComponenents(ActionListener ae) {
view.submit.addActionListener(ae);
}
My problem is in assigning the action listener outside of the UI class (see comments in code)... is there a better way to do this? I know its only a simple example but I want to be comfortable with MVC Design.
I´m looking for a way to show and hide a working indicator in my web application. I use GWT with model view presenter pattern and have places for my different pages and activities, which are my presenter objects.
What I tried so far:
View objects have to implement an
public interface HasWorkingIndicator
void showWorkingIndicator(boolean show);
Activity objects call the showWorkingIndicator on their view object in a start method.
#Override
public void start(final AcceptsOneWidget panel, EventBus eventBus){
page.showWorkingIndicator(true);
//more code...
}
So what is the best way to hide the WorkingIndicatorView? I cant call showWorkingIndicator(false) at the end of the start(), because the page is not set up at that time.
Maybe any patterns to look at?
It depends how/where/when you want to show the indicator.
If the goal is to show it at the place of the activity, then you have two choices: handle it in the view, or calling setWidget twice on the AcceptsOnWidget that's passed to the activity's start(): once with a wait indicator widget, then with the real activity's view.
If you can guarantee that there will always be an activity for the given display region, then you can also bake this in the AcceptsOneWidget implementation: when setWidget is called with a null you display the waiting indicator (a similar trick is to use an IsWidget whose asWidget returns null instead of a waiting indicator widget in the activity's start).
If however you can live with a global indicator, then you can use a NotificationMole or similar widget, and trigger its showing depending on pending RPC/RequestFactory calles and/or events you'll dispatch on the event bus from the activities.
If you are using activities this becomes a pretty easy task to accomplish.
I have an AbstractActity that implements Activity, this handles things like my clientfactory and the parent panel.
The Activity interface implements mayStop(), onStop and onStart etc.
public class WorkingIndicator extends Composite {
private static WorkingIndicator instance = null;
private WorkingIndicator(){
initWidget(new Label("Working"));
}
public static WorkingIndicator getInstance() {
if (instance == null) {
instance = new WorkingIndicator();
}
return instance;
}
public void show() {
RootLayoutPanel.get().add(this);
}
public void hide() {
RootLayoutPanel.get().remove(this);
}
}
The activity would look something like this.
public abstract class AbstractActivity<T extends ApplicationPlace, V extends View> implements Activity {
protected ClientFactory clientFactory;
protected EventBus eventBus;
protected AcceptsOneWidget parentPanel;
protected final T place;
protected final V display;
protected final List<HandlerRegistration> handlers = new ArrayList<HandlerRegistration>();
public AbstractActivity(T place, ClientFactory clientFactory, V display) {
this.place = place;
this.clientFactory = clientFactory;
this.display = display;
}
protected void setEventBus(EventBus eventBus) {
this.eventBus = eventBus;
}
protected EventBus getEventBus() {
return this.eventBus;
}
#Override
public void start(AcceptsOneWidget parentPanel, EventBus eventBus) {
this.parentPanel = parentPanel;
this.eventBus = eventBus;
parentPanel.setWidget(display.asWidget());
bindToView();
WorkingIndicator.getInstance().hide();
}
public AcceptsOneWidget getParentPanel() {
return parentPanel;
}
public T getPlace() {
return place;
}
public V getDisplay() {
return display;
}
public ClientFactory getClientFactory() {
return clientFactory;
}
/**
* Shortcut getter for the CSS style in Resources.
*
* #return
*/
public Style style() {
return clientFactory.getResources().style();
}
#Override
public String mayStop() {
return null;
}
#Override
public void onCancel() {
}
#Override
public void onStop() {
cleanup();
display.reset();
WorkingIndicator.getInstance().show();
}
protected void addHandler(HandlerRegistration registration) {
handlers.add(registration);
}
public List<HandlerRegistration> getHandlers() {
return handlers;
}
protected void cleanup() {
for (HandlerRegistration handler : handlers) {
handler.removeHandler();
}
}
/**
* This function will be called immediately after adding the view to the
* DOM. This function should be used to hook up click handlers, populate
* HasData handlers and such.
*/
protected abstract void bindToView();
protected DaoRequestFactory daoRequestFactory() {
return clientFactory.daoRequestFactory();
}
protected AnalyticsTaskRequest analyticsTaskRequest() {
return clientFactory.daoRequestFactory().analyticsTaskRequest();
}
protected EventBus eventBus() {
return clientFactory.getEventBus();
}
protected PersonProxy currentPerson() {
return clientFactory.getCurrentPerson();
}
}
Places change instantly. I assume you want to show an indicator when (A) the view is being constructed for the first time, or (B) you wait for data to arrive from your server before showing a view.
In either case you need to add a flag to your view, e.g. isInitialized(), to tell the activity if it needs to do something to build the view (like create a DataGrid, populate a tree, etc.), or the view has been already built before so this step can be skipped.
When your activity starts, check if the view is initialized. If not, show a loading indicator. I recommend a simple PopupPanel with a glass enabled to block the UI. When the activity finishes building the view/loading data, it should set the flag in the view (e.g. setInitialize()), and then you hide this popup panel.
I need to write a custom ValueChangeHandler and call out onValueChange(ValueChangeEvent). However I don't understand how to write a ValueChangeEvent.
Maybe I understand the entire GWT event system wrong. Can anyone help?
Edit: I am asking how to create my own class that dispatches the ValueChangeEvent. I understand how to listen to it.
The constructor of ValueChangeEvent is not visible and I can't create it.
If you want to fire a ValueChangeEvent you must implement the interface HasValueChangeHandlers by or your class or somewhere in the class.
A simple implementation would be to use the EventBus:
EventBus bus = new SimpleEventBus();
#Override
public void fireEvent(GwtEvent<?> event) {
bus.fireEvent(event);
}
#Override
public HandlerRegistration addValueChangeHandler(ValueChangeHandler<T> handler) {
return bus.addHandler(ValueChangeEvent.getType(), handler);
}
Note you need to substitute T with the type you want to fire.
Because you can't create a ValueChangeEvent directly dispatching an event is done via the fire method:
ValueChangeEvent.fire(this, value);
Where this refers to the class/field implementing the HasValueChangeHandlers and value refers to the value that has been changed and you want to dispatch the event.
Actually, instead of creating a new EventBus or HandlerManager, as your widget will be a subclass of Wiget, it the standard way would be to use the Widget.addHandler(handler, eventType) method. Here's a minimal example:
public class MyWidget<T> extends Composite implements HasValueChangeHandlers<T>, HasValue<T> {
private T value;
public MyWidget() {
// Initialize stuff
}
#Override
public HandlerRegistration addValueChangeHandler(final ValueChangeHandler<T> handler) {
return addHandler(handler, ValueChangeEvent.getType());
}
#Override
public T getValue() {
return value;
}
#Override
public void setValue(T value) {
setValue(value, false);
}
#Override
public void setValue(T value, boolean fireEvents) {
this.value = value;
if (fireEvents) {
ValueChangeEvent.fire(this, getValue());
}
}
}
Really late to answer, but I've just solved this problem like this:
ValueChangeEvent.fire(hasValueChangeHandlerInstance, getValue());
The ValueChangeEvent is generated for you by GWT. You can add one (or more) ValueChangeHandler to any class that implements the interface HasValueChangeHandlers. One of these classes is TextArea, so let's look at a little example:
TextArea textArea = new TextArea();
textArea.addValueChangeHandler(new ValueChangeHandler<String>() {
#Override
public void onValueChange(ValueChangeEvent<String> event) {
// do something
}
});
When the value of the text area changes, GWT will automatically generate a ValueChangeEvent, which you can use in the part I marked with "do something".