/******************************************************************************* * 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.profile; 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.DateChangedEvent; import com.delect.motiver.client.event.MeasurementCreatedEvent; import com.delect.motiver.client.event.MeasurementRemovedEvent; import com.delect.motiver.client.event.MeasurementValueCreatedEvent; import com.delect.motiver.client.event.handler.DateChangedEventHandler; import com.delect.motiver.client.event.handler.MeasurementValueCreatedEventHandler; 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.profile.AddNewMeasurementValuePresenter.AddNewMeasurementValueDisplay; 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.profile.AddNewMeasurementValueView; import com.delect.motiver.shared.Constants; import com.delect.motiver.shared.MeasurementModel; import com.delect.motiver.shared.MeasurementValueModel; import com.delect.motiver.shared.util.CommonUtils; import com.extjs.gxt.ui.client.widget.LayoutContainer; /** * Shows single measurement * @author Antti * */ public class MeasurementPresenter extends Presenter { /** * Abstract class for view to extend */ public abstract static class MeasurementDisplay extends Display { public abstract LayoutContainer getCommentsContainer(); public abstract LayoutContainer getDataContainer(); public abstract LayoutContainer getDatesContainer(); public abstract void setCollapsible(boolean isCollapsible); public abstract void setHandler(MeasurementHandler measurementHandler); public abstract void setModel(MeasurementModel measurement); public abstract void setValues(List<MeasurementValueModel> values); public abstract void showContent(); } public interface MeasurementHandler { void measurementRemoved(); void newValue(); void saveData(MeasurementModel model); void valuesRemoved(List<MeasurementValueModel> values); void valuesVisible(); //called when measurement visible (we load foods then) } private AddNewMeasurementValuePresenter addNewMeasurementValuePresenter; private CommentsBoxPresenter commentsPresenter; private Date dateEnd; private DatesSelectorPresenter datesSelectorPresenter; private Date dateStart; private MeasurementDisplay display; //child presenters private Presenter emptyPresenter = null; private boolean isCollapsible; private boolean openAsDefault; private List<MeasurementValueModel> values = new ArrayList<MeasurementValueModel>(); protected MeasurementModel measurement; //callback for loading values final MyAsyncCallback<List<MeasurementValueModel>> callback = new MyAsyncCallback<List<MeasurementValueModel>>() { @Override public void onSuccess(List<MeasurementValueModel> 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()); } } }; /** * Shows all values from single measurement * @param rpcService * @param eventBus * @param display * @param measurement * @param openAsDefault */ public MeasurementPresenter(MyServiceAsync rpcService, SimpleEventBus eventBus, MeasurementDisplay display, MeasurementModel measurement, boolean isCollapsible, boolean openAsDefault) { super(rpcService, eventBus); this.display = display; this.measurement = measurement; this.isCollapsible = isCollapsible; this.openAsDefault = openAsDefault; //init date selector datesSelectorPresenter = new DatesSelectorPresenter(rpcService, eventBus, (DatesSelectorDisplay)GWT.create(DatesSelectorView.class), Constants.DAYS_DIFF_MAX_MEASUREMENT, Constants.DAYS_INDEX_MEASUREMENT); dateStart = datesSelectorPresenter.getDateStart(); dateEnd = datesSelectorPresenter.getDateEnd(); } @Override public Display getView() { return display; } @Override public void onBind() { display.setModel(measurement); display.setCollapsible(isCollapsible); //Event handlers //Launch MeasurementUpdatedEvent if measurement (content) changes display.setHandler(new MeasurementHandler() { @Override public void measurementRemoved() { display.setContentEnabled(false); //remove measurement rpcService.removeMeasurement(measurement, new MyAsyncCallback<Boolean>() { @Override public void onSuccess(Boolean result) { stop(); //fire event eventBus.fireEvent(new MeasurementRemovedEvent(measurement)); } }); } @Override public void newValue() { addNewMeasurementValuePresenter = new AddNewMeasurementValuePresenter(rpcService, eventBus, (AddNewMeasurementValueDisplay)GWT.create(AddNewMeasurementValueView.class), measurement); addNewMeasurementValuePresenter.run(display.getDataContainer()); } @SuppressWarnings("unchecked") @Override public void saveData(MeasurementModel model) { //if cancelled adding new measurement if(model == null) { stop(); //fire event eventBus.fireEvent(new MeasurementRemovedEvent(measurement)); } //added new measurement else if(model.getId() == 0) { measurement = model; display.setContentEnabled(false); //create model rpcService.addMeasurement(model, new MyAsyncCallback<MeasurementModel>() { @Override public void onSuccess(MeasurementModel result) { display.setContentEnabled(true); measurement = result; refresh(); //fire event final MeasurementCreatedEvent event = new MeasurementCreatedEvent(measurement); fireEvent(event); } }); } //edited old value else { measurement = model; rpcService.updateMeasurement(measurement, MyAsyncCallback.EmptyCallback); } } @SuppressWarnings("unchecked") @Override public void valuesRemoved(List<MeasurementValueModel> list) { rpcService.removeMeasurementValues(measurement, list, MyAsyncCallback.EmptyCallback); //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: measurement value added addEventHandler(MeasurementValueCreatedEvent.TYPE, new MeasurementValueCreatedEventHandler() { @SuppressWarnings("deprecation") @Override public void onMeasurementValueCreated(MeasurementValueCreatedEvent event) { //check dates (to make sure value is visible) Date dEvent = event.getMeasurementValue().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 measurement values loadValues(dateStart, dateEnd); } }); } @Override public void onRefresh() { if(addNewMeasurementValuePresenter != null) { addNewMeasurementValuePresenter.stop(); } if(datesSelectorPresenter != null) { datesSelectorPresenter.run(display.getDatesContainer()); } } @Override public void onRun() { //if all measurements if(measurement != null) { if(measurement.getId() != 0) { //if measurement 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(addNewMeasurementValuePresenter != null) { addNewMeasurementValuePresenter.stop(); } if(datesSelectorPresenter != null) { datesSelectorPresenter.stop(); } } /** * Loads values */ void loadValues(Date dateStart, Date dateEnd) { //only if id is not zero if(measurement.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), measurement); commentsPresenter.run(display.getCommentsContainer()); } Motiver.setNextCallCacheable(true); final Request req = rpcService.getMeasurementValues(measurement, CommonUtils.trimDateToDatabase(dateStart, true), CommonUtils.trimDateToDatabase(dateEnd, true), callback); addRequest(req); } }