diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs index 96cf561c..588e59de 100644 --- a/.settings/org.eclipse.jdt.core.prefs +++ b/.settings/org.eclipse.jdt.core.prefs @@ -1,6 +1,9 @@ eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning org.eclipse.jdt.core.compiler.source=1.8 org.eclipse.jdt.core.javaFormatter=org.eclipse.jdt.core.defaultJavaFormatter diff --git a/pom.xml b/pom.xml index c73b8d98..6846218d 100755 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.warp.picalculator warppi-calculator jar - 0.7-SNAPSHOT + 0.8-SNAPSHOT WarpPI Calculator http://warp.ovh @@ -40,14 +40,14 @@ - - 1_teavm-dev - https://dl.bintray.com/konsoletyper/teavm - - true - - default - + + 1_teavm-dev + https://dl.bintray.com/konsoletyper/teavm + + true + + default + @@ -100,6 +100,13 @@ ecj 4.6.1 + @@ -109,8 +116,8 @@ maven-compiler-plugin 2.3.2 - 1.8 - 1.8 + ${maven.compiler.source} + ${maven.compiler.target} UTF-8 ${buildprops.exclude1} @@ -170,8 +177,8 @@ org/warp/picalculator/gui/graphicengine/headless8/* org/warp/picalculator/gui/graphicengine/framebuffer/* - 1.8 - 1.8 + ${maven.compiler.source} + ${maven.compiler.target} UTF-8 @@ -230,11 +237,6 @@ commons-lang3 3.8 - - io.reactivex.rxjava2 - rxjava - 2.2.1 - diff --git a/src/js-specific/java/org/warp/picalculator/ConsoleUtils.java b/src/js-specific/java/org/warp/picalculator/ConsoleUtils.java index 21c9999f..7b174970 100644 --- a/src/js-specific/java/org/warp/picalculator/ConsoleUtils.java +++ b/src/js-specific/java/org/warp/picalculator/ConsoleUtils.java @@ -43,7 +43,7 @@ public class ConsoleUtils { } } - public void println(int level, String str) { + public void println(int level, Object str) { if (StaticVars.outputLevel >= level) { final String time = getTimeString(); if (StaticVars.outputLevel == 0) { @@ -64,7 +64,7 @@ public class ConsoleUtils { } } - public void println(int level, String prefix, String str) { + public void println(int level, Object prefix, Object str) { if (StaticVars.outputLevel >= level) { final String time = getTimeString(); if (StaticVars.outputLevel == 0) { @@ -75,7 +75,7 @@ public class ConsoleUtils { } } - public void println(int level, String... parts) { + public void println(int level, Object... parts) { if (StaticVars.outputLevel >= level) { final String time = getTimeString(); String output = ""; diff --git a/src/js-specific/java/org/warp/picalculator/deps/DAtomicInteger.java b/src/js-specific/java/org/warp/picalculator/deps/DAtomicInteger.java index 3df2ceef..8177b840 100644 --- a/src/js-specific/java/org/warp/picalculator/deps/DAtomicInteger.java +++ b/src/js-specific/java/org/warp/picalculator/deps/DAtomicInteger.java @@ -36,7 +36,6 @@ package org.warp.picalculator.deps; import java.util.function.IntUnaryOperator; import java.util.function.IntBinaryOperator; -import sun.misc.Unsafe; /** * An {@code int} value that may be updated atomically. See the diff --git a/src/js-specific/java/org/warp/picalculator/gui/graphicengine/html/HtmlEngine.java b/src/js-specific/java/org/warp/picalculator/gui/graphicengine/html/HtmlEngine.java index 60ecd2ad..cac24bd0 100644 --- a/src/js-specific/java/org/warp/picalculator/gui/graphicengine/html/HtmlEngine.java +++ b/src/js-specific/java/org/warp/picalculator/gui/graphicengine/html/HtmlEngine.java @@ -24,6 +24,8 @@ import org.warp.picalculator.Utils; import org.warp.picalculator.deps.DSemaphore; import org.warp.picalculator.deps.StorageUtils; import org.warp.picalculator.device.Keyboard; +import org.warp.picalculator.flow.BehaviorSubject; +import org.warp.picalculator.flow.Observable; import org.warp.picalculator.gui.graphicengine.BinaryFont; import org.warp.picalculator.gui.graphicengine.GraphicEngine; import org.warp.picalculator.gui.graphicengine.Renderer; @@ -43,6 +45,7 @@ public class HtmlEngine implements GraphicEngine { private HtmlRenderer renderer; private int width = -1, height = -1; private final int frameTime = (int) (1000d/10d); + private final BehaviorSubject onResize = BehaviorSubject.create(); @Override public int[] getSize() { @@ -194,11 +197,6 @@ public class HtmlEngine implements GraphicEngine { } } - @Override - public boolean wasResized() { - return false; - } - @Override public int getWidth() { if (width == -1) { @@ -293,4 +291,9 @@ public class HtmlEngine implements GraphicEngine { return true; } + @Override + public Observable onResize() { + return onResize; + } + } diff --git a/src/main/java/org/warp/picalculator/StaticVars.java b/src/main/java/org/warp/picalculator/StaticVars.java index 2586eee0..94fb218c 100644 --- a/src/main/java/org/warp/picalculator/StaticVars.java +++ b/src/main/java/org/warp/picalculator/StaticVars.java @@ -1,13 +1,10 @@ package org.warp.picalculator; -import java.util.Iterator; -import java.util.concurrent.CompletableFuture; +import java.util.function.Function; import org.warp.picalculator.boot.StartupArguments; - -import io.reactivex.Maybe; -import io.reactivex.Observable; -import io.reactivex.subjects.BehaviorSubject; +import org.warp.picalculator.flow.Observable; +import org.warp.picalculator.flow.BehaviorSubject; public class StaticVars { public static final boolean enableVBO = true; @@ -17,19 +14,19 @@ public class StaticVars { public static boolean haxMode = true; public static final boolean zoomed = true; public static int[] screenPos = new int[] { 0, 0 }; - public static final int[] screenSize = new int[] { 480, 320 }; + public static final int[] screenSize = new int[] {480, 320}; public static boolean debugOn; public static int outputLevel = 0; public static boolean debugWindow2x = false; - public static BehaviorSubject windowZoom = BehaviorSubject.createDefault(2F); - public static Observable windowZoom$ = windowZoom.map((val) -> { + public static BehaviorSubject windowZoom = BehaviorSubject.create(2F); + public static Function windowZoomFunction = (val) -> { if (StaticVars.debugOn & StaticVars.debugWindow2x) { return val + 1; } else { return val; } - }); - public static Iterator windowZoomValue = windowZoom$.blockingMostRecent(2F).iterator(); + }; + public static Observable windowZoom$ = windowZoom.map(windowZoomFunction); public static StartupArguments startupArguments; private StaticVars() { diff --git a/src/main/java/org/warp/picalculator/boot/Main.java b/src/main/java/org/warp/picalculator/boot/Main.java index 24790456..c6032bbe 100644 --- a/src/main/java/org/warp/picalculator/boot/Main.java +++ b/src/main/java/org/warp/picalculator/boot/Main.java @@ -1,15 +1,9 @@ package org.warp.picalculator.boot; -import java.io.IOException; import java.util.Arrays; -import java.util.stream.Stream; - import org.warp.picalculator.ConsoleUtils; import org.warp.picalculator.PICalculator; -import org.warp.picalculator.Utils; -import org.warp.picalculator.device.PIHardwareDisplay; -import org.warp.picalculator.gui.CalculatorHUD; -import org.warp.picalculator.gui.screens.LoadingScreen; +import org.warp.picalculator.flow.TestFlow; public class Main { public static void main(String[] args) throws Exception { diff --git a/src/main/java/org/warp/picalculator/device/Keyboard.java b/src/main/java/org/warp/picalculator/device/Keyboard.java index b37a8451..8f6be7bd 100755 --- a/src/main/java/org/warp/picalculator/device/Keyboard.java +++ b/src/main/java/org/warp/picalculator/device/Keyboard.java @@ -813,7 +813,7 @@ public class Keyboard { refresh = true; break; case ZOOM_MODE: - float newZoom = (StaticVars.windowZoom.blockingLatest().iterator().next().floatValue() % 3) + 1; + float newZoom = (StaticVars.windowZoom.getLastValue() % 3) + 1; StaticVars.windowZoom.onNext(newZoom); ConsoleUtils.out.println(ConsoleUtils.OUTPUTLEVEL_DEBUG_MIN, "Keyboard", "Zoom: " + newZoom); // StaticVars.windowZoom = ((StaticVars.windowZoom - 0.5f) % 2f) + 1f; diff --git a/src/main/java/org/warp/picalculator/flow/Action0.java b/src/main/java/org/warp/picalculator/flow/Action0.java new file mode 100644 index 00000000..ce01c6fa --- /dev/null +++ b/src/main/java/org/warp/picalculator/flow/Action0.java @@ -0,0 +1,5 @@ +package org.warp.picalculator.flow; + +public interface Action0 { + void call(); +} diff --git a/src/main/java/org/warp/picalculator/flow/Action1.java b/src/main/java/org/warp/picalculator/flow/Action1.java new file mode 100644 index 00000000..947f046c --- /dev/null +++ b/src/main/java/org/warp/picalculator/flow/Action1.java @@ -0,0 +1,5 @@ +package org.warp.picalculator.flow; + +public interface Action1 { + void call(T t); +} diff --git a/src/main/java/org/warp/picalculator/flow/Action2.java b/src/main/java/org/warp/picalculator/flow/Action2.java new file mode 100644 index 00000000..446e103a --- /dev/null +++ b/src/main/java/org/warp/picalculator/flow/Action2.java @@ -0,0 +1,5 @@ +package org.warp.picalculator.flow; + +public interface Action2 { + void call(T t, U u); +} diff --git a/src/main/java/org/warp/picalculator/flow/BehaviorSubject.java b/src/main/java/org/warp/picalculator/flow/BehaviorSubject.java new file mode 100644 index 00000000..36e9dbda --- /dev/null +++ b/src/main/java/org/warp/picalculator/flow/BehaviorSubject.java @@ -0,0 +1,98 @@ +package org.warp.picalculator.flow; + +import java.util.LinkedList; +import java.util.List; + +public class BehaviorSubject extends Subject { + + private T lastValue; + private boolean lastValueSet; + + protected BehaviorSubject() { + super(); + lastValue = null; + lastValueSet = false; + } + + protected BehaviorSubject(T initialValue) { + super(); + lastValue = initialValue; + lastValueSet = true; + } + + public final static BehaviorSubject create() { + return new BehaviorSubject<>(); + } + + public final static BehaviorSubject create(T initialValue) { + return new BehaviorSubject(initialValue); + } + + @Override + public void onComplete() { + for (Subscriber sub : this.subscribers) { + sub.onComplete(); + } + } + + @Override + public void onError(Throwable e) { + for (Subscriber sub : this.subscribers) { + sub.onError(e); + }; + } + + @Override + public void onNext(T t) { + lastValue = t; + lastValueSet = true; + for (Subscriber sub : this.subscribers) { + sub.onNext(t); + } + } + + @Override + Throwable getThrowable() { + // TODO Auto-generated method stub + return null; + } + + @Override + boolean hasComplete() { + // TODO Auto-generated method stub + return false; + } + + @Override + boolean hasObservers() { + // TODO Auto-generated method stub + return false; + } + + @Override + boolean hasThrowable() { + // TODO Auto-generated method stub + return false; + } + + @Override + Subject toSerialized() { + // TODO Auto-generated method stub + return null; + } + + @Override + public void onSubscribe(Disposable d) { + @SuppressWarnings("unchecked") + DisposableOfSubscriber ds = (DisposableOfSubscriber) d; + Subscriber s = ds.getSubscriber(); + if (lastValueSet) { + s.onNext(lastValue); + } + } + + public T getLastValue() { + return lastValue; + } + +} diff --git a/src/main/java/org/warp/picalculator/flow/Consumer.java b/src/main/java/org/warp/picalculator/flow/Consumer.java new file mode 100644 index 00000000..4911a9a4 --- /dev/null +++ b/src/main/java/org/warp/picalculator/flow/Consumer.java @@ -0,0 +1,30 @@ +package org.warp.picalculator.flow; + +import java.util.Objects; + +public interface Consumer { + + /** + * Performs this operation on the given argument. + * + * @param t the input argument + */ + void accept(T t); + + /** + * Returns a composed {@code Consumer} that performs, in sequence, this + * operation followed by the {@code after} operation. If performing either + * operation throws an exception, it is relayed to the caller of the + * composed operation. If performing this operation throws an exception, + * the {@code after} operation will not be performed. + * + * @param after the operation to perform after this operation + * @return a composed {@code Consumer} that performs in sequence this + * operation followed by the {@code after} operation + * @throws NullPointerException if {@code after} is null + */ + default Consumer andThen(Consumer after) { + Objects.requireNonNull(after); + return (T t) -> { accept(t); after.accept(t); }; + } +} \ No newline at end of file diff --git a/src/main/java/org/warp/picalculator/flow/Disposable.java b/src/main/java/org/warp/picalculator/flow/Disposable.java new file mode 100644 index 00000000..39aac5e5 --- /dev/null +++ b/src/main/java/org/warp/picalculator/flow/Disposable.java @@ -0,0 +1,7 @@ +package org.warp.picalculator.flow; + +public interface Disposable { + public void dispose(); + + public boolean isDisposed(); +} diff --git a/src/main/java/org/warp/picalculator/flow/IntervalsManager.java b/src/main/java/org/warp/picalculator/flow/IntervalsManager.java new file mode 100644 index 00000000..78794922 --- /dev/null +++ b/src/main/java/org/warp/picalculator/flow/IntervalsManager.java @@ -0,0 +1,48 @@ +package org.warp.picalculator.flow; + +import java.util.LinkedList; +import java.util.List; + +import org.warp.picalculator.PlatformUtils; + +public class IntervalsManager { + private static List intervals = new LinkedList<>(); + + static { + startChecker(); + } + + private IntervalsManager() { + + } + + public static void register(ObservableInterval t) { + synchronized (intervals) { + if (!intervals.contains(t)) { + intervals.add(t); + } + } + } + + private static void startChecker() { + Thread t = new Thread(() -> { + try { + while (true) { + Thread.sleep(1000); + for (ObservableInterval interval : intervals) { + if (interval.running) { + if (interval.subscribers.size() <= 0) { + interval.stopInterval(); + } + } + } + } + } catch (InterruptedException e) { + e.printStackTrace(); + } + }); + PlatformUtils.setDaemon(t); + PlatformUtils.setThreadName(t, "Intervals Manager"); + t.start(); + } +} diff --git a/src/main/java/org/warp/picalculator/flow/Observable.java b/src/main/java/org/warp/picalculator/flow/Observable.java new file mode 100644 index 00000000..8cab3803 --- /dev/null +++ b/src/main/java/org/warp/picalculator/flow/Observable.java @@ -0,0 +1,166 @@ +package org.warp.picalculator.flow; + +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.function.Function; + +import org.apache.commons.lang3.tuple.Pair; + +public abstract class Observable implements ObservableSource { + + protected List> subscribers = new LinkedList<>(); + + public Disposable subscribe() { + return null; + } + public Disposable subscribe(Action1 onNext) { + return subscribe(createSubscriber(onNext)); + } + protected Observable.DisposableOfSubscriber createDisposable(Subscriber sub) { + return new DisposableOfSubscriber(sub); + } + public Disposable subscribe(Action1 onNext, Action1 onError) { + return subscribe(createSubscriber(onNext, onError)); + } + public Disposable subscribe(Action1 onNext, Action1 onError, Action0 onCompleted) { + return subscribe(createSubscriber(onNext, onError, onCompleted)); + } + public void subscribe(Observer obs) { + subscribe(createSubscriber(obs)); + } + public Disposable subscribe(Subscriber sub) { + subscribers.add(sub); + return createDisposable(sub); + } + + protected Subscriber createSubscriber(Action1 onNext) { + return new Subscriber() { + @Override public void onSubscribe(Subscription s) {} + public void onNext(T t) { + onNext.call(t); + } + }; + } + + protected Subscriber createSubscriber(Action1 onNext, Action1 onError) { + return new Subscriber() { + @Override public void onSubscribe(Subscription s) {} + public void onNext(T t) { + onNext.call(t); + } + @Override + public void onError(Throwable t) { + onError.call(t); + } + }; + } + + protected Subscriber createSubscriber(Action1 onNext, Action1 onError, Action0 onCompl) { + return new Subscriber() { + @Override public void onSubscribe(Subscription s) {} + public void onNext(T t) { + onNext.call(t); + } + @Override + public void onError(Throwable t) { + onError.call(t); + } + @Override + public void onComplete() { + onCompl.call(); + } + }; + } + + protected Subscriber createSubscriber(Observer obs) { + return new Subscriber() { + @Override public void onSubscribe(Subscription s) {} + public void onNext(T t) { + obs.onNext(t); + } + @Override + public void onError(Throwable t) { + obs.onError(t); + } + @Override + public void onComplete() { + obs.onComplete(); + } + }; + } + + public static final Observable merge(Observable a, Observable b) { + return new ObservableMerged<>(a, b); + } + + @Deprecated + public static final Observable of(Observable a) { + return null; + } + + public final Observable map(Function f) { + return new ObservableMap(this, f); + } + + public static final Observable> combineLatest(Observable a, Observable b) { + return new ObservableCombinedLatest<>(a, b); + } + + public static final Observable> combineChanged(Observable a, Observable b) { + return new ObservableCombinedChanged<>(a, b); + } + + public static final Observable> zip(Observable a, Observable b) { + return new ObservableZipped<>(a, b); + } + + public static final Observable interval(long interval) { + return new ObservableInterval(interval); + } + + protected class DisposableOfSubscriber implements Disposable { + + private final Subscriber sub; + + public DisposableOfSubscriber(Subscriber sub) { + this.sub = sub; + } + + protected Subscriber getSubscriber() { + return sub; + } + + protected Observable getObservable() { + return Observable.this; + } + + @Override + public void dispose() { + if (isDisposed()) { + throw new RuntimeException("Already disposed!"); + } + subscribers.remove(sub); + Observable.this.onDisposed(sub); + } + + @Override + public boolean isDisposed() { + return !subscribers.contains(sub); + } + + } + + public Observable doOnNext(Action1 onNext) { + Subject onNextSubject = BehaviorSubject.create(); + this.subscribe((val) -> { + onNext.call(val); + onNextSubject.onNext(val); + }); + return onNextSubject; + } + + public void onDisposed(Subscriber sub) { + + } +} diff --git a/src/main/java/org/warp/picalculator/flow/ObservableCombinedChanged.java b/src/main/java/org/warp/picalculator/flow/ObservableCombinedChanged.java new file mode 100644 index 00000000..17a0d50c --- /dev/null +++ b/src/main/java/org/warp/picalculator/flow/ObservableCombinedChanged.java @@ -0,0 +1,72 @@ +package org.warp.picalculator.flow; + +import java.util.function.Function; + +import org.apache.commons.lang3.tuple.Pair; + +public class ObservableCombinedChanged extends Observable> { + private volatile boolean initialized = false; + private Observable a; + private Observable b; + private Disposable disposableA; + private Disposable disposableB; + private Subject> pairSubject; + private Subject mapSubject; + + public ObservableCombinedChanged(Observable a, Observable b) { + super(); + this.a = a; + this.b = b; + this.pairSubject = SimpleSubject.create(); + } + + private void initialize() { + this.disposableA = a.subscribe((t) -> { + for (Subscriber> sub : this.subscribers) { + sub.onNext(Pair.of(t, null)); + } + }, (e) -> { + for (Subscriber> sub : this.subscribers) { + sub.onError(e); + }; + }, () -> { + for (Subscriber> sub : this.subscribers) { + sub.onComplete(); + }; + }); + this.disposableB = b.subscribe((t) -> { + for (Subscriber> sub : this.subscribers) { + sub.onNext(Pair.of(null, t)); + }; + }, (e) -> { + for (Subscriber> sub : this.subscribers) { + sub.onError(e); + }; + }, () -> { + for (Subscriber> sub : this.subscribers) { + sub.onComplete(); + }; + }); + } + + private void chechInitialized() { + if (!initialized) { + initialized = true; + initialize(); + } + } + + @Override + public Disposable subscribe(Subscriber> sub) { + Disposable disp = super.subscribe(sub); + chechInitialized(); + return disp; + } + + @Override + public void onDisposed(Subscriber> sub) { + super.onDisposed(sub); + this.disposableA.dispose(); + this.disposableB.dispose(); + } +} diff --git a/src/main/java/org/warp/picalculator/flow/ObservableCombinedLatest.java b/src/main/java/org/warp/picalculator/flow/ObservableCombinedLatest.java new file mode 100644 index 00000000..63095a6f --- /dev/null +++ b/src/main/java/org/warp/picalculator/flow/ObservableCombinedLatest.java @@ -0,0 +1,84 @@ +package org.warp.picalculator.flow; + +import java.util.function.Function; + +import org.apache.commons.lang3.tuple.Pair; + +public class ObservableCombinedLatest extends Observable> { + private volatile boolean initialized = false; + private Observable a; + private Observable b; + private Disposable disposableA; + private Disposable disposableB; + private volatile T lastA; + private volatile U lastB; + private volatile boolean didAOneTime; + private volatile boolean didBOneTime; + private Subject> pairSubject; + private Subject mapSubject; + + public ObservableCombinedLatest(Observable a, Observable b) { + super(); + this.a = a; + this.b = b; + this.pairSubject = SimpleSubject.create(); + } + + private void initialize() { + this.disposableA = a.subscribe((t) -> { + lastA = t; + didAOneTime = true; + receivedNext(); + }, (e) -> { + for (Subscriber> sub : this.subscribers) { + sub.onError(e); + }; + }, () -> { + for (Subscriber> sub : this.subscribers) { + sub.onComplete(); + }; + }); + this.disposableB = b.subscribe((t) -> { + lastB = t; + didBOneTime = true; + receivedNext(); + }, (e) -> { + for (Subscriber> sub : this.subscribers) { + sub.onError(e); + }; + }, () -> { + for (Subscriber> sub : this.subscribers) { + sub.onComplete(); + }; + }); + } + + private void receivedNext() { + if (didAOneTime && didBOneTime) { + this.subscribers.forEach(sub -> { + sub.onNext(Pair.of(lastA, lastB)); + }); + } + } + + private void chechInitialized() { + if (!initialized) { + initialized = true; + initialize(); + } + } + + @Override + public Disposable subscribe(Subscriber> sub) { + Disposable disp = super.subscribe(sub); + chechInitialized(); + return disp; + } + + @Override + public void onDisposed(Subscriber> sub) { + super.onDisposed(sub); + this.disposableA.dispose(); + this.disposableB.dispose(); + } +} diff --git a/src/main/java/org/warp/picalculator/flow/ObservableInterval.java b/src/main/java/org/warp/picalculator/flow/ObservableInterval.java new file mode 100644 index 00000000..8279ae8e --- /dev/null +++ b/src/main/java/org/warp/picalculator/flow/ObservableInterval.java @@ -0,0 +1,71 @@ +package org.warp.picalculator.flow; + +import java.util.function.Function; + +import org.apache.commons.lang3.tuple.Pair; +import org.warp.picalculator.PlatformUtils; + +public class ObservableInterval extends Observable { + private final long interval; + volatile boolean running; + volatile Thread timeThread; + + protected ObservableInterval(long interval) { + super(); + this.interval = interval; + try { + startInterval(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + void stopInterval() { + if (running) { + running = false; + this.timeThread.interrupt(); + } + } + + @Override + public Disposable subscribe(Subscriber sub) { + try { + startInterval(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + return super.subscribe(sub); + } + + void startInterval() throws InterruptedException { + if (running == false) { + while (timeThread != null) { + Thread.sleep(100); + } + timeThread = new Thread(() -> { + try { + while(!Thread.interrupted()) { + for (Subscriber sub : this.subscribers) { + sub.onNext(System.currentTimeMillis()); + } + Thread.sleep(interval); + } + } catch (InterruptedException e) {} + timeThread = null; + }); + PlatformUtils.setThreadName(timeThread, "ObservableTimer"); + timeThread.start(); + running = true; + } + } + + public static ObservableInterval create(long l) { + return new ObservableInterval(l); + } + + @Override + public void onDisposed(Subscriber sub) { + super.onDisposed(sub); + stopInterval(); + } +} diff --git a/src/main/java/org/warp/picalculator/flow/ObservableMap.java b/src/main/java/org/warp/picalculator/flow/ObservableMap.java new file mode 100644 index 00000000..1e9258d0 --- /dev/null +++ b/src/main/java/org/warp/picalculator/flow/ObservableMap.java @@ -0,0 +1,55 @@ +package org.warp.picalculator.flow; + +import java.util.function.Function; + +import org.apache.commons.lang3.tuple.Pair; + +public class ObservableMap extends Observable { + private Observable originalObservable; + private Function mapAction; + private volatile boolean initialized = false; + private Disposable mapDisposable; + private Subject mapSubject; + + public ObservableMap(Observable originalObservable, Function mapAction) { + super(); + this.originalObservable = originalObservable; + this.mapAction = mapAction; + this.mapSubject = SimpleSubject.create(); + } + + private void initialize() { + this.mapDisposable = originalObservable.subscribe((t) -> { + for (Subscriber sub : this.subscribers) { + sub.onNext(mapAction.apply(t)); + }; + }, (e) -> { + for (Subscriber sub : this.subscribers) { + sub.onError(e); + }; + }, () -> { + for (Subscriber sub : this.subscribers) { + sub.onComplete(); + }; + }); + } + + private void chechInitialized() { + if (!initialized) { + initialized = true; + initialize(); + } + } + + @Override + public Disposable subscribe(Subscriber sub) { + Disposable disp = super.subscribe(sub); + chechInitialized(); + return disp; + } + @Override + public void onDisposed(Subscriber sub) { + super.onDisposed(sub); + mapDisposable.dispose(); + } +} diff --git a/src/main/java/org/warp/picalculator/flow/ObservableMerged.java b/src/main/java/org/warp/picalculator/flow/ObservableMerged.java new file mode 100644 index 00000000..a7aa41bb --- /dev/null +++ b/src/main/java/org/warp/picalculator/flow/ObservableMerged.java @@ -0,0 +1,71 @@ +package org.warp.picalculator.flow; + +import java.util.function.Function; + +import org.apache.commons.lang3.tuple.Pair; + +public class ObservableMerged extends Observable { + private Observable originalObservableA; + private Observable originalObservableB; + private volatile boolean initialized = false; + private Disposable mapDisposableA; + private Disposable mapDisposableB; + private Subject mapSubject; + + public ObservableMerged(Observable originalObservableA, Observable originalObservableB) { + super(); + this.originalObservableA = originalObservableA; + this.originalObservableB = originalObservableB; + this.mapSubject = SimpleSubject.create(); + } + + private void initialize() { + this.mapDisposableA = originalObservableA.subscribe((t) -> { + for (Subscriber sub : this.subscribers) { + sub.onNext(t); + }; + }, (e) -> { + for (Subscriber sub : this.subscribers) { + sub.onError(e); + }; + }, () -> { + for (Subscriber sub : this.subscribers) { + sub.onComplete(); + }; + }); + this.mapDisposableB = originalObservableB.subscribe((t) -> { + for (Subscriber sub : this.subscribers) { + sub.onNext(t); + }; + }, (e) -> { + for (Subscriber sub : this.subscribers) { + sub.onError(e); + }; + }, () -> { + for (Subscriber sub : this.subscribers) { + sub.onComplete(); + }; + }); + } + + private void chechInitialized() { + if (!initialized) { + initialized = true; + initialize(); + } + } + + @Override + public Disposable subscribe(Subscriber sub) { + Disposable disp = super.subscribe(sub); + chechInitialized(); + return disp; + } + + @Override + public void onDisposed(Subscriber sub) { + super.onDisposed(sub); + this.mapDisposableA.dispose(); + this.mapDisposableB.dispose(); + } +} diff --git a/src/main/java/org/warp/picalculator/flow/ObservableSource.java b/src/main/java/org/warp/picalculator/flow/ObservableSource.java new file mode 100644 index 00000000..48ad441a --- /dev/null +++ b/src/main/java/org/warp/picalculator/flow/ObservableSource.java @@ -0,0 +1,5 @@ +package org.warp.picalculator.flow; + +public interface ObservableSource { + public void subscribe(Observer observer); +} diff --git a/src/main/java/org/warp/picalculator/flow/ObservableZipped.java b/src/main/java/org/warp/picalculator/flow/ObservableZipped.java new file mode 100644 index 00000000..526f9772 --- /dev/null +++ b/src/main/java/org/warp/picalculator/flow/ObservableZipped.java @@ -0,0 +1,86 @@ +package org.warp.picalculator.flow; + +import java.util.function.Function; + +import org.apache.commons.lang3.tuple.Pair; + +public class ObservableZipped extends Observable> { + private volatile boolean initialized = false; + private Observable a; + private Observable b; + private Disposable disposableA; + private Disposable disposableB; + private volatile T lastA; + private volatile U lastB; + private volatile boolean didA; + private volatile boolean didB; + private Subject> pairSubject; + private Subject mapSubject; + + public ObservableZipped(Observable a, Observable b) { + super(); + this.a = a; + this.b = b; + this.pairSubject = SimpleSubject.create(); + } + + private void initialize() { + this.disposableA = a.subscribe((t) -> { + lastA = t; + didA = true; + receivedNext(); + }, (e) -> { + for (Subscriber> sub : this.subscribers) { + sub.onError(e); + }; + }, () -> { + for (Subscriber> sub : this.subscribers) { + sub.onComplete(); + }; + }); + this.disposableB = b.subscribe((t) -> { + lastB = t; + didB = true; + receivedNext(); + }, (e) -> { + for (Subscriber> sub : this.subscribers) { + sub.onError(e); + }; + }, () -> { + for (Subscriber> sub : this.subscribers) { + sub.onComplete(); + }; + }); + } + + private void receivedNext() { + if (didA && didB) { + didA = false; + didB = false; + for (Subscriber> sub : this.subscribers) { + sub.onNext(Pair.of(lastA, lastB)); + }; + } + } + + private void chechInitialized() { + if (!initialized) { + initialized = true; + initialize(); + } + } + + @Override + public Disposable subscribe(Subscriber> sub) { + Disposable disp = super.subscribe(sub); + chechInitialized(); + return disp; + } + + @Override + public void onDisposed(Subscriber> sub) { + super.onDisposed(sub); + this.disposableA.dispose(); + this.disposableB.dispose(); + } +} diff --git a/src/main/java/org/warp/picalculator/flow/Observer.java b/src/main/java/org/warp/picalculator/flow/Observer.java new file mode 100644 index 00000000..4dd096bd --- /dev/null +++ b/src/main/java/org/warp/picalculator/flow/Observer.java @@ -0,0 +1,8 @@ +package org.warp.picalculator.flow; + +public interface Observer { + public void onComplete(); + public void onError(Throwable e); + public void onNext(T t); + public void onSubscribe(Disposable d); +} diff --git a/src/main/java/org/warp/picalculator/flow/SimpleSubject.java b/src/main/java/org/warp/picalculator/flow/SimpleSubject.java new file mode 100644 index 00000000..f67f621d --- /dev/null +++ b/src/main/java/org/warp/picalculator/flow/SimpleSubject.java @@ -0,0 +1,72 @@ +package org.warp.picalculator.flow; + +import java.util.LinkedList; +import java.util.List; + +import org.apache.commons.lang3.tuple.Pair; + +public class SimpleSubject extends Subject { + + protected SimpleSubject() { + } + + public final static SimpleSubject create() { + return new SimpleSubject<>(); + } + + @Override + public void onComplete() { + for (Subscriber sub : this.subscribers) { + sub.onComplete(); + }; + } + + @Override + public void onError(Throwable e) { + for (Subscriber sub : this.subscribers) { + sub.onError(e); + }; + } + + @Override + public void onNext(T t) { + for (Subscriber sub : this.subscribers) { + sub.onNext(t); + }; + } + + @Override + Throwable getThrowable() { + // TODO Auto-generated method stub + return null; + } + + @Override + boolean hasComplete() { + // TODO Auto-generated method stub + return false; + } + + @Override + boolean hasObservers() { + // TODO Auto-generated method stub + return false; + } + + @Override + boolean hasThrowable() { + // TODO Auto-generated method stub + return false; + } + + @Override + Subject toSerialized() { + // TODO Auto-generated method stub + return null; + } + + @Override + public void onSubscribe(Disposable d) { + } + +} diff --git a/src/main/java/org/warp/picalculator/flow/Subject.java b/src/main/java/org/warp/picalculator/flow/Subject.java new file mode 100644 index 00000000..29bfd868 --- /dev/null +++ b/src/main/java/org/warp/picalculator/flow/Subject.java @@ -0,0 +1,36 @@ +package org.warp.picalculator.flow; + +public abstract class Subject extends Observable implements Observer { + abstract Throwable getThrowable(); + abstract boolean hasComplete(); + abstract boolean hasObservers(); + abstract boolean hasThrowable(); + abstract Subject toSerialized(); + + @Override + public Disposable subscribe(Action1 onNext) { + return subscribe(createSubscriber(onNext)); + } + + @Override + public Disposable subscribe(Action1 onNext, Action1 onError) { + return subscribe(createSubscriber(onNext, onError)); + } + + @Override + public Disposable subscribe(Action1 onNext, Action1 onError, Action0 onCompl) { + return subscribe(createSubscriber(onNext, onError, onCompl)); + } + + @Override + public void subscribe(Observer obs) { + subscribe(createSubscriber(obs)); + } + + @Override + public Disposable subscribe(Subscriber sub) { + Disposable disp = super.subscribe(sub); + this.onSubscribe(disp); + return disp; + } +} diff --git a/src/main/java/org/warp/picalculator/flow/Subscriber.java b/src/main/java/org/warp/picalculator/flow/Subscriber.java new file mode 100644 index 00000000..2da92954 --- /dev/null +++ b/src/main/java/org/warp/picalculator/flow/Subscriber.java @@ -0,0 +1,8 @@ +package org.warp.picalculator.flow; + +public interface Subscriber { + default void onComplete() {} + default void onError(Throwable t) {} + void onNext(T t); + void onSubscribe(Subscription s); +} diff --git a/src/main/java/org/warp/picalculator/flow/Subscription.java b/src/main/java/org/warp/picalculator/flow/Subscription.java new file mode 100644 index 00000000..b5ad231b --- /dev/null +++ b/src/main/java/org/warp/picalculator/flow/Subscription.java @@ -0,0 +1,6 @@ +package org.warp.picalculator.flow; + +public interface Subscription { + void cancel(); + void request(long n); +} diff --git a/src/main/java/org/warp/picalculator/flow/TestFlow.java b/src/main/java/org/warp/picalculator/flow/TestFlow.java new file mode 100644 index 00000000..5c378629 --- /dev/null +++ b/src/main/java/org/warp/picalculator/flow/TestFlow.java @@ -0,0 +1,138 @@ +package org.warp.picalculator.flow; + +import org.apache.commons.lang3.tuple.Pair; + +public class TestFlow { + public static void main(String[] args) { + try { + + BehaviorSubject subject0 = BehaviorSubject.create(0f); + + Disposable s00 = subject0.subscribe((val) -> { + System.out.println(val); + }); + Thread.sleep(100); + subject0.onNext(1f); + subject0.onNext(2f); + subject0.onNext(3f); + subject0.onNext(4f); + subject0.onNext(5f); + subject0.onNext(60f); + s00.dispose(); + subject0.onNext(60f); + subject0.onNext(7f); + + + subject0.onComplete(); + System.out.println("items sent."); + + Subject subject1 = BehaviorSubject.create(0f); + + Disposable s01 = subject1.map((val) -> val + 1).subscribe((val) -> { + System.out.println(val); + }); + Thread.sleep(100); + subject1.onNext(1f); + subject1.onNext(2f); + subject1.onNext(3f); + subject1.onNext(4f); + subject1.onNext(5f); + subject1.onNext(60f); + s01.dispose(); + subject1.onNext(60f); + subject1.onNext(7f); + + subject1.onComplete(); + System.out.println("items sent."); + + BehaviorSubject subjectA = BehaviorSubject.create(); + BehaviorSubject subjectB = BehaviorSubject.create(); + Observable observable = Observable.merge(subjectA, subjectB); + + Disposable s1 = observable.subscribe((val) -> { + System.out.println(val); + }); + Thread.sleep(100); + subjectA.onNext(1f); + subjectA.onNext(2f); + subjectA.onNext(3f); + subjectA.onNext(4f); + subjectA.onNext(5f); + subjectB.onNext(60f); + s1.dispose(); + subjectB.onNext(60f); + subjectA.onNext(7f); + + subjectB.onComplete(); + subjectA.onComplete(); + Thread.sleep(100); + System.out.println("no more news subscribers left, closing publisher.."); + + BehaviorSubject subjectC = BehaviorSubject.create(); + BehaviorSubject subjectD = BehaviorSubject.create(); + Observable> observableCombined = Observable.combineLatest(subjectC, subjectD); + System.out.println("Combined observable: " + observableCombined.toString()); + Disposable s2 = observableCombined.subscribe((val) -> { + System.out.println(val); + }); + Thread.sleep(100); + subjectC.onNext(1f); + subjectC.onNext(2f); + subjectC.onNext(3f); + subjectC.onNext(4f); + subjectC.onNext(5f); + subjectD.onNext(60f); + subjectD.onNext(60f); + subjectC.onNext(7f); + s2.dispose(); + + subjectD.onComplete(); + subjectC.onComplete(); + System.out.println("items sent."); + + ObservableInterval timA = ObservableInterval.create(100L); + Disposable d = timA.subscribe((t) -> { + System.out.println(t); + }); + + Thread.sleep(500); + d.dispose(); + System.out.println("items sent."); + + ObservableInterval subjectE = ObservableInterval.create(100L); + BehaviorSubject subjectF = BehaviorSubject.create(); + Observable> observableZipped = Observable.zip(subjectE, subjectF); + System.out.println("Zipped observable: " + observableZipped.toString()); + Disposable s3 = observableZipped.subscribe((val) -> { + System.out.println(val); + }); + Thread.sleep(100); + subjectF.onNext(1f); + Thread.sleep(100); + subjectF.onNext(2f); + Thread.sleep(100); + subjectF.onNext(3f); + Thread.sleep(100); + subjectF.onNext(4f); + Thread.sleep(100); + subjectF.onNext(5f); + Thread.sleep(100); + subjectF.onNext(60f); + Thread.sleep(100); + subjectF.onNext(60f); + Thread.sleep(100); + subjectF.onNext(7f); + Thread.sleep(500); + s3.dispose(); + + subjectF.onComplete(); + System.out.println("items sent."); + + + + } catch (Exception ex) { + ex.printStackTrace(); + } + } + +} diff --git a/src/main/java/org/warp/picalculator/gui/DisplayManager.java b/src/main/java/org/warp/picalculator/gui/DisplayManager.java index 725f1c18..67d3353f 100755 --- a/src/main/java/org/warp/picalculator/gui/DisplayManager.java +++ b/src/main/java/org/warp/picalculator/gui/DisplayManager.java @@ -22,6 +22,7 @@ import org.warp.picalculator.event.TouchEvent; import org.warp.picalculator.event.TouchEventListener; import org.warp.picalculator.event.TouchMoveEvent; import org.warp.picalculator.event.TouchStartEvent; +import org.warp.picalculator.flow.Observable; import org.warp.picalculator.gui.graphicengine.BinaryFont; import org.warp.picalculator.gui.graphicengine.GraphicEngine; import org.warp.picalculator.gui.graphicengine.Renderer; @@ -30,8 +31,6 @@ import org.warp.picalculator.gui.graphicengine.Skin; import org.warp.picalculator.gui.graphicengine.nogui.NoGuiEngine; import org.warp.picalculator.gui.screens.Screen; -import io.reactivex.Observable; -import io.reactivex.Scheduler; import it.unimi.dsi.fastutil.longs.Long2ObjectMap.Entry; import it.unimi.dsi.fastutil.objects.ObjectArrayList; @@ -401,9 +400,9 @@ public final class DisplayManager implements RenderingLoop { DSystem.exit(0); } - Observable workTimer = Observable.interval(tickDuration, TimeUnit.MILLISECONDS); + Observable workTimer = Observable.interval(tickDuration); - Observable.combineLatest(workTimer, engine.onResize(), (time, windowSize) -> windowSize).subscribe((windowSize) -> { + Observable.combineChanged(workTimer, engine.onResize()).subscribe((pair) -> { double dt = 0; final long newtime = System.nanoTime(); if (precTime == -1) { @@ -413,8 +412,11 @@ public final class DisplayManager implements RenderingLoop { } precTime = newtime; - StaticVars.screenSize[0] = windowSize[0]; - StaticVars.screenSize[1] = windowSize[1]; + if (pair.getRight() != null) { + Integer[] windowSize = pair.getRight(); + StaticVars.screenSize[0] = windowSize[0]; + StaticVars.screenSize[1] = windowSize[1]; + } screen.beforeRender((float) (dt / 1000d)); }); diff --git a/src/main/java/org/warp/picalculator/gui/graphicengine/GraphicEngine.java b/src/main/java/org/warp/picalculator/gui/graphicengine/GraphicEngine.java index 9ba81524..998ab473 100755 --- a/src/main/java/org/warp/picalculator/gui/graphicengine/GraphicEngine.java +++ b/src/main/java/org/warp/picalculator/gui/graphicengine/GraphicEngine.java @@ -3,7 +3,7 @@ package org.warp.picalculator.gui.graphicengine; import java.io.IOException; import java.util.List; -import io.reactivex.Observable; +import org.warp.picalculator.flow.Observable; public interface GraphicEngine { diff --git a/src/main/java/org/warp/picalculator/gui/graphicengine/cpu/CPUEngine.java b/src/main/java/org/warp/picalculator/gui/graphicengine/cpu/CPUEngine.java index 93e02f48..704eff6a 100644 --- a/src/main/java/org/warp/picalculator/gui/graphicengine/cpu/CPUEngine.java +++ b/src/main/java/org/warp/picalculator/gui/graphicengine/cpu/CPUEngine.java @@ -8,14 +8,13 @@ import java.util.concurrent.Semaphore; import org.warp.picalculator.StaticVars; import org.warp.picalculator.Utils; import org.warp.picalculator.device.HardwareDevice; +import org.warp.picalculator.flow.Observable; import org.warp.picalculator.gui.DisplayManager; import org.warp.picalculator.gui.graphicengine.BinaryFont; import org.warp.picalculator.gui.graphicengine.GraphicEngine; import org.warp.picalculator.gui.graphicengine.RenderingLoop; import org.warp.picalculator.gui.graphicengine.Skin; -import io.reactivex.Observable; - public class CPUEngine implements GraphicEngine { private SwingWindow INSTANCE; diff --git a/src/main/java/org/warp/picalculator/gui/graphicengine/cpu/SwingWindow.java b/src/main/java/org/warp/picalculator/gui/graphicengine/cpu/SwingWindow.java index c80a5bb2..65757a03 100755 --- a/src/main/java/org/warp/picalculator/gui/graphicengine/cpu/SwingWindow.java +++ b/src/main/java/org/warp/picalculator/gui/graphicengine/cpu/SwingWindow.java @@ -29,11 +29,11 @@ import org.warp.picalculator.event.TouchEndEvent; import org.warp.picalculator.event.TouchMoveEvent; import org.warp.picalculator.event.TouchPoint; import org.warp.picalculator.event.TouchStartEvent; +import org.warp.picalculator.flow.BehaviorSubject; +import org.warp.picalculator.flow.Observable; import org.warp.picalculator.gui.DisplayManager; import org.warp.picalculator.gui.graphicengine.RenderingLoop; -import io.reactivex.Observable; -import io.reactivex.subjects.BehaviorSubject; import it.unimi.dsi.fastutil.objects.ObjectArrayList; public class SwingWindow extends JFrame { @@ -55,7 +55,8 @@ public class SwingWindow extends JFrame { // Transparent 16 x 16 pixel cursor image. final BufferedImage cursorImg = new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB); - mult = StaticVars.windowZoomValue.next().intValue(); + mult = StaticVars.windowZoomFunction.apply(StaticVars.windowZoom.getLastValue()).intValue(); + if (StaticVars.debugOn) { if (Utils.debugThirdScreen) { this.setLocation(2880, 900); diff --git a/src/main/java/org/warp/picalculator/gui/graphicengine/framebuffer/FBEngine.java b/src/main/java/org/warp/picalculator/gui/graphicengine/framebuffer/FBEngine.java index d400ed5e..bddebd79 100644 --- a/src/main/java/org/warp/picalculator/gui/graphicengine/framebuffer/FBEngine.java +++ b/src/main/java/org/warp/picalculator/gui/graphicengine/framebuffer/FBEngine.java @@ -10,6 +10,8 @@ import org.warp.picalculator.MmapByteBuffer; import org.warp.picalculator.StaticVars; import org.warp.picalculator.TestJNI; import org.warp.picalculator.Utils; +import org.warp.picalculator.flow.BehaviorSubject; +import org.warp.picalculator.flow.Observable; import org.warp.picalculator.gui.graphicengine.BinaryFont; import org.warp.picalculator.gui.graphicengine.GraphicEngine; import org.warp.picalculator.gui.graphicengine.Renderer; @@ -18,9 +20,6 @@ import org.warp.picalculator.gui.graphicengine.Skin; import org.warp.picalculator.gui.graphicengine.cpu.CPUFont; import org.warp.picalculator.gui.graphicengine.cpu.CPUSkin; -import io.reactivex.Observable; -import io.reactivex.subjects.BehaviorSubject; - public class FBEngine implements GraphicEngine { private static final int FB_DISPLAY_WIDTH = 320; @@ -59,7 +58,7 @@ public class FBEngine implements GraphicEngine { @Override public void create(Runnable onInitialized) { - onResize = BehaviorSubject.createDefault(new Integer[] {SIZE[0], SIZE[1]}); + onResize = BehaviorSubject.create(new Integer[] {SIZE[0], SIZE[1]}); realFb = jni.retrieveBuffer(); final long fbLen = realFb.getLength(); fb = (MappedByteBuffer) ByteBuffer.allocateDirect((int) fbLen); diff --git a/src/main/java/org/warp/picalculator/gui/graphicengine/gpu/GPUEngine.java b/src/main/java/org/warp/picalculator/gui/graphicengine/gpu/GPUEngine.java index 984428dd..87058a20 100755 --- a/src/main/java/org/warp/picalculator/gui/graphicengine/gpu/GPUEngine.java +++ b/src/main/java/org/warp/picalculator/gui/graphicengine/gpu/GPUEngine.java @@ -10,6 +10,7 @@ import java.util.concurrent.Semaphore; import org.warp.picalculator.StaticVars; import org.warp.picalculator.Utils; +import org.warp.picalculator.flow.Observable; import org.warp.picalculator.gui.graphicengine.BinaryFont; import org.warp.picalculator.gui.graphicengine.GraphicEngine; import org.warp.picalculator.gui.graphicengine.RenderingLoop; @@ -18,10 +19,6 @@ import org.warp.picalculator.gui.graphicengine.Skin; import com.jogamp.opengl.GLProfile; import com.jogamp.opengl.util.texture.Texture; -import io.reactivex.Observable; -import io.reactivex.processors.BehaviorProcessor; -import io.reactivex.subjects.BehaviorSubject; - public class GPUEngine implements GraphicEngine { private volatile boolean initialized = false; @@ -63,8 +60,6 @@ public class GPUEngine implements GraphicEngine { @Override public void setDisplayMode(int ww, int wh) { - size[0] = ww; - size[1] = wh; wnd.setSize(ww, wh); } @@ -89,7 +84,7 @@ public class GPUEngine implements GraphicEngine { @Override public Observable onResize() { - return wnd.onResize; + return wnd.onResizeEvent; } @Override diff --git a/src/main/java/org/warp/picalculator/gui/graphicengine/gpu/NEWTWindow.java b/src/main/java/org/warp/picalculator/gui/graphicengine/gpu/NEWTWindow.java index d69d0fc7..fdfb05aa 100755 --- a/src/main/java/org/warp/picalculator/gui/graphicengine/gpu/NEWTWindow.java +++ b/src/main/java/org/warp/picalculator/gui/graphicengine/gpu/NEWTWindow.java @@ -28,12 +28,8 @@ package org.warp.picalculator.gui.graphicengine.gpu; -import java.nio.file.WatchService; -import java.util.ArrayList; import java.util.List; -import org.apache.commons.lang3.tuple.Pair; -import org.warp.picalculator.ConsoleUtils; import org.warp.picalculator.StaticVars; import org.warp.picalculator.device.HardwareDevice; import org.warp.picalculator.device.Keyboard; @@ -42,11 +38,11 @@ import org.warp.picalculator.event.TouchEndEvent; import org.warp.picalculator.event.TouchMoveEvent; import org.warp.picalculator.event.TouchPoint; import org.warp.picalculator.event.TouchStartEvent; -import org.warp.picalculator.gui.DisplayManager; +import org.warp.picalculator.flow.BehaviorSubject; +import org.warp.picalculator.flow.SimpleSubject; +import org.warp.picalculator.flow.Subject; import org.warp.picalculator.gui.graphicengine.GraphicEngine; -import com.jogamp.newt.event.GestureHandler.GestureEvent; -import com.jogamp.newt.event.GestureHandler.GestureListener; import com.jogamp.newt.event.KeyEvent; import com.jogamp.newt.event.KeyListener; import com.jogamp.newt.event.MouseEvent; @@ -67,15 +63,6 @@ import com.jogamp.opengl.fixedfunc.GLPointerFunc; import com.jogamp.opengl.util.Animator; import com.jogamp.opengl.util.texture.Texture; -import io.reactivex.Observable; -import io.reactivex.ObservableSource; -import io.reactivex.Observer; -import io.reactivex.disposables.Disposable; -import io.reactivex.processors.BehaviorProcessor; -import io.reactivex.subjects.BehaviorSubject; -import io.reactivex.subjects.PublishSubject; -import io.reactivex.subjects.ReplaySubject; -import io.reactivex.subjects.Subject; import it.unimi.dsi.fastutil.objects.ObjectArrayList; /** @@ -95,26 +82,46 @@ class NEWTWindow implements GLEventListener { public volatile boolean refreshViewport; public List touches = new ObjectArrayList<>(); - final BehaviorSubject onResize = BehaviorSubject.create(); + final BehaviorSubject onRealResize; + final BehaviorSubject onResizeEvent = BehaviorSubject.create(); private BehaviorSubject onZoom = BehaviorSubject.create(); - private Subject onGLContext = PublishSubject.create(); + private Subject onGLContext = SimpleSubject.create(); public NEWTWindow(GPUEngine disp) { this.disp = disp; renderer = disp.getRenderer(); - realWindowSize = new int[] { 1, 1 }; + disp.size[0] = StaticVars.screenSize[0]; + disp.size[1] = StaticVars.screenSize[1]; + realWindowSize = new int[] { StaticVars.screenSize[0], StaticVars.screenSize[1] }; + windowZoom = StaticVars.windowZoomFunction.apply(StaticVars.windowZoom.getLastValue()); + onRealResize = BehaviorSubject.create(new Integer[] {(int) (StaticVars.screenSize[0] * windowZoom), (int) (StaticVars.screenSize[1] * windowZoom)}); - Observable.zip(onZoom, onGLContext, (gl,zoom)->{return Pair.of(gl, zoom);}).subscribe((pair) -> { - windowZoom = pair.getLeft(); - onDisplayChanged(pair.getRight(), true, false); + onRealResize.subscribe((realSize) -> { + System.err.println("[[[SET REALWINDOWZOOM"); + realWindowSize[0] = realSize[0]; + realWindowSize[1] = realSize[1]; + disp.size[0] = realSize[0] / (int) windowZoom; + disp.size[1] = realSize[1] / (int) windowZoom; + System.err.println("[[["+realWindowSize[0]); + System.err.println("[[["+windowZoom); + System.err.println("[[["+disp.size[0]); + onResizeEvent.onNext(new Integer[] {disp.size[0], disp.size[1]}); + refreshViewport = true; }); - Observable.zip(onResize, onGLContext, (gl,size)->{return Pair.of(gl, size);}).subscribe((pair) -> { - final Integer[] size = pair.getLeft(); - realWindowSize[0] = size[0]; - realWindowSize[1] =size[1]; - disp.size[0] = size[0]; - disp.size[1] = size[1]; - onDisplayChanged(pair.getRight(), false, true); + StaticVars.windowZoom$.subscribe((zoom) -> {onZoom.onNext(zoom);}); + onZoom.subscribe((z)-> { + if (windowZoom != 0) { + windowZoom = z; + disp.size[0] = (int) (realWindowSize[0] / windowZoom); + disp.size[1] = (int) (realWindowSize[1] / windowZoom); + StaticVars.screenSize[0] = disp.size[0]; + StaticVars.screenSize[1] = disp.size[1]; + System.err.println("[[[SET WINDOWZOOM"); + System.err.println("[[["+realWindowSize[0]); + System.err.println("[[["+windowZoom); + System.err.println("[[[A:"+disp.size[0]); + refreshViewport = true; + } }); } @@ -472,8 +479,6 @@ class NEWTWindow implements GLEventListener { } catch (final Exception e) { e.printStackTrace(); } - StaticVars.windowZoom$.subscribe((zoom) -> {onZoom.onNext(zoom);}); - onResize.onNext(new Integer[] {disp.size[0], disp.size[1]}); if (onInitialized != null) { onInitialized.run(); @@ -489,21 +494,7 @@ class NEWTWindow implements GLEventListener { @Override public void reshape(GLAutoDrawable glad, int x, int y, int width, int height) { - onResize.onNext(new Integer[] {width, height}); - } - - private void onDisplayChanged(GL2ES1 gl, boolean zoomChanged, boolean sizeChanged) { - disp.size[0] = (int) (realWindowSize[0] / windowZoom); - disp.size[1] = (int) (realWindowSize[1] / windowZoom); - - if (zoomChanged) { - final boolean linear = (windowZoom % ((int) windowZoom)) != 0f; - for (final Texture t : disp.registeredTextures) { - t.setTexParameteri(gl, GL.GL_TEXTURE_MAG_FILTER, linear ? GL.GL_LINEAR : GL.GL_NEAREST); - t.setTexParameteri(gl, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR); - } - } - refreshViewport = true; + onRealResize.onNext(new Integer[] {width, height}); } @Override @@ -512,18 +503,9 @@ class NEWTWindow implements GLEventListener { GPURenderer.gl = gl; onGLContext.onNext(gl); - Boolean linear = null; - while (!disp.unregisteredTextures.isEmpty()) { - if (linear == null) { - linear = (windowZoom % ((int) windowZoom)) != 0f; - } - final Texture t = disp.unregisteredTextures.pop(); - t.setTexParameteri(gl, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST); - t.setTexParameteri(gl, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR); - disp.registeredTextures.addLast(t); - } - + boolean linear = (windowZoom % ((int) windowZoom)) != 0f; if (refreshViewport) { + System.err.println("[[[REFVP"); refreshViewport = false; gl.glViewport(0, 0, realWindowSize[0], realWindowSize[1]); @@ -534,6 +516,17 @@ class NEWTWindow implements GLEventListener { gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); gl.glLoadIdentity(); + + for (final Texture t : disp.registeredTextures) { + t.setTexParameteri(gl, GL.GL_TEXTURE_MAG_FILTER, linear ? GL.GL_LINEAR : GL.GL_NEAREST); + t.setTexParameteri(gl, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR); + } + } + while (disp.unregisteredTextures.isEmpty() == false) { + final Texture t = disp.unregisteredTextures.pop(); + t.setTexParameteri(gl, GL.GL_TEXTURE_MAG_FILTER, linear ? GL.GL_LINEAR : GL.GL_NEAREST); + t.setTexParameteri(gl, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR); + disp.registeredTextures.addLast(t); } gl.glEnableClientState(GLPointerFunc.GL_COLOR_ARRAY); @@ -554,12 +547,16 @@ class NEWTWindow implements GLEventListener { } - public void setSize(final int width, final int height) { + void setSize(final int width, final int height) { int zoom = (int) windowZoom; if (zoom == 0) { - zoom = onZoom.blockingFirst().intValue(); + zoom = onZoom.getLastValue().intValue(); + } + if (zoom == 0) { + zoom = 1; } window.setSize(width * zoom, height * zoom); + onRealResize.onNext(new Integer[] {width * zoom, height * zoom}); } @Override diff --git a/src/main/java/org/warp/picalculator/gui/graphicengine/headless24bit/Headless24bitEngine.java b/src/main/java/org/warp/picalculator/gui/graphicengine/headless24bit/Headless24bitEngine.java index 2ed0ec9e..57a5e606 100644 --- a/src/main/java/org/warp/picalculator/gui/graphicengine/headless24bit/Headless24bitEngine.java +++ b/src/main/java/org/warp/picalculator/gui/graphicengine/headless24bit/Headless24bitEngine.java @@ -9,11 +9,10 @@ import org.warp.picalculator.StaticVars; import org.warp.picalculator.Utils; import org.warp.picalculator.device.Keyboard; import org.warp.picalculator.event.Key; +import org.warp.picalculator.flow.DObservable; import org.warp.picalculator.gui.graphicengine.Renderer; import org.warp.picalculator.gui.graphicengine.RenderingLoop; -import io.reactivex.Observable; - public class Headless24bitEngine implements org.warp.picalculator.gui.graphicengine.GraphicEngine { private final Headless24bitRenderer r = new Headless24bitRenderer(); @@ -140,7 +139,7 @@ public class Headless24bitEngine implements org.warp.picalculator.gui.graphiceng } @Override - public Observable onResize() { + public DObservable onResize() { return null; } diff --git a/src/main/java/org/warp/picalculator/gui/graphicengine/headless256/Headless256Engine.java b/src/main/java/org/warp/picalculator/gui/graphicengine/headless256/Headless256Engine.java index a139685f..48fc30ef 100755 --- a/src/main/java/org/warp/picalculator/gui/graphicengine/headless256/Headless256Engine.java +++ b/src/main/java/org/warp/picalculator/gui/graphicengine/headless256/Headless256Engine.java @@ -9,12 +9,11 @@ import org.warp.picalculator.StaticVars; import org.warp.picalculator.Utils; import org.warp.picalculator.device.Keyboard; import org.warp.picalculator.event.Key; +import org.warp.picalculator.flow.DObservable; import org.warp.picalculator.gui.graphicengine.Renderer; import org.warp.picalculator.gui.graphicengine.RenderingLoop; import org.warp.picalculator.gui.graphicengine.headless24bit.Headless24bitRenderer; -import io.reactivex.Observable; - public class Headless256Engine implements org.warp.picalculator.gui.graphicengine.GraphicEngine { private final Headless256Renderer r = new Headless256Renderer(); @@ -139,7 +138,7 @@ public class Headless256Engine implements org.warp.picalculator.gui.graphicengin } @Override - public Observable onResize() { + public DObservable onResize() { return null; } diff --git a/src/main/java/org/warp/picalculator/gui/graphicengine/headless8/Headless8Engine.java b/src/main/java/org/warp/picalculator/gui/graphicengine/headless8/Headless8Engine.java index a20f0b05..12938038 100644 --- a/src/main/java/org/warp/picalculator/gui/graphicengine/headless8/Headless8Engine.java +++ b/src/main/java/org/warp/picalculator/gui/graphicengine/headless8/Headless8Engine.java @@ -9,12 +9,11 @@ import org.warp.picalculator.StaticVars; import org.warp.picalculator.Utils; import org.warp.picalculator.device.Keyboard; import org.warp.picalculator.event.Key; +import org.warp.picalculator.flow.DObservable; import org.warp.picalculator.gui.graphicengine.Renderer; import org.warp.picalculator.gui.graphicengine.RenderingLoop; import org.warp.picalculator.gui.graphicengine.headless24bit.Headless24bitRenderer; -import io.reactivex.Observable; - public class Headless8Engine implements org.warp.picalculator.gui.graphicengine.GraphicEngine { private final Headless8Renderer r = new Headless8Renderer(); @@ -139,7 +138,7 @@ public class Headless8Engine implements org.warp.picalculator.gui.graphicengine. } @Override - public Observable onResize() { + public DObservable onResize() { return null; } diff --git a/src/main/java/org/warp/picalculator/gui/graphicengine/nogui/NoGuiEngine.java b/src/main/java/org/warp/picalculator/gui/graphicengine/nogui/NoGuiEngine.java index 966ef8f2..cb4e377b 100644 --- a/src/main/java/org/warp/picalculator/gui/graphicengine/nogui/NoGuiEngine.java +++ b/src/main/java/org/warp/picalculator/gui/graphicengine/nogui/NoGuiEngine.java @@ -5,14 +5,13 @@ import java.util.concurrent.Semaphore; import org.warp.picalculator.Utils; import org.warp.picalculator.deps.DSemaphore; +import org.warp.picalculator.flow.Observable; import org.warp.picalculator.gui.graphicengine.BinaryFont; import org.warp.picalculator.gui.graphicengine.GraphicEngine; import org.warp.picalculator.gui.graphicengine.Renderer; import org.warp.picalculator.gui.graphicengine.RenderingLoop; import org.warp.picalculator.gui.graphicengine.Skin; -import io.reactivex.Observable; - public class NoGuiEngine implements GraphicEngine { private boolean initialized; diff --git a/src/main/java/org/warp/picalculator/gui/screens/LoadingScreen.java b/src/main/java/org/warp/picalculator/gui/screens/LoadingScreen.java index 6c837992..db98f338 100755 --- a/src/main/java/org/warp/picalculator/gui/screens/LoadingScreen.java +++ b/src/main/java/org/warp/picalculator/gui/screens/LoadingScreen.java @@ -26,7 +26,7 @@ public class LoadingScreen extends Screen { @Override public void initialized() throws InterruptedException { - previousZoomValue = StaticVars.windowZoomValue.next(); + previousZoomValue = StaticVars.windowZoomFunction.apply(StaticVars.windowZoom.getLastValue()); StaticVars.windowZoom.onNext(1f); }