Mouse handling changes

Method relay now uses weak references rather than strong references. This gets rid of the dangling button memory leak
This commit is contained in:
61616
2022-05-06 17:55:37 -04:00
parent 358dbe7ff8
commit c92e6ba345
5 changed files with 60 additions and 29 deletions

View File

@@ -1,5 +1,5 @@
class MouseHandler { class MouseHandler {
MouseData md; private MouseData md;
private LiveMethodRelay[] mrs; private LiveMethodRelay[] mrs;
MouseHandler(MouseData _md) { MouseHandler(MouseData _md) {
@@ -7,11 +7,13 @@ class MouseHandler {
mrs = new LiveMethodRelay[0]; mrs = new LiveMethodRelay[0];
} }
// PASSTHROUGH FOR MOUSE DATA //
float sMouseX(){return md.sMouseX();} float sMouseX(){return md.sMouseX();}
float sMouseY(){return md.sMouseY();} float sMouseY(){return md.sMouseY();}
float pSMouseX(){return md.pSMouseX();} float pSMouseX(){return md.pSMouseX();}
float pSMouseY(){return md.pSMouseY();} float pSMouseY(){return md.pSMouseY();}
void frameUpdate(PVector offset, float scale){md.update(offset, scale);} void frameUpdate(PVector offset, float scale){md.update(offset, scale); println(mrs.length + " " + millis());}
void addRelay(LiveMethodRelay r) { void addRelay(LiveMethodRelay r) {
clean(); clean();
@@ -30,6 +32,7 @@ class MouseHandler {
} }
void cascade(char tag, float... data) { void cascade(char tag, float... data) {
clean();
for (int i = 0; i < mrs.length; i++) { for (int i = 0; i < mrs.length; i++) {
if(mrs[i].getTag() == tag){ if(mrs[i].getTag() == tag){
mrs[i].execute(data); mrs[i].execute(data);
@@ -97,15 +100,18 @@ class LiveMethodRelay extends MethodRelay {
import java.lang.reflect.*; import java.lang.reflect.*;
import java.lang.ref.*;
/** /**
A class that encapsulates a named method to be invoked. A class that encapsulates a named method to be invoked.
Quark 2015 Quark 2015
see https://forum.processing.org/two/discussion/13093/how-to-call-function-by-string-content.html see https://forum.processing.org/two/discussion/13093/how-to-call-function-by-string-content.html
Modified to use weak references
*/ */
public static class MethodRelay { public static class MethodRelay {
/** The object to handle the draw event */ /** The object to handle the draw event */
private Object handlerObject = null; private WeakReference reference = null;
//private Object handlerObject = null;
/** The method in drawHandlerObject to execute */ /** The method in drawHandlerObject to execute */
private Method handlerMethod = null; private Method handlerMethod = null;
/** the name of the method to handle the event */ /** the name of the method to handle the event */
@@ -125,7 +131,7 @@ public static class MethodRelay {
handlerMethodName = name; handlerMethodName = name;
parameters = args; parameters = args;
handlerMethod = obj.getClass().getMethod(handlerMethodName, parameters); handlerMethod = obj.getClass().getMethod(handlerMethodName, parameters);
handlerObject = obj; reference = new WeakReference(obj);
} }
catch (Exception e) { catch (Exception e) {
println("Unable to find the function -"); println("Unable to find the function -");
@@ -160,9 +166,9 @@ public static class MethodRelay {
to be passed to the method to be passed to the method
*/ */
void execute(Object... data) { void execute(Object... data) {
if (handlerObject != null) { if (reference.get() != null) {
try { try {
handlerMethod.invoke(handlerObject, data); handlerMethod.invoke(reference.get(), data);
} }
catch (Exception e) { catch (Exception e) {
println("Error on invoke"); println("Error on invoke");

View File

@@ -3,15 +3,16 @@ float scale = 2;
PVector offset; PVector offset;
public static final int DECIMAL = 65; public static final int DECIMAL = 65;
MouseHandler mh; // Mouse event handler MouseHandler mh; // Mouse event handler
//MouseData md;
Calculator calc; Calculator calc;
Button b;
void setup(){ void setup(){
size(400,400); size(400,400);
offset = new PVector(width/2, height/2); offset = new PVector(width/2, height/2);
mh = new MouseHandler(new MouseData(offset, scale)); mh = new MouseHandler(new MouseData(offset, scale));
//md = new MouseData(offset, scale); b = new Button(mh, new PVector(20,-20), new PVector(20,20));
b.setFunction(new MethodRelay(this, "changeMode"));
calc = new Calculator(mh); calc = new Calculator(mh);
@@ -23,7 +24,8 @@ void draw(){
translate(offset.x,offset.y); translate(offset.x,offset.y);
scale(scale); scale(scale);
calc.display(); if(calc != null) calc.display();
b.display();
} }
void mouseClicked(){ void mouseClicked(){
@@ -31,11 +33,20 @@ void mouseClicked(){
mh.cascade('c', mh.sMouseX(), mh.sMouseY(), mouseButton); mh.cascade('c', mh.sMouseX(), mh.sMouseY(), mouseButton);
} }
void mouseMoved(){mh.cascade('m', mh.sMouseX(), mh.sMouseY());} void mouseMoved(){mh.cascade('m', mh.sMouseX(), mh.sMouseY());}
void mousePressed(){mh.cascade('m', mh.sMouseX(), mh.sMouseY(), mouseButton);} void mousePressed(){mh.cascade('p', mh.sMouseX(), mh.sMouseY(), mouseButton);}
void mouseReleased(){mh.cascade('m', mh.sMouseX(), mh.sMouseY(), mouseButton);} void mouseReleased(){mh.cascade('r', mh.sMouseX(), mh.sMouseY(), mouseButton);}
void mouseWheel(MouseEvent event){mh.cascade('m', mh.sMouseX(), mh.sMouseY(), event.getCount());} void mouseWheel(MouseEvent event){mh.cascade('w', mh.sMouseX(), mh.sMouseY(), event.getCount());}
void mouseDragged(){mh.cascade('m', mh.sMouseX(), mh.sMouseY(), mouseButton);} void mouseDragged(){mh.cascade('d', mh.sMouseX(), mh.sMouseY(), mouseButton);}
void call(String _call){ void call(String _call){
method(_call); method(_call);
} }
void changeMode(){
if(calc == null){
calc = new Calculator(mh);
return;
}
calc = null;
Runtime.getRuntime().gc();
}

View File

@@ -1,14 +1,15 @@
class Button{ // TODO make most of the attributes private class Button{ // TODO make most of the attributes private
MouseHandler mh; private LiveMethodRelay listener;
PVector pos; // Position to render from private MouseHandler mh;
PVector dim; // Second coordinate for CORNERS or len/wid for CORNER and CENTER private PVector pos; // Position to render from
float radius; // Optional corner radius private PVector dim; // Second coordinate for CORNERS or len/wid for CORNER and CENTER
int mode; // Stores rect draw mode for button private float radius; // Optional corner radius
color col; // Stores static color private int mode; // Stores rect draw mode for button
color highlight; // Stores mouseover color private color col; // Stores static color
MethodRelay function; // Gets called when button is pressed private color highlight; // Stores mouseover color
boolean mouseOver; private MethodRelay function; // Gets called when button is pressed
Object[] data; // Anything that gets passed to MethodRelay function when key pressed. Must be set manually private boolean mouseOver;
private Object[] data; // Anything that gets passed to MethodRelay function when key pressed. Must be set manually
Button(MouseHandler _mh, PVector _pos, PVector _dim, float _radius){ Button(MouseHandler _mh, PVector _pos, PVector _dim, float _radius){
mh = _mh; mh = _mh;
@@ -19,7 +20,8 @@ class Button{ // TODO make most of the attributes private
col = color(200); col = color(200);
highlight = color(100); highlight = color(100);
mouseOver = false; mouseOver = false;
mh.addRelay(new LiveMethodRelay(this, "clicked", 'c', Object.class)); listener = new LiveMethodRelay(this, "clicked", 'p', Object.class);
mh.addRelay(listener);
data = null; data = null;
} }
Button(MouseHandler _mh, PVector _pos, PVector _dim){ Button(MouseHandler _mh, PVector _pos, PVector _dim){
@@ -121,4 +123,12 @@ class Button{ // TODO make most of the attributes private
} }
mouseOver = true; mouseOver = true;
} }
// GARBAGE COLLECTION //
// kill the mouse listener so it will get removed from the mouse event cascade
@Override
protected void finalize(){
println("finalized");
listener.kill();
}
} }

View File

@@ -62,9 +62,9 @@ class B12Button extends Button{
pushMatrix(); pushMatrix();
translate(pos.x,pos.y); translate(super.pos.x,super.pos.y);
switch(mode){ switch(super.mode){
case CORNER: digit.setRefPos(dim.x/2 - 4,dim.y - 2); case CORNER: digit.setRefPos(super.dim.x/2 - 4, super.dim.y - 2);
} }
digit.display(); digit.display();

View File

@@ -11,7 +11,8 @@
Includes method relay code be Quark - see https://forum.processing.org/two/discussion/13093/how-to-call-function-by-string-content.html Includes method relay code be Quark - see https://forum.processing.org/two/discussion/13093/how-to-call-function-by-string-content.html
for more details. for more details.
// TODO redo mouse handling -- in progress // TODO redo position data handling
// WORKING redo mouse handling
// TODO add cursor and dynamic position for MathDisplay (Maybe add a "highlighted" attribute to B12Digit?) might need some restructuring // TODO add cursor and dynamic position for MathDisplay (Maybe add a "highlighted" attribute to B12Digit?) might need some restructuring
// TODO add parsing expression to operable math string (tricky to get base 12 to base 10) // TODO add parsing expression to operable math string (tricky to get base 12 to base 10)
// TODO add operator and action buttons to MathPad // TODO add operator and action buttons to MathPad
@@ -20,7 +21,10 @@
// MAYBE add additional operations like power, log, and trig functions // MAYBE add additional operations like power, log, and trig functions
changelog 0.1.5.2 changelog 0.1.5.2
- major changes to mouse handling - major changes to mouse handling, and MethodRelay now
uses weak references rather than strong references so
that there will no longer be the possibility of dangling
objects. This allows gc to collect dead buttons, Yay!
changelog 0.1.5.0 changelog 0.1.5.0
- Quite a few changes by this point. The readme has been - Quite a few changes by this point. The readme has been