Merge pull request #9 from fourbites/master
Add support for zooming in VirtualMediaPanel
This commit is contained in:
@@ -19,27 +19,25 @@
|
||||
|
||||
package com.threerings.media;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseWheelEvent;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import javax.swing.SwingUtilities;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import com.samskivert.util.RunAnywhere;
|
||||
|
||||
import static com.threerings.media.Log.log;
|
||||
import com.threerings.media.image.ImageUtil;
|
||||
import com.threerings.media.image.Mirage;
|
||||
import com.threerings.media.util.MathUtil;
|
||||
import com.threerings.media.util.Pathable;
|
||||
|
||||
import static com.threerings.media.Log.log;
|
||||
|
||||
/**
|
||||
* Extends the base media panel with the notion of a virtual coordinate system. All entities in
|
||||
* the virtual media panel have virtual coordinates and the virtual media panel displays a window
|
||||
@@ -67,6 +65,11 @@ public class VirtualMediaPanel extends MediaPanel
|
||||
public VirtualMediaPanel (FrameManager framemgr)
|
||||
{
|
||||
super(framemgr);
|
||||
|
||||
addZoomListener((oldZoom, newZoom) -> {
|
||||
_vbounds = _zoomManager.rescaleBounds(_vbounds, getWidth(), getHeight());
|
||||
_metamgr.getRegionManager().addDirtyRegion(_vbounds);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -149,7 +152,8 @@ public class VirtualMediaPanel extends MediaPanel
|
||||
@Override
|
||||
protected void processMouseEvent (MouseEvent event)
|
||||
{
|
||||
event.translatePoint(_vbounds.x, _vbounds.y);
|
||||
event.translatePoint(_nx, _ny);
|
||||
_zoomManager.adjustMouseEvent(event, _vbounds);
|
||||
super.processMouseEvent(event);
|
||||
}
|
||||
|
||||
@@ -160,7 +164,8 @@ public class VirtualMediaPanel extends MediaPanel
|
||||
@Override
|
||||
protected void processMouseMotionEvent (MouseEvent event)
|
||||
{
|
||||
event.translatePoint(_vbounds.x, _vbounds.y);
|
||||
event.translatePoint(_nx, _ny);
|
||||
_zoomManager.adjustMouseEvent(event, _vbounds);
|
||||
super.processMouseMotionEvent(event);
|
||||
}
|
||||
|
||||
@@ -171,7 +176,8 @@ public class VirtualMediaPanel extends MediaPanel
|
||||
@Override
|
||||
protected void processMouseWheelEvent (MouseWheelEvent event)
|
||||
{
|
||||
event.translatePoint(_vbounds.x, _vbounds.y);
|
||||
event.translatePoint(_nx, _ny);
|
||||
_zoomManager.adjustMouseEvent(event, _vbounds);
|
||||
super.processMouseWheelEvent(event);
|
||||
}
|
||||
|
||||
@@ -179,7 +185,8 @@ public class VirtualMediaPanel extends MediaPanel
|
||||
protected void dirtyScreenRect (Rectangle rect)
|
||||
{
|
||||
// translate the screen rect into happy coordinates
|
||||
rect.translate(_vbounds.x, _vbounds.y);
|
||||
rect.translate(_nx, _ny);
|
||||
rect = _zoomManager.scaleOnCenter(rect);
|
||||
_metamgr.getRegionManager().addDirtyRegion(rect);
|
||||
}
|
||||
|
||||
@@ -201,6 +208,7 @@ public class VirtualMediaPanel extends MediaPanel
|
||||
// keep track of the size of the viewport
|
||||
_vbounds.width = getWidth();
|
||||
_vbounds.height = getHeight();
|
||||
_vbounds = _zoomManager.scaleOnCenter(_vbounds);
|
||||
|
||||
// we need to obtain our absolute screen coordinates to work
|
||||
// around the Windows copyArea() bug
|
||||
@@ -212,7 +220,7 @@ public class VirtualMediaPanel extends MediaPanel
|
||||
{
|
||||
// Adjust for any scrolling we're currently doing.
|
||||
super.addObscurerDirtyRegion(
|
||||
new Rectangle(region.x - _dx, region.y - _dy, region.width, region.height));
|
||||
new Rectangle(region.x - (int) _dx, region.y - (int) _dy, region.width, region.height));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -235,47 +243,60 @@ public class VirtualMediaPanel extends MediaPanel
|
||||
|
||||
protected void adjustBoundsCenter ()
|
||||
{
|
||||
int width = getWidth(), height = getHeight();
|
||||
int width = _vbounds.width, height = _vbounds.height;
|
||||
|
||||
// adjusts our view location to track any pathable we might be tracking
|
||||
trackPathable();
|
||||
|
||||
// our offset is from the center of the view panel, so we need to adjust
|
||||
// coordinates to account for zoom.
|
||||
Point viewCenter = ZoomManager.center(_vbounds);
|
||||
Point panelCenter = new Point(getWidth() / 2, getHeight() / 2);
|
||||
int offsetX = viewCenter.x - panelCenter.x;
|
||||
int offsetY = viewCenter.y - panelCenter.y;
|
||||
|
||||
// if we have a new target location, we'll need to generate dirty
|
||||
// regions for the area exposed by the scrolling
|
||||
if (_nx != _vbounds.x || _ny != _vbounds.y) {
|
||||
if (_nx != offsetX || _ny != offsetY) {
|
||||
// determine how far we'll be moving on this tick
|
||||
int dx = _nx - _vbounds.x, dy = _ny - _vbounds.y;
|
||||
int dx = _nx - offsetX, dy = _ny - offsetY;
|
||||
|
||||
// log.info("Scrolling into place [n=(" + _nx + ", " + _ny +
|
||||
// "), t=(" + _vbounds.x + ", " + _vbounds.y +
|
||||
// "), d=(" + dx + ", " + dy +
|
||||
// "), width=" + width + ", height=" + height + "].");
|
||||
|
||||
_dx = dx;
|
||||
_dy = dy;
|
||||
|
||||
// these are used to prevent the vertical strip from
|
||||
// overlapping the horizontal strip
|
||||
int sy = _ny, shei = height;
|
||||
|
||||
// and add invalid rectangles for the exposed areas
|
||||
if (dy > 0) {
|
||||
shei = Math.max(shei - dy, 0);
|
||||
_metamgr.getRegionManager().invalidateRegion(_nx, _ny + height - dy, width, dy);
|
||||
} else if (dy < 0) {
|
||||
sy -= dy;
|
||||
_metamgr.getRegionManager().invalidateRegion(_nx, _ny, width, -dy);
|
||||
}
|
||||
if (dx > 0) {
|
||||
_metamgr.getRegionManager().invalidateRegion(_nx + width - dx, sy, dx, shei);
|
||||
} else if (dx < 0) {
|
||||
_metamgr.getRegionManager().invalidateRegion(_nx, sy, -dx, shei);
|
||||
}
|
||||
|
||||
_dx += dx * getZoomLevel();
|
||||
_dy += dy * getZoomLevel();
|
||||
|
||||
// now go ahead and update our location so that changes in between here and the call
|
||||
// to paint() for this tick don't booch everything
|
||||
_vbounds.x = _nx; _vbounds.y = _ny;
|
||||
_vbounds.x += dx;
|
||||
_vbounds.y += dy;
|
||||
|
||||
// these are used to prevent the vertical strip from
|
||||
// overlapping the horizontal strip
|
||||
int sy = _vbounds.y, shei = height;
|
||||
|
||||
// and add invalid rectangles for the exposed areas
|
||||
if (dy > 0) {
|
||||
// zoom rounding makes it so copyArea can't always get the full region
|
||||
// so we extend each invalidation region by 1 pixel to make sure we don't leave artifacts
|
||||
int dy2 = dy + 1;
|
||||
shei = Math.max(shei - dy2, 0);
|
||||
_metamgr.getRegionManager().invalidateRegion(_vbounds.x, _vbounds.y + height - dy2, width, dy2);
|
||||
} else if (dy < 0) {
|
||||
int dy2 = dy - 1;
|
||||
sy -= dy2;
|
||||
_metamgr.getRegionManager().invalidateRegion(_vbounds.x, _vbounds.y, width, -dy2);
|
||||
}
|
||||
if (dx > 0) {
|
||||
int dx2 = dx + 1;
|
||||
_metamgr.getRegionManager().invalidateRegion(_vbounds.x + width - dx2, sy, dx2, shei);
|
||||
} else if (dx < 0) {
|
||||
int dx2 = dx - 1;
|
||||
_metamgr.getRegionManager().invalidateRegion(_vbounds.x, sy, -dx2, shei);
|
||||
}
|
||||
|
||||
addObscurerDirtyRegions(false);
|
||||
|
||||
@@ -313,8 +334,8 @@ public class VirtualMediaPanel extends MediaPanel
|
||||
return;
|
||||
}
|
||||
|
||||
int width = getWidth(), height = getHeight();
|
||||
int nx = _vbounds.x, ny = _vbounds.y;
|
||||
int width = _vbounds.width, height = _vbounds.height;
|
||||
int nx = _nx, ny = _ny;
|
||||
|
||||
// figure out where to move
|
||||
switch (_fmode) {
|
||||
@@ -356,11 +377,12 @@ public class VirtualMediaPanel extends MediaPanel
|
||||
@Override
|
||||
protected void paint (Graphics2D gfx, Rectangle[] dirty)
|
||||
{
|
||||
// if we're scrolling, go ahead and do the business
|
||||
if (_dx != 0 || _dy != 0) {
|
||||
int dx = (int) Math.round(_dx);
|
||||
int dy = (int) Math.round(_dy);
|
||||
if (dx != 0 || dy != 0) {
|
||||
int width = getWidth(), height = getHeight();
|
||||
int cx = (_dx > 0) ? _dx : 0;
|
||||
int cy = (_dy > 0) ? _dy : 0;
|
||||
int cx = (dx > 0) ? dx : 0;
|
||||
int cy = (dy > 0) ? dy : 0;
|
||||
|
||||
// set the clip to the bounds of the component (we can't assume the clip is anything
|
||||
// sensible upon entry to paint() because the frame manager expects us to set our own
|
||||
@@ -373,14 +395,14 @@ public class VirtualMediaPanel extends MediaPanel
|
||||
if (RunAnywhere.isWindows()) {
|
||||
gfx.translate(-_abounds.x, -_abounds.y);
|
||||
gfx.copyArea(_abounds.x + cx, _abounds.y + cy,
|
||||
width - Math.abs(_dx),
|
||||
height - Math.abs(_dy), -_dx, -_dy);
|
||||
width - Math.abs(dx),
|
||||
height - Math.abs(dy), -dx, -dy);
|
||||
gfx.translate(_abounds.x, _abounds.y);
|
||||
} else if (RunAnywhere.isMacOS()) {
|
||||
try {
|
||||
gfx.copyArea(cx, cy,
|
||||
width - Math.abs(_dx),
|
||||
height - Math.abs(_dy), -_dx, -_dy);
|
||||
width - Math.abs(dx),
|
||||
height - Math.abs(dy), -dx, -dy);
|
||||
} catch (Exception e) {
|
||||
// HACK when it throws an exception trying to do the copy area, just repaint
|
||||
// everything
|
||||
@@ -388,29 +410,41 @@ public class VirtualMediaPanel extends MediaPanel
|
||||
}
|
||||
} else {
|
||||
gfx.copyArea(cx, cy,
|
||||
width - Math.abs(_dx),
|
||||
height - Math.abs(_dy), -_dx, -_dy);
|
||||
width - Math.abs(dx),
|
||||
height - Math.abs(dy), -dx, -dy);
|
||||
}
|
||||
|
||||
// and clear out our scroll deltas
|
||||
_dx = 0; _dy = 0;
|
||||
_dx -= dx;
|
||||
_dy -= dy;
|
||||
}
|
||||
|
||||
AffineTransform originalTransform = gfx.getTransform();
|
||||
|
||||
int centerX = _vbounds.x + _vbounds.width / 2;
|
||||
int centerY = _vbounds.y + _vbounds.height / 2;
|
||||
|
||||
// if we zoom too quickly, the zoomManager scale may not be in sync with the paint tick
|
||||
// so we check based on the actual view bounds to be safe
|
||||
double scale = getWidth() / (double) _vbounds.width;
|
||||
|
||||
// translate into happy space
|
||||
gfx.translate(-_vbounds.x, -_vbounds.y);
|
||||
gfx.translate(getWidth() / 2, getHeight() / 2);
|
||||
gfx.scale(scale, scale);
|
||||
gfx.translate(-centerX, -centerY);
|
||||
|
||||
// now do the actual painting
|
||||
super.paint(gfx, dirty);
|
||||
|
||||
// translate back out of happy space
|
||||
gfx.translate(_vbounds.x, _vbounds.y);
|
||||
gfx.setTransform(originalTransform);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void constrainToBounds (Rectangle dirty)
|
||||
{
|
||||
SwingUtilities.computeIntersection(
|
||||
_vbounds.x, _vbounds.y, getWidth(), getHeight(), dirty);
|
||||
_vbounds.x, _vbounds.y, _vbounds.width, _vbounds.height, dirty);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -429,14 +463,48 @@ public class VirtualMediaPanel extends MediaPanel
|
||||
}
|
||||
}
|
||||
|
||||
protected void enableZoom() {
|
||||
addMouseWheelListener(_zoomManager.createMouseWheelListener());
|
||||
}
|
||||
|
||||
protected void enableZoom(double min, double max) {
|
||||
enableZoom();
|
||||
setZoomConstraints(min, max);
|
||||
}
|
||||
|
||||
protected void setZoomConstraints(double min, double max) {
|
||||
_zoomManager.setMinZoomLevel(min);
|
||||
_zoomManager.setMaxZoomLevel(max);
|
||||
}
|
||||
|
||||
protected void setZoomLevel(double zoom) {
|
||||
_zoomManager.setZoomLevel(zoom);
|
||||
}
|
||||
|
||||
protected double getZoomLevel() {
|
||||
return _zoomManager.getZoomLevel();
|
||||
}
|
||||
|
||||
protected void addZoomListener(ZoomManager.ZoomListener listener) {
|
||||
_zoomManager.addZoomListener(listener);
|
||||
}
|
||||
|
||||
protected void removeZoomListener(ZoomManager.ZoomListener listener) {
|
||||
_zoomManager.removeZoomListener(listener);
|
||||
}
|
||||
|
||||
protected ZoomManager _zoomManager = new ZoomManager();
|
||||
|
||||
/** Our viewport bounds in virtual coordinates. */
|
||||
protected Rectangle _vbounds = new Rectangle();
|
||||
|
||||
/** Our target offsets to be effected on the next tick. */
|
||||
protected int _nx, _ny;
|
||||
|
||||
/** Our scroll offsets. */
|
||||
protected int _dx, _dy;
|
||||
/**
|
||||
* Our scroll offsets in real pixels.
|
||||
*/
|
||||
protected double _dx, _dy;
|
||||
|
||||
/** Our tiling background image. */
|
||||
protected Mirage _background;
|
||||
|
||||
@@ -0,0 +1,217 @@
|
||||
package com.threerings.media;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseWheelListener;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
public class ZoomManager {
|
||||
|
||||
protected static final double ZOOM_SNAP_THRESHOLD = 0.05;
|
||||
protected static final double[] DEFAULT_ZOOM_STEPS = { 0.25, 0.3333, 0.5, 1.0, 2.0 };
|
||||
|
||||
protected double _zoomLevel = 1.0;
|
||||
protected double _minZoomLevel = 0.25;
|
||||
protected double _maxZoomLevel = 2.0;
|
||||
protected double _zoomSteps[] = DEFAULT_ZOOM_STEPS;
|
||||
|
||||
public interface ZoomListener {
|
||||
|
||||
void zoomChanged(double oldZoom, double newZoom);
|
||||
}
|
||||
|
||||
private final List<ZoomListener> _listeners = new CopyOnWriteArrayList<>();
|
||||
|
||||
public ZoomManager() {
|
||||
}
|
||||
|
||||
public ZoomManager(double zoomLevel) {
|
||||
_zoomLevel = zoomLevel;
|
||||
}
|
||||
|
||||
public ZoomManager(double zoomLevel, double minZoomLevel, double maxZoomLevel) {
|
||||
_zoomLevel = zoomLevel;
|
||||
_minZoomLevel = minZoomLevel;
|
||||
_maxZoomLevel = maxZoomLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the center point of the given rectangle.
|
||||
*
|
||||
* @param rect the rectangle to find the center of
|
||||
* @return the center point of the rectangle
|
||||
*/
|
||||
public static Point center(Rectangle rect) {
|
||||
int centerX = rect.x + rect.width / 2;
|
||||
int centerY = rect.y + rect.height / 2;
|
||||
return new Point(centerX, centerY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rescales the given bounds rectangle based on the current zoom level.
|
||||
* Useful when the zoom level changes to update the viewport.
|
||||
*
|
||||
* @param viewport the rectangle to rescale
|
||||
* @param width the new width
|
||||
* @param height the new height
|
||||
* @return a new rectangle representing the rescaled bounds
|
||||
*/
|
||||
public Rectangle rescaleBounds(Rectangle viewPort, int width, int height) {
|
||||
Point center = center(viewPort);
|
||||
int newWidth = (int) (width / _zoomLevel);
|
||||
int newHeight = (int) (height / _zoomLevel);
|
||||
return new Rectangle(center.x - newWidth / 2, center.y - newHeight / 2, newWidth, newHeight);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scales the given viewport rectangle based on the current zoom level,
|
||||
* centering the scaling on the viewport's center.
|
||||
*
|
||||
* @param viewPort the viewport rectangle to scale
|
||||
* @return a new rectangle representing the scaled viewport
|
||||
*/
|
||||
public Rectangle scaleOnCenter(Rectangle viewPort) {
|
||||
Point center = center(viewPort);
|
||||
int newWidth = (int) (viewPort.width / _zoomLevel);
|
||||
int newHeight = (int) (viewPort.height / _zoomLevel);
|
||||
return new Rectangle(center.x - newWidth / 2, center.y - newHeight / 2, newWidth, newHeight);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjusts the given mouse event for the current zoom level. Uses scaled
|
||||
* distance from the center of the panel
|
||||
*
|
||||
* @param event the mouse event to adjust
|
||||
*/
|
||||
public void adjustMouseEvent(MouseEvent event, Rectangle viewPort) {
|
||||
Point adjustedPoint = screenToVirtual(viewPort, event.getPoint());
|
||||
event.translatePoint(
|
||||
adjustedPoint.x - event.getX(),
|
||||
adjustedPoint.y - event.getY());
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjusts the given point for the current zoom level. Zoom happens from the
|
||||
* center of the viewport.
|
||||
*
|
||||
* @param viewPort the viewport rectangle
|
||||
* @param toAdjust the point to adjust
|
||||
* @return a new point representing the adjusted coordinates
|
||||
*/
|
||||
public Point screenToVirtual(Rectangle viewPort, Point screenPoint) {
|
||||
Point center = center(viewPort);
|
||||
double scale = _zoomLevel;
|
||||
int virtX = (int) ((screenPoint.x - center.x) / scale + center.x);
|
||||
int virtY = (int) ((screenPoint.y - center.y) / scale + center.y);
|
||||
return new Point(virtX, virtY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the zoom steps to use when zooming in and out.
|
||||
*
|
||||
* @param zoomSteps the zoom steps to set
|
||||
*/
|
||||
public void setZoomSteps(double[] zoomSteps) {
|
||||
_zoomSteps = zoomSteps;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a mouse wheel listener that adjusts the zoom level.
|
||||
*
|
||||
* @return a mouse wheel listener
|
||||
*/
|
||||
public MouseWheelListener createMouseWheelListener() {
|
||||
return e -> {
|
||||
int closestStepIndex = 0;
|
||||
double smallestDiff = Math.abs(_zoomLevel - _zoomSteps[0]);
|
||||
for (int i = 0; i < _zoomSteps.length; i++) {
|
||||
double diff = Math.abs(_zoomLevel - _zoomSteps[i]);
|
||||
if (diff < smallestDiff) {
|
||||
smallestDiff = diff;
|
||||
closestStepIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
int notches = e.getWheelRotation();
|
||||
int newIndex = closestStepIndex + (notches > 0 ? -1 : 1);
|
||||
if (newIndex < 0) {
|
||||
newIndex = 0;
|
||||
} else if (newIndex >= _zoomSteps.length) {
|
||||
newIndex = _zoomSteps.length - 1;
|
||||
}
|
||||
setZoomLevel(_zoomSteps[newIndex]);
|
||||
};
|
||||
}
|
||||
|
||||
public double getZoomLevel() {
|
||||
return _zoomLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scales the current zoom level by the given factor.
|
||||
*
|
||||
* @param scale the scale factor
|
||||
* @return the actual scale factor applied after clamping to min and max
|
||||
*/
|
||||
public double scaleZoomLevel(double scale) {
|
||||
double oldZoom = _zoomLevel;
|
||||
setZoomLevel(_zoomLevel * scale);
|
||||
return _zoomLevel / oldZoom;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current zoom level, clamping it to the min and max zoom levels.
|
||||
*
|
||||
* @param zoomLevel the new zoom level
|
||||
*/
|
||||
public void setZoomLevel(double zoomLevel) {
|
||||
double oldZoom = _zoomLevel;
|
||||
if (zoomLevel < _minZoomLevel) {
|
||||
_zoomLevel = _minZoomLevel;
|
||||
} else if (zoomLevel > _maxZoomLevel) {
|
||||
_zoomLevel = _maxZoomLevel;
|
||||
} else {
|
||||
_zoomLevel = zoomLevel;
|
||||
// if we're close to 1.0, we might as well snap to it
|
||||
if (Math.abs(_zoomLevel - 1.0) < ZOOM_SNAP_THRESHOLD) {
|
||||
_zoomLevel = 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
if (oldZoom != _zoomLevel) {
|
||||
fireZoomChanged(oldZoom, _zoomLevel);
|
||||
}
|
||||
}
|
||||
|
||||
public double getMaxZoomLevel() {
|
||||
return _maxZoomLevel;
|
||||
}
|
||||
|
||||
public void setMaxZoomLevel(double maxZoomLevel) {
|
||||
_maxZoomLevel = maxZoomLevel;
|
||||
}
|
||||
|
||||
public double getMinZoomLevel() {
|
||||
return _minZoomLevel;
|
||||
}
|
||||
|
||||
public void setMinZoomLevel(double minZoomLevel) {
|
||||
_minZoomLevel = minZoomLevel;
|
||||
}
|
||||
|
||||
public void addZoomListener(ZoomListener listener) {
|
||||
_listeners.add(listener);
|
||||
}
|
||||
|
||||
public void removeZoomListener(ZoomListener listener) {
|
||||
_listeners.remove(listener);
|
||||
}
|
||||
|
||||
private void fireZoomChanged(double oldZoom, double newZoom) {
|
||||
for (ZoomListener listener : _listeners) {
|
||||
listener.zoomChanged(oldZoom, newZoom);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -118,6 +118,10 @@ public class MisoScenePanel extends VirtualMediaPanel
|
||||
_resolver.start();
|
||||
_resolvers.put(_ctx, _resolver);
|
||||
}
|
||||
|
||||
addZoomListener((oldZoom, newZoom) -> {
|
||||
rethink();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -716,7 +720,7 @@ public class MisoScenePanel extends VirtualMediaPanel
|
||||
|
||||
// compute the tile coordinates of our upper left screen coordinate and request a rethink
|
||||
// if they've changed
|
||||
MisoUtil.screenToTile(_metrics, _vbounds.x, _vbounds.y, _tcoords);
|
||||
MisoUtil.screenToTile(_metrics, _nx, _ny, _tcoords);
|
||||
if (_ulpos == null || !_tcoords.equals(_ulpos)) {
|
||||
// if this is a forced rethink (_ulpos is null), we might delay paint as a result of
|
||||
// it, but only if we queue up blocks for resolution in our rethink
|
||||
|
||||
Reference in New Issue
Block a user