8291805: IGV: Improve Zooming

Reviewed-by: rcastanedalo, lujaniuk, chagedorn
This commit is contained in:
Tobias Holenstein 2022-09-28 14:31:22 +00:00
parent 37f83b9b8e
commit 30e3bf9da0
14 changed files with 941 additions and 545 deletions

View File

@ -1,182 +0,0 @@
/*
* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
package com.sun.hotspot.igv.util;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Rectangle;
import javax.swing.JComponent;
import javax.swing.JScrollPane;
import org.netbeans.api.visual.action.WidgetAction;
import org.netbeans.api.visual.action.WidgetAction.State;
import org.netbeans.api.visual.action.WidgetAction.WidgetMouseWheelEvent;
import org.netbeans.api.visual.animator.SceneAnimator;
import org.netbeans.api.visual.widget.Scene;
import org.netbeans.api.visual.widget.Widget;
/**
*
* @author Thomas Wuerthinger
*/
public class BoundedZoomAction extends WidgetAction.Adapter {
private double minFactor = 0.0;
private double maxFactor = Double.MAX_VALUE;
private double zoomMultiplier;
private boolean useAnimator;
public BoundedZoomAction(double zoomMultiplier, boolean useAnimator) {
this.zoomMultiplier = zoomMultiplier;
this.useAnimator = useAnimator;
}
public double getMinFactor() {
return minFactor;
}
public void setMinFactor(double d) {
minFactor = d;
}
public double getMaxFactor() {
return maxFactor;
}
public void setMaxFactor(double d) {
maxFactor = d;
}
private JScrollPane findScrollPane(JComponent component) {
for (;;) {
if (component == null) {
return null;
}
if (component instanceof JScrollPane) {
return ((JScrollPane) component);
}
Container parent = component.getParent();
if (!(parent instanceof JComponent)) {
return null;
}
component = (JComponent) parent;
}
}
@Override
public State mouseWheelMoved(Widget widget, WidgetMouseWheelEvent event) {
final Scene scene = widget.getScene();
int amount = event.getWheelRotation();
JScrollPane scrollPane = findScrollPane(scene.getView());
Point viewPosition = null;
Point mouseLocation = scene.convertSceneToView(event.getPoint());
int xOffset = 0;
int yOffset = 0;
Point oldViewPosition = null;
Rectangle bounds = new Rectangle(scene.getBounds());
Dimension componentSize = new Dimension(scene.getView().getPreferredSize());
if (scrollPane != null) {
viewPosition = new Point(scrollPane.getViewport().getViewPosition());
oldViewPosition = new Point(viewPosition);
xOffset = (mouseLocation.x - viewPosition.x);
yOffset = (mouseLocation.y - viewPosition.y);
viewPosition.x += xOffset;
viewPosition.y += yOffset;
}
if (useAnimator) {
SceneAnimator sceneAnimator = scene.getSceneAnimator();
synchronized (sceneAnimator) {
double zoom = sceneAnimator.isAnimatingZoomFactor() ? sceneAnimator.getTargetZoomFactor() : scene.getZoomFactor();
while (amount > 0 && zoom / zoomMultiplier >= minFactor && zoom / zoomMultiplier <= maxFactor) {
zoom /= zoomMultiplier;
if (viewPosition != null) {
viewPosition.x /= zoomMultiplier;
viewPosition.y /= zoomMultiplier;
bounds.width /= zoomMultiplier;
bounds.height /= zoomMultiplier;
componentSize.width /= zoomMultiplier;
componentSize.height /= zoomMultiplier;
}
amount--;
}
while (amount < 0 && zoom * zoomMultiplier >= minFactor && zoom * zoomMultiplier <= maxFactor) {
zoom *= zoomMultiplier;
if (viewPosition != null) {
viewPosition.x *= zoomMultiplier;
viewPosition.y *= zoomMultiplier;
bounds.width *= zoomMultiplier;
bounds.height *= zoomMultiplier;
componentSize.width *= zoomMultiplier;
componentSize.height *= zoomMultiplier;
}
amount++;
}
sceneAnimator.animateZoomFactor(zoom);
}
} else {
double zoom = scene.getZoomFactor();
while (amount > 0 && zoom / zoomMultiplier >= minFactor && zoom / zoomMultiplier <= maxFactor) {
zoom /= zoomMultiplier;
if (viewPosition != null) {
viewPosition.x /= zoomMultiplier;
viewPosition.y /= zoomMultiplier;
bounds.width /= zoomMultiplier;
bounds.height /= zoomMultiplier;
componentSize.width /= zoomMultiplier;
componentSize.height /= zoomMultiplier;
}
amount--;
}
while (amount < 0 && zoom * zoomMultiplier >= minFactor && zoom * zoomMultiplier <= maxFactor) {
zoom *= zoomMultiplier;
if (viewPosition != null) {
viewPosition.x *= zoomMultiplier;
viewPosition.y *= zoomMultiplier;
bounds.width *= zoomMultiplier;
bounds.height *= zoomMultiplier;
componentSize.width *= zoomMultiplier;
componentSize.height *= zoomMultiplier;
}
amount++;
}
scene.setZoomFactor(zoom);
}
if (scrollPane != null) {
scene.validate(); // Call validate to update size of scene
Dimension size = scrollPane.getViewport().getExtentSize();
viewPosition.x -= xOffset;
viewPosition.y -= yOffset;
scene.resolveBounds(scene.getLocation(), bounds);
scene.getView().setPreferredSize(componentSize);
scene.getView().revalidate();
scene.getView().addNotify();
scrollPane.getViewport().setViewPosition(viewPosition);
}
return WidgetAction.State.CONSUMED;
}
}

View File

@ -1,175 +0,0 @@
/*
* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
package com.sun.hotspot.igv.view;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Rectangle;
import javax.swing.JComponent;
import javax.swing.JScrollPane;
import org.netbeans.api.visual.action.WidgetAction;
import org.netbeans.api.visual.action.WidgetAction.State;
import org.netbeans.api.visual.action.WidgetAction.WidgetMouseWheelEvent;
import org.netbeans.api.visual.animator.SceneAnimator;
import org.netbeans.api.visual.widget.Scene;
import org.netbeans.api.visual.widget.Widget;
/**
*
* @author Thomas Wuerthinger
*/
public class BoundedZoomAction extends WidgetAction.Adapter {
private double minFactor = 0.0;
private double maxFactor = Double.MAX_VALUE;
private double zoomMultiplier;
private boolean useAnimator;
public BoundedZoomAction(double zoomMultiplier, boolean useAnimator) {
assert zoomMultiplier > 1.0;
this.zoomMultiplier = zoomMultiplier;
this.useAnimator = useAnimator;
}
public double getMinFactor() {
return minFactor;
}
public void setMinFactor(double d) {
minFactor = d;
}
public double getMaxFactor() {
return maxFactor;
}
public void setMaxFactor(double d) {
maxFactor = d;
}
private JScrollPane findScrollPane(JComponent component) {
for (;;) {
if (component == null) {
return null;
}
if (component instanceof JScrollPane) {
return ((JScrollPane) component);
}
Container parent = component.getParent();
if (!(parent instanceof JComponent)) {
return null;
}
component = (JComponent) parent;
}
}
@Override
public State mouseWheelMoved(Widget widget, WidgetMouseWheelEvent event) {
final Scene scene = widget.getScene();
int amount = event.getWheelRotation();
JScrollPane scrollPane = findScrollPane(scene.getView());
Point viewPosition = null;
Point mouseLocation = scene.convertSceneToView(event.getPoint());
int xOffset = 0;
int yOffset = 0;
Rectangle bounds = new Rectangle(scene.getBounds());
Dimension componentSize = new Dimension(scene.getView().getPreferredSize());
if (scrollPane != null) {
viewPosition = new Point(scrollPane.getViewport().getViewPosition());
xOffset = (mouseLocation.x - viewPosition.x);
yOffset = (mouseLocation.y - viewPosition.y);
viewPosition.x += xOffset;
viewPosition.y += yOffset;
}
if (useAnimator) {
SceneAnimator sceneAnimator = scene.getSceneAnimator();
synchronized (sceneAnimator) {
double zoom = sceneAnimator.isAnimatingZoomFactor() ? sceneAnimator.getTargetZoomFactor() : scene.getZoomFactor();
while (amount > 0 && zoom / zoomMultiplier >= minFactor) {
zoom /= zoomMultiplier;
if (viewPosition != null) {
viewPosition.x /= zoomMultiplier;
viewPosition.y /= zoomMultiplier;
bounds.width /= zoomMultiplier;
bounds.height /= zoomMultiplier;
componentSize.width /= zoomMultiplier;
componentSize.height /= zoomMultiplier;
}
amount--;
}
while (amount < 0 && zoom * zoomMultiplier <= maxFactor) {
zoom *= zoomMultiplier;
if (viewPosition != null) {
viewPosition.x *= zoomMultiplier;
viewPosition.y *= zoomMultiplier;
bounds.width *= zoomMultiplier;
bounds.height *= zoomMultiplier;
componentSize.width *= zoomMultiplier;
componentSize.height *= zoomMultiplier;
}
amount++;
}
sceneAnimator.animateZoomFactor(zoom);
}
} else {
double zoom = scene.getZoomFactor();
while (amount > 0 && zoom / zoomMultiplier >= minFactor) {
zoom /= zoomMultiplier;
if (viewPosition != null) {
viewPosition.x /= zoomMultiplier;
viewPosition.y /= zoomMultiplier;
bounds.width /= zoomMultiplier;
bounds.height /= zoomMultiplier;
componentSize.width /= zoomMultiplier;
componentSize.height /= zoomMultiplier;
}
amount--;
}
while (amount < 0 && zoom * zoomMultiplier <= maxFactor) {
zoom *= zoomMultiplier;
if (viewPosition != null) {
viewPosition.x *= zoomMultiplier;
viewPosition.y *= zoomMultiplier;
bounds.width *= zoomMultiplier;
bounds.height *= zoomMultiplier;
componentSize.width *= zoomMultiplier;
componentSize.height *= zoomMultiplier;
}
amount++;
}
scene.setZoomFactor(zoom);
}
if (scrollPane != null) {
viewPosition.x -= xOffset;
viewPosition.y -= yOffset;
scrollPane.getViewport().setViewPosition(viewPosition);
}
return WidgetAction.State.CONSUMED;
}
}

View File

@ -37,14 +37,15 @@ import com.sun.hotspot.igv.util.DoubleClickAction;
import com.sun.hotspot.igv.util.PropertiesSheet;
import com.sun.hotspot.igv.view.actions.CustomSelectAction;
import com.sun.hotspot.igv.view.actions.CustomizablePanAction;
import com.sun.hotspot.igv.view.actions.MouseZoomAction;
import com.sun.hotspot.igv.view.widgets.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.*;
import java.util.List;
import java.util.*;
import javax.swing.*;
import static javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS;
import static javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS;
import javax.swing.event.UndoableEditEvent;
import javax.swing.undo.AbstractUndoableEdit;
import javax.swing.undo.CannotRedoException;
@ -60,7 +61,6 @@ import org.openide.nodes.AbstractNode;
import org.openide.nodes.Children;
import org.openide.nodes.Sheet;
import org.openide.util.Lookup;
import org.openide.util.Utilities;
import org.openide.util.lookup.AbstractLookup;
import org.openide.util.lookup.InstanceContent;
@ -82,8 +82,6 @@ public class DiagramScene extends ObjectScene implements DiagramViewer {
private UndoRedo.Manager undoRedoManager;
private LayerWidget mainLayer;
private LayerWidget blockLayer;
private Widget topLeft;
private Widget bottomRight;
private DiagramViewModel model;
private DiagramViewModel modelCopy;
private boolean rebuilding;
@ -96,14 +94,12 @@ public class DiagramScene extends ObjectScene implements DiagramViewer {
/**
* The offset of the graph to the border of the window showing it.
*/
public static final int BORDER_SIZE = 20;
public static final int BORDER_SIZE = 100;
public static final int UNDOREDO_LIMIT = 100;
public static final int SCROLL_UNIT_INCREMENT = 80;
public static final int SCROLL_BLOCK_INCREMENT = 400;
public static final float ZOOM_MAX_FACTOR = 3.0f;
public static final float ZOOM_MIN_FACTOR = 0.0f;//0.15f;
public static final float ZOOM_MAX_FACTOR = 4.0f;
public static final float ZOOM_MIN_FACTOR = 0.25f;
public static final float ZOOM_INCREMENT = 1.5f;
public static final int SLOT_OFFSET = 8;
public static final int ANIMATION_LIMIT = 40;
@ -148,33 +144,71 @@ public class DiagramScene extends ObjectScene implements DiagramViewer {
return false;
}
@Override
public void zoomOut() {
double zoom = getZoomFactor();
double newZoom = zoom / DiagramScene.ZOOM_INCREMENT;
if (newZoom > DiagramScene.ZOOM_MIN_FACTOR) {
zoom(newZoom);
}
public double getZoomMinFactor() {
double factorWidth = getScrollPane().getViewport().getViewRect().getWidth() / getBounds().getWidth() ;
double factorHeight = getScrollPane().getViewport().getViewRect().getHeight() / getBounds().getHeight();
double zoomToFit = 0.98 * Math.min(factorWidth, factorHeight);
return Math.min(zoomToFit, ZOOM_MIN_FACTOR);
}
public double getZoomMaxFactor() {
return ZOOM_MAX_FACTOR;
}
@Override
public void zoomIn() {
double zoom = getZoomFactor();
double newZoom = zoom * DiagramScene.ZOOM_INCREMENT;
if (newZoom < DiagramScene.ZOOM_MAX_FACTOR) {
zoom(newZoom);
}
public void zoomIn(Point zoomCenter, double factor) {
centredZoom(getZoomFactor() * factor, zoomCenter);
}
private void zoom(double newZoom) {
double currentZoom = getZoomFactor();
Point viewPosition = getScrollPane().getViewport().getViewPosition();
Rectangle viewRect = getScrollPane().getViewport().getViewRect();
setZoomFactor(newZoom);
@Override
public void zoomOut(Point zoomCenter, double factor) {
centredZoom(getZoomFactor() / factor, zoomCenter);
}
@Override
public void setZoomPercentage(int percentage) {
centredZoom((double)percentage / 100.0, null);
}
@Override
public int getZoomPercentage() {
return (int) (getZoomFactor() * 100);
}
private void centredZoom(double zoomFactor, Point zoomCenter) {
zoomFactor = Math.max(zoomFactor, getZoomMinFactor());
zoomFactor = Math.min(zoomFactor, getZoomMaxFactor());
double oldZoom = getZoomFactor();
Rectangle visibleRect = getView().getVisibleRect();
if (zoomCenter == null) {
zoomCenter = new Point(visibleRect.x + visibleRect.width / 2, visibleRect.y + visibleRect.height / 2);
zoomCenter = getScene().convertViewToScene(zoomCenter);
}
setZoomFactor(zoomFactor);
validate();
getScrollPane().getViewport().validate();
getScrollPane().getViewport().setViewPosition(new Point((int) ((viewPosition.x + viewRect.width / 2) * newZoom / currentZoom - viewRect.width / 2), (int) ((viewPosition.y + viewRect.height / 2) * newZoom / currentZoom - viewRect.height / 2)));
Point location = getScene().getLocation();
visibleRect.x += (int)(zoomFactor * (double)(location.x + zoomCenter.x)) - (int)(oldZoom * (double)(location.x + zoomCenter.x));
visibleRect.y += (int)(zoomFactor * (double)(location.y + zoomCenter.y)) - (int)(oldZoom * (double)(location.y + zoomCenter.y));
// Ensure to be within area
visibleRect.x = Math.max(0, visibleRect.x);
visibleRect.y = Math.max(0, visibleRect.y);
// Fix for jumping during zooming
getView().scrollRectToVisible(visibleRect);
getView().scrollRectToVisible(visibleRect);
zoomChangedEvent.fire();
}
private final ChangedEvent<DiagramViewer> zoomChangedEvent = new ChangedEvent<>(this);
@Override
public ChangedEvent<DiagramViewer> getZoomChangedEvent() {
return zoomChangedEvent;
}
@Override
@ -269,20 +303,36 @@ public class DiagramScene extends ObjectScene implements DiagramViewer {
getScrollPane().getViewport().setViewPosition(p);
}
private JScrollPane createScrollPane() {
JComponent comp = this.createView();
comp.setDoubleBuffered(true);
comp.setBackground(Color.WHITE);
comp.setOpaque(true);
this.setBackground(Color.WHITE);
this.setOpaque(true);
JScrollPane result = new JScrollPane(comp);
result.setBackground(Color.WHITE);
result.getVerticalScrollBar().setUnitIncrement(SCROLL_UNIT_INCREMENT);
result.getVerticalScrollBar().setBlockIncrement(SCROLL_BLOCK_INCREMENT);
result.getHorizontalScrollBar().setUnitIncrement(SCROLL_UNIT_INCREMENT);
result.getHorizontalScrollBar().setBlockIncrement(SCROLL_BLOCK_INCREMENT);
return result;
private JScrollPane createScrollPane(MouseZoomAction mouseZoomAction) {
setBackground(Color.WHITE);
setOpaque(true);
JComponent viewComponent = createView();
viewComponent.setBackground(Color.WHITE);
viewComponent.setOpaque(true);
JPanel centeringPanel = new JPanel(new GridBagLayout());
centeringPanel.setBackground(Color.WHITE);
centeringPanel.setOpaque(true);
centeringPanel.add(viewComponent);
JScrollPane scrollPane = new JScrollPane(centeringPanel, VERTICAL_SCROLLBAR_ALWAYS, HORIZONTAL_SCROLLBAR_ALWAYS);
scrollPane.setBackground(Color.WHITE);
scrollPane.getVerticalScrollBar().setUnitIncrement(SCROLL_UNIT_INCREMENT);
scrollPane.getVerticalScrollBar().setBlockIncrement(SCROLL_BLOCK_INCREMENT);
scrollPane.getHorizontalScrollBar().setUnitIncrement(SCROLL_UNIT_INCREMENT);
scrollPane.getHorizontalScrollBar().setBlockIncrement(SCROLL_BLOCK_INCREMENT);
scrollPane.getViewport().setScrollMode(JViewport.BACKINGSTORE_SCROLL_MODE);
// remove the default MouseWheelListener of the JScrollPane
for (MouseWheelListener listener: scrollPane.getMouseWheelListeners()) {
scrollPane.removeMouseWheelListener(listener);
}
// add a new MouseWheelListener for zooming if the mouse is outside the viewComponent
// but still inside the scrollPane
scrollPane.addMouseWheelListener(mouseZoomAction);
return scrollPane;
}
private ObjectSceneListener selectionChangedListener = new ObjectSceneListener() {
@ -383,7 +433,8 @@ public class DiagramScene extends ObjectScene implements DiagramViewer {
this.setCheckClipping(true);
scrollPane = createScrollPane();
MouseZoomAction mouseZoomAction = new MouseZoomAction(this);
scrollPane = createScrollPane(mouseZoomAction);
hoverAction = createObjectHoverAction();
@ -431,19 +482,10 @@ public class DiagramScene extends ObjectScene implements DiagramViewer {
mainLayer = new LayerWidget(this);
this.addChild(mainLayer);
topLeft = new Widget(this);
topLeft.setPreferredLocation(new Point(-BORDER_SIZE, -BORDER_SIZE));
this.addChild(topLeft);
bottomRight = new Widget(this);
bottomRight.setPreferredLocation(new Point(-BORDER_SIZE, -BORDER_SIZE));
this.addChild(bottomRight);
this.setBorder(BorderFactory.createLineBorder(Color.white, BORDER_SIZE));
this.setLayout(LayoutFactory.createAbsoluteLayout());
this.getInputBindings().setZoomActionModifiers(Utilities.isMac() ? KeyEvent.META_MASK : KeyEvent.CTRL_MASK);
this.getActions().addAction(ActionFactory.createMouseCenteredZoomAction(1.1));
this.getActions().addAction(mouseZoomAction);
this.getActions().addAction(ActionFactory.createPopupMenuAction(popupMenuProvider));
this.getActions().addAction(ActionFactory.createWheelPanAction());
LayerWidget selectLayer = new LayerWidget(this);
this.addChild(selectLayer);
@ -732,63 +774,6 @@ public class DiagramScene extends ObjectScene implements DiagramViewer {
Diagram diagram = getModel().getDiagramToView();
int maxX = -BORDER_SIZE;
int maxY = -BORDER_SIZE;
for (Figure f : diagram.getFigures()) {
FigureWidget w = getWidget(f);
if (w.isVisible()) {
Point p = f.getPosition();
Dimension d = f.getSize();
maxX = Math.max(maxX, p.x + d.width);
maxY = Math.max(maxY, p.y + d.height);
}
}
for (FigureConnection c : diagram.getConnections()) {
List<Point> points = c.getControlPoints();
FigureWidget w1 = getWidget((Figure) c.getTo().getVertex());
FigureWidget w2 = getWidget((Figure) c.getFrom().getVertex());
if (w1.isVisible() && w2.isVisible()) {
for (Point p : points) {
if (p != null) {
maxX = Math.max(maxX, p.x);
maxY = Math.max(maxY, p.y);
}
}
}
}
if (getModel().getShowBlocks() || getModel().getShowCFG()) {
for (Block b : diagram.getBlocks()) {
BlockWidget w = getWidget(b.getInputBlock());
if (w != null && w.isVisible()) {
Rectangle r = b.getBounds();
maxX = Math.max(maxX, r.x + r.width);
maxY = Math.max(maxY, r.y + r.height);
}
}
}
bottomRight.setPreferredLocation(new Point(maxX + BORDER_SIZE, maxY + BORDER_SIZE));
int offx = 0;
int offy = 0;
int curWidth = maxX + 2 * BORDER_SIZE;
int curHeight = maxY + 2 * BORDER_SIZE;
Rectangle bounds = this.getScrollPane().getBounds();
bounds.width /= getZoomFactor();
bounds.height /= getZoomFactor();
if (curWidth < bounds.width) {
offx = (bounds.width - curWidth) / 2;
}
if (curHeight < bounds.height) {
offy = (bounds.height - curHeight) / 2;
}
final int offx2 = offx;
final int offy2 = offy;
SceneAnimator animator = this.getSceneAnimator();
connectionLayer.removeChildren();
int visibleFigureCount = 0;
@ -811,14 +796,14 @@ public class DiagramScene extends ObjectScene implements DiagramViewer {
for (FigureConnection c : s.getConnections()) {
cl.add((Connection) c);
}
processOutputSlot(lastLineCache, s, cl, 0, null, null, offx2, offy2, anim);
processOutputSlot(lastLineCache, s, cl, 0, null, null, 0, 0, anim);
}
}
if (getModel().getShowCFG()) {
for (BlockConnection c : diagram.getBlockConnections()) {
if (isVisible(c)) {
processOutputSlot(lastLineCache, null, Collections.singletonList(c), 0, null, null, offx2, offy2, animator);
processOutputSlot(lastLineCache, null, Collections.singletonList(c), 0, null, null, 0, 0, animator);
}
}
}
@ -827,7 +812,7 @@ public class DiagramScene extends ObjectScene implements DiagramViewer {
FigureWidget w = getWidget(f);
if (w.isVisible()) {
Point p = f.getPosition();
Point p2 = new Point(p.x + offx2, p.y + offy2);
Point p2 = new Point(p.x, p.y);
if ((visibleFigureCount <= ANIMATION_LIMIT && oldVisibleWidgets != null && oldVisibleWidgets.contains(w))) {
animator.animatePreferredLocation(w, p2);
} else {
@ -841,7 +826,7 @@ public class DiagramScene extends ObjectScene implements DiagramViewer {
for (Block b : diagram.getBlocks()) {
BlockWidget w = getWidget(b.getInputBlock());
if (w != null && w.isVisible()) {
Point location = new Point(b.getBounds().x + offx2, b.getBounds().y + offy2);
Point location = new Point(b.getBounds().x, b.getBounds().y);
Rectangle r = new Rectangle(location.x, location.y, b.getBounds().width, b.getBounds().height);
if ((visibleFigureCount <= ANIMATION_LIMIT && oldVisibleWidgets != null && oldVisibleWidgets.contains(w))) {
@ -967,16 +952,6 @@ public class DiagramScene extends ObjectScene implements DiagramViewer {
return lookup;
}
@Override
public void initialize() {
Figure f = getModel().getDiagramToView().getRootFigure();
if (f != null) {
setUndoRedoEnabled(false);
gotoFigure(f);
setUndoRedoEnabled(true);
}
}
public void gotoFigures(final List<Figure> figures) {
Rectangle overall = null;
getModel().showFigures(figures);
@ -1055,44 +1030,26 @@ public class DiagramScene extends ObjectScene implements DiagramViewer {
setSelectedObjects(objects);
}
private Point calcCenter(Rectangle r) {
Point center = new Point((int) r.getCenterX(), (int) r.getCenterY());
center.x -= getScrollPane().getViewport().getViewRect().width / 2;
center.y -= getScrollPane().getViewport().getViewRect().height / 2;
// Ensure to be within area
center.x = Math.max(0, center.x);
center.x = Math.min(getScrollPane().getViewport().getViewSize().width - getScrollPane().getViewport().getViewRect().width, center.x);
center.y = Math.max(0, center.y);
center.y = Math.min(getScrollPane().getViewport().getViewSize().height - getScrollPane().getViewport().getViewRect().height, center.y);
return center;
}
private void centerRectangle(Rectangle r) {
if (getScrollPane().getViewport().getViewRect().width == 0 || getScrollPane().getViewport().getViewRect().height == 0) {
return;
Rectangle rect = convertSceneToView(r);
Rectangle viewRect = getScrollPane().getViewport().getViewRect();
double factor = Math.min(viewRect.getWidth() / rect.getWidth(), viewRect.getHeight() / rect.getHeight());
if (factor < 1.0) {
centredZoom(getZoomFactor() * factor, null);
rect.x *= factor;
rect.y *= factor;
rect.width *= factor;
rect.height *= factor;
}
viewRect.x = rect.x + rect.width / 2 - viewRect.width / 2;
viewRect.y = rect.y + rect.height / 2 - viewRect.height / 2;
// Ensure to be within area
viewRect.x = Math.max(0, viewRect.x);
viewRect.x = Math.min(getScrollPane().getViewport().getViewSize().width - viewRect.width, viewRect.x);
viewRect.y = Math.max(0, viewRect.y);
viewRect.y = Math.min(getScrollPane().getViewport().getViewSize().height - viewRect.height, viewRect.y);
getView().scrollRectToVisible(viewRect);
Rectangle r2 = new Rectangle(r.x, r.y, r.width, r.height);
r2 = convertSceneToView(r2);
double factorX = (double) r2.width / (double) getScrollPane().getViewport().getViewRect().width;
double factorY = (double) r2.height / (double) getScrollPane().getViewport().getViewRect().height;
double factor = Math.max(factorX, factorY);
if (factor >= 1.0) {
Point p = getScrollPane().getViewport().getViewPosition();
setZoomFactor(getZoomFactor() / factor);
r2.x /= factor;
r2.y /= factor;
r2.width /= factor;
r2.height /= factor;
getScrollPane().getViewport().setViewPosition(calcCenter(r2));
} else {
getScrollPane().getViewport().setViewPosition(calcCenter(r2));
}
}
@Override

View File

@ -24,9 +24,11 @@
package com.sun.hotspot.igv.view;
import com.sun.hotspot.igv.data.ChangedEvent;
import com.sun.hotspot.igv.graph.Figure;
import java.awt.Component;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.util.Collection;
import java.util.List;
@ -38,7 +40,7 @@ import org.openide.util.Lookup;
*
* @author Thomas Wuerthinger
*/
interface DiagramViewer {
public interface DiagramViewer {
enum InteractionMode {
SELECTION,
@ -47,32 +49,39 @@ interface DiagramViewer {
DiagramViewModel getModel();
public void paint(Graphics2D generator);
void paint(Graphics2D generator);
public Lookup getLookup();
Lookup getLookup();
public JComponent createSatelliteView();
JComponent createSatelliteView();
public Component getComponent();
Component getComponent();
public void zoomOut();
double getZoomMinFactor();
public void zoomIn();
double getZoomMaxFactor();
public UndoRedo getUndoRedo();
void zoomOut(Point zoomCenter, double speed);
public void componentHidden();
void zoomIn(Point zoomCenter, double speed);
public void componentShowing();
void setZoomPercentage(int percentage);
int getZoomPercentage();
ChangedEvent<DiagramViewer> getZoomChangedEvent();
public void initialize();
UndoRedo getUndoRedo();
public void setSelection(Collection<Figure> list);
void componentHidden();
public void centerFigures(List<Figure> list);
void componentShowing();
public void setInteractionMode(InteractionMode mode);
void setSelection(Collection<Figure> list);
public Rectangle getBounds();
void centerFigures(List<Figure> list);
void setInteractionMode(InteractionMode mode);
Rectangle getBounds();
JComponent getView();
}

View File

@ -36,6 +36,8 @@ import com.sun.hotspot.igv.util.LookupHistory;
import com.sun.hotspot.igv.util.RangeSlider;
import com.sun.hotspot.igv.view.actions.*;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.util.List;
import java.util.*;
import javax.swing.*;
@ -155,6 +157,16 @@ public final class EditorTopComponent extends TopComponent {
centerPanel.setBackground(Color.WHITE);
satelliteComponent = scene.createSatelliteView();
satelliteComponent.setSize(200, 200);
// needed to update when the satellite component is moved
satelliteComponent.addMouseMotionListener(new MouseMotionListener() {
@Override
public void mouseDragged(MouseEvent e) {
centerPanel.repaint();
}
@Override
public void mouseMoved(MouseEvent e) {}
});
centerPanel.add(SCENE_STRING, scene.getComponent());
centerPanel.add(SATELLITE_STRING, satelliteComponent);
add(centerPanel, BorderLayout.CENTER);
@ -173,9 +185,6 @@ public final class EditorTopComponent extends TopComponent {
toolBar.add(ExtractAction.get(ExtractAction.class));
toolBar.add(HideAction.get(HideAction.class));
toolBar.add(ShowAllAction.get(ShowAllAction.class));
toolBar.addSeparator();
toolBar.add(ZoomOutAction.get(ZoomOutAction.class));
toolBar.add(ZoomInAction.get(ZoomInAction.class));
toolBar.addSeparator();
ButtonGroup layoutButtons = new ButtonGroup();
@ -212,6 +221,8 @@ public final class EditorTopComponent extends TopComponent {
toolBar.addSeparator();
toolBar.add(new JToggleButton(new SelectionModeAction()));
toolBar.addSeparator();
toolBar.add(new ZoomLevelAction(scene));
toolBar.add(Box.createHorizontalGlue());
quickSearchToolbar = new Toolbar();
@ -261,11 +272,15 @@ public final class EditorTopComponent extends TopComponent {
}
public void zoomOut() {
scene.zoomOut();
scene.zoomOut(null, DiagramScene.ZOOM_INCREMENT);
}
public void zoomIn() {
scene.zoomIn();
scene.zoomIn(null, DiagramScene.ZOOM_INCREMENT);
}
public void setZoomLevel(int percentage) {
scene.setZoomPercentage(percentage);
}
public static EditorTopComponent getActive() {

View File

@ -64,4 +64,4 @@ public class CustomSelectAction extends WidgetAction.LockedAdapter {
return State.REJECTED;
}
}
}

View File

@ -0,0 +1,120 @@
/*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
package com.sun.hotspot.igv.view.actions;
import com.sun.hotspot.igv.view.DiagramScene;
import com.sun.hotspot.igv.view.DiagramViewer;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.InputEvent;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import javax.swing.JComponent;
import org.netbeans.api.visual.action.WidgetAction;
import org.netbeans.api.visual.widget.Widget;
import org.openide.util.Utilities;
public class MouseZoomAction extends WidgetAction.Adapter implements MouseWheelListener {
public static final int PAN_INCREMENT = 32;
private static final int MODIFIER = Utilities.isMac() ? InputEvent.META_DOWN_MASK : InputEvent.CTRL_DOWN_MASK;
private final DiagramViewer scene;
private int prev_n;
public MouseZoomAction(DiagramScene scene) {
this.prev_n = 0;
this.scene = scene;
}
private boolean performPanning(int modifiersEx, int wheelRotation) {
// If modifier key is not pressed, use wheel for panning
JComponent view = scene.getView();
Rectangle visibleRect = view.getVisibleRect();
int amount = wheelRotation * PAN_INCREMENT;
if (modifiersEx == 0) {
visibleRect.y += amount;
} else if (modifiersEx == InputEvent.SHIFT_DOWN_MASK) {
visibleRect.x += amount;
} else {
return false;
}
view.scrollRectToVisible(visibleRect);
return true;
}
private boolean performZooming(Point sceneMouseLocation, int n) {
if (n > 0) {
if (prev_n > 0) {
scene.zoomOut(sceneMouseLocation, Math.pow(1.1, Math.abs(n)));
return true;
} else {
prev_n = 1;
}
} else if (n < 0) {
if (prev_n < 0) {
scene.zoomIn(sceneMouseLocation, Math.pow(1.1, Math.abs(n)));
return true;
} else {
prev_n = -1;
}
}
return false;
}
/**
* Perform mouse centered zooming
*/
@Override
public State mouseWheelMoved(Widget widget, WidgetMouseWheelEvent event) {
if ((event.getModifiersEx() & MODIFIER) != MODIFIER) {
// If modifier key is not pressed, use wheel for panning
if (performPanning(event.getModifiersEx(), event.getWheelRotation())) {
return State.CONSUMED;
} else {
return State.REJECTED;
}
}
if (performZooming(widget.convertLocalToScene(event.getPoint()), event.getWheelRotation())) {
return State.CONSUMED;
} else {
return State.REJECTED;
}
}
/**
* Perform scene centered zooming
*/
@Override
public void mouseWheelMoved(MouseWheelEvent event) {
if ((event.getModifiersEx() & MODIFIER) != MODIFIER) {
// If modifier key is not pressed, use wheel for panning
performPanning(event.getModifiersEx(), event.getWheelRotation());
} else {
performZooming(null, event.getWheelRotation());
}
}
}

View File

@ -42,7 +42,8 @@ import org.openide.util.actions.CallableSystemAction;
@ActionRegistration(displayName = "#CTL_ZoomInAction")
@ActionReferences({
@ActionReference(path = "Menu/View", position = 450),
@ActionReference(path = "Shortcuts", name = "D-EQUALS")
@ActionReference(path = "Shortcuts", name = "D-EQUALS"),
@ActionReference(path = "Shortcuts", name = "DS-MINUS")
})
@Messages({
"CTL_ZoomInAction=Zoom in",
@ -84,6 +85,6 @@ public final class ZoomInAction extends CallableSystemAction {
@Override
protected String iconResource() {
return "com/sun/hotspot/igv/view/images/zoom_in.png";
return "com/sun/hotspot/igv/view/images/zoomIn.svg"; // NOI18N
}
}

View File

@ -0,0 +1,91 @@
/*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
package com.sun.hotspot.igv.view.actions;
import com.sun.hotspot.igv.data.ChangedListener;
import com.sun.hotspot.igv.view.DiagramViewer;
import com.sun.hotspot.igv.view.EditorTopComponent;
import java.awt.Color;
import java.awt.event.ActionEvent;
import javax.swing.*;
import javax.swing.plaf.basic.BasicComboBoxUI;
public final class ZoomLevelAction extends JComboBox<String> implements ChangedListener<DiagramViewer> {
private static final String[] CHOICES = { "25%", "50%", "75%", "100%", "125%", "150%", "200%", "400%"};
private final DiagramViewer diagramScene;
@Override
public void actionPerformed(ActionEvent e) {
EditorTopComponent editor = EditorTopComponent.getActive();
if (editor != null) {
editor.requestActive();
}
String levelStr = (String) getSelectedItem();
assert levelStr != null;
levelStr = levelStr.replaceAll("\\s","");
levelStr = levelStr.replaceFirst("%","");
try {
int level = Integer.parseInt(levelStr);
int minLevel = (int) (diagramScene.getZoomMinFactor() * 100.0);
int maxLevel = (int) (diagramScene.getZoomMaxFactor() * 100.0);
level = Math.max(level, minLevel);
level = Math.min(level, maxLevel);
setZoomLevel(level);
} catch(NumberFormatException exception) {
changed(diagramScene);
}
}
public ZoomLevelAction(DiagramViewer scene) {
diagramScene = scene;
setModel(new DefaultComboBoxModel<>(CHOICES));
setSelectedIndex(3); // init value: 100%
setVisible(true);
setEditable(true);
setUI(new BasicComboBoxUI());
setFont(getFont().deriveFont((float)(getFont().getSize2D()*0.9)));
addActionListener(this);
JTextField text = (JTextField) getEditor().getEditorComponent();
text.setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY, 1));
text.setColumns(3);
setMaximumSize(getPreferredSize());
scene.getZoomChangedEvent().addListener(this);
}
private void setZoomLevel(int zoomLevel) {
setSelectedItem(zoomLevel + "%");
diagramScene.setZoomPercentage(zoomLevel);
}
@Override
public void changed(DiagramViewer diagramViewer) {
setSelectedItem(diagramViewer.getZoomPercentage() + "%");
}
}

View File

@ -84,6 +84,6 @@ public final class ZoomOutAction extends CallableSystemAction {
@Override
protected String iconResource() {
return "com/sun/hotspot/igv/view/images/zoom_out.png";
return "com/sun/hotspot/igv/view/images/zoomOut.svg"; // NOI18N
}
}

View File

@ -0,0 +1,85 @@
/*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
package com.sun.hotspot.igv.view.actions;
import com.sun.hotspot.igv.view.EditorTopComponent;
import javax.swing.Action;
import org.openide.awt.ActionID;
import org.openide.awt.ActionReference;
import org.openide.awt.ActionReferences;
import org.openide.awt.ActionRegistration;
import org.openide.util.HelpCtx;
import org.openide.util.ImageUtilities;
import org.openide.util.NbBundle;
import org.openide.util.actions.CallableSystemAction;
@ActionID(category = "View", id = "com.sun.hotspot.igv.view.actions.ZoomResetAction")
@ActionRegistration(displayName = "#CTL_ZoomResetAction")
@ActionReferences({
@ActionReference(path = "Menu/View", position = 550),
@ActionReference(path = "Shortcuts", name = "D-0")
})
@NbBundle.Messages({
"CTL_ZoomResetAction=Reset zoom (100%",
"HINT_ZoomResetAction=Rest the zoom level to 100%"
})
public final class ZoomResetAction extends CallableSystemAction {
public ZoomResetAction() {
putValue(Action.SHORT_DESCRIPTION, getDescription());
putValue(Action.SMALL_ICON , ImageUtilities.loadImageIcon(iconResource(), true));
}
@Override
public void performAction() {
EditorTopComponent editor = EditorTopComponent.getActive();
if (editor != null) {
editor.setZoomLevel(100);
}
}
@Override
public String getName() {
return NbBundle.getMessage(NextDiagramAction.class, "CTL_ZoomResetAction");
}
private String getDescription() {
return NbBundle.getMessage(NextDiagramAction.class, "HINT_ZoomResetAction");
}
@Override
public HelpCtx getHelpCtx() {
return HelpCtx.DEFAULT_HELP;
}
@Override
protected boolean asynchronous() {
return false;
}
@Override
protected String iconResource() {
return "com/sun/hotspot/igv/view/images/zoomReset.svg"; // NOI18N
}
}

View File

@ -0,0 +1,163 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<!-- Generator: Adobe Illustrator 23.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg
version="1.1"
id="Vector_Icons"
x="0px"
y="0px"
width="16px"
height="16px"
viewBox="0 0 16 16"
style="enable-background:new 0 0 16 16;"
xml:space="preserve"
sodipodi:docname="zoomIn.svg"
inkscape:version="1.2.1 (9c6d41e, 2022-07-14)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><defs
id="defs30" /><sodipodi:namedview
id="namedview28"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showgrid="false"
inkscape:zoom="64.1875"
inkscape:cx="3.5443038"
inkscape:cy="8.3583252"
inkscape:window-width="2452"
inkscape:window-height="1205"
inkscape:window-x="2204"
inkscape:window-y="82"
inkscape:window-maximized="0"
inkscape:current-layer="Vector_Icons" />
<style
type="text/css"
id="style9">
.st0{fill:#FFFFFF;}
.st1{opacity:0.25;}
.st2{fill:#FAFAFA;}
.st3{opacity:0.33;}
.st4{fill:none;stroke:#474747;stroke-miterlimit:10;}
.st5{opacity:0.42;}
.st6{fill:#CAE3FF;}
.st7{opacity:0.2;}
.st8{opacity:0.03;}
.st9{opacity:0.1;}
.st10{opacity:0.15;}
.st11{opacity:0.45;}
.st12{fill:#FFE1B0;}
.st13{fill:#B3DBFF;}
.st14{fill:#FBDC7C;}
.st15{fill:#FFDB43;}
.st16{fill:#E79B00;}
.st17{fill:#3883CE;}
.st18{fill:none;stroke:#003399;stroke-width:1.375;stroke-miterlimit:10;}
.st19{fill:#E8513D;}
.st20{fill:#1E1E1E;}
.st21{fill:#FFC36D;}
.st22{fill:#9FCBFF;}
.st23{fill:#E9F7FF;}
.st24{fill:#62707C;}
.st25{fill:#7A8896;}
.st26{fill:#57BFFF;}
.st27{fill:#E69D35;}
.st28{fill:#9CFF73;}
.st29{fill:#4891CC;}
.st30{fill:#474747;}
.st31{fill:#CCA05E;}
.st32{opacity:0.67;}
.st33{opacity:0.3;}
.st34{fill:#EAEAEA;}
.st35{fill:#FFE945;}
.st36{fill:#FFCF8C;}
.st37{fill:#FF5252;}
.st38{opacity:0.12;}
.st39{fill:#45A5F4;}
.st40{fill:url(#SVGID_1_);}
.st41{fill:url(#SVGID_2_);}
.st42{opacity:0.05;}
.st43{fill:#3D81F5;}
.st44{fill:#CECECE;}
.st45{fill:#B5B5B5;}
.st46{opacity:0.4;}
.st47{fill:#595959;}
.st48{fill:#80FF80;}
.st49{fill:#C8FF80;}
.st50{fill:#FFEE80;}
.st51{fill:#FFA680;}
.st52{fill:#FF8080;}
.st53{fill:none;}
.st54{fill:#007AFF;}
.st55{fill:#EFFF78;}
.st56{fill:#FFDA00;}
.st57{fill:#3EADFF;}
.st58{opacity:0.67;fill:#FFFFFF;}
.st59{fill:#2E92FF;}
.st60{fill:#3AEA00;}
.st61{fill:#303030;}
</style>
<ellipse
class="st6"
cx="6.8032284"
cy="6.8893313"
id="circle19"
style="fill:#c1ddf1;fill-opacity:1;stroke:#000000;stroke-width:1.01708;stroke-opacity:1"
rx="6.136837"
ry="6.0683227" />
<path
class="st17"
d="m 6.8032287,1.8192652 c 2.9663162,0 5.3796083,2.2744318 5.3796083,5.0700662 0,2.7956345 -2.4132921,5.0700656 -5.3796083,5.0700656 -2.9663161,0 -5.3796085,-2.2744311 -5.3796085,-5.0700656 0,-2.7956344 2.4132924,-5.0700662 5.3796085,-5.0700662 m 0,-1.01401319 c -3.5656045,0 -6.45553013,2.72363949 -6.45553013,6.08407939 0,3.3604396 2.88992563,6.0840796 6.45553013,6.0840796 3.5656043,0 6.4555293,-2.72364 6.4555293,-6.0840796 0,-3.3604399 -2.889925,-6.08407939 -6.4555293,-6.08407939 z"
id="path21"
style="fill:#000000;stroke-width:1.04452" />
<line
class="st18"
x1="6.6498079"
y1="3.85517"
x2="6.6498079"
y2="9.9234934"
id="line23"
style="fill:#000000;stroke:#000000;stroke-opacity:1;stroke-width:1.398;stroke-dasharray:none;stroke-linecap:round" />
<line
class="st18"
x1="3.7348101"
y1="6.7376232"
x2="9.8716478"
y2="6.7376232"
id="line25"
style="fill:#000000;stroke:#000000;stroke-opacity:1;stroke-linecap:round" /><line
class="st18"
x1="11.240422"
y1="11.341141"
x2="14.91732"
y2="14.941232"
id="line25-0"
style="fill:#c1ddf1;fill-opacity:1;stroke:#000000;stroke-width:1.846;stroke-linecap:round;stroke-miterlimit:9.8;stroke-dasharray:none;stroke-opacity:1;paint-order:markers fill stroke" />
</svg>

After

Width:  |  Height:  |  Size: 4.9 KiB

View File

@ -0,0 +1,156 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<!-- Generator: Adobe Illustrator 23.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg
version="1.1"
id="Vector_Icons"
x="0px"
y="0px"
width="16px"
height="16px"
viewBox="0 0 16 16"
style="enable-background:new 0 0 16 16;"
xml:space="preserve"
sodipodi:docname="zoomIn.svg"
inkscape:version="1.2.1 (9c6d41e, 2022-07-14)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><defs
id="defs30" /><sodipodi:namedview
id="namedview28"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showgrid="false"
inkscape:zoom="64.1875"
inkscape:cx="3.5443038"
inkscape:cy="8.3583252"
inkscape:window-width="2452"
inkscape:window-height="1205"
inkscape:window-x="2204"
inkscape:window-y="82"
inkscape:window-maximized="0"
inkscape:current-layer="Vector_Icons" />
<style
type="text/css"
id="style9">
.st0{fill:#FFFFFF;}
.st1{opacity:0.25;}
.st2{fill:#FAFAFA;}
.st3{opacity:0.33;}
.st4{fill:none;stroke:#474747;stroke-miterlimit:10;}
.st5{opacity:0.42;}
.st6{fill:#CAE3FF;}
.st7{opacity:0.2;}
.st8{opacity:0.03;}
.st9{opacity:0.1;}
.st10{opacity:0.15;}
.st11{opacity:0.45;}
.st12{fill:#FFE1B0;}
.st13{fill:#B3DBFF;}
.st14{fill:#FBDC7C;}
.st15{fill:#FFDB43;}
.st16{fill:#E79B00;}
.st17{fill:#3883CE;}
.st18{fill:none;stroke:#003399;stroke-width:1.375;stroke-miterlimit:10;}
.st19{fill:#E8513D;}
.st20{fill:#1E1E1E;}
.st21{fill:#FFC36D;}
.st22{fill:#9FCBFF;}
.st23{fill:#E9F7FF;}
.st24{fill:#62707C;}
.st25{fill:#7A8896;}
.st26{fill:#57BFFF;}
.st27{fill:#E69D35;}
.st28{fill:#9CFF73;}
.st29{fill:#4891CC;}
.st30{fill:#474747;}
.st31{fill:#CCA05E;}
.st32{opacity:0.67;}
.st33{opacity:0.3;}
.st34{fill:#EAEAEA;}
.st35{fill:#FFE945;}
.st36{fill:#FFCF8C;}
.st37{fill:#FF5252;}
.st38{opacity:0.12;}
.st39{fill:#45A5F4;}
.st40{fill:url(#SVGID_1_);}
.st41{fill:url(#SVGID_2_);}
.st42{opacity:0.05;}
.st43{fill:#3D81F5;}
.st44{fill:#CECECE;}
.st45{fill:#B5B5B5;}
.st46{opacity:0.4;}
.st47{fill:#595959;}
.st48{fill:#80FF80;}
.st49{fill:#C8FF80;}
.st50{fill:#FFEE80;}
.st51{fill:#FFA680;}
.st52{fill:#FF8080;}
.st53{fill:none;}
.st54{fill:#007AFF;}
.st55{fill:#EFFF78;}
.st56{fill:#FFDA00;}
.st57{fill:#3EADFF;}
.st58{opacity:0.67;fill:#FFFFFF;}
.st59{fill:#2E92FF;}
.st60{fill:#3AEA00;}
.st61{fill:#303030;}
</style>
<ellipse
class="st6"
cx="6.8032284"
cy="6.8893313"
id="circle19"
style="fill:#c1ddf1;fill-opacity:1;stroke:#000000;stroke-width:1.01708;stroke-opacity:1"
rx="6.136837"
ry="6.0683227" />
<path
class="st17"
d="m 6.8032287,1.8192652 c 2.9663162,0 5.3796083,2.2744318 5.3796083,5.0700662 0,2.7956345 -2.4132921,5.0700656 -5.3796083,5.0700656 -2.9663161,0 -5.3796085,-2.2744311 -5.3796085,-5.0700656 0,-2.7956344 2.4132924,-5.0700662 5.3796085,-5.0700662 m 0,-1.01401319 c -3.5656045,0 -6.45553013,2.72363949 -6.45553013,6.08407939 0,3.3604396 2.88992563,6.0840796 6.45553013,6.0840796 3.5656043,0 6.4555293,-2.72364 6.4555293,-6.0840796 0,-3.3604399 -2.889925,-6.08407939 -6.4555293,-6.08407939 z"
id="path21"
style="fill:#000000;stroke-width:1.04452" />
<line
class="st18"
x1="3.7348101"
y1="6.7376232"
x2="9.8716478"
y2="6.7376232"
id="line25"
style="fill:#000000;stroke:#000000;stroke-opacity:1;stroke-linecap:round" /><line
class="st18"
x1="11.240422"
y1="11.341141"
x2="14.91732"
y2="14.941232"
id="line25-0"
style="fill:#c1ddf1;fill-opacity:1;stroke:#000000;stroke-width:1.846;stroke-linecap:round;stroke-miterlimit:9.8;stroke-dasharray:none;stroke-opacity:1;paint-order:markers fill stroke" />
</svg>

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

@ -0,0 +1,156 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<!-- Generator: Adobe Illustrator 23.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg
version="1.1"
id="Vector_Icons"
x="0px"
y="0px"
width="16px"
height="16px"
viewBox="0 0 16 16"
style="enable-background:new 0 0 16 16;"
xml:space="preserve"
sodipodi:docname="zoomReset.svg"
inkscape:version="1.2.1 (9c6d41e, 2022-07-14)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><defs
id="defs30" /><sodipodi:namedview
id="namedview28"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showgrid="false"
inkscape:zoom="36.320439"
inkscape:cx="2.2163829"
inkscape:cy="6.8694104"
inkscape:window-width="2452"
inkscape:window-height="1205"
inkscape:window-x="2204"
inkscape:window-y="25"
inkscape:window-maximized="0"
inkscape:current-layer="Vector_Icons" />
<style
type="text/css"
id="style9">
.st0{fill:#FFFFFF;}
.st1{opacity:0.25;}
.st2{fill:#FAFAFA;}
.st3{opacity:0.33;}
.st4{fill:none;stroke:#474747;stroke-miterlimit:10;}
.st5{opacity:0.42;}
.st6{fill:#CAE3FF;}
.st7{opacity:0.2;}
.st8{opacity:0.03;}
.st9{opacity:0.1;}
.st10{opacity:0.15;}
.st11{opacity:0.45;}
.st12{fill:#FFE1B0;}
.st13{fill:#B3DBFF;}
.st14{fill:#FBDC7C;}
.st15{fill:#FFDB43;}
.st16{fill:#E79B00;}
.st17{fill:#3883CE;}
.st18{fill:none;stroke:#003399;stroke-width:1.375;stroke-miterlimit:10;}
.st19{fill:#E8513D;}
.st20{fill:#1E1E1E;}
.st21{fill:#FFC36D;}
.st22{fill:#9FCBFF;}
.st23{fill:#E9F7FF;}
.st24{fill:#62707C;}
.st25{fill:#7A8896;}
.st26{fill:#57BFFF;}
.st27{fill:#E69D35;}
.st28{fill:#9CFF73;}
.st29{fill:#4891CC;}
.st30{fill:#474747;}
.st31{fill:#CCA05E;}
.st32{opacity:0.67;}
.st33{opacity:0.3;}
.st34{fill:#EAEAEA;}
.st35{fill:#FFE945;}
.st36{fill:#FFCF8C;}
.st37{fill:#FF5252;}
.st38{opacity:0.12;}
.st39{fill:#45A5F4;}
.st40{fill:url(#SVGID_1_);}
.st41{fill:url(#SVGID_2_);}
.st42{opacity:0.05;}
.st43{fill:#3D81F5;}
.st44{fill:#CECECE;}
.st45{fill:#B5B5B5;}
.st46{opacity:0.4;}
.st47{fill:#595959;}
.st48{fill:#80FF80;}
.st49{fill:#C8FF80;}
.st50{fill:#FFEE80;}
.st51{fill:#FFA680;}
.st52{fill:#FF8080;}
.st53{fill:none;}
.st54{fill:#007AFF;}
.st55{fill:#EFFF78;}
.st56{fill:#FFDA00;}
.st57{fill:#3EADFF;}
.st58{opacity:0.67;fill:#FFFFFF;}
.st59{fill:#2E92FF;}
.st60{fill:#3AEA00;}
.st61{fill:#303030;}
</style>
<ellipse
class="st6"
cx="6.8032284"
cy="6.8893313"
id="circle19"
style="fill:#c1ddf1;fill-opacity:1;stroke:#000000;stroke-width:1.01708;stroke-opacity:1"
rx="6.136837"
ry="6.0683227" /><ellipse
class="st6"
cx="6.7592793"
cy="6.7868128"
id="circle19-5"
style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.227052;stroke-opacity:1"
rx="1.3970011"
ry="1.3284868" />
<path
class="st17"
d="m 6.8032287,1.8192652 c 2.9663162,0 5.3796083,2.2744318 5.3796083,5.0700662 0,2.7956345 -2.4132921,5.0700656 -5.3796083,5.0700656 -2.9663161,0 -5.3796085,-2.2744311 -5.3796085,-5.0700656 0,-2.7956344 2.4132924,-5.0700662 5.3796085,-5.0700662 m 0,-1.01401319 c -3.5656045,0 -6.45553013,2.72363949 -6.45553013,6.08407939 0,3.3604396 2.88992563,6.0840796 6.45553013,6.0840796 3.5656043,0 6.4555293,-2.72364 6.4555293,-6.0840796 0,-3.3604399 -2.889925,-6.08407939 -6.4555293,-6.08407939 z"
id="path21"
style="fill:#000000;stroke-width:1.04452" />
<line
class="st18"
x1="11.240422"
y1="11.341141"
x2="14.91732"
y2="14.941232"
id="line25-0"
style="fill:#c1ddf1;fill-opacity:1;stroke:#000000;stroke-width:1.846;stroke-linecap:round;stroke-miterlimit:9.8;stroke-dasharray:none;stroke-opacity:1;paint-order:markers fill stroke" />
</svg>

After

Width:  |  Height:  |  Size: 4.7 KiB