/*******************************************************************************
* 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.view.statistics;
import java.util.ArrayList;
import java.util.List;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Widget;
import com.delect.motiver.client.AppController;
import com.delect.motiver.client.Motiver;
import com.delect.motiver.client.Templates;
import com.delect.motiver.client.presenter.statistics.StatsExerciseHistoryPresenter;
import com.delect.motiver.client.presenter.statistics.StatsExerciseHistoryPresenter.StatsExerciseHistoryHandler;
import com.delect.motiver.client.view.CustomListener;
import com.delect.motiver.shared.Constants;
import com.delect.motiver.shared.ExerciseNameModel;
import com.delect.motiver.shared.util.CommonUtils;
import com.extjs.gxt.charts.client.Chart;
import com.extjs.gxt.charts.client.model.ChartModel;
import com.extjs.gxt.charts.client.model.ToolTip;
import com.extjs.gxt.charts.client.model.ToolTip.MouseStyle;
import com.extjs.gxt.charts.client.model.axis.XAxis;
import com.extjs.gxt.charts.client.model.axis.YAxis;
import com.extjs.gxt.charts.client.model.charts.HorizontalBarChart;
import com.extjs.gxt.ui.client.core.XTemplate;
import com.extjs.gxt.ui.client.data.BaseListLoader;
import com.extjs.gxt.ui.client.data.BasePagingLoadConfig;
import com.extjs.gxt.ui.client.data.ListLoadResult;
import com.extjs.gxt.ui.client.data.LoadEvent;
import com.extjs.gxt.ui.client.data.Loader;
import com.extjs.gxt.ui.client.data.ModelData;
import com.extjs.gxt.ui.client.data.ModelProcessor;
import com.extjs.gxt.ui.client.data.ModelReader;
import com.extjs.gxt.ui.client.data.RpcProxy;
import com.extjs.gxt.ui.client.event.Events;
import com.extjs.gxt.ui.client.event.FieldEvent;
import com.extjs.gxt.ui.client.event.Listener;
import com.extjs.gxt.ui.client.store.ListStore;
import com.extjs.gxt.ui.client.util.Margins;
import com.extjs.gxt.ui.client.widget.LayoutContainer;
import com.extjs.gxt.ui.client.widget.Text;
import com.extjs.gxt.ui.client.widget.form.ComboBox;
import com.extjs.gxt.ui.client.widget.form.ComboBox.TriggerAction;
import com.extjs.gxt.ui.client.widget.form.ListModelPropertyEditor;
import com.extjs.gxt.ui.client.widget.layout.RowData;
import com.extjs.gxt.ui.client.widget.layout.RowLayout;
public class StatsExerciseHistoryView extends StatsExerciseHistoryPresenter.StatsExerciseHistoryDisplay {
static String[] colors = new String[] {"#EFD279", "#95CBE9", "#024769", "#AFD775", "#2C5700", "#DE9D7F"};
private StatsExerciseHistoryHandler handler;
private ListStore<ExerciseNameModel> store;
LayoutContainer panelData = new LayoutContainer();
public StatsExerciseHistoryView() {
this.setLayout(new RowLayout());
}
@Override
public Widget asWidget() {
//title
Text textTitle = new Text(AppController.Lang.Exercises());
textTitle.setStyleName("label-title-big");
this.add(textTitle, new RowData(-1, -1, new Margins(0, 0, 20, 0)));
//search box
ComboBox<ExerciseNameModel> comboName = addExerciseCombo();
comboName.setWidth("100%");
this.add(comboName, new RowData(1, -1, new Margins(0, 0, 10, 0)));
panelData.setAutoHeight(true);
this.add(panelData);
return this;
}
@Override
public LayoutContainer getBodyContainer() {
return panelData;
}
@Override
public void setExercisesData(List<ExerciseNameModel> exercises) {
try {
//show bar graph
final Chart chart = new Chart(Constants.URL_APP_STATIC+"resources/chart/open-flash-chart.swf");
int height = 100;
if(exercises.size() > 0) {
height = exercises.size() * 40;
}
chart.setHeight(height);
panelData.setHeight(height);
chart.setWidth(600);
HorizontalBarChart bchart = new HorizontalBarChart();
bchart.setTooltip("#val#");
//add values
List<String> list = new ArrayList<String>();
int maxCount = 0;
int i = 0;
for(ExerciseNameModel m : exercises) {
try {
list.add(0, CommonUtils.getExerciseName(m));
int count = Integer.parseInt(m.get("count").toString());
if(count > maxCount) {
maxCount = count;
}
bchart.addBars(new HorizontalBarChart.Bar(count, colors[ (i < colors.length)? i : i - colors.length]));
i++;
} catch (Exception e) {
Motiver.showException(e);
}
}
ChartModel cm = new ChartModel();
cm.setBackgroundColour("#fffff5");
//y-axis
YAxis ya = new YAxis();
ya.setOffset(true);
ya.addLabels(list);
cm.setYAxis(ya);
//x-axis
XAxis xa = new XAxis();
double max = (double)maxCount * 1.3;
max -= max % 10;
cm.setXAxis(xa);
chart.setChartModel(cm);
cm.addChartConfig(bchart);
cm.setTooltipStyle(new ToolTip(MouseStyle.NORMAL));
panelData.removeAll();
panelData.add(chart);
panelData.layout();
} catch (Exception e) {
Motiver.showException(e);
}
}
@Override
public void setHandler(StatsExerciseHistoryHandler handler) {
this.handler = handler;
}
/**
* Adds exercise search combo
*/
protected ComboBox<ExerciseNameModel> addExerciseCombo() {
final ComboBox<ExerciseNameModel> combo = new ComboBox<ExerciseNameModel>();
//custom editors so we see also target correctly
combo.setPropertyEditor(new ListModelPropertyEditor<ExerciseNameModel>() {
@Override
public ExerciseNameModel convertStringValue(String value) {
return store.findModel("fn", value);
}
@Override
public String getStringValue(ExerciseNameModel value) {
return CommonUtils.getExerciseName(value);
}
});
//set fullname to "fn" so we see target correctly
combo.getView().setModelProcessor(new ModelProcessor<ExerciseNameModel>() {
@Override
public ExerciseNameModel prepareData(ExerciseNameModel model) {
model.set("fn", CommonUtils.getExerciseName(model));
return model;
}
});
// proxy, reader and loader
RpcProxy<List<ExerciseNameModel>> proxy = new RpcProxy<List<ExerciseNameModel>>() {
@Override
protected void load(Object loadConfig, AsyncCallback<List<ExerciseNameModel>> callback) {
BasePagingLoadConfig config = (BasePagingLoadConfig)loadConfig;
handler.query(config.get("query").toString(), callback);
}
};
ModelReader reader = new ModelReader();
BaseListLoader<ListLoadResult<ModelData>> loader = new BaseListLoader<ListLoadResult<ModelData>>(proxy, reader);
loader.addListener(Loader.BeforeLoad, new Listener<LoadEvent>() {
public void handleEvent(LoadEvent be) {
be.<ModelData>getConfig().set("start", be.<ModelData>getConfig().get("offset"));
}
});
store = new ListStore<ExerciseNameModel>(loader);
combo.addListener(Events.OnMouseOver, CustomListener.fieldMouseOver);
combo.addListener(Events.OnMouseOut, CustomListener.fieldMouseOut);
combo.setWidth(300);
combo.setForceSelection(true);
combo.setMessageTarget("none");
combo.setDisplayField("fn");
combo.setTemplate(XTemplate.create(Templates.getExerciseNameTemplate()) );
combo.setStore(store);
combo.setEmptyText(AppController.Lang.EnterKeywordToSearchForExercises());
combo.setHideTrigger(true);
combo.setTriggerAction(TriggerAction.ALL);
combo.addListener(Events.Valid, new Listener<FieldEvent>() {
@SuppressWarnings("unchecked")
@Override
public void handleEvent(FieldEvent be) {
try {
ComboBox<ExerciseNameModel> cb = ((ComboBox<ExerciseNameModel>)be.getSource());
//if selected something from the list
if(cb.getSelection().size() > 0) {
ExerciseNameModel mo = cb.getSelection().get(0);
handler.selected(mo);
}
} catch (Exception e) {
Motiver.showException(e);
}
}
});
return combo;
}
}