com.bearsoft.gwt.ui.widgets.progress.ProgressBar.java Source code

Java tutorial

Introduction

Here is the source code for com.bearsoft.gwt.ui.widgets.progress.ProgressBar.java

Source

/*
 * Copyright 2008 Google Inc.
 * 
 * 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.bearsoft.gwt.ui.widgets.progress;

import com.bearsoft.gwt.ui.XElement;
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.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.ui.HasValue;
import com.google.gwt.user.client.ui.RequiresResize;
import com.google.gwt.user.client.ui.Widget;

/**
 * A widget that displays progress on an arbitrary scale.
 *
 * <h3>CSS Style Rules</h3>
 * <ul class='css'>
 * <li>.gwt-ProgressBar-shell { primary style } </li>
 * <li>.gwt-ProgressBar-shell .gwt-ProgressBar-bar { the actual progress bar }
 * </li>
 * <li>.gwt-ProgressBar-shell .gwt-ProgressBar-text { text on the bar } </li>
 * <li>.gwt-ProgressBar-shell .gwt-ProgressBar-text-firstHalf { applied to text
 * when progress is less than 50 percent } </li>
 * <li>.gwt-ProgressBar-shell .gwt-ProgressBar-text-secondHalf { applied to text
 * when progress is greater than 50 percent } </li>
 * </ul>
 */
public class ProgressBar extends Widget implements RequiresResize, HasValue<Double> {

    /**
     * A formatter used to format the text displayed in the progress bar widget.
     */
    public interface TextFormatter {

        /**
         * Generate the text to display in the ProgressBar based on the current
         * value.
         *
         * Override this method to change the text displayed within the
         * ProgressBar.
         *
         * @param bar the progress bar
         * @param curProgress the current progress
         * @return the text to display in the progress bar
         */
        public String getText(ProgressBar bar, Double curProgress);
    }

    /**
     * The bar element that displays the progress.
     */
    private Element barElement;

    /**
     * The current progress.
     */
    private Double value;

    /**
     * The maximum progress.
     */
    private double maxProgress;

    /**
     * The minimum progress.
     */
    private double minProgress;

    /**
     * A boolean that determines if the text is visible.
     */
    private boolean textVisible = true;

    /**
     * The element that displays text on the page.
     */
    private Element textElement;

    /**
     * The current text formatter.
     */
    private TextFormatter textFormatter;

    /**
     * Create a progress bar with default range of 0 to 100.
     */
    public ProgressBar() {
        this(0.0, 100.0, 0.0);
    }

    /**
     * Create a progress bar with an initial progress and a default range of 0
     * to 100.
     *
     * @param aValue the current progress
     */
    public ProgressBar(Double aValue) {
        this(0.0, 100.0, aValue);
    }

    /**
     * Create a progress bar within the given range.
     *
     * @param aMinProgress the minimum progress
     * @param aMaxProgress the maximum progress
     */
    public ProgressBar(double aMinProgress, double aMaxProgress) {
        this(aMinProgress, aMaxProgress, 0.0);
    }

    /**
     * Create a progress bar within the given range starting at the specified
     * progress amount.
     *
     * @param aMinProgress the minimum progress
     * @param aMaxProgress the maximum progress
     * @param aValue the current progress
     */
    public ProgressBar(double aMinProgress, double aMaxProgress, Double aValue) {
        this(aMinProgress, aMaxProgress, aValue, null);
    }

    /**
     * Create a progress bar within the given range starting at the specified
     * progress amount.
     *
     * @param aMinProgress the minimum progress
     * @param aMaxProgress the maximum progress
     * @param aValue the current progress
     * @param aTextFormatter the text formatter
     */
    public ProgressBar(double aMinProgress, double aMaxProgress, Double aValue, TextFormatter aTextFormatter) {
        super();
        minProgress = aMinProgress;
        maxProgress = aMaxProgress;
        value = aValue;
        setTextFormatter(aTextFormatter);

        // Create the outer shell
        setElement(Document.get().createDivElement());
        getElement().getStyle().setDisplay(Style.Display.INLINE_BLOCK);
        getElement().getStyle().setPosition(Style.Position.RELATIVE);
        // default preferred size
        getElement().getStyle().setWidth(150, Style.Unit.PX);
        getElement().getStyle().setHeight(16, Style.Unit.PX);
        setStyleName("gwt-ProgressBar-shell");

        // Create the bar element
        barElement = DOM.createDiv();
        getElement().appendChild(barElement);
        barElement.getStyle().setHeight(100, Style.Unit.PCT);
        barElement.setClassName("gwt-ProgressBar-bar");

        // Create the text element
        textElement = DOM.createDiv();
        DOM.appendChild(getElement(), textElement);

        textElement.getStyle().setPosition(Style.Position.ABSOLUTE);
        textElement.getStyle().setTop(0, Style.Unit.PX);
        textElement.setClassName("gwt-ProgressBar-text");
        // Set the current progress
        setValue(aValue);
        getElement().<XElement>cast().addResizingTransitionEnd(this);
    }

    /**
     * Get the maximum progress.
     *
     * @return the maximum progress
     */
    public double getMaxProgress() {
        return maxProgress;
    }

    /**
     * Get the minimum progress.
     *
     * @return the minimum progress
     */
    public double getMinProgress() {
        return minProgress;
    }

    /**
     * Get the current percent complete, relative to the minimum and maximum
     * values. The percent will always be between 0.0 - 1.0.
     *
     * @return the current percent complete
     */
    public double getPercent() {
        // If we have no range
        if (maxProgress <= minProgress) {
            return 0.0;
        }

        // Calculate the relative progress
        double percent = ((value != null ? value : 0) - minProgress) / (maxProgress - minProgress);
        return Math.max(0.0, Math.min(1.0, percent));
    }

    /**
     * Get the current progress.
     *
     * @return the current progress
     */
    @Override
    public Double getValue() {
        return value;
    }

    /**
     * Get the text formatter.
     *
     * @return the text formatter
     */
    public TextFormatter getTextFormatter() {
        return textFormatter;
    }

    /**
     * Check whether the text is visible or not.
     *
     * @return true if the text is visible
     */
    public boolean isTextVisible() {
        return textVisible;
    }

    /**
     * This method is called when the dimensions of the parent element change.
     * Subclasses should override this method as needed.
     *
     * Move the text to the center of the progress bar.
     *
     */
    @Override
    public void onResize() {
        if (textVisible) {
            int width = getElement().getClientWidth();
            int height = getElement().getClientHeight();
            int textWidth = textElement.getOffsetWidth();
            int textHeight = textElement.getOffsetHeight();
            int left = (width / 2) - (textWidth / 2);
            textElement.getStyle().setLeft(left, Style.Unit.PX);
            textElement.getStyle().setTop((height - textHeight) / 2, Style.Unit.PX);
        }
    }

    /**
     * Redraw the progress bar when something changes the layout.
     */
    public void redraw() {
        if (isAttached()) {
            onResize();
        }
    }

    /**
     * Set the maximum progress. If the minimum progress is more than the
     * current progress, the current progress is adjusted to be within the new
     * range.
     *
     * @param aValue the maximum progress
     */
    public void setMaxProgress(double aValue) {
        maxProgress = aValue;
        value = Math.min((value != null ? value : 0), aValue);
        resetProgress();
    }

    /**
     * Set the minimum progress. If the minimum progress is more than the
     * current progress, the current progress is adjusted to be within the new
     * range.
     *
     * @param aValue the minimum progress
     */
    public void setMinProgress(double aValue) {
        minProgress = aValue;
        value = Math.max((value != null ? value : 0), aValue);
        resetProgress();
    }

    /**
     * Set the current progress.
     *
     * @param aValue the current aValue
     */
    @Override
    public void setValue(Double aValue) {
        setValue(aValue, false);
    }

    /**
     * Set the current progress.
     *
     * @param aValue the current aValue
     * @param fireEvents
     */
    @Override
    public void setValue(Double aValue, boolean fireEvents) {
        value = aValue != null ? Math.max(minProgress, Math.min(maxProgress, aValue)) : null;

        // Calculate percent complete
        int percent = (int) (100 * getPercent());
        barElement.getStyle().setWidth(percent, Style.Unit.PCT);
        textElement.setInnerHTML(generateText(value));

        // Set the style depending on the size of the bar
        if (percent < 50) {
            textElement.removeClassName("gwt-ProgressBar-text-secondHalf");
            textElement.addClassName("gwt-ProgressBar-text-firstHalf");
        } else {
            textElement.removeClassName("gwt-ProgressBar-text-firstHalf");
            textElement.addClassName("gwt-ProgressBar-text-secondHalf");
        }
        // Realign the text
        redraw();
        if (fireEvents) {
            ValueChangeEvent.fire(ProgressBar.this, getValue());
        }
    }

    @Override
    public HandlerRegistration addValueChangeHandler(ValueChangeHandler<Double> handler) {
        return addHandler(handler, ValueChangeEvent.getType());
    }

    /**
     * Set the text formatter.
     *
     * @param aFormatter the text formatter
     */
    public void setTextFormatter(TextFormatter aFormatter) {
        textFormatter = aFormatter;
        if (isAttached()) {
            setValue(getValue());
        }
    }

    /**
     * Sets whether the text is visible over the bar.
     *
     * @param aValue True to show text, false to hide it
     */
    public void setTextVisible(boolean aValue) {
        textVisible = aValue;
        if (textVisible) {
            textElement.getStyle().clearDisplay();
            redraw();
        } else {
            textElement.getStyle().setDisplay(Style.Display.NONE);
        }
    }

    /**
     * Generate the text to display within the progress bar. Override this
     * function to change the default progress percent to a more informative
     * message, such as the number of kilobytes downloaded.
     *
     * @param curProgress the current progress
     * @return the text to display in the progress bar
     */
    protected String generateText(Double curProgress) {
        if (textFormatter != null) {
            return textFormatter.getText(this, curProgress);
        } else {
            return (int) (100 * getPercent()) + "%";
        }
    }

    /**
     * Get the bar element.
     *
     * @return the bar element
     */
    protected Element getBarElement() {
        return barElement;
    }

    /**
     * Get the text element.
     *
     * @return the text element
     */
    protected Element getTextElement() {
        return textElement;
    }

    @Override
    protected void onAttach() {
        super.onAttach();
        redraw();
    }

    /**
     * Reset the progress text based on the current min and max progress range.
     */
    protected void resetProgress() {
        setValue(getValue());
    }
}