-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
b5110b8
commit 5b465ff
Showing
7 changed files
with
460 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
/* | ||
* To change this license header, choose License Headers in Project Properties. | ||
* To change this template file, choose Tools | Templates | ||
* and open the template in the editor. | ||
*/ | ||
package combinedeventstreamtest; | ||
|
||
import java.util.Optional; | ||
import org.reactfx.Change; | ||
|
||
/** | ||
* | ||
* @author bwhitworth | ||
*/ | ||
public class ChangeA extends ChangeBase<Double> { | ||
|
||
public ChangeA(DataModel model, double oldVal, double newVal) { | ||
super(model, oldVal, newVal); | ||
} | ||
|
||
public ChangeA(DataModel model, Change<Number> c) { | ||
super(model, (Double)c.getOldValue(), (Double)c.getNewValue()); | ||
} | ||
|
||
@Override | ||
public ChangeBase<Double> invert() { | ||
System.out.println("ChangeA invert "+this); | ||
return new ChangeA(this.model, this.newValue, this.oldValue); | ||
} | ||
|
||
@Override | ||
public void redo() { | ||
System.out.println("ChangeA redo "+this); | ||
this.model.setA(this.newValue); | ||
} | ||
|
||
@Override | ||
public Optional<UndoChange> mergeWith(UndoChange other) { | ||
System.out.print("ChangeA attempting merge with "+other+"... "); | ||
if(other instanceof ChangeA) { | ||
System.out.println("merged"); | ||
return Optional.of(new ChangeA(this.model, this.oldValue, ((ChangeA) other).newValue)); | ||
} | ||
System.out.println("did not merge"); | ||
return Optional.empty(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
/* | ||
* To change this license header, choose License Headers in Project Properties. | ||
* To change this template file, choose Tools | Templates | ||
* and open the template in the editor. | ||
*/ | ||
package combinedeventstreamtest; | ||
|
||
import java.util.Optional; | ||
import org.reactfx.Change; | ||
|
||
/** | ||
* | ||
* @author bwhitworth | ||
*/ | ||
public class ChangeB extends ChangeBase<Double> { | ||
|
||
public ChangeB(DataModel model, double oldVal, double newVal) { | ||
super(model, oldVal, newVal); | ||
} | ||
|
||
public ChangeB(DataModel model, Change<Number> c) { | ||
super(model, (Double)c.getOldValue(), (Double)c.getNewValue()); | ||
} | ||
|
||
@Override | ||
public ChangeBase<Double> invert() { | ||
System.out.println("ChangeB invert "+this); | ||
return new ChangeB(this.model, this.newValue, this.oldValue); | ||
} | ||
|
||
@Override | ||
public void redo() { | ||
System.out.println("ChangeB redo "+this); | ||
this.model.setB(this.newValue); | ||
} | ||
|
||
@Override | ||
public Optional<UndoChange> mergeWith(UndoChange other) { | ||
System.out.print("ChangeB attempting merge with "+other+"... "); | ||
if(other instanceof ChangeB) { | ||
System.out.println("merged"); | ||
return Optional.of(new ChangeB(this.model, this.oldValue, ((ChangeB) other).newValue)); | ||
} | ||
System.out.println("did not merge"); | ||
return Optional.empty(); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
/* | ||
* To change this license header, choose License Headers in Project Properties. | ||
* To change this template file, choose Tools | Templates | ||
* and open the template in the editor. | ||
*/ | ||
package combinedeventstreamtest; | ||
|
||
import java.util.Objects; | ||
import java.util.Optional; | ||
|
||
/** | ||
* | ||
* @author bwhitworth | ||
*/ | ||
public abstract class ChangeBase<T> implements UndoChange { | ||
protected final T oldValue, newValue; | ||
protected final DataModel model; | ||
|
||
protected ChangeBase(DataModel model, T oldValue, T newValue) { | ||
this.model = model; | ||
this.oldValue = oldValue; | ||
this.newValue = newValue; | ||
} | ||
|
||
public abstract ChangeBase<T> invert(); | ||
public abstract void redo(); | ||
|
||
public Optional<ChangeBase<?>> mergeWith(ChangeBase<?> other) { | ||
return Optional.empty(); | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
return Objects.hash(this.oldValue, this.newValue); | ||
} | ||
|
||
@Override | ||
public boolean equals(Object obj) { | ||
if (this == obj) { | ||
return true; | ||
} | ||
if (obj == null) { | ||
return false; | ||
} | ||
if (getClass() != obj.getClass()) { | ||
return false; | ||
} | ||
final ChangeBase<?> other = (ChangeBase<?>) obj; | ||
if (!Objects.equals(this.oldValue, other.oldValue)) { | ||
return false; | ||
} | ||
if (!Objects.equals(this.newValue, other.newValue)) { | ||
return false; | ||
} | ||
if (!Objects.equals(this.model, other.model)) { | ||
return false; | ||
} | ||
return true; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
/* | ||
* To change this license header, choose License Headers in Project Properties. | ||
* To change this template file, choose Tools | Templates | ||
* and open the template in the editor. | ||
*/ | ||
package combinedeventstreamtest; | ||
|
||
import java.util.Objects; | ||
import java.util.Optional; | ||
import org.reactfx.util.Tuple2; | ||
|
||
/** | ||
* | ||
* @author bwhitworth | ||
*/ | ||
public class ChangeBoth implements UndoChange { | ||
|
||
private final ChangeA aChange; | ||
private final ChangeB bChange; | ||
|
||
public ChangeBoth(ChangeA ac, ChangeB bc) { | ||
this.aChange = ac; | ||
this.bChange = bc; | ||
} | ||
|
||
public ChangeBoth(Tuple2<UndoChange, UndoChange> tuple) { | ||
this.aChange = ((ChangeBoth)tuple.get1()).aChange; | ||
this.bChange = ((ChangeBoth)tuple.get2()).bChange; | ||
} | ||
|
||
@Override | ||
public UndoChange invert() { | ||
System.out.println("ChangeBoth invert "+this); | ||
return new ChangeBoth(new ChangeA(this.aChange.model, this.aChange.newValue, this.aChange.oldValue), | ||
new ChangeB(this.bChange.model, this.bChange.newValue, this.bChange.oldValue)); | ||
} | ||
|
||
@Override | ||
public void redo() { | ||
System.out.println("ChangeBoth redo "+this); | ||
DataModel model = this.aChange.model; | ||
model.setA(this.aChange.newValue); | ||
model.setB(this.bChange.newValue); | ||
} | ||
|
||
@Override | ||
public Optional<UndoChange> mergeWith(UndoChange other) { | ||
System.out.print("ChangeBoth attempting merge with "+other+"... "); | ||
if(other instanceof ChangeBoth) { | ||
System.out.println("merged"); | ||
ChangeBoth cb = (ChangeBoth)other; | ||
ChangeA ac = (cb.aChange == null) ? this.aChange : cb.aChange; | ||
ChangeB bc = (cb.bChange == null) ? this.bChange : cb.bChange; | ||
return Optional.of( | ||
new ChangeBoth( | ||
new ChangeA(this.aChange.model, this.aChange.oldValue, ac.newValue), | ||
new ChangeB(this.bChange.model, this.bChange.oldValue, bc.newValue) | ||
) | ||
); | ||
} | ||
System.out.println("did not merge"); | ||
return Optional.empty(); | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
int hash = 7; | ||
hash = 17 * hash + Objects.hashCode(this.aChange); | ||
hash = 17 * hash + Objects.hashCode(this.bChange); | ||
return hash; | ||
} | ||
|
||
@Override | ||
public boolean equals(Object obj) { | ||
if (this == obj) { | ||
return true; | ||
} | ||
if (obj == null) { | ||
return false; | ||
} | ||
if (getClass() != obj.getClass()) { | ||
return false; | ||
} | ||
final ChangeBoth other = (ChangeBoth) obj; | ||
if (!Objects.equals(this.aChange, other.aChange)) { | ||
return false; | ||
} | ||
if (!Objects.equals(this.bChange, other.bChange)) { | ||
return false; | ||
} | ||
return true; | ||
} | ||
} |
118 changes: 118 additions & 0 deletions
118
src/combinedeventstreamtest/CombinedEventStreamTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
/* | ||
* To change this license header, choose License Headers in Project Properties. | ||
* To change this template file, choose Tools | Templates | ||
* and open the template in the editor. | ||
*/ | ||
package combinedeventstreamtest; | ||
|
||
import javafx.application.Application; | ||
import javafx.beans.property.DoubleProperty; | ||
import javafx.collections.FXCollections; | ||
import javafx.collections.ListChangeListener; | ||
import javafx.collections.ObservableList; | ||
import javafx.event.ActionEvent; | ||
import javafx.scene.Scene; | ||
import javafx.scene.control.Button; | ||
import javafx.scene.layout.FlowPane; | ||
import javafx.stage.Stage; | ||
import org.fxmisc.undo.UndoManager; | ||
import org.fxmisc.undo.UndoManagerFactory; | ||
import org.reactfx.Change; | ||
import org.reactfx.EventStream; | ||
import org.reactfx.EventStreams; | ||
|
||
/** | ||
* | ||
* @author bwhitworth | ||
*/ | ||
public class CombinedEventStreamTest extends Application { | ||
|
||
@Override | ||
public void start(Stage primaryStage) { | ||
//a data model | ||
DataModel model = new DataModel(); | ||
//event streams of property changes | ||
EventStream<UndoChange> changeAStream = EventStreams.changesOf(model.aProperty()) | ||
.hook(c -> System.out.println("Change in A stream")) | ||
.map(c -> new ChangeA(model, (Change<Number>)c)); | ||
EventStream<UndoChange> changeBStream = EventStreams.changesOf(model.bProperty()) | ||
.hook(c -> System.out.println("Change in B stream")) | ||
.map(c -> new ChangeB(model, (Change<Number>)c)); | ||
//combine event streams | ||
EventStream<UndoChange> bothStream = EventStreams.merge(changeAStream, changeBStream); | ||
|
||
// EventStream<UndoChange> bothStream = EventStreams.combine(changeAStream, changeBStream) | ||
// .hook(c -> System.out.println("Change in Both stream")) | ||
// .map(ChangeBoth::new); | ||
|
||
//undo manager | ||
UndoManager<UndoChange> um = UndoManagerFactory.unlimitedHistoryUndoManager( | ||
bothStream, | ||
c -> c.invert(), | ||
c -> c.redo(), | ||
(c1, c2) -> c1.mergeWith(c2) | ||
); | ||
|
||
//generate new A | ||
Button aButton = new Button(); | ||
aButton.setText("A change"); | ||
aButton.setOnAction((ActionEvent event) -> { | ||
System.out.print(model+"\t->\t"); | ||
model.setA(Math.random()*10.0); | ||
System.out.println(model); | ||
}); | ||
|
||
//generate new B | ||
Button bButton = new Button(); | ||
bButton.setText("B change"); | ||
bButton.setOnAction((ActionEvent event) -> { | ||
System.out.print(model+"\t->\t"); | ||
model.setB(Math.random()*10.0); | ||
System.out.println(model); | ||
}); | ||
|
||
//generate new A and B | ||
Button bothButton = new Button("A and B change"); | ||
bothButton.setOnAction(event -> { | ||
System.out.print(model+"\t->\t"); | ||
model.setA(Math.random()*10.0); | ||
model.setB(Math.random()*10.0); | ||
System.out.println(model); | ||
}); | ||
|
||
//undo/redo buttons | ||
Button undoButton = new Button("Undo"); | ||
Button redoButton = new Button("Redo"); | ||
undoButton.disableProperty().bind(um.undoAvailableProperty().map(x -> !x)); | ||
redoButton.disableProperty().bind(um.redoAvailableProperty().map(x -> !x)); | ||
undoButton.setOnAction(event -> { | ||
System.out.print("undo "+model+"\t->\t"); | ||
um.undo(); | ||
System.out.println(model); | ||
}); | ||
redoButton.setOnAction(event -> { | ||
System.out.print("redo "+model+"\t->\t"); | ||
um.redo(); | ||
System.out.println(model); | ||
}); | ||
|
||
FlowPane root = new FlowPane(); | ||
root.setHgap(5); | ||
root.setVgap(5); | ||
root.getChildren().addAll(aButton, bButton, bothButton, undoButton, redoButton); | ||
|
||
Scene scene = new Scene(root, 300, 250); | ||
|
||
primaryStage.setTitle("Combined stream test"); | ||
primaryStage.setScene(scene); | ||
primaryStage.show(); | ||
} | ||
|
||
/** | ||
* @param args the command line arguments | ||
*/ | ||
public static void main(String[] args) { | ||
launch(args); | ||
} | ||
|
||
} |
Oops, something went wrong.