From fa583842de20970cff1fc8c51ea2d884e8be3f4e Mon Sep 17 00:00:00 2001 From: fmittag Date: Fri, 18 May 2012 17:12:03 +0200 Subject: [PATCH] update highcharts Gwt from version 1.1.3 to 1.3.0 Includes also the checkbox position fix in BaseChart.java --- .../META-INF/MANIFEST.MF | 10 +- .../moxieapps/gwt/highcharts/client/Axis.java | 147 ++++++++++++- .../gwt/highcharts/client/BaseChart.java | 198 ++++++++++++++---- .../gwt/highcharts/client/Legend.java | 32 ++- .../gwt/highcharts/client/Point.java | 43 +++- .../gwt/highcharts/client/Series.java | 98 ++++++++- .../client/labels/BaseDataLabels.java | 90 ++++++++ .../highcharts/client/plotOptions/Marker.java | 12 +- 8 files changed, 564 insertions(+), 66 deletions(-) diff --git a/java/org.moxieapps.gwt.highcharts/META-INF/MANIFEST.MF b/java/org.moxieapps.gwt.highcharts/META-INF/MANIFEST.MF index 9a461463a56..128904b0118 100755 --- a/java/org.moxieapps.gwt.highcharts/META-INF/MANIFEST.MF +++ b/java/org.moxieapps.gwt.highcharts/META-INF/MANIFEST.MF @@ -2,21 +2,21 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Moxie Apps GWT Highcharts Bundle-SymbolicName: org.moxieapps.gwt.highcharts -Bundle-Version: 1.1.4.qualifier +Bundle-Version: 1.3.0.qualifier Bundle-RequiredExecutionEnvironment: JavaSE-1.6 Export-Package: org.moxieapps.gwt.highcharts.client.plotOptions;uses:="o rg.moxieapps.gwt.highcharts.client,com.google.gwt.json.client,org.moxie apps.gwt.highcharts.client.events,org.moxieapps.gwt.highcharts.client.l - abels";version="1.1.3",org.moxieapps.gwt.highcharts;version="1.1.3",org + abels";version="1.3.0",org.moxieapps.gwt.highcharts;version="1.3.0",org .moxieapps.gwt.highcharts.client;uses:="com.google.gwt.core.client,com. google.gwt.dom.client,com.google.gwt.json.client,org.moxieapps.gwt.high charts.client.plotOptions,com.google.gwt.user.client,org.moxieapps.gwt. highcharts.client.events,org.moxieapps.gwt.highcharts.client.labels,com - .google.gwt.user.client.ui";version="1.1.3",org.moxieapps.gwt.highchart + .google.gwt.user.client.ui";version="1.3.0",org.moxieapps.gwt.highchart s.client.events;uses:="com.google.gwt.core.client,com.google.gwt.dom.cl - ient,org.moxieapps.gwt.highcharts.client";version="1.1.3",org.moxieapps + ient,org.moxieapps.gwt.highcharts.client";version="1.3.0",org.moxieapps .gwt.highcharts.client.labels;uses:="com.google.gwt.core.client,org.mox - ieapps.gwt.highcharts.client,com.google.gwt.json.client";version="1.1.3 + ieapps.gwt.highcharts.client,com.google.gwt.json.client";version="1.3.0 " Import-Package: com.google.gwt.core.client,com.google.gwt.dom.client,com .google.gwt.json.client,com.google.gwt.user.client,com.google.gwt.user. diff --git a/java/org.moxieapps.gwt.highcharts/src/org/moxieapps/gwt/highcharts/client/Axis.java b/java/org.moxieapps.gwt.highcharts/src/org/moxieapps/gwt/highcharts/client/Axis.java index a0e2cbccc8a..1918e5a0795 100755 --- a/java/org.moxieapps.gwt.highcharts/src/org/moxieapps/gwt/highcharts/client/Axis.java +++ b/java/org.moxieapps.gwt.highcharts/src/org/moxieapps/gwt/highcharts/client/Axis.java @@ -16,6 +16,8 @@ package org.moxieapps.gwt.highcharts.client; +import org.moxieapps.gwt.highcharts.client.events.AxisSetExtremesEventHandler; + import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.dom.client.Document; import com.google.gwt.json.client.JSONObject; @@ -46,6 +48,12 @@ public abstract class Axis extends Configurable { */ LINEAR("linear"), + /** + * Scale the axis tick values logarithmically instead of linearly. + * @since 1.2.0 + */ + LOGARITHMIC("logarithmic"), + /** * In a datetime axis, the numbers are given in milliseconds, and tick * marks are placed on appropriate values like full hours or days. @@ -124,6 +132,8 @@ public abstract class Axis extends Configurable { // The unique id for this axis, that we can use to access the native axis instance later if changes // come into the axis after it is rendered private String id; + + private AxisSetExtremesEventHandler axisSetExtremesEventHandler; /** * Use the {@link Chart#getXAxis()} or {@link Chart#getYAxis()} methods to get access @@ -136,6 +146,36 @@ public abstract class Axis extends Configurable { id = Document.get().createUniqueId(); setOption("id", id); } + + /** + * Set a callback handler that will be invoked whenever the minimum and maximum is set for the axis, either by calling the + * {@link #setExtremes(Number, Number)} method or by selecting an area in the chart. + * + * Additional information about the new extremes value (such as the new minimum and maximum) can be + * found via the {@link org.moxieapps.gwt.highcharts.client.events.AxisSetExtremesEvent} instance + * that is passed to the handler's {@link org.moxieapps.gwt.highcharts.client.events.AxisSetExtremesEventHandler#onSetExtremes(org.moxieapps.gwt.highcharts.client.events.AxisSetExtremesEvent)} method. + * + * @param axisSetExtremesEventHandler The handler that should be invoked whenever a set extremes event occurs. + * @return A reference to this {@link Axis} instance for convenient method chaining. + * + * @since 1.3.0 + */ + public T setAxisSetExtremesEventHandler(AxisSetExtremesEventHandler axisSetExtremesEventHandler) { + this.axisSetExtremesEventHandler = axisSetExtremesEventHandler; + return getThis(); + } + + /** + * Returns the custom event handler that has been set on the axis, or null if no event + * handler has been set. + * + * @return The custom event handler that has been applied, or null if it has not been set. + * + * @since 1.3.0 + */ + public AxisSetExtremesEventHandler getAxisSetExtremesEventHandler() { + return this.axisSetExtremesEventHandler; + } /** * Create a new plot line that can be configured, and then added to this axis instance via the @@ -302,10 +342,10 @@ public abstract class Axis extends Configurable { if (nativeAxis != null) { if (animation == null || animation.getOptions() == null) { final boolean animationFlag = animation != null; - nativeSetExtremes(nativeAxis, min, max, redraw, animationFlag); + nativeSetExtremes(nativeAxis, min.doubleValue(), max.doubleValue(), redraw, animationFlag); } else { final JavaScriptObject animationOptions = animation.getOptions().getJavaScriptObject(); - nativeSetExtremes(nativeAxis, min, max, redraw, animationOptions); + nativeSetExtremes(nativeAxis, min.doubleValue(), max.doubleValue(), redraw, animationOptions); } } } else { @@ -353,6 +393,10 @@ public abstract class Axis extends Configurable { protected JavaScriptObject getNativeAxis() { return chart.get(this.id); } + + /* package */ String getId() { + return this.id; + } // Save some typing in the getExtremes() method private Number getNumberFromJSONObject(JSONObject jsonObject, String key) { @@ -513,7 +557,7 @@ public abstract class Axis extends Configurable { private Number min; /** - * Convenience method for setting the 'max' option for the axis. Equivalent to: + * Convenience method for setting the 'min' option for the axis. Equivalent to: *

      *     axis.setOption("min", 10);
      * 
@@ -525,7 +569,7 @@ public abstract class Axis extends Configurable { * To change the min/max value of the chart after render time use the {@link #setExtremes(Number, Number)} * method instead. * - * @param min The maximum value of the axis, or null to automatically calculate the maximum. + * @param min The minimum value of the axis, or null to automatically calculate the minimum. * @return A reference to this {@link Axis} instance for convenient method chaining. */ public T setMin(Number min) { @@ -925,10 +969,16 @@ public abstract class Axis extends Configurable { } /** - * Convenience method for setting the 'title/text' axis option. Equivalent to: + * Convenience method for setting the 'title/text' axis option, before or after + * the chart is rendered. Before the chart is rendered this is equivalent to: *

      *     axis.setOption("/title/text", "A Fine Axis Indeed");
      * 
+ * After the chart is rendered this is equivalent to a direct JS call like + *

+     *     Axis.setTitle({text: "A Fine Axis Indeed"});
+     * 
+ * * The actual text of the axis title. It can contain basic HTML text markup like * <b>, <i> and spans with style. Defaults to null for the x-axis * and "Y-values" for the y-axis. @@ -942,15 +992,56 @@ public abstract class Axis extends Configurable { * @return A reference to this {@link Axis} instance for convenient method chaining. */ public T setAxisTitleText(String title) { - return this.setOption("/title/text", title); + return this.setAxisTitleText(title, true); } /** - * Convenience method for setting the 'title/text' axis option. Equivalent to: + * Convenience method for setting the 'title/text' axis option, before or after + * the chart is rendered (explicitly controlling whether or not the new title will + * be immediately drawn in the case of being called after the chart is rendered). + * Before the chart is rendered this is equivalent to: + *

+     *     axis.setOption("/title/text", "A Fine Axis Indeed");
+     * 
+ * After the chart is rendered this is equivalent to a JS call like: + *

+     *     Axis.setTitle({text: "A Fine Axis Indeed"}, true);
+     * 
+ * + * The actual text of the axis title. It can contain basic HTML text markup like + * <b>, <i> and spans with style. Defaults to null for the x-axis + * and "Y-values" for the y-axis. + *

+ * Note that for more control over the title, utilize the {@link #setAxisTitle(AxisTitle)} + * method instead. + *

+ * Also note that to hide an axis title completely, simply set the text to null. + * + * @param title Sets the title of axis, or null to hide the title. + * @param redraw Whether to redraw the chart now or hold until the next {@link org.moxieapps.gwt.highcharts.client.BaseChart#redraw()} + * @return A reference to this {@link Axis} instance for convenient method chaining. + * @since 1.2.0 + */ + public T setAxisTitleText(String title, boolean redraw) { + if(getNativeAxis() != null) { + this.setAxisTitle(new AxisTitle().setText(title), redraw); + } else { + this.setOption("/title/text", title); + } + return getThis(); + } + + /** + * Convenience method for setting the 'title/text' axis option, before or after + * the chart is rendered. Before the chart is rendered this is equivalent to: *


      *     axis.setOption("/title/text", "A Fine Axis Indeed");
      *     axis.setOption("/title/align", AxisTitle.Align.HIGH);
      * 
+ * After the chart is rendered this is equivalent to a JS call like: + *

+     *     Axis.setTitle({text: "A Fine Axis Indeed", align: "high"});
+     * 
*

* Note that if you call this method it will overwrite any existing * settings that have already been applied to the title (e.g. if you @@ -964,6 +1055,40 @@ public abstract class Axis extends Configurable { * @return A reference to this {@link Axis} instance for convenient method chaining. */ public T setAxisTitle(AxisTitle title) { + return this.setAxisTitle(title, true); + } + + /** + * Convenience method for setting the 'title/text' axis option, before or after + * the chart is rendered (explicitly controlling whether or not the new title will + * be immediately drawn in the case of being called after the chart is rendered). + * Before the chart is rendered this is equivalent to: + *


+     *     axis.setOption("/title/text", "A Fine Axis Indeed");
+     *     axis.setOption("/title/align", AxisTitle.Align.HIGH);
+     * 
+ * After the chart is rendered this is equivalent to a JS call like: + *

+     *     Axis.setTitle({text: "A Fine Axis Indeed", align: "high"});
+     * 
+ *

+ * Note that if you call this method it will overwrite any existing + * settings that have already been applied to the title (e.g. if you + * had previously called the {@link #setAxisTitleText(String)} method that change + * will get overwritten by this call.) + *

+ * Note that if you only want to change the text of the axis, you can simply + * use the {@link #setAxisTitleText(String)} method instead. + * + * @param title Sets the axis title options, or null to hide the title. + * @param redraw Whether to redraw the chart now or hold until the next {@link org.moxieapps.gwt.highcharts.client.BaseChart#redraw()} + * @return A reference to this {@link Axis} instance for convenient method chaining. + * @since 1.2.0 + */ + public T setAxisTitle(AxisTitle title, boolean redraw) { + if(getNativeAxis() != null) { + nativeSetTitle(getNativeAxis(), title != null ? title.getOptions().getJavaScriptObject() : null, redraw); + } return this.setOption("/title", title != null ? title.getOptions() : null); } @@ -1065,11 +1190,11 @@ public abstract class Axis extends Configurable { return instance; } - private static native void nativeSetExtremes(JavaScriptObject axis, Number min, Number max, boolean redraw, boolean animation) /*-{ + private static native void nativeSetExtremes(JavaScriptObject axis, double min, double max, boolean redraw, boolean animation) /*-{ axis.setExtremes(min, max, redraw, animation); }-*/; - private static native void nativeSetExtremes(JavaScriptObject axis, Number min, Number max, boolean redraw, JavaScriptObject animationOptions) /*-{ + private static native void nativeSetExtremes(JavaScriptObject axis, double min, double max, boolean redraw, JavaScriptObject animationOptions) /*-{ axis.setExtremes(min, max, redraw, animationOptions); }-*/; @@ -1092,4 +1217,8 @@ public abstract class Axis extends Configurable { private native void nativeRemovePlotBand(JavaScriptObject axis, String id)/*-{ axis.removePlotBand(id); }-*/; + + private native void nativeSetTitle(JavaScriptObject axis, JavaScriptObject titleOptions, boolean redraw)/*-{ + axis.setTitle(titleOptions, redraw); + }-*/; } diff --git a/java/org.moxieapps.gwt.highcharts/src/org/moxieapps/gwt/highcharts/client/BaseChart.java b/java/org.moxieapps.gwt.highcharts/src/org/moxieapps/gwt/highcharts/client/BaseChart.java index e33d6a5cf75..2084705329c 100644 --- a/java/org.moxieapps.gwt.highcharts/src/org/moxieapps/gwt/highcharts/client/BaseChart.java +++ b/java/org.moxieapps.gwt.highcharts/src/org/moxieapps/gwt/highcharts/client/BaseChart.java @@ -26,6 +26,7 @@ import com.google.gwt.user.client.ui.Widget; import org.moxieapps.gwt.highcharts.client.events.*; import org.moxieapps.gwt.highcharts.client.labels.AxisLabelsData; import org.moxieapps.gwt.highcharts.client.labels.DataLabelsData; +import org.moxieapps.gwt.highcharts.client.labels.LegendLabelsData; import org.moxieapps.gwt.highcharts.client.labels.StackLabelsData; import org.moxieapps.gwt.highcharts.client.plotOptions.*; @@ -485,6 +486,9 @@ public abstract class BaseChart extends Widget { return this.setOption("/labels/style", style != null ? style.getOptions() : null); } + // We need to maintain a local reference to legend to deal with the formatter function + private Legend legend; + /** * Convenience method for setting the 'legend' options of the chart. Equivalent to: *


@@ -498,6 +502,7 @@ public abstract class BaseChart extends Widget {
      * @return A reference to this {@link BaseChart} instance for convenient method chaining.
      */
     public T setLegend(Legend legend) {
+        this.legend = legend;
         return this.setOption("/legend", legend != null ? legend.getOptions() : null);
     }
 
@@ -1415,8 +1420,8 @@ public abstract class BaseChart extends Widget {
      * @param persistent 'true' to retain the data associated with the points in the series in the chart locally
      *                   within a GWT managed Java array (as well as within the DOM via the core Highcharts JS library).
      *                   Defaults to 'false' for memory savings.
-     * @since 1.2.0
      * @return A reference to this {@link BaseChart} instance for convenient method chaining.
+     * @since 1.2.0
      */
     public T setPersistent(boolean persistent) {
         this.persistent = persistent;
@@ -1709,7 +1714,7 @@ public abstract class BaseChart extends Widget {
         }
         return returnThis();
     }
-
+    
     // Purposefully using a specific type instead of the generic List interface for enhanced GWT performance
     private ArrayList xAxes = new ArrayList();
     private ArrayList yAxes = new ArrayList();
@@ -1771,6 +1776,30 @@ public abstract class BaseChart extends Widget {
         }
         return yAxes.get(axisIndex);
     }
+    
+    /**
+     * Get a axis by id
+     * @param axisId the id of the Axis
+     * @return the Axis instance, may be XAxis or YAxis, null if not found
+     */
+    private Axis getAxis(String axisId) {
+        if (axisId == null) {
+            return null;
+        }
+        for (XAxis xAxis : xAxes) {
+            if (axisId.equals(xAxis.getId())) {
+                return xAxis;
+            }
+        }
+        
+        for (YAxis yAxis : yAxes) {
+            if (axisId.equals(yAxis.getId())) {
+                return yAxis;
+            }
+        }
+        
+        return null;
+    }
 
     /**
      * Redraw the chart after changes have been done to the data or axis extremes. All methods for
@@ -1808,18 +1837,28 @@ public abstract class BaseChart extends Widget {
     protected void onLoad() {
 
         // Build some arrays that we can pass into the JS function so that it knows how many custom callback functions it needs to wire
-        // up on the client side for formatter functions.
+        // up on the client side for formatter functions and event handlers.
         JSONArray xAxisLabelFormatters = new JSONArray();
+        JSONArray xAxisEventHandlers = new JSONArray();
         for (int i = 0, xAxesSize = xAxes.size(); i < xAxesSize; i++) {
             XAxis xAxis = xAxes.get(i);
             xAxisLabelFormatters.set(i, JSONBoolean.getInstance(xAxis.getLabels() != null && xAxis.getLabels().getFormatter() != null));
+            
+            JSONObject axisEventHandlers = new JSONObject();
+            axisEventHandlers.put("setExtremes", JSONBoolean.getInstance(xAxis.getAxisSetExtremesEventHandler() != null));
+            xAxisEventHandlers.set(i, axisEventHandlers);
         }
         JSONArray yAxisLabelFormatters = new JSONArray();
         JSONArray yAxisStackLabelFormatters = new JSONArray();
+        JSONArray yAxisEventHandlers = new JSONArray();
         for (int i = 0, yAxesSize = yAxes.size(); i < yAxesSize; i++) {
             YAxis yAxis = yAxes.get(i);
             yAxisLabelFormatters.set(i, JSONBoolean.getInstance(yAxis.getLabels() != null && yAxis.getLabels().getFormatter() != null));
             yAxisStackLabelFormatters.set(i, JSONBoolean.getInstance(yAxis.getStackLabels() != null && yAxis.getStackLabels().getFormatter() != null));
+                        
+            JSONObject axisEventHandlers = new JSONObject();
+            axisEventHandlers.put("setExtremes", JSONBoolean.getInstance(yAxis.getAxisSetExtremesEventHandler() != null));
+            yAxisEventHandlers.set(i, axisEventHandlers);
         }
 
         // Build a similar object for dealing with all of the data label formatters that may be set on the plot options
@@ -1851,7 +1890,7 @@ public abstract class BaseChart extends Widget {
         // And two more for events that have been applied to the series (or the points within the series)
         JSONObject seriesEventHandlers = new JSONObject();
         JSONObject pointEventHandlers = new JSONObject();
-
+        
         if (seriesPlotOptions != null) {
 
             // Series event
@@ -1912,9 +1951,12 @@ public abstract class BaseChart extends Widget {
             getChartTypeName(),
             createNativeOptions(),
             toolTip != null && toolTip.getToolTipFormatter() != null,
+            legend != null && legend.getLabelsFormatter() != null,
             chartEventHandlers.getJavaScriptObject(),
             seriesEventHandlers.getJavaScriptObject(),
             pointEventHandlers.getJavaScriptObject(),
+            xAxisEventHandlers.getJavaScriptObject(),
+            yAxisEventHandlers.getJavaScriptObject(),
             xAxisLabelFormatters.getJavaScriptObject(),
             yAxisLabelFormatters.getJavaScriptObject(),
             yAxisStackLabelFormatters.getJavaScriptObject(),
@@ -1932,22 +1974,6 @@ public abstract class BaseChart extends Widget {
 
     }
 
-    /**
-     * Fixing a bug currently in the base Highcharts implementation regarding the placement of the checkbox in the legend.
-     * Requires the symbol padding (see {@link Legend#setSymbolPadding(Number)}) to be set to 20. Invoked
-     * whenever a series is added / displayed in a rendered chart.

- * - * The implementation moves the legend item text 15px to the left, using the space made by setting the symbol - * padding to 20px; the checkbox is moved 18px to the left with the top margin set to 0px. - */ - private static native JavaScriptObject nativeAdjustCheckboxPosition(JavaScriptObject series) /*-{ - if (series.legendItem && series.checkbox) { - series.legendItem.translate(-15, 0); - series.checkbox.style.marginLeft = '-18px' - series.checkbox.style.marginTop = '0px' - } - }-*/; - /** * To be overridden in a sub class to return the JS type name of the chart instance that * should be created when the chart is rendered. E.g. "Chart", "StockChart", etc. @@ -2065,7 +2091,7 @@ public abstract class BaseChart extends Widget { return JSONNull.getInstance(); } - private static void copyPointsToJSONArray(Point[] points, JSONArray jsonArray) { + private void copyPointsToJSONArray(Point[] points, JSONArray jsonArray) { for (int i = 0, pointsLength = points.length; i < pointsLength; i++) { final Point point = points[i]; jsonArray.set(i, convertPointToJSON(point)); @@ -2073,14 +2099,20 @@ public abstract class BaseChart extends Widget { } // Purposefully package scope so we can get to this method from the Series and Point classes as well - static JSONValue convertPointToJSON(Point point) { + JSONValue convertPointToJSON(Point point) { JSONObject options = point.getOptions(); if (options != null) { - return addPointScalarValues(point, options); + addPointScalarValues(point, options); + return addPointId(point, options); } else if(point.hasNativeProperties()) { options = new JSONObject(); addPointScalarValues(point, options); + addPointId(point, options); return Point.addPointNativeProperties(point, options); + } else if(isPersistent()) { + options = new JSONObject(); + addPointScalarValues(point, options); + return addPointId(point, options); } else if (point.getX() != null) { JSONArray jsonArray = new JSONArray(); jsonArray.set(0, new JSONNumber(point.getX().doubleValue())); @@ -2104,6 +2136,19 @@ public abstract class BaseChart extends Widget { } } + // Purposefully package scope + JSONValue addPointId(Point point, JSONObject options) { + if (isPersistent()) { + String id = point.getId(); + if(id == null) { + id = Document.get().createUniqueId(); + point.setId(id); + } + options.put("id", new JSONString(id)); + } + return options; + } + // Purposefully package scope static JSONValue addPointScalarValues(Point point, JSONObject options) { if (point.getX() != null) { @@ -2141,9 +2186,12 @@ public abstract class BaseChart extends Widget { private native JavaScriptObject nativeRenderChart(String chartTypeName, JavaScriptObject options, boolean toolTipFormatterFlag, + boolean legendLabelsFormatterFlag, JavaScriptObject chartEventHandlerFlags, JavaScriptObject seriesEventHandlerFlags, JavaScriptObject pointEventHandlerFlags, + JavaScriptObject xAxisEventHandlerFlags, + JavaScriptObject yAxisEventHandlerFlags, JavaScriptObject xAxisLabelFormatterFlags, JavaScriptObject yAxisLabelFormatterFlags, JavaScriptObject yAxisStackLabelFormatterFlags, @@ -2189,6 +2237,32 @@ public abstract class BaseChart extends Widget { options.plotOptions.series.point.events[type3].type = type3; } } + + // Add in GWT interceptor callback functions for the various X axis event handlers + for (i = 0; i < xAxisEventHandlerFlags.length; i++) { + if (!xAxisEventHandlerFlags[i]) continue; + var xAxisA = xAxisEventHandlerFlags.length == 1 ? options.xAxis : options.xAxis[i]; + xAxisA.events = xAxisA.events || {}; + for (var type4 in xAxisEventHandlerFlags[i]) { + xAxisA.events[type4] = function(e) { + return self.@org.moxieapps.gwt.highcharts.client.BaseChart::axisEventCallback(Ljava/lang/String;Lcom/google/gwt/core/client/JavaScriptObject;Ljava/lang/String;)(this.options.id, e, arguments.callee.type); + }; + xAxisA.events[type4].type = type4; + } + } + + // Add in GWT interceptor callback functions for the various Y axis event handlers + for (i = 0; i < yAxisEventHandlerFlags.length; i++) { + if (!yAxisEventHandlerFlags[i]) continue; + var yAxisA = yAxisEventHandlerFlags.length == 1 ? options.yAxis : options.yAxis[i]; + yAxisA.events = yAxisA.events || {}; + for (var type5 in yAxisEventHandlerFlags[i]) { + yAxisA.events[type5] = function(e) { + return self.@org.moxieapps.gwt.highcharts.client.BaseChart::axisEventCallback(Ljava/lang/String;Lcom/google/gwt/core/client/JavaScriptObject;Ljava/lang/String;)(this.options.id, e, arguments.callee.type); + }; + yAxisA.events[type5].type = type5; + } + } // Add in GWT interceptor callback functions for the various formatters so that we can move from // the native JS world back to the Java world... @@ -2202,47 +2276,57 @@ public abstract class BaseChart extends Widget { return result; }; } + if (legendLabelsFormatterFlag) { + options.legend = options.legend || {}; + options.legend.labelFormatter = function() { + var result = self.@org.moxieapps.gwt.highcharts.client.BaseChart::legendLabelsFormatterCallback(Lcom/google/gwt/core/client/JavaScriptObject;)(this); + if (result == null) { + return false; + } + return result; + }; + } // X axis label formatters for (i = 0; i < xAxisLabelFormatterFlags.length; i++) { if (!xAxisLabelFormatterFlags[i]) continue; - var xAxis = xAxisLabelFormatterFlags.length == 1 ? options.xAxis : options.xAxis[i]; - xAxis.labels = xAxis.labels || {}; - xAxis.labels.formatter = function() { + var xAxisB = xAxisLabelFormatterFlags.length == 1 ? options.xAxis : options.xAxis[i]; + xAxisB.labels = xAxisB.labels || {}; + xAxisB.labels.formatter = function() { return self.@org.moxieapps.gwt.highcharts.client.BaseChart::xAxisLabelFormatterCallback(Lcom/google/gwt/core/client/JavaScriptObject;I)(this, arguments.callee.index); }; - xAxis.labels.formatter.index = i; + xAxisB.labels.formatter.index = i; } // Y axis label formatters for (i = 0; i < yAxisLabelFormatterFlags.length && i < yAxisStackLabelFormatterFlags.length; i++) { - var yAxis = yAxisLabelFormatterFlags.length == 1 ? options.yAxis : options.yAxis[i]; + var yAxisB = yAxisLabelFormatterFlags.length == 1 ? options.yAxis : options.yAxis[i]; if (yAxisLabelFormatterFlags[i]) { - yAxis.labels = yAxis.labels || {}; - yAxis.labels.formatter = function() { + yAxisB.labels = yAxisB.labels || {}; + yAxisB.labels.formatter = function() { return self.@org.moxieapps.gwt.highcharts.client.BaseChart::yAxisLabelFormatterCallback(Lcom/google/gwt/core/client/JavaScriptObject;I)(this, arguments.callee.index); }; - yAxis.labels.formatter.index = i; + yAxisB.labels.formatter.index = i; } if (yAxisStackLabelFormatterFlags[i]) { - yAxis.stackLabels = yAxis.stackLabels || {}; - yAxis.stackLabels.formatter = function() { + yAxisB.stackLabels = yAxisB.stackLabels || {}; + yAxisB.stackLabels.formatter = function() { return self.@org.moxieapps.gwt.highcharts.client.BaseChart::yAxisStackLabelFormatterCallback(Lcom/google/gwt/core/client/JavaScriptObject;I)(this, arguments.callee.index); }; - yAxis.stackLabels.formatter.index = i; + yAxisB.stackLabels.formatter.index = i; } } // Plot options data label formatters - for (var type4 in plotOptionsLabelsFormatterFlags) { - if (type4.indexOf("gwt") < 0 && plotOptionsLabelsFormatterFlags[type4]) { + for (var type6 in plotOptionsLabelsFormatterFlags) { + if (type6.indexOf("gwt") < 0 && plotOptionsLabelsFormatterFlags[type6]) { options.plotOptions = options.plotOptions || {}; - options.plotOptions[type4] = options.plotOptions[type4] || {}; - options.plotOptions[type4].dataLabels = options.plotOptions[type4].dataLabels || {}; - options.plotOptions[type4].dataLabels.formatter = function() { + options.plotOptions[type6] = options.plotOptions[type6] || {}; + options.plotOptions[type6].dataLabels = options.plotOptions[type6].dataLabels || {}; + options.plotOptions[type6].dataLabels.formatter = function() { return self.@org.moxieapps.gwt.highcharts.client.BaseChart::plotOptionsLabelsFormatterCallback(Lcom/google/gwt/core/client/JavaScriptObject;Ljava/lang/String;)(this, arguments.callee.type); }; - options.plotOptions[type4].dataLabels.formatter.type = type4; + options.plotOptions[type6].dataLabels.formatter.type = type6; } } @@ -2316,6 +2400,16 @@ public abstract class BaseChart extends Widget { } return true; } + + @SuppressWarnings({"UnusedDeclaration"}) + private boolean axisEventCallback(String axisId, JavaScriptObject nativeEvent, String eventType) { + Axis axis = getAxis(axisId); + //noinspection SimplifiableIfStatement + if ("setExtremes".equals(eventType) && axis != null && axis.getAxisSetExtremesEventHandler() != null) { + return axis.getAxisSetExtremesEventHandler().onSetExtremes(new AxisSetExtremesEvent(nativeEvent, axis)); + } + return true; + } @SuppressWarnings({"UnusedDeclaration"}) private String toolTipFormatterCallback(JavaScriptObject nativeData) { @@ -2325,6 +2419,14 @@ public abstract class BaseChart extends Widget { return toolTip.getToolTipFormatter().format(new ToolTipData(nativeData)); } + @SuppressWarnings({"UnusedDeclaration"}) + private String legendLabelsFormatterCallback(JavaScriptObject nativeData) { + if (legend == null || legend.getLabelsFormatter() == null) { + return null; + } + return legend.getLabelsFormatter().format(new LegendLabelsData(nativeData)); + } + @SuppressWarnings({"UnusedDeclaration"}) private String xAxisLabelFormatterCallback(JavaScriptObject nativeData, int axisIndex) { if (xAxes == null || xAxes.size() <= axisIndex || @@ -2385,6 +2487,22 @@ public abstract class BaseChart extends Widget { return seriesList.get(seriesIndex).getPlotOptions().getDataLabels().getFormatter().format(new DataLabelsData(nativeData)); } + /** + * Fixing a bug currently in the base Highcharts implementation regarding the placement of the checkbox in the legend. + * Requires the symbol padding (see {@link Legend#setSymbolPadding(Number)}) to be set to 20. Invoked + * whenever a series is added / displayed in a rendered chart.

+ * + * The implementation moves the legend item text 15px to the left, using the space made by setting the symbol + * padding to 20px; the checkbox is moved 18px to the left with the top margin set to 0px. + */ + private static native JavaScriptObject nativeAdjustCheckboxPosition(JavaScriptObject series) /*-{ + if (series.legendItem && series.checkbox) { + series.legendItem.translate(-15, 0); + series.checkbox.style.marginLeft = '-18px' + series.checkbox.style.marginTop = '0px' + } + }-*/; + private static native void nativeRedraw(JavaScriptObject chart) /*-{ chart.redraw(); }-*/; diff --git a/java/org.moxieapps.gwt.highcharts/src/org/moxieapps/gwt/highcharts/client/Legend.java b/java/org.moxieapps.gwt.highcharts/src/org/moxieapps/gwt/highcharts/client/Legend.java index 14181eb8742..fa10209135c 100755 --- a/java/org.moxieapps.gwt.highcharts/src/org/moxieapps/gwt/highcharts/client/Legend.java +++ b/java/org.moxieapps.gwt.highcharts/src/org/moxieapps/gwt/highcharts/client/Legend.java @@ -16,6 +16,8 @@ package org.moxieapps.gwt.highcharts.client; +import org.moxieapps.gwt.highcharts.client.labels.LegendLabelsFormatter; + /** * A configurable class that can be used to represent custom legend options for the * chart, which can then be set on the chart (via the {@link Chart#setLegend(Legend)} method.) @@ -317,7 +319,35 @@ public class Legend extends Configurable { return this.setOption("layout", layout != null ? layout.toString() : null); } - // TODO: Add label formatter + private LegendLabelsFormatter legendLabelsFormatter; + + /** + * Sets a custom formatter for the labels that can be used to control how the text of the + * legend labels will be displayed. See the {@link LegendLabelsFormatter} interface, and + * in particular the {@link LegendLabelsFormatter#format(org.moxieapps.gwt.highcharts.client.labels.LegendLabelsData)} + * method for more details on the capabilities available to custom legend formatters. + * + * @param legendLabelsFormatter The custom formatter to use for the labels (if not given a built-in + * generic formatter is used which simply returns the name of the series + * or, for pie charts, the name of the point). + * @return A reference to this {@link Legend} instance for convenient method chaining. + * @since 1.3.0 + */ + public Legend setLabelsFormatter(LegendLabelsFormatter legendLabelsFormatter) { + this.legendLabelsFormatter = legendLabelsFormatter; + return this; + } + + /** + * Returns the custom labels formatter that has been applied to the legend, or null if the + * built-in generic formatter is being used instead. + * + * @return The custom data labels formatter that has been applied, or null if it has not been set. + * @since 1.3.0 + */ + public LegendLabelsFormatter getLabelsFormatter() { + return this.legendLabelsFormatter; + } /** * Convenience method for setting the 'margin' option of the legend. Equivalent to: diff --git a/java/org.moxieapps.gwt.highcharts/src/org/moxieapps/gwt/highcharts/client/Point.java b/java/org.moxieapps.gwt.highcharts/src/org/moxieapps/gwt/highcharts/client/Point.java index 2d00b27640d..027f6bf0b22 100644 --- a/java/org.moxieapps.gwt.highcharts/src/org/moxieapps/gwt/highcharts/client/Point.java +++ b/java/org.moxieapps.gwt.highcharts/src/org/moxieapps/gwt/highcharts/client/Point.java @@ -365,7 +365,10 @@ public class Point extends Configurable { * animation options.

* Note that this method is only relevant on Point instance that are obtained from the chart * after it has been rendered, such as via an event or dynamically retrieving the points of - * a series. + * a series.

+ * Also note that when using persistent chart's, you'll normally want to use the + * {@link Series#removePoint(Point)} method instead of this one. + * * * @return A reference to this {@link Point} instance for convenient method chaining. * @since 1.1.0 @@ -379,7 +382,9 @@ public class Point extends Configurable { * and/or animated or not.

* Note that this method is only relevant on Point instance that are obtained from the chart * after it has been rendered, such as via an event or dynamically retrieving the points of - * a series. + * a series.

+ * Also note that when using persistent chart's, you'll normally want to use the + * {@link Series#removePoint(Point, boolean, boolean)} method instead of this one. * * @param redraw Whether to redraw the chart after the point is removed. When removing more than one * point, it is highly recommended that the redraw option be set to false, and instead @@ -399,7 +404,9 @@ public class Point extends Configurable { * and the details of the animation options.

* Note that this method is only relevant on Point instance that are obtained from the chart * after it has been rendered, such as via an event or dynamically retrieving the points of - * a series. + * a series.

+ * Also note that when using persistent chart's, you'll normally want to use the + * {@link Series#removePoint(Point, boolean, Animation)} method instead of this one. * * @param redraw Whether to redraw the chart after the point is removed. When removing more than one * point, it is highly recommended that the redraw option be set to false, and instead @@ -677,7 +684,7 @@ public class Point extends Configurable { nativeUpdate(this.nativePoint, pointOptions.getY().doubleValue(), redraw, animation != null); } } else { - nativeUpdate(this.nativePoint, Series.convertPointToJavaScriptObject(pointOptions), redraw, animation != null); + nativeUpdate(this.nativePoint, convertPointToJavaScriptObject(pointOptions), redraw, animation != null); } } else { if (pointOptions.isSingleValue()) { @@ -687,7 +694,7 @@ public class Point extends Configurable { nativeUpdate(this.nativePoint, pointOptions.getY().doubleValue(), redraw, animation.getOptions().getJavaScriptObject()); } } else { - nativeUpdate(this.nativePoint, Series.convertPointToJavaScriptObject(pointOptions), redraw, animation.getOptions().getJavaScriptObject()); + nativeUpdate(this.nativePoint, convertPointToJavaScriptObject(pointOptions), redraw, animation.getOptions().getJavaScriptObject()); } } } else { @@ -728,6 +735,32 @@ public class Point extends Configurable { return options; } + // Only needed and used when handling removing of points from charts that have been set in "persistent" mode + private String id; + + // Internal method purposefully package scope + void setId(String id) { + this.id = id; + } + + // Internal method purposefully package scope + String getId() { + if(this.nativePoint != null) { + return nativeGetString(this.nativePoint, "id"); + } else { + return this.id; + } + } + + private static JavaScriptObject convertPointToJavaScriptObject(Point point) { + final JSONObject options = point.getOptions() != null ? point.getOptions() : new JSONObject(); + Chart.addPointScalarValues(point, options); + if(point.hasNativeProperties()) { + Point.addPointNativeProperties(point, options); + } + return options.getJavaScriptObject(); + } + private static native boolean nativeContainsKey(JavaScriptObject point, String key) /*-{ return point[key] != undefined; }-*/; diff --git a/java/org.moxieapps.gwt.highcharts/src/org/moxieapps/gwt/highcharts/client/Series.java b/java/org.moxieapps.gwt.highcharts/src/org/moxieapps/gwt/highcharts/client/Series.java index de2c0105e9e..1c9798adb0b 100644 --- a/java/org.moxieapps.gwt.highcharts/src/org/moxieapps/gwt/highcharts/client/Series.java +++ b/java/org.moxieapps.gwt.highcharts/src/org/moxieapps/gwt/highcharts/client/Series.java @@ -27,6 +27,7 @@ import org.moxieapps.gwt.highcharts.client.plotOptions.PlotOptions; import java.util.ArrayList; import java.util.Collections; +import java.util.Iterator; /** * Manages a data series (and its options) that can then be added to a {@link Chart}. As an extension @@ -513,14 +514,14 @@ public class Series extends Configurable { if (nativeSeries != null) { if (animation == null || animation.getOptions() == null) { final boolean animationFlag = animation != null; - if (point.isSingleValue()) { + if (point.isSingleValue() && !chart.isPersistent() && !point.hasNativeProperties()) { nativeAddPoint(nativeSeries, point.getY(), redraw, shift, animationFlag); } else { nativeAddPoint(nativeSeries, convertPointToJavaScriptObject(point), redraw, shift, animationFlag); } } else { final JavaScriptObject animationOptions = animation.getOptions().getJavaScriptObject(); - if (point.isSingleValue()) { + if (point.isSingleValue() && !chart.isPersistent() && !point.hasNativeProperties()) { nativeAddPoint(nativeSeries, point.getY(), redraw, shift, animationOptions); } else { nativeAddPoint(nativeSeries, convertPointToJavaScriptObject(point), redraw, shift, animationOptions); @@ -531,13 +532,15 @@ public class Series extends Configurable { return this; } - // Purposefully friendly scope so that we can get to this method from the Point class as well - static JavaScriptObject convertPointToJavaScriptObject(Point point) { + private JavaScriptObject convertPointToJavaScriptObject(Point point) { final JSONObject options = point.getOptions() != null ? point.getOptions() : new JSONObject(); Chart.addPointScalarValues(point, options); if(point.hasNativeProperties()) { Point.addPointNativeProperties(point, options); } + if(chart != null) { + chart.addPointId(point, options); + } return options.getJavaScriptObject(); } @@ -696,7 +699,7 @@ public class Series extends Configurable { if (nativeSeries != null) { JSONArray jsonArray = new JSONArray(); for (int i = 0, pointsLength = points.length; i < pointsLength; i++) { - jsonArray.set(i, Chart.convertPointToJSON(points[i])); + jsonArray.set(i, chart.convertPointToJSON(points[i])); } nativeSetData(nativeSeries, jsonArray.getJavaScriptObject(), redraw); } @@ -730,6 +733,91 @@ public class Series extends Configurable { return convertedPoints.toArray(new Point[convertedPoints.size()]); } + /** + * Remove the point from the series, automatically redrawing the chart using the default + * animation options.

+ * Note that this method is only relevant given Point instances that are obtained from the chart + * after it has been rendered, such as via an event or dynamically retrieving the points of + * a series.

+ * Also note that this method is primarily intended to ensure compatibility with chart's + * that have been set in persistent mode via the {@link BaseChart#setPersistent(boolean)} method. + * If you're using non-persistent charts, you can instead simply use the + * {@link Point#remove()} method to achieve the same affect. + * + * @param point The point instance (obtained dynamically from the chart) to remove from the series. + * + * @return A reference to this {@link Series} instance for convenient method chaining. + * @since 1.3.0 + */ + public Series removePoint(Point point) { + return this.removePoint(point, true, true); + } + + /** + * Remove the point from the series, explicitly controlling whether the chart is redrawn + * and/or animated or not.

+ * Note that this method is only relevant given Point instances that are obtained from the chart + * after it has been rendered, such as via an event or dynamically retrieving the points of + * a series.

+ * Also note that this method is primarily intended to ensure compatibility with chart's + * that have been set in persistent mode via the {@link BaseChart#setPersistent(boolean)} method. + * If you're using non-persistent charts, you can instead simply use the + * {@link Point#remove(boolean, boolean)} method to achieve the same affect. + * + * @param point The point instance (obtained dynamically from the chart) to remove from the series. + * @param redraw Whether to redraw the chart after the point is removed. When removing more than one + * point, it is highly recommended that the redraw option be set to false, and instead + * {@link Chart#redraw()} is explicitly called after the removing of points is finished. + * @param animation Defaults to true. When true, the graph will be animated with default animation options. + * Note, see the {@link #removePoint(Point, boolean, Animation)} method + * for more control over how the animation will run. + * @return A reference to this {@link Series} instance for convenient method chaining. + * @since 1.3.0 + */ + public Series removePoint(Point point, boolean redraw, boolean animation) { + return this.removePoint(point, redraw, animation ? new Animation() : null); + } + + /** + * Remove the point from the series, explicitly controlling whether the chart is redrawn + * and the details of the animation options.

+ * Note that this method is only relevant given Point instances that are obtained from the chart + * after it has been rendered, such as via an event or dynamically retrieving the points of + * a series.

+ * Also note that this method is primarily intended to ensure compatibility with chart's + * that have been set in persistent mode via the {@link BaseChart#setPersistent(boolean)} method. + * If you're using non-persistent charts, you can instead simply use the + * {@link Point#remove(boolean, Animation)} method to achieve the same affect. + * + * @param point The point instance (obtained dynamically from the chart) to remove from the series. + * @param redraw Whether to redraw the chart after the point is removed. When removing more than one + * point, it is highly recommended that the redraw option be set to false, and instead + * {@link Chart#redraw()} is explicitly called after the removing of points is finished. + * @param animation The custom animation to use when removing the point from the series. + * @return A reference to this {@link Series} instance for convenient method chaining. + * @since 1.3.0 + */ + public Series removePoint(Point point, boolean redraw, Animation animation) { + String id = point.getId(); + + // First, tell the point to remove itself from the underlying Highcharts instance + point.remove(redraw, animation); + + // Second, find the matching point within the series, and remove it. + // Note that this logic is purposefully only functional for chart's that are using the "setPersistent()" + // option. Removing a point from a non-persistent chart can be achieved by simply using + // the "Point.remove()" methods. + if(id != null && points != null) { + for (Iterator iterator = points.iterator(); iterator.hasNext(); ) { + Point existingPoint = iterator.next(); + if(id.equals(existingPoint.getId())) { + iterator.remove(); + } + } + } + return this; + } + /** * Remove this series from the chart it is a part of. * diff --git a/java/org.moxieapps.gwt.highcharts/src/org/moxieapps/gwt/highcharts/client/labels/BaseDataLabels.java b/java/org.moxieapps.gwt.highcharts/src/org/moxieapps/gwt/highcharts/client/labels/BaseDataLabels.java index ea44795e6f2..dbf2e3c24a7 100755 --- a/java/org.moxieapps.gwt.highcharts/src/org/moxieapps/gwt/highcharts/client/labels/BaseDataLabels.java +++ b/java/org.moxieapps.gwt.highcharts/src/org/moxieapps/gwt/highcharts/client/labels/BaseDataLabels.java @@ -26,6 +26,96 @@ package org.moxieapps.gwt.highcharts.client.labels; */ public abstract class BaseDataLabels extends Labels { + /** + * Convenience method for setting the 'backgroundColor' option for the data labels. Equivalent to: + *


+     *     labels.setOption("backgroundColor", "#CC0000");
+     * 
+ * The background color or gradient for the data label. Defaults to undefined. + * + * @param backgroundColor The background color or gradient for the data label. + * @return A reference to this {@link BaseDataLabels} instance for convenient method chaining. + * @since 1.3.0 + */ + public T setBackgroundColor(String backgroundColor) { + return this.setOption("backgroundColor", backgroundColor); + } + + /** + * Convenience method for setting the 'borderColor' option for the data labels. Equivalent to: + *

+     *     labels.setOption("borderColor", "#CC0000");
+     * 
+ * The border color for the data label. Defaults to undefined. + * + * @param borderColor The border color for the data label. + * @return A reference to this {@link BaseDataLabels} instance for convenient method chaining. + * @since 1.3.0 + */ + public T setBorderColor(String borderColor) { + return this.setOption("borderColor", borderColor); + } + + /** + * Convenience method for setting the 'borderRadius' option for the data labels. Equivalent to: + *

+     *     labels.setOption("borderRadius", 3);
+     * 
+ * The border radius in pixels for the data label. Defaults to 0. + * + * @param borderRadius The border radius in pixels for the data label. + * @return A reference to this {@link BaseDataLabels} instance for convenient method chaining. + * @since 1.3.0 + */ + public T setBorderRadius(Number borderRadius) { + return this.setOption("borderRadius", borderRadius); + } + + /** + * Convenience method for setting the 'borderWidth' option for the data labels. Equivalent to: + *

+     *     labels.setOption("borderWidth", 3);
+     * 
+ * The border width in pixels for the data label. Defaults to 0. + * + * @param borderWidth The border width in pixels for the data label. + * @return A reference to this {@link BaseDataLabels} instance for convenient method chaining. + * @since 1.3.0 + */ + public T setBorderWidth(Number borderWidth) { + return this.setOption("borderWidth", borderWidth); + } + + /** + * Convenience method for setting the 'padding' option for the data labels. Equivalent to: + *

+     *     labels.setOption("padding", 3);
+     * 
+ * When either the borderWidth or the backgroundColor is set, this is the padding within the box. Defaults to 2. + * + * @param padding The padding within the box (only visible when 'borderWidth' is non-zero). + * @return A reference to this {@link BaseDataLabels} instance for convenient method chaining. + * @since 1.3.0 + */ + public T setPadding(Number padding) { + return this.setOption("padding", padding); + } + + /** + * Convenience method for setting the 'shadow' option for the data labels. Equivalent to: + *

+     *     labels.setOption("shadow", true);
+     * 
+ * The shadow of the box. Works best with borderWidth or backgroundColor Defaults to false. + * + * @param shadow 'true' to disable a shadow around the box. + * @return A reference to this {@link BaseDataLabels} instance for convenient method chaining. + * @since 1.3.0 + */ + public T setShadow(boolean shadow) { + return this.setOption("shadow", shadow); + } + private DataLabelsFormatter dataLabelsFormatter; /** diff --git a/java/org.moxieapps.gwt.highcharts/src/org/moxieapps/gwt/highcharts/client/plotOptions/Marker.java b/java/org.moxieapps.gwt.highcharts/src/org/moxieapps/gwt/highcharts/client/plotOptions/Marker.java index 43e161d8c73..11d24f54635 100755 --- a/java/org.moxieapps.gwt.highcharts/src/org/moxieapps/gwt/highcharts/client/plotOptions/Marker.java +++ b/java/org.moxieapps.gwt.highcharts/src/org/moxieapps/gwt/highcharts/client/plotOptions/Marker.java @@ -23,7 +23,7 @@ import org.moxieapps.gwt.highcharts.client.Configurable; * Controls configuration options for the markers within a series. Can be set as a plot option on a series * via the {@link PlotOptions#setMarker(Marker)} method. Example usage: *
- *   chart.setPlotOptions(new PlotOptions()
+ *   chart.setSeriesPlotOptions(new SeriesPlotOptions()
  *      .setMarker(
  *         new Marker()
  *            .setEnabled(true)
@@ -41,6 +41,11 @@ public class Marker extends Configurable {
     /**
      * An enumeration of supported marker symbol types, which can be passed to methods
      * like {@link Marker#setSymbol(Marker.Symbol)} method.
+     * 

Note that custom marker images are also supported by simply setting the + * "symbol" option to a URL reference. E.g. + *


+     *    marker.setOption("symbol", "url(/serverpath/image.png)");
+     * 
*/ public enum Symbol { @@ -246,6 +251,11 @@ public class Marker extends Configurable { * A predefined shape or symbol for the marker. When null, the symbol is pulled from the default * {@link org.moxieapps.gwt.highcharts.client.Chart#setSymbols(org.moxieapps.gwt.highcharts.client.plotOptions.Marker.Symbol[])} * options. Defaults to null. + *

+ * Note that custom marker images are also supported by simply setting the "symbol" option to a URL reference. E.g. + *


+     *     marker.setOption("symbol", "url(/serverpath/image.png)");
+     * 
* * @param symbol The shape or symbol for the marker. * @return A reference to this {@link Marker} instance for convenient method chaining.