/*
 * 作成日: 2006/03/15
 */
package net.sourceforge.swingx.jspread;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;

import javax.swing.Box;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

import net.sourceforge.swingx.Logger;

/**
 * JSpreadのビューを構築する。
 * いくつかのコンポーネントは名前がついており、JSpreadUtilities.getComponent(String)で取得できる。
	<table border="1">
	<tr><th>名前</th><th>クラス</th></tr>
	<tr><td>"CellPane"</td><td>JSpreadCellPane</td></tr>
	<tr><td>"RowHeaderPane"</td><td>JSpreadHeaderPane</td></tr>
	<tr><td>"ColumnHeaderPane"</td><td>JSpreadHeaderPane</td></tr>
	<tr><td>"UselessCorner"</td><td>JComponent</td></tr>
	</table>
 * @author Asan
 */
class JSpreadControllerBuilder implements JSpreadConstant {
	private static Logger logger = Logger.getLogger(JSpreadControllerBuilder.class);
	private final JSpread spread;

	JSpreadControllerBuilder(JSpread spread) {
		this.spread = spread;
	}
	
	/** 現在の状態に従ってビューを作成する. */
	JPanel createView(JPanel panel) {
		panel.removeAll();
		JSpreadSheet sheet = spread.getSheet();
		// シートがないとラベルを作成する。
		if (sheet == null) {
			panel.add(new JLabel("JSpread"));
			return panel;
		}
		// 現在の状態に従ってビューを作成する
		if (sheet.rowHeaderVisible && sheet.colHeaderVisible) {
			// ペインを作成
			JSpreadCellPane cellPane = createCellPane(sheet, 0, 0);
			JSpreadHeaderPane rowHeaderPane = createRowHeaderPane(sheet);
			JSpreadHeaderPane colHeaderPane = createColHeaderPane(sheet);
			JSpreadHeaderPane cornerPane = new JSpreadHeaderPane(JSpread.CORNER, spread);
			JSpread2x2Panel pane = new JSpread2x2Panel(0, 0);
			pane.setPane(0, 0, cornerPane); 
			pane.setPane(0, 1,	colHeaderPane);
			pane.setPane(1, 0, rowHeaderPane);
			pane.setPane(1, 1, cellPane);
			pane.addComponentListener(new CellResizeListener(spread));
			panel.setLayout(new BorderLayout());
			panel.add(pane, BorderLayout.CENTER);
			panel.invalidate();		// TODO:これは不要かな？あるいは、JSpread2x2Panel側でやるべき？
			return panel;
		} else if (sheet.rowHeaderVisible) {
			JSpreadCellPane cellPane = createCellPane(sheet, 0, 0);
			JSpreadHeaderPane rowHeaderPane = createRowHeaderPane(sheet);
			panel.setLayout(new BorderLayout());
			panel.add(rowHeaderPane, BorderLayout.WEST);
			panel.add(cellPane, BorderLayout.CENTER);
			panel.addComponentListener(new CellResizeListener(spread));
			panel.invalidate();
			return panel;
		} else if (sheet.colHeaderVisible) {
			JSpreadCellPane cellPane = createCellPane(sheet, 0, 0);
			JSpreadHeaderPane colHeaderPane = createColHeaderPane(sheet);
			panel.setLayout(new BorderLayout());
			panel.add(colHeaderPane, BorderLayout.NORTH);
			panel.add(cellPane, BorderLayout.CENTER);
			panel.addComponentListener(new CellResizeListener(spread));
			panel.invalidate();
			return panel;
		} else {
			JSpreadCellPane cellPane = createCellPane(sheet, 0, 0);
			return cellPane;
		}
	}
	protected JPanel createScrollView(JPanel panel, int vsbPolicy, int hsbPolicy) {
		// 現在の状態に従ってビューを作成する
		panel.removeAll();
		panel.setLayout(new BorderLayout());
		JSpreadSheet sheet = spread.getSheet();
		if (sheet.rowHeaderVisible && sheet.colHeaderVisible) {
			// ペインを作成
			JSpreadCellPane cellPane = createCellPane(sheet, 0, 0);
			JSpreadHeaderPane rowHeaderPane = createRowHeaderPane(sheet);
			JSpreadHeaderPane colHeaderPane = createColHeaderPane(sheet);
			JSpreadHeaderPane cornerPane = new JSpreadHeaderPane(JSpread.CORNER, spread);
			cornerPane.setName(CORNER_PANE_NAME);

			// JScrollPaneに割り当てる
			JScrollPane pane = new JScrollPane(vsbPolicy, hsbPolicy);
			pane.setViewportView(cellPane);
			pane.setColumnHeaderView(colHeaderPane);
			pane.setRowHeaderView(rowHeaderPane);
			pane.setCorner(JScrollPane.UPPER_LEFT_CORNER, cornerPane); 
			pane.setCorner(JScrollPane.LOWER_RIGHT_CORNER, createUselessCorner());
			// リスナを設定
			pane.addComponentListener(new CellResizeListener(spread));
			pane.invalidate();		// TODO:これは不要かな？
			panel.add(pane, BorderLayout.CENTER);
			return panel;
		} else if (sheet.rowHeaderVisible) {
			JSpreadCellPane cellPane = createCellPane(sheet, 0, 0);
			JSpreadHeaderPane rowHeaderPane = createRowHeaderPane(sheet);
			JScrollPane pane = new JScrollPane(vsbPolicy, hsbPolicy);
			pane.setViewportView(cellPane);
			pane.setRowHeaderView(rowHeaderPane);
			pane.addComponentListener(new CellResizeListener(spread));
			pane.invalidate();
			panel.add(pane, BorderLayout.CENTER);
			return panel;
		} else if (sheet.colHeaderVisible) {
			JSpreadCellPane cellPane = createCellPane(sheet, 0, 0);
			JSpreadHeaderPane colHeaderPane = createColHeaderPane(sheet);
			JScrollPane pane = new JScrollPane(vsbPolicy, hsbPolicy);
			pane.setViewportView(cellPane);
			pane.setColumnHeaderView(colHeaderPane);
			pane.addComponentListener(new CellResizeListener(spread));
			pane.invalidate();
			panel.add(pane, BorderLayout.CENTER);
			return panel;
		} else {
			JSpreadCellPane cellPane = createCellPane(sheet, 0, 0);
			JScrollPane pane = new JScrollPane(cellPane, vsbPolicy, hsbPolicy);
			panel.add(pane, BorderLayout.CENTER);
			return panel;
		}
	}
	// TODO:引数r,cは不要か？
	protected JSpreadCellPane createCellPane(JSpreadSheet sheet, int r, int c) {
		JSpreadCellPane cellPane = new JSpreadCellPane(spread, r, c);
		cellPane.setName(CELL_PANE_NAME);
		int totalW = sheet.colHeader.getTotalWidth();
		int totalH = sheet.rowHeader.getTotalWidth();
		logger.debug("totalW="+totalW+" totalH="+totalH);
		cellPane.setSize(totalW, totalH);
		return cellPane;
	}
	/** ヘッダのビューポートを作成. */
	protected JSpreadHeaderPane createRowHeaderPane(JSpreadSheet sheet) {
		JSpreadHeaderPane rowHeaderPane = new JSpreadHeaderPane(JSpread.VERTICAL, spread);
		rowHeaderPane.setName(ROW_HEADER_PANE_NAME);
		return rowHeaderPane;
	}
	/** ヘッダのビューポートを作成. */
	protected JSpreadHeaderPane createColHeaderPane(JSpreadSheet sheet) {
		JSpreadHeaderPane colHeaderPane = new JSpreadHeaderPane(JSpread.HORIZONTAL, spread);
		colHeaderPane.setName(COLUMN_HEADER_PANE_NAME);
		return colHeaderPane;
	}
	/**
	 * スクロールバーを表示したときに右下に現れる、役に立たないビューを作成します.
	 *  
	 */
	protected JComponent createUselessCorner() {
		Dimension dim = new Dimension(1, 1);
		JComponent uselessCornerPane = new Box.Filler(dim, dim, dim);
		uselessCornerPane.setName("UselessCorner");
		uselessCornerPane.setForeground(Color.RED);
		uselessCornerPane.setBackground(Color.BLUE);
		return uselessCornerPane;
	}
	class CellResizeListener extends ComponentAdapter {
		//private Logger logger = Logger.getLogger(CellResizeListener.class);
		private final JSpread spread;
		CellResizeListener(JSpread spread) {
			assert spread != null;
			this.spread = spread;
		}
		public void componentResized(ComponentEvent e) {
			//logger.debug(e, new Throwable());
			spread.doLayout();
		}
	}
}
