/******************************************************************************* * Copyright 2011 Antti Havanko * * This file is part of Motiver.fi. * Motiver.fi is licensed under one open source license and one commercial license. * * Commercial license: This is the appropriate option if you want to use Motiver.fi in * commercial purposes. Contact license@motiver.fi for licensing options. * * Open source license: This is the appropriate option if you are creating an open source * application with a license compatible with the GNU GPL license v3. Although the GPLv3 has * many terms, the most important is that you must provide the source code of your application * to your users so they can be free to modify your application for their own needs. ******************************************************************************/ package com.delect.motiver.client.presenter.nutrition; import java.util.ArrayList; import java.util.List; import com.google.gwt.core.client.GWT; import com.google.gwt.event.shared.SimpleEventBus; import com.google.gwt.http.client.Request; import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.rpc.AsyncCallback; import com.delect.motiver.client.AppController; import com.delect.motiver.client.Motiver; import com.delect.motiver.client.MyAsyncCallback; import com.delect.motiver.client.event.FoodCreatedEvent; import com.delect.motiver.client.event.FoodNameUpdatedEvent; import com.delect.motiver.client.event.FoodRemovedEvent; import com.delect.motiver.client.event.FoodUpdatedEvent; import com.delect.motiver.client.event.handler.FoodNameUpdatedEventHandler; import com.delect.motiver.client.presenter.Presenter; import com.delect.motiver.client.presenter.nutrition.FoodNameEditorPresenter.FoodNameEditorDisplay; import com.delect.motiver.client.presenter.nutrition.FoodNameEditorPresenter.FoodNameEditorHandler; import com.delect.motiver.client.service.MyServiceAsync; import com.delect.motiver.client.view.Display; import com.delect.motiver.client.view.nutrition.FoodNameEditorView; import com.delect.motiver.shared.Constants; import com.delect.motiver.shared.FoodModel; import com.delect.motiver.shared.FoodNameModel; /** * Shows single food * @author Antti * */ public class FoodPresenter extends Presenter { /** * Abstract class for view to extend */ public abstract static class FoodDisplay extends Display { public abstract void setHandler(FoodHandler foodHandler); public abstract void setModel(FoodModel food); public abstract void setNameComboEnabled(boolean b); } public interface FoodHandler { void foodEdited(); void foodRemoved(); void newNameEntered(String newName); //when new name is typed void query(String query, AsyncCallback<List<FoodNameModel>> callback); //called when user search for foods void saveData(FoodModel food); } private FoodDisplay display; //child presenters private FoodNameEditorPresenter foodNameEditorPresenter; private String lastQuery = ""; protected FoodModel food; private Timer timerUpdate; public FoodPresenter(MyServiceAsync rpcService, SimpleEventBus eventBus, FoodDisplay display, FoodModel food) { super(rpcService, eventBus); this.display = display; this.food = food; } @Override public Display getView() { return display; } @Override public void onBind() { //if new food -> set uid to our if(food.getId() == 0) { food.setUid(AppController.User.getUid()); } display.setModel(food); if(food.getId() != 0) { display.setContentEnabled(true); //event handler (fire event) display.setHandler(new FoodHandler() { @Override public void foodEdited() { //if presenter already visible -> cancel if(foodNameEditorPresenter != null) { return; } //disable combo display.setNameComboEnabled(false); foodNameEditorPresenter = new FoodNameEditorPresenter(rpcService, eventBus, (FoodNameEditorDisplay)GWT.create(FoodNameEditorView.class), food.getName()); foodNameEditorPresenter.run(display.getBaseContainer()); //refresh view when name set / edit cancelled foodNameEditorPresenter.setHandler(new FoodNameEditorHandler() { @Override public void editCancelled() { //enable combo display.setNameComboEnabled(true); //reset model display.setModel(food); foodNameEditorPresenter = null; } @Override public void nameSaved(FoodNameModel model) { //enable combo display.setNameComboEnabled(true); foodNameEditorPresenter = null; } }); } @Override public void foodRemoved() { display.setContentEnabled(false); List<FoodModel> list = new ArrayList<FoodModel>(); list.add(food); final Request req = rpcService.removeFoods(list, new MyAsyncCallback<Boolean>() { @Override public void onSuccess(Boolean result) { if(result) { stop(); if(result) { fireEvent(new FoodRemovedEvent(food)); } } } }); addRequest(req); } @Override public void newNameEntered(String newName) { //if presenter already visible -> cancel if(foodNameEditorPresenter != null) { return; } //disable combo display.setNameComboEnabled(false); //create dummy model FoodNameModel model = new FoodNameModel(0L, newName); model.setLocale(AppController.User.getLocale()); //new name typed -> launch NewFoodNamePresenter foodNameEditorPresenter = new FoodNameEditorPresenter(rpcService, eventBus, (FoodNameEditorDisplay)GWT.create(FoodNameEditorView.class), model); foodNameEditorPresenter.run(display.getBaseContainer()); //refresh view when name set / edit cancelled foodNameEditorPresenter.setHandler(new FoodNameEditorHandler() { @Override public void editCancelled() { //enable combo display.setNameComboEnabled(true); //reset model display.setModel(food); foodNameEditorPresenter = null; } @Override public void nameSaved(FoodNameModel model) { //enable combo display.setNameComboEnabled(true); foodNameEditorPresenter = null; food.setName(model); //update food updateFood(); } }); } @Override public void query(final String query, final AsyncCallback<List<FoodNameModel>> callback) { //save query lastQuery = query; Motiver.setNextCallCacheable(true); final Request req = rpcService.searchFoodNames(query, Constants.LIMIT_SEARCH_NAMES, new MyAsyncCallback<List<FoodNameModel>>() { @Override public void onSuccess(List<FoodNameModel> result) { //only if last query if(query.equals(lastQuery)) { callback.onSuccess(result); } } }); addRequest(req); } @Override public void saveData(FoodModel model) { food = model; updateFood(); } }); //EVENT: food name updated addEventHandler(FoodNameUpdatedEvent.TYPE, new FoodNameUpdatedEventHandler() { @Override public void onFoodNameUpdated(FoodNameUpdatedEvent event) { if(food.getName() != null && food.getName().equals(event.getFoodName())) { food.setName(event.getFoodName()); fireEvent(new FoodUpdatedEvent(food)); } } }); } } @Override public void onRun() { //if no food -> create new one if(food.getId() == 0) { display.setContentEnabled(false); final Request req = rpcService.addFood(food, new MyAsyncCallback<FoodModel>() { @Override public void onSuccess(FoodModel result) { if(result != null) { display.setContentEnabled(true); //set data food.setId(result.getId()); //fire event fireEvent(new FoodCreatedEvent(food)); //refresh display.setModel(food); run(display.getBaseContainer()); } } }); addRequest(req); } } @Override public void onStop() { if(foodNameEditorPresenter != null) { foodNameEditorPresenter.stop(); } } /** * Updates food from server based to model-variable * Fires FoodUpdatedEvent */ protected void updateFood() { if(timerUpdate != null) timerUpdate.cancel(); food.setName(food.getName()); timerUpdate = new Timer() { @Override public void run() { rpcService.updateFood(food, new MyAsyncCallback<FoodModel>() { @Override public void onSuccess(FoodModel result) { //update model if(result != null) { food.setName(result.getName()); food.setAmount(result.getAmount()); display.setModel(food); } } }); } }; timerUpdate.schedule(Constants.DELAY_MODEL_UPDATE); fireEvent(new FoodUpdatedEvent(food)); } }