| /******************************************************************************* |
| * Copyright (c) 2005, 2017 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| *******************************************************************************/ |
| package org.eclipse.dltk.console.ui.internal; |
| |
| import java.io.IOException; |
| import java.util.ArrayList; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.StringTokenizer; |
| |
| import org.eclipse.dltk.compiler.util.Util; |
| import org.eclipse.dltk.console.IScriptConsoleInterpreter; |
| import org.eclipse.dltk.console.IScriptExecResult; |
| import org.eclipse.dltk.console.ScriptConsoleHistory; |
| import org.eclipse.dltk.console.ScriptConsolePrompt; |
| import org.eclipse.dltk.console.ui.AnsiColorHelper; |
| import org.eclipse.dltk.console.ui.AnsiColorHelper.IAnsiColorHandler; |
| import org.eclipse.dltk.console.ui.IScriptConsoleViewer; |
| import org.eclipse.dltk.console.ui.ScriptConsole; |
| import org.eclipse.dltk.console.ui.ScriptConsolePartitioner; |
| import org.eclipse.dltk.core.DLTKCore; |
| import org.eclipse.jface.text.BadLocationException; |
| import org.eclipse.jface.text.DocumentEvent; |
| import org.eclipse.jface.text.IDocument; |
| import org.eclipse.jface.text.IDocumentListener; |
| import org.eclipse.jface.text.IDocumentPartitioner; |
| import org.eclipse.jface.text.TextUtilities; |
| import org.eclipse.jface.text.hyperlink.HyperlinkManager; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.custom.ST; |
| import org.eclipse.swt.custom.StyleRange; |
| import org.eclipse.swt.custom.StyledText; |
| import org.eclipse.swt.dnd.Clipboard; |
| import org.eclipse.swt.dnd.DND; |
| import org.eclipse.swt.dnd.DropTarget; |
| import org.eclipse.swt.dnd.DropTargetAdapter; |
| import org.eclipse.swt.dnd.DropTargetEvent; |
| import org.eclipse.swt.dnd.TextTransfer; |
| import org.eclipse.swt.dnd.Transfer; |
| import org.eclipse.swt.events.FocusEvent; |
| import org.eclipse.swt.events.FocusListener; |
| import org.eclipse.swt.events.KeyEvent; |
| import org.eclipse.swt.events.KeyListener; |
| import org.eclipse.swt.graphics.Point; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Display; |
| import org.eclipse.ui.PlatformUI; |
| import org.eclipse.ui.console.TextConsoleViewer; |
| |
| public class ScriptConsoleViewer extends TextConsoleViewer implements IScriptConsoleViewer { |
| public static class ConsoleDocumentListener implements IDocumentListener { |
| |
| private boolean bEnabled = true; |
| private ICommandHandler handler; |
| private boolean handleSynchronously; |
| |
| private ScriptConsolePrompt prompt; |
| |
| private ScriptConsoleHistory history; |
| |
| private int inviteStart = 0; |
| private int inviteEnd = 0; |
| |
| private IDocument doc; |
| |
| private AnsiColorHelper ansiHelper = new AnsiColorHelper(); |
| |
| private List<ScriptConsoleViewer> viewerList = new ArrayList<ScriptConsoleViewer>(); |
| |
| private void addViewer(ScriptConsoleViewer viewer) { |
| viewerList.add(viewer); |
| } |
| |
| private void removeViewer(ScriptConsoleViewer viewer) { |
| viewerList.remove(viewer); |
| } |
| |
| protected void connectListener() { |
| doc.addDocumentListener(this); |
| } |
| |
| protected void disconnectListener() { |
| doc.removeDocumentListener(this); |
| } |
| |
| public void clear() { |
| try { |
| disconnectListener(); |
| doc.set(""); //$NON-NLS-1$ |
| ScriptConsoleViewer viewer; |
| for (Iterator<ScriptConsoleViewer> iter = viewerList.iterator(); iter.hasNext();) { |
| viewer = iter.next(); |
| IDocumentPartitioner partitioner = viewer.getDocument().getDocumentPartitioner(); |
| if (partitioner instanceof ScriptConsolePartitioner) { |
| ScriptConsolePartitioner scriptConsolePartitioner = (ScriptConsolePartitioner) partitioner; |
| scriptConsolePartitioner.clearRanges(); |
| } |
| } |
| appendInvitation(); |
| for (Iterator<ScriptConsoleViewer> iter = viewerList.iterator(); iter.hasNext();) { |
| iter.next().setCaretPosition(doc.getLength()); |
| } |
| } catch (BadLocationException e) { |
| e.printStackTrace(); |
| } finally { |
| connectListener(); |
| } |
| } |
| |
| public ConsoleDocumentListener(ICommandHandler handler, ScriptConsolePrompt prompt, |
| ScriptConsoleHistory history) { |
| this.prompt = prompt; |
| this.handler = handler; |
| this.history = history; |
| this.doc = null; |
| } |
| |
| public void setDocument(IDocument doc) { |
| if (this.doc != null) { |
| disconnectListener(); |
| } |
| |
| this.doc = doc; |
| |
| if (this.doc != null) { |
| connectListener(); |
| } |
| } |
| |
| @Override |
| public void documentAboutToBeChanged(DocumentEvent event) { |
| |
| } |
| |
| protected void handleCommandLine(final String command) throws BadLocationException, IOException { |
| if (handleSynchronously) { |
| IScriptExecResult result = handler.handleCommand(command); |
| if (((ScriptConsole) handler).getState() != IScriptConsoleInterpreter.WAIT_USER_INPUT) { |
| processResult(result); |
| } |
| return; |
| } |
| |
| Thread handlerThread = new Thread(Messages.ScriptConsoleViewer_scriptConsoleCommandHandler) { |
| |
| @Override |
| public void run() { |
| try { |
| final IScriptExecResult result = handler.handleCommand(command); |
| |
| if (((ScriptConsole) handler).getState() != IScriptConsoleInterpreter.WAIT_USER_INPUT) { |
| ((ScriptConsole) handler).getPage().getSite().getShell().getDisplay() |
| .asyncExec(() -> processResult(result)); |
| } |
| } catch (IOException ixcn) { |
| ixcn.printStackTrace(); |
| } |
| } |
| |
| }; |
| handlerThread.setDaemon(true); |
| handlerThread.setPriority(Thread.MIN_PRIORITY); |
| handlerThread.start(); |
| } |
| |
| protected void appendText(int offset, String text) throws BadLocationException { |
| doc.replace(offset, 0, text); |
| } |
| |
| protected void processText(int originalOffset, String content, boolean isInput, boolean isError, |
| final boolean shouldReveal, final boolean shouldRedraw) throws BadLocationException { |
| if (originalOffset == -1) { |
| originalOffset = doc.getLength(); |
| } |
| |
| ansiHelper.processText(originalOffset, content, isInput, isError, new IAnsiColorHandler() { |
| |
| @Override |
| public void handleText(int start, String content, boolean isInput, boolean isError) |
| throws BadLocationException { |
| appendText(start, content); |
| addToPartitioner(start, content, isInput, isError); |
| } |
| |
| @Override |
| public void processingComplete(int start, int length) { |
| for (Iterator<ScriptConsoleViewer> iter = viewerList.iterator(); iter.hasNext();) { |
| final ScriptConsoleViewer viewer = iter.next(); |
| if (shouldReveal == true) { |
| viewer.setCaretPosition(doc.getLength()); |
| viewer.revealEndOfDocument(); |
| } |
| |
| if (shouldRedraw == true) { |
| if (viewer.getTextWidget() != null) { |
| viewer.getTextWidget().redrawRange(start, length, true); |
| } |
| } |
| } |
| } |
| |
| }); |
| } |
| |
| protected void processResult(final IScriptExecResult result) { |
| disconnectListener(); |
| try { |
| if (result != null) { |
| final String output = result.getOutput(); |
| if (output != null && output.length() != 0) { |
| ansiHelper.reset(); |
| processText(-1, output, false, result.isError(), false, true); |
| } |
| } |
| appendInvitation(); |
| } catch (BadLocationException bxcn) { |
| bxcn.printStackTrace(); |
| } finally { |
| connectListener(); |
| } |
| } |
| |
| private void addToPartitioner(ScriptConsoleViewer viewer, StyleRange style) { |
| IDocumentPartitioner partitioner = viewer.getDocument().getDocumentPartitioner(); |
| if (partitioner instanceof ScriptConsolePartitioner) { |
| ScriptConsolePartitioner scriptConsolePartitioner = (ScriptConsolePartitioner) partitioner; |
| scriptConsolePartitioner.addRange(style); |
| } |
| } |
| |
| protected void addToPartitioner(int start, String content, boolean isInput, boolean isError) { |
| // ssanders: Content has to be tokenized in order for style and |
| // hyperlinks to display correctly |
| StringTokenizer tokenizer = new StringTokenizer(content, " \t\n\r\f@#=|,()[]{}<>'\"", true); //$NON-NLS-1$ |
| String token; |
| int tokenStart = start; |
| ScriptConsoleViewer viewer; |
| while (tokenizer.hasMoreTokens() == true) { |
| token = tokenizer.nextToken(); |
| |
| for (Iterator<ScriptConsoleViewer> iter = viewerList.iterator(); iter.hasNext();) { |
| viewer = iter.next(); |
| if (isInput == true) { |
| addToPartitioner(viewer, new StyleRange(tokenStart, token.length(), AnsiColorHelper.COLOR_BLACK, |
| null, SWT.BOLD)); |
| } else { |
| addToPartitioner(viewer, ansiHelper.resolveStyleRange(tokenStart, token.length(), isError)); |
| } |
| } |
| |
| tokenStart += token.length(); |
| } |
| for (Iterator<ScriptConsoleViewer> iter = viewerList.iterator(); iter.hasNext();) { |
| viewer = iter.next(); |
| viewer.getTextWidget().redraw(); |
| } |
| |
| } |
| |
| protected void processAddition(int offset, String text) { |
| if (!bEnabled) { |
| return; |
| } |
| try { |
| final String delim = TextUtilities.getDefaultLineDelimiter(doc); |
| text = doc.get(offset, doc.getLength() - offset); |
| doc.replace(offset, text.length(), ""); //$NON-NLS-1$ |
| text = text.replaceAll("\r\n|\n|\r", delim); //$NON-NLS-1$ |
| int start = 0; |
| int index; |
| while ((index = text.indexOf(delim, start)) != -1) { |
| if (index > start) { |
| processText(getCommandLineOffset(), text.substring(start, index), true, false, false, true); |
| } |
| final String commandLine = getCommandLine(); |
| processText(-1, delim, true, false, false, true); |
| inviteStart = inviteEnd = doc.getLength(); |
| history.add(commandLine); |
| start = index + delim.length(); |
| handleCommandLine(commandLine); |
| } |
| if (start < text.length()) { |
| processText(-1, text.substring(start, text.length()), true, false, false, true); |
| } |
| } catch (BadLocationException e) { |
| if (DLTKCore.DEBUG) { |
| e.printStackTrace(); |
| } |
| } catch (IOException e) { |
| if (DLTKCore.DEBUG) { |
| e.printStackTrace(); |
| } |
| } |
| } |
| |
| @Override |
| public void documentChanged(final DocumentEvent event) { |
| ansiHelper.disableWhile(() -> { |
| disconnectListener(); |
| try { |
| processAddition(event.getOffset(), event.getText()); |
| } finally { |
| connectListener(); |
| } |
| }); |
| } |
| |
| public void appendInvitation() throws BadLocationException { |
| inviteStart = doc.getLength(); |
| processText(inviteStart, prompt.toString(), true, false, true, true); |
| inviteEnd = doc.getLength(); |
| } |
| |
| public void appendDelimeter() throws BadLocationException { |
| processText(-1, TextUtilities.getDefaultLineDelimiter(doc), false, false, false, true); |
| } |
| |
| protected int getLastLineLength() throws BadLocationException { |
| int lastLine = doc.getNumberOfLines() - 1; |
| return doc.getLineLength(lastLine); |
| } |
| |
| public int getCommandLineOffset() throws BadLocationException { |
| return inviteEnd; |
| } |
| |
| public int getCommandLineLength() throws BadLocationException { |
| return doc.getLength() - inviteEnd; |
| } |
| |
| public String getCommandLine() throws BadLocationException { |
| return doc.get(getCommandLineOffset(), getCommandLineLength()); |
| } |
| |
| public void setCommandLine(final String command) { |
| ansiHelper.disableWhile(() -> { |
| try { |
| doc.replace(getCommandLineOffset(), getCommandLineLength(), command); |
| } catch (BadLocationException bxcn) { |
| bxcn.printStackTrace(); |
| } |
| }); |
| } |
| |
| /** |
| * @param command |
| */ |
| public void executeCommand(String command) { |
| disconnectListener(); |
| try { |
| final int docLen = doc.getLength(); |
| if (docLen > inviteEnd) { |
| // clear current command if any |
| doc.replace(inviteEnd, docLen - inviteEnd, Util.EMPTY_STRING); |
| // TODO should we restore the text after this command |
| // execution? |
| } |
| processText(getCommandLineOffset(), command + TextUtilities.getDefaultLineDelimiter(doc), true, false, |
| true, true); |
| inviteStart = inviteEnd = doc.getLength(); |
| handleCommandLine(command); |
| } catch (BadLocationException e) { |
| if (DLTKCore.DEBUG) { |
| e.printStackTrace(); |
| } |
| } catch (IOException e) { |
| if (DLTKCore.DEBUG) { |
| e.printStackTrace(); |
| } |
| } finally { |
| connectListener(); |
| } |
| } |
| |
| /** |
| * @param text |
| * @param isError |
| */ |
| public void write(final String text, final boolean isError) { |
| final Display display = PlatformUI.getWorkbench().getDisplay(); |
| if (display != null && !display.isDisposed()) |
| display.asyncExec(() -> { |
| disconnectListener(); |
| try { |
| processText(inviteStart, text, false, isError, true, true); |
| inviteStart += text.length(); |
| inviteEnd += text.length(); |
| } catch (BadLocationException bxcn) { |
| if (DLTKCore.DEBUG) { |
| bxcn.printStackTrace(); |
| } |
| } finally { |
| connectListener(); |
| } |
| }); |
| } |
| } |
| |
| /** |
| * @since 2.0 |
| */ |
| public class ScriptConsoleStyledText extends StyledText { |
| |
| public ScriptConsoleStyledText(Composite parent, int style) { |
| super(parent, (style | SWT.WRAP)); |
| } |
| |
| @Override |
| public void invokeAction(int action) { |
| if (isEditable() && isCaretOnLastLine()) { |
| switch (action) { |
| case ST.LINE_UP: |
| updateSelectedLine(); |
| if (history.prev()) { |
| console.getDocumentListener().setCommandLine(history.get()); |
| setCaretOffset(getDocument().getLength()); |
| } else { |
| beep(); |
| } |
| return; |
| |
| case ST.LINE_DOWN: |
| updateSelectedLine(); |
| if (history.next()) { |
| console.getDocumentListener().setCommandLine(history.get()); |
| setCaretOffset(getDocument().getLength()); |
| } else { |
| beep(); |
| } |
| return; |
| |
| case ST.DELETE_PREVIOUS: |
| if (getCaretOffset() <= getCommandLineOffset() && getSelectionCount() == 0) { |
| return; |
| } |
| break; |
| |
| case ST.DELETE_NEXT: |
| if (getCaretOffset() < getCommandLineOffset()) { |
| return; |
| } |
| break; |
| |
| case ST.DELETE_WORD_PREVIOUS: |
| return; |
| |
| case ST.SELECT_LINE_START: |
| if (isCaretOnLastLine()) { |
| final int prevCaret = getCaretOffset(); |
| final Point prevSelection = getSelection(); |
| final int caret = getCommandLineOffset(); |
| if (prevCaret == prevSelection.x) { |
| setSelection(prevSelection.y, caret); |
| } else if (prevCaret == prevSelection.y) { |
| setSelection(prevSelection.x, caret); |
| } else { |
| setCaretOffset(caret); |
| } |
| Point selectedRange = getSelectedRange(); |
| selectionChanged(selectedRange.x, selectedRange.y); |
| return; |
| } |
| break; |
| case ST.LINE_START: |
| if (isCaretOnLastLine()) { |
| setCaretOffset(getCommandLineOffset()); |
| return; |
| } |
| break; |
| case ST.COLUMN_PREVIOUS: |
| case ST.SELECT_COLUMN_PREVIOUS: |
| if (isCaretOnLastLine() && getCaretOffset() == getCommandLineOffset()) { |
| return; |
| } |
| } |
| |
| super.invokeAction(action); |
| |
| if (isCaretOnLastLine() && getCaretOffset() <= getCommandLineOffset()) { |
| setCaretOffset(getCommandLineOffset()); |
| } |
| } else { |
| |
| super.invokeAction(action); |
| } |
| } |
| |
| private void updateSelectedLine() { |
| try { |
| history.updateSelectedLine(console.getDocumentListener().getCommandLine()); |
| } catch (BadLocationException e) { |
| if (DLTKCore.DEBUG) { |
| e.printStackTrace(); |
| } |
| } |
| } |
| |
| private void beep() { |
| getDisplay().beep(); |
| } |
| |
| @Override |
| public void paste() { |
| if (isCaretOnLastLine()) { |
| console.getDocumentListener().ansiHelper.disableWhile(() -> { |
| checkWidget(); |
| Clipboard clipboard = new Clipboard(getDisplay()); |
| TextTransfer plainTextTransfer = TextTransfer.getInstance(); |
| String text = (String) clipboard.getContents(plainTextTransfer, DND.CLIPBOARD); |
| clipboard.dispose(); |
| paste(text); |
| }); |
| } |
| } |
| |
| /** |
| * @param text |
| */ |
| private void paste(String text) { |
| if (text != null && text.length() > 0) { |
| // ssanders: Process the lines one-by-one in |
| // order to have the proper prompting |
| console.getDocumentListener().handleSynchronously = true; |
| try { |
| |
| if (text.indexOf("\n") == -1) { |
| Point selectedRange = getSelectedRange(); |
| getTextWidget().insert(text); |
| setCaretOffset(selectedRange.x + text.length()); |
| |
| } else { |
| StringTokenizer tokenizer = new StringTokenizer(text, "\n\r"); //$NON-NLS-1$ |
| while (tokenizer.hasMoreTokens() == true) { |
| final String finText = tokenizer.nextToken(); |
| insertText(finText + "\n"); //$NON-NLS-1$ |
| } |
| } |
| } finally { |
| console.getDocumentListener().handleSynchronously = false; |
| } |
| } |
| } |
| |
| } |
| |
| private ScriptConsoleHistory history; |
| |
| private ScriptConsole console; |
| |
| public int getCaretPosition() { |
| return getTextWidget().getCaretOffset(); |
| } |
| |
| public void enableProcessing() { |
| console.getDocumentListener().bEnabled = true; |
| } |
| |
| public void disableProcessing() { |
| console.getDocumentListener().bEnabled = false; |
| } |
| |
| public void setCaretPosition(final int offset) { |
| if (getTextWidget() != null) { |
| getTextWidget().getDisplay().asyncExec(() -> { |
| if (getTextWidget() != null) { |
| getTextWidget().setCaretOffset(offset); |
| } |
| }); |
| } |
| } |
| |
| // public int beginLineOffset() throws BadLocationException { |
| // IDocument doc = getDocument(); |
| // int offset = getCaretPosition(); |
| // int line = doc.getLineOfOffset(offset); |
| // return offset - doc.getLineOffset(line); |
| // } |
| |
| protected boolean isCaretOnLastLine() { |
| try { |
| IDocument doc = getDocument(); |
| int line = doc.getLineOfOffset(getCaretPosition()); |
| return line == doc.getNumberOfLines() - 1; |
| } catch (BadLocationException e) { |
| if (DLTKCore.DEBUG) { |
| e.printStackTrace(); |
| } |
| return false; |
| } |
| } |
| |
| @Override |
| protected StyledText createTextWidget(Composite parent, int styles) { |
| return new ScriptConsoleStyledText(parent, styles); |
| } |
| |
| public ScriptConsoleViewer(Composite parent, final ScriptConsole console, |
| final IScriptConsoleContentHandler contentHandler) { |
| super(parent, console); |
| |
| this.console = console; |
| |
| this.history = console.getHistory(); |
| |
| console.getDocumentListener().addViewer(this); |
| |
| final StyledText styledText = getTextWidget(); |
| |
| // styledText.setEditable(false); |
| |
| // Correct keyboard actions |
| styledText.addFocusListener(new FocusListener() { |
| |
| @Override |
| public void focusGained(FocusEvent e) { |
| setCaretPosition(getDocument().getLength()); |
| styledText.removeFocusListener(this); |
| } |
| |
| @Override |
| public void focusLost(FocusEvent e) { |
| |
| } |
| }); |
| DropTarget target = new DropTarget(styledText, |
| DND.DROP_DEFAULT | DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_LINK); |
| target.setTransfer(new Transfer[] { TextTransfer.getInstance() }); |
| target.addDropListener(new DropTargetAdapter() { |
| @Override |
| public void dragEnter(DropTargetEvent e) { |
| if (e.detail == DND.DROP_DEFAULT) |
| e.detail = DND.DROP_COPY; |
| } |
| |
| @Override |
| public void dragOperationChanged(DropTargetEvent e) { |
| if (e.detail == DND.DROP_DEFAULT) |
| e.detail = DND.DROP_COPY; |
| } |
| |
| @Override |
| public void drop(DropTargetEvent e) { |
| ((ScriptConsoleStyledText) styledText).paste((String) e.data); |
| } |
| }); |
| styledText.setKeyBinding('X' | SWT.MOD1, ST.COPY); |
| styledText.addVerifyKeyListener(event -> { |
| try { |
| if (event.character != '\0') { |
| if ((event.stateMask & SWT.MOD1) == 0) { |
| // Printable character |
| // ssanders: Ensure selection is on last line |
| ConsoleDocumentListener listener = console.getDocumentListener(); |
| int selStart = getSelectedRange().x; |
| int selEnd = (getSelectedRange().x + getSelectedRange().y); |
| int clOffset = listener.getCommandLineOffset(); |
| int clLength = listener.getCommandLineLength(); |
| if (selStart < clOffset) { |
| int selLength; |
| |
| if (selEnd < clOffset) { |
| selStart = (clOffset + clLength); |
| selLength = 0; |
| } else { |
| selStart = clOffset; |
| selLength = (selEnd - selStart); |
| } |
| |
| setSelectedRange(selStart, selLength); |
| } |
| |
| if (getCaretPosition() < console.getDocumentListener().getCommandLineOffset()) { |
| event.doit = false; |
| return; |
| } |
| } |
| |
| if (event.character == SWT.CR) { |
| getTextWidget().setCaretOffset(getDocument().getLength()); |
| return; |
| } |
| |
| // ssanders: Avoid outputting " " when invoking |
| // completion on Mac OS X |
| if (event.keyCode == 32 && (event.stateMask & SWT.CTRL) > 0) { |
| event.doit = false; |
| return; |
| } |
| |
| // ssanders: Avoid outputting "<Tab>" when invoking |
| // completion on Mac OS X |
| if (event.keyCode == SWT.TAB) { |
| event.doit = false; |
| return; |
| } |
| } |
| } catch (Exception e) { |
| e.printStackTrace(); |
| } |
| }); |
| |
| styledText.addKeyListener(new KeyListener() { |
| @Override |
| public void keyPressed(KeyEvent e) { |
| if (e.keyCode == SWT.TAB || (e.keyCode == ' ' && e.stateMask == SWT.CTRL)) { |
| contentHandler.contentAssistRequired(); |
| } |
| } |
| |
| @Override |
| public void keyReleased(KeyEvent e) { |
| } |
| }); |
| |
| if (console.getDocumentListener().viewerList.size() == 1) { |
| clear(); |
| } |
| } |
| |
| // IConsoleTextViewer |
| @Override |
| public String getCommandLine() { |
| try { |
| return console.getDocumentListener().getCommandLine(); |
| } catch (BadLocationException e) { |
| return null; |
| } |
| } |
| |
| @Override |
| public int getCommandLineOffset() { |
| try { |
| return console.getDocumentListener().getCommandLineOffset(); |
| } catch (BadLocationException e) { |
| return -1; |
| } |
| } |
| |
| public void clear() { |
| console.getDocumentListener().clear(); |
| } |
| |
| public void insertText(String text) { |
| getTextWidget().append(text); |
| } |
| |
| @Override |
| public boolean canDoOperation(int operation) { |
| boolean canDoOperation = super.canDoOperation(operation); |
| |
| if (canDoOperation) { |
| switch (operation) { |
| case CUT: |
| case DELETE: |
| // case PASTE: |
| case SHIFT_LEFT: |
| case SHIFT_RIGHT: |
| case PREFIX: |
| case STRIP_PREFIX: |
| canDoOperation = isCaretOnLastLine(); |
| } |
| } |
| |
| return canDoOperation; |
| } |
| |
| @Override |
| public void activatePlugins() { |
| fHyperlinkManager = new HyperlinkManager(HyperlinkManager.LONGEST_REGION_FIRST); |
| fHyperlinkManager.install(this, fHyperlinkPresenter, fHyperlinkDetectors, fHyperlinkStateMask); |
| |
| super.activatePlugins(); |
| } |
| |
| public void dispose() { |
| console.getDocumentListener().removeViewer(this); |
| } |
| |
| } |