1 /******************************************************************************* 2 * Copyright (c) 2007, 2020 IBM Corporation and others. 3 * 4 * This program and the accompanying materials 5 * are made available under the terms of the Eclipse Public License 2.0 6 * which accompanies this distribution, and is available at 7 * https://www.eclipse.org/legal/epl-2.0/ 8 * 9 * SPDX-License-Identifier: EPL-2.0 10 * 11 * Contributors: 12 * IBM Corporation - initial API and implementation 13 * Alexander Fedorov <alexander.fedorov@arsysop.ru> - ongoing support 14 *******************************************************************************/ 15 16 package org.eclipse.ui.internal.views.markers; 17 18 import java.lang.reflect.InvocationTargetException; 19 import java.util.Collection; 20 import java.util.Map; 21 import java.util.Objects; 22 import java.util.Optional; 23 import java.util.function.Consumer; 24 25 import org.eclipse.core.resources.IMarker; 26 import org.eclipse.core.runtime.IProgressMonitor; 27 import org.eclipse.e4.ui.internal.workspace.markers.Translation; 28 import org.eclipse.jface.operation.IRunnableWithProgress; 29 import org.eclipse.jface.viewers.StructuredViewer; 30 import org.eclipse.jface.wizard.Wizard; 31 import org.eclipse.swt.widgets.Control; 32 import org.eclipse.swt.widgets.Display; 33 import org.eclipse.ui.IMarkerResolution; 34 import org.eclipse.ui.internal.ide.IDEInternalWorkbenchImages; 35 import org.eclipse.ui.views.markers.WorkbenchMarkerResolution; 36 import org.eclipse.ui.views.markers.internal.MarkerMessages; 37 38 /** 39 * QuickFixWizard is the wizard for quick fixes. 40 * 41 * @since 3.4 42 * 43 */ 44 class QuickFixWizard extends Wizard { 45 46 private IMarker[] selectedMarkers; 47 private Map<IMarkerResolution, Collection<IMarker>> resolutionMap; 48 private String description; 49 private final Consumer<StructuredViewer> showMarkers; 50 private final Consumer<Control> bindHelp; 51 private final Consumer<Throwable> reporter; 52 private QuickFixPage quickFixPage; 53 54 /** 55 * Create the wizard with the map of resolutions. 56 * 57 * @param description the description of the problem 58 * @param selectedMarkers the markers that were selected 59 * @param resolutions Map key {@link IMarkerResolution} value 60 * {@link IMarker} [] 61 * @param showMarkers the consumer to show markers 62 * @param bindHelp the consumer to bind help system 63 * @param reporter used to report failures during 64 * {@link Wizard#performFinish()} call 65 */ QuickFixWizard(String description, IMarker[] selectedMarkers, Map<IMarkerResolution, Collection<IMarker>> resolutions, Consumer<StructuredViewer> showMarkers, Consumer<Control> bindHelp, Consumer<Throwable> reporter)66 public QuickFixWizard(String description, IMarker[] selectedMarkers, 67 Map<IMarkerResolution, Collection<IMarker>> resolutions, Consumer<StructuredViewer> showMarkers, 68 Consumer<Control> bindHelp, 69 Consumer<Throwable> reporter) { 70 Objects.requireNonNull(reporter); 71 this.selectedMarkers= selectedMarkers; 72 this.resolutionMap = resolutions; 73 this.description = description; 74 this.showMarkers = showMarkers; 75 this.bindHelp = bindHelp; 76 this.reporter = reporter; 77 setDefaultPageImageDescriptor(IDEInternalWorkbenchImages 78 .getImageDescriptor(IDEInternalWorkbenchImages.IMG_DLGBAN_QUICKFIX_DLG)); 79 setNeedsProgressMonitor(true); 80 } 81 82 @Override addPages()83 public void addPages() { 84 quickFixPage = new QuickFixPage(description, selectedMarkers, resolutionMap, showMarkers, bindHelp); 85 addPage(quickFixPage); 86 } 87 88 @Override performFinish()89 public boolean performFinish() { 90 Optional<IMarkerResolution> resolution = quickFixPage.getSelectedMarkerResolution(); 91 if (!resolution.isPresent()) { 92 return true; // for backward compatibility 93 } 94 final IMarker[] markers = quickFixPage.getCheckedMarkers(); 95 if (markers.length == 0) { 96 return true; // for backward compatibility 97 } 98 IRunnableWithProgress finishRunnable = monitor -> processResolution(resolution.get(), markers, monitor); 99 try { 100 getContainer().run(false, true, finishRunnable); 101 } catch (InvocationTargetException | InterruptedException e) { 102 reporter.accept(e); 103 return false; 104 } 105 return true; 106 } 107 108 /** 109 * Runs the resolution in UI thread. It should be in UI because a lot of 110 * resolutions expect to be executed in the UI thread at the moment. We can 111 * think about some interface to mark resolutions that are ready to be executed 112 * outside of the UI thread. 113 * 114 * @param resolution the resolution to run 115 * @param markers the array of markers to resolve 116 * @param monitor progress callback 117 */ processResolution(final IMarkerResolution resolution, final IMarker[] markers, IProgressMonitor monitor)118 private void processResolution(final IMarkerResolution resolution, final IMarker[] markers, 119 IProgressMonitor monitor) { 120 monitor.beginTask(MarkerMessages.MarkerResolutionDialog_Fixing, markers.length); 121 ensureRepaint(); 122 if (resolution instanceof WorkbenchMarkerResolution) { 123 ((WorkbenchMarkerResolution) resolution).run(markers, monitor); 124 } else { 125 Translation translation = new Translation(); 126 for (IMarker marker : markers) { 127 ensureRepaint(); 128 if (monitor.isCanceled()) { 129 return; 130 } 131 monitor.subTask(translation.message(marker).orElse("")); //$NON-NLS-1$ 132 resolution.run(marker); 133 monitor.worked(1); 134 } 135 } 136 } 137 138 /** 139 * org.eclipse.jface.wizard.ProgressMonitorPart needs to take a breath 140 */ ensureRepaint()141 private void ensureRepaint() { 142 final Display display = getShell().getDisplay(); 143 boolean dispatch = true; 144 while (dispatch) { 145 dispatch = display.readAndDispatch(); 146 } 147 } 148 149 } 150