All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.fujion.highcharts.Chart Maven / Gradle / Ivy

There is a newer version: 3.1.0
Show newest version
/*
 * #%L
 * fujion
 * %%
 * Copyright (C) 2008 - 2017 Regenstrief Institute, Inc.
 * %%
 * 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.
 *
 * #L%
 */
package org.fujion.highcharts;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.fujion.ancillary.ConvertUtil;
import org.fujion.ancillary.OptionMap;
import org.fujion.ancillary.OptionMap.IOptionMapConverter;
import org.fujion.ancillary.Options;
import org.fujion.annotation.Component;
import org.fujion.annotation.Component.PropertyGetter;
import org.fujion.annotation.Component.PropertySetter;
import org.fujion.component.BaseUIComponent;
import org.fujion.component.Page;

/**
 * Fujion wrapper for HighCharts component.
 */
@Component(tag = "hchart", widgetModule = "fujion-hchart", widgetClass = "HChart", parentTag = "*")
public class Chart extends BaseUIComponent implements IOptionMapConverter {
    
    private static final String GLOBAL_SETTINGS = Chart.class.getName() + ".global";
    
    /**
     * Top level chart settings.
     */
    public static class ChartSettings extends Options {
        
        public final ChartOptions chart = new ChartOptions();
        
        public final List colors = new ArrayList<>();
        
        public final CreditsOptions credits = new CreditsOptions();
        
        public final ExportingOptions exporting = new ExportingOptions();
        
        public final LegendOptions legend = new LegendOptions();
        
        public final LoadingOptions loading = new LoadingOptions();
        
        public final NavigationOptions navigation = new NavigationOptions();
        
        public final PaneOptions pane = new PaneOptions();
        
        public final PlotOptions plotOptions = null;
        
        public final List series = new ArrayList<>();
        
        public final TitleOptions subtitle = new TitleOptions();
        
        public final TitleOptions title = new TitleOptions();
        
        public final TooltipOptions tooltip = new TooltipOptions();
        
        public final List xAxis = new ArrayList<>();
        
        public final List yAxis = new ArrayList<>();
        
    }
    
    public final ChartSettings options = new ChartSettings();
    
    private boolean running;
    
    /**
     * Create default chart (line plot, single x- and y-axis).
     */
    public Chart() {
        super();
        addXAxis();
        addYAxis();
        setType("line");
    }
    
    /**
     * Sets the default colors for the chart's series. When all colors are used, new colors are
     * pulled from the start again.
     *
     * @param colors List of default colors. If null or empty, the Highcharts defaults are used.
     */
    public void setDefaultColors(String... colors) {
        options.colors.clear();
        
        if (colors != null) {
            options.colors.addAll(Arrays.asList(colors));
        }
    }
    
    /**
     * Returns the chart type.
     *
     * @return The chart type.
     */
    @PropertyGetter("type")
    public String getType() {
        return options.chart.type;
    }
    
    /**
     * Sets the chart type. This will remove any existing series.
     *
     * @param type One of the supported chart types.
     */
    @PropertySetter("type")
    public void setType(String type) {
        try {
            Field field = ChartSettings.class.getField("plotOptions");
            field.setAccessible(true);
            PlotOptions plotOptions = Util.getPlotType(type);
            plotOptions.type = type;
            field.set(options, plotOptions);
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        options.chart.type = type;
        options.series.clear();
    }
    
    /**
     * Convenience method for returning the x-axis. If there are no x-axes, returns null. If there
     * are multiple x-axes, returns the first only.
     *
     * @return The x-axis.
     */
    public Axis getXAxis() {
        return options.xAxis.isEmpty() ? null : options.xAxis.get(0);
    }
    
    /**
     * Convenience method for returning the y-axis. If there are no y-axes, returns null. If there
     * are multiple y-axes, returns the first only.
     *
     * @return The y-axis.
     */
    public Axis getYAxis() {
        return options.yAxis.isEmpty() ? null : options.yAxis.get(0);
    }
    
    /**
     * Adds a new series to the chart using the chart's default type.
     *
     * @return The newly created series.
     */
    public Series addSeries() {
        return addSeries(options.chart.type);
    }
    
    /**
     * Adds a new series to the chart using the specified type.
     *
     * @param type The plot type.
     * @return The newly created series.
     */
    public Series addSeries(String type) {
        Series series = new Series(type);
        options.series.add(series);
        return series;
    }
    
    /**
     * Adds an additional x axis.
     *
     * @return The newly added axis.
     */
    public Axis addXAxis() {
        return new Axis(options.xAxis);
    }
    
    /**
     * Adds an additional y axis.
     *
     * @return The newly added axis.
     */
    public Axis addYAxis() {
        return new Axis(options.yAxis);
    }
    
    /**
     * Build the graph on the client.
     */
    public void run() {
        init();
        invoke("_run", toMap());
        running = true;
    }
    
    /**
     * Returns true if a chart is currently running on the client.
     *
     * @return True if a chart is running.
     */
    public boolean isRunning() {
        return running;
    }
    
    /**
     * Removes all series and data points and destroys the client graph.
     */
    public void clear() {
        running = false;
        options.series.clear();
        invoke("_reset");
    }
    
    /**
     * Force a redraw of the chart.
     */
    public void redraw() {
        if (running) {
            invoke("_redraw");
        } else {
            run();
        }
    }
    
    /**
     * Send global settings to client if necessary.
     */
    private void init() {
        if (shouldInitialize()) {
            invoke("_global", new GlobalSettings().toMap());
        }
    }
    
    /**
     * Returns true if global settings need to be sent to client. This occurs once per page.
     *
     * @return True if global settings need to be sent.
     */
    private boolean shouldInitialize() {
        Page pg = getPage();
        
        if (pg != null && !pg.hasAttribute(GLOBAL_SETTINGS)) {
            pg.setAttribute(GLOBAL_SETTINGS, true);
            return true;
        }
        
        return false;
    }
    
    /**
     * Converts all options to map for sending to client.
     */
    @Override
    public OptionMap toMap() {
        options.chart.renderTo = getId();
        return options.toMap();
    }
    
    /**
     * Convenience method for getting title.
     *
     * @return Title text
     */
    @PropertyGetter("title")
    public String getTitle() {
        return options.title.text;
    }
    
    /**
     * Convenience method for setting title.
     *
     * @param text Title text
     */
    @PropertySetter("title")
    public void setTitle(String text) {
        options.title.text = text;
        updateTitle();
    }
    
    /**
     * Convenience method for getting subtitle.
     *
     * @return Subtitle text
     */
    @PropertyGetter("subtitle")
    public String getSubtitle() {
        return options.subtitle.text;
    }
    
    /**
     * Convenience method for setting subtitle.
     *
     * @param text Subtitle text
     */
    @PropertySetter("subtitle")
    public void setSubtitle(String text) {
        options.subtitle.text = text;
        updateTitle();
    }
    
    /**
     * Calls the exportChart function on the chart.
     */
    public void export() {
        ensureRunning("Exporting");
        invokeJS("_export", options.exporting.buttons_exportButton.onclick);
    }
    
    /**
     * Calls the print function on the chart.
     */
    public void print() {
        ensureRunning("Printing");
        invokeJS("_print", options.exporting.buttons_printButton.onclick);
    }
    
    /**
     * Invokes the specified widget function, passing the JavaScript snippet as its argument.
     *
     * @param func Widget function name.
     * @param js JavaScript snippet.
     */
    private void invokeJS(String func, String js) {
        invoke(func, ConvertUtil.convertToJS(js));
    }
    
    /**
     * If the chart is active, dynamically update the title and subtitle.
     */
    private void updateTitle() {
        if (running) {
            OptionMap map = new OptionMap();
            map.put("title", options.title);
            map.put("subtitle", options.subtitle);
            invoke("_title", map);
        }
    }
    
    /**
     * Throws an exception if a chart is not currently running.
     *
     * @param operation The operation to be invoked.
     */
    private void ensureRunning(String operation) {
        if (!running) {
            throw new RuntimeException(operation + " requires an active chart.");
        }
    }
    
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy