Package games.stendhal.client.gui.styled

Source Code of games.stendhal.client.gui.styled.PixmapBorder

/* $Id: PixmapBorder.java,v 1.7 2010/10/19 14:45:36 kiheru Exp $ */
/***************************************************************************
*                   (C) Copyright 2003-2010 - Stendhal                    *
***************************************************************************
***************************************************************************
*                                                                         *
*   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.                                   *
*                                                                         *
***************************************************************************/
package games.stendhal.client.gui.styled;

import games.stendhal.client.sprite.Sprite;

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.Insets;
import java.awt.Polygon;
import java.awt.Rectangle;
import java.awt.Transparency;
import java.awt.image.BufferedImage;

import javax.swing.border.Border;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;

/**
* A <code>Border</code> that draws raised or lowered borders
* based on a template image.
*/
public class PixmapBorder implements Border {
  /** Drawing width of the borders */
  private static final int WIDTH = 2;
  private static final int NARROW_WIDTH = 1;
 
  /** Insets for most components using these borders */
  private static final Insets insets = new Insets(WIDTH, WIDTH, WIDTH, WIDTH);
  /**
   * Insets for components that should have narrow borders
   * <em>and</em> no padding.
   */
  private static final Insets smallInsets = new Insets(NARROW_WIDTH,
    NARROW_WIDTH, NARROW_WIDTH, NARROW_WIDTH);

 
  /** Image for painting the top and left borders */
  private final Image topLeftImage;
  /** Image for painting the bottom and right borders */
  private final Image bottomRightImage;
 
  private final int imageWidth, imageHeight;
 
  /**
   * Create a new <code>PixmapBorder</code>.
   *
   * @param template {@link Sprite} to be used as the base image for drawing
   *   the border
   * @param raised if <code>true</code>, the border will appear raised,
   *   otherwise it will look sunken
   */
  public PixmapBorder(Sprite template, boolean raised) {
    if (raised) {
      bottomRightImage = makeModifiedImage(template, Color.BLACK);
      topLeftImage = makeModifiedImage(template, Color.WHITE);
    } else {
      bottomRightImage = makeModifiedImage(template, Color.WHITE);
      topLeftImage = makeModifiedImage(template, Color.BLACK);
    }
    imageWidth = template.getWidth();
    imageHeight = template.getHeight();
  }
 
  /**
   * Create a painted over version if a {@link Sprite} image. The image is
   * painted over with alpha 0.5.
   *
   * @param template {@link Sprite} to used as the original image
   * @param color painting color
   * @return modified image
   */
  private Image makeModifiedImage(Sprite template, Color color) {
    final int width = template.getWidth();
    final int height = template.getHeight();
   
    final GraphicsConfiguration gc = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
    final BufferedImage image = gc.createCompatibleImage(width, height, Transparency.OPAQUE);
   
    Graphics2D g = image.createGraphics();
    template.draw(g, 0, 0);
    g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));
    g.setColor(color);
    g.fillRect(0, 0, width, height);
    g.dispose();
   
    return image;
  }
 
  public Insets getBorderInsets(Component component) {
    if (component instanceof JPopupMenu) {
      return smallInsets;
    } else {
      return insets;
    }
  }

  public boolean isBorderOpaque() {
    return false;
  }

  public void paintBorder(Component component, Graphics graphics, int x, int y,
      int width, int height) {
    Rectangle oldClip = graphics.getClipBounds();
    Graphics g = graphics.create();
   
    int borderWidth = getBorderWidth(component);
   
    // *** Clipping for  top and left borders ***
    Polygon p = new Polygon();
    p.addPoint(x, y);
    p.addPoint(x + width, y);
    p.addPoint(x + width - borderWidth, y + borderWidth);
    p.addPoint(x + borderWidth, y + borderWidth);
    p.addPoint(x + borderWidth, y + height - borderWidth);
    p.addPoint(x, y + height);
    g.setClip(p);
    g.clipRect(oldClip.x, oldClip.y, oldClip.width, oldClip.height);
   
    // top border
    for (int i = x; i < x + width; i += imageWidth) {
      g.drawImage(topLeftImage, i, y, null);
    }
    // left border
    for (int i = y; i < y + height; i += imageHeight) {
      g.drawImage(topLeftImage, x, i, null);
    }
   
    // *** Clipping for bottom and right borders ***
    // We have the same number of vertices as before, so it's efficient to
    // reuse the polygon 
    p.reset();
    p.addPoint(x + width, y);
    p.addPoint(x + width, y + height);
    p.addPoint(x, y + height);
    p.addPoint(x + borderWidth, y + height - borderWidth);
    p.addPoint(x + width - borderWidth, y + height - borderWidth);
    p.addPoint(x + width - borderWidth, y + borderWidth);
    g.setClip(p);
    g.clipRect(oldClip.x, oldClip.y, oldClip.width, oldClip.height);
   
    // Bottom border. More than one y coordinate may be needed in case the
    // tile border coincides to be inside the bottom border.
    int startY = y + height - borderWidth - (height - borderWidth) % imageHeight;
    int endY = y + height - height % imageHeight;
    for (int borderY = startY; borderY <= endY; borderY += imageHeight) {
      for (int i = x; i < x + width; i += imageWidth) {
        g.drawImage(bottomRightImage, i, borderY, null);
      }
    }
    // Right border. More than one x coordinate may be needed in case the
    // tile border coincides to be inside the right border.
    int startX = x + width - borderWidth - (width - borderWidth) % imageWidth;
    int endX = x + width - width % imageWidth;
    for (int borderX = startX; borderX <= endX; borderX += imageWidth) {
      for (int i = y; i < y + height; i += imageHeight) {
        g.drawImage(bottomRightImage, borderX, i, null);
      }
    }
   
    g.dispose();
  }
 
  /**
   * Get the appropriate border draw width for a component.
   *
   * @param component
   * @return border width
   */
  private int getBorderWidth(Component component) {
    if ((component instanceof JMenuItem)
        || (component instanceof JPopupMenu)) {
      return NARROW_WIDTH;
    } else {
      return WIDTH;
    }
  }
}
TOP

Related Classes of games.stendhal.client.gui.styled.PixmapBorder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.