Reactive Framework / DoubleClick - PullRequest
       9

Reactive Framework / DoubleClick

2 голосов
/ 08 марта 2011

Я знаю, что есть простой способ сделать это - но сегодня я победил ...

Я хочу знать, происходят ли два события в пределах 300 миллисекунд друг от друга, как при двойном щелчке.

Два щелчка левой кнопкой мыши в течение 300 миллисекунд - я знаю, что это то, для чего была построена реактивная структура - но, черт побери, я могу найти хороший документ, в котором есть простые примеры для всех операторов расширений - Throttle, BufferWithCount, BufferWithTime - все который просто не сделал это для меня ....

Ответы [ 2 ]

9 голосов
/ 08 марта 2011

Метод TimeInterval даст вам время между значениями.

public static IObservable<Unit> DoubleClicks<TSource>(
    this IObservable<TSource> source, TimeSpan doubleClickSpeed, IScheduler scheduler)
{
    return source
        .TimeInterval(scheduler)
        .Skip(1)
        .Where(interval => interval.Interval <= doubleClickSpeed)
        .RemoveTimeInterval();
}

Если вы хотите быть уверены, что тройной щелчок не вызывает значения, вы можете просто использовать Repeat на горячемнаблюдаемый (я использовал FastSubject здесь, поскольку все клики будут приходить на один поток и, следовательно, не требуют тяжести нормальных тем):

public static IObservable<TSource> DoubleClicks<TSource>(
    this IObservable<TSource> source, TimeSpan doubleClickSpeed, IScheduler scheduler)
{
    return source.Multicast<TSource, TSource, TSource>(
        () => new FastSubject<TSource>(), // events won't be multithreaded
        values =>
        {
            return values
                .TimeInterval(scheduler)
                .Skip(1)
                .Where(interval => interval.Interval <= doubleClickSpeed)
                .RemoveTimeInterval()
                .Take(1)
                .Repeat();
        });
}
3 голосов
/ 08 марта 2011

Edit - используйте TimeInterval() вместо.

Операторы Zip() and Timestamp() могут быть хорошим началом.

var ioClicks = Observable.FromEvent<MouseButtonEventHandler, RoutedEventArgs>(
                                        h => new MouseButtonEventHandler(h),
                                        h => btn.MouseLeftButtonDown += h,
                                        h => btn.MouseLeftButtonDown -= h);
var ioTSClicks = ioClicks.Timestamp();

var iodblClicks = ioTSClicks.Zip(ioTSClicks.Skip(1), 
                                 (r, l) => l.Timestamp - r.Timestamp)
                            .Where(tspan => tspan.TotalMilliseconds < 300);

Вероятно, лучше всего проверить это с помощью планировщика тестов, так что вы знаете,именно то, что вы получаете:

[Fact]
public void DblClick()
{
    // setup
    var ioClicks = _scheduler.CreateHotObservable(
                     OnNext(210, "click"),
                     OnNext(220, "click"),
                     OnNext(300, "click"),
                     OnNext(365, "click"))
                     .Timestamp(_scheduler);

    // act
    Func<IObservable<TimeSpan>> target = 
        () => ioClicks.Zip(ioClicks.Skip(1), 
                          (r, l) => l.Timestamp - r.Timestamp)
                        .Where(tspan => tspan.Ticks < 30);
    var actuals = _scheduler.Run(target);

    // assert
    Assert.Equal(actuals.Count(), 1);
    // + more
}
public static Recorded<Notification<T>> OnNext<T>(long ticks, T value)
{
    return new Recorded<Notification<T>>(
        ticks, 
        new Notification<T>.OnNext(value));
}
...