private void trackLineLegend(XYChart c1, int mousec1X, int chartNo)
{
// Clear the current dynamic layer and get the DrawArea object to draw on it.
if (_multiChart == null)
d1 = c1.initDynamicLayer();
else
{ }
// The plot area object
PlotArea plotArea1 = c1.getPlotArea();
// Get the data x-value that is nearest to the mouse, and find its pixel coordinate.
double xValue1 = c1.getNearestXValue(mousec1X);
int xCoor1 = c1.getXCoor(xValue1);
// Draw a vertical track line at the x-position
d1.vline(plotArea1.getTopY(), plotArea1.getBottomY(), xCoor1, 0xaaaaaa);
// Container to hold the legend entries
ArrayList legendEntries = new ArrayList();
// Iterate through all layers to build the legend array
for (int i = 0; i < c1.getLayerCount(); ++i)
{
Layer layer = c1.getLayerByZ(i);
// The data array index of the x-value
int xIndex = layer.getXIndexOf(xValue1);
// 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();
if (!string.IsNullOrEmpty(dataName))
{
if (chartNo == 1)
{
TabConfig tap = APList.FirstOrDefault(p => p.APName == dataName);
if (tap != null && tap.IsChecked == false)
continue;
}
else
{
PerformancePerameter item = OTWPerformanceParameterList.FirstOrDefault(p => p.ParameterName == dataName && p.IsChecked == true);
if (item == null)
continue;
}
}
int color = dataSet.getDataColor();
if ((!string.IsNullOrEmpty(dataName)) && (color != Chart.Transparent))
{
// Build the legend entry, consist of the legend icon, name and data value.
string str = dataSet.getLegendIcon();
double dataValue = dataSet.getValue(xIndex);
legendEntries.Add("<*block*>" + dataSet.getLegendIcon() + " " + dataName + " : " + ((
dataValue == Chart.NoValue) ? "N/A" : c1.formatValue(dataValue, "{value|P4}")) + "<*/*>");
// Draw a track dot for data points within the plot area
int yCoor = c1.getYCoor(dataSet.getPosition(xIndex), dataSet.getUseYAxis());
if ((yCoor >= plotArea1.getTopY()) && (yCoor <= plotArea1.getBottomY()))
{
d1.circle(xCoor1, yCoor, 4, 4, color, color);
}
}
}
}
// Create the legend by joining the legend entries
legendEntries.Reverse();
string legendText = "<*block,maxWidth=" + plotArea1.getWidth() + "*><*block*><*font=Arial Bold*>["
+ c1.xAxis().getFormattedLabel(xValue1, "hh:nn:ss") + "]<*/*> " + String.Join(
" ", (string[])legendEntries.ToArray(typeof(string))) + "<*/*>";
// Display the legend on the top of the plot area
TTFText t = d1.text(legendText, "Arial Bold", 10);
int chart1Height = 0;
if(_multiChart != null)
chart1Height = _multiChart.getChart(0).getHeight();
if (chartNo == 1)
t.draw(plotArea1.getLeftX(), plotArea1.getTopY() - 3, 0x000000, Chart.BottomLeft);
else
t.draw(plotArea1.getLeftX(), plotArea1.getTopY() + chart1Height - 50, 0x000000, Chart.BottomLeft);
// t.draw(plotArea.getLeftX() + 5, plotArea.getTopY() - 3, 0x000000, Chart.BottomCenter);
}
private void WPFChartViewer1_MouseMovePlotArea(object sender, MouseEventArgs e)
{
//var viewer = sender as WPFChartViewer;
//trackLineLegend((XYChart)viewer.Chart, viewer.PlotAreaMouseX);
//viewer.updateDisplay();
WPFChartViewer viewer = (WPFChartViewer)sender;
MultiChart m = (MultiChart)viewer.Chart;
_multiChart.removeDynamicLayer();
d1 = _multiChart.initDynamicLayer();
trackLineLegend((XYChart)_multiChart.getChart(0), viewer.PlotAreaMouseX, 1);
trackLineLegend((XYChart)_multiChart.getChart(1), viewer.PlotAreaMouseX, 2);
viewer.updateDisplay();
}
//Draw Chart Method
private void drawChart(WPFChartViewer viewer)
{
if(_multiChart != null)
{
_multiChart.removeDynamicLayer();
_multiChart = null;
}
Dictionary<string, int> graphNameAndDisplayValue = new Dictionary<string, int>();
DateTime viewPortStartDate = Chart.NTime(viewer.getValueAtViewPort("x", viewer.ViewPortLeft));
DateTime viewPortEndDate = Chart.NTime(viewer.getValueAtViewPort("x", viewer.ViewPortLeft +
viewer.ViewPortWidth));
// Get the array indexes that corresponds to the visible start and end dates
/* int startIndex = (int)Math.Floor(Chart.bSearch(timeStamps, viewPortStartDate));
int endIndex = (int)Math.Ceiling(Chart.bSearch(timeStamps, viewPortEndDate));*/
int startIndex = (int)Math.Floor(Chart.bSearch(_timeSpanList.ToArray(), viewPortStartDate));
int endIndex = (int)Math.Ceiling(Chart.bSearch(_timeSpanList.ToArray(), viewPortEndDate));
int noOfPoints = endIndex - startIndex + 1;
// Extract the part of the data array that are visible.
// DateTime[] viewPortTimeStamps = (DateTime[])Chart.arraySlice(timeStamps, startIndex, noOfPoints);
DateTime[] viewPortTimeStamps = (DateTime[])Chart.arraySlice(_timeSpanList.ToArray(), startIndex, noOfPoints);
//
// At this stage, we have extracted the visible data. We can use those data to plot the chart.
//
//================================================================================
// Configure overall chart appearance.
//================================================================================
double width = mainGrid.ColumnDefinitions[1].ActualWidth;
double height = mainGrid.RowDefinitions[0].ActualHeight + mainGrid.RowDefinitions[1].ActualHeight;
// Create an XYChart object of size 640 x 400 pixels
XYChart c1 = new XYChart((int)width, (int)height/2, 0xffffff, 0x000000, 1);
XYChart c2 = new XYChart((int)width, (int)height /2, 0xffffff, 0x000000, 1);
// XYChart c = new XYChart(, winChartViewer1.Height);
// Set the plotarea at (55, 55) with width 80 pixels less than chart width, and height 90 pixels
// less than chart height. Use a vertical gradient from light blue (f0f6ff) to sky blue (a0c0ff)
// as background. Set border to transparent and grid lines to white (ffffff).
//c.setPlotArea(55, 55, c.getWidth() - 120, c.getHeight() - 90, c.linearGradientColor(0, 55, 0,
// c.getHeight() - 35, 0xf0f6ff, 0xa0c0ff), -1, Chart.Transparent, 0xffffff, 0xffffff);
c1.setPlotArea(55, 100, c1.getWidth() - 80, c1.getHeight() - 130, 0xffffff, -1, 0x6A6666, 0xD8D5D5, 0xD8D5D5);
c2.setPlotArea(55, 100, c1.getWidth() - 80, c2.getHeight() - 130, 0xffffff, -1, 0x6A6666, 0xD8D5D5, 0xD8D5D5);
// As the data can lie outside the plotarea in a zoomed chart, we need enable clipping.
c1.setClipping();
c2.setClipping();
// Add a title to the chart using 15pt Arial Bold font
c1.addTitle(" Moxa Radio Analyzer RSSI And Performace Logs ", "Arial Bold", 15);
// Set legend icon style to use line style icon, sized for 10pt font
c1.getLegend().setLineStyleKey();
c1.getLegend().setFontSize(10);
c2.getLegend().setLineStyleKey();
c2.getLegend().setFontSize(10);
// Set the x and y axis stems to transparent and the label font to 10pt Arial
c1.xAxis().setColors(Chart.Transparent);
c1.yAxis().setColors(Chart.Transparent);
c1.xAxis().setLabelStyle("Arial", 10);
c1.yAxis().setLabelStyle("Arial", 10);
c2.xAxis().setColors(Chart.Transparent);
c2.yAxis().setColors(Chart.Transparent);
c2.xAxis().setLabelStyle("Arial", 10);
c2.yAxis().setLabelStyle("Arial", 10);
// c2.yAxis().setLinearScale(0, 50);
// Add axis title using 10pt Arial Bold font
c1.yAxis().setTitle("Signal Strength", "Arial Bold", 10);
foreach (PerformancePerameter item in OTWPerformanceParameterList)
{
if (item.IsChecked)
{
string yAxis2Title = "";
switch (item.ParameterName)
{
case KEY_BAND:
yAxis2Title = KEY_BAND;
break;
case KEY_JTR:
yAxis2Title = KEY_JTR;
break;
case KEY_PCTLOSS:
yAxis2Title = KEY_PCTLOSS;
break;
case KEY_PERPCTLOSS:
yAxis2Title = KEY_PERPCTLOSS;
break;
}
c2.yAxis().setTitle(yAxis2Title, "Arial Bold", 10);
}
}
foreach (PerformancePerameter item in WTOPerformanceParameterList)
{
if (item.IsChecked)
{
string yAxis2Title = "";
switch (item.ParameterName)
{
case KEY_BAND:
yAxis2Title = KEY_BAND;
break;
case KEY_JTR:
yAxis2Title = KEY_JTR;
break;
case KEY_PCTLOSS:
yAxis2Title = KEY_PCTLOSS;
break;
case KEY_PERPCTLOSS:
yAxis2Title = KEY_PERPCTLOSS;
break;
}
c2.yAxis().setTitle(yAxis2Title, "Arial Bold", 10);
}
}
//================================================================================
// Add data to chart
//================================================================================
//
// In this example, we represent the data by lines. You may modify the code below to use other
// representations (areas, scatter plot, etc).
//
// Add a line layer for the lines, using a line width of 2 pixels
LineLayer layer = c1.addLineLayer2();
layer.setLineWidth(2);
// In this demo, we do not have too many data points. In real code, the chart may contain a lot
// of data points when fully zoomed out - much more than the number of horizontal pixels in this
// plot area. So it is a good idea to use fast line mode.
layer.setFastLineMode();
layer.setXData(viewPortTimeStamps);
// Add a line layer for the lines, using a line width of 2 pixels
LineLayer layer2 = c2.addLineLayer2();
layer2.setLineWidth(2);
layer2.setFastLineMode();
bool handoffDrawn = false;
foreach (string key in _dicTapNameAndTapMACAddress.Keys)
{
string graphName = key;
string equipName = _dicTapNameAndTapMACAddress[graphName];
if (_dicTapMacAndValues.ContainsKey(equipName))
{
string dataSeriesName = graphName;
double[] dataSeriesValue = _dicTapMacAndValues[equipName].ToArray();
DateTime[] dataDateTimeForAxisY = _dicTapMacAndDateTimeValues[equipName].ToArray();
int countDateTimeHnadOff = dataDateTimeForAxisY.Count();
TabConfig tap = APList.FirstOrDefault(p => p.APName == graphName);
double[] viewPortDataSeries = (double[])Chart.arraySlice(dataSeriesValue, startIndex, noOfPoints);
LineLayer layerTest = null;
if (_tapMacAddressAndInfo.ContainsKey(equipName))
layerTest = c1.addLineLayer(dataSeriesValue, _tapMacAddressAndInfo[equipName].color, dataSeriesName);
else
layerTest = c1.addLineLayer(dataSeriesValue, _colorGenerator.NextColorInt(), dataSeriesName);
layerTest.setXData(dataDateTimeForAxisY);
layerTest.setLineWidth(2);
if (tap != null && tap.IsChecked == false)
{
layerTest.setLineWidth(0);
}
else if (tap != null && tap.IsChecked == true)
{
layerTest.setLineWidth(2);
}
if (handoffDrawn == false)
{
handoffDrawn = true;
if (_handOffEquipment.Count > 0 && _timeSpanHandOff.Count > 0)
{
int x = 0;
foreach (string handoff in _handOffEquipment)
{
string[] separators = { "," };
string[] word = handoff.Split(separators, StringSplitOptions.RemoveEmptyEntries);
DateTime time = _timeSpanHandOff[x];
DateTime[] dateTimeHandOffList2 = new DateTime[2];
dateTimeHandOffList2[0] = time;
dateTimeHandOffList2[1] = time;
int indexStartTabHandoff = _minValue + 10;
int indexEndTabHandoff = _maxValue + (-10);
double[] dataY0 = { indexStartTabHandoff, indexEndTabHandoff }; // Define value for plot trackinfo fix value.
LineLayer layerTrackInfo = c1.addLineLayer(dataY0, c1.dashLineColor(0xff3333)); // fix color
layerTrackInfo.setXData(dateTimeHandOffList2);
layerTrackInfo.addCustomDataLabel(0, 0, " " + word[0] + " \\n " + word[1] + "\\n" + word[2] + "\\n" + word[3], "Arial Bold");
layerTrackInfo.setLineWidth(2);
layerTrackInfo.getDataSet(0).setDataSymbol(Chart.SquareSymbol, 7);
x++;
}
}
}
} // end if mapEquipAndValue
//} //end if mapGrapNameAndEquip
} // end For loop
/**** Case Add Mark BAr ******/
//if (_valueMarkLineList.Count() != 0)
//{
// foreach (int n in _valueMarkLineList)
// {
// c.yAxis().addMark(n, 0x008000 + (1500 + n), " Line : " + n).setLineWidth(2);
// }
//} // End if value mark line
//AddTunnelStatus(c);
//AddModemStatus(c);
foreach (PerformancePerameter item in OTWPerformanceParameterList)
{
if (!item.IsChecked)
{
continue;
}
if (!_dicPerVariableAndValueOTW.ContainsKey(item.ParameterName))
{
continue;
}
string dataSeriesName = item.ParameterName;
double[] dataSeriesValue = _dicPerVariableAndValueOTW[item.ParameterName].ToArray();
DateTime[] dataDateTimeForAxisY = _dicIperVariableAndDateTimeOTW[item.ParameterName].ToArray();
double[] viewPortDataSeries = (double[])Chart.arraySlice(dataSeriesValue, startIndex, noOfPoints);
LineLayer layerPerformace = c2.addLineLayer(dataSeriesValue, _dicIperVariableAndColorOTW[item.ParameterName], dataSeriesName);
layerPerformace.setXData(dataDateTimeForAxisY);
layerPerformace.setLineWidth(2);
}
foreach (PerformancePerameter item in WTOPerformanceParameterList)
{
if (!item.IsChecked)
{
continue;
}
if (!_dicPerVariableAndValueWTO.ContainsKey(item.ParameterName))
{
continue;
}
string dataSeriesName = item.ParameterName;
double[] dataSeriesValue = _dicPerVariableAndValueWTO[item.ParameterName].ToArray();
DateTime[] dataDateTimeForAxisY = _dicIperVariableAndDateTimeWTO[item.ParameterName].ToArray();
double[] viewPortDataSeries = (double[])Chart.arraySlice(dataSeriesValue, startIndex, noOfPoints);
LineLayer layerPerformance = c2.addLineLayer(dataSeriesValue, _dicIperVariableAndColorWTO[item.ParameterName], dataSeriesName);
layerPerformance.setXData(dataDateTimeForAxisY);
layerPerformance.setLineWidth(2);
}
//================================================================================
// Configure axis scale and labelling
//================================================================================
//Set the x - axis as a date / time axis with the scale according to the view port x range.
//viewer.syncDateAxisWithViewPort("x", c.xAxis());
// For the automatic y-axis labels, set the minimum spacing to 30 pixels.
c1.yAxis().setTickDensity(20);
//c.yAxis2().setTickDensity(20);
c2.yAxis().setTickDensity(20);
c2.yAxis().setLinearScale(0, 50);
//
// In this demo, the time range can be from a few years to a few days. We demonstrate how to set
// up different date/time format based on the time range.
//
// If all ticks are yearly aligned, then we use "yyyy" as the label format.
c1.xAxis().setFormatCondition("align", 360 * 86400);
c1.xAxis().setLabelFormat("{value|yyyy}");
c2.xAxis().setFormatCondition("align", 360 * 86400);
c2.xAxis().setLabelFormat("{value|yyyy}");
// If all ticks are monthly aligned, then we use "mmm yyyy" in bold font as the first label of a
// year, and "mmm" for other labels.
c1.xAxis().setFormatCondition("align", 30 * 86400);
c1.xAxis().setMultiFormat(Chart.StartOfYearFilter(), "<*font=bold*>{value|mmm<*br*>yyyy}",
Chart.AllPassFilter(), "{value|mmm}");
c2.xAxis().setFormatCondition("align", 30 * 86400);
c2.xAxis().setMultiFormat(Chart.StartOfYearFilter(), "<*font=bold*>{value|mmm<*br*>yyyy}",
Chart.AllPassFilter(), "{value|mmm}");
// If all ticks are daily algined, then we use "mmm dd<*br*>yyyy" in bold font as the first
// label of a year, and "mmm dd" in bold font as the first label of a month, and "dd" for other
// labels.
c1.xAxis().setFormatCondition("align", 86400);
c1.xAxis().setMultiFormat(Chart.StartOfYearFilter(),
"<*block,halign=left*><*font=bold*>{value|mmm dd<*br*>yyyy}", Chart.StartOfMonthFilter(),
"<*font=bold*>{value|mmm dd}");
c1.xAxis().setMultiFormat2(Chart.AllPassFilter(), "{value|dd}");
c1.xAxis().setFormatCondition("align", 3600);
c1.xAxis().setLabelFormat("{value|hh:nn}");
c1.xAxis().setFormatCondition("align", 3600);
c1.xAxis().setLabelFormat("{value|hh:nn:ss}");
// For all other cases (sub-daily ticks), use "hh:nn<*br*>mmm dd" for the first label of a day,
// and "hh:nn" for other labels.
c1.xAxis().setFormatCondition("else");
c1.xAxis().setMultiFormat(Chart.StartOfDayFilter(), "<*font=bold*>{value|hh:nn:ss}",
Chart.AllPassFilter(), "{value|hh:nn:ss.ff}");
c2.xAxis().setFormatCondition("align", 86400);
c2.xAxis().setMultiFormat(Chart.StartOfYearFilter(),
"<*block,halign=left*><*font=bold*>{value|mmm dd<*br*>yyyy}", Chart.StartOfMonthFilter(),
"<*font=bold*>{value|mmm dd}");
c2.xAxis().setMultiFormat2(Chart.AllPassFilter(), "{value|dd}");
c2.xAxis().setFormatCondition("align", 3600);
c2.xAxis().setLabelFormat("{value|hh:nn}");
c2.xAxis().setFormatCondition("align", 3600);
c2.xAxis().setLabelFormat("{value|hh:nn:ss}");
// For all other cases (sub-daily ticks), use "hh:nn<*br*>mmm dd" for the first label of a day,
// and "hh:nn" for other labels.
c2.xAxis().setFormatCondition("else");
c2.xAxis().setMultiFormat(Chart.StartOfDayFilter(), "<*font=bold*>{value|hh:nn:ss}",
Chart.AllPassFilter(), "{value|hh:nn:ss.ff}");
viewer.syncLinearAxisWithViewPort("x", c1.xAxis());
//viewer.syncLinearAxisWithViewPort("y", c1.yAxis());
viewer.syncLinearAxisWithViewPort("x", c2.xAxis());
//viewer.syncLinearAxisWithViewPort("y", c2.yAxis());
//================================================================================
// Output the chart
//================================================================================
// We need to update the track line too. If the mouse is moving on the chart (eg. if
// the user drags the mouse on the chart to scroll it), the track line will be updated
// in the MouseMovePlotArea event. Otherwise, we need to update the track line here.
if (!viewer.IsInMouseMoveEvent)
{
trackLineLegend(c1, (null == viewer.Chart) ? c1.getPlotArea().getRightX() :
viewer.PlotAreaMouseX, 1);
trackLineLegend(c2, (null == viewer.Chart) ? c2.getPlotArea().getRightX() :
viewer.PlotAreaMouseX, 2);
}
_multiChart = new MultiChart((int)width, (int)height);
_multiChart.addChart(0, 0, c1);
_multiChart.addChart(0, c1.getHeight(), c2);
_multiChart.setMainChart(_multiChart);
viewer.Chart = _multiChart;
} |