Java tutorial
/* * Java Terrain and Stellar System Ports * * Copyright (C) 2006 Martin H. Smith based on work by original * authors. * * Released under the terms of the GNU General Public License * * This program 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; either version 2 * of the License, or (at your option) any later version. * * This program 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301, USA. * * Linking TerraJ statically or dynamically with other modules is making a * combined work based on TerraJ. Thus, the terms and conditions of the * GNU General Public License cover the whole combination. * * In addition, as a special exception, the copyright holders of TerraJ * give you permission to combine this program with free software programs * or libraries that are released under the GNU LGPL and with code included * in the standard release of JOGL, Java Getopt and FreeMarker under the BSD * license (or modified versions of such code, with unchanged license) and with * Apache Commons and Log4J libraries under the Apache license (or modified versions * of such code. You may copy and distribute such a system following the terms * of the GNU GPL for TerraJ and the licenses of the other code concerned, * provided that you include the source code of that other code when and as the * GNU GPL requires distribution of source code. * * Note that people who make modified versions of TerraJ are not obligated to grant * this special exception for their modified versions; it is their choice whether * to do so. The GNU General Public License gives permission to release a modified * version without this exception; this exception also makes it possible to release * a modified version which carries forward this exception. */ /* * UIUtils.java * * Created on 19 April 2006, 21:21 */ package com.alvermont.terraj.stargen.ui; import com.alvermont.terraj.stargen.Constants; import com.alvermont.terraj.stargen.Enviro; import com.alvermont.terraj.stargen.Planet; import com.alvermont.terraj.stargen.PlanetType; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics2D; import java.awt.geom.AffineTransform; import java.awt.image.BufferedImage; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import javax.imageio.ImageIO; import javax.swing.ImageIcon; import javax.swing.JLabel; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * Some utility functions useful to the UI * * @author martin * @version $Id: UIUtils.java,v 1.7 2006/07/06 06:58:35 martin Exp $ */ public class UIUtils { /** Our logger object */ private static Log log = LogFactory.getLog(UIUtils.class); private static Enviro enviro = new Enviro(); /** Creates a new instance of UIUtils */ public UIUtils() { } /** * Get the size in pixels to be used for displaying a planet icon. This * will be derived from its actual size. * * @param planet The planet to get the icon size for * @return The size in pixels to be used for the planet. This assumes the * icons will be square */ public static int getSizeInPixels(Planet planet) { int pixels = ((int) (Math.sqrt(planet.getRadius() / Constants.KM_EARTH_RADIUS) * 30.0)) + 1; if (planet.getType() == PlanetType.ASTEROIDS) { pixels = (int) (25.0 + (5.0 * Math .log((planet.getMass() * Constants.SUN_MASS_IN_EARTH_MASSES) / Constants.ASTEROID_MASS_LIMIT))); } pixels = Math.max(pixels, 3); return pixels; } /** * Get an information string about the planet. This will include its type, * mass and orbital zone where appropriate. * * @param planet The planet to get the information for * @return A short descriptive string about the planet suitable for use * as a tooltip or alt text in a web page */ public static String getInfo(Planet planet) { if ((planet.getType() == PlanetType.GASGIANT) || (planet.getType() == PlanetType.SUBGASGIANT) || (planet.getType() == PlanetType.SUBSUBGASGIANT)) { double estTemp = enviro.getEstTemp(planet.getPrimary().getREcosphere(), planet.getOrbitZone(), planet.getAlbedo()); return String.format("%s: %.1fEM (c. %.0f°)", planet.getType().getPrintText(), planet.getMass() * Constants.SUN_MASS_IN_EARTH_MASSES, estTemp); } else if (planet.getType() == PlanetType.UNKNOWN) { return String.format("%s: %.1fEM, %.2fEM from gas (%.1f%c) Zone = %d", planet.getType().getPrintText(), planet.getMass() * Constants.SUN_MASS_IN_EARTH_MASSES, planet.getGasMass() * Constants.SUN_MASS_IN_EARTH_MASSES, 100.0 * (planet.getGasMass() / planet.getMass()), '%', planet.getOrbitZone()); } else { return String.format("%s: %.2fEM, %.2fg, %.1f° Zone = %d", planet.getType().getPrintText(), planet.getMass() * Constants.SUN_MASS_IN_EARTH_MASSES, planet.getSurfaceGravity(), (planet.getSurfaceTemperature() - Constants.FREEZING_POINT_OF_WATER), planet.getOrbitZone()); } } /** * Get an input stream to an image for a planet via a resource * * @param imageName The name of the planetary resource to be located * @return An input stream to the resource data or null if it was not * found */ public static InputStream getImageResourceStream(String imageName) { InputStream stream = UIUtils.class .getResourceAsStream("/com/alvermont/terraj/stargen/images/" + imageName + "Planet.png"); if (stream == null) { stream = UIUtils.class .getResourceAsStream("/com/alvermont/terraj/stargen/images/" + imageName + ".png"); } return stream; } /** * Get the name of a planetary image to be used in HTML format output * * @param planet The planet to get the image name for * @return A string suitable for use in HTML as the target of an img src */ public static String getHtmlImageName(Planet planet) { String name = planet.getType().getPrintText(); return name + "Planet.png"; } /** * Get an image by name using the resource mechanism * * @param imageName The name of the image to be obtained * @throws java.io.IOException If there is an error reading the image * @return A <code>BufferedImage</code> containing the image */ public static BufferedImage getImage(String imageName) throws IOException { return ImageIO.read(getImageResourceStream(imageName)); } /** * Scale an image to a particular X and Y size in pixels * * @param image The image to be scaled * @param pixelsX The desired horizontal size in pixels * @param pixelsY The desired vertical size in pixels * @return A new image scaled to the requested dimensions */ public static BufferedImage scaleImage(BufferedImage image, int pixelsX, int pixelsY) { int actualWidth = image.getWidth(); int actualHeight = image.getHeight(); // work out the scale factor double sx = (float) (pixelsX) / actualWidth; double sy = (float) (pixelsY) / actualHeight; BufferedImage nbi = new BufferedImage(pixelsX, pixelsY, image.getType()); Graphics2D g2 = nbi.createGraphics(); AffineTransform at = AffineTransform.getScaleInstance(sx, sy); g2.setTransform(at); g2.drawImage(image, 0, 0, null); return nbi; } /** * Get a list of images to be used for a list of planets * * @param planets The list of planets to get images for * @throws java.io.IOException If there is an error building the images * @return A list containing an image for each planet in the same order * as the input list */ public static List<BufferedImage> getPlanetImages(List<Planet> planets) throws IOException { List<BufferedImage> images = new ArrayList<BufferedImage>(); for (Planet p : planets) { try { String name = p.getType().getPrintText(p.getType()); BufferedImage bi = UIUtils.getImage(name); bi = UIUtils.scaleImage(bi, UIUtils.getSizeInPixels(p), UIUtils.getSizeInPixels(p)); images.add(bi); } catch (IOException ex) { log.error("Error loading icon: " + ex); throw ex; } } return images; } /** * Build a list of label objects from a list of planets * * @param planets The list of planets to build labels for * @throws java.io.IOException If there is an error building the labels * @return A list of <code>JLabel</code> objects in the same order as the * input list */ public static List<JLabel> buildImages(List<Planet> planets) throws IOException { List<JLabel> labels = new ArrayList<JLabel>(); List<BufferedImage> images = getPlanetImages(planets); Planet p = planets.get(0); for (BufferedImage bi : images) { ImageIcon icon = new ImageIcon(bi); JLabel label = new JLabel(icon); label.setPreferredSize(new Dimension(bi.getWidth(), bi.getHeight())); label.setMinimumSize(new Dimension(bi.getWidth(), bi.getHeight())); label.setToolTipText("<html>" + UIUtils.getInfo(p) + "</html>"); labels.add(label); log.debug("Added icon for planet " + p.getNumber() + " size " + bi.getWidth() + "," + bi.getHeight()); p = p.getNextPlanet(); } return labels; } /** * Get a JLabel object to display with star details * * @throws java.io.IOException If there is an error building the list * @return A <code>JLabel</code> representing the star */ public static JLabel getSunLabel() throws IOException { BufferedImage bi = UIUtils.getImage("Sun"); bi = UIUtils.scaleImage(bi, 30, 120); ImageIcon icon = new ImageIcon(bi); JLabel label = new JLabel(icon); label.setPreferredSize(new Dimension(bi.getWidth(), bi.getHeight())); label.setMinimumSize(new Dimension(bi.getWidth(), bi.getHeight())); label.setToolTipText("The Star"); return label; } /** * Combine a list of images horizontally into one new image. * * @param images The list of images to be combined * @return A new image, as wide horizontally as the sum of the input images, * containing all the input images */ public static BufferedImage combineImagesHorizontal(List<BufferedImage> images) { int imageType = -1; int height = 0; int width = 0; // first work out the sizing and image type, we assume the images // are all compatible. for (BufferedImage image : images) { if (imageType == -1) { imageType = image.getType(); } width += image.getWidth(); height = Math.max(height, image.getHeight()); } // create the new image and clear it to black BufferedImage bi = new BufferedImage(width, height, imageType); Graphics2D g = bi.createGraphics(); g.setColor(Color.BLACK); g.fillRect(0, 0, width, height); // merge the images into the new one int xpos = 0; for (BufferedImage image : images) { int ypos = (height - image.getHeight()) / 2; g.drawImage(image, xpos, ypos, null); xpos += image.getWidth(); } return bi; } }