com.google.gwt.widgetideas.client.ProgressBar.java Source code

Java tutorial

Introduction

Here is the source code for com.google.gwt.widgetideas.client.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.google.gwt.widgetideas.client;

import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
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 ResizableWidget {

    private static final String DEFAULT_TEXT_CLASS_NAME = "gwt-ProgressBar-text";

    private String textClassName = DEFAULT_TEXT_CLASS_NAME;
    private String textFirstHalfClassName = DEFAULT_TEXT_CLASS_NAME + "-firstHalf";
    private String textSecondHalfClassName = DEFAULT_TEXT_CLASS_NAME + "-secondHalf";

    /**
     * A formatter used to format the text displayed in the progress bar widget.
     */
    public abstract static class 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
         */
        protected abstract String getText(ProgressBar bar, double curProgress);
    }

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

    /**
     * The current progress.
     */
    private double curProgress;

    /**
     * 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 curProgress the current progress
     */
    public ProgressBar(double curProgress) {
        this(0.0, 100.0, curProgress);
    }

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

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

    /**
     * Create a progress bar within the given range starting at the specified
     * progress amount.
     * 
     * @param minProgress the minimum progress
     * @param maxProgress the maximum progress
     * @param curProgress the current progress
     * @param textFormatter the text formatter
     */
    public ProgressBar(double minProgress, double maxProgress, double curProgress, TextFormatter textFormatter) {
        this.minProgress = minProgress;
        this.maxProgress = maxProgress;
        this.curProgress = curProgress;
        setTextFormatter(textFormatter);

        // Create the outer shell
        setElement(DOM.createDiv());
        DOM.setStyleAttribute(getElement(), "position", "relative");
        setStyleName("gwt-ProgressBar-shell");

        // Create the bar element
        barElement = DOM.createDiv();
        DOM.appendChild(getElement(), barElement);
        DOM.setStyleAttribute(barElement, "height", "100%");
        setBarStyleName("gwt-ProgressBar-bar");

        // Create the text element
        textElement = DOM.createDiv();
        DOM.appendChild(getElement(), textElement);
        DOM.setStyleAttribute(textElement, "position", "absolute");
        DOM.setStyleAttribute(textElement, "top", "0px");

        // Set the current progress
        setProgress(curProgress);
    }

    /**
     * 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 = (curProgress - minProgress) / (maxProgress - minProgress);
        return Math.max(0.0, Math.min(1.0, percent));
    }

    /**
     * Get the current progress.
     *
     * @return the current progress
     */
    public double getProgress() {
        return curProgress;
    }

    /**
     * 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.
     *
     * @param width the new client width of the element
     * @param height the new client height of the element
     */
    public void onResize(int width, int height) {
        if (textVisible) {
            int textWidth = DOM.getElementPropertyInt(textElement, "offsetWidth");
            int left = (width / 2) - (textWidth / 2);
            DOM.setStyleAttribute(textElement, "left", left + "px");
        }
    }

    /**
     * Redraw the progress bar when something changes the layout.
     */
    public void redraw() {
        if (isAttached()) {
            int width = DOM.getElementPropertyInt(getElement(), "clientWidth");
            int height = DOM.getElementPropertyInt(getElement(), "clientHeight");
            onResize(width, height);
        }
    }

    public void setBarStyleName(String barClassName) {
        DOM.setElementProperty(barElement, "className", barClassName);
    }

    /**
     * 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 maxProgress the maximum progress
     */
    public void setMaxProgress(double maxProgress) {
        this.maxProgress = maxProgress;
        curProgress = Math.min(curProgress, maxProgress);
        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 minProgress the minimum progress
     */
    public void setMinProgress(double minProgress) {
        this.minProgress = minProgress;
        curProgress = Math.max(curProgress, minProgress);
        resetProgress();
    }

    /**
     * Set the current progress.
     *
     * @param curProgress the current progress
     */
    public void setProgress(double curProgress) {
        this.curProgress = Math.max(minProgress, Math.min(maxProgress, curProgress));

        // Calculate percent complete
        int percent = (int) (100 * getPercent());
        DOM.setStyleAttribute(barElement, "width", percent + "%");
        DOM.setElementProperty(textElement, "innerHTML", generateText(curProgress));
        updateTextStyle(percent);

        // Realign the text
        redraw();
    }

    public void setTextFirstHalfStyleName(String textFirstHalfClassName) {
        this.textFirstHalfClassName = textFirstHalfClassName;
        onTextStyleChange();
    }

    /**
     * Set the text formatter.
     *
     * @param textFormatter the text formatter
     */
    public void setTextFormatter(TextFormatter textFormatter) {
        this.textFormatter = textFormatter;
    }

    public void setTextSecondHalfStyleName(String textSecondHalfClassName) {
        this.textSecondHalfClassName = textSecondHalfClassName;
        onTextStyleChange();
    }

    public void setTextStyleName(String textClassName) {
        this.textClassName = textClassName;
        onTextStyleChange();
    }

    /**
     * Sets whether the text is visible over the bar.
     *
     * @param textVisible True to show text, false to hide it
     */
    public void setTextVisible(boolean textVisible) {
        this.textVisible = textVisible;
        if (this.textVisible) {
            DOM.setStyleAttribute(textElement, "display", "");
            redraw();
        } else {
            DOM.setStyleAttribute(textElement, "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;
    }

    /**
     * This method is called immediately after a widget becomes attached to the
     * browser's document.
     */
    @Override
    protected void onLoad() {
        // Reset the position attribute of the parent element
        DOM.setStyleAttribute(getElement(), "position", "relative");
        ResizableWidgetCollection.get().add(this);
        redraw();
    }

    @Override
    protected void onUnload() {
        ResizableWidgetCollection.get().remove(this);
    }

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

    private void onTextStyleChange() {
        int percent = (int) (100 * getPercent());
        updateTextStyle(percent);
    }

    private void updateTextStyle(int percent) {
        // Set the style depending on the size of the bar
        if (percent < 50) {
            DOM.setElementProperty(textElement, "className", textClassName + " " + textFirstHalfClassName);
        } else {
            DOM.setElementProperty(textElement, "className", textClassName + " " + textSecondHalfClassName);
        }
    }
}