diff --git a/diylc/diylc-core/src/org/diylc/presenter/update.xml b/diylc/diylc-core/src/org/diylc/presenter/update.xml
index 9a2ef701..f6e45d5b 100644
--- a/diylc/diylc-core/src/org/diylc/presenter/update.xml
+++ b/diylc/diylc-core/src/org/diylc/presenter/update.xml
@@ -3269,5 +3269,25 @@
https://github.com/bancika/diy-layout-creator/releases
+
+
+ 4
+ 12
+ 0
+
+ 2020-11-19 00:00:00.000 CET
+
+
+
+ NEW_FEATURE
+ macOS: added pinch zooming functionality
+
+
+ IMPROVEMENT
+ macOS: added meta +/- (minus and equal keys) keyboard shortcuts for zooming
+
+
+ https://github.com/bancika/diy-layout-creator/releases
+
diff --git a/diylc/diylc-swing/.classpath b/diylc/diylc-swing/.classpath
index 8159a3ea..c9ca94d3 100644
--- a/diylc/diylc-swing/.classpath
+++ b/diylc/diylc-swing/.classpath
@@ -15,6 +15,7 @@
+
diff --git a/diylc/diylc-swing/build.xml b/diylc/diylc-swing/build.xml
index 6fefedc7..52338685 100644
--- a/diylc/diylc-swing/build.xml
+++ b/diylc/diylc-swing/build.xml
@@ -10,7 +10,7 @@
-
+
diff --git a/diylc/diylc-swing/lib/diylc-core.jar b/diylc/diylc-swing/lib/diylc-core.jar
index b9185f38..459b2fbf 100644
Binary files a/diylc/diylc-swing/lib/diylc-core.jar and b/diylc/diylc-swing/lib/diylc-core.jar differ
diff --git a/diylc/diylc-swing/lib/gestures-wrapper-0.2.jar b/diylc/diylc-swing/lib/gestures-wrapper-0.2.jar
new file mode 100644
index 00000000..d72ddc8a
Binary files /dev/null and b/diylc/diylc-swing/lib/gestures-wrapper-0.2.jar differ
diff --git a/diylc/diylc-swing/src/org/diylc/swing/plugins/canvas/CanvasGestureListener.java b/diylc/diylc-swing/src/org/diylc/swing/plugins/canvas/CanvasDragGestureListener.java
similarity index 87%
rename from diylc/diylc-swing/src/org/diylc/swing/plugins/canvas/CanvasGestureListener.java
rename to diylc/diylc-swing/src/org/diylc/swing/plugins/canvas/CanvasDragGestureListener.java
index 5906bcb7..409d6248 100644
--- a/diylc/diylc-swing/src/org/diylc/swing/plugins/canvas/CanvasGestureListener.java
+++ b/diylc/diylc-swing/src/org/diylc/swing/plugins/canvas/CanvasDragGestureListener.java
@@ -29,15 +29,15 @@ import java.awt.event.MouseEvent;
import org.diylc.common.IPlugInPort;
/**
- * {@link DragGestureListener} for {@link CanvasPanel}.
+ * {@link DragGestureListener} implementation for {@link CanvasPanel}.
*
* @author Branislav Stojkovic
*/
-class CanvasGestureListener implements DragGestureListener {
+class CanvasDragGestureListener implements DragGestureListener {
private IPlugInPort presenter;
- public CanvasGestureListener(IPlugInPort presenter) {
+ public CanvasDragGestureListener(IPlugInPort presenter) {
super();
this.presenter = presenter;
}
diff --git a/diylc/diylc-swing/src/org/diylc/swing/plugins/canvas/CanvasPanel.java b/diylc/diylc-swing/src/org/diylc/swing/plugins/canvas/CanvasPanel.java
index a1c4166d..2417e0eb 100644
--- a/diylc/diylc-swing/src/org/diylc/swing/plugins/canvas/CanvasPanel.java
+++ b/diylc/diylc-swing/src/org/diylc/swing/plugins/canvas/CanvasPanel.java
@@ -124,7 +124,7 @@ public class CanvasPanel extends JComponent implements Autoscroll {
// Initialize drag source recognizer.
DragSource.getDefaultDragSource().createDefaultDragGestureRecognizer(this,
DnDConstants.ACTION_COPY_OR_MOVE | DnDConstants.ACTION_LINK,
- new CanvasGestureListener(plugInPort));
+ new CanvasDragGestureListener(plugInPort));
// Initialize drop target.
new DropTarget(this, DnDConstants.ACTION_COPY_OR_MOVE, new CanvasTargetListener(plugInPort),
true);
@@ -143,8 +143,12 @@ public class CanvasPanel extends JComponent implements Autoscroll {
.put(KeyStroke.getKeyStroke(KeyEvent.VK_SUBTRACT, KeyEvent.CTRL_DOWN_MASK), "zoomOut");
getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
.put(KeyStroke.getKeyStroke(KeyEvent.VK_ADD, KeyEvent.META_DOWN_MASK), "zoomIn");
+ getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
+ .put(KeyStroke.getKeyStroke(KeyEvent.VK_EQUALS, KeyEvent.META_DOWN_MASK), "zoomIn");
getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
.put(KeyStroke.getKeyStroke(KeyEvent.VK_SUBTRACT, KeyEvent.META_DOWN_MASK), "zoomOut");
+ getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
+ .put(KeyStroke.getKeyStroke(KeyEvent.VK_MINUS, KeyEvent.META_DOWN_MASK), "zoomOut");
getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
.put(KeyStroke.getKeyStroke(KeyEvent.VK_0, KeyEvent.CTRL_DOWN_MASK), "resetZoom");
getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
@@ -169,35 +173,35 @@ public class CanvasPanel extends JComponent implements Autoscroll {
});
}
- getActionMap().put("zoomIn", new AbstractAction() {
-
- private static final long serialVersionUID = 1L;
-
- @Override
- public void actionPerformed(ActionEvent e) {
- LOG.debug("Keyboard zoom-in triggered");
- double oldZoom = CanvasPanel.this.plugInPort.getZoomLevel();
- Double[] availableZoomLevels = CanvasPanel.this.plugInPort.getAvailableZoomLevels();
- int index = Arrays.binarySearch(availableZoomLevels, oldZoom);
- if (index < availableZoomLevels.length - 1)
- CanvasPanel.this.plugInPort.setZoomLevel(availableZoomLevels[index + 1]);
- }
- });
-
- getActionMap().put("zoomOut", new AbstractAction() {
-
- private static final long serialVersionUID = 1L;
-
- @Override
- public void actionPerformed(ActionEvent e) {
- LOG.debug("Keyboard zoom-out triggered");
- double oldZoom = CanvasPanel.this.plugInPort.getZoomLevel();
- Double[] availableZoomLevels = CanvasPanel.this.plugInPort.getAvailableZoomLevels();
- int index = Arrays.binarySearch(availableZoomLevels, oldZoom);
- if (index > 0)
- CanvasPanel.this.plugInPort.setZoomLevel(availableZoomLevels[index - 1]);
- }
- });
+// getActionMap().put("zoomIn", new AbstractAction() {
+//
+// private static final long serialVersionUID = 1L;
+//
+// @Override
+// public void actionPerformed(ActionEvent e) {
+// LOG.debug("Keyboard zoom-in triggered");
+// double oldZoom = CanvasPanel.this.plugInPort.getZoomLevel();
+// Double[] availableZoomLevels = CanvasPanel.this.plugInPort.getAvailableZoomLevels();
+// int index = Arrays.binarySearch(availableZoomLevels, oldZoom);
+// if (index < availableZoomLevels.length - 1)
+// CanvasPanel.this.plugInPort.setZoomLevel(availableZoomLevels[index + 1]);
+// }
+// });
+//
+// getActionMap().put("zoomOut", new AbstractAction() {
+//
+// private static final long serialVersionUID = 1L;
+//
+// @Override
+// public void actionPerformed(ActionEvent e) {
+// LOG.debug("Keyboard zoom-out triggered");
+// double oldZoom = CanvasPanel.this.plugInPort.getZoomLevel();
+// Double[] availableZoomLevels = CanvasPanel.this.plugInPort.getAvailableZoomLevels();
+// int index = Arrays.binarySearch(availableZoomLevels, oldZoom);
+// if (index > 0)
+// CanvasPanel.this.plugInPort.setZoomLevel(availableZoomLevels[index - 1]);
+// }
+// });
getActionMap().put("resetZoom", new AbstractAction() {
diff --git a/diylc/diylc-swing/src/org/diylc/swing/plugins/canvas/CanvasPlugin.java b/diylc/diylc-swing/src/org/diylc/swing/plugins/canvas/CanvasPlugin.java
index 7de953d8..e6a08e6d 100644
--- a/diylc/diylc-swing/src/org/diylc/swing/plugins/canvas/CanvasPlugin.java
+++ b/diylc/diylc-swing/src/org/diylc/swing/plugins/canvas/CanvasPlugin.java
@@ -61,19 +61,24 @@ import org.diylc.common.IPlugInPort;
import org.diylc.core.ExpansionMode;
import org.diylc.core.IDIYComponent;
import org.diylc.core.Template;
-import org.diylc.swing.images.IconLoader;
import org.diylc.core.measures.Size;
import org.diylc.core.measures.SizeUnit;
import org.diylc.swing.ActionFactory;
import org.diylc.swing.ISwingUI;
import org.diylc.swing.gui.TranslatedMenu;
import org.diylc.swing.gui.TranslatedPopupMenu;
+import org.diylc.swing.images.IconLoader;
import org.diylc.swing.plugins.edit.ComponentTransferable;
import org.diylc.swing.plugins.file.ProjectDrawingProvider;
import org.diylc.swingframework.ruler.IRulerListener;
import org.diylc.swingframework.ruler.Ruler.InchSubdivision;
import org.diylc.swingframework.ruler.RulerScrollPane;
+import com.guigarage.gestures.GestureMagnificationEvent;
+import com.guigarage.gestures.GestureMagnificationListener;
+import com.guigarage.gestures.GestureUtilities;
+import com.guigarage.gestures.GesturesNotSupportedException;
+
public class CanvasPlugin implements IPlugIn, ClipboardOwner {
private static final Logger LOG = Logger.getLogger(CanvasPlugin.class);
@@ -343,6 +348,55 @@ public class CanvasPlugin implements IPlugIn, ClipboardOwner {
e.isShiftDown(), e.isAltDown());
}
});
+
+ canvasPanel.getActionMap().put("zoomIn", new AbstractAction() {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ LOG.debug("Keyboard zoom-in triggered");
+ zoom(-1);
+ }
+ });
+
+ canvasPanel.getActionMap().put("zoomOut", new AbstractAction() {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ LOG.debug("Keyboard zoom-out triggered");
+ zoom(1);
+ }
+ });
+
+ if (!GestureUtilities.isSupported()) {
+ LOG.info("Gestures are not supported, skipping initialization");
+ }
+ try {
+ GestureUtilities.registerListener(canvasPanel, new GestureMagnificationListener() {
+
+ private long prevEventTime = 0;
+ private static final int DELAY = 100;
+
+ @Override
+ public void magnify(GestureMagnificationEvent e) {
+ if (System.currentTimeMillis() - this.prevEventTime < DELAY)
+ return;
+
+ if (e.getMagnification() > 0)
+ CanvasPlugin.this.zoom(-1);
+ else if (e.getMagnification() < 0)
+ CanvasPlugin.this.zoom(1);
+
+ prevEventTime = System.currentTimeMillis();
+ }
+ });
+ LOG.info("Magnification gesture listener initialized.");
+ } catch (GesturesNotSupportedException e) {
+ LOG.error("Error registering gesture listener", e);
+ }
}
return canvasPanel;
}
@@ -390,48 +444,7 @@ public class CanvasPlugin implements IPlugIn, ClipboardOwner {
configManager.readBoolean(IPlugInPort.WHEEL_ZOOM_KEY, false);
if (wheelZoom || (Utils.isMac() ? e.isMetaDown() : e.isControlDown())) {
-
- Point mousePos = getCanvasPanel().getMousePosition(true);
-
- // change zoom level
- double oldZoom = plugInPort.getZoomLevel();
- double newZoom;
- Double[] availableZoomLevels = plugInPort.getAvailableZoomLevels();
- if (e.getWheelRotation() > 0) {
- int i = availableZoomLevels.length - 1;
- while (i > 0 && availableZoomLevels[i] >= oldZoom) {
- i--;
- }
- plugInPort.setZoomLevel(newZoom = availableZoomLevels[i]);
- } else {
- int i = 0;
- while (i < availableZoomLevels.length - 1 && availableZoomLevels[i] <= oldZoom) {
- i++;
- }
- plugInPort.setZoomLevel(newZoom = availableZoomLevels[i]);
- }
-
- Rectangle2D selectionBounds = plugInPort.getSelectionBounds(true);
- Rectangle visibleRect = scrollPane.getVisibleRect();
-
- JScrollBar horizontal = scrollPane.getHorizontalScrollBar();
- JScrollBar vertical = scrollPane.getVerticalScrollBar();
-
- if (selectionBounds == null) {
- // center to cursor
- Point desiredPos = new Point((int) (1d * mousePos.x / oldZoom * newZoom),
- (int) (1d * mousePos.y / oldZoom * newZoom));
- int dx = desiredPos.x - mousePos.x;
- int dy = desiredPos.y - mousePos.y;
- horizontal.setValue(horizontal.getValue() + dx);
- vertical.setValue(vertical.getValue() + dy);
- } else {
- // center to selection
- horizontal.setValue((int) (selectionBounds.getX() + selectionBounds.getWidth() / 2
- - visibleRect.getWidth() / 2));
- vertical.setValue((int) (selectionBounds.getY() + selectionBounds.getHeight() / 2
- - visibleRect.getHeight() / 2));
- }
+ CanvasPlugin.this.zoom(e.getWheelRotation());
}
if (e.isShiftDown()) {
int iScrollAmount = e.getScrollAmount();
@@ -451,6 +464,50 @@ public class CanvasPlugin implements IPlugIn, ClipboardOwner {
}
return scrollPane;
}
+
+ public void zoom(int direction) {
+ Point mousePos = canvasPanel.getMousePosition(true);
+
+ // change zoom level
+ double oldZoom = plugInPort.getZoomLevel();
+ double newZoom;
+ Double[] availableZoomLevels = plugInPort.getAvailableZoomLevels();
+ if (direction > 0) {
+ int i = availableZoomLevels.length - 1;
+ while (i > 0 && availableZoomLevels[i] >= oldZoom) {
+ i--;
+ }
+ plugInPort.setZoomLevel(newZoom = availableZoomLevels[i]);
+ } else {
+ int i = 0;
+ while (i < availableZoomLevels.length - 1 && availableZoomLevels[i] <= oldZoom) {
+ i++;
+ }
+ plugInPort.setZoomLevel(newZoom = availableZoomLevels[i]);
+ }
+
+ Rectangle2D selectionBounds = plugInPort.getSelectionBounds(true);
+ Rectangle visibleRect = scrollPane.getVisibleRect();
+
+ JScrollBar horizontal = scrollPane.getHorizontalScrollBar();
+ JScrollBar vertical = scrollPane.getVerticalScrollBar();
+
+ if (selectionBounds == null) {
+ // center to cursor
+ Point desiredPos = new Point((int) (1d * mousePos.x / oldZoom * newZoom),
+ (int) (1d * mousePos.y / oldZoom * newZoom));
+ int dx = desiredPos.x - mousePos.x;
+ int dy = desiredPos.y - mousePos.y;
+ horizontal.setValue(horizontal.getValue() + dx);
+ vertical.setValue(vertical.getValue() + dy);
+ } else {
+ // center to selection
+ horizontal.setValue((int) (selectionBounds.getX() + selectionBounds.getWidth() / 2
+ - visibleRect.getWidth() / 2));
+ vertical.setValue((int) (selectionBounds.getY() + selectionBounds.getHeight() / 2
+ - visibleRect.getHeight() / 2));
+ }
+ }
private void showPopupAt(int x, int y) {
updateSelectionMenu(x, y);