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


// @(#)GroupWidget.java, 1.33, 12/18/96





package marimba.gui;





import java.io.*;


import java.awt.*;





import marimba.persist.*;





/**


 * Group widget container. All widgets are containers,


 * this widget however adds painting of the container


 * background.


 *


 * @author	Arthur van Hoff


 * @version 	1.33, 12/18/96


 */


public class GroupWidget extends ContainerWidget {


    int prevtx, prevty;





    /**


     * The possible options for the fillMode.


     * @see #getFillOptions


     * @see #fillMode


     */


    public static Options  fillOptions = new Options();


    static {


	fillOptions.add("none", NONE);


	fillOptions.add("solid", SOLID);


	fillOptions.add("pattern", PATTERN);


    }





    /**


     * The possible options for the lineMode.


     * @see #getLineOptions


     * @see #lineMode


     */


    public static Options  lineOptions = new Options();


    static {


	lineOptions.add("none", NONE);


	lineOptions.add("solid", SOLID);


	lineOptions.add("raised", RAISED);


	lineOptions.add("lowered", LOWERED);


    }





    /**


     * The type of line that is being displayed.


     * It can be none, solid, raised or lowered.


     * @see #getLineMode


     * @see #setLineMode


     * @see #lineOptions


     */


    public int  lineMode = LOWERED;





    /**


     * The fillMode of this group.


     * It can be none, solid or pattern.


     * @see #getFillMode


     * @see #setFillMode


     * @see #fillOptions


     */


    public int  fillMode = NONE;





    /**


     * The source of the pattern.


     * @see #getPatternSource


     * @see #setPattern


     */


    public String  patsrc;





    /**


     * The pattern for the background.


     * @see #getPattern


     * @see #setPattern


     */


    public Pattern  pattern;





    /**


     * Enables or disables the use of the inline editor.


     * @see #getEditor


     * @see #getEditing


     * @see #setEditing


     */


    public boolean  editing = true;





    /**


     * Get the properties.


     */


    public void getProperties(PropertyList list) {


	super.getProperties(list);


	list.setOption("linemode", lineOptions, lineMode, LOWERED);


	list.setOption("fillmode", fillOptions, fillMode, NONE);


	list.setURL("pattern", patsrc, null);


    }





    /**


     * Set the properties.


     */


    public void setProperties(PropertyList list) {


	super.setProperties(list);


	lineMode = list.getOption("linemode", lineOptions, LOWERED);


	fillMode = list.getOption("fillmode", fillOptions, NONE);


	patsrc = list.getURL("pattern", null);


	transparent = (fillMode == NONE);


    }





    /**


     * Initialize.


     */


    public void init() {


	if (patsrc != null) {


	    Presentation p = getPresentation();


	    if (p != null) {


		pattern = Pattern.getPattern(background, p.getURL(patsrc));


	    }


	}


    }





    /**


     * Get the possible options for the fillMode.


     * @see #fillOptions


     */


    public Options getFillOptions() {


	return fillOptions;


    }





    /**


     * Get the possible options for the lineMode.


     * @see #lineOptions


     */


    public Options getLineOptions() {


	return lineOptions;


    }





    /**


     * Get the name of the class that can be used for


     * in-place editing. This inline editor of the GroupWidget


     * can be disabled by setting inline editing to true or


     * false.


     * @see #editing


     */


    public String getEditor() {


	if (editing) {


	    return "marimba.builder.GroupWidgetEditor";


	} else {


	    return null;


	}


    }





    /**


     * Check whether the inline editor is being used.


     * @see #editing


     */


    public boolean getEditing() {


	return editing;


    }





    /**


     * Enable or disable the use of the inline editor.


     * @see #editing


     */


    public void setEditing(boolean useEditor) {


	this.editing = useEditor;


    }





    /**


     * Get the line mode


     * @see #lineMode


     */


    public int getLineMode() {


	return lineMode;


    }





    /**


     * Set the line mode


     * @see #lineMode


     */


    public void setLineMode(int lineMode) {


	if (this.lineMode != lineMode) {


	    this.lineMode = lineMode;


	    repaint();


	}


    }





    /**


     * Get the fill mode


     * @see #fillMode


     */


    public int getFillMode() {


	return fillMode;


    }





    /**


     * Set the line mode


     * @see #fillMode


     */


    public void setFillMode(int fillMode) {


	if (this.fillMode != fillMode) {


	    this.fillMode = fillMode;


	    transparent = (fillMode == NONE);


	    repaint();


	}


    }





    /**


     * Get the pattern.


     * @see #pattern


     */


    public Pattern getPattern() {


	return pattern;


    }





    /**


     * Get the source of the pattern.


     * @see #patsrc


     */


    public String getPatternSource() {


	return patsrc;


    }





    /**


     * Set the pattern and patternsource using the given source.


     * @see #pattern


     * @see #patsrc


     */


    public void setPattern(String src) {


	if (src != null) {


	    patsrc = src;


	    pattern = null;


	    if (patsrc != null) {


		Presentation p = getPresentation();


		if (p != null) {


		    pattern = Pattern.getPattern(background, p.getURL(patsrc));


		}


	    }


	    repaint();


	}


    }





    /**


     * Paint the background


     */


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


	prevtx = tx;


	prevty = ty;





	Pattern pattern = this.pattern;





	switch (fillMode) {


	  case NONE:


	    if (parent != null) {


		break;


	    }


	      


	  case PATTERN:


	    if (pattern != null) {


		pattern.fillRect(g, 0, 0, width - tx, height - ty, cx, cy, cw, ch, this);


		break;


	    }





	  default:


	    g.setColor(background);


	    g.fillRect(-tx, -ty, width, height);


	    break;


	}





	switch (lineMode) {


	  case LOWERED:


	    g.setColor(parent.background);


	    Bevel.drawFieldBorder(g, -tx, -ty, width, height);


	    g.clipRect(2 - tx, 2 - ty, width-4, height-4);


	    break;





	  case RAISED:


	    g.setColor(background);


	    Bevel.drawWindowBorder(g, -tx, -ty, width, height);


	    g.clipRect(2 - tx, 2 - ty, width-4, height-4);


	    break;





	  case NONE:


	    break;





	  default:


	    g.setColor(foreground);


	    g.drawRect(-tx, -ty, width-1, height-1);


	    g.clipRect(1 - tx, 1 - ty, width-2, height-2);


	    break;


	}





	paint(g);


    }





    /**


     * Remember the translation


     */


    public void update(Graphics g) {


	int dx = tx - prevtx;


	int dy = ty - prevty;





	prevtx = tx;


	prevty = ty;


	


	if (((dx == 0) && (dy == 0)) || (dx >= width) || (dx <= -width) || (dy >= height) || (dy <= -height)) {


	    super.update(g);


	    return;


	}





	int w = 0;


	switch (lineMode) {


	  case LOWERED:


	  case RAISED:


	    w = 2;


	    break;


	  case NONE:


	    break;


	  default:


	    w = 1;


	    break;


	}





	int x = -tx + w;


	int y = -ty + w;


	int width = this.width - 2*w;


	int height = this.height - 2*w;





	//System.out.println("SCROLL: " + dx + "," + dy);


	if (dx < 0) {


	    if (dy < 0) {


		g.copyArea(x - dx, y - dy, width + dx, height + dy, dx, dy);


		updateArea(g, x + width + dx, y, -dx, height);


		updateArea(g, x, y + height + dy, width + dx, -dy);


	    } else {


		g.copyArea(x - dx, y, width + dx, height - dy, dx, dy);


		updateArea(g, x + width + dx, y, -dx, height);


		updateArea(g, x, y, width + dx, dy);


	    }


	} else {


	    if (dy < 0) {


		g.copyArea(x, y - dy, width-dx, height+dy, dx, dy);


		updateArea(g, x, y, dx, height);


		updateArea(g, x + dx, y + height + dy, width-dx, -dy);


	    } else {


		g.copyArea(x, y, width-dx, height-dy, dx, dy);


		updateArea(g, x, y, dx, height);


		updateArea(g, x + dx, y, width-dx, dy);


	    }


	}


    }





    /**


     * Update a portion of the widget.


     */


    void updateArea(Graphics g, int x, int y, int width, int height) {


	if ((width > 0) && (height > 0)) {


	    //System.out.println("AREA: " + x + "," + y + "," + width + "x" + height);





	    Graphics gc = g.create();


	    try {


		gc.clipRect(x, y, width, height);





		// Paint the widget itself


		paint(gc, x, y, width, height);


		//gc.setColor(Color.pink);


		//gc.fillRect(x, y, width, height);





		// Paint the children


		if (nwidgets > 0) {


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


			Widget w = widgets[i];


			if (w != null) {


			    w.paintAll(gc, x, y, width, height);


			}


		    }


		}


	    } finally {


		gc.dispose();


	    }


	}


    }





    /**


     * Wait for the pattern of this container to arrive...


     */


    public void waitForPattern() {


	if (fillMode == PATTERN) {


	    Pattern p = pattern;


	    if (p != null) {


		p.waitFor();


	    }


	}


    }





    /**


     * Parameters.


     */


    public void paramString(StringBuffer buf) {


	super.paramString(buf);


	if (patsrc != null) {


	    buf.append(",pat=");


	    buf.append(patsrc);


	}


    }


}


