Package de.sciss.gui

Source Code of de.sciss.gui.FloatingPaletteHandler

/*
*  FloatingPaletteHandler.java
*  (de.sciss.gui package)
*
*  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:
*    09-Jul-06  created
*/

package de.sciss.gui;

import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import javax.swing.Timer;

import de.sciss.app.AbstractApplication;
import de.sciss.app.Application;
import de.sciss.app.AbstractWindow;

/**
*  Regular windows and floating palettes register themselves with a
*  a <code>FloatingPaletteHandler</code>. The handler then takes care
*  of hiding and showing the palettes when the application becomes
*  active or inactive (i.e. one of the regular windows has focus or none of them).
*
*  The class is closely based on <code>FloatingPaletteHandler14</code> v2.0 by
*  Werner Randelshofer (Quaqua project).
*
@author    Hanns Holger Rutz
@version  0.13, 19-May-08
*
*  @synchronization  all methods must be called in the Swing thread
*
*  @todo        selecting an item from the right menu bar
*            (e.g. clock) causes a palette flicker
*/
public class FloatingPaletteHandler
implements ActionListener
{
  private static final int    TIMEOUT      = 100;

    private final Set        palettes    = new HashSet();
    protected final Set        frames      = new HashSet();
    private final Set        hiddenPalettes  = new HashSet();
    protected final Timer      timer;  // when executed, no frame has gotten focus since current window lost focus
    private AbstractWindow      focusedWindow  = null;
 
  private static final Map    instances    = new HashMap()// apps to instances
 
  private final AbstractWindow.Listener  winListener;
 
  private boolean          listen      = false;
//  private boolean          hidden      = false;
//  private AbstractWindow      borrower    = null;
   
  private static final boolean  DEBUG      = false;
 
  private int            modalDlgs    = 0;
 
    public static FloatingPaletteHandler getInstance()
  {
    return getInstance( AbstractApplication.getApplication() );
    }
 
    public static FloatingPaletteHandler getInstance( Application app )
  {
    FloatingPaletteHandler fph = (FloatingPaletteHandler) instances.get( app );
    if( fph == null ) {
      fph = new FloatingPaletteHandler();
      instances.put( app, fph );
    }
    return fph;
    }
   
    public FloatingPaletteHandler()
  {
        timer = new Timer( TIMEOUT, this );
        timer.setRepeats( false );

    winListener = new AbstractWindow.Adapter() {
//      public void windowGainedFocus( AbstractWindow.Event e )
      public void windowActivated( AbstractWindow.Event e )
      {
        final AbstractWindow w = e.getWindow();

        timer.stop();
       
        if( frames.contains( w )) {
          setFocusedWindow( w );
//        } else if( DEBUG ) {
//          System.out.println( "windowActivated : not registered : " + w );
        }
      }
     
//      public void windowLostFocus( AbstractWindow.Event e )
      public void windowDeactivated( AbstractWindow.Event e )
      {
        // since a focus traversal always contains
        // a focus loss and a focus gain, we have to
        // wait a little to make sure that no new
        // window was focussed. the timer is executed
        // after 100ms.
        timer.restart();
      }
    };
    }
 
  public void setListening( boolean b )
  {
    listen = b;
    if( !palettes.isEmpty() || !frames.isEmpty() ) throw new IllegalStateException( "Must only be called initially" );
  }
 
//  public void setMenuBarBorrower( AbstractWindow w )
//  {
//    if( (w != null) && !frames.contains( w )) throw new IllegalArgumentException( "Borrower was not registered" );
// 
//    for( Iterator iter = palettes.iterator(); iter.hasNext(); ) {
//      ((AbstractWindow) iter.next()).borrowMenuBar( w );
//    }
//   
//    borrower = w;
//  }
// 
//  public AbstractWindow getMenuBarBorrower()
//  {
//    return borrower;
//  }
   
    /**
     * Registers a project window with the FloatingPaletteHandler.
     * <p>
     * When none of the registered windows has focus, the FloatingPaletteHandler
     * hides all registered palette windows.
     * When at least one of the registered windows has focus, the
     * FloatingPaletteHandler shows all registered palette windows.
     */
  public void add( AbstractWindow w )
  {
      if( DEBUG ) System.out.println( "add : " + w.getClass().getName() );

      if( w.isFloating() ) {
      if( !palettes.add( w )) {
        throw new IllegalArgumentException( "Palette was already registered" );
      }
//      if( (borrower != null) && (w instanceof AppWindow) ) w.setMenuBarBorrower( borrower );
      if( listen ) w.addListener( winListener );
    } else {
      if( !frames.add( w )) {
        throw new IllegalArgumentException( "Frame was already registered" );
      }
     
      if( listen ) {
        w.addListener( winListener );
        if( isFocused( w )) {
//          setFocusedWindow( w );
focusedWindow = w;
if( DEBUG ) System.out.println( "focusedWindow = " + w.getClass().getName() );
        }
      }
    }
  }
 
//  public void switchFloating( AbstractWindow w )
//  {
//    if( w.isFloating() ) {
//      if( !frames.remove( w )) {
//        throw new IllegalArgumentException( "Frame was not registered" );
//      }
//     
//      if( listen ) {
//        w.removeListener( winListener );
//        if(  isFocused( w )) {
//focusedWindow = null;
//if( DEBUG ) System.out.println( "focusedWindow = null" );
//timer.restart();
//        }
//      }
//    } else {
//     
//    }
//  }
 
  public void addModalDialog()
  {
    modalDlgs++;
  }
 
  public void removeModalDialog()
  {
    modalDlgs--;
  }
   
    /**
     * Unregisters a project window with the FloatingPaletteHandler.
     */
    public void remove( AbstractWindow w )
  {
      if( DEBUG ) System.out.println( "remove : " + w.getClass().getName() );

      if( w.isFloating() ) {
      if( !palettes.remove( w )) {
        throw new IllegalArgumentException( "Palette was not registered" );
      }
      if( listen ) w.removeListener( winListener );
      hiddenPalettes.remove( w );
     
    } else {
      if( !frames.remove( w )) {
        throw new IllegalArgumentException( "Frame was not registered" );
      }
     
      if( listen ) {
        w.removeListener( winListener );
        ifisFocused( w )) {
//          setFocusedWindow( null );
focusedWindow = null;
if( DEBUG ) System.out.println( "focusedWindow = null" );
//System.out.println( "got null" );
timer.restart();
        }
      }
    }
    }
   
    /**
     * Registers a palette window with the FloatingPaletteHandler.
     * <p>
     * The FloatingPaletteHandler shows and hides the palette windows depending
     * on the focused state of the registered project windows.
     */
//    public void addPalette( Window p ) {
//    if( !palettes.add( p )) {
//      throw new IllegalArgumentException( "Palette was already registered" );
//    }
//
//        p.addWindowFocusListener( this );
//    }
   
    /**
     * Removes a project window from the FloatingPaletteHandler.
     */
//    public void removePalette( Window p )
//  {
//    if( !palettes.remove( p )) {
//      throw new IllegalArgumentException( "Palette was not registered" );
//    }
//        p.removeWindowFocusListener( this );
//    }
   
    /**
     * Returns the current applicatin window (the window which was the last to
     * gain focus). Floating palettes may use this method to determine on which
     * window they need to act on.
     */
    public AbstractWindow getFocussedWindow() {
        return focusedWindow;
    }
   
//    public AbstractWindow findAFloatingPalette()
//    {
//      AbstractWindow w;
//        for( Iterator iter = palettes.iterator(); iter.hasNext(); ) {
//            w = (AbstractWindow) iter.next();
//            if( w.isVisible() ) return w;
//        }
//        return null;
//    }
   
  // --------------- ActionListener interface ---------------

  public void actionPerformed( ActionEvent e )
  {
    setFocusedWindow( null );
  }
   
  // --------------- private methods ---------------

    private static boolean isFocused( AbstractWindow w )
  {
//        if( w.isFocused() ) return true;
        if( w.isActive() ) return true;
   
        final Window[] owned = w.getOwnedWindows();
   
        for( int i = 0; i < owned.length; i++ ) {
            if( isFocused( owned[ i ])) return true;
        }
        return false;
    }

    private static boolean isFocused( Window w )
  {
        if( w.isFocused() ) return true;
   
        final Window[] owned = w.getOwnedWindows();
   
        for( int i = 0; i < owned.length; i++ ) {
            if( isFocused( owned[ i ])) return true;
        }
        return false;
    }
 
//    boolean DEBUG_ENTERED = false;
   
    protected void setFocusedWindow( AbstractWindow w )
  {
//if( !EventQueue.isDispatchThread() ) throw new IllegalMonitorStateException();
//      System.err.println( "setFocusedWindow " + w );
//      if( DEBUG_ENTERED ) throw new IllegalStateException( "DEADLOCK" );
//      DEBUG_ENTERED = true;
     
        focusedWindow = w;
    if( DEBUG ) System.out.println( "focusedWindow : " + (w == null ? null : w.getClass().getName()) );
   
    if( modalDlgs == 0 ) {
      if( w != null ) {
              showPalettes();
      } else {
        hidePalettes();
      }
    }
   
//      System.err.println( "...done" );
//      DEBUG_ENTERED = false;
  }
 
    private void showPalettes()
  {
//      hidden = false;
//System.out.println( "in the beginning " + (focusedWindow != null) );
    if( !hiddenPalettes.isEmpty() ) {
      // in metal look-n-feel, seems that
      // setVisible might dispatch instanenously\
      // somehow setting focusedWindow to null (weird?!!!)
//      final AbstractWindow w = focusedWindow;
      AbstractWindow w;
      for( Iterator iter = hiddenPalettes.iterator(); iter.hasNext(); ) {
        w = (AbstractWindow) iter.next();
        if( DEBUG ) System.out.println( "setVisible( true ) : " + w.getClass().getName() );
        w.setVisible( true );
      }
      if( DEBUG ) System.out.println( "hiddenPalettes.clear" );
      hiddenPalettes.clear();
      //    focusedWindow.requestFocus();
      // trick to not have the originally focussed window loose its focus due to palettes showing up
//System.out.println( "entonces " + (focusedWindow != null) );
     
      // for some reason focusedWindow can be null, although
      // showPalettes is only called when focusedWindow is not null
      // (bug 1953444). the only explanation is that setVisible will
      // immediately invoke one of windowActivated or windowDeactivated
      // without deferal to the event-queue... anyway, we're safe
      // by checking again against null...
      if( focusedWindow != null ) {
        if( DEBUG ) System.out.println( "setVisible( true ) : " + focusedWindow.getClass().getName() );
        focusedWindow.setVisible( true );
//        if( DEBUG ) System.out.println( "toFront : " + focusedWindow.getClass().getName() );
//        focusedWindow.toFront();
      }
    }
    }
   
    private void hidePalettes()
  {
//      hidden = true;
    AbstractWindow w;

    if( !frames.isEmpty() ) {
      for( Iterator iter = frames.iterator(); iter.hasNext(); ) {
        w = (AbstractWindow) iter.next();
        if( isFocused( w )) return;
      }
    }
    if( !palettes.isEmpty() ) {
            for( Iterator iter = palettes.iterator(); iter.hasNext(); ) {
                w = (AbstractWindow) iter.next();
                if( isFocused( w )) return;
            }
        }

    for( Iterator iter = palettes.iterator(); iter.hasNext(); ) {
            w = (AbstractWindow) iter.next();
      if( w.isVisible() ) {
        if( DEBUG ) {
          System.out.println( "hiddenPalettes.add : " + w.getClass().getName() );
          System.out.println( "setVisible( false ) : " + w.getClass().getName() );
        }
        hiddenPalettes.add( w );
        w.setVisible( false );
            }
        }
   
//    // XXX fuer test
//    for( Iterator iter = hiddenPalettes.iterator(); iter.hasNext(); ) {
//            w = (AbstractWindow) iter.next();
//      w.setVisible( false );
//      if( DEBUG ) System.out.println( "setVisible( false ) : " + w.getClass().getName() );
//    }
    }
}
TOP

Related Classes of de.sciss.gui.FloatingPaletteHandler

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.