blob: 5813c7d4a1c759100d85ebaa8a7f260ade982f26 [file] [log] [blame]
/*
* Copyright (c) 2014, 2015 Ed Merks (Berlin, Germany) 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:
* Ed Merks - initial API and implementation
*/
package org.eclipse.oomph.setup.presentation.handlers;
import org.eclipse.oomph.setup.presentation.SetupEditorPlugin;
import org.eclipse.oomph.setup.ui.SetupPropertyTester;
import org.eclipse.oomph.setup.ui.wizards.ProgressPage;
import org.eclipse.oomph.ui.ButtonAnimator;
import org.eclipse.oomph.ui.UIUtil;
import org.eclipse.oomph.util.OS;
import org.eclipse.oomph.util.ReflectUtil;
import org.eclipse.emf.common.CommonPlugin;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.menus.WorkbenchWindowControlContribution;
import java.lang.reflect.Method;
/**
* @author Ed Merks
*/
public class PerformStatusControl extends WorkbenchWindowControlContribution
{
public PerformStatusControl()
{
}
protected void resetPerforming()
{
SetupPropertyTester.setPerformingShell(null);
SetupPropertyTester.setPerformingStatus(null);
}
@Override
protected Control createControl(final Composite parent)
{
final ToolBar toolBar = new ToolBar(parent, SWT.FLAT | SWT.HORIZONTAL);
final ToolItem toolItem = new ToolItem(toolBar, SWT.CHECK);
toolItem.setImage(SetupEditorPlugin.INSTANCE.getSWTImage("progress0"));
toolItem.addSelectionListener(new SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent e)
{
Shell shell = SetupPropertyTester.getPerformingShell();
if (shell != null)
{
boolean visible = !shell.isVisible();
shell.setVisible(visible);
if (SetupPropertyTester.getPerformingStatus() != null)
{
resetPerforming();
}
if (visible)
{
shell.setFocus();
}
}
}
});
if (OS.INSTANCE.isLinux())
{
toolBar.addControlListener(new ControlAdapter()
{
@Override
public void controlResized(ControlEvent e)
{
parent.pack();
toolBar.removeControlListener(this);
}
});
}
// Create an animator to indicate the a setup is being performed, and to provide feedback once it's done.
final ButtonAnimator buttonAnimator = new ButtonAnimator(SetupEditorPlugin.INSTANCE, toolItem, "progress", 7, true)
{
private boolean done;
private boolean fixed;
@Override
public void run()
{
if (!toolItem.isDisposed())
{
// Fix the position once or when the tool bar isn't visible.
if (!fixed || !toolBar.isVisible())
{
fixed = fixPosition();
}
super.run();
}
}
@Override
public Shell getShell()
{
Shell shell = SetupPropertyTester.getPerformingShell();
if (shell != null && !shell.isDisposed())
{
boolean visible = shell.isVisible();
if (toolItem.getSelection() != visible)
{
toolItem.setSelection(visible);
}
IStatus status = SetupPropertyTester.getPerformingStatus();
if (status == null)
{
// If there is a status, reflect the feedback into the images.
status = (IStatus)shell.getData(ProgressPage.PROGRESS_STATUS);
SetupPropertyTester.setPerformingStatus(status);
if (status != null)
{
String statusImage;
switch (status.getSeverity())
{
case IStatus.OK:
{
statusImage = "progress_success";
delayedDispose(shell);
break;
}
case IStatus.WARNING:
{
statusImage = "progress_warning";
break;
}
case IStatus.ERROR:
{
statusImage = "progress_error";
break;
}
case IStatus.CANCEL:
{
statusImage = "progress_cancel";
delayedDispose(shell);
break;
}
default:
{
statusImage = "progress";
break;
}
}
if (images == null)
{
images = new Image[1 + additionalImages];
}
for (int i = 0; i < images.length; ++i)
{
images[i] = SetupEditorPlugin.INSTANCE.getSWTImage(i >= 4 ? statusImage : "progress");
}
done = true;
}
}
}
return shell;
}
@Override
protected int getQuietCycles()
{
if (done)
{
return 2;
}
return super.getQuietCycles();
}
private void delayedDispose(final Shell shell)
{
UIUtil.timerExec(15000, new Runnable()
{
public void run()
{
if (!toolItem.isDisposed() && !shell.isDisposed() && !shell.isVisible())
{
shell.dispose();
}
}
});
}
@Override
protected boolean doAnimate()
{
// Keep animating once there is a status.
if (SetupPropertyTester.getPerformingStatus() != null)
{
Shell shell = getShell();
if (shell.isVisible())
{
resetPerforming();
}
return true;
}
// When the job is done, reset the performing state to re-enable the menus.
if (Job.getJobManager().find(ProgressPage.PROGRESS_FAMILY).length == 0)
{
resetPerforming();
}
return true;
}
};
buttonAnimator.run();
return toolBar;
}
private boolean fixPosition()
{
IWorkbenchWindow workbenchWindow = getWorkbenchWindow();
try
{
// Use the model service to move the perform status control before the progress bar.
Object model = ReflectUtil.getValue("model", workbenchWindow);
Object modelService = ReflectUtil.getValue("modelService", workbenchWindow);
Class<?> elementClass = CommonPlugin.loadClass("org.eclipse.ui.workbench", "org.eclipse.e4.ui.model.application.ui.MUIElement");
Method findMethod = ReflectUtil.getMethod(modelService.getClass(), "find", String.class, elementClass);
EObject progressBar = (EObject)ReflectUtil.invokeMethod(findMethod, modelService, "org.eclipse.ui.ProgressBar", model);
EObject performStatusBar = (EObject)ReflectUtil.invokeMethod(findMethod, modelService, "org.eclipse.oomph.setup.status", model);
if (progressBar == null)
{
// Try again later.
return false;
}
// Just moving it in the model doesn't update the IDE, so make sure it's definitely added.
@SuppressWarnings("unchecked")
EList<EObject> children = (EList<EObject>)progressBar.eContainer().eGet(progressBar.eContainmentFeature());
children.remove(performStatusBar);
children.add(children.indexOf(progressBar), performStatusBar);
// The layout is needed to ensure the bar is made visible.
workbenchWindow.getShell().layout(true, true);
}
catch (Throwable t)
{
// Ignore.
}
return true;
}
}