/** * Copyright (C) 2013 Tokanagrammar Team * * This is a jigsaw-like puzzle game, * except each piece is token from a source file, * and the 'complete picture' is the program. * * 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 3 of the License, or * 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, see <http://www.gnu.org/licenses/>. */ package edu.umb.cs.gui; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Image; import java.awt.image.BufferedImage; import java.io.IOException; import java.util.LinkedList; import java.util.List; import javafx.embed.swing.SwingFXUtils; import javafx.scene.image.WritableImage; import javax.imageio.ImageIO; import edu.umb.cs.source.SourceToken; import edu.umb.cs.source.SourceTokenKind; /** * @author Matt */ public class RHSTokenIconizer { final static int TOKEN_HEIGHT = 20; //token height is always the same final static int MIN_WIDTH = 32; //the minimum token width final static Font tokenFont = new Font("Courier New", Image.SCALE_DEFAULT, 12); private static int index; /** * Takes a list of SourceToken intended for the RHS and creates * RHSIconizedTokens from them. * @param tokens * @return a list of IconizedTokens */ public static List<RHSIconizedToken> iconizeTokens(List<SourceToken> tokens) { index = 0; LinkedList<RHSIconizedToken> iconizedTokens = new LinkedList<RHSIconizedToken>(); for (SourceToken token : tokens) iconizedTokens.add(iconizeToken(token)); return iconizedTokens; } /** * Take a token and makes a graphic representation of it. * This is a sub-routine of iconizeTokens(..). * @param token * @return an IconizedToken */ private static RHSIconizedToken iconizeToken(SourceToken token) { SourceTokenKind kind = token.kind(); BufferedImage image = null; BufferedImage finalImage = null; Graphics graphics = null; int imagePadding = 20; try { switch(kind) { case KEYWORD: image = ImageIO.read(Thread.currentThread().getContextClassLoader().getResourceAsStream("images/ui/tokens/ui_token_pink.fw.png")); break; case IDENTIFIER: image = ImageIO.read(Thread.currentThread().getContextClassLoader().getResourceAsStream("images/ui/tokens/ui_token_green.fw.png")); break; case STRING_LITERAL: case NUM_LITERAL: case CHAR_LITERAL: image = ImageIO.read(Thread.currentThread().getContextClassLoader().getResourceAsStream("images/ui/tokens/ui_token_green.fw.png")); break; case SEPARATOR: image = ImageIO.read(Thread.currentThread().getContextClassLoader().getResourceAsStream("images/ui/tokens/ui_token_yellow.fw.png")); break; case OPERATOR: image = ImageIO.read(Thread.currentThread().getContextClassLoader().getResourceAsStream("images/ui/tokens/ui_token_purple.fw.png")); break; default: System.out.println("Unsupported token: " + kind); } } catch (IOException e) { e.printStackTrace(); } graphics = image.getGraphics(); FontMetrics fm = graphics.getFontMetrics(tokenFont); if (fm.stringWidth(token.image()) < 25) finalImage = finalizeImage(image, token, TOKEN_HEIGHT, MIN_WIDTH, Image.SCALE_DEFAULT); else finalImage = finalizeImage(image, token, TOKEN_HEIGHT, fm.stringWidth(token.image()) + imagePadding, Image.SCALE_DEFAULT); WritableImage writableImage = SwingFXUtils.toFXImage(finalImage, null); return new RHSIconizedToken(writableImage, token, index++); } /** * Creates a "pretty" clear token so the user can tell it's a placed token. * @param token * @return an IconizedToken */ public static RHSIconizedToken createSingleIconizedToken(SourceToken token, int newIndex) { SourceTokenKind kind = token.kind(); BufferedImage image = null; BufferedImage finalImage = null; Graphics graphics = null; try { switch(kind) { case KEYWORD: image = ImageIO.read(Thread.currentThread().getContextClassLoader().getResourceAsStream("images/ui/tokens/lucentPink.fw.png")); break; case IDENTIFIER: image = ImageIO.read(Thread.currentThread().getContextClassLoader().getResourceAsStream("images/ui/tokens/lucentGreen.fw.png")); break; case STRING_LITERAL: case NUM_LITERAL: case CHAR_LITERAL: image = ImageIO.read(Thread.currentThread().getContextClassLoader().getResourceAsStream("images/ui/tokens/lucentGreen.fw.png")); break; case SEPARATOR: image = ImageIO.read(Thread.currentThread().getContextClassLoader().getResourceAsStream("images/ui/tokens/lucentYellow.fw.png")); break; case OPERATOR: image = ImageIO.read(Thread.currentThread().getContextClassLoader().getResourceAsStream("images/ui/tokens/lucentPurple.fw.png")); break; default: System.out.println("Unsupported token: " + kind); } } catch (IOException e) { e.printStackTrace(); } graphics = image.getGraphics(); FontMetrics fm = graphics.getFontMetrics(tokenFont); if (fm.stringWidth(token.image()) < 25) finalImage = finalizeImage(image, token, TOKEN_HEIGHT, MIN_WIDTH, Image.SCALE_DEFAULT); else finalImage = finalizeImage(image, token, TOKEN_HEIGHT, fm.stringWidth(token.image()), Image.SCALE_DEFAULT); WritableImage writableImage = SwingFXUtils.toFXImage(finalImage, null); return new RHSIconizedToken(writableImage, token, newIndex); } /** * Resizes an image and adds the string text. * @param originalImage * @param height * @param width * @param type * @return an image to put on the GameBoard */ private static BufferedImage finalizeImage(Image originalImage, SourceToken token, int height, int width, int type) { String tokenImage = token.image(); SourceTokenKind kind = token.kind(); BufferedImage resizedImage = new BufferedImage(width, height, type); Graphics2D g = resizedImage.createGraphics(); FontMetrics fm = g.getFontMetrics(tokenFont); int strWidth = (fm.stringWidth(tokenImage)); int imageWidth = resizedImage.getWidth(); int textBegin = (imageWidth - strWidth) / 2; int textHeight = (fm.getAscent() + (TOKEN_HEIGHT - (fm.getAscent() + fm.getDescent())) / 2); g.drawImage(originalImage, 0, 0, width, height, null); g.setColor(LHSTokenIconizer.tokenFontColors.get(kind)); g.setFont(tokenFont); g.drawString(tokenImage, textBegin, textHeight); g.dispose(); return resizedImage; } public static void resetIndex() { index = 0; } }