// Copyright 1996, Marimba Inc. All Rights Reserved.


// @(#)TableContent.java, 1.20, 12/12/96





package marimba.gui;





import java.awt.*;


import java.util.*;





import marimba.persist.*;








/**


 * Displays the content of a TableWidget.


 *


 * @author	Klaas Waslander


 * @version 	1.20, 12/12/96


 */


public class TableContent extends GroupWidget {


    /**


     * The height of all the rows together.


     * Calculated by the layout method.


     * @see #getRowsHeight


     */


    protected int  rowsHeight = 0;





    /**


     * This method gets the properties for the children of this widget.


     * Since all data is persistified in the TableRows, nothing has to


     * be persistified here.


     */


    public void getChildProperties(PropertyList list) {


	// do nothing here anymore


    }





    /**


     * Get the height of all the rows together.


     * @see #rowsHeight


     */


    public int getRowsHeight() {


	return rowsHeight;


    }





    /**


     * Get the height of the table font.


     */


    protected int tableFontHeight() {


	FontMetrics  fm = getFontMetrics(((TableWidget)parent).font);


	return fm.getHeight();


    }





    /**


     * Get the ascent of the table font.


     */


    protected int tableFontAscent() {


	FontMetrics  fm = getFontMetrics(((TableWidget)parent).font);


	return fm.getAscent();


    }





    /**


     * Layout the content and add widgets in the data to the content.


     * Calling this method is always necessary to let widgets show up


     * in the content.


     */


    public void layout() {


	super.layout();





	TableWidget  table = (TableWidget)parent;


	int  rowPad = table.rowPadding;


	int  colPad = table.colPadding;


	removeAll();





	int  yPos = 0;


	for (int rowIndex = 0; rowIndex < table.rowCount; rowIndex++) {


	    TableRow  currentRow = table.getRow(table.getRowIndex(rowIndex));


	    currentRow.pos = yPos;





	    // reshape every widget of this row


	    int  maxRowHeight = 0;


	    Vector  rowData = currentRow.data;


	    for (int colIndex = 0; colIndex < table.columnCount && colIndex < rowData.size(); colIndex++) {


		Object  cellItem = rowData.elementAt(colIndex);





		// reshape if cell item is a widget


		if (cellItem instanceof Widget) {


		    TableColumn  col = table.getColumn(colIndex);


		    Widget  item = (Widget)cellItem;


		    maxRowHeight = Math.max(maxRowHeight, item.height + rowPad * 2);





		    // widgetheight remains the same, width adjusted if necessary


		    int  itemWidth;


		    if (table.sizeToCell) {


			itemWidth = col.size - colPad * 2;


		    } else {


			itemWidth = Math.min(item.width, col.size - colPad * 2);


			if (col.size >= 20 + colPad*2 && itemWidth < 20) {


			    itemWidth = 20;


			}


		    }


		    add(item);


		    item.reshape(col.pos + colPad, yPos + rowPad, itemWidth, item.height);


		}


	    }





	    // set size of current row


	    int  currentHeight = ((maxRowHeight == 0) ? tableFontHeight() + rowPad * 2 : maxRowHeight);


	    currentRow.size = currentHeight;





	    // go to next row


	    yPos += currentHeight;


	}





	// set the height of all the rows together


	rowsHeight = yPos;


    }





    /**


     * Paint lines at the right of every column if table wants that.


     */


    protected void paintColumnLines(Graphics g) {


	TableWidget  table = (TableWidget)parent;





	if (table.columnLine) {


	    g.setColor(foreground.brighter());


	    for (int colIndex = 0; colIndex < table.columnCount-1; colIndex++) {


		TableColumn  col = table.getColumn(table.getColumnIndex(colIndex));


		int  xPos = col.pos + col.size;


		if (xPos > -tx) {


		    // painting ready when right border of column is not visible


		    if (xPos > -tx + width) {


			break;


		    }


		    Dash.drawFocusLine(g, xPos, -ty, xPos, -ty+height);


		}


	    }


	}


    }





    /**


     * Paint the items in the content which are not widgets.


     * It will not do anything when there are only widgets in the content.


     */


    public void paint(Graphics g) {


	paintColumnLines(g);





	// do nothing if there are only widgets in the content.


	TableWidget  table = (TableWidget)parent;


	if (nwidgets == table.columnCount * table.rowCount) {


	    return;


	}





	// create gc's for every column with correct clipping


	g.setColor(table.foreground);


	Graphics[]  colGC = new Graphics[table.columnCount];


	for (int colIndex = 0; colIndex < table.columnCount; colIndex++) {


	    TableColumn  col = table.getColumn(colIndex);


	    Graphics  newGC = g.create();


	    newGC.clipRect(col.pos, -ty, col.size, (-ty)+height);


	    colGC[colIndex] = newGC;


	}





	// paint every row


	int  rowPad = table.rowPadding;


	int  colPad = table.colPadding;


	for (int rowIndex = 0; rowIndex < table.rowCount; rowIndex++) {


	    TableRow  currentRow = table.getRow(table.getRowIndex(rowIndex));


	    int  yPos = currentRow.pos;





	    // only paint if visible


	    if (yPos >= -ty - currentRow.size && yPos <= -ty + this.height) {


		Vector  rowData = currentRow.data;





		// check whether this row is selected and paint if the table has focus


		Color  foreColor;


		if (table.rowIsSelected(currentRow)) {


		    if (!table.isDisabled()) {


			g.setColor(getSelBackground());


		    } else {


			g.setColor(getForeground());


		    }


		    g.fillRect(-tx + 3, yPos, width-6, currentRow.size);


		    if (table.hasFocus() && rowIndex == table.currentRowIndex) {


			g.setColor(getSelFocusColor());


			Dash.drawFocusRect(g, -tx + 3, yPos, width-6, currentRow.size);


		    }


		    foreColor = (!table.isDisabled()) ? getSelForeground() : getBackground();


		} else {


		    foreColor = foreground;


		}





		// paint the cells of this row that need repainting


		FontMetrics  fm = g.getFontMetrics(font);


		for (int colIndex = 0; colIndex < table.columnCount && colIndex < rowData.size(); colIndex++) {


		    TableColumn  colInfo = table.getColumn(colIndex);


		    Object  cellItem = rowData.elementAt(colIndex);





		    // draw necessary things, widgets draw themselves


		    if (cellItem != null && !(cellItem instanceof Widget)) {


			String  item = cellItem.toString();


			colGC[colIndex].setColor(foreColor);





			int  strw = fm.stringWidth(item);


			int  lx = colInfo.pos + colPad;


			switch (colInfo.align) {


			    case CENTER:


				lx += (colInfo.size - colPad * 2 - strw) / 2;


				break;


			    case RIGHT:


				lx += (colInfo.size - colPad * 2 - strw);


				break;


			}


			colGC[colIndex].drawString(item, lx, yPos + tableFontAscent() + rowPad);


		    }


		}


	    }


	}





	// dispose the gc's for every column


	for (int colIndex = 0; colIndex < table.columnCount; colIndex++) {


	    colGC[colIndex].dispose();


	}


    }





    /**


     * Find the display index of the column in which


     * the event took place.


     * Returns -1 if no column is found.


     */


    protected int findColumn(Event evt) {


	int  result = -1;


	TableWidget  table = (TableWidget)parent;


	for (int colIndex = 0; colIndex < table.columnCount; colIndex++) {


	    TableColumn  colInfo = table.getColumn(colIndex);


	    if (evt.x > colInfo.pos && evt.x < colInfo.pos + colInfo.size) {


		result = colIndex;


		break;


	    }


	}


	return result;


    }





    /**


     * Find the display index of the row in which


     * the event took place.


     * Returns -1 if no row is found.


     */


    protected int findRow(Event evt) {


	int  result = -1;


	TableWidget  table = (TableWidget)parent;


	for (int rowIndex = 0; rowIndex < table.rowCount; rowIndex++) {


	    TableRow  currentRow = table.getRow(table.getRowIndex(rowIndex));


	    int  pos = currentRow.pos;


	    if (evt.y > pos && evt.y < pos + currentRow.size) {


		result = rowIndex;


		break;


	    }


	}


	return result;


    }





    /**


     * Find the coordinates of the cell in which the event took place.


     * Returns null if no cell is found.


     */


    protected int[] findCell(Event evt) {


	TableWidget  table = (TableWidget)parent;


	if (evt.x < 0 || evt.x > table.contWidth || evt.y < 0 || evt.y > table.contHeight) {


	    return null;


	}





	// find the column and row and return null if none is found


	int  colResult = findColumn(evt);


	if (colResult == -1) {


	    return null;


	}


	int  rowResult = findRow(evt);


	if (rowResult == -1) {


	    return null;


	}





	// return the coordinates


	int result[] = {colResult, rowResult};


	return result;


    }





    /**


     * Handle events for selections.


     */


    public boolean handleEvent(Event evt) {


	TableWidget  table = (TableWidget)parent;





	switch (evt.id) {


	    case Event.MOUSE_DOWN: {


		if (evt.target != this || table.isDisabled()) {


		    break;


		}


		int  cell[] = findCell(evt);


		if (cell != null) {


		    table.requestFocus();


		    int  rowIndex = table.getRowIndex(cell[1]);


		    if (!table.rowIsSelectedAt(rowIndex)) {


			table.selectRowAt(rowIndex);


			table.currentRowIndex = cell[1];


			// post action- or select-event


			if (evt.clickCount > 1) {


			    table.action(cell[0], cell[1]);


			} else {


			    table.postEvent(new Event(table, Event.LIST_SELECT, new Integer(cell[1])));


			}


		    } else {


			// post action- or deselect-event


			if (evt.clickCount > 1) {


			    table.action(cell[0], cell[1]);


			} else {


			    if (!table.isExclusive()) {


				table.deselectRowAt(rowIndex);


				table.currentRowIndex = -1;


			    }


			    table.postEvent(new Event(table, Event.LIST_DESELECT, new Integer(cell[1])));


			}


		    }


		    repaint();


		    return true;


		}


		break;


	    }





	    case Event.MOUSE_UP: {


		return true;


	    }


	}


	return super.handleEvent(evt);


    }


}


