@Override public List<TerminalAction> getActions() { return Lists.newArrayList( new TerminalAction( "Copy", mySettingsProvider.getCopyKeyStrokes(), new Predicate<KeyEvent>() { @Override public boolean apply(KeyEvent input) { return handleCopy(true); } }) .withMnemonicKey(KeyEvent.VK_C) .withEnabledSupplier( new Supplier<Boolean>() { @Override public Boolean get() { return mySelection != null; } }), new TerminalAction( "Paste", mySettingsProvider.getPasteKeyStrokes(), new Predicate<KeyEvent>() { @Override public boolean apply(KeyEvent input) { handlePaste(); return true; } }) .withMnemonicKey(KeyEvent.VK_P) .withEnabledSupplier( new Supplier<Boolean>() { @Override public Boolean get() { return getClipboardString() != null; } }), new TerminalAction( "Clear Buffer", mySettingsProvider.getClearBufferKeyStrokes(), new Predicate<KeyEvent>() { @Override public boolean apply(KeyEvent input) { clearBuffer(); return true; } }) .withMnemonicKey(KeyEvent.VK_K) .withEnabledSupplier( new Supplier<Boolean>() { @Override public Boolean get() { return !myTerminalTextBuffer.isUsingAlternateBuffer(); } }) .separatorBefore(true)); }
/** * Draw every char in separate terminal cell to guaranty equal width for different lines. * Nevertheless to improve kerning we draw word characters as one block for monospaced fonts. */ private void drawChars(int x, int y, CharBuffer buf, TextStyle style, Graphics2D gfx) { final int blockLen = 1; int offset = 0; int drawCharsOffset = 0; // workaround to fix Swing bad rendering of bold special chars on Linux // TODO required for italic? CharBuffer renderingBuffer; if (mySettingsProvider.DECCompatibilityMode() && style.hasOption(TextStyle.Option.BOLD)) { renderingBuffer = CharUtils.heavyDecCompatibleBuffer(buf); } else { renderingBuffer = buf; } while (offset + blockLen <= buf.length()) { if (renderingBuffer.getBuf()[buf.getStart() + offset] == CharUtils.DWC) { offset += blockLen; drawCharsOffset += blockLen; continue; // dont' draw second part(fake one) of double width character } Font font = getFontToDisplay(buf.charAt(offset + blockLen - 1), style); // while (myMonospaced && (offset + blockLen < buf.getLength()) && // isWordCharacter(buf.charAt(offset + blockLen - 1)) // && (font == getFontToDisplay(buf.charAt(offset + blockLen - 1), style))) { // blockLen++; // } gfx.setFont(font); int descent = gfx.getFontMetrics(font).getDescent(); int baseLine = (y + 1) * myCharSize.height - descent; int xCoord = (x + drawCharsOffset) * myCharSize.width; int textLength = CharUtils.getTextLengthDoubleWidthAware( buf.getBuf(), buf.getStart() + offset, blockLen, mySettingsProvider.ambiguousCharsAreDoubleWidth()); int yCoord = y * myCharSize.height; gfx.setClip( xCoord, yCoord, Math.min(textLength * myCharSize.width, getWidth() - xCoord), Math.min(myCharSize.height, getHeight() - yCoord)); gfx.setColor(getPalette().getColor(myStyleState.getForeground(style.getForegroundForRun()))); gfx.drawChars(renderingBuffer.getBuf(), buf.getStart() + offset, blockLen, xCoord, baseLine); drawCharsOffset += blockLen; offset += blockLen; } gfx.setClip(null); }
private TextStyle getSelectionStyle(TextStyle style) { TextStyle selectionStyle = style.clone(); if (mySettingsProvider.useInverseSelectionColor()) { selectionStyle = getInversedStyle(style); } else { TextStyle mySelectionStyle = mySettingsProvider.getSelectionColor(); selectionStyle.setBackground(mySelectionStyle.getBackground()); selectionStyle.setForeground(mySelectionStyle.getForeground()); } return selectionStyle; }
protected Font getFontToDisplay(char c, TextStyle style) { boolean bold = style.hasOption(TextStyle.Option.BOLD); boolean italic = style.hasOption(TextStyle.Option.ITALIC); // workaround to fix Swing bad rendering of bold special chars on Linux if (bold && mySettingsProvider.DECCompatibilityMode() && CharacterSets.isDecBoxChar(c)) { return myNormalFont; } return bold ? (italic ? myBoldItalicFont : myBoldFont) : (italic ? myItalicFont : myNormalFont); }
private void processTerminalKeyTyped(KeyEvent e) { final char keychar = e.getKeyChar(); if ((keychar & 0xff00) != 0) { final char[] foo; if (mySettingsProvider.altSendsEscape() && (e.getModifiers() & InputEvent.ALT_MASK) != 0) { foo = new char[] {Ascii.ESC, keychar}; } else { foo = new char[] {keychar}; } try { myTerminalStarter.sendString(new String(foo)); if (mySettingsProvider.scrollToBottomOnTyping()) { scrollToBottom(); } } catch (final RuntimeException ex) { LOG.error("Error sending key to emulator", ex); } } }
protected void setupAntialiasing(Graphics graphics) { if (graphics instanceof Graphics2D) { Graphics2D myGfx = (Graphics2D) graphics; final Object mode = mySettingsProvider.useAntialiasing() ? RenderingHints.VALUE_TEXT_ANTIALIAS_ON : RenderingHints.VALUE_TEXT_ANTIALIAS_OFF; final RenderingHints hints = new RenderingHints(RenderingHints.KEY_TEXT_ANTIALIASING, mode); myGfx.setRenderingHints(hints); } }
private void processTerminalKeyPressed(KeyEvent e) { try { final int keycode = e.getKeyCode(); final char keychar = e.getKeyChar(); // numLock does not change the code sent by keypad VK_DELETE // although it send the char '.' if (keycode == KeyEvent.VK_DELETE && keychar == '.') { myTerminalStarter.sendBytes(new byte[] {'.'}); return; } // CTRL + Space is not handled in KeyEvent; handle it manually else if (keychar == ' ' && (e.getModifiers() & InputEvent.CTRL_MASK) != 0) { myTerminalStarter.sendBytes(new byte[] {Ascii.NUL}); return; } final byte[] code = myTerminalStarter.getCode(keycode, e.getModifiers()); if (code != null) { myTerminalStarter.sendBytes(code); if (mySettingsProvider.scrollToBottomOnTyping() && isCodeThatScrolls(keycode)) { scrollToBottom(); } } else if ((keychar & 0xff00) == 0) { final byte[] obuffer; if (mySettingsProvider.altSendsEscape() && (e.getModifiers() & InputEvent.ALT_MASK) != 0) { obuffer = new byte[] {Ascii.ESC, (byte) keychar}; } else { obuffer = new byte[] {(byte) keychar}; } myTerminalStarter.sendBytes(obuffer); if (mySettingsProvider.scrollToBottomOnTyping()) { scrollToBottom(); } } } catch (final Exception ex) { LOG.error("Error sending key to emulator", ex); } }
private void establishFontMetrics() { final BufferedImage img = createBufferedImage(1, 1); final Graphics2D graphics = img.createGraphics(); graphics.setFont(myNormalFont); final float lineSpace = mySettingsProvider.getLineSpace(); final FontMetrics fo = graphics.getFontMetrics(); myDescent = fo.getDescent(); myCharSize.width = fo.charWidth('W'); myCharSize.height = fo.getHeight() + (int) (lineSpace * 2); myDescent += lineSpace; myMonospaced = isMonospaced(fo); if (!myMonospaced) { LOG.info("WARNING: Font " + myNormalFont.getName() + " is non-monospaced"); } img.flush(); graphics.dispose(); }
private void drawCharacters(int x, int y, TextStyle style, CharBuffer buf, Graphics2D gfx) { int xCoord = x * myCharSize.width; int yCoord = y * myCharSize.height; if (xCoord < 0 || xCoord > getWidth() || yCoord < 0 || yCoord > getHeight()) { return; } gfx.setColor(getPalette().getColor(myStyleState.getBackground(style.getBackgroundForRun()))); int textLength = CharUtils.getTextLengthDoubleWidthAware( buf.getBuf(), buf.getStart(), buf.length(), mySettingsProvider.ambiguousCharsAreDoubleWidth()); gfx.fillRect( xCoord, yCoord, Math.min(textLength * myCharSize.width, getWidth() - xCoord), Math.min(myCharSize.height, getHeight() - yCoord)); if (buf.isNul()) { return; // nothing more to do } drawChars(x, y, buf, style, gfx); gfx.setColor(getPalette().getColor(myStyleState.getForeground(style.getForegroundForRun()))); int baseLine = (y + 1) * myCharSize.height - myDescent; if (style.hasOption(TextStyle.Option.UNDERLINED)) { gfx.drawLine(xCoord, baseLine + 1, (x + textLength) * myCharSize.width, baseLine + 1); } }
public TerminalPanel( @NotNull SettingsProvider settingsProvider, @NotNull TerminalTextBuffer terminalTextBuffer, @NotNull StyleState styleState) { mySettingsProvider = settingsProvider; myTerminalTextBuffer = terminalTextBuffer; myStyleState = styleState; myTermSize.width = terminalTextBuffer.getWidth(); myTermSize.height = terminalTextBuffer.getHeight(); myMaxFPS = mySettingsProvider.maxRefreshRate(); updateScrolling(); enableEvents(AWTEvent.KEY_EVENT_MASK | AWTEvent.INPUT_METHOD_EVENT_MASK); enableInputMethods(true); terminalTextBuffer.addModelListener( new TerminalModelListener() { @Override public void modelChanged() { repaint(); } }); }
private int getBlinkingPeriod() { if (myBlinkingPeriod != mySettingsProvider.caretBlinkingMs()) { setBlinkingPeriod(mySettingsProvider.caretBlinkingMs()); } return myBlinkingPeriod; }
protected Font createFont() { return mySettingsProvider.getTerminalFont(); }
public boolean isLocalMouseAction(MouseEvent e) { return mySettingsProvider.forceActionOnMouseReporting() || (isMouseReporting() == e.isShiftDown()); }
@Override public boolean ambiguousCharsAreDoubleWidth() { return mySettingsProvider.ambiguousCharsAreDoubleWidth(); }
public void beep() { if (mySettingsProvider.audibleBell()) { Toolkit.getDefaultToolkit().beep(); } }
private ColorPalette getPalette() { return mySettingsProvider.getTerminalColorPalette(); }