/*
* OpIcon.java
* (FScape)
*
* Copyright (c) 2001-2016 Hanns Holger Rutz. All rights reserved.
*
* This software is published under the GNU General Public License v3+
*
*
* For further information, please contact Hanns Holger Rutz at
* contact@sciss.de
*/
package de.sciss.fscape.gui;
import de.sciss.fscape.op.Operator;
import javax.swing.*;
import java.awt.*;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.event.FocusEvent;
import java.awt.event.MouseEvent;
import java.io.IOException;
/**
* GUI element representing a spectral
* operator's icon.
*/
public class OpIcon
extends IconicComponent {
// -------- private static variables --------
// private static final String ibName = "images" + File.separator + "op.png"; // IconBitmap
private static final int ibWidth = 45; // width of icons
private static final int ibHeight = 45; // height of icons
private static IconBitmap opib = null;
private static IconicComponent basicIcons[];
private static DataFlavor flavors[] = null; // all supported DataFlavors
// -------- public variables --------
public static final String OBJ_NAME = "OpIcon";
public static DataFlavor op_flavor = null; // DataFlavor representing this class
public static final int ICON_WIDTH = ibWidth;
public static final int ICON_HEIGHT = ibHeight;
public static final int ID_INPUT = 8;
public static final int ID_OUTPUT = 9;
public static final int ID_FOLDER = 10;
public static final int ID_FLIPTIME = 11;
public static final int ID_FLIPFREQ = 12;
public static final int ID_SHARED = 13;
public static final int ID_UNITOR = 14;
public static final int ID_SPLITTER = 15;
public static final int ID_MONO2STEREO = 16;
public static final int ID_SMEAR = 17;
public static final int STATE_NORMAL = 0;
public static final int STATE_ERROR = 1;
public static final int STATE_FRIENDLY = 4;
public static final int STATE_BYPASS = 5;
public static Color progColor = new Color( 255, 160, 0 ); // Farbe fuer Progressindicatoren
public static Color normalColor = new Color( 152, 179, 132 ); // Farbe fuer normale Objekte
public static Color selectColor = new Color( 100, 115, 162 ); // Farbe fuer selektierte Objekte
// -------- private variables --------
private static final int STATE_UNKNOWN = -1;
private static final int STATE_SELECTED = 3; // "plus"
private Operator op;
private OpIconLabel lab;
private int opFlags;
private int state = STATE_UNKNOWN; // Status wie STATE_NORMAL, selektiert etc.
private int statePlus = 0;
// -------- public methods --------
// public void addTo( Container c );
// public void removeFrom( Container c );
// public void setIconLocation( Point p );
// public Point recallLocation();
// public Operator getOperator();
// public void setName( String iName );
// public String getName();
// public int setSelected( int state );
// public int isSelected();
/**
* @param op Operator who owns the icon
* @param ID Icon-ID
* @param iName Name fuer den Operator
*/
public OpIcon( Operator op, int ID, String iName )
{
super( getIconBitmap(), ID );
this.op = op;
// data flavors
if( OpIcon.op_flavor == null ) {
OpIcon.op_flavor = new DataFlavor( getClass(), "Operator Icon" );
}
lab = new OpIconLabel( this, iName );
opFlags = ~op.getFlags(); // pretend everything changed
operatorFlagsChanged( ~opFlags ); // invokes setSelected()
setSize( getPreferredSize() );
setLocation( 0, 0 );
// Event handling
enableEvents( AWTEvent.FOCUS_EVENT_MASK );
enableEvents( AWTEvent.MOUSE_EVENT_MASK );
}
public OpIcon( Operator op )
{
this( op, -1, "Untitled" );
}
// initializer!!
protected synchronized static IconBitmap getIconBitmap()
{
if( opib == null ) {
final Image imgOp = Toolkit.getDefaultToolkit().getImage(
OpIcon.class.getResource( "op.png" ));
opib = new IconBitmap( imgOp, ibWidth, ibHeight );
basicIcons = new IconicComponent[ 5 ];
for( int i = 0; i < basicIcons.length; i++ ) {
basicIcons[ i ] = new IconicComponent( opib, i );
}
}
return opib;
}
public void setLocation( int x, int y )
{
super.setLocation( x, y );
lab.updateLocation();
}
/**
* Ermittelt die vereinigten Ausmasse
* aus Icon und JLabel
*/
public Rectangle getUnionBounds()
{
final Rectangle iconBnd = getBounds();
final Rectangle labBnd = lab.getBounds();
final Rectangle union;
union = new Rectangle( Math.min( iconBnd.x, labBnd.x ), iconBnd.y,
Math.max( iconBnd.width, labBnd.width ),
iconBnd.height + labBnd.height );
return union;
}
/**
* Fuegt dieses Icon einem Container zu; STATT Container.add( OpIcon ) zu verwenden!!
*/
public void addTo( JComponent c )
{
c.add( this );
c.add( lab );
c.revalidate(); c.repaint();
}
/**
* Entfernt dieses Icon von einem Container; STATT Container.remove( OpIcon ) zu verwenden!!
*/
public void removeFrom( JComponent c )
{
c.remove( this );
c.remove( lab );
c.revalidate(); c.repaint();
}
/**
* Zugehoerigen Operator ermitteln
*/
public Operator getOperator()
{
return op;
}
/**
* Zugehoeriges JLabel ermitteln
*/
public OpIconLabel getLabel()
{
return lab;
}
/**
* JLabel des Icons festlegen
*
* @param iName JLabel
*/
public void setName( String iName )
{
lab.setName( iName );
}
/**
* JLabel des Icons ermitteln
*
* @return JLabel-String
*/
public String getName()
{
return lab.getName();
}
/**
* @return returns OBJ_OPICON so you can identify it ('==' Operator) as the real OpIcon
*/
public String toString()
{
return OBJ_NAME;
}
public void update( Graphics g )
{
paint( g ); // don't clear rect previously; we're proud to be round
}
// public void paint( Graphics g )
public void paintComponent( Graphics g )
{
basicIcons[ state + statePlus ].paint( g );
opib.paint( g, ID, 0, 0 );
if( !op.threadDead ) { // wenn Operator "laeuft", Progress-Indikator zeichnen
paintProgress( g );
}
}
/**
* Zeichnet nur den run()-Fortschritt
*
* @param g darf null sein
*/
public void paintProgress( Graphics g )
{
final int prog = (int) (op.getProgress() * 360);
final Graphics g2 = g != null ? g : getGraphics();
if( g2 != null ) {
g2.setColor( progColor );
g2.drawArc( 1, 1, ICON_WIDTH - 2, ICON_HEIGHT - 2, 90, prog );
g2.drawArc( 2, 2, ICON_WIDTH - 4, ICON_HEIGHT - 4, 90, prog );
if( g == null ) {
g2.dispose();
}
}
}
/**
* Status veraendern
*
* @param newState neuer Status wie STATE_ERROR
* @return vorheriger Status
*/
public int setSelected( int newState )
{
final int lastState = state;
state = newState;
if( lastState != newState ) {
repaint();
lab.repaint();
}
return lastState;
}
public int isSelected()
{
return state;
}
/**
* Icon mitteilen, dass der Operator neue Flags besitzt
* (bsp. Alias, Bypass)
*/
public void operatorFlagsChanged( int newFlags )
{
// Bypass-Type changed?
if( ((newFlags ^ opFlags) & Operator.FLAGS_BYPASS) != 0 ) {
setSelected( ((newFlags & Operator.FLAGS_BYPASS) == 0) ? STATE_NORMAL : STATE_BYPASS );
}
opFlags = newFlags;
lab.operatorFlagsChanged( newFlags );
}
// public boolean isFocusTraversable()
// {
// return true;
// }
// -------- Dragable methods --------
/**
* Zeichnet ein OpIcon-Schema mit den angegebenen Koordinaten
*/
public void paintScheme( Graphics g, int x, int y, boolean mode )
{
final int top = y - (OpIcon.ICON_HEIGHT>>1);
final Dimension dim = lab.getSize();
g.drawOval( x - (OpIcon.ICON_WIDTH>>1), top, OpIcon.ICON_WIDTH - 1, OpIcon.ICON_HEIGHT - 1 );
g.drawRect( x - (dim.width>>1), top + OpIcon.ICON_HEIGHT, dim.width - 1, dim.height - 1 );
}
// -------- Transferable methods --------
public DataFlavor[] getTransferDataFlavors()
{
if( flavors == null ) {
final DataFlavor iconFlavors[] = super.getTransferDataFlavors();
flavors = new DataFlavor[ iconFlavors.length + 1 ];
flavors[ 0 ] = OpIcon.op_flavor;
for( int i = 0; i < iconFlavors.length; i++ ) {
flavors[ i + 1 ] = iconFlavors[ i ];
}
}
return flavors;
}
public boolean isDataFlavorSupported( DataFlavor fl )
{
final DataFlavor flavs[] = getTransferDataFlavors();
for( int i = 0; i < flavs.length; i++ ) {
if( flavs[ i ].equals( fl )) return true;
}
return false;
}
public Object getTransferData( DataFlavor fl )
throws UnsupportedFlavorException, IOException
{
if( fl.equals( OpIcon.op_flavor )) {
return this;
} else if( fl.equals( DataFlavor.stringFlavor )) {
return getName();
} else {
return super.getTransferData( fl );
}
}
// -------- private methods --------
protected void processMouseEvent( MouseEvent e )
{
if( e.getID() == MouseEvent.MOUSE_PRESSED ) {
requestFocus();
}
super.processMouseEvent( e );
}
protected void processFocusEvent( FocusEvent e )
{
int oldStatePlus = statePlus;
if( e.getID() == FocusEvent.FOCUS_GAINED ) {
lab.setFocus( true );
statePlus = (state == STATE_NORMAL) ? STATE_SELECTED : 0;
} else if( e.getID() == FocusEvent.FOCUS_LOST ) {
lab.setFocus( false );
statePlus = 0;
}
if( statePlus != oldStatePlus ) repaint();
super.processFocusEvent( e );
}
}