package cnp.ew.lightweight;

import java.awt.*;
import java.util.*;

import cnp.ew.util.*;
import cnp.ew.layout.*;
import cnp.ew.displayer.*;

public interface CpLightweightComponent extends CpObservable, CpObserver, CpCopyable
{
    /*
     * Paint the lc.  Clip will be in local coordinates.
     */
    public void paint(Graphics g, Rectangle clip);

    /**
     * Allow parents to do some painting on top of their children.
     */
    public void paintAfterChildren(Graphics g, Rectangle clip);

    /**
     * damage in local coordinates
     */
    public void damage(Rectangle r);
    public void damage();

    /**
     * This component will draw to an offscreen bitmap before displaying if this is true.
     */
    public void setDrawOffscreen(boolean newDrawOffscreen);

    public void setFont(Font newFont);
    public void setForeground(Color newForeground);
    public void setBackground(Color newBackground);
    /**
     * if any of these values have not been set within the lc, the value will be retrieved
     * from its parent, recursively, all the way up to the component if necessary,
     * then following its recursive chain.
     */
    public Color getForeground();
    public Color getBackground();
    public Font getFont();
    public FontMetrics getFontMetrics();
    public FontMetrics getFontMetrics(Font font);

    /**
     * Set the layout manager for the children of this lc.
     */
    public void setLayout(CpLayoutManager layoutManager);

    /**
     * Answer the layout manager for the children of this lc.
     */
    public CpLayoutManager getLayout();


    /**
     * answer whether x, y are inside the lc, in local coordinates
     */
	public boolean inside(int x, int y);

	/**
	 * answer the bounds of the lc in local coordinates, where the origin is the
	 * offset from its parent (for compatibility with component)
	 */
	public Rectangle bounds();

	/**
	 * Answer the inner bounds of the lc in local coordinates, taking insets into
	 * account.
	 */
	public Rectangle getClientRect();

	/**
	 * move the lc to x, y within its parent.  This will update the coordinates of
	 * the children recursively, but will not cause a layout to be
	 * executed.   This will have the side effect of a paint occurring.
	 */
	public void moveBy(int x, int y);
    public void move(int x, int y);
    public void move(Point loc);

    /**
     * resize the lc within its parent.  This will not update the coordinates of
     * the children, but will cause a layout to be executed. A paint will occur
     * as a result.
     */
    public void resize(int width, int height);
    public void resize(Dimension dim);

    /**
     * Size and move the lc.  Coordinates are local to the parent of the lc. If the
     * position has changed, this will cause a move.  If the size has changed, this
     * will cause a size,which in turn will cause a layout().  A paint will occur
     * as a result of this.
     */
     public void reshape(int x, int y, int width, int height);
     public void reshape(Rectangle rect);


	/**
	 * Answer the left top of the lc relative to its parent.
	 */
	public Point location();

	/**
	 * Answer the size of the lc.
	 */
	public Dimension size();

    /**
     * Answer the suggested size for this lc.
     */
    public Dimension preferredSize();

    /**
     * Answer the minimum size for this lc.
     */
    public Dimension minimumSize();

    /**
     * Answer the maximum size for this lc.
     */
    public Dimension maximumSize();

    /**
     * Answer the insets of the border displayer for this lc.
     */
    public Insets insets();

    /**
     * Set the border displayer for this lc.  This displayer will automatically
     * be told to paint itself after the lc is displayed.  The lc should take
     * its insets into account if it will display.
     * The calculation of insets is delegated to the border displayer, so any
     * layout management of children will be affected by the border displayer.
     */
    public void setBorderDisplayer(CpBorderDisplayable newDisplayer);

    /**
     * Answer the border displayer for this lc.
     */
    public CpBorderDisplayable getBorderDisplayer();

    /**
     * Answer whether this lc has any children.  Any lc can have children.
     */
    public boolean hasChildren();

    /**
     * Answer a vector of CpLightweightComponents.
     */
	public Vector getChildren();

    /**
     * Answer the siblings of this lc
     */

	public Vector getSiblings();

	/**
	 * Add either a collection of lcs, or one individual one. The parent will be repainted.
	 */
    public void add(Vector v);
    public void add(CpLightweightComponent child);

    /**
     * Remove either a collection of lcs, or one individual one. The parent will be repainted.
     */
    public void remove(Vector v);
    public void remove(CpLightweightComponent child);

    /**
     * Remove this lc from its parent.  This is a no-op if there is no parent. The
     * parent will be removed.
     */
	public void remove();

	/**
	 * Answer the parent lc for this lc.  If there is none, answer null.
	 */
	public CpLightweightComponent getParent();

	/**
	 * Answer the component this lc is contained within.
	 */
	public CpLcPanel getComponent();

	/**
	 * Answer true if the component is currently not visible.
	 */
    public boolean isHidden();

    /**
     * Set whether the lc is hidden.
     */
    public void hide(boolean hide);

    /**
     * Request the focus.  The lc will subsequently receive a gettingFocus message.
     */
    public void requestFocus();

    /**
     * Answer true if this lc has the focus.
     */
     public boolean hasFocus();

    /**
     * Answer whether lc is disabled.
     */
    public boolean isDisabled();

    /**
     * Set whether the lc is disabled or not. If so, it will not receive input
     * events, and it will be removed from the tab order list.
     */
    public void setIsDisabled(boolean disable);

    /**
     * Scale the lc visually using factor.  1.0 is normal size.
     */
    public void scale(double newScale);

    public double getScale();

    /**
     * TBD: try to blend this with cloneable...
     */
	public Object getCopy();

	/**
	 * Cause layout management to occur.  This should be used if a parent wants to
	 * relayout its children without resizing itself.  It can also be subclassed, if
	 * a layout manager is not used.
	 */
	public void layout();

	 /**
     * Move ourselves to the end of the z-order list (so we will draw last).
     */
	public void sendToBack();

    /**
     * Move ourselves to the beginning of the z-order list (so we will draw first).
     */
	public void bringToFront();

	public void repairDamage();
	public void repaintClientArea();

	public Image createImage(int x, int y);

	/**
	 * Allows the implementer of an lc to cache its drawing. Whenever it wants to
	 * redraw, it should flush the cache.
	 */
	public void setKeepCachedImage(boolean shouldKeep);
	public void flushCachedImage();


    /*
     * Any lightweight component can set text for itself that will appear over
     * the component if the mouse comes to a rest over it.
     */
	public void setFlyingTipText(String text);
	public String getFlyingTipText();

    public void setHelpText(String newHelpText);
    public String getHelpText();
    public String getHelpText(Point p);

	/**
	 * Any component can pop up another lc.  Note that coordinates are local;
	 * Values above or to the left of the component should be negative.
	 */
	 public void popUpLcAt(CpLightweightComponent lc, Rectangle r);
	 public void popDownPoppedUpLc();

	 /**
	  * Set the cursor to the cursor defined by this constant.
	  */
	 public void setCursor(int cursorId);

    /**
     * The methods below should be subclassed to handle interactive behavior.
     * If they handle the event, they should return true.
     */
    public boolean keyDown(Event e, int key);
    public boolean keyUp(Event e, int key);
    public boolean parentKeyUp(Event e, int key);
    public boolean parentKeyDown(Event e, int key);
    public boolean mouseDown(Event evt, int cellX, int cellY);
    public boolean parentMouseDown(Event evt, int cellX, int cellY);
    public boolean mouseDrag(Event evt, int cellX, int cellY);
    public boolean mouseUp(Event evt, int cellX, int cellY);
    public boolean mouseExit(Event evt, int cellX, int cellY);
    public boolean mouseEnter(Event evt, int cellX, int cellY);
    public boolean mouseMove(Event evt, int cellX, int cellY);

    public Point mouseLocation();
    public boolean gotFocus();
    public boolean lostFocus();




    /**
     * =============================================================================
     * FRAMEWORK METHODS
     * =============================================================================
     * The methods below should be ignored when implementing most lcs.  They are used
     * internally by the framework, and abstract implementations are the only implementers
     * and senders of them.
     */


     /**
      * set the parent lc for this lc.
      */
	public void setParent(CpLightweightComponent newParent);

	/**
	 * Set the component for this lc. In general, this is only done on the root level
	 * lc, since getComponent uses lazy initialization up the parent chain to set it
	 * internally.
	 */
	public void setComponent(CpLcPanel component);

	/**
	 * Paint yourself and your children.  If the image is null, use the graphics from
	 * the component, otherwise, use the graphics from the image.  If image is not null,
	 * the offset will be an offset from the origin of the image, and the globalClip
	 * rectangle will be in the coordinates of the image. Otherwise, offset will be 0,0,
	 * and globalClip will be in global coordinates.
	 * The image is used to handle localized double buffering within a particular lc
	 * or its children.
	 */
    public void paintIn(Component c, Image image, Rectangle globalClip, Point offset);

    /**
     * Damage a rect within the lc, using global coordinates.
     */
    public void damageGlobal(Rectangle r);

    /**
     * Any repair damages that occur while this is false will not happen.
     * This should always be done in pairs of false and true.
     */
    public void enableDamageRepair(boolean shouldEnable);
    public boolean isDamageRepairEnabled();

    /**
     * Clear any accumulated damage rect. The next repairDamage will have no effect.
     */
    public void clearDamagedRect();

    /**
     * Answer true if the given point is inside the lc, where the point is in global
     * coordinates.
     */
	public boolean insideGlobal(int x, int y);

	/**
	 * Answer the bounds of this lc, in global coordinates.
	 */

	public Rectangle boundsGlobal();

	/**
	 * Answer the location of this lc, in global coordinates.
	 */
	public Point locationGlobal();

	/**
	 * Answer the offspring lc that contains x, y, where the point is in global coordinates.
	 * If there is none, answer null.
	 */
    public CpLightweightComponent locateGlobal(int x, int y);

	/**
	 * Answer whether this Lc intersects r (r is in global coordinates)
	 */
    public boolean intersectsGlobal(Rectangle r);


    /**
     * Move child to the end of the z-order list (so it will draw last).
     */
	public void sendToBack(CpLightweightComponent child);


    /**
     * Move child to the beginning of the z-order list (so it will draw first).
     */
	public void bringToFront(CpLightweightComponent child);

	/**
	 * Answer true if this lc should allow drawing and hits right through itself.
	 */
    public boolean isTransparent();

	/**
	 * Answer true if this lc is not visible (hidden, no component, no parent and component not visible)
	 */
    public boolean isVisible();

    /**
     * Answer the outmost lc (the one connected to the actual component).
     */
    public CpLightweightComponent getRootLc();

    /**
     * =============================================================================
     * KEYBOARD SUPPORT
     * =============================================================================
     */

    /**
     * Answer whether this lc wants to make use of these keys
     */
    public boolean wantsTab();
    public boolean wantsCr();
    public boolean wantsEscape();
    public boolean wantsLeftAndRightArrows();

    /*
     * Answer true if lcs of this class ever want the focus
     */
    public boolean usesFocus();

    /*
     * Internal only - answer whether this lc both uses the focus and is a tab stop.
     * This is a recursive call, answering true if any children want it.
     */
    public boolean wantsTabFocus();

    public boolean isTabStop();
    public void setIsTabStop(boolean isGroupStart);

    public boolean isGroupStart();
    public void setIsGroupStart(boolean isGroupStart);

    /*
     * Move the focus
     */
    public void shiftFocusForward();
    public void shiftFocusBackward();
    public void shiftFocusForwardWithinGroup();
    public void shiftFocusBackwardWithinGroup();
    public void giveFirstChildFocus();
    public void giveLastChildFocus();
    public CpLightweightComponent firstChildWantingFocus();
    public CpLightweightComponent lastChildWantingFocus();

    public boolean pushDefaultButton();
    public boolean pushCancelButton();

}