CPP-35553 Features Trainer: Add Run / Debug workflow lesson

* add run Configuration lesson

GitOrigin-RevId: 3a28c5bb686c5d12db378b46d3c095783aa8e48f
This commit is contained in:
Maxim Banaev
2024-02-27 16:38:28 +01:00
committed by intellij-monorepo-bot
parent 355c67a399
commit f9690088ad
3 changed files with 49 additions and 40 deletions

View File

@@ -1,17 +1,13 @@
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.java.ift.lesson.run
import com.intellij.codeInsight.daemon.LineMarkerInfo
import com.intellij.execution.ExecutionBundle
import com.intellij.execution.application.ApplicationConfiguration
import com.intellij.icons.AllIcons
import com.intellij.java.ift.JavaLessonsBundle
import com.intellij.openapi.actionSystem.CommonDataKeys
import com.intellij.openapi.actionSystem.DataProvider
import com.intellij.openapi.editor.ex.EditorGutterComponentEx
import training.dsl.*
import training.dsl.LessonUtil.highlightRunGutter
import training.learn.lesson.general.run.CommonRunConfigurationLesson
import java.awt.Rectangle
class JavaRunConfigurationLesson : CommonRunConfigurationLesson("java.run.configuration") {
private val demoClassName = "Sample"
@@ -32,7 +28,7 @@ class JavaRunConfigurationLesson : CommonRunConfigurationLesson("java.run.config
override fun LessonContext.runTask() {
task {
caret(1, 1)
highlightRunGutters()
highlightRunGutter()
}
task("RunClass") {
@@ -60,21 +56,3 @@ class JavaRunConfigurationLesson : CommonRunConfigurationLesson("java.run.config
override val sampleFilePath: String = "src/${demoClassName}.java"
}
internal fun TaskContext.highlightRunGutters(highlightInside: Boolean = false, usePulsation: Boolean = false) {
triggerAndBorderHighlight {
this.highlightInside = highlightInside
this.usePulsation = usePulsation
}.componentPart l@{ ui: EditorGutterComponentEx ->
if (CommonDataKeys.EDITOR.getData(ui as DataProvider) != editor) return@l null
val runGutterLines = (0 until editor.document.lineCount).mapNotNull { lineInd ->
if (ui.getGutterRenderers(lineInd).any { (it as? LineMarkerInfo.LineMarkerGutterIconRenderer<*>)?.featureId == "run" })
lineInd
else null
}
if (runGutterLines.size < 2) return@l null
val startLineY = editor.visualLineToY(runGutterLines.first())
val endLineY = editor.visualLineToY(runGutterLines.last())
Rectangle(25, startLineY, ui.width - 40, endLineY - startLineY + editor.lineHeight)
}
}

View File

@@ -1,6 +1,7 @@
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package training.dsl
import com.intellij.codeInsight.daemon.LineMarkerInfo
import com.intellij.codeInsight.documentation.DocumentationEditorPane
import com.intellij.execution.RunManager
import com.intellij.execution.actions.ConfigurationContext
@@ -282,6 +283,24 @@ object LessonUtil {
}
}
fun TaskContext.highlightRunGutter(highlightInside: Boolean = false, usePulsation: Boolean = false, singleLineGutter: Boolean = false) {
triggerAndBorderHighlight {
this.highlightInside = highlightInside
this.usePulsation = usePulsation
}.componentPart l@{ ui: EditorGutterComponentEx ->
if (CommonDataKeys.EDITOR.getData(ui as DataProvider) != editor) return@l null
val runGutterLines = (0 until editor.document.lineCount).mapNotNull { lineInd ->
if (ui.getGutterRenderers(lineInd).any { (it as? LineMarkerInfo.LineMarkerGutterIconRenderer<*>)?.featureId == "run" })
lineInd
else null
}
val startLineY = editor.visualLineToY(runGutterLines.first())
val endLineY = editor.visualLineToY(runGutterLines.last())
val startX = if (singleLineGutter) 30 else 25
Rectangle(startX, startLineY, ui.width - 40, endLineY - startLineY + editor.lineHeight)
}
}
/**
* Should be called after task with detection of UI element inside desired window to adjust
* @return location of window before adjustment
@@ -637,7 +656,7 @@ fun LessonContext.highlightButtonById(actionId: String,
}
}
catch (e: Throwable) {
// Just go to the next step if we cannot find needed button (when this method is used as pass trigger)
// Just go to the next step if we cannot find the needed button (when this method is used as pass trigger)
taskInvokeLater { feature.complete(false) }
throw IllegalStateException("Cannot find button for $actionId", e)
}

View File

@@ -160,22 +160,9 @@ abstract class CommonRunConfigurationLesson(id: String) : KLesson(id, LessonsBun
highlightButtonById("RedesignedRunConfigurationSelector", usePulsation = false)
task("editRunConfigurations") {
text(LessonsBundle.message("run.configuration.edit.configuration",
LessonUtil.rawShift(),
strong(ActionsBundle.message("action.editRunConfigurations.text").dropMnemonic())))
triggerAndBorderHighlight().component { ui: JBCheckBox ->
ui.text?.contains(ExecutionBundle.message("run.configuration.store.as.project.file").dropMnemonic()) == true
}
test {
actions(it)
}
}
openEditRunConfiguration()
task {
text(LessonsBundle.message("run.configuration.settings.description"))
gotItStep(Balloon.Position.below, 300, LessonsBundle.message("run.configuration.tip.about.save.configuration.into.file"))
}
storeAsCheckbox()
task {
before {
@@ -234,4 +221,29 @@ abstract class CommonRunConfigurationLesson(id: String) : KLesson(id, LessonsBun
Pair(LessonsBundle.message("run.configuration.help.link"),
LessonUtil.getHelpLink("run-debug-configuration.html")),
)
companion object {
fun LessonContext.openEditRunConfiguration() {
task("editRunConfigurations") {
text(LessonsBundle.message("run.configuration.edit.configuration",
LessonUtil.rawShift(),
strong(ActionsBundle.message("action.editRunConfigurations.text").dropMnemonic())))
test {
actions(it)
}
}
}
fun LessonContext.storeAsCheckbox() {
task {
triggerAndBorderHighlight().component { ui: JBCheckBox ->
ui.text?.contains(ExecutionBundle.message("run.configuration.store.as.project.file").dropMnemonic()) == true
}
}
task {
text(LessonsBundle.message("run.configuration.settings.description"))
gotItStep(Balloon.Position.below, 300, LessonsBundle.message("run.configuration.tip.about.save.configuration.into.file"))
}
}
}
}