Example #1
0
        public OverlayAuraModelBase(
            [NotNull] ISharedContext sharedContext,
            [NotNull] IAuraRepository repository,
            [NotNull] IConfigSerializer configSerializer,
            [NotNull] IUniqueIdGenerator idGenerator,
            [NotNull] IFactory <IEyeOverlayViewModel, IOverlayWindowController, IAuraModelController> overlayViewModelFactory,
            [NotNull] IFactory <IOverlayWindowController, IWindowTracker> overlayWindowControllerFactory,
            [NotNull] IFactory <WindowTracker, IStringMatcher> windowTrackerFactory,
            [NotNull][Dependency(WellKnownSchedulers.UI)] IScheduler uiScheduler,
            [NotNull][Dependency(WellKnownSchedulers.Background)] IScheduler bgScheduler)
        {
            defaultAuraName = $"Aura #{Interlocked.Increment(ref GlobalAuraIdx)}";
            Name            = defaultAuraName;
            Id           = idGenerator.Next();
            using var sw = new BenchmarkTimer($"[{Name}({Id})] OverlayAuraModel initialization", Log, nameof(OverlayAuraModelBase));

            var auraTriggers = new ComplexAuraTrigger();

            Triggers = auraTriggers.Triggers;

            var auraActions = new ComplexAuraAction();

            OnEnterActions = auraActions.Actions;

            this.repository       = repository;
            this.configSerializer = configSerializer;
            var matcher       = new RegexStringMatcher().AddToWhitelist(".*");
            var windowTracker = windowTrackerFactory
                                .Create(matcher)
                                .AddTo(Anchors);

            var overlayController = overlayWindowControllerFactory
                                    .Create(windowTracker)
                                    .AddTo(Anchors);

            sw.Step($"Overlay controller created: {overlayController}");

            var overlayViewModel = overlayViewModelFactory
                                   .Create(overlayController, this)
                                   .AddTo(Anchors);

            sw.Step($"Overlay view model created: {overlayViewModel}");

            Overlay = overlayViewModel;
            Observable.Merge(
                overlayViewModel.WhenValueChanged(x => x.AttachedWindow, false).ToUnit(),
                overlayViewModel.WhenValueChanged(x => x.IsLocked, false).ToUnit(),
                this.WhenValueChanged(x => x.IsActive, false).ToUnit())
            .StartWithDefault()
            .Select(
                () => new
            {
                OverlayShouldBeShown = IsActive || !overlayViewModel.IsLocked,
                WindowIsAttached     = overlayViewModel.AttachedWindow != null
            })
            .Subscribe(x => overlayController.IsEnabled = x.OverlayShouldBeShown && x.WindowIsAttached)
            .AddTo(Anchors);
            sw.Step($"Overlay view model initialized: {overlayViewModel}");

            Observable.CombineLatest(
                auraTriggers.WhenAnyValue(x => x.IsActive),
                sharedContext.SystemTrigger.WhenValueChanged(x => x.IsActive))
            .DistinctUntilChanged()
            .Subscribe(x => IsActive = x.All(isActive => isActive), Log.HandleException)
            .AddTo(Anchors);

            auraTriggers.WhenAnyValue(x => x.IsActive)
            .WithPrevious((prev, curr) => new { prev, curr })
            .Where(x => x.prev == false && x.curr)
            .Subscribe(ExecuteOnEnterActions, Log.HandleException)
            .AddTo(Anchors);

            this.repository.KnownEntities
            .ToObservableChangeSet()
            .SkipInitial()
            .Throttle(ModelsReloadTimeout, bgScheduler)
            .ObserveOn(uiScheduler)
            .Subscribe(
                () =>
            {
                var properties = Properties;
                ReloadCollections(properties);
            })
            .AddTo(Anchors);

            var modelPropertiesToIgnore = new[]
            {
                nameof(IAuraTrigger.IsActive),
                nameof(IAuraTrigger.TriggerDescription),
                nameof(IAuraTrigger.TriggerName),
            }.ToImmutableHashSet();

            //FIXME Properties mechanism should have inverted logic - only important parameters must matter
            Observable.Merge(
                this.WhenAnyProperty(x => x.Name, x => x.TargetWindow, x => x.IsEnabled).Select(x => $"[{Name}].{x.EventArgs.PropertyName} property changed"),
                Overlay.WhenAnyProperty().Where(x => !modelPropertiesToIgnore.Contains(x.EventArgs.PropertyName)).Select(x => $"[{Name}].{nameof(Overlay)}.{x.EventArgs.PropertyName} property changed"),
                Triggers.ToObservableChangeSet().Select(x => $"[{Name}({Id})] Trigger list changed, item count: {Triggers.Count}"),
                Triggers.ToObservableChangeSet().WhenPropertyChanged().Where(x => !modelPropertiesToIgnore.Contains(x.EventArgs.PropertyName)).Select(x => $"[{Name}].{x.Sender}.{x.EventArgs.PropertyName} Trigger property changed"),
                OnEnterActions.ToObservableChangeSet().Select(x => $"[{Name}({Id})] Action list changed, item count: {OnEnterActions.Count}"),
                OnEnterActions.ToObservableChangeSet().WhenPropertyChanged().Where(x => !modelPropertiesToIgnore.Contains(x.EventArgs.PropertyName)).Select(x => $"[{Name}].{x.Sender}.{x.EventArgs.PropertyName} Action property changed"))
            .Subscribe(reason => RaisePropertyChanged(nameof(Properties)))
            .AddTo(Anchors);

            Disposable.Create(() =>
            {
                Log.Debug(
                    $"Disposed Aura {Name}({Id}) (aka {defaultAuraName}), triggers: {Triggers.Count}, actions: {OnEnterActions.Count}");
                OnEnterActions.Clear();
                Triggers.Clear();
            }).AddTo(Anchors);
            sw.Step($"Overlay model properties initialized");

            overlayController.RegisterChild(overlayViewModel).AddTo(Anchors);
            sw.Step($"Overlay registration completed: {this}");
        }
Example #2
0
 private void ExecuteOnEnterActions()
 {
     Log.Debug($"[{Name}({Id})] Trigger state changed, executing OnEnter Actions");
     OnEnterActions.ForEach(action => action.Execute());
 }