| /*=============================================================================# |
| # Copyright (c) 2006, 2021 Stephan Wahlbrink and others. |
| # |
| # This program and the accompanying materials are made available under the |
| # terms of the Eclipse Public License 2.0 which is available at |
| # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 |
| # which is available at https://www.apache.org/licenses/LICENSE-2.0. |
| # |
| # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 |
| # |
| # Contributors: |
| # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation |
| #=============================================================================*/ |
| |
| package org.eclipse.statet.nico.ui.util; |
| |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.core.runtime.jobs.Job; |
| import org.eclipse.debug.core.DebugEvent; |
| import org.eclipse.debug.core.DebugPlugin; |
| import org.eclipse.debug.core.IDebugEventSetListener; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.events.DisposeEvent; |
| import org.eclipse.swt.events.DisposeListener; |
| import org.eclipse.swt.graphics.Image; |
| import org.eclipse.swt.layout.GridData; |
| import org.eclipse.swt.layout.GridLayout; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.Label; |
| import org.eclipse.swt.widgets.ProgressBar; |
| import org.eclipse.ui.progress.WorkbenchJob; |
| |
| import org.eclipse.statet.jcommons.ts.core.ToolRunnable; |
| |
| import org.eclipse.statet.ecommons.ui.components.ShortedLabel; |
| import org.eclipse.statet.ecommons.ui.util.UIAccess; |
| |
| import org.eclipse.statet.internal.nico.ui.NicoUIPlugin; |
| import org.eclipse.statet.nico.core.runtime.IProgressInfo; |
| import org.eclipse.statet.nico.core.runtime.Queue; |
| import org.eclipse.statet.nico.core.runtime.Queue.StateDelta; |
| import org.eclipse.statet.nico.core.runtime.ToolController; |
| import org.eclipse.statet.nico.core.runtime.ToolProcess; |
| import org.eclipse.statet.nico.ui.NicoUI; |
| import org.eclipse.statet.nico.ui.NicoUITools; |
| |
| |
| /** |
| * UI Component showing the progress information of a NICO tool. |
| */ |
| public class ToolProgressGroup { |
| |
| |
| private final static int TOTAL_TICKS= 0xFFFF; |
| |
| |
| private static final IProgressInfo DUMMY_INFO= new IProgressInfo() { |
| @Override |
| public String getLabel() { |
| return ""; //$NON-NLS-1$ |
| } |
| @Override |
| public String getSubLabel() { |
| return ""; //$NON-NLS-1$ |
| } |
| @Override |
| public double getWorked() { |
| return 0; |
| } |
| @Override |
| public ToolRunnable getRunnable() { |
| return null; |
| } |
| }; |
| |
| |
| private static final int SCHEDULE_ON_EVENT= 50; |
| private static final int SCHEDULE_DEFAULT= 150; |
| |
| |
| private class RefreshJob extends WorkbenchJob { |
| |
| RefreshJob() { |
| super("ToolProgress Refresh"); //$NON-NLS-1$ |
| setSystem(true); |
| } |
| |
| @Override |
| public IStatus runInUIThread(final IProgressMonitor monitor) { |
| internalRefresh(); |
| |
| final ToolInfo info= ToolProgressGroup.this.toolInfo; |
| if (info.scheduleRefresh) { |
| schedule(SCHEDULE_DEFAULT); |
| } |
| |
| return Status.OK_STATUS; |
| } |
| } |
| |
| private class DebugEventListener implements IDebugEventSetListener { |
| |
| @Override |
| public void handleDebugEvents(final DebugEvent[] events) { |
| final ToolInfo info= ToolProgressGroup.this.toolInfo; |
| if (info.process != null) { |
| for (final DebugEvent event : events) { |
| if (event.getSource() == info.process.getQueue()) { |
| if (Queue.isStateChange(event)) { |
| final StateDelta delta= ((Queue.StateDelta) event.getData()); |
| info.scheduleRefresh= (delta.newState == Queue.PROCESSING_STATE); |
| ToolProgressGroup.this.refreshJob.schedule(SCHEDULE_ON_EVENT); |
| } |
| } |
| } |
| } |
| } |
| |
| } |
| |
| private static class ToolInfo { |
| |
| final ToolProcess process; |
| |
| Image imageCache; |
| |
| boolean scheduleRefresh= false; |
| |
| ToolInfo(final ToolProcess process) { |
| this.process= process; |
| if (process != null) { |
| this.scheduleRefresh= process.getToolStatus().isRunning(); |
| } |
| else { |
| this.scheduleRefresh= false; |
| } |
| } |
| |
| } |
| |
| |
| private final DebugEventListener debugEventListener; |
| private final Job refreshJob; |
| |
| private Composite composite; |
| private Label imageLabel; |
| private ShortedLabel mainLabel; |
| private ProgressBar progressBar; |
| private ShortedLabel subLabel; |
| |
| private ToolInfo toolInfo= new ToolInfo(null); |
| |
| |
| /** |
| * Creates a new group |
| * |
| * @param parent the parent composite |
| */ |
| public ToolProgressGroup(final Composite parent) { |
| this.debugEventListener= new DebugEventListener(); |
| this.refreshJob= new RefreshJob(); |
| |
| createControls(parent); |
| |
| final DebugPlugin manager= DebugPlugin.getDefault(); |
| if (manager != null) { |
| manager.addDebugEventListener(this.debugEventListener); |
| } |
| } |
| |
| |
| private void createControls(final Composite parent) { |
| this.composite= new Composite(parent, SWT.NONE); |
| this.composite.addDisposeListener(new DisposeListener() { |
| @Override |
| public void widgetDisposed(final DisposeEvent e) { |
| ToolProgressGroup.this.dispose(); |
| } |
| }); |
| final GridLayout layout= new GridLayout(2, false); |
| layout.marginHeight= 0; |
| layout.marginWidth= 2; |
| layout.verticalSpacing= 2; |
| this.composite.setLayout(layout); |
| |
| this.imageLabel= new Label(this.composite, SWT.NONE); |
| GridData gd= new GridData(SWT.LEFT, SWT.TOP, false, false); |
| gd.verticalSpan= 2; |
| gd.verticalIndent= 2; |
| gd.widthHint= 16; |
| gd.heightHint= 16; |
| this.imageLabel.setLayoutData(gd); |
| |
| this.mainLabel= new ShortedLabel(this.composite, SWT.NONE); |
| this.mainLabel.getControl().setLayoutData( |
| new GridData(SWT.FILL, SWT.CENTER, true, false)); |
| |
| this.subLabel= new ShortedLabel(this.composite, SWT.NONE); |
| gd= new GridData(SWT.FILL, SWT.CENTER, true, false); |
| this.subLabel.getControl().setLayoutData(gd); |
| |
| this.progressBar= new ProgressBar(this.composite, SWT.HORIZONTAL); |
| this.progressBar.setMinimum(0); |
| this.progressBar.setMaximum(TOTAL_TICKS); |
| gd= new GridData(SWT.FILL, SWT.CENTER, true, false); |
| gd.horizontalSpan= 2; |
| this.progressBar.setLayoutData(gd); |
| } |
| |
| public Control getControl() { |
| return this.composite; |
| } |
| |
| |
| public void setTool(final ToolProcess tool, final boolean directRefresh) { |
| this.toolInfo= new ToolInfo(tool); |
| refresh(directRefresh); |
| } |
| |
| /** |
| * Refreshes the components. |
| * |
| * If <code>directRefresh</code> is requested, you have to be in UI thread. |
| * |
| * @param directRefresh refresh is directly executed instead of scheduled. |
| */ |
| public void refresh(final boolean directRefresh) { |
| if (directRefresh) { |
| this.refreshJob.cancel(); |
| internalRefresh(); |
| this.refreshJob.schedule(SCHEDULE_DEFAULT); |
| } |
| else { |
| this.refreshJob.schedule(SCHEDULE_ON_EVENT); |
| } |
| } |
| |
| private void internalRefresh() { |
| if (!UIAccess.isOkToUse(this.composite)) { |
| return; |
| } |
| final ToolInfo info= this.toolInfo; |
| final ToolController controller= (info.process != null) ? info.process.getController() : null; |
| final IProgressInfo progressInfo= (controller != null) ? controller.getProgressInfo() : DUMMY_INFO; |
| Image image= null; |
| final ToolRunnable runnable= progressInfo.getRunnable(); |
| if (runnable != null) { |
| image= NicoUITools.getImage(runnable); |
| } |
| if (image == null && info.process != null) { |
| image= getToolImage(info); |
| } |
| if (image == null) { |
| image= NicoUIPlugin.getInstance().getImageRegistry().get(NicoUI.OBJ_TASK_DUMMY_IMAGE_ID); |
| } |
| if (!(image.equals(this.imageLabel.getImage()))) { |
| this.imageLabel.setImage(image); |
| } |
| this.mainLabel.setText(progressInfo.getLabel()); |
| this.subLabel.setText(progressInfo.getSubLabel()); |
| this.progressBar.setSelection((int) (Math.max(progressInfo.getWorked(), 0) * TOTAL_TICKS)); |
| } |
| |
| private Image getToolImage(final ToolInfo tool) { |
| if (tool.imageCache == null) { |
| tool.imageCache= NicoUITools.getImage(tool.process); |
| } |
| return tool.imageCache; |
| } |
| |
| private void dispose() { |
| this.toolInfo= new ToolInfo(null); |
| this.refreshJob.cancel(); |
| final DebugPlugin manager= DebugPlugin.getDefault(); |
| if (manager != null) { |
| manager.removeDebugEventListener(this.debugEventListener); |
| } |
| } |
| |
| } |