public Operation(IWlanWorker worker)
        {
            this._worker = worker;

            IsLoading = new BooleanNotifier();
            IsWorking = new BooleanNotifier();

            ShowLoadingTime();             // For debug
            ShowWorkingTime();             // For debug

            ReloadTimer = new ReactiveTimer(TimeSpan.FromSeconds(Settings.Current.AutoReloadInterval))
                          .AddTo(this.Subscription);
            ReloadTimer
            .Subscribe(async _ => await LoadProfilesAsync(true))
            .AddTo(this.Subscription);

            Settings.Current
            .ObserveProperty(x => x.AutoReloadInterval)
            .Throttle(TimeSpan.FromMilliseconds(100))
            .Subscribe(x => ReloadTimer.Interval = TimeSpan.FromSeconds(x))
            .AddTo(this.Subscription);

            this.ObserveProperty(x => x.IsAutoReloadEnabled)
            .Subscribe(isEnabled =>
            {
                if (isEnabled)
                {
                    ReloadTimer.Start();
                }
                else
                {
                    ReloadTimer.Stop();
                }
            })
            .AddTo(this.Subscription);

            this.ObserveProperty(x => x.IsSuspended, false)
            .Subscribe(async isSuspended =>
            {
                if (isSuspended)
                {
                    ReloadTimer.Stop();
                }
                else
                {
                    if (IsAutoReloadEnabled)
                    {
                        ReloadTimer.Start();
                    }
                    else
                    {
                        await LoadProfilesAsync(false);
                    }
                }
            })
            .AddTo(this.Subscription);

            var initialTask = LoadProfilesAsync(false);
        }
    public void TimerTestStart2()
    {
        var testScheduler = new TestScheduler();
        var recorder      = testScheduler.CreateObserver <long>();

        var timer = new ReactiveTimer(TimeSpan.FromSeconds(1), testScheduler);

        timer.Subscribe(recorder);

        timer.Start();

        testScheduler.AdvanceTo(TimeSpan.FromSeconds(3).Ticks + 1);

        recorder.Messages.Is(
            OnNext(TimeSpan.FromSeconds(0).Ticks + 1, 0L),
            OnNext(TimeSpan.FromSeconds(1).Ticks + 1, 1L),
            OnNext(TimeSpan.FromSeconds(2).Ticks + 1, 2L),
            OnNext(TimeSpan.FromSeconds(3).Ticks + 1, 3L));

        timer.Stop();
        recorder.Messages.Clear();

        testScheduler.AdvanceBy(TimeSpan.FromSeconds(5).Ticks);

        recorder.Messages.Count.Is(0);
    }
        public void TimerTestStart2()
        {
            var testScheduler = new TestScheduler();
            var recorder = testScheduler.CreateObserver<long>();

            var timer = new ReactiveTimer(TimeSpan.FromSeconds(1), testScheduler);
            timer.Subscribe(recorder);

            timer.Start();

            testScheduler.AdvanceTo(TimeSpan.FromSeconds(3).Ticks + 1);

            recorder.Messages.Is(
                OnNext(TimeSpan.FromSeconds(0).Ticks + 1, 0L),
                OnNext(TimeSpan.FromSeconds(1).Ticks + 1, 1L),
                OnNext(TimeSpan.FromSeconds(2).Ticks + 1, 2L),
                OnNext(TimeSpan.FromSeconds(3).Ticks + 1, 3L));
            
            timer.Stop();
            recorder.Messages.Clear();

            testScheduler.AdvanceBy(TimeSpan.FromSeconds(5).Ticks);

            recorder.Messages.Count.Is(0);
        }
Beispiel #4
0
		public Operation(IWlanWorker worker)
		{
			this._worker = worker;

			IsLoading = new BooleanNotifier();
			IsWorking = new BooleanNotifier();

			ShowLoadingTime(); // For debug
			ShowWorkingTime(); // For debug

			ReloadTimer = new ReactiveTimer(TimeSpan.FromSeconds(Settings.Current.AutoReloadInterval))
				.AddTo(this.Subscription);
			ReloadTimer
				.Subscribe(async _ => await LoadProfilesAsync(true))
				.AddTo(this.Subscription);

			Settings.Current
				.ObserveProperty(x => x.AutoReloadInterval)
				.Throttle(TimeSpan.FromMilliseconds(100))
				.Subscribe(x => ReloadTimer.Interval = TimeSpan.FromSeconds(x))
				.AddTo(this.Subscription);

			this.ObserveProperty(x => x.IsAutoReloadEnabled)
				.Subscribe(isEnabled =>
				{
					if (isEnabled)
						ReloadTimer.Start();
					else
						ReloadTimer.Stop();
				})
				.AddTo(this.Subscription);

			this.ObserveProperty(x => x.IsSuspended, false)
				.Subscribe(async isSuspended =>
				{
					if (isSuspended)
					{
						ReloadTimer.Stop();
					}
					else
					{
						if (IsAutoReloadEnabled)
							ReloadTimer.Start();
						else
							await LoadProfilesAsync(false);
					}
				})
				.AddTo(this.Subscription);

			var initialTask = LoadProfilesAsync(false);
		}
    public void IsEnabledTest()
    {
        var testScheduler = new TestScheduler();
        var recorder      = testScheduler.CreateObserver <long>();

        var timer = new ReactiveTimer(TimeSpan.FromSeconds(1), testScheduler);
        var isEnabledChangedCounter = 0;

        timer.ObserveProperty(x => x.IsEnabled, false).Subscribe(_ => isEnabledChangedCounter++);
        timer.IsEnabled.IsFalse();
        timer.Start();
        timer.IsEnabled.IsTrue();
        timer.Stop();
        timer.IsEnabled.IsFalse();
        isEnabledChangedCounter.Is(2);
    }
    public void TimerTest1()
    {
        var testScheduler = new TestScheduler();
        var recorder      = testScheduler.CreateObserver <long>();
        var timer         = new ReactiveTimer(TimeSpan.FromSeconds(1), testScheduler);

        timer.Subscribe(recorder);

        timer.Start(TimeSpan.FromSeconds(10));
        testScheduler.AdvanceTo(TimeSpan.FromSeconds(13).Ticks);
        recorder.Messages.Is(
            OnNext(TimeSpan.FromSeconds(10).Ticks, 0L),
            OnNext(TimeSpan.FromSeconds(11).Ticks, 1L),
            OnNext(TimeSpan.FromSeconds(12).Ticks, 2L),
            OnNext(TimeSpan.FromSeconds(13).Ticks, 3L));
        recorder.Messages.Clear();

        timer.Stop();
        testScheduler.AdvanceBy(TimeSpan.FromSeconds(5).Ticks);
        recorder.Messages.Count.Is(0);

        timer.Start();
        var reStartClock = testScheduler.Clock + 1;

        testScheduler.AdvanceBy(TimeSpan.FromSeconds(3).Ticks + 1);
        recorder.Messages.Is(
            OnNext(reStartClock, 4L),
            OnNext(reStartClock + TimeSpan.FromSeconds(1).Ticks, 5L),
            OnNext(reStartClock + TimeSpan.FromSeconds(2).Ticks, 6L),
            OnNext(reStartClock + TimeSpan.FromSeconds(3).Ticks, 7L));
        recorder.Messages.Clear();

        timer.Reset();
        testScheduler.AdvanceBy(TimeSpan.FromSeconds(5).Ticks);
        recorder.Messages.Count.Is(0);

        timer.Dispose();

        recorder.Messages.Is(OnCompleted <long>(testScheduler.Clock));

        timer.Dispose(); // dispose again
    }
        public void TimerTest1()
        {
            var testScheduler = new TestScheduler();
            var recorder = testScheduler.CreateObserver<long>();
            var timer = new ReactiveTimer(TimeSpan.FromSeconds(1), testScheduler);
            timer.Subscribe(recorder);

            timer.Start(TimeSpan.FromSeconds(10));
            testScheduler.AdvanceTo(TimeSpan.FromSeconds(13).Ticks);
            recorder.Messages.Is(
                OnNext(TimeSpan.FromSeconds(10).Ticks, 0L),
                OnNext(TimeSpan.FromSeconds(11).Ticks, 1L),
                OnNext(TimeSpan.FromSeconds(12).Ticks, 2L),
                OnNext(TimeSpan.FromSeconds(13).Ticks, 3L));
            recorder.Messages.Clear();

            timer.Stop();
            testScheduler.AdvanceBy(TimeSpan.FromSeconds(5).Ticks);
            recorder.Messages.Count.Is(0);

            timer.Start();
            var reStartClock = testScheduler.Clock + 1;
            testScheduler.AdvanceBy(TimeSpan.FromSeconds(3).Ticks + 1);
            recorder.Messages.Is(
                OnNext(reStartClock, 4L),
                OnNext(reStartClock + TimeSpan.FromSeconds(1).Ticks, 5L),
                OnNext(reStartClock + TimeSpan.FromSeconds(2).Ticks, 6L),
                OnNext(reStartClock + TimeSpan.FromSeconds(3).Ticks, 7L));
            recorder.Messages.Clear();

            timer.Reset();
            testScheduler.AdvanceBy(TimeSpan.FromSeconds(5).Ticks);
            recorder.Messages.Count.Is(0);

            timer.Dispose();

            recorder.Messages.Is(OnCompleted<long>(testScheduler.Clock));

            timer.Dispose(); // dispose again
        }
Beispiel #8
0
        public MainController(StartupAgent agent, IWlanWorker worker)
        {
            StartupAgent = agent ?? throw new ArgumentNullException(nameof(agent));

            Profiles = new ObservableCollection <ProfileItem>();
            BindingOperations.EnableCollectionSynchronization(Profiles, _profilesLock);

            NotifyIconContainer = new NotifyIconContainer();
            NotifyIconContainer.MouseLeftButtonClick  += OnMainWindowShowRequested;
            NotifyIconContainer.MouseRightButtonClick += OnMenuWindowShowRequested;

            this._worker = worker;

            IsUpdating = new BooleanNotifier();
            IsWorking  = new BooleanNotifier();

            ShowUpdatingTime();            // For debug
            ShowWorkingTime();             // For debug

            RushesRescan = new ReactiveProperty <bool>()
                           .AddTo(this.Subscription);

            EngagesPriority = new ReactiveProperty <bool>()
                              .AddTo(this.Subscription);
            EngagesPriority
            .Subscribe(_ => SetNotifyIconText())
            .AddTo(this.Subscription);

            #region Update

            RescanTimer = new ReactiveTimer(TimeSpan.FromSeconds(Settings.Current.RescanInterval))
                          .AddTo(this.Subscription);

            RescanCommand = IsUpdating
                            .Inverse()
                            .ObserveOnUIDispatcher()     // This is for thread access by ReactiveCommand.
                            .ToReactiveCommand();
            RescanCommand
            .Merge(EngagesPriority.Where(x => x).Select(x => x as object))
            .Merge(RescanTimer.Select(x => x as object))
            .Subscribe(async _ => await ScanNetworkAsync())
            .AddTo(this.Subscription);

            Settings.Current
            .ObserveProperty(x => x.RescanInterval)
            .Subscribe(rescanInterval => RescanTimer.Interval = TimeSpan.FromSeconds(rescanInterval))
            .AddTo(this.Subscription);

            RushesRescan
            .Subscribe(rushesRescan =>
            {
                if (rushesRescan)
                {
                    RescanTimer.Start();
                }
                else
                {
                    RescanTimer.Stop();
                }

                SetNotifyIconText();
            })
            .AddTo(this.Subscription);

            var networkRefreshed = Observable.FromEventPattern(
                h => _worker.NetworkRefreshed += h,
                h => _worker.NetworkRefreshed -= h);
            var availabilityChanged = Observable.FromEventPattern(
                h => _worker.AvailabilityChanged += h,
                h => _worker.AvailabilityChanged -= h);
            var interfaceChanged = Observable.FromEventPattern(
                h => _worker.InterfaceChanged += h,
                h => _worker.InterfaceChanged -= h);
            var connectionChanged = Observable.FromEventPattern(
                h => _worker.ConnectionChanged += h,
                h => _worker.ConnectionChanged -= h);
            var profileChanged = Observable.FromEventPattern(
                h => _worker.ProfileChanged += h,
                h => _worker.ProfileChanged -= h);
            Observable.Merge(networkRefreshed, availabilityChanged, interfaceChanged, connectionChanged, profileChanged)
            .Throttle(TimeSpan.FromMilliseconds(100))
            .Subscribe(async _ =>
            {
                if (RushesRescan.Value)
                {
                    RescanTimer.Start(TimeSpan.FromSeconds(Settings.Current.RescanInterval));                             // Wait for due time.
                }
                await LoadProfilesAsync();
            })
            .AddTo(this.Subscription);

            #endregion

            #region Close

            CloseCommand = new ReactiveProperty <bool>(true)
                           .ToReactiveCommand();
            CloseCommand
            .Subscribe(_ => _current.Shutdown())
            .AddTo(this.Subscription);

            #endregion
        }
 public void Pause()
 {
     Status.Value = TimerStatus.PAUSE;
     ReactiveTimer.Stop();
 }
Beispiel #10
0
        public async void OnNavigatedTo(NavigationParameters parameters)
        {
            App.AppStatus = "ResultPage";
            App.EventList.Add(Observable.FromEventPattern <PositionEventArgs>(
                                  h => CrossGeolocator.Current.PositionChanged += h, h => CrossGeolocator.Current.PositionChanged -= h)
                              .Subscribe(e => OnPositionChanged(e.Sender, e.EventArgs)));

            //CrossGeolocator.Current.PositionChanged += OnPositionChanged;
            if (CrossGeolocator.Current.IsListening == false)
            {
                CrossGeolocator.Current.DesiredAccuracy = 1;
                await CrossGeolocator.Current.StartListeningAsync(minimumTime : TimeSpan.FromMilliseconds(1000), minimumDistance : 0, includeHeading : false);
            }

            _calculatorParam = parameters[ParamCalculator] as ECOLOGCalculator;
            _calculatorMine  = new ECOLOGCalculator();
            _calculatorMine.Init();

            _lostEnergy  = _calculatorParam.LostEnergyList.Sum();
            _transitTime = (int)(_calculatorParam.PositionCollection.Last().Timestamp -
                                 _calculatorParam.PositionCollection.First().Timestamp).TotalSeconds;
            var semanticLink = parameters[ParamSemanticLink] as SemanticLink;

            _ecgModel = ECGModel.GetECGModel(semanticLink);

            //DependencyService.Get<IAudio>().PlayAudioFile("broadcasting.mp3");

            /*** デバッグコード ***/

            /*Debug.WriteLine("Count: " + _calculatorParam.PositionCollection.Count);
             * Debug.WriteLine("LostEnergy: " + _calculatorParam.LostEnergyList.Sum());
             * Debug.WriteLine("AirResistance: " + _calculatorParam.AirResistanceList.Sum());
             * Debug.WriteLine("Rolling: " + _calculatorParam.RollingResistanceList.Sum());
             * Debug.WriteLine("Convert: " + _calculatorParam.ConvertLossList.Sum());
             * Debug.WriteLine("Regene: " + _calculatorParam.RegeneLossList.Sum());*/
            /*** デバッグコード ***/

            PlotModel.Value = CreatePlotModel();

            var timer = new ReactiveTimer(TimeSpan.FromSeconds(1));

            timer.Subscribe(v =>
            {
                Device.BeginInvokeOnMainThread(() =>
                {
                    _count++;
                    /*** テストコード ***/
                    //OnPositionChanged(null, new PositionEventArgs(TestPosition.TestPositions[TestPosition.Index]));
                    //TestPosition.Index++;
                    /*** テストコード ***/

                    if (_count >= 10)
                    {
                        timer.Stop();
                        if (_semanticLink != null)
                        {
                            var parameter = new NavigationParameters
                            {
                                { ECGsPageViewModel.ParamCalculator, _calculatorMine },
                                { ECGsPageViewModel.ParamSemanticLink, _semanticLink }
                            };
                            _navigationService.NavigateAsync($"/{nameof(ECGsPage)}", parameter);
                        }
                        else
                        {
                            _navigationService.NavigateAsync($"/{nameof(MapPage)}");
                        }
                    }
                });
            });
            timer.Start();
        }
Beispiel #11
0
        internal MotorViewModel(Motor motor)
        {
            CultureInfo culture = CultureInfo.InvariantCulture;

            MessageBox = motor
                         .ObserveProperty(x => x.MessageBox)
                         .Do(_ => MessageBox?.Value.Dispose())
                         .Select(x => new MessageBoxViewModel(x))
                         .ToReadOnlyReactivePropertySlim()
                         .AddTo(disposable);

            ToolTipVertexPitch = motor
                                 .ObserveProperty(x => x.ToolTipVertexPitch)
                                 .Do(_ => ToolTipVertexPitch?.Value.Dispose())
                                 .Select(x => new ToolTipViewModel(x))
                                 .ToReadOnlyReactivePropertySlim()
                                 .AddTo(disposable);

            ToolTipVertexVolume = motor
                                  .ObserveProperty(x => x.ToolTipVertexVolume)
                                  .Do(_ => ToolTipVertexVolume?.Value.Dispose())
                                  .Select(x => new ToolTipViewModel(x))
                                  .ToReadOnlyReactivePropertySlim()
                                  .AddTo(disposable);

            CurrentModifierKeys = motor
                                  .ToReactivePropertyAsSynchronized(x => x.CurrentModifierKeys)
                                  .AddTo(disposable);

            CurrentCursorType = motor
                                .ObserveProperty(x => x.CurrentCursorType)
                                .ToReadOnlyReactivePropertySlim()
                                .AddTo(disposable);

            MinVelocity = motor
                          .ToReactivePropertyAsSynchronized(
                x => x.MinVelocity,
                x => x.ToString(culture),
                x => double.Parse(x, NumberStyles.Float, culture),
                ignoreValidationErrorValue: true
                )
                          .AddTo(disposable);

            MinVelocity.Subscribe(_ => motor.IsRefreshGlControl = true).AddTo(disposable);

            MaxVelocity = motor
                          .ToReactivePropertyAsSynchronized(
                x => x.MaxVelocity,
                x => x.ToString(culture),
                x => double.Parse(x, NumberStyles.Float, culture),
                ignoreValidationErrorValue: true
                )
                          .AddTo(disposable);

            MaxVelocity.Subscribe(_ => motor.IsRefreshGlControl = true).AddTo(disposable);

            MinPitch = motor
                       .ToReactivePropertyAsSynchronized(
                x => x.MinPitch,
                x => x.ToString(culture),
                x => double.Parse(x, NumberStyles.Float, culture),
                ignoreValidationErrorValue: true
                )
                       .AddTo(disposable);

            MinPitch.Subscribe(_ => motor.IsRefreshGlControl = true).AddTo(disposable);

            MaxPitch = motor
                       .ToReactivePropertyAsSynchronized(
                x => x.MaxPitch,
                x => x.ToString(culture),
                x => double.Parse(x, NumberStyles.Float, culture),
                ignoreValidationErrorValue: true
                )
                       .AddTo(disposable);

            MaxPitch.Subscribe(_ => motor.IsRefreshGlControl = true).AddTo(disposable);

            MinVolume = motor
                        .ToReactivePropertyAsSynchronized(
                x => x.MinVolume,
                x => x.ToString(culture),
                x => double.Parse(x, NumberStyles.Float, culture),
                ignoreValidationErrorValue: true
                )
                        .AddTo(disposable);

            MinVolume.Subscribe(_ => motor.IsRefreshGlControl = true).AddTo(disposable);

            MaxVolume = motor
                        .ToReactivePropertyAsSynchronized(
                x => x.MaxVolume,
                x => x.ToString(culture),
                x => double.Parse(x, NumberStyles.Float, culture),
                ignoreValidationErrorValue: true
                )
                        .AddTo(disposable);

            MaxVolume.Subscribe(_ => motor.IsRefreshGlControl = true).AddTo(disposable);

            NowVelocity = motor
                          .ObserveProperty(x => x.NowVelocity)
                          .ToReadOnlyReactivePropertySlim()
                          .AddTo(disposable);

            NowPitch = motor
                       .ObserveProperty(x => x.NowPitch)
                       .ToReadOnlyReactivePropertySlim()
                       .AddTo(disposable);

            NowVolume = motor
                        .ObserveProperty(x => x.NowVolume)
                        .ToReadOnlyReactivePropertySlim()
                        .AddTo(disposable);

            CurrentSelectedTrack = motor
                                   .ObserveProperty(x => x.SelectedTrackInfo)
                                   .ToReadOnlyReactivePropertySlim()
                                   .AddTo(disposable);

            CurrentSelectedTrack
            .Subscribe(_ =>
            {
                motor.ResetSelect();
                motor.IsRefreshGlControl = true;
            })
            .AddTo(disposable);

            CurrentInputMode = motor
                               .ObserveProperty(x => x.CurrentInputMode)
                               .ToReadOnlyReactivePropertySlim()
                               .AddTo(disposable);

            CurrentInputMode
            .Subscribe(_ =>
            {
                motor.ResetSelect();
                motor.IsRefreshGlControl = true;
            })
            .AddTo(disposable);

            SelectedSoundIndex = motor
                                 .ToReactivePropertyAsSynchronized(x => x.SelectedSoundIndex)
                                 .AddTo(disposable);

            CurrentToolMode = motor
                              .ObserveProperty(x => x.CurrentToolMode)
                              .ToReadOnlyReactivePropertySlim()
                              .AddTo(disposable);

            CurrentToolMode
            .Subscribe(_ =>
            {
                motor.ResetSelect();
                motor.IsRefreshGlControl = true;
            })
            .AddTo(disposable);

            StoppedSim = motor
                         .ObserveProperty(x => x.CurrentSimState)
                         .Select(x => x == Motor.SimulationState.Disable || x == Motor.SimulationState.Stopped)
                         .ToReadOnlyReactivePropertySlim()
                         .AddTo(disposable);

            RunIndex = motor
                       .ToReactivePropertyAsSynchronized(x => x.RunIndex)
                       .AddTo(disposable);

            IsPlayTrack1 = motor
                           .ToReactivePropertyAsSynchronized(x => x.IsPlayTrack1)
                           .AddTo(disposable);

            IsPlayTrack2 = motor
                           .ToReactivePropertyAsSynchronized(x => x.IsPlayTrack2)
                           .AddTo(disposable);

            IsLoop = motor
                     .ToReactivePropertyAsSynchronized(x => x.IsLoop)
                     .AddTo(disposable);

            IsConstant = motor
                         .ToReactivePropertyAsSynchronized(x => x.IsConstant)
                         .AddTo(disposable);

            Acceleration = motor
                           .ToReactivePropertyAsSynchronized(
                x => x.Acceleration,
                x => x.ToString(culture),
                x => double.Parse(x, NumberStyles.Float, culture),
                ignoreValidationErrorValue: true
                )
                           .SetValidateNotifyError(x =>
            {
                double result;
                string message;

                Utilities.TryParse(x, NumberRange.NonNegative, out result, out message);

                return(message);
            })
                           .AddTo(disposable);

            StartSpeed = motor
                         .ToReactivePropertyAsSynchronized(
                x => x.StartSpeed,
                x => x.ToString(culture),
                x => double.Parse(x, NumberStyles.Float, culture),
                ignoreValidationErrorValue: true
                )
                         .SetValidateNotifyError(x =>
            {
                double result;
                string message;

                Utilities.TryParse(x, NumberRange.NonNegative, out result, out message);

                return(message);
            })
                         .AddTo(disposable);

            EndSpeed = motor
                       .ToReactivePropertyAsSynchronized(
                x => x.EndSpeed,
                x => x.ToString(culture),
                x => double.Parse(x, NumberStyles.Float, culture),
                ignoreValidationErrorValue: true
                )
                       .SetValidateNotifyError(x =>
            {
                double result;
                string message;

                Utilities.TryParse(x, NumberRange.NonNegative, out result, out message);

                return(message);
            })
                       .AddTo(disposable);

            EnabledDirect = new[]
            {
                CurrentInputMode.Select(x => x != Motor.InputMode.SoundIndex),
                StoppedSim
            }
            .CombineLatestValuesAreAllTrue()
            .ToReadOnlyReactivePropertySlim()
            .AddTo(disposable);

            DirectX = new ReactiveProperty <string>(0.0.ToString(culture))
                      .SetValidateNotifyError(x =>
            {
                double result;
                string message;

                switch (CurrentToolMode.Value)
                {
                case Motor.ToolMode.Move:
                    Utilities.TryParse(x, NumberRange.Any, out result, out message);
                    break;

                case Motor.ToolMode.Dot:
                    Utilities.TryParse(x, NumberRange.NonNegative, out result, out message);
                    break;

                default:
                    message = null;
                    break;
                }

                return(message);
            })
                      .AddTo(disposable);

            DirectY = new ReactiveProperty <string>(0.0.ToString(culture))
                      .SetValidateNotifyError(x =>
            {
                double result;
                string message;

                switch (CurrentToolMode.Value)
                {
                case Motor.ToolMode.Move:
                    Utilities.TryParse(x, NumberRange.Any, out result, out message);
                    break;

                case Motor.ToolMode.Dot:
                    Utilities.TryParse(x, NumberRange.NonNegative, out result, out message);
                    break;

                default:
                    message = null;
                    break;
                }

                return(message);
            })
                      .AddTo(disposable);

            CurrentToolMode
            .Subscribe(_ =>
            {
                DirectX.ForceValidate();
                DirectY.ForceValidate();
            })
            .AddTo(disposable);

            GlControlWidth = motor
                             .ToReactivePropertyAsSynchronized(
                x => x.GlControlWidth,
                ignoreValidationErrorValue: true
                )
                             .SetValidateNotifyError(x => x <= 0 ? string.Empty : null)
                             .AddTo(disposable);

            GlControlWidth.Subscribe(_ => motor.IsRefreshGlControl = true).AddTo(disposable);

            GlControlHeight = motor
                              .ToReactivePropertyAsSynchronized(
                x => x.GlControlHeight,
                ignoreValidationErrorValue: true
                )
                              .SetValidateNotifyError(x => x <= 0 ? string.Empty : null)
                              .AddTo(disposable);

            GlControlHeight.Subscribe(_ => motor.IsRefreshGlControl = true).AddTo(disposable);

            IsRefreshGlControl = motor
                                 .ToReactivePropertyAsSynchronized(x => x.IsRefreshGlControl)
                                 .AddTo(disposable);

            ChangeSelectedTrack = new ReactiveCommand <Motor.TrackInfo>().WithSubscribe(x => motor.SelectedTrackInfo = x).AddTo(disposable);

            ChangeInputMode = new ReactiveCommand <Motor.InputMode>().WithSubscribe(x => motor.CurrentInputMode = x).AddTo(disposable);

            ChangeToolMode = new[]
            {
                CurrentInputMode.Select(x => x != Motor.InputMode.SoundIndex),
                StoppedSim
            }
            .CombineLatestValuesAreAllTrue()
            .ToReactiveCommand <Motor.ToolMode>()
            .WithSubscribe(x => motor.CurrentToolMode = x)
            .AddTo(disposable);

            ZoomIn = new ReactiveCommand().WithSubscribe(motor.ZoomIn).AddTo(disposable);

            ZoomOut = new ReactiveCommand().WithSubscribe(motor.ZoomOut).AddTo(disposable);

            Reset = new ReactiveCommand().WithSubscribe(motor.Reset).AddTo(disposable);

            MoveLeft = new ReactiveCommand().WithSubscribe(motor.MoveLeft).AddTo(disposable);

            MoveRight = new ReactiveCommand().WithSubscribe(motor.MoveRight).AddTo(disposable);

            MoveBottom = new ReactiveCommand().WithSubscribe(motor.MoveBottom).AddTo(disposable);

            MoveTop = new ReactiveCommand().WithSubscribe(motor.MoveTop).AddTo(disposable);

            Undo = new[]
            {
                new[]
                {
                    motor.PropertyChangedAsObservable().Where(x => x.PropertyName == nameof(motor.SelectedTrackInfo)).OfType <object>(),
                    motor.PrevTrackStates.CollectionChangedAsObservable().OfType <object>()
                }
                .Merge()
                .Select(_ => motor.PrevTrackStates.Any(x => x.Info == motor.SelectedTrackInfo)),
                StoppedSim
            }
            .CombineLatestValuesAreAllTrue()
            .ToReactiveCommand(false)
            .WithSubscribe(motor.Undo)
            .AddTo(disposable);

            Redo = new[]
            {
                new[]
                {
                    motor.PropertyChangedAsObservable().Where(x => x.PropertyName == nameof(motor.SelectedTrackInfo)).OfType <object>(),
                    motor.NextTrackStates.CollectionChangedAsObservable().OfType <object>()
                }
                .Merge()
                .Select(_ => motor.NextTrackStates.Any(x => x.Info == motor.SelectedTrackInfo)),
                StoppedSim
            }
            .CombineLatestValuesAreAllTrue()
            .ToReactiveCommand(false)
            .WithSubscribe(motor.Redo)
            .AddTo(disposable);

            TearingOff = StoppedSim
                         .ToReactiveCommand()
                         .WithSubscribe(motor.TearingOff)
                         .AddTo(disposable);

            Copy = StoppedSim
                   .ToReactiveCommand()
                   .WithSubscribe(motor.Copy)
                   .AddTo(disposable);

            Paste = new[]
            {
                motor.ObserveProperty(x => x.CopyTrack).Select(x => x != null),
                StoppedSim
            }
            .CombineLatestValuesAreAllTrue()
            .ToReactiveCommand()
            .WithSubscribe(motor.Paste)
            .AddTo(disposable);

            Cleanup = StoppedSim
                      .ToReactiveCommand()
                      .WithSubscribe(motor.Cleanup)
                      .AddTo(disposable);

            Delete = StoppedSim
                     .ToReactiveCommand()
                     .WithSubscribe(motor.Delete)
                     .AddTo(disposable);

            MouseDown = new ReactiveCommand <InputEventModel.EventArgs>().WithSubscribe(motor.MouseDown).AddTo(disposable);

            MouseMove = new ReactiveCommand <InputEventModel.EventArgs>().WithSubscribe(motor.MouseMove).AddTo(disposable);

            MouseUp = new ReactiveCommand().WithSubscribe(motor.MouseUp).AddTo(disposable);

            DirectDot = new[]
            {
                StoppedSim,
                CurrentToolMode.Select(x => x == Motor.ToolMode.Dot),
                DirectX.ObserveHasErrors.Select(x => !x),
                DirectY.ObserveHasErrors.Select(x => !x)
            }
            .CombineLatestValuesAreAllTrue()
            .ToReactiveCommand()
            .WithSubscribe(() => motor.DirectDot(double.Parse(DirectX.Value), double.Parse(DirectY.Value)))
            .AddTo(disposable);

            DirectMove = new[]
            {
                StoppedSim,
                CurrentToolMode.Select(x => x == Motor.ToolMode.Move),
                DirectX.ObserveHasErrors.Select(x => !x),
                DirectY.ObserveHasErrors.Select(x => !x)
            }
            .CombineLatestValuesAreAllTrue()
            .ToReactiveCommand()
            .WithSubscribe(() => motor.DirectMove(double.Parse(DirectX.Value), double.Parse(DirectY.Value)))
            .AddTo(disposable);

            SwapSpeed = StoppedSim
                        .ToReactiveCommand()
                        .WithSubscribe(() =>
            {
                string tmp       = StartSpeed.Value;
                StartSpeed.Value = EndSpeed.Value;
                EndSpeed.Value   = tmp;
            })
                        .AddTo(disposable);

            SimulationTimer = new ReactiveTimer(TimeSpan.FromMilliseconds(1000.0 / 30.0));

            SimulationTimer
            .Subscribe(_ =>
            {
                SimulationTimer.Stop();
                Observable.Start(motor.RunSimulation, UIDispatcherScheduler.Default).Wait();
                SimulationTimer.Start(TimeSpan.FromMilliseconds(1000.0 / 30.0));
            })
            .AddTo(disposable);

            motor.ObserveProperty(x => x.CurrentSimState)
            .ToReadOnlyReactivePropertySlim()
            .Subscribe(x =>
            {
                switch (x)
                {
                case Motor.SimulationState.Started:
                    SimulationTimer.Start();
                    break;

                default:
                    SimulationTimer.Stop();
                    break;
                }
            })
            .AddTo(disposable);

            StartSimulation = motor
                              .ObserveProperty(x => x.CurrentSimState)
                              .Select(x => x == Motor.SimulationState.Paused || x == Motor.SimulationState.Stopped)
                              .ToReactiveCommand()
                              .WithSubscribe(motor.StartSimulation)
                              .AddTo(disposable);

            PauseSimulation = motor
                              .ObserveProperty(x => x.CurrentSimState)
                              .Select(x => x == Motor.SimulationState.Started)
                              .ToReactiveCommand()
                              .WithSubscribe(motor.PauseSimulation)
                              .AddTo(disposable);

            StopSimulation = motor
                             .ObserveProperty(x => x.CurrentSimState)
                             .Select(x => x == Motor.SimulationState.Paused || x == Motor.SimulationState.Started)
                             .ToReactiveCommand()
                             .WithSubscribe(motor.StopSimulation)
                             .AddTo(disposable);

            DrawGlControl = new ReactiveCommand()
                            .WithSubscribe(motor.DrawGlControl)
                            .AddTo(disposable);

            MinVelocity
            .SetValidateNotifyError(x =>
            {
                double min;
                string message;

                if (Utilities.TryParse(x, NumberRange.NonNegative, out min, out message))
                {
                    double max;

                    if (Utilities.TryParse(MaxVelocity.Value, NumberRange.NonNegative, out max) && min >= max)
                    {
                        message = "MinはMax未満でなければなりません。";
                    }
                }

                return(message);
            })
            .Subscribe(_ => MaxVelocity.ForceValidate())
            .AddTo(disposable);

            MinVelocity.ObserveHasErrors
            .ToReadOnlyReactivePropertySlim(mode: ReactivePropertyMode.DistinctUntilChanged)
            .Where(x => !x)
            .Subscribe(_ => MinVelocity.ForceNotify())
            .AddTo(disposable);

            MaxVelocity
            .SetValidateNotifyError(x =>
            {
                double max;
                string message;

                if (Utilities.TryParse(x, NumberRange.NonNegative, out max, out message))
                {
                    double min;

                    if (Utilities.TryParse(MinVelocity.Value, NumberRange.NonNegative, out min) && max <= min)
                    {
                        message = "MinはMax未満でなければなりません。";
                    }
                }

                return(message);
            })
            .Subscribe(_ => MinVelocity.ForceValidate())
            .AddTo(disposable);

            MaxVelocity.ObserveHasErrors
            .ToReadOnlyReactivePropertySlim(mode: ReactivePropertyMode.DistinctUntilChanged)
            .Where(x => !x)
            .Subscribe(_ => MaxVelocity.ForceNotify())
            .AddTo(disposable);

            MinPitch
            .SetValidateNotifyError(x =>
            {
                double min;
                string message;

                if (Utilities.TryParse(x, NumberRange.NonNegative, out min, out message))
                {
                    double max;

                    if (Utilities.TryParse(MaxPitch.Value, NumberRange.NonNegative, out max) && min >= max)
                    {
                        message = "MinはMax未満でなければなりません。";
                    }
                }

                return(message);
            })
            .Subscribe(_ => MaxPitch.ForceValidate())
            .AddTo(disposable);

            MinPitch.ObserveHasErrors
            .ToReadOnlyReactivePropertySlim(mode: ReactivePropertyMode.DistinctUntilChanged)
            .Where(x => !x)
            .Subscribe(_ => MinPitch.ForceNotify())
            .AddTo(disposable);

            MaxPitch
            .SetValidateNotifyError(x =>
            {
                double max;
                string message;

                if (Utilities.TryParse(x, NumberRange.NonNegative, out max, out message))
                {
                    double min;

                    if (Utilities.TryParse(MinPitch.Value, NumberRange.NonNegative, out min) && max <= min)
                    {
                        message = "MinはMax未満でなければなりません。";
                    }
                }

                return(message);
            })
            .Subscribe(_ => MinPitch.ForceValidate())
            .AddTo(disposable);

            MaxPitch.ObserveHasErrors
            .ToReadOnlyReactivePropertySlim(mode: ReactivePropertyMode.DistinctUntilChanged)
            .Where(x => !x)
            .Subscribe(_ => MaxPitch.ForceNotify())
            .AddTo(disposable);

            MinVolume
            .SetValidateNotifyError(x =>
            {
                double min;
                string message;

                if (Utilities.TryParse(x, NumberRange.NonNegative, out min, out message))
                {
                    double max;

                    if (Utilities.TryParse(MaxVolume.Value, NumberRange.NonNegative, out max) && min >= max)
                    {
                        message = "MinはMax未満でなければなりません。";
                    }
                }

                return(message);
            })
            .Subscribe(_ => MaxVolume.ForceValidate())
            .AddTo(disposable);

            MinVolume.ObserveHasErrors
            .ToReadOnlyReactivePropertySlim(mode: ReactivePropertyMode.DistinctUntilChanged)
            .Where(x => !x)
            .Subscribe(_ => MinVolume.ForceNotify())
            .AddTo(disposable);

            MaxVolume
            .SetValidateNotifyError(x =>
            {
                double max;
                string message;

                if (Utilities.TryParse(x, NumberRange.NonNegative, out max, out message))
                {
                    double min;

                    if (Utilities.TryParse(MinVolume.Value, NumberRange.NonNegative, out min) && max <= min)
                    {
                        message = "MinはMax未満でなければなりません。";
                    }
                }

                return(message);
            })
            .Subscribe(_ => MinVolume.ForceValidate())
            .AddTo(disposable);

            MaxVolume.ObserveHasErrors
            .ToReadOnlyReactivePropertySlim(mode: ReactivePropertyMode.DistinctUntilChanged)
            .Where(x => !x)
            .Subscribe(_ => MaxVolume.ForceNotify())
            .AddTo(disposable);
        }