|
From: Frederick W. <fre...@us...> - 2012-01-10 11:22:28
|
rails/ui/swing/ImageLoader.java | 22 +++++++++-
rails/ui/swing/MapPanel.java | 81 ++++++++++++++++++++++++++++++++++++--
rails/ui/swing/hexmap/HexMap.java | 44 ++------------------
3 files changed, 105 insertions(+), 42 deletions(-)
New commits:
commit 38e4a6e05fae1349af459ed47c438271dc7373da
Author: Frederick Weld <fre...@gm...>
Date: Tue Jan 10 12:16:54 2012 +0100
Added round-off to the fit-to-xyz zoom (continuous zoom, scroll bar)
The current logic of discrete zoom steps is still valid - but it is
complemented by a continuous adjustment factor ("last mile adjustment").
In addition, the appearance and width of the scroll bar is now
considered.
diff --git a/rails/ui/swing/ImageLoader.java b/rails/ui/swing/ImageLoader.java
index b22bcbf..f663639 100644
--- a/rails/ui/swing/ImageLoader.java
+++ b/rails/ui/swing/ImageLoader.java
@@ -27,6 +27,9 @@ public class ImageLoader {
private static Map<Integer, Document> svgMap;
private static double[] zoomFactors = new double[21];
+ //defines adjustment of zoom factor (should be close to 1)
+ //(used for perfect-fit sizing that requires arbitrary zoom)
+ private static double zoomAdjustmentFactor = 1;
private static double svgWidth = 75;
private static double svgHeight = svgWidth * 0.5 * Math.sqrt(3.0);
@@ -129,11 +132,28 @@ public class ImageLoader {
if (zoomStep < 0) zoomStep = 0;
else if (zoomStep > 20) zoomStep = 20;
if (zoomFactors[zoomStep] == 0.0) {
- zoomFactors[zoomStep] = 1.0 * Math.pow(2.0, 0.25*(zoomStep-10));
+ zoomFactors[zoomStep] = zoomAdjustmentFactor * Math.pow(2.0, 0.25*(zoomStep-10));
}
return zoomFactors[zoomStep];
}
+
+ /**
+ * @param zoomAdjustmentFactor Additional factor applied to zoom factor. Used
+ * for precisely adjusting zoom-step based zoom factors for perfect fit requirements.
+ */
+ public void setZoomAdjustmentFactor (double zoomAdjustmentFactor) {
+ ImageLoader.zoomAdjustmentFactor = zoomAdjustmentFactor;
+
+ //invalidate buffered zoom step zoom factors
+ for (int i = 0 ; i < zoomFactors.length ; i++) {
+ zoomFactors[i] = 0;
+ }
+ }
+
+ public void resetAdjustmentFactor() {
+ setZoomAdjustmentFactor(1);
+ }
public ImageLoader() {
directories.add(tileRootDir + svgTileDir);
diff --git a/rails/ui/swing/MapPanel.java b/rails/ui/swing/MapPanel.java
index e1be54b..6175b9b 100644
--- a/rails/ui/swing/MapPanel.java
+++ b/rails/ui/swing/MapPanel.java
@@ -20,11 +20,14 @@ import rails.ui.swing.hexmap.*;
public class MapPanel extends JPanel {
private static final long serialVersionUID = 1L;
+ //defines how many pixels should be left as safety margin when calculating fit zooms
+ private static final int zoomFitSafetyMargin = 4;
+
private MapManager mmgr;
private HexMap map;
private HexMapImage mapImage;
private JScrollPane scrollPane;
-
+
private GameUIManager gameUIManager;
private JLayeredPane layeredPane;
@@ -132,8 +135,80 @@ public class MapPanel extends JPanel {
adjustToNewMapZoom();
}
- private void zoomFit (boolean fitWidth, boolean fitHeight) {
- map.zoomFit (getSize(), fitWidth, fitHeight);
+ /**
+ * Zoom-to-fit functionality is based on the discrete zoom steps.
+ * In order to achieve correctly fitting zoom, continuous adjustment factors are
+ * determined on top of that.
+ */
+ private void zoomFit (boolean fitToWidth, boolean fitToHeight) {
+ ImageLoader imageLoader = GameUIManager.getImageLoader();
+ int zoomStep = map.getZoomStep();
+
+ //reset adjustment factor
+ imageLoader.resetAdjustmentFactor();
+
+ //determine the available size to fit to
+ //(double needed for subsequent calculations)
+ double width = getSize().width - zoomFitSafetyMargin;
+ double height = getSize().height - zoomFitSafetyMargin;
+
+ double idealFactorWidth = width / originalMapSize.width;
+ double idealFactorHeight = height / originalMapSize.height;
+
+ //determine which dimension will be the critical one for the resize
+ boolean isWidthCritical = ( !fitToHeight
+ || (fitToWidth && idealFactorWidth < idealFactorHeight));
+
+ //check whether scrollbar will appear in the fit-to dimension and
+ //reduce available size accordingly (not relevant for fit-to-window)
+ if (isWidthCritical && idealFactorWidth > idealFactorHeight) {
+ width -= scrollPane.getVerticalScrollBar().getPreferredSize().width;
+ idealFactorWidth = width / originalMapSize.width;
+ }
+ if (!isWidthCritical && idealFactorWidth < idealFactorHeight) {
+ height -= scrollPane.getHorizontalScrollBar().getPreferredSize().height;
+ idealFactorHeight = height / originalMapSize.height;
+ }
+
+ //abort resize if no space available
+ if (width < 0 || height < 0) return;
+
+ //increase zoomFactor until constraints do not hold
+ //OR zoom cannot be increased any more
+ while
+ (
+ (
+ (!fitToWidth || idealFactorWidth > imageLoader.getZoomFactor(zoomStep))
+ &&
+ (!fitToHeight || idealFactorHeight > imageLoader.getZoomFactor(zoomStep))
+ )
+ &&
+ imageLoader.getZoomFactor(zoomStep+1) != imageLoader.getZoomFactor(zoomStep)
+ )
+ zoomStep++;
+
+ //decrease zoomFactor until constraints do hold
+ //OR zoom cannot be decreased any more
+ while
+ (
+ (
+ (fitToWidth && idealFactorWidth < imageLoader.getZoomFactor(zoomStep))
+ ||
+ (fitToHeight && idealFactorHeight < imageLoader.getZoomFactor(zoomStep))
+ )
+ &&
+ imageLoader.getZoomFactor(zoomStep-1) != imageLoader.getZoomFactor(zoomStep)
+ )
+ zoomStep--;
+
+ //Determine and apply adjustment factor for precise fit
+ double idealFactor = isWidthCritical ? idealFactorWidth : idealFactorHeight;
+ imageLoader.setZoomAdjustmentFactor (
+ idealFactor / imageLoader.getZoomFactor(zoomStep));
+
+ //trigger zoom execution
+ map.setZoomStep(zoomStep);
+
adjustToNewMapZoom();
}
diff --git a/rails/ui/swing/hexmap/HexMap.java b/rails/ui/swing/hexmap/HexMap.java
index 0dc3c1a..e862f6d 100644
--- a/rails/ui/swing/hexmap/HexMap.java
+++ b/rails/ui/swing/hexmap/HexMap.java
@@ -562,43 +562,15 @@ public abstract class HexMap implements MouseListener,
zoom();
}
-/**
- * Zoom-to-fit functionality is based on the discrete zoom steps.
- * This means that no pixel precision is to be expected
- */
- public void zoomFit (Dimension availableSize, boolean fitToWidth, boolean fitToHeight) {
- double idealFactorWidth = availableSize.getWidth() / originalSize.width;
- double idealFactorHeight = availableSize.getHeight() / originalSize.height;
- //increase zoomFactor until constraints do not hold
- //OR zoom cannot be increased any more
- while
- (
- (
- (!fitToWidth || idealFactorWidth > GameUIManager.getImageLoader().getZoomFactor(zoomStep))
- &&
- (!fitToHeight || idealFactorHeight > GameUIManager.getImageLoader().getZoomFactor(zoomStep))
- )
- &&
- GameUIManager.getImageLoader().getZoomFactor(zoomStep+1) != GameUIManager.getImageLoader().getZoomFactor(zoomStep)
- )
- zoomStep++;
- //decrease zoomFactor until constraints do hold
- //OR zoom cannot be decreased any more
- while
- (
- (
- (fitToWidth && idealFactorWidth < GameUIManager.getImageLoader().getZoomFactor(zoomStep))
- ||
- (fitToHeight && idealFactorHeight < GameUIManager.getImageLoader().getZoomFactor(zoomStep))
- )
- &&
- GameUIManager.getImageLoader().getZoomFactor(zoomStep-1) != GameUIManager.getImageLoader().getZoomFactor(zoomStep)
- )
- zoomStep--;
- //trigger zoom execution
+ public void setZoomStep (int zoomStep) {
+ this.zoomStep = zoomStep;
zoom();
}
+ public int getZoomStep () {
+ return zoomStep;
+ }
+
private void zoom() {
zoomFactor = GameUIManager.getImageLoader().getZoomFactor(zoomStep);
log.debug("HexMap: zoomStep = "+ zoomStep);
@@ -614,10 +586,6 @@ public abstract class HexMap implements MouseListener,
scale = (Scale.get() * zoomFactor);
}
- public int getZoomStep () {
- return zoomStep;
- }
-
public Dimension getOriginalSize() {
return originalSize;
}
|