@Override public void execute(final Object arg) { rend.updateScrollbar(); // update scrollbar to display value within valid range scroll.pos(scroll.pos()); rend.repaint(); }
/** * Jumps to the current, next or previous search string. * * @param dir search direction * @param select select hit */ protected final void jump(final SearchDir dir, final boolean select) { // updates the visible area final int y = rend.jump(dir, select); final int h = getHeight(); final int p = scroll.pos(); final int m = y + rend.fontHeight() * 3 - h; if (y != -1 && (p < m || p > y)) scroll.pos(y - h / 2); rend.repaint(); }
@Override public void execute(final Object algn) { // updates the visible area final int p = scroll.pos(); final int y = rend.cursorY(); final int m = y + rend.fontHeight() * 3 - getHeight(); if (p < m || p > y) { final int align = (Integer) algn; scroll.pos(align == 0 ? y : align == 1 ? y - getHeight() / 2 : m); } rend.repaint(); }
@Override public final void setEnabled(final boolean enabled) { super.setEnabled(enabled); rend.setEnabled(enabled); scroll.setEnabled(enabled); caret(enabled); }
@Override public final void setFont(final Font f) { super.setFont(f); if (rend != null) { rend.setFont(f); scrollCode.invokeLater(true); } }
/** * Performs a search. * * @param sc search context * @param jump jump to next hit */ final void search(final SearchContext sc, final boolean jump) { try { rend.search(sc); if (!sc.search.isEmpty()) gui.status.setText(Util.info(Text.STRINGS_FOUND_X, sc.nr())); if (jump) jump(SearchDir.CURRENT, false); } catch (final Exception ex) { final String msg = Util.message(ex).replaceAll(Prop.NL + ".*", ""); gui.status.setError(Text.REGULAR_EXPR + Text.COLS + msg); } }
@Override public void mouseReleased(final MouseEvent e) { if (linkListener == null) return; if (SwingUtilities.isLeftMouseButton(e)) { editor.endSelection(); // evaluate link if (!editor.selected()) { final TextIterator iter = rend.jump(e.getPoint()); final String link = iter.link(); if (link != null) linkListener.linkClicked(link); } } }
/** * Replaces the text. * * @param rc replace context */ final void replace(final ReplaceContext rc) { try { final int[] select = rend.replace(rc); if (rc.text != null) { final boolean sel = editor.selected(); setText(rc.text); editor.select(select[0], select[sel ? 1 : 0]); release(Action.CHECK); } gui.status.setText(Text.STRINGS_REPLACED); } catch (final Exception ex) { final String msg = Util.message(ex).replaceAll(Prop.NL + ".*", ""); gui.status.setError(Text.REGULAR_EXPR + Text.COLS + msg); } }
/** Code completion. */ private void complete() { if (selected()) return; // find first character final int caret = editor.pos(), startPos = editor.completionStart(); final String prefix = string(substring(editor.text(), startPos, caret)); if (prefix.isEmpty()) return; // find insertion candidates final TreeMap<String, String> tmp = new TreeMap<>(); for (final Entry<String, String> entry : REPLACE.entrySet()) { final String key = entry.getKey(); if (key.startsWith(prefix)) tmp.put(key, entry.getValue()); } if (tmp.size() == 1) { // insert single candidate complete(tmp.values().iterator().next(), startPos); } else if (!tmp.isEmpty()) { // show popup menu final JPopupMenu pm = new JPopupMenu(); final ActionListener al = new ActionListener() { @Override public void actionPerformed(final ActionEvent ae) { complete(ae.getActionCommand().replaceAll("^.*?\\] ", ""), startPos); } }; for (final Entry<String, String> entry : tmp.entrySet()) { final JMenuItem mi = new JMenuItem("[" + entry.getKey() + "] " + entry.getValue()); pm.add(mi); mi.addActionListener(al); } pm.addSeparator(); final JMenuItem mi = new JMenuItem(Text.INPUT + Text.COLS + prefix); mi.setEnabled(false); pm.add(mi); final int[] cursor = rend.cursor(); pm.show(this, cursor[0], cursor[1]); // highlight first entry final MenuElement[] me = {pm, (JMenuItem) pm.getComponent(0)}; MenuSelectionManager.defaultManager().setSelectedPath(me); } }
@Override public void execute(final Object down) { rend.updateScrollbar(); cursorCode.execute((Boolean) down ? 2 : 0); }
@Override public void keyPressed(final KeyEvent e) { // ignore modifier keys if (specialKey(e) || modifier(e)) return; // re-animate cursor caret(true); // operations without cursor movement... final int fh = rend.fontHeight(); if (SCROLLDOWN.is(e)) { scroll.pos(scroll.pos() + fh); return; } if (SCROLLUP.is(e)) { scroll.pos(scroll.pos() - fh); return; } // set cursor position final boolean selected = editor.selected(); final int pos = editor.pos(); final boolean shift = e.isShiftDown(); boolean down = true, consumed = true; // move caret int lc = Integer.MIN_VALUE; final byte[] txt = editor.text(); if (NEXTWORD.is(e)) { editor.nextWord(shift); } else if (PREVWORD.is(e)) { editor.prevWord(shift); down = false; } else if (TEXTSTART.is(e)) { editor.textStart(shift); down = false; } else if (TEXTEND.is(e)) { editor.textEnd(shift); } else if (LINESTART.is(e)) { editor.lineStart(shift); down = false; } else if (LINEEND.is(e)) { editor.lineEnd(shift); } else if (PREVPAGE_RO.is(e) && !hist.active()) { lc = editor.linesUp(getHeight() / fh, false, lastCol); down = false; } else if (NEXTPAGE_RO.is(e) && !hist.active()) { lc = editor.linesDown(getHeight() / fh, false, lastCol); } else if (PREVPAGE.is(e) && !sc(e)) { lc = editor.linesUp(getHeight() / fh, shift, lastCol); down = false; } else if (NEXTPAGE.is(e) && !sc(e)) { lc = editor.linesDown(getHeight() / fh, shift, lastCol); } else if (NEXTLINE.is(e) && !MOVEDOWN.is(e)) { lc = editor.linesDown(1, shift, lastCol); } else if (PREVLINE.is(e) && !MOVEUP.is(e)) { lc = editor.linesUp(1, shift, lastCol); down = false; } else if (NEXTCHAR.is(e)) { editor.next(shift); } else if (PREVCHAR.is(e)) { editor.previous(shift); down = false; } else { consumed = false; } lastCol = lc == Integer.MIN_VALUE ? -1 : lc; // edit text if (hist.active()) { if (COMPLETE.is(e)) { complete(); return; } if (MOVEDOWN.is(e)) { editor.move(true); } else if (MOVEUP.is(e)) { editor.move(false); } else if (DELLINE.is(e)) { editor.deleteLine(); } else if (DELNEXTWORD.is(e)) { editor.deleteNext(true); } else if (DELLINEEND.is(e)) { editor.deleteNext(false); } else if (DELNEXT.is(e)) { editor.delete(); } else if (DELPREVWORD.is(e)) { editor.deletePrev(true); down = false; } else if (DELLINESTART.is(e)) { editor.deletePrev(false); down = false; } else if (DELPREV.is(e)) { editor.deletePrev(); down = false; } else { consumed = false; } } if (consumed) e.consume(); final byte[] tmp = editor.text(); if (txt != tmp) { // text has changed: add old text to history hist.store(tmp, pos, editor.pos()); scrollCode.invokeLater(down); } else if (pos != editor.pos() || selected != editor.selected()) { // cursor position or selection state has changed cursorCode.invokeLater(down ? 2 : 0); } }
/** * Selects the text at the specified position. * * @param point mouse position * @param start states if selection has just been started */ private void select(final Point point, final boolean start) { editor.select(rend.jump(point).pos(), start); rend.repaint(); }
@Override public final void mouseWheelMoved(final MouseWheelEvent e) { scroll.pos(scroll.pos() + e.getUnitsToScroll() * 20); rend.repaint(); }
/** Selects the whole text. */ private void selectAll() { editor.selectAll(); rend.repaint(); }
/** Formats the selected text. */ public final void format() { final int caret = editor.pos(); if (editor.format(rend.getSyntax())) hist.store(editor.text(), caret, editor.pos()); scrollCode.invokeLater(true); }
/** * Sets the error marker. * * @param pos start of optional error mark */ public final void error(final int pos) { editor.error(pos); rend.repaint(); }
/** Removes the error marker. */ public final void resetError() { editor.error(-1); rend.repaint(); }
@Override public void actionPerformed(final ActionEvent e) { rend.caret(!rend.caret()); }
/** * Stops an old text cursor thread and, if requested, starts a new one. * * @param start start/stop flag */ private void caret(final boolean start) { caretTimer.stop(); if (start) caretTimer.start(); rend.caret(start); }
/** * Returns the line and column of the current caret position. * * @return line/column */ public final int[] pos() { return rend.pos(); }
@Override public final void mouseMoved(final MouseEvent e) { if (linkListener == null) return; final TextIterator iter = rend.jump(e.getPoint()); gui.cursor(iter.link() != null ? CURSORHAND : CURSORARROW); }
/** * Sets a syntax highlighter. * * @param syntax syntax reference */ public final void setSyntax(final Syntax syntax) { rend.setSyntax(syntax); }