/* * AP(r) Computer Science GridWorld Case Study: * Copyright(c) 2002-2006 College Entrance Examination Board * (http://www.collegeboard.com). * * This code is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License 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 for more details. * * @author Julie Zelenski * @author Cay Horstmann */ package info.gridworld.gui; import java.awt.Rectangle; import java.beans.*; import java.lang.reflect.*; import java.awt.Component; import java.awt.Graphics2D; import java.awt.BasicStroke; /** * This class provides common implementation code for drawing objects. It will * translate, scale, and rotate the graphics system as needed and then invoke * its abstract <code>draw</code> method. Subclasses of this abstract class * define <code>draw</code> to display an object in a fixed size and * orientation. <br /> * This code is not tested on the AP CS A and AB exams. It contains GUI * implementation details that are not intended to be understood by AP CS * students. */ public abstract class AbstractDisplay implements Display { /** * Draw the given object. Subclasses should implement this method to draw * the occupant facing North in a cell of size (1,1) centered around (0,0) on * the drawing surface. (All scaling/rotating has been done beforehand). * @param obj the occupant we want to draw * @param comp the component on which to draw * @param g2 the graphics context */ abstract public void draw(Object obj, Component comp, Graphics2D g2); /** * Draw the given object. Scales and rotates the coordinate appropriately * then invokes the simple draw method above that is only responsible for * drawing a unit-length occupant facing North. * @param obj the occupant we want to draw * @param comp the component on which to draw * @param g2 the graphics context * @param rect rectangle in which to draw */ public void draw(Object obj, Component comp, Graphics2D g2, Rectangle rect) { float scaleFactor = Math.min(rect.width, rect.height); g2 = (Graphics2D) g2.create(); // Translate to center of the object g2.translate(rect.x + rect.width / 2.0, rect.y + rect.height / 2.0); // Rotate drawing surface before drawing to capture object's // orientation (direction). if (obj != null) { Integer direction = (Integer) getProperty(obj, "direction"); int rotationInDegrees = direction == null ? 0 : direction .intValue(); g2.rotate(Math.toRadians(rotationInDegrees)); } // Scale to size of rectangle, adjust stroke back to 1-pixel wide g2.scale(scaleFactor, scaleFactor); g2.setStroke(new BasicStroke(1.0f / scaleFactor)); draw(obj, comp, g2); } public static Object getProperty(Object obj, String propertyName) { if (obj == null) return null; try { BeanInfo info = Introspector.getBeanInfo(obj.getClass()); PropertyDescriptor[] descriptors = info.getPropertyDescriptors(); for (int i = 0; i < descriptors.length; i++) { if (descriptors[i].getName().equals(propertyName)) { Method getter = descriptors[i].getReadMethod(); if (getter == null) return null; try { return getter.invoke(obj); } catch (Exception ex) { System.out.println(descriptors[i].getName()); return null; } } } } catch (Exception ex) { ex.printStackTrace(); } return null; } }