cc.alcina.framework.gwt.client.ide.widget.ActionProgress.java Source code

Java tutorial

Introduction

Here is the source code for cc.alcina.framework.gwt.client.ide.widget.ActionProgress.java

Source

/*
 * 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 cc.alcina.framework.gwt.client.ide.widget;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import javax.persistence.Transient;

import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.InlineLabel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Widget;
import com.totsp.gwittir.client.beans.SourcesPropertyChangeEvents;

import cc.alcina.framework.common.client.WrappedRuntimeException;
import cc.alcina.framework.common.client.csobjects.JobResultType;
import cc.alcina.framework.common.client.csobjects.JobTracker;
import cc.alcina.framework.common.client.csobjects.JobTrackerImpl;
import cc.alcina.framework.common.client.logic.MutablePropertyChangeSupport;
import cc.alcina.framework.common.client.util.CommonUtils;
import cc.alcina.framework.common.client.util.CommonUtils.DateStyle;
import cc.alcina.framework.gwt.client.ClientBase;
import cc.alcina.framework.gwt.client.widget.Link;

/**
 *
 * @author Nick Reddel
 */
public class ActionProgress extends Composite implements SourcesPropertyChangeEvents {
    private static final String CANCELLED = " - Cancelled";

    public static int REFRESH_DELAY_MS = 3500;

    protected transient MutablePropertyChangeSupport propertyChangeSupport = new MutablePropertyChangeSupport(this);

    private FlowPanel fp;

    private JobTracker info = new JobTrackerImpl();

    private Grid grid;

    private Label jobName;

    private Label message;

    private FlowPanel progress;

    private HTML times;

    private FlowPanel bar;

    private Link cancelLink;

    private InlineLabel cancellingStatusMessage;

    private Timer timer;

    private final AsyncCallback<JobTracker> completionCallback;

    private int maxConnectionFailure = 2;

    private String id;

    private int row = 0;

    private boolean stopped;

    public ActionProgress(final String id) {
        this(id, null);
    }

    public ActionProgress(final String id, AsyncCallback<JobTracker> completionCallback) {
        this.id = id;
        this.completionCallback = completionCallback;
        this.fp = new FlowPanel();
        fp.setStyleName("alcina-ActionProgress");
        grid = new Grid(4, 2);
        jobName = new InlineLabel();
        FlowPanel jobNCancel = new FlowPanel();
        jobNCancel.add(jobName);
        jobName.setStyleName("pad-right-5");
        this.cancelLink = new Link("(Cancel)", new ClickHandler() {
            public void onClick(ClickEvent event) {
                Widget sender = (Widget) event.getSource();
                cancelJob();
            }
        });
        jobNCancel.add(cancelLink);
        cancellingStatusMessage = new InlineLabel();
        cancellingStatusMessage.setVisible(false);
        jobNCancel.add(cancellingStatusMessage);
        addToGrid("Job", jobNCancel);
        times = new HTML();
        addToGrid("Time", times);
        message = new Label();
        message.setStyleName("message");
        addToGrid("Status", message);
        progress = new FlowPanel();
        progress.setStyleName("progress");
        bar = new FlowPanel();
        bar.setStyleName("bar");
        bar.add(progress);
        addToGrid("Progress", bar);
        grid.setCellSpacing(2);
        fp.add(grid);
        initWidget(fp);
        updateProgress();
        timer = new Timer() {
            boolean checking = false;

            @Override
            public void run() {
                AsyncCallback<JobTracker> callback = new AsyncCallback<JobTracker>() {
                    public void onFailure(Throwable caught) {
                        checking = false;
                        if (maxConnectionFailure-- <= 0) {
                            stopTimer();
                            if (ActionProgress.this.completionCallback != null) {
                                ActionProgress.this.completionCallback.onFailure(caught);
                            }
                            throw new WrappedRuntimeException(caught);
                        }
                    }

                    public void onSuccess(JobTracker info) {
                        checking = false;
                        if (info == null) {
                            info = new JobTrackerImpl();
                            info.setJobName("Unknown job");
                            info.setComplete(true);
                            info.setProgressMessage("---");
                        }
                        if (info.isComplete()) {
                            stopTimer();
                            if (ActionProgress.this.completionCallback != null) {
                                ActionProgress.this.completionCallback.onSuccess(info);
                            }
                        }
                        setJobInfo(info);
                        fireNullPropertyChange("Updated");
                    }
                };
                if (!checking) {
                    ClientBase.getCommonRemoteServiceAsyncInstance().pollJobStatus(id, false, callback);
                    checking = true;
                }
            }
        };
    }

    public void addPropertyChangeListener(PropertyChangeListener listener) {
        this.propertyChangeSupport.addPropertyChangeListener(listener);
    }

    public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {
        this.propertyChangeSupport.addPropertyChangeListener(propertyName, listener);
    }

    public void ensureRunning() {
        if (timer != null && stopped) {
            startTimer();
        }
    }

    public void fireNullPropertyChange(String name) {
        this.propertyChangeSupport.fireNullPropertyChange(name);
    }

    public void firePropertyChange(PropertyChangeEvent evt) {
        this.propertyChangeSupport.firePropertyChange(evt);
    }

    public void firePropertyChange(String propertyName, boolean oldValue, boolean newValue) {
        this.propertyChangeSupport.firePropertyChange(propertyName, oldValue, newValue);
    }

    public void firePropertyChange(String propertyName, int oldValue, int newValue) {
        this.propertyChangeSupport.firePropertyChange(propertyName, oldValue, newValue);
    }

    public void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
        this.propertyChangeSupport.firePropertyChange(propertyName, oldValue, newValue);
    }

    public String getId() {
        return this.id;
    }

    public JobTracker getJobInfo() {
        return info;
    }

    public int getMaxConnectionFailure() {
        return this.maxConnectionFailure;
    }

    @Transient
    public PropertyChangeListener[] getPropertyChangeListeners() {
        return this.propertyChangeSupport.getPropertyChangeListeners();
    }

    public void minimal() {
        CellFormatter cf = grid.getCellFormatter();
        cf.setVisible(0, 0, false);
        cf.setVisible(0, 1, false);
        cf.setVisible(1, 0, false);
        cf.setVisible(1, 1, false);
        fp.addStyleName("minimal");
    }

    public void removePropertyChangeListener(PropertyChangeListener listener) {
        this.propertyChangeSupport.removePropertyChangeListener(listener);
    }

    public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) {
        this.propertyChangeSupport.removePropertyChangeListener(propertyName, listener);
    }

    public void setId(String id) {
        this.id = id;
    }

    public void setJobInfo(JobTracker jobTracker) {
        this.info = jobTracker;
        updateProgress();
    }

    public void setMaxConnectionFailure(int maxConnectionFailure) {
        this.maxConnectionFailure = maxConnectionFailure;
    }

    private void addToGrid(String label, Widget widget) {
        InlineLabel l = new InlineLabel(label + ": ");
        l.setStyleName("caption");
        grid.setWidget(row, 0, l);
        grid.setWidget(row, 1, widget);
        grid.getCellFormatter().setVerticalAlignment(row, 0, HasVerticalAlignment.ALIGN_TOP);
        grid.getCellFormatter().setVerticalAlignment(row, 1, HasVerticalAlignment.ALIGN_TOP);
        row++;
    }

    private void cancelJob() {
        cancelLink.setVisible(false);
        cancellingStatusMessage.setText(" - Cancelling...");
        cancellingStatusMessage.setVisible(true);
        ClientBase.getCommonRemoteServiceAsyncInstance().pollJobStatus(getId(), true,
                new AsyncCallback<JobTracker>() {
                    public void onFailure(Throwable e) {
                        cancellingStatusMessage.setText(" - Error cancelling");
                        throw new WrappedRuntimeException(e);
                    }

                    public void onSuccess(JobTracker result) {
                        cancellingStatusMessage.setText(CANCELLED);
                    }
                });
        return;
    }

    private void startTimer() {
        stopped = false;
        timer.scheduleRepeating(REFRESH_DELAY_MS);
    }

    private void stopTimer() {
        stopped = true;
        timer.cancel();
    }

    private void updateProgress() {
        jobName.setText(info.getJobName());
        String time = info.getStartTime() == null ? ""
                : "Start: " + CommonUtils.formatDate(info.getStartTime(), DateStyle.AU_DATE_TIME_MS);
        if (info.getEndTime() != null) {
            time += "<br>End: " + CommonUtils.formatDate(info.getEndTime(), DateStyle.AU_DATE_TIME_MS);
        }
        times.setHTML(time);
        String msg = info.getProgressMessage();
        if (CommonUtils.isNotNullOrEmpty(info.getSubProgressMessage()) && info.getEndTime() == null) {
            msg += " - " + info.getSubProgressMessage();
        }
        if (info.getJobResultType() == JobResultType.FAIL) {
            msg = info.getJobResult();
            message.addStyleName("error");
        }
        if (!info.isComplete() && cancellingStatusMessage.getText().equals(CANCELLED)) {
            cancellingStatusMessage.setVisible(false);
            cancelLink.setVisible(true);
        }
        message.setText(msg);
        if (info.isComplete()) {
            info.setPercentComplete(Math.max(1.0, info.getPercentComplete()));
        }
        if (isAttached()) {
            progress.setWidth(Math.max(0, ((int) (bar.getOffsetWidth() - 2) * info.getPercentComplete())) + "px");
        }
    }

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

    @Override
    protected void onDetach() {
        stopTimer();
        super.onDetach();
    }
}