// 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); }
// // Draw the differences between the track lines // void drawTrackDiff(XYChart c, Dictionary <string, double> log0, Dictionary <string, double> log1) { double x0, x1; if (!((null != log0) && log0.TryGetValue("x", out x0) && (null != log1) && log1.TryGetValue("x", out x1))) { return; } // Two columns in the table var leftCol = new System.Text.StringBuilder(); var rightCol = new System.Text.StringBuilder(); leftCol.Append("Change in x: "); rightCol.Append(c.formatValue(x1 - x0, "{value|2}")); // Iterate through all layers to draw the data labels for (int i = 0; i < c.getLayerCount(); ++i) { Layer layer = c.getLayerByZ(i); // Iterate through all the data sets in the layer for (int j = 0; j < layer.getDataSetCount(); ++j) { var dataSetName = layer.getDataSet(j).getDataName(); double v0, v1; if (!(log0.TryGetValue(dataSetName, out v0) && log1.TryGetValue(dataSetName, out v1))) { continue; } leftCol.Append("\nChange in ").Append(dataSetName).Append(": "); rightCol.Append("\n").Append(c.formatValue(v1 - v0, "{value|2}")); } } string table = "<*block,bgColor=80ffffff,margin=4*><*block*>" + leftCol.ToString() + "<*/*><*block,halign=right*>" + rightCol.ToString() + "<*/*><*/*>"; TTFText t = c.getDrawArea().text(table, "Arial", 10); t.draw(c.getPlotArea().getRightX() - t.getWidth(), c.getPlotArea().getTopY(), 0x000000); }
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); } } } } }
// // 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); } }
// // 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); }
// // 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); } }