Package com.vaadin.ui

Source Code of com.vaadin.ui.AbsoluteLayout$ComponentPosition

/*
* Copyright 2010 IT Mill Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.vaadin.ui;

import java.io.Serializable;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Map;

import com.vaadin.event.LayoutEvents.LayoutClickEvent;
import com.vaadin.event.LayoutEvents.LayoutClickListener;
import com.vaadin.terminal.PaintException;
import com.vaadin.terminal.PaintTarget;
import com.vaadin.terminal.gwt.client.MouseEventDetails;
import com.vaadin.terminal.gwt.client.ui.VAbsoluteLayout;

/**
* AbsoluteLayout is a layout implementation that mimics html absolute
* positioning.
*
*/
@SuppressWarnings("serial")
@ClientWidget(VAbsoluteLayout.class)
public class AbsoluteLayout extends AbstractLayout {

    private static final String CLICK_EVENT = VAbsoluteLayout.CLICK_EVENT_IDENTIFIER;

    // The components in the layout
    private Collection<Component> components = new LinkedHashSet<Component>();

    // Maps each component to a position
    private Map<Component, ComponentPosition> componentToCoordinates = new HashMap<Component, ComponentPosition>();

    /**
     * Creates an AbsoluteLayout with full size.
     */
    public AbsoluteLayout() {
        setSizeFull();
    }

    /**
     * Gets an iterator for going through all components enclosed in the
     * absolute layout.
     */
    public Iterator<Component> getComponentIterator() {
        return components.iterator();
    }

    /**
     * Replaces one component with another one. The new component inherits the
     * old components position.
     */
    public void replaceComponent(Component oldComponent, Component newComponent) {
        ComponentPosition position = getPosition(oldComponent);
        removeComponent(oldComponent);
        addComponent(newComponent);
        componentToCoordinates.put(newComponent, position);
    }

    /*
     * (non-Javadoc)
     *
     * @see
     * com.vaadin.ui.AbstractComponentContainer#addComponent(com.vaadin.ui.Component
     * )
     */
    @Override
    public void addComponent(Component c) {
        components.add(c);
        super.addComponent(c);
        requestRepaint();
    }

    /*
     * (non-Javadoc)
     *
     * @see
     * com.vaadin.ui.AbstractComponentContainer#removeComponent(com.vaadin.ui
     * .Component)
     */
    @Override
    public void removeComponent(Component c) {
        components.remove(c);
        super.removeComponent(c);
        requestRepaint();
    }

    /**
     * Adds a component to the layout. The component can be positioned by
     * providing a string formatted in CSS-format.
     * <p>
     * For example the string "top:10px;left:10px" will position the component
     * 10 pixels from the left and 10 pixels from the top. The identifiers:
     * "top","left","right" and "bottom" can be used to specify the position.
     * </p>
     *
     * @param c
     *            The component to add to the layout
     * @param cssPosition
     *            The css position string
     */
    public void addComponent(Component c, String cssPosition) {
        addComponent(c);
        getPosition(c).setCSSString(cssPosition);
    }

    /**
     * Gets the position of a component in the layout. Returns null if component
     * is not attached to the layout.
     *
     * @param component
     *            The component which position is needed
     * @return An instance of ComponentPosition containing the position of the
     *         component, or null if the component is not enclosed in the
     *         layout.
     */
    public ComponentPosition getPosition(Component component) {
        if (componentToCoordinates.containsKey(component)) {
            return componentToCoordinates.get(component);
        } else {
            ComponentPosition coords = new ComponentPosition();
            componentToCoordinates.put(component, coords);
            return coords;
        }
    }

    /**
     * The CompontPosition class represents a components position within the
     * absolute layout. It contains the CSS attributes for left, right, top and
     * bottom and the units used to specify them. *
     *
     * TODO symmetric getters and setters for fields to make this simpler to use
     * in generic java tools
     *
     */
    public class ComponentPosition implements Serializable {

        private int zIndex = -1;
        private Float topValue = null;
        private Float rightValue = null;
        private Float bottomValue = null;
        private Float leftValue = null;

        private int topUnits;
        private int rightUnits;
        private int bottomUnits;
        private int leftUnits;

        /**
         * Sets the position attributes using CSS syntax. Example usage:
         *
         * <code><pre>
         * setCSSString("top:10px;left:20%;z-index:16;");
         * </pre></code>
         *
         * @param css
         */
        public void setCSSString(String css) {
            if (css == null) {
                return;
            }

            String[] cssProperties = css.split(";");
            for (int i = 0; i < cssProperties.length; i++) {
                String[] keyValuePair = cssProperties[i].split(":");
                String key = keyValuePair[0].trim();
                if (key.equals("")) {
                    continue;
                }
                if (key.equals("z-index")) {
                    zIndex = Integer.parseInt(keyValuePair[1]);
                } else {
                    String value;
                    if (keyValuePair.length > 1) {
                        value = keyValuePair[1].trim();
                    } else {
                        value = "";
                    }
                    String unit = value.replaceAll("[0-9\\.\\-]+", "");
                    if (!unit.equals("")) {
                        value = value.substring(0, value.indexOf(unit)).trim();
                    }
                    float v = Float.parseFloat(value);
                    int unitInt = parseCssUnit(unit);
                    if (key.equals("top")) {
                        topValue = v;
                        topUnits = unitInt;
                    } else if (key.equals("right")) {
                        rightValue = v;
                        rightUnits = unitInt;
                    } else if (key.equals("bottom")) {
                        bottomValue = v;
                        bottomUnits = unitInt;
                    } else if (key.equals("left")) {
                        leftValue = v;
                        leftUnits = unitInt;
                    }
                }
            }
            requestRepaint();
        }

        /**
         * Parses a string and checks if a unit is found. If a unit is not found
         * from the string the unit pixels is used.
         *
         * @param string
         *            The string to parse the unit from
         * @return The found unit
         */
        private int parseCssUnit(String string) {
            for (int i = 0; i < UNIT_SYMBOLS.length; i++) {
                if (UNIT_SYMBOLS[i].equals(string)) {
                    return i;
                }
            }
            return 0; // defaults to px (eg. top:0;)
        }

        /**
         * Converts the internal values into a valid CSS string.
         *
         * @return A valid CSS string
         */
        public String getCSSString() {
            String s = "";
            if (topValue != null) {
                s += "top:" + topValue + UNIT_SYMBOLS[topUnits] + ";";
            }
            if (rightValue != null) {
                s += "right:" + rightValue + UNIT_SYMBOLS[rightUnits] + ";";
            }
            if (bottomValue != null) {
                s += "bottom:" + bottomValue + UNIT_SYMBOLS[bottomUnits] + ";";
            }
            if (leftValue != null) {
                s += "left:" + leftValue + UNIT_SYMBOLS[leftUnits] + ";";
            }
            if (zIndex >= 0) {
                s += "z-index:" + zIndex + ";";
            }
            return s;
        }

        /**
         * Sets the 'top' CSS-attribute
         *
         * @param topValue
         *            The value of the 'top' attribute
         * @param topUnits
         *            The unit of the 'top' attribute. See UNIT_SYMBOLS for a
         *            description of the available units.
         */
        public void setTop(float topValue, int topUnits) {
            validateLength(topValue, topUnits);
            this.topValue = topValue;
            this.topUnits = topUnits;
            requestRepaint();
        }

        /**
         * Sets the 'right' CSS-attribute
         *
         * @param rightValue
         *            The value of the 'right' attribute
         * @param rightUnits
         *            The unit of the 'right' attribute. See UNIT_SYMBOLS for a
         *            description of the available units.
         */
        public void setRight(float rightValue, int rightUnits) {
            validateLength(rightValue, rightUnits);
            this.rightValue = rightValue;
            this.rightUnits = rightUnits;
            requestRepaint();
        }

        /**
         * Sets the 'bottom' CSS-attribute
         *
         * @param bottomValue
         *            The value of the 'bottom' attribute
         * @param units
         *            The unit of the 'bottom' attribute. See UNIT_SYMBOLS for a
         *            description of the available units.
         */
        public void setBottom(float bottomValue, int units) {
            validateLength(bottomValue, units);
            this.bottomValue = bottomValue;
            bottomUnits = units;
            requestRepaint();
        }

        /**
         * Sets the 'left' CSS-attribute
         *
         * @param leftValue
         *            The value of the 'left' attribute
         * @param units
         *            The unit of the 'left' attribute. See UNIT_SYMBOLS for a
         *            description of the available units.
         */
        public void setLeft(float leftValue, int units) {
            validateLength(leftValue, units);
            this.leftValue = leftValue;
            leftUnits = units;
            requestRepaint();
        }

        /**
         * Sets the 'z-index' CSS-attribute
         *
         * @param zIndex
         *            The z-index for the component.
         */
        public void setZIndex(int zIndex) {
            this.zIndex = zIndex;
            requestRepaint();
        }

        /**
         * Sets the value of the 'top' CSS-attribute
         *
         * @param topValue
         *            The value of the 'left' attribute
         */
        public void setTopValue(float topValue) {
            validateLength(topValue, topUnits);
            this.topValue = topValue;
            requestRepaint();
        }

        /**
         * Gets the 'top' CSS-attributes value in specified units.
         *
         * @return The value of the 'top' CSS-attribute
         */
        public float getTopValue() {
            return topValue == null ? 0 : topValue.floatValue();
        }

        /**
         * Gets the 'right' CSS-attributes value in specified units.
         *
         * @return The value of the 'right' CSS-attribute
         */
        public float getRightValue() {
            return rightValue == null ? 0 : rightValue.floatValue();
        }

        /**
         * Sets the 'right' CSS-attributes value in specified units.
         *
         * @param rightValue
         *            The value of the 'right' CSS-attribute
         */
        public void setRightValue(float rightValue) {
            validateLength(rightValue, rightUnits);
            this.rightValue = rightValue;
            requestRepaint();
        }

        /**
         * Gets the 'bottom' CSS-attributes value in specified units.
         *
         * @return The value of the 'bottom' CSS-attribute
         */
        public float getBottomValue() {
            return bottomValue == null ? 0 : bottomValue.floatValue();
        }

        /**
         * Sets the 'bottom' CSS-attributes value in specified units.
         *
         * @param bottomValue
         *            The value of the 'bottom' CSS-attribute
         */
        public void setBottomValue(float bottomValue) {
            validateLength(bottomValue, bottomUnits);
            this.bottomValue = bottomValue;
            requestRepaint();
        }

        /**
         * Gets the 'left' CSS-attributes value in specified units.
         *
         * @return The value of the 'left' CSS-attribute
         */
        public float getLeftValue() {
            return leftValue == null ? 0 : leftValue.floatValue();
        }

        /**
         * Sets the 'left' CSS-attributes value in specified units.
         *
         * @param leftValue
         *            The value of the 'left' CSS-attribute
         */
        public void setLeftValue(float leftValue) {
            validateLength(leftValue, leftUnits);
            this.leftValue = leftValue;
            requestRepaint();
        }

        /**
         * Gets the unit for the 'top' CSS-attribute
         *
         * @return See UNIT_SYMBOLS for a description of the available units.
         */
        public int getTopUnits() {
            return topUnits;
        }

        /**
         * Sets the unit for the 'top' CSS-attribute
         *
         * @param topUnits
         *            See UNIT_SYMBOLS for a description of the available units.
         */
        public void setTopUnits(int topUnits) {
            validateLength(topValue, topUnits);
            this.topUnits = topUnits;
            requestRepaint();
        }

        /**
         * Gets the unit for the 'right' CSS-attribute
         *
         * @return See UNIT_SYMBOLS for a description of the available units.
         */
        public int getRightUnits() {
            return rightUnits;
        }

        /**
         * Sets the unit for the 'right' CSS-attribute
         *
         * @param rightUnits
         *            See UNIT_SYMBOLS for a description of the available units.
         */
        public void setRightUnits(int rightUnits) {
            validateLength(rightValue, rightUnits);
            this.rightUnits = rightUnits;
            requestRepaint();
        }

        /**
         * Gets the unit for the 'bottom' CSS-attribute
         *
         * @return See UNIT_SYMBOLS for a description of the available units.
         */
        public int getBottomUnits() {
            return bottomUnits;
        }

        /**
         * Sets the unit for the 'bottom' CSS-attribute
         *
         * @param bottomUnits
         *            See UNIT_SYMBOLS for a description of the available units.
         */
        public void setBottomUnits(int bottomUnits) {
            validateLength(bottomValue, bottomUnits);
            this.bottomUnits = bottomUnits;
            requestRepaint();
        }

        /**
         * Gets the unit for the 'left' CSS-attribute
         *
         * @return See UNIT_SYMBOLS for a description of the available units.
         */
        public int getLeftUnits() {
            return leftUnits;
        }

        /**
         * Sets the unit for the 'left' CSS-attribute
         *
         * @param leftUnits
         *            See UNIT_SYMBOLS for a description of the available units.
         */
        public void setLeftUnits(int leftUnits) {
            validateLength(leftValue, leftUnits);
            this.leftUnits = leftUnits;
            requestRepaint();
        }

        /**
         * Gets the 'z-index' CSS-attribute.
         *
         * @return the zIndex The z-index attribute
         */
        public int getZIndex() {
            return zIndex;
        }

        /*
         * (non-Javadoc)
         *
         * @see java.lang.Object#toString()
         */
        @Override
        public String toString() {
            return getCSSString();
        }

    }

    /*
     * (non-Javadoc)
     *
     * @see
     * com.vaadin.ui.AbstractLayout#paintContent(com.vaadin.terminal.PaintTarget
     * )
     */
    @Override
    public void paintContent(PaintTarget target) throws PaintException {
        super.paintContent(target);
        for (Component component : components) {
            target.startTag("cc");
            target.addAttribute("css", getPosition(component).getCSSString());
            component.paint(target);
            target.endTag("cc");
        }
    }

    /**
     * Validates a value with the unit
     *
     * @param topValue
     *            The value to validate
     * @param topUnits2
     *            The unit to validate
     */
    private static void validateLength(float topValue, int topUnits2) {
        // TODO throw on invalid value

    }

    /*
     * (non-Javadoc)
     *
     * @see com.vaadin.ui.AbstractComponent#changeVariables(java.lang.Object,
     * java.util.Map)
     */
    @Override
    public void changeVariables(Object source, Map variables) {
        super.changeVariables(source, variables);
        if (variables.containsKey(CLICK_EVENT)) {
            fireClick((Map<String, Object>) variables.get(CLICK_EVENT));
        }

    }

    /**
     * Fires a click event when the layout is clicked
     *
     * @param parameters
     *            The parameters recieved from the client side implementation
     */
    private void fireClick(Map<String, Object> parameters) {
        MouseEventDetails mouseDetails = MouseEventDetails
                .deSerialize((String) parameters.get("mouseDetails"));
        Component childComponent = (Component) parameters.get("component");

        fireEvent(new LayoutClickEvent(this, mouseDetails, childComponent));
    }

    /**
     * Add a click listener to the layout. The listener is called whenever the
     * user clicks inside the layout. Also when the click targets a component
     * inside the Panel, provided the targeted component does not prevent the
     * click event from propagating.
     *
     * The child component that was clicked is included in the
     * {@link LayoutClickEvent}.
     *
     * Use {@link #removeListener(LayoutClickListener)} to remove the listener.
     *
     * @param listener
     *            The listener to add
     */
    public void addListener(LayoutClickListener listener) {
        addListener(CLICK_EVENT, LayoutClickEvent.class, listener,
                LayoutClickListener.clickMethod);
    }

    /**
     * Remove a click listener from the layout. The listener should earlier have
     * been added using {@link #addListener(LayoutClickListener)}.
     *
     * @param listener
     *            The listener to remove
     */
    public void removeListener(LayoutClickListener listener) {
        removeListener(CLICK_EVENT, LayoutClickEvent.class, listener);
    }

}
TOP

Related Classes of com.vaadin.ui.AbsoluteLayout$ComponentPosition

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.