| /*=============================================================================# |
| # Copyright (c) 2009, 2019 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.internal.nico.ui.console; |
| |
| import org.eclipse.jface.text.AbstractDocument; |
| import org.eclipse.jface.text.DocumentEvent; |
| import org.eclipse.jface.text.IDocument; |
| import org.eclipse.jface.text.IDocumentExtension4; |
| import org.eclipse.jface.text.IDocumentListener; |
| import org.eclipse.swt.custom.StyledText; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Display; |
| import org.eclipse.ui.console.TextConsole; |
| import org.eclipse.ui.console.TextConsoleViewer; |
| |
| import org.eclipse.statet.ecommons.ui.util.UIAccess; |
| |
| |
| public class OutputViewer extends TextConsoleViewer { |
| |
| |
| /** |
| * will always scroll with output if value is true. |
| */ |
| private boolean autoScroll= true; |
| |
| private IDocumentListener documentListener; |
| |
| |
| public OutputViewer(final Composite parent, final TextConsole console) { |
| super(parent, console); |
| setEditable(false); |
| } |
| |
| |
| public boolean isAutoScroll() { |
| return this.autoScroll; |
| } |
| |
| public void setAutoScroll(final boolean scroll) { |
| this.autoScroll= scroll; |
| } |
| |
| @Override |
| public void setDocument(final IDocument document) { |
| final IDocument oldDocument= getDocument(); |
| if (oldDocument != null) { |
| oldDocument.removeDocumentListener(getDocumentListener()); |
| } |
| |
| super.setDocument(document); |
| |
| if (document != null) { |
| document.addDocumentListener(getDocumentListener()); |
| } |
| } |
| |
| private IDocumentListener getDocumentListener() { |
| if (this.documentListener == null) { |
| this.documentListener= new IDocumentListener() { |
| @Override |
| public void documentAboutToBeChanged(final DocumentEvent event) { |
| } |
| |
| @Override |
| public void documentChanged(final DocumentEvent event) { |
| if (OutputViewer.this.autoScroll) { |
| revealEndOfDocument(); |
| } |
| } |
| }; |
| } |
| return this.documentListener; |
| } |
| |
| @Override |
| public void revealEndOfDocument() { |
| final Display display= UIAccess.getDisplay(); |
| display.asyncExec(new Runnable() { |
| @Override |
| public void run() { |
| final StyledText textWidget= getTextWidget(); |
| if (!UIAccess.isOkToUse(textWidget)) { |
| return; |
| } |
| final AbstractDocument document= (AbstractDocument) getDocument(); |
| final long timestamp= document.getModificationStamp(); |
| final int lineCount= textWidget.getLineCount(); |
| final int lineToShow= ((lineCount > 1 && |
| textWidget.getCharCount() == textWidget.getOffsetAtLine(lineCount - 1)) ? |
| (lineCount - 1) : (lineCount)); |
| final int visiblePixel= textWidget.getClientArea().height; |
| final int linePixel= textWidget.getLineHeight(); |
| final int topPixel= (linePixel * (lineToShow - 1)) - visiblePixel + 2; |
| if (topPixel + linePixel > 0) { |
| if (topPixel < 0) { |
| textWidget.setTopPixel( |
| topPixel + linePixel ); |
| } |
| else { |
| final int[] move= new int[] { |
| topPixel, |
| topPixel + linePixel - 2, |
| topPixel + linePixel - 1, |
| topPixel + linePixel |
| }; |
| textWidget.setTopPixel(move[0]); |
| final int[] state= new int[] { 1 }; |
| display.timerExec(75, new Runnable() { |
| @Override |
| public void run() { |
| int i= state[0]; |
| if (!UIAccess.isOkToUse(textWidget) |
| || timestamp != ((IDocumentExtension4) getDocument()).getModificationStamp() |
| || move[i-1] != textWidget.getTopPixel()) { |
| return; |
| } |
| textWidget.setTopPixel(move[i++]); |
| if (i < move.length) { |
| state[0]= i; |
| display.timerExec(25, this); |
| } |
| } |
| }); |
| } |
| } |
| } |
| }); |
| } |
| |
| } |