public EyeOverlayViewModel( [NotNull] [Dependency(WellKnownWindows.AllWindows)] IWindowTracker mainWindowTracker, [NotNull] IOverlayWindowController overlayWindowController, [NotNull] IAuraModelController auraModelController, [NotNull] IWindowListProvider windowListProvider, [NotNull] ISelectionAdornerViewModel selectionAdorner, [NotNull] [Dependency(WellKnownSchedulers.UI)] IScheduler uiScheduler) { using var sw = new BenchmarkTimer("Initialization", Log, nameof(EyeOverlayViewModel)); SelectionAdorner = selectionAdorner.AddTo(Anchors); activeConfigEditorAnchors.AddTo(Anchors); this.mainWindowTracker = mainWindowTracker; this.overlayWindowController = overlayWindowController; this.auraModelController = auraModelController; this.windowListProvider = windowListProvider; MinSize = new Size(32, 32); SizeToContent = SizeToContent.Manual; Width = 400; Height = 400; Left = 200; Top = 200; IsUnlockable = true; Title = "EyeAuras"; EnableHeader = false; thumbnailOpacity.SetDefaultValue(DefaultThumbnailOpacity); ResetRegionCommandExecuted(); sw.Step("Basic properties initialized"); WhenLoaded .Take(1) .Subscribe(ApplyConfig) .AddTo(Anchors); sw.Step("WhenLoaded executed"); resetRegionCommand = CommandWrapper.Create(ResetRegionCommandExecuted, ResetRegionCommandCanExecute); selectRegionCommand = CommandWrapper.Create(SelectRegionCommandExecuted, SelectRegionCommandCanExecute); closeConfigEditorCommand = CommandWrapper.Create(CloseConfigEditorCommandExecuted); fitOverlayCommand = CommandWrapper.Create<double?>(FitOverlayCommandExecuted); setAttachedWindowCommand = CommandWrapper.Create<WindowHandle>(SetAttachedWindowCommandExecuted); setClickThroughCommand = CommandWrapper.Create<bool?>(SetClickThroughModeExecuted); DisableAuraCommand = CommandWrapper.Create(() => auraModelController.IsEnabled = false); CloseCommand = CommandWrapper.Create(CloseCommandExecuted, auraModelController.WhenAnyValue(x => x.CloseController).Select(CloseCommandCanExecute)); ToggleLockStateCommand = CommandWrapper.Create( () => { if (IsLocked && UnlockWindowCommand.CanExecute(null)) { UnlockWindowCommand.Execute(null); } else if (!IsLocked && LockWindowCommand.CanExecute(null)) { LockWindowCommand.Execute(null); } else { throw new ApplicationException($"Something went wrong - invalid Overlay Lock state: {new {IsLocked, IsUnlockable, CanUnlock = UnlockWindowCommand.CanExecute(null), CanLock = LockWindowCommand.CanExecute(null) }}"); } }); auraModelController.WhenAnyValue(x => x.Name) .Where(x => !string.IsNullOrEmpty(x)) .Subscribe(x => OverlayName = x) .AddTo(Anchors); this.RaiseWhenSourceValue(x => x.ActiveThumbnailOpacity, thumbnailOpacity, x => x.Value).AddTo(Anchors); this.RaiseWhenSourceValue(x => x.ThumbnailOpacity, this, x => x.ActiveThumbnailOpacity).AddTo(Anchors); this.RaiseWhenSourceValue(x => x.SourceBounds, Region, x => x.Bounds).AddTo(Anchors); isInEditMode = Observable.Merge( this.WhenAnyProperty(x => x.IsInSelectMode, x => x.IsLocked)) .Select(change => IsInSelectMode || !IsLocked) .ToPropertyHelper(this, x => x.IsInEditMode, uiScheduler) .AddTo(Anchors); this.WhenAnyValue(x => x.IsLocked) .Where(x => x && isInSelectMode) .Subscribe(() => IsInSelectMode = false) .AddTo(Anchors); aspectRatio = this.WhenAnyProperty(x => x.Bounds, x => x.ViewModelLocation) .Select(change => Width >= 0 && Height >= 0 ? Width / Height : double.PositiveInfinity) .ToPropertyHelper(this, x => x.AspectRatio, uiScheduler) .AddTo(Anchors); sw.ResetStep(); configEditorSupplier = new Lazy<OverlayConfigEditor>(() => CreateConfigEditor(this)); sw.Step("Initialized Config editor"); }
public MicSwitchOverlayViewModel( IOverlayWindowController overlayWindowController, IMicrophoneControllerEx microphoneController, IConfigProvider<MicSwitchOverlayConfig> configProvider, IImageProvider imageProvider, [Dependency(WellKnownSchedulers.UI)] IScheduler uiScheduler) { this.overlayWindowController = overlayWindowController; this.microphoneController = microphoneController; this.configProvider = configProvider; this.imageProvider = imageProvider; OverlayMode = OverlayMode.Transparent; MinSize = new Size(40, 40); MaxSize = new Size(300, 300); DefaultSize = new Size(120, 120); SizeToContent = SizeToContent.Manual; TargetAspectRatio = MinSize.Width / MinSize.Height; IsUnlockable = true; Title = "MicSwitch"; IsEnabled = true; this.WhenAnyValue(x => x.IsLocked) .SubscribeSafe(isLocked => OverlayMode = isLocked ? OverlayMode.Transparent : OverlayMode.Layered, Log.HandleUiException) .AddTo(Anchors); this.RaiseWhenSourceValue(x => x.IsEnabled, overlayWindowController, x => x.IsEnabled).AddTo(Anchors); this.RaiseWhenSourceValue(x => x.Mute, microphoneController, x => x.Mute, uiScheduler).AddTo(Anchors); this.RaiseWhenSourceValue(x => x.MicrophoneImage, imageProvider, x => x.MicrophoneImage, uiScheduler).AddTo(Anchors); ToggleLockStateCommand = CommandWrapper.Create( () => { if (IsLocked && UnlockWindowCommand.CanExecute(null)) { UnlockWindowCommand.Execute(null); } else if (!IsLocked && LockWindowCommand.CanExecute(null)) { LockWindowCommand.Execute(null); } else { throw new ApplicationException($"Something went wrong - invalid Overlay Lock state: {new {IsLocked, IsUnlockable, CanUnlock = UnlockWindowCommand.CanExecute(null), CanLock = LockWindowCommand.CanExecute(null) }}"); } }); this.WhenAnyValue(x => x.IsEnabled) .Where(x => !IsEnabled && !IsLocked) .ObserveOn(uiScheduler) .SubscribeSafe(() => LockWindowCommand.Execute(null), Log.HandleUiException) .AddTo(Anchors); this.WhenAnyValue(x => x.OverlayWindow) .Where(x => x != null) .SubscribeSafe(x => x.LogWndProc("MicOverlay").AddTo(Anchors), Log.HandleUiException) .AddTo(Anchors); this.WhenAnyValue(x => x.OverlayVisibilityMode, x => x.Mute) .Select(_ => { return OverlayVisibilityMode switch { OverlayVisibilityMode.Always => true, OverlayVisibilityMode.Never => false, OverlayVisibilityMode.WhenMuted => Mute, OverlayVisibilityMode.WhenUnmuted => !Mute, _ => throw new ArgumentOutOfRangeException(nameof(overlayVisibilityMode), overlayVisibilityMode, "Unknown visibility mode") }; }) .DistinctUntilChanged() .ObserveOn(uiScheduler) .SubscribeSafe(x => IsEnabled = x, Log.HandleUiException) .AddTo(Anchors); WhenLoaded .Take(1) .SubscribeSafe(_ => { configProvider .WhenChanged .ObserveOn(uiScheduler) .SubscribeSafe(LoadConfig, Log.HandleUiException) .AddTo(Anchors); Observable.Merge( this.ObservableForProperty(x => x.NativeBounds, skipInitial: true).ToUnit(), this.ObservableForProperty(x => x.Opacity, skipInitial: true).ToUnit(), this.ObservableForProperty(x => x.OverlayVisibilityMode, skipInitial: true).ToUnit(), this.ObservableForProperty(x => x.IsEnabled, skipInitial: true).ToUnit(), this.ObservableForProperty(x => x.IsLocked, skipInitial: true).ToUnit()) .SkipUntil(WhenLoaded) .Throttle(ConfigThrottlingTimeout) .ObserveOn(uiScheduler) .SubscribeSafe(SaveConfig, Log.HandleUiException) .AddTo(Anchors); }, Log.HandleUiException) .AddTo(Anchors); }
public MicSwitchOverlayViewModel( [NotNull] IOverlayWindowController overlayWindowController, [NotNull] IMicrophoneControllerEx microphoneController, [NotNull] IConfigProvider<MicSwitchConfig> configProvider, [NotNull] IImageProvider imageProvider, [NotNull] [Dependency(WellKnownSchedulers.UI)] IScheduler uiScheduler) { this.overlayWindowController = overlayWindowController; this.microphoneController = microphoneController; this.configProvider = configProvider; this.imageProvider = imageProvider; OverlayMode = OverlayMode.Transparent; MinSize = new Size(120, 120); MaxSize = new Size(300, 300); SizeToContent = SizeToContent.Manual; TargetAspectRatio = MinSize.Width / MinSize.Height; IsUnlockable = true; Title = "MicSwitch"; WhenLoaded .Take(1) .Select(x => configProvider.WhenChanged) .Switch() .ObserveOn(uiScheduler) .Subscribe(ApplyConfig) .AddTo(Anchors); this.WhenAnyValue(x => x.IsLocked) .Subscribe(isLocked => OverlayMode = isLocked ? OverlayMode.Transparent : OverlayMode.Layered) .AddTo(Anchors); configProvider.ListenTo(x => x.MicrophoneLineId) .ObserveOn(uiScheduler) .Subscribe(lineId => { microphoneController.LineId = lineId; }) .AddTo(Anchors); this.RaiseWhenSourceValue(x => x.IsEnabled, overlayWindowController, x => x.IsEnabled).AddTo(Anchors); this.RaiseWhenSourceValue(x => x.Mute, microphoneController, x => x.Mute, uiScheduler).AddTo(Anchors); this.RaiseWhenSourceValue(x => x.MicrophoneImage, imageProvider, x => x.ActiveMicrophoneImage, uiScheduler).AddTo(Anchors); ToggleLockStateCommand = CommandWrapper.Create( () => { if (IsLocked && UnlockWindowCommand.CanExecute(null)) { UnlockWindowCommand.Execute(null); } else if (!IsLocked && LockWindowCommand.CanExecute(null)) { LockWindowCommand.Execute(null); } else { throw new ApplicationException($"Something went wrong - invalid Overlay Lock state: {new {IsLocked, IsUnlockable, CanUnlock = UnlockWindowCommand.CanExecute(null), CanLock = LockWindowCommand.CanExecute(null) }}"); } }); Observable.Merge( this.ObservableForProperty(x => x.Left, skipInitial: true).ToUnit(), this.ObservableForProperty(x => x.Top, skipInitial: true).ToUnit(), this.ObservableForProperty(x => x.Width, skipInitial: true).ToUnit(), this.ObservableForProperty(x => x.Height, skipInitial: true).ToUnit(), this.ObservableForProperty(x => x.IsEnabled, skipInitial: true).ToUnit(), this.ObservableForProperty(x => x.IsLocked, skipInitial: true).ToUnit()) .SkipUntil(WhenLoaded) .Throttle(ConfigThrottlingTimeout) .ObserveOn(uiScheduler) .Subscribe(SaveConfig, Log.HandleUiException) .AddTo(Anchors); this.WhenAnyValue(x => x.IsEnabled) .Where(x => !IsEnabled && !IsLocked) .ObserveOn(uiScheduler) .Subscribe(() => LockWindowCommand.Execute(null), Log.HandleUiException) .AddTo(Anchors); }