| /*=============================================================================# |
| # Copyright (c) 2005, 2020 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.console; |
| |
| import java.io.IOException; |
| import java.util.EnumSet; |
| import java.util.HashMap; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import org.eclipse.core.runtime.IAdaptable; |
| import org.eclipse.debug.core.DebugEvent; |
| import org.eclipse.debug.core.DebugPlugin; |
| import org.eclipse.debug.core.IDebugEventSetListener; |
| import org.eclipse.debug.core.ILaunch; |
| import org.eclipse.debug.core.ILaunchConfiguration; |
| import org.eclipse.debug.core.IStreamListener; |
| import org.eclipse.debug.core.model.IProcess; |
| import org.eclipse.debug.core.model.IStreamMonitor; |
| import org.eclipse.jface.resource.FontRegistry; |
| import org.eclipse.jface.resource.JFaceResources; |
| import org.eclipse.jface.util.IPropertyChangeListener; |
| import org.eclipse.jface.util.PropertyChangeEvent; |
| import org.eclipse.swt.graphics.Font; |
| import org.eclipse.ui.console.ConsolePlugin; |
| import org.eclipse.ui.console.IConsoleView; |
| import org.eclipse.ui.console.TextConsole; |
| import org.eclipse.ui.part.IPageBookViewPage; |
| |
| import org.eclipse.statet.jcommons.ts.core.Tool; |
| |
| import org.eclipse.statet.ecommons.preferences.PreferencesUtil; |
| import org.eclipse.statet.ecommons.preferences.SettingsChangeNotifier; |
| import org.eclipse.statet.ecommons.preferences.core.util.PreferenceUtils; |
| import org.eclipse.statet.ecommons.ui.util.UIAccess; |
| |
| import org.eclipse.statet.internal.nico.ui.NicoUIPlugin; |
| import org.eclipse.statet.internal.nico.ui.console.NIConsolePartitioner; |
| import org.eclipse.statet.internal.nico.ui.preferences.ConsolePreferences; |
| import org.eclipse.statet.nico.core.runtime.SubmitType; |
| import org.eclipse.statet.nico.core.runtime.ToolProcess; |
| import org.eclipse.statet.nico.core.runtime.ToolStreamMonitor; |
| import org.eclipse.statet.nico.ui.NicoUIPreferences; |
| import org.eclipse.statet.nico.ui.NicoUITools; |
| |
| |
| /** |
| * A console to interact with controller using command-line-based interface. |
| */ |
| public abstract class NIConsole extends TextConsole implements IAdaptable { |
| |
| |
| public static final String NICONSOLE_TYPE= "org.eclipse.statet.nico.console"; //$NON-NLS-1$ |
| |
| public static final String ADJUST_OUTPUT_WIDTH_COMMAND_ID= "org.eclipse.statet.nico.commands.AdjustOutputWidth"; //$NON-NLS-1$ |
| |
| |
| private static boolean gFontInitialized; |
| |
| |
| private class SettingsListener implements SettingsChangeNotifier.ChangeListener, IPropertyChangeListener { |
| |
| @Override |
| public void settingsChanged(final Set<String> groupIds) { |
| if (groupIds.contains(ConsolePreferences.GROUP_ID)) { |
| updateSettings(); |
| } |
| if (groupIds.contains(ConsolePreferences.OUTPUT_TEXTSTYLE_GROUP_ID)) { |
| final NIConsoleColorAdapter adapter= NIConsole.this.adapter; |
| if (adapter != null) { |
| adapter.updateSettings(); |
| } |
| } |
| } |
| |
| @Override |
| public void propertyChange(final PropertyChangeEvent event) { |
| if (getSymbolicFontName().equals(event.getProperty()) ) { |
| setFont(null); |
| } |
| } |
| |
| } |
| |
| private final NIConsolePartitioner partitioner; |
| private final Map<String, NIConsoleOutputStream> streams= new HashMap<>(); |
| private boolean streamsClosed; |
| |
| private final ToolProcess process; |
| private NIConsoleColorAdapter adapter; |
| |
| private IDebugEventSetListener debugListener; |
| private final SettingsListener settingsListener= new SettingsListener(); |
| private int currentWatermark; |
| |
| |
| /** |
| * Constructs a new console. |
| * |
| * @param name console name |
| */ |
| public NIConsole(final ToolProcess process, final NIConsoleColorAdapter adapter) { |
| super(process.getAttribute(IProcess.ATTR_PROCESS_LABEL), |
| NICONSOLE_TYPE, |
| NicoUITools.getImageDescriptor(process), |
| true); |
| this.process= process; |
| this.adapter= adapter; |
| |
| this.partitioner= new NIConsolePartitioner(this, this.adapter.getStreamIds()); |
| this.partitioner.connect(getDocument()); |
| |
| if (!gFontInitialized) { |
| UIAccess.getDisplay().syncExec(new Runnable() { |
| @Override |
| public void run() { |
| setFont(null); |
| gFontInitialized= true; |
| } |
| }); |
| } |
| else { |
| setFont(null); |
| } |
| PreferencesUtil.getSettingsChangeNotifier().addChangeListener(this.settingsListener); |
| updateWatermarks(); |
| |
| this.streamsClosed= this.process.isTerminated(); |
| this.adapter.connect(process, this); |
| |
| this.debugListener= new IDebugEventSetListener() { |
| @Override |
| public void handleDebugEvents(final DebugEvent[] events) { |
| ITER_EVENTS: for (final DebugEvent event : events) { |
| if (event.getSource() == NIConsole.this.process) { |
| switch (event.getKind()) { |
| case DebugEvent.CHANGE: |
| final Object obj= event.getData(); |
| if (obj != null && obj instanceof String[]) { |
| final String[] attrChange= (String[]) obj; |
| if (attrChange.length == 3 && IProcess.ATTR_PROCESS_LABEL.equals(attrChange[0])) { |
| runSetName(attrChange[2]); |
| } |
| } |
| continue ITER_EVENTS; |
| case DebugEvent.TERMINATE: |
| disconnect(); |
| continue ITER_EVENTS; |
| } |
| } |
| } |
| } |
| |
| private void runSetName(final String name) { |
| UIAccess.getDisplay().syncExec(new Runnable() { |
| @Override |
| public void run() { |
| setName(name); |
| // ConsolePlugin.getDefault().getConsoleManager().warnOfContentChange(NIConsole.this); |
| ConsolePlugin.getDefault().getConsoleManager().refresh(NIConsole.this); |
| } |
| }); |
| } |
| }; |
| DebugPlugin.getDefault().addDebugEventListener(this.debugListener); |
| } |
| |
| protected void updateSettings() { |
| updateWatermarks(); |
| } |
| |
| protected void updateWatermarks() { |
| final boolean limitBufferSize= true; |
| if (limitBufferSize) { |
| int lowWater= PreferenceUtils.getInstancePrefs().getPreferenceValue(NicoUIPreferences.OUTPUT_CHARLIMIT_PREF); |
| if (lowWater < 100000) { |
| lowWater= 100000; |
| } |
| if (lowWater == this.currentWatermark) { |
| return; |
| } |
| final int highWater= lowWater + 10000; |
| this.partitioner.setWaterMarks(lowWater, highWater); |
| } |
| else { |
| this.partitioner.setWaterMarks(-1, -1); |
| } |
| } |
| |
| protected String getSymbolicFontName() { |
| return JFaceResources.TEXT_FONT; |
| } |
| |
| @Override |
| public void setFont(Font newFont) { |
| if (newFont == null) { |
| JFaceResources.getFont(getSymbolicFontName()).getFontData()[0].getName(); |
| newFont= JFaceResources.getFont(getSymbolicFontName()); |
| } |
| super.setFont(newFont); |
| } |
| |
| @Override |
| protected void init() { |
| super.init(); |
| |
| JFaceResources.getFontRegistry().addListener(this.settingsListener); |
| } |
| |
| @Override |
| public void clearConsole() { |
| if (this.partitioner != null) { |
| this.partitioner.clearBuffer(); |
| } |
| } |
| |
| |
| @Override |
| protected void dispose() { |
| super.dispose(); |
| |
| final DebugPlugin debugPlugin= DebugPlugin.getDefault(); |
| if (debugPlugin != null) { |
| debugPlugin.removeDebugEventListener(this.debugListener); |
| } |
| this.debugListener= null; |
| |
| final SettingsChangeNotifier changeNotifier= PreferencesUtil.getSettingsChangeNotifier(); |
| if (changeNotifier != null) { |
| changeNotifier.removeChangeListener(this.settingsListener); |
| } |
| final FontRegistry fontRegistry= JFaceResources.getFontRegistry(); |
| if (fontRegistry != null) { |
| fontRegistry.removeListener(this.settingsListener); |
| } |
| |
| disconnect(); |
| } |
| |
| @Override |
| public abstract IPageBookViewPage createPage(IConsoleView view); |
| |
| |
| @Override |
| protected NIConsolePartitioner getPartitioner() { |
| return this.partitioner; |
| } |
| |
| |
| public void connect(final ToolStreamMonitor streamMonitor, final String streamId, |
| final EnumSet<SubmitType> filter) { |
| synchronized (this.streams) { |
| if (this.streamsClosed) { |
| return; |
| } |
| |
| NIConsoleOutputStream stream= this.streams.get(streamId); |
| if (stream == null) { |
| stream= new NIConsoleOutputStream(this, streamId); |
| this.streams.put(streamId, stream); |
| } |
| |
| final NIConsoleOutputStream out= stream; |
| streamMonitor.addListener(new IStreamListener() { |
| @Override |
| public void streamAppended(final String text, final IStreamMonitor monitor) { |
| try { |
| out.write(text); |
| } |
| catch (final IOException e) { |
| NicoUIPlugin.logError(NicoUIPlugin.INTERNAL_ERROR, "Error of unexpected type occured, when writing to console stream.", e); //$NON-NLS-1$ |
| } |
| } |
| }, filter); |
| } |
| } |
| |
| public NIConsoleOutputStream getStream(final String streamId) { |
| synchronized (this.streams) { |
| return this.streams.get(streamId); |
| } |
| } |
| |
| private void disconnect() { |
| synchronized (this.streams) { |
| if (this.streamsClosed) { |
| return; |
| } |
| |
| for (final NIConsoleOutputStream stream : this.streams.values()) { |
| stream.close(); |
| } |
| this.streamsClosed= true; |
| this.partitioner.finish(); |
| |
| this.adapter.disconnect(); |
| this.adapter= null; |
| } |
| } |
| |
| public final ToolProcess getProcess() { |
| return this.process; |
| } |
| |
| @Override |
| @SuppressWarnings("unchecked") |
| public <T> T getAdapter(final Class<T> adapterType) { |
| if (adapterType == Tool.class) { |
| return (T) this.process; |
| } |
| if(adapterType == ILaunchConfiguration.class) { |
| final ILaunch launch= getProcess().getLaunch(); |
| if (launch != null) { |
| return (T) launch.getLaunchConfiguration(); |
| } |
| return null; |
| } |
| return null; |
| } |
| |
| } |