/*******************************************************************************
* 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.training;
import java.util.ArrayList;
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.google.gwt.user.client.Window;
import com.delect.motiver.client.AppController;
import com.delect.motiver.client.Motiver;
import com.delect.motiver.client.MyAsyncCallback;
import com.delect.motiver.client.event.UserSelectedEvent;
import com.delect.motiver.client.event.WorkoutCreatedEvent;
import com.delect.motiver.client.event.WorkoutRemovedEvent;
import com.delect.motiver.client.event.WorkoutSelectCancelledEvent;
import com.delect.motiver.client.event.WorkoutSelectedEvent;
import com.delect.motiver.client.event.WorkoutShowEvent;
import com.delect.motiver.client.event.handler.UserSelectedEventHandler;
import com.delect.motiver.client.event.handler.WorkoutCreatedEventHandler;
import com.delect.motiver.client.event.handler.WorkoutRemovedEventHandler;
import com.delect.motiver.client.event.handler.WorkoutSelectedEventHandler;
import com.delect.motiver.client.event.handler.WorkoutShowEventHandler;
import com.delect.motiver.client.presenter.Presenter;
import com.delect.motiver.client.presenter.training.WorkoutPresenter.WorkoutDisplay;
import com.delect.motiver.client.presenter.training.WorkoutsListSearchPresenter.WorkoutsListSearchDisplay;
import com.delect.motiver.client.presenter.training.WorkoutsListSubPresenter.WorkoutsListSubDisplay;
import com.delect.motiver.client.service.MyServiceAsync;
import com.delect.motiver.client.view.Display;
import com.delect.motiver.client.view.training.WorkoutView;
import com.delect.motiver.client.view.training.WorkoutsListSearchView;
import com.delect.motiver.client.view.training.WorkoutsListSubView;
import com.delect.motiver.shared.RoutineModel;
import com.delect.motiver.shared.WorkoutModel;
import com.delect.motiver.shared.util.CommonUtils;
import com.extjs.gxt.ui.client.widget.LayoutContainer;
/**
* 3 "pages": (with search box on top)
* <br>- main page (shows user's workouts, most popular)
* <br>- search results
* <br>- single workout (when individual workout is selected)
* <br>- Fires {@link com.delect.motiver.client.event.WorkoutCreatedEvent WorkoutCreatedEvent} when workout is selected.
* <br>- Fires {@link com.delect.motiver.client.event.WorkoutSelectCancelledEvent WorkoutSelectCancelledEvent} when selection is cancelled and stops itself
* @author Antti
*
*/
public class WorkoutsListPresenter extends Presenter {
/**
* Abstract class for view to extend
*/
public abstract static class WorkoutsListDisplay extends Display {
public abstract LayoutContainer getDataContainer();
public abstract void setBackButtonVisible(boolean b);
public abstract void setCancelButtonVisible(boolean b);
public abstract void setCopyButtonVisible(boolean b);
public abstract void setHandler(WorkoutsListHandler workoutsListHandler);
public abstract void setMoveToDateButtonVisible(boolean b, Date date);
public abstract void setMoveToRoutineButtonVisible(boolean visible, RoutineModel routine);
public abstract void setQuickSelectionButtonVisible(boolean b, Date date);
}
public interface WorkoutsListHandler {
void onBackButtonClicked();
void onCancelButtonClicked();
void onCopyButtonClicked();
void onMoveToDateButtonClicked();
void onMoveToRoutineButtonClicked();
void onQuickSelectionButtonClicked();
void search(String query);
}
private Date date;
private int day;
private WorkoutsListDisplay display;
private String lastQuery = "";
private int lastView = 0;
private List<WorkoutModel> quickSelectionWorkouts = new ArrayList<WorkoutModel>(); //meals which are selected
private RoutineModel routine;
private WorkoutPresenter singleWorkoutPresenter;
private long workoutId = 0;
private WorkoutsListSearchPresenter workoutsListSearchPresenter;
//child presenters
private WorkoutsListSubPresenter workoutsListSubPresenter;
/**
*
* @param rpcService
* @param eventBus
* @param display
* @param date
* @param workoutId : if some workout is open as default
*/
public WorkoutsListPresenter(MyServiceAsync rpcService, SimpleEventBus eventBus, WorkoutsListDisplay display, Date date, long workoutId) {
super(rpcService, eventBus);
this.display = display;
this.date = date;
this.workoutId = workoutId;
boolean quickSelectionEnabled = (date != null);
workoutsListSubPresenter = new WorkoutsListSubPresenter(rpcService, eventBus, (WorkoutsListSubDisplay)GWT.create(WorkoutsListSubView.class), quickSelectionEnabled);
}
/**
* Adds workout to routine
* @param rpcService
* @param eventBus
* @param workoutsListView
* @param routine
* @param day
*/
public WorkoutsListPresenter(MyServiceAsync rpcService, SimpleEventBus eventBus, WorkoutsListDisplay display, RoutineModel routine, int day) {
super(rpcService, eventBus);
this.display = display;
this.routine = routine;
this.day = day;
boolean quickSelectionEnabled = (date != null);
workoutsListSubPresenter = new WorkoutsListSubPresenter(rpcService, eventBus, (WorkoutsListSubDisplay)GWT.create(WorkoutsListSubView.class), quickSelectionEnabled);
}
@Override
public Display getView() {
return display;
}
@Override
public void onBind() {
display.setHandler(new WorkoutsListHandler() {
@Override
public void onBackButtonClicked() {
//coming back from search results
if(singleWorkoutPresenter == null) {
showMainView();
}
//if coming back from single exercise
else {
//unbind workout
singleWorkoutPresenter.stop();
singleWorkoutPresenter = null;
//last view was search results
if(lastView == 1) {
loadSearch(lastQuery);
}
//last view was main menu
else {
showMainView();
}
}
}
@Override
public void onCancelButtonClicked() {
//unbind this
stop();
//fire cancel event
fireEvent(new WorkoutSelectCancelledEvent(date));
}
@Override
public void onCopyButtonClicked() {
copyWorkout();
}
@Override
public void onMoveToDateButtonClicked() {
//get workout from single presenter
List<WorkoutModel> workouts = new ArrayList<WorkoutModel>();
workouts.add(singleWorkoutPresenter.workout);
moveWorkoutToDate(workouts);
}
@Override
public void onMoveToRoutineButtonClicked() {
copyWorkout();
}
@Override
public void onQuickSelectionButtonClicked() {
//get meals from quick selection
moveWorkoutToDate(quickSelectionWorkouts);
quickSelectionWorkouts.clear();
}
@Override
public void search(String query) {
loadSearch(query);
}
});
//EVENT: workout created -> open workout
addEventHandler(WorkoutCreatedEvent.TYPE, new WorkoutCreatedEventHandler() {
@Override
public void onWorkoutCreated(WorkoutCreatedEvent event) {
//if no date
if(event.getWorkout() != null && event.getWorkout().getDate() == null) {
showSingleWorkout(event.getWorkout());
}
}
});
//EVENT: workout removed -> show main view
addEventHandler(WorkoutRemovedEvent.TYPE, new WorkoutRemovedEventHandler() {
@Override
public void onWorkoutRemoved(WorkoutRemovedEvent event) {
//if workout in list
if(event.getWorkout() != null && event.getWorkout().getDate() == null) {
showMainView();
}
}
});
//EVENT: show workouts
addEventHandler(WorkoutShowEvent.TYPE, new WorkoutShowEventHandler() {
@Override
public void selectWorkout(WorkoutShowEvent event) {
showSingleWorkout(event.getWorkout());
}
});
//EVENT: workout selected (quick select)
addEventHandler(WorkoutSelectedEvent.TYPE, new WorkoutSelectedEventHandler() {
@Override
public void workoutSelected(WorkoutSelectedEvent event) {
setQuickSelection(event.getWorkout(), event.isSelected());
}
});
//EVENT: user selected -> show blog
addEventHandler(UserSelectedEvent.TYPE, new UserSelectedEventHandler() {
@Override
public void userSelected(UserSelectedEvent event) {
//open blog in new window
Window.open(event.getUser().getBlogUrl(), "_blank", "status=1,toolbar=1,location=1,menubar=1,directories=1,resizable=1,scrollbars=1");
}
});
//if date -> show inner title
if(date != null) {
//info text
display.setTitle(AppController.Lang.SelectWorkout());
display.setCancelButtonVisible(true);
}
//if routine -> show inner title
else if(routine != null) {
//info text
display.setTitle(AppController.Lang.SelectWorkoutToRoutine(routine.getName(), day));
display.setCancelButtonVisible(true);
}
}
@Override
public void onRefresh() {
super.onRefresh();
//highlight and scroll
highlight();
}
@Override
public void onRun() {
//show single workout
if(workoutId != 0) {
final Request req = rpcService.getWorkout(workoutId, new MyAsyncCallback<WorkoutModel>() {
@Override
public void onSuccess(WorkoutModel result) {
showSingleWorkout(result);
}
});
addRequest(req);
}
else {
showMainView();
}
//highlight and scroll
highlight();
}
@Override
public void onStop() {
if(workoutsListSubPresenter != null) {
workoutsListSubPresenter.stop();
}
if(singleWorkoutPresenter != null) {
singleWorkoutPresenter.stop();
}
if(workoutsListSearchPresenter != null) {
workoutsListSearchPresenter.stop();
}
}
/**
* Copies workout ro routine or to our workouts
*/
protected void copyWorkout() {
try {
display.setContentEnabled(false);
//get workout from single presenter
WorkoutModel model = singleWorkoutPresenter.workout;
//reset date
model.setDate(null);
//set routine id if set
if(routine != null) {
model.setRoutineId(routine.getId());
model.setDayInRoutine(day);
}
//add workout
rpcService.addWorkout(model, new MyAsyncCallback<WorkoutModel>() {
@Override
public void onSuccess(WorkoutModel result) {
display.setContentEnabled(true);
//fire event
fireEvent(new WorkoutCreatedEvent(result));
}
});
} catch (Exception e) {
Motiver.showException(e);
}
}
/**
* Moves workout to date
*/
protected void moveWorkoutToDate(List<WorkoutModel> workouts) {
try {
display.setContentEnabled(false);
//set date
for(WorkoutModel model : workouts) {
model.setDate(CommonUtils.trimDateToDatabase(date, true));
}
//add workout
final Request req = rpcService.addWorkouts(workouts, new MyAsyncCallback<List<WorkoutModel>>() {
@Override
public void onSuccess(List<WorkoutModel> result) {
display.setContentEnabled(true);
stop();
List<WorkoutModel> workouts = result;
//fire events
for(WorkoutModel workout : workouts) {
workout.setDate(CommonUtils.trimDateToDatabase(date, true));
//fire event
fireEvent(new WorkoutCreatedEvent(workout));
}
}
});
addRequest(req);
} catch (Exception e) {
Motiver.showException(e);
}
}
/**
* Called when workouts is selected (or selection is set off)
* <br>Shows button to quick select workouts
* @param workout
* @param selected
*/
protected void setQuickSelection(WorkoutModel workout, boolean selected) {
//if new workout
if(selected) {
quickSelectionWorkouts.add(workout);
}
else {
quickSelectionWorkouts.remove(workout);
}
//only if models selected and date not null
display.setQuickSelectionButtonVisible(quickSelectionWorkouts.size() > 0 && date != null, date);
}
/**
* Shows main view
* - my workouts
* - most popular
*/
protected void showMainView() {
lastView = 0;
//show/hide buttons
display.setBackButtonVisible(false);
display.setCopyButtonVisible(false);
display.setMoveToDateButtonVisible(false, null);
display.setMoveToRoutineButtonVisible(false, null);
display.setQuickSelectionButtonVisible(false, null);
if(singleWorkoutPresenter != null) {
singleWorkoutPresenter.stop();
}
singleWorkoutPresenter = null;
if(workoutsListSearchPresenter != null) {
workoutsListSearchPresenter.hide();
}
//run main view
workoutsListSubPresenter.run(display.getDataContainer());
}
/*
* VIEW 3 (single workout
*/
protected void showSingleWorkout(WorkoutModel m) {
try {
if(singleWorkoutPresenter != null) {
singleWorkoutPresenter.stop();
}
//hide main page
if(workoutsListSubPresenter != null) {
workoutsListSubPresenter.hide();
}
if(workoutsListSearchPresenter != null) {
workoutsListSearchPresenter.hide();
}
//show single workout (clear exercises)
singleWorkoutPresenter = new WorkoutPresenter(rpcService, eventBus, (WorkoutDisplay)GWT.create(WorkoutView.class), m);
singleWorkoutPresenter.run(display.getDataContainer());
//buttons
display.setBackButtonVisible(true);
display.setCopyButtonVisible(false);
display.setMoveToDateButtonVisible(false, null);
display.setMoveToRoutineButtonVisible(false, null);
display.setQuickSelectionButtonVisible(false, null);
//show buttons only if workout's id set
if(m.getId() > 0) {
//to routine
if(routine != null) {
display.setMoveToRoutineButtonVisible(true, routine);
}
//if date set
else if(date != null) {
display.setMoveToDateButtonVisible(true, date);
}
else {
//copy to our workouts
if(!m.getUser().equals(AppController.User)) {
display.setCopyButtonVisible(true);
}
}
}
} catch (Exception e) {
Motiver.showException(e);
}
}
/**
* Loads workouts
*/
void loadSearch(final String query) {
lastView = 1;
//show/hide buttons
display.setBackButtonVisible(true);
display.setCopyButtonVisible(false);
display.setMoveToDateButtonVisible(false, null);
display.setMoveToRoutineButtonVisible(false, null);
display.setQuickSelectionButtonVisible(false, null);
if(singleWorkoutPresenter != null) {
singleWorkoutPresenter.stop();
}
singleWorkoutPresenter = null;
if(workoutsListSubPresenter != null) {
workoutsListSubPresenter.hide();
}
//if not already loaded
if(workoutsListSearchPresenter == null || !query.equals(lastQuery)) {
lastQuery = query;
if(workoutsListSearchPresenter != null) {
workoutsListSearchPresenter.stop();
}
boolean quickSelectionEnabled = (date != null);
workoutsListSearchPresenter = new WorkoutsListSearchPresenter(rpcService, eventBus, (WorkoutsListSearchDisplay)GWT.create(WorkoutsListSearchView.class), query, quickSelectionEnabled);
workoutsListSearchPresenter.run(display.getDataContainer());
}
else {
workoutsListSearchPresenter.run(display.getDataContainer());
}
}
}