ch.opentrainingcenter.client.views.ngchart.DynamicChartViewPart.java Source code

Java tutorial

Introduction

Here is the source code for ch.opentrainingcenter.client.views.ngchart.DynamicChartViewPart.java

Source

/**
 *    OpenTrainingCenter
 *
 *    Copyright (C) 2013 Sascha Iseli sascha.iseli(at)gmx.ch
 *
 *    This program is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package ch.opentrainingcenter.client.views.ngchart;

import java.text.DateFormat;
import java.text.DateFormatSymbols;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import org.apache.log4j.Logger;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.ScrolledForm;
import org.eclipse.ui.forms.widgets.Section;
import org.eclipse.ui.forms.widgets.TableWrapData;
import org.eclipse.ui.forms.widgets.TableWrapLayout;
import org.eclipse.ui.part.ViewPart;
import org.joda.time.DateTime;
import org.joda.time.DateTimeFieldType;

import ch.opentrainingcenter.charts.bar.OTCCategoryChartViewer;
import ch.opentrainingcenter.charts.ng.TrainingChart;
import ch.opentrainingcenter.charts.single.XAxisChart;
import ch.opentrainingcenter.client.Activator;
import ch.opentrainingcenter.client.ui.FormToolkitSupport;
import ch.opentrainingcenter.client.ui.datepicker.DateWidget;
import ch.opentrainingcenter.client.views.ApplicationContext;
import ch.opentrainingcenter.core.PreferenceConstants;
import ch.opentrainingcenter.core.cache.Event;
import ch.opentrainingcenter.core.cache.IRecordListener;
import ch.opentrainingcenter.core.cache.TrainingCache;
import ch.opentrainingcenter.core.charts.IStatistikCreator;
import ch.opentrainingcenter.core.charts.PastTraining;
import ch.opentrainingcenter.core.charts.StatistikFactory;
import ch.opentrainingcenter.core.charts.TrainingCalculator;
import ch.opentrainingcenter.core.data.SimplePair;
import ch.opentrainingcenter.core.db.IDatabaseAccess;
import ch.opentrainingcenter.core.helper.ColorFromPreferenceHelper;
import ch.opentrainingcenter.core.helper.TimeHelper;
import ch.opentrainingcenter.core.service.IDatabaseService;
import ch.opentrainingcenter.i18n.Messages;
import ch.opentrainingcenter.model.training.filter.Filter;
import ch.opentrainingcenter.model.training.filter.FilterFactory;
import ch.opentrainingcenter.model.training.filter.TrainingFilter;
import ch.opentrainingcenter.transfer.IAthlete;
import ch.opentrainingcenter.transfer.ITraining;
import ch.opentrainingcenter.transfer.Sport;

public class DynamicChartViewPart extends ViewPart implements IRecordListener<ITraining> {

    private static final String PFEIL = " -----> "; //$NON-NLS-1$
    public static final String ID = "ch.opentrainingcenter.client.views.ngchart.DynamicChart"; //$NON-NLS-1$
    private static final DateFormat DATE_FORMAT = DateFormat.getDateInstance(DateFormat.LONG, Locale.getDefault());

    private static final String[] NEW_SHORT_WEEKDAYS = new String[] { "", Messages.DynamicChartViewPart_Montag, // //$NON-NLS-1$
            Messages.DynamicChartViewPart_Dienstag, Messages.DynamicChartViewPart_Mittwoch, //
            Messages.DynamicChartViewPart_Donnerstag, Messages.DynamicChartViewPart_Freitag, //
            Messages.DynamicChartViewPart_Samstag, Messages.DynamicChartViewPart_Sonntag };

    private static final Logger LOGGER = Logger.getLogger(DynamicChartViewPart.class);

    private FormToolkit toolkit;
    private ScrolledForm form;

    private final IDatabaseAccess databaseAccess;
    private final IPreferenceStore store;
    private final OTCCategoryChartViewer chartViewer;
    private final IAthlete athlete;

    private Section sectionChart;
    private Section sectionLegende;

    private DateWidget dateVon;
    private DateWidget dateBis;

    private Combo tagMonatJahrCombo;
    private Combo yAchseCombo;
    private Button compareWithLastYear;
    private Label labelIconPastPast;
    private Label labelTextPastPast;
    private Label labelIconPast;
    private Label labelTextPast;
    private Label labelIconNow;
    private Label labelTextNow;
    private Combo comboSport;
    private org.joda.time.DateTime von;

    public DynamicChartViewPart() {
        this((IDatabaseService) PlatformUI.getWorkbench().getService(IDatabaseService.class),
                Activator.getDefault().getPreferenceStore(),
                ApplicationContext.getApplicationContext().getAthlete());
    }

    /**
     * Fuer Tests
     */
    public DynamicChartViewPart(final IDatabaseService service, final IPreferenceStore store,
            final IAthlete athlete) {
        LOGGER.debug("<< --- DynamicChartViewPart"); //$NON-NLS-1$
        databaseAccess = service.getDatabaseAccess();
        this.store = store;
        this.athlete = athlete;
        chartViewer = new OTCCategoryChartViewer(store);
        TrainingCache.getInstance().addListener(this);
        LOGGER.debug("DynamicChartViewPart --- >>"); //$NON-NLS-1$
    }

    @Override
    public void createPartControl(final Composite parent) {

        toolkit = new FormToolkit(parent.getDisplay());
        form = toolkit.createScrolledForm(parent);

        toolkit.decorateFormHeading(form.getForm());

        form.setText(Messages.DynamicChartViewPart_0);
        final Composite body = form.getBody();

        final TableWrapLayout layout = new TableWrapLayout();
        layout.makeColumnsEqualWidth = true;
        layout.numColumns = 1;
        body.setLayout(layout);

        addFilterSection(body);

        addChartSection(body);

        addLegendeSection(body);

        update();
    }

    private void addFilterSection(final Composite body) {
        final Section sectionFilter = toolkit.createSection(body, FormToolkitSupport.SECTION_STYLE);
        sectionFilter.setExpanded(true);
        sectionFilter.setText(Messages.DynamicChartViewPart_1);
        sectionFilter.setDescription(Messages.DynamicChartViewPart_2);

        final TableWrapData td = new TableWrapData(TableWrapData.FILL_GRAB);
        td.colspan = 1;
        td.grabHorizontal = true;
        td.grabVertical = true;
        sectionFilter.setLayoutData(td);

        final Composite container = toolkit.createComposite(sectionFilter);
        GridLayoutFactory.swtDefaults().numColumns(7).applyTo(container);

        final Label lDay = new Label(container, SWT.NONE);
        lDay.setText(Messages.DynamicChartViewPart_3);
        GridDataFactory.swtDefaults().align(SWT.RIGHT, SWT.CENTER).applyTo(lDay);

        tagMonatJahrCombo = new Combo(container, SWT.READ_ONLY);
        tagMonatJahrCombo.setBounds(50, 50, 150, 65);

        tagMonatJahrCombo.setItems(XAxisChart.items());
        tagMonatJahrCombo.select(store.getInt(PreferenceConstants.CHART_XAXIS_CHART));
        tagMonatJahrCombo.addSelectionListener(new UpdateSelectionAdapter());

        final Label y = new Label(container, SWT.NONE);
        y.setText(Messages.DynamicChartViewPart_4);
        GridDataFactory.swtDefaults().align(SWT.RIGHT, SWT.CENTER).applyTo(y);

        yAchseCombo = new Combo(container, SWT.READ_ONLY);
        yAchseCombo.setItems(TrainingChart.items());
        yAchseCombo.select(store.getInt(PreferenceConstants.CHART_YAXIS_CHART));
        yAchseCombo.addSelectionListener(new UpdateSelectionAdapter());
        final XAxisChart cst = XAxisChart.getByIndex(tagMonatJahrCombo.getSelectionIndex());

        compareWithLastYear = new Button(container, SWT.CHECK);
        compareWithLastYear.setText(Messages.DynamicChartViewPart_9);
        compareWithLastYear.setEnabled(!XAxisChart.DAY.equals(cst));
        compareWithLastYear.setSelection(store.getBoolean(PreferenceConstants.CHART_COMPARE));
        compareWithLastYear.setToolTipText(Messages.DynamicChartViewPart_10);
        compareWithLastYear.addSelectionListener(new UpdateSelectionAdapter());

        GridDataFactory.swtDefaults().align(SWT.BEGINNING, SWT.BEGINNING).span(3, 1).applyTo(compareWithLastYear);
        // ------- neue Zeile
        final Label vonLabel = toolkit.createLabel(container, Messages.DynamicChartViewPart_6);
        von = org.joda.time.DateTime.now().minusWeeks(store.getInt(PreferenceConstants.CHART_WEEKS));

        final DateFormatSymbols symbols = DateFormatSymbols.getInstance(Locale.getDefault());
        symbols.setShortWeekdays(NEW_SHORT_WEEKDAYS);

        dateVon = new DateWidget(container, SWT.BORDER | SWT.DATE | SWT.DROP_DOWN);
        dateVon.setDate(von);
        dateVon.addSelectionListener(new UpdateSelectionAdapter());
        GridDataFactory.swtDefaults().align(SWT.RIGHT, SWT.CENTER).applyTo(vonLabel);

        final Label bisLabel = toolkit.createLabel(container, Messages.DynamicChartViewPart_7);

        dateBis = new DateWidget(container, SWT.BORDER | SWT.DATE | SWT.DROP_DOWN);
        dateBis.setDate(DateTime.now());
        dateBis.addSelectionListener(new UpdateSelectionAdapter());
        GridDataFactory.swtDefaults().align(SWT.RIGHT, SWT.CENTER).applyTo(bisLabel);

        comboSport = new Combo(container, SWT.READ_ONLY);
        comboSport.setItems(Sport.items());
        comboSport.select(store.getInt(PreferenceConstants.CHART_SPORT));
        comboSport.addSelectionListener(new SelectionAdapter() {

            @Override
            public void widgetSelected(final SelectionEvent e) {
                update();
            }

        });

        sectionFilter.setClient(container);
    }

    private class UpdateSelectionAdapter extends SelectionAdapter {
        @Override
        public void widgetSelected(final SelectionEvent e) {
            update();
        }
    }

    private void addChartSection(final Composite body) {
        sectionChart = toolkit.createSection(body, FormToolkitSupport.SECTION_STYLE);
        sectionChart.setExpanded(false);
        sectionChart.setText(Messages.DynamicChartViewPart_8);

        final TableWrapData td = new TableWrapData(TableWrapData.FILL_GRAB);
        td.colspan = 1;
        td.grabHorizontal = true;
        td.grabVertical = true;
        sectionChart.setLayoutData(td);

        final Composite container = toolkit.createComposite(sectionChart);
        GridLayoutFactory.swtDefaults().numColumns(1).applyTo(container);
        GridDataFactory.swtDefaults().grab(true, true).align(SWT.FILL, SWT.FILL).hint(SWT.DEFAULT, 400)
                .applyTo(container);

        chartViewer.setParent(container);
        chartViewer.createPartControl();

        sectionChart.setClient(container);
    }

    private void addLegendeSection(final Composite body) {
        sectionLegende = toolkit.createSection(body, FormToolkitSupport.SECTION_STYLE);
        sectionLegende.setExpanded(false);
        sectionLegende.setText(Messages.DynamicChartViewPart_Legende);

        final TableWrapData td = new TableWrapData(TableWrapData.FILL_GRAB);
        td.colspan = 1;
        td.grabHorizontal = true;
        td.grabVertical = true;
        sectionLegende.setLayoutData(td);

        final Composite container = toolkit.createComposite(sectionLegende);
        GridLayoutFactory.swtDefaults().numColumns(2).applyTo(container);
        GridDataFactory.swtDefaults().grab(true, true).align(SWT.FILL, SWT.FILL).hint(SWT.DEFAULT, 400)
                .applyTo(container);

        labelIconNow = new Label(container, SWT.NONE);
        labelTextNow = new Label(container, SWT.NONE);

        labelIconPast = new Label(container, SWT.NONE);
        labelIconPast.setVisible(false);

        labelTextPast = new Label(container, SWT.NONE);
        labelTextPast.setVisible(false);

        labelIconPastPast = new Label(container, SWT.NONE);
        labelIconPastPast.setVisible(false);

        labelTextPastPast = new Label(container, SWT.NONE);
        labelTextPastPast.setVisible(false);

        sectionLegende.setClient(container);
    }

    private Image createImage(final Color color) {
        final Display display = PlatformUI.getWorkbench().getDisplay();
        final Image image = new Image(display, 32, 32);
        final GC gc = new GC(image);

        gc.setBackground(color);
        gc.fillRectangle(new Rectangle(0, 0, 32, 32));
        gc.dispose();

        return image;
    }

    private void update() {
        Display.getDefault().asyncExec(new Runnable() {

            @Override
            public void run() {
                final XAxisChart xAxis = XAxisChart.getByIndex(tagMonatJahrCombo.getSelectionIndex());
                compareWithLastYear.setEnabled(!XAxisChart.DAY.equals(xAxis));
                final SimplePair<Date> startEnd = getStartEnd();
                final String start = TimeHelper.convertDateToString(startEnd.getFirst());
                final String end = TimeHelper.convertDateToString(startEnd.getSecond());
                LOGGER.info(String.format("Chart now      %s von %s bis %s", xAxis, start, end)); //$NON-NLS-1$

                final int sportIndex = comboSport.getSelectionIndex();
                final Sport sport = Sport.getByIndex(sportIndex);

                final List<ITraining> dataNow = getFilteredData(xAxis, startEnd.getFirst(), startEnd.getSecond(),
                        sport);

                final DateTime dtStartCurrent = new DateTime(startEnd.getFirst().getTime());
                final DateTime dtEndCurrent = new DateTime(startEnd.getSecond().getTime());

                final Date startPastOne = dtStartCurrent.minusYears(1).toDate();
                final Date endPastOne = dtEndCurrent.minusYears(1).toDate();
                final String readablePastStartOne = TimeHelper.convertDateToString(startPastOne);
                final String readablePastEndOne = TimeHelper.convertDateToString(endPastOne);
                LOGGER.info(String.format("Chart past One %s von %s bis %s", xAxis, readablePastStartOne, //$NON-NLS-1$
                        readablePastEndOne));
                final List<ITraining> dataPastOne = getFilteredData(xAxis, startPastOne, endPastOne, sport);

                final Date startPastTwo = dtStartCurrent.minusYears(2).toDate();
                final Date endPastTwo = dtEndCurrent.minusYears(2).toDate();
                final String readablePastStart2 = TimeHelper.convertDateToString(startPastTwo);
                final String readablePastEnd2 = TimeHelper.convertDateToString(endPastTwo);
                LOGGER.info(String.format("Chart past Two %s von %s bis %s", xAxis, readablePastStart2, //$NON-NLS-1$
                        readablePastEnd2));
                final List<ITraining> dataPastTwo = getFilteredData(xAxis, startPastTwo, endPastTwo, sport);

                final List<PastTraining> past = new ArrayList<>();
                past.add(new PastTraining(2, dataPastTwo));
                past.add(new PastTraining(1, dataPastOne));

                final TrainingChart chartType = TrainingChart.getByIndex(yAchseCombo.getSelectionIndex());
                final boolean compareLast = compareWithLastYear.getSelection();

                chartViewer.updateData(dataNow, past, xAxis, chartType, compareLast);
                chartViewer.updateRenderer(xAxis, chartType, compareLast);
                chartViewer.forceRedraw();
                sectionChart.setExpanded(true);
                final java.awt.Color color;
                if (TrainingChart.DISTANZ.equals(chartType)) {
                    color = ColorFromPreferenceHelper.getColor(store, PreferenceConstants.CHART_DISTANCE_COLOR,
                            255);
                } else {
                    color = ColorFromPreferenceHelper.getColor(store, PreferenceConstants.CHART_HEART_COLOR, 255);
                }

                labelIconNow.setImage(createImage(ColorFromPreferenceHelper.awtColor2swtColot(color)));
                labelIconPast.setImage(createImage(ColorFromPreferenceHelper.awtColor2swtColot(color.brighter())));
                labelIconPastPast.setImage(
                        createImage(ColorFromPreferenceHelper.awtColor2swtColot(color.brighter().brighter())));

                labelTextNow.setText(DATE_FORMAT.format(dtStartCurrent.toDate()) + PFEIL
                        + DATE_FORMAT.format(dtEndCurrent.toDate()));
                labelTextPast.setText(DATE_FORMAT.format(startPastOne) + PFEIL + DATE_FORMAT.format(endPastOne));
                labelTextPastPast
                        .setText(DATE_FORMAT.format(startPastTwo) + PFEIL + DATE_FORMAT.format(endPastTwo));

                labelIconPast.setVisible(compareLast);
                labelTextPast.setVisible(compareLast);
                labelIconPastPast.setVisible(compareLast);
                labelTextPastPast.setVisible(compareLast);

                sectionLegende.setExpanded(true);
            }

        });
    }

    private SimplePair<Date> getStartEnd() {
        final XAxisChart xAxis = XAxisChart.getByIndex(tagMonatJahrCombo.getSelectionIndex());
        final boolean year = XAxisChart.YEAR.equals(xAxis);
        final boolean yearTillNow = XAxisChart.YEAR_START_TILL_NOW.equals(xAxis);
        Date start = dateVon.getDate().toDate();// von.toDate();
        Date end = dateBis.getDate().toDate();// DateTime.now().toDate();
        dateVon.setEnabled(!(yearTillNow || year));
        dateBis.setEnabled(!year);
        if (yearTillNow || year) {
            final int yStart = new DateTime(end.getTime()).get(DateTimeFieldType.year());
            start = TimeHelper.getDate(yStart, 0, 1);
            dateVon.setEnabled(false);
        }
        if (year) {
            final int yEnd = new DateTime(end.getTime()).get(DateTimeFieldType.year());
            end = TimeHelper.getDate(yEnd, 11, 31);
            dateBis.setEnabled(false);
        }
        return new SimplePair<Date>(start, end);
    }

    private List<ITraining> getFilteredData(final XAxisChart xAxisChart, final Date start, final Date end,
            final Sport sport) {
        final List<ITraining> allTrainings = databaseAccess.getAllTrainings(athlete);
        final List<ITraining> filtered = filter(allTrainings, start, end, sport);
        return createSum(filtered, xAxisChart, StatistikFactory.createStatistik());
    }

    List<ITraining> filter(final List<ITraining> allTrainings, final Date start, final Date end,
            final Sport sport) {
        final List<ITraining> filteredData = new ArrayList<>();
        final List<Filter<ITraining>> filters = new ArrayList<>();
        filters.add(FilterFactory.createFilterByDate(start, end));
        filters.add(FilterFactory.createFilterBySport(sport));
        final TrainingFilter filter = new TrainingFilter(filters);
        for (final ITraining training : allTrainings) {
            if (filter.matches(training)) {
                filteredData.add(training);
            }
        }
        return filteredData;
    }

    List<ITraining> createSum(final List<ITraining> filteredData, final XAxisChart xAxisChart,
            final IStatistikCreator statistik) {
        switch (xAxisChart) {
        case DAY:
            return statistik.getTrainingsProTag(filteredData);
        case WEEK:
            return TrainingCalculator.createSum(statistik.getTrainingsProWoche(filteredData));
        case MONTH:
            return TrainingCalculator.createSum(statistik.getTrainingsProMonat(filteredData));
        case YEAR:
            // fall through
        case YEAR_START_TILL_NOW:
            final Map<Integer, List<ITraining>> trainingsProJahr = statistik.getTrainingsProJahr(filteredData);
            final Map<Integer, Map<Integer, List<ITraining>>> tmp = new HashMap<Integer, Map<Integer, List<ITraining>>>();
            tmp.put(1, trainingsProJahr);
            return TrainingCalculator.createSum(tmp);
        default:
            throw new IllegalArgumentException("Es sind nicht alle Enum Werte abgebildet!!!!"); //$NON-NLS-1$
        }
    }

    @Override
    public void setFocus() {
        if (dateVon != null) {
            dateVon.setFocus();
        }
    }

    @Override
    public void dispose() {
        TrainingCache.getInstance().removeListener(this);
        dateVon.dispose();
        dateBis.dispose();
        super.dispose();
    }

    @Override
    public void onEvent(final Collection<ITraining> entry, final Event event) {
        update();
    }

}