Package de.sciss.meloncillo.gui

Source Code of de.sciss.meloncillo.gui.CurvePanel$Icon

/*
*  CurvePanel.java
*  Meloncillo
*
*  Copyright (c) 2004-2008 Hanns Holger Rutz. All rights reserved.
*
*  This software 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, june 1991 of the License, or (at your option) any later version.
*
*  This software 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 (gpl.txt) along with this software; if not, write to the Free Software
*  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*
*
*  For further information, please contact Hanns Holger Rutz at
*  contact@sciss.de
*
*
*  Changelog:
*    15-Jul-05  created
*    14-Jul-08  copied from EisK
*/

package de.sciss.meloncillo.gui;

import java.awt.AWTEventMulticaster;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Paint;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.geom.AffineTransform;
import java.awt.geom.Area;
import java.awt.geom.CubicCurve2D;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Point2D;
import java.util.prefs.Preferences;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.event.MouseInputAdapter;

/**
*  This class describes a generic GUI tool
*  that can be aquired and dismissed by
*  a <code>Component</code>.
*
@author    Hanns Holger Rutz
@version  0.70, 31-May-08
*/
public class CurvePanel
extends JComponent
// implements LaterInvocationManager.Listener
{
  private static final String    KEY_CTRLX1    = "ctrlx1";
  private static final String    KEY_CTRLY1    = "ctrly1";
  private static final String    KEY_CTRLX2    = "ctrlx2";
  private static final String    KEY_CTRLY2    = "ctrly2";
//  private static final String[]  KEYS      = { KEY_CTRLX1, KEY_CTRLY1, KEY_CTRLX2, KEY_CTRLY2 };

  private final CubicCurve2D[]  shpFades;
  private final AffineTransform  at        = new AffineTransform();
  protected static final Insets  insets      = new Insets( 1, 1, 1, 1 );
  private static final Shape    shpCtrlIn    = new Ellipse2D.Double( -2, -2, 5, 5 );
  private static final Area    shpCtrlOut;
  private static final Paint    pntCtrlIn    = new Color( 0x00, 0x00, 0x00, 0x7F );
  private static final Paint    pntCtrlOut    = new Color( 0x00, 0x00, 0x00, 0x3F );
  private static final Paint    pntCtrlOutS    = new Color( 0x00, 0x00, 0xFF, 0x7F );

  private final Shape[]      tShpFades;

  protected final Point2D[]  ctrlPt  = new Point2D[] {
    new Point2D.Double( 0.5, 0.5 ), new Point2D.Double( 0.5, 0.5 )};

  protected int          recentWidth    = -1;
  protected int          recentHeight  = -1;
  protected boolean        recalc      = true;
  protected Point2D        dragPt      = null;
//  private final Preferences    prefs;
 
  private ActionListener      actionListener  = null;
 
  static {
    shpCtrlOut       = new Area( new Ellipse2D.Double( -7, -7, 15, 15 ));
    shpCtrlOut.subtract( new Area( new Ellipse2D.Double( -4, -4, 9, 9 )));
  }
       
  public CurvePanel( CubicCurve2D[] basicCurves, final Preferences prefs )
  {
    super();
 
    final Dimension d = new Dimension( 64, 64 );
   
    shpFades  = basicCurves;
//    prefs    = prefs;
    tShpFades    = new Shape[ shpFades.length ];
   
    if( prefs != null ) {
      ctrlPt[0].setLocation( prefs.getDouble( KEY_CTRLX1, 0.5 ), prefs.getDouble( KEY_CTRLY1, 0.5 ));
      ctrlPt[1].setLocation( prefs.getDouble( KEY_CTRLX2, 0.5 ), prefs.getDouble( KEY_CTRLY2, 0.5 ));
    }

    setMinimumSize( d );
    setPreferredSize( d );
    setBorder( BorderFactory.createEmptyBorder( insets.left, insets.top, insets.bottom, insets.right ));

//    if( prefs != null ) {
//      new DynamicAncestorAdapter( new DynamicPrefChangeManager( prefs, KEYS, this )).addTo( this );
//    }

    MouseInputAdapter  mia  = new MouseInputAdapter() {
      private boolean didThemDragga = false;
   
      public void mousePressed( MouseEvent e )
      {
        Point2D  mousePt = getVirtualMousePos( e );
     
        if( mousePt.distanceSq( ctrlPt[ 0 ]) <= mousePt.distanceSq( ctrlPt[ 1 ])) {
          dragPt  = ctrlPt[ 0 ];
        } else {
          dragPt  = ctrlPt[ 1 ];
        }
       
        processDrag( mousePt, !e.isControlDown() );
      }

      public void mouseReleased( MouseEvent e )
      {
        dragPt      = null;
        repaint();
        if( didThemDragga ) {
          dispatchAction();
          didThemDragga  = false;
        }
      }
     
      private Point2D getVirtualMousePos( MouseEvent e )
      {
        return new Point2D.Double(
          Math.max( 0.0, Math.min( 1.0, (double) (e.getX() - insets.left) / recentWidth )),
          1.0 - Math.max( 0.0, Math.min( 1.0, (double) (e.getY() - insets.top) / recentHeight )));
      }

      public void mouseMoved( MouseEvent e )
      {
        mouseDragged( e )// mouseDragged not called with popup dialog!
      }

      public void mouseDragged( MouseEvent e )
      {
        if( dragPt != null ) processDrag( getVirtualMousePos( e ), !e.isControlDown() );
      }
     
      private void processDrag( Point2D mousePt, boolean snap )
      {
        didThemDragga = true;
        if( snap ) {
          if( Math.abs( mousePt.getX() - 0.5 ) < 0.1 ) mousePt.setLocation( 0.5, mousePt.getY() );
          ifMath.abs( mousePt.getY() - 0.5 ) < 0.1 ) mousePt.setLocation( mousePt.getX(), 0.5 );
        }
        dragPt.setLocation( mousePt );
        if( prefs != null ) {
          if( dragPt == ctrlPt[0] ) {
            prefs.putDouble( KEY_CTRLX1, dragPt.getX() );
            prefs.putDouble( KEY_CTRLY1, dragPt.getY() );
          } else {
            prefs.putDouble( KEY_CTRLX2, dragPt.getX() );
            prefs.putDouble( KEY_CTRLY2, dragPt.getY() );
          }
        }
        recalc = true;
        repaint();
      }
    };
   
    addMouseListener( mia );
    addMouseMotionListener( mia );
  }
 
     public void addActionListener( ActionListener l )
   {
    synchronized( this ) {
      actionListener = AWTEventMulticaster.add( actionListener, l );
    }
     }
  
     public void removeActionListener( ActionListener l )
   {
    synchronized( this ) {
      actionListener = AWTEventMulticaster.remove( actionListener, l );
    }
     }
  
     protected void dispatchAction()
   {
         final ActionListener listener = actionListener;
         if( listener != null ) {
             listener.actionPerformed( new ActionEvent( this, ActionEvent.ACTION_PERFORMED, null ));
         }
     }

   public Point2D[] getControlPoints()
   {
     return new Point2D[] { new Point2D.Double( ctrlPt[ 0 ].getX(), ctrlPt[ 0 ].getY() ),
                  new Point2D.Double( ctrlPt[ 1 ].getX(), ctrlPt[ 1 ].getY() )};
   }
  
   public void setControlPoints( Point2D ctrlPt1, Point2D ctrlPt2 )
   {
    ctrlPt[0].setLocation( ctrlPt1.getX(), ctrlPt1.getY() );
    ctrlPt[1].setLocation( ctrlPt2.getX(), ctrlPt2.getY() );
    recalc = true;
    repaint();
  }

  // this is static to allow calculations
  // without actually creating GUI elements
  public static Point2D[] getControlPoints( Preferences prefs )
  {
    return new Point2D[] {
      new Point2D.Double( prefs.getDouble( KEY_CTRLX1, 0.5 ), prefs.getDouble( KEY_CTRLY1, 0.5 )),
      new Point2D.Double( prefs.getDouble( KEY_CTRLX2, 0.5 ), prefs.getDouble( KEY_CTRLY2, 0.5 ))
    };
  }

  public static void toPrefs( Point2D[] ctrlPt, Preferences prefs )
  {
    prefs.putDouble( KEY_CTRLX1, ctrlPt[0].getX() );
    prefs.putDouble( KEY_CTRLY1, ctrlPt[0].getY() );
    prefs.putDouble( KEY_CTRLX2, ctrlPt[1].getX() );
    prefs.putDouble( KEY_CTRLY2, ctrlPt[1].getY() );
  }

  public void toPrefs( Preferences prefs )
  {
    toPrefs( ctrlPt, prefs );
  }

  public void paintComponent( Graphics g )
  {
    super.paintComponent( g );
   
    final Graphics2D    g2        = (Graphics2D) g;
    final int        currentWidth  = getWidth() - insets.left - insets.right;
    final int        currentHeight  = getHeight() - insets.top - insets.bottom;
    final AffineTransform  atOrig      = g2.getTransform();

    double trnsX, trnsY;
   
    if( (currentWidth != recentWidth) || (currentHeight != recentHeight) || recalc ) {
      recentWidth    = currentWidth;
      recentHeight  = currentHeight;
      at.setToScale( currentWidth, -currentHeight );
      at.translate( 0, -1.0 );
      recalcTransforms();
    }
   
    g2.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON );
    g2.translate( insets.left, insets.top );
    for( int i = 0; i < tShpFades.length; i++ ) {
      g2.draw( tShpFades[ i ]);
    }
   
    for( int i = 0; i < ctrlPt.length; i++ ) {
      trnsX  = ctrlPt[i].getX() * currentWidth;
      trnsY  = (1.0 - ctrlPt[i].getY()) * currentHeight;
      g2.translate( trnsX, trnsY );
      g2.setPaint( pntCtrlIn );
      g2.fill( shpCtrlIn );
      if( ctrlPt[i] == dragPt ) {
        g2.setPaint( pntCtrlOutS );
      } else {
        g2.setPaint( pntCtrlOut );
      }
      g2.fill( shpCtrlOut );
      g2.translate( -trnsX, -trnsY );
    }

    g2.setTransform( atOrig );
  }

  private void recalcTransforms()
  {
//    if( prefs != null ) {
//      ctrlPt[0].setLocation( prefs.getDouble( KEY_CTRLX1, 0.5 ), prefs.getDouble( KEY_CTRLY1, 0.5 ));
//      ctrlPt[1].setLocation( prefs.getDouble( KEY_CTRLX2, 0.5 ), prefs.getDouble( KEY_CTRLY2, 0.5 ));
//    }
    for( int i = 0; i < shpFades.length; i++ ) {
//      shpFades[ i ].setCurve( shpFades[ i ].getP1(), ctrlPt[ i % 2 ], ctrlPt[ (i+1) % 2 ], shpFades[ i ].getP2() );
      shpFades[ i ].setCurve( shpFades[ i ].getX1(), shpFades[ i ].getY1(),
        ctrlPt[ 0 ].getX(), ctrlPt[ i % 2 ].getY(),
        ctrlPt[ 1 ].getX(), ctrlPt[ (i+1) % 2 ].getY(),
        shpFades[ i ].getX2(), shpFades[ i ].getY2() );
      tShpFades[ i = at.createTransformedShape( shpFades[ i ]);
    }
    recalc  = false;
  }

//  // o instanceof PreferenceChangeEvent
//  public void laterInvocation( Object o )
//  {
//    recalc = true;
//    repaint();
//  }
 
  public static class Icon
  implements javax.swing.Icon
  {
    private final int width;
    private final int height;
    private final AffineTransform at;

    private final CubicCurve2D[]  shpFades;
    private final Shape[]      tShpFades;

    private final Point2D[]  ctrlPt  = new Point2D[] {
      new Point2D.Double( 0.5, 0.5 ), new Point2D.Double( 0.5, 0.5 )};

    public Icon( CubicCurve2D[] basicCurves )
    {
      this( basicCurves, 16, 16 );
    }

    public Icon( CubicCurve2D[] basicCurves, int width, int height )
    {
      this.width  = width;
      this.height  = height;

      at      = AffineTransform.getScaleInstance( width, -height );
      at.translate( 0, -1.0 );
     
      shpFades  = basicCurves;
      tShpFades  = new Shape[ shpFades.length ];
    }
   
    public int getIconWidth() { return width; }
    public int getIconHeight() { return height; }
   
//    public void update( Preferences prefs )
//    {
//      ctrlPt[0].setLocation( prefs.getDouble( KEY_CTRLX1, 0.5 ), prefs.getDouble( KEY_CTRLY1, 0.5 ));
//      ctrlPt[1].setLocation( prefs.getDouble( KEY_CTRLX2, 0.5 ), prefs.getDouble( KEY_CTRLY2, 0.5 ));
//
//      for( int i = 0; i < shpFades.length; i++ ) {
//        shpFades[ i ].setCurve( shpFades[ i ].getX1(), shpFades[ i ].getY1(),
//          ctrlPt[ 0 ].getX(), ctrlPt[ i % 2 ].getY(),
//          ctrlPt[ 1 ].getX(), ctrlPt[ (i+1) % 2 ].getY(),
//          shpFades[ i ].getX2(), shpFades[ i ].getY2() );
//        tShpFades[ i ]  = at.createTransformedShape( shpFades[ i ]);
//      }
//    }
     
    public void update( Point2D ctrl1, Point2D ctrl2 )
    {
      ctrlPt[0].setLocation( ctrl1.getX(), ctrl1.getY() );
      ctrlPt[1].setLocation( ctrl2.getX(), ctrl2.getY() );

      for( int i = 0; i < shpFades.length; i++ ) {
        shpFades[ i ].setCurve( shpFades[ i ].getX1(), shpFades[ i ].getY1(),
          ctrlPt[ 0 ].getX(), ctrlPt[ i % 2 ].getY(),
          ctrlPt[ 1 ].getX(), ctrlPt[ (i+1) % 2 ].getY(),
          shpFades[ i ].getX2(), shpFades[ i ].getY2() );
        tShpFades[ i = at.createTransformedShape( shpFades[ i ]);
      }
    }
     
    public void paintIcon( Component c, Graphics g, int x, int y )
    {
      final Graphics2D    g2        = (Graphics2D) g;
      final AffineTransform  atOrig      = g2.getTransform();
     
      g2.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON );
      g2.translate( x, y );
      g2.setColor( Color.black );
      for( int i = 0; i < tShpFades.length; i++ ) {
        g2.draw( tShpFades[ i ]);
      }
      g2.setTransform( atOrig );
    }   
  }
}
TOP

Related Classes of de.sciss.meloncillo.gui.CurvePanel$Icon

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.