// draw track line with data labels
        private void trackLineLabel(XYChart c, int mouseX)
        {
            DrawArea d = c.initDynamicLayer();

            PlotArea plotArea = c.getPlotArea();
            double   xValue   = c.getNearestXValue(mouseX);

            int xCoor = c.getXCoor(xValue);

            d.vline(plotArea.getTopY(), plotArea.getBottomY(), xCoor, d.dashLineColor(0x000000, 0x0101));


            // container to hold the legned entries
            ArrayList legendEntries = new ArrayList();

            for (int i = 0; i < c.getLayerCount(); ++i)
            {
                Layer layer  = c.getLayerByZ(i);
                int   xIndex = layer.getXIndexOf(xValue);

                // iterate through all the data sets in the layer
                for (int j = 0; j < layer.getDataSetCount(); ++j)
                {
                    ChartDirector.DataSet dataSet = layer.getDataSetByZ(j);
                    // we are only interested in visibale sets with names
                    string dataName = dataSet.getDataName();
                    int    color    = dataSet.getDataColor();
                    if ((!string.IsNullOrEmpty(dataName)) && (color != Chart.Transparent))
                    {
                        // Build the legend entry, consist of the legend icon, name and data value.
                        double dataValue = dataSet.getValue(xIndex);
                        legendEntries.Add("<*block*>" + dataSet.getLegendIcon() + " " + dataName + ": " + ((
                                                                                                               dataValue == Chart.NoValue) ? "N/A" : c.formatValue(dataValue, "{value|P4}")) +
                                          "<*/*>");

                        // Draw a track dot for data points within the plot area
                        int yCoor = c.getYCoor(dataSet.getPosition(xIndex), dataSet.getUseYAxis());
                        if ((yCoor >= plotArea.getTopY()) && (yCoor <= plotArea.getBottomY()))
                        {
                            d.circle(xCoor, yCoor, 4, 4, color, color);
                        }
                    }
                }
            }
            // Create the legend by joining the legend entries
            legendEntries.Reverse();
            string legendText = "<*block,maxWidth=" + plotArea.getWidth() + "*><*block*><*font=Arial Bold*>["
                                + c.xAxis().getFormattedLabel(xValue, "{value|P4") + "]<*/*>        " + String.Join(
                "        ", (string[])legendEntries.ToArray(typeof(string))) + "<*/*>";

            // Display the legend on the top of the plot area
            TTFText t = d.text(legendText, "Arial", 8);

            t.draw(plotArea.getLeftX() + 5, plotArea.getTopY() - 3, 0x000000, Chart.BottomLeft);
        }
Beispiel #2
0
        void drawTrackLine(XYChart c, int lineX, Dictionary <string, double> log)
        {
            // The drawarea and plotarea objects
            DrawArea d        = c.getDrawArea();
            PlotArea plotArea = c.getPlotArea();

            // Get the data x-value that is nearest to the mouse, and find its pixel coordinate.
            double xValue = c.getNearestXValue(lineX);
            int    xCoor  = c.getXCoor(xValue);

            // Draw empty track line if it is ahead of the data
            if ((currentIndex <= 0) || ((xCoor < lineX) && (xValue >= chartTimeLimit)))
            {
                d.vline(plotArea.getTopY(), plotArea.getBottomY(), lineX, 0x888888);
                return;
            }

            // Draw a vertical track line at the x-position
            d.vline(plotArea.getTopY(), plotArea.getBottomY(), xCoor, 0x888888);

            // Draw a label on the x-axis to show the track line position.
            string xlabel = "<*font,bgColor=000000*> " + c.xAxis().getFormattedLabel(xValue, "nn:ss.ff") +
                            " <*/font*>";
            TTFText t = d.text(xlabel, "Arial Bold", 10);

            log["x"] = xValue;

            // Restrict the x-pixel position of the label to make sure it stays inside the chart image.
            int xLabelPos = Math.Max(0, Math.Min(xCoor - t.getWidth() / 2, c.getWidth() - t.getWidth()));

            t.draw(xLabelPos, plotArea.getBottomY() + 6, 0xffffff);

            // Iterate through all layers to draw the data labels
            for (int i = 0; i < c.getLayerCount(); ++i)
            {
                Layer layer = c.getLayerByZ(i);

                // The data array index of the x-value
                int xIndex = layer.getXIndexOf(xValue);

                // Iterate through all the data sets in the layer
                for (int j = 0; j < layer.getDataSetCount(); ++j)
                {
                    ChartDirector.DataSet dataSet = layer.getDataSetByZ(j);

                    // Get the color and position of the data label
                    int color = dataSet.getDataColor();
                    int yCoor = c.getYCoor(dataSet.getPosition(xIndex), dataSet.getUseYAxis());

                    // Draw a track dot with a label next to it for visible data points in the plot area
                    if ((yCoor >= plotArea.getTopY()) && (yCoor <= plotArea.getBottomY()) && (color !=
                                                                                              Chart.Transparent) && (!string.IsNullOrEmpty(dataSet.getDataName())))
                    {
                        d.circle(xCoor, yCoor, 4, 4, color, color);

                        string label = "<*font,bgColor=" + color.ToString("x") + "*> " + c.formatValue(
                            dataSet.getValue(xIndex), "{value|P4}") + " <*/font*>";
                        t = d.text(label, "Arial Bold", 10);
                        log[dataSet.getDataName()] = dataSet.getValue(xIndex);

                        // Draw the label on the right side of the dot if the mouse is on the left side the
                        // chart, and vice versa. This ensures the label will not go outside the chart image.
                        if (xCoor <= (plotArea.getLeftX() + plotArea.getRightX()) / 2)
                        {
                            t.draw(xCoor + 5, yCoor, 0xffffff, Chart.Left);
                        }
                        else
                        {
                            t.draw(xCoor - 5, yCoor, 0xffffff, Chart.Right);
                        }
                    }
                }
            }
        }
        //
        // Draw track line with data labels
        //
        private void trackLineLabel(XYChart c, int mouseX)
        {
            // Clear the current dynamic layer and get the DrawArea object to draw on it.
            DrawArea d = c.initDynamicLayer();

            // The plot area object
            PlotArea plotArea = c.getPlotArea();

            // Get the data x-value that is nearest to the mouse, and find its pixel coordinate.
            double xValue = c.getNearestXValue(mouseX);
            int    xCoor  = c.getXCoor(xValue);

            // Draw a vertical track line at the x-position
            d.vline(plotArea.getTopY(), plotArea.getBottomY(), xCoor, d.dashLineColor(0x000000, 0x0101));

            // Draw a label on the x-axis to show the track line position.
            string xlabel = "<*font,bgColor=000000*> " + c.xAxis().getFormattedLabel(xValue, "mmm dd, yyyy") +
                            " <*/font*>";
            TTFText t = d.text(xlabel, "Arial Bold", 8);

            // Restrict the x-pixel position of the label to make sure it stays inside the chart image.
            int xLabelPos = Math.Max(0, Math.Min(xCoor - t.getWidth() / 2, c.getWidth() - t.getWidth()));

            t.draw(xLabelPos, plotArea.getBottomY() + 6, 0xffffff);

            // Iterate through all layers to draw the data labels
            for (int i = 0; i < c.getLayerCount(); ++i)
            {
                Layer layer = c.getLayerByZ(i);

                // The data array index of the x-value
                int xIndex = layer.getXIndexOf(xValue);

                // Iterate through all the data sets in the layer
                for (int j = 0; j < layer.getDataSetCount(); ++j)
                {
                    ChartDirector.DataSet dataSet = layer.getDataSetByZ(j);

                    // Get the color and position of the data label
                    int color = dataSet.getDataColor();
                    int yCoor = c.getYCoor(dataSet.getPosition(xIndex), dataSet.getUseYAxis());

                    // Draw a track dot with a label next to it for visible data points in the plot area
                    if ((yCoor >= plotArea.getTopY()) && (yCoor <= plotArea.getBottomY()) && (color !=
                                                                                              Chart.Transparent))
                    {
                        d.circle(xCoor, yCoor, 4, 4, color, color);

                        string label = "<*font,bgColor=" + color.ToString("x") + "*> " + c.formatValue(
                            dataSet.getValue(xIndex), "{value|P4}") + " <*/font*>";
                        t = d.text(label, "Arial Bold", 8);

                        // Draw the label on the right side of the dot if the mouse is on the left side the
                        // chart, and vice versa. This ensures the label will not go outside the chart image.
                        if (xCoor <= (plotArea.getLeftX() + plotArea.getRightX()) / 2)
                        {
                            t.draw(xCoor + 5, yCoor, 0xffffff, Chart.Left);
                        }
                        else
                        {
                            t.draw(xCoor - 5, yCoor, 0xffffff, Chart.Right);
                        }
                    }
                }
            }
        }
Beispiel #4
0
        //
        // Draw the track box with legend
        //
        private void trackBoxLegend(XYChart c, int mouseX, int mouseY)
        {
            // Clear the current dynamic layer and get the DrawArea object to draw on it.
            DrawArea d = c.initDynamicLayer();

            // The plot area object
            PlotArea plotArea = c.getPlotArea();

            // Get the data x-value that is nearest to the mouse
            double xValue = c.getNearestXValue(mouseX);

            // Compute the position of the box. This example assumes a label based x-axis, in which the
            // labeling spacing is one x-axis unit. So the left and right sides of the box is 0.5 unit from
            // the central x-value.
            int boxLeft   = c.getXCoor(xValue - 0.5);
            int boxRight  = c.getXCoor(xValue + 0.5);
            int boxTop    = plotArea.getTopY();
            int boxBottom = plotArea.getBottomY();

            // Draw the track box
            d.rect(boxLeft, boxTop, boxRight, boxBottom, 0x000000, Chart.Transparent);

            // Container to hold the legend entries
            ArrayList legendEntries = new ArrayList();

            // Iterate through all layers to build the legend array
            for (int i = 0; i < c.getLayerCount(); ++i)
            {
                Layer layer = c.getLayerByZ(i);

                // The data array index of the x-value
                int xIndex = layer.getXIndexOf(xValue);

                // Iterate through all the data sets in the layer
                for (int j = 0; j < layer.getDataSetCount(); ++j)
                {
                    ChartDirector.DataSet dataSet = layer.getDataSetByZ(j);

                    // Build the legend entry, consist of the legend icon, the name and the data value.
                    double dataValue = dataSet.getValue(xIndex);
                    if ((dataValue != Chart.NoValue) && (dataSet.getDataColor() != Chart.Transparent))
                    {
                        legendEntries.Add(dataSet.getLegendIcon() + " " + dataSet.getDataName() + ": " +
                                          c.formatValue(dataValue, "{value|P4}"));
                    }
                }
            }

            // Create the legend by joining the legend entries
            if (legendEntries.Count > 0)
            {
                legendEntries.Reverse();
                string legend = "<*block,bgColor=FFFFCC,edgeColor=000000,margin=5*><*font,underline=1*>" +
                                c.xAxis().getFormattedLabel(xValue) + "<*/font*><*br*>" + String.Join("<*br*>", (string[])
                                                                                                      legendEntries.ToArray(typeof(string))) + "<*/*>";

                // Display the legend at the bottom-right side of the mouse cursor, and make sure the legend
                // will not go outside the chart image.
                TTFText t = d.text(legend, "Arial Bold", 8);
                t.draw(Math.Min(mouseX + 12, c.getWidth() - t.getWidth()), Math.Min(mouseY + 18, c.getHeight()
                                                                                    - t.getHeight()), 0x000000, Chart.TopLeft);
            }
        }
Beispiel #5
0
        //
        // Draw the track line with legend
        //
        private void trackLineLegend(XYChart c, int mouseX)
        {
            // Clear the current dynamic layer and get the DrawArea object to draw on it.
            DrawArea d = c.initDynamicLayer();

            // The plot area object
            PlotArea plotArea = c.getPlotArea();

            // Get the data x-value that is nearest to the mouse, and find its pixel coordinate.
            double xValue = c.getNearestXValue(mouseX);
            int    xCoor  = c.getXCoor(xValue);

            // Draw a vertical track line at the x-position
            d.vline(plotArea.getTopY(), plotArea.getBottomY(), xCoor, 0xaaaaaa);

            // Container to hold the legend entries
            var legendEntries = new List <string>();

            // Iterate through all layers to build the legend array
            for (int i = 0; i < c.getLayerCount(); ++i)
            {
                Layer layer = c.getLayerByZ(i);

                // The data array index of the x-value
                int xIndex = layer.getXIndexOf(xValue);

                // Iterate through all the data sets in the layer
                for (int j = 0; j < layer.getDataSetCount(); ++j)
                {
                    ChartDirector.DataSet dataSet = layer.getDataSetByZ(j);

                    // We are only interested in visible data sets with names
                    string dataName = dataSet.getDataName();
                    int    color    = dataSet.getDataColor();
                    if ((!string.IsNullOrEmpty(dataName)) && (color != Chart.Transparent))
                    {
                        // Build the legend entry, consist of the legend icon, name and data value.
                        double dataValue = dataSet.getValue(xIndex);
                        legendEntries.Add("<*block*>" + dataSet.getLegendIcon() + " " + dataName + ": " + ((
                                                                                                               dataValue == Chart.NoValue) ? "N/A" : c.formatValue(dataValue, "{value|P4}")) +
                                          "<*/*>");

                        // Draw a track dot for data points within the plot area
                        int yCoor = c.getYCoor(dataSet.getPosition(xIndex), dataSet.getUseYAxis());
                        if ((yCoor >= plotArea.getTopY()) && (yCoor <= plotArea.getBottomY()))
                        {
                            d.circle(xCoor, yCoor, 4, 4, color, color);
                        }
                    }
                }
            }

            // Create the legend by joining the legend entries
            legendEntries.Reverse();
            string legendText = "<*block,maxWidth=" + plotArea.getWidth() + "*><*block*><*font=Arial Bold*>["
                                + c.xAxis().getFormattedLabel(xValue, "mmm dd, yyyy") + "]<*/*>        " + String.Join(
                "        ", legendEntries) + "<*/*>";

            // Display the legend on the top of the plot area
            TTFText t = d.text(legendText, "Arial Bold", 10);

            t.draw(plotArea.getLeftX() + 5, plotArea.getTopY() - 3, 0x000000, Chart.BottomLeft);
        }
Beispiel #6
0
        //
        // Create chart
        //
        private void createChart(RazorChartViewer viewer)
        {
            // Get the selected year.
            string selectedYear = Request["xLabel"];

            //
            // In real life, the data may come from a database based on selectedYear. In this example, we
            // just use a random number generator.
            //
            int      seed     = 50 + (int.Parse(selectedYear) - 1996) * 15;
            RanTable rantable = new RanTable(seed, 1, 12);

            rantable.setCol2(0, seed, -seed * 0.25, seed * 0.33, seed * 0.1, seed * 3);

            double[] data = rantable.getCol(0);

            //
            // Now we obtain the data into arrays, we can start to draw the chart using ChartDirector
            //

            // Create a XYChart object of size 600 x 320 pixels
            XYChart c = new XYChart(600, 360);

            // Add a title to the chart using 18pt Times Bold Italic font
            c.addTitle("Month Revenue for Star Tech for " + selectedYear, "Times New Roman Bold Italic",
                       18);

            // Set the plotarea at (60, 40) and of size 500 x 280 pixels. Use a vertical gradient color
            // from light blue (eeeeff) to deep blue (0000cc) as background. Set border and grid lines to
            // white (ffffff).
            c.setPlotArea(60, 40, 500, 280, c.linearGradientColor(60, 40, 60, 280, 0xeeeeff, 0x0000cc),
                          -1, 0xffffff, 0xffffff);

            // Add a red line (ff0000) chart layer using the data
            ChartDirector.DataSet dataSet = c.addLineLayer().addDataSet(data, 0xff0000, "Revenue");

            // Set the line width to 3 pixels
            dataSet.setLineWidth(3);

            // Use a 13 point circle symbol to plot the data points
            dataSet.setDataSymbol(Chart.CircleSymbol, 13);

            // Set the labels on the x axis. In this example, the labels must be Jan - Dec.
            string[] labels = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sept", "Oct",
                                "Nov", "Dec" };
            c.xAxis().setLabels(labels);

            // When auto-scaling, use tick spacing of 40 pixels as a guideline
            c.yAxis().setTickDensity(40);

            // Add a title to the x axis to reflect the selected year
            c.xAxis().setTitle("Year " + selectedYear, "Times New Roman Bold Italic", 12);

            // Add a title to the y axis
            c.yAxis().setTitle("USD (millions)", "Times New Roman Bold Italic", 12);

            // Set axis label style to 8pt Arial Bold
            c.xAxis().setLabelStyle("Arial Bold", 8);
            c.yAxis().setLabelStyle("Arial Bold", 8);

            // Set axis line width to 2 pixels
            c.xAxis().setWidth(2);
            c.yAxis().setWidth(2);

            // Create the image and save it in a temporary location
            viewer.Image = c.makeWebImage(Chart.PNG);

            // Create an image map for the chart
            viewer.ImageMap = c.getHTMLImageMap(Url.Action("", "clickpie", new { year = selectedYear }),
                                                "", "title='{xLabel}: US$ {value|0}M'");
        }
Beispiel #7
0
        //
        // Draw track line with axis labels
        //
        private void trackLineAxis(XYChart c, int mouseX)
        {
            // Clear the current dynamic layer and get the DrawArea object to draw on it.
            DrawArea d = c.initDynamicLayer();

            // The plot area object
            PlotArea plotArea = c.getPlotArea();

            // Get the data x-value that is nearest to the mouse, and find its pixel coordinate.
            double xValue = c.getNearestXValue(mouseX);
            int    xCoor  = c.getXCoor(xValue);

            // The vertical track line is drawn up to the highest data point (the point with smallest
            // y-coordinate). We need to iterate all datasets in all layers to determine where it is.
            int minY = plotArea.getBottomY();

            // Iterate through all layers to find the highest data point
            for (int i = 0; i < c.getLayerCount(); ++i)
            {
                Layer layer = c.getLayerByZ(i);

                // The data array index of the x-value
                int xIndex = layer.getXIndexOf(xValue);

                // Iterate through all the data sets in the layer
                for (int j = 0; j < layer.getDataSetCount(); ++j)
                {
                    ChartDirector.DataSet dataSet = layer.getDataSetByZ(j);

                    double dataPoint = dataSet.getPosition(xIndex);
                    if ((dataPoint != Chart.NoValue) && (dataSet.getDataColor() != Chart.Transparent))
                    {
                        minY = Math.Min(minY, c.getYCoor(dataPoint, dataSet.getUseYAxis()));
                    }
                }
            }

            // Draw a vertical track line at the x-position up to the highest data point.
            d.vline(Math.Max(minY, plotArea.getTopY()), plotArea.getBottomY() + 6, xCoor, d.dashLineColor(
                        0x000000, 0x0101));

            // Draw a label on the x-axis to show the track line position
            d.text("<*font,bgColor=000000*> " + c.xAxis().getFormattedLabel(xValue, "mmm dd, yyyy") +
                   " <*/font*>", "Arial Bold", 8).draw(xCoor, plotArea.getBottomY() + 6, 0xffffff, Chart.Top);

            // Iterate through all layers to build the legend array
            for (int i = 0; i < c.getLayerCount(); ++i)
            {
                Layer layer = c.getLayerByZ(i);

                // The data array index of the x-value
                int xIndex = layer.getXIndexOf(xValue);

                // Iterate through all the data sets in the layer
                for (int j = 0; j < layer.getDataSetCount(); ++j)
                {
                    ChartDirector.DataSet dataSet = layer.getDataSetByZ(j);

                    // The positional value, axis binding, pixel coordinate and color of the data point.
                    double dataPoint = dataSet.getPosition(xIndex);
                    Axis   yAxis     = dataSet.getUseYAxis();
                    int    yCoor     = c.getYCoor(dataPoint, yAxis);
                    int    color     = dataSet.getDataColor();

                    // Draw the axis label only for visible data points of named data sets
                    if ((dataPoint != Chart.NoValue) && (color != Chart.Transparent) && (yCoor >=
                                                                                         plotArea.getTopY()) && (yCoor <= plotArea.getBottomY()))
                    {
                        // The axis label consists of 3 parts - a track dot for the data point, an axis label,
                        // and a line joining the track dot to the axis label.

                        // Draw the line first. The end point of the line at the axis label side depends on
                        // whether the label is at the left or right side of the axis (that is, on whether the
                        // axis is on the left or right side of the plot area).
                        int xPos = yAxis.getX() + ((yAxis.getAlignment() == Chart.Left) ? -4 : 4);
                        d.hline(xCoor, xPos, yCoor, d.dashLineColor(color, 0x0101));

                        // Draw the track dot
                        d.circle(xCoor, yCoor, 4, 4, color, color);

                        // Draw the axis label. If the axis is on the left side of the plot area, the labels
                        // should right aligned to the axis, and vice versa.
                        d.text("<*font,bgColor=" + color.ToString("x") + "*> " + c.formatValue(dataPoint,
                                                                                               "{value|P4}") + " <*/font*>", "Arial Bold", 8).draw(xPos, yCoor, 0xffffff, ((
                                                                                                                                                                               yAxis.getAlignment() == Chart.Left) ? Chart.Right : Chart.Left));
                    }
                }
            }
        }
        //
        // Draw finance chart track line with legend
        //
        private void trackFinance(MultiChart m, int mouseX)
        {
            // Clear the current dynamic layer and get the DrawArea object to draw on it.
            DrawArea d = m.initDynamicLayer();

            // It is possible for a FinanceChart to be empty, so we need to check for it.
            if (m.getChartCount() == 0)
            {
                return;
            }

            // Get the data x-value that is nearest to the mouse
            int xValue = (int)(((XYChart)m.getChart(0)).getNearestXValue(mouseX));

            // Iterate the XY charts (main price chart and indicator charts) in the FinanceChart
            XYChart c = null;

            for (int i = 0; i < m.getChartCount(); ++i)
            {
                c = (XYChart)m.getChart(i);

                // Variables to hold the legend entries
                string    ohlcLegend    = "";
                ArrayList legendEntries = new ArrayList();

                // Iterate through all layers to find the highest data point
                for (int j = 0; j < c.getLayerCount(); ++j)
                {
                    Layer layer        = c.getLayerByZ(j);
                    int   xIndex       = layer.getXIndexOf(xValue);
                    int   dataSetCount = layer.getDataSetCount();

                    // In a FinanceChart, only layers showing OHLC data can have 4 data sets
                    if (dataSetCount == 4)
                    {
                        double highValue  = layer.getDataSet(0).getValue(xIndex);
                        double lowValue   = layer.getDataSet(1).getValue(xIndex);
                        double openValue  = layer.getDataSet(2).getValue(xIndex);
                        double closeValue = layer.getDataSet(3).getValue(xIndex);

                        if (closeValue != Chart.NoValue)
                        {
                            // Build the OHLC legend
                            ohlcLegend = "Open: " + c.formatValue(openValue, "{value|P4}") + ", High: " +
                                         c.formatValue(highValue, "{value|P4}") + ", Low: " + c.formatValue(lowValue,
                                                                                                            "{value|P4}") + ", Close: " + c.formatValue(closeValue, "{value|P4}");

                            // We also draw an upward or downward triangle for up and down days and the %
                            // change
                            double lastCloseValue = layer.getDataSet(3).getValue(xIndex - 1);
                            if (lastCloseValue != Chart.NoValue)
                            {
                                double change  = closeValue - lastCloseValue;
                                double percent = change * 100 / closeValue;
                                string symbol  = ((change >= 0) ?
                                                  "<*font,color=008800*><*img=@triangle,width=8,color=008800*>" :
                                                  "<*font,color=CC0000*><*img=@invertedtriangle,width=8,color=CC0000*>");

                                ohlcLegend = ohlcLegend + "  " + symbol + " " + c.formatValue(change,
                                                                                              "{value|P4}") + " (" + c.formatValue(percent, "{value|2}") + "%)<*/font*>"
                                ;
                            }

                            // Use a <*block*> to make sure the line does not wrap within the legend entry
                            ohlcLegend = "<*block*>" + ohlcLegend + "      <*/*>";
                        }
                    }
                    else
                    {
                        // Iterate through all the data sets in the layer
                        for (int k = 0; k < layer.getDataSetCount(); ++k)
                        {
                            ChartDirector.DataSet dataSet = layer.getDataSetByZ(k);

                            string name  = dataSet.getDataName();
                            double value = dataSet.getValue(xIndex);
                            if ((!string.IsNullOrEmpty(name)) && (value != Chart.NoValue))
                            {
                                // In a FinanceChart, the data set name consists of the indicator name and its
                                // latest value. It is like "Vol: 123M" or "RSI (14): 55.34". As we are
                                // generating the values dynamically, we need to extract the indictor name
                                // out, and also the volume unit (if any).

                                // The unit character, if any, is the last character and must not be a digit.
                                string unitChar = name.Substring(name.Length - 1);
                                if (unitChar.CompareTo("0") >= 0 && unitChar.CompareTo("9") <= 0)
                                {
                                    unitChar = "";
                                }

                                // The indicator name is the part of the name up to the colon character.
                                int delimiterPosition = name.IndexOf(":");
                                if (delimiterPosition != -1)
                                {
                                    name = name.Substring(0, delimiterPosition);
                                }

                                // In a FinanceChart, if there are two data sets, it must be representing a
                                // range.
                                if (dataSetCount == 2)
                                {
                                    // We show both values in the range in a single legend entry
                                    value = layer.getDataSet(0).getValue(xIndex);
                                    double value2 = layer.getDataSet(1).getValue(xIndex);
                                    name = name + ": " + c.formatValue(Math.Min(value, value2), "{value|P3}")
                                           + " - " + c.formatValue(Math.Max(value, value2), "{value|P3}");
                                }
                                else
                                {
                                    // In a FinanceChart, only the layer for volume bars has 3 data sets for
                                    // up/down/flat days
                                    if (dataSetCount == 3)
                                    {
                                        // The actual volume is the sum of the 3 data sets.
                                        value = layer.getDataSet(0).getValue(xIndex) + layer.getDataSet(1
                                                                                                        ).getValue(xIndex) + layer.getDataSet(2).getValue(xIndex);
                                    }

                                    // Create the legend entry
                                    name = name + ": " + c.formatValue(value, "{value|P3}") + unitChar;
                                }

                                // Build the legend entry, consist of a colored square box and the name (with
                                // the data value in it).
                                legendEntries.Add("<*block*><*img=@square,width=8,edgeColor=000000,color=" +
                                                  dataSet.getDataColor().ToString("x") + "*> " + name + "<*/*>");
                            }
                        }
                    }
                }

                // Get the plot area position relative to the entire FinanceChart
                PlotArea plotArea      = c.getPlotArea();
                int      plotAreaLeftX = plotArea.getLeftX() + c.getAbsOffsetX();
                int      plotAreaTopY  = plotArea.getTopY() + c.getAbsOffsetY();

                // The legend is formed by concatenating the legend entries.
                legendEntries.Reverse();
                string legendText = String.Join("      ", (string[])legendEntries.ToArray(typeof(string)));

                // Add the date and the ohlcLegend (if any) at the beginning of the legend
                legendText = "<*block,valign=top,maxWidth=" + (plotArea.getWidth() - 5) +
                             "*><*font=Arial Bold*>[" + c.xAxis().getFormattedLabel(xValue, "mmm dd, yyyy") +
                             "]<*/font*>      " + ohlcLegend + legendText;

                // Draw a vertical track line at the x-position
                d.vline(plotAreaTopY, plotAreaTopY + plotArea.getHeight(), c.getXCoor(xValue) +
                        c.getAbsOffsetX(), d.dashLineColor(0x000000, 0x0101));

                // Display the legend on the top of the plot area
                TTFText t = d.text(legendText, "Arial", 8);
                t.draw(plotAreaLeftX + 5, plotAreaTopY + 3, 0x000000, Chart.TopLeft);
            }
        }