Пример #1
0
        /// <summary>
        /// Map many Behaviours to a single Behaviour with a function.
        /// </summary>
        public Behaviour <R> Combine <B, R>(Func <A, B, R> combine, Behaviour <B> b)
        {
            var r = new Behaviour <R>(combine(Value, b.Value));

            Subject.CombineLatest(b.Subject, combine).Subscribe(r.Subject);
            return(r);
        }
        public static void Create(IFuse fuse, IObservable <Unit> doneLoadingMainWindow, BehaviorSubject <bool> showSetupGuide)
        {
            var showSublimeNotification   = new BehaviorSubject <bool>(false);
            var dontCheckForSublimePlugin = UserSettings.Bool("DontCheckForSublimePlugin").AutoInvalidate();

            Application.Desktop.CreateSingletonWindow(
                isVisible: showSublimeNotification.CombineLatest(doneLoadingMainWindow, (show, _) => show),
                window: dialog => new Window
            {
                Title   = Observable.Return("No editor plugin detected"),
                Size    = Optional.Some(Property.Constant(Optional.Some(new Size <Points>(600, 270)))),
                Content = Control.Lazy(() => CreateContent(showSublimeNotification, showSetupGuide, dontCheckForSublimePlugin))
                          .WithBackground(Theme.PanelBackground),
                Background = Theme.PanelBackground,
                Foreground = Theme.DefaultText,
                Border     = Separator.MediumStroke,
            });

            dontCheckForSublimePlugin
            .Select(v => v.Or(false))
            .Where(v => !v)
            .Take(1)
            .SubscribeOn(TaskPoolScheduler.Default)
            .Subscribe(_ => Task.Run(() =>
            {
                if (new SublimePlugin(fuse.ModulesDir).Status == ComponentStatus.NotInstalled)
                {
                    showSublimeNotification.OnNext(true);
                }
            }));
        }
Пример #3
0
        public static IControl CreateDebugControl()
        {
            var debugControls = DebugControls
                                .Throttle(TimeSpan.FromMilliseconds(10));
            var controls = debugControls
                           .CachePerElement(getKey: ctrl => ctrl.Value, getValue: ctrl => ctrl.Value.Name)
                           .SelectPerElement(name =>
                                             CreateDebugItem(name, Command.Enabled(action: () => SelectedControl.OnNext(name))));

            var infoPanel = SelectedControl
                            .CombineLatest(debugControls, (sel, ctrls) => sel.HasValue ? CreateInfoPanel(ctrls[sel.Value]) : CreateNothingSelected())
                            .Switch();

            return(Layout.Dock()
                   .Left(
                       Layout.Dock().Top(Header("Debug Controls"))
                       .Fill(controls.StackFromTop().MakeScrollable())
                       .WithWidth(200)
                       .WithPadding(new Thickness <Points>(10))
                       )
                   .Left(
                       Layout.StackFromTop(
                           Header("Mount Info"),
                           infoPanel
                           ).WithPadding(new Thickness <Points>(10))
                       )
                   .Fill()
                   .WithPadding(new Thickness <Points>(10)));
        }
Пример #4
0
        public SetupGuide(IFuse fuse, IObservable <Unit> doneLoadingMainWindow)
        {
            var output = new Subject <string>();

            LogMessages = output;

            var report    = fuse.Report;
            var softwares = new SoftwareCollectionStatus(fuse);

            var showSetupGuide = new BehaviorSubject <bool>(false);

            MissingPluginNotification.Create(fuse, doneLoadingMainWindow, showSetupGuide);

            Application.Desktop.CreateSingletonWindow(
                isVisible: showSetupGuide.CombineLatest(doneLoadingMainWindow, (s, _) => s),
                window: dialog => new Window
            {
                Title   = Observable.Return("Setup guide"),
                Size    = Optional.Some(Property.Constant(Optional.Some(new Size <Points>(500, 300)))),
                Content = Control.Lazy(() => Create(softwares, report, dialog).ShowWhen(showSetupGuide))
                          .WithBackground(Theme.PanelBackground),
                Background = Theme.PanelBackground,
                Foreground = Theme.DefaultText,
                Border     = Separator.MediumStroke,
                Style      = WindowStyle.Fat,
            });

            Menu
                = Menu.Item("Install Android SDKs", () => fuse.RunFuse("install", new [] { "android" }, Observer.Create <string>(output.OnNext)))
                  + Menu.Item("Setup guide", () => showSetupGuide.OnNext(true));
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="FeatureActivator"/> class.
        /// </summary>
        /// <param name="activate">A function to be called when the first observer subscribes and all dependencies (if any) are available.</param>
        /// <param name="deactivate">A function to be called when any dependency becomes unavailable.</param>
        /// <param name="dependsOn">A set of dependencies, all of which must produce a true result in order for activation to be triggered.</param>
        public FeatureActivator(Func <T> activate, Func <T> deactivate, params IObservable <bool>[] dependsOn)
        {
            if (activate == null)
            {
                throw new ArgumentNullException("activate");
            }
            this.activate   = activate;
            this.deactivate = deactivate ?? (() => default(T));

            IObservable <bool> dependenciesAvailable = new BehaviorSubject <bool>(true);

            foreach (var dependency in dependsOn)
            {
                dependenciesAvailable = dependenciesAvailable.CombineLatest(dependency, (x, y) => x && y);
            }

            available = dependenciesAvailable
                        .DistinctUntilChanged()
                        .Select(availableNow =>
            {
                if (!availableNow)
                {
                    if (hasBeenActivated)
                    {
                        return(Deactivate());
                    }
                    return(default(T));
                }

                return(Activate());
            })
                        .Replay(1);
        }
Пример #6
0
        public Submission()
        {
            children = new BehaviorSubject <IEnumerable <Submission> >(Enumerable.Empty <Submission>());

            answer = new BehaviorSubject <string>("");

            manualGrade = new BehaviorSubject <float?>(null);

            childGrade = children.Select(xs => xs.Select(x => x.grade).CombineLatestSafe()).Merge().Select(x => x.Flatten().AverageSafe());

            childPass = children.Select(xs => xs.Select(x => x.pass).CombineLatestSafe()).Merge().Select(xs => xs.Conjunction());

            grade = manualGrade.CombineLatest(childGrade, childPass, (manualGrade1, childGrade1, childPass1) =>
            {
                if (manualGrade1.HasValue)
                {
                    return(manualGrade1);
                }
                else
                {
                    if (childPass1)
                    {
                        return(childGrade1);
                    }
                    else
                    {
                        return(null);
                    }
                }
            });

            pass = grade.Select(g => g.HasValue ? g >= 5.5f : false);
        }
Пример #7
0
        public void RxPrecise()
        {
            var lefts       = new BehaviorSubject <bool>(false);
            var rights      = new BehaviorSubject <bool>(false);
            var leftOrRight = lefts.CombineLatest(rights, (left, right) => left || right);

            leftOrRight.Subscribe(value => Console.WriteLine("leftOrRight = " + value)); // Prints 'leftOrRight = False'

            rights.OnNext(true);                                                         // Prints 'leftOrRight = True'
            lefts.OnNext(true);                                                          // Prints 'leftOrRight = True'
            rights.OnNext(false);                                                        // Prints 'leftOrRight = True' (while SmartReactives prints nothing here)
        }
Пример #8
0
 private IControl CreateContent()
 {
     return
         (Layout.StackFromTop(
              Label.Create(
                  _mainFile
                  .Select(x => x.Select(path => "Start/stop random mutation of " + path.NativePath))
                  .Or("No file with <App> tag found.")
                  .AsText())
              .WithHeight(70)
              .Center(),
              Button.Create(clicked: _state.CombineLatest(_mainFile, CreateCommand).Switch())
              .Center(),
              Label.Create("DANGER: This will overwrite stuff in your file!")
              .WithHeight(70)
              .Center()));
 }
Пример #9
0
        public async Task SyncBufferTest()
        {
            var i1        = new BehaviorSubject <int>(1);
            var i2        = new BehaviorSubject <int>(4);
            var sum       = i1.CombineLatest(i2, (i1Value, i2Value) => i1Value + i2Value);
            var listAsync = sum.SynchronousBuffer().Select(buf => buf.Last()).ToList().RunAsync(new CancellationToken());

            Action syncChange1 = () =>
            {
                i1.OnNext(2);
                i2.OnNext(5);
                i1.OnNext(7);
            };

            Action syncChange2 = () =>
            {
                i1.OnNext(1);
                i2.OnNext(1);
            };

            Action syncChange3 = () =>
            {
                i1.OnNext(3);
                i1.OnCompleted();
                i2.OnCompleted();
            };


            var changeTask = Task.Run(syncChange1)
                             .ContinueWith(t => syncChange2())
                             .ContinueWith(t => syncChange3());

            var list = await listAsync;

            await changeTask;

            Assert.Equal(new List <int> {
                5, 12, 2, 4
            }, list.ToList());
        }
Пример #10
0
        public static void Create()
        {
            var lightTheme = new OriginalLightTheme();
            var darkTheme  = new OriginalDarkTheme();

            var path    = new BehaviorSubject <string>(string.Empty);
            var refresh = new BehaviorSubject <Unit>(Unit.Default);
            var image   = path
                          .CombineLatest(refresh, ((p, _) => p))
                          .Select(p => AbsoluteFilePath.TryParse(p)
                                  .Where(f => File.Exists(f.NativePath))
                                  .Select(
                                      absPath => absPath.NativePath.EndsWith(".svg")
                                                        ? (IImage) new SvgImage(() => File.OpenRead(absPath.NativePath))
                                                        : new MultiResolutionImage(
                                          new[] { new ImageStream(new Ratio <Pixels, Points>(1), () => File.OpenRead(absPath.NativePath)) }))
                                  .Or(() => (IImage) new SvgImage(() => new MemoryStream(FallbackImage))));

            var content =
                Layout.Dock().Top(
                    Layout.Dock()
                    .Left(Label.Create("Path: ", font: Theme.DefaultFont, color: Theme.DefaultText).CenterVertically())
                    .Right(Buttons.DefaultButton("Refresh", Command.Enabled(() => refresh.OnNext(Unit.Default))))
                    .Fill(ThemedTextBox.Create(path.AsProperty())))
                .Fill(Layout.SubdivideHorizontally(ImageVersionsRowForTheme(image, darkTheme), ImageVersionsRowForTheme(image, lightTheme)))
                .WithBackground(Theme.PanelBackground);

            Application.Desktop.CreateSingletonWindow(
                Observable.Return(true),
                dialog => new Window
            {
                Title      = Observable.Return("Icon preview"),
                Size       = Property.Create <Optional <Size <Points> > >(new Size <Points>(600, 600)).ToOptional(),
                Content    = content,
                Background = Theme.PanelBackground,
                Foreground = Theme.DefaultText,
                Border     = Separator.MediumStroke
            });
        }
Пример #11
0
        public void AsyncObservableThreadsWithBetterThrottleOnComputeAndIsCalculating()
        {
            Console.WriteLine("Starting Thread " + Thread.CurrentThread.ManagedThreadId);
            BehaviorSubject<int> s1 = new BehaviorSubject<int>(2);
            BehaviorSubject<int> s2 = new BehaviorSubject<int>(3);
            BehaviorSubject<int> sum = new BehaviorSubject<int>(5);
            List<int> computeThreads = new List<int>();
            List<int> receiveThreads = new List<int>();
            IScheduler throttleScheduler = new EventLoopScheduler();
            Func<IScheduler> getComputeScheduler = () => new EventLoopScheduler();
            IScheduler receiveScheduler = new EventLoopScheduler();

            IObservable<Tuple<int, int>> sumObservable = s1.CombineLatest(s2, Tuple.Create).Throttle(TimeSpan.FromMilliseconds(100), throttleScheduler);

            IDisposable sumObservableSubscription = null;
            using (sumObservable.Subscribe(v =>
                {
                    if (sumObservableSubscription != null)
                    {
                        Console.WriteLine("Canceling previous.");
                        sumObservableSubscription.Dispose();
                    }
                    sumObservableSubscription = Observable.Create<int>((o, token) => Task.Factory.StartNew(() =>
                        {
                            Thread.Sleep(200);
                            if (!token.IsCancellationRequested)
                            {
                                Console.WriteLine("Computing value " + v.Item1 + " + " + v.Item2 + " = " + (v.Item1 + v.Item2) + " on Thread " + Thread.CurrentThread.ManagedThreadId + ".");
                                computeThreads.Add(Thread.CurrentThread.ManagedThreadId);
                                o.OnNext(v.Item1 + v.Item2);
                            }
                            o.OnCompleted();
                            return Disposable.Empty;
                        })).ObserveOn(receiveScheduler).Subscribe(v2 =>
                            {
                                Console.WriteLine("Received value " + v2 + " on Thread " + Thread.CurrentThread.ManagedThreadId + ".");
                                receiveThreads.Add(Thread.CurrentThread.ManagedThreadId);
                            });
                }))
            {
                Stopwatch stopwatch = new Stopwatch();
                stopwatch.Start();

                Thread.Sleep(150);
                s2.OnNext(1);
                Thread.Sleep(50);
                s1.OnNext(4);
                Thread.Sleep(250);
                s2.OnNext(4);
                Thread.Sleep(150);
                s1.OnNext(1);
                Thread.Sleep(350);

                stopwatch.Stop();
                Console.WriteLine("Total Time: " + stopwatch.ElapsedMilliseconds + " ms");

                foreach (KeyValuePair<int, int> p in
                    computeThreads.GroupBy(v => v).Select(g => new KeyValuePair<int, int>(g.Key, g.Count())))
                {
                    Console.WriteLine(p.Value + " computes on Thread " + p.Key);
                }
                foreach (KeyValuePair<int, int> p in
                    receiveThreads.GroupBy(v => v).Select(g => new KeyValuePair<int, int>(g.Key, g.Count())))
                {
                    Console.WriteLine(p.Value + " receives on Thread " + p.Key);
                }
            }
        }
Пример #12
0
        public void RxOnlyAsyncObservableThreadsWithBetterThrottleOnComputeAndIsCalculating()
        {
            Console.WriteLine("Starting Thread " + Thread.CurrentThread.ManagedThreadId);
            BehaviorSubject<int> s1 = new BehaviorSubject<int>(2);
            BehaviorSubject<int> s2 = new BehaviorSubject<int>(3);
            List<int> computeThreads = new List<int>();
            List<int> receiveThreads = new List<int>();
            IScheduler throttleScheduler = new EventLoopScheduler();
            IScheduler computeScheduler = NewThreadScheduler.Default;
            IScheduler receiveScheduler = new EventLoopScheduler();

            IObservable<Tuple<int, int>> sumObservable = s1.CombineLatest(s2, Tuple.Create).Throttle(TimeSpan.FromMilliseconds(100), throttleScheduler);

            Func<CalculatedPropertyHelper, int, int, Task<int>> calculate = async (helper, v1, v2) =>
                {
                    Thread.Sleep(200);
                    helper.CheckCancellationToken();
                    Console.WriteLine("Computing value " + v1 + " + " + v2 + " = " + (v1 + v2) + " on Thread " + Thread.CurrentThread.ManagedThreadId + ".");
                    computeThreads.Add(Thread.CurrentThread.ManagedThreadId);
                    return await Task.FromResult(v1 + v2);
                };

            BehaviorSubject<int> sum = new BehaviorSubject<int>(0);
            IDisposable scheduledTask = computeScheduler.ScheduleAsync(async (scheduler, token) =>
                {
                    await scheduler.Yield();
                    sum.OnNext(await calculate(new CalculatedPropertyHelper(scheduler, token), s1.Value, s2.Value));
                });
            using (sumObservable.Subscribe(v =>
                {
                    if (scheduledTask != null)
                    {
                        Console.WriteLine("Canceling previous.");
                        scheduledTask.Dispose();
                    }
                    scheduledTask = computeScheduler.ScheduleAsync(async (scheduler, token) =>
                        {
                            await scheduler.Yield();
                            sum.OnNext(await calculate(new CalculatedPropertyHelper(scheduler, token), v.Item1, v.Item2));
                        });
                }))
            {
                using (sum.ObserveOn(receiveScheduler).Subscribe(v2 =>
                    {
                        Console.WriteLine("Received value " + v2 + " on Thread " + Thread.CurrentThread.ManagedThreadId + ".");
                        receiveThreads.Add(Thread.CurrentThread.ManagedThreadId);
                    }))
                {
                    Stopwatch stopwatch = new Stopwatch();
                    stopwatch.Start();

                    Thread.Sleep(150);
                    s2.OnNext(1);
                    Thread.Sleep(50);
                    s1.OnNext(4);
                    Thread.Sleep(250);
                    s2.OnNext(4);
                    Thread.Sleep(150);
                    s1.OnNext(1);
                    Thread.Sleep(350);

                    stopwatch.Stop();
                    Console.WriteLine("Total Time: " + stopwatch.ElapsedMilliseconds + " ms");

                    foreach (KeyValuePair<int, int> p in
                        computeThreads.GroupBy(v => v).Select(g => new KeyValuePair<int, int>(g.Key, g.Count())))
                    {
                        Console.WriteLine(p.Value + " computes on Thread " + p.Key);
                    }
                    foreach (KeyValuePair<int, int> p in
                        receiveThreads.GroupBy(v => v).Select(g => new KeyValuePair<int, int>(g.Key, g.Count())))
                    {
                        Console.WriteLine(p.Value + " receives on Thread " + p.Key);
                    }
                }
            }
        }
Пример #13
0
        public static IControl Create(ITreeViewModel model)
        {
            var rowHeight      = TreeRowView.Height;
            var hoverIndicator = model.PendingDrop.SelectPerElement(
                x => Point.Create(
                    Observable.Return(TreeRowView.GetIndentation(x.Depth + (x.DropPosition == DropPosition.Inside ? 1 : 0))),
                    Observable.Return <Points>((x.RowOffset + (x.DropPosition != DropPosition.Before ? 1 : 0)) * rowHeight)));

            var rowCount = model.TotalRowCount.Replay(1).RefCount();

            var visibleHeight = new BehaviorSubject <Points>(0);
            var contentHeight = visibleHeight.CombineLatest(rowCount, (vheight, rcount) => (Points)Math.Max(vheight, rcount * rowHeight)).Replay(1).RefCount();

            var flipy = ShouldFlip ? ((Func <IObservable <Points>, IObservable <Points> >)(logicalY => logicalY.CombineLatest(contentHeight, (ly, ch) => ch - ly))) : (y => y);

            var rowOffsetToTop = (Func <IObservable <int>, IObservable <Points> >)
                                     (rowOffset => flipy(
                                         rowOffset.Select(offset => new Points(rowHeight.Value * offset))));

            var top = RectangleEdge.Top.FlipVerticallyOnMac();
            //var down = ShouldFlip ? -1.0 : 1.0;
            //var scrollTargetRect =
            //	rowOffsetToTop(model.ScrollTarget)
            //	.Select(rowTop =>
            //		Rectangle.FromPositionSize<Points>(0, 0, 50, 0)
            //		.WithEdge(top, rowTop)
            //		.WithEdge(top.Opposite(), rowTop + rowHeight * down));

            var rowViews = model.VisibleRows
                           .CachePerElement(rowModel => CreateRow(rowModel, rowOffsetToTop))
                           .Replay(1)
                           .RefCount();

            var background =
                rowViews.SelectPerElement(x => x.Background).Layer();
            var foreground =
                rowViews.SelectPerElement(x => x.Foreground).Layer();
            var overlay =
                rowViews.SelectPerElement(x => x.Overlay).Layer();

            var width =
                rowViews.Select(
                    rows => rows.Select(row => row.Foreground.DesiredSize.Width)
                    .CombineLatest()
                    .Select(widths => widths.ConcatOne(0).Max()))
                .Switch()
                .DistinctUntilChanged();

            var treeView =
                Layout.Layer(background, foreground, overlay)
                .WithBackground(Theme.PanelBackground)
                .WithOverlay(InsertionRod.Create(hoverIndicator))
                .WithHeight(contentHeight)
                .WithWidth(width)
                .MakeScrollable(
                    darkTheme: Theme.IsDark,
                    // scrollToRectangle: scrollTargetRect,
                    onBoundsChanged: bounds =>
            {
                var rowTop             = bounds.Visible.GetEdge(top);
                rowTop                 = ShouldFlip ? bounds.Content.Height - rowTop : rowTop;
                var rowOffset          = (int)Math.Floor(rowTop / rowHeight);
                model.VisibleRowOffset = rowOffset;
                var maxVisibleRowCount = (int)Math.Ceiling(bounds.Visible.VerticalInterval.Length / rowHeight.Value) + 1;
                model.VisibleRowCount  = maxVisibleRowCount;
                visibleHeight.OnNext(bounds.Visible.Height);
            });

            // TODO: CAN'T GET LOCAL KEYS TO WORK PROPERLY
            //.OnKeyPressed(ModifierKeys.None, Key.Up, model.NavigateUpCommand, isGlobal: true)
            //.OnKeyPressed(ModifierKeys.None, Key.Down, model.NavigateDownCommand, isGlobal: true);

            return(CreatePopScopeButton(model).DockTop(fill: treeView));
        }
Пример #14
0
        protected override IObservable <float> CreateObservable(IAttributeHolder holder)
        {
            Ensure.That(holder, nameof(holder)).IsNotNull();

            return(_value.CombineLatest(OnModifierChange, OnRangeChange, (v, m, r) => r.Clamp(v * m)));
        }