
import java.awt.*; 
import java.awt.event.*;
//import java.awt.Color;
import java.awt.Dimension;

public class CollapsingPanel extends Panel {
    static String __revision__ = "$Id: CollapsingPanel.java,v 1.5 2001/12/18 00:33:05 akuchlin Exp $";

    public static final int COLLAPSE_VERTICAL = 0;
    public static final int COLLAPSE_HORIZONTAL = 1;
    
    int collapse_mode, collapsed_size;
    boolean minimized;
    int xsize, ysize;
    
    public CollapsingPanel(int collapse, int size) {
	super();
	
        this.minimized = false;
	this.collapse_mode = collapse;
	this.collapsed_size = size;

	this.enableEvents(AWTEvent.MOUSE_EVENT_MASK);
    }
    
    // Alternate constructors for default argument values
    public CollapsingPanel() {
	this(COLLAPSE_VERTICAL, 11);
	}
    
    public CollapsingPanel(int collapse) {
	this(collapse, 11);
    }
    
    
    public void processMouseEvent(MouseEvent e) {
	if (e.getID() != MouseEvent.MOUSE_CLICKED)
	    {
		super.processMouseEvent(e); 
		return;
	    }

	// If the panel is minimized and the user clicks on it, it
	// gets maximized again. 
        if (this.minimized) 
	    {
		this.maximize(); 
		e.consume(); 
	    }
        else
	    {
		// The panel is maximized, so we have to check the
		// coordinates of the mouse click.  If they're within
		// the thin strip along the proper edge, the panel
		// must be minimized.  Otherwise we just ignore the
		// click.

		if ( (this.collapse_mode == COLLAPSE_VERTICAL) &&
		     (e.getX() <= this.collapsed_size)  )
		    {
			this.minimize();
			e.consume();
			this.redraw();
		    }

		if ( (this.collapse_mode == COLLAPSE_HORIZONTAL &&
		      e.getY() <= this.collapsed_size ) )
                {
		    this.minimize(); 
		    e.consume();
		    this.redraw();
		}
	    }
	if (!e.isConsumed()) {super.processMouseEvent(e);}
    }

    // This internal method simply finds the root of the widget tree
    // (probably a Frame) and forces it to recompute its size, which
    // will also resize its contents.  Therefore the frame should
    // adjust itself properly to the fact that the CollapsingPanel has 
    // just changed its size.

    void redraw()
    {
	Component ptr = this;
        while (ptr.getParent() != null)
	    { 
		ptr = ptr.getParent(); 
	    }
	
        ptr.setSize( ptr.getPreferredSize() );
        ptr.validate();
        ptr.repaint();
    }

    // Return the preferred size of this panel.  In minimized mode,
    // it's a slim rectangle; in maximum mode, it calls awt.Panel's
    // method, which will query the Panel's layout manager and compute 
    // a result.

    public Dimension getPreferredSize() {
        if (this.minimized)
	    {
		if (this.collapse_mode == COLLAPSE_VERTICAL)
		    {
			return new Dimension( this.getSize().width,
					      this.collapsed_size);
		    }
		else 
		    {
			return new Dimension( this.collapsed_size,
					      this.getSize().height);
		    }
	    }
        return super.getPreferredSize();
    }

    void minimize() {
	int i;

        this.xsize = this.getSize().width;
	this.ysize = this.getSize().height;
	System.out.println("minimize: "+this.xsize +" "+this.ysize);
        this.minimized = true;
	
        if (this.collapse_mode == COLLAPSE_VERTICAL)
	    {
		this.setSize(this.xsize, this.collapsed_size);
	    }
        else
	    {
		this.setSize(this.collapsed_size, this.ysize );
	    }
	
        // Mark all the subcomponents as invisible
	Component array[] = this.getComponents();

        for (i=0; i<this.getComponentCount(); i++) {
            array[i].setVisible(false);
	}

        this.invalidate();
        this.getParent().setSize( this.getParent().getPreferredSize() );
    }

    void maximize() {
	int i;

	System.out.println("maximize: "+this.xsize +" "+this.ysize);
        this.minimized = false;
        
        // Mark all the subcomponents as visible
	Component array[] = this.getComponents();

        for (i=0; i<this.getComponentCount(); i++) 
	    {array[i].setVisible(true);}

        this.setSize( this.xsize, this.ysize );
        this.invalidate();
        this.getParent().setSize( this.getParent().getPreferredSize() );

    }

    void drawBar(Graphics gc, int x1, int y1, int width, int height)
    {
	int mid, x, y;


        gc.setColor( Color.darkGray );
        gc.drawRect(x1, y1, width, height);
        gc.clipRect(x1, y1, width,height);
        if (width < height)
	    {
		// Vertical orientation
		mid = x1 + width/2;
		for (y = y1 + 5; y < y1 + width; y += 6) {
		    gc.setColor(Color.white);
		    gc.drawRect(mid, y, 1,1);
		    gc.drawRect(mid-4, y+2, 1,1);
		    gc.setColor(Color.darkGray);
		    gc.drawRect(mid+2, y+2, 1,1);
		    gc.drawRect(mid-2, y+4, 1,1);
		}
	    }
        else
	    {
		// Horizontal orientation
		mid = y1 + height / 2;
		for (x = x1 + 5; x < x1 + width; x += 6) {
		    gc.setColor(Color.white);
		    gc.drawRect(x, mid, 1,1);
		    gc.drawRect(x+2, mid-4, 1,1);
		    gc.setColor(Color.darkGray);
		    gc.drawRect(x+2, mid+2, 1,1);
		    gc.drawRect(x+4, mid-2, 1,1);
		}
	    }
    }

    public void paint(Graphics gc)
    {
        if (this.minimized)
	    {
		if (this.collapse_mode == COLLAPSE_HORIZONTAL) {
		    this.drawBar(gc, 0,0, this.collapsed_size,
				 this.getSize().height-1);
		}
		else
		    {
			this.drawBar(gc, 0,0, this.getSize().width-1,
				     this.collapsed_size);
		    }
	    }
        else
	    {
		if (this.collapse_mode == COLLAPSE_VERTICAL) {
		    this.drawBar(gc, 0,0, this.collapsed_size,
				 this.getSize().height-1); 
		}
		else
		    {
			this.drawBar(gc, 0,0, this.getSize().width-1,
				     this.collapsed_size); 
		    }
	    }
    }

}

