Skip to content

Instantly share code, notes, and snippets.

@GoToLoop
Last active March 26, 2019 17:57
Show Gist options
  • Save GoToLoop/1d1eb18f468a7d5758469707276b6ea1 to your computer and use it in GitHub Desktop.
Save GoToLoop/1d1eb18f468a7d5758469707276b6ea1 to your computer and use it in GitHub Desktop.
Canvas Resize Watcher
/**
* Canvas Resize Watcher (v1.0)
* GoToLoop (2018/May/04)
* Developed on P3 (v3.3.5)
*
* https://Discourse.Processing.org/t/event-called-when-canvas-is-resized/6643/8
* https://Gist.GitHub.com/GoToLoop/1d1eb18f468a7d5758469707276b6ea1
*/
import gotoloop.listener.CanvasResizeWatcher;
static final String RENDERER = FX2D;
static final color BG = 0x40 << 030, BG_RANGE = 1 << 030;
static final color FILL = -1, STROKE = 0;
static final float WEIGHT = 2.5, FPS = 60.0;
PGraphics pg;
color bg;
CanvasResizeWatcher watcher;
void setup() {
size(800, 600, RENDERER);
frameRate(FPS);
cursor(ARROW);
colorMode(RGB);
imageMode(CENTER);
createLayer();
println( watcher = new CanvasResizeWatcher(this).start() );
}
void draw() {
background(bg);
image(pg, width>>1, height>>1);
displayTitle();
}
void mousePressed() {
final CanvasResizeWatcher w = watcher;
switch (mouseButton) {
case LEFT:
if (w.isPaused()) w.resume();
else w.pause();
return;
case RIGHT:
w.immediate ^= true;
return;
default:
w.resume();
w.immediate = false;
}
}
void displayTitle() {
final CanvasResizeWatcher w = watcher;
getSurface().setTitle("Paused: " + w.isPaused()
+ " - Immediate: " + w.immediate);
}
void frameResized(final int w, final int h) {
createLayer();
bg = (color) random(BG_RANGE);
print(w, h, TAB);
}
void createLayer() {
final int w = max(1, width>>1), h = max(1, height>>1);
( pg = createGraphics(w, h) ).beginDraw();
pg.colorMode(RGB);
pg.background(BG);
pg.fill(FILL);
pg.stroke(STROKE);
pg.strokeWeight(WEIGHT);
pg.ellipseMode(CENTER);
pg.ellipse(pg.width>>1, pg.height>>1, pg.width, pg.height);
pg.endDraw();
}
/**
* Canvas Resize Watcher (v1.0)
* GoToLoop (2018/May/04)
* Developed on P3 (v3.3.5)
*
* https://Discourse.Processing.org/t/event-called-when-canvas-is-resized/6643/8
* https://Gist.GitHub.com/GoToLoop/1d1eb18f468a7d5758469707276b6ea1
*/
package gotoloop.listener;
import processing.core.PApplet;
import processing.core.PGraphics;
import java.util.concurrent.atomic.AtomicBoolean;
// JAVA2D
import java.awt.Component;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
// FX2D
import javafx.scene.canvas.Canvas;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
// P2D, P3D & OPENGL
import com.jogamp.newt.Window;
import com.jogamp.newt.event.WindowAdapter;
import com.jogamp.newt.event.WindowEvent;
public class CanvasResizeWatcher {
protected final AtomicBoolean resized = new AtomicBoolean();
protected final PApplet p;
protected final Object window;
protected final PGraphics pg;
protected SizeListener listener;
protected boolean paused = true;
public boolean immediate, auto, synced;
public CanvasResizeWatcher(final PApplet pa) {
this(pa, false);
}
public CanvasResizeWatcher(final PApplet pa, boolean now) {
window = ( p = pa ).getSurface().getNative();
pg = pa.getGraphics();
immediate = now;
}
public CanvasResizeWatcher start() {
createRendererListener();
resume().p.getSurface().setResizable(true);
return this;
}
public CanvasResizeWatcher stop() {
if (pause().listener != null) {
listener.removeListener();
listener = null;
}
return this;
}
public CanvasResizeWatcher resume() {
if (paused) {
p.registerMethod("pre", this);
paused = false;
}
return this;
}
public CanvasResizeWatcher pause() {
if (!paused) {
p.unregisterMethod("pre", this);
paused = true;
}
return this;
}
public boolean isPaused() {
return paused;
}
public void pre() {
actIfResized();
}
protected boolean actIfResized() {
return resized.weakCompareAndSet(true, false) && invokeCallback();
}
protected boolean invokeCallback() {
if (!paused) {
p.frameResized(p.width, p.height);
return true;
}
return false;
}
public String discoverRenderer() {
if (window instanceof Canvas) return PApplet.FX2D;
else if (pg.isGL()) return pg.is3D()? PApplet.P3D : PApplet.P2D;
return PApplet.JAVA2D;
}
protected SizeListener createRendererListener() {
return createRendererListener(null);
}
protected SizeListener createRendererListener(String render) {
if (render == null || render.isEmpty()) render = discoverRenderer();
switch (render) {
case PApplet.P2D:
case PApplet.P3D:
return new SizeListenerOPENGL();
case PApplet.FX2D:
return new SizeListenerFX2D<Double>();
default:
return new SizeListenerJAVA2D();
}
}
@Override public String toString() {
return "Renderer: " + listener + "\t\tPaused: "
+ paused + "\tImmediate: " + immediate;
}
public interface SizeListener {
SizeListener addListener();
SizeListener removeListener();
}
public class SizeListenerJAVA2D extends ComponentAdapter
implements SizeListener {
public final Component win = (Component) window;
public SizeListenerJAVA2D() {
if (listener != null) listener.removeListener();
listener = addListener();
}
@Override public SizeListener addListener() {
win.addComponentListener(this);
return this;
}
@Override public SizeListener removeListener() {
win.removeComponentListener(this);
return this;
}
@Override public void componentResized(final ComponentEvent evt) {
if (!immediate) resized.set(true);
else invokeCallback();
}
@Override public String toString() {
return discoverRenderer();
}
}
public class SizeListenerFX2D<N extends Number>
implements SizeListener, ChangeListener<N> {
public final Canvas win = (Canvas) window;
protected final ChangeListener changeListener = this;
public SizeListenerFX2D() {
if (listener != null) listener.removeListener();
listener = addListener();
}
@Override public SizeListener addListener() {
win.widthProperty().addListener(changeListener);
win.heightProperty().addListener(changeListener);
return this;
}
@Override public SizeListener removeListener() {
win.widthProperty().removeListener(changeListener);
win.heightProperty().removeListener(changeListener);
return this;
}
@Override public void
changed(ObservableValue<? extends N> obs, N old, N cur) {
if (!immediate) resized.set(true);
else invokeCallback();
}
@Override public String toString() {
return discoverRenderer();
}
}
public class SizeListenerOPENGL extends WindowAdapter
implements SizeListener {
public final Window win = (Window) window;
public SizeListenerOPENGL() {
if (listener != null) listener.removeListener();
listener = addListener();
}
@Override public SizeListener addListener() {
win.addWindowListener(this);
return this;
}
@Override public SizeListener removeListener() {
win.removeWindowListener(this);
return this;
}
@Override public void windowResized(final WindowEvent evt) {
if (!immediate) resized.set(true);
else invokeCallback();
}
@Override public String toString() {
return discoverRenderer();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment