MapCanvas.java
/*
$RCSfile: MapCanvas.java,v $
$Id: MapCanvas.java,v 1.6 1998/11/30 02:21:07 devnull Exp $
by Lee Wilson, http://www.ad1440.net/~devnull
Development started on 1998 10 01
(c) Devnull Software, LLC. (http://www.devnullsoftware.com)
*/
package com.devnullsoftware.javaterrain;
/**
Performs the actual drawing of the map.
@author Lee Wilson
@version 1.0
*/
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class MapCanvas extends JPanel {
//-------------------------------------------------------------------
// Global Constants
//
public static final int [] HEXSIZE = {
9,13,25,49,99
};
public static final int VIEW_TERRAIN = 0;
public static final int VIEW_TEMPERATURE = 1;
public static final int VIEW_RAINFALL = 2;
public static final int VIEW_ELEVATION = 3;
//-------------------------------------------------------------------
// Instance Variables
//
private Map pMap = null;
int iZoomLevel = 2;
int iViewMode = VIEW_TERRAIN;
Dimension pPreferredSize = new Dimension (300,300);
MapWindow pMapWindow = null;
private Dimension pCanvasSize = new Dimension ();
private SmallViewPanel pSmallView = null;
//-------------------------------------------------------------------
// Constructors
//
MapCanvas (Map m, MapWindow pMapWindow) {
super (true);
pMap = m;
this.pMapWindow = pMapWindow;
init ();
}
private void init () {
Hex.rescaleImages(pMap.pParams.pTerrainImage, iZoomLevel);
pSmallView = new SmallViewPanel();
}
//-------------------------------------------------------------------
// Accessors & Mutators
//
public Component getSmallView () {
return pSmallView;
}
public void setSmallViewSize(int width, int height) {
pSmallView.setSize(width, height);
pSmallView.setPreferredSize(new Dimension(width, height));
}
public Dimension getSmallViewSize() {
return pSmallView.getSize();
}
public void setSmallViewPort (Rectangle pRect) {
Rectangle pNewRect = new Rectangle();
Dimension pSmallSize = getSmallViewSize();
float fXScale = (float)pCanvasSize.width/(float)pSmallSize.width;
float fYScale = (float)pCanvasSize.height/(float)pSmallSize.height;
pNewRect.x = (int)((float)pRect.x / fXScale);
pNewRect.y = (int)((float)pRect.y / fYScale);
pNewRect.width = (int)((float)pRect.width / fXScale);
pNewRect.height = (int)((float)pRect.height / fYScale);
pSmallView.setViewRect(pNewRect);
pSmallView.repaint();
}
public void zoomIn () {
if (iZoomLevel < (HEXSIZE.length-1)) {
iZoomLevel++;
Hex.rescaleImages(pMap.pParams.pTerrainImage, iZoomLevel);
repaint();
}
}
public void zoomOut () {
if (iZoomLevel > 0) {
iZoomLevel--;
Hex.rescaleImages(pMap.pParams.pTerrainImage, iZoomLevel);
repaint();
}
}
public int getViewMode () {
return iViewMode;
}
public void setViewMode (int i) {
iViewMode = i;
repaint();
}
//-------------------------------------------------------------------
// Security
//
//-------------------------------------------------------------------
// Overridden Methods
//
public Dimension getPreferredSize() {
return pPreferredSize;
}
public void paintComponent (Graphics g) {
int x,y;
int i;
float fHeightCenter, fHeightAdjustment;
float fWidthAdjustment, fWidthCenter;
float fHexWidth, fHexHeight;
int xPoints[] = new int[6];
int yPoints[] = new int[6];
Hex pTempHex, pTempNeighborHex;
fHexWidth = fHexHeight = (float)HEXSIZE[iZoomLevel];
fWidthCenter = fHexWidth / 2.0f;
fWidthAdjustment = fHexWidth / 4.0f;
fHeightCenter = fHexHeight / 2.0f;
pCanvasSize.width = Math.round ((
(
(float)pMap.getDimension()
* (fWidthCenter+fWidthAdjustment)
)
+ (fHexWidth * 2.0f)
));
pCanvasSize.height = Math.round(((float)pMap.getDimension() * fHexHeight) + (fHexHeight * 3.0f));
pPreferredSize = pCanvasSize;
setSize(pCanvasSize);
Rectangle pRect = pMapWindow.pMapScrollPane.getViewport().getViewRect();
g.setClip(pRect);
setSmallViewPort(pRect);
pMapWindow.pMapScrollPane.getHorizontalScrollBar().setUnitIncrement((int)fHexWidth);
pMapWindow.pMapScrollPane.getVerticalScrollBar().setUnitIncrement((int)fHexHeight);
g.setColor (Color.black);
g.fillRect (0, 0, pCanvasSize.width, pCanvasSize.height);
for (x = 0; x < pMap.getDimension(); x++) {
if (x % 2 == 0) {
fHeightAdjustment = fHexHeight / 2.0f;
}
else {
fHeightAdjustment = 0.0f;
}
for (y = 0; y < pMap.getDimension(); y++) {
xPoints[0] = Math.round((
fHexWidth
+ ((float)x * (fWidthCenter + fWidthAdjustment))
+ fWidthCenter
- fWidthAdjustment
));
yPoints[0] = Math.round(
fHexHeight
+ ((float)y * fHexHeight)
+ fHeightAdjustment
);
if (g.hitClip(xPoints[0], yPoints[0],
(int)fHexWidth, (int)fHexHeight)) {
xPoints[1] = Math.round(
fHexWidth
+ ((float)x
* (fWidthCenter + fWidthAdjustment))
+ fWidthCenter
+ fWidthAdjustment
);
yPoints[1] = yPoints[0];
xPoints[2] = Math.round(
fHexWidth
+ (fHexWidth
+ ((float)x
* (fWidthCenter + fWidthAdjustment))
- 1.0f
)
);
yPoints[2] = Math.round(yPoints[0] + (int)fHeightCenter);
xPoints[3] = xPoints[1];
yPoints[3] = Math.round(
fHexHeight
+ (((float)y + 1.0f) * fHexHeight)
+ fHeightAdjustment
- 1.0f
);
xPoints[4] = xPoints[0];
yPoints[4] = yPoints[3];
xPoints[5] = Math.round(
fHexWidth
+ ((float)x
* (fWidthCenter + fWidthAdjustment))
);
yPoints[5] = yPoints[2];
// Draw Hex border
Polygon pHexBorder = new Polygon(xPoints, yPoints, 6);
Rectangle pHexRect = pHexBorder.getBounds();
if (pRect.contains(pHexRect)) {
switch (getViewMode()) {
case VIEW_TEMPERATURE:
case VIEW_RAINFALL:
case VIEW_ELEVATION:
pTempHex = pMap.getHex(x,y);
for (i = 0; i < 6; i++) {
if (pTempHex.isShoreline (Hex.BW_DIRS[i])) {
g.setColor(Color.black);
}
else {
g.setColor(Color.white);
}
g.drawLine(xPoints[i], yPoints[i], xPoints[(i+1)%6], yPoints[(i+1)%6]);
}
break;
case VIEW_TERRAIN:
default:
g.setColor(Color.white);
g.drawPolygon(pHexBorder);
break;
}
// Draw Hex Inside
yPoints[0] += 1;
yPoints[1] += 1;
xPoints[2] -= 1;
yPoints[3] -= 1;
yPoints[4] -= 1;
xPoints[5] += 1;
Polygon pHexInside = new Polygon(xPoints, yPoints, 6);
pMap.getHex(x,y).paintHex(g,pHexInside,iZoomLevel,iViewMode);
}
}
}
}
}
public class SmallViewPanel extends JPanel implements MouseListener {
Image offscreen;
Image pScaledImage;
Rectangle pViewRect;
Dimension pLastScreenSize;
SmallViewPanel () {
super();
init ();
}
private void init () {
addMouseListener (this);
}
public void setViewRect (Rectangle pRect) {
pViewRect = pRect;
}
public void paintComponent (Graphics g) {
Dimension d = getSize();
if ( pLastScreenSize == null
|| pLastScreenSize.width != d.width
|| pLastScreenSize.height != d.height
|| pScaledImage == null) {
Graphics offgraphics;
MediaTracker pTracker
= new MediaTracker (Main.pThisApplet);
if (pScaledImage != null) {
pScaledImage.flush();
}
pScaledImage = null;
pLastScreenSize = d;
if (offscreen == null) {
offscreen = createImage (pMap.getDimension(),
pMap.getDimension());
}
offgraphics = offscreen.getGraphics();
offgraphics.setColor (Color.black);
offgraphics.fillRect (0, 0,
pMap.getDimension(),pMap.getDimension());
for (int x = 0; x < pMap.getDimension(); x++) {
for (int y = 0; y < pMap.getDimension(); y++) {
offgraphics.setColor(Hex.COLOR_TERRAIN[pMap.getHex(x,y).getTerrainType()]);
offgraphics.drawLine (x,y,x,y);
}
}
offgraphics.dispose();
pScaledImage = offscreen.getScaledInstance(d.width, d.height,
Image.SCALE_FAST);
pTracker.addImage(pScaledImage, 0);
try {
pTracker.waitForID(0);
}
catch (InterruptedException e) {
}
}
g.drawImage(pScaledImage, 0, 0, null);
if (pViewRect != null) {
g.setColor(Color.black);
g.drawRect(pViewRect.x, pViewRect.y, pViewRect.width, pViewRect.height);
}
}
//------------------------------------------------------------------------
// MouseListener Interface
//
public void mouseClicked(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
if (pViewRect == null) {
return;
}
pViewRect.x = e.getX() - (pViewRect.width / 2);
pViewRect.y = e.getY() - (pViewRect.height / 2);
Dimension pSmallSize = getSmallViewSize();
pMapWindow.pMapScrollPane.getViewport().setViewPosition
(new Point ((int)((float)pViewRect.x
* (float)pCanvasSize.width
/ (float)pSmallSize.width
),
(int)((float)pViewRect.y
* (float)pCanvasSize.height
/ (float)pSmallSize.height
)
)
);
repaint();
}
public void mouseReleased (MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
}
}