[IFT] Add end lesson dialog for onboarding tour

IDEA-CR-70872

GitOrigin-RevId: 67ba0af9626a22e6c71c555df1350883fd3613d8
This commit is contained in:
Alexey Merkulov
2021-03-10 16:11:10 +03:00
committed by intellij-monorepo-bot
parent 64a5e99c64
commit 4536f36359
5 changed files with 69 additions and 11 deletions

View File

@@ -11,6 +11,7 @@ import com.intellij.openapi.ui.popup.LightweightWindowEvent
import com.intellij.ui.UIBundle
import com.intellij.ui.awt.RelativePoint
import com.intellij.util.Alarm
import icons.FeaturesTrainerIcons
import training.dsl.LearningBalloonConfig
import training.dsl.TaskContext
import training.dsl.TaskRuntimeContext
@@ -99,9 +100,11 @@ internal object LessonExecutorUtil {
val checkStopLesson = {
invokeLater {
if (actionsRecorder.disposed) return@invokeLater
val yesNo = Messages.showYesNoDialog(project, LearnBundle.message("learn.stop.lesson.question"), LearnBundle.message("learn.stop.lesson"), null)
val yesNo = Messages.showYesNoDialog(project, LearnBundle.message("learn.stop.lesson.question"), LearnBundle.message("learn.stop.lesson"), FeaturesTrainerIcons.Img.PluginIcon)
if (yesNo == Messages.YES) {
LessonManager.instance.stopLesson()
invokeLater {
LessonManager.instance.stopLesson()
}
}
else {
if (actionsRecorder.disposed) return@invokeLater

View File

@@ -36,6 +36,14 @@ abstract class Lesson(@NonNls val id: String, @Nls val name: String) {
open val testScriptProperties : TaskTestContext.TestScriptProperties = TaskTestContext.TestScriptProperties()
fun addLessonListener(lessonListener: LessonListener) {
lessonListeners.add(lessonListener)
}
fun removeLessonListener(lessonListener: LessonListener) {
lessonListeners.remove(lessonListener)
}
//-------------------------------------------------------------
internal val passed: Boolean
@@ -43,10 +51,6 @@ abstract class Lesson(@NonNls val id: String, @Nls val name: String) {
internal val lessonListeners: MutableList<LessonListener> = mutableListOf()
internal fun addLessonListener(lessonListener: LessonListener) {
lessonListeners.add(lessonListener)
}
internal fun onStart() {
lessonListeners.forEach { it.lessonStarted(this) }
}

View File

@@ -75,7 +75,7 @@ class LessonManager {
internal fun lessonIsRunning() : Boolean = currentLessonExecutor?.hasBeenStopped?.not() ?: false
internal fun stopLesson() {
fun stopLesson() {
shownRestoreNotification = null
currentLessonExecutor?.takeIf { !it.hasBeenStopped }?.let {
it.lesson.onStop()

View File

@@ -37,7 +37,15 @@ python.onboarding.case.changed=The case has changed.
python.onboarding.epilog=Congratulations! You have completed the onboarding tour. At this point you can:\
\n - <callback id="{0}">Close</callback> the learning project{1}\
\n - <callback id="{2}">Show</callback> more lessons
python.onboarding.return.to.welcome=\ and return to the welcome screen
python.onboarding.return.to.welcome=\ and return to the Welcome screen
python.onboarding.finish.title=Congratulations
python.onboarding.finish.text=You have just completed the PyCharm Onboarding tour.\n\
Now you can close the Learning project{0}.\n\
You can also continue your study and try other lessons.
python.onboarding.finish.exit=Close demo project
python.onboarding.finish.modules=Show more lessons
python.f.string.completion.lesson.name=F-string completion
python.f.string.completion.type.prefix=<ide/> supports automatic f-string conversion. Just start typing {0}.

View File

@@ -22,6 +22,8 @@ import com.intellij.openapi.editor.LogicalPosition
import com.intellij.openapi.fileEditor.FileEditorManager
import com.intellij.openapi.project.ProjectManager
import com.intellij.openapi.roots.ProjectRootManager
import com.intellij.openapi.ui.MessageDialogBuilder
import com.intellij.openapi.ui.Messages
import com.intellij.openapi.ui.popup.Balloon
import com.intellij.openapi.wm.ToolWindowManager
import com.intellij.openapi.wm.impl.FocusManagerImpl
@@ -33,6 +35,7 @@ import com.intellij.xdebugger.XDebuggerBundle
import com.jetbrains.python.PyBundle
import com.jetbrains.python.PyPsiBundle
import com.jetbrains.python.ift.PythonLessonsBundle
import icons.FeaturesTrainerIcons
import org.intellij.lang.annotations.Language
import org.jetbrains.annotations.Nls
import training.dsl.*
@@ -42,7 +45,10 @@ import training.dsl.LessonUtil.restoreIfModifiedOrMoved
import training.learn.LearnBundle
import training.learn.LessonsBundle
import training.learn.course.KLesson
import training.learn.course.Lesson
import training.learn.course.LessonProperties
import training.learn.lesson.LessonListener
import training.learn.lesson.LessonManager
import training.learn.lesson.general.run.toggleBreakpointTask
import training.ui.LearningUiHighlightingManager
import training.ui.LearningUiManager
@@ -82,6 +88,7 @@ class PythonOnboardingTour :
override val lessonContent: LessonContext.() -> Unit = {
prepareRuntimeTask {
addEndLessonListener()
configurations().forEach { runManager().removeConfiguration(it) }
val root = ProjectRootManager.getInstance(project).contentRoots[0]
@@ -111,15 +118,51 @@ class PythonOnboardingTour :
searchEverywhereTasks()
task {
val isSingleProject = ProjectManager.getInstance().openProjects.size == 1
val welcomeScreenRemark = if (isSingleProject) PythonLessonsBundle.message("python.onboarding.return.to.welcome") else ""
text(PythonLessonsBundle.message("python.onboarding.epilog",
getCallBackActionId("CloseProject"),
welcomeScreenRemark,
returnToWelcomeScreenRemark(),
LearningUiManager.addCallback { LearningUiManager.resetModulesView() }))
}
}
private fun returnToWelcomeScreenRemark(): String {
val isSingleProject = ProjectManager.getInstance().openProjects.size == 1
return if (isSingleProject) PythonLessonsBundle.message("python.onboarding.return.to.welcome") else ""
}
private fun TaskRuntimeContext.addEndLessonListener() {
val listener = object : LessonListener {
override fun lessonPassed(lesson: Lesson) {
invokeLater {
val result = MessageDialogBuilder.yesNoCancel(PythonLessonsBundle.message("python.onboarding.finish.title"),
PythonLessonsBundle.message("python.onboarding.finish.text", returnToWelcomeScreenRemark()))
.yesText(PythonLessonsBundle.message("python.onboarding.finish.exit"))
.noText(PythonLessonsBundle.message("python.onboarding.finish.modules"))
.icon(FeaturesTrainerIcons.Img.PluginIcon)
.show(project)
when (result) {
Messages.YES -> invokeLater {
LessonManager.instance.stopLesson()
val closeAction = ActionManager.getInstance().getAction("CloseProject") ?: error("No close project action found")
invokeActionForFocusContext(closeAction)
}
Messages.NO -> invokeLater {
LearningUiManager.resetModulesView()
}
}
}
}
override fun lessonStopped(lesson: Lesson) {
invokeLater {
removeLessonListener(this)
}
}
}
addLessonListener(listener)
}
private fun getCallBackActionId(@Suppress("SameParameterValue") actionId: String): Int {
val action = ActionManager.getInstance().getAction(actionId) ?: error("No action with Id $actionId")
return LearningUiManager.addCallback { invokeActionForFocusContext(action) }