9 package micropolisj.gui;
12 import java.awt.event.*;
13 import java.awt.image.*;
17 import javax.swing.event.*;
18 import javax.swing.Timer;
20 import micropolisj.engine.*;
21 import static micropolisj.engine.TileConstants.*;
22 import static micropolisj.gui.ColorParser.parseColor;
25 implements Scrollable, MapListener
28 boolean blinkUnpoweredZones =
true;
29 HashSet<Point> unpoweredZones =
new HashSet<Point>();
32 ToolCursor toolCursor;
33 ToolPreview toolPreview;
36 static final Dimension PREFERRED_VIEWPORT_SIZE =
new Dimension(640,640);
37 static final ResourceBundle strings =
MainWindow.strings;
39 static final int DEFAULT_TILE_SIZE = 16;
52 addAncestorListener(
new AncestorListener() {
53 public void ancestorAdded(AncestorEvent evt) {
56 public void ancestorRemoved(AncestorEvent evt) {
59 public void ancestorMoved(AncestorEvent evt) {}
62 addMouseListener(
new MouseListener() {
65 public void mousePressed(MouseEvent e) {
66 if(e.getButton()==MouseEvent.BUTTON2)
71 public void mouseReleased(MouseEvent e) {
72 if(e.getButton()==MouseEvent.BUTTON2)
77 public void mouseEntered(MouseEvent e) {
81 public void mouseExited(MouseEvent e) {
85 public void mouseClicked(MouseEvent e) {
89 addMouseMotionListener(
new MouseMotionListener() {
92 public void mouseMoved(MouseEvent e) {
96 public void mouseDragged(MouseEvent e) {
106 TILE_WIDTH = tileImages.TILE_WIDTH;
107 TILE_HEIGHT = tileImages.TILE_HEIGHT;
118 return new CityLocation(x / TILE_WIDTH, y / TILE_HEIGHT);
124 assert this.m != null;
131 assert newEngine != null;
133 if (this.m != null) {
137 if (this.m != null) {
146 void drawSprite(Graphics gr, Sprite sprite)
148 assert sprite.isVisible();
151 (sprite.x + sprite.offx) * TILE_WIDTH / 16,
152 (sprite.y + sprite.offy) * TILE_HEIGHT / 16
155 Image img = tileImages.
getSpriteImage(sprite.kind, sprite.frame-1);
157 gr.drawImage(img, p.x, p.y, null);
160 gr.setColor(Color.RED);
161 gr.fillRect(p.x, p.y, 16, 16);
162 gr.setColor(Color.WHITE);
163 gr.drawString(Integer.toString(sprite.frame-1),p.x,p.y);
172 Rectangle clipRect = gr.getClipBounds();
173 int minX = Math.max(0, clipRect.x / TILE_WIDTH);
174 int minY = Math.max(0, clipRect.y / TILE_HEIGHT);
175 int maxX = Math.min(width, 1 + (clipRect.x + clipRect.width-1) / TILE_WIDTH);
176 int maxY = Math.min(height, 1 + (clipRect.y + clipRect.height-1) / TILE_HEIGHT);
178 for (
int y = minY; y < maxY; y++)
180 for (
int x = minX; x < maxX; x++)
183 if (blinkUnpoweredZones &&
184 isZoneCenter(cell) &&
187 unpoweredZones.add(
new Point(x,y));
189 cell = LIGHTNINGBOLT;
192 if (toolPreview != null) {
193 int c = toolPreview.getTile(x, y);
200 x*TILE_WIDTH + (shakeStep != 0 ? getShakeModifier(y) : 0),
208 if (sprite.isVisible())
210 drawSprite(gr, sprite);
214 if (toolCursor != null)
216 int x0 = toolCursor.rect.x * TILE_WIDTH;
217 int x1 = (toolCursor.rect.x + toolCursor.rect.width) * TILE_WIDTH;
218 int y0 = toolCursor.rect.y * TILE_HEIGHT;
219 int y1 = (toolCursor.rect.y + toolCursor.rect.height) * TILE_HEIGHT;
221 gr.setColor(Color.BLACK);
222 gr.drawLine(x0-1,y0-1,x0-1,y1-1);
223 gr.drawLine(x0-1,y0-1,x1-1,y0-1);
224 gr.drawLine(x1+3,y0-3,x1+3,y1+3);
225 gr.drawLine(x0-3,y1+3,x1+3,y1+3);
227 gr.setColor(toolCursor.borderColor);
228 gr.drawRect(x0-3,y0-3,x1-x0+5,y1-y0+5);
229 gr.drawRect(x0-2,y0-2,x1-x0+3,y1-y0+3);
231 gr.setColor(Color.WHITE);
232 gr.drawLine(x0-3,y0-3,x1+3,y0-3);
233 gr.drawLine(x0-3,y0-3,x0-3,y1+3);
234 gr.drawLine(x1, y0-1,x1, y1 );
235 gr.drawLine(x0-1,y1, x1, y1 );
237 if (toolCursor.fillColor != null) {
238 gr.setColor(toolCursor.fillColor);
239 gr.fillRect(x0,y0,x1-x0,y1-y0);
244 static class ToolCursor
253 ToolCursor tp =
new ToolCursor();
255 tp.borderColor = parseColor(
256 strings.containsKey(
"tool."+tool.name()+
".border") ?
257 strings.getString(
"tool."+tool.name()+
".border") :
258 strings.getString(
"tool.*.border")
260 tp.fillColor = parseColor(
261 strings.containsKey(
"tool."+tool.name()+
".bgcolor") ?
262 strings.getString(
"tool."+tool.name()+
".bgcolor") :
263 strings.getString(
"tool.*.bgcolor")
270 if (toolCursor == newCursor)
272 if (toolCursor != null && toolCursor.equals(newCursor))
275 if (toolCursor != null)
277 repaint(
new Rectangle(
278 toolCursor.rect.x*TILE_WIDTH - 4,
279 toolCursor.rect.y*TILE_HEIGHT - 4,
280 toolCursor.rect.width*TILE_WIDTH + 8,
281 toolCursor.rect.height*TILE_HEIGHT + 8
284 toolCursor = newCursor;
285 if (toolCursor != null)
287 repaint(
new Rectangle(
288 toolCursor.rect.x*TILE_WIDTH - 4,
289 toolCursor.rect.y*TILE_HEIGHT - 4,
290 toolCursor.rect.width*TILE_WIDTH + 8,
291 toolCursor.rect.height*TILE_HEIGHT + 8
298 if (toolPreview != null) {
299 CityRect b = toolPreview.getBounds();
300 Rectangle r =
new Rectangle(
309 toolPreview = newPreview;
310 if (toolPreview != null) {
312 CityRect b = toolPreview.getBounds();
313 Rectangle r =
new Rectangle(
326 return PREFERRED_VIEWPORT_SIZE;
332 if (orientation == SwingConstants.VERTICAL)
333 return visibleRect.height;
335 return visibleRect.width;
353 if (orientation == SwingConstants.VERTICAL)
354 return TILE_HEIGHT * 3;
356 return TILE_WIDTH * 3;
361 return new Rectangle(
362 (x+sprite.offx)*TILE_WIDTH/16,
363 (y+sprite.offy)*TILE_HEIGHT/16,
364 sprite.width*TILE_WIDTH/16,
365 sprite.height*TILE_HEIGHT/16
371 return new Rectangle(xpos*TILE_WIDTH, ypos * TILE_HEIGHT,
372 TILE_WIDTH, TILE_HEIGHT);
413 JScrollPane js = (JScrollPane)getParent().getParent();
414 js.getHorizontalScrollBar().setValue(
415 js.getHorizontalScrollBar().getValue()-dx);
416 js.getVerticalScrollBar().setValue(
417 js.getVerticalScrollBar().getValue()-dy);
422 if (!unpoweredZones.isEmpty())
425 for (Point loc : unpoweredZones)
429 unpoweredZones.clear();
433 void startBlinkTimer()
435 assert blinkTimer == null;
437 ActionListener callback =
new ActionListener() {
438 public void actionPerformed(ActionEvent evt)
444 blinkTimer =
new Timer(500, callback);
448 void stopBlinkTimer()
450 if (blinkTimer != null) {
462 static final int SHAKE_STEPS = 40;
463 int getShakeModifier(
int row)
465 return (
int)Math.round(4.0 * Math.sin((
double)(shakeStep+row/2)/2.0));