/******************************************************************************* * 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.cardio; import java.util.ArrayList; import java.util.Collections; import java.util.Date; 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.delect.motiver.client.AppController; import com.delect.motiver.client.Motiver; import com.delect.motiver.client.MyAsyncCallback; import com.delect.motiver.client.event.CardioCreatedEvent; import com.delect.motiver.client.event.CardioRemovedEvent; import com.delect.motiver.client.event.CardioValueCreatedEvent; import com.delect.motiver.client.event.DateChangedEvent; import com.delect.motiver.client.event.handler.CardioValueCreatedEventHandler; import com.delect.motiver.client.event.handler.DateChangedEventHandler; import com.delect.motiver.client.presenter.CommentsBoxPresenter; import com.delect.motiver.client.presenter.CommentsBoxPresenter.CommentsBoxDisplay; import com.delect.motiver.client.presenter.DatesSelectorPresenter; import com.delect.motiver.client.presenter.DatesSelectorPresenter.DatesSelectorDisplay; import com.delect.motiver.client.presenter.EmptyPresenter; import com.delect.motiver.client.presenter.EmptyPresenter.EmptyDisplay; import com.delect.motiver.client.presenter.Presenter; import com.delect.motiver.client.presenter.cardio.AddNewCardioValuePresenter.AddNewCardioValueDisplay; import com.delect.motiver.client.service.MyServiceAsync; import com.delect.motiver.client.view.CommentsBoxView; import com.delect.motiver.client.view.DatesSelectorView; import com.delect.motiver.client.view.Display; import com.delect.motiver.client.view.EmptyView; import com.delect.motiver.client.view.cardio.AddNewCardioValueView; import com.delect.motiver.shared.CardioModel; import com.delect.motiver.shared.CardioValueModel; import com.delect.motiver.shared.Constants; import com.delect.motiver.shared.util.CommonUtils; import com.extjs.gxt.ui.client.widget.LayoutContainer; /** * Shows single cardio (name and foods) * @author Antti * */ public class CardioPresenter extends Presenter { /** * Abstract class for view to extend */ public abstract static class CardioDisplay extends Display { public abstract LayoutContainer getCommentsContainer(); public abstract LayoutContainer getDataContainer(); public abstract LayoutContainer getDatesContainer(); public abstract void setCollapsible(boolean isCollapsible); public abstract void setHandler(CardioHandler cardioHandler); public abstract void setModel(CardioModel cardio); public abstract void setValues(List<CardioValueModel> values); public abstract void showContent(); } public interface CardioHandler { void cardioRemoved(); void newValue(); void saveData(CardioModel model); void valuesRemoved(List<CardioValueModel> values); void valuesVisible(); //called when cardio visible (we load foods then) } private AddNewCardioValuePresenter addNewCardioValuePresenter; //callback for loading values private MyAsyncCallback<List<CardioValueModel>> callback = new MyAsyncCallback<List<CardioValueModel>>() { @Override public void onSuccess(List<CardioValueModel> result) { values = result; //sort list (date DESC) Collections.sort(values); if(emptyPresenter != null) { emptyPresenter.stop(); emptyPresenter = null; } display.setValues(values); //no values -> show empty presenter if(values.size() == 0) { //add empty presenter emptyPresenter = new EmptyPresenter(rpcService, eventBus, (EmptyDisplay)GWT.create(EmptyView.class), AppController.Lang.NoValues()); emptyPresenter.run(display.getDataContainer()); } } }; private CommentsBoxPresenter commentsPresenter; private Date dateEnd; private DatesSelectorPresenter datesSelectorPresenter; private Date dateStart; private CardioDisplay display; //child presenters private Presenter emptyPresenter = null; private boolean isCollapsible; private boolean openAsDefault; private List<CardioValueModel> values = new ArrayList<CardioValueModel>(); protected CardioModel cardio; /** * Shows all values from single cardio * @param rpcService * @param eventBus * @param display * @param cardio * @param openAsDefault */ public CardioPresenter(MyServiceAsync rpcService, SimpleEventBus eventBus, CardioDisplay display, CardioModel cardio, boolean isCollapsible, boolean openAsDefault) { super(rpcService, eventBus); this.display = display; this.cardio = cardio; this.isCollapsible = isCollapsible; this.openAsDefault = openAsDefault; //init date selector datesSelectorPresenter = new DatesSelectorPresenter(rpcService, eventBus, (DatesSelectorDisplay)GWT.create(DatesSelectorView.class), Constants.DAYS_DIFF_MAX_CARDIO, Constants.DAYS_INDEX_CARDIO); dateStart = datesSelectorPresenter.getDateStart(); dateEnd = datesSelectorPresenter.getDateEnd(); } @Override public Display getView() { return display; } @Override public void onBind() { display.setModel(cardio); display.setCollapsible(isCollapsible); //Event handlers //Launch CardioUpdatedEvent if cardio (content) changes display.setHandler(new CardioHandler() { @Override public void cardioRemoved() { display.setContentEnabled(false); //remove cardio final Request req = rpcService.removeCardio(cardio, new MyAsyncCallback<Boolean>() { @Override public void onSuccess(Boolean result) { stop(); //fire event eventBus.fireEvent(new CardioRemovedEvent(cardio)); } }); addRequest(req); } @Override public void newValue() { addNewCardioValuePresenter = new AddNewCardioValuePresenter(rpcService, eventBus, (AddNewCardioValueDisplay)GWT.create(AddNewCardioValueView.class), cardio, null); addNewCardioValuePresenter.run(display.getDataContainer()); } @SuppressWarnings("unchecked") @Override public void saveData(CardioModel model) { //if cancelled adding new measurement if(model == null) { stop(); //fire event eventBus.fireEvent(new CardioRemovedEvent(cardio)); } //added new measurement else if(model.getId() == 0) { cardio = model; display.setContentEnabled(false); //create model final Request req = rpcService.addCardio(model, new MyAsyncCallback<CardioModel>() { @Override public void onSuccess(CardioModel result) { display.setContentEnabled(true); cardio = result; refresh(); //fire event final CardioCreatedEvent event = new CardioCreatedEvent(cardio); fireEvent(event); } }); addRequest(req); } //edited old value else { cardio = model; final Request req = rpcService.updateCardio(cardio, MyAsyncCallback.EmptyCallback); addRequest(req); } } @SuppressWarnings("unchecked") @Override public void valuesRemoved(List<CardioValueModel> list) { final Request req = rpcService.removeCardioValues(cardio, list, MyAsyncCallback.EmptyCallback); addRequest(req); //remove values from list values.removeAll(list); display.setValues(values); if(values.size() == 0) { //add empty presenter emptyPresenter = new EmptyPresenter(rpcService, eventBus, (EmptyDisplay)GWT.create(EmptyView.class), AppController.Lang.NoValues()); emptyPresenter.run(display.getDataContainer()); } } @Override public void valuesVisible() { loadValues(dateStart, dateEnd); } }); //EVENT: dates changed addEventHandler(DateChangedEvent.TYPE, new DateChangedEventHandler() { @Override public void onDateChanged(DateChangedEvent event) { if(event.getSource() != null && event.getSource().equals(datesSelectorPresenter)) { loadValues(event.getDate(), event.getDateEnd()); } } }); //EVENT: cardio value added addEventHandler(CardioValueCreatedEvent.TYPE, new CardioValueCreatedEventHandler() { @SuppressWarnings("deprecation") @Override public void onCardioValueCreated(CardioValueCreatedEvent event) { //check dates (to make sure value is visible) Date dEvent = event.getCardioValue().getDate(); long d1 = Date.UTC(dateStart.getYear(), dateStart.getMonth(), dateStart.getDate(), 0, 0, 0); long d2 = Date.UTC(dateEnd.getYear(), dateEnd.getMonth(), dateEnd.getDate(), 23, 59, 59); //not visible if(dEvent.getTime() < d1 || dEvent.getTime() > d2) { //show week after cardio values date dateStart = dEvent; dateEnd = new Date( (dateStart.getTime() + 1000 * 3600 * 24 * 7) ); //update dates selector datesSelectorPresenter.setDates(dateStart, dateEnd); } //reload cardio values loadValues(dateStart, dateEnd); } }); } @Override public void onRefresh() { if(addNewCardioValuePresenter != null) { addNewCardioValuePresenter.stop(); } if(datesSelectorPresenter != null) { datesSelectorPresenter.run(display.getDatesContainer()); } } @Override public void onRun() { //if all measurements if(cardio != null) { if(cardio.getId() != 0) { //if cardio is "open" as default if(openAsDefault) { display.showContent(); } } //no model -> hightlight else { highlight(); } } else { display.showContent(); } } @Override public void onStop() { if(emptyPresenter != null) { emptyPresenter.stop(); } if(commentsPresenter != null) { commentsPresenter.stop(); } if(addNewCardioValuePresenter != null) { addNewCardioValuePresenter.stop(); } if(datesSelectorPresenter != null) { datesSelectorPresenter.stop(); } } /** * Loads values */ void loadValues(Date dateStart, Date dateEnd) { //only if id is not zero if(cardio.getId() == 0) { return; } if(emptyPresenter != null) { emptyPresenter.stop(); } datesSelectorPresenter.run(display.getDatesContainer()); //reset data display.setValues(null); //add empty presenter emptyPresenter = new EmptyPresenter(rpcService, eventBus, (EmptyDisplay)GWT.create(EmptyView.class), EmptyPresenter.EMPTY_LOADING); emptyPresenter.run(display.getDataContainer()); //show comments if(commentsPresenter == null) { commentsPresenter = new CommentsBoxPresenter(rpcService, eventBus, (CommentsBoxDisplay)GWT.create(CommentsBoxView.class), cardio); commentsPresenter.run(display.getCommentsContainer()); } Motiver.setNextCallCacheable(true); final Request req = rpcService.getCardioValues(cardio, CommonUtils.trimDateToDatabase(dateStart, true), CommonUtils.trimDateToDatabase(dateEnd, true), callback); addRequest(req); } }