using RealTimeGraphEx.Components.ComponentsItems; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Media; using System.Windows.Media.Animation; namespace RealTimeGraphEx.Components { public class YAxisScroll : ComponentBase { private Grid innerGrid; #region Properties public int Interval { get { return (int)GetValue(IntervalProperty); } set { SetValue(IntervalProperty, value); } } public static readonly DependencyProperty IntervalProperty = DependencyProperty.Register("Interval", typeof(int), typeof(YAxisScroll), new PropertyMetadata(4)); public double VerticalOffset { get { return (double)GetValue(VerticalOffsetProperty); } set { SetValue(VerticalOffsetProperty, value); } } public static readonly DependencyProperty VerticalOffsetProperty = DependencyProperty.Register("VerticalOffset", typeof(double), typeof(YAxisScroll), new PropertyMetadata(0.0)); public double HorizontalOffset { get { return (double)GetValue(HorizontalOffsetProperty); } set { SetValue(HorizontalOffsetProperty, value); } } public static readonly DependencyProperty HorizontalOffsetProperty = DependencyProperty.Register("HorizontalOffset", typeof(double), typeof(YAxisScroll), new PropertyMetadata(0.0)); public DataTemplate LabelTemplate { get { return (DataTemplate)GetValue(LabelTemplateProperty); } set { SetValue(LabelTemplateProperty, value); } } public static readonly DependencyProperty LabelTemplateProperty = DependencyProperty.Register("LabelTemplate", typeof(DataTemplate), typeof(YAxisScroll), new PropertyMetadata(null)); public ObservableCollection Labels { get { return (ObservableCollection)GetValue(LabelsProperty); } set { SetValue(LabelsProperty, value); } } public static readonly DependencyProperty LabelsProperty = DependencyProperty.Register("Labels", typeof(ObservableCollection), typeof(YAxisScroll), new PropertyMetadata(null)); public String StringFormat { get { return (String)GetValue(StringFormatProperty); } set { SetValue(StringFormatProperty, value); } } public static readonly DependencyProperty StringFormatProperty = DependencyProperty.Register("StringFormat", typeof(String), typeof(YAxisScroll), new PropertyMetadata("#0.0")); #endregion public YAxisScroll() { Labels = new ObservableCollection(); Location = ComponentLocationEnum.Left; this.SizeChanged += (x, y) => { Render(Graph); }; } public override void Render(RealTimeGraphExBase graph, bool animate = false) { if (graph == null) return; if (Interval < 2) return; if (innerGrid == null) { innerGrid = new Grid(); } var grid = innerGrid; double animationTime = animate ? 0.2 : 0; DoubleAnimation heightAnimation = new DoubleAnimation() { Duration = new Duration(TimeSpan.FromSeconds(animationTime)) }; heightAnimation.To = double.IsNaN(Graph.gridLinesAndImageWrapperGrid.Height) ? Graph.gridLinesAndImageWrapperGrid.ActualHeight : Graph.gridLinesAndImageWrapperGrid.Height; if (!double.IsNaN(grid.Height)) { grid.BeginAnimation(Grid.HeightProperty, heightAnimation); } else { grid.Height = Graph.gridLinesAndImageWrapperGrid.ActualHeight; } grid.VerticalAlignment = System.Windows.VerticalAlignment.Top; ThicknessAnimation marginAni = new ThicknessAnimation() { Duration = new Duration(TimeSpan.FromSeconds(animationTime)) }; marginAni.To = new Thickness(0, Graph.gridLinesAndImageWrapperGrid.Margin.Top, 0, 0); if (!double.IsNaN(grid.Height)) { grid.BeginAnimation(MarginProperty, marginAni); } else { grid.Margin = new Thickness(0, Graph.gridLinesAndImageWrapperGrid.Margin.Top, 0, 0); } double height = double.IsNaN(Graph.gridLinesAndImageWrapperGrid.Height) ? Graph.gridLinesAndImageWrapperGrid.ActualHeight : Graph.gridLinesAndImageWrapperGrid.Height; int interval = (int)Math.Round((Interval * (((height * 100) / Graph.gridMain.ActualHeight) / 100)), MidpointRounding.ToEven); this.Content = grid; this.ClipToBounds = true; grid.RowDefinitions.Clear(); grid.Children.Clear(); if (Labels != null && Labels.Count > 0) { for (int i = 0; i < Labels.Count - 1; i++) { RowDefinition rowLabels = new RowDefinition(); rowLabels.Height = new GridLength(1, GridUnitType.Star); grid.RowDefinitions.Add(rowLabels); AddLabel(Labels[i], graph, grid, i, System.Windows.VerticalAlignment.Top); } AddLabel(Labels.Last(), graph, grid, interval - 1, System.Windows.VerticalAlignment.Bottom); } else { for (int i = 0; i < interval; i++) { RowDefinition rowLabels = new RowDefinition(); rowLabels.Height = new GridLength(1, GridUnitType.Star); grid.RowDefinitions.Add(rowLabels); } for (int i = 0; i < interval; i++) { double value = graph.Maximum - (i * ((graph.Maximum - graph.Minimum) / interval)); AddLabel(value.ToString(StringFormat), graph, grid, i, System.Windows.VerticalAlignment.Top); } AddLabel(graph.Minimum.ToString(StringFormat), graph, grid, interval - 1, System.Windows.VerticalAlignment.Bottom); } grid.InvalidateArrange(); grid.InvalidateMeasure(); grid.UpdateLayout(); grid.InvalidateVisual(); } protected void AddLabel(Object content, RealTimeGraphExBase graph, Grid grid, int row, VerticalAlignment align) { //Add Labels YAxisLabel label = new YAxisLabel(); label.HorizontalAlignment = System.Windows.HorizontalAlignment.Center; label.VerticalAlignment = align; label.Content = content; if (row > 0 || VerticalOffset > 0) { label.Margin = new Thickness(HorizontalOffset, VerticalOffset, 0, 0); } Grid.SetRow(label, row); grid.Children.Add(label); if (LabelTemplate != null) { label.ContentTemplate = LabelTemplate; } } protected override void OnGraphZoomComplete(Point transformOrigin, double scaleX, double scaleY) { Render(Graph, true); } protected override void OnGraphMinMaxChanged() { Render(Graph); } protected override void OnGraphPanningComplete(Point translate) { if (innerGrid != null) { var renderBounds = Graph.GetGraphRenderBounds(); innerGrid.BeginAnimation(MarginProperty, null); innerGrid.Margin = new Thickness(0, Graph.gridLinesAndImageWrapperGrid.Margin.Top, 0, 0); } } } }