122 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			C#
		
	
	
	
		
		
			
		
	
	
			122 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			C#
		
	
	
	
| 
								 | 
							
								using System;
							 | 
						|||
| 
								 | 
							
								using System.Collections.Generic;
							 | 
						|||
| 
								 | 
							
								using System.Reactive.Concurrency;
							 | 
						|||
| 
								 | 
							
								using System.Reactive.Linq;
							 | 
						|||
| 
								 | 
							
								using System.Reactive.Subjects;
							 | 
						|||
| 
								 | 
							
								using System.Windows;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								namespace DM_Weight.util.TabTip
							 | 
						|||
| 
								 | 
							
								{
							 | 
						|||
| 
								 | 
							
								    public static class TabTipAutomation
							 | 
						|||
| 
								 | 
							
								    {
							 | 
						|||
| 
								 | 
							
								        static TabTipAutomation()
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            if (EnvironmentEx.GetOSVersion() == OSVersion.Win7)
							 | 
						|||
| 
								 | 
							
								                return;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            TabTip.Closed += () => TabTipClosedSubject.OnNext(true);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            AutomateTabTipOpen(FocusSubject.AsObservable());
							 | 
						|||
| 
								 | 
							
								            AutomateTabTipClose(FocusSubject.AsObservable(), TabTipClosedSubject);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            AnimationHelper.ExceptionCatched += exception => ExceptionCatched?.Invoke(exception);
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        private static readonly Subject<Tuple<UIElement, bool>> FocusSubject = new Subject<Tuple<UIElement, bool>>();
							 | 
						|||
| 
								 | 
							
								        private static readonly Subject<bool> TabTipClosedSubject = new Subject<bool>();
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        private static readonly List<Type> BindedUIElements = new List<Type>();
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        /// <summary>
							 | 
						|||
| 
								 | 
							
								        /// By default TabTip automation happens only when no keyboard is connected to device.
							 | 
						|||
| 
								 | 
							
								        /// Change IgnoreHardwareKeyboard if you want to automate
							 | 
						|||
| 
								 | 
							
								        /// TabTip even if keyboard is connected.
							 | 
						|||
| 
								 | 
							
								        /// </summary>
							 | 
						|||
| 
								 | 
							
								        public static HardwareKeyboardIgnoreOptions IgnoreHardwareKeyboard
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            get { return HardwareKeyboard.IgnoreOptions; }
							 | 
						|||
| 
								 | 
							
								            set { HardwareKeyboard.IgnoreOptions = value; } 
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								      
							 | 
						|||
| 
								 | 
							
								        /// <summary>
							 | 
						|||
| 
								 | 
							
								        /// Subscribe to this event if you want to know about exceptions (errors) in this library
							 | 
						|||
| 
								 | 
							
								        /// </summary>
							 | 
						|||
| 
								 | 
							
								        public static event Action<Exception> ExceptionCatched;
							 | 
						|||
| 
								 | 
							
								      
							 | 
						|||
| 
								 | 
							
								        /// <summary>
							 | 
						|||
| 
								 | 
							
								        /// Description of keyboards to ignore if there is only one instance of given keyboard.
							 | 
						|||
| 
								 | 
							
								        /// If you want to ignore some ghost keyboard, add it's description to this list
							 | 
						|||
| 
								 | 
							
								        /// </summary>
							 | 
						|||
| 
								 | 
							
								        public static List<string> ListOfHardwareKeyboardsToIgnoreIfSingleInstance => HardwareKeyboard.ListOfKeyboardsToIgnore;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        /// <summary>
							 | 
						|||
| 
								 | 
							
								        /// Description of keyboards to ignore.
							 | 
						|||
| 
								 | 
							
								        /// If you want to ignore some ghost keyboard, add it's description to this list
							 | 
						|||
| 
								 | 
							
								        /// </summary>
							 | 
						|||
| 
								 | 
							
								        public static List<string> ListOfKeyboardsToIgnore => HardwareKeyboard.ListOfKeyboardsToIgnore;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        private static void AutomateTabTipClose(IObservable<Tuple<UIElement, bool>> focusObservable, Subject<bool> tabTipClosedSubject)
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            focusObservable
							 | 
						|||
| 
								 | 
							
								                .ObserveOn(Scheduler.Default)
							 | 
						|||
| 
								 | 
							
								                .Where(_ => IgnoreHardwareKeyboard == HardwareKeyboardIgnoreOptions.IgnoreAll || !HardwareKeyboard.IsConnectedAsync().Result)
							 | 
						|||
| 
								 | 
							
								                .Throttle(TimeSpan.FromMilliseconds(100)) // Close only if no other UIElement got focus in 100 ms
							 | 
						|||
| 
								 | 
							
								                .Where(tuple => tuple.Item2 == false)
							 | 
						|||
| 
								 | 
							
								                .Do(_ => TabTip.Close())
							 | 
						|||
| 
								 | 
							
								                .Subscribe(_ => tabTipClosedSubject.OnNext(true));
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            tabTipClosedSubject
							 | 
						|||
| 
								 | 
							
								                .Subscribe(_ => AnimationHelper.GetEverythingInToWorkAreaWithTabTipClosed());
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        private static void AutomateTabTipOpen(IObservable<Tuple<UIElement, bool>> focusObservable)
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            focusObservable
							 | 
						|||
| 
								 | 
							
								                .ObserveOn(Scheduler.Default)
							 | 
						|||
| 
								 | 
							
								                .Where(_ => IgnoreHardwareKeyboard == HardwareKeyboardIgnoreOptions.IgnoreAll || !HardwareKeyboard.IsConnectedAsync().Result)
							 | 
						|||
| 
								 | 
							
								                .Where(tuple => tuple.Item2 == true)
							 | 
						|||
| 
								 | 
							
								                .Do(_ => TabTip.OpenUndockedAndStartPoolingForClosedEvent())
							 | 
						|||
| 
								 | 
							
								                .Subscribe(tuple => AnimationHelper.GetUIElementInToWorkAreaWithTabTipOpened(tuple.Item1));
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        /// <summary>
							 | 
						|||
| 
								 | 
							
								        /// Automate TabTip for given UIElement.
							 | 
						|||
| 
								 | 
							
								        /// Keyboard opens on GotFocusEvent or TouchDownEvent (if focused already) 
							 | 
						|||
| 
								 | 
							
								        /// and closes on LostFocusEvent.
							 | 
						|||
| 
								 | 
							
								        /// </summary>
							 | 
						|||
| 
								 | 
							
								        /// <typeparam name="T"></typeparam>
							 | 
						|||
| 
								 | 
							
								        public static void BindTo<T>() where T : UIElement
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            if (EnvironmentEx.GetOSVersion() == OSVersion.Win7)
							 | 
						|||
| 
								 | 
							
								                return;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            if (BindedUIElements.Contains(typeof(T)))
							 | 
						|||
| 
								 | 
							
								                return;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            EventManager.RegisterClassHandler(
							 | 
						|||
| 
								 | 
							
								                classType: typeof(T),
							 | 
						|||
| 
								 | 
							
								                routedEvent: UIElement.TouchDownEvent,
							 | 
						|||
| 
								 | 
							
								                handler: new RoutedEventHandler((s, e) =>
							 | 
						|||
| 
								 | 
							
								                {
							 | 
						|||
| 
								 | 
							
								                    if (((UIElement)s).IsFocused)
							 | 
						|||
| 
								 | 
							
								                        FocusSubject.OnNext(new Tuple<UIElement, bool>((UIElement)s, true));
							 | 
						|||
| 
								 | 
							
								                }),
							 | 
						|||
| 
								 | 
							
								                handledEventsToo: true);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            EventManager.RegisterClassHandler(
							 | 
						|||
| 
								 | 
							
								                classType: typeof(T), 
							 | 
						|||
| 
								 | 
							
								                routedEvent: UIElement.GotFocusEvent, 
							 | 
						|||
| 
								 | 
							
								                handler: new RoutedEventHandler((s, e) => FocusSubject.OnNext(new Tuple<UIElement, bool>((UIElement) s, true))), 
							 | 
						|||
| 
								 | 
							
								                handledEventsToo: true);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            EventManager.RegisterClassHandler(
							 | 
						|||
| 
								 | 
							
								                classType: typeof(T), 
							 | 
						|||
| 
								 | 
							
								                routedEvent: UIElement.LostFocusEvent, 
							 | 
						|||
| 
								 | 
							
								                handler: new RoutedEventHandler((s, e) => FocusSubject.OnNext(new Tuple<UIElement, bool>((UIElement) s, false))), 
							 | 
						|||
| 
								 | 
							
								                handledEventsToo: true);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            BindedUIElements.Add(typeof(T));
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								    }
							 | 
						|||
| 
								 | 
							
								}
							 |