org.vaadin.alump.distributionbar.gwt.client.dom.ElementBuilder.java Source code

Java tutorial

Introduction

Here is the source code for org.vaadin.alump.distributionbar.gwt.client.dom.ElementBuilder.java

Source

/**
 * ElementBuilder.java (DistributionBar)
 * 
 * Copyright 2012 Vaadin Ltd, Sami Viitanen <alump@vaadin.org>
 *
 * 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 org.vaadin.alump.distributionbar.gwt.client.dom;

import java.util.List;
import java.util.logging.Logger;

import org.vaadin.alump.distributionbar.gwt.client.GwtDistributionBar;

import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Style;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.MouseMoveEvent;
import com.google.gwt.event.dom.client.MouseOutEvent;
import com.google.gwt.event.dom.client.MouseOverEvent;
import com.google.gwt.safehtml.shared.SafeHtmlUtils;

/**
 * This is help class for GwtDistributionBar and so is designed to be used only
 * by it. It's split to own class to allow later totally browser specific
 * versions. For now there is single if that is done browser specific so there
 * is no need for own class.
 */
public class ElementBuilder {

    protected static final String PART_CLASSNAME_PREFIX = GwtDistributionBar.CLASSNAME + "-part-";
    protected static final String PART_VALUE_CLASSNAME = GwtDistributionBar.CLASSNAME + "-value";
    protected static final String UNINITIALIZED_VALUE_CLASSNAME = GwtDistributionBar.CLASSNAME + "-uninitizalized";

    //private final static Logger LOGGER = Logger.getLogger(ElementBuilder.class.getName());

    /**
     * Parent is needed to get access to DOM tree
     */
    protected GwtDistributionBar parent;

    /**
     * Tool tip presenter. Constructed in setParent.
     */
    protected ToolTipPresenter tooltip;

    /**
     * Empty constructor for GWT.create. setParent must be called always after
     * this to have instance correctly initialized.
     */
    public ElementBuilder() {

    }

    private ToolTipPresenter getToolTip() {
        if (tooltip == null) {
            tooltip = new ToolTipPresenter();
            parent.addDomHandler(tooltip, MouseOutEvent.getType());
            parent.addDomHandler(tooltip, MouseOverEvent.getType());
            parent.addDomHandler(tooltip, MouseMoveEvent.getType());
        }

        return tooltip;
    }

    /**
     * This function must be called after constructor. It's left out of
     * constructor to allow replacement creation easily with GWT.create()
     * 
     * @param parent
     *            Parent using builder. Used to access DOM tree.
     */
    public void setParent(GwtDistributionBar parent) {
        this.parent = parent;
    }

    /**
     * Return full width of root element. Used to calculate width of parts.
     * 
     * @return Full width of the root element in pixels.
     */
    public int getFullWidth() {
        return parent.getElement().getOffsetWidth();
    }

    /**
     * Get element where parts are added
     * 
     * @return
     */
    public Element getParentElementForParts() {
        return parent.getElement();
    }

    /**
     * Other part elements must be siblings to this element. If not you have to
     * override functions above this.
     * 
     * @return Element for first part which has other parts as siblings
     */
    public Element getFirstPartElement() {
        return getParentElementForParts().getFirstChildElement();
    }

    /**
     * Initialize root element of distribution bar
     * 
     * @return Root element initialized
     */
    public Element initRootElement() {

        Element element = parent.getElement();

        if (element != null) {

            getToolTip().clearAllToolTips();

            Element child = null;
            while ((child = element.getFirstChildElement()) != null) {
                element.removeChild(child);
            }

        } else {
            element = Document.get().createDivElement();
            element.setClassName(GwtDistributionBar.CLASSNAME);
            parent.setRootElement(element);
        }

        return element;
    }

    /**
     * Generate class names for element
     * 
     * @param element
     *            Element that will get new class names
     * @param index
     *            Index of part (useful for left/middle/right)
     * @param parts
     *            Number of parts totally (useful for left/middle/right)
     * @param extraStyleName
     *            Extra style name(s) defined by used
     */
    public void setPartClassNames(Element element, int index, int styleIndex, int parts, String extraStyleName) {
        String styleName = GwtDistributionBar.CLASSNAME;

        // Allows styling like rounded corners
        if (parts == 1) {
            styleName += "-only";
        } else if (index == 0) {
            styleName += "-left";
        } else if (index == (parts - 1)) {
            styleName += "-right";
        } else {
            styleName += "-middle";
        }

        element.setClassName(styleName);
        element.addClassName(PART_CLASSNAME_PREFIX + String.valueOf(styleIndex + 1));
        if (extraStyleName != null) {
            element.addClassName(extraStyleName);
        }
    }

    /**
     * Adds new DOM element under widget
     * 
     * @param index
     *            Index for added part
     * @param parts
     *            Number of parts
     * @param size
     *            Size of part added
     * @param title
     *            Title of part added
     */
    public void addPartElement(int index, int parts, int size, String title) {

        final Element element = createPartElement();
        setPartClassNames(element, index, index, parts, null);
        element.setAttribute("title", title);

        Element textElem = Document.get().createSpanElement();
        textElem.setClassName(PART_VALUE_CLASSNAME);
        textElem.setInnerText(String.valueOf(size));

        element.appendChild(textElem);

        getParentElementForParts().appendChild(element);
    }

    /**
     * Add warning text shown if distribution bar is used uninitialized
     */
    public void addUninitializedWarning() {

        Element element = createPartElement();

        Element content = Document.get().createSpanElement();
        content.setClassName(UNINITIALIZED_VALUE_CLASSNAME);
        content.setInnerText("uninitialized");
        element.appendChild(content);

        getParentElementForParts().appendChild(element);
    }

    /**
     * Get root element of part with index
     * 
     * @param index
     *            Index of part [0..N]. Use only valid indexes.
     * @return Element of part.
     */
    public Element getPartElement(int index) {
        Element element = getFirstPartElement();

        for (int i = 0; i < index && element != null; ++i) {
            element = element.getNextSiblingElement();
        }

        return element;
    }

    /**
     * Change part title to given string
     * 
     * @param index
     *            Index of part modified
     * @param title
     *            New title (can be empty)
     */
    public void changePartTitle(int index, String title) {
        Element element = getPartElement(index);

        if (element != null) {
            if (title.isEmpty()) {
                if (element.hasAttribute("title")) {
                    element.removeAttribute("title");
                }
            } else {
                String safe = SafeHtmlUtils.htmlEscape(title);
                element.setAttribute("title", safe);
            }
        }
    }

    public void changePartTooltip(int index, String content) {
        Element element = getPartElement(index);

        if (element != null) {
            if (content.isEmpty()) {
                getToolTip().removeToolTip(element);
            } else {
                getToolTip().setToolTip(element, content);
            }
        }
    }

    public void changePartStyleName(int index, int styleIndex, int parts, String styleName) {
        Element element = getPartElement(index);

        if (element != null) {
            setPartClassNames(element, index, styleIndex, parts, styleName);
        }
    }

    /**
     * Update DOM presentation of distribution. This has to be called always
     * after changes are done to parts.
     */
    public void updateParts(List<Integer> sizes, double minElementWidth) {

        int totalSize = parent.totalSize();

        Element element = getFirstPartElement();
        int totalWidth = getFullWidth();

        for (int i = 0; (i < sizes.size()) && (element != null); ++i) {

            int size = sizes.get(i);

            setPartElementSize(element, size, totalSize, sizes.size(), totalWidth, minElementWidth);

            Element nextElement = element.getNextSiblingElement();
            element = nextElement;
        }
    }

    /**
     * Set size (width) for part element
     * 
     * @param part
     *            Part element
     * @param size
     *            New size
     * @param total
     *            Sum of all sizes
     * @param part
     *            How many parts there are
     * @param parentSize
     *            Size of parent in pixels
     * @param minElementSize
     *            Minimum width of part with value
     */
    public void setPartElementSize(Element part, double size, double total, double parts, double parentSize,
            double minElementSize) {

        double elementSize = 0.0;
        Style.Unit elementSizeUnit = Unit.PX;

        if (parentSize <= 0.0 || total == 0.0) {
            elementSize = Math.floor(100.0 / parts);
            elementSizeUnit = Unit.PCT;
        } else {
            final double minTotalSize = minElementSize * parts;
            final double availableSize = parentSize - minTotalSize;

            elementSize = minElementSize + size / total * availableSize;
        }

        setPartElementWidth(part, elementSize, elementSizeUnit);
        setPartElementValueText(part, String.valueOf(size));
    }

    /**
     * Change the width of part element
     * 
     * @param element
     *            Part element changed
     * @param width
     *            New width value
     * @param unit
     *            New width unit
     */
    public void setPartElementWidth(Element element, double width, Style.Unit unit) {

        element.getStyle().setWidth(width, unit);
    }

    /**
     * Simple function that return element used to represent part.
     * 
     * @return Element used to represent the element
     */
    public Element createPartElement() {
        // if (BrowserInfo.get().isIE6() || BrowserInfo.get().isIE7()) {
        // return Document.get().createSpanElement();
        // } else {
        return Document.get().createDivElement();
        // }
    }

    /**
     * Change the text presentation of part size in part element
     * 
     * @param element
     *            Part element given
     * @param text
     *            Text shown
     */
    public void setPartElementValueText(Element element, String text) {
        Element textElem = element.getFirstChildElement();
        textElem.setInnerText(text);
    }

}