package com.python.pydev.debug.actions; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Rectangle; 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.Display; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; import org.python.pydev.shared_core.io.ThreadStreamReader; /** * This is the window used to handle a process. Currently specific to google app engine (could be more customizable * if needed). */ public class ShowProcessOutputDialog extends Dialog { private static final int NUMBER_OF_COLUMNS = 2; protected Text output; //only while running private ThreadStreamReader err; private ThreadStreamReader std; private volatile boolean disposed = false; /** * We need to set the shell style to be resizable. * @param o1 */ public ShowProcessOutputDialog(Shell parentShell, final Process process) { super(parentShell); setShellStyle(getShellStyle() | SWT.RESIZE); std = new ThreadStreamReader(process.getInputStream()); err = new ThreadStreamReader(process.getErrorStream()); std.start(); err.start(); parentShell.getDisplay().timerExec(250, new Runnable() { @Override public void run() { // Will run in UI thread, so, no need for locking. if (disposed) { std.stopGettingOutput(); err.stopGettingOutput(); return; } try { int exitValue = process.exitValue(); String stdout = std.getAndClearContents(); String stderr = err.getAndClearContents(); output.append(stdout); output.append(stderr); output.append("Process finished with exitValue: " + exitValue); } catch (Exception e) { //still hasn't exited: get outputs String stdout = std.getAndClearContents(); String stderr = err.getAndClearContents(); output.append(stdout); output.append(stderr); Display.getCurrent().timerExec(250, this); } } }); } @Override protected void configureShell(final Shell shell) { super.configureShell(shell); shell.setText("Process output"); } /** * Create the dialog contents */ @Override protected Control createDialogArea(Composite parent) { Composite top = (Composite) super.createDialogArea(parent); Composite composite = new Composite(top, SWT.None); composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); composite.setLayout(new GridLayout(NUMBER_OF_COLUMNS, false)); //--- main output output = new Text(composite, SWT.MULTI | SWT.BORDER | SWT.V_SCROLL | SWT.WRAP | SWT.READ_ONLY); GridData gridData = new GridData(GridData.FILL_BOTH); gridData.horizontalSpan = NUMBER_OF_COLUMNS; gridData.grabExcessHorizontalSpace = true; gridData.grabExcessVerticalSpace = true; output.setLayoutData(gridData); return top; } @Override protected void constrainShellSize() { Shell shell = getShell(); shell.setSize(640, 480); // Move the dialog to the center of the top level shell. Rectangle shellBounds = getParentShell().getBounds(); shell.setLocation(shellBounds.x + (shellBounds.width - 640) / 2, shellBounds.y + (shellBounds.height - 480) / 2); super.constrainShellSize(); } @Override protected void createButtonsForButtonBar(Composite parent) { createButton(parent, IDialogConstants.OK_ID, "Close", true); } @Override public int open() { try { return super.open(); } finally { disposed = true; std.stopGettingOutput(); err.stopGettingOutput(); } } }