@Override public final void mousePressed(final MouseEvent e) { if (!isEnabled() || !isFocusable()) return; requestFocusInWindow(); caret(true); if (SwingUtilities.isMiddleMouseButton(e)) copy(); final boolean shift = e.isShiftDown(); final boolean selected = editor.selected(); if (SwingUtilities.isLeftMouseButton(e)) { final int c = e.getClickCount(); if (c == 1) { // selection mode if (shift) editor.startSelection(true); select(e.getPoint(), !shift); } else if (c == 2) { editor.selectWord(); } else { editor.selectLine(); } } else if (!selected) { select(e.getPoint(), true); } }
@Override public void keyTyped(final KeyEvent e) { if (!hist.active() || control(e) || DELNEXT.is(e) || DELPREV.is(e) || ESCAPE.is(e) || CUT2.is(e)) return; final int caret = editor.pos(); // remember if marked text is to be deleted final StringBuilder sb = new StringBuilder(1).append(e.getKeyChar()); final boolean indent = TAB.is(e) && editor.indent(sb, e.isShiftDown()); // delete marked text final boolean selected = editor.selected() && !indent; if (selected) editor.delete(); final int move = ENTER.is(e) ? editor.enter(sb) : editor.add(sb, selected); // refresh history and adjust cursor position hist.store(editor.text(), caret, editor.pos()); if (move != 0) editor.pos(Math.min(editor.size(), caret + move)); // adjust text height scrollCode.invokeLater(true); e.consume(); }
/** Sorts text. */ public final void sort() { final int caret = editor.pos(); final DialogSort ds = new DialogSort(gui); if (!ds.ok() || !editor.sort()) return; hist.store(editor.text(), caret, editor.pos()); scrollCode.invokeLater(true); repaint(); }
@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); } }
/** * Copies the selected text to the clipboard. * * @return true if text was copied */ private boolean copy() { final String txt = editor.copy(); if (txt.isEmpty()) return false; // copy selection to clipboard BaseXLayout.copy(txt); return true; }
/** * Sets the output text. * * @param text output text * @param size text size */ public final void setText(final byte[] text, final int size) { byte[] txt = text; if (Token.contains(text, '\r')) { // remove carriage returns int ns = 0; for (int r = 0; r < size; ++r) { final byte b = text[r]; if (b != '\r') text[ns++] = b; } // new text is different... txt = Arrays.copyOf(text, ns); } else if (text.length != size) { txt = Arrays.copyOf(text, size); } if (editor.text(txt)) { if (hist != null) hist.store(txt, editor.pos(), 0); } if (isShowing()) resizeCode.invokeLater(); }
/** Jumps to a specific line. */ private void gotoLine() { final byte[] last = editor.text(); final int ll = last.length; final int cr = getCaret(); int l = 1; for (int e = 0; e < ll && e < cr; e += cl(last, e)) { if (last[e] == '\n') ++l; } final DialogLine dl = new DialogLine(gui, l); if (!dl.ok()) return; final int el = dl.line(); l = 1; int p = 0; for (int e = 0; e < ll && l < el; e += cl(last, e)) { if (last[e] != '\n') continue; p = e + 1; ++l; } setCaret(p); gui.editor.posCode.invokeLater(); }
/** * Finishes a command. * * @param old old cursor position; store entry to history if position != -1 */ private void finish(final int old) { if (old != -1) hist.store(editor.text(), old, editor.pos()); scrollCode.invokeLater(true); release(Action.CHECK); }
/** * Auto-completes a string at the specified position. * * @param string string * @param start start position */ private void complete(final String string, final int start) { final int caret = editor.pos(); editor.complete(string, start); hist.store(editor.text(), caret, editor.pos()); scrollCode.invokeLater(true); }
/** * Default constructor. * * @param txt initial text * @param editable editable flag * @param win parent window */ public TextPanel(final String txt, final boolean editable, final Window win) { super(win); this.editable = editable; editor = new TextEditor(gui); setFocusable(true); setFocusTraversalKeysEnabled(!editable); setBackground(BACK); setOpaque(editable); addMouseMotionListener(this); addMouseWheelListener(this); addComponentListener(this); addMouseListener(this); addKeyListener(this); addFocusListener( new FocusAdapter() { @Override public void focusGained(final FocusEvent e) { if (isEnabled()) caret(true); } @Override public void focusLost(final FocusEvent e) { caret(false); rend.caret(false); } }); setFont(dmfont); layout(new BorderLayout()); scroll = new BaseXScrollBar(this); rend = new TextRenderer(editor, scroll, editable, gui); add(rend, BorderLayout.CENTER); add(scroll, BorderLayout.EAST); setText(txt); hist = new History(editable ? editor.text() : null); new BaseXPopup( this, editable ? new GUICommand[] { new FindCmd(), new FindNextCmd(), new FindPrevCmd(), null, new GotoCmd(), null, new UndoCmd(), new RedoCmd(), null, new AllCmd(), new CutCmd(), new CopyCmd(), new PasteCmd(), new DelCmd() } : new GUICommand[] { new FindCmd(), new FindNextCmd(), new FindPrevCmd(), null, new GotoCmd(), null, new AllCmd(), new CopyCmd() }); }
/** * Returns a currently marked string if it does not extend over more than one line. * * @return search string */ public final String searchString() { final String string = editor.copy(); return string.indexOf('\n') != -1 ? "" : string; }
/** * Pastes a string. * * @param string string to be pasted */ public final void paste(final String string) { final int pos = editor.pos(); if (editor.selected()) editor.delete(); editor.add(string); finish(pos); }
/** * 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 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); } }
/** * Returns the current text cursor. * * @return cursor position */ private int getCaret() { return editor.pos(); }
/** * Sets the caret to the specified position. A text selection will be removed. * * @param pos caret position */ public final void setCaret(final int pos) { editor.pos(pos); cursorCode.invokeLater(1); caret(true); }
/** Selects the whole text. */ private void selectAll() { editor.selectAll(); rend.repaint(); }
/** * Returns the output text. * * @return output text */ public final byte[] getText() { return editor.text(); }
/** 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); }
/** * Tests if text has been selected. * * @return result of check */ public final boolean selected() { return editor.selected(); }
/** * Case conversion. * * @param cs case type */ public final void toCase(final Case cs) { final int caret = editor.pos(); if (editor.toCase(cs)) 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(); }