/* * Copyright (C) 2007 Snorre Gylterud, Stein Magnus Jodal, Johannes Knutsen, * Erik Bagge Ottesen, Ralf Bjarne Taraldset, and Iterate AS * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 * as published by the Free Software Foundation. */ package no.ntnu.mmfplanner.util; import java.awt.Color; import java.awt.Font; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.font.FontRenderContext; import java.awt.geom.Rectangle2D; import java.util.ArrayList; import java.util.StringTokenizer; /** * Utility functions for the Graphical User Interface. */ public class GuiUtil { /** * Finds the correct grayscale for the given color. Uses human visual * priorities on each of the color parts, specifically green is weighted * higher and blue lower. This method is deterministic. * * @param color the color to calculate grayscale for * @return a value from 0 to 255 giving the grayscale value of the given * color. */ public static int getGrayscale(Color color) { return (color.getRed() * 299 + color.getGreen() * 587 + color.getBlue() * 114) / 1000; } /** * Returns the appropriate foreground color for the given background color. * This uses the getGrayscale() method and returns Color.BLACK for the 3/8 * darkest colors, and Color.WHITE for the lightest colors. * * @param color the given background color * @return the appropriate foreground/text color */ public static Color getBlackWhiteColor(Color color) { return getGrayscale(color) < 96 ? Color.WHITE : Color.BLACK; } /** * Returns a string representation of the given color. For now this contains * only names of TangoColors. For all unknown colors a hexadecimal * representation is given. * * @param color * @return string representation either as a proper name or hexadecimal * notation. */ public static final String getColorName(Color color) { for (int i = 0; i < TangoColor.TANGO_COLORS.length; i++) { if (color.equals(TangoColor.TANGO_COLORS[i])) { return TangoColor.TANGO_NAMES[i]; } } // If color is not found, default to hex color return getColorString(color); } /** * Returns a hexadecimal string representation of the given color. * * @param color * @return string representation in hexadecimal notation. */ public static final String getColorString(Color color) { return Integer.toHexString(color.getRGB()).substring(2).toUpperCase(); } /** * Draws a horizontal/vertical centered string inside a rectangle on a * graphics Chops off the string if it too long and adds "..." * * @param g2 Graphic to draw on * @param rectangle Rectangle to draw centered in * @param text String to draw * @see wrapString() */ public static void drawCenteredString(Graphics2D g2, Rectangle2D rectangle, String text) { if ((text == null) || "".equals(text)) { return; } g2.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_OFF); Font font = g2.getFont(); double fontHeight = font.getStringBounds(text, g2.getFontRenderContext()).getHeight(); int maxLines = (int) (rectangle.getHeight() / fontHeight); String[] lines = GuiUtil.wrapString(g2, text, rectangle.getWidth()); int linesToDraw = Math.min(lines.length, maxLines); // initial y-pos double yPos = rectangle.getY() + (rectangle.getHeight() - linesToDraw * fontHeight) / 2; yPos -= fontHeight - g2.getFontMetrics().getMaxAscent(); // chop lastline and adds "..." if (lines.length > maxLines) { String lastLine = lines[maxLines - 1]; lastLine += "..."; int j = 1; while (font.getStringBounds(lastLine, g2.getFontRenderContext()) .getWidth() > rectangle.getWidth()) { lastLine = lastLine.substring(0, lastLine.length() - 3 - j) + "..."; j++; } lines[maxLines - 1] = lastLine; } // draw lines for (int i = 0; i < linesToDraw; i++) { double lineWidth = g2.getFont().getStringBounds(lines[i], g2.getFontRenderContext()).getWidth(); yPos += fontHeight; double xPos = rectangle.getX() + (int) ((rectangle.getWidth() - lineWidth) / 2); g2.drawString(lines[i], (float) (xPos), (float) yPos); } g2.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); } /** * Wraps a string according to width * * @param g2 Graphic to get font from * @param string String to wrap * @param width Width the string must fit into * @return */ public static String[] wrapString(Graphics2D g2, String string, double width) { FontRenderContext frc = g2.getFontRenderContext(); Font font = g2.getFont(); // Split string into tokens, split by spaces StringTokenizer st = new StringTokenizer(string, " "); ArrayList<String> wrappedString = new ArrayList<String>(); int i; while (st.hasMoreTokens()) { i = wrappedString.size() - 1; String nextToken = st.nextToken(); // Place next token on current line if possible, // else add a new line with the token. if ((i > -1) && (font.getStringBounds( wrappedString.get(i) + " " + nextToken, frc) .getWidth() < width)) { String nextLineString = wrappedString.get(i) + " " + nextToken; wrappedString.set(i, nextLineString); } else { // Wrap words that are too long... while (font.getStringBounds(nextToken, frc).getWidth() > width) { String part = ""; int j; for (j = 0; font.getStringBounds(part, frc).getWidth() < width; j++) { part = nextToken.substring(0, j); } nextToken = nextToken.substring(j - 1); wrappedString.add(part); } // Insert nextToken or the part that is left after wordwrap wrappedString.add(nextToken); } } return wrappedString.toArray(new String[0]); } }