Package com.sun.dtv.lwuit

Source Code of com.sun.dtv.lwuit.Container

/*
* Copyright 2008 Sun Microsystems, Inc.  All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.  Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package com.sun.dtv.lwuit;

import com.sun.dtv.lwuit.animations.Animation;
import com.sun.dtv.lwuit.animations.Transition;
import com.sun.dtv.lwuit.layouts.BorderLayout;
import com.sun.dtv.lwuit.layouts.FlowLayout;
import com.sun.dtv.lwuit.layouts.Layout;
import com.sun.dtv.lwuit.plaf.UIManager;
import com.sun.dtv.ui.Matte;
import com.sun.dtv.ui.MatteException;
import java.util.Enumeration;
import com.sun.dtv.lwuit.geom.Dimension;
import com.sun.dtv.lwuit.geom.Rectangle;
import com.sun.dtv.ui.MatteEnabled;


/**
* A composite pattern with {@link Component}, allows nesting and arranging multiple
* components using a pluggable layout manager architecture. Containers can be nested
* one within the other to form elaborate UI's.
*
* @see com.sun.lwuit.layouts
* @see Component
* @author Chen Fishbein
*/
public class Container extends Component implements MatteEnabled {
   
    private Layout layout;
    private java.util.Vector components = new java.util.Vector();
    private boolean shouldLayout = true;
    private boolean scrollableX;
    private boolean scrollableY;

    /**
     * Constructs a new Container with a new layout manager.
     *
     * @param layout the specified layout manager
     */
    public Container(Layout layout) {
        super();
        this.layout = layout;
        setFocusable(false);
    }

    /**
     * Constructs a new Container, with a {@link FlowLayout}.
     */
    public Container() {
        this(new FlowLayout());
    }

    /**
     * Returns the layout manager responsible for arranging this container
     *
     * Presente no JAVADTV 1.1
     * @return the container layout manager
     */
    public Layout getLayout() {
        return layout;
    }

    /**
     * Sets the layout manager responsible for arranging this container
     *
     * @param layout the specified layout manager
     */
    public void setLayout(Layout layout) {
        this.layout = layout;
    }

    /**
     * Same as setShouldCalcPreferredSize(true) but made accessible for
     * layout managers
     */
    public void invalidate() {
        setShouldCalcPreferredSize(true);
    }

    /**
     * @inheritDoc
     */
    protected void setShouldCalcPreferredSize(boolean shouldCalcPreferredSize) {
        super.setShouldCalcPreferredSize(shouldCalcPreferredSize);
        shouldLayout = shouldCalcPreferredSize;
        Enumeration enums = components.elements();
        if (shouldLayout) {
            while (enums.hasMoreElements()) {
                Component cmp = (Component) enums.nextElement();
                if (cmp instanceof Container) {
                    ((Container) cmp).setShouldCalcPreferredSize(shouldCalcPreferredSize);
                }
            }
        }
        Form f = getComponentForm();
        if (f != null) {
            f.clearFocusVectors();
        }
    }

    /**
     * Returns the width for layout manager purposes, this takes scrolling
     * into consideration unlike the getWidth method.
     *
     * Presente no JAVADTV 1.1
     * @return the layout width
     */
    public int getLayoutWidth() {
        if (isScrollableX()) {
            int scrollH = UIManager.getInstance().getLookAndFeel().getHorizontalScrollHeight();
            return Math.max(getWidth() + scrollH, getPreferredSize().getWidth() + scrollH);
        } else {
            Container parent = getScrollableParent();
            if (parent != null && parent.isScrollableX()) {
                return Math.max(getWidth(), getPreferredSize().getWidth());
            }
            int width = getWidth();
            if (width <= 0) {
                return getPreferredSize().getWidth();
            }
            return width;
        }
    }

    /**
     * Returns the height for layout manager purposes, this takes scrolling
     * into consideration unlike the getWidth method.
     *
     * Presente no JAVADTV 1.1
     * @return the layout height
     */
    public int getLayoutHeight() {
        if (isScrollableY()) {
            int scrollW = UIManager.getInstance().getLookAndFeel().getVerticalScrollWidth();
            return Math.max(getHeight() + scrollW, getPreferredSize().getHeight() + scrollW);
        } else {
            Container parent = getScrollableParent();
            if (parent != null && parent.isScrollableY()) {
                return Math.max(getHeight(), getPreferredSize().getHeight());
            }
            int height = getHeight();
            if (height <= 1) {
                return getPreferredSize().getHeight();
            }
            return height;
        }
    }

    /**
     * Returns a parent container that is scrollable or null if no parent is
     * scrollable.
     *
     * @return a parent container that is scrollable or null if no parent is
     * scrollable.
     */
    private Container getScrollableParent() {
        Container parent = getParent();
        while (parent != null) {
            if (parent.isScrollable()) {
                return parent;
            }
            parent = parent.getParent();
        }
        return null;
    }

    /**
     * Adds a Component to the Container
     *
     * Presente no JAVADTV 1.1
     * @param cmp the component to be added
     */
    public void addComponent(Component cmp) {
        // helper check for a common mistake...
        if (layout instanceof BorderLayout) {
            throw new IllegalArgumentException("Cannot add component to BorderLayout Container without constraint parameter");
        }

        insertComponentAt(components.size(), cmp);
    }

    /**
     * Adds a Component to the Container
     *
     * Presente no JAVADTV 1.1
     * @param constraints this method is useful when the Layout requires a constraint
     * such as the BorderLayout.
     * In this case you need to specify an additional data when you add a Component,
     * such as "CENTER", "NORTH"...
     *
     * @param cmp component to add
     */
    public void addComponent(Object constraints, Component cmp) {
        layout.addLayoutComponent(constraints, cmp, this);
        insertComponentAt(components.size(), cmp);
    }

    private void insertComponentAt(int index, Component cmp) {
        if (cmp.getParent() != null) {
            throw new IllegalArgumentException("Component is already contained in Container: " + cmp.getParent());
        }
        if (cmp instanceof Form) {
            throw new IllegalArgumentException("A form cannot be added to a container");
        }
        cmp.setParent(this);
        components.insertElementAt(cmp, index);
        setShouldCalcPreferredSize(true);
        if (isInitialized()) {
            cmp.initComponentImpl();
        }
        Form f = getComponentForm();
        if (f != null) {
            f.clearFocusVectors();
        }
    //repaint();
    }

    /**
     * This method adds the Component at a specific index location in the Conatiner
     * Components array.
     *
     * Presente no JAVADTV 1.1
     * @param index location to insert the Component
     * @param cmp the Component to add
     * @throws ArrayIndexOutOfBoundsException if index is out of bounds
     * @throws IllegalArgumentException if Component is already contained or
     * the cmp is a Form Component
     */
    public void addComponent(int index, Component cmp) {
        insertComponentAt(index, cmp);
    }

    /**
     * This method replaces the current Component with the next Component.
     * Current Component must be contained in this Container.
     * This method return immediately.
     *
     * @param current a Component to remove from the Container
     * @param next a Component that replaces the current Component
     * @param t a Transition between the add and removal of the Components
     *  a Transition can be null
     */
    public void replace(final Component current, final Component next, final Transition t) {
        if (!contains(current)) {
            throw new IllegalArgumentException("Component " + current + " is not contained in this Container");
        }
        if (t == null) {
            replace(current, next);
            return;
        }

        next.setX(current.getX());
        next.setY(current.getY());
        next.setWidth(current.getWidth());
        next.setHeight(current.getHeight());
        next.setParent(this);
        if (next instanceof Container) {
            ((Container) next).layoutContainer();
        }

        Animation anim = new Anim(this, current, next, t);

        // block events as long as the transition is animating
        Display.getInstance().blockEvents(true);

        // register the transition animation
        getComponentForm().registerAnimated(anim);
    }

    void replace(final Component current, final Component next) {
        int index = components.indexOf(current);
        boolean currentFocused = false;
        if (current.getComponentForm() != null && current.getComponentForm().getFocused() == current) {
            currentFocused = true;
        }
        if (layout instanceof BorderLayout) {
            Object constraint = layout.getComponentConstraint(current);
            removeComponent(current);
            layout.addLayoutComponent(constraint, next, Container.this);
        } else {
            removeComponent(current);
        }
        next.setParent(null);
        if (index < 0) {
            index = 0;
        }
        insertComponentAt(index, next);
        if (currentFocused && next.isFocusable()) {
            next.requestFocus();
        }
    }

    /**
     * @inheritDoc
     */
    void initComponentImpl() {
        if (!isInitialized()) {
            if (isSmoothScrolling()) {
                getComponentForm().registerAnimated(this);
            }
            super.initComponentImpl();
        }
        Enumeration e = components.elements();
        while (e.hasMoreElements()) {
            ((Component) e.nextElement()).initComponentImpl();
        }
    }

    /**
     * removes a Component from the Container
     *
     * @param cmp the removed component
     */
    public void removeComponent(Component cmp) {
        Form parentForm = cmp.getComponentForm();
        layout.removeLayoutComponent(cmp);
        cmp.deinitializeImpl();
        components.removeElement(cmp);
        cmp.setParent(null);
        cmp.setShouldCalcPreferredSize(true);
        if (parentForm != null) {
            if (parentForm.getFocused() == cmp || cmp instanceof Container && ((Container) cmp).contains(parentForm.getFocused())) {
                parentForm.setFocused(null);
            }
            parentForm.clearFocusVectors();
            if (cmp.isSmoothScrolling()) {
                parentForm.deregisterAnimated(cmp);
            }
        }
        setShouldCalcPreferredSize(true);
    }

    /**
     * Cleansup the initialization flags in the hierachy
     */
    void deinitializeImpl() {
        super.deinitializeImpl();
        int size = components.size();
        for (int iter = 0; iter < size; iter++) {
            ((Component) components.elementAt(iter)).deinitializeImpl();
        }
    }

    /**
     * remove all Components from container
     */
    public void removeAll() {
        Form parentForm = getComponentForm();
        if (parentForm != null) {
            Component focus = parentForm.getFocused();
            if (focus != null && contains(focus)) {
                parentForm.setFocused(null);
            }
        }
        Object[] arr = new Object[components.size()];
        components.copyInto(arr);

        for (int i = 0; i < arr.length; i++) {
            removeComponent((Component) arr[i]);
        }
    }

    /**
     * Re-layout the container, this is useful when we modify the container hierarchy and
     * need to redo the layout
     */
    public void revalidate() {
        setShouldCalcPreferredSize(true);
        Form root = getComponentForm();
        if (root != null) {
            root.layoutContainer();
            root.repaint();
        } else {
            layoutContainer();
            repaint();
        }
    }

    /**
     * @inheritDoc
     */
    public void paint(Graphics g) {
        layoutContainer();
        g.translate(getX(), getY());
        Enumeration enums = components.elements();
        while (enums.hasMoreElements()) {
            Component cmp = (Component) enums.nextElement();
            cmp.paintInternal(g);
        }

        g.translate(-getX(), -getY());
    }

    void paintIntersecting(Graphics g, Component cmp, Rectangle bounds, boolean above) {
       
        if (layout.isOverlapSupported() && components.contains(cmp)) {
            int indexOfComponent = components.indexOf(cmp);
            int startIndex;
            int endIndex;
            if (above) {
                startIndex = indexOfComponent + 1;
                endIndex = components.size();
            } else {
                startIndex = 0;
                endIndex = indexOfComponent;
            }

            for (int i = startIndex; i < endIndex; i++) {
                Component cmp2 = (Component) components.elementAt(i);
                Rectangle rect = new Rectangle(cmp2.getBounds());
                rect.setX(cmp2.getAbsoluteX());
                rect.setY(cmp2.getAbsoluteY());

                if (rect.intersects(bounds)) {
                    cmp2.paintInternal(g, false);
                }
            }
        }
    }

    /**
     * Performs the layout of the container if a layout is necessary
     */
    public void layoutContainer() {
        //will compute the container + components and will layout the components.
        if (shouldLayout) {
            shouldLayout = false;
            doLayout();
        }

    }

    /**
     * Lays out the container
     */
    void doLayout() {
        layout.layoutContainer(this);
        int count = getComponentCount();
        for (int i = 0; i <
                count; i++) {
            Component c = getComponentAt(i);
            if (c instanceof Container) {
                ((Container) c).doLayout();
            }

        }
    }

    /**
     * Returns the number of components
     *
     * Presente no JAVADTV 1.1
     * @return the Component count
     */
    public int getComponentCount() {
        return components.size();
    }

    /**
     * Returns the Component at a given index
     *
     * Presente no JAVADTV 1.1
     * @param index of the Component you wish to get
     * @return a Component
     * @throws ArrayIndexOutOfBoundsException if an invalid index was given.
     */
    public Component getComponentAt(int index) {
        return (Component) components.elementAt(index);
    }

    /**
     * Returns the Component index in the Container
     *
     * Presente no JAVADTV 1.1
     * @param cmp the component to search for
     * @return the Component index in the Container or -1 if not found
     */
    public int getComponentIndex(Component cmp) {
        int count = getComponentCount();
        for (int i = 0; i <
                count; i++) {
            Component c = getComponentAt(i);
            if (c.equals(cmp)) {
                return i;
            }
        }
        return -1;
    }

    /**
     * Returns true if the given component is within the hierarchy of this container
     *
     * Presente no JAVADTV 1.1
     * @param cmp a Component to check
     * @return true if this Component contains in this Container
     */
    public boolean contains(Component cmp) {
        boolean found = false;
        int count = getComponentCount();
        for (int i = 0; i < count; i++) {
            Component c = getComponentAt(i);
            if (c.equals(cmp)) {
                return true;
            }

            if (c instanceof Container) {
                found = ((Container) c).contains(cmp);
                if (found) {
                    return true;
                }

            }
        }
        return false;
    }

    /**
     * Makes sure the component is visible in the scroll if this container is
     * scrollable
     *
     * @param c the component that will be scrolling for visibility
     */
    protected void scrollComponentToVisible(Component c) {
        if (isScrollable()) {
            if (c != null) {
                if (c.getParent() != null) {
                    // special case for the first component to allow the user to scroll all the
                    // way to the top
                    Form f = getComponentForm();
                    if (f != null && f.getFocusPosition(c) == 0) {
                        scrollRectToVisible(new Rectangle(0, 0, c.getX() + c.getWidth(), c.getY() + c.getHeight()), c);
                        return;
                    }
                }
                scrollRectToVisible(c.getBounds(), c);
            }
        }

    }

    /**
     * Returns a Component that exists in the given x, y coordinates by traversing
     * component objects and invoking contains
     *
     * Presente no JAVADTV 1.1
     * @param x absolute screen location
     * @param y absolute screen location
     * @return a Component if found, null otherwise
     * @see Component#contains
     */
    public Component getComponentAt(int x, int y) {
        int count = getComponentCount();
        for (int i = count - 1; i >= 0; i--) {
            Component cmp = getComponentAt(i);
            if (cmp.contains(x, y)) {
                if (cmp instanceof Container) {
                    return ((Container) cmp).getComponentAt(x, y);
                }
                return cmp;
            }

        }
        return null;
    }

    /**
     * @inheritDoc
     */
    public void pointerPressed(int x, int y) {
        if (!isDragActivated()) {
            Component cmp = getComponentAt(x, y);
            if (cmp != null) {
                cmp.pointerPressed(x, y);
            }
        }
    }

    /**
     * @inheritDoc
     */
    public void pointerReleased(int x, int y) {
        if (isDragActivated()) {
            super.pointerReleased(x, y);
            return;
        }
        Component cmp = getComponentAt(x, y);
        if (cmp != null) {
            cmp.pointerReleased(x, y);
        }

    }

    /**
     * @inheritDoc
     */
    Dimension calcPreferredSize() {
        Dimension d = layout.getPreferredSize(this);
        return d;
    }

//    /**
//     * @inheritDoc
//     */
//    public boolean isFocusable() {
//        return false;
//    }
    /**
     * @inheritDoc
     */
    protected String paramString() {
        String className = layout.getClass().getName();
        String layoutStr = className.substring(className.lastIndexOf('.') + 1);
        return super.paramString() + ", layout = " + layoutStr +
                ", scrollableX = " + scrollableX +
                ", scrollableY = " + scrollableY +
                ", components = " + getComponentsNames();
    }

    /**
     * Return the conatainer components objects as list of Strings
     * @return the conatainer components objects as list of Strings
     */
    private String getComponentsNames() {
        String ret = "[";
        Enumeration enums = components.elements();
        while (enums.hasMoreElements()) {
            String className = enums.nextElement().getClass().getName();
            ret += className.substring(className.lastIndexOf('.') + 1) + ", ";
        }

        return ret.substring(0, ret.length() - 2) + "]";
    }

    /**
     * @inheritDoc
     */
    public void refreshTheme() {
        super.refreshTheme();
        Enumeration enums = components.elements();
        while (enums.hasMoreElements()) {
            Component cmp = (Component) enums.nextElement();
            cmp.refreshTheme();
        }
    }

    /**
     * @inheritDoc
     */
    public boolean isScrollableX() {
        return scrollableX && getPreferredSize().getWidth() > getWidth();
    }

    /**
     * @inheritDoc
     */
    public boolean isScrollableY() {
        return scrollableY && getPreferredSize().getHeight() > getHeight();
    }

    /**
     * Sets whether the component should/could scroll on the X axis
     *
     * @param scrollableX whether the component should/could scroll on the X axis
     */
    public void setScrollableX(boolean scrollableX) {
        this.scrollableX = scrollableX;
    }

    /**
     * Sets whether the component should/could scroll on the Y axis
     *
     * @param scrollableY whether the component should/could scroll on the Y axis
     */
    public void setScrollableY(boolean scrollableY) {
        this.scrollableY = scrollableY;
    }

    /**
     * The equivalent of calling both setScrollableY and setScrollableX
     *
     * @param scrollable whether the component should/could scroll on the
     * X and Y axis
     */
    public void setScrollable(boolean scrollable) {
        setScrollableX(scrollable);
        setScrollableY(scrollable);
    }

    /**
     * @inheritDoc
     */
    public void setCellRenderer(boolean cellRenderer) {
        if (isCellRenderer() != cellRenderer) {
            super.setCellRenderer(cellRenderer);
            int size = getComponentCount();
            for (int iter = 0; iter <
                    size; iter++) {
                getComponentAt(iter).setCellRenderer(cellRenderer);
            }
        }
    }

    /**
     * @inheritDoc
     */
    String getUIID() {
        return "Container";
    }

    /**
     * @return
     */
    public Matte getMatte() {
        // TODO implementar
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public void setMatte(Matte matte) throws MatteException {
        // TODO implementar
        throw new UnsupportedOperationException("Not supported yet.");
    }
}

class Anim implements Animation {

    private Transition t;
    private Component current;
    private Component next;
    private boolean started = false;
    private Container thisContainer;

    public Anim(Container thisContainer, Component current, Component next, Transition t) {
        this.t = t;
        this.next = next;
        this.current = current;
        this.thisContainer = thisContainer;
    }

    public boolean animate() {
        if (!started) {
            t.init(current, next);
            t.initTransition();
            started = true;
        }
        boolean notFinished = t.animate();
        if (!notFinished) {
            next.setParent(null);
            thisContainer.replace(current, next);
            //release the events blocking
            Display.getInstance().blockEvents(false);
            t.cleanup();
            thisContainer.getComponentForm().deregisterAnimated(this);
        }
        return notFinished;
    }

    public void paint(Graphics g) {
        t.paint(g);
    }
}

TOP

Related Classes of com.sun.dtv.lwuit.Container

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.