/*=============================================================================# # Copyright (c) 2006-2016 Stephan Wahlbrink (WalWare.de) 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: # Stephan Wahlbrink - initial API and implementation #=============================================================================*/ package de.walware.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 de.walware.ecommons.ts.IToolRunnable; import de.walware.ecommons.ui.components.ShortedLabel; import de.walware.ecommons.ui.util.UIAccess; import de.walware.statet.nico.core.runtime.IProgressInfo; import de.walware.statet.nico.core.runtime.Queue; import de.walware.statet.nico.core.runtime.Queue.StateDelta; import de.walware.statet.nico.core.runtime.ToolController; import de.walware.statet.nico.core.runtime.ToolProcess; import de.walware.statet.nico.internal.ui.NicoUIPlugin; import de.walware.statet.nico.ui.NicoUI; import de.walware.statet.nico.ui.NicoUITools; /** * UI Component showing the progress information of a NICO tool. */ public class ToolProgressGroup { 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 int getWorked() { return 0; } @Override public IToolRunnable 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(); if (ToolProgressGroup.this.toolInfo.scheduleRefresh) { schedule(SCHEDULE_DEFAULT); } return Status.OK_STATUS; } } private class DebugEventListener implements IDebugEventSetListener { @Override public void handleDebugEvents(final DebugEvent[] events) { final ToolInfo tool= ToolProgressGroup.this.toolInfo; for (final DebugEvent event : events) { if (event.getSource() == tool.process.getQueue()) { if (Queue.isStateChange(event)) { final StateDelta delta= ((Queue.StateDelta) event.getData()); tool.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(IToolRunnable.TOTAL_WORK); 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 tool= this.toolInfo; final ToolController controller= (tool.process != null) ? tool.process.getController() : null; final IProgressInfo info= (controller != null) ? controller.getProgressInfo() : DUMMY_INFO; Image image= null; final IToolRunnable runnable= info.getRunnable(); if (runnable != null) { image= NicoUITools.getImage(runnable); } if (image == null && tool.process != null) { image= getToolImage(tool); } if (image == null) { image= NicoUIPlugin.getDefault().getImageRegistry().get(NicoUI.OBJ_TASK_DUMMY_IMAGE_ID); } if (!(image.equals(this.imageLabel.getImage()))) { this.imageLabel.setImage(image); } this.mainLabel.setText(info.getLabel()); this.subLabel.setText(info.getSubLabel()); this.progressBar.setSelection(info.getWorked()); } 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); } } }