| /* |
| * 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; |
| } |
| } |