Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mac: Add support for zooming map via touchpad pinch. #12002

Merged
merged 3 commits into from
Sep 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .idea/runConfigurations/HeadedGameRunner.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import org.triplea.swing.gestures.Gestures;

/**
* A large image that can be scrolled according to a ImageScrollModel. Generally used in conjunction
Expand Down Expand Up @@ -96,14 +97,8 @@ public ImageScrollerLargeView(final Dimension dimension, final ImageScrollModel
final MouseWheelListener mouseWheelListener =
e -> {
if (e.isControlDown()) {
final int oldWidth = model.getBoxWidth();
final int oldHeight = model.getBoxHeight();
final float zoomFactor = ClientSetting.mapZoomFactor.getValueOrThrow() / 100f;
setScale(scale - zoomFactor * e.getPreciseWheelRotation());
final Point mouse = getMousePosition();
final int dx = (int) (mouse.getX() / getWidth() * (oldWidth - model.getBoxWidth()));
final int dy = (int) (mouse.getY() / getHeight() * (oldHeight - model.getBoxHeight()));
model.set(model.getX() + dx, model.getY() + dy);
setScaleViaMouseZoom(scale - zoomFactor * e.getPreciseWheelRotation());
} else {
if (edge == NONE) {
insideCount = 0;
Expand Down Expand Up @@ -223,6 +218,8 @@ public void componentResized(final ComponentEvent e) {
repaint();
notifyScollListeners();
});
Gestures.registerMagnificationListener(
this, (double factor) -> setScaleViaMouseZoom(scale * factor));
}

public boolean wasLastActionDraggingAndReset() {
Expand Down Expand Up @@ -309,6 +306,16 @@ public void setScale(final double value) {
refreshBoxSize();
}

private void setScaleViaMouseZoom(double newScale) {
final int oldWidth = model.getBoxWidth();
final int oldHeight = model.getBoxHeight();
setScale(newScale);
final Point mouse = getMousePosition();
final int dx = (int) (mouse.getX() / getWidth() * (oldWidth - model.getBoxWidth()));
final int dy = (int) (mouse.getY() / getHeight() * (oldHeight - model.getBoxHeight()));
model.set(model.getX() + dx, model.getY() + dy);
}

public double getMinScale() {
final double minScale =
scale
Expand Down
1 change: 1 addition & 0 deletions game-app/game-headed/build.install4j
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,7 @@ return Math.min(is32BitJavaRuntime ? 1024L : 2048L, halfMemoryMiB);</property>
<element index="0">-Xmx${installer:heapSizeMiB}M</element>
<element index="1">-Xms${installer:heapSizeMiB}M</element>
<element index="2">-Xss1250K</element>
<element index="3">--add-opens java.desktop/com.apple.eawt.event=ALL-UNNAMED</element>
</property>
</serializedBean>
</action>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package org.triplea.swing.gestures;

import games.strategy.engine.framework.system.SystemProperties;
import java.lang.reflect.Proxy;
import javax.swing.JComponent;

/**
* Provides support for platform-specific gestures. Currently, supports only the magnification
* gestures on Mac (e.g. pinch to zoom using the trackpad).
*
* <p>Since there is no cross-platform API in Swing for this, it relies on Mac-specific
* com.apple.eawt classes for the support, which are loaded via reflection in order for the code to
* compile on all platforms.
*
* <p>This implementation is based on the following sources:
* https://stackoverflow.com/questions/69221217/multi-touch-gestures-in-java-swing-awt-and-java-17
* https://gist.github.com/alanwhite/42502f20390baf879d093691ebb72066
*
* <p>Note: This functionality requires passing the following args to java when running the app:
* --add-opens java.desktop/com.apple.eawt.event=ALL-UNNAMED
*/
public class Gestures {
@SuppressWarnings({"rawtypes"})
public static void registerMagnificationListener(JComponent c, MagnificationListener listener) {
// The current implementation only supports Mac.
if (!SystemProperties.isMac()) {
return;
}
// Wrapped in a try, as this may fail if the specific classes or their methods are not found.
try {
Class listenerClass = Class.forName("com.apple.eawt.event.MagnificationListener");
Object listenerProxy =
Proxy.newProxyInstance(
listenerClass.getClassLoader(),
new Class[] {listenerClass},
(proxy, method, args) -> {
if (method.getName().equals("magnify")) {
try {
Object mag = args[0].getClass().getMethod("getMagnification").invoke(args[0]);
listener.magnify(1 + (double) mag);
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
});

Class.forName("com.apple.eawt.event.GestureUtilities")
.getMethod(
"addGestureListenerTo",
Class.forName("javax.swing.JComponent"),
Class.forName("com.apple.eawt.event.GestureListener"))
.invoke(null, c, listenerProxy);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package org.triplea.swing.gestures;

/** Listener for magnification events (e.g. pinch gesture with a trackpad). */
public interface MagnificationListener {
/**
* Called when a magnification event occurred.
*
* @param factor The magnification multiplier to apply over the current zoom level (e.g. 1 = no
* change, 2 = double the zoom, etc).
*/
void magnify(double factor);
}