Skip to content

A little Swing wrap-up #350

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Sep 6, 2013
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Added a helper for computing relative mouse motion.
  • Loading branch information
jmhofer committed May 9, 2013
commit ff7312055a6ff5bb76b349af02f6d9c4169fe31e
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

import java.awt.Component;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ComponentEvent;
import java.awt.event.KeyEvent;
Expand Down Expand Up @@ -110,6 +111,16 @@ public static Observable<MouseEvent> fromMouseMotionEvents(Component component)
return MouseEventSource.fromMouseMotionEventsOf(component);
}

/**
* Creates an observable corresponding to relative mouse motion.
* @param component
* The component to register the observable for.
* @return A point whose x and y coordinate represent the relative horizontal and vertical mouse motion.
*/
public static Observable<Point> fromRelativeMouseMotion(Component component) {
return MouseEventSource.fromRelativeMouseMotion(component);
}

/**
* Creates an observable corresponding to raw component events.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,28 @@
*/
package rx.swing.sources;

import static org.mockito.Mockito.*;

import java.awt.Component;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;

import javax.swing.JPanel;

import org.junit.Test;
import org.mockito.InOrder;
import org.mockito.Matchers;

import rx.Observable;
import rx.Observer;
import rx.Subscription;
import rx.subscriptions.Subscriptions;
import rx.util.functions.Action0;
import rx.util.functions.Action1;
import rx.util.functions.Func1;
import rx.util.functions.Func2;

public enum MouseEventSource { ; // no instances

Expand Down Expand Up @@ -103,4 +114,86 @@ public void call() {
}
});
}

/**
* @see rx.observables.SwingObservable#fromRelativeMouseMotion
*/
public static Observable<Point> fromRelativeMouseMotion(final Component component) {
class OldAndRelative {
public final Point old;
public final Point relative;

private OldAndRelative(Point old, Point relative) {
this.old = old;
this.relative = relative;
}
}

class Relativize implements Func2<OldAndRelative, MouseEvent, OldAndRelative> {
@Override
public OldAndRelative call(OldAndRelative last, MouseEvent event) {
Point current = new Point(event.getX(), event.getY());
Point relative = new Point(current.x - last.old.x, current.y - last.old.y);
return new OldAndRelative(current, relative);
}
}

class OnlyRelative implements Func1<OldAndRelative, Point> {
@Override
public Point call(OldAndRelative oar) {
return oar.relative;
}
}

return fromMouseMotionEventsOf(component)
.scan(new OldAndRelative(new Point(0, 0), new Point(0, 0)), new Relativize())
.map(new OnlyRelative())
.skip(2); // skip the useless initial value and the invalid first computation
}

public static class UnitTest {
private Component comp = new JPanel();

@Test
public void testRelativeMouseMotion() {
@SuppressWarnings("unchecked")
Action1<Point> action = mock(Action1.class);
@SuppressWarnings("unchecked")
Action1<Exception> error = mock(Action1.class);
Action0 complete = mock(Action0.class);

Subscription sub = fromRelativeMouseMotion(comp).subscribe(action, error, complete);

InOrder inOrder = inOrder(action);

verify(action, never()).call(Matchers.<Point>any());
verify(error, never()).call(Matchers.<Exception>any());
verify(complete, never()).call();

fireMouseEvent(mouseEvent(0, 0));
verify(action, never()).call(Matchers.<Point>any());

fireMouseEvent(mouseEvent(10, -5));
inOrder.verify(action, times(1)).call(new Point(10, -5));

fireMouseEvent(mouseEvent(6, 10));
inOrder.verify(action, times(1)).call(new Point(-4, 15));

sub.unsubscribe();
fireMouseEvent(mouseEvent(0, 0));
inOrder.verify(action, never()).call(Matchers.<Point>any());
verify(error, never()).call(Matchers.<Exception>any());
verify(complete, never()).call();
}

private MouseEvent mouseEvent(int x, int y) {
return new MouseEvent(comp, MouseEvent.MOUSE_MOVED, 1L, 0, x, y, 0, false);
}

private void fireMouseEvent(MouseEvent event) {
for (MouseMotionListener listener: comp.getMouseMotionListeners()) {
listener.mouseMoved(event);
}
}
}
}