edu.ucsb.eucalyptus.admin.client.extensions.store.ImageWidget.java Source code

Java tutorial

Introduction

Here is the source code for edu.ucsb.eucalyptus.admin.client.extensions.store.ImageWidget.java

Source

/*******************************************************************************
*Copyright (c) 2009  Eucalyptus Systems, Inc.
* 
*  This program is free software: you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published by
*  the Free Software Foundation, only version 3 of the License.
* 
* 
*  This file 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
*  for more details.
* 
*  You should have received a copy of the GNU General Public License along
*  with this program.  If not, see <http://www.gnu.org/licenses/>.
* 
*  Please contact Eucalyptus Systems, Inc., 130 Castilian
*  Dr., Goleta, CA 93101 USA or visit <http://www.eucalyptus.com/licenses/>
*  if you need additional information or have any questions.
* 
*  This file may incorporate work covered under the following copyright and
*  permission notice:
* 
*    Software License Agreement (BSD License)
* 
*    Copyright (c) 2008, Regents of the University of California
*    All rights reserved.
* 
*    Redistribution and use of this software in source and binary forms, with
*    or without modification, are permitted provided that the following
*    conditions are met:
* 
*      Redistributions of source code must retain the above copyright notice,
*      this list of conditions and the following disclaimer.
* 
*      Redistributions in binary form must reproduce the above copyright
*      notice, this list of conditions and the following disclaimer in the
*      documentation and/or other materials provided with the distribution.
* 
*    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
*    IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
*    TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
*    PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
*    OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
*    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
*    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
*    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
*    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
*    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
*    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. USERS OF
*    THIS SOFTWARE ACKNOWLEDGE THE POSSIBLE PRESENCE OF OTHER OPEN SOURCE
*    LICENSED MATERIAL, COPYRIGHTED MATERIAL OR PATENTED MATERIAL IN THIS
*    SOFTWARE, AND IF ANY SUCH MATERIAL IS DISCOVERED THE PARTY DISCOVERING
*    IT MAY INFORM DR. RICH WOLSKI AT THE UNIVERSITY OF CALIFORNIA, SANTA
*    BARBARA WHO WILL THEN ASCERTAIN THE MOST APPROPRIATE REMEDY, WHICH IN
*    THE REGENTS DISCRETION MAY INCLUDE, WITHOUT LIMITATION, REPLACEMENT
*    OF THE CODE SO IDENTIFIED, LICENSING OF THE CODE SO IDENTIFIED, OR
*    WITHDRAWAL OF THE CODE CAPABILITY TO THE EXTENT NEEDED TO COMPLY WITH
*    ANY SUCH LICENSES OR RIGHTS.
*******************************************************************************/
package edu.ucsb.eucalyptus.admin.client.extensions.store;

import java.util.List;

import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.InlineLabel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.DisclosurePanel;

import com.google.gwt.event.logical.shared.OpenHandler;
import com.google.gwt.event.logical.shared.CloseHandler;
import com.google.gwt.event.logical.shared.OpenEvent;
import com.google.gwt.event.logical.shared.CloseEvent;

import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.ClickEvent;

import com.google.gwt.core.client.GWT;

public class ImageWidget extends Composite {

    private static final String DEFAULT_ICON_URI = GraphicsUtil.uri("default-image-icon.png");
    private static final String UPGRADE_ICON_URI = GraphicsUtil.uri("available-upgrade.png");
    private static final String PROGRESS_BASE_URI = GraphicsUtil.uri("progress-base.png");
    private static final String PROGRESS_DONE_URI = GraphicsUtil.uri("progress-done.png");
    private static final String INSTALL_BUTTON_URI = GraphicsUtil.uri("install-button.png");
    private static final String DOWNLOADING_BUTTON_URI = GraphicsUtil.uri("downloading-button.gif");
    private static final String INSTALLING_BUTTON_URI = GraphicsUtil.uri("installing-button.gif");
    private static final String INSTALLED_BUTTON_URI = GraphicsUtil.uri("installed-button.png");
    private static final String SPINNER_URI = GraphicsUtil.uri("spinner.gif");

    /* Left panel. */
    private final Image iconImage = new Image();
    private final SimplePanel providerTitlePanel = new SimplePanel();

    /* Center panel. */
    private final Label titleLabel = new Label();
    private final Label summaryLabel = new Label();
    private final Label readMoreLabel = new Label("read more...");
    private final FlowPanel versionPanel = new FlowPanel();
    private final Label versionLabel = new InlineLabel("Unknown");
    private final FlowPanel sizePanel = new FlowPanel();
    private final Label sizeLabel = new InlineLabel("Unknown");
    private final FlowPanel tagsPanel = new FlowPanel();
    private final Label tagsLabel = new InlineLabel();
    private final HTML descriptionHtml = new HTML();

    /* Right panel. */
    private final FlexTable commandPanel = new FlexTable();
    private final SimplePanel buttonPanel = new SimplePanel();
    private final Image spinnerImage = new Image(SPINNER_URI);
    private final VerticalPanel progressPanel = new VerticalPanel();
    private ProgressBarWidget progressBar;

    private int howToRunRowIndex;
    private int showErrorRowIndex;
    private int cancelRowIndex;
    private int upgradeIconRowIndex;

    private final ImageInfo imageInfo;
    private ImageState imageState;

    public ImageWidget(ImageInfo imageInfo, ImageState imageState) {
        this.imageInfo = imageInfo;

        /* Rather than doing this, with a single horizontal panel
         *
         *           [   |   |   ]
         *
         * We do this, with two horizontal panels:
         *
         *           [[  |  ]|   ]
         *
         * This makes it easier to keep the right-hand side cell
         * aligned across different lines, even if the left panels
         * shift a little bit. */
        HorizontalPanel internalPanel = new HorizontalPanel();
        HorizontalPanel externalPanel = new HorizontalPanel();

        Widget iconPanel = buildIconPanel();
        Widget titlePanel = buildTitlePanel();
        Widget commandPanel = buildCommandPanel();

        /* Three vertical panels inside a horizontal panel. */
        internalPanel.add(iconPanel);
        internalPanel.add(titlePanel);
        externalPanel.add(internalPanel);
        externalPanel.add(commandPanel);

        /* For these, the image sizes (icon and button) will dictate
         * their real widths. */
        internalPanel.setCellWidth(iconPanel, "1px");
        externalPanel.setCellWidth(commandPanel, "1px");

        internalPanel.setStyleName("istore-left-panels");

        initWidget(externalPanel);

        setStyleName("istore-image-widget");

        setImageTitle(imageInfo.getTitle());
        setSummary(imageInfo.getSummary());
        setIconUri(imageInfo.getIconUri());
        setVersion(imageInfo.getVersion());
        setSizeInMB(imageInfo.getSizeInMB());
        setProvider(imageInfo.getProviderTitle(), imageInfo.getProviderUri());
        setTags(imageInfo.getTags());
        setDescriptionHtml(imageInfo.getDescriptionHtml());

        setImageState(imageState);
    }

    public ImageInfo getImageInfo() {
        return imageInfo;
    }

    public ImageState getImageState() {
        return imageState;
    }

    public void setImageState(ImageState imageState) {
        this.imageState = imageState;

        if (imageState.getStatus() == ImageState.Status.UNKNOWN
                || (imageState.getStatus() == ImageState.Status.UNINSTALLED
                        && !imageState.hasAction(ImageState.Action.INSTALL))) {
            GWT.log("ERROR: Received unknown image status.", null);
            commandPanel.setVisible(false);
        } else {
            updateButtonImage(imageState.getStatus());

            Integer percentage = imageState.getProgressPercentage();
            if (percentage == null) {
                progressPanel.setVisible(false);
            } else {
                progressBar.setPercentage(percentage);
                progressPanel.setVisible(true);
            }

            setHowToRunVisible(imageState.getEMI() != null);
            setShowErrorVisible(imageState.getErrorMessage() != null);
            setCancelVisible(imageState.hasAction(ImageState.Action.CANCEL));
            setUpgradeIconVisible(imageState.isUpgrade());
        }
    }

    public void addInstallHandler(InstallHandler<ImageWidget> handler) {
        addHandler(handler, InstallEvent.getType());
    }

    public void addCancelHandler(CancelHandler<ImageWidget> handler) {
        addHandler(handler, CancelEvent.getType());
    }

    public void addClearErrorHandler(ClearErrorHandler<ImageState> handler) {
        addHandler(handler, ClearErrorEvent.getType());
    }

    private Widget buildIconPanel() {
        VerticalPanel verticalPanel = new VerticalPanel();
        Label byLabel = new Label("by");

        verticalPanel.add(iconImage);
        verticalPanel.add(byLabel);
        verticalPanel.add(providerTitlePanel);

        byLabel.setStyleName("istore-provider-title-by");

        verticalPanel.setSpacing(3);
        verticalPanel.setStyleName("istore-image-icon-panel");

        return verticalPanel;
    }

    private Widget buildTitlePanel() {

        FlowPanel visibleDetailsPanel = new FlowPanel();
        visibleDetailsPanel.add(versionPanel);

        FlowPanel hiddenDetailsPanel = new FlowPanel();
        hiddenDetailsPanel.add(sizePanel);
        hiddenDetailsPanel.add(tagsPanel);

        InlineLabel versionHeaderLabel = new InlineLabel("Image version:");
        InlineLabel sizeHeaderLabel = new InlineLabel("Image size:");
        InlineLabel tagsHeaderLabel = new InlineLabel("Image tags:");

        versionPanel.add(versionHeaderLabel);
        versionPanel.add(versionLabel);
        sizePanel.add(sizeHeaderLabel);
        sizePanel.add(sizeLabel);
        tagsPanel.add(tagsHeaderLabel);
        tagsPanel.add(tagsLabel);

        VerticalPanel readMorePanel = new VerticalPanel();
        readMorePanel.add(hiddenDetailsPanel);
        readMorePanel.add(descriptionHtml);

        DisclosurePanel readMoreDisclosurePanel = new DisclosurePanel();
        readMoreDisclosurePanel.setHeader(readMoreLabel);
        readMoreDisclosurePanel.setContent(readMorePanel);

        VerticalPanel topPanel = new VerticalPanel();
        topPanel.add(titleLabel);
        topPanel.add(visibleDetailsPanel);
        topPanel.add(summaryLabel);
        topPanel.add(readMoreDisclosurePanel);

        titleLabel.setStyleName("istore-image-title");
        summaryLabel.setStyleName("istore-image-summary");
        topPanel.setStyleName("istore-title-panel");
        readMoreLabel.setStyleName("istore-read-more-label");

        visibleDetailsPanel.setStyleName("istore-visible-image-details-panel");
        hiddenDetailsPanel.setStyleName("istore-hidden-image-details-panel");
        versionHeaderLabel.setStyleName("istore-image-version-label");
        versionHeaderLabel.addStyleName("istore-image-detail-label");
        versionLabel.setStyleName("istore-image-version-value-label");
        versionLabel.addStyleName("istore-image-detail-value-label");
        sizeHeaderLabel.setStyleName("istore-image-size-label");
        sizeHeaderLabel.addStyleName("istore-image-detail-label");
        sizeLabel.setStyleName("istore-image-size-value-label");
        sizeLabel.addStyleName("istore-image-detail-value-label");
        tagsHeaderLabel.setStyleName("istore-image-tags-label");
        tagsHeaderLabel.addStyleName("istore-image-detail-label");
        tagsLabel.setStyleName("istore-image-tags-value-label");
        tagsLabel.addStyleName("istore-image-detail-value-label");

        descriptionHtml.setStyleName("istore-image-description");

        ReadMoreOpenCloseHandler rmoch = this.new ReadMoreOpenCloseHandler();
        readMoreDisclosurePanel.addOpenHandler(rmoch);
        readMoreDisclosurePanel.addCloseHandler(rmoch);

        return topPanel;
    }

    private Widget buildCommandPanel() {
        progressBar = new ProgressBarWidget(PROGRESS_BASE_URI, PROGRESS_DONE_URI, 120, 12);

        final Anchor howToRunAnchor = new Anchor("How to run?");
        final Anchor showErrorAnchor = new Anchor("Show error");
        final Anchor cancelAnchor = new Anchor("Cancel");

        Image upgradeIconImage = new Image(UPGRADE_ICON_URI);

        commandPanel.setCellSpacing(0);
        commandPanel.setCellPadding(0);

        spinnerImage.setVisible(false);

        commandPanel.setWidget(0, 0, buttonPanel);
        commandPanel.setWidget(0, 1, spinnerImage);
        commandPanel.setWidget(1, 0, progressPanel);
        howToRunRowIndex = 2;
        showErrorRowIndex = 3;
        cancelRowIndex = 4;
        upgradeIconRowIndex = 5;
        commandPanel.setWidget(howToRunRowIndex, 0, howToRunAnchor);
        commandPanel.setWidget(showErrorRowIndex, 0, showErrorAnchor);
        commandPanel.setWidget(cancelRowIndex, 0, cancelAnchor);
        commandPanel.setWidget(upgradeIconRowIndex, 0, upgradeIconImage);

        progressPanel.add(progressBar);

        commandPanel.setStyleName("istore-command-panel");
        buttonPanel.setStyleName("istore-button-panel");
        spinnerImage.setStyleName("istore-spinner");
        progressPanel.setStyleName("istore-progress-panel");
        howToRunAnchor.setStyleName("istore-how-to-run-anchor");
        showErrorAnchor.setStyleName("istore-show-error-anchor");
        cancelAnchor.setStyleName("istore-cancel-anchor");
        upgradeIconImage.setStyleName("istore-upgrade-icon");

        commandPanel.getRowFormatter().setStyleName(howToRunRowIndex, "istore-how-to-run-panel");
        commandPanel.getRowFormatter().setStyleName(showErrorRowIndex, "istore-show-error-panel");
        commandPanel.getRowFormatter().setStyleName(cancelRowIndex, "istore-cancel-panel");
        commandPanel.getRowFormatter().setStyleName(upgradeIconRowIndex, "istore-upgrade-icon-panel");

        howToRunAnchor.addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent event) {
                event.preventDefault();
                ImageInfo imageInfo = ImageWidget.this.imageInfo;
                ImageState imageState = ImageWidget.this.imageState;
                HowToRunDialog dialog = new HowToRunDialog(imageInfo, imageState);
                dialog.center();
            }
        });

        // Show the error dialog when the anchor is clicked, and hook its
        // clear error event into the firing of the same event on this widget.
        showErrorAnchor.addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent event) {
                event.preventDefault();
                ImageInfo imageInfo = ImageWidget.this.imageInfo;
                ImageState imageState = ImageWidget.this.imageState;
                ImageErrorDialog dialog = new ImageErrorDialog(imageInfo, imageState);
                dialog.center();
                dialog.addClearErrorHandler(new ClearErrorHandler<ImageState>() {
                    public void onClearError(ClearErrorEvent<ImageState> event) {
                        ImageWidget.this.fireEvent(event);
                    }
                });
            }
        });

        // Translate the click event into a cancel event.
        cancelAnchor.addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent event) {
                setInProgress(true);
                ImageWidget.this.fireEvent(new CancelEvent<ImageWidget>(ImageWidget.this));
                event.preventDefault();
            }
        });

        return commandPanel;
    }

    private void setHowToRunVisible(boolean isVisible) {
        commandPanel.getRowFormatter().setVisible(howToRunRowIndex, isVisible);
    }

    private void setShowErrorVisible(boolean isVisible) {
        commandPanel.getRowFormatter().setVisible(showErrorRowIndex, isVisible);
    }

    private void setCancelVisible(boolean isVisible) {
        commandPanel.getRowFormatter().setVisible(cancelRowIndex, isVisible);
    }

    private void setUpgradeIconVisible(boolean isVisible) {
        commandPanel.getRowFormatter().setVisible(upgradeIconRowIndex, isVisible);
    }

    private void setImageTitle(String title) {
        titleLabel.setText(title);
    }

    private void setSummary(String summary) {
        summaryLabel.setText(summary);
    }

    private void setVersion(String version) {
        if (version == null) {
            versionPanel.setVisible(false);
        } else {
            versionLabel.setText(version);
            versionPanel.setVisible(true);
        }
    }

    private void setSizeInMB(Integer sizeInMB) {
        if (sizeInMB == null) {
            sizePanel.setVisible(false);
        } else {
            sizeLabel.setText(sizeInMB.toString() + "MB");
            sizePanel.setVisible(true);
        }
    }

    private void setTags(List<String> tags) {
        if (tags == null || tags.size() == 0) {
            tagsPanel.setVisible(false);
        } else {
            String joinedTags;
            if (tags.size() == 1) {
                joinedTags = tags.get(0);
            } else {
                StringBuilder builder = new StringBuilder();
                builder.append(tags.get(0));
                for (int i = 1; i != tags.size(); i++) {
                    builder.append(", ");
                    builder.append(tags.get(i));
                }
                joinedTags = builder.toString();
            }
            tagsLabel.setText(joinedTags);
            tagsPanel.setVisible(true);
        }
    }

    private void setDescriptionHtml(String description) {
        descriptionHtml.setHTML(description);
    }

    private void setIconUri(String uri) {
        if (uri == null) {
            iconImage.setUrl(DEFAULT_ICON_URI);
        } else {
            iconImage.setUrl(uri);
        }
    }

    private void setProvider(String title, String uri) {
        String styleName = "istore-known-provider-title";

        if (title == null) {
            styleName = "istore-unknown-provider-title";
            title = "Unknown";
        }

        Widget providerTitleWidget;
        if (uri == null) {
            Label providerLabel = new Label();
            providerLabel.setText(title);
            providerTitleWidget = providerLabel;
        } else {
            Anchor providerAnchor = new Anchor();
            providerAnchor.setText(title);
            providerAnchor.setHref(uri);
            providerTitleWidget = providerAnchor;
        }

        providerTitlePanel.setWidget(providerTitleWidget);
        providerTitleWidget.setStyleName(styleName);
        providerTitleWidget.addStyleName("istore-provider-title");
    }

    private Image createButtonImage(ImageState.Status status) {
        String uri;
        switch (status) {
        case UNINSTALLED:
            uri = INSTALL_BUTTON_URI;
            break;
        case DOWNLOADING:
            uri = DOWNLOADING_BUTTON_URI;
            break;
        case INSTALLING:
            uri = INSTALLING_BUTTON_URI;
            break;
        case INSTALLED:
            uri = INSTALLED_BUTTON_URI;
            break;
        default:
            return null; // Unsupported status.
        }
        return new Image(uri);
    }

    private void updateButtonImage(ImageState.Status status) {
        final Image buttonImage = createButtonImage(status);

        // If we don't have support for the given status, prevent any
        // commands from happening on this image.
        if (buttonImage == null) {
            GWT.log("ERROR: Couldn't find an appropriate button for the given status.", null);
            commandPanel.setVisible(false);
        } else {
            commandPanel.setVisible(true);
            if (status == ImageState.Status.UNINSTALLED) {
                // Translate the click event into a download event.
                buttonImage.addClickHandler(new ClickHandler() {
                    public void onClick(ClickEvent event) {
                        setInProgress(true);
                        ImageWidget.this.fireEvent(new InstallEvent<ImageWidget>(ImageWidget.this));
                    }
                });
                buttonImage.setStyleName("istore-install-button");
            }
            buttonPanel.setWidget(buttonImage);
        }
    }

    public void setInProgress(boolean inProgress) {
        spinnerImage.setVisible(inProgress);
        Widget buttonImage = buttonPanel.getWidget();
        if (buttonImage != null && imageState.getStatus() == ImageState.Status.UNINSTALLED) {
            if (inProgress) {
                buttonImage.addStyleName("istore-install-button-progress");
            } else {
                buttonImage.removeStyleName("istore-install-button-progress");
            }
        }
    }

    private class ReadMoreOpenCloseHandler implements OpenHandler<DisclosurePanel>, CloseHandler<DisclosurePanel> {

        public void onOpen(OpenEvent<DisclosurePanel> event) {
            readMoreLabel.setText("hide...");
        }

        public void onClose(CloseEvent<DisclosurePanel> event) {
            readMoreLabel.setText("read more...");
        }
    }

}