summaryrefslogtreecommitdiff
path: root/platform/lang-impl/src/com/intellij/ide/bookmark/actions/NextBookmarkInEditor.kt
blob: bf836ab618bdec402e5233165f7e116d37036257 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.ide.bookmark.actions

import com.intellij.ide.bookmark.BookmarkBundle.messagePointer
import com.intellij.ide.bookmark.BookmarkOccurrence
import com.intellij.ide.bookmark.BookmarksManager
import com.intellij.ide.bookmark.LineBookmark
import com.intellij.openapi.actionSystem.CommonDataKeys
import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.editor.*
import com.intellij.openapi.editor.actionSystem.EditorAction
import com.intellij.openapi.editor.actionSystem.EditorActionHandler
import com.intellij.openapi.fileEditor.FileDocumentManager

internal class NextBookmarkInEditorAction : EditorAction(NextBookmarkInEditor(true)) {
  init {
    templatePresentation.setText(messagePointer("bookmark.go.to.next.editor.action.text"))
  }
}

internal class PreviousBookmarkInEditorAction : EditorAction(NextBookmarkInEditor(false)) {
  init {
    templatePresentation.setText(messagePointer("bookmark.go.to.previous.editor.action.text"))
  }
}

private class NextBookmarkInEditor(val forward: Boolean) : EditorActionHandler() {
  override fun isEnabledForCaret(editor: Editor, caret: Caret, context: DataContext) = getNextBookmark(editor, context) != null
  override fun doExecute(editor: Editor, caret: Caret?, context: DataContext) {
    val bookmark = getNextBookmark(editor, context) ?: return
    val pos = bookmark.line.let { if (0 <= it && it < editor.document.lineCount) LogicalPosition(it, 0) else return }
    editor.selectionModel.removeSelection()
    editor.caretModel.removeSecondaryCarets()
    editor.caretModel.moveToLogicalPosition(pos)
    editor.scrollingModel.scrollTo(pos, ScrollType.CENTER)
  }

  private fun getNextBookmark(editor: Editor, context: DataContext): LineBookmark? {
    if (editor.isOneLineMode) return null
    val file = FileDocumentManager.getInstance().getFile(editor.document) ?: return null
    val manager = BookmarksManager.getInstance(editor.project ?: CommonDataKeys.PROJECT.getData(context)) ?: return null
    val bookmarks = manager.bookmarks.mapNotNullTo(mutableListOf()) { if (it is LineBookmark && it.file == file) it else null }
    if (bookmarks.isNotEmpty()) {
      val line = editor.caretModel.logicalPosition.line
      if (forward) {
        // select next bookmark
        bookmarks.sortBy { it.line }
        for (bookmark in bookmarks) {
          if (bookmark.line > line) return bookmark
        }
      }
      else {
        // select previous bookmark
        bookmarks.sortByDescending { it.line }
        for (bookmark in bookmarks) {
          if (bookmark.line < line) return bookmark
        }
      }
      if (BookmarkOccurrence.cyclic) {
        val bookmark = bookmarks[0]
        if (bookmark.line != line) return bookmark
      }
    }
    return null
  }
}