text: /*******************************************************************************
   * Copyright (c) 2007, 2018 Wind River Systems, Inc. and others.
   * All rights reserved. This program and the accompanying materials
   * are made available under the terms of the Eclipse Public License 2.0
   * which accompanies this distribution, and is available at
   * https://www.eclipse.org/legal/epl-2.0/
   *
   * Contributors:
   * Michael Scharf (Wind River) - initial API and implementation
   *******************************************************************************/
  package org.eclipse.tm.internal.terminal.test.ui;
  
  import java.io.File;
  import java.util.ArrayList;
  import java.util.Iterator;
  import java.util.List;
  
  import org.eclipse.swt.SWT;
  import org.eclipse.swt.events.SelectionAdapter;
  import org.eclipse.swt.events.SelectionEvent;
  import org.eclipse.swt.layout.GridData;
  import org.eclipse.swt.layout.GridLayout;
  import org.eclipse.swt.layout.RowData;
  import org.eclipse.swt.layout.RowLayout;
  import org.eclipse.swt.widgets.Button;
  import org.eclipse.swt.widgets.Composite;
  import org.eclipse.swt.widgets.Control;
  import org.eclipse.swt.widgets.Display;
  import org.eclipse.swt.widgets.Label;
  import org.eclipse.swt.widgets.Shell;
  import org.eclipse.swt.widgets.Text;
  import org.eclipse.tm.internal.terminal.textcanvas.ITextCanvasModel;
  import org.eclipse.tm.internal.terminal.textcanvas.PollingTextCanvasModel;
  import org.eclipse.tm.internal.terminal.textcanvas.TextCanvas;
  import org.eclipse.tm.internal.terminal.textcanvas.TextLineRenderer;
  import org.eclipse.tm.terminal.model.ITerminalTextData;
  import org.eclipse.tm.terminal.model.ITerminalTextDataSnapshot;
  import org.eclipse.tm.terminal.model.TerminalTextDataFactory;
  
  /**
   * adjust columns when table gets resized....
   *
   */
  public class TerminalTextUITest {
  	static TextCanvas fgTextCanvas;
  	static ITextCanvasModel fgModel;
  	static ITerminalTextData fTerminalModel;
  	static Label fStatusLabel;
  	static volatile int fHeight;
  	static volatile int fWidth;
  	static DataReader fDataReader;
  	static List fDataReaders = new ArrayList();
  	private static Text heightText;
  
  	static class Status implements IStatus {
  		@Override
  		public void setStatus(final String s) {
  			if (!fStatusLabel.isDisposed())
  				Display.getDefault().asyncExec(() -> {
  					if (!fStatusLabel.isDisposed())
  						fStatusLabel.setText(s);
  				});
  		}
  
  	}
  
  	public static void main(String[] args) {
  		Display display = new Display();
  		Shell shell = new Shell(display);
  		shell.setLayout(new GridLayout());
  		Composite composite = new Composite(shell, SWT.NONE);
  		composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
  		RowLayout layout = new RowLayout(SWT.HORIZONTAL);
  		layout.wrap = true;
  		layout.fill = false;
  		fTerminalModel = TerminalTextDataFactory.makeTerminalTextData();
  		fHeight = 24;
  		fWidth = 80;
  		fTerminalModel.setDimensions(fHeight, fWidth);
  		fTerminalModel.setMaxHeight(fHeight);
  		ITerminalTextDataSnapshot snapshot = fTerminalModel.makeSnapshot();
  		// TODO how to get the initial size correctly!
  		snapshot.updateSnapshot(false);
  		fgModel = new PollingTextCanvasModel(snapshot);
  		fgTextCanvas = new TextCanvas(shell, fgModel, SWT.NONE, new TextLineRenderer(fgTextCanvas, fgModel));
  		fgTextCanvas.setLayoutData(new GridData(GridData.FILL_BOTH));
  
  		composite.setLayout(layout);
  		addAutorevealCursorButton(composite);
  		Text maxHeightText = addMaxHeightInput(composite);
  		addHeightInput(composite, maxHeightText);
  		addWidthText(composite);
  		Text throttleText = addThrottleText(composite);
  
  		IStatus status = new Status();
  		DataReader reader = new DataReader("Line Count", fTerminalModel, new LineCountingDataSource(), status);
  		addDataReader(composite, reader);
  		reader = new DataReader("Fast", fTerminalModel, new FastDataSource(), status);
  		addDataReader(composite, reader);
  		reader = new DataReader("Colors", fTerminalModel, new VT100DataSource(), status);
  		addDataReader(composite, reader);
  		reader = new DataReader("Random", fTerminalModel, new RandomDataSource(), status);
  		addDataReader(composite, reader);
  		for (int i = 0; i < args.length; i++) {
  			File file = new File(args[i]);
  			reader = new DataReader(file.getName(), fTerminalModel, new VT100DataSource(args[i]), status);
  			addDataReader(composite, reader);
  		}
  		addStopAllButton(composite, reader);
  
  		fStatusLabel = new Label(shell, SWT.NONE);
  		fStatusLabel.setLayoutData(new GridData(250, 15));
  		throttleText.setText("100");
  		setThrottleForAll(100);
  
  		if (args.length == 0)
  			addLabel(composite, "[Files can be added via commandline]");
  		shell.setSize(600, 300);
  		shell.open();
  		while (!shell.isDisposed()) {
  			if (!display.readAndDispatch())
  				display.sleep();
  		}
  		display.dispose();
  	}
  
  	private static Text addMaxHeightInput(Composite composite) {
  		addLabel(composite, "maxHeight:");
  		final Text maxHeightText = new Text(composite, SWT.BORDER);
  		setLayoutData(maxHeightText, 30);
  		maxHeightText.addModifyListener(e -> {
  			synchronized (fTerminalModel) {
  				int height = textToInt(maxHeightText);
  				if (height < 1)
  					return;
  				if (fTerminalModel.getHeight() > height) {
  					fTerminalModel.scroll(0, fTerminalModel.getHeight(), height - fTerminalModel.getHeight());
  					fTerminalModel.setDimensions(height, fTerminalModel.getWidth());
  					heightText.setText(height + "");
  				}
  				fTerminalModel.setMaxHeight(height);
  			}
  		});
  		maxHeightText.setText(fHeight + "");
  		return maxHeightText;
  	}
  
  	private static void addHeightInput(Composite composite, final Text maxHeightText) {
  		addLabel(composite, "heigth:");
  		heightText = new Text(composite, SWT.BORDER);
  		setLayoutData(heightText, 30);
  		heightText.addModifyListener(e -> {
  			synchronized (fTerminalModel) {
  				int height = textToInt(heightText);
  				if (height < 1)
  					return;
  				maxHeightText.setText("" + height);
  				fTerminalModel.setDimensions(height, fTerminalModel.getWidth());
  				fTerminalModel.setMaxHeight(height);
  			}
  		});
  		heightText.setText(fHeight + "");
  	}
  
  	private static Text addWidthText(Composite composite) {
  		addLabel(composite, "width:");
  		final Text widthText = new Text(composite, SWT.BORDER);
  		setLayoutData(widthText, 30);
  		widthText.addModifyListener(e -> {
  			synchronized (fTerminalModel) {
  				int width = textToInt(widthText);
  				if (width > 1)
  					fTerminalModel.setDimensions(fTerminalModel.getHeight(), width);
  			}
  		});
  		widthText.setText(fWidth + "");
  		return widthText;
  	}
  
  	private static Text addThrottleText(Composite composite) {
  		addLabel(composite, "throttle:");
  		final Text throttleText = new Text(composite, SWT.BORDER);
  		setLayoutData(throttleText, 30);
  		throttleText.addModifyListener(e -> {
  			synchronized (fTerminalModel) {
  				int throttle = textToInt(throttleText);
  				setThrottleForAll(throttle);
  			}
  		});
  		return throttleText;
  	}
  
  	private static void addStopAllButton(Composite composite, DataReader reader) {
  		final Button stopAllButton = new Button(composite, SWT.CHECK);
  		stopAllButton.setText("Stop ALL");
  		stopAllButton.addSelectionListener(new SelectionAdapter() {
  
  			@Override
  			public void widgetSelected(SelectionEvent e) {
  				boolean stop = stopAllButton.getSelection();
  				for (Iterator iterator = fDataReaders.iterator(); iterator.hasNext();) {
  					DataReader reader = (DataReader) iterator.next();
  					reader.setStop(stop);
  
  				}
  			}
  		});
  		stopAllButton.setSelection(reader.isStart());
  	}
  
  	private static void addAutorevealCursorButton(Composite composite) {
  		final Button button = new Button(composite, SWT.CHECK);
  		button.setText("ScrollLock");
  		button.addSelectionListener(new SelectionAdapter() {
  			@Override
  			public void widgetSelected(SelectionEvent e) {
  				boolean scrollLock = button.getSelection();
  				fgTextCanvas.setScrollLock(scrollLock);
  			}
  		});
  		button.setSelection(fgTextCanvas.isScrollLock());
  	}
  
  	private static void addLabel(Composite composite, String message) {
  		Label label;
  		label = new Label(composite, SWT.NONE);
  		label.setText(message);
  	}
  
  	private static void addDataReader(Composite composite, final DataReader reader) {
  		fDataReaders.add(reader);
  		final Button button = new Button(composite, SWT.CHECK);
  		button.setText(reader.getName());
  		button.addSelectionListener(new SelectionAdapter() {
  
  			@Override
  			public void widgetSelected(SelectionEvent e) {
  				reader.setStart(button.getSelection());
  			}
  		});
  		button.setSelection(reader.isStart());
  
  	}
  
  	static private void setThrottleForAll(int throttle) {
  		for (Iterator iterator = fDataReaders.iterator(); iterator.hasNext();) {
  			DataReader reader = (DataReader) iterator.next();
  			reader.setThrottleTime(throttle);
  		}
  	}
  
  	static void setLayoutData(Control c, int width) {
  		c.setLayoutData(new RowData(width, -1));
  	}
  
  	static int textToInt(Text text) {
  		try {
  			return Integer.valueOf(text.getText()).intValue();
  		} catch (Exception ex) {
  			return 0;
  		}
  	}
  }
  