Rx Workshop: Reactive Coincidence

Sign in to queue

The Discussion

  • User profile image
    aL_

    awsome stuff.. Smiley

     

  • User profile image
    BennyG

    Am I allowed to post the solution of the challange?

    Benny

  • User profile image
    AceHack

    Here is what I came up with

                var query = Observable.Join(
                    mouseDown, 
                    mouseMove, 
                    _ => mouseUp, 
                    _ => Observable.Empty<Unit>(), 
                    (_, r) => r)
                    .Publish(evt => evt.Zip(evt.Skip(1), 
                        (previous, current) => Subtract(current, previous)));
    

    I am having difficulty translating this into query comprehension syntax.  Anyone figure that out?  Thanks.

  • User profile image
    AceHack

    Alright here is a working query comprehension version

    var query = from start in mouseDown
                join move in mouseMove
                on mouseUp equals Observable.Empty<Unit>() into moveGroup
                let drag = moveGroup.Zip(moveGroup.Skip(1),
                    (prev, curr) => Subtract(curr, prev))
                from delta in drag
                select delta;
    

    Still curious if this could be cleaner.  Thanks.

     

  • User profile image
    MrLovebucket

    Here is my solution:

    var query = Observable.Join(
    mouseDown,
    mouseMove.Buffer(2),
    _ => mouseUp,
    m => Observable.Empty<Unit>(),
    (_, r) => Subtract(r.Last(),r.First()));

  • User profile image
    BennyG

    I think my solution is close to the optimum!?

    But I had to modify the subscibtion from deltas to absolute points.

       var query = mouseDown.Join(mouseMove, l => mouseUp, r => Observable.Empty<Point>(),(l,r)=> Subtract(r,l));
    
               query.Subscribe(pos=>
                {
                    Canvas.SetLeft(image, pos.X);
                    Canvas.SetTop(image, pos.Y);
                });

  • User profile image
    AceHack

    I notied there is a bug when releasing the mouse button from outside of the window.  Here is a fix that will merge mouseUp and mouseLeave to accomplish the task.  What is normal UI guidance for drag and drop when going outside the window?  Thanks.

                var mouseLeave = from evt in Observable.FromEventPattern<MouseEventHandler, MouseEventArgs>(h => MouseLeave += h, h => MouseLeave -= h)
                                 select evt.EventArgs.GetPosition(this);
                var query = from start in mouseDown
                            join move in mouseMove.Buffer(2)
                            on mouseUp.Merge(mouseLeave) equals Observable.Empty<Unit>()
                            select Subtract(move.Last(), move.First());
    

  • User profile image
    AceHack

    Hey what happened to the challenges.  They are showing up 404.  I was trying to dowload again.  Thanks.

  • User profile image
    Ivar_​Rummelhoff

    Here is my (edited) suggestion:

    mouseMove
    .Buffer(2, 1)
    .Select(b => b[1] - b[0])
    .Window(mouseDown, _ => mouseUp)
    .Concat();
    

    The Subtract method is not needed.

  • User profile image
    Malc
    What I ended up with in query and fluent:
                var query = from down in mouseDown
                            join delta in
                                from move in mouseMove.Buffer(2)
                                select Subtract(move.Last(), move.First())
                                on mouseUp equals Observable.Empty<Unit>() 
                            select delta;
    //            var query = Observable.Join(
    //                mouseDown,
    //                mouseMove.Buffer(2).Select(b => Subtract(b.Last(), b.First())),
    //                _ => mouseUp,
    //                _ => Observable.Empty<EventArgs>(),
    //                (_, r) => r);
    ...though interested if anyone came up with a way to buffer then collapse after the join (I battered my head against that approach for a while before going for this).
    Also ended up with the same sln as BennyG first time after missreading the subscribe lambda...

  • User profile image
    JJJ

    Here is a solution that uses the Scan method:

    var query = mouseDown.Join(
    mouseMove
    .Scan(new { Prev = new Point(), Delta = new Point() },
    (current, next) => new { Prev = next, Delta = Subtract(next, current.Prev) })
    .Select(x => x.Delta),
    down => mouseUp,
    delta => Observable.Empty<Unit>(),
    (down, delta) => delta);

  • User profile image
    Geoffreyk

    reopening comments

  • User profile image
    Anaristos

    My solution was based on a similar handling by SelectMany().

    private void DragAndDrop()
            {
                var mousedown = Observable.FromEventPattern<MouseButtonEventHandler, MouseButtonEventArgs>(h => image.MouseDown += h,
                                                                                                           h => image.MouseDown -= h)
                                          .Select(e => e.EventArgs.GetPosition(image));
    
                var mousemove = Observable.FromEventPattern<MouseEventHandler, MouseEventArgs>(h => image.MouseMove += h,
                                                                                               h => image.MouseMove -= h)
                                          .Select(e => e.EventArgs.GetPosition(canvas));
    
                var mouseup = Observable.FromEventPattern<MouseButtonEventHandler, MouseButtonEventArgs>(h => image.MouseUp += h,
                                                                                                         h => image.MouseUp -= h)
                                        .Select(e => e.EventArgs.GetPosition(image));
    
                var query = Observable.Join( mousedown
                                            ,mousemove
                                            ,p1 => mouseup
                                            ,p2 => Observable.Empty<Point>()
                                            ,(p1, p2) => new { X = p2.X - p1.X, Y = p2.Y - p1.Y }
                                          )
                                     .Subscribe(p => { Canvas.SetLeft(image, p.X); Canvas.SetTop(image, p.Y); });
            }
     
    

Add Your 2 Cents