Summary

JTextAreaのキャレット移動アクションを表示上での右端の折り返し位置、その次に改行記号位置の順番で遷移するよう設定します。

Source Code Examples

class CursorEndAction extends AbstractAction {
  @Override public void actionPerformed(ActionEvent e) {
    Object src = e.getSource();
    if (src instanceof JTextComponent) {
      JTextComponent target = (JTextComponent) src;
      int offs = target.getCaretPosition();
      int rowEndOffs;
      try {
        rowEndOffs = Utilities.getRowEnd(target, offs);
      } catch (BadLocationException ex) {
        Logger.getGlobal().severe(ex::getMessage);
        return;
      }
      if (rowEndOffs == offs) {
        int length = target.getDocument().getLength();
        int end = Utilities.getParagraphElement(target, offs).getEndOffset();
        target.setCaretPosition(Math.min(length, end - 1));
      } else {
        target.setCaretPosition(rowEndOffs);
      }
    }
  }
}
View in GitHub: Java, Kotlin

Explanation

  • cursor-end: Ctrl+E
    • Utilities.getRowEnd(...)を使用して、指定されたモデル位置を含む行の終了行モデル位置を取得
      • JTextArea#setLineWrap(true)で行折返しが有効の場合、Utilities.getRowEnd(...)は右端の折り返し位置を返す
    • このアクションを実行したときのキャレット位置(指定されたモデル位置)が取得した行の終了行モデル位置より手前に存在する場合は行の終了行モデル位置まで移動
    • 現在のキャレット位置と取得した行の終了行モデル位置が等しい場合は改行記号位置(段落末尾)をUtilities.getParagraphElement(...).getEndOffset()で取得しそのひとつ手前に移動
    • JTextArea#setLineWrap(false)で行折返しが無効の場合終了行モデル位置と改行記号位置は等しくなるので、デフォルトで用意されているcaret-end-lineアクション(END)と同じ動作になる
  • caret-end-line(default): END(default)
    • 行末まで移動
    • 行折返しが有効の場合、行末は表示上での右端の折り返し位置、無効の場合は改行記号位置(パラグラフ末尾)
  • caret-end-paragraph(default): Ctrl+P
    • パラグラフ末尾まで移動
    • デフォルトではキーバインドは未設定なので、このサンプルではCtrl+Pで追加
    • 改行記号の後にキャレットが移動するので、実質次のパラグラフ先頭へのキャレット移動になる?
      • このため、caret-end-linecaret-end-paragraphアクションを連続して実行しても、このサンプルで自作したcursor-endアクションと同じキャレット位置までの移動にはならない
  • caret-end(default): Ctrl+END(default)
    • 全テキストの末尾までキャレットを移動

Reference

Comment