
/**
 * Example showing extension of JSplitPane to provide correct hide/show operation.
 *
 * Contributed to Apache Chainsaw project.
 * Provided 'AS IS' with no warranty.
 *
 * @author David Barker <dbarker@borland.com>
 */
package com.borland.test;

import javax.swing.JFrame;
import javax.swing.JSplitPane;
import javax.swing.plaf.SplitPaneUI;
import java.awt.Component;
import java.awt.Graphics;
import javax.swing.plaf.basic.BasicSplitPaneUI;
import javax.swing.JPanel;
import java.awt.Color;
import java.awt.BorderLayout;
import javax.swing.JMenuBar;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.UIManager;

// *****************************************************************************
//                         Class: SplitPane
// *****************************************************************************

public class SplitPane extends JFrame
{
    // -------------------------------------------------------------------------
    //                            attributes
    // -------------------------------------------------------------------------

    protected FwSplitPane k_split;
    protected JPanel k_msgview;
    protected double m_last_location;

    // -------------------------------------------------------------------------
    //                            constructor
    // -------------------------------------------------------------------------

    public SplitPane()
    {
        setTitle( "SplitPane Sample" );
        addControls();
        addMenus();
        setSize(640,400);
        setLocationRelativeTo(null);
        setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
    }

    // -------------------------------------------------------------------------
    //                            main
    // -------------------------------------------------------------------------

    static public void main( String[] p_argv )
    {
        SplitPane  p = new SplitPane();
        p.setVisible(true);
    }

    // -------------------------------------------------------------------------
    //                            addControls
    // -------------------------------------------------------------------------

    public void addControls()
    {
        JPanel top = new JPanel();
        top.setBackground( Color.red );
        k_msgview = new JPanel();
        k_msgview.setBackground( Color.blue );
        k_split = new FwSplitPane(JSplitPane.VERTICAL_SPLIT,top,k_msgview);
        getContentPane().add( k_split, BorderLayout.CENTER );
        m_last_location = 0.8;
        k_split.setInitialSplit(m_last_location);
        k_split.setOneTouchExpandable(true);
    }

    // -------------------------------------------------------------------------
    //                            addControls
    // -------------------------------------------------------------------------

    public void addMenus()
    {
        JMenuBar mb = new JMenuBar();
        setJMenuBar(mb);

        // file menu
        JMenu file = new JMenu("File");
        file.setMnemonic('F');
        mb.add(file);

        JMenuItem exit = new JMenuItem("Exit",'x');
        file.add(exit);

        ActionListener exit_list = new ActionListener()
        {
            public void actionPerformed(ActionEvent e) { System.exit(0); }
        };
        exit.addActionListener(exit_list);

        // view menu
        JMenu view = new JMenu("View");
        view.setMnemonic('V');
        mb.add(view);

        JMenuItem show = new JMenuItem("Show Messages",'s');
        view.add(show);
        ActionListener show_list = new ActionListener()
        {
            public void actionPerformed(ActionEvent e) { onShowMessageView(); }
        };
        show.addActionListener(show_list);

        JMenuItem hide = new JMenuItem("Hide Messages",'h');
        view.add(hide);
        ActionListener hide_list = new ActionListener()
        {
            public void actionPerformed(ActionEvent e) { onHideMessageView(); }
        };
        hide.addActionListener(hide_list);
    }

    // -------------------------------------------------------------------------
    //                    updateLastKnownMsgSplitPosition
    // -------------------------------------------------------------------------

    public void updateLastKnownMsgSplitPosition()
    {
        double loc = k_split.getDividerProportionalLocation();
        if( loc>=0.0 && loc<1.0 ) m_last_location = loc;
    }

    // -------------------------------------------------------------------------
    //                            onHideMessageView
    // -------------------------------------------------------------------------

    public void onHideMessageView()
    {
         updateLastKnownMsgSplitPosition();
         k_split.adjustDividerSize(0);
         k_msgview.setVisible(false);
    }

    // -------------------------------------------------------------------------
    //                            onShowMessageView
    // -------------------------------------------------------------------------

    public void onShowMessageView()
    {
         if( m_last_location>0.95 ) m_last_location = 0.95;
         if( k_split != null )
         {
             Integer ds = (Integer)UIManager.get("SplitPane.dividerSize"); //NORES
             k_split.adjustDividerSize( ds==null ? 0 : ds.intValue() );
             k_split.setDividerLocation( m_last_location );
         }
         k_msgview.setVisible(true);
    }
}

// *****************************************************************************
//                         Class: FwSplitPane
// *****************************************************************************

class FwSplitPane extends JSplitPane
{
    // -------------------------------------------------------------------------
    //                            constants
    // -------------------------------------------------------------------------

    // use the golden mean to default to a supposedly 'aesthetically pleasing' ratio
    static public final double GOLDEN_MEAN = 1.61803;
    static public final double DFLT_INITSPLIT = 1.0 - 1.0 / GOLDEN_MEAN;

    // -------------------------------------------------------------------------
    //                            attributes
    // -------------------------------------------------------------------------

    protected double m_initial_split;
    protected boolean t_initialized;
    protected boolean m_flat;
    protected SplitPaneUI m_ui;

    // -------------------------------------------------------------------------
    //                            constructors
    // -------------------------------------------------------------------------

    public FwSplitPane( int p_orient, Component p_left_or_top, Component p_bottom_or_right, boolean p_flat_ui )
    {
        super( p_orient, p_left_or_top, p_bottom_or_right );
        setOneTouchExpandable(false);
        setContinuousLayout(false);
        setInitialSplit( DFLT_INITSPLIT );
        m_flat = p_flat_ui;
        updateUI();
    }

    ////////////////////////////////////////////////////////////////////////////

    public FwSplitPane( int p_orient, Component p_left_or_top, Component p_bottom_or_right )
    {
        this( p_orient, p_left_or_top, p_bottom_or_right, true );
    }

    ////////////////////////////////////////////////////////////////////////////

    public FwSplitPane( int p_orient )
    {
        this( p_orient, null, null, true );
    }

    ////////////////////////////////////////////////////////////////////////////

    public FwSplitPane()
    {
        this( JSplitPane.HORIZONTAL_SPLIT, null, null, true );
    }

    // -------------------------------------------------------------------------
    //                            get/setInitialSplit
    // -------------------------------------------------------------------------

    public double getInitialSplit() { return m_initial_split; }
    public void setInitialSplit( double p_initial_split ) { m_initial_split=p_initial_split; }

    // -------------------------------------------------------------------------
    //                       getDividerProportionalLocation
    // -------------------------------------------------------------------------

    public double getDividerProportionalLocation()
    {
         double size = 1.0;
         if( getOrientation() == VERTICAL_SPLIT )
             size = (double)( getHeight()-getDividerSize() );
         else
             size = (double)( getWidth()-getDividerSize() );
         return size==0.0 ? 0.0 : (double)getDividerLocation() / size;
    }

    // -------------------------------------------------------------------------
    //                            doLayout override
    // -------------------------------------------------------------------------

    public void doLayout()
    {
         // we need to defer setting the initial divider location until after
         // the peers have been created

         if( !t_initialized && getWidth()>0 && getHeight()>0 )
         {
             t_initialized = true;
             if( m_initial_split > -1.0 )
                 setDividerLocation( m_initial_split );
         }
         super.doLayout();
    }

    // -------------------------------------------------------------------------
    //                            updateUI override
    // -------------------------------------------------------------------------

    public void updateUI()
    {
        int sz = 0;
        if( t_initialized )
            sz = getDividerSize();
        super.updateUI();
        if( t_initialized && sz==0 )
            adjustDividerSize( sz );
    }

    // -------------------------------------------------------------------------
    //                            paintBorder override
    // -------------------------------------------------------------------------

    public void paintBorder( Graphics p_g )
    {
    }

    // -------------------------------------------------------------------------
    //                            setUI override
    // -------------------------------------------------------------------------

    public void setUI( SplitPaneUI p_ui )
    {
         if( m_ui == null ) m_ui = p_ui;
         super.setUI( p_ui );
         setBorder(null);
    }

    // -------------------------------------------------------------------------
    //                            adjustDividerSize
    // -------------------------------------------------------------------------

    public void adjustDividerSize( int p_newsize )
    {
         SplitPaneUI ui = m_ui;
         if( p_newsize == 0 )
             setUI( new BasicSplitPaneUI() );
         super.setDividerSize( p_newsize );
         if( p_newsize != 0 )
             setUI( ui );
    }
}
