/// <summary> /// キーボード操作を登録 /// </summary> /// <param name="keyReceiver"></param> /// <param name="client"></param> private void RegisterKeyReceiver(ClientWindowViewModel parent) { var keyReceiver = parent.KeyReceiver; var pageFilter = keyReceiver.AddPreFilter(x => (client.SelectedPage.Value == PageType.Catalog)); var cursorFilter = keyReceiver.AddPreFilter(x => { if (client.SelectedPage.Value != PageType.Catalog) { return(false); } return(!(x.FocusedControl is TextBox)); }); var buttonFilter = keyReceiver.AddPreFilter(x => { if (client.SelectedPage.Value != PageType.Catalog) { return(false); } return(!(x.FocusedControl is ButtonBase) && !(x.FocusedControl is TextBox)); }); keyReceiver.Register(Key.PageUp, (t, key) => this.RequestScrollAction?.Invoke(new Vector(0, -0.8)), pageFilter, isPreview: true); keyReceiver.Register(Key.PageDown, (t, key) => this.RequestScrollAction?.Invoke(new Vector(0, 0.8)), pageFilter, isPreview: true); keyReceiver.Register(Key.Up, (t, key) => this.RequestScrollAction?.Invoke(new Vector(0, -0.2)), pageFilter, isPreview: true); keyReceiver.Register(Key.Down, (t, key) => this.RequestScrollAction?.Invoke(new Vector(0, 0.2)), pageFilter, isPreview: true); keyReceiver.Register(Key.Home, (t, key) => this.RequestScrollAction?.Invoke(new Vector(0, double.NegativeInfinity)), pageFilter, isPreview: true); keyReceiver.Register(Key.End, (t, key) => this.RequestScrollAction?.Invoke(new Vector(0, double.PositiveInfinity)), pageFilter, isPreview: true); keyReceiver.Register(Key.A, (t, key) => { if (this.SelectedItems.Count != this.client.Length.Value) { this.client.SelectAllAsync().FireAndForget(); } else { this.SelectedItems.Clear(); } }, pageFilter, modifier: ModifierKeys.Control); keyReceiver.Register(Key.N, (t, key) => this.SelectedItems.Clear(), pageFilter, modifier: ModifierKeys.Control); keyReceiver.Register(Key.C, (t, key) => this.parent.Core.CopySelectedItemsPath(this.SelectedItems), pageFilter, modifier: ModifierKeys.Control); keyReceiver.Register(Key.T, (t, key) => this.parent.ShowTagSelector(null), cursorFilter, modifier: ModifierKeys.Control); keyReceiver.Register(Key.Apps, (t, key) => { if (!parent.IsPaneFixed.Value) { parent.ToggleInformationPane(); } }, cursorFilter); keyReceiver.Register(k => k >= Key.A && k <= Key.Z, (t, key) => this.SetTag(((char)(key - Key.A + 'a')).ToString()), cursorFilter); keyReceiver.Register(Key.Delete, async(t, key) => await this.client.DeleteSelectedFiles(false), cursorFilter); keyReceiver.Register(Key.Delete, async(t, key) => await this.client.DeleteSelectedFiles(true), cursorFilter, modifier: ModifierKeys.Control); keyReceiver.Register(Key.F5, (t, key) => this.client.Refresh(), cursorFilter); }
public CatalogPageViewModel(ClientWindowViewModel parent) { this.parent = parent; this.client = parent.Client; this.library = parent.Library; var core = parent.Core; this.Length = client.Length.ToReadOnlyReactiveProperty().AddTo(this.Disposables); this.IsInSelecting = this.client.SelectedItemsCount .Select(x => x > 0) .ToReadOnlyReactiveProperty() .AddTo(this.Disposables); //表示中のインデックス this.StartIndex = this.client .CatalogIndex .Select(x => (x < int.MaxValue) ? (int)x : int.MaxValue) .ToReactiveProperty() .AddTo(this.Disposables); this.StartIndex .Subscribe(x => this.client.CatalogIndex.Value = x) .AddTo(this.Disposables); this.DisplayIndex = this.StartIndex.Select(x => x + 1).ToReactiveProperty().AddTo(this.Disposables); this.DisplayIndex.Subscribe(x => this.StartIndex.Value = x - 1).AddTo(this.Disposables); this.ThumbnailSize = core.ObserveProperty(x => x.ThumbNailSize) .Select(x => (double)x) .ToReactiveProperty().AddTo(this.Disposables); this.ThumbnailViewSize = this.ThumbnailSize .Select(x => new Size(x, x)) .ToReadOnlyReactiveProperty() .AddTo(this.Disposables); this.ImagePropertiesVisibility = this.ThumbnailSize .Select(x => VisibilityHelper.Set(x > 128)).ToReactiveProperty().AddTo(this.Disposables); this.ThumbnailMargin = this.ThumbnailSize .Select(x => new Thickness((x < 128) ? 1 : (x < 256) ? 2 : 4)) .ToReactiveProperty().AddTo(this.Disposables); this.IsRefreshEnabled = this.client.IsStateChanging .Select(x => !x) .ToReadOnlyReactiveProperty() .AddTo(this.Disposables); this.IsRenderingEnabled = this.client.IsCatalogRenderingEnabled .CombineLatest(this.client.SelectedPage, (e, p) => e && p == PageType.Catalog) .ToReadOnlyReactiveProperty(true) .AddTo(this.Disposables); //戻ってきたときにサムネイル再読み込み client.BackHistoryCount .Pairwise() .CombineLatest(client.SelectedPage, (history, page) => history.OldItem > history.NewItem && page == PageType.Catalog) .Where(x => x) .Subscribe(_ => this.RefreshTrigger = !this.RefreshTrigger) .AddTo(this.Disposables); client.CacheUpdated .SkipUntil(client.StateChanged) .Take(1) .Repeat() .Subscribe(_ => this.RefreshTrigger = !this.RefreshTrigger) .AddTo(this.Disposables); //スクロールが落ち着いたら再読み込み this.StartIndex .Throttle(TimeSpan.FromMilliseconds(3000)) .ObserveOnUIDispatcher() .Subscribe(_ => this.RefreshTrigger = !this.RefreshTrigger) .AddTo(this.Disposables); //スクロール位置復元 this.client.CatalogScrollIndex .Subscribe(x => this.ScrollToIndexAction?.Invoke((int)x)) .AddTo(this.Disposables); //サムネイルクリック this.ItemClickCommand = new ReactiveCommand() .WithSubscribe(context => this.SelectOrShow(context, true), this.Disposables); //選択 this.ItemSelectCommand = new ReactiveCommand() .WithSubscribe(context => this.SelectOrShow(context, false), this.Disposables); //ソート条件編集 this.EditSortCommand = new ReactiveCommand() .WithSubscribe(x => { var control = x as FrameworkElement; var content = new SortEditor() { ItemsSource = this.client.GetSort(), }; content.IsEnabledChanged += (o, e) => { var value = e.NewValue as bool?; if (value.HasValue && !value.Value) { this.client.SetSort(content.SortSettings); } }; this.parent.PopupOwner.PopupDialog.Show(content, new Thickness(double.NaN, 10.0, 0.0, double.NaN), HorizontalAlignment.Right, VerticalAlignment.Bottom, control); }, this.Disposables); //すべて選択 this.SelectAllCommand = new ReactiveCommand() .WithSubscribe(async _ => await this.client.SelectAllAsync(), this.Disposables); //選択をクリア this.SelectionClearCommand = this.IsInSelecting .ToReactiveCommand() .WithSubscribe(_ => this.SelectedItems.Clear(), this.Disposables); //グループ化 this.GroupingCommand = this.client.SelectedItemsCount .CombineLatest(this.client.IsGroupMode, (c, g) => c > 1 && !g) .ToReactiveCommand() .WithSubscribe(_ => this.client.Grouping(), this.Disposables); //グループから退去 this.RemoveFromGroupCommand = this.client.SelectedItemsCount .CombineLatest(this.client.IsGroupMode, (c, g) => c >= 1 && g) .ToReactiveCommand() .WithSubscribe(_ => this.client.RemoveFromGroup(), this.Disposables); this.SetToLeaderCommand = this.client.SelectedItemsCount .CombineLatest(this.client.IsGroupMode, (c, g) => c == 1 && g) .ToReactiveCommand() .WithSubscribe(_ => this.client.SetGroupLeader(), this.Disposables); this.RefreshCommand = new ReactiveCommand() .WithSubscribe(_ => this.client.Refresh(), this.Disposables); this.RegisterKeyReceiver(parent); }
public ViewerPageViewModel(ClientWindowViewModel parent) { this.parent = parent; this.client = parent.Client; this.library = parent.Library; this.DisplayIndex = client.ViewerIndex .Select(x => x + 1) .ToReactiveProperty() .AddTo(this.Disposables); this.DisplayIndex.Subscribe(x => { client.ViewerIndex.Value = x - 1; }) .AddTo(this.Disposables); this.Length = client.Length.ToReadOnlyReactiveProperty().AddTo(this.Disposables); this.randomNumber = new RandomNumber(); this.IsRandom = parent.Core .ToReactivePropertyAsSynchronized(x => x.IsSlideshowRandom).AddTo(this.Disposables); this.IsRandom.Select(_ => Unit.Default) .Merge(this.Length.Select(_ => Unit.Default)) .Subscribe(x => { if (this.IsRandom.Value && this.Length.Value > 0) { this.randomNumber.Length = (int)this.Length.Value; this.randomNumber.Clear(); this.client.PrepareNext(this.randomNumber.GetNext()); } }) .AddTo(this.Disposables); this.client.ViewerCacheClearedTrigger .Subscribe(x => { if (this.IsRandom.Value && this.Length.Value > 0) { this.client.PrepareNext(this.randomNumber.GetNext()); } }) .AddTo(this.Disposables); this.ZoomFactor = new ReactiveProperty <double>().AddTo(this.Disposables); this.DesiredZoomFactor = new ReactiveProperty <double>(0.0).AddTo(this.Disposables); this.CurrentZoomFactorPercent = this.ZoomFactor .Select(x => x * 100.0) .ToReactiveProperty() .AddTo(this.Disposables); this.DisplayZoomFactor = this.CurrentZoomFactorPercent.ToReactiveProperty().AddTo(this.Disposables); this.DisplayZoomFactor.Where(x => x != this.CurrentZoomFactorPercent.Value) .Subscribe(x => this.ChangeZoomFactor(x / 100.0)) .AddTo(this.Disposables); this.UsePhysicalPixel = parent.Core .ObserveProperty(x => x.UseLogicalPixel) .Select(x => !x) .ToReadOnlyReactiveProperty() .AddTo(this.Disposables); this.ScalingMode = parent.Core .ObserveProperty(x => x.ScalingMode) .ToReadOnlyReactiveProperty() .AddTo(this.Disposables); this.IsImageChanging = new ReactiveProperty <bool>().AddTo(this.Disposables); //拡大率表示ポップアップ this.ZoomFactorVisibility = this.ZoomFactor.Select(x => true) .Merge(this.ZoomFactor.Throttle(TimeSpan.FromMilliseconds(zoomFactorDisplayTime)).Select(x => false)) .Where(x => !this.IsImageChanging.Value) .Merge(this.IsImageChanging.Where(x => x).Select(x => !x)) .Select(x => VisibilityHelper.Set(x)) .ToReactiveProperty(Visibility.Collapsed) .AddTo(this.Disposables); this.IsGifAnimationEnabled = parent.Core .ToReactivePropertyAsSynchronized(x => x.IsAnimatedGifEnabled) .AddTo(this.Disposables); this.IsFill = parent.Core .ObserveProperty(x => x.IsSlideshowResizeToFill) .ToReadOnlyReactiveProperty() .AddTo(this.Disposables); this.IsZoomoutOnly = parent.Core .ObserveProperty(x => x.IsSlideshowResizingAlways) .Select(x => !x) .ToReadOnlyReactiveProperty() .AddTo(this.Disposables); parent.MouseExButtonPressed .Subscribe(x => { if (parent.Core.UseExtendedMouseButtonsToSwitchImage && client.SelectedPage.Value == PageType.Viewer) { if (x) { this.MoveRight(); } else { this.MoveLeft(); } } }) .AddTo(this.Disposables); this.ViewWidth = new ReactiveProperty <double>().AddTo(this.Disposables); this.ViewWidth.Subscribe(x => client.ViewWidth = x).AddTo(this.Disposables); this.ViewHeight = new ReactiveProperty <double>().AddTo(this.Disposables); this.ViewHeight.Subscribe(x => client.ViewHeight = x).AddTo(this.Disposables); this.IsInHorizontalMirror = new ReactiveProperty <bool>(false).AddTo(this.Disposables); this.IsInVerticalMirror = new ReactiveProperty <bool>(false).AddTo(this.Disposables); this.IsAutoScalingEnabled = new ReactiveProperty <bool>(false).AddTo(this.Disposables); this.Orientation = new ReactiveProperty <int>().AddTo(this.Disposables); this.IsScrollRequested = new ReactiveProperty <bool>().AddTo(this.Disposables); this.IsTopBarOpen = new ReactiveProperty <bool>(false).AddTo(this.Disposables); this.IsTopBarFixed = parent.Core .ToReactivePropertyAsSynchronized(x => x.IsViewerPageTopBarFixed) .AddTo(this.Disposables); if (this.IsTopBarFixed.Value) { this.IsTopBarOpen.Value = true; } this.OpenPaneCommand = new ReactiveCommand() .WithSubscribe(_ => parent.TogglePane(OptionPaneType.ItemInfo), this.Disposables); this.TogglePaneCommand = new ReactiveCommand() .WithSubscribe(_ => this.TogglePane(), this.Disposables); this.TapCommand = new ReactiveCommand().AddTo(this.Disposables); var tapped = this.TapCommand.OfType <ViewerTapEventArgs>().Publish().RefCount(); tapped .Subscribe(e => { if (e.HolizontalRate < edgeTapThreshold) { this.MoveLeft(); } else if (e.HolizontalRate > (1.0 - edgeTapThreshold)) { this.MoveRight(); } }) .AddTo(this.Disposables); tapped .Where(_ => parent.Core.IsOpenNavigationWithSingleTapEnabled) .Throttle(TimeSpan.FromMilliseconds(500)) .Subscribe(e => { if (e.Count == 1 && parent.Core.IsOpenNavigationWithSingleTapEnabled && e.HolizontalRate >= edgeTapThreshold && e.HolizontalRate <= (1.0 - edgeTapThreshold) && (!this.IsTopBarFixed.Value || !this.IsTopBarOpen.Value)) { this.IsTopBarOpen.Toggle(); } }) .AddTo(this.Disposables); this.PointerMoveCommand = new ReactiveCommand() .WithSubscribe(x => { var y = ((Point)x).Y; if (y < 100) { this.IsTopBarOpen.Value = true; this.topBarOpenedByPointer = true; } else if (y > 150) { if (this.topBarOpenedByPointer && !this.IsTopBarFixed.Value) { this.IsTopBarOpen.Value = false; } this.topBarOpenedByPointer = false; } }, this.Disposables); this.BackCommand = client.BackHistoryCount .Select(x => x > 0) .ToReactiveCommand() .WithSubscribe(_ => client.Back(), this.Disposables); this.SplitViewButtonVisibility = parent.IsPaneFixed .Select(x => VisibilityHelper.Set(!x)) .ToReactiveProperty() .AddTo(this.Disposables); this.IsSlideshowPlaying = this.client.SelectedPage .Select(_ => false) .ToReactiveProperty(false) .AddTo(this.Disposables); this.IsSlideshowPlaying.Subscribe(x => { if (x) { this.StartSlideShow(); } else { this.parent.IsFullScreen.Value = false; } }) .AddTo(this.Disposables); this.SlideshowSubject = new Subject <Unit>().AddTo(this.Disposables); var slideshowSubscription = new SerialDisposable().AddTo(this.Disposables); this.parent.Core.ObserveProperty(x => x.SlideshowFlipTimeMillisec) .Subscribe(x => { slideshowSubscription.Disposable = this.SlideshowSubject .Throttle(TimeSpan.FromMilliseconds(x)) .Where(_ => this.IsSlideshowPlaying.Value) .ObserveOnUIDispatcher() .Subscribe(y => { if (this.IsSlideshowPlaying.Value) { this.MoveNext(); } }); if (this.IsSlideshowPlaying.Value) { this.SlideshowSubject.OnNext(Unit.Default); } }) .AddTo(this.Disposables); // Transform Dialog this.IsTransformDialogEnabled = new ReactiveProperty <bool>(true).AddTo(this.Disposables); this.VerticalMirrorCommand = new ReactiveCommand() .WithSubscribe(_ => { this.VerticalMirror(); this.HidePopup(); }, this.Disposables); this.HorizontalMirrorCommand = new ReactiveCommand() .WithSubscribe(_ => { this.HorizontalMirror(); this.HidePopup(); }, this.Disposables); this.RotateCwCommand = new ReactiveCommand() .WithSubscribe(_ => { this.Rotate(1); this.HidePopup(); }, this.Disposables); this.RotateCcwCommand = new ReactiveCommand() .WithSubscribe(_ => { this.Rotate(-1); this.HidePopup(); }, this.Disposables); this.MoveToGroupCommand = this.Record.Select(x => x?.IsGroup ?? false).ToReactiveCommand() .WithSubscribe(_ => this.client.DisplayGroup(0), this.Disposables); this.CheckHorizontalScrollRequestFunction = () => { var k = this.CheckKeyboardScrollModifier(); return((Keyboard.IsKeyDown(Key.Right)) ? k : (Keyboard.IsKeyDown(Key.Left)) ? -k : 0); }; this.CheckVerticalScrollRequestFunction = () => { var k = this.CheckKeyboardScrollModifier(); return((Keyboard.IsKeyDown(Key.Down)) ? k : (Keyboard.IsKeyDown(Key.Up)) ? -k : 0); }; this.TopBarWheelAction = (o, e) => { if (e.Delta > 0) { this.MovePrev(); } else if (e.Delta < 0) { this.MoveNext(); } }; //画像変更ボタン this.MoveButtonVisibility = parent.Core .ObserveProperty(x => x.IsViewerMoveButtonDisabled) .Select(x => VisibilityHelper.Set(!x)) .ToReadOnlyReactiveProperty() .AddTo(this.Disposables); this.IsLeftButtonEnter = new ReactiveProperty <bool>(false).AddTo(this.Disposables); this.IsRightButtonEnter = new ReactiveProperty <bool>(false).AddTo(this.Disposables); this.IsLeftButtonPressed = new ReactiveProperty <bool>(false).AddTo(this.Disposables); this.IsRightButtonPressed = new ReactiveProperty <bool>(false).AddTo(this.Disposables); this.PointerMoveAction = (o, e) => { if (this.IsDisposed) { return; } var element = o as FrameworkElement; if (element == null) { return; } var point = (Vector)e.GetPosition(element) / element.ActualWidth; if (point.X < edgeTapThreshold) { this.IsLeftButtonEnter.Value = true; } else { this.IsLeftButtonEnter.Value = false; this.IsLeftButtonPressed.Value = false; } if (point.X > (1.0 - edgeTapThreshold)) { this.IsRightButtonEnter.Value = true; } else { this.IsRightButtonEnter.Value = false; this.IsRightButtonPressed.Value = false; } }; this.PointerLeaveAction = (o, e) => { if (this.IsDisposed) { return; } this.IsLeftButtonEnter.Value = false; this.IsRightButtonEnter.Value = false; this.IsLeftButtonPressed.Value = false; this.IsRightButtonPressed.Value = false; }; this.PointerDownAction = (o, e) => { if (this.IsDisposed) { return; } var element = o as FrameworkElement; if (element == null) { return; } var point = (Vector)e.GetPosition(element) / element.ActualWidth; this.IsLeftButtonPressed.Value = point.X < edgeTapThreshold; this.IsRightButtonPressed.Value = point.X > (1.0 - edgeTapThreshold); }; this.PointerUpAction = (o, e) => { if (this.IsDisposed) { return; } this.IsLeftButtonPressed.Value = false; this.IsRightButtonPressed.Value = false; }; //キーボード操作 this.RegisterKeyReceiver(parent); }
/// <summary> /// キーボード操作を登録 /// </summary> /// <param name="keyReceiver"></param> /// <param name="client"></param> private void RegisterKeyReceiver(ClientWindowViewModel parent) { var keyReceiver = parent.KeyReceiver; var pageFilter = keyReceiver.AddPreFilter(x => (client.SelectedPage.Value == PageType.Viewer)); var cursorFilter = keyReceiver.AddPreFilter(x => { if (client.SelectedPage.Value != PageType.Viewer) { return(false); } return(!(x.FocusedControl is TextBox)); }); var buttonFilter = keyReceiver.AddPreFilter(x => { if (client.SelectedPage.Value != PageType.Viewer) { return(false); } return(!(x.FocusedControl is ButtonBase) && !(x.FocusedControl is TextBox)); }); //var scrollDelta = 100; var zoom = 1.2; var shiftOrControlKey = new[] { ModifierKeys.Shift, ModifierKeys.Control }; shiftOrControlKey.ForEach(m => { keyReceiver.Register( new[] { Key.Up, Key.Down, Key.Right, Key.Left }, (t, key) => this.ReceiveCursorKey(key, !this.CursorKeyForMove, zoom), cursorFilter, isPreview: true, modifier: m); }); keyReceiver.Register( new Key[] { Key.Up, Key.Down, Key.Right, Key.Left }, (t, key) => this.ReceiveCursorKey(key, this.CursorKeyForMove, zoom), cursorFilter, isPreview: true); keyReceiver.Register(new[] { Key.Add, Key.OemPlus }, (t, key) => this.ZoomImage(zoom), cursorFilter, modifier: ModifierKeys.Control); //keyReceiver.Register(k => (int)k == 187, (t, key) => this.ZoomImage(zoom), // pageFilter, false, ModifierKeys.Control); keyReceiver.Register(new[] { Key.Subtract, Key.OemMinus }, (t, key) => this.ZoomImage(1.0 / zoom), cursorFilter, modifier: ModifierKeys.Control); //keyReceiver.Register(k => (int)k == 189, (t, key) => this.ZoomImage(1.0 / zoom), // pageFilter, false, ModifierKeys.Control); keyReceiver.Register(Key.PageUp, (t, key) => this.MovePrev(), pageFilter, isPreview: true); keyReceiver.Register(Key.PageDown, (t, key) => this.MoveNext(), pageFilter, isPreview: true); keyReceiver.Register(Key.Home, (t, key) => this.client.ViewerIndex.Value = 0, cursorFilter, isPreview: true); keyReceiver.Register(Key.End, (t, key) => this.client.ViewerIndex.Value = this.Length.Value - 1, cursorFilter, isPreview: true); keyReceiver.Register(Key.Escape, (t, key) => { if (!this.IsTopBarOpen.Value && !this.parent.IsPaneOpen.Value) { this.parent.IsFullScreen.Value = false; } else { this.IsTopBarOpen.Value = false; } }, cursorFilter); keyReceiver.Register(new[] { Key.Space, Key.Enter }, (t, key) => this.StartAutoScaling(), buttonFilter); //keyReceiver.Register(k => (int)k == 190, (t, key) => this.StartAutoScaling(), pageFilter); keyReceiver.Register(new[] { Key.Decimal, Key.OemPeriod }, (t, key) => this.StartAutoScaling(), cursorFilter); keyReceiver.Register(new[] { Key.Space, Key.Enter }, (t, key) => this.IsSlideshowPlaying.Toggle(), buttonFilter, modifier: ModifierKeys.Control); keyReceiver.Register(new[] { Key.Decimal, Key.OemPeriod }, (t, key) => this.IsSlideshowPlaying.Toggle(), cursorFilter, modifier: ModifierKeys.Control); //keyReceiver.Register(k => (int)k == 190, (t, key) => this.StartSlideShow(), // pageFilter, false, ModifierKeys.Control); keyReceiver.Register(new[] { Key.Add, Key.OemPlus }, (t, key) => this.SetRating(true), cursorFilter); keyReceiver.Register(new[] { Key.Subtract, Key.OemMinus }, (t, key) => this.SetRating(false), cursorFilter); //keyReceiver.Register(k => (int)k == 187, (t, key) => this.SetRating(true), pageFilter); //keyReceiver.Register(k => (int)k == 189, (t, key) => this.SetRating(false), pageFilter); keyReceiver.Register(k => k >= Key.A && k <= Key.Z, (t, key) => this.SetTagWithShortCut(((char)(key - Key.A + 'a')).ToString()), cursorFilter); keyReceiver.Register(Key.H, (t, key) => this.HorizontalMirror(), cursorFilter, modifier: ModifierKeys.Control); keyReceiver.Register(Key.V, (t, key) => this.VerticalMirror(), cursorFilter, modifier: ModifierKeys.Control); keyReceiver.Register(Key.E, (t, key) => this.Rotate(-1), cursorFilter, modifier: ModifierKeys.Control); keyReceiver.Register(Key.R, (t, key) => this.Rotate(1), cursorFilter, modifier: ModifierKeys.Control); keyReceiver.Register(Key.T, (t, key) => this.parent.ShowTagSelector(null), cursorFilter, modifier: ModifierKeys.Control); keyReceiver.Register(Key.P, (t, key) => { if (!parent.IsPaneFixed.Value) { parent.TogglePane(OptionPaneType.ItemInfo); } }, cursorFilter, modifier: ModifierKeys.Control); keyReceiver.Register(Key.S, (t, key) => this.IsRandom.Toggle(), cursorFilter, modifier: ModifierKeys.Control); keyReceiver.Register(Key.L, (t, key) => { SharePathOperation.OpenExplorer(this.Record.Value?.FullPath); }, cursorFilter, modifier: ModifierKeys.Control); keyReceiver.Register(Key.C, (t, key) => { SharePathOperation.CopyPath(this.Record.Value?.FullPath); }, cursorFilter, modifier: ModifierKeys.Control); keyReceiver.Register(Key.Apps, (t, key) => this.TogglePane(), cursorFilter); keyReceiver.Register(Key.G, (t, key) => this.client.DisplayGroup(0), cursorFilter, modifier: ModifierKeys.Control); keyReceiver.Register(Key.Delete, async(t, key) => await this.client.DeleteDisplayingFile(false), cursorFilter); keyReceiver.Register(Key.Delete, async(t, key) => await this.client.DeleteDisplayingFile(true), cursorFilter, modifier: ModifierKeys.Control); keyReceiver.Register(Key.F5, (t, key) => this.client.Refresh(), cursorFilter); keyReceiver.Register(Key.F11, (t, key) => this.parent.IsFullScreen.Toggle(), cursorFilter); #if DEBUG keyReceiver.Register(Key.Divide, async(t, key) => { var index = await this.client.FindIndexFromDatabaseAsync(this.Record.Value); MessageBox.Show((index + 1).ToString()); }, cursorFilter); #endif }
public SearchPageViewModel(ClientWindowViewModel parent) { this.parent = parent; var client = parent.Client; var library = parent.Library; var core = parent.Core; var searcher = library.Searcher; this.HistoryList = searcher.SearchHistory.ToReadOnlyReactiveCollection().AddTo(this.Disposables); this.FavoriteList = searcher.FavoriteSearchList.ToReadOnlyReactiveCollection().AddTo(this.Disposables); this.SelectedTab = new ReactiveProperty <TabMode> ((searcher.FavoriteSearchList.Count > 0 && core.LastSearchedFavorite) ? TabMode.Favorite : TabMode.History) .AddTo(this.Disposables); this.SelectedTab .Subscribe(x => core.LastSearchedFavorite = (x == TabMode.Favorite)) .AddTo(this.Disposables); this.IsEditing = new ReactiveProperty <bool>(false).AddTo(this.Disposables); this.SelectHistoryCommand = new ReactiveCommand().AddTo(this.Disposables); this.SelectFavoriteCommand = new ReactiveCommand().AddTo(this.Disposables); var hitoryItem = this.SelectHistoryCommand .OfType <SearchInformation>() .Select(x => x.Clone()); var favoriteItem = this.SelectFavoriteCommand .OfType <SearchInformation>(); this.CurrentSearch = Observable .Merge(hitoryItem, favoriteItem)//, newItem) .ToReactiveProperty(SearchInformation.GenerateEmpty()) .AddTo(this.Disposables); this.CurrentSearch .Subscribe(x => this.IsEditing.Value = (x != null && !x.Key.IsNullOrEmpty())) .AddTo(this.Disposables); this.IsThumbnailVisible = this.CurrentSearch .Select(x => x.DateLastUsed > default(DateTimeOffset)) .ToReadOnlyReactiveProperty() .AddTo(this.Disposables); searcher.FavoriteSearchList .ObserveAddChanged() .Subscribe(x => { if (this.CurrentSearch.Value == x) { this.SelectedTab.Value = TabMode.Favorite; } }) .AddTo(this.Disposables); searcher.FavoriteSearchList .ObserveRemoveChanged() .Subscribe(x => { if (this.CurrentSearch.Value == x && this.SelectedTab.Value == TabMode.Favorite) { this.CurrentSearch.Value = SearchInformation.GenerateEmpty(); } }) .AddTo(this.Disposables); this.CurrentSearchType = this.HistoryList .CollectionChangedAsObservable() .Merge(this.FavoriteList.CollectionChangedAsObservable()) .Select(_ => this.CurrentSearch.Value) .Merge(this.CurrentSearch) .Select(x => this.HasFavoriteSearch(x) ? 1 : this.HasHistorySearch(x) ? 0 : 2) .ToReadOnlyReactiveProperty() .AddTo(this.Disposables); this.IsFavoriteSearch = this.CurrentSearchType .Select(x => x == 1) .ToReadOnlyReactiveProperty() .AddTo(this.Disposables); this.ClickHistoryCommand = new ReactiveCommand().AddTo(this.Disposables); this.ClickFavoriteCommand = new ReactiveCommand().AddTo(this.Disposables); this.ClickHistoryCommand .Select(x => x as SearchInformation) .Where(x => x != null) .Subscribe(x => { if (!this.IsEditing.Value || this.CurrentSearch.Value == null || this.CurrentSearch.Value.Key.IsNullOrEmpty() || this.CurrentSearch.Value.Key.Equals(x.Key)) { this.StartSearch(client, x); } else { this.SelectHistoryCommand.Execute(x); } }) .AddTo(this.Disposables); this.ClickFavoriteCommand .Select(x => x as SearchInformation) .Where(x => x != null) .Subscribe(x => { if (!this.IsEditing.Value || this.CurrentSearch.Value == null || this.CurrentSearch.Value.Key.IsNullOrEmpty() || this.CurrentSearch.Value.Key.Equals(x.Key)) { this.StartSearch(client, x); } else { this.SelectFavoriteCommand.Execute(x); } }) .AddTo(this.Disposables); this.StartSearchCommand = new ReactiveCommand() .WithSubscribe(_ => this.StartSearch(client, this.CurrentSearch.Value), this.Disposables); this.AddCriteriaCommand = new ReactiveCommand() .WithSubscribe(_ => this.EditSearch(this.CurrentSearch.Value.Root), this.Disposables); this.ItemClickCommand = new ReactiveCommand() .WithSubscribe(item => { var search = item as ISqlSearch; if (search != null) { this.EditSearch(search); } }, this.Disposables); this.AddToFavoriteCommand = new ReactiveCommand() .WithSubscribe(_ => { var item = this.CurrentSearch.Value; if (item == null) { return; } if (this.HasFavoriteSearch(item)) { searcher.MarkSearchUnfavorite(item); } else { searcher.MarkSearchFavorite(item); } }, this.Disposables); this.SwitchModeCommand = new ReactiveCommand() .WithSubscribe(_ => { var item = this.CurrentSearch.Value; if (item == null) { return; } item.Root.IsOr = !item.Root.IsOr; }, this.Disposables); this.NewSearchCommand = new ReactiveCommand() .WithSubscribe(_ => this.CurrentSearch.Value = SearchInformation.GenerateEmpty(), this.Disposables); this.ShowFavoriteCommand = new ReactiveCommand() .WithSubscribe(_ => this.SelectedTab.Value = TabMode.Favorite, this.Disposables); this.ShowHistoryCommand = new ReactiveCommand() .WithSubscribe(_ => this.SelectedTab.Value = TabMode.History, this.Disposables); }