Package de.sciss.meloncillo.surface

Source Code of de.sciss.meloncillo.surface.SurfaceFrame

/*
*  SurfaceFrame.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:
*    27-Jul-04   trace surface resizing and make sure it's square shaped
*    01-Aug-04   commented
*      24-Dec-04   support for intruding-grow-box prefs
*      27-Dec-04   added online help
*    15-Jan-05  moved to separate package
*    17-Apr-05  bugfix in editClear
*/

package de.sciss.meloncillo.surface;

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.ClipboardOwner;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.event.ActionEvent;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.geom.Point2D;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
import java.util.prefs.PreferenceChangeEvent;
import java.util.prefs.PreferenceChangeListener;

import javax.swing.Action;
import javax.swing.Box;
import javax.swing.JPanel;
import javax.swing.JSplitPane;

import de.sciss.app.AbstractApplication;
import de.sciss.app.AbstractCompoundEdit;
import de.sciss.app.Application;
import de.sciss.app.DynamicPrefChangeManager;
import de.sciss.app.PerformableEdit;
import de.sciss.common.BasicApplication;
import de.sciss.gui.AbstractWindowHandler;
import de.sciss.gui.GUIUtil;
import de.sciss.gui.MenuAction;
import de.sciss.gui.VectorSpace;
import de.sciss.meloncillo.Main;
import de.sciss.meloncillo.edit.BasicCompoundEdit;
import de.sciss.meloncillo.edit.EditAddSessionObjects;
import de.sciss.meloncillo.edit.EditSetSessionObjects;
import de.sciss.meloncillo.gui.Axis;
import de.sciss.meloncillo.gui.MenuFactory;
import de.sciss.meloncillo.receiver.Receiver;
import de.sciss.meloncillo.session.BasicSessionCollection;
import de.sciss.meloncillo.session.DocumentFrame;
import de.sciss.meloncillo.session.GroupableSessionObject;
import de.sciss.meloncillo.session.Session;
import de.sciss.meloncillo.session.SessionGroupTable;
import de.sciss.meloncillo.util.PrefsUtil;
import de.sciss.meloncillo.util.TransferableCollection;

/**
*  The frame that hosts the <code>SurfacePane</code>
*  panel. Implements <code>EditMenuListener</code>
*  to deal with cut / copy / paste operations.
*
@author    Hanns Holger Rutz
@version  0.75, 19-Jun-08
*/
public class SurfaceFrame
extends DocumentFrame
implements ClipboardOwner, PreferenceChangeListener
{
  private final SurfacePane  surface;
 
  private final Axis      haxis, vaxis;
  private final Box      haxisBox;

  /**
   *  Constructs a new <code>SurfaceFrame</code>
   *  object. A <code>Surface</code> will be
   *  added to the frame's root pane.
   *
   *  @param  root  application root
   *  @param  doc    session document
   */
  public SurfaceFrame( Main root, Session doc )
  {
    super( doc );
   
    final Container      cp    = getContentPane();
    final JSplitPane    split  = new JSplitPane( JSplitPane.HORIZONTAL_SPLIT );
    final JSplitPane    split2  = new JSplitPane( JSplitPane.VERTICAL_SPLIT );
    final JPanel      sp    = new JPanel( new BorderLayout() );
//    final VectorSpace    space  = VectorSpace.createLinSpace( 0.0, 1.0, 0.0, 1.0, null, null, null, null );  // XXX
    final VectorSpace    space  = VectorSpace.createLinSpace( -1.0, 1.0, -1.0, 1.0, null, null, null, null )// XXX
    final SurfaceToolBar  stb    = new SurfaceToolBar( doc );
    final Application    app    = AbstractApplication.getApplication();
    final JPanel      gp    = GUIUtil.createGradientPanel();

    setTitle( app.getResourceString( "frameSurface" ));

    stb.setOpaque( false );
    gp.add( stb );
    haxisBox  = Box.createHorizontalBox();
    haxis    = new Axis( Axis.HORIZONTAL, Axis.FIXEDBOUNDS );
    vaxis    = new Axis( Axis.VERTICAL, /* Axis.MIRROIR | */ Axis.FIXEDBOUNDS );
    surface    = new SurfacePane( root, doc );
    surface.addComponentListener( new ComponentAdapter() {
      public void componentResized( ComponentEvent e )
      {
        Dimension d = surface.getSize();
        if( d.width != d.height ) {
          int diam = Math.min( d.width, d.height );
          surface.setSize( diam, diam );
        }
        haxis.setSize( d.width, haxis.getHeight() );
        vaxis.setSize( vaxis.getWidth(), d.height );
      }
    });
    stb.addToolActionListener( surface );

    cp.setLayout( new BorderLayout() );
//    split.setLeftComponent( new JScrollPane( new SessionGroupTable( root, doc, doc,
//      SessionGroupTable.VIEW_RECEIVERS )));
    split2.setTopComponent( new SessionGroupTable( doc, doc,
      SessionGroupTable.VIEW_RECEIVERS | SessionGroupTable.VIEW_FLAGS ));
    split2.setBottomComponent( new SessionGroupTable( doc, doc, SessionGroupTable.VIEW_GROUPS | SessionGroupTable.VIEW_FLAGS ));
//        HelpGlassPane.setHelp( split2, "SurfaceObjectTables" );  // EEE

    haxis.setSpace( space );
    vaxis.setSpace( space );
//    haxis.setVisible( false );
//    vaxis.setVisible( false );
//    strut.setVisible( false );
    haxisBox.add( Box.createHorizontalStrut( vaxis.getPreferredSize().width ));
    haxisBox.add( haxis );
    sp.add( haxisBox, BorderLayout.NORTH );
    sp.add( vaxis, BorderLayout.WEST );
    sp.add( surface, BorderLayout.CENTER );

    split.setLeftComponent( split2 );
    split.setRightComponent( sp );
    split.setOneTouchExpandable( true );
    split.setContinuousLayout( false );
//    split.setLastDividerLocation( 120 );
    split.setDividerLocation( 80 );    // this will be the size when using one-touch-expansion
    split.setDividerLocation( 0 );    // when showing up, the group component is hidden
//    split.setDividerSize( 4 );
    cp.add( split, BorderLayout.CENTER );
    cp.add( gp, BorderLayout.NORTH );
        if( app.getUserPrefs().getBoolean( PrefsUtil.KEY_INTRUDINGSIZE, false )) {
            cp.add( Box.createVerticalStrut( 16 ), BorderLayout.SOUTH );
        }

    // -------

//        addListener( new AbstractWindow.Adapter() {
//      public void windowClosing( AbstractWindow.Event e )
//      {
//        dispose();
//      }
//    });
//    setDefaultCloseOperation( WindowConstants.DO_NOTHING_ON_CLOSE ); // window listener see above!

//        HelpGlassPane.setHelp( getRootPane(), "SurfaceFrame" ); // EEE
    AbstractWindowHandler.setDeepFont( cp );
       
        addDynamicListening( new DynamicPrefChangeManager( app.getUserPrefs().node( PrefsUtil.NODE_SHARED ),
      new String[] { PrefsUtil.KEY_VIEWRULERS }, this ));
   
        init();
    app.addComponent( Main.COMP_SURFACE, this );
  }

  public void dispose()
  {
    AbstractApplication.getApplication().removeComponent( Main.COMP_SURFACE );
    super.dispose();
  }

  protected boolean autoUpdatePrefs()
  {
    return true;
  }

  protected boolean alwaysPackSize()
  {
    return false;
  }

  protected Point2D getPreferredLocation()
  {
    return new Point2D.Float( 0.05f, 0.7f );
  }

  /*
   *  Performs a copy operation
   *  on the selected receivers
   *
   *  @synchronization  waitShared on DOOR_RCV
   */
  private boolean editCopy()
  {
    final List      v    = new ArrayList();
    final Application  app    = AbstractApplication.getApplication();
    Object        o;
    Receiver      rcv;
    List        collSelection;
    boolean        success = false;

    try {
      doc.bird.waitShared( Session.DOOR_RCV );
      collSelection   = doc.getSelectedReceivers().getAll();
      for( int i = 0; i < collSelection.size(); i++ ) {
        o = collSelection.get( i );
        if( o instanceof Transferable ) {
          if( ((Transferable) o).isDataFlavorSupported( Receiver.receiverFlavor )) {
            rcv = (Receiver) ((Transferable) o).getTransferData( Receiver.receiverFlavor );
            v.add( rcv );
          }
        }
      }
      if( !v.isEmpty() ) {
        app.getClipboard().setContents( new TransferableCollection( v ), this );
      }
      success = true;
    }
    catch( IllegalStateException e1 ) {
      System.err.println( AbstractApplication.getApplication().getResourceString( "errClipboard" ));
    }
    catch( UnsupportedFlavorException e2 ) {}
    catch( IOException e3 ) {}
    finally {
      doc.bird.releaseShared( Session.DOOR_RCV );
    }

    return success;
  }

  /*
   *  Tries to find transferable receivers in the clipboard
   *  and paste those to the surface, automatically renaming
   *  them and finding a good position on the surface. (undoable)
   *
   *  @synchronization  waitExclusive on DOOR_RCV + DOOR_GRP
   */
  private boolean editPaste()
  {
    Transferable          t;
    java.util.List          coll, coll2, coll3;
    Receiver            rcv, rcv2;
    Transferable          o;
    Point2D              pt, pt2;
    boolean              success  = false;
    boolean              retry;
    AbstractCompoundEdit      edit;
    Object[]            args;
    final Application        app    = AbstractApplication.getApplication();
 
    try {
      t = app.getClipboard().getContents( this );
      if( t == null ) return false;
     
      if( t.isDataFlavorSupported( TransferableCollection.collectionFlavor )) {
        coll = (java.util.List) t.getTransferData( TransferableCollection.collectionFlavor );
      } else if( t.isDataFlavorSupported( Receiver.receiverFlavor )) {
        rcv = (Receiver ) t.getTransferData( Receiver.receiverFlavor );
        coll = new Vector( 1 );
        coll.add( rcv );
      } else {
        return false;
      }

      try {
        args = new Object[ 3 ];
       
        doc.bird.waitExclusive( Session.DOOR_RCV | Session.DOOR_GRP );
        coll2   = doc.getReceivers().getAll();
        coll3  = new ArrayList( coll2 );
        for( int i = 0; i < coll.size(); i++ ) {
          o = (Transferable) coll.get( i );
          if( o.isDataFlavorSupported( Receiver.receiverFlavor )) {
            rcv = (Receiver) o.getTransferData( Receiver.receiverFlavor );
            do {
              retry = false;
              for( int j = 0; j < coll3.size(); j++ ) {
                rcv2 = (Receiver) coll3.get( j );
                pt = rcv.getAnchor();
                if( pt.distance( rcv2.getAnchor() ) < 0.05 ) {
                  pt2 = new Point2D.Double( Math.min( 1.0, pt.getX() + 0.05 ),
                                Math.min( 1.0, pt.getY() + 0.05 ));
                  rcv.setAnchor( pt2 );
                  if( pt2.distance( pt ) > 0.05 ) retry = true;
                }
              }
            } while( retry );
            coll3.add( rcv );
          }
        } // for( i = 0; i < coll.size(); i++ )
        coll3.removeAll( coll2 ); // now only the new ones remain

        // ensure unique names
        for( int i = 0; i < coll3.size(); i++ ) {
          rcv = (Receiver) coll3.get( i );
          if( doc.getReceivers().findByName( rcv.getName() ) != null ) {
            Session.makeNamePattern( rcv.getName(), args );
            rcv.setName( BasicSessionCollection.createUniqueName( Session.SO_NAME_PTRN, args, coll2 ));
          }
          coll2.add( rcv );
        }
       
        if( !coll3.isEmpty() ) {
          edit = new BasicCompoundEdit();
          final List selectedGroups = doc.getSelectedGroups().getAll();
          if( !selectedGroups.isEmpty() ) {
            for( int i = 0; i < coll3.size(); i++ ) {
              final GroupableSessionObject so = (GroupableSessionObject) coll3.get( i );
              edit.addPerform( new EditAddSessionObjects( this, so.getGroups(), selectedGroups ));
            }
          }
          edit.addPerform( new EditAddSessionObjects( this, doc.getMutableReceivers(), coll3 ));
//          for( int i = 0; i < doc.getSelectedGroups().size(); i++ ) {
//            group  = (SessionGroup) doc.getSelectedGroups().get( i );
//            edit.addPerform( new EditAddSessionObjects( this, group.getReceivers(), coll3 ));
//          }

          edit.addPerform( new EditSetSessionObjects( this, doc.getMutableSelectedReceivers(), coll3 ));
          edit.perform();
          edit.end();
          doc.getUndoManager().addEdit( edit );
        }
       
        success = true;
      }
      finally {
        doc.bird.releaseExclusive( Session.DOOR_RCV | Session.DOOR_GRP );
      }
    }
    catch( IllegalStateException e1 ) {
      System.err.println( AbstractApplication.getApplication().getResourceString( "errClipboard" ));
    }
    catch( UnsupportedFlavorException e2 ) {}
    catch( IOException e3 ) {}

    return success;
  }

  /*
   *  Deletes all selected receivers
   *  from the surface (undoable)
   *
   *  @synchronization  waitExclusive on DOOR_RCV + DOOR_GRP
   */
  private void editClear()
  {
    ((MenuFactory) ((BasicApplication) AbstractApplication.getApplication()).getMenuFactory()).actionRemoveReceivers.perform();
// 
//    java.util.List  collSelection;
//    CompoundEdit  edit;
//    SessionGroup  group;
//    int        i;
//
//    try {
//      doc.bird.waitExclusive( Session.DOOR_RCV | Session.DOOR_GRP );
//      collSelection   = doc.selectedReceivers.getAll();
//      edit      = new BasicSyncCompoundEdit( doc.bird, Session.DOOR_RCV | Session.DOOR_GRP );
//      edit.addEdit( new EditSetSessionObjects( this, doc, doc.selectedReceivers,
//                                new ArrayList( 1 ), Session.DOOR_RCV ));
//      for( i = 0; i < doc.groups.size(); i++ ) {
//        group  = (SessionGroup) doc.selectedGroups.get( i );
//        edit.addEdit( new EditRemoveSessionObjects( this, doc, group.receivers, collSelection, Session.DOOR_RCV ));
//      }
//      edit.addEdit( new EditRemoveSessionObjects( this, doc, doc.receivers,
//                            collSelection, Session.DOOR_RCV ));
//      edit.end();
//      doc.getUndoManager().addEdit( edit );
//    }
//    finally {
//      doc.bird.releaseExclusive( Session.DOOR_RCV | Session.DOOR_GRP );
//    }
  }

  /*
   *  Selects all receivers (undoable)
   *
   *  @synchronization  waitExclusive on DOOR_RCV
   */
  private void editSelectAll()
  {
    final PerformableEdit edit;
 
    try {
      doc.bird.waitExclusive( Session.DOOR_RCV );
      edit = new EditSetSessionObjects( this, doc.getMutableSelectedReceivers(), doc.getMutableReceivers().getAll() );
      doc.getUndoManager().addEdit( edit.perform() );
    }
    finally {
      doc.bird.releaseExclusive( Session.DOOR_RCV );
    }
  }

  /**
   *  Returns the surface panel
   *
   *  @return the surface which is attached to this frame
   */
  public SurfacePane getSurfacePane()
  {
    return surface;
  }

// ---------------- LaterInvocationManager.Listener interface ----------------

  // o instanceof PreferenceChangeEvent
  public void preferenceChange( PreferenceChangeEvent pce )
  {
    String  key    = pce.getKey();
    String  value  = pce.getNewValue();
    boolean  b;

    if( key.equals( PrefsUtil.KEY_VIEWRULERS )) {
      b = Boolean.valueOf( value ).booleanValue();
      haxisBox.setVisible( b );
      vaxis.setVisible( b );
    }
  }

// ---------------- DocumentFrame abstract methods ----------------
 
  protected Action getCutAction() { return new ActionCut(); }
  protected Action getCopyAction() { return new ActionCopy(); }
  protected Action getPasteAction() { return new ActionPaste(); }
  protected Action getDeleteAction() { return new ActionDelete(); }
  protected Action getSelectAllAction() { return new ActionSelectAll(); }
 
// ---------------- EditMenuListener interface ----------------

  private class ActionCut
  extends MenuAction
  {
    protected ActionCut() { /* empty */ }

    public void actionPerformed( ActionEvent e )
    {
      if( editCopy() ) editClear();
    }
  }
 
  private class ActionCopy
  extends MenuAction
  {
    protected ActionCopy() { /* empty */ }

    public void actionPerformed( ActionEvent e )
    {
      editCopy();
    }
  }

  private class ActionPaste
  extends MenuAction
  {
    protected ActionPaste() { /* empty */ }

    public void actionPerformed( ActionEvent e )
    {
      editPaste();
    }
  }

  private class ActionDelete
  extends MenuAction
  {
    protected ActionDelete() { /* empty */ }

    public void actionPerformed( ActionEvent e )
    {
      editClear();
    }
  }

  private class ActionSelectAll
  extends MenuAction
  {
    protected ActionSelectAll() { /* empty */ }

    public void actionPerformed( ActionEvent e )
    {
      editSelectAll();
    }
  }

// ---------------- ClipboardOwner interface ----------------

  public void lostOwnership( Clipboard clipboard, Transferable contents )
  {
    // XXX evtl. dispose() aufrufen
  }
}
TOP

Related Classes of de.sciss.meloncillo.surface.SurfaceFrame

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.