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 {
MouseData md;
private MouseData md;
private LiveMethodRelay[] mrs;
MouseHandler(MouseData _md) {
@@ -7,11 +7,13 @@ class MouseHandler {
mrs = new LiveMethodRelay[0];
}
// PASSTHROUGH FOR MOUSE DATA //
float sMouseX(){return md.sMouseX();}
float sMouseY(){return md.sMouseY();}
float pSMouseX(){return md.pSMouseX();}
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) {
clean();
@@ -30,6 +32,7 @@ class MouseHandler {
}
void cascade(char tag, float... data) {
clean();
for (int i = 0; i < mrs.length; i++) {
if(mrs[i].getTag() == tag){
mrs[i].execute(data);
@@ -97,15 +100,18 @@ class LiveMethodRelay extends MethodRelay {
import java.lang.reflect.*;
import java.lang.ref.*;
/**
A class that encapsulates a named method to be invoked.
Quark 2015
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 {
/** 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 */
private Method handlerMethod = null;
/** the name of the method to handle the event */
@@ -125,7 +131,7 @@ public static class MethodRelay {
handlerMethodName = name;
parameters = args;
handlerMethod = obj.getClass().getMethod(handlerMethodName, parameters);
handlerObject = obj;
reference = new WeakReference(obj);
}
catch (Exception e) {
println("Unable to find the function -");
@@ -160,9 +166,9 @@ public static class MethodRelay {
to be passed to the method
*/
void execute(Object... data) {
if (handlerObject != null) {
if (reference.get() != null) {
try {
handlerMethod.invoke(handlerObject, data);
handlerMethod.invoke(reference.get(), data);
}
catch (Exception e) {
println("Error on invoke");

View File

@@ -3,15 +3,16 @@ float scale = 2;
PVector offset;
public static final int DECIMAL = 65;
MouseHandler mh; // Mouse event handler
//MouseData md;
Calculator calc;
Button b;
void setup(){
size(400,400);
offset = new PVector(width/2, height/2);
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);
@@ -23,7 +24,8 @@ void draw(){
translate(offset.x,offset.y);
scale(scale);
calc.display();
if(calc != null) calc.display();
b.display();
}
void mouseClicked(){
@@ -31,11 +33,20 @@ void mouseClicked(){
mh.cascade('c', mh.sMouseX(), mh.sMouseY(), mouseButton);
}
void mouseMoved(){mh.cascade('m', mh.sMouseX(), mh.sMouseY());}
void mousePressed(){mh.cascade('m', mh.sMouseX(), mh.sMouseY(), mouseButton);}
void mouseReleased(){mh.cascade('m', mh.sMouseX(), mh.sMouseY(), mouseButton);}
void mouseWheel(MouseEvent event){mh.cascade('m', mh.sMouseX(), mh.sMouseY(), event.getCount());}
void mouseDragged(){mh.cascade('m', mh.sMouseX(), mh.sMouseY(), mouseButton);}
void mousePressed(){mh.cascade('p', mh.sMouseX(), mh.sMouseY(), mouseButton);}
void mouseReleased(){mh.cascade('r', mh.sMouseX(), mh.sMouseY(), mouseButton);}
void mouseWheel(MouseEvent event){mh.cascade('w', mh.sMouseX(), mh.sMouseY(), event.getCount());}
void mouseDragged(){mh.cascade('d', mh.sMouseX(), mh.sMouseY(), mouseButton);}
void call(String _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
MouseHandler mh;
PVector pos; // Position to render from
PVector dim; // Second coordinate for CORNERS or len/wid for CORNER and CENTER
float radius; // Optional corner radius
int mode; // Stores rect draw mode for button
color col; // Stores static color
color highlight; // Stores mouseover color
MethodRelay function; // Gets called when button is pressed
boolean mouseOver;
Object[] data; // Anything that gets passed to MethodRelay function when key pressed. Must be set manually
private LiveMethodRelay listener;
private MouseHandler mh;
private PVector pos; // Position to render from
private PVector dim; // Second coordinate for CORNERS or len/wid for CORNER and CENTER
private float radius; // Optional corner radius
private int mode; // Stores rect draw mode for button
private color col; // Stores static color
private color highlight; // Stores mouseover color
private MethodRelay function; // Gets called when button is pressed
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){
mh = _mh;
@@ -19,7 +20,8 @@ class Button{ // TODO make most of the attributes private
col = color(200);
highlight = color(100);
mouseOver = false;
mh.addRelay(new LiveMethodRelay(this, "clicked", 'c', Object.class));
listener = new LiveMethodRelay(this, "clicked", 'p', Object.class);
mh.addRelay(listener);
data = null;
}
Button(MouseHandler _mh, PVector _pos, PVector _dim){
@@ -121,4 +123,12 @@ class Button{ // TODO make most of the attributes private
}
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();
translate(pos.x,pos.y);
switch(mode){
case CORNER: digit.setRefPos(dim.x/2 - 4,dim.y - 2);
translate(super.pos.x,super.pos.y);
switch(super.mode){
case CORNER: digit.setRefPos(super.dim.x/2 - 4, super.dim.y - 2);
}
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
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 parsing expression to operable math string (tricky to get base 12 to base 10)
// TODO add operator and action buttons to MathPad
@@ -20,7 +21,10 @@
// MAYBE add additional operations like power, log, and trig functions
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
- Quite a few changes by this point. The readme has been