aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/PPC/Modules/Tango.PPC.MachineSettings/MachineSettingsModuleSettings.cs
blob: 869ecc5d6833f38f276800c200c6dd424d92915f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Tango.Settings;

namespace Tango.PPC.MachineSettings
{
    public class MachineSettingsModuleSettings : SettingsBase
    {

    }
}
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Threading;
using Tango.SharedUI.Helpers;

namespace Tango.SharedUI.Controls
{
    [ContentProperty(nameof(Elements))]
    public class NavigationControl : UserControl
    {
        private Action _onCompleted;

        #region Transition Types

        public enum TransitionTypes
        {
            Fade,
            Zoom,
            Slide,
        }

        #endregion

        #region Navigation Element

        private class NavigationElement : ContentControl
        {
            public FrameworkElement Element
            {
                get { return (FrameworkElement)GetValue(ElementProperty); }
                set { SetValue(ElementProperty, value); }
            }
            public static readonly DependencyProperty ElementProperty =
                DependencyProperty.Register("Element", typeof(FrameworkElement), typeof(NavigationControl), new PropertyMetadata(null));

            public ScaleTransform Scale
            {
                get { return (ScaleTransform)GetValue(ScaleProperty); }
                set { SetValue(ScaleProperty, value); }
            }
            public static readonly DependencyProperty ScaleProperty =
                DependencyProperty.Register("Scale", typeof(ScaleTransform), typeof(NavigationControl), new PropertyMetadata(null));

            public RotateTransform Rotate
            {
                get { return (RotateTransform)GetValue(RotateProperty); }
                set { SetValue(RotateProperty, value); }
            }
            public static readonly DependencyProperty RotateProperty =
                DependencyProperty.Register("Rotate", typeof(RotateTransform), typeof(NavigationControl), new PropertyMetadata(null));

            public TranslateTransform Translate
            {
                get { return (TranslateTransform)GetValue(TranslateProperty); }
                set { SetValue(TranslateProperty, value); }
            }
            public static readonly DependencyProperty TranslateProperty =
                DependencyProperty.Register("Translate", typeof(TranslateTransform), typeof(NavigationControl), new PropertyMetadata(null));

            public NavigationElement()
            {
                Visibility = Visibility.Hidden;

                Scale = new ScaleTransform(1, 1);
                Rotate = new RotateTransform(0);
                Translate = new TranslateTransform(0, 0);

                TransformGroup group = new TransformGroup();
                group.Children.Add(Scale);
                group.Children.Add(Rotate);
                group.Children.Add(Translate);

                RenderTransformOrigin = new Point(0.5, 0.5);
                RenderTransform = group;
            }

            public NavigationElement(FrameworkElement element) : this()
            {
                Element = element;
            }

            public void AnimateScale(DoubleAnimation animation)
            {
                Scale.BeginAnimation(ScaleTransform.ScaleXProperty, animation);
                Scale.BeginAnimation(ScaleTransform.ScaleYProperty, animation);
            }

            public void AnimateTranslateX(DoubleAnimation animation)
            {
                Translate.BeginAnimation(TranslateTransform.XProperty, animation);
            }

            public void AnimateOpacity(DoubleAnimation animation)
            {
                BeginAnimation(OpacityProperty, animation);
            }

            public void Reset()
            {
                Scale.BeginAnimation(ScaleTransform.ScaleXProperty, null);
                Scale.BeginAnimation(ScaleTransform.ScaleYProperty, null);
                Rotate.BeginAnimation(RotateTransform.AngleProperty, null);
                Translate.BeginAnimation(TranslateTransform.XProperty, null);
                Translate.BeginAnimation(TranslateTransform.YProperty, null);
                Opacity = 1;
            }

            public void Activate()
            {
                if (Content != Element)
                {
                    Content = Element;
                }

                Visibility = Visibility.Visible;
            }

            public void Deactivate(bool detach)
            {
                if (detach)
                {
                    Content = null;
                }

                Visibility = Visibility.Hidden;
            }
        }

        #endregion

        #region INavigationView

        public interface INavigationView
        {
            void OnNavigatedTo();
            void OnNavigatedFrom();
        }

        #endregion

        #region INavigationViewModel

        /// <summary>
        /// Represents a view data context which can be notified when its view is being navigated in or out.
        /// </summary>
        public interface INavigationViewModel
        {
            /// <summary>
            /// Called when the navigation system has navigated to this VM view.
            /// </summary>
            void OnNavigatedTo();

            /// <summary>
            /// Called when the navigation system has navigated from this VM view.
            /// </summary>
            void OnNavigatedFrom();
        }

        #endregion

        private Grid _grid;
        private bool _loaded;

        #region Properties

        public ObservableCollection<FrameworkElement> Elements
        {
            get { return (ObservableCollection<FrameworkElement>)GetValue(ElementsProperty); }
            set { SetValue(ElementsProperty, value); }
        }
        public static readonly DependencyProperty ElementsProperty =
            DependencyProperty.Register("Elements", typeof(ObservableCollection<FrameworkElement>), typeof(NavigationControl), new PropertyMetadata(null, (d, e) => (d as NavigationControl).OnElementsChanged()));

        public FrameworkElement SelectedElement
        {
            get { return (FrameworkElement)GetValue(SelectedElementProperty); }
            set { SetValue(SelectedElementProperty, value); }
        }
        public static readonly DependencyProperty SelectedElementProperty =
            DependencyProperty.Register("SelectedElement", typeof(FrameworkElement), typeof(NavigationControl), new PropertyMetadata(null, (d, e) => (d as NavigationControl).OnSelectedElementChanged(e.OldValue as FrameworkElement, e.NewValue as FrameworkElement)));

        public TransitionTypes TransitionType
        {
            get { return (TransitionTypes)GetValue(TransitionTypeProperty); }
            set { SetValue(TransitionTypeProperty, value); }
        }
        public static readonly DependencyProperty TransitionTypeProperty =
            DependencyProperty.Register("TransitionType", typeof(TransitionTypes), typeof(NavigationControl), new PropertyMetadata(TransitionTypes.Zoom));

        public bool TransitionAlwaysFades
        {
            get { return (bool)GetValue(TransitionAlwaysFadesProperty); }
            set { SetValue(TransitionAlwaysFadesProperty, value); }
        }
        public static readonly DependencyProperty TransitionAlwaysFadesProperty =
            DependencyProperty.Register("TransitionAlwaysFades", typeof(bool), typeof(NavigationControl), new PropertyMetadata(false));

        public Duration TransitionDuration
        {
            get { return (Duration)GetValue(TransitionDurationProperty); }
            set { SetValue(TransitionDurationProperty, value); }
        }
        public static readonly DependencyProperty TransitionDurationProperty =
            DependencyProperty.Register("TransitionDuration", typeof(Duration), typeof(NavigationControl), new PropertyMetadata(new Duration(TimeSpan.FromSeconds(0.5))));

        public bool KeepElementsAttached
        {
            get { return (bool)GetValue(KeepElementsAttachedProperty); }
            set { SetValue(KeepElementsAttachedProperty, value); }
        }
        public static readonly DependencyProperty KeepElementsAttachedProperty =
            DependencyProperty.Register("KeepElementsAttached", typeof(bool), typeof(NavigationControl), new PropertyMetadata(false));



        public int SelectedIndex
        {
            get { return (int)GetValue(SelectedIndexProperty); }
            set { SetValue(SelectedIndexProperty, value); }
        }

        // Using a DependencyProperty as the backing store for SelectedIndex.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty SelectedIndexProperty =
            DependencyProperty.Register("SelectedIndex", typeof(int), typeof(NavigationControl), new PropertyMetadata(0, (d, e) => (d as NavigationControl).OnSelectedIndexChanged()));

        private void OnSelectedIndexChanged()
        {
            SelectedElement = Elements[SelectedIndex > Elements.Count - 1 ? 0 : SelectedIndex];
        }

        #endregion

        #region Attached Properties

        #region NavigationName

        /// <summary>
        /// Determines the element navigation name.
        /// </summary>
        public static readonly DependencyProperty NavigationName =
            DependencyProperty.RegisterAttached("NavigationName",
            typeof(String), typeof(NavigationControl),
            new FrameworkPropertyMetadata(""));

        /// <summary>
        /// Sets the name of the navigation.
        /// </summary>
        /// <param name="element">The element.</param>
        /// <param name="value">The value.</param>
        public static void SetNavigationName(FrameworkElement element, String value)
        {
            element.SetValue(NavigationName, value);
        }

        /// <summary>
        /// Gets the name of the navigation.
        /// </summary>
        /// <param name="element">The element.</param>
        /// <returns></returns>
        public static String GetNavigationName(FrameworkElement element)
        {
            return element.GetValue(NavigationName).ToStringSafe();
        }

        #endregion

        #endregion

        #region Constructors

        public NavigationControl()
        {
            ClipToBounds = true;
            _grid = new Grid();
            Content = _grid;
            Elements = new ObservableCollection<FrameworkElement>();
            Loaded += NavigationControl_Loaded;
        }

        #endregion

        #region Event Handlers

        private void NavigationControl_Loaded(object sender, RoutedEventArgs e)
        {
            if (!_loaded)
            {
                if (Elements != null)
                {
                    SelectedElement = Elements.FirstOrDefault();
                }

                _loaded = true;
            }
        }

        private void Elements_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            SyncElements();
        }

        #endregion

        #region Private Methods

        private void OnElementsChanged()
        {
            if (Elements != null)
            {
                Elements.CollectionChanged -= Elements_CollectionChanged;
                Elements.CollectionChanged += Elements_CollectionChanged;
            }

            SyncElements();
        }

        private void SyncElements()
        {
            if (Elements == null)
            {
                _grid.Children.Clear();
            }
            else
            {
                var toRemove = _grid.Children.OfType<NavigationElement>().ToList().Where(x => !Elements.Contains(x.Element)).ToList();
                var toAdd = Elements.Where(x => !_grid.Children.OfType<NavigationElement>().Select(y => y.Element).ToList().Contains(x)).ToList();

                toRemove.ForEach(x => _grid.Children.Remove(x));
                toAdd.ForEach(x => _grid.Children.Add(
                    new NavigationElement()
                    {
                        RenderTransformOrigin = new Point(0.5, 0.5),
                        Element = x,
                        Content = KeepElementsAttached ? x : null,
                    }));
            }

            if (!Elements.Contains(SelectedElement))
            {
                SelectedElement = null;
            }
        }

        private NavigationElement GetElementContainer(FrameworkElement element)
        {
            return _grid.Children.OfType<NavigationElement>().ToList().SingleOrDefault(x => x.Element == element);
        }

        private void Navigate(NavigationElement fromElement, NavigationElement toElement)
        {
            if (toElement == null || toElement == fromElement)
            {
                _onCompleted?.Invoke();
            }

            if (fromElement != null)
            {
                DoubleAnimation toAnimation = new DoubleAnimation();
                toAnimation.Duration = TransitionDuration;

                DoubleAnimation fromAnimation = new DoubleAnimation();
                fromAnimation.Duration = TransitionDuration;

                int fromIndex = Elements.IndexOf(fromElement.Element);
                int toIndex = Elements.IndexOf(toElement.Element);

                fromElement.Reset();
                toElement.Reset();

                fromAnimation.Completed += (_, __) =>
                {
                    fromElement.Deactivate(!KeepElementsAttached);
                };

                bool completed = false;

                toAnimation.Completed += (_, __) =>
                {
                    if (!completed)
                    {
                        completed = true;

                        INavigationView fromNavigationView = fromElement.Element as INavigationView;
                        INavigationView toNavigationView = toElement.Element as INavigationView;

                        if (fromNavigationView != null)
                        {
                            fromNavigationView.OnNavigatedFrom();
                        }
                        if (toNavigationView != null)
                        {
                            toNavigationView.OnNavigatedTo();
                        }

                        INavigationViewModel fromVM = fromElement.Element.DataContext as INavigationViewModel;
                        INavigationViewModel toVM = toElement.Element.DataContext as INavigationViewModel;

                        if (fromVM != null && fromVM != toVM) fromVM.OnNavigatedFrom();
                        if (toVM != null) toVM.OnNavigatedTo();

                        _onCompleted?.Invoke();
                    }
                };

                switch (TransitionType)
                {
                    case TransitionTypes.Fade:
                        fromAnimation.From = 1;
                        fromAnimation.To = 0;

                        toAnimation.From = 0;
                        toAnimation.To = 1;

                        fromElement.AnimateOpacity(fromAnimation);
                        toElement.AnimateOpacity(toAnimation);

                        break;
                    case TransitionTypes.Zoom:
                        fromAnimation.From = 1;
                        fromAnimation.To = 0;

                        toAnimation.From = 0;
                        toAnimation.To = 1;

                        fromElement.AnimateScale(fromAnimation);
                        toElement.AnimateScale(toAnimation);

                        break;
                    case TransitionTypes.Slide:

                        if (toIndex > fromIndex)
                        {
                            fromAnimation.From = 0;
                            fromAnimation.To = -ActualWidth;

                            toAnimation.From = ActualWidth;
                            toAnimation.To = 0;
                        }
                        else
                        {
                            fromAnimation.From = 0;
                            fromAnimation.To = ActualWidth;

                            toAnimation.From = -ActualWidth;
                            toAnimation.To = 0;
                        }

                        fromElement.AnimateTranslateX(fromAnimation);
                        toElement.AnimateTranslateX(toAnimation);

                        break;
                }

                if (TransitionAlwaysFades && TransitionType != TransitionTypes.Fade)
                {
                    DoubleAnimation fromFadeAnimation = new DoubleAnimation();
                    fromFadeAnimation.From = 1;
                    fromFadeAnimation.To = 0;
                    fromFadeAnimation.Duration = TransitionDuration;

                    DoubleAnimation toFadeAnimation = new DoubleAnimation();
                    toFadeAnimation.From = 0;
                    toFadeAnimation.To = 1;
                    toFadeAnimation.Duration = TransitionDuration;

                    fromElement.AnimateOpacity(fromFadeAnimation);
                    toElement.AnimateOpacity(toFadeAnimation);
                }

                fromElement.Activate();
                toElement.Activate();
            }
            else
            {
                toElement.Activate();
                toElement.Reset();

                INavigationViewModel toVM = toElement.Element.DataContext as INavigationViewModel;
                if (toVM != null) toVM.OnNavigatedTo();
            }
        }

        #endregion

        #region Properties Changes

        protected virtual void OnSelectedElementChanged(FrameworkElement fromElement, FrameworkElement toElement)
        {
            Navigate(GetElementContainer(fromElement), GetElementContainer(toElement));
        }

        #endregion

        #region Public Methods

        public void NavigateTo(FrameworkElement element)
        {
            var e = Elements.SingleOrDefault(x => x == element);

            if (e != null)
            {
                SelectedElement = element;
            }
        }

        public FrameworkElement NavigateTo(String navigationName)
        {
            return NavigateTo(navigationName, null);
        }

        public FrameworkElement NavigateTo(String navigationName, Action onCompleted = null)
        {
            _onCompleted = onCompleted;

            var element = Elements.SingleOrDefault(x => GetNavigationName(x) == navigationName || x.GetType().Name == navigationName);

            if (element != null)
            {
                if (SelectedElement == element)
                {
                    _onCompleted?.Invoke();
                }
                else
                {
                    SelectedElement = element;
                }
            }

            return element;
        }

        public FrameworkElement GetElement(String navigationName)
        {
            return Elements.SingleOrDefault(x => GetNavigationName(x) == navigationName || x.GetType().Name == navigationName);
        }

        public FrameworkElement GetAndDetach(String navigationName)
        {
            var element = Elements.SingleOrDefault(x => GetNavigationName(x) == navigationName);
            GetElementContainer(element).Deactivate(!KeepElementsAttached);
            return element;
        }

        #endregion
    }
}