public NormalHeatMapControl() { var changes = MeanSubject .CombineLatest(StandardDeviationSubject, MinXSubject, MaxXSubject, MaxYSubject, (a, b, c, d, e) => Calculate(a, b, c, d, e)); var minMax = MeanSubject .CombineLatest(StandardDeviationSubject, (a, b) => CalculateMinMax(a, b)); var esee = MeanSubject.CombineLatest(minMax, (a, b) => Calculate2(a, b.min, b.max)); var esdse = MeanSubject .CombineLatest(MinXSubject, MaxXSubject, (a, b, c) => Calculate2(a, b, c)); var changes2 = MeanSubject .CombineLatest(StandardDeviationSubject, minMax, (a, b, c) => { return(Calculate(a, b, c.min, c.max, 1)); }); rect1Subject .CombineLatest(changes.Merge(changes2), esdse.Merge(esee), (a, b, c) => (a, b, c)) .Subscribe(c => { var(lower, middle, upper) = c.b; GradientStopAnimationExample(c.a, c.c, lower, middle, upper); }); }
public Equality() { Value1Changes.CombineLatest(Value2Changes, (one, two) => new { one, two }).Subscribe(_ => { this.SetValue(IsEqualProperty, _.one.Equals(_.two)); }); }
public InputBindings( InputSourceMapping <TAction> initialMapping, IObservable <InputSettings> inputSettingChanges, IImmutableDictionary <InputDefaults, InputSourceMapping <TAction> > defaultMappings) { _defaultMappings = defaultMappings; _usesDefaultMapping = false; foreach (var defaultMapping in defaultMappings.Values) { if (initialMapping.Equals(defaultMapping)) { _usesDefaultMapping = true; } } _inputMappings = new BehaviorSubject <InputSourceMapping <TAction> >(initialMapping); _inputMappings.Subscribe(mapping => { _currentMapping = mapping; }); _activeControllerId = null; _activeControllerUpdates = new BehaviorSubject <JoystickActivator.Controller?>(null); _actionMap = _inputMappings.CombineLatest( _activeControllerUpdates, inputSettingChanges.DistinctUntilChanged(EqualityComparer <InputSettings> .Default), (mapping, controller, settings) => { var controllerId = controller.HasValue ? controller.Value.Id : null; return(new ActionMapConfig <TAction> { InputMapping = mapping, ControllerId = controllerId, InputSettings = settings }); }); }
public GaussianControl() { rect1Subject .CombineLatest(ratioSubject, (a, b) => (a, b)) .Subscribe(c => { GradientStopAnimationExample(c.a, c.b / 100d); }); }
/// <summary> /// Get everything setup to show the PDF document /// </summary> /// <param name="docSequence"></param> /// <param name="initialPage">The page that should be shown when we start up. Zero indexed</param> /// <param name="screen">The screen that hosts everything (routing!)</param> public FullTalkAsStripViewModel(IScreen screen, PDFFile file) { Debug.Assert(file != null); Debug.Assert(screen != null); HostScreen = screen; // We basically re-set each time a new file comes down from the top. Pages = new ReactiveList <PDFPageViewModel>(); var pageSizeChanged = file.WhenAny(x => x.NumberOfPages, x => x.Value) .DistinctUntilChanged() .ObserveOn(RxApp.MainThreadScheduler); var b = from newPageLength in pageSizeChanged let np = Pages.Count from allpages in CreateNPages(newPageLength - np, np, file) select new { numPages = newPageLength, freshPages = allpages }; b .ObserveOn(RxApp.MainThreadScheduler) .Subscribe(info => SetNPages(info.numPages, info.freshPages)); // Page navigation. Make sure things are clean and we don't over-burden the UI before // we pass the info back to the UI! _moveToPage = new ReplaySubject <int>(1); _loaded = new ReplaySubject <Unit>(1); MoveToPage = _moveToPage .CombineLatest(_loaded, (p, _) => p) .Select(scrubPageIndex) .DistinctUntilChanged(); PageForward = ReactiveCommand.Create(); PageForward .Cast <int>() .Select(pn => pn + 1) .Subscribe(_moveToPage); PageBack = ReactiveCommand.Create(); PageBack .Cast <int>() .Select(pn => pn - 1) .Subscribe(_moveToPage); PageMove = ReactiveCommand.Create(); PageMove .Cast <int>() .Subscribe(_moveToPage); }
public override void OnApplyTemplate() { DataGrid = this.GetTemplateChild("DataGrid") as DataGrid; DataGrid.ItemsSource = dataTable?.DefaultView; var buttonSaveToCsv = this.GetTemplateChild("Save_To_Csv") as Button; buttonSave = this.GetTemplateChild("Save") as Button; buttonLoad = this.GetTemplateChild("Load") as Button; sliderItemsControl = this.GetTemplateChild("SliderItemsControl") as SliderItemsControl; Diagram = this.GetTemplateChild("Diagram") as OxyPlot.Wpf.PlotView; Observable.FromEventPattern <RoutedEventHandler, RoutedEventArgs>(h => buttonSave.Click += h, h => buttonSave.Click -= h) .WithLatestFrom <EventPattern <RoutedEventArgs>, object, Action>(regressorChanges, (a, b) => (b as ISaveLoad).Save) .Subscribe(_ => _.Invoke()); Observable.FromEventPattern <RoutedEventHandler, RoutedEventArgs>(h => buttonLoad.Click += h, h => buttonLoad.Click -= h) .WithLatestFrom <EventPattern <RoutedEventArgs>, object, Action>(regressorChanges, (a, b) => (b as ISaveLoad).Load) .Subscribe(_ => _.Invoke()); if (buttonSaveToCsv != null) { Observable.FromEventPattern <RoutedEventHandler, RoutedEventArgs>(h => buttonSaveToCsv.Click += h, h => buttonSaveToCsv.Click -= h) .WithLatestFrom <EventPattern <RoutedEventArgs>, object, Task <bool> >(trainDataViewChanges, (a, b) => SaveToCsv(dataTable)) .Subscribe(async _ => await _); } var xxx = Observable.FromEventPattern <RoutedEventHandler, RoutedEventArgs>(h => sliderItemsControl.ValueChanged += h, h => sliderItemsControl.ValueChanged -= h) .WithLatestFrom(regressorChanges, (a, b) => new Action(() => SliderItemsControl_ValueChanged(a.EventArgs, b))) .Buffer(TimeSpan.FromMilliseconds(100)) .ObserveOnDispatcher() .Subscribe(_ => _.LastOrDefault()?.Invoke()); regressorChanges.CombineLatest(testDataViewChanges, AddPoints).Subscribe(async _ => { await _; }); Diagram.Model = CreatePlotModel(); Diagram.Model.InvalidatePlot(true); // sliderItemsControl.ValueChanged +=(a,s SliderItemsControl_ValueChanged; }
public static IControl Create <T>( ISubject <T> selection, IObservable <T> data, Func <SelectionState, IControl> control, Menu menu, Command defaultCommand, Text toolTip = default(Text)) { return(control( new SelectionState { IsSelected = selection.CombineLatest(data, (s, d) => s.Equals(d)).Replay(1).RefCount(), }) .WithBackground(Color.AlmostTransparent) .OnMouse( pressed: data.Switch(selection.Update), doubleClicked: defaultCommand) .SetContextMenu(menu) .SetToolTip(toolTip)); }
public ObjectControl() { converterChanges .CombineLatest(objectChanges, comparerChanges, textBlockChanges, filterChanges, (valueConverter, value, comparer, textBlock, filter) => (valueConverter, value, comparer, textBlock, filter)) .Subscribe(valueTuple => { var(valueConverter, value, comparer, textBlock, filter) = valueTuple; Task.Run(() => value switch { string _ => (Visibility.Collapsed, value), Version _ => (Visibility.Collapsed, value), { } x when x.GetType().IsClass == false => (Visibility.Collapsed, value), null => (Visibility.Collapsed, value), IEnumerable <string> _ => (Visibility.Collapsed, value), IEnumerable enumerable when enumerable.NotOfClassType() => (Visibility.Collapsed, enumerable), IEnumerable enumerable when enumerable.OfSameType() => (Visibility.Collapsed, enumerable), IEnumerable enumerable => DictionaryConverter.ConvertMany(enumerable, valueConverter, filter, comparer) .Pipe(a => (a.Keys.Cast <object>().Any() ? Visibility.Visible : Visibility.Collapsed, a)), _ => DictionaryConverter.Convert(value, valueConverter, filter, comparer) .Pipe(a => (a.Keys.Cast <object>().Any() ? Visibility.Visible : Visibility.Collapsed, a)) }) .ToObservable() .ObserveOnDispatcher() .Subscribe(a => { var(visibility, content) = a; textBlock.SetValue(VisibilityProperty, visibility); this.SetValue(ContentProperty, content); }, e => { SetValue(ContentProperty, new OrderedDictionary(1) { { "Error", e.Message } }); this.Log().Write(e, $"Error in {nameof(ObjectControl)} creating content", typeof(ObjectControl), LogLevel.Error); }, () => { }); });
public PathControl() { Uri resourceLocater = new Uri("/PathWpf;component/Themes/PathControl.xaml", System.UriKind.Relative); ResourceDictionary resourceDictionary = (ResourceDictionary)Application.LoadComponent(resourceLocater); Style = resourceDictionary["PathControlStyle"] as Style; Random rd = new Random(); PointChanges .CombineLatest(DiameterChanges, SpeedChanges, (a, c, d) => { var startPoint = (a as PathGeometry).Figures.First().StartPoint; var endPoint = (a as PathGeometry).Figures.Last().StartPoint; byte[] rgb = new byte[] { (byte)rd.Next(0, 255), (byte)rd.Next(0, 255), (byte)rd.Next(0, 255) }; Path particlePath = PathEllipse.GetPath(startPoint, endPoint, _storyboard, rgb, (a as PathGeometry), 2); return(PathEllipse.GetAnimation(startPoint, endPoint, c, a, rgb, _storyboard, 2, m_PointData)); }) .Subscribe(_ => { foreach (var x in _) { try { contentGrid.Children.Add((UIElement)x); } catch (Exception e) { } } _storyboard.Begin(this); }); }
/// <summary> /// Initializes a new instance of the <see cref="ObservableTimer"/> class. /// </summary> /// <param name="schedulerProvider">The scheduler provider.</param> protected ObservableTimer(ISchedulerProvider schedulerProvider) { _timerEvents .Select(x => x is TimerStartEvent) .ToProperty(this, nameof(IsRunning), out _isRunning) .DisposeWith(Garbage); _elapsed = _timerEvents .CombineLatest( _timerEvents .OfType <TimerStartEvent>() .Select(x => x.Duration), (timerEvent, duration) => (duration, isRunning: timerEvent is TimerStartEvent)) .Select( x => x.isRunning ? Observable .Interval(TimeSpans.RefreshInterval, schedulerProvider.BackgroundThread) .Scan(x.duration, (duration, _) => Accumulator(duration)) .TakeUntil(Elapsed) .Do(elapsed => _resumeTime = elapsed, () => _resumeTime = x.duration) : Observable.Return(_resumeTime)) .Switch(); }
public TailViewModel([NotNull] ILogger logger, [NotNull] ISchedulerProvider schedulerProvider, [NotNull] IEnumerable <IFileWatcher> fileWatcher, [NotNull] ISelectionMonitor selectionMonitor, [NotNull] IClipboardHandler clipboardHandler, [NotNull] ISearchInfoCollection searchInfoCollection, [NotNull] IInlineViewerFactory inlineViewerFactory, [NotNull] ISetting <GeneralOptions> generalOptions, [NotNull] ISearchMetadataCollection searchMetadataCollection, [NotNull] SearchOptionsViewModel searchOptionsViewModel, [NotNull] SearchHints searchHints) { if (logger == null) { throw new ArgumentNullException(nameof(logger)); } if (schedulerProvider == null) { throw new ArgumentNullException(nameof(schedulerProvider)); } if (fileWatcher == null) { throw new ArgumentNullException(nameof(fileWatcher)); } if (selectionMonitor == null) { throw new ArgumentNullException(nameof(selectionMonitor)); } if (clipboardHandler == null) { throw new ArgumentNullException(nameof(clipboardHandler)); } if (searchInfoCollection == null) { throw new ArgumentNullException(nameof(searchInfoCollection)); } if (inlineViewerFactory == null) { throw new ArgumentNullException(nameof(inlineViewerFactory)); } if (generalOptions == null) { throw new ArgumentNullException(nameof(generalOptions)); } if (searchMetadataCollection == null) { throw new ArgumentNullException(nameof(searchMetadataCollection)); } if (searchOptionsViewModel == null) { throw new ArgumentNullException(nameof(searchOptionsViewModel)); } if (searchHints == null) { throw new ArgumentNullException(nameof(searchHints)); } _stateProvider = new TailViewPersister(this); var enumerable = fileWatcher as IFileWatcher[] ?? fileWatcher.ToArray(); Names = enumerable.Select(t => t.FullName); SelectionMonitor = selectionMonitor; SearchOptions = searchOptionsViewModel; SearchHints = searchHints; SearchCollection = new SearchCollection(searchInfoCollection, schedulerProvider); CopyToClipboardCommand = new Command(() => clipboardHandler.WriteToClipboard(selectionMonitor.GetSelectedText())); OpenFileCommand = new Command(() => Process.Start(enumerable[0].FullName)); OpenFolderCommand = new Command(() => Process.Start(enumerable[0].Folder)); UsingDarkTheme = generalOptions.Value .ObserveOn(schedulerProvider.MainThread) .Select(options => options.Theme == Theme.Dark) .ForBinding(); HighlightTail = generalOptions.Value .ObserveOn(schedulerProvider.MainThread) .Select(options => options.HighlightTail) .ForBinding(); HighlightDuration = generalOptions.Value .ObserveOn(schedulerProvider.MainThread) .Select(options => new Duration(TimeSpan.FromSeconds(options.HighlightDuration))) .ForBinding(); //An observable which acts as a scroll command var autoChanged = this.WhenValueChanged(vm => vm.AutoTail); var scroller = _userScrollRequested.CombineLatest(autoChanged, (user, auto) => { var mode = AutoTail ? ScrollReason.Tail : ScrollReason.User; return(new ScrollRequest(mode, user.PageSize, user.FirstIndex)); }) .Do(x => logger.Info("Scrolling to {0}/{1}", x.FirstIndex, x.PageSize)) .DistinctUntilChanged(); FileStatus = enumerable .Select(t => t.Status) .Merge() .Scan(default(FileStatus), (status, fileStatus) => status | fileStatus) .ForBinding(); //command to add the current search to the tail collection var searchInvoker = SearchHints.SearchRequested.Subscribe( request => { searchInfoCollection.Add(request.Text, request.UseRegEx); }); //User feedback to show file size FileSizeText = enumerable .Select(t => t.Latest) .Merge() .Select(t => t.Size) .Scan(0f, (previousSize, currentSize) => previousSize + currentSize / 2f) .Select(t => ((long)t).FormatWithAbbreviation()) .DistinctUntilChanged() .ForBinding(); //tailer is the main object used to tail, scroll and filter in a file var lineScroller = new LineScroller(SearchCollection.Latest.ObserveOn(schedulerProvider.Background), scroller); //load lines into observable collection var lineProxyFactory = new LineProxyFactory(new TextFormatter(searchMetadataCollection), new LineMatches(searchMetadataCollection)); var loader = lineScroller.Lines.Connect() .RecordChanges(logger, "Received") .Transform(lineProxyFactory.Create, new ParallelisationOptions(ParallelType.Ordered, 3)) .Sort(SortExpressionComparer <LineProxy> .Ascending(proxy => proxy)) .ObserveOn(schedulerProvider.MainThread) .Bind(out _data, 100) .DisposeMany() .LogErrors(logger) .Subscribe(); //monitor matching lines and start index, Count = searchInfoCollection.All .GroupBy(t => t) .Select(groupedProvider => groupedProvider.Key.Count) .Scan(0, (i, providerCount) => i + providerCount) .ForBinding(); CountText = searchInfoCollection.All .GroupBy(t => t) .Select(groupedProvider => groupedProvider.Key.Count) .Scan(0, (i, providerCount) => i + providerCount) .Select(latestCount => $"{latestCount.ToString("##,###")} lines") .ForBinding(); //iterate over every items to evaluate the lines' count LatestCount = SearchCollection.Latest .GroupBy(t => t) .Do(Console.WriteLine) .Scan(0, (acc, provider) => { if (provider.Key is IndexCollection && provider.Key.NumberOfPreviousProvider == 0) { acc = 0; } else if (provider.Key is FileSearchResult && provider.Key.NumberOfPreviousProvider == 0) { acc = 0; } return(provider.Key.Count + acc); }) .ForBinding(); ////track first visible index var firstIndexMonitor = lineScroller.Lines.Connect() .Buffer(TimeSpan.FromMilliseconds(25)).FlattenBufferResult() .ToCollection() .Select(lines => lines.Count == 0 ? 0 : lines.Select(l => l.Index).Max() - lines.Count + 1) .ObserveOn(schedulerProvider.MainThread) .Subscribe(first => { FirstIndex = first; }); //Create objects required for inline viewing var isUserDefinedChanged = SearchCollection.WhenValueChanged(sc => sc.Selected) .Where(selected => selected != null) .Select(selected => selected.IsUserDefined) .DistinctUntilChanged() .Replay(1) .RefCount(); var inlineViewerVisible = isUserDefinedChanged.CombineLatest(this.WhenValueChanged(vm => vm.ShowInline), (userDefined, showInline) => userDefined && showInline); CanViewInline = isUserDefinedChanged.ForBinding(); InlineViewerVisible = inlineViewerVisible.ForBinding(); //return an empty line provider unless user is viewing inline - this saves needless trips to the file var inline = searchInfoCollection.All.CombineLatest(inlineViewerVisible, (index, ud) => ud ? index : new EmptyLineProvider()); var firstVisibleRow = _data.ToObservableChangeSet().ToCollection() .Select(collection => collection.FirstOrDefault()); //var itemToSelect = this.WhenValueChanged(vm => vm.SelectedItem) // .CombineLatest(firstVisibleRow, (selected, first) => selected ?? first); //// InlineViewer = inlineViewerFactory.Create(inline, this.WhenValueChanged(vm => vm.SelectedItem), lineProxyFactory); _cleanUp = new CompositeDisposable(lineScroller, loader, firstIndexMonitor, FileStatus, Count, LatestCount, FileSizeText, CanViewInline, InlineViewer, InlineViewerVisible, SearchCollection, searchInfoCollection, HighlightTail, UsingDarkTheme, searchHints, searchMetadataCollection, searchMetadataCollection, SelectionMonitor, SearchOptions, searchInvoker, _userScrollRequested.SetAsComplete()); }
public TailViewModel([NotNull] ILogger logger, [NotNull] ISchedulerProvider schedulerProvider, [NotNull] IFileWatcher fileWatcher, [NotNull] ISelectionMonitor selectionMonitor, [NotNull] IClipboardHandler clipboardHandler, [NotNull] ISearchInfoCollection searchInfoCollection, [NotNull] IInlineViewerFactory inlineViewerFactory, [NotNull] GeneralOptionBindings generalOptionBindings, [NotNull] ICombinedSearchMetadataCollection combinedSearchMetadataCollection, [NotNull] IStateBucketService stateBucketService, [NotNull] ITailViewStateRestorer restorer, [NotNull] SearchHints searchHints, [NotNull] ITailViewStateControllerFactory tailViewStateControllerFactory, [NotNull] IThemeProvider themeProvider, [NotNull] SearchCollection searchCollection, [NotNull] ITextFormatter textFormatter, [NotNull] ILineMatches lineMatches, [NotNull] IObjectProvider objectProvider, [NotNull] IDialogCoordinator dialogCoordinator) { if (logger == null) { throw new ArgumentNullException(nameof(logger)); } if (schedulerProvider == null) { throw new ArgumentNullException(nameof(schedulerProvider)); } if (fileWatcher == null) { throw new ArgumentNullException(nameof(fileWatcher)); } if (clipboardHandler == null) { throw new ArgumentNullException(nameof(clipboardHandler)); } if (searchInfoCollection == null) { throw new ArgumentNullException(nameof(searchInfoCollection)); } if (inlineViewerFactory == null) { throw new ArgumentNullException(nameof(inlineViewerFactory)); } if (stateBucketService == null) { throw new ArgumentNullException(nameof(stateBucketService)); } if (themeProvider == null) { throw new ArgumentNullException(nameof(themeProvider)); } if (textFormatter == null) { throw new ArgumentNullException(nameof(textFormatter)); } if (lineMatches == null) { throw new ArgumentNullException(nameof(lineMatches)); } if (objectProvider == null) { throw new ArgumentNullException(nameof(objectProvider)); } if (dialogCoordinator == null) { throw new ArgumentNullException(nameof(dialogCoordinator)); } if (combinedSearchMetadataCollection == null) { throw new ArgumentNullException(nameof(combinedSearchMetadataCollection)); } Name = fileWatcher.FullName; SelectionMonitor = selectionMonitor ?? throw new ArgumentNullException(nameof(selectionMonitor)); GeneralOptionBindings = generalOptionBindings; SearchHints = searchHints ?? throw new ArgumentNullException(nameof(searchHints)); CopyToClipboardCommand = new Command(() => clipboardHandler.WriteToClipboard(selectionMonitor.GetSelectedText())); OpenFileCommand = new Command(() => Process.Start(fileWatcher.FullName)); OpenFolderCommand = new Command(() => Process.Start(fileWatcher.Folder)); CopyPathToClipboardCommand = new Command(() => clipboardHandler.WriteToClipboard(fileWatcher.FullName)); UnClearCommand = new Command(fileWatcher.Reset); ClearCommand = new Command(fileWatcher.Clear); KeyAutoTail = new Command(() => { AutoTail = true; }); OpenSearchOptionsCommand = new Command(async() => { await Task.Run(() => { var content = objectProvider.Get <SearchOptionsViewModel>(new Argument <ICombinedSearchMetadataCollection>(combinedSearchMetadataCollection)); dialogCoordinator.Show(this, content, x => content.Dispose()); }); }); var closeOnDeselect = this.WhenValueChanged(vm => vm.IsSelected, false) .Where(selected => !selected) .Subscribe(_ => dialogCoordinator.Close()); SearchCollection = searchCollection ?? throw new ArgumentNullException(nameof(searchCollection)); SearchMetadataCollection = combinedSearchMetadataCollection.Local; var horizonalScrollArgs = new ReplaySubject <TextScrollInfo>(1); HorizonalScrollChanged = args => horizonalScrollArgs.OnNext(args); _tailViewStateControllerFactory = tailViewStateControllerFactory; //this deals with state when loading the system at start up and at shut-down _persister = new TailViewPersister(this, restorer); FileStatus = fileWatcher.Status.ForBinding(); //command to add the current search to the tail collection var searchInvoker = SearchHints.SearchRequested.Subscribe(request => searchInfoCollection.Add(request.Text, request.UseRegEx)); //An observable which acts as a scroll command var autoChanged = this.WhenValueChanged(vm => vm.AutoTail); var scroller = _userScrollRequested.CombineLatest(autoChanged, (user, auto) => { var mode = AutoTail ? ScrollReason.Tail : ScrollReason.User; return(new ScrollRequest(mode, user.PageSize, user.FirstIndex)); }) .Do(x => logger.Info("Scrolling to {0}/{1}", x.FirstIndex, x.PageSize)) .DistinctUntilChanged(); //User feedback to show file size FileSizeText = fileWatcher.Latest.Select(fn => fn.Size) .Select(size => size.FormatWithAbbreviation()) .DistinctUntilChanged() .ForBinding(); //tailer is the main object used to tail, scroll and filter in a file var selectedProvider = SearchCollection.Latest.ObserveOn(schedulerProvider.Background); var lineScroller = new LineScroller(selectedProvider, scroller); MaximumChars = lineScroller.MaximumLines() .ObserveOn(schedulerProvider.MainThread) .ForBinding(); var lineProxyFactory = new LineProxyFactory(textFormatter, lineMatches, horizonalScrollArgs.DistinctUntilChanged(), themeProvider); var loader = lineScroller.Lines.Connect() .LogChanges(logger, "Received") .Transform(lineProxyFactory.Create) .LogChanges(logger, "Sorting") .Sort(SortExpressionComparer <LineProxy> .Ascending(proxy => proxy)) .ObserveOn(schedulerProvider.MainThread) .Bind(out _data, 100) .LogChanges(logger, "Bound") .DisposeMany() .LogErrors(logger) .Subscribe(); //monitor matching lines and start index, Count = searchInfoCollection.All.Select(latest => latest.Count).ForBinding(); CountText = searchInfoCollection.All.Select(latest => $"{latest.Count:##,###} lines").ForBinding(); LatestCount = SearchCollection.Latest.Select(latest => latest.Count).ForBinding(); ////track first visible index var firstIndexMonitor = lineScroller.Lines.Connect() .Buffer(TimeSpan.FromMilliseconds(25)).FlattenBufferResult() .ToCollection() .Select(lines => lines.Count == 0 ? 0 : lines.Select(l => l.Index).Max() - lines.Count + 1) .ObserveOn(schedulerProvider.MainThread) .Subscribe(first => { FirstIndex = first; }); //Create objects required for inline viewing var isUserDefinedChanged = SearchCollection.WhenValueChanged(sc => sc.Selected) .Where(selected => selected != null) .Select(selected => selected.IsUserDefined) .DistinctUntilChanged() .Replay(1) .RefCount(); var showInline = this.WhenValueChanged(vm => vm.ShowInline); var inlineViewerVisible = isUserDefinedChanged.CombineLatest(showInline, (userDefined, showInlne) => userDefined && showInlne); CanViewInline = isUserDefinedChanged.ForBinding(); InlineViewerVisible = inlineViewerVisible.ForBinding(); //return an empty line provider unless user is viewing inline - this saves needless trips to the file var inline = searchInfoCollection.All.CombineLatest(inlineViewerVisible, (index, ud) => ud ? index : EmptyLineProvider.Instance); InlineViewer = inlineViewerFactory.Create(combinedSearchMetadataCollection, inline, this.WhenValueChanged(vm => vm.SelectedItem)); _cleanUp = new CompositeDisposable(lineScroller, loader, firstIndexMonitor, FileStatus, Count, CountText, LatestCount, FileSizeText, CanViewInline, InlineViewer, InlineViewerVisible, SearchCollection, searchInfoCollection, searchHints, SelectionMonitor, closeOnDeselect, Disposable.Create(dialogCoordinator.Close), searchInvoker, MaximumChars, _stateMonitor, combinedSearchMetadataCollection, horizonalScrollArgs.SetAsComplete(), _userScrollRequested.SetAsComplete()); }
public FileTailerViewModel([NotNull] ILogger logger, [NotNull] ISchedulerProvider schedulerProvider, [NotNull] IFileWatcher fileWatcher, [NotNull] ISelectionMonitor selectionMonitor, [NotNull] IClipboardHandler clipboardHandler, [NotNull] ISearchInfoCollection searchInfoCollection, [NotNull] IInlineViewerFactory inlineViewerFactory, [NotNull] ISetting <GeneralOptions> generalOptions, [NotNull] IRecentSearchCollection recentSearchCollection, [NotNull] SearchHints searchHints) { if (logger == null) { throw new ArgumentNullException(nameof(logger)); } if (schedulerProvider == null) { throw new ArgumentNullException(nameof(schedulerProvider)); } if (fileWatcher == null) { throw new ArgumentNullException(nameof(fileWatcher)); } if (selectionMonitor == null) { throw new ArgumentNullException(nameof(selectionMonitor)); } if (clipboardHandler == null) { throw new ArgumentNullException(nameof(clipboardHandler)); } if (searchInfoCollection == null) { throw new ArgumentNullException(nameof(searchInfoCollection)); } if (inlineViewerFactory == null) { throw new ArgumentNullException(nameof(inlineViewerFactory)); } if (generalOptions == null) { throw new ArgumentNullException(nameof(generalOptions)); } if (searchHints == null) { throw new ArgumentNullException(nameof(searchHints)); } SelectionMonitor = selectionMonitor; SearchHints = searchHints; CopyToClipboardCommand = new Command(() => clipboardHandler.WriteToClipboard(selectionMonitor.GetSelectedText())); SelectedItemsCount = selectionMonitor.Selected.Connect().QueryWhenChanged(collection => collection.Count).ForBinding(); SearchCollection = new SearchCollection(searchInfoCollection, schedulerProvider); UsingDarkTheme = generalOptions.Value .ObserveOn(schedulerProvider.MainThread) .Select(options => options.Theme == Theme.Dark) .ForBinding(); HighlightTail = generalOptions.Value .ObserveOn(schedulerProvider.MainThread) .Select(options => options.HighlightTail) .ForBinding(); HighlightDuration = generalOptions.Value .ObserveOn(schedulerProvider.MainThread) .Select(options => new Duration(TimeSpan.FromSeconds(options.HighlightDuration))) .ForBinding(); //An observable which acts as a scroll command var autoChanged = this.WhenValueChanged(vm => vm.AutoTail); var scroller = _userScrollRequested.CombineLatest(autoChanged, (user, auto) => { var mode = AutoTail ? ScrollReason.Tail : ScrollReason.User; return(new ScrollRequest(mode, user.PageSize, user.FirstIndex)); }) .ObserveOn(schedulerProvider.Background) .DistinctUntilChanged(); //tailer is the main object used to tail, scroll and filter in a file var lineScroller = new LineScroller(SearchCollection.Latest.ObserveOn(schedulerProvider.Background), scroller); //Add a complete file display [No search info here] var indexed = fileWatcher.Latest.Index() .Replay(1).RefCount(); IsLoading = indexed.Take(1).Select(_ => false).StartWith(true).ForBinding(); searchInfoCollection.Add("<All>", indexed, SearchType.All); //command to add the current search to the tail collection KeepSearchCommand = new Command(() => { var text = SearchHints.SearchText; var latest = fileWatcher.Latest .Search(s => s.Contains(text, StringComparison.OrdinalIgnoreCase)) .Replay(1).RefCount(); searchInfoCollection.Add(text, latest); recentSearchCollection.Add(new RecentSearch(text)); SearchHints.SearchText = string.Empty; }, () => SearchHints.SearchText.IsLongerThanOrEqualTo(3)); //User feedback to show file size FileSizeText = fileWatcher.Latest.Select(fn => fn.Size) .Select(size => size.FormatWithAbbreviation()) .DistinctUntilChanged() .ForBinding(); //User feedback to guide them whilst typing SearchHint = this.WhenValueChanged(vm => vm.SearchHints.SearchText) .Select(text => { if (string.IsNullOrEmpty(text)) { return("Type to search"); } return(text.Length < 3 ? "Enter at least 3 characters" : "Hit enter to search"); }).ForBinding(); //load lines into observable collection var lineProxyFactory = new LineProxyFactory(new TextFormatter(searchInfoCollection)); var loader = lineScroller.Lines.Connect() .Transform(lineProxyFactory.Create, new ParallelisationOptions(ParallelType.Ordered, 5)) .Sort(SortExpressionComparer <LineProxy> .Ascending(proxy => proxy)) .ObserveOn(schedulerProvider.MainThread) .Bind(out _data) .DisposeMany() .Subscribe(changes => logger.Info($"Rows changed. {changes.Adds} adds, {changes.Removes} removed"), ex => logger.Error(ex, "There is a problem with bind data")); //monitor matching lines and start index, Count = indexed.Select(latest => latest.Count).ForBinding(); CountText = indexed.Select(latest => $"{latest.Count.ToString("##,###")} lines").ForBinding(); LatestCount = SearchCollection.Latest.Select(latest => latest.Count).ForBinding(); //track first visible index var firstIndexMonitor = lineScroller.Lines.Connect() .Buffer(TimeSpan.FromMilliseconds(250)).FlattenBufferResult() .ToCollection() .Select(lines => lines.Count == 0 ? 0 : lines.Select(l => l.Index).Max() - lines.Count + 1) .ObserveOn(schedulerProvider.MainThread) .Subscribe(first => FirstIndex = first); //Create objects required for inline viewing var isUserDefinedChanged = SearchCollection.WhenValueChanged(sc => sc.Selected) .Select(selected => selected.IsUserDefined) .DistinctUntilChanged(); var inlineViewerVisible = isUserDefinedChanged.CombineLatest(this.WhenValueChanged(vm => vm.ShowInline), (userDefined, showInline) => userDefined && showInline); CanViewInline = isUserDefinedChanged.ForBinding(); InlineViewerVisible = inlineViewerVisible.ForBinding(); //return an empty line provider unless user is viewing inline - this saves needless trips to the file var inline = indexed.CombineLatest(inlineViewerVisible, (index, ud) => ud ? index : new EmptyLineProvider()); InlineViewer = inlineViewerFactory.Create(inline, this.WhenValueChanged(vm => vm.SelectedItem), lineProxyFactory); _cleanUp = new CompositeDisposable(lineScroller, loader, firstIndexMonitor, IsLoading, Count, LatestCount, FileSizeText, SearchHint, SelectedItemsCount, CanViewInline, InlineViewer, InlineViewerVisible, SearchCollection, searchInfoCollection, HighlightTail, UsingDarkTheme, searchHints, Disposable.Create(() => { _userScrollRequested.OnCompleted(); SelectionMonitor?.Dispose(); })); }
public FileTailerViewModel(ILogger logger, ISchedulerProvider schedulerProvider, FileInfo fileInfo) { if (logger == null) { throw new ArgumentNullException(nameof(logger)); } if (schedulerProvider == null) { throw new ArgumentNullException(nameof(schedulerProvider)); } if (fileInfo == null) { throw new ArgumentNullException(nameof(fileInfo)); } var filterRequest = this.WhenValueChanged(vm => vm.SearchText).Throttle(TimeSpan.FromMilliseconds(125)); var autoChanged = this.WhenValueChanged(vm => vm.AutoTail); var scroller = _userScrollRequested .CombineLatest(autoChanged, (user, auto) => { var mode = AutoTail ? ScrollingMode.Tail : ScrollingMode.User; return(new ScrollRequest(mode, user.PageSize, user.FirstIndex)); }) .Sample(TimeSpan.FromMilliseconds(150)) .DistinctUntilChanged(); var tailer = new FileTailer(fileInfo, filterRequest, scroller); //create user display for count line count var lineCounter = tailer.TotalLines.CombineLatest(tailer.MatchedLines, (total, matched) => { return(total == matched ? $"File has {total.ToString("#,###")} lines" : $"Showing {matched.ToString("#,###")} of {total.ToString("#,###")} lines"); }) .Subscribe(text => LineCountText = text); //load lines into observable collection var loader = tailer.Lines.Connect() .Transform(line => new LineProxy(line)) .Sort(SortExpressionComparer <LineProxy> .Ascending(proxy => proxy.Number)) .ObserveOn(schedulerProvider.MainThread) .Bind(out _data) .Subscribe(changes => logger.Info($"Rows changed {changes.Adds} adds, {changes.Removes} removed"), ex => logger.Error(ex, "There is a problem with bind data")); //monitor matching lines and start index, var matchedLinesMonitor = tailer.MatchedLines .Subscribe(matched => MatchedLineCount = matched); //track first visible index var firstIndexMonitor = tailer.Lines.Connect() .QueryWhenChanged(lines => lines.Count == 0 ? 0 : lines.Select(l => l.Index).Min()) .Subscribe(first => FirstIndex = first); _cleanUp = new CompositeDisposable(tailer, lineCounter, loader, firstIndexMonitor, matchedLinesMonitor, Disposable.Create(() => { _userScrollRequested.OnCompleted(); })); }
public DateTimeControl() { startChanges.CombineLatest(endChanges, (s, e) => new { s, e }).Subscribe(_ => { }); }
public MasterDetailView() { var outputChanges = SelectChanges(nameof(Output)).Where(obj => obj != null); //Dictionary<Type, object> dict = new Dictionary<Type, object>(); outputChanges .CombineLatest(SelectChanges <string>(nameof(Id)).StartWith(Id), (a, b) => (a, b)) .Select(vm => { var id = vm.a.GetType().GetProperty(vm.b).GetValue(vm.a).ToString(); return(id); }).Subscribe(NameChanges); outputChanges .CombineLatest(SelectChanges <IValueConverter>(nameof(DataConverter)).StartWith(default(IValueConverter)), (a, b) => (a, b)) .SubscribeOn(TaskPoolScheduler.Default) .ObserveOnDispatcher() .Subscribe(collConv => Dispatcher.InvokeAsync(() => { Convert(collConv.a, collConv.b, (items, conv) => conv.Convert(collConv.a, null, null, null) as IEnumerable); }, DispatcherPriority.Normal)); SelectChanges <PropertyGroupDescription>().StartWith(PropertyGroupDescription) .CombineLatest(ControlChanges.Where(c => c.GetType() == typeof(DockPanel)).Take(1), (pgd, DockPanel) => (pgd, DockPanel)).Subscribe(_ => { if ((_.DockPanel as DockPanel)?.FindResource("GroupedItems") is CollectionViewSource collectionViewSource) { collectionViewSource.GroupDescriptions.Add(_.pgd); } }); GroupClick = new Command.RelayCommand <string>(a => GroupNameChanges.OnNext(a)); NameChanges .Merge(GroupNameChanges) .CombineLatest(ControlChanges.Select(c => c as TextBlock).Where(c => c != null), (text, textBlock) => (text, textBlock)) .ObserveOnDispatcher() .Subscribe(input => { input.textBlock.Text = input.text; input.textBlock.Visibility = Visibility.Visible; input.textBlock.IsEnabled = true; input.textBlock.IsEnabled = false; }); GroupNameChanges.CombineLatest( SelectChanges <PropertyGroupDescription>().StartWith(PropertyGroupDescription), SelectChanges <IValueConverter>(nameof(DataConverter)).StartWith(default(IValueConverter)), SelectChanges <string>(nameof(Id)).StartWith(Id), (text, pg, conv, id) => (text, pg, conv, id)) //.ObserveOn(TaskPoolScheduler.Default) .Subscribe(async input => { await Dispatcher.InvokeAsync(() => { var paths = Items.Cast <object>(); var prop = paths.First().GetType().GetProperty(input.pg.PropertyName); // property-group-converter var converter = input.pg.Converter; var group = paths.Where(ad => { bool result = converter != default ? input.text .Equals(converter.Convert(prop.GetValue(ad), null, null, null)) : input.text .Equals(prop.GetValue(ad)); return(result); }) .Select(viewmodel => new Property.KeyValue( viewmodel.GetType().GetProperty(input.id).GetValue(viewmodel).ToString(), viewmodel)); Convert(group, input.conv, (items, conv) => conv.Convert(items, null, null, null)); }, DispatcherPriority.Background); }); ContentTemplateSelector = new PropertyDataTemplateSelector(); }
public TailViewModel([NotNull] ILogger logger, [NotNull] ISchedulerProvider schedulerProvider, [NotNull] IFileWatcher fileWatcher, [NotNull] ISelectionMonitor selectionMonitor, [NotNull] IClipboardHandler clipboardHandler, [NotNull] ISearchInfoCollection searchInfoCollection, [NotNull] IInlineViewerFactory inlineViewerFactory, [NotNull] ISetting <GeneralOptions> generalOptions, [NotNull] ISearchMetadataCollection searchMetadataCollection, [NotNull] IStateBucketService stateBucketService, [NotNull] SearchOptionsViewModel searchOptionsViewModel, [NotNull] ITailViewStateRestorer restorer, [NotNull] SearchHints searchHints, [NotNull] ITailViewStateControllerFactory tailViewStateControllerFactory) { if (logger == null) { throw new ArgumentNullException(nameof(logger)); } if (schedulerProvider == null) { throw new ArgumentNullException(nameof(schedulerProvider)); } if (fileWatcher == null) { throw new ArgumentNullException(nameof(fileWatcher)); } if (selectionMonitor == null) { throw new ArgumentNullException(nameof(selectionMonitor)); } if (clipboardHandler == null) { throw new ArgumentNullException(nameof(clipboardHandler)); } if (searchInfoCollection == null) { throw new ArgumentNullException(nameof(searchInfoCollection)); } if (inlineViewerFactory == null) { throw new ArgumentNullException(nameof(inlineViewerFactory)); } if (generalOptions == null) { throw new ArgumentNullException(nameof(generalOptions)); } if (searchMetadataCollection == null) { throw new ArgumentNullException(nameof(searchMetadataCollection)); } if (stateBucketService == null) { throw new ArgumentNullException(nameof(stateBucketService)); } if (searchOptionsViewModel == null) { throw new ArgumentNullException(nameof(searchOptionsViewModel)); } if (searchHints == null) { throw new ArgumentNullException(nameof(searchHints)); } Name = fileWatcher.FullName; SelectionMonitor = selectionMonitor; SearchOptions = searchOptionsViewModel; SearchHints = searchHints; SearchCollection = new SearchCollection(searchInfoCollection, schedulerProvider); CopyToClipboardCommand = new Command(() => clipboardHandler.WriteToClipboard(selectionMonitor.GetSelectedText())); OpenFileCommand = new Command(() => Process.Start(fileWatcher.FullName)); OpenFolderCommand = new Command(() => Process.Start(fileWatcher.Folder)); SearchMetadataCollection = searchMetadataCollection; var horizonalScrollArgs = new ReplaySubject <TextScrollInfo>(1); HorizonalScrollChanged = args => { horizonalScrollArgs.OnNext(args); }; _tailViewStateControllerFactory = tailViewStateControllerFactory; //Move these 2 highlight fields to a service as all views require them UsingDarkTheme = generalOptions.Value .ObserveOn(schedulerProvider.MainThread) .Select(options => options.Theme == Theme.Dark) .ForBinding(); HighlightTail = generalOptions.Value .ObserveOn(schedulerProvider.MainThread) .Select(options => options.HighlightTail) .ForBinding(); //this deals with state when loading the system at start up and at shut-down _persister = new TailViewPersister(this, restorer); //An observable which acts as a scroll command var autoChanged = this.WhenValueChanged(vm => vm.AutoTail); var scroller = _userScrollRequested.CombineLatest(autoChanged, (user, auto) => { var mode = AutoTail ? ScrollReason.Tail : ScrollReason.User; return(new ScrollRequest(mode, user.PageSize, user.FirstIndex)); }) .Do(x => logger.Info("Scrolling to {0}/{1}", x.FirstIndex, x.PageSize)) .DistinctUntilChanged(); FileStatus = fileWatcher.Status.ForBinding(); //command to add the current search to the tail collection var searchInvoker = SearchHints.SearchRequested.Subscribe(request => { searchInfoCollection.Add(request.Text, request.UseRegEx); }); //User feedback to show file size FileSizeText = fileWatcher.Latest.Select(fn => fn.Size) .Select(size => size.FormatWithAbbreviation()) .DistinctUntilChanged() .ForBinding(); //tailer is the main object used to tail, scroll and filter in a file var lineScroller = new LineScroller(SearchCollection.Latest.ObserveOn(schedulerProvider.Background), scroller); MaximumChars = lineScroller.MaximumLines() .ObserveOn(schedulerProvider.MainThread) .ForBinding(); //load lines into observable collection var lineProxyFactory = new LineProxyFactory(new TextFormatter(searchMetadataCollection), new LineMatches(searchMetadataCollection), horizonalScrollArgs.DistinctUntilChanged()); var loader = lineScroller.Lines.Connect() .LogChanges(logger, "Received") .Transform(lineProxyFactory.Create, new ParallelisationOptions(ParallelType.Ordered, 3)) .LogChanges(logger, "Sorting") .Sort(SortExpressionComparer <LineProxy> .Ascending(proxy => proxy)) .ObserveOn(schedulerProvider.MainThread) .Bind(out _data, 100) .LogChanges(logger, "Bound") .DisposeMany() .LogErrors(logger) .Subscribe(); //monitor matching lines and start index, Count = searchInfoCollection.All.Select(latest => latest.Count).ForBinding(); CountText = searchInfoCollection.All.Select(latest => $"{latest.Count.ToString("##,###")} lines").ForBinding(); LatestCount = SearchCollection.Latest.Select(latest => latest.Count).ForBinding(); ////track first visible index var firstIndexMonitor = lineScroller.Lines.Connect() .Buffer(TimeSpan.FromMilliseconds(25)).FlattenBufferResult() .ToCollection() .Select(lines => lines.Count == 0 ? 0 : lines.Select(l => l.Index).Max() - lines.Count + 1) .ObserveOn(schedulerProvider.MainThread) .Subscribe(first => { FirstIndex = first; }); //Create objects required for inline viewing var isUserDefinedChanged = SearchCollection.WhenValueChanged(sc => sc.Selected) .Where(selected => selected != null) .Select(selected => selected.IsUserDefined) .DistinctUntilChanged() .Replay(1) .RefCount(); var inlineViewerVisible = isUserDefinedChanged.CombineLatest(this.WhenValueChanged(vm => vm.ShowInline), (userDefined, showInline) => userDefined && showInline); CanViewInline = isUserDefinedChanged.ForBinding(); InlineViewerVisible = inlineViewerVisible.ForBinding(); //return an empty line provider unless user is viewing inline - this saves needless trips to the file var inline = searchInfoCollection.All.CombineLatest(inlineViewerVisible, (index, ud) => ud ? index : new EmptyLineProvider()); InlineViewer = inlineViewerFactory.Create(inline, this.WhenValueChanged(vm => vm.SelectedItem), searchMetadataCollection); _cleanUp = new CompositeDisposable(lineScroller, loader, firstIndexMonitor, FileStatus, Count, LatestCount, FileSizeText, CanViewInline, InlineViewer, InlineViewerVisible, SearchCollection, searchInfoCollection, HighlightTail, UsingDarkTheme, searchHints, searchMetadataCollection, SelectionMonitor, SearchOptions, searchInvoker, MaximumChars, _stateMonitor, horizonalScrollArgs.SetAsComplete(), _userScrollRequested.SetAsComplete()); }
public ReportsViewModel(ITogglDataSource dataSource, ITimeService timeService, INavigationService navigationService, IInteractorFactory interactorFactory, IAnalyticsService analyticsService, ISchedulerProvider schedulerProvider, IRxActionFactory rxActionFactory) : base(navigationService) { Ensure.Argument.IsNotNull(dataSource, nameof(dataSource)); Ensure.Argument.IsNotNull(timeService, nameof(timeService)); Ensure.Argument.IsNotNull(rxActionFactory, nameof(rxActionFactory)); Ensure.Argument.IsNotNull(analyticsService, nameof(analyticsService)); Ensure.Argument.IsNotNull(interactorFactory, nameof(interactorFactory)); Ensure.Argument.IsNotNull(schedulerProvider, nameof(schedulerProvider)); Ensure.Argument.IsNotNull(navigationService, nameof(navigationService)); this.dataSource = dataSource; this.timeService = timeService; this.analyticsService = analyticsService; this.interactorFactory = interactorFactory; CalendarViewModel = new ReportsCalendarViewModel(timeService, dataSource, rxActionFactory, navigationService); var totalsObservable = reportSubject .SelectMany(_ => interactorFactory.GetReportsTotals(userId, workspaceId, startDate, endDate).Execute()) .Catch <ITimeEntriesTotals, OfflineException>(_ => Observable.Return <ITimeEntriesTotals>(null)) .Where(report => report != null); BarChartViewModel = new ReportsBarChartViewModel(schedulerProvider, dataSource.Preferences, totalsObservable, navigationService); IsLoadingObservable = isLoading.AsObservable().StartWith(true).AsDriver(schedulerProvider); StartDate = startDateSubject.AsObservable().AsDriver(schedulerProvider); EndDate = endDateSubject.AsObservable().AsDriver(schedulerProvider); SelectWorkspace = rxActionFactory.FromAsync(selectWorkspace); WorkspaceNameObservable = workspaceSubject .Select(workspace => workspace?.Name ?? string.Empty) .DistinctUntilChanged() .AsDriver(schedulerProvider); WorkspaceHasBillableFeatureEnabled = workspaceSubject .Where(workspace => workspace != null) .SelectMany(workspace => interactorFactory.GetWorkspaceFeaturesById(workspace.Id).Execute()) .Select(workspaceFeatures => workspaceFeatures.IsEnabled(WorkspaceFeatureId.Pro)) .StartWith(false) .DistinctUntilChanged() .AsDriver(schedulerProvider); CurrentDateRange = currentDateRangeStringSubject .Select(text => !string.IsNullOrEmpty(text) ? $"{text} ▾" : "") .DistinctUntilChanged() .AsDriver(schedulerProvider); WorkspacesObservable = interactorFactory.ObserveAllWorkspaces().Execute() .Select(list => list.Where(w => !w.IsInaccessible)) .Select(readOnlyWorkspaceSelectOptions) .AsDriver(schedulerProvider); DurationFormatObservable = dataSource.Preferences.Current .Select(prefs => prefs.DurationFormat) .AsDriver(schedulerProvider); SegmentsObservable = segmentsSubject.CombineLatest(DurationFormatObservable, applyDurationFormat); GroupedSegmentsObservable = SegmentsObservable.CombineLatest(DurationFormatObservable, groupSegments); ShowEmptyStateObservable = SegmentsObservable.CombineLatest(IsLoadingObservable, shouldShowEmptyState); }