/// <summary>
        /// Creates a square image and attaches an event handler to the layout changed event that
        /// adds the the square in the upper right-hand corner of the TextView via the adornment layer
        /// </summary>
        /// <param name="view">The <see cref="IWpfTextView"/> upon which the adornment will be drawn</param>
        public SaveAllTheTimeAdornment(IWpfTextView view, IVisualStudioOps vsOps)
        {
            _view           = view;
            _adornmentLayer = view.GetAdornmentLayer("SaveAllTheTimeAdornment");

            var filePath = getFilePathFromView(_view);

            if (shouldSuppressAdornment(filePath))
            {
                _inner = Disposable.Empty;
                return;
            }

            var commitControl = new CommitHintView()
            {
                ViewModel = new CommitHintViewModel(filePath, vsOps, settings),
            };

            var disp = new CompositeDisposable();

            var sizeChanged = Observable.Merge(
                Observable.FromEventPattern <EventHandler, EventArgs>(x => _view.ViewportHeightChanged += x, x => _view.ViewportHeightChanged -= x),
                Observable.FromEventPattern <EventHandler, EventArgs>(x => _view.ViewportWidthChanged  += x, x => _view.ViewportWidthChanged -= x));

            var hasAdded = false;

            disp.Add(sizeChanged.Subscribe(__ => {
                if (!hasAdded)
                {
                    _adornmentLayer.AddAdornment(AdornmentPositioningBehavior.ViewportRelative, null, null, commitControl, null);
                    hasAdded = true;
                }

                // NB: The scheduling is to get around initialization where ActualXXX is zero
                var action = new Action <double>(_ => {
                    Canvas.SetLeft(commitControl, _view.ViewportRight - commitControl.ActualWidth);
                    Canvas.SetTop(commitControl, _view.ViewportBottom - commitControl.ActualHeight);
                });

                if (commitControl.ActualWidth > 1)
                {
                    action(commitControl.ActualWidth);
                }
                else
                {
                    commitControl.WhenAny(x => x.ActualWidth, x => x.Value)
                    .Where(x => x > 1)
                    .Take(1)
                    .Subscribe(action);
                }
            }));

            disp.Add(Disposable.Create(() => _adornmentLayer.RemoveAllAdornments()));

            disp.Add(Observable.FromEventPattern <EventHandler, EventArgs>(x => _view.Closed += x, x => _view.Closed -= x)
                     .Subscribe(_ => Dispose()));

            _inner = disp;
            disp.Add(commitControl.ViewModel);
        }
        /// <summary>
        /// Creates a square image and attaches an event handler to the layout changed event that
        /// adds the the square in the upper right-hand corner of the TextView via the adornment layer
        /// </summary>
        /// <param name="view">The <see cref="IWpfTextView"/> upon which the adornment will be drawn</param>
        public SaveAllTheTimeAdornment(IWpfTextView view, IVisualStudioOps vsOps)
        {
            _view = view;
            _adornmentLayer = view.GetAdornmentLayer("SaveAllTheTimeAdornment");

            var filePath = getFilePathFromView(_view);
            if (shouldSuppressAdornment(filePath)) {
                _inner = Disposable.Empty;
                return;
            }

            var commitControl = new CommitHintView() {
                ViewModel = new CommitHintViewModel(filePath, vsOps, settings),
            };

            var disp = new CompositeDisposable();

            var sizeChanged = Observable.Merge(
                Observable.FromEventPattern<EventHandler, EventArgs>(x => _view.ViewportHeightChanged += x, x => _view.ViewportHeightChanged -= x),
                Observable.FromEventPattern<EventHandler, EventArgs>(x => _view.ViewportWidthChanged += x, x => _view.ViewportWidthChanged -= x));

            var hasAdded = false;
            disp.Add(sizeChanged.Subscribe(__ => {
                if (!hasAdded) {
                    _adornmentLayer.AddAdornment(AdornmentPositioningBehavior.ViewportRelative, null, null, commitControl, null);
                    hasAdded = true;
                }

                // NB: The scheduling is to get around initialization where ActualXXX is zero
                var action = new Action<double>(_ => {
                    Canvas.SetLeft(commitControl, _view.ViewportRight - commitControl.ActualWidth);
                    Canvas.SetTop(commitControl, _view.ViewportBottom - commitControl.ActualHeight);
                });

                if (commitControl.ActualWidth > 1) {
                    action(commitControl.ActualWidth);
                } else {
                    commitControl.WhenAny(x => x.ActualWidth, x => x.Value)
                        .Where(x => x > 1)
                        .Take(1)
                        .Subscribe(action);
                }
            }));

            disp.Add(Disposable.Create(() => _adornmentLayer.RemoveAllAdornments()));

            disp.Add(Observable.FromEventPattern<EventHandler, EventArgs>(x => _view.Closed += x, x => _view.Closed -= x)
                .Subscribe(_ => Dispose()));

            _inner = disp;
            disp.Add(commitControl.ViewModel);
        }
        /// <summary>
        /// Creates a square image and attaches an event handler to the layout changed event that
        /// adds the the square in the upper right-hand corner of the TextView via the adornment layer
        /// </summary>
        /// <param name="view">The <see cref="IWpfTextView"/> upon which the adornment will be drawn</param>
        public SaveAllTheTimeAdornment(IWpfTextView view, IVisualStudioOps vsOps)
        {
            _view = view;
            _adornmentLayer = view.GetAdornmentLayer("SaveAllTheTimeAdornment");

            var commitControl = new CommitHintView() {
                ViewModel = new CommitHintViewModel(getFilePathFromView(_view), vsOps, settings),
            };

            var disp = new CompositeDisposable();

            var sizeChanged = Observable.Merge(
                Observable.FromEventPattern<EventHandler, EventArgs>(x => _view.ViewportHeightChanged += x, x => _view.ViewportHeightChanged -= x),
                Observable.FromEventPattern<EventHandler, EventArgs>(x => _view.ViewportWidthChanged += x, x => _view.ViewportWidthChanged -= x));

            var hasAdded = false;
            disp.Add(sizeChanged.Subscribe(x => {
                if (!hasAdded) {
                    _adornmentLayer.AddAdornment(AdornmentPositioningBehavior.ViewportRelative, null, null, commitControl, null);
                    hasAdded = true;
                }

                // NB: The scheduling is to get around initialization where ActualXXX is zero
                var sched = (commitControl.ActualWidth > 0 ? ImmediateScheduler.Instance : RxApp.MainThreadScheduler);
                sched.Schedule(() => {
                    Canvas.SetLeft(commitControl, _view.ViewportRight - commitControl.ActualWidth);
                    Canvas.SetTop(commitControl, _view.ViewportBottom - commitControl.ActualHeight);
                });
            }));

            disp.Add(Disposable.Create(() => _adornmentLayer.RemoveAllAdornments()));

            disp.Add(Observable.FromEventPattern<EventHandler, EventArgs>(x => _view.Closed += x, x => _view.Closed -= x)
                .Subscribe(_ => Dispose()));

            disp.Add(commitControl.ViewModel);
            _inner = disp;
        }
 public SaveAllTheTimeFactory(IVisualStudioOps vsOps)
 {
     _vsOps = vsOps;
 }
Exemple #5
0
        public CommitHintViewModel(string filePath, IVisualStudioOps vsOps, UserSettings settings = null, IGitRepoOps gitRepoOps = null, IFilesystemWatchCache watchCache = null)
        {
            FilePath     = filePath;
            watchCache   = watchCache ?? _defaultWatchCache;
            _gitRepoOps  = gitRepoOps ?? new GitRepoOps();
            UserSettings = settings ?? new UserSettings();

            IsGitHubForWindowsInstalled = _gitRepoOps.IsGitHubForWindowsInstalled();

            this.Log().Info("Starting Commit Hint for {0}", filePath);

            this.WhenAny(x => x.FilePath, x => x.Value)
            .Where(x => !String.IsNullOrWhiteSpace(x))
            .Select(_gitRepoOps.FindGitRepo)
            .ToProperty(this, x => x.RepoPath, out _RepoPath);

            this.WhenAny(x => x.RepoPath, x => x.Value)
            .Where(x => !String.IsNullOrWhiteSpace(x))
            .Select(_gitRepoOps.ProtocolUrlForRepoPath)
            .ToProperty(this, x => x.ProtocolUrl, out _ProtocolUrl);

            Open                  = new ReactiveCommand(this.WhenAny(x => x.ProtocolUrl, x => !String.IsNullOrWhiteSpace(x.Value)));
            GoAway                = new ReactiveCommand();
            RefreshStatus         = new ReactiveCommand(this.WhenAny(x => x.RepoPath, x => !String.IsNullOrWhiteSpace(x.Value)));
            RefreshLastCommitTime = new ReactiveCommand(this.WhenAny(x => x.RepoPath, x => !String.IsNullOrWhiteSpace(x.Value)));
            ShowTFSGitWarning     = new ReactiveCommand();
            HelpMe                = new ReactiveCommand();

            var repoWatchSub = this.WhenAny(x => x.RepoPath, x => x.Value)
                               .Where(x => !String.IsNullOrWhiteSpace(x))
                               .Select(x => watchCache.Register(Path.Combine(x, ".git", "refs")).Select(_ => x))
                               .Switch()
                               .InvokeCommand(RefreshLastCommitTime);

            RefreshLastCommitTime.RegisterAsync(_ => _gitRepoOps.LastCommitTime(RepoPath))
            .StartWith(_gitRepoOps.ApplicationStartTime)
            .ToProperty(this, x => x.LastRepoCommitTime, out _LastRepoCommitTime);

            MessageBus.Current.Listen <Unit>("AnyDocumentChanged")
            .Timestamp(RxApp.MainThreadScheduler)
            .Select(x => x.Timestamp)
            .StartWith(_gitRepoOps.ApplicationStartTime)
            .ToProperty(this, x => x.LastTextActiveTime, out _LastTextActiveTime);

            var refreshDisp = this.WhenAny(x => x.LastTextActiveTime, x => Unit.Default)
                              .Buffer(TimeSpan.FromSeconds(5), RxApp.TaskpoolScheduler)
                              .Where(x => x.Count > 0)
                              .StartWith(new List <Unit> {
                Unit.Default
            })
                              .ObserveOn(RxApp.MainThreadScheduler)
                              .InvokeCommand(RefreshStatus);

            this.WhenAny(x => x.LastRepoCommitTime, x => x.LastTextActiveTime, x => x.MinutesTimeOverride, (commit, active, _) => active.Value - commit.Value)
            .Select(x => x.Ticks < 0 ? TimeSpan.Zero : x)
            .Select(x => MinutesTimeOverride != null ? TimeSpan.FromMinutes(MinutesTimeOverride.Value) : x)
            .Select(x => LastCommitTimeToOpacity(x))
            .ToProperty(this, x => x.SuggestedOpacity, out _SuggestedOpacity, 1.0);

            var hintState = new Subject <CommitHintState>();

            hintState.ToProperty(this, x => x.HintState, out _HintState);

            Open.Subscribe(_ => vsOps.SaveAll());

            RefreshStatus.RegisterAsync(_ => _gitRepoOps.GetStatus(RepoPath))
            .ToProperty(this, x => x.LatestRepoStatus, out _LatestRepoStatus);

            this.WhenAny(x => x.SuggestedOpacity, x => x.LatestRepoStatus, (opacity, status) => new { Opacity = opacity.Value, Status = status.Value })
            .Select(x => {
                if (x.Status == null)
                {
                    return(CommitHintState.Green);
                }
                if (!x.Status.Added.Any() &&
                    !x.Status.Removed.Any() &&
                    !x.Status.Modified.Any() &&
                    !x.Status.Missing.Any())
                {
                    return(CommitHintState.Green);
                }

                if (x.Opacity >= 0.95)
                {
                    return(CommitHintState.Red);
                }
                if (x.Opacity >= 0.6)
                {
                    return(CommitHintState.Yellow);
                }
                return(CommitHintState.Green);
            })
            .Subscribe(hintState);

            // NB: Because _LastRepoCommitTime at the end of the day creates a
            // FileSystemWatcher, we have to dispose it or else we'll get FSW
            // messages for evar.
            _inner = new CompositeDisposable(repoWatchSub, _LastRepoCommitTime, _LastTextActiveTime);
        }
Exemple #6
0
 public SaveAllTheTimeFactory(IVisualStudioOps vsOps)
 {
     _vsOps = vsOps;
 }
        public CommitHintViewModel(string filePath, IVisualStudioOps vsOps, UserSettings settings = null, IGitRepoOps gitRepoOps = null, IFilesystemWatchCache watchCache = null)
        {
            FilePath = filePath;
            watchCache = watchCache ?? _defaultWatchCache;
            _gitRepoOps = gitRepoOps ?? new GitRepoOps();
            UserSettings = settings ?? new UserSettings();

            this.Log().Info("Starting Commit Hint for {0}", filePath);

            this.WhenAny(x => x.FilePath, x => x.Value)
                .Where(x => !String.IsNullOrWhiteSpace(x))
                .Select(_gitRepoOps.FindGitRepo)
                .ToProperty(this, x => x.RepoPath, out _RepoPath);

            this.WhenAny(x => x.RepoPath, x => x.Value)
                .Where(x => !String.IsNullOrWhiteSpace(x))
                .Select(_gitRepoOps.ProtocolUrlForRepoPath)
                .ToProperty(this, x => x.ProtocolUrl, out _ProtocolUrl);

            Open = new ReactiveCommand(this.WhenAny(x => x.ProtocolUrl, x => !String.IsNullOrWhiteSpace(x.Value)));
            GoAway = new ReactiveCommand();
            RefreshStatus = new ReactiveAsyncCommand(this.WhenAny(x => x.RepoPath, x => !String.IsNullOrWhiteSpace(x.Value)));
            RefreshLastCommitTime = new ReactiveAsyncCommand(this.WhenAny(x => x.RepoPath, x => !String.IsNullOrWhiteSpace(x.Value)));

            var repoWatchSub = this.WhenAny(x => x.RepoPath, x => x.Value)
                .Where(x => !String.IsNullOrWhiteSpace(x))
                .Select(x => watchCache.Register(Path.Combine(x, ".git", "refs")).Select(_ => x))
                .Switch()
                .InvokeCommand(RefreshLastCommitTime);

            RefreshLastCommitTime.RegisterAsyncObservable(_ => _gitRepoOps.LastCommitTime(RepoPath))
                .StartWith(_gitRepoOps.ApplicationStartTime)
                .ToProperty(this, x => x.LastRepoCommitTime, out _LastRepoCommitTime);

            MessageBus.Current.Listen<Unit>("AnyDocumentChanged")
                .Timestamp(RxApp.MainThreadScheduler)
                .Select(x => x.Timestamp)
                .StartWith(_gitRepoOps.ApplicationStartTime)
                .ToProperty(this, x => x.LastTextActiveTime, out _LastTextActiveTime);

            var refreshDisp = this.WhenAny(x => x.LastTextActiveTime, x => Unit.Default)
                .Buffer(TimeSpan.FromSeconds(5), RxApp.TaskpoolScheduler)
                .ObserveOn(RxApp.MainThreadScheduler)
                .InvokeCommand(RefreshStatus);

            this.WhenAny(x => x.LastRepoCommitTime, x => x.LastTextActiveTime, x => x.MinutesTimeOverride, (commit, active, _) => active.Value - commit.Value)
                .Select(x => x.Ticks < 0 ? TimeSpan.Zero : x)
                .Select(x => MinutesTimeOverride != null ? TimeSpan.FromMinutes(MinutesTimeOverride.Value) : x)
                .Select(x => LastCommitTimeToOpacity(x))
                .ToProperty(this, x => x.SuggestedOpacity, out _SuggestedOpacity, 1.0);

            var hintState = new Subject<CommitHintState>();
            hintState.ToProperty(this, x => x.HintState, out _HintState);

            Open.Subscribe(_ => vsOps.SaveAll());

            RefreshStatus.RegisterAsyncObservable(_ => _gitRepoOps.GetStatus(RepoPath))
                .ToProperty(this, x => x.LatestRepoStatus, out _LatestRepoStatus);

            this.WhenAny(x => x.SuggestedOpacity, x => x.LatestRepoStatus, (opacity, status) => new { Opacity = opacity.Value, Status = status.Value })
                .Select(x => {
                    if (x.Status == null) return CommitHintState.Green;
                    if (!x.Status.Added.Any() &&
                        !x.Status.Removed.Any() &&
                        !x.Status.Modified.Any() &&
                        !x.Status.Missing.Any()) return CommitHintState.Green;

                    if (x.Opacity >= 0.95) return CommitHintState.Red;
                    if (x.Opacity >= 0.6) return CommitHintState.Yellow;
                    return CommitHintState.Green;
                })
                .Subscribe(hintState);

            // NB: Because _LastRepoCommitTime at the end of the day creates a
            // FileSystemWatcher, we have to dispose it or else we'll get FSW
            // messages for evar.
            _inner = new CompositeDisposable(repoWatchSub, _LastRepoCommitTime, _LastTextActiveTime);
        }