diff options
Diffstat (limited to 'Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging')
27 files changed, 1475 insertions, 180 deletions
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Controls/TimeRuler.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Controls/TimeRuler.cs new file mode 100644 index 000000000..552f8f416 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Controls/TimeRuler.cs @@ -0,0 +1,227 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Media; + +namespace Tango.MachineStudio.Logging.Controls +{ + public class TimeRuler : Control + { + private double _smallStep; + private double _bigStep; + + #region Private Methods + + private static T FindVisualParent<T>(DependencyObject child) where T : DependencyObject + { + // get parent item + DependencyObject parentObject = VisualTreeHelper.GetParent(child); + + // we’ve reached the end of the tree + if (parentObject == null) return null; + + // check if the parent matches the type we’re looking for + T parent = parentObject as T; + if (parent != null) + { + return parent; + } + else + { + // use recursion to proceed with next level + return FindVisualParent<T>(parentObject); + } + } + + #endregion + + #region Properties + + public double RenderWidth + { + get { return (double)GetValue(RenderWidthProperty); } + set { SetValue(RenderWidthProperty, value); } + } + public static readonly DependencyProperty RenderWidthProperty = + DependencyProperty.Register("RenderWidth", typeof(double), typeof(TimeRuler), new FrameworkPropertyMetadata(400.0, FrameworkPropertyMetadataOptions.AffectsRender)); + + public double HorizontalOffset + { + get { return (double)GetValue(HorizontalOffsetProperty); } + set { SetValue(HorizontalOffsetProperty, value); } + } + public static readonly DependencyProperty HorizontalOffsetProperty = + DependencyProperty.Register("HorizontalOffset", typeof(double), typeof(TimeRuler), new PropertyMetadata(0.0, HorizontalOffsetChanged)); + + private static void HorizontalOffsetChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var control = d as TimeRuler; + control.Margin = new Thickness(-control.HorizontalOffset, 0, 0, 0); + control.InvalidateVisual(); + } + + + + #region Zoom + /// <summary> + /// Gets or sets the zoom factor for the ruler. The default value is 1.0. + /// </summary> + public double Zoom + { + get + { + return (double)GetValue(ZoomProperty); + } + set + { + SetValue(ZoomProperty, value); + this.InvalidateVisual(); + } + } + + private void SetSteps(double value) + { + if (value >= 50) + { + _smallStep = 0.25; + _bigStep = 1; + } + else if (value >= 40) + { + _smallStep = 0.25; + _bigStep = 2; + } + else if (value >= 30) + { + _smallStep = 0.5; + _bigStep = 2; + } + else if (value >= 20) + { + _smallStep = 1; + _bigStep = 5; + } + else if (value >= 10) + { + _smallStep = 1; + _bigStep = 10; + } + else if (value >= 5) + { + _smallStep = 2; + _bigStep = 20; + } + else if (value >= 3) + { + _smallStep = 5; + _bigStep = 30; + } + else if (value >= 1) + { + _smallStep = 30; + _bigStep = 300; + } + else if (value >= 0.5) + { + _smallStep = 60; + _bigStep = 600; + } + } + + /// <summary> + /// Identifies the Zoom dependency property. + /// </summary> + public static readonly DependencyProperty ZoomProperty = + DependencyProperty.Register("Zoom", typeof(double), typeof(TimeRuler), new FrameworkPropertyMetadata((double)1.0, FrameworkPropertyMetadataOptions.AffectsRender, new PropertyChangedCallback(ZoomChanged))); + + private static void ZoomChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + (d as TimeRuler).SetSteps((double)e.NewValue); + } + + + #endregion + + #endregion + + #region Constructor + + public TimeRuler() + { + _smallStep = 1; + _bigStep = 10; + FontSize = 10; + this.Loaded += TimeRuler_Loaded; + } + + private void TimeRuler_Loaded(object sender, RoutedEventArgs e) + { + this.InvalidateVisual(); + } + + #endregion + + #region Methods + + /// <summary> + /// Participates in rendering operations. + /// </summary> + /// <param name="drawingContext">The drawing instructions for a specific element. This context is provided to the layout system.</param> + protected override void OnRender(DrawingContext drawingContext) + { + base.OnRender(drawingContext); + + double xDest = RenderWidth; + int start = (int)(HorizontalOffset / Zoom); + + drawingContext.DrawRectangle(Background, new Pen(BorderBrush, 0), new Rect(new Point(start * Zoom, 0.0), new Point(xDest + (start * Zoom) + 100, Height))); + drawingContext.DrawLine(new Pen(BorderBrush, 1), new Point(start * Zoom, Height - 1), new Point(xDest + (start * Zoom) + 100, Height)); + + + double l = (start % _smallStep); + while (l != 0) //I don't know why, but this is needed in order to prevent ruler from flickering on some lower scale factors :/ + { + start += 1; + l = (start % _smallStep); + } + + for (double dUnit = start; dUnit < (RenderWidth / Zoom) + (start) + 10; dUnit += _smallStep) + { + double d = dUnit * (this.Zoom); + + double startHeight; + double endHeight; + + startHeight = Height; + endHeight = ((dUnit % _bigStep == 0) ? (this.ActualHeight / 5) * 1.5 : this.ActualHeight / 5); + + drawingContext.DrawLine(new Pen(Foreground, 1), new Point(d, startHeight), new Point(d, (startHeight - endHeight))); + + double uu = (dUnit % _bigStep); + + if ((dUnit != 0.0) && (uu == 0) && (dUnit < (RenderWidth / Zoom) + start + 10)) + { + double u = dUnit; + TimeSpan t = TimeSpan.FromSeconds((u)); + + FormattedText ft = new FormattedText(t.ToString("g"), + CultureInfo.CurrentCulture, + FlowDirection.LeftToRight, + new Typeface(FontFamily.ToString()), + FontSize, + Foreground); + ft.SetFontWeight(FontWeight); + ft.TextAlignment = TextAlignment.Center; + drawingContext.DrawText(ft, new Point(d, (Height / 2) - (ft.Height / 2) - 2)); + } + } + } + + #endregion + } +} diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Controls/TimelineScrollViewer.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Controls/TimelineScrollViewer.cs new file mode 100644 index 000000000..dd1227a06 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Controls/TimelineScrollViewer.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Controls; +using System.Windows.Input; + +namespace Tango.MachineStudio.Logging.Controls +{ + public class TimelineScrollViewer : ScrollViewer + { + public event EventHandler<MouseWheelEventArgs> MouseZooming; + + protected override void OnMouseWheel(MouseWheelEventArgs e) + { + if (Keyboard.IsKeyDown(Key.LeftCtrl)) + { + e.Handled = true; + OnMouseZooming(e); + } + else + { + base.OnMouseWheel(e); + } + + e.Handled = false; + } + + protected override void OnKeyDown(KeyEventArgs e) + { + if (e.KeyboardDevice.Modifiers == ModifierKeys.Control) + { + if (e.Key == Key.Left || e.Key == Key.Right) + e.Handled = true; + return; + } + base.OnKeyDown(e); + } + + protected override void OnPreviewKeyDown(KeyEventArgs e) + { + e.Handled = true; + } + + protected virtual void OnMouseZooming(MouseWheelEventArgs e) + { + if (MouseZooming != null) MouseZooming(this, e); + } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Converters/DateIsInListToBooleanConverter.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Converters/DateIsInListToBooleanConverter.cs new file mode 100644 index 000000000..cd4f60d4c --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Converters/DateIsInListToBooleanConverter.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Data; +using Tango.MachineStudio.Logging.ViewModels; + +namespace Tango.MachineStudio.Logging.Converters +{ + public class DateIsInListToBooleanConverter : IMultiValueConverter + { + public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) + { + if (values.Length < 2 || !(values[0] is DateTime) || !(values[1] is IEnumerable<DateTime>)) + return false; + + var date = (DateTime)values[0]; + var dateList = (IEnumerable<DateTime>)values[1]; + + return dateList.ToList().Exists(x => x.ToLocalTime().ToShortDateString() == date.ToLocalTime().ToShortDateString()); + } + + public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Converters/EventsToTimeRulerTicksConverter.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Converters/EventsToTimeRulerTicksConverter.cs new file mode 100644 index 000000000..35df1723b --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Converters/EventsToTimeRulerTicksConverter.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Data; +using Tango.MachineStudio.Logging.ViewModels; + +namespace Tango.MachineStudio.Logging.Converters +{ + public class EventsToTimeRulerTicksConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + ObservableCollection<TimelineEventGroup> groups = value as ObservableCollection<TimelineEventGroup>; + + DateTime maxTime = groups.SelectMany(x => x.Events).Max(x => x.DateTime); + DateTime minTime = groups.SelectMany(x => x.Events).Min(x => x.DateTime); + + List<DateTime> dates = new List<DateTime>(); + + for (DateTime time = minTime; time < maxTime; time = time.AddSeconds(1)) + { + dates.Add(time); + } + + return dates; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Converters/MachineEventToXConverter.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Converters/MachineEventToXConverter.cs new file mode 100644 index 000000000..193a63ffc --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Converters/MachineEventToXConverter.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Data; +using Tango.BL.Entities; +using Tango.MachineStudio.Logging.Helpers; +using Tango.MachineStudio.Logging.ViewModels; + +namespace Tango.MachineStudio.Logging.Converters +{ + public class MachineEventToXConverter : IMultiValueConverter + { + public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) + { + if (values.Length == 3) + { + MachinesEvent ev = values[0] as MachinesEvent; + + if (ev != null) + { + ObservableCollection<TimelineEventGroup> groups = values[1] as ObservableCollection<TimelineEventGroup>; + + if (groups.Count > 0) + { + double scale = (double)values[2]; + + DateTime maxTime = groups.SelectMany(x => x.Events).Max(x => x.DateTime); + DateTime minTime = groups.SelectMany(x => x.Events).Min(x => x.DateTime); + + TimeSpan range = maxTime - minTime; + TimeSpan time = maxTime - ev.DateTime; + + time = range - time; + + return TimelineHelper.ConvertTimeToPixels(time, scale); + } + } + } + + return 0.0; + } + + public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Converters/SecondsToWidthConverter.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Converters/SecondsToWidthConverter.cs new file mode 100644 index 000000000..66e888cc0 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Converters/SecondsToWidthConverter.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Data; +using Tango.MachineStudio.Logging.Helpers; + +namespace Tango.MachineStudio.Logging.Converters +{ + public class SecondsToWidthConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + double scale = (double)value; + double seconds = System.Convert.ToDouble(parameter.ToString()); + + return TimelineHelper.ConvertTimeToPixels(TimeSpan.FromSeconds(seconds), scale); + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Converters/TimeSpanToXConverter.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Converters/TimeSpanToXConverter.cs new file mode 100644 index 000000000..c5f310d52 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Converters/TimeSpanToXConverter.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Data; +using Tango.MachineStudio.Logging.Helpers; + +namespace Tango.MachineStudio.Logging.Converters +{ + public class TimeSpanToXConverter : IMultiValueConverter + { + public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) + { + if (values.Length == 2) + { + TimeSpan time = (TimeSpan)values[0]; + double scale = (double)values[1]; + + return TimelineHelper.ConvertTimeToPixels(time, scale) + (parameter != null ? System.Convert.ToDouble(parameter) : 0); + } + + return null; + } + + public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Helpers/TimelineHelper.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Helpers/TimelineHelper.cs new file mode 100644 index 000000000..6cfe51ba4 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Helpers/TimelineHelper.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.MachineStudio.Logging.Helpers +{ + public static class TimelineHelper + { + public static double ConvertTimeToPixels(TimeSpan time, double scaleFactor) + { + return ((double)(0.05f * ((double)(time.TotalSeconds) * 20))) * scaleFactor; + } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Navigation/LoggingNavigationManager.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Navigation/LoggingNavigationManager.cs new file mode 100644 index 000000000..b86df7b0f --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Navigation/LoggingNavigationManager.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Logging; +using Tango.MachineStudio.Common.Navigation; +using Tango.MachineStudio.Logging.Views; + +namespace Tango.MachineStudio.Logging.Navigation +{ + public class LoggingNavigationManager + { + private LogManager LogManager = LogManager.Default; + + public void NavigateTo(LoggingNavigationView view) + { + LogManager.Log(String.Format("Navigating to view {0}...", view.ToString())); + MainView.Instance.TransitionControl.AutoNavigate(view.ToString()); + } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Navigation/LoggingNavigationView.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Navigation/LoggingNavigationView.cs new file mode 100644 index 000000000..6f4fcbceb --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Navigation/LoggingNavigationView.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.MachineStudio.Logging.Navigation +{ + public enum LoggingNavigationView + { + EventsView, + TimelineView, + } +} diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Tango.MachineStudio.Logging.csproj b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Tango.MachineStudio.Logging.csproj index be3e1ef93..4b817a124 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Tango.MachineStudio.Logging.csproj +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Tango.MachineStudio.Logging.csproj @@ -81,13 +81,37 @@ <Compile Include="..\..\..\Versioning\GlobalVersionInfo.cs"> <Link>GlobalVersionInfo.cs</Link> </Compile> + <Compile Include="Controls\TimelineScrollViewer.cs" /> + <Compile Include="Controls\TimeRuler.cs" /> + <Compile Include="Converters\DateIsInListToBooleanConverter.cs" /> + <Compile Include="Converters\EventsToTimeRulerTicksConverter.cs" /> + <Compile Include="Converters\MachineEventToXConverter.cs" /> + <Compile Include="Converters\SecondsToWidthConverter.cs" /> + <Compile Include="Converters\TimeSpanToXConverter.cs" /> + <Compile Include="Helpers\TimelineHelper.cs" /> <Compile Include="LoggingModule.cs" /> + <Compile Include="Navigation\LoggingNavigationManager.cs" /> + <Compile Include="Navigation\LoggingNavigationView.cs" /> <Compile Include="ViewModelLocator.cs" /> - <Compile Include="ViewModels\DateVM.cs" /> + <Compile Include="ViewModels\EventDetailsViewVM.cs" /> <Compile Include="ViewModels\MainViewVM.cs" /> + <Compile Include="ViewModels\TimelineEventGroup.cs" /> + <Compile Include="ViewModels\TimelineViewVM.cs" /> + <Compile Include="Views\EventDetailsView.xaml.cs"> + <DependentUpon>EventDetailsView.xaml</DependentUpon> + </Compile> + <Compile Include="Views\EventsView.xaml.cs"> + <DependentUpon>EventsView.xaml</DependentUpon> + </Compile> <Compile Include="Views\MainView.xaml.cs"> <DependentUpon>MainView.xaml</DependentUpon> </Compile> + <Compile Include="Views\TimelineView.xaml.cs"> + <DependentUpon>TimelineView.xaml</DependentUpon> + </Compile> + <Compile Include="Views\TimelineWrapperView.xaml.cs"> + <DependentUpon>TimelineWrapperView.xaml</DependentUpon> + </Compile> </ItemGroup> <ItemGroup> <Compile Include="Properties\AssemblyInfo.cs"> @@ -160,10 +184,26 @@ </ProjectReference> </ItemGroup> <ItemGroup> + <Page Include="Views\EventDetailsView.xaml"> + <SubType>Designer</SubType> + <Generator>MSBuild:Compile</Generator> + </Page> + <Page Include="Views\EventsView.xaml"> + <SubType>Designer</SubType> + <Generator>MSBuild:Compile</Generator> + </Page> <Page Include="Views\MainView.xaml"> <SubType>Designer</SubType> <Generator>MSBuild:Compile</Generator> </Page> + <Page Include="Views\TimelineView.xaml"> + <SubType>Designer</SubType> + <Generator>MSBuild:Compile</Generator> + </Page> + <Page Include="Views\TimelineWrapperView.xaml"> + <SubType>Designer</SubType> + <Generator>MSBuild:Compile</Generator> + </Page> </ItemGroup> <ItemGroup> <Resource Include="Images\machine-trans.png" /> diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/ViewModelLocator.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/ViewModelLocator.cs index 76c89000d..ef6923e27 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/ViewModelLocator.cs +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/ViewModelLocator.cs @@ -1,6 +1,7 @@ using GalaSoft.MvvmLight; using GalaSoft.MvvmLight.Ioc; using Microsoft.Practices.ServiceLocation; +using Tango.MachineStudio.Logging.Navigation; using Tango.MachineStudio.Logging.ViewModels; namespace Tango.MachineStudio.Logging @@ -18,6 +19,9 @@ namespace Tango.MachineStudio.Logging { ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default); SimpleIoc.Default.Register<MainViewVM>(); + + SimpleIoc.Default.Unregister<LoggingNavigationManager>(); + SimpleIoc.Default.Register<LoggingNavigationManager>(() => new LoggingNavigationManager()); } public static MainViewVM MainViewVM diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/ViewModels/DateVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/ViewModels/DateVM.cs deleted file mode 100644 index fd03d6328..000000000 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/ViewModels/DateVM.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Tango.Core; - -namespace Tango.MachineStudio.Logging.ViewModels -{ - public class DateVM : ExtendedObject - { - public DateTime Date { get; set; } - - public String Description { get; set; } - - public DateVM(DateTime date) - { - Date = date; - Description = date.ToLocalTime().ToShortDateString(); - } - } -} diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/ViewModels/EventDetailsViewVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/ViewModels/EventDetailsViewVM.cs new file mode 100644 index 000000000..0e3d19748 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/ViewModels/EventDetailsViewVM.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.BL.Entities; +using Tango.Core.Commands; +using Tango.MachineStudio.Common.Notifications; +using Tango.SharedUI; + +namespace Tango.MachineStudio.Logging.ViewModels +{ + public class EventDetailsViewVM : DialogViewVM + { + public MachinesEvent Event { get; set; } + + public EventDetailsViewVM() + { + + } + + public EventDetailsViewVM(MachinesEvent ev) : this() + { + Event = ev; + } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/ViewModels/MainViewVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/ViewModels/MainViewVM.cs index 2b773c1c2..e5121e709 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/ViewModels/MainViewVM.cs +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/ViewModels/MainViewVM.cs @@ -7,10 +7,13 @@ using System.Text; using System.Threading.Tasks; using Tango.BL; using Tango.BL.Entities; +using Tango.Core.Commands; using Tango.MachineStudio.Common.EventLogging; using Tango.MachineStudio.Common.Messages; using Tango.MachineStudio.Common.Notifications; using Tango.MachineStudio.Common.StudioApplication; +using Tango.MachineStudio.Logging.Navigation; +using Tango.MachineStudio.Logging.Views; using Tango.SharedUI; namespace Tango.MachineStudio.Logging.ViewModels @@ -20,9 +23,9 @@ namespace Tango.MachineStudio.Logging.ViewModels private INotificationProvider _notification; private IStudioApplicationManager _application; private IEventLogger _eventLogger; - private DateVM _realTimeDate; private ObservableCollection<MachinesEvent> _realTimeEvents; private Machine _connectedMachine; + private LoggingNavigationManager _navigation; private Machine _selectedMachine; public Machine SelectedMachine @@ -45,30 +48,68 @@ namespace Tango.MachineStudio.Logging.ViewModels set { _selectedEvent = value; RaisePropertyChangedAuto(); OnSelectedEventChanged(); } } - private ObservableCollection<DateVM> _dates; - public ObservableCollection<DateVM> Dates + private ObservableCollection<DateTime> _dates; + public ObservableCollection<DateTime> Dates { get { return _dates; } set { _dates = value; RaisePropertyChangedAuto(); } } - private DateVM _selectedDate; - public DateVM SelectedDate + private DateTime _selectedDate; + public DateTime SelectedDate { get { return _selectedDate; } set { _selectedDate = value; RaisePropertyChangedAuto(); OnSelectedDateChanged(); } } - public MainViewVM(INotificationProvider notification, IEventLogger eventLogger, IStudioApplicationManager application) + private DateTime _minDate; + public DateTime MinDate { + get { return _minDate; } + set { _minDate = value; RaisePropertyChangedAuto(); } + } + + private DateTime _maxDate; + public DateTime MaxDate + { + get { return _maxDate; } + set { _maxDate = value; RaisePropertyChangedAuto(); } + } + + + private bool _isRealTime; + public bool IsRealTime + { + get { return _isRealTime; } + set { _isRealTime = value; RaisePropertyChangedAuto(); OnSelectedDateChanged(); } + } + + private TimelineViewVM _timelineViewVM; + + public TimelineViewVM TimelineViewVM + { + get { return _timelineViewVM; } + set { _timelineViewVM = value; RaisePropertyChangedAuto(); } + } + + public RelayCommand<MachinesEvent> DisplayTimelineCommand { get; set; } + + public RelayCommand NavigateToEventsCommand { get; set; } + + public MainViewVM(INotificationProvider notification, IEventLogger eventLogger, IStudioApplicationManager application, LoggingNavigationManager navigation) + { + TimelineViewVM = new TimelineViewVM(notification); + + _navigation = navigation; _application = application; _notification = notification; _eventLogger = eventLogger; - _realTimeDate = new DateVM(DateTime.Now) { Description = "Real Time" }; _realTimeEvents = new ObservableCollection<MachinesEvent>(); _eventLogger.NewLog += _eventLogger_NewLog; RegisterMessage<MachineConnectionChangedMessage>(OnMachineConnectionChanged); + DisplayTimelineCommand = new RelayCommand<MachinesEvent>(DisplayTimeline); + NavigateToEventsCommand = new RelayCommand(() => _navigation.NavigateTo(LoggingNavigationView.EventsView)); } private void OnMachineConnectionChanged(MachineConnectionChangedMessage msg) @@ -88,7 +129,7 @@ namespace Tango.MachineStudio.Logging.ViewModels { InvokeUI(() => { - _realTimeEvents.Add(machineEvent); + _realTimeEvents.Insert(0, machineEvent); }); } @@ -96,27 +137,30 @@ namespace Tango.MachineStudio.Logging.ViewModels { if (SelectedMachine != null) { - Dates = new ObservableCollection<DateVM>(); + Dates = new ObservableCollection<DateTime>(); if (SelectedMachine == _connectedMachine) { - Dates.Add(_realTimeDate); + IsRealTime = true; } foreach (var day in SelectedMachine.MachinesEvents.GroupBy(x => x.DateTime.DayOfYear).Select(x => x.First().DateTime).OrderByDescending(x => x)) { - Dates.Add(new DateVM(day)); + Dates.Add(day); } + MinDate = Dates.Min(); + MaxDate = Dates.Max(); + SelectedDate = Dates.FirstOrDefault(); } } private void OnSelectedDateChanged() { - if (SelectedDate != null) + if (SelectedDate != null && SelectedMachine != null) { - if (SelectedDate == _realTimeDate) + if (IsRealTime) { Events = _realTimeEvents; } @@ -129,10 +173,20 @@ namespace Tango.MachineStudio.Logging.ViewModels private void OnSelectedEventChanged() { - if (SelectedEvent != null) + if (SelectedEvent != null && SelectedEvent.Type != BL.Enumerations.EventTypes.ApplicationStarted) { - _notification.ShowInfo(SelectedEvent.Description); + _notification.ShowModalDialog<EventDetailsViewVM, EventDetailsView>(new EventDetailsViewVM(SelectedEvent), (x) => { }, () => { }); } } + + private void DisplayTimeline(MachinesEvent ev) + { + var events = Events.OrderBy(x => x.DateTime).SkipWhile(x => x != ev).Skip(1).TakeWhile(x => x.DateTime > ev.DateTime && x.Type != BL.Enumerations.EventTypes.ApplicationStarted).ToObservableCollection(); + events.Insert(0, ev); + + TimelineViewVM.Initialize(events.ToList()); + + _navigation.NavigateTo(LoggingNavigationView.TimelineView); + } } } diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/ViewModels/TimelineEventGroup.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/ViewModels/TimelineEventGroup.cs new file mode 100644 index 000000000..978348fd2 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/ViewModels/TimelineEventGroup.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.BL.Entities; +using Tango.Core; + +namespace Tango.MachineStudio.Logging.ViewModels +{ + public class TimelineEventGroup : ExtendedObject + { + public String Name { get; set; } + + public ObservableCollection<MachinesEvent> Events { get; set; } + + public TimelineEventGroup() + { + Events = new ObservableCollection<MachinesEvent>(); + } + + public TimelineEventGroup(String name) : this() + { + Name = name; + } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/ViewModels/TimelineViewVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/ViewModels/TimelineViewVM.cs new file mode 100644 index 000000000..edf53bbd2 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/ViewModels/TimelineViewVM.cs @@ -0,0 +1,97 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.BL.Entities; +using Tango.Core.Commands; +using Tango.MachineStudio.Common.Notifications; +using Tango.MachineStudio.Logging.Views; +using Tango.SharedUI; + +namespace Tango.MachineStudio.Logging.ViewModels +{ + public class TimelineViewVM : ViewModel + { + private ObservableCollection<TimelineEventGroup> _timelineEventGroups; + public ObservableCollection<TimelineEventGroup> TimelineEventGroups + { + get { return _timelineEventGroups; } + set { _timelineEventGroups = value; RaisePropertyChangedAuto(); } + } + + private TimeSpan _timelineMaxTime; + public TimeSpan TimelineMaxTime + { + get { return _timelineMaxTime; } + set { _timelineMaxTime = value; RaisePropertyChangedAuto(); } + } + + private double _timelineScaleFactor; + public double TimelineScaleFactor + { + get { return _timelineScaleFactor; } + set + { + + if (value < 0.1) value = 0.1; + + _timelineScaleFactor = value; + RaisePropertyChangedAuto(); + } + } + + private TimeSpan _currentPosition; + + public TimeSpan CurrentPosition + { + get { return _currentPosition; } + set { _currentPosition = value; RaisePropertyChangedAuto(); } + } + + private bool _enableTimeMarker; + + public bool EnableTimeMarker + { + get { return _enableTimeMarker; } + set { _enableTimeMarker = value; RaisePropertyChangedAuto(); } + } + + public RelayCommand<MachinesEvent> EventSelectedCommand { get; set; } + + + public TimelineViewVM(INotificationProvider notification) + { + TimelineScaleFactor = 10; + TimelineEventGroups = new ObservableCollection<TimelineEventGroup>(); + + EventSelectedCommand = new RelayCommand<MachinesEvent>((ev) => + { + notification.ShowModalDialog<EventDetailsViewVM, EventDetailsView>(new EventDetailsViewVM(ev), (x) => { }, () => { }); + }); + } + + public void Initialize(List<MachinesEvent> events) + { + TimelineEventGroups = new ObservableCollection<TimelineEventGroup>(); + + if (events != null && events.Count > 0) + { + foreach (var group in events.GroupBy(x => x.Group)) + { + TimelineEventGroup evGroup = new TimelineEventGroup(group.Key.ToString().ToWords()); + + foreach (var e in group) + { + evGroup.Events.Add(e); + } + + TimelineEventGroups.Add(evGroup); + } + + TimelineMaxTime = events.Max(x => x.DateTime) - events.Min(x => x.DateTime); + } + } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Views/EventDetailsView.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Views/EventDetailsView.xaml new file mode 100644 index 000000000..c75ef41ee --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Views/EventDetailsView.xaml @@ -0,0 +1,93 @@ +<UserControl x:Class="Tango.MachineStudio.Logging.Views.EventDetailsView" + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:converters="clr-namespace:Tango.SharedUI.Converters;assembly=Tango.SharedUI" + xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" + xmlns:controls="clr-namespace:Tango.SharedUI.Controls;assembly=Tango.SharedUI" + xmlns:vm="clr-namespace:Tango.MachineStudio.Logging.ViewModels" + xmlns:entities="clr-namespace:Tango.BL.Entities;assembly=Tango.BL" + xmlns:local="clr-namespace:Tango.MachineStudio.Logging.Views" + mc:Ignorable="d" + Height="500" Width="800" Background="White" d:DataContext="{d:DesignInstance Type=vm:EventDetailsViewVM, IsDesignTimeCreatable=False}"> + + <UserControl.Resources> + <converters:DateTimeUTCToStringConverter x:Key="DateTimeUTCToStringConverter" /> + </UserControl.Resources> + + <Grid> + <Grid Grid.RowSpan="2"> + <Grid.RowDefinitions> + <RowDefinition Height="60"/> + <RowDefinition Height="31*"/> + <RowDefinition Height="50"/> + </Grid.RowDefinitions> + + <StackPanel Orientation="Horizontal"> + <materialDesign:PackIcon Width="42" Height="42" VerticalAlignment="Center"> + <materialDesign:PackIcon.Style> + <Style TargetType="materialDesign:PackIcon"> + <Setter Property="Kind" Value="Alert"></Setter> + <Style.Triggers> + <DataTrigger Binding="{Binding Event.Category}" Value="Info"> + <Setter Property="Kind" Value="Information"></Setter> + <Setter Property="Foreground" Value="DimGray"></Setter> + </DataTrigger> + <DataTrigger Binding="{Binding Event.Category}" Value="Warning"> + <Setter Property="Kind" Value="Alert"></Setter> + <Setter Property="Foreground" Value="#FFA300"></Setter> + </DataTrigger> + <DataTrigger Binding="{Binding Event.Category}" Value="Error"> + <Setter Property="Kind" Value="AlertOctagon"></Setter> + <Setter Property="Foreground" Value="#FF5C5C"></Setter> + </DataTrigger> + <DataTrigger Binding="{Binding Event.Category}" Value="Critical"> + <Setter Property="Kind" Value="BellPlus"></Setter> + <Setter Property="Foreground" Value="Red"></Setter> + </DataTrigger> + <DataTrigger Binding="{Binding Event.Type}" Value="ApplicationStarted"> + <Setter Property="Kind" Value="ClockFast"></Setter> + <Setter Property="Foreground" Value="White"></Setter> + </DataTrigger> + </Style.Triggers> + </Style> + </materialDesign:PackIcon.Style> + </materialDesign:PackIcon> + <TextBlock VerticalAlignment="Center" Text="{Binding Event.EventType.Name}" Margin="10 0 0 0" FontSize="16"></TextBlock> + </StackPanel> + + <Grid Grid.Row="1"> + <DockPanel> + <UniformGrid Columns="2" DockPanel.Dock="Top"> + <controls:TableGrid RowHeight="30"> + <TextBlock Text="Date:" FontWeight="SemiBold" /> + <TextBlock Text="{Binding Event.DateTime,Converter={StaticResource DateTimeUTCToStringConverter},ConverterParameter='MM/dd/yyyy HH:mm:ss.fff'}"></TextBlock> + <TextBlock Text="Host Name:" FontWeight="SemiBold" /> + <TextBlock Text="{Binding Event.HostName}"></TextBlock> + <TextBlock Text="Machine:" FontWeight="SemiBold" /> + <TextBlock Text="{Binding Event.Machine.SerialNumber}"></TextBlock> + <TextBlock Text="User:" FontWeight="SemiBold" /> + <TextBlock Text="{Binding Event.User.Contact.FullName}"></TextBlock> + </controls:TableGrid> + + <controls:TableGrid RowHeight="30"> + <TextBlock Text="Category:" FontWeight="SemiBold" /> + <TextBlock Text="{Binding Event.EventType.EventTypesCategory.Name}"></TextBlock> + <TextBlock Text="Group:" FontWeight="SemiBold" /> + <TextBlock Text="{Binding Event.EventType.EventTypesGroup.Name}"></TextBlock> + </controls:TableGrid> + </UniformGrid> + + <Border Padding="5" BorderThickness="1" BorderBrush="Gainsboro"> + <TextBox BorderThickness="0" Text="{Binding Event.Description}" Style="{x:Null}" TextWrapping="Wrap" IsReadOnly="True" HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto" Background="Transparent" /> + </Border> + </DockPanel> + </Grid> + + <Grid Grid.Row="2"> + <Button HorizontalAlignment="Right" Width="140" Command="{Binding CloseCommand}">CLOSE</Button> + </Grid> + </Grid> + </Grid> +</UserControl> diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Views/EventDetailsView.xaml.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Views/EventDetailsView.xaml.cs new file mode 100644 index 000000000..dd447e1b6 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Views/EventDetailsView.xaml.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace Tango.MachineStudio.Logging.Views +{ + /// <summary> + /// Interaction logic for EventDetailsView.xaml + /// </summary> + public partial class EventDetailsView : UserControl + { + public EventDetailsView() + { + InitializeComponent(); + } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Views/EventsView.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Views/EventsView.xaml new file mode 100644 index 000000000..d92e56ddc --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Views/EventsView.xaml @@ -0,0 +1,245 @@ +<UserControl x:Class="Tango.MachineStudio.Logging.Views.EventsView" + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:autoComplete="clr-namespace:Tango.AutoComplete.Editors;assembly=Tango.AutoComplete" + xmlns:autoCompleteMachine="clr-namespace:Tango.MachineStudio.Common.AutoComplete;assembly=Tango.MachineStudio.Common" + xmlns:converters="clr-namespace:Tango.SharedUI.Converters;assembly=Tango.SharedUI" + xmlns:global="clr-namespace:Tango.MachineStudio.Logging" + xmlns:localConverters="clr-namespace:Tango.MachineStudio.Logging.Converters" + xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" + xmlns:vm="clr-namespace:Tango.MachineStudio.Logging.ViewModels" + xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:local="clr-namespace:Tango.MachineStudio.Logging.Views" + mc:Ignorable="d" + d:DesignHeight="1080" d:DesignWidth="1920" d:DataContext="{d:DesignInstance Type=vm:MainViewVM, IsDesignTimeCreatable=False}" DataContext="{x:Static global:ViewModelLocator.MainViewVM}"> + <UserControl.Resources> + <autoCompleteMachine:MachinesProvider x:Key="MachinesProvider" /> + <converters:DateTimeUTCToShortDateTimeConverter x:Key="DateTimeUTCToShortDateTimeConverter" /> + <converters:DateTimeUTCToStringConverter x:Key="DateTimeUTCToStringConverter" /> + <localConverters:DateIsInListToBooleanConverter x:Key="DateIsInListToBooleanConverter" /> + + <Style x:Key="CustomCalendarDayButtonStyle" TargetType="{x:Type CalendarDayButton}" BasedOn="{StaticResource MaterialDesignCalendarDayButton}"> + <Style.Triggers> + <DataTrigger Value="True"> + <DataTrigger.Binding> + <MultiBinding Converter="{StaticResource DateIsInListToBooleanConverter}"> + <Binding /> + <Binding RelativeSource="{RelativeSource AncestorType=UserControl}" Path="DataContext.Dates" /> + <Binding RelativeSource="{RelativeSource AncestorType=DatePicker}" Path="IsDropDownOpen" ></Binding> + </MultiBinding> + </DataTrigger.Binding> + <Setter Property="Foreground" Value="{StaticResource AccentColorBrush}" /> + </DataTrigger> + </Style.Triggers> + </Style> + + <Style x:Key="HighlightDatePickerStyle" TargetType="{x:Type Calendar}" BasedOn="{StaticResource {x:Type Calendar}}"> + <Setter Property="CalendarDayButtonStyle" Value="{StaticResource CustomCalendarDayButtonStyle}" /> + </Style> + + <Style TargetType="DatePickerTextBox" BasedOn="{StaticResource {x:Type DatePickerTextBox}}"> + <Setter Property="IsReadOnly" Value="True"/> + </Style> + </UserControl.Resources> + + <Grid> + <Grid> + <Grid.RowDefinitions> + <RowDefinition Height="79"/> + <RowDefinition Height="1*"/> + </Grid.RowDefinitions> + + <Border Background="#F1F1F1"> + <Border.Effect> + <DropShadowEffect /> + </Border.Effect> + <Grid> + <StackPanel Orientation="Horizontal"> + <Border Margin="10" Padding="5" BorderBrush="DimGray" BorderThickness="1"> + <Border.Background> + <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1"> + <GradientStop Color="White"/> + <GradientStop Color="#FFEAEAEA" Offset="1"/> + </LinearGradientBrush> + </Border.Background> + <StackPanel Orientation="Horizontal"> + <Image Source="../Images/machine-trans.png" RenderOptions.BitmapScalingMode="Fant"></Image> + <StackPanel Orientation="Horizontal" Width="300" Margin="20 0 0 5" VerticalAlignment="Bottom"> + <materialDesign:PackIcon Kind="BarcodeScan" VerticalAlignment="Center" Width="24" Height="24" /> + <autoComplete:AutoCompleteTextBox HorizontalContentAlignment="Stretch" Width="300" Margin="10 0 0 0" FontSize="16" Provider="{StaticResource MachinesProvider}" SelectedItem="{Binding SelectedMachine,Mode=TwoWay}" materialDesign:HintAssist.Hint="Serial Number / Name" DisplayMember="SerialNumber"> + <autoComplete:AutoCompleteTextBox.ItemTemplate> + <DataTemplate> + <Border Padding="5"> + <DockPanel LastChildFill="False" Width="250"> + <StackPanel Orientation="Horizontal" DockPanel.Dock="Left"> + <Image Source="/Images/machine-trans.png" Width="24" RenderOptions.BitmapScalingMode="Fant" /> + <TextBlock Margin="10 0 0 0" FontWeight="SemiBold" Text="{Binding SerialNumber}" VerticalAlignment="Center"></TextBlock> + </StackPanel> + <TextBlock DockPanel.Dock="Right" HorizontalAlignment="Right" Text="{Binding Name}" Foreground="Gray" VerticalAlignment="Center"></TextBlock> + </DockPanel> + </Border> + </DataTemplate> + </autoComplete:AutoCompleteTextBox.ItemTemplate> + </autoComplete:AutoCompleteTextBox> + </StackPanel> + </StackPanel> + </Border> + <Border Margin="10" Padding="5" BorderBrush="DimGray" BorderThickness="1"> + <Border.Background> + <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1"> + <GradientStop Color="White"/> + <GradientStop Color="#FFEAEAEA" Offset="1"/> + </LinearGradientBrush> + </Border.Background> + <StackPanel Orientation="Horizontal"> + <materialDesign:PackIcon Kind="Calendar" Width="24" Height="24" VerticalAlignment="Bottom" Margin="0 0 0 5" /> + <DatePicker x:Name="datePicker" DisplayDateStart="{Binding MinDate}" DisplayDateEnd="{Binding MaxDate}" CalendarStyle="{StaticResource HighlightDatePickerStyle}" SelectedDate="{Binding SelectedDate}" materialDesign:HintAssist.Hint="Pick Date" Margin="10 0 0 5" Width="200" VerticalAlignment="Bottom" FontSize="16"> + </DatePicker> + <ToggleButton VerticalAlignment="Bottom" Margin="20 0 0 5" IsChecked="{Binding IsRealTime}"></ToggleButton> + <TextBlock VerticalAlignment="Center" Margin="10 17 0 0">Real-Time</TextBlock> + </StackPanel> + </Border> + </StackPanel> + </Grid> + </Border> + + <Grid Grid.Row="1" Background="#B3FFFFFF"> + <Grid Margin="10"> + <Grid.ColumnDefinitions> + + <ColumnDefinition Width="1*"/> + </Grid.ColumnDefinitions> + + <Grid> + <Grid> + <Grid> + <DataGrid Background="Transparent" AutoGenerateColumns="False" SelectionMode="Single" ItemsSource="{Binding Events}" SelectedItem="{Binding SelectedEvent}" RowHeight="40" CanUserAddRows="False" CanUserDeleteRows="False" CanUserReorderColumns="True" IsReadOnly="True"> + <DataGrid.RowStyle> + <Style TargetType="DataGridRow" BasedOn="{StaticResource {x:Type DataGridRow}}"> + <Style.Triggers> + <Trigger Property="IsMouseOver" Value="True"> + <Setter Property="Background" Value="Transparent"></Setter> + <Setter Property="Foreground" Value="{StaticResource AccentColorBrush}" /> + <Setter Property="Cursor" Value="Hand"></Setter> + </Trigger> + <Trigger Property="IsSelected" Value="True"> + <Setter Property="Background" Value="Transparent"></Setter> + </Trigger> + <Trigger Property="IsFocused" Value="True"> + <Setter Property="Background" Value="Transparent"></Setter> + </Trigger> + <DataTrigger Binding="{Binding Type}" Value="ApplicationStarted"> + <Setter Property="Background" Value="{StaticResource AccentColorBrush}"></Setter> + <Setter Property="Foreground" Value="White" /> + <Setter Property="FontWeight" Value="SemiBold"></Setter> + <Setter Property="Cursor" Value="Arrow"></Setter> + </DataTrigger> + </Style.Triggers> + </Style> + </DataGrid.RowStyle> + <DataGrid.CellStyle> + <Style TargetType="DataGridCell" BasedOn="{StaticResource {x:Type DataGridCell}}"> + <Setter Property="BorderThickness" Value="0"/> + <Setter Property="FocusVisualStyle" Value="{x:Null}"/> + <Setter Property="VerticalContentAlignment" Value="Center"></Setter> + <Style.Triggers> + <Trigger Property="IsSelected" Value="True"> + <Setter Property="Background" Value="Transparent"></Setter> + </Trigger> + <DataTrigger Binding="{Binding Type}" Value="ApplicationStarted"> + <Setter Property="Background" Value="{StaticResource AccentColorBrush}"></Setter> + <Setter Property="Foreground" Value="White" /> + <Setter Property="FontWeight" Value="SemiBold"></Setter> + <Setter Property="Cursor" Value="Arrow"></Setter> + </DataTrigger> + </Style.Triggers> + </Style> + </DataGrid.CellStyle> + <DataGrid.Columns> + <DataGridTemplateColumn Header="#"> + <DataGridTemplateColumn.CellTemplate> + <DataTemplate> + <materialDesign:PackIcon Width="16" Height="16"> + <materialDesign:PackIcon.Style> + <Style TargetType="materialDesign:PackIcon"> + <Setter Property="Kind" Value="Alert"></Setter> + <Style.Triggers> + <DataTrigger Binding="{Binding Category}" Value="Info"> + <Setter Property="Kind" Value="Information"></Setter> + <Setter Property="Foreground" Value="DimGray"></Setter> + </DataTrigger> + <DataTrigger Binding="{Binding Category}" Value="Warning"> + <Setter Property="Kind" Value="Alert"></Setter> + <Setter Property="Foreground" Value="#FFA300"></Setter> + </DataTrigger> + <DataTrigger Binding="{Binding Category}" Value="Error"> + <Setter Property="Kind" Value="AlertOctagon"></Setter> + <Setter Property="Foreground" Value="#FF5C5C"></Setter> + </DataTrigger> + <DataTrigger Binding="{Binding Category}" Value="Critical"> + <Setter Property="Kind" Value="BellPlus"></Setter> + <Setter Property="Foreground" Value="Red"></Setter> + </DataTrigger> + <DataTrigger Binding="{Binding Type}" Value="ApplicationStarted"> + <Setter Property="Kind" Value="ClockFast"></Setter> + <Setter Property="Foreground" Value="White"></Setter> + </DataTrigger> + </Style.Triggers> + </Style> + </materialDesign:PackIcon.Style> + </materialDesign:PackIcon> + </DataTemplate> + </DataGridTemplateColumn.CellTemplate> + </DataGridTemplateColumn> + <DataGridTextColumn Header="DATE TIME" Binding="{Binding DateTime,Converter={StaticResource DateTimeUTCToStringConverter},ConverterParameter='MM/dd/yyyy HH:mm:ss.fff'}" /> + <DataGridTextColumn Header="HOST" Binding="{Binding HostName}" /> + <DataGridTextColumn Header="USER" Binding="{Binding User.Contact.FullName,Mode=OneTime}" /> + <DataGridTextColumn Header="GROUP" Binding="{Binding EventType.EventTypesGroup.Name}" /> + <DataGridTextColumn Header="EVENT" Binding="{Binding EventType.Name}" /> + <DataGridTemplateColumn Header="MESSAGE" Width="1*"> + <DataGridTemplateColumn.CellTemplate> + <DataTemplate> + <TextBlock Text="{Binding Description}" TextTrimming="CharacterEllipsis"></TextBlock> + </DataTemplate> + </DataGridTemplateColumn.CellTemplate> + </DataGridTemplateColumn> + <DataGridTemplateColumn Header="" Width="150"> + <DataGridTemplateColumn.CellTemplate> + <DataTemplate> + <ContentControl> + <ContentControl.Style> + <Style TargetType="ContentControl"> + <Setter Property="ContentTemplate" Value="{x:Null}"></Setter> + <Style.Triggers> + <DataTrigger Binding="{Binding Type}" Value="ApplicationStarted"> + <Setter Property="ContentTemplate"> + <Setter.Value> + <DataTemplate> + <Button Style="{StaticResource emptyButton}" Cursor="Hand" Foreground="White" Command="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=DataContext.DisplayTimelineCommand}" CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=ContentControl},Path=DataContext}"> + <StackPanel Orientation="Horizontal"> + <TextBlock Text="Display Timeline" VerticalAlignment="Center"></TextBlock> + <materialDesign:PackIcon VerticalAlignment="Center" Margin="5 0 0 0" Kind="ArrowRight" Width="16" Height="16" /> + </StackPanel> + </Button> + </DataTemplate> + </Setter.Value> + </Setter> + </DataTrigger> + </Style.Triggers> + </Style> + </ContentControl.Style> + </ContentControl> + </DataTemplate> + </DataGridTemplateColumn.CellTemplate> + </DataGridTemplateColumn> + </DataGrid.Columns> + </DataGrid> + </Grid> + </Grid> + </Grid> + </Grid> + </Grid> + </Grid> + </Grid> +</UserControl> diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Views/EventsView.xaml.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Views/EventsView.xaml.cs new file mode 100644 index 000000000..b17eea54c --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Views/EventsView.xaml.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace Tango.MachineStudio.Logging.Views +{ + /// <summary> + /// Interaction logic for EventsView.xaml + /// </summary> + public partial class EventsView : UserControl + { + public EventsView() + { + InitializeComponent(); + } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Views/MainView.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Views/MainView.xaml index 3d59ee88e..6d5f98b51 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Views/MainView.xaml +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Views/MainView.xaml @@ -8,153 +8,23 @@ xmlns:autoCompleteMachine="clr-namespace:Tango.MachineStudio.Common.AutoComplete;assembly=Tango.MachineStudio.Common" xmlns:converters="clr-namespace:Tango.SharedUI.Converters;assembly=Tango.SharedUI" xmlns:global="clr-namespace:Tango.MachineStudio.Logging" + xmlns:localConverters="clr-namespace:Tango.MachineStudio.Logging.Converters" xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" + xmlns:controls="clr-namespace:Tango.SharedUI.Controls;assembly=Tango.SharedUI" xmlns:vm="clr-namespace:Tango.MachineStudio.Logging.ViewModels" mc:Ignorable="d" d:DesignHeight="1080" d:DesignWidth="1920" d:DataContext="{d:DesignInstance Type=vm:MainViewVM, IsDesignTimeCreatable=False}" DataContext="{x:Static global:ViewModelLocator.MainViewVM}"> - <UserControl.Resources> - <autoCompleteMachine:MachinesProvider x:Key="MachinesProvider" /> - <converters:DateTimeUTCToShortDateTimeConverter x:Key="DateTimeUTCToShortDateTimeConverter" /> - </UserControl.Resources> - <Grid> - <Grid> - <Grid.RowDefinitions> - <RowDefinition Height="79"/> - <RowDefinition Height="1*"/> - </Grid.RowDefinitions> - - <Border Background="#F1F1F1"> - <Border.Effect> - <DropShadowEffect /> - </Border.Effect> - <Grid> - <StackPanel Orientation="Horizontal" Margin="10"> - <Image Source="../Images/machine-trans.png" RenderOptions.BitmapScalingMode="Fant"></Image> - <StackPanel Orientation="Horizontal" Width="300" Margin="20 0 0 5" VerticalAlignment="Bottom"> - <materialDesign:PackIcon Kind="BarcodeScan" VerticalAlignment="Center" Width="24" Height="24" /> - <autoComplete:AutoCompleteTextBox HorizontalContentAlignment="Stretch" Width="300" Margin="10 0 0 0" FontSize="16" Provider="{StaticResource MachinesProvider}" SelectedItem="{Binding SelectedMachine,Mode=TwoWay}" materialDesign:HintAssist.Hint="Serial Number / Name" DisplayMember="SerialNumber"> - <autoComplete:AutoCompleteTextBox.ItemTemplate> - <DataTemplate> - <Border Padding="5"> - <DockPanel LastChildFill="False" Width="250"> - <StackPanel Orientation="Horizontal" DockPanel.Dock="Left"> - <Image Source="/Images/machine-trans.png" Width="24" RenderOptions.BitmapScalingMode="Fant" /> - <TextBlock Margin="10 0 0 0" FontWeight="SemiBold" Text="{Binding SerialNumber}" VerticalAlignment="Center"></TextBlock> - </StackPanel> - <TextBlock DockPanel.Dock="Right" HorizontalAlignment="Right" Text="{Binding Name}" Foreground="Gray" VerticalAlignment="Center"></TextBlock> - </DockPanel> - </Border> - </DataTemplate> - </autoComplete:AutoCompleteTextBox.ItemTemplate> - </autoComplete:AutoCompleteTextBox> - </StackPanel> - - <materialDesign:PackIcon Kind="Calendar" Width="24" Height="24" VerticalAlignment="Bottom" Margin="20 0 0 5" /> - <ComboBox Margin="10 0 0 5" Width="200" VerticalAlignment="Bottom" FontSize="16" ItemsSource="{Binding Dates}" SelectedItem="{Binding SelectedDate}" DisplayMemberPath="Description"></ComboBox> - </StackPanel> - </Grid> - </Border> - - <Grid Grid.Row="1" Background="#B3FFFFFF"> - <Grid Margin="10"> - <Grid.ColumnDefinitions> - - <ColumnDefinition Width="1*"/> - </Grid.ColumnDefinitions> - - <Grid> - <DockPanel> - <Grid DockPanel.Dock="Top"> - <StackPanel Orientation="Horizontal"> - <materialDesign:PackIcon Kind="NoteText" Width="32" Height="32" /> - <TextBlock VerticalAlignment="Center" Margin="10 0 0 0" FontSize="16" FontWeight="SemiBold" FontStyle="Italic">MACHINE EVENTS</TextBlock> - </StackPanel> - </Grid> - - <Grid> - <DataGrid Background="Transparent" AutoGenerateColumns="False" SelectionMode="Single" ItemsSource="{Binding Events}" SelectedItem="{Binding SelectedEvent}" RowHeight="40" CanUserAddRows="False" CanUserDeleteRows="False" CanUserReorderColumns="True" IsReadOnly="True"> - <DataGrid.RowStyle> - <Style TargetType="DataGridRow" BasedOn="{StaticResource {x:Type DataGridRow}}"> - <Style.Triggers> - <Trigger Property="IsMouseOver" Value="True"> - <Setter Property="Background" Value="Transparent"></Setter> - <Setter Property="Foreground" Value="{StaticResource AccentColorBrush}" /> - <Setter Property="Cursor" Value="Hand"></Setter> - </Trigger> - <DataTrigger Binding="{Binding Type}" Value="ApplicationStarted"> - <Setter Property="Background" Value="{StaticResource AccentColorBrush}"></Setter> - <Setter Property="Foreground" Value="White" /> - <Setter Property="FontWeight" Value="SemiBold"></Setter> - <Setter Property="Cursor" Value="Arrow"></Setter> - <Setter Property="IsHitTestVisible" Value="False"></Setter> - </DataTrigger> - </Style.Triggers> - </Style> - </DataGrid.RowStyle> - <DataGrid.CellStyle> - <Style TargetType="DataGridCell" BasedOn="{StaticResource {x:Type DataGridCell}}"> - <Setter Property="BorderThickness" Value="0"/> - <Setter Property="FocusVisualStyle" Value="{x:Null}"/> - <Setter Property="VerticalContentAlignment" Value="Center"></Setter> - </Style> - </DataGrid.CellStyle> - <DataGrid.Columns> - <DataGridTemplateColumn Header="#"> - <DataGridTemplateColumn.CellTemplate> - <DataTemplate> - <materialDesign:PackIcon Width="16" Height="16"> - <materialDesign:PackIcon.Style> - <Style TargetType="materialDesign:PackIcon"> - <Setter Property="Kind" Value="Alert"></Setter> - <Style.Triggers> - <DataTrigger Binding="{Binding Category}" Value="Info"> - <Setter Property="Kind" Value="Information"></Setter> - <Setter Property="Foreground" Value="DimGray"></Setter> - </DataTrigger> - <DataTrigger Binding="{Binding Category}" Value="Warning"> - <Setter Property="Kind" Value="Alert"></Setter> - <Setter Property="Foreground" Value="#FFA300"></Setter> - </DataTrigger> - <DataTrigger Binding="{Binding Category}" Value="Error"> - <Setter Property="Kind" Value="AlertOctagon"></Setter> - <Setter Property="Foreground" Value="#FF5C5C"></Setter> - </DataTrigger> - <DataTrigger Binding="{Binding Category}" Value="Critical"> - <Setter Property="Kind" Value="BellPlus"></Setter> - <Setter Property="Foreground" Value="Red"></Setter> - </DataTrigger> - <DataTrigger Binding="{Binding Type}" Value="ApplicationStarted"> - <Setter Property="Kind" Value="ClockFast"></Setter> - <Setter Property="Foreground" Value="White"></Setter> - </DataTrigger> - </Style.Triggers> - </Style> - </materialDesign:PackIcon.Style> - </materialDesign:PackIcon> - </DataTemplate> - </DataGridTemplateColumn.CellTemplate> - </DataGridTemplateColumn> - <DataGridTextColumn Header="DATE TIME" Binding="{Binding DateTime,Converter={StaticResource DateTimeUTCToShortDateTimeConverter}}" /> - <DataGridTextColumn Header="HOST" Binding="{Binding HostName}" /> - <DataGridTextColumn Header="USER" Binding="{Binding User.Contact.FullName,Mode=OneTime}" /> - <DataGridTextColumn Header="GROUP" Binding="{Binding EventType.EventTypesGroup.Name}" /> - <DataGridTextColumn Header="EVENT" Binding="{Binding EventType.Name}" /> - <DataGridTemplateColumn Header="MESSAGE" Width="1*"> - <DataGridTemplateColumn.CellTemplate> - <DataTemplate> - <TextBlock Text="{Binding Description}" TextTrimming="CharacterEllipsis"></TextBlock> - </DataTemplate> - </DataGridTemplateColumn.CellTemplate> - </DataGridTemplateColumn> - </DataGrid.Columns> - </DataGrid> - </Grid> - </DockPanel> - </Grid> - </Grid> - </Grid> - </Grid> + <controls:MultiTransitionControl x:Name="TransitionControl" x:FieldModifier="internal" TransitionType="Slide"> + <controls:MultiTransitionControl.Controls> + <ContentControl Tag="EventsView"> + <local:EventsView/> + </ContentControl> + <ContentControl Tag="TimelineView"> + <local:TimelineWrapperView /> + </ContentControl> + </controls:MultiTransitionControl.Controls> + </controls:MultiTransitionControl> </Grid> </UserControl> diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Views/MainView.xaml.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Views/MainView.xaml.cs index 160767603..c8d232e86 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Views/MainView.xaml.cs +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Views/MainView.xaml.cs @@ -20,9 +20,12 @@ namespace Tango.MachineStudio.Logging.Views /// </summary> public partial class MainView : UserControl { + public static MainView Instance { get; private set; } + public MainView() { InitializeComponent(); + Instance = this; } } } diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Views/TimelineView.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Views/TimelineView.xaml new file mode 100644 index 000000000..504514cbb --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Views/TimelineView.xaml @@ -0,0 +1,187 @@ +<UserControl x:Class="Tango.MachineStudio.Logging.Views.TimelineView" + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:converters="clr-namespace:Tango.SharedUI.Converters;assembly=Tango.SharedUI" + xmlns:global="clr-namespace:Tango.MachineStudio.Logging" + xmlns:localConverters="clr-namespace:Tango.MachineStudio.Logging.Converters" + xmlns:entities="clr-namespace:Tango.BL.Entities;assembly=Tango.BL" + xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" + xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" + xmlns:vm="clr-namespace:Tango.MachineStudio.Logging.ViewModels" + xmlns:localControls="clr-namespace:Tango.MachineStudio.Logging.Controls" + xmlns:local="clr-namespace:Tango.MachineStudio.Logging.Views" + mc:Ignorable="d" + d:DesignHeight="1080" d:DesignWidth="1920" Background="White" d:DataContext="{d:DesignInstance Type=vm:TimelineViewVM, IsDesignTimeCreatable=False}" MouseWheel="UserControl_MouseWheel"> + + <UserControl.Resources> + <localConverters:TimeSpanToXConverter x:Key="TimeSpanToXConverter" /> + <localConverters:MachineEventToXConverter x:Key="MachineEventToXConverter" /> + <localConverters:SecondsToWidthConverter x:Key="SecondsToWidthConverter" /> + <converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" /> + + <LinearGradientBrush x:Key="infoBrush" StartPoint="0.5,0" EndPoint="0.5,1"> + <GradientStop Color="White"/> + <GradientStop Color="#FFBFBFBF" Offset="1"/> + </LinearGradientBrush> + + <LinearGradientBrush x:Key="warningBrush" StartPoint="0.5,0" EndPoint="0.5,1"> + <GradientStop Color="#FFFF8C57"/> + <GradientStop Color="White" Offset="1"/> + </LinearGradientBrush> + + <LinearGradientBrush x:Key="errorBrush" StartPoint="0.5,0" EndPoint="0.5,1"> + <GradientStop Color="#FFFF6A6A"/> + <GradientStop Color="#FFD9D9" Offset="1"/> + </LinearGradientBrush> + + <LinearGradientBrush x:Key="criticalBrush" StartPoint="0.5,0" EndPoint="0.5,1"> + <GradientStop Color="Red"/> + <GradientStop Color="White" Offset="1"/> + </LinearGradientBrush> + + <LinearGradientBrush x:Key="hoverBrush" StartPoint="0.5,0" EndPoint="0.5,1"> + <GradientStop Color="#9D9D9D"/> + <GradientStop Color="#F9F9F9" Offset="1"/> + </LinearGradientBrush> + </UserControl.Resources> + + <Grid> + <Grid> + <Grid Grid.Row="1"> + <Grid.RowDefinitions> + <RowDefinition Height="30"/> + <RowDefinition Height="1*"/> + </Grid.RowDefinitions> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="300"/> + <ColumnDefinition Width="1*"/> + </Grid.ColumnDefinitions> + + <Grid Grid.Column="1" ClipToBounds="True"> + <localControls:TimeRuler HorizontalAlignment="Left" FontSize="14" HorizontalOffset="{Binding ElementName=scrollViewer,Path=HorizontalOffset}" Background="White" BorderBrush="{StaticResource AccentColorBrush}" BorderThickness="1" Foreground="{StaticResource AccentColorBrush}" Height="30" x:Name="ruler" Width="{Binding RelativeSource={RelativeSource AncestorType=Grid},Path=ActualWidth}" RenderWidth="{Binding RelativeSource={RelativeSource AncestorType=Grid},Path=ActualWidth}" Zoom="{Binding TimelineScaleFactor}"></localControls:TimeRuler> + </Grid> + + <Grid Background="White"> + + </Grid> + + <ItemsControl ItemsSource="{Binding TimelineEventGroups}" Grid.Column="0" Grid.Row="1" Margin="0 0 0 0" Background="#FCFCFC" Height="{Binding ElementName=scrollViewer,Path=ViewportHeight}" VerticalAlignment="Top"> + <ItemsControl.ItemsPanel> + <ItemsPanelTemplate> + <UniformGrid Columns="1" /> + </ItemsPanelTemplate> + </ItemsControl.ItemsPanel> + <ItemsControl.ItemTemplate> + <DataTemplate DataType="{x:Type vm:TimelineEventGroup}"> + <Border BorderThickness="1 0.5 1 0.5" BorderBrush="{StaticResource AccentColorBrush}" Margin="2 0 0 0" Padding="5"> + + <TextBlock Text="{Binding Name}" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="22" TextWrapping="Wrap" TextAlignment="Center" FontWeight="SemiBold" Foreground="{StaticResource AccentColorBrush}"></TextBlock> + </Border> + </DataTemplate> + </ItemsControl.ItemTemplate> + </ItemsControl> + + <localControls:TimelineScrollViewer x:Name="scrollViewer" Grid.Column="1" Grid.Row="1" VerticalScrollBarVisibility="Disabled" HorizontalScrollBarVisibility="Auto"> + <Grid HorizontalAlignment="Left"> + <ItemsControl ItemsSource="{Binding TimelineEventGroups}" HorizontalAlignment="Left" MinWidth="{Binding RelativeSource={RelativeSource AncestorType=localControls:TimelineScrollViewer},Path=ActualWidth}"> + <ItemsControl.Width> + <MultiBinding Converter="{StaticResource TimeSpanToXConverter}" ConverterParameter="300"> + <Binding Path="TimelineMaxTime" /> + <Binding Path="TimelineScaleFactor" /> + </MultiBinding> + </ItemsControl.Width> + <ItemsControl.ItemsPanel> + <ItemsPanelTemplate> + <UniformGrid Columns="1" /> + </ItemsPanelTemplate> + </ItemsControl.ItemsPanel> + <ItemsControl.ItemTemplate> + <DataTemplate DataType="{x:Type vm:TimelineEventGroup}"> + <Border BorderThickness="0 0 0 1" BorderBrush="#98DEFF" Margin="0 0 0 0"> + <ItemsControl ItemsSource="{Binding Events}"> + <ItemsControl.ItemsPanel> + <ItemsPanelTemplate> + <UniformGrid IsItemsHost="True" Columns="1"></UniformGrid> + </ItemsPanelTemplate> + </ItemsControl.ItemsPanel> + <ItemsControl.ItemTemplate> + <DataTemplate DataType="{x:Type entities:MachinesEvent}"> + <Canvas Margin="0 5 0 5" MinHeight="20"> + <Grid Height="{Binding RelativeSource={RelativeSource AncestorType=Canvas},Path=ActualHeight}"> + <Canvas.Left> + <MultiBinding Converter="{StaticResource MachineEventToXConverter}"> + <Binding Path="." /> + <Binding RelativeSource="{RelativeSource AncestorType=UserControl}" Path="DataContext.TimelineEventGroups" /> + <Binding RelativeSource="{RelativeSource AncestorType=UserControl}" Path="DataContext.TimelineScaleFactor" /> + </MultiBinding> + </Canvas.Left> + <Border BorderBrush="#4E4E4E" BorderThickness="1" Padding="2" MinWidth="50" Cursor="Hand"> + <i:Interaction.Triggers> + <i:EventTrigger EventName="PreviewMouseUp"> + <i:InvokeCommandAction Command="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=DataContext.EventSelectedCommand}" CommandParameter="{Binding}" /> + </i:EventTrigger> + </i:Interaction.Triggers> + <Border.Style> + <Style TargetType="Border"> + <Style.Triggers> + <DataTrigger Binding="{Binding Category}" Value="Info"> + <Setter Property="Background" Value="{StaticResource infoBrush}"></Setter> + </DataTrigger> + <DataTrigger Binding="{Binding Category}" Value="Warning"> + <Setter Property="Background" Value="{StaticResource warningBrush}"></Setter> + </DataTrigger> + <DataTrigger Binding="{Binding Category}" Value="Error"> + <Setter Property="Background" Value="{StaticResource errorBrush}"></Setter> + </DataTrigger> + <DataTrigger Binding="{Binding Category}" Value="Crtitical"> + <Setter Property="Background" Value="{StaticResource criticalBrush}"></Setter> + </DataTrigger> + <Trigger Property="IsMouseOver" Value="True"> + <Setter Property="Opacity" Value="0.7"></Setter> + </Trigger> + </Style.Triggers> + </Style> + </Border.Style> + <StackPanel Orientation="Horizontal"> + <TextBlock FontWeight="SemiBold" Text="{Binding EventType.Name}" Height="14" FontSize="11"></TextBlock> + <TextBlock Margin="10 0 0 0" Text="{Binding Description}" Height="14" FontSize="11"></TextBlock> + </StackPanel> + </Border> + </Grid> + </Canvas> + </DataTemplate> + </ItemsControl.ItemTemplate> + </ItemsControl> + </Border> + </DataTemplate> + </ItemsControl.ItemTemplate> + </ItemsControl> + + <Canvas Visibility="{Binding EnableTimeMarker,Converter={StaticResource BooleanToVisibilityConverter}}" MinWidth="{Binding RelativeSource={RelativeSource AncestorType=localControls:TimelineScrollViewer},Path=ActualWidth}" ClipToBounds="False" IsHitTestVisible="False"> + <Grid Height="{Binding RelativeSource={RelativeSource AncestorType=Canvas},Path=ActualHeight}" ClipToBounds="False"> + <Canvas.Left> + <MultiBinding Converter="{StaticResource TimeSpanToXConverter}"> + <Binding Path="CurrentPosition" /> + <Binding Path="TimelineScaleFactor" /> + </MultiBinding> + </Canvas.Left> + + <Rectangle Stroke="DodgerBlue" StrokeThickness="1" HorizontalAlignment="Left" VerticalAlignment="Stretch" /> + <Polygon Fill="DodgerBlue" Points="0,0 16,0 8,15 0,0" Margin="-8 -5 0 0" VerticalAlignment="Top" /> + </Grid> + </Canvas> + </Grid> + </localControls:TimelineScrollViewer> + + <Border Grid.Row="1" Grid.Column="1" HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="20" Padding="10" Background="#7ECECECE" CornerRadius="5"> + <Grid> + <materialDesign:PackIcon Kind="MagnifyPlus" Margin="0 -35 0 0" Width="20" Height="20" Foreground="Gray" /> + <Slider Minimum="0.5" Maximum="100" Value="{Binding TimelineScaleFactor}" Orientation="Vertical" Height="120"/> + </Grid> + </Border> + </Grid> + </Grid> + </Grid> +</UserControl> diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Views/TimelineView.xaml.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Views/TimelineView.xaml.cs new file mode 100644 index 000000000..e1c09e49f --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Views/TimelineView.xaml.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; +using Tango.MachineStudio.Logging.ViewModels; + +namespace Tango.MachineStudio.Logging.Views +{ + /// <summary> + /// Interaction logic for TimelineView.xaml + /// </summary> + public partial class TimelineView : UserControl + { + private TimelineViewVM _vm; + + public TimelineView() + { + InitializeComponent(); + this.Loaded += (_, __) => _vm = DataContext as TimelineViewVM; + } + + private void UserControl_MouseWheel(object sender, MouseWheelEventArgs e) + { + if (e.Delta > 0) + { + _vm.TimelineScaleFactor += 0.5; + } + else + { + _vm.TimelineScaleFactor -= 0.5; + } + } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Views/TimelineWrapperView.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Views/TimelineWrapperView.xaml new file mode 100644 index 000000000..abab55264 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Views/TimelineWrapperView.xaml @@ -0,0 +1,33 @@ +<UserControl x:Class="Tango.MachineStudio.Logging.Views.TimelineWrapperView" + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:global="clr-namespace:Tango.MachineStudio.Logging" + xmlns:vm="clr-namespace:Tango.MachineStudio.Logging.ViewModels" + xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" + xmlns:local="clr-namespace:Tango.MachineStudio.Logging.Views" + mc:Ignorable="d" + d:DesignHeight="1080" d:DesignWidth="1920" d:DataContext="{d:DesignInstance Type=vm:MainViewVM, IsDesignTimeCreatable=False}" DataContext="{x:Static global:ViewModelLocator.MainViewVM}"> + <Grid> + <Grid.RowDefinitions> + <RowDefinition Height="70"/> + <RowDefinition Height="1*"/> + </Grid.RowDefinitions> + + <Grid> + <StackPanel Orientation="Horizontal" Margin="10"> + <Button MinWidth="160" Height="50" Style="{StaticResource MaterialDesignFlatButton}" Command="{Binding NavigateToEventsCommand}" HorizontalContentAlignment="Left"> + <StackPanel Orientation="Horizontal" > + <materialDesign:PackIcon Kind="KeyboardBackspace" Width="20" Height="20" /> + <TextBlock Margin="5 0 0 0" FontSize="16">BACK</TextBlock> + </StackPanel> + </Button> + </StackPanel> + </Grid> + + <Grid Grid.Row="1"> + <local:TimelineView DataContext="{Binding TimelineViewVM}" /> + </Grid> + </Grid> +</UserControl> diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Views/TimelineWrapperView.xaml.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Views/TimelineWrapperView.xaml.cs new file mode 100644 index 000000000..1ca2c30cb --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Views/TimelineWrapperView.xaml.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace Tango.MachineStudio.Logging.Views +{ + /// <summary> + /// Interaction logic for TimelineWrapperView.xaml + /// </summary> + public partial class TimelineWrapperView : UserControl + { + public TimelineWrapperView() + { + InitializeComponent(); + } + } +} |
