Package de.sciss.common

Source Code of de.sciss.common.BasicWindowHandler$MasterFrame

/*
*  BasicWindowHandler.java
*  (de.sciss.common 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:
*    21-May-05  created
*    09-Jul-06  hosts a FloatingPaletteHandler
*/

package de.sciss.common;

import java.awt.Component;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.GraphicsEnvironment;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.StringTokenizer;
import java.util.prefs.Preferences;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JDesktopPane;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JMenuBar;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;

import net.roydesign.mac.MRJAdapter;

import de.sciss.app.AbstractApplication;
import de.sciss.app.AbstractWindow;
import de.sciss.app.WindowHandler;
import de.sciss.gui.AbstractWindowHandler;
import de.sciss.gui.FloatingPaletteHandler;
import de.sciss.gui.GUIUtil;
import de.sciss.gui.MenuRoot;
import de.sciss.gui.WindowListenerWrapper;

//import de.sciss.eisenkraut.Main;
//import de.sciss.eisenkraut.util.PrefsUtil;

/**
@author    Hanns Holger Rutz
@version  0.72, 13-Jul-08
*/
public class BasicWindowHandler
extends AbstractWindowHandler
{
  /**
   *  Value: Boolean stating whether internal frames within one
     *  big app frame are used. Has default value: no!<br>
   *  Node: root
   */
  public static final String KEY_INTERNALFRAMES = "internalframes";

  /**
   *  Value: Boolean stating whether palette windows should
     *  be floating on top and have palette decoration. Has default value: no!<br>
   *  Node: root
   */
  public static final String KEY_FLOATINGPALETTES = "floatingpalettes";

  /**
   *  Value: Boolean stating whether to use the look-and-feel (true)
     *  or native (false) decoration for frame borders. Has default value: no!<br>
   *  Node: root
   */
  public static final String KEY_LAFDECORATION = "lafdecoration";

  /**
   *  Value: Rectangle describing the usable screen space last time
     *  the application was launched. Has default value: no!<br>
   *  Node: root
   */
  public static final String KEY_SCREENSPACE = "screenspace";

  private final FloatingPaletteHandler  fph;
  private final boolean          internalFrames, floating;
  protected final JDesktopPane      desktop;
  private final MasterFrame        masterFrame;
//  private final Window          hiddenTopWindow;
 
  private final List            collBorrowListeners    = new ArrayList();
  private AbstractWindow          borrower        = null;
  private AbstractWindow          defaultBorrower      = null;    // when no doc frame active (usually the main log window)

  private final Action          actionCollect;
  private final boolean          autoCollect;
 
  private final BasicApplication      root;

  public BasicWindowHandler( BasicApplication root )
  {
    super();
   
    final Preferences  prefs  = root.getUserPrefs();
    final boolean    lafDeco = prefs.getBoolean( KEY_LAFDECORATION, false );
    final Rectangle    oScreen  = stringToRectangle( prefs.get( KEY_SCREENSPACE, null ));
    final Rectangle    nScreen;
    JFrame.setDefaultLookAndFeelDecorated( lafDeco );
   
    this.root    = root;
    internalFrames  = prefs.getBoolean( KEY_INTERNALFRAMES, false );
    floating    = prefs.getBoolean( BasicWindowHandler.KEY_FLOATINGPALETTES, false );
    fph        = FloatingPaletteHandler.getInstance();

    if( internalFrames ) {
      masterFrame = new MasterFrame();
      masterFrame.setTitle( root.getName() );
//      masterFrame.setSize( 400, 400 ); // XXX
//      masterFrame.setVisible( true );
      desktop    = new JDesktopPane();
      masterFrame.getContentPane().add( desktop );
//      hiddenTopWindow = null;
    } else {
      desktop    = null;
      masterFrame  = null;
      fph.setListening( true );
//      if( floating ) {
//        hiddenTopWindow = new Frame();
//        GUIUtil.setAlwaysOnTop( hiddenTopWindow, true );
//      } else {
//        hiddenTopWindow = null;
//      }
    }
   
    nScreen    = calcOuterBounds();
    autoCollect  = !nScreen.equals( oScreen );
    prefs.put( KEY_SCREENSPACE, rectangleToString( nScreen ));
    actionCollect = new ActionCollect( root.getResourceString( "menuCollectWindows" ));
//System.out.println( "autoCollect = " + autoCollect );
   
//    MenuGroup  mg;
//
//    mg  = (MenuGroup) root.getMenuFactory().get( "window" );
//    mg.add( new MenuItem( "collect", new actionCollectClass( root.getResourceString( "menuCollectWindows" ))));
//    mg.addSeparator();
  }
 
  public MenuRoot getMenuBarRoot()
  {
    return root.getMenuBarRoot();
  }
 
  public Action getCollectAction()
  {
    return actionCollect;
  }
 
  public static Component getWindowAncestor( Component c )
  {
    final WindowHandler wh = AbstractApplication.getApplication().getWindowHandler();
   
    return SwingUtilities.getAncestorOfClass( (wh instanceof BasicWindowHandler) && ((BasicWindowHandler) wh).internalFrames ?
                          JInternalFrame.class : Window.class, c );
  }
 
  // make sure the menuFactory is ready when calling this
  public void init()
  {
    if( masterFrame != null ) {
      masterFrame.setDefaultMenuBar( root.getMenuBarRoot().createBar( masterFrame ));
      masterFrame.setVisible( true );
    }
  }
 
  public void setMenuBarBorrower( AbstractWindow w )
  {
    borrower = w;
    for( Iterator iter = collBorrowListeners.iterator(); iter.hasNext(); ) {
      ((AppWindow) iter.next()).borrowMenuBar( borrower == null ? defaultBorrower : borrower );
    }
  }
 
  public void setDefaultBorrower( AbstractWindow w )
  {
    if( !internalFrames ) {
      defaultBorrower = w;
    }
  }
 
  public void addBorrowListener( AppWindow w )
  {
    collBorrowListeners.add( w );
  }
 
  public void removeBorrowListener( AppWindow w )
  {
    collBorrowListeners.remove( w );
  }
 
  public AbstractWindow getMenuBarBorrower()
  {
    return( borrower == null ? defaultBorrower : borrower );
  }
 
//  public MenuRoot getMenuBarRoot()
//  {
//    return ((BasicApplication) AbstractApplication.getApplication()).getMenuBarRoot();
//  }
//
//  public Font getDefaultFont()
//  {
//    return GraphicsUtil.smallGUIFont;
//  }
//
//  public void addWindow( Window w, Map options )
//  {
//    super.addWindow( w, options );
//    if( (w instanceof FloatingPalette) && ((FloatingPalette) w).isFloating() ) {
//      fph.addPalette( w );
//    } else {
//      fph.addFrame( w );
//    }
//  }
 
  public void addWindow( AbstractWindow w, Map options )
  {
    super.addWindow( w, options );
//    if( (w instanceof FloatingPalette) && ((FloatingPalette) w).isFloating() ) {
    if( fph != null ) fph.add( w );
//System.out.println( "checkin " + w );
    if( autoCollect ) {
      collect( w, calcOuterBounds() );
    }
//    if( w.isFloating() ) {
//      fph.addPalette( w );
//    } else {
//      fph.addFrame( w );
//    }
  }
 
//  public void removeWindow( Window w, Map options )
//  {
//    super.removeWindow( w, options );
//    if( (w instanceof FloatingPalette) && ((FloatingPalette) w).isFloating() ) {
//      fph.removePalette( w );
//    } else {
//      fph.removeFrame( w );
//    }
//  }

  public void removeWindow( AbstractWindow w, Map options )
  {
    super.removeWindow( w, options );
    if( fph != null ) fph.remove( w );
//    if( w.isFloating() ) {
//      fph.removePalette( w );
//    } else {
//      fph.removeFrame( w );
//    }
  }
 
  public AbstractWindow createWindow( int flags )
  {
//    final BasicFrame f = new BasicFrame();
//    f.init( root );
//    return f;
    return new AppWindow( flags );
  }
 
  public boolean usesInternalFrames()
  {
    return internalFrames;
  }

  public boolean usesFloating()
  {
    return floating;
  }

  public boolean usesScreenMenuBar()
  {
    return MRJAdapter.isSwingUsingScreenMenuBar();
  }

  public JDesktopPane getDesktop()
  {
    return desktop;
  }
 
  public AbstractWindow getMasterFrame()
  {
    return masterFrame;
  }
 
//  public Window getHiddenTopWindow()
//  {
//    return hiddenTopWindow;
//  }
 
  public Rectangle getWindowSpace()
  {
    if( masterFrame != null ) {
      return new Rectangle( 0, 0, masterFrame.getWidth(), masterFrame.getHeight() );
    } else {
      return GraphicsEnvironment.getLocalGraphicsEnvironment().getMaximumWindowBounds();
    }
  }
 
  public void place( AbstractWindow w, float halign, float valign )
  {
    final Rectangle sr = getWindowSpace();
    final Dimension wd = w.getSize();
    w.setLocation( new Point(
      (int) (sr.x + halign * (sr.width - wd.width)),
       (int) (sr.y + valign * (sr.height - wd.height)) ));
  }
 
//  public Action getCollectAction()
//  {
//    return actionCollect;
//  }
 
  private static Rectangle stringToRectangle( String value )
  {
    Rectangle        rect  = null;
    final StringTokenizer  tok;
   
    if( value != null ) {
      try {
        tok    = new StringTokenizer( value );
        rect  = new Rectangle( Integer.parseInt( tok.nextToken() ), Integer.parseInt( tok.nextToken() ),
                     Integer.parseInt( tok.nextToken() ), Integer.parseInt( tok.nextToken() ));
      }
      catch( NoSuchElementException e1 ) { e1.printStackTrace(); }
      catch( NumberFormatException e2 ) { e2.printStackTrace(); }
    }
    return rect;
  }

  private static String rectangleToString( Rectangle value )
  {
    return( value != null ? (value.x + " " + value.y + " " + value.width + " " + value.height) : null );
  }

  protected Rectangle calcOuterBounds()
  {
    final Rectangle  outerBounds;
    final boolean  isMacOS = System.getProperty( "os.name" ).indexOf( "Mac OS" ) >= 0;
   
    if( desktop == null ) {
      outerBounds = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration().getBounds();
      if( isMacOS ) {
        outerBounds.y     += 22;
        outerBounds.width -= 80;
        outerBounds.height-= 22;
      }
    } else {
      outerBounds = new Rectangle( 0, 0, desktop.getWidth(), desktop.getHeight() );
    }
    return outerBounds;
  }

  protected void collect( AbstractWindow w, Rectangle outerBounds )
  {
    final boolean  adjustLeft, adjustTop;
    final Rectangle  winBounds;
    boolean      adjustRight, adjustBottom;
   
    winBounds  = w.getBounds();
    adjustLeft  = winBounds.x < outerBounds.x;
    adjustTop  = winBounds.y < outerBounds.y;
    adjustRight  = (winBounds.x + winBounds.width) > (outerBounds.x + outerBounds.width);
    adjustBottom= (winBounds.y + winBounds.height) > (outerBounds.y + outerBounds.height);
   
    if( !(adjustLeft || adjustTop || adjustRight || adjustBottom) ) return;

    if( adjustLeft ) {
      winBounds.x = outerBounds.x;
      adjustRight  = (winBounds.x + winBounds.width) > (outerBounds.x + outerBounds.width);
    }
    if( adjustTop ) {
      winBounds.y = outerBounds.y;
      adjustBottom= (winBounds.y + winBounds.height) > (outerBounds.y + outerBounds.height);
    }
    if( adjustRight ) {
      winBounds.x = Math.max( outerBounds.x, outerBounds.x + outerBounds.width - winBounds.width );
      adjustRight  = (winBounds.x + winBounds.width) > (outerBounds.x + outerBounds.width);
      if( adjustRight && w.isResizable() ) winBounds.width = outerBounds.width;
    }
    if( adjustBottom ) {
      winBounds.y = Math.max( outerBounds.y, outerBounds.y + outerBounds.height - winBounds.height );
      adjustBottom= (winBounds.y + winBounds.height) > (outerBounds.y + outerBounds.height);
      if( adjustBottom && w.isResizable() ) winBounds.height = outerBounds.height;
    }
    w.setBounds( winBounds );
  }

  public static void showDialog( Dialog dlg )
  {
    final BasicWindowHandler wh = (BasicWindowHandler) AbstractApplication.getApplication().getWindowHandler();
    wh.instShowDialog( dlg );
  }
 
  public static int showDialog( JOptionPane op, Component parent, String title )
  {
    final JDialog  dlg;
    final Object  value;
    final int    result;
   
    dlg = op.createDialog( parent, title );
    showDialog( dlg );
    value = op.getValue();
    if( value == null ) {
      result = JOptionPane.CLOSED_OPTION;
    } else {
      final Object[] options = op.getOptions();
      if( options == null ) {
        if( value instanceof Integer ) {
          result = ((Integer) value).intValue();
        } else {
          result = JOptionPane.CLOSED_OPTION;
             }
      } else {
        int i;
        for( i = 0; i < options.length; i++ ) {
              if( options[ i ].equals( value )) break;
        }
        result = i < options.length ? i : JOptionPane.CLOSED_OPTION;
      }
    }
    return result;
  }

  public static void showErrorDialog( Component component, Throwable exception, String title )
  {
    final StringBuffer  strBuf  = new StringBuffer( GUIUtil.getResourceString( "errException" ));
    final JOptionPane  op;
    String        message = exception.getClass().getName() + " - " + exception.getLocalizedMessage();
    StringTokenizer    tok;
    int          lineLen = 0;
    String        word;
    String[]      options = { GUIUtil.getResourceString( "buttonOk" ),
                    GUIUtil.getResourceString( "optionDlgStack" )};
 
    if( message == null ) message = exception.getClass().getName();
    tok = new StringTokenizer( message );
    strBuf.append( ":\n" );
    while( tok.hasMoreTokens() ) {
      word = tok.nextToken();
      if( lineLen > 0 && lineLen + word.length() > 40 ) {
        strBuf.append( "\n" );
        lineLen = 0;
      }
      strBuf.append( word );
      strBuf.append( ' ' );
      lineLen += word.length() + 1;
    }
    op = new JOptionPane( strBuf.toString(), JOptionPane.ERROR_MESSAGE, JOptionPane.YES_NO_OPTION, null, options, options[ 0 ]);
    if( showDialog( op, component, title ) == 1 ) {
      exception.printStackTrace();
    }
  }

  private void instShowDialog( Dialog dlg )
  {
//    System.out.println( "instShowDialog" );
   
    final AbstractWindow  w;
    final List        wasOnTop  = new ArrayList();
    final boolean      modal    = dlg.isModal() && (fph != null);
    AbstractWindow      w2;
//boolean gaga = false;
   
    // temporarily disable alwaysOnTop
    if( !internalFrames && floating ) {
      for( Iterator iter = getWindows(); iter.hasNext(); ) {
        w2 = (AbstractWindow) iter.next();
        if( GUIUtil.isAlwaysOnTop( w2.getWindow() )) {
//gaga = true;
//break;
          wasOnTop.add( w2 );
          GUIUtil.setAlwaysOnTop( w2.getWindow(), false );
        }
      }
    }
    try {
      w = new AppWindow( dlg );
      w.init()// calls addWindow
//      ((AppWindow) w).gaga();
       
      // --- modal interruption ---
      if( modal ) fph.addModalDialog(); // this shit is necessary because java.awt.FileDialog doesn't fire windowActivated ...
//      if( gaga ) GUIUtil.setAlwaysOnTop( dlg, true );
      w.setVisible( true );
      if( modal ) fph.removeModalDialog();
     
  //    wh.removeWindow( w, null );
      w.dispose()// calls removeWindow

    } finally { // make sure to restore original state
      for( int i = 0; i < wasOnTop.size(); i++ ) {
        w2 = (AbstractWindow) wasOnTop.get( i );
//        System.out.println( "wasOnTop " + i + " : " + w2.getClass().getName() );
        GUIUtil.setAlwaysOnTop( w2.getWindow(), true );
      }
    }
  }

  // -------------------- internal classes --------------------
  private static class MasterFrame
  extends JFrame
  implements AbstractWindow
  {
    private JMenuBar bar = null;
   
    protected MasterFrame()
    {
      super();
     
      setBounds( GraphicsEnvironment.getLocalGraphicsEnvironment().getMaximumWindowBounds() );
    }
   
    public void init() { /* empty */ }
   
    protected void setDefaultMenuBar( JMenuBar m )
    {
      bar = m;
      setJMenuBar( null );
    }
   
    public void setJMenuBar( JMenuBar m )
    {
      super.setJMenuBar( m == null ? bar : m );
    }
   
    public void revalidate()
    {
      getRootPane().revalidate();
    }
   
    public void setDirty( boolean b ) { /* empty */ }
   
    public ActionMap getActionMap()
    {
      return getRootPane().getActionMap();
    }

    public InputMap getInputMap( int mode )
    {
      return getRootPane().getInputMap( mode );
    }

    public void addListener( Listener l )
    {
      WindowListenerWrapper.add( l, this );
    }
   
    public void removeListener( Listener l )
    {
      WindowListenerWrapper.remove( l, this );
    }
   
    public boolean isFloating()
    {
      return false;
    }
   
    public Component getWindow()
    {
      return this;
    }
  }
 
  private class ActionCollect
  extends AbstractAction
  {
    protected ActionCollect( String text )
    {
      super( text );
    }
   
    public void actionPerformed( ActionEvent e )
    {
      final Rectangle  outerBounds = calcOuterBounds();

      for( Iterator iter = getWindows(); iter.hasNext(); ) {
        collect( (AbstractWindow) iter.next(), outerBounds );
      }
    }
  }
}
TOP

Related Classes of de.sciss.common.BasicWindowHandler$MasterFrame

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.