import java.awt.*;

class book_layout implements LayoutManager {
    private int minWidth = 0, minHeight = 0;
    private int preferredWidth = 0, preferredHeight = 0;
	book fl;

	public book_layout (book fl){
		super();
		this.fl = fl;
	}

	public void addLayoutComponent(String name, Component comp) {
	}
	public void removeLayoutComponent(Component comp) {
	}

	private Dimension setsizes (int left, int top, boolean use_cur_dim){
		//if (!fl.was_modified()) return;

		int n = fl.countComponents();
  		int bkwidth = 0;
		int bkheight = 0;
		FontMetrics met = fl.getGraphics().getFontMetrics();
		int padswidth = 0;
		for (int i=0; i<n; i++){
			Component c = fl.getComponent(i);
			Dimension d = use_cur_dim
					? c.size()
					: c.preferredSize();

			if (d.width > bkwidth) bkwidth = d.width;
			if (d.height > bkheight) bkheight = d.height;
			int padwidth = met.stringWidth(fl.pads[i].title) + 20;
			fl.pads[i].start = padswidth;
			fl.pads[i].below = false;
			padswidth += padwidth;
			fl.pads[i].stop = padswidth;
		}
		int bottom_pads = 0;
		if (padswidth > bkwidth){
			for (int i=0; i<n; i++){
				if (fl.pads[i].stop > bkwidth){
					// Move those pads to the bottom
					bottom_pads = 20;
					int off = fl.pads[i].start;
					for (; i<n; i++){
						fl.pads[i].below = true;
						fl.pads[i].start -= off;
						fl.pads[i].stop  -= off;
					}
					break;
				}
			}
		}
		bkwidth += left;
		bkheight += top + 20;
		fl.b_offsety = bkheight;
		bkheight += bottom_pads;
		fl.offsetx = left;
		fl.offsety = top + 20;
		for (int i=0; i<n; i++){
			Component c = fl.getComponent(i);
			Dimension d = use_cur_dim
				? c.size()
				: c.preferredSize();
			c.reshape (fl.offsetx,fl.offsety,d.width,d.height);
			if (i==fl.nopage){
				c.show();
			}else{
				c.hide();
			}
		}
		return new Dimension (bkwidth,bkheight);
	}

	private Dimension setsizes (Container parent, boolean use_cur_dim){
		Dimension dim = new Dimension(0, 0);
		int nComps = parent.countComponents();

		Insets insets = parent.insets();
		Dimension d = setsizes (insets.left+3,insets.top,false);
		preferredWidth = minWidth = d.width;
		preferredHeight = minHeight = d.height;

		//Always add the container's insets!
		dim.width = preferredWidth + insets.right + 3;
		dim.height = preferredHeight + insets.bottom + 3;

		return dim;
	}
	/* Required by LayoutManager. */
	public Dimension preferredLayoutSize(Container parent) {
		return setsizes (parent,false);
	}

	/* Required by LayoutManager. */
	public Dimension minimumLayoutSize(Container parent) {
		Dimension dim = new Dimension(0, 0);
		//Always add the container's insets!
		Insets insets = parent.insets();
		dim.width = minWidth + insets.left + insets.right;
		dim.height = minHeight + insets.top + insets.bottom;
		return dim;
	}

	/* Required by LayoutManager. */
	/* This is called when the panel is first displayed, 
	 * and every time its size changes. 
	 * Note: You CAN'T assume preferredLayoutSize() or minimumLayoutSize()
	 * will be called -- in the case of applets, at leas, they probably
	 * won't be. */
	public void layoutContainer(Container parent) {
		Dimension pref = preferredLayoutSize(parent);
		Dimension  cur = parent.size();
		int diffx = cur.width - pref.width;
		int diffy = cur.height - pref.height;
System.err.println ("layoutContainer " + fl.id + " " + diffx + " " + diffy);
		if (diffx > 0 || diffy > 0){
			int n = fl.countComponents();
			for (int i=0; i<n; i++){
				Component c = fl.getComponent(i);
				Dimension d = c.preferredSize();
				c.resize(d.width+diffx,d.height+diffy);
			}
			setsizes (parent,true);
		}
    }
    
	public String toString() {
		String str = "";
		return getClass().getName() + "[" + str + "]";
	}
}

class pagepad{
	public String title;
	public int start;	// Horizontal coordinate of the pad
	public int stop;	// End of the pad
	public boolean below;	// Above or below the forms
	public pagepad(String title){
		this.title = title;
		start = 0;
		stop = 0;
		below = false;
	}
}
	
class book extends formbase{
	int nbpage;
	public int nopage;
	public int offsetx,offsety,b_offsety;
	public pagepad pads[];
	public book(formbase _parent, String _id){
		super(_parent,_id);
		nbpage = 0;
		nopage = 0;
		pads = new pagepad[20];
		offsetx = offsety = b_offsety = 0;
		setLayout(new book_layout(this));
	}
	public void New_page (Component c, String s){
		pads[nbpage++] = new pagepad(s);
		add (c);
	}
	public mform New_form (String s){
		pads[nbpage++] = new pagepad(s);
		mform ret = new mform (this,"");
		add (ret);
		return ret;
	}
	private void drawsel (Graphics g, int no, boolean select){
		// The selected pad has a double edge because it is on
		// top while the non selected ones have a single edge
		// which shows that they are lower
		int x0 = pads[no].start+1;
		int x1 = x0 + 3;
		int x3 = pads[no].stop;
		int x2 = x3 - 3;
		if (pads[no].below){
			int y1 = b_offsety;
			int y2 = b_offsety + 1;
			int by2 = b_offsety + 18;
			g.setColor (Color.black);
			g.drawString (pads[no].title,x1+7,b_offsety + 15);
			g.drawLine (x0 == 1 ? x0 +1 : x0 ,y1,x1,y1);
			g.drawLine (x0,y2,x1,y2);
			g.drawLine (x1,by2,x2,by2);

			g.drawLine (x2,y1,x3,y1);
			g.drawLine (x2,y2,x3,y2);


			g.setColor (Color.white);
			g.drawLine (x1,by2,x1,y1+1);
			if (!select) g.setColor (Color.lightGray);
			{
				int x1_1 = x1 + 1;
				g.drawLine (x1_1,by2,x1_1,y1+1);
			}

			g.setColor (Color.black);
			g.drawLine (x2,by2,x2,y1);
			if (!select) g.setColor (Color.lightGray);
			{
				int x2_1 = x2 + 1;
				g.drawLine (x2_1,by2,x2_1,y1+1);
				g.drawLine (x1,by2+1,x2,by2+1);
			}

			g.setColor (select ? Color.lightGray : Color.black);
			g.drawLine (x1,y1,x2,y1);
			g.drawLine (x1,y2,x2,y2);
		}else{
			int y1 = offsety - 2;
			int y2 = offsety - 1;
			g.setColor (Color.black);
			g.drawString (pads[no].title,x1+7,15);
			g.setColor (Color.white);
			g.drawLine (no == 0 ? x0 +1 : x0 ,y1,x1,y1);
			g.drawLine (x0,y2,x1,y2);
			g.drawLine (x1,2,x1,y1+1);
			g.drawLine (x1,2,x2,2);
			g.drawLine (x2,y1,x3,y1);
			g.drawLine (x2,y2,x3,y2);
			if (!select) g.setColor (Color.lightGray);
			{
				int x1_1 = x1 - 1;
				g.drawLine (x1_1,2,x1_1,y1-1);
				g.drawLine (x1,1,x2,1);
			}

			g.setColor (Color.black);
			g.drawLine (x2,2,x2,y1);
			if (!select) g.setColor (Color.lightGray);
			{
				int x2_1 = x2+1;
				g.drawLine (x2_1,2,x2_1,y1-1);
			}

			g.setColor (select ? Color.lightGray : Color.white);
			g.drawLine (x1,y1,x2,y1);
			g.drawLine (x1,y2,x2,y2);
		}
	}
	public void selpage (int no){
		if (no != nopage){
			Graphics g = getGraphics();
			getComponent(nopage).hide();
			drawsel (g,nopage,false);
			nopage = no;
			getComponent(nopage).show();
			drawsel (g,nopage,true);
		}
	}
	private boolean locatepad (int x, boolean below){
		for (int i=0; i<nbpage; i++){
			if (pads[i].below == below
				&& pads[i].start < x
				&& x < pads[i].stop){
				selpage (i);
				return true;
			}
		}
		return false;
	}
	public boolean handleEvent(Event e) {
		if (e.id == e.MOUSE_DOWN){
			if (e.y < offsety){
				return locatepad(e.x,false);
			}else if (e.y > b_offsety){
				return locatepad(e.x,true);
			}
		}
		return false;
	}
	public void paint (Graphics g){
		Dimension d = size();
		int y0 = offsety - 2;
		int y1 = y0 + 1;
		int lasty = b_offsety + 1;
		int lastx = d.width-2;
		g.setColor (Color.white);
		//g.drawLine (1,y0,3,y0);
		//g.drawLine (pads[nbpage-1].stop-3,y0,lastx,y0);
		//g.drawLine (pads[nbpage-1].stop-3,y1,lastx-1,y1);
		g.drawLine (1,y0,lastx,y0);
		g.drawLine (2,y1,lastx-1,y1);
		g.drawLine (1,y0,1,lasty);
		g.drawLine (2,y1,2,lasty);

		// Bottom shadow
		g.setColor (Color.black);
		g.drawLine (1,lasty,lastx,lasty);
		int lasty_1 = lasty - 1;
		g.drawLine (2,lasty_1,lastx,lasty_1);

		// Right shadow
		g.drawLine (lastx,lasty,lastx,y0+2);
		int lastx_1 = lastx - 1;
		g.drawLine (lastx_1,lasty,lastx_1,y0+2);
		
		for (int i=0; i<nbpage; i++){
			drawsel (g,i,i==nopage);
		}
	}
	public void dump(){
		int n = countComponents();
		for (int i=0; i<n; i++){
			Component c = getComponent(i);
			formbase f = (formbase) c;
			f.dump();
		}
	}
	public boolean locate (String _id, mformctx ctx){
		boolean ret = false;
		ctx.bk = null;
		for (int i=0; i<nbpage; i++){
			mform m = (mform)getComponent(i);
			if (m.id.compareTo(_id)==0){
				ctx.fl = m;
				ctx.bk = null;
				ret = true;
				break;
			}
		}
		return ret;
	}
}

