All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.netbeans.modules.terminal.ioprovider.Task Maven / Gradle / Ivy

The newest version!
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.netbeans.modules.terminal.ioprovider;

import java.awt.Color;
import java.io.CharConversionException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import javax.swing.Action;
import javax.swing.Icon;

import javax.swing.SwingUtilities;
import org.netbeans.lib.terminalemulator.ActiveRegion;
import org.openide.util.Exceptions;

import org.openide.windows.IOContainer;
import org.openide.windows.IOSelect;
import org.openide.windows.OutputListener;
import org.openide.xml.XMLUtil;

import org.netbeans.lib.terminalemulator.Coord;
import org.netbeans.lib.terminalemulator.LineDiscipline;
import org.netbeans.modules.terminal.api.ui.TerminalContainer;

/**
 * Perform a Task on the EDT.
 * @author ivan
 */

/* package */ abstract class Task {

    /**
     * Performs a computation on the EDT. The value can be retrieved
     * using the get() method which uses futures until the value is available.
     * @param 
     */
    public abstract static class ValueTask extends Task implements Callable {
	private final FutureTask future;

	protected  ValueTask(Terminal terminal) {
	    super(terminal);
	    this.future = new FutureTask(this);
	}

	@Override
	abstract public V call();

	@Override
	protected final void perform() {
	    future.run();
	}

	@Override
	protected boolean isValueTask() {
	    return true;
	}

	public V get() {
	    try {
		return future.get();
	    } catch (InterruptedException ex) {
		Exceptions.printStackTrace(ex);
		return null;
	    } catch (ExecutionException ex) {
		Exceptions.printStackTrace(ex);
		return null;
	    }
	}
    }

    private static int scheduledTasks;

    private final IOContainer container;
    private final Terminal terminal;

    /**
     * Schedule this task to be performed on the EDT, or perform it now.
     */
    public final void post() {

	scheduledTasks++;

	if (! SwingUtilities.isEventDispatchThread()) {
	    SwingUtilities.invokeLater(new Runnable() {
		@Override
		public void run() {
		    dispatch();
		}
	    });
	    return;
	} else {
	    dispatch();
	}
    }

    private void dispatch() {
	try {
	    if (terminal().isDisposed() && ! isValueTask()) {
		// closeInputOutput has been called
		return;
	    } else {
		perform();
	    }
	} finally {
	    scheduledTasks--;
	}
    }

    static boolean isQuiescent() {
	return scheduledTasks == 0;
    }

    protected abstract void perform();

    protected boolean isValueTask() {
	return false;
    }

    /**
     * Common task that involves both container and Terminal.
     * @param container
     * @param terminal
     */
    protected Task(IOContainer container, Terminal terminal) {
	this.container = container;
	this.terminal = terminal;
    }

    /**
     * Common task that only involves the Terminal.
     * @param terminal
     */
    protected Task(Terminal terminal) {
	this.container = null;
	this.terminal = terminal;
    }

    protected final IOContainer container() {
	return container;
    }

    protected final Terminal terminal() {
	return terminal;
    }


    static class Add extends Task {
	private final Action[] actions;

	public Add(IOContainer container, Terminal terminal, Action[] actions) {
	    super(container, terminal);
	    this.actions = actions;
	}

	@Override
	public void perform() {
	    // It's important to add first because otherwise output2's
	    // container impl will assert.
	    container().add(terminal(), terminal().callBacks());

	    container().setToolbarActions(terminal(), actions);
	    terminal().setVisibleInContainer(true);
	    /* OLD bug #181064
	    container().open();
	    container().requestActive();
	     */
	    /* OLD
	    // output2 tacks on this " ".
	    // If anything it protects against null names.
	    terminal().setTitle(terminal().name() + " ");	// NOI18N
	     */
	    terminal().updateName(terminal().name());

	    // TMP container().add(terminal(), terminal().callBacks());
	}
    }

    static class Select extends Task {
	private final Set extraOps;

	public Select(IOContainer container, Terminal terminal,
		      Set extraOps) {
	    super(container, terminal);
	    this.extraOps = extraOps;
	}

	@Override
	public void perform() {
	    if (terminal().isDisposed())
		return;

	    terminal().setClosedUnconditionally(false);

	    if (!terminal().isVisibleInContainer()) {
		container().add(terminal(), terminal().callBacks());
		terminal().setVisibleInContainer(true);
	    }
	    if (extraOps != null) {
		if (extraOps.contains(IOSelect.AdditionalOperation.OPEN))
		    container().open();
		if (extraOps.contains(IOSelect.AdditionalOperation.REQUEST_VISIBLE))
		    container().requestVisible();
		if (extraOps.contains(IOSelect.AdditionalOperation.REQUEST_ACTIVE))
		    container().requestActive();
	    }
	    container().select(terminal());
	}
    }

    static class DeSelect extends Task {

	public DeSelect(IOContainer container, Terminal terminal) {
	    super(container, terminal);
	}

	@Override
	public void perform() {
	    container().setToolbarActions(terminal(), new Action[0]);
	    terminal().closeUnconditionally();
	}
    }

    static class StrongClose extends Task {

	public StrongClose(IOContainer container, Terminal terminal) {
	    super(container, terminal);
	}

	@Override
	public void perform() {
	    terminal().closeUnconditionally();
	    terminal().dispose();
	}
    }
    
    static class ActivateSearch extends Task {
        private final TerminalContainer tc;

        public ActivateSearch(TerminalContainer tc, Terminal terminal) {
            super(terminal);
            this.tc = tc;
        }

        @Override
        protected void perform() {
            tc.activateSearch(terminal());
        }
        
    }

    static class UpdateName extends Task {

	public UpdateName(IOContainer container, Terminal terminal) {
	    super(container, terminal);
	}

	@Override
	public void perform() {
	    if (!terminal().isVisibleInContainer()) {
		return ;
	    }
	    String newTitle = terminal().getTitle();
	    if (terminal().isConnected() && newTitle != null) {
		String escaped;
		try {
		    escaped = XMLUtil.toAttributeValue(newTitle);
		} catch (CharConversionException ex) {
		    escaped = newTitle;
		}

		newTitle = "" + escaped + "";	// NOI18N
	    }
	    container().setTitle(terminal(), newTitle);
	}
    }

    static class SetIcon extends Task {
	private final Icon icon;

	public SetIcon(IOContainer container, Terminal terminal, Icon icon) {
	    super(container, terminal);
	    this.icon = icon;
	}

	@Override
	public void perform() {
	    container().setIcon(terminal(), icon);
	}
    }

    static class SetToolTipText extends Task {
	private final String text;

	public SetToolTipText(IOContainer container, Terminal terminal, String text) {
	    super(container, terminal);
	    this.text = text;
	}

	@Override
	public void perform() {
	    container().setToolTipText(terminal(), text);
	}
    }

    static class Scroll extends Task {
	private final Coord coord;

	public Scroll(Terminal terminal, Coord coord) {
	    super(terminal);
	    this.coord = coord;
	}

	@Override
	public void perform() {
	    terminal().scrollTo(coord);
	}
    }

    static class SetClosable extends Task {
	private final boolean closable;

	public SetClosable(IOContainer container, Terminal terminal, boolean closable) {
	    super(container, terminal);
	    this.closable = closable;
	}

	@Override
	public void perform() {
	    terminal().setClosable(closable);
	}
    }

    static class SetDisciplined extends Task {
	private final boolean disciplined;

	public SetDisciplined(Terminal terminal, boolean disciplined) {
	    super(terminal);
	    this.disciplined = disciplined;
	}

	@Override
	public void perform() {
	    if (disciplined)
		terminal().term().pushStream(new LineDiscipline());
	}
    }

    static class SetCustomColor extends Task {
	private final int index;
	private final Color color;

	public SetCustomColor(Terminal terminal, int index, Color color) {
	    super(terminal);
	    this.index = index;
	    this.color = color;
	}

	@Override
	protected void perform() {
	    terminal().term().setCustomColor(index, color);
	}
    }

    static class ClearHistory extends Task {
	public ClearHistory(Terminal terminal) {
	    super(terminal);
	}

	@Override
	protected void perform() {
	    terminal().term().clearHistory();
	}
    }

    static class Connect extends Task {
	private final OutputStream pin;
	private final InputStream pout;
	private final InputStream perr;
	private final String charset;

	public Connect(Terminal terminal,
		       OutputStream pin, InputStream pout, InputStream perr, String charset) {
	    super(terminal);
	    this.pin = pin;
	    this.pout = pout;
	    this.perr = perr;
	    this.charset = charset;
	}

	@Override
	protected void perform() {
	    terminal().term().connect(pin, pout, perr, charset); // NOI18N
	    terminal().setExtConnected(true);
	}
    }

    static class Disconnect extends Task {
	private final Runnable continuation;

	public Disconnect(Terminal terminal, Runnable continuation) {
	    super(terminal);
	    this.continuation = continuation;
	}

	@Override
	protected void perform() {
	    // Wrap 'continuation' in another one so we can
	    // set the extConnected state at the right time.
	    terminal().term().disconnect(new Runnable() {
		@Override
		public void run() {
		    terminal().setExtConnected(false);
		    if (continuation != null)
			continuation.run();
		}
	    });
	}
    }

    static class BeginActiveRegion extends Task {
	private final OutputListener listener;

	public BeginActiveRegion(Terminal terminal,
		                 OutputListener listener) {
	    super(terminal);
	    this.listener = listener;
	}

	@Override
	protected void perform() {
            ActiveRegion ar = terminal().term().beginRegion(true);
            ar.setUserObject(listener);
            ar.setLink(true);
	}
    }

    static class EndActiveRegion extends Task {
	public EndActiveRegion(Terminal terminal) {
	    super(terminal);
	}

	@Override
	protected void perform() {
            terminal().term().endRegion();
	}
    }


    static class GetPosition extends ValueTask implements Callable {
	public GetPosition(Terminal terminal) {
	    super(terminal);
	}

	@Override
	public Coord call() {
	    return terminal().term().getCursorCoord();
	}
    }

    static class GetOut extends ValueTask implements Callable {
	public GetOut(Terminal terminal) {
	    super(terminal);
	}

	@Override
	public Writer call() {
	    return terminal().term().getOut();
	}
    }

    static class GetIn extends ValueTask implements Callable {
	public GetIn(Terminal terminal) {
	    super(terminal);
	}

	@Override
	public Reader call() {
	    return terminal().term().getIn();
	}
    }

    static class IsClosable extends ValueTask implements Callable {

	public IsClosable(Terminal terminal) {
	    super(terminal);
	}

	@Override
	public Boolean call() {
	    return terminal().isClosable();
	}
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy