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


// @(#)URLTextWidget.java, 1.11, 12/20/96





package marimba.gui;





import java.awt.*;





import marimba.util.*;


import marimba.persist.*;





/**


 * A simple URL text widget.


 *


 * @author	Klaas Waslander


 * @version 	1.11, 12/20/96


 */


public class URLTextWidget extends TextWidget {


    final static Color defaultSelColor = Color.red;


    final static Color defaultFollowColor = new Color(200, 10, 200);


    final static Color defaultFocusColor = Color.yellow;





    /**


     * The possible options for the align.


     * @see #getAlignOptions()


     * @see #align


     */


    public static Options alignOptions = new Options();


    static {


	alignOptions.add("left", LEFT);


	alignOptions.add("right", RIGHT);


	alignOptions.add("center", CENTER);


    }





    /**


     * The color to highlight the text with when the mouse is down.


     */


    public Color  selColor = defaultSelColor;





    /**


     * The color used when the link has been followed.


     */


    public Color  followColor = defaultFollowColor;





    /**


     * The color used for the link when the mouse is pointing at the link.


     */


    public Color  focusColor = defaultFocusColor;





    /**


     * The URL that this textbox points to.


     * @see #getURL


     * @see #setURL


     */


    public String  url;





    /**


     * Text can be aligned to the left, right or can be centered.


     * @see #getAlign


     * @see #setAlign


     * @see #alignOptions


     */


    public int  align = LEFT;





    /**


     * A link can detect whether it has been followed.


     * @see #getDetectFollow


     * @see #setDetectFollow


     */


    public boolean detectFollow = false;





    /**


     * Detects whether this link has been followed.


     * @see #isFollowed


     * @see #setFollowed


     */


    public boolean  followed = false;





    /**


     * Detects whether the link is underlines.


     * @see #isUnderlined


     * @see #setUnderlined


     */


    public boolean  underlined = true;





    /**


     * The link can change the mouse cursor when the mouse


     * is pointing at the link. This does not work properly in


     * channels, so by default it is disabled.


     * @see #getChangeCursor


     * @see #setChangeCursor


     */


    public boolean  changeCursor = true;











    /** The length of the text. */


    int len;





    /** The content of the textbox. */


    public char  text[] = new char[4];





    int  textLeft = 0;   // left position of text


    int  textRight = 0;  // right most position of text


    int  textTop = 0;    // upper most position of text


    int  textBottom = 0; // lowest position of text


    boolean  down = false;


    boolean  focused = false;





    /**


     * Default constructor.


     */


    public URLTextWidget() {


	this("URL");


    }





    /**


     * Constructor with value.


     */


    public URLTextWidget(String text) {


	this(text, null);


    }





    /**


     * Constructor with value.


     */


    public URLTextWidget(String text, String url) {


	setValue(text);


	setURL(url);


	editable = false;


	wBackground = defaultBackground;


	wForeground = Color.blue;


    }





    /**


     * Get the properties of this widget.


     */


    public void getProperties(PropertyList list) {


	super.getProperties(list);


	list.setColor("selcolor", selColor, defaultSelColor);


	list.setColor("followcolor", followColor, defaultFollowColor);


	list.setColor("focuscolor", focusColor, defaultFocusColor);


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


	list.setOption("align", alignOptions, align, LEFT);


	list.setString("text", getText(), null);


	list.setURL("URL", url, null);


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


	list.setBoolean("detectFollow", detectFollow, false);


	list.setBoolean("followed", followed, false);


    }





    /**


     * Set the properties of this widget.


     */


    public void setProperties(PropertyList list) {


	super.setProperties(list);


	selColor = list.getColor("selcolor", defaultSelColor);


	followColor = list.getColor("followcolor", defaultFollowColor);


	focusColor = list.getColor("focuscolor", defaultFocusColor);


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


	align = list.getOption("align", alignOptions, LEFT);


	url = list.getURL("URL", url);


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


	detectFollow = list.getBoolean("detectFollow", false);


	followed = list.getBoolean("followed", false);





	String str = list.getString("text", "");


	len = str.length();


	text = new char[len];


	str.getChars(0, len, text, 0);





	transparent = true;


    }





    /**


     * Get the length of the text.


     */


    public int getLength() {


	return len;


    }





    /**


     * Get the value of the text.


     */


    public String getText() {


	return new String(text, 0, len);


    }





    /**


     * Set the value of the text.


     */


    public void setText(String text) {


	if (text == null) {


	    text = "";


	}


	String old = getText();


	if (!text.equals(old)) {


	    this.text = new char[len = text.length()];


	    text.getChars(0, len, this.text, 0);


	    repaint();


	} else {


	    select(len);


	}


	focus(0);


    }





    /**


     * Return text characters.


     * @see #text


     */


    public char[] getTextChars() {


	return text;


    }





    /**


     * Set the value.


     * @param label	The label of this url.


     * @param url	The actual content of the url.


     */


    public void setValue(String label, String url) {


	setValue(label);


	setURL(url);


    }





    /**


     * Get the possible options for align.


     * @see #alignOptions


     */


    public Options getAlignOptions() {


	return alignOptions;


    }





    /**


     * Get the alignment of this widget.


     * @see #align


     */


    public int getAlign() {


	return align;


    }





    /**


     * Set the style of this widget.


     * @see #align


     */


    public void setAlign(int align) {


	if (align==LEFT || align==RIGHT || align==CENTER ) {


	    if (this.align != align) {


		this.align = align;


		repaint();


	    }


	}


    }





    /**


     * Check whether the link detects whether it has been followed.


     * @see #detectFollow


     */


    public boolean getDetectFollow() {


	return detectFollow;


    }





    /**


     * A link can detect whether it has been followed.


     * @see #detectFollow


     */


    public void setDetectFollow(boolean detectFollow) {


	if (detectFollow != this.detectFollow) {


	    this.detectFollow = detectFollow;


	    if (!detectFollow) {


		followed = false;


	    }


	    repaint();


	}


    }





    /**


     * Check whether this link has been followed


     * @see #followed


     */


    public boolean isFollowed() {


	return followed;


    }





    /**


     * Set followed to true or false.


     * @see #followed


     */


    public void setFollowed(boolean followed) {


	if (followed != this.followed) {


	    this.followed = followed;


	    repaint();


	}


    }





    /**


     * Check whether the link should be underlined.


     * @see #underlined


     */


    public boolean isUnderlined() {


	return underlined;


    }





    /**


     * Set underlined to true or false.


     * @see #underlined


     */


    public void setUnderlined(boolean underlined) {


	if (this.underlined != underlined) {


	    this.underlined = underlined;


	    repaint();


	}


    }





    /**


     * Check whether the link changes the mouse cursor.


     * @see #changeCursor


     */


    public boolean getChangeCursor() {


	return changeCursor;


    }





    /**


     * Let the link change the mouse cursor or not.


     * @see #changeCursor


     */


    public void setChangeCursor(boolean changeCursor) {


	this.changeCursor = changeCursor;


    }





    /**


     * Left margin.


     * @see #rightMargin


     */


    public int leftMargin() {


	return 0;


    }





    /**


     * Right margin.


     * @see #leftMargin


     */


    public int rightMargin() {


	return 0;


    }





    /**


     * Get the value of the URL.


     * @see #URL


     */


    public String getURL() {


	return url;


    }





    /**


     * Set the URL.


     * @see #URL


     */


    public void setURL(String url) {


	this.url = url;


    }





    /**


     * Resizes this widget to the size of the text.


     */


    public void adjustSize() {


	FontMetrics fm = Toolkit.getDefaultToolkit().getFontMetrics(font);


	int leftMar = leftMargin();


	int rightMar = rightMargin();


	int ht = fm.getHeight() + fm.getAscent();


	int wd = leftMar + rightMar + fm.charsWidth(text, 0, len);


	resize(wd,ht);


    }





    /**


     * Paint the text widget.


     */


    public void paint(Graphics g) {


	char  text[] = getTextChars();


	FontMetrics  fm = g.getFontMetrics(font);


	int  leftMar = leftMargin();


	int  rightMar = rightMargin();


	int  bothMar = leftMar + rightMar;


	int  vertMar = 0;





	int  lx = leftMar + 5;


	int  ly = (height - fm.getHeight())/2 + fm.getAscent();


	int  strw = fm.charsWidth(text, 0, len);





	switch (align) {


	  case RIGHT:


	     lx = (width - rightMar) - (strw + 5);


	     break;


	  case CENTER:


	     lx = leftMar + ((width - bothMar) - strw) / 2;


	     break;


	  case LEFT:


	     lx = leftMar;


	}





	textLeft = lx;


	textRight = lx+strw;


	textTop = ly - fm.getAscent();;


	textBottom = textTop + fm.getHeight();





	// draw the text


	if (down) {


	    g.setColor(selColor);


	} else {


	    if (focused) {


		g.setColor(focusColor);


	    } else {


		g.setColor((followed) ? followColor : foreground);


	    }


	}


	g.drawChars(text, 0, len, lx, ly);


	if (underlined) {


	    g.drawLine(textLeft, ly + 2, textRight, ly + 2);


	}


    }





    /**


     * Change the cursor in the current frame if changeCursor is set to true.


     */


    public void setCursor(int cursor) {


	if (changeCursor) {


	    super.setCursor(cursor);


	}


    }





    /**


     * When the link is focused, the text is drawn in the focusColor and


     * the user can click to follow the link.


     */


    void setFocused(boolean focused) {


	if (focused != this.focused) {


	    this.focused = focused;


	    repaint();


	}


    }





    /**


     * Checks whether the coordinates of the given event are


     * within the area where the text is.


     */


    protected boolean eventInText(Event evt) {


	return	evt.x >= textLeft && evt.x <= textRight && evt.y >= textTop && evt.y <= textBottom;


    }





    /**


     * Handle an event.


     */


    public boolean handleEvent(Event evt) {


	if (disabled) {


	    return true;


	}


	switch (evt.id) {


	    case Event.MOUSE_ENTER:


		// make sure the mouse enter belongs to this widget


		if (evt.target != this) {


		    break;


		}


		if (eventInText(evt)) {


		    setFocused(true);


		    setCursor(Frame.HAND_CURSOR);


		} else {


		    setFocused(false);


		    resetCursor();


		}


		return true;





	    case Event.MOUSE_EXIT:


		// make sure the mouse exit belongs to this widget


		if (evt.target != this) {


		    break;


		}


		setFocused(false);


		resetCursor();


		return true;





	    case Event.MOUSE_MOVE:


		if (eventInText(evt)) {


		    setFocused(true);


		    setCursor(Frame.HAND_CURSOR);


		} else {


		    setFocused(false);


		    resetCursor();


		}


		return true;





	    case Event.MOUSE_DOWN:


		if (eventInText(evt)) {


		    down = true;


		    repaint();


		}


		return false;





	    case Event.MOUSE_DRAG:


		if (eventInText(evt)) {


		    setFocused(true);


		    if (down == false) {


			down = true;


			repaint();


		    }


		} else {


		    setFocused(false);


		    down = false;


		    repaint();


		}


		return true;





	    case Event.MOUSE_UP:


		if (down == true) {


		    down = false;


		    action();


		    repaint();


		}


		return true;


	}


	return super.handleEvent(evt);


    }





    /**


     * The url is being followed.


     * Followed is set to true if it is detected.


     */


    public void action() {


	Presentation p = getPresentation();


	if (p == null || url == null || url.length() == 0 ||


			!Environment.showURL(p.getURL(url))) {


	    // FAILED


	    postEvent(new Event(this, Event.ACTION_EVENT, new Boolean(false)));


	} else {


	    // SUCCEEDED


	    postEvent(new Event(this, Event.ACTION_EVENT, new Boolean(true)));


	    if (detectFollow) {


		setFollowed(true);


	    }


	}


	super.action();


    }


}


