/******************************************************************************* * 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; import java.util.Date; import java.util.List; import com.google.gwt.event.shared.SimpleEventBus; import com.google.gwt.http.client.Request; import com.google.gwt.i18n.client.DateTimeFormat; import com.google.gwt.user.client.Timer; import com.delect.motiver.client.AppController; import com.delect.motiver.client.Motiver; import com.delect.motiver.client.MyAsyncCallback; import com.delect.motiver.client.event.CardioValueCreatedEvent; import com.delect.motiver.client.event.CardioValueRemovedEvent; import com.delect.motiver.client.event.DateChangedEvent; import com.delect.motiver.client.event.RoutineCreatedEvent; import com.delect.motiver.client.event.RunValueCreatedEvent; import com.delect.motiver.client.event.RunValueRemovedEvent; import com.delect.motiver.client.event.WorkoutCreatedEvent; import com.delect.motiver.client.event.WorkoutMovedEvent; import com.delect.motiver.client.event.WorkoutRemovedEvent; import com.delect.motiver.client.event.handler.CardioValueCreatedEventHandler; import com.delect.motiver.client.event.handler.CardioValueRemovedEventHandler; import com.delect.motiver.client.event.handler.DateChangedEventHandler; import com.delect.motiver.client.event.handler.RoutineCreatedEventHandler; import com.delect.motiver.client.event.handler.RunValueCreatedEventHandler; import com.delect.motiver.client.event.handler.RunValueRemovedEventHandler; import com.delect.motiver.client.event.handler.WorkoutCreatedEventHandler; import com.delect.motiver.client.event.handler.WorkoutMovedEventHandler; import com.delect.motiver.client.event.handler.WorkoutRemovedEventHandler; import com.delect.motiver.client.service.MyServiceAsync; import com.delect.motiver.client.view.Display; import com.delect.motiver.shared.BlogData; import com.delect.motiver.shared.RoutineModel; import com.delect.motiver.shared.WorkoutModel; import com.delect.motiver.shared.util.CommonUtils; /** * Shows +1/-2 weeks from given day * <dl> * <dt><b>Events:</b></dt> * * <dd><b>onDateChanged</b> : DateEvent()<br> * <div>Fires after date changes</div> * <ul> * <li>date : new date</li> * </ul> * </dd> * * </dl> * */ public class DateWeekSelectorPresenter extends Presenter { /** * Abstract class for view to extend */ public abstract static class DateWeekSelectorDisplay extends Display { /** * Refreshes view (scrolls to correct dates) */ public abstract void refreshView(); /** * Sets start date * @param dateStart Date */ public abstract void setDate(Date dateStart); /** * Sets selected date * @param date Date */ public abstract void setDateSelected(Date date); /** * Sets handler * @param handler DateWeekSelectorHandler */ public abstract void setHandler(DateWeekSelectorHandler handler); /** * Sets markers for each day. Single marker is true if day has training/nutrition. * @param markers boolean[] */ public abstract void setMarkers(boolean[] markers); /** * How many days are shown at once * @return */ public abstract int getTotalDays(); } /** Handler for this presenter. */ public interface DateWeekSelectorHandler { /** * View calls when date is selected * @param startDate Date * @param dateSelected Date */ void dateSelected(Date startDate, Date dateSelected); } private Date dateSelected; private Date dateStart; private DateWeekSelectorDisplay display; private boolean showNutrition; private boolean showTraining; private Timer timer; /** * Constructor for DateWeekSelectorPresenter. * @param rpcService MyServiceAsync * @param eventBus SimpleEventBus * @param display DateWeekSelectorDisplay */ public DateWeekSelectorPresenter(MyServiceAsync rpcService, SimpleEventBus eventBus, DateWeekSelectorDisplay display) { super(rpcService, eventBus); this.display = display; } @Override public Display getView() { return display; } @Override public void onBind() { //when date selected -> fire event display.setHandler(new DateWeekSelectorHandler() { @Override public void dateSelected(Date dateSt, Date dateSel) { //fire event final DateChangedEvent event = new DateChangedEvent(dateSel); fireEvent(event); } }); //EVENT: new workout created -> refresh view addEventHandler(WorkoutCreatedEvent.TYPE, new WorkoutCreatedEventHandler() { @Override public void onWorkoutCreated(WorkoutCreatedEvent event) { final WorkoutModel model = event.getWorkout(); if(model.getDate() != null) { load(); } } }); //EVENT: workout moved -> refresh view addEventHandler(WorkoutMovedEvent.TYPE, new WorkoutMovedEventHandler() { @Override public void onWorkoutMoved(WorkoutMovedEvent event) { load(); } }); //EVENT: new workout created -> refresh view addEventHandler(WorkoutRemovedEvent.TYPE, new WorkoutRemovedEventHandler() { @Override public void onWorkoutRemoved(WorkoutRemovedEvent event) { final WorkoutModel model = event.getWorkout(); if(model.getDate() != null) { load(); } } }); //EVENT: new routine created -> refresh view addEventHandler(RoutineCreatedEvent.TYPE, new RoutineCreatedEventHandler() { @Override public void onRoutineCreated(RoutineCreatedEvent event) { final RoutineModel model = event.getRoutine(); if(model.getDate() != null) { load(); } } }); //EVENT: new cardio value created -> refresh view addEventHandler(CardioValueCreatedEvent.TYPE, new CardioValueCreatedEventHandler() { @Override public void onCardioValueCreated(CardioValueCreatedEvent event) { load(); } }); //EVENT: new run value created -> refresh view addEventHandler(RunValueCreatedEvent.TYPE, new RunValueCreatedEventHandler() { @Override public void onRunValueCreated(RunValueCreatedEvent event) { load(); } }); //EVENT: new cardio value created -> refresh view addEventHandler(CardioValueRemovedEvent.TYPE, new CardioValueRemovedEventHandler() { @Override public void onCardioValueRemoved(CardioValueRemovedEvent event) { load(); } }); //EVENT: new run value created -> refresh view addEventHandler(RunValueRemovedEvent.TYPE, new RunValueRemovedEventHandler() { @Override public void onRunValueRemoved(RunValueRemovedEvent event) { load(); } }); //EVENT: reload view when date changes addEventHandler(DateChangedEvent.TYPE, new DateChangedEventHandler() { @Override public void onDateChanged(DateChangedEvent event) { final Date dateStartOld = dateStart; //refresh setParameters(event.getDate(), showTraining, showNutrition); //if changed final DateTimeFormat fmt = DateTimeFormat.getFormat("y-M-d"); if(!fmt.format(dateStartOld).equals(fmt.format(dateStart))) { load(); } } }); } @Override public void onRun() { if(timer != null) { timer.cancel(); } //small delay so everything else is loaded first timer = new Timer() { @Override public void run() { load(); } }; timer.schedule(1000); } @Override public void onStop() { if(timer != null) { timer.cancel(); } } /** * Method setParameters. * @param date Date * @param showTraining boolean * @param showNutrition boolean */ public void setParameters(Date date, boolean showTraining, boolean showNutrition) { try { dateSelected = date; display.setDateSelected(dateSelected); //set date to start one week before selected date //only change start date if is it not visible if(dateStart == null || dateSelected == null || dateSelected.getTime() < dateStart.getTime() || (dateSelected.getTime() / 1000) > (dateStart.getTime() / 1000 + 3600 * 24 * 21)) { final long d = CommonUtils.findPreviousMonday(date.getTime() / 1000 - 3600 * 24 * 7); dateStart = new Date(d * 1000); display.setDate(dateStart); } this.showTraining = showTraining; this.showNutrition = showNutrition; } catch (Exception e) { Motiver.showException(e); } //reload view display.refreshView(); } /** * Loads data from server */ private void load() { final Date dateEnd = new Date(dateStart.getTime() + 1000 * 3600 * 24 * (display.getTotalDays() - 1)); //fetch workouts if(showTraining) { Motiver.setNextCallCacheable(true); final Request req = rpcService.getBlogData(0, 30, 5, CommonUtils.trimDateToDatabase(dateStart, true), CommonUtils.trimDateToDatabase(dateEnd, true), String.valueOf(AppController.User.getUid()), true, new MyAsyncCallback<List<BlogData>>() { @Override public void onSuccess(List<BlogData> list) { if(list == null) { return; } //save data to markers array (data needs to be inverted) final boolean[] markers = new boolean[21]; int i = list.size() - 1; for(BlogData bd : list) { final boolean hasTraining = (bd != null) && (bd.getWorkouts().size() > 0 || bd.getCardios().size() > 0 || bd.getRuns().size() > 0); markers[i] = hasTraining; i--; } display.setMarkers(markers); } }); addRequest(req); } //fetch nutrition if(showNutrition) { Motiver.setNextCallCacheable(true); final Request req = rpcService.getBlogData(0, 30, 2, CommonUtils.trimDateToDatabase(dateStart, true), CommonUtils.trimDateToDatabase(dateEnd, true), String.valueOf(AppController.User.getUid()), true, new MyAsyncCallback<List<BlogData>>() { @Override public void onSuccess(List<BlogData> list) { if(list == null) { return; } //save data to markers array (data needs to be inverted) final boolean[] markers = new boolean[21]; int i = list.size() - 1; for(BlogData bd : list) { final boolean hasNutrition = (bd != null) && (bd.getNutrition() != null); markers[i] = hasNutrition; i--; } display.setMarkers(markers); } }); addRequest(req); } } }