Skip to content

Commit

Permalink
Reset MouseHandler upon refreshing (#47)
Browse files Browse the repository at this point in the history
* fix(framework): MouseHandler hack
* feat(framework): Make reflection elements static and use log instead of exception
* refactor(framework): Move hack into util class

---------

Co-authored-by: Adrian Kunz <[email protected]>
  • Loading branch information
LeStegii and Clashsoft authored Feb 23, 2024
1 parent 692356f commit 4396f76
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 5 deletions.
4 changes: 3 additions & 1 deletion framework/src/main/java/org/fulib/fx/FulibFxApp.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import org.fulib.fx.dagger.DaggerFrameworkComponent;
import org.fulib.fx.dagger.FrameworkComponent;
import org.fulib.fx.util.ControllerUtil;
import org.fulib.fx.util.ReflectionUtil;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.MustBeInvokedByOverriders;
import org.jetbrains.annotations.NotNull;
Expand Down Expand Up @@ -324,7 +325,8 @@ public void refresh() {
Map<String, Object> params = this.component.router().current().getValue(); // Use the same parameters as before
this.component.controllerManager().init(currentMainController, params, true); // Re-initialize the controller
Parent parent = this.component.controllerManager().render(currentMainController, params); // Re-render the controller
display(parent); // Display the controller
ReflectionUtil.resetMouseHandler(stage());
display(parent);
}

/**
Expand Down
42 changes: 38 additions & 4 deletions framework/src/main/java/org/fulib/fx/util/ReflectionUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,40 @@
import javafx.collections.ObservableList;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import org.fulib.fx.FulibFxApp;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.inject.Provider;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.*;

/**
* Utility class containing different helper methods for the framework or the user.
* Parts of this class are hacky and should be used with caution.
*/
public class ReflectionUtil {

private ReflectionUtil() {
// Prevent instantiation
}

// Reflection for mouse handler
private static Field mouseHandlerField;
private static Constructor<?> mouseHandlerCtor;

static {
try {
mouseHandlerField = Scene.class.getDeclaredField("mouseHandler");
mouseHandlerCtor = Class.forName(Scene.class.getName() + "$MouseHandler").getDeclaredConstructor(Scene.class);
mouseHandlerField.setAccessible(true);
mouseHandlerCtor.setAccessible(true);
} catch (ReflectiveOperationException e) {
FulibFxApp.LOGGER.severe("Could not initialize mouse handler reflection. This may cause problems with mouse drag events.");
}
}

/**
* Returns the class provided by the given provider field.
*
Expand Down Expand Up @@ -86,4 +102,22 @@ public static Object getInstanceOfProviderField(Field provider, Object instance)
}
}

/**
* Resets the mouse handler of the given stage. This method is used to reset the mouse handler of a scene to avoid
* problems with mouse drag events. This should be used with caution and is mainly used for refreshing the scene.
*
* @param stage The stage to reset the mouse handler for
*/
public static void resetMouseHandler(Stage stage) {
// NB: This hack avoids problems with mouse drag events.
// In particular, the scene's MouseHandler would keep a list of its previous nodes,
// which do not have a reference back to the scene and subsequently cause an NPE.
try {
final Scene scene = stage.getScene();
final Object mouseHandler = mouseHandlerCtor.newInstance(scene);
mouseHandlerField.set(scene, mouseHandler);
} catch (ReflectiveOperationException e) {
FulibFxApp.LOGGER.warning("Could not reset mouse handler. This may cause problems with mouse drag events after refreshing the scene.");
}
}
}

0 comments on commit 4396f76

Please sign in to comment.