com.googlecode.gflot.client.PlotWithInteractiveLegend.java Source code

Java tutorial

Introduction

Here is the source code for com.googlecode.gflot.client.PlotWithInteractiveLegend.java

Source

/*
 * Copyright (c) 2012 Nicolas Morel
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */
package com.googlecode.gflot.client;

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import com.google.gwt.dom.client.Style.BorderStyle;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HasValue;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.googlecode.gflot.client.PlotModel.PlotModelListener;
import com.googlecode.gflot.client.event.PlotClickListener;
import com.googlecode.gflot.client.event.PlotHoverListener;
import com.googlecode.gflot.client.event.PlotLoadEvent;
import com.googlecode.gflot.client.event.PlotSelectedListener;
import com.googlecode.gflot.client.event.PlotSelectingListener;
import com.googlecode.gflot.client.event.PlotUnselectedListener;
import com.googlecode.gflot.client.jsni.JsonObject;
import com.googlecode.gflot.client.jsni.Plot;

/**
 * @author Alexander De Leon
 */
public class PlotWithInteractiveLegend extends Composite
        implements PlotWidget, PlotModelListener, PlotLoadEvent.Handler {

    protected final PlotWidget plot;
    protected Panel legendPanel;
    private final Map<SeriesHandler, LegendItem> legend;

    public PlotWithInteractiveLegend(PlotWidget plot) {
        legend = new HashMap<SeriesHandler, LegendItem>();
        this.plot = plot;
        addLoadHandler(this);
        initWidget(createUi());
        buildLegendFromModel(plot.getModel());
    }

    private void buildLegendFromModel(PlotModel model) {
        for (SeriesHandler seriesHandler : model.getHandlers()) {
            addSeriesToLegend(seriesHandler);
        }
        model.addListener(this);
    }

    public void addClickListener(PlotClickListener listener, boolean onlyOnDatapoint) {
        plot.addClickListener(listener, onlyOnDatapoint);
    }

    public void addHoverListener(PlotHoverListener listener, boolean onlyOnDatapoint) {
        plot.addHoverListener(listener, onlyOnDatapoint);
    }

    public void addSelectedListener(PlotSelectedListener listener) {
        plot.addSelectedListener(listener);
    }

    @Override
    public void addSelectingListener(final PlotSelectingListener listener) {
        plot.addSelectingListener(listener);
    }

    @Override
    public void addUnselectedListener(final PlotUnselectedListener listener) {
        plot.addUnselectedListener(listener);
    }

    @Override
    public PlotSelectionArea getSelection() {
        return plot.getSelection();
    }

    @Override
    public void setSelection(PlotSelectionArea area) {
        plot.setSelection(area);
    }

    @Override
    public void setSelection(PlotSelectionArea area, boolean preventEvent) {
        plot.setSelection(area, preventEvent);
    }

    @Override
    public void clearSelection() {
        plot.clearSelection();
    }

    @Override
    public void clearSelection(boolean preventEvent) {
        plot.clearSelection(preventEvent);
    }

    public int getHeight() {
        return plot.getHeight();
    }

    public int getWidth() {
        return plot.getWidth();
    }

    public void setHeight(int height) {
        plot.setHeight(height);
    }

    public void setLinearSelection(double x1, double x2) {
        plot.setLinearSelection(x1, x2);
    }

    public void setRectangularSelection(double x1, double y1, double x2, double y2) {
        plot.setRectangularSelection(x1, y1, x2, y2);
    }

    public void setWidth(int width) {
        plot.setWidth(width);
    }

    public void redraw() {
        plot.redraw();
    }

    public Widget getWidget() {
        return this;
    }

    public PlotModel getModel() {
        return plot.getModel();
    }

    public void onAddSeries(PlotModel model, SeriesHandler handler) {
        addSeriesToLegend(handler);
    }

    public void onRemoveSeries(PlotModel model, SeriesHandler handler) {
        legendPanel.remove(legend.get(handler));
        legend.remove(handler);
    }

    /* --------------------- helper methods -- */
    private void addSeriesToLegend(final SeriesHandler handler) {
        LegendItem item = createLegendItem();
        item.addValueChangeHandler(new ValueChangeHandler<Boolean>() {
            @Override
            public void onValueChange(ValueChangeEvent<Boolean> event) {
                handler.setVisible(event.getValue());
                plot.redraw();
            }
        });
        legend.put(handler, item);
        legendPanel.add(item);
    }

    protected LegendItem createLegendItem() {
        return new DefaultLegendItem();
    }

    protected Widget createUi() {
        VerticalPanel panel = new VerticalPanel();

        legendPanel = new HorizontalPanel();
        legendPanel.getElement().getStyle().setMarginBottom(5, Unit.PX);

        panel.add(legendPanel);
        panel.add(plot);

        return panel;
    }

    public void setSerieVisible(SeriesHandler handler, boolean visible, boolean redraw) {
        handler.setVisible(visible);
        legend.get(handler).setValue(visible, false);
        if (redraw) {
            plot.redraw();
        }
    }

    protected abstract class LegendItem extends Composite implements HasValue<Boolean> {
        protected LegendItem() {
            init();
        }

        protected abstract void init();

        protected abstract void update(String color, String label);
    }

    /**
     * Class for the legend item widget
     */
    protected class DefaultLegendItem extends LegendItem {
        protected static final String COLOR_BAND_HEIGHT = "3px";

        protected SimplePanel panel;

        protected CheckBox checkBox;

        @Override
        protected void init() {
            panel = new SimplePanel();
            panel.getElement().getStyle().setPaddingTop(2, Unit.PX);
            panel.getElement().getStyle().setMarginRight(5, Unit.PX);
            panel.getElement().getStyle().setProperty("borderTopStyle", BorderStyle.SOLID.getCssName());
            panel.getElement().getStyle().setProperty("borderTopWidth", 3, Unit.PX);

            checkBox = new CheckBox();
            checkBox.setValue(true);

            panel.setWidget(checkBox);

            initWidget(panel);
        }

        @Override
        protected void update(String color, String seriesLabel) {
            panel.getElement().getStyle().setProperty("borderTopColor", color);
            checkBox.setText(seriesLabel);
        }

        @Override
        public HandlerRegistration addValueChangeHandler(ValueChangeHandler<Boolean> handler) {
            return checkBox.addValueChangeHandler(handler);
        }

        @Override
        public Boolean getValue() {
            return checkBox.getValue();
        }

        @Override
        public void setValue(Boolean value) {
            checkBox.setValue(value);
        }

        @Override
        public void setValue(Boolean value, boolean fireEvents) {
            checkBox.setValue(value, fireEvents);
        }

    }

    @Override
    public HandlerRegistration addLoadHandler(PlotLoadEvent.Handler handler) {
        return plot.addLoadHandler(handler);
    }

    @Override
    public void onLoad(PlotLoadEvent event) {
        updateLegend();
    }

    private void updateLegend() {
        for (Entry<SeriesHandler, LegendItem> entry : legend.entrySet()) {
            int index = plot.getModel().indexOf(entry.getKey());
            JsonObject series = plot.getPlot().getData().get(index);

            // if no data is given to flot, it puts the label inside a data object...
            String label = null;
            if (series.hasKey("label")) {
                label = series.getString("label");
            } else if (series.hasKey("data")) {
                JsonObject data = series.getJsObject("data");
                if (data.hasKey("label")) {
                    label = data.getString("label");
                }
            }

            String color = series.getString("color");
            entry.getValue().update(color, label);
        }
    }

    @Override
    public Plot getPlot() {
        return plot.getPlot();
    }

}