using Microsoft.VisualBasic.CompilerServices; using MuchInfo.Chart.Data.EnumTypes; using MuchInfo.Chart.Data.Interfaces; using MuchInfo.Chart.Data.Models; using MuchInfo.Chart.Infrastructure.Utilities; using MuchInfo.Chart.WPF.Helpers; using MuchInfo.Chart.WPF.Primitives.Interfaces; using System; using System.Collections.Generic; using System.Linq; using System.Runtime.CompilerServices; using System.Windows; using System.Windows.Media; namespace MuchInfo.Chart.WPF.Primitives { public class ComparisonPlot : LinePlot { #region Fields private GoodsInfo _currentGoods; private ChartDataSet _data; private bool _isActive; private TimeSpan _timeSpan; #endregion Fields #region Constructors /// /// Initializes a new instance of the class. /// public ComparisonPlot() { this._timeSpan = new TimeSpan(1, 0, 0, 0); this._isActive = false; this._data = new ChartDataSet(); } /// /// /// /// /// /// public ComparisonPlot(IndicatorModel indeicator, Chart chart, GoodsInfo goodsInfo) : base(indeicator, chart) { this.mChart = chart; this.CurrentGoods = goodsInfo; this._timeSpan = new TimeSpan(1, 0, 0, 0); this._isActive = false; this._data = new ChartDataSet(); //bool flag = calc is IComparisonCalculation; //if (flag) //{ // bool flag2 = SymbolManager.Manager().AllSymbolsLoaded(); // if (flag2) // { // this.Symbol = SymbolManager.Manager().SymbolFromSymbol(((IComparisonCalculation)calc).DefaultSymbol()); // } // else // { // this.mSymSearch = SymbolManager.Manager().FetchSingleSymbolBySymbol(((IComparisonCalculation)calc).DefaultSymbol()); // this.mSymSearch.GoGetIt(); // } //} this.UpdateOutData(); } #endregion Constructors #region Properties #region Public Properties /// /// Gets or sets the current goods. /// public GoodsInfo CurrentGoods { get { return this._currentGoods; } set { bool flag = false; bool flag2 = value == null && this._currentGoods != null; if (flag2) { flag = true; } else { flag2 = (value != null && this._currentGoods == null); if (flag2) { flag = true; } else { flag2 = (value != null && this._currentGoods != null && Operators.CompareString(this._currentGoods.Symbol, value.Symbol, false) != 0); if (flag2) { flag = true; } } } flag2 = flag; if (flag2) { this._currentGoods = value; this.UpdateData(); } } } /// /// Gets or sets the m data. /// public virtual ChartDataSet Data { get { return this._data; } set { var obj = new LineDataSetDataChangedEventHandler(this.OnDataChanged); bool flag = this._data != null; if (flag) { this._data.DataChanged -= obj; } this._data = value; flag = (this._data != null); if (flag) { this._data.DataChanged += obj; } } } /// /// Gets or sets a value indicating whether this instance is active. /// public bool IsActive { get { return this._isActive; } set { bool flag = value != this._isActive; if (flag) { this._isActive = value; this.UpdateData(); } } } /// /// Gets or sets the time frame. /// public TimeSpan TimeFrame { get { return this._timeSpan; } set { bool flag = !(value == this._timeSpan); if (flag) { this._timeSpan = value; this.UpdateData(); } } } #endregion Public Properties #endregion Properties #region Methods #region Public Methods /// /// Sources the data change. /// /// The change. public override void SourceDataChange(object change) { base.SourceDataChange(RuntimeHelpers.GetObjectValue(change)); bool flag = this.mChart != null; if (flag) { this.mChart.Refresh(true); } } #endregion Public Methods #region Internal Methods /// /// 重写返回空:不添加LegendButton /// /// List{FrameworkElement}. internal List AddLegendButton() { return new List(); } /// /// Builds the plot. /// /// The owner. /// A scale. /// The date scale. /// The val scale. /// A rect. /// List{FrameworkElement}. internal override List BuildPlot(Chart owner, ScaleLayer aScale, IDateScaler dateScale, IValueScaler valScale, Rect aRect) { // bool flag = this.PlotCalculation is ComparisonCalculation; bool flag = true; List result; if (flag) { this.mChart = owner; this.mScale = aScale; flag = !this._isActive; if (flag) { result = new List(); } else { var painter = new PlotPainter(aRect, null, 1.2); switch (this.Indicator.LinePlotType) { case LinePlotType.Candlestick: this.BuildCandlestickPoints(painter, dateScale, valScale, aRect); break; case LinePlotType.Line: //分时图叠加 this.BuildAreaLine(painter, dateScale, valScale, aRect); break; default: //叠加商品直线画虚线 painter.DashStyle = new DoubleCollection { 3.0, 3.0 }; this.BuildAreaLine(painter, dateScale, valScale, aRect); break; } var list = painter.GetGraph(); if (list != null && list.Any()) { foreach (var element in list) { element.IsHitTestVisible = false; } } result = list; } } else { result = base.BuildPlot(owner, aScale, dateScale, valScale, aRect); } return result; } /// /// 检测画图面板中的图例,并返回它们在aDate日期下的数据面板 /// /// A date. /// if set to true [is dark background]. /// if set to true [is forex]. /// List{ControlPair}. internal override List GetControlPairs(DateTime aDate, bool isDarkBackground, bool isForex) { var digits = isForex ? 4 : 2; return GetControlPairs(aDate, isDarkBackground, digits); } /// /// Gets the control pairs. /// /// A date. /// if set to true [is dark background]. /// The digits. /// List{ControlPair}. internal override List GetControlPairs(DateTime aDate, bool isDarkBackground, int digits) { // bool flag = this.PlotCalculation is ComparisonCalculation; bool flag = true; checked { List result; if (flag) { var list = new List(); flag = (this._isActive && this.OutputSource != null && this.OutputSource.CalculateDataPoints != null); if (flag) { var list2 = this.OutputSource.CalculateDataPoints; int num = list2.Count - 1; while (true) { int arg_E3_0 = num; int num2 = 0; if (arg_E3_0 < num2) { goto IL_E5; } flag = (DateTime.Compare(list2[num].Date, aDate) == 0); if (flag) { bool flag2 = this._currentGoods != null; if (flag2) { break; } } num += -1; } list.Add(this.GetPointerPair(this._currentGoods.Symbol, this.GetPlotColor(), list2[num].Value, false, digits, false)); } IL_E5: result = list; } else { result = base.GetControlPairs(aDate, isDarkBackground, digits); } return result; } } /// /// Updates the out data. /// internal void UpdateOutData() { //bool flag = this.PlotCalculation == null; //if (!flag) //{ // flag = (this.PlotCalculation is IComparisonCalculation); // if (flag) // { // this.mOutputData.OnDataSetDataChanged(((IComparisonCalculation)this.PlotCalculation).CalculateComparison(this.mSource, this.Data, this.CurrentPlotColor(), this._currentGoods)); // } // else // { // this.mOutputData.OnDataSetDataChanged(((ILineCalculation)this.PlotCalculation).Calculate(this.mSource, this.CurrentPlotColor())); // } //} } #endregion Internal Methods #region Protected Methods /// /// Deletes the data. /// protected override void DeleteData() { base.DeleteData(); this._currentGoods = null; this.UpdateData(); if (_data != null) { this._data.OnDelete(); this._data = null; } } protected Color UpBrush(IndicatorModel indicator) { return this.CurrentPlotColor(); } #endregion Protected Methods #region Private Methods /// /// Builds the area line. /// /// The painter. /// The date scale. /// The val scale. /// A rect. private void BuildAreaLine(PlotPainter painter, IDateScaler dateScale, IValueScaler valScale, Rect aRect) { var destionation = GetComparisonList(dateScale); if (destionation == null || !destionation.Any()) return; //if (destionation.Count < 2) return; float num = 1; if (this.mChart != null && this.mChart.CycleType == CycleType.TimeSharing) { if (Math.Abs(CurrentGoods.PreClose) > 0) { num = ((ValueScalerArithmetic)valScale).GetPercentBaseline() / CurrentGoods.PreClose; } } else { num = ((ValueScalerArithmetic)valScale).GetPercentBaseline() / destionation[1].Value; } for (var i = 1; i < destionation.Count; i++) { var startIndex = dateScale.IndexFromDate(destionation[i - 1].Date); var endIndex = dateScale.IndexFromDate(destionation[i].Date); if (startIndex < 0 || endIndex < 0) continue; var start = dateScale.XforDate(destionation[i - 1].Date); var end = dateScale.XforDate(destionation[i].Date); if (start < 0 || end < 0 || start.Equals(end)) continue; var lineGeometry = new LineGeometry { //lineplot都加上了0.5buffer. StartPoint = new Point((double)start, 0.5 + (double)valScale.ScaledY(destionation[(i - 1)].Value * num, aRect)), EndPoint = new Point((double)end, 0.5 + (double)valScale.ScaledY(destionation[i].Value * num, aRect)) }; painter.AddLine(lineGeometry, this.CurrentPlotColor()); } } /// /// Builds the candlestick points. /// /// The painter. /// The date scale. /// The val scale. /// A rect. private void BuildCandlestickPoints(PlotPainter painter, IDateScaler dateScale, IValueScaler valScale, Rect aRect) { var list = GetComparisonList(dateScale); if (list == null || !list.Any()) return; //初始化时出现101需修改 //var index = list.Count > 2 ? 1 : 0; var index = 0; var percent = ((ValueScalerArithmetic)valScale).GetPercentBaseline() / list[index].Value; var num = (float)((int)Math.Round(unchecked(0.3 * (double)dateScale.DistanceBetweenDates()))); var start = dateScale.FirstVisibleIndexFromData(list); var length = list.Count; for (var i = start; i < length; i++) { var current = list[i]; var visible = dateScale.DateVisible(current.Date); if (!visible) continue; var ohlcDataPoint = current as IOHLCDataPoint; if (ohlcDataPoint == null) continue; var dateX = (float)((int)Math.Round((double)dateScale.XforDate(ohlcDataPoint.Date))); var color = this.CurrentPlotColor(); var isRising = false; var isDeclining = false; if (ohlcDataPoint.Close > ohlcDataPoint.Open) { isRising = true; } else if (ohlcDataPoint.Close < ohlcDataPoint.Open) { isDeclining = true; } Rect rect; if (!isRising && !isDeclining) { //相等画直线 rect = new Rect(dateX - num + 0.5, 0.5 + valScale.ScaledY(ohlcDataPoint.Open * percent, aRect), 2f * num, 0); painter.AddLine(new LineGeometry { StartPoint = new Point(rect.X - 0.5, rect.Y), EndPoint = new Point(rect.Right + 0.5, rect.Y) }, color); } else if (isRising) { rect = new Rect(dateX - num + 0.5, 0.5 + (double)valScale.ScaledY(ohlcDataPoint.Close * percent, aRect), 2f * num, 0); rect.Height = (0.5 + (double)valScale.ScaledY(ohlcDataPoint.Open * percent, aRect) - rect.Top); var rectangleGeometry = new RectangleGeometry { Rect = rect }; if (mChart.FillComparisonCandle) { painter.AddShape(rectangleGeometry, color); } else { painter.AddLine(rectangleGeometry, color); } } else { rect = new Rect(dateX - num + 0.5, 0.5 + (double)valScale.ScaledY(ohlcDataPoint.Open * percent, aRect), 2f * num, 0); rect.Height = (0.5 + (double)valScale.ScaledY(ohlcDataPoint.Close * percent, aRect) - rect.Top); var rectangleGeometry = new RectangleGeometry { Rect = (rect) }; if (mChart.FillComparisonCandle) { painter.AddShape(rectangleGeometry, color); } else { painter.AddLine(rectangleGeometry, color); } } painter.AddLine(new LineGeometry { StartPoint = new Point(dateX + 0.5, (double)valScale.ScaledY(ohlcDataPoint.High * percent, aRect)), EndPoint = new Point((double)dateX + 0.5, rect.Top) }, color); painter.AddLine(new LineGeometry { StartPoint = new Point(dateX + 0.5, (double)valScale.ScaledY(ohlcDataPoint.Low * percent, aRect)), EndPoint = new Point(dateX + 0.5, rect.Bottom) }, color); } } private List GetComparisonList(IDateScaler dateScale) { var list = this.OutputSource.CalculateDataPoints; if (list == null || !list.Any()) return null; var firstIndex = dateScale.FirstVisibleIndexFromData(list); var lastIndex = dateScale.LastVisibleIndexFromData(list); //只添加包含的时间 var destionation = new List(); for (var i = firstIndex; i <= lastIndex; i++) { var current = list[i].Date; if (dateScale.DateContains(current)) { destionation.Add(list[i]); } else if (this.mChart.CycleType == CycleType.TimeSharing) { destionation.Add(list[i]); } } return destionation; } /// /// Called when [data changed]. /// /// The change. private void OnDataChanged(object change) { this.SourceDataChange(RuntimeHelpers.GetObjectValue(change)); } /// /// Updates the data. /// private void UpdateData() { bool flag = this._currentGoods == null || !this._isActive; if (flag) { bool flag2 = this.Data != null; if (flag2) { this.Data.OnDelete(); this.Data = null; } } else { bool flag2 = this.Data == null; if (flag2) { this.Data = new ChartDataSet(); } if (mChart.ComparisionTimeShareDic.ContainsKey(CurrentGoods.GoodsCode) && mChart.ComparisionDictionary.ContainsKey(this.CurrentGoods.Symbol)) { var dataPoints = mChart.CycleType == CycleType.TimeSharing ? mChart.ComparisionTimeShareDic[CurrentGoods.GoodsCode] : mChart.ComparisionDictionary[this.CurrentGoods.Symbol]; this.Data.DataPoints = dataPoints; } this.UpdateOutData(); } } #endregion Private Methods #endregion Methods } }