Package net.xoetrope.swing

Source Code of net.xoetrope.swing.XImage

package net.xoetrope.swing;

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Composite;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Insets;
import java.awt.Shape;
import java.awt.event.InputEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Area;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.awt.image.ImageObserver;
import javax.swing.JComponent;
import javax.swing.TransferHandler;
import javax.swing.border.Border;
import net.xoetrope.swing.dnd.XTransferHandlerFactory;
import net.xoetrope.swing.util.XGraphicsUtils;

import net.xoetrope.xui.XImageHolder;
import net.xoetrope.xui.XAttributedComponent;

import net.xoetrope.xui.XProject;
import net.xoetrope.xui.XProjectManager;

import net.xoetrope.xui.helper.XuiUtilities;
import org.jdesktop.swingx.painter.Painter;

/**
* <p>Draws an image</p>
* <p>Copyright (c) Xoetrope Ltd., 1998-2007</p>
* License:      see license.txt
* $Revision: 2.18 $
*/
public class XImage extends JComponent implements XImageHolder, XAttributedComponent, MouseListener, MouseMotionListener
{
  public static final int STRETCH = 0;
  public static final int PRESERVE_ASPECT = 1;
  public static final int NO_SCALE = 2;
  public static final int TILE = 3;

  protected Image image = null;
  protected Image disabledImage = null;
  protected String imageName;
  protected BufferedImage shadow;
  protected boolean drawBorder, drawShadow, fillBorder, dragEnabled, centerImage;
  protected int arc;
  protected int shadowSize = 10;
  protected int distance = -5;
  protected int stretchMode = STRETCH;
 
  protected Painter painter;
  protected MouseEvent firstMouseEvent;
 
  /**
   * The current project
   */
  protected XProject currentProject;

  /**
   * Constructs a blank image control.
   */
  public XImage()
  {
    currentProject = XProjectManager.getCurrentProject();
    dragEnabled = true;
  }

 
  /**
   * Requests a repaint of the control once it has been created
   */
  public void addNotify()
  {
    super.addNotify();
    repaint( 0 );
  }

  /**
   * Get the size of the shadow
   * @return the shadow size
   */
  public int getShadowSize()
  {
    return shadowSize;
  }
 
  /**
   * Sets the image to display.
   * @param img the image
   */
  public void setImage( Image img )
  {
    image = img;
    repaint();
    prepareImage( img, this );
  }

  /**
   * Gets the name of the image being displayed.
   * @return the image name
   */
  public String getImageName()
  {
    return imageName;
  }

  /**
   * Sets the name of the image being displayed.
   * @param name the image name
   */
  public void setImageName( String name )
  {
    imageName = name;
    setImage( currentProject.getImage( imageName ));

    repaint();
  }
 
  /**
   * Gets the shadow flag value.
   * @return true if he shadow is drawn
   */
  public boolean getDrawShadow()
  {
    return drawShadow;
  }
 
  /**
   * Gets the fill border flag value.
   * @return true if the area within the border is filled
   */
  public boolean getFillBorder()
  {
    return fillBorder;
  }

  /**
   * Gets the arc value, the number of pixels by which the corners are radiused
   * @return the arc size in pixels
   */
  public int getArc()
  {
    return arc;
  }

  /**
   * Sets the arc value, the number of pixels by which the corners are radiused
   * @param value the arc size in pixels
   */
  public void setArc( int arcSize)
  {
    arc = arcSize;
  }
 
 
  /**
   * Gets the opaque flag value.
   * @return true if the background is opaque
   */
  public boolean getOpaque()
  {
    return isOpaque();
  }
 
  /**
   * Gets the border flag value.
   * @return true if he border is drawn
   */
  public boolean getDrawBorder()
  {
    return drawBorder;
  }
 
  /**
   * Sets the border flag value.
   * @param state true if he border is drawn
   */
  public void setDrawBorder( boolean state )
  {
    drawBorder = state;
  }
 
  /**
   * Get the preferred size of this image
   * @return the preferred size
   */
  public Dimension getPreferredSize( )
  {
    Dimension dim;
    if ( image == null )
      dim = super.getPreferredSize();
    else
      dim = new Dimension( image.getWidth( null ), image.getHeight( null ));
 
    Border border = getBorder();
    if ( border != null ) {
      Insets insets = border.getBorderInsets( this );
      dim.setSize( dim.getWidth() + insets.left + insets.right,
        dim.getHeight() + insets.top + insets.bottom );
    }
    return dim;
  }
 
  /**
   * Renders the component
   * @param g the graphics context
   */
  public void paintComponent( Graphics g )
  {
    Dimension d = getSize();
    if ( painter != null )
      painter.paint( (Graphics2D)g, this, d.width, d.height );
    else if ( image != null ) {
      Insets insets = new Insets( 0, 0, 0, 0 );
      Border border = getBorder();
      if ( border != null )
        insets = border.getBorderInsets( this );
     
      Dimension componentSize = d;
      Graphics2D g2d = (Graphics2D)g;
      Shape borderShape = null;
      int distance = 0;
      int pad = ( drawBorder || fillBorder ) ? 8 : 0;
      int shadowOffset = 0;
      if ( drawShadow ) {
        shadowOffset = shadowSize;
        if ( shadow == null ) {
          // Create a shadow image
          BufferedImage src = new BufferedImage( d.width, d.height, fillBorder ? BufferedImage.TYPE_BYTE_GRAY : BufferedImage.TYPE_INT_ARGB );
          src = XuiUtilities.createCompatibleImage( g2d, src );
          Graphics imgG = src.getGraphics();
          if ( fillBorder ) {
            // For a filled background fill the border area
            Shape backgroundShape = new RoundRectangle2D.Double( insets.left,
              insets.top,
              componentSize.width - insets.left - insets.right,
              componentSize.height - insets.top - insets.bottom,
              arc, arc );
            imgG.setColor( Color.gray );
            ((Graphics2D)imgG).fill( backgroundShape );
          }
          else // Otherwise generate a copy of theimage
            drawImage( (Graphics2D)imgG, image, insets.left, insets.top, componentSize.width - insets.left - insets.right,
                  componentSize.height - insets.top - insets.bottom, null );
          imgG.dispose();
         
          // Now blue the image
          shadow = new XGraphicsUtils().createShadow( src, shadowSize );
        }
       
        if ( !drawBorder )
          distance = shadowSize;
        d = new Dimension( componentSize.width - shadowSize - pad - pad - insets.left - insets.right,
          componentSize.height - shadowSize - pad - pad - insets.top - insets.top );
       
        if ( fillBorder ) {
          // Clear the part of the background that is 'filled''
          drawImage( g2d, shadow,
            shadowSize, shadowSize,
            componentSize.width - shadowSize,
            componentSize.height - shadowSize,
            null );   
          g.setColor( getBackground());
          g.fillRoundRect( insets.left,
            insets.top,
            componentSize.width - shadowSize - insets.left - insets.right,
            componentSize.height - shadowSize - insets.top - insets.bottom,
            arc, arc );
        }
        else
          drawImage( g2d, shadow, shadowSize + distance + pad + insets.left, shadowSize + distance + pad + insets.top, d.width, d.height, null );   
      }
      else  if ( fillBorder ) {
        g2d.setColor( getBackground());
        g2d.fillRoundRect( insets.left, insets.top,
          componentSize.width - insets.left - insets.right,
          componentSize.height - insets.top - insets.bottom, arc, arc );
      }

      
      Shape clipShape = g2d.getClip();
      if ( drawBorder ) {
        // Draw the border
        borderShape = new RoundRectangle2D.Double( insets.left, insets.top,
          componentSize.width -shadowOffset-1 - insets.left - insets.right,
          componentSize.height -shadowOffset-1 - insets.top - insets.bottom,
          arc, arc );
        g2d.setColor( getForeground());
        g2d.draw( borderShape );
        Area clipArea = new Area( borderShape );
        clipArea.intersect( new Area( clipShape ));
       
        // Clip any subsequent images
        g2d.setClip( clipArea );
      }
     
      if ( isEnabled())
        drawImage( g2d, image, pad, pad, d.width, d.height, this );
      else {
        // Draw a translucent version of the image
        Composite ac = g2d.getComposite();
        g2d.setComposite( AlphaComposite.getInstance( AlphaComposite.SRC_OVER, 0.5f ));
        drawImage( g2d, image, pad + insets.left, pad + insets.top, d.width, d.height, this );      
        g2d.setComposite( ac );
      }
     
      // Restore the clip area
      g2d.setClip( clipShape );     
    }   
  }

  /**
   * Draw the image according to the stretch mode
   * @param g2d
   * @param image
   * @param x
   * @param y
   * @param w
   * @param h
   * @param obs
   */
  public void drawImage( Graphics2D g2d, Image image, int x, int y, int w, int h, ImageObserver obs )
  {
    int imgW = image.getWidth( obs );
    int imgH = image.getHeight( obs );
   
    switch ( stretchMode ) {
      case NO_SCALE: {
          if ( centerImage ) {
            int padX = ( imgW - w ) / 2;
            int padY = ( imgH - h ) / 2;
            g2d.drawImage( image, x + padX, y + padY, obs );      
          }
          else
            g2d.drawImage( image, x, y, obs );
        }
        break;
      case PRESERVE_ASPECT: {
          if ( imgW > imgH ) {
            int destH = imgH * w / imgW;
            int pad = centerImage ? ( h - destH ) / 2 : 0;
            g2d.drawImage( image, x, y + pad, w, destH, obs );      
          }
          else {
            int destW = imgW * h / imgH;
            int pad = centerImage ? ( w - destW ) / 2 : 0;
            g2d.drawImage( image, x + pad, y, destW, imgH, obs );                
          }
        }
        break;
      case TILE: {
          for ( int ix = x; ix < w; ix += imgW ) {
            for ( int iy = y; iy < w; iy += imgW ) {
              g2d.drawImage( image, ix, iy, imgW, imgH, obs );      
            }           
          }
        }
        break;
      case STRETCH:
      default:
        g2d.drawImage( image, x, y, w, h, obs );      
    }
  }

  /**
   * Update the image as it is loaded.
   * @param img the image
   * @param infoflags the flags
   * @param x the x/left coordinate
   * @param y the y/top coordinate
   * @param width the image width
   * @param height the height
   * @return super.imageUpdate(...)
   */
  public boolean imageUpdate( Image img, int infoflags, int x, int y, int width, int height )
  {   
    if ( infoflags == ImageObserver.ALLBITS ) {
      repaint( x, y, getWidth(), getHeight() );
      return false;
    }
    else if ( infoflags > ImageObserver.ALLBITS )
      return false;

    if ( drawShadow )
      getParent().repaint();
   
    repaint( x, y, getWidth(), getHeight() );
    return true;
  }
 
  /**
   * Set the background painter object
   * @param xp the painter object
   */
  public void setPainter( Painter xp )
  {
    painter = xp;
  }

  /**
   * Get the background painter object
   * @return the painter object
   */
  public Painter getPainter()
  {
    return painter;
  }

  /**
   * Set one or more attributes of the component.
   * <OL>
   * <LI>content, value=the image file name</LI>
   * <LI>imagename, value=the image file name</LI>
   * <LI>tooltip, value=the tooltip text</LI>
   * <LI>opaque, value=true for an opaque image (fills the entire client area)</LI>
   * <LI>border, value=true to draw a border around the image</LI>
   * <LI>stretch, value=STRETCH = 0, PRESERVE_ASPECT = 1, NO_SCALE = 2, TILE = 3</LI>
   * <LI>arc, value=the rounding arc for the border if any</LI>
   * <LI>center, value=true to center the image</LI>
   * </OL>
   * @param attribName the attribute name
   * @param attribValue the attribute value
   * @return 0 for success, non zero for failure or to require some further action
   */
  public int setAttribute( String attribName, Object attribValue )
  {   
    String attribNameLwr = attribName.toLowerCase();
    String attribValueStr = (String)attribValue;
    String attribValueLwr = null;
    if ( attribValue != null )
      attribValueLwr = attribValueStr.toLowerCase();
   
    if ( attribNameLwr.equals( "content" ) || attribNameLwr.equals( "imagename" )) {
      imageName = attribValueStr;
      setImage( currentProject.getImage( imageName ));
    }
    else if ( attribValue == null )
      return -1;
    else if ( attribNameLwr.equals( "tooltip" ))
      setToolTipText( attribValueStr );
    else if ( attribNameLwr.equals( "opaque" ))
      setOpaque( attribValueLwr.equals( "true" ) );
    else if ( attribNameLwr.equals( "border" ))
      drawBorder = attribValueLwr.equals( "true" ) || attribValueLwr.equals( "1" );
    else if ( attribNameLwr.equals( "fill" ))
      fillBorder = attribValueLwr.equals( "true" ) || attribValueLwr.equals( "1" );
    else if ( attribNameLwr.equals( "shadow" ))
      drawShadow = attribValueLwr.equals( "true" ) || attribValueLwr.equals( "1" );
    else if ( attribNameLwr.equals( "arc" ))
      arc = Math.max( 0, new Integer( attribValueStr ).intValue());
    else if ( attribNameLwr.equals( "stretch" ))
      setStretchMode( Math.max( 0, new Integer( attribValueStr ).intValue()));
    else if ( attribNameLwr.equals( "center" ))
      setCenterImage( attribValueLwr.equals( "true" ));
    else if ( attribNameLwr.equals( "painter" )) {
      try {
        Painter xp = (Painter)Class.forName( attribValueStr.trim()).newInstance();
        setPainter( xp );
      }
      catch ( Exception e )
      {}
    }
    else if ( attribNameLwr.equals( "dragenabled" )) {
      boolean state = "true".equals( attribValueLwr );
      if ( state ) {
        XTransferHandlerFactory thf = XTransferHandlerFactory.getInstance( XProjectManager.getCurrentProject());
        if ( thf != null ) {
          TransferHandler th = thf.getTransferHandler( this, null );
          if ( th != null ) {
            addMouseListener( this );
            addMouseMotionListener( this );
            setTransferHandler( th );
            return 0;
          }
        }
      }
    }
    else
      return -1;

    return 0;   
  }
 
  // DND -----------------------------------------------------------------------
  public void mousePressed( MouseEvent e )
  {
      //Don't bother to drag if there is no image.
      if ( imageName == null )
        return;

      firstMouseEvent = e;
      e.consume();
  }

  public void mouseDragged( MouseEvent e )
  {
    //Don't bother to drag if the component displays no image.
    if ( imageName == null )
      return;

    if ( firstMouseEvent != null ) {
      e.consume();

      //If they are holding down the control key, COPY rather than MOVE
      int ctrlMask = InputEvent.CTRL_DOWN_MASK;
      int action = (( e.getModifiersEx() & ctrlMask) == ctrlMask) ?
            TransferHandler.COPY : TransferHandler.MOVE;

      int dx = Math.abs( e.getX() - firstMouseEvent.getX());
      int dy = Math.abs( e.getY() - firstMouseEvent.getY());
      //Arbitrarily define a 5-pixel shift as the
      //official beginning of a drag.
      if (( dx > 5 ) || ( dy > 5 )) {
        //This is a drag, not a click.
        JComponent c = (JComponent)e.getSource();
        //Tell the transfer handler to initiate the drag.
        TransferHandler handler = c.getTransferHandler();
        handler.exportAsDrag( c, firstMouseEvent, action );
        firstMouseEvent = null;
      }
    }
  }

  /**
   * Invoked when the mouse cursor has been moved onto a component
   * but no buttons have been pushed.
   */
  public void mouseMoved( MouseEvent e )
  {

  }
   
  public void mouseReleased( MouseEvent e )
  {
    firstMouseEvent = null;
  }
 
  /**
   * Invoked when the mouse enters a component.
   */
  public void mouseEntered( MouseEvent e ) {}

  /**
   * Invoked when the mouse exits a component.
   */
  public void mouseExited( MouseEvent e ) {}
   
  /**
   * Invoked when the mouse button has been clicked (pressed
   * and released) on a component.
   */
  public void mouseClicked( MouseEvent e ) {}
  // DND -----------------------------------------------------------------------

  /**
   * Get the stretch mode for this image
   * @return
   * @since 3.2
   */
  public int getStretchMode()
  {
    return stretchMode;
  }

  /**
   * Set the stretch mode for this image. The mode can be
   * <ul>
   * <li>STRETCH = 0, the image completely fills the available area</li>
   * <li>PRESERVE_ASPECT = 1, the aspect ratio is preserved while filling the maximum possible area</li>
   * <li>NO_SCALE = 2, no stretching is performed and the image is drawn at it's original size</li>
   * <li>TILE = 3, the image is tiles at its original size to fill the available area</li>
   * </ul>
   *
   * @param mode the new stretch mode
   * @since 3.2
   */
  public void setStretchMode( int mode )
  {
    stretchMode = mode;
    repaint();
  }

  /**
   * Is the image cetered?
   * @return true if the image is centered when the aspect is preserved or when the
   * original size is smaller than the available space
   */
  public boolean isCenterImage()
  {
    return centerImage;
  }

  /**
   * Set the image centering options
   * @param state
   */
  public void setCenterImage( boolean state )
  {
    centerImage = state;
    repaint();
  }
}
TOP

Related Classes of net.xoetrope.swing.XImage

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.