585 lines · 20.0 KB · C#
RawDownload
//******************************************************************************************************//  ChartWindowUserControl.xaml.cs - Gbtc////  Copyright © 2010, Grid Protection Alliance.  All Rights Reserved.////  Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See//  the NOTICE file distributed with this work for additional information regarding copyright ownership.//  The GPA licenses this file to you under the MIT License (MIT), the "License"; you may//  not use this file except in compliance with the License. You may obtain a copy of the License at:////      http://www.opensource.org/licenses/MIT////  Unless agreed to in writing, the subject software distributed under the License is distributed on an//  "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the//  License for the specific language governing permissions and limitations.////  Code Modification History://  ----------------------------------------------------------------------------------------------------//  12/22/2011 - Aniket Salver//       Generated original version of source code.////****************************************************************************************************** using System;using System.Collections.Generic;using System.Linq;using System.Windows;using System.Windows.Controls;using System.Windows.Controls.DataVisualization.Charting;using System.Windows.Input;using System.Windows.Media;using System.Windows.Shapes;using GSF.Historian;using GSF.Historian.Files; namespace GSF.PhasorProtocols.UI.UserControls{    /// <summary>    /// Interaction logic for ChartWindowUserConrol.xaml    /// </summary>    public partial class ChartWindowUserControl : UserControl    {        #region [ Members ]         // Nested Types        private struct ChartBoundary        {            public DateTime? Left { get; set; }            public DateTime? Right { get; set; }            public double? Top { get; set; }            public double? Bottom { get; set; }        }         private class DataPointWrapper        {            private readonly IDataPoint m_point;             public DataPointWrapper(IDataPoint point)            {                m_point = point;            }             public IDataPoint ArchiveDataPoint            {                get                {                    return m_point;                }            }             public DateTime Time            {                get                {                    return m_point.Time.ToDateTime();                }            }             public float Value            {                get                {                    return m_point.Value;                }            }        }         // Events         /// <summary>        /// Event Generated        /// </summary>        public event EventHandler ChartUpdated;         // Fields        private ICollection<ArchiveFile> m_archiveFiles;        private ICollection<MetadataRecord> m_visiblePoints;        private int m_chartResolution;        private readonly LinkedList<ChartBoundary> m_backwardHistory;        private readonly LinkedList<ChartBoundary> m_forwardHistory;        private List<Color> m_lineColors;        private Rectangle m_selectionArea;        private Point m_mousePressedPosition;        private Point m_mouseDragPosition;        private bool m_selecting;        private bool m_ctrlPressed;        private bool m_shiftPressed;         #endregion         #region[Constructors]         /// <summary>        ///  Initializing the members         /// </summary>        public ChartWindowUserControl()        {            m_archiveFiles = new List<ArchiveFile>();            m_visiblePoints = new List<MetadataRecord>();            m_chartResolution = 100;             m_backwardHistory = new LinkedList<ChartBoundary>();            m_forwardHistory = new LinkedList<ChartBoundary>();             InitializeComponent();            InitializeColors();            InitializeSelectionArea();        }         #endregion         #region [ Properties ]         /// <summary>        /// Gets or sets the start time to be displayed on the graph or exported to CSV.        /// </summary>        public ICollection<ArchiveFile> ArchiveFiles        {            get            {                return m_archiveFiles;            }            set            {                m_archiveFiles = value;                m_visiblePoints.Clear();            }        }          /// <summary>        /// Gets or sets the start time to be displayed on the graph or exported to CSV.        /// </summary>        public ICollection<MetadataRecord> VisiblePoints        {            get            {                return m_visiblePoints;            }            set            {                m_visiblePoints = value;            }        }          /// <summary>        /// Gets or sets the start time to be displayed on the graph or exported to CSV.        /// </summary>        public int ChartResolution        {            get            {                return m_chartResolution;            }            set            {                m_chartResolution = value;            }        }         /// <summary>        /// Gets or sets the start time to be displayed on the graph or exported to CSV.        /// </summary>        public DateTime StartTime        {            get            {                return m_xAxis.ActualMinimum.Value;            }        }         /// <summary>        /// Gets or sets the start time to be displayed on the graph or exported to CSV.        /// </summary>        public DateTime EndTime        {            get            {                return m_xAxis.ActualMaximum.Value;            }        }         private Grid PlotArea        {            get            {                FrameworkElement chartChild = (VisualTreeHelper.GetChildrenCount(m_chart) == 0) ? null : VisualTreeHelper.GetChild(m_chart, 0) as FrameworkElement;                return (chartChild == null) ? null : chartChild.FindName("PlotArea") as Grid;            }        }         #endregion         #region [ Methods ]         /// <summary>        /// Sets the boundaries for the x-axis.        /// </summary>        /// <param name="startTimeString">A string representation of the lower x-axis boundary.</param>        /// <param name="endTimeString">A string representation of the upper x-axis boundary.</param>        public void SetInterval(string startTimeString, string endTimeString)        {            DateTime startTime = TimeTag.Parse(startTimeString).ToDateTime();            DateTime endTime = TimeTag.Parse(endTimeString).ToDateTime();             if (startTime > endTime)                throw new ArgumentException("startTime > endTime");             ClearHistory();            m_xAxis.Minimum = null;            m_xAxis.Maximum = null;            m_yAxis.Minimum = null;            m_yAxis.Maximum = null;             m_xAxis.Minimum = startTime;            m_xAxis.Maximum = endTime;        }         /// <summary>        /// Updates the chart after changes have been made to the chart boundaries or the data displayed in the chart.        /// </summary>        public void UpdateChart()        {            Cursor windowCursor = Cursor;            int colorIndex = 0;            DateTime startTime = m_xAxis.Minimum ?? TimeTag.MinValue.ToDateTime();            DateTime endTime = m_xAxis.Maximum ?? TimeTag.MaxValue.ToDateTime();             Cursor = Cursors.Wait;             m_chart.Series.Clear();            foreach (ArchiveFile file in m_archiveFiles)            {                foreach (MetadataRecord record in file.MetadataFile.Read())                {                    if (m_chartResolution > 0 && colorIndex < m_lineColors.Count && m_visiblePoints.Any(point => record == point))                    {                        LineSeries series = new LineSeries();                        IEnumerable<IDataPoint> data = file.ReadData(record.HistorianID, startTime, endTime);                        int interval = (data.Count() / m_chartResolution) + 1;                        int pointCount = 0;                         // Change how data points are displayed.                        series.DataPointStyle = new Style(typeof(LineDataPoint));                        series.DataPointStyle.Setters.Add(new Setter(BackgroundProperty, new SolidColorBrush(m_lineColors[colorIndex])));                        series.DataPointStyle.Setters.Add(new Setter(TemplateProperty, new ControlTemplate()));                        colorIndex++;                         // Set the title of the series as it will appear in the legend.                        series.Title = record.Name;                         // Filter the data to 100 data points.                        series.ItemsSource = data.Where(point => (pointCount++ % interval) == 0).Select(point => new DataPointWrapper(point));                        series.IndependentValuePath = "Time";                        series.DependentValuePath = "Value";                         // Add the series to the chart.                        m_chart.Series.Add(series);                    }                }            }             UpdateLayout();            Cursor = windowCursor;            OnChartUpdated();        }         // Initializes the list of colors used for lines on the graph.        private void InitializeColors()        {            m_lineColors = new List<Color>();            m_lineColors.Add(Colors.Blue);            m_lineColors.Add(Colors.Red);            m_lineColors.Add(Colors.Yellow);            m_lineColors.Add(Colors.Green);            m_lineColors.Add(Colors.Orange);            m_lineColors.Add(Colors.Purple);            m_lineColors.Add(Colors.Black);            m_lineColors.Add(Colors.White);            m_lineColors.Add(Colors.Brown);            m_lineColors.Add(Colors.Cyan);            m_lineColors.Add(Colors.Lime);            m_lineColors.Add(Colors.Salmon);        }         // Initializes the selection area used to select regions of the graph for zooming in.        private void InitializeSelectionArea()        {            m_selectionArea = new Rectangle();            m_selectionArea.Stroke = new SolidColorBrush(Colors.Black);            m_selectionArea.HorizontalAlignment = HorizontalAlignment.Left;            m_selectionArea.VerticalAlignment = VerticalAlignment.Top;        }         // Updates the rectangle indicating the area selected by the user for zooming.        private void UpdateSelectionArea()        {            Grid plotArea = PlotArea;             if (plotArea != null)            {                double left = Math.Min(m_mousePressedPosition.X, m_mouseDragPosition.X);                double top = Math.Min(m_mousePressedPosition.Y, m_mouseDragPosition.Y);                double right = Math.Max(m_mousePressedPosition.X, m_mouseDragPosition.X);                double bottom = Math.Max(m_mousePressedPosition.Y, m_mouseDragPosition.Y);                 left = Math.Max(left, 0.0);                top = Math.Max(top, 0.0);                right = Math.Min(right, plotArea.ActualWidth);                bottom = Math.Min(bottom, plotArea.ActualHeight);                 if (m_ctrlPressed)                {                    top = 0.0;                    bottom = plotArea.ActualHeight;                }                 if (m_shiftPressed)                {                    left = 0.0;                    right = plotArea.ActualWidth;                }                 m_selectionArea.Margin = new Thickness(left, top, 0.0, 0.0);                m_selectionArea.Width = right - left;                m_selectionArea.Height = bottom - top;            }        }         // Triggers the ChartUpdated event.        private void OnChartUpdated()        {            if (ChartUpdated != null)                ChartUpdated(this, new EventArgs());        }         // Moves backward in the chart history.        private void GoBackInHistory()        {            if (m_backwardHistory.Count > 0)            {                ChartBoundary boundary = m_backwardHistory.Last.Value;                 AddCurrentToForwardHistory();                m_backwardHistory.RemoveLast();                m_xAxis.Minimum = boundary.Left;                m_xAxis.Maximum = boundary.Right;                m_yAxis.Maximum = boundary.Top;                m_yAxis.Minimum = boundary.Bottom;                 if (m_backwardHistory.Count == 0)                    m_backButton.IsEnabled = false;                 UpdateChart();            }        }         // Moves forward in the chart history.        private void GoForwardInHistory()        {            if (m_forwardHistory.Count > 0)            {                ChartBoundary boundary = m_forwardHistory.First.Value;                 AddCurrentToBackwardHistory();                m_forwardHistory.RemoveFirst();                m_xAxis.Minimum = boundary.Left;                m_xAxis.Maximum = boundary.Right;                m_yAxis.Maximum = boundary.Top;                m_yAxis.Minimum = boundary.Bottom;                 if (m_forwardHistory.Count == 0)                    m_forwardButton.IsEnabled = false;                 UpdateChart();            }        }         // Changes the chart boundaries based on the given percentages.        private void Zoom(double leftPercent, double topPercent, double rightPercent, double bottomPercent)        {            DateTime xAxisMinimum = m_xAxis.ActualMinimum.Value;            DateTime xAxisMaximum = m_xAxis.ActualMaximum.Value;            double yAxisMinimum = m_yAxis.Minimum ?? m_yAxis.ActualMinimum.Value;            double yAxisMaximum = m_yAxis.Maximum ?? m_yAxis.ActualMaximum.Value;             // Save current boundary to backward chart history and clear out forward history.            AddCurrentToBackwardHistory();            ClearForwardHistory();             // Clear chart boundaries.            //m_xAxis.Minimum = null;            //m_xAxis.Maximum = null;            //m_yAxis.Minimum = null;            //m_yAxis.Maximum = null;             // Update chart boundaries.            m_xAxis.Minimum = new DateTime((long)(xAxisMaximum.Ticks * leftPercent + xAxisMinimum.Ticks * (1.0 - leftPercent)));            m_xAxis.Maximum = new DateTime((long)(xAxisMaximum.Ticks * rightPercent + xAxisMinimum.Ticks * (1.0 - rightPercent)));            m_yAxis.Minimum = yAxisMinimum * bottomPercent + yAxisMaximum * (1.0 - bottomPercent);            m_yAxis.Maximum = yAxisMinimum * topPercent + yAxisMaximum * (1.0 - topPercent);            UpdateChart();        }         // Adds the current boundary to the backward history.        private void AddCurrentToBackwardHistory()        {            m_backwardHistory.AddLast(GetCurrentChartBoundary());            m_backButton.IsEnabled = true;             if (m_backwardHistory.Count > 20)                m_backwardHistory.RemoveFirst();        }         // Adds the current boundary to the forward history.        private void AddCurrentToForwardHistory()        {            m_forwardHistory.AddFirst(GetCurrentChartBoundary());            m_forwardButton.IsEnabled = true;        }         // Clears all history.        private void ClearHistory()        {            ClearBackwardHistory();            ClearForwardHistory();        }         // Clears the backward history.        private void ClearBackwardHistory()        {            m_backwardHistory.Clear();            m_backButton.IsEnabled = false;        }         // Clears the forward history.        private void ClearForwardHistory()        {            m_forwardHistory.Clear();            m_forwardButton.IsEnabled = false;        }         // Gets the current bounds of the chart's axes.        private ChartBoundary GetCurrentChartBoundary()        {            return new ChartBoundary                {                Left = m_xAxis.Minimum ?? m_xAxis.ActualMinimum,                Right = m_xAxis.Maximum ?? m_xAxis.ActualMaximum,                Top = m_yAxis.Maximum ?? m_yAxis.ActualMaximum,                Bottom = m_yAxis.Minimum ?? m_yAxis.ActualMinimum            };        }         // Detects left ctrl and left shift key presses used for different types of zooming.        private void Window_KeyDown(object sender, KeyEventArgs e)        {            m_ctrlPressed = m_ctrlPressed || e.Key == Key.LeftCtrl;            m_shiftPressed = m_shiftPressed || e.Key == Key.LeftShift;            UpdateSelectionArea();        }         // Detects left ctrl and left shift key releases to return zooming to normal.        private void Window_KeyUp(object sender, KeyEventArgs e)        {            m_ctrlPressed = m_ctrlPressed && e.Key != Key.LeftCtrl;            m_shiftPressed = m_shiftPressed && e.Key != Key.LeftShift;            UpdateSelectionArea();        }         // Detects mouse clicks on the plot area used for selecting regions for zooming.        private void PlotArea_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)        {            Grid plotArea = sender as Grid;             if (plotArea != null)                m_mousePressedPosition = e.GetPosition(plotArea);             m_selecting = true;

Lines 1–500 of 585.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t