blob: dc02729e8452f2486d0768ecbb6123a8e2a4b358 [file] [log] [blame]
/*
* 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.core.output2;
import java.awt.Color;
import java.io.IOException;
import java.io.Reader;
import java.util.EnumSet;
import java.util.Set;
import java.util.WeakHashMap;
import java.util.logging.Level;
import javax.swing.Action;
import org.netbeans.api.io.Hyperlink;
import org.netbeans.api.io.OutputColor;
import org.netbeans.api.io.ShowOperation;
import org.netbeans.spi.io.InputOutputProvider;
import org.netbeans.spi.io.support.Hyperlinks;
import org.netbeans.spi.io.support.OutputColorType;
import org.netbeans.spi.io.support.OutputColors;
import org.openide.util.Exceptions;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.openide.util.lookup.ServiceProvider;
import org.openide.util.lookup.ServiceProviders;
import org.openide.windows.IOColors;
import org.openide.windows.IOContainer;
import org.openide.windows.IOProvider;
import org.openide.windows.IOSelect;
import org.openide.windows.InputOutput;
import org.openide.windows.OutputEvent;
import org.openide.windows.OutputListener;
import org.openide.windows.OutputWriter;
/**
* Supplies Output Window implementation through Lookup.
* @author Jesse Glick, Tim Boudreau
*/
@ServiceProviders({
@ServiceProvider(service=IOProvider.class, position=100),
@ServiceProvider(service=InputOutputProvider.class, position=100)
})
public final class NbIOProvider extends IOProvider implements
InputOutputProvider<InputOutput, OutputWriter, Integer, Integer> {
private static final WeakHashMap<IOContainer, PairMap> containerPairMaps =
new WeakHashMap<IOContainer, PairMap>();
private static final String STDOUT = NbBundle.getMessage(NbIOProvider.class,
"LBL_STDOUT"); //NOI18N
private static final String NAME = "output2"; // NOI18N
public OutputWriter getStdOut() {
if (Controller.LOG) {
Controller.log("NbIOProvider.getStdOut");
}
NbIO stdout = (NbIO) getIO(STDOUT, false);
NbWriter out = stdout.writer();
NbIO.post(new IOEvent(stdout, IOEvent.CMD_CREATE, true));
//ensure it is not closed
if (out != null && out.isClosed()) {
try {
out.reset();
out = (NbWriter) stdout.getOut();
} catch (IOException e) {
Exceptions.printStackTrace(e);
stdout = (NbIO) getIO(STDOUT, true);
out = (NbWriter) stdout.getOut();
}
} else {
out = (NbWriter) stdout.getOut();
}
return out;
}
@Override
public InputOutput getIO(String name, boolean newIO) {
return getIO (name, newIO, new Action[0], null);
}
@Override
public InputOutput getIO(String name, Action[] toolbarActions) {
return getIO (name, true, toolbarActions, null);
}
@Override
public InputOutput getIO(String name, Action[] additionalActions, IOContainer ioContainer) {
return getIO(name, true, additionalActions, ioContainer);
}
@Override
public String getName() {
return NAME;
}
@Override
public InputOutput getIO(String name, boolean newIO,
Action[] toolbarActions, IOContainer ioContainer) {
if (Controller.LOG) {
Controller.log("GETIO: " + name + " new:" + newIO);
}
IOContainer realIoContainer = ioContainer == null
? IOContainer.getDefault() : ioContainer;
NbIO result;
synchronized (containerPairMaps) {
PairMap namesToIos = containerPairMaps.get(realIoContainer);
result = namesToIos != null ? namesToIos.get(name) : null;
}
if (result == null || newIO) {
result = new NbIO(name, toolbarActions, realIoContainer);
synchronized (containerPairMaps) {
PairMap namesToIos = containerPairMaps.get(realIoContainer);
if (namesToIos == null) {
namesToIos = new PairMap();
containerPairMaps.put(realIoContainer, namesToIos);
}
namesToIos.add(name, result);
}
NbIO.post(new IOEvent(result, IOEvent.CMD_CREATE, newIO));
}
return result;
}
static void dispose (NbIO io) {
IOContainer ioContainer = io.getIOContainer();
if (ioContainer == null) {
ioContainer = IOContainer.getDefault();
}
synchronized (containerPairMaps) {
PairMap namesToIos = containerPairMaps.get(ioContainer);
if (namesToIos != null) {
namesToIos.remove(io);
if (namesToIos.isEmpty()) {
containerPairMaps.remove(ioContainer);
}
}
}
}
@Override
public String getId() {
return getName();
}
@Override
public InputOutput getIO(String name, boolean newIO, Lookup lookup) {
Action[] actions = lookup.lookup(Action[].class);
IOContainer container = lookup.lookup(IOContainer.class);
return getIO(name, newIO,
actions == null ? new Action[0] : actions,
container);
}
@Override
public Reader getIn(InputOutput io) {
return io.getIn();
}
@Override
public OutputWriter getOut(InputOutput io) {
return io.getOut();
}
@Override
public OutputWriter getErr(InputOutput io) {
return io.getErr();
}
@Override
public void print(InputOutput io, OutputWriter writer, String text,
Hyperlink link, OutputColor outputColor, boolean printLineEnd) {
Color awtColor = outputColorToAwtColor(io, outputColor);
OutputListener listener = hyperlinkToOutputListener(link);
boolean listenerImportant = link != null && Hyperlinks.isImportant(link);
if (io instanceof NbIO) {
OutWriter out = ((NbIO) io).out();
if (out != null) {
out.print(text, listener, listenerImportant, awtColor, null,
OutputKind.OUT, printLineEnd);
}
} else {
throw new IllegalArgumentException();
}
}
@Override
public Lookup getIOLookup(InputOutput io) {
if (io instanceof NbIO) {
return ((NbIO) io).getLookup();
} else {
throw new IllegalArgumentException();
}
}
@Override
public void resetIO(InputOutput io) {
if (io instanceof NbIO) {
try {
// ((NbWriter)io.getOut).reset() does OutWriter fixup,
// then NbWriter invokes ((NbIO) io).reset()
io.getOut().reset();
} catch (IOException ex) {
Exceptions.attachSeverity(ex, Level.WARNING);
Exceptions.printStackTrace(ex);
}
} else {
throw new IllegalArgumentException();
}
}
@Override
public void showIO(InputOutput io, Set<ShowOperation> operations) {
if (operations.contains(ShowOperation.OPEN)
&& operations.contains(ShowOperation.MAKE_VISIBLE)
&& operations.size() == 2) {
io.select();
} else {
IOSelect.select(io, showOperationsToIoSelect(operations));
}
}
@Override
public void closeIO(InputOutput io) {
io.closeInputOutput();
}
@Override
public boolean isIOClosed(InputOutput io) {
return io.isClosed();
}
@Override
public Integer getCurrentPosition(InputOutput io,
OutputWriter writer) {
if (io instanceof NbIO) {
OutWriter out = ((NbIO) io).out();
int size = 0;
if (out != null) {
size = out.getLines().getCharCount();
}
return size;
} else {
throw new IllegalArgumentException();
}
}
@Override
public void scrollTo(InputOutput io, OutputWriter writer,
Integer position) {
if (io instanceof NbIO) {
NbIO.post(new IOEvent((NbIO) io, IOEvent.CMD_SCROLL, position));
}
}
@Override
public Integer startFold(InputOutput io, OutputWriter writer,
boolean expanded) {
if (io instanceof NbIO) {
return ((NbIO) io).startFold(expanded);
} else {
throw new IllegalArgumentException();
}
}
@Override
public void endFold(InputOutput io, OutputWriter writer, Integer fold) {
if (io instanceof NbIO) {
((NbIO) io).endFold(fold);
} else {
throw new IllegalArgumentException();
}
}
@Override
public void setFoldExpanded(InputOutput io, OutputWriter writer,
Integer fold, boolean expanded) {
if (io instanceof NbIO) {
NbIO nbIO = ((NbIO) io);
if (expanded) {
nbIO.out().getLines().showFoldAndParentFolds(fold);
} else {
nbIO.out().getLines().hideFold(fold);
}
} else {
throw new IllegalArgumentException();
}
}
@Override
public String getIODescription(InputOutput io) {
if (io instanceof NbIO) {
return ((NbIO) io).getToolTipText();
} else {
throw new IllegalArgumentException();
}
}
@Override
public void setIODescription(InputOutput io, String description) {
if (io instanceof NbIO) {
((NbIO) io).setTooltipText(description);
} else {
throw new IllegalArgumentException();
}
}
/**
* Translate set of {@link ShowOperation}s to set of
* {@link IOSelect.AdditionalOperation}s.
*/
private Set<IOSelect.AdditionalOperation> showOperationsToIoSelect(
Set<ShowOperation> operations) {
Set<IOSelect.AdditionalOperation> res
= EnumSet.noneOf(IOSelect.AdditionalOperation.class);
for (ShowOperation so : operations) {
switch (so) {
case OPEN:
res.add(IOSelect.AdditionalOperation.OPEN);
break;
case MAKE_VISIBLE:
res.add(IOSelect.AdditionalOperation.REQUEST_VISIBLE);
break;
case ACTIVATE:
res.add(IOSelect.AdditionalOperation.REQUEST_ACTIVE);
break;
}
}
return res;
}
/**
* Convert a hyperlink to an output listener.
*
* @param link The hyperlink.
* @return The wrapping output listener.
*/
private static OutputListener hyperlinkToOutputListener(
final Hyperlink link) {
if (link == null) {
return null;
}
return new OutputListener() {
@Override
public void outputLineSelected(OutputEvent ev) {
}
@Override
public void outputLineAction(OutputEvent ev) {
Hyperlinks.invoke(link);
}
@Override
public void outputLineCleared(OutputEvent ev) {
}
};
}
private static Color outputColorToAwtColor(InputOutput io,
OutputColor color) {
if (color == null) {
return null;
}
OutputColorType type = OutputColors.getType(color);
if (type == OutputColorType.RGB) {
return new Color(OutputColors.getRGB(color));
} else {
switch (type) {
case DEBUG:
return IOColors.getColor(io, IOColors.OutputType.LOG_DEBUG);
case FAILURE:
return IOColors.getColor(io, IOColors.OutputType.LOG_FAILURE);
case WARNING:
return IOColors.getColor(io, IOColors.OutputType.LOG_WARNING);
case SUCCESS:
return IOColors.getColor(io, IOColors.OutputType.LOG_SUCCESS);
default:
return null;
}
}
}
}