org.dussan.vaadin.dcharts.DCharts.java Source code

Java tutorial

Introduction

Here is the source code for org.dussan.vaadin.dcharts.DCharts.java

Source

/**
 * Copyright (C) 2012-2013  Duan Vejnovi?  <vaadin@dussan.org>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.dussan.vaadin.dcharts;

import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import javax.imageio.ImageIO;

import org.apache.commons.codec.binary.Base64;
import org.dussan.vaadin.dcharts.client.rpc.DChartsClientRPC;
import org.dussan.vaadin.dcharts.client.rpc.DChartsServerRpc;
import org.dussan.vaadin.dcharts.data.DataSeries;
import org.dussan.vaadin.dcharts.events.ChartData;
import org.dussan.vaadin.dcharts.events.chartImageChange.ChartImageChangeEvent;
import org.dussan.vaadin.dcharts.events.chartImageChange.ChartImageChangeHandler;
import org.dussan.vaadin.dcharts.events.click.ChartDataClickEvent;
import org.dussan.vaadin.dcharts.events.click.ChartDataClickHandler;
import org.dussan.vaadin.dcharts.events.mouseenter.ChartDataMouseEnterEvent;
import org.dussan.vaadin.dcharts.events.mouseenter.ChartDataMouseEnterHandler;
import org.dussan.vaadin.dcharts.events.mouseleave.ChartDataMouseLeaveEvent;
import org.dussan.vaadin.dcharts.events.mouseleave.ChartDataMouseLeaveHandler;
import org.dussan.vaadin.dcharts.events.rightclick.ChartDataRightClickEvent;
import org.dussan.vaadin.dcharts.events.rightclick.ChartDataRightClickHandler;
import org.dussan.vaadin.dcharts.helpers.ChartDataHelper;
import org.dussan.vaadin.dcharts.helpers.ManifestHelper;
import org.dussan.vaadin.dcharts.options.Options;

import com.google.gwt.event.shared.HandlerManager;
import com.vaadin.server.FileDownloader;
import com.vaadin.server.StreamResource;
import com.vaadin.server.StreamResource.StreamSource;
import com.vaadin.ui.AbstractSingleComponentContainer;
import com.vaadin.ui.Button;
import com.vaadin.ui.Notification;
import com.vaadin.ui.Notification.Type;

public class DCharts extends AbstractSingleComponentContainer {

    private static final long serialVersionUID = -7224003274781707144L;
    private static final int ID = 0;
    private static final int DECIMAL_SEPARATOR = 1;
    private static final int THOUSANDS_SEPARATOR = 2;
    private static final int DATA_SERIES = 3;
    private static final int OPTIONS = 4;
    private static final int SHOW_CHART = 5;
    private static final int REPLOT_CHART_CLEAR = 6;
    private static final int REPLOT_CHART_RESET_AXES = 7;
    private static final int MARGIN_TOP = 8;
    private static final int MARGIN_RIGHT = 9;
    private static final int MARGIN_BOTTOM = 10;
    private static final int MARGIN_LEFT = 11;
    private static final int MOUSE_ENTER_EVENT = 12;
    private static final int MOUSE_LEAVE_EVENT = 13;
    private static final int CLICK_EVENT = 14;
    private static final int RIGHT_CLICK_EVENT = 15;
    private static final int CHART_IMAGE_CHANGE_DELAY = 16;
    private static final int CHART_IMAGE_CHANGE_EVENT = 17;
    private static final int DOWNLOAD_BUTTON_ENABLE = 18;
    private static final int DOWNLOAD_BUTTON_LOCATION = 19;

    private byte[] chartImage = null;
    private int chartImageChangeDelay;
    private Map<Integer, String> chartData = null;
    private ChartImageFormat chartImageFormat = null;

    private HandlerManager handlerManager = null;
    private DataSeries dataSeries = null;
    private Options options = null;

    private Boolean downloadButtonEnable = null;
    private Button downloadButton = null;
    private String downloadFilename = null;
    private DownloadButtonLocation downloadButtonLocation = null;
    private FileDownloader fileDownloader = null;

    private String chartId = null;
    private String decimalSeparator = null;
    private String thousandsSeparator = null;
    private Integer marginTop = null;
    private Integer marginRight = null;
    private Integer marginBottom = null;
    private Integer marginLeft = null;

    private Boolean enableChartDataMouseEnterEvent = null;
    private Boolean enableChartDataMouseLeaveEvent = null;
    private Boolean enableChartDataClickEvent = null;
    private Boolean enableChartDataRightClickEvent = null;
    private Boolean enableChartImageChangeEvent = null;

    public DCharts() {
        chartId = "dCharts-" + ((long) (Math.random() * 10000000000000000L));
        // set init chart's dimensions
        setSizeFull();

        marginTop = 0;
        marginRight = 0;
        marginBottom = 0;
        marginLeft = 0;

        handlerManager = new HandlerManager(this);
        enableChartDataMouseEnterEvent = false;
        enableChartDataMouseLeaveEvent = false;
        enableChartDataClickEvent = false;
        enableChartDataRightClickEvent = false;
        enableChartImageChangeEvent = false;

        chartImageChangeDelay = 600;
        chartData = new HashMap<Integer, String>();
        chartImageFormat = ChartImageFormat.PNG;

        downloadButtonEnable = false;
        downloadFilename = "chart";
        downloadButtonLocation = DownloadButtonLocation.TOP_RIGHT;

        addChartContainer();
        registerRpc(new DChartsServerRpc() {
            private static final long serialVersionUID = -3805014254043430235L;

            @Override
            public void onEventFired(Map<String, String> eventData) {
                processEvent(eventData);
            }
        });
    }

    public DCharts(String caption, String idChart, DataSeries dataSeries, Options options) {
        this();
        setCaption(caption);
        this.dataSeries = dataSeries;
        this.options = options;
    }

    public DCharts(String caption, DataSeries dataSeries, Options options) {
        this();
        setCaption(caption);
        this.dataSeries = dataSeries;
        this.options = options;
    }

    public DCharts(DataSeries dataSeries, Options options) {
        this();
        this.dataSeries = dataSeries;
        this.options = options;
    }

    public DCharts(String caption, DataSeries dataSeries) {
        this();
        setCaption(caption);
        this.dataSeries = dataSeries;
    }

    public DCharts(DataSeries dataSeries) {
        this();
        this.dataSeries = dataSeries;
    }

    private StreamResource getChartResource() {
        return new StreamResource(new StreamSource() {
            private static final long serialVersionUID = -6463786579404065303L;

            @Override
            public InputStream getStream() {
                try {
                    ByteArrayOutputStream bos = new ByteArrayOutputStream();
                    ImageIO.write(getChartImage(), getChartImageFormat().getFormat(), bos);
                    return new ByteArrayInputStream(bos.toByteArray());
                } catch (Exception e) {
                    return new ByteArrayInputStream("".getBytes());
                }
            }
        }, getDownloadFilename() + getChartImageFormat().getFormatExtension());
    }

    private void addChartContainer() {
        chartData.put(ID, chartId);

        downloadButton = new Button("Download chart");
        downloadButton.setId(chartId + "-button");
        downloadButton.addStyleName("small");
        downloadButton.setSizeUndefined();
        setContent(downloadButton);

        fileDownloader = new FileDownloader(getChartResource());
        fileDownloader.extend(downloadButton);

        setSizeFull();
        markAsDirty();
    }

    private void processEvent(Map<String, String> eventData) {
        if (eventData != null && !eventData.isEmpty()) {
            ChartData chartData = ChartDataHelper.process(eventData);
            if (chartId.equals(chartData.getChartId())) {
                if (chartData != null && chartData.getSeriesIndex() != null && chartData.getPointIndex() != null) {
                    chartData.setOriginData(dataSeries.getSeriesValue(chartData.getSeriesIndex().intValue(),
                            chartData.getPointIndex().intValue()));
                }

                if (chartData != null) {
                    switch (chartData.getChartEventType()) {
                    // mouse enter
                    case BAR_MOUSE_ENTER:
                        handlerManager.fireEvent(new ChartDataMouseEnterEvent(chartData));
                        break;
                    case BUBBLE_MOUSE_ENTER:
                        handlerManager.fireEvent(new ChartDataMouseEnterEvent(chartData));
                        break;
                    case DONUT_MOUSE_ENTER:
                        handlerManager.fireEvent(new ChartDataMouseEnterEvent(chartData));
                        break;
                    case OHLC_MOUSE_ENTER:
                        handlerManager.fireEvent(new ChartDataMouseEnterEvent(chartData));
                        break;
                    case PIE_MOUSE_ENTER:
                        handlerManager.fireEvent(new ChartDataMouseEnterEvent(chartData));
                        break;
                    case PYRAMID_MOUSE_ENTER:
                        handlerManager.fireEvent(new ChartDataMouseEnterEvent(chartData));
                        break;
                    // mouse leave
                    case BAR_MOUSE_LEAVE:
                        handlerManager.fireEvent(new ChartDataMouseLeaveEvent(chartData));
                        break;
                    case BUBBLE_MOUSE_LEAVE:
                        handlerManager.fireEvent(new ChartDataMouseLeaveEvent(chartData));
                        break;
                    case DONUT_MOUSE_LEAVE:
                        handlerManager.fireEvent(new ChartDataMouseLeaveEvent(chartData));
                        break;
                    case OHLC_MOUSE_LEAVE:
                        handlerManager.fireEvent(new ChartDataMouseLeaveEvent(chartData));
                        break;
                    case PIE_MOUSE_LEAVE:
                        handlerManager.fireEvent(new ChartDataMouseLeaveEvent(chartData));
                        break;
                    case PYRAMID_MOUSE_LEAVE:
                        handlerManager.fireEvent(new ChartDataMouseLeaveEvent(chartData));
                        break;
                    // left click
                    case BAR_CLICK:
                        handlerManager.fireEvent(new ChartDataClickEvent(chartData));
                        break;
                    case BUBBLE_CLICK:
                        handlerManager.fireEvent(new ChartDataClickEvent(chartData));
                        break;
                    case DONUT_CLICK:
                        handlerManager.fireEvent(new ChartDataClickEvent(chartData));
                        break;
                    case LINE_CLICK:
                        handlerManager.fireEvent(new ChartDataClickEvent(chartData));
                        break;
                    case OHLC_CLICK:
                        handlerManager.fireEvent(new ChartDataClickEvent(chartData));
                        break;
                    case PIE_CLICK:
                        handlerManager.fireEvent(new ChartDataClickEvent(chartData));
                        break;
                    // right click
                    case BAR_RIGHT_CLICK:
                        handlerManager.fireEvent(new ChartDataRightClickEvent(chartData));
                        break;
                    case BUBBLE_RIGHT_CLICK:
                        handlerManager.fireEvent(new ChartDataRightClickEvent(chartData));
                        break;
                    case DONUT_RIGHT_CLICK:
                        handlerManager.fireEvent(new ChartDataRightClickEvent(chartData));
                        break;
                    case LINE_RIGHT_CLICK:
                        handlerManager.fireEvent(new ChartDataRightClickEvent(chartData));
                        break;
                    case PIE_RIGHT_CLICK:
                        handlerManager.fireEvent(new ChartDataRightClickEvent(chartData));
                        break;
                    // raw image
                    case RAW_IMAGE_DATA:
                        try {
                            String data = chartData.getData()[0].toString()
                                    .substring("data:image/png;base64,".length());
                            chartImage = Base64.decodeBase64(data);
                            downloadButton.setEnabled(chartImage.length > 0);
                            fileDownloader.setFileDownloadResource(getChartResource());
                            if (enableChartImageChangeEvent) {
                                handlerManager.fireEvent(new ChartImageChangeEvent(getChartImage()));
                            }
                        } catch (Exception e) {
                            downloadButton.setEnabled(false);
                            if (enableChartImageChangeEvent) {
                                handlerManager.fireEvent(new ChartImageChangeEvent(null));
                            }
                        }
                        break;

                    case NOT_DEFINED:
                    default:
                        String caption = "UNKNOWN EVENT";
                        String description = "Cannot process unknown chart data event!";
                        Notification.show(caption, description, Type.ERROR_MESSAGE);
                        break;
                    }
                }
            }
        }
    }

    @Override
    public void beforeClientResponse(boolean initial) {
        super.beforeClientResponse(initial);
        if (chartData != null && chartData.size() > 0) {
            // always put chart id into chart data
            chartData.put(ID, chartId);
            getRpcProxy(DChartsClientRPC.class).setChartId(chartId);
            getRpcProxy(DChartsClientRPC.class).setChartData(chartData);
        }
    }

    public static String getVersion() {
        if (ManifestHelper.getManifest() != null) {
            return ManifestHelper.getManifest().getMainAttributes().getValue("Implementation-Version");
        }
        return null;
    }

    public static String getGitVersion() {
        if (ManifestHelper.getManifest() != null) {
            return ManifestHelper.getManifest().getMainAttributes().getValue("Git-Version");
        }
        return null;
    }

    public static String getJqPlotVersion() {
        if (ManifestHelper.getManifest() != null) {
            return ManifestHelper.getManifest().getMainAttributes().getValue("JqPlot-Version");
        }
        return null;
    }

    public BufferedImage getChartImage() {
        if (chartImage != null && chartImage.length > 0) {
            try {
                return ImageIO.read(new ByteArrayInputStream(chartImage));
            } catch (IOException e) {
                // not catch any error
            }
        }
        return null;
    }

    public int getChartImageChangeDelay() {
        return chartImageChangeDelay;
    }

    public void setChartImageChangeDelay(int delay) {
        chartImageChangeDelay = Math.max(100, delay);
        chartData.put(CHART_IMAGE_CHANGE_DELAY, Integer.toString(chartImageChangeDelay));
    }

    public ChartImageFormat getChartImageFormat() {
        return chartImageFormat;
    }

    public DCharts setChartImageFormat(ChartImageFormat chartImageFormat) {
        this.chartImageFormat = chartImageFormat;
        return this;
    }

    public DCharts autoSelectDecimalAndThousandsSeparator(Locale locale) {
        decimalSeparator = Character.toString(((DecimalFormat) NumberFormat.getNumberInstance(locale))
                .getDecimalFormatSymbols().getDecimalSeparator());
        thousandsSeparator = Character.toString(((DecimalFormat) NumberFormat.getNumberInstance(locale))
                .getDecimalFormatSymbols().getGroupingSeparator());
        chartData.put(DECIMAL_SEPARATOR, decimalSeparator);
        chartData.put(THOUSANDS_SEPARATOR, thousandsSeparator);
        return this;
    }

    public DCharts autoSelectDecimalSeparator(Locale locale) {
        decimalSeparator = Character.toString(((DecimalFormat) NumberFormat.getNumberInstance(locale))
                .getDecimalFormatSymbols().getDecimalSeparator());
        chartData.put(DECIMAL_SEPARATOR, decimalSeparator);
        return this;
    }

    public DCharts autoSelectThousandsSeparator(Locale locale) {
        thousandsSeparator = Character.toString(((DecimalFormat) NumberFormat.getNumberInstance(locale))
                .getDecimalFormatSymbols().getGroupingSeparator());
        chartData.put(THOUSANDS_SEPARATOR, thousandsSeparator);
        return this;
    }

    public String getDecimalSeparator() {
        return decimalSeparator;
    }

    public DCharts setDecimalSeparator(String decimalSeparator) {
        if (decimalSeparator != null && decimalSeparator.length() > 0) {
            this.decimalSeparator = decimalSeparator;
            chartData.put(DECIMAL_SEPARATOR, decimalSeparator);
        }
        return this;
    }

    public String getThousandsSeparator() {
        return thousandsSeparator;
    }

    public DCharts setThousandsSeparator(String thousandsSeparator) {
        this.thousandsSeparator = thousandsSeparator;
        if (thousandsSeparator != null && thousandsSeparator.length() > 0) {
            this.thousandsSeparator = thousandsSeparator;
            chartData.put(THOUSANDS_SEPARATOR, thousandsSeparator);
        }
        return this;
    }

    public DCharts setMargins(int marginTop, int marginRight, int marginBottom, int marginLeft) {
        this.marginTop = marginTop;
        this.marginRight = marginRight;
        this.marginBottom = marginBottom;
        this.marginLeft = marginLeft;
        chartData.put(MARGIN_TOP, Integer.toString(marginTop));
        chartData.put(MARGIN_RIGHT, Integer.toString(marginRight));
        chartData.put(MARGIN_BOTTOM, Integer.toString(marginBottom));
        chartData.put(MARGIN_LEFT, Integer.toString(marginLeft));
        return this;
    }

    public int getMarginTop() {
        return marginTop;
    }

    public DCharts setMarginTop(int marginTop) {
        this.marginTop = marginTop;
        chartData.put(MARGIN_TOP, Integer.toString(marginTop));
        return this;
    }

    public int getMarginRight() {
        return marginRight;
    }

    public DCharts setMarginRight(int marginRight) {
        this.marginRight = marginRight;
        chartData.put(MARGIN_RIGHT, Integer.toString(marginRight));
        return this;
    }

    public int getMarginBottom() {
        return marginBottom;
    }

    public DCharts setMarginBottom(int marginBottom) {
        this.marginBottom = marginBottom;
        chartData.put(MARGIN_BOTTOM, Integer.toString(marginBottom));
        return this;
    }

    public int getMarginLeft() {
        return marginLeft;
    }

    public DCharts setMarginLeft(int marginLeft) {
        this.marginLeft = marginLeft;
        chartData.put(MARGIN_LEFT, Integer.toString(marginLeft));
        return this;
    }

    public Boolean isEnableDownload() {
        return downloadButtonEnable;
    }

    public DCharts setEnableDownload(boolean enable) {
        downloadButtonEnable = enable;
        chartData.put(DOWNLOAD_BUTTON_ENABLE, Boolean.toString(enable));
        return this;
    }

    public String getDownloadFilename() {
        return downloadFilename;
    }

    public DCharts setDownloadFilename(String filename) {
        if (filename != null && !filename.trim().isEmpty()) {
            downloadFilename = filename;
        }
        return this;
    }

    public DownloadButtonLocation getDownloadButtonLocation() {
        return downloadButtonLocation;
    }

    public DCharts setDownloadButtonLocation(DownloadButtonLocation location) {
        downloadButtonLocation = location;
        chartData.put(DOWNLOAD_BUTTON_LOCATION, location.toString());
        return this;
    }

    public String getDownloadButtonCaption() {
        return downloadButton.getCaption();
    }

    public DCharts setDownloadButtonCaption(String caption) {
        if (caption != null && !caption.trim().isEmpty()) {
            downloadButton.setCaption(caption);
        }
        return this;
    }

    public DataSeries getDataSeries() {
        return dataSeries;
    }

    public DCharts setDataSeries(DataSeries dataSeries) {
        if (dataSeries != null && !dataSeries.isEmpty()) {
            this.dataSeries = dataSeries;
            chartData.put(DATA_SERIES, dataSeries.getValue());
        }
        return this;
    }

    public Options getOptions() {
        return options;
    }

    public DCharts setOptions(Options options) {
        if (options != null && !options.isEmpty()) {
            this.options = options;
            chartData.put(OPTIONS, options.getValue());
        }
        return this;
    }

    public boolean isEnableChartDataMouseEnterEvent() {
        return enableChartDataMouseEnterEvent;
    }

    public DCharts setEnableChartDataMouseEnterEvent(boolean enableChartDataMouseEnterEvent) {
        this.enableChartDataMouseEnterEvent = enableChartDataMouseEnterEvent;
        chartData.put(MOUSE_ENTER_EVENT, Boolean.toString(enableChartDataMouseEnterEvent));
        return this;
    }

    public boolean isEnableChartDataMouseLeaveEvent() {
        return enableChartDataMouseLeaveEvent;
    }

    public DCharts setEnableChartDataMouseLeaveEvent(boolean enableChartDataMouseLeaveEvent) {
        this.enableChartDataMouseLeaveEvent = enableChartDataMouseLeaveEvent;
        chartData.put(MOUSE_LEAVE_EVENT, Boolean.toString(enableChartDataMouseLeaveEvent));
        return this;
    }

    public boolean isEnableChartDataClickEvent() {
        return enableChartDataClickEvent;
    }

    public DCharts setEnableChartDataClickEvent(boolean enableChartDataClickEvent) {
        this.enableChartDataClickEvent = enableChartDataClickEvent;
        chartData.put(CLICK_EVENT, Boolean.toString(enableChartDataClickEvent));
        return this;
    }

    public boolean isEnableChartDataRightClickEvent() {
        return enableChartDataRightClickEvent;
    }

    public DCharts setEnableChartDataRightClickEvent(boolean enableChartDataRightClickEvent) {
        this.enableChartDataRightClickEvent = enableChartDataRightClickEvent;
        chartData.put(RIGHT_CLICK_EVENT, Boolean.toString(enableChartDataRightClickEvent));
        return this;
    }

    public boolean isEnableChartImageChangeEvent() {
        return enableChartImageChangeEvent;
    }

    public DCharts setEnableChartImageChangeEvent(boolean enableChartImageChangeEvent) {
        this.enableChartImageChangeEvent = enableChartImageChangeEvent;
        chartData.put(CHART_IMAGE_CHANGE_EVENT, Boolean.toString(enableChartImageChangeEvent));
        return this;
    }

    public DCharts show() {
        if (dataSeries != null && !dataSeries.isEmpty()) {
            chartData.put(SHOW_CHART, Boolean.TRUE.toString());
            markAsDirty();
        }
        return this;
    }

    public DCharts hide() {
        chartData.put(SHOW_CHART, Boolean.FALSE.toString());
        markAsDirty();
        return this;
    }

    public DCharts replot(boolean clean, boolean resetAxes) {
        chartData.put(REPLOT_CHART_CLEAR, Boolean.toString(clean));
        chartData.put(REPLOT_CHART_RESET_AXES, Boolean.toString(resetAxes));
        markAsDirty();
        return this;
    }

    @Deprecated
    public DCharts refresh() {
        markAsDirty();
        return this;
    }

    public void addHandler(ChartDataMouseEnterHandler handler) {
        if (isEnableChartDataMouseEnterEvent()) {
            handlerManager.addHandler(ChartDataMouseEnterEvent.getType(), handler);
        }
    }

    public void removeHandler(ChartDataMouseEnterHandler handler) {
        if (handlerManager.isEventHandled(ChartDataMouseEnterEvent.getType())) {
            handlerManager.removeHandler(ChartDataMouseEnterEvent.getType(), handler);
        }
    }

    public void addHandler(ChartDataMouseLeaveHandler handler) {
        if (isEnableChartDataMouseLeaveEvent()) {
            handlerManager.addHandler(ChartDataMouseLeaveEvent.getType(), handler);
        }
    }

    public void removeHandler(ChartDataMouseLeaveHandler handler) {
        if (handlerManager.isEventHandled(ChartDataMouseLeaveEvent.getType())) {
            handlerManager.removeHandler(ChartDataMouseLeaveEvent.getType(), handler);
        }
    }

    public void addHandler(ChartDataClickHandler handler) {
        if (isEnableChartDataClickEvent()) {
            handlerManager.addHandler(ChartDataClickEvent.getType(), handler);
        }
    }

    public void removeHandler(ChartDataClickHandler handler) {
        if (handlerManager.isEventHandled(ChartDataClickEvent.getType())) {
            handlerManager.removeHandler(ChartDataClickEvent.getType(), handler);
        }
    }

    public void addHandler(ChartDataRightClickHandler handler) {
        if (isEnableChartDataRightClickEvent()) {
            handlerManager.addHandler(ChartDataRightClickEvent.getType(), handler);
        }
    }

    public void removeHandler(ChartDataRightClickHandler handler) {
        if (handlerManager.isEventHandled(ChartDataRightClickEvent.getType())) {
            handlerManager.removeHandler(ChartDataRightClickEvent.getType(), handler);
        }
    }

    public void addHandler(ChartImageChangeHandler handler) {
        handlerManager.addHandler(ChartImageChangeEvent.getType(), handler);
    }

    public void removeHandler(ChartImageChangeHandler handler) {
        if (handlerManager.isEventHandled(ChartImageChangeEvent.getType())) {
            handlerManager.removeHandler(ChartImageChangeEvent.getType(), handler);
        }
    }

}