/******************************************************************************* * Copyright (c) 2007, 2014 compeople AG and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * compeople AG - initial API and implementation *******************************************************************************/ package org.eclipse.riena.ui.swt.uiprocess; import org.osgi.service.log.LogService; import org.eclipse.core.runtime.Assert; import org.eclipse.equinox.log.Logger; import org.eclipse.jface.window.Window; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.ProgressBar; import org.eclipse.swt.widgets.Shell; import org.eclipse.riena.core.Log4r; import org.eclipse.riena.core.util.ListenerList; import org.eclipse.riena.core.util.StringUtils; import org.eclipse.riena.ui.swt.utils.IPropertyNameProvider; /** * Control for showing a progress or process info window. */ public class UIProcessControl implements IProgressControl, IPropertyNameProvider { private final static Logger logger = Log4r.getLogger(UIProcessControl.class); private static final int UPDATE_DELAY = 200; private boolean processing; // the jface window private UIProcessWindow processWindow; private final ListenerList<ICancelListener> cancelListeners = new ListenerList<ICancelListener>( ICancelListener.class); private ProcessUpdateThread processUpdateThread; private String name; private Rectangle initBounds; public UIProcessControl(final Shell parentShell) { Assert.isNotNull(parentShell); createProcessWindow(parentShell); } private void createProcessWindow(final Shell parentShell) { // create window processWindow = new UIProcessWindow(parentShell, this); // observe window processWindow.addProcessWindowListener(new IProcessWindowListener() { public void windowAboutToClose() { stopProcessing(); fireCanceled(true); } }); } /** * @return the {@link Window} */ public Window getWindow() { return processWindow; } /** * open the Jface Window */ private void showWindow() { processWindow.openWindow(); } /** * close the window */ public void stop() { closeWindow(); } private void closeWindow() { // stop update thread stopProcessing(); // close AppWindow processWindow.closeWindow(); } /** * * @return true if the window is in processing state */ protected synchronized boolean isProcessing() { return processing; } public synchronized void setProcessing(final boolean processing) { this.processing = processing; } /* * (non-Javadoc) * * @see org.eclipse.riena.ui.swt.uiprocess.IProgressControl#showProcessing() */ public void showProcessing() { startProcessing(); } /** * technical implementation of progressing in the window */ private void startProcessing() { // only if not already processing if (!isProcessing()) {// use the synched way.. setProcessing(true); if (null != getProgressBar() && !getProgressBar().isDisposed()) { getProgressBar().setMaximum(100); } if (null != getPercentControl() && !getPercentControl().isDisposed()) { getPercentControl().setText(""); //$NON-NLS-1$ } if (processUpdateThread == null || !processUpdateThread.isAlive()) { startUpdateThread(); } } } /* * starts the update thread needed in conjunction with the progressing state * to visualize some activity */ private void startUpdateThread() { processUpdateThread = new ProcessUpdateThread(); processUpdateThread.start(); } /** * This Thread is used to visualize "progressing" */ private final class ProcessUpdateThread extends Thread { @Override public void run() { setPriority(Thread.MAX_PRIORITY); setName("ProcessUpdateThread"); //$NON-NLS-1$ processUpdateLoop(); } } /* * called by a worker thread used to visualize progressing activity */ private void processUpdateLoop() { final int[] selection = new int[] { 0 }; while (isProcessing()) { if (selection[0] <= 100) { selection[0] += 10; } else { selection[0] = 0; } if (null != getProgressBar() && !getProgressBar().isDisposed()) { getProgressBar().getDisplay().asyncExec(new Runnable() { public void run() { if (!getProgressBar().isDisposed()) { if (isProcessing()) { getProgressBar().setSelection(selection[0]); } } } }); } try { Thread.sleep(UPDATE_DELAY); } catch (final InterruptedException e) { logger.log(LogService.LOG_ERROR, e.getMessage(), e); } } } /* * returns the progressbar of the window */ private ProgressBar getProgressBar() { return processWindow.getProgressBar(); } /* * (non-Javadoc) * * @see * org.eclipse.riena.ui.swt.uiprocess.IProgressControl#showProgress(int, * int) */ public void showProgress(final int value, final int maxValue) { if (maxValue <= 0) { return; } stopProcessing(); final int percentValue = calcSelection(value, maxValue); if (getWindow().getShell() != null && !getWindow().getShell().isDisposed()) { getPercentControl().setText(String.valueOf(percentValue) + " %"); //$NON-NLS-1$ getProgressBar().setSelection(percentValue); } } private Label getPercentControl() { return processWindow.getPercent(); } private int calcSelection(final int value, final int maxValue) { final double v = (double) value / (double) maxValue * 100; return (int) v; } private void stopProcessing() { setProcessing(false); } public void start() { // open the ui showWindow(); } public void setDescription(final String text) { processWindow.setDescription(text); } /** * @since 4.0 */ public String getDescription() { final String text = processWindow.getDescription().getText(); if (text == null) { return ""; //$NON-NLS-1$ } return text; } public void setTitle(final String text) { final Shell shell = processWindow.getShell(); if (!StringUtils.equals(text, shell.getText())) { shell.setText(text); final Rectangle bounds = shell.getBounds(); shell.redraw(0, 0, bounds.width, bounds.height, true); } } /** * add an {@link ICancelListener} to be notified about cancel events. */ public void addCancelListener(final ICancelListener listener) { cancelListeners.add(listener); } public void removeCancelListener(final ICancelListener listener) { cancelListeners.remove(listener); } /** * notify listener * * @param windowClosing */ protected void fireCanceled(final boolean windowClosing) { for (final ICancelListener listener : cancelListeners.getListeners()) { listener.canceled(windowClosing); } } /* * (non-Javadoc) * * @see * org.eclipse.riena.ui.swt.utils.IPropertyNameProvider#getPropertyName() */ public String getPropertyName() { return name; } /* * (non-Javadoc) * * @see * org.eclipse.riena.ui.swt.utils.IPropertyNameProvider#setPropertyName( * java.lang.String) */ public void setPropertyName(final String propertyName) { this.name = propertyName; } /** * @param sets * the cancelButton of the {@link UIProcessWindow} visible/hidden * @since 3.0 */ public void setCancelVisible(final boolean cancelVisible) { processWindow.setCancelVisible(cancelVisible); } /** * @param sets * the cancelButton of the {@link UIProcessWindow} * enabled/disabled * @since 3.0 */ public void setCancelEnabled(final boolean cancelEnabled) { processWindow.setCancelEnabled(cancelEnabled); } /** * @since 4.0 */ public void pack() { if (initBounds == null) { final Shell shell = getWindow().getShell(); shell.pack(); final Rectangle bounds = shell.getBounds(); final Rectangle constrainedShellBounds = getConstrainedShellBounds(bounds); if (!bounds.equals(constrainedShellBounds)) { shell.setBounds(constrainedShellBounds); shell.layout(); } initBounds = shell.getBounds(); } } /** * @since 4.0 */ protected Rectangle getConstrainedShellBounds(final Rectangle preferredSize) { final Rectangle result = new Rectangle(preferredSize.x, preferredSize.y, preferredSize.width, preferredSize.height); final Shell shell = getWindow().getShell(); final Rectangle bounds = shell.getMonitor().getClientArea(); bounds.x += 10; bounds.y += 10; bounds.height -= 20; bounds.width -= 20; if (result.height > bounds.height) { result.height = bounds.height; } if (result.width > bounds.width) { result.width = bounds.width; } result.x = Math.max(bounds.x, Math.min(result.x, bounds.x + bounds.width - result.width)); result.y = Math.max(bounds.y, Math.min(result.y, bounds.y + bounds.height - result.height)); return result; } }