Skip to content

Commit d3791f6

Browse files
Merge pull request #350 from jmhofer/swing
A little Swing wrap-up
2 parents 0b4b390 + cb02e2a commit d3791f6

File tree

8 files changed

+125
-16
lines changed

8 files changed

+125
-16
lines changed

rxjava-contrib/rxjava-swing/src/main/java/rx/observables/SwingObservable.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import java.awt.Component;
1919
import java.awt.Dimension;
20+
import java.awt.Point;
2021
import java.awt.event.ActionEvent;
2122
import java.awt.event.ComponentEvent;
2223
import java.awt.event.KeyEvent;
@@ -108,6 +109,16 @@ public static Observable<MouseEvent> fromMouseMotionEvents(Component component)
108109
return MouseEventSource.fromMouseMotionEventsOf(component);
109110
}
110111

112+
/**
113+
* Creates an observable corresponding to relative mouse motion.
114+
* @param component
115+
* The component to register the observable for.
116+
* @return A point whose x and y coordinate represent the relative horizontal and vertical mouse motion.
117+
*/
118+
public static Observable<Point> fromRelativeMouseMotion(Component component) {
119+
return MouseEventSource.fromRelativeMouseMotion(component);
120+
}
121+
111122
/**
112123
* Creates an observable corresponding to raw component events.
113124
*

rxjava-contrib/rxjava-swing/src/main/java/rx/swing/sources/AbstractButtonSource.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,14 @@
2929
import rx.Observable.OnSubscribeFunc;
3030
import rx.Observer;
3131
import rx.Subscription;
32-
import rx.observables.SwingObservable;
3332
import rx.subscriptions.Subscriptions;
3433
import rx.util.functions.Action0;
3534
import rx.util.functions.Action1;
3635

3736
public enum AbstractButtonSource { ; // no instances
3837

3938
/**
40-
* @see SwingObservable.fromButtonAction
39+
* @see rx.observables.SwingObservable#fromButtonAction
4140
*/
4241
public static Observable<ActionEvent> fromActionOf(final AbstractButton button) {
4342
return Observable.create(new OnSubscribeFunc<ActionEvent>() {

rxjava-contrib/rxjava-swing/src/main/java/rx/swing/sources/ComponentEventSource.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
public enum ComponentEventSource { ; // no instances
3535

3636
/**
37-
* @see SwingObservable.fromComponentEvents
37+
* @see rx.observables.SwingObservable#fromComponentEvents
3838
*/
3939
public static Observable<ComponentEvent> fromComponentEventsOf(final Component component) {
4040
return Observable.create(new OnSubscribeFunc<ComponentEvent>() {
@@ -74,7 +74,7 @@ public void call() {
7474
}
7575

7676
/**
77-
* @see SwingObservable.fromResizing
77+
* @see SwingObservable#fromResizing
7878
*/
7979
public static Observable<Dimension> fromResizing(final Component component) {
8080
return fromComponentEventsOf(component).filter(RESIZED).map(new Func1<ComponentEvent, Dimension>() {
@@ -104,6 +104,5 @@ private Predicate(int id) {
104104
public Boolean call(ComponentEvent event) {
105105
return event.getID() == id;
106106
}
107-
108107
}
109108
}

rxjava-contrib/rxjava-swing/src/main/java/rx/swing/sources/KeyEventSource.java

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,13 @@
3838
import rx.subscriptions.Subscriptions;
3939
import rx.util.functions.Action0;
4040
import rx.util.functions.Action1;
41+
import rx.util.functions.Func1;
4142
import rx.util.functions.Func2;
4243

4344
public enum KeyEventSource { ; // no instances
4445

4546
/**
46-
* @see SwingObservable.fromKeyEvents(Component)
47+
* @see rx.observables.SwingObservable#fromKeyEvents(Component)
4748
*/
4849
public static Observable<KeyEvent> fromKeyEventsOf(final Component component) {
4950
return Observable.create(new OnSubscribeFunc<KeyEvent>() {
@@ -78,10 +79,10 @@ public void call() {
7879
}
7980

8081
/**
81-
* @see SwingObservable.fromKeyEvents(Component, Set)
82+
* @see rx.observables.SwingObservable#fromPressedKeys(Component)
8283
*/
8384
public static Observable<Set<Integer>> currentlyPressedKeysOf(Component component) {
84-
return fromKeyEventsOf(component).<Set<Integer>>scan(new HashSet<Integer>(), new Func2<Set<Integer>, KeyEvent, Set<Integer>>() {
85+
class CollectKeys implements Func2<Set<Integer>, KeyEvent, Set<Integer>>{
8586
@Override
8687
public Set<Integer> call(Set<Integer> pressedKeys, KeyEvent event) {
8788
Set<Integer> afterEvent = new HashSet<Integer>(pressedKeys);
@@ -98,7 +99,16 @@ public Set<Integer> call(Set<Integer> pressedKeys, KeyEvent event) {
9899
}
99100
return afterEvent;
100101
}
102+
}
103+
104+
Observable<KeyEvent> filteredKeyEvents = fromKeyEventsOf(component).filter(new Func1<KeyEvent, Boolean>() {
105+
@Override
106+
public Boolean call(KeyEvent event) {
107+
return event.getID() == KeyEvent.KEY_PRESSED || event.getID() == KeyEvent.KEY_RELEASED;
108+
}
101109
});
110+
111+
return filteredKeyEvents.scan(Collections.<Integer>emptySet(), new CollectKeys());
102112
}
103113

104114
public static class UnitTest {
@@ -154,6 +164,7 @@ public void testObservingPressedKeys() {
154164
verify(complete, never()).call();
155165

156166
fireKeyEvent(keyEvent(2, KeyEvent.KEY_PRESSED));
167+
fireKeyEvent(keyEvent(KeyEvent.VK_UNDEFINED, KeyEvent.KEY_TYPED));
157168
inOrder.verify(action, times(1)).call(new HashSet<Integer>(asList(1, 2)));
158169

159170
fireKeyEvent(keyEvent(2, KeyEvent.KEY_RELEASED));

rxjava-contrib/rxjava-swing/src/main/java/rx/swing/sources/MouseEventSource.java

Lines changed: 96 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,23 +15,34 @@
1515
*/
1616
package rx.swing.sources;
1717

18+
import static org.mockito.Mockito.*;
19+
1820
import java.awt.Component;
21+
import java.awt.Point;
1922
import java.awt.event.MouseEvent;
2023
import java.awt.event.MouseListener;
2124
import java.awt.event.MouseMotionListener;
2225

26+
import javax.swing.JPanel;
27+
28+
import org.junit.Test;
29+
import org.mockito.InOrder;
30+
import org.mockito.Matchers;
31+
2332
import rx.Observable;
2433
import rx.Observable.OnSubscribeFunc;
2534
import rx.Observer;
2635
import rx.Subscription;
27-
import rx.observables.SwingObservable;
2836
import rx.subscriptions.Subscriptions;
2937
import rx.util.functions.Action0;
38+
import rx.util.functions.Action1;
39+
import rx.util.functions.Func1;
40+
import rx.util.functions.Func2;
3041

3142
public enum MouseEventSource { ; // no instances
3243

3344
/**
34-
* @see SwingObservable.fromMouseEvents
45+
* @see rx.observables.SwingObservable#fromMouseEvents
3546
*/
3647
public static Observable<MouseEvent> fromMouseEventsOf(final Component component) {
3748
return Observable.create(new OnSubscribeFunc<MouseEvent>() {
@@ -76,7 +87,7 @@ public void call() {
7687
}
7788

7889
/**
79-
* @see SwingObservable.fromMouseMotionEvents
90+
* @see rx.observables.SwingObservable#fromMouseMotionEvents
8091
*/
8192
public static Observable<MouseEvent> fromMouseMotionEventsOf(final Component component) {
8293
return Observable.create(new OnSubscribeFunc<MouseEvent>() {
@@ -104,4 +115,86 @@ public void call() {
104115
}
105116
});
106117
}
118+
119+
/**
120+
* @see rx.observables.SwingObservable#fromRelativeMouseMotion
121+
*/
122+
public static Observable<Point> fromRelativeMouseMotion(final Component component) {
123+
class OldAndRelative {
124+
public final Point old;
125+
public final Point relative;
126+
127+
private OldAndRelative(Point old, Point relative) {
128+
this.old = old;
129+
this.relative = relative;
130+
}
131+
}
132+
133+
class Relativize implements Func2<OldAndRelative, MouseEvent, OldAndRelative> {
134+
@Override
135+
public OldAndRelative call(OldAndRelative last, MouseEvent event) {
136+
Point current = new Point(event.getX(), event.getY());
137+
Point relative = new Point(current.x - last.old.x, current.y - last.old.y);
138+
return new OldAndRelative(current, relative);
139+
}
140+
}
141+
142+
class OnlyRelative implements Func1<OldAndRelative, Point> {
143+
@Override
144+
public Point call(OldAndRelative oar) {
145+
return oar.relative;
146+
}
147+
}
148+
149+
return fromMouseMotionEventsOf(component)
150+
.scan(new OldAndRelative(new Point(0, 0), new Point(0, 0)), new Relativize())
151+
.map(new OnlyRelative())
152+
.skip(2); // skip the useless initial value and the invalid first computation
153+
}
154+
155+
public static class UnitTest {
156+
private Component comp = new JPanel();
157+
158+
@Test
159+
public void testRelativeMouseMotion() {
160+
@SuppressWarnings("unchecked")
161+
Action1<Point> action = mock(Action1.class);
162+
@SuppressWarnings("unchecked")
163+
Action1<Throwable> error = mock(Action1.class);
164+
Action0 complete = mock(Action0.class);
165+
166+
Subscription sub = fromRelativeMouseMotion(comp).subscribe(action, error, complete);
167+
168+
InOrder inOrder = inOrder(action);
169+
170+
verify(action, never()).call(Matchers.<Point>any());
171+
verify(error, never()).call(Matchers.<Exception>any());
172+
verify(complete, never()).call();
173+
174+
fireMouseEvent(mouseEvent(0, 0));
175+
verify(action, never()).call(Matchers.<Point>any());
176+
177+
fireMouseEvent(mouseEvent(10, -5));
178+
inOrder.verify(action, times(1)).call(new Point(10, -5));
179+
180+
fireMouseEvent(mouseEvent(6, 10));
181+
inOrder.verify(action, times(1)).call(new Point(-4, 15));
182+
183+
sub.unsubscribe();
184+
fireMouseEvent(mouseEvent(0, 0));
185+
inOrder.verify(action, never()).call(Matchers.<Point>any());
186+
verify(error, never()).call(Matchers.<Exception>any());
187+
verify(complete, never()).call();
188+
}
189+
190+
private MouseEvent mouseEvent(int x, int y) {
191+
return new MouseEvent(comp, MouseEvent.MOUSE_MOVED, 1L, 0, x, y, 0, false);
192+
}
193+
194+
private void fireMouseEvent(MouseEvent event) {
195+
for (MouseMotionListener listener: comp.getMouseMotionListeners()) {
196+
listener.mouseMoved(event);
197+
}
198+
}
199+
}
107200
}

rxjava-core/src/main/java/rx/operators/OperationMostRecent.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
package rx.operators;
1717

1818
import static org.junit.Assert.*;
19-
import static org.mockito.Mockito.*;
2019

2120
import java.util.Iterator;
2221
import java.util.concurrent.atomic.AtomicBoolean;
@@ -26,7 +25,6 @@
2625

2726
import rx.Observable;
2827
import rx.Observer;
29-
import rx.Subscription;
3028
import rx.subjects.PublishSubject;
3129
import rx.subjects.Subject;
3230
import rx.util.Exceptions;

rxjava-core/src/main/java/rx/operators/OperationNext.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
package rx.operators;
1717

1818
import static org.junit.Assert.*;
19-
import static org.mockito.Mockito.*;
2019

2120
import java.util.Iterator;
2221
import java.util.concurrent.ArrayBlockingQueue;
@@ -203,7 +202,7 @@ public void testNext() throws Throwable {
203202

204203
@Test(expected = TestException.class)
205204
public void testOnError() throws Throwable {
206-
Subject<String, String> obs = PublishSubject.create();;
205+
Subject<String, String> obs = PublishSubject.create();
207206

208207
Iterator<String> it = next(obs).iterator();
209208

rxjava-core/src/test/java/rx/ObservableTests.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535
import rx.subscriptions.BooleanSubscription;
3636
import rx.subscriptions.Subscriptions;
3737
import rx.util.functions.Action1;
38-
import rx.util.functions.Func1;
3938
import rx.util.functions.Func2;
4039

4140
public class ObservableTests {

0 commit comments

Comments
 (0)