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}"); }
/// <summary> /// Prepares context for next iteration /// </summary> public void PrepareNext() { _context.Reset(_threadIterationIdGenerator.Next(), _globalCounters.IterationId.Next()); }
public IIterationControl Create() { int newThreadId = _threadIdGenerator.Next(); return(new IterationContext(newThreadId, _timer, _initialUserData)); }