private bool IsInformationPane(OptionPaneType pane)
        {
            switch (pane)
            {
            case OptionPaneType.NoInformation:
            case OptionPaneType.ItemInfo:
            case OptionPaneType.SelectedItems:
                return(true);

            default:
                return(false);
            }
        }
 public void TogglePane(OptionPaneType type)
 {
     if (!this.IsPaneOpen.Value)
     {
         this.SelectedInformationPage.Value = type;
         this.IsPaneOpen.Value = true;
     }
     else
     {
         this.SelectedInformationPage.Value = OptionPaneType.None;
         this.IsPaneOpen.Value = false;
     }
 }
        public ClientWindowViewModel()
        {
            var core    = ((App)Application.Current).Core;
            var library = core.Library;

            var client = new Client(new LibraryFront(library), core).AddTo(this.Disposables);

            this.Client = client;
            this.Core   = core;

            this.KeyReceiver = new KeyReceiver <object>().AddTo(this.Disposables);

            this.WindowTitle = client.SelectedPage
                               .CombineLatest(client.ViewerDisplaying, (Page, Item) => new { Page, Item })
                               .Select(x =>
            {
                var file = (x.Page == PageType.Viewer) ? x.Item?.FileName : null;
                return((file == null) ? core.AppName : (file + " - " + core.AppName));
            })
                               .ToReadOnlyReactiveProperty()
                               .AddTo(this.Disposables);

            this.SelectedInformationPage = new ReactiveProperty <OptionPaneType>
                                               (core.IsViewerPageLeftBarFixed ? OptionPaneType.ItemInfo : OptionPaneType.None)
                                           .AddTo(this.Disposables);

            this.IsPaneOpen = new ReactiveProperty <bool>(core.IsViewerPageLeftBarFixed)
                              .AddTo(this.Disposables);


            this.IsPaneFixed = core
                               .ToReactivePropertyAsSynchronized(x => x.IsViewerPageLeftBarFixed)
                               .AddTo(this.Disposables);

            this.SelectedTab = client.SelectedPage
                               .Select(x =>
            {
                switch (x)
                {
                case PageType.Search:
                    return(0);

                case PageType.Catalog:
                    return(1);

                case PageType.Viewer:
                    return(2);

                default:
                    return(0);
                }
            })
                               .ToReactiveProperty(0)
                               .AddTo(this.Disposables);


            this.SelectedTab.Subscribe(x =>
            {
                if (this.IsPaneOpen.Value)
                {
                    if (this.IsPaneFixed.Value)
                    {
                        this.ShowInformationPane();
                    }
                    else
                    {
                        this.IsPaneOpen.Value = false;
                    }
                }
            })
            .AddTo(this.Disposables);

            this.Client.FeaturedGroupChanged.Subscribe(x =>
            {
                if (client.SelectedPage.Value == PageType.Catalog && this.IsPaneOpen.Value)
                {
                    this.ShowInformationPane();
                }
            })
            .AddTo(this.Disposables);


            this.PaneSelectedPath = new ReactiveProperty <string>((string)null)
                                    .AddTo(this.Disposables);
            this.PaneSelectedPath.Where(x => !string.IsNullOrWhiteSpace(x))
            .Subscribe(x => this.StartPathOrTagSearch(FileProperty.DirectoryPathStartsWith, x))
            .AddTo(this.Disposables);

            this.PaneSelectedTag = new ReactiveProperty <TagInformation>((TagInformation)null)
                                   .AddTo(this.Disposables);
            this.PaneSelectedTag.Where(x => x != null)
            .Subscribe(x => this.StartPathOrTagSearch(FileProperty.ContainsTag, x.Id))
            .AddTo(this.Disposables);

            this.DefaultPaneMode = client.SelectedPage
                                   .Select(x => (x == PageType.Viewer) ? PaneMode.HideInClosing
                    : PaneMode.AlwaysVisible)
                                   .ToReactiveProperty(PaneMode.AlwaysVisible)
                                   .AddTo(this.Disposables);



            this.IsOptionPageOpen = this.SelectedInformationPage
                                    .Select(x => x > 0)
                                    .ToReactiveProperty()
                                    .AddTo(this.Disposables);


            //情報
            this.IsInformationPaneOpen = this.SelectedInformationPage
                                         .Select(x => this.IsInformationPane(x))
                                         .ToReactiveProperty(false)
                                         .AddTo(this.Disposables);

            this.OpenInformationPaneCommand = new ReactiveCommand()
                                              .WithSubscribe(_ =>
            {
                if (this.IsInformationPaneOpen.Value)
                {
                    if (this.prevPaneSelected == OptionPaneType.None)
                    {
                        this.prevPaneSelected = OptionPaneType.NoInformation;
                    }
                    this.ShowInformationPane(true);
                }
                else
                {
                    if (this.SelectedInformationPage.Value != OptionPaneType.Setting)
                    {
                        this.SelectedInformationPage.Value = OptionPaneType.None;
                    }
                }
            }, this.Disposables);



            //設定
            this.IsSettingPaneOpen = this.SelectedInformationPage
                                     .Select(x => x == OptionPaneType.Setting)
                                     .ToReactiveProperty(false)
                                     .AddTo(this.Disposables);

            this.OpenSettingPaneCommand = new ReactiveCommand()
                                          .WithSubscribe(_ =>
            {
                if (this.IsSettingPaneOpen.Value)
                {
                    this.SelectedInformationPage.Value = OptionPaneType.Setting;
                    this.IsPaneOpen.Value = true;
                }
                else
                {
                    if (this.SelectedInformationPage.Value == OptionPaneType.Setting)
                    {
                        this.SelectedInformationPage.Value = OptionPaneType.None;
                    }
                }
            }, this.Disposables);



            //ヘルプ
            this.IsHelpPaneOpen = this.SelectedInformationPage
                                  .Select(x => x == OptionPaneType.Help)
                                  .ToReactiveProperty(false)
                                  .AddTo(this.Disposables);

            this.OpenHelpPaneCommand = new ReactiveCommand()
                                       .WithSubscribe(_ =>
            {
                if (this.IsHelpPaneOpen.Value)
                {
                    this.SelectedInformationPage.Value = OptionPaneType.Help;
                    this.IsPaneOpen.Value = true;
                }
                else
                {
                    if (this.SelectedInformationPage.Value == OptionPaneType.Help)
                    {
                        this.SelectedInformationPage.Value = OptionPaneType.None;
                    }
                }
            }, this.Disposables);



            this.OptionPaneVisibility = this.SelectedInformationPage
                                        .Select(x => VisibilityHelper.Set(x > 0))
                                        .ToReactiveProperty()
                                        .AddTo(this.Disposables);

            this.FrameWidth = new ReactiveProperty <double>(300).AddTo(this.Disposables);

            this.IsFullScreen = client.SelectedPage.Select(_ => false).ToReactiveProperty().AddTo(this.Disposables);

            this.PageChangedSubject = new Subject <SplitViewDisplayMode>().AddTo(this.Disposables);

            this.PaneDisplayMode = this.IsPaneFixed
                                   .CombineLatest(this.DefaultPaneMode,
                                                  (paneFixed, defaultMode) =>
                                                  (defaultMode == PaneMode.Disabled) ? SplitViewDisplayMode.Overlay
                    : (paneFixed) ? SplitViewDisplayMode.CompactInline
                    : (defaultMode == PaneMode.HideInClosing) ? SplitViewDisplayMode.Overlay
                    : SplitViewDisplayMode.CompactOverlay)
                                   .ToReactiveProperty()
                                   .AddTo(this.Disposables);

            this.IsPaneOpen
            .Subscribe(x =>
            {
                if (!x)
                {
                    this.IsPaneFixed.Value             = false;
                    this.SelectedInformationPage.Value = OptionPaneType.None;
                    if (this.PaneDisplayMode.Value == SplitViewDisplayMode.CompactInline)
                    {
                        this.PaneDisplayMode.Value = SplitViewDisplayMode.CompactOverlay;
                    }
                }
            })
            .AddTo(this.Disposables);


            this.PaneOpenButtonVisibility = new ReactiveProperty <Visibility>(Visibility.Collapsed)
                                            .ToReactiveProperty()
                                            .AddTo(this.Disposables);

            var isWide = this.FrameWidth.Select(y => y > middleWindowWidth).Publish().RefCount();

            this.PaneFixButtonVisibility = isWide.Select(y => VisibilityHelper.Set(y))
                                           .ToReactiveProperty().AddTo(this.Disposables);
            isWide.Where(y => !y).Skip(2).Subscribe(y => this.IsPaneFixed.Value = false).AddTo(this.Disposables);

            this.JumpListWidth = this.IsOptionPageOpen.Select(x => x ? compactPaneWidth : openPaneWidth)
                                 .ToReactiveProperty().AddTo(this.Disposables);

            this.IsOptionPageOpen.Subscribe(x =>
            {
                if (x && this.SelectedInformationPage.Value != OptionPaneType.NoInformation &&
                    !core.IsAutoInformationPaneDisabled)
                {
                    this.IsPaneOpen.Value = true;
                }
            }).AddTo(this.Disposables);



            this.OpenSettingWindowCommand = new ReactiveCommand()
                                            .WithSubscribe(_ => ((App)Application.Current).ShowSettingWindow(-1), this.Disposables);

            this.OptionPageCommand = new ReactiveCommand <string>().AddTo(this.Disposables);



            this.IsPopupOpen = new ReactiveProperty <bool>(false).AddTo(this.Disposables);

            this.IsPopupOpen
            .Subscribe(x => this.KeyReceiver.Mode
                           = (int)(x ? KeyReceiverMode.PopupIsOpened : KeyReceiverMode.Normal))
            .AddTo(this.Disposables);



            this.prevPaneMode     = this.PaneDisplayMode.Value;
            this.prevPaneOpen     = this.IsPaneOpen.Value;
            this.prevPaneSelected = (OptionPaneType)this.SelectedInformationPage.Value;

            this.SelectedItems.ObserveProperty(x => x.Count).Pairwise().Subscribe(x =>
            {
                var autoOpen = !core.IsAutoInformationPaneDisabled;

                if (x.OldItem <= 0 && x.NewItem > 0)
                {
                    this.prevPaneMode     = this.PaneDisplayMode.Value;
                    this.prevPaneOpen     = this.IsPaneOpen.Value;
                    this.prevPaneSelected = (OptionPaneType)this.SelectedInformationPage.Value;

                    if (autoOpen && this.FrameWidth.Value > wideWindowWidth)
                    {
                        this.PaneDisplayMode.Value = SplitViewDisplayMode.CompactInline;
                        this.IsPaneOpen.Value      = true;
                    }

                    this.ShowInformationPane();
                }
                else if (x.OldItem > 0 && x.NewItem > 0 &&
                         (this.FrameWidth.Value > wideWindowWidth || this.IsPaneOpen.Value))
                {
                    this.ShowInformationPane();
                }
                else if (x.OldItem > 0 && x.NewItem <= 0)
                {
                    if (autoOpen)
                    {
                        this.PaneDisplayMode.Value = this.prevPaneMode;
                    }

                    this.ShowInformationPane();

                    if (autoOpen)
                    {
                        this.IsPaneOpen.Value = this.prevPaneOpen;
                    }
                }
            })
            .AddTo(this.Disposables);


            this.IsPaneFixed
            .Subscribe(x =>
            {
                if (x)
                {
                    this.prevPaneMode = SplitViewDisplayMode.CompactInline;
                    this.prevPaneOpen = true;
                }
                else
                {
                    this.prevPaneMode = SplitViewDisplayMode.CompactOverlay;
                    this.prevPaneOpen = false;
                }
            })
            .AddTo(this.Disposables);

            this.TagSelectorSortMode = core
                                       .ToReactivePropertyAsSynchronized(x => x.TagSelectorSortMode)
                                       .AddTo(this.Disposables);

            this.ExifVisibilityCheck = new ReactiveProperty <bool>(false).AddTo(this.Disposables);
            this.ExifVisibilityCheck
            .Skip(1)
            .Subscribe(x => core.Library.ExifManager.EnableAll(x)).AddTo(this.Disposables);

            this.IsExifEnabled = core.Library.ExifManager.HasVisibleItem
                                 .ToReadOnlyReactiveProperty().AddTo(this.Disposables);


            this.BackCommand = client.BackHistoryCount
                               .Select(x => x > 0)
                               .ToReactiveCommand()
                               .WithSubscribe(_ => client.Back(), this.Disposables);

            this.MoveToSearchPageCommand = new ReactiveCommand()
                                           .WithSubscribe(x => client.MoveToSearch(), this.Disposables);

            this.OpenPaneCommand = new ReactiveCommand()
                                   .WithSubscribe(_ => this.TogglePane(OptionPaneType.None), this.Disposables);

            // ウインドウへのファイルのドラッグ&ドロップ
            this.FileDropCommand = new ReactiveCommand()
                                   .WithSubscribe(obj =>
            {
                var files = obj as string[];
                if (files != null)
                {
                    this.Client.ActivateFiles(files);
                }
            }, this.Disposables);

            this.MouseExButtonSubject = new Subject <bool>().AddTo(this.Disposables);

            this.MouseExButtonLeftCommand = new ReactiveCommand()
                                            .WithSubscribe(_ =>
            {
                if (core.UseExtendedMouseButtonsToSwitchImage &&
                    client.SelectedPage.Value == PageType.Viewer)
                {
                    this.MouseExButtonSubject.OnNext(false);
                }
                else
                {
                    client.Back();
                }
            }, this.Disposables);

            this.MouseExButtonRightCommand = new ReactiveCommand()
                                             .WithSubscribe(_ =>
            {
                if (core.UseExtendedMouseButtonsToSwitchImage &&
                    client.SelectedPage.Value == PageType.Viewer)
                {
                    this.MouseExButtonSubject.OnNext(true);
                }
                else
                {
                    client.Forward();
                }
            }, this.Disposables);


            //Keyboard
            this.RegisterKeyReceiver(client);

            this.Catalog = new CatalogPageViewModel(this).AddTo(this.Disposables);
            this.Viewer  = new ViewerPageViewModel(this).AddTo(this.Disposables);
            this.Search  = new SearchPageViewModel(this).AddTo(this.Disposables);
        }