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


// @(#)ListWidget.java, 1.42, 12/09/96





package marimba.gui;





import java.awt.*;


import java.util.*;





import marimba.persist.*;





/**


 * Column descriptor.


 */


class ListColumn {


    /**


     * The label for this column.


     */


    public String  lbl;





    /**


     * The x-coordinate.


     */


    public int  x;





    /**


     * The width of the column.


     */


    public int  width;


}





/**


 * List widget.


 *


 * @author	Arthur van Hoff


 * @author	Klaas Waslander


 * @version 	1.42, 12/09/96


 */ 


public class ListWidget extends ScrollingContainerWidget implements WidgetLayoutMgr {


    final static Font defaultHdrFont = new Font("Dialog", Font.PLAIN, 10);





    /**


     * If a ListWidget is exclusive and it has ListItemWidgets,


     * then more ListItemWidgets can be selected at the same time,


     * because ListItems check this property in their List.


     * @see #isExclusive


     * @see #setExclusive


     */


    public boolean  exclusive = true;





    /**


     * The font that has to be used for the header.


     * @see #getHdrFont


     * @see #setHdrFont


     */


    public Font  hdrFont = defaultHdrFont;





    /** the number of columns, determined within setColumns and addColumn */


    int ncols = 0;





    /** the actual columns, determined within setColumns and addColumn */


    ListColumn cols[] = new ListColumn[4];





    /**


     * Constructor.


     */


    public ListWidget() {


	horzmode = NEVER;


    }





    /**


     * Get the properties of this widget.


     */


    public void getProperties(PropertyList list) {


	super.getProperties(list);


	list.setBoolean("exclusive", exclusive, true);


	list.setFont("hdrfont", hdrFont, defaultHdrFont);





	StringBuffer buf = new StringBuffer();


	for (int i = 0 ; i < ncols ; i++) {


	    if (i > 0) {


		buf.append(',');


	    }


	    buf.append(cols[i].lbl);


	    if (cols[i].width != 100) {


		buf.append('/');


		buf.append(cols[i].width);


	    }


	}


	list.setString("columns", buf.toString(), "");


    }





    /**


     * Set the properties of this widget.


     */


    public void setProperties(PropertyList list) {


	super.setProperties(list);


	exclusive = list.getBoolean("exclusive", true);


	hdrFont = list.getFont("hdrfont", defaultHdrFont);


	setColumns(list.getString("columns",""));


    }





    /**


     * Check if this ListWidget is exlusive.


     * @see #exclusive


     */


    public boolean isExclusive() {


	return exclusive;


    }





    /**


     * Set the ListWidget to be exclusive or not.


     * @see #exclusive


     */


    public void setExclusive(boolean exclusive) {


	this.exclusive = exclusive;


    }





    /**


     * Get the font for the header.


     * @see #hdrFont


     */


    public Font getHdrFont() {


	return hdrFont;


    }





    /**


     * Set the font for the header.


     * @see #hdrFont


     */


    public void setHdrFont(Font hdrFont) {


	if (hdrFont != null && !hdrFont.equals(this.hdrFont)) {


	    this.hdrFont = hdrFont;


	    layout();


	    repaint();


	}


    }





    /**


     * Allocate the content.


     */


    public Widget newContent() {


	GroupWidget w = new GroupWidget();


	w.lineMode = LOWERED;


	w.layoutMgr = this;


	return w;


    }





    /**


     * Add columns


     */


    public synchronized void setColumns(String str) {


	ncols = 0;


	cols = new ListColumn[4];


	if (str != null && str.length() > 0) {


	    for (StringTokenizer t = new StringTokenizer(str, ",") ; t.hasMoreTokens() ;) {


		String lbl = t.nextToken();


		int width = 100;


		


		int i = lbl.indexOf('/');


		if (i >= 0) {


		    width = Integer.parseInt(lbl.substring(i+1));


		    lbl = lbl.substring(0, i);


		}


		addColumn(lbl, width);


	    }


	}


	layout();


	repaint();


    }





    /**


     * Add a column.


     */


    public synchronized void addColumn(String lbl, int width) {


	if (ncols == cols.length) {


	    ListColumn newcols[] = new ListColumn[Math.max(ncols*2, 4)];


	    System.arraycopy(cols, 0, newcols, 0, ncols);


	    cols = newcols;


	}





	ListColumn col = new ListColumn();


	col.lbl = lbl;


	col.width = width;


	col.x = (ncols > 0) ? (cols[ncols-1].x + cols[ncols-1].width + 4) : 0;


	cols[ncols++] = col;


	repaint();


    }





    /**


     * Add an item.


     */


    public void addItem(Widget item) {


	synchronized (content) {


	    content.add(content.nwidgets, item);


	}


    }





    /**


     * Add an item at a given position


     */


    public void addItem(int n, Widget item) {


	content.add(n, item);


    }





    /**


     * Add an item in a sorted list, they key of the item


     * is used to determined the sorting order.


     */


    public void addSorted(ListItemWidget item) {


	synchronized (content) {


	    String key = item.key();


	    for (int i = content.nwidgets ; i-- > 0 ; ) {


		ListItemWidget item2 = (ListItemWidget)content.widgets[i];


		if (key.compareTo(item2.key()) > 0) {


		    content.add(i+1, item);


		    return;


		}


	    }


	    content.add(0, item);


	}


    }





    /**


     * Delete an item


     */


    public void deleteItem(Widget item) {


	content.remove(item);


    }





    /**


     * Delete an item


     */


    public void deleteItem(int i) {


	synchronized (content) {


	    if ((i >= 0) && (i < content.nwidgets)) {


		content.remove(content.widgets[i]);


	    }


	}


    }





    /**


     * Get the index of the first selected item.


     */


    public int getIntegerValue() {


	return indexOf(selectedItem());


    }





    /**


     * Get the index of the first selected item.


     */


    public Object getValue() {


	return new Integer(getIntegerValue());


    }





    /**


     * Select an item.


     */


    public void setValue(Object value) {


	if (value instanceof Number) {


	    setValue(getItem(((Number)value).intValue()));


	} else if (value instanceof String) {


	    setValue((ListItemWidget)getWidget((String)value));


	} else if (value == null) {


	    setValue((ListItemWidget)null);


	}


    }





    /**


     * Select an item.


     */


    public void setValue(ListItemWidget item) {


	if (item == null) {


	    clearSelection();


	} else {


	    item.select();


	}


    }





    /**


     * Get item by key.


     */


    public ListItemWidget getItem(String key) {


	synchronized (content) {


	    for (int i = content.nwidgets ; i-- > 0 ; ) {


		ListItemWidget item = (ListItemWidget)content.widgets[i];


		if (key.equals(item.key())){


		    return item;


		}


	    }


	}


	return null;


    }





    /**


     * Get item by index


     */


    public ListItemWidget getItem(int i) {


	synchronized (content) {


	    return ((i < 0) || (i >= content.nwidgets)) ? null : (ListItemWidget)content.widgets[i];


	}


    }





    /**


     * Get the index of an item.


     */


    public int indexOf(ListItemWidget item) {


	synchronized (content) {


	    for (int i = content.nwidgets ; i-- > 0 ;) {


		if (content.widgets[i] == item) {


		    return i;


		}


	    }


	}


	return -1;


    }





    /**


     * Get the first selected item.


     */


    public ListItemWidget selectedItem() {


	synchronized (content) {


	    for (int i = 0 ; i < content.nwidgets ; i++) {


		ListItemWidget item = (ListItemWidget)content.widgets[i];


		if (item.selected) {


		    return item;


		}


	    }


	}


	return null;


    }





    /**


     * Count how many items there are in this list


     */


    public int countItems() {


	return content.nwidgets;


    }





    /**


     * Select an item.


     */


    public void clearSelection() {


	synchronized (content) {


	    for (int i = 0 ; i < content.nwidgets ; i++) {


		ListItemWidget  anItem = (ListItemWidget) content.widgets[i];


		anItem.select(false);


	    }


	}


    }





    /**


     * Clear all items.


     */


    public void clear() {


	synchronized (content) {


	    scrollContent(0, 0);


	    for (int i = content.nwidgets ; i-- > 0 ;) {


		content.remove(content.widgets[i]);


	    }


	}


    }





    /**


     * Layout the widget itself.


     */


    public void layout() {


	hdrHeight = (ncols == 0) ? 0 : ((getFontMetrics(hdrFont).getHeight()+4)/5)*5;


	super.layout();


    }





    /**


     * Layout the content.


     */


    public void layout(Widget w) {


	if (w.nwidgets == 0) {


	    setContentSize(0, 0);


	    return;


	}





	int y = 5;


	for (int i = 0 ; i < w.nwidgets ; i++) {


	    Widget item = w.widgets[i];


	    item.reshape(7, y, w.width-14, item.height);


	    item.validate();


	    y += item.height;


	}


	setContentSize(w.width, y + 5);


    }





    /**


     * Paint the widget.


     */


    public void paint(Graphics g, int cx, int cy, int cw, int ch) {


	FontMetrics fm = g.getFontMetrics(hdrFont);


	if (cy < hdrHeight) {


	    int y = fm.getAscent();





	    g.setColor(foreground);


	    g.setFont(hdrFont);


	    for (int c = 0 ; c < ncols ; c++) {


		ListColumn col = cols[c];


		g.drawString(col.lbl, col.x + 5, y);


	    }


	}


    }


}


