From c92e6ba345ff71bc8c4c88f7f41503053a07494f Mon Sep 17 00:00:00 2001 From: 61616 Date: Fri, 6 May 2022 17:55:37 -0400 Subject: [PATCH] Mouse handling changes Method relay now uses weak references rather than strong references. This gets rid of the dangling button memory leak --- B12NumbersV3/ActionCodeAll.pde | 18 ++++++++++++------ B12NumbersV3/B12NumbersV3.pde | 25 ++++++++++++++++++------- B12NumbersV3/guiButton.pde | 32 +++++++++++++++++++++----------- B12NumbersV3/guiMathPad.pde | 6 +++--- B12NumbersV3/zchangelog.pde | 8 ++++++-- 5 files changed, 60 insertions(+), 29 deletions(-) diff --git a/B12NumbersV3/ActionCodeAll.pde b/B12NumbersV3/ActionCodeAll.pde index 91a5142..41757fc 100644 --- a/B12NumbersV3/ActionCodeAll.pde +++ b/B12NumbersV3/ActionCodeAll.pde @@ -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"); diff --git a/B12NumbersV3/B12NumbersV3.pde b/B12NumbersV3/B12NumbersV3.pde index 0abb95f..94e2f9a 100644 --- a/B12NumbersV3/B12NumbersV3.pde +++ b/B12NumbersV3/B12NumbersV3.pde @@ -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(); +} diff --git a/B12NumbersV3/guiButton.pde b/B12NumbersV3/guiButton.pde index fadd91b..7825b98 100644 --- a/B12NumbersV3/guiButton.pde +++ b/B12NumbersV3/guiButton.pde @@ -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(); + } } diff --git a/B12NumbersV3/guiMathPad.pde b/B12NumbersV3/guiMathPad.pde index 625e3b4..44f1bd3 100644 --- a/B12NumbersV3/guiMathPad.pde +++ b/B12NumbersV3/guiMathPad.pde @@ -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(); diff --git a/B12NumbersV3/zchangelog.pde b/B12NumbersV3/zchangelog.pde index 00ec12e..1fd6368 100644 --- a/B12NumbersV3/zchangelog.pde +++ b/B12NumbersV3/zchangelog.pde @@ -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