refactoring pycharm educational second iteration

extracted interactive-learning (language independent) and interactive-learning-python modules
This commit is contained in:
Ekaterina Tuzova
2015-01-14 17:18:49 +03:00
parent ce963db18f
commit 01c96de0b7
96 changed files with 796 additions and 552 deletions
@@ -1,27 +0,0 @@
package icons;
import com.intellij.openapi.util.IconLoader;
import javax.swing.*;
/**
* NOTE THIS FILE IS AUTO-GENERATED
* DO NOT EDIT IT BY HAND, run build/scripts/icons.gant instead
*/
public class StudyIcons {
private static Icon load(String path) {
return IconLoader.getIcon(path, StudyIcons.class);
}
public static final Icon EducationalProjectType = load("/icons/com/jetbrains/python/edu/EducationalProjectType.png"); // 16x16
public static final Icon Lesson = load("/icons/com/jetbrains/python/edu/Lesson.png"); // 16x16
public static final Icon LessonCompl = load("/icons/com/jetbrains/python/edu/LessonCompl.png"); // 16x16
public static final Icon Prev = load("/icons/com/jetbrains/python/edu/prev.png"); // 16x16
public static final Icon Resolve = load("/icons/com/jetbrains/python/edu/resolve.png"); // 16x16
public static final Icon Sandbox = load("/icons/com/jetbrains/python/edu/Sandbox.png"); // 16x16
public static final Icon ShowHint = load("/icons/com/jetbrains/python/edu/showHint.png"); // 16x16
public static final Icon Task = load("/icons/com/jetbrains/python/edu/Task.png"); // 16x16
public static final Icon TaskCompl = load("/icons/com/jetbrains/python/edu/TaskCompl.png"); // 16x16
public static final Icon TaskProbl = load("/icons/com/jetbrains/python/edu/TaskProbl.png"); // 16x16
public static final Icon WatchInput = load("/icons/com/jetbrains/python/edu/WatchInput.png"); // 24x24
}
-21
View File
@@ -1,21 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/gen" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/resources" type="java-resource" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="platform-impl" />
<orderEntry type="module" module-name="python-community" />
<orderEntry type="module" module-name="lang-impl" />
<orderEntry type="library" name="gson" level="project" />
<orderEntry type="library" scope="TEST" name="JUnit4" level="project" />
<orderEntry type="module" module-name="python-ide-community" />
<orderEntry type="module" module-name="testFramework" scope="TEST" />
</component>
</module>
@@ -1,82 +0,0 @@
<!--suppress XmlUnboundNsPrefix -->
<idea-plugin version="2">
<id>com.jetbrains.python.edu.learn-python</id>
<name>Educational plugin for PyCharm</name>
<version>1.2</version>
<description><![CDATA[
Educational plugin for students. This plugin allows to learn Python
using intelligent PyCharm IDE.
]]></description>
<change-notes><![CDATA[
]]>
</change-notes>
<!--depends>com.intellij.modules.python</depends-->
<!-- please see http://confluence.jetbrains.net/display/IDEADEV/Plugin+Compatibility+with+IntelliJ+Platform+Products
on how to target different products -->
<depends>com.intellij.modules.lang</depends>
<depends>com.intellij.modules.python</depends>
<project-components>
<component>
<implementation-class>com.jetbrains.python.edu.StudyTaskManager</implementation-class>
<interface-class>com.jetbrains.python.edu.StudyTaskManager</interface-class>
</component>
</project-components>
<application-components>
<component>
<implementation-class>com.jetbrains.python.edu.StudyInitialConfigurator</implementation-class>
<headless-implementation-class/>
</component>
</application-components>
<actions>
<action id="CheckAction" class="com.jetbrains.python.edu.actions.StudyCheckAction" text="Check Task"
description="Check current task">
</action>
<action id="PrevWindowAction" class="com.jetbrains.python.edu.actions.StudyPrevWindowAction" text="Previous Answer Placeholder"
description="Navigate to the previous answer placeholder">
</action>
<action id="NextWindow" class="com.jetbrains.python.edu.actions.StudyNextWindowAction" text="Next Answer Placeholder"
description="Navigate to the next answer holder">
</action>
<action id="PreviousTaskAction" class="com.jetbrains.python.edu.actions.StudyPreviousStudyTaskAction" text="Previous Task"
description="Navigate to previous task"/>
<action id="NextTaskAction" class="com.jetbrains.python.edu.actions.StudyNextStudyTaskAction" text="Next Task"
description="Navigate to next task"/>
<action id="RefreshTaskAction" class="com.jetbrains.python.edu.actions.StudyRefreshTaskFileAction" text="Reset Task File"
description="Refresh current task"/>
<action id="WatchInputAction" class="com.jetbrains.python.edu.actions.StudyEditInputAction" text="Watch Test Input"
description="Watch test input "/>
<action id="ShowHintAction" class="com.jetbrains.python.edu.actions.StudyShowHintAction" text="Show Hint for Answer Placeholder"
description="Show hint for answer placeholder"/>
<action id="StudyRunAction" class="com.jetbrains.python.edu.actions.StudyRunAction" text="Run File With Tests"
description="Run your code with tests"/>
<action id="WelcomeScreen.PythonIntro" class="com.jetbrains.python.edu.actions.StudyIntroductionCourseAction" icon="StudyIcons.EducationalProjectType">
<add-to-group group-id="WelcomeScreen.QuickStart" anchor="first"/>
</action>
<action id="StudyWatchTutorial" class="com.jetbrains.python.edu.actions.StudyWatchTutorialAction">
<add-to-group group-id="HelpMenu" anchor="first"/>
</action>
</actions>
<extensions defaultExtensionNs="com.intellij">
<toolWindow id="Course Description" anchor="right" factoryClass="com.jetbrains.python.edu.ui.StudyToolWindowFactory" conditionClass="com.jetbrains.python.edu.ui.StudyCondition"/>
<fileEditorProvider implementation="com.jetbrains.python.edu.editor.StudyFileEditorProvider"/>
<directoryProjectGenerator implementation="com.jetbrains.python.edu.StudyDirectoryProjectGenerator"/>
<treeStructureProvider implementation="com.jetbrains.python.edu.projectView.StudyTreeStructureProvider"/>
<applicationService serviceInterface="com.intellij.openapi.fileEditor.impl.EditorEmptyTextPainter"
serviceImplementation="com.jetbrains.python.edu.StudyInstructionPainter" overrides="true"/>
<errorHandler implementation="com.intellij.diagnostic.ITNReporter"/>
</extensions>
<extensions defaultExtensionNs="Pythonid">
<visitorFilter language="Python" implementationClass="com.jetbrains.python.edu.highlighting.StudyVisitorFilter"/>
</extensions>
</idea-plugin>
@@ -1,5 +0,0 @@
package com.jetbrains.python.edu;
public interface StudyResourceManger {
String USER_TESTER = "user_tester.py";
}
@@ -1,96 +0,0 @@
package com.jetbrains.python.edu.actions;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.RunContentExecutor;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.execution.process.OSProcessHandler;
import com.intellij.execution.process.ProcessHandler;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.vfs.VirtualFile;
import com.jetbrains.python.edu.StudyResourceManger;
import com.jetbrains.python.edu.StudyTaskManager;
import com.jetbrains.python.edu.StudyUtils;
import com.jetbrains.python.edu.course.Task;
import com.jetbrains.python.edu.course.TaskFile;
import com.jetbrains.python.edu.editor.StudyEditor;
import com.jetbrains.python.run.PythonTracebackFilter;
import org.jetbrains.annotations.NotNull;
import java.io.File;
public class StudyRunAction extends DumbAwareAction {
private static final Logger LOG = Logger.getInstance(StudyRunAction.class.getName());
public static final String ACTION_ID = "StudyRunAction";
private ProcessHandler myHandler;
public void run(@NotNull final Project project, @NotNull final Sdk sdk) {
if (myHandler != null && !myHandler.isProcessTerminated()) return;
Editor selectedEditor = StudyEditor.getSelectedEditor(project);
FileDocumentManager fileDocumentManager = FileDocumentManager.getInstance();
assert selectedEditor != null;
VirtualFile openedFile = fileDocumentManager.getFile(selectedEditor.getDocument());
StudyTaskManager taskManager = StudyTaskManager.getInstance(project);
if (openedFile != null && openedFile.getCanonicalPath() != null) {
String filePath = openedFile.getCanonicalPath();
GeneralCommandLine cmd = new GeneralCommandLine();
cmd.withWorkDirectory(openedFile.getParent().getCanonicalPath());
String pythonPath = sdk.getHomePath();
if (pythonPath != null) {
cmd.setExePath(pythonPath);
TaskFile selectedTaskFile = taskManager.getTaskFile(openedFile);
assert selectedTaskFile != null;
Task currentTask = selectedTaskFile.getTask();
if (!currentTask.getUserTests().isEmpty()) {
cmd.addParameter(new File(project.getBaseDir().getPath(), StudyResourceManger.USER_TESTER).getPath());
cmd.addParameter(pythonPath);
cmd.addParameter(filePath);
Process process;
try {
process = cmd.createProcess();
}
catch (ExecutionException e) {
LOG.error(e);
return;
}
myHandler = new OSProcessHandler(process);
RunContentExecutor executor = new RunContentExecutor(project, myHandler).withFilter(new PythonTracebackFilter(project));
Disposer.register(project, executor);
executor.run();
return;
}
try {
cmd.addParameter(filePath);
Process p = cmd.createProcess();
myHandler = new OSProcessHandler(p);
RunContentExecutor executor = new RunContentExecutor(project, myHandler).withFilter(new PythonTracebackFilter(project));
Disposer.register(project, executor);
executor.run();
}
catch (ExecutionException e) {
LOG.error(e);
}
}
}
}
public void actionPerformed(@NotNull AnActionEvent e) {
Project project = e.getProject();
if (project == null) {
return;
}
Sdk sdk = StudyUtils.findPythonSdk(project);
if (sdk == null) {
return;
}
run(project, sdk);
}
}
+2 -1
View File
@@ -15,9 +15,10 @@
<orderEntry type="module" module-name="platform-main" />
<orderEntry type="module" module-name="ShortcutPromoter" />
<orderEntry type="module" module-name="python-educational" />
<orderEntry type="module" module-name="learn-python" />
<orderEntry type="module" module-name="course-creator" />
<orderEntry type="module" module-name="course-creator-python" />
<orderEntry type="module" module-name="interactive-learning" />
<orderEntry type="module" module-name="interactive-learning-python" />
<orderEntry type="module" module-name="hg4idea" />
</component>
</module>
@@ -4,8 +4,26 @@
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="interactive-learning" />
<orderEntry type="module" module-name="lang-impl" />
<orderEntry type="module" module-name="python-community" />
<orderEntry type="module" module-name="platform-impl" />
<orderEntry type="module" module-name="python-ide-community" />
<orderEntry type="library" name="gson" level="project" />
<orderEntry type="module-library" scope="TEST">
<library>
<CLASSES>
<root url="jar://$APPLICATION_HOME_DIR$/lib/junit.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
<orderEntry type="module" module-name="testFramework" scope="TEST" />
</component>
</module>
@@ -0,0 +1,43 @@
<!--suppress XmlUnboundNsPrefix -->
<idea-plugin version="2">
<id>com.jetbrains.python.edu.interactivelearning.python</id>
<name>Educational plugin for PyCharm</name>
<version>2.0</version>
<description><![CDATA[
Educational plugin for students. This plugin allows to learn Python
using intelligent PyCharm IDE.
]]></description>
<change-notes><![CDATA[
]]>
</change-notes>
<!--depends>com.intellij.modules.python</depends-->
<!-- please see http://confluence.jetbrains.net/display/IDEADEV/Plugin+Compatibility+with+IntelliJ+Platform+Products
on how to target different products -->
<depends>com.intellij.modules.lang</depends>
<depends>com.intellij.modules.python</depends>
<depends>com.jetbrains.edu.interactivelearning</depends>
<extensions defaultExtensionNs="com.intellij">
<directoryProjectGenerator implementation="com.jetbrains.edu.learning.PyStudyDirectoryProjectGenerator"/>
</extensions>
<extensions defaultExtensionNs="Pythonid">
<visitorFilter language="Python" implementationClass="com.jetbrains.edu.learning.highlighting.PyStudyVisitorFilter"/>
</extensions>
<extensions defaultExtensionNs="Edu">
<StudyUtils implementation="com.jetbrains.edu.learning.PyStudyUtils"/>
</extensions>
<actions>
<action id="WelcomeScreen.PythonIntro" class="com.jetbrains.edu.learning.actions.PyStudyIntroductionCourseAction" icon="InteractiveLearningPythonIcons.EducationalProjectType">
<add-to-group group-id="WelcomeScreen.QuickStart" anchor="first"/>
</action>
<action id="StudyWatchTutorial" class="com.jetbrains.edu.learning.actions.PyStudyWatchTutorialAction">
<add-to-group group-id="HelpMenu" anchor="first"/>
</action>
</actions>
</idea-plugin>
@@ -0,0 +1,95 @@
package com.jetbrains.edu.learning;
import com.intellij.facet.ui.FacetEditorValidator;
import com.intellij.facet.ui.FacetValidatorsManager;
import com.intellij.facet.ui.ValidationResult;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.platform.DirectoryProjectGenerator;
import com.jetbrains.edu.learning.course.CourseInfo;
import com.jetbrains.edu.learning.ui.StudyNewProjectPanel;
import com.jetbrains.python.newProject.PythonProjectGenerator;
import icons.InteractiveLearningPythonIcons;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.io.File;
import java.util.Map;
public class PyStudyDirectoryProjectGenerator extends PythonProjectGenerator implements DirectoryProjectGenerator {
private final StudyProjectGenerator myGenerator;
public ValidationResult myValidationResult = new ValidationResult("selected course is not valid");
public PyStudyDirectoryProjectGenerator() {
myGenerator = new StudyProjectGenerator();
myGenerator.addSettingsStateListener(new StudyProjectGenerator.SettingsListener() {
@Override
public void stateChanged(ValidationResult result) {
setValidationResult(result);
}
});
}
@Nls
@NotNull
@Override
public String getName() {
return "Educational";
}
@Nullable
@Override
public Object showGenerationSettings(VirtualFile baseDir) throws ProcessCanceledException {
return null;
}
@Nullable
@Override
public Icon getLogo() {
return InteractiveLearningPythonIcons.EducationalProjectType;
}
@Override
public void generateProject(@NotNull final Project project, @NotNull final VirtualFile baseDir,
@Nullable Object settings, @NotNull Module module) {
myGenerator.generateProject(project, baseDir);
}
@NotNull
@Override
public ValidationResult validate(@NotNull String s) {
return myValidationResult;
}
public void setValidationResult(ValidationResult validationResult) {
myValidationResult = validationResult;
}
@Nullable
@Override
public JPanel extendBasePanel() throws ProcessCanceledException {
StudyNewProjectPanel settingsPanel = new StudyNewProjectPanel(myGenerator);
settingsPanel.registerValidators(new FacetValidatorsManager() {
public void registerValidator(FacetEditorValidator validator, JComponent... componentsToWatch) {
throw new UnsupportedOperationException();
}
public void validate() {
fireStateChanged();
}
});
return settingsPanel.getContentPanel();
}
public Map<CourseInfo, File> getCourses() {
return myGenerator.getCourses();
}
public void setSelectedCourse(CourseInfo course) {
myGenerator.setSelectedCourse(course);
}
}
@@ -1,36 +1,26 @@
package com.jetbrains.python.edu;
package com.jetbrains.edu.learning;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.execution.process.ProcessOutput;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.jetbrains.python.edu.course.Course;
import com.jetbrains.python.edu.course.Task;
import com.jetbrains.edu.learning.course.Course;
import com.jetbrains.edu.learning.course.Task;
import com.jetbrains.python.sdk.PythonSdkType;
import org.jetbrains.annotations.NotNull;
import java.io.*;
import java.io.File;
import java.util.Map;
public class StudyTestRunner {
public static final String STUDY_PREFIX="#educational_plugin";
public static final String TEST_OK = "test OK";
private static final String TEST_FAILED = "FAILED + ";
public class PyStudyTestRunner extends StudyTestRunner {
private static final String PYTHONPATH = "PYTHONPATH";
private static final Logger LOG = Logger.getInstance(StudyTestRunner.class);
private final Task myTask;
private final VirtualFile myTaskDir;
public StudyTestRunner(Task task, VirtualFile taskDir) {
myTask = task;
myTaskDir = taskDir;
PyStudyTestRunner(@NotNull final Task task, @NotNull final VirtualFile taskfile) {
super(task, taskfile);
}
public Process createCheckProcess(Project project, String executablePath) throws ExecutionException {
Sdk sdk = PythonSdkType.findPythonSdk(ModuleManager.getInstance(project).getModules()[0]);
File testRunner = new File(myTaskDir.getPath(), myTask.getTestFile());
@@ -61,20 +51,4 @@ public class StudyTestRunner {
}
return null;
}
@NotNull
public String getTestsOutput(@NotNull final ProcessOutput processOutput) {
for (String line : processOutput.getStdoutLines()) {
if (line.contains(STUDY_PREFIX)) {
if (line.contains(TEST_OK)) {
continue;
}
int messageStart = line.indexOf(TEST_FAILED);
return line.substring(messageStart + TEST_FAILED.length());
}
}
return TEST_OK;
}
}
@@ -0,0 +1,76 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jetbrains.edu.learning;
import com.intellij.execution.RunContentExecutor;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.execution.process.ProcessHandler;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.vfs.VirtualFile;
import com.jetbrains.edu.learning.course.Task;
import com.jetbrains.python.run.PythonTracebackFilter;
import com.jetbrains.python.sdk.PythonSdkType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
public class PyStudyUtils implements StudyUtilsExtensionPoint {
@Override
public Sdk findSdk(@NotNull final Project project) {
return PythonSdkType.findPythonSdk(ModuleManager.getInstance(project).getModules()[0]);
}
@Nullable
@Override
public String getLinkToTutorial() {
return "<html>If you'd like to learn" +
" more about PyCharm " +
"Educational Edition, " +
"click <a href=\"https://www.jetbrains.com/pycharm-educational/quickstart/\">here</a> to watch a tutorial</html>";
}
@Override
public StudyTestRunner getTestRunner(@NotNull final Task task, @NotNull final VirtualFile taskDir) {
return new PyStudyTestRunner(task, taskDir);
}
@Override
public RunContentExecutor getExecutor(@NotNull final Project project, @NotNull final ProcessHandler handler) {
return new RunContentExecutor(project, handler).withFilter(new PythonTracebackFilter(project));
}
@Override
public void setCommandLineParameters(@NotNull final GeneralCommandLine cmd,
@NotNull final Project project,
@NotNull final String filePath,
@NotNull final String pythonPath,
@NotNull final Task currentTask) {
if (!currentTask.getUserTests().isEmpty()) {
cmd.addParameter(new File(project.getBaseDir().getPath(), StudyNames.USER_TESTER).getPath());
cmd.addParameter(pythonPath);
cmd.addParameter(filePath);
}
else {
cmd.addParameter(filePath);
}
}
}
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jetbrains.python.edu.actions;
package com.jetbrains.edu.learning.actions;
import com.intellij.ide.impl.ProjectUtil;
import com.intellij.openapi.actionSystem.AnAction;
@@ -21,23 +21,23 @@ import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.projectRoots.Sdk;
import com.jetbrains.edu.learning.PyStudyDirectoryProjectGenerator;
import com.jetbrains.edu.learning.StudyUtils;
import com.jetbrains.edu.learning.course.CourseInfo;
import com.jetbrains.python.configuration.PyConfigurableInterpreterList;
import com.jetbrains.python.edu.StudyDirectoryProjectGenerator;
import com.jetbrains.python.edu.StudyUtils;
import com.jetbrains.python.edu.course.CourseInfo;
import com.jetbrains.python.newProject.actions.GenerateProjectCallback;
import com.jetbrains.python.newProject.actions.ProjectSpecificSettingsStep;
import icons.StudyIcons;
import icons.InteractiveLearningPythonIcons;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.util.List;
import java.util.Map;
public class StudyIntroductionCourseAction extends AnAction {
public class PyStudyIntroductionCourseAction extends AnAction {
public StudyIntroductionCourseAction() {
super("Introduction to Python", "Introduction to Python", StudyIcons.EducationalProjectType);
public PyStudyIntroductionCourseAction() {
super("Introduction to Python", "Introduction to Python", InteractiveLearningPythonIcons.EducationalProjectType);
}
@Override
@@ -48,7 +48,7 @@ public class StudyIntroductionCourseAction extends AnAction {
}
else {
final GenerateProjectCallback callback = new GenerateProjectCallback();
final StudyDirectoryProjectGenerator generator = new StudyDirectoryProjectGenerator();
final PyStudyDirectoryProjectGenerator generator = new PyStudyDirectoryProjectGenerator();
final Map<CourseInfo, File> courses = generator.getCourses();
CourseInfo introCourse = null;
for (CourseInfo info : courses.keySet()) {
@@ -1,12 +1,12 @@
package com.jetbrains.python.edu.actions;
package com.jetbrains.edu.learning.actions;
import com.intellij.ide.BrowserUtil;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.project.DumbAwareAction;
import org.jetbrains.annotations.NotNull;
public class StudyWatchTutorialAction extends DumbAwareAction {
public StudyWatchTutorialAction() {
public class PyStudyWatchTutorialAction extends DumbAwareAction {
public PyStudyWatchTutorialAction() {
super("Learn more about PyCharm Educational Edition", null, null);
}
@@ -1,12 +1,12 @@
package com.jetbrains.python.edu.highlighting;
package com.jetbrains.edu.learning.highlighting;
import com.intellij.psi.PsiFile;
import com.jetbrains.python.edu.StudyTaskManager;
import com.jetbrains.edu.learning.StudyTaskManager;
import com.jetbrains.python.inspections.PythonVisitorFilter;
import com.jetbrains.python.inspections.unresolvedReference.PyUnresolvedReferencesInspection;
import org.jetbrains.annotations.NotNull;
public class StudyVisitorFilter implements PythonVisitorFilter {
public class PyStudyVisitorFilter implements PythonVisitorFilter {
@Override
public boolean isSupported(@NotNull final Class visitorClass, @NotNull final PsiFile file) {
if (StudyTaskManager.getInstance(file.getProject()).getCourse() == null) return true;
@@ -0,0 +1,17 @@
package icons;
import com.intellij.openapi.util.IconLoader;
import javax.swing.*;
/**
* NOTE THIS FILE IS AUTO-GENERATED
* DO NOT EDIT IT BY HAND, run build/scripts/icons.gant instead
*/
public class InteractiveLearningPythonIcons {
private static Icon load(String path) {
return IconLoader.getIcon(path, InteractiveLearningPythonIcons.class);
}
public static final Icon EducationalProjectType = load("/icons/com/jetbrains/edu/learning/EducationalProjectType.png"); // 16x16
}
@@ -1,32 +1,30 @@
import com.google.gson.FieldNamingPolicy;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.junit.Before;
import org.junit.Test;
import com.jetbrains.python.edu.StudyUtils;
import com.jetbrains.python.edu.course.Course;
import com.jetbrains.edu.learning.StudyUtils;
import com.jetbrains.edu.learning.course.Course;
import com.jetbrains.python.PythonHelpersLocator;
import junit.framework.TestCase;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStreamReader;
import java.io.Reader;
import static org.junit.Assert.assertEquals;
/**
* author: liana
* data: 7/4/14.
*/
public class JsonParserTest {
public class JsonParserTest extends TestCase {
private Course myCourse = null;
@Before
public void setUp() throws FileNotFoundException {
Reader reader = new InputStreamReader(new FileInputStream("testData/course.json"));
public void setUp() throws Exception {
super.setUp();
Reader reader = new InputStreamReader(new FileInputStream(getTestDataPath() + "/course.json"));
Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create();
myCourse = gson.fromJson(reader, Course.class);
}
@Test
public void testCourseLevel() {
assertEquals(myCourse.getName(), "Python для начинающих");
assertEquals(StudyUtils.getFirst(myCourse.getLessons().get(1).getTaskList().get(0).getUserTests()).getInput(), "sum-input.txt");
@@ -34,4 +32,7 @@ public class JsonParserTest {
assertEquals(myCourse.getLessons().get(0).getTaskList().size(), 2);
assertEquals(myCourse.getLessons().get(1).getTaskList().size(), 1);
}
protected String getTestDataPath() {
return PythonHelpersLocator.getPythonCommunityPath() + "/edu/learn-python/testData";
}
}
@@ -3,9 +3,9 @@ import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.psi.PsiFile;
import com.jetbrains.python.edu.StudyDocumentListener;
import com.jetbrains.python.edu.course.TaskFile;
import com.jetbrains.python.edu.course.TaskWindow;
import com.jetbrains.edu.learning.StudyDocumentListener;
import com.jetbrains.edu.learning.course.TaskFile;
import com.jetbrains.edu.learning.course.TaskWindow;
import java.util.ArrayList;
import java.util.List;
@@ -16,6 +16,9 @@ import org.jetbrains.annotations.NotNull;
public class CCProjectGeneratorUtil {
private CCProjectGeneratorUtil() {
}
public static void generateProject(@NotNull final Project project, @NotNull final VirtualFile baseDir,
@NotNull final String name, @NotNull final String author,
@NotNull final String description) {
@@ -4,8 +4,11 @@
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/resources" type="java-resource" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="lang-impl" />
<orderEntry type="library" name="gson" level="project" />
</component>
</module>
@@ -0,0 +1,74 @@
<!--suppress XmlUnboundNsPrefix -->
<idea-plugin version="2">
<id>com.jetbrains.edu.interactivelearning</id>
<name>Educational plugin core</name>
<version>2.0</version>
<description><![CDATA[
Educational plugin core for students.
]]></description>
<change-notes><![CDATA[
]]>
</change-notes>
<!--depends>com.intellij.modules.python</depends-->
<!-- please see http://confluence.jetbrains.net/display/IDEADEV/Plugin+Compatibility+with+IntelliJ+Platform+Products
on how to target different products -->
<depends>com.intellij.modules.lang</depends>
<project-components>
<component>
<implementation-class>com.jetbrains.edu.learning.StudyTaskManager</implementation-class>
<interface-class>com.jetbrains.edu.learning.StudyTaskManager</interface-class>
</component>
</project-components>
<application-components>
<component>
<implementation-class>com.jetbrains.edu.learning.StudyInitialConfigurator</implementation-class>
<headless-implementation-class/>
</component>
</application-components>
<extensionPoints>
<extensionPoint qualifiedName="Edu.StudyUtils" interface="com.jetbrains.edu.learning.StudyUtilsExtensionPoint"/>
</extensionPoints>
<actions>
<action id="CheckAction" class="com.jetbrains.edu.learning.actions.StudyCheckAction" text="Check Task"
description="Check current task">
</action>
<action id="PrevWindowAction" class="com.jetbrains.edu.learning.actions.StudyPrevWindowAction" text="Previous Answer Placeholder"
description="Navigate to the previous answer placeholder">
</action>
<action id="NextWindow" class="com.jetbrains.edu.learning.actions.StudyNextWindowAction" text="Next Answer Placeholder"
description="Navigate to the next answer holder">
</action>
<action id="PreviousTaskAction" class="com.jetbrains.edu.learning.actions.StudyPreviousStudyTaskAction" text="Previous Task"
description="Navigate to previous task"/>
<action id="NextTaskAction" class="com.jetbrains.edu.learning.actions.StudyNextStudyTaskAction" text="Next Task"
description="Navigate to next task"/>
<action id="RefreshTaskAction" class="com.jetbrains.edu.learning.actions.StudyRefreshTaskFileAction" text="Reset Task File"
description="Refresh current task"/>
<action id="WatchInputAction" class="com.jetbrains.edu.learning.actions.StudyEditInputAction" text="Watch Test Input"
description="Watch test input "/>
<action id="ShowHintAction" class="com.jetbrains.edu.learning.actions.StudyShowHintAction" text="Show Hint for Answer Placeholder"
description="Show hint for answer placeholder"/>
<action id="StudyRunAction" class="com.jetbrains.edu.learning.actions.StudyRunAction" text="Run File With Tests"
description="Run your code with tests"/>
</actions>
<extensions defaultExtensionNs="com.intellij">
<toolWindow id="Course Description" anchor="right" factoryClass="com.jetbrains.edu.learning.ui.StudyToolWindowFactory" conditionClass="com.jetbrains.edu.learning.ui.StudyCondition"/>
<fileEditorProvider implementation="com.jetbrains.edu.learning.editor.StudyFileEditorProvider"/>
<treeStructureProvider implementation="com.jetbrains.edu.learning.projectView.StudyTreeStructureProvider"/>
<applicationService serviceInterface="com.intellij.openapi.fileEditor.impl.EditorEmptyTextPainter"
serviceImplementation="com.jetbrains.edu.learning.StudyInstructionPainter" overrides="true"/>
<errorHandler implementation="com.intellij.diagnostic.ITNReporter"/>
</extensions>
</idea-plugin>
@@ -1,12 +1,12 @@
package com.jetbrains.python.edu;
package com.jetbrains.edu.learning;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.event.DocumentAdapter;
import com.intellij.openapi.editor.event.DocumentEvent;
import com.intellij.openapi.editor.impl.event.DocumentEventImpl;
import com.jetbrains.python.edu.course.TaskFile;
import com.jetbrains.python.edu.course.TaskWindow;
import com.jetbrains.edu.learning.course.TaskFile;
import com.jetbrains.edu.learning.course.TaskWindow;
import java.util.ArrayList;
import java.util.List;
@@ -1,4 +1,4 @@
package com.jetbrains.python.edu;
package com.jetbrains.edu.learning;
import com.intellij.openapi.application.ApplicationManager;
@@ -12,9 +12,9 @@ import com.intellij.openapi.editor.event.EditorMouseEvent;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.jetbrains.python.edu.course.TaskFile;
import com.jetbrains.python.edu.course.TaskWindow;
import com.jetbrains.python.edu.editor.StudyEditor;
import com.jetbrains.edu.learning.course.TaskFile;
import com.jetbrains.edu.learning.course.TaskWindow;
import com.jetbrains.edu.learning.editor.StudyEditor;
import org.jetbrains.annotations.NotNull;
import java.awt.*;
@@ -1,4 +1,4 @@
package com.jetbrains.python.edu;
package com.jetbrains.edu.learning;
import com.intellij.codeInsight.CodeInsightSettings;
import com.intellij.ide.RecentProjectsManager;
@@ -1,4 +1,4 @@
package com.jetbrains.python.edu;
package com.jetbrains.edu.learning;
import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.actionSystem.AnAction;
@@ -12,7 +12,7 @@ import com.intellij.ui.JBColor;
import com.intellij.util.PairFunction;
import com.intellij.util.ui.GraphicsUtil;
import com.intellij.util.ui.UIUtil;
import com.jetbrains.python.edu.actions.*;
import com.jetbrains.edu.learning.actions.*;
import javax.swing.*;
import java.awt.*;
@@ -32,7 +32,7 @@ public class StudyInstructionPainter extends EditorEmptyTextPainter {
UIUtil.TextPainter painter = new UIUtil.TextPainter().withLineSpacing(1.5f);
painter.appendLine("PyCharm Educational Edition").underlined(new JBColor(Gray._150, Gray._180));
painter.appendLine("Educational Edition").underlined(new JBColor(Gray._150, Gray._180));
addAction(painter, "Navigate to the next answer placeholder", StudyNextWindowAction.ACTION_ID, StudyNextWindowAction.SHORTCUT2, true);
String shortcut1 = getShortcutText(StudyPrevWindowAction.ACTION_ID, StudyPrevWindowAction.SHORTCUT, false, false);
String shortcut2 = getShortcutText(StudyNextWindowAction.ACTION_ID, StudyNextWindowAction.SHORTCUT, false, false);
@@ -13,18 +13,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jetbrains.python.edu;
package com.jetbrains.edu.learning;
import org.jetbrains.annotations.NonNls;
@NonNls
public class StudyNames {
public static final String INTRODUCTION_COURSE = "introduction_course";
public static final String TASK_HTML = "task.html";
public static final String TASK_TESTS = "tests.py";
public static final String COURSES = "courses";
public static final String LESSON = "lesson";
public static final String TEST_HELPER = "test_helper.py";
public static final String USER_TESTER = "user_tester.py";
private StudyNames() {
}
@@ -1,9 +1,7 @@
package com.jetbrains.python.edu;
package com.jetbrains.edu.learning;
import com.google.gson.*;
import com.google.gson.stream.JsonReader;
import com.intellij.facet.ui.FacetEditorValidator;
import com.intellij.facet.ui.FacetValidatorsManager;
import com.intellij.facet.ui.ValidationResult;
import com.intellij.ide.projectView.ProjectView;
import com.intellij.ide.projectView.impl.AbstractProjectViewPane;
@@ -13,8 +11,6 @@ import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.vfs.LocalFileSystem;
@@ -24,29 +20,26 @@ import com.intellij.openapi.vfs.newvfs.NewVirtualFile;
import com.intellij.openapi.vfs.newvfs.impl.VirtualDirectoryImpl;
import com.intellij.openapi.wm.ex.ToolWindowManagerAdapter;
import com.intellij.openapi.wm.ex.ToolWindowManagerEx;
import com.intellij.platform.DirectoryProjectGenerator;
import com.intellij.platform.templates.github.GeneratorException;
import com.intellij.platform.templates.github.ZipUtil;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.jetbrains.python.edu.course.*;
import com.jetbrains.python.edu.ui.StudyNewProjectPanel;
import com.jetbrains.python.newProject.PythonProjectGenerator;
import icons.StudyIcons;
import org.jetbrains.annotations.Nls;
import com.intellij.util.containers.ContainerUtil;
import com.jetbrains.edu.learning.course.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.io.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class StudyDirectoryProjectGenerator extends PythonProjectGenerator implements DirectoryProjectGenerator {
private static final Logger LOG = Logger.getInstance(StudyDirectoryProjectGenerator.class.getName());
public class StudyProjectGenerator {
private static final Logger LOG = Logger.getInstance(StudyProjectGenerator.class.getName());
private final List<SettingsListener> myListeners = ContainerUtil.newArrayList();
private static final String REPO_URL = "https://github.com/JetBrains/pycharm-courses/archive/master.zip";
private static final String USER_NAME = "PyCharm";
private static final String COURSE_META_FILE = "course.json";
@@ -59,15 +52,6 @@ public class StudyDirectoryProjectGenerator extends PythonProjectGenerator imple
private Map<CourseInfo, File> myCourses = new HashMap<CourseInfo, File>();
private File mySelectedCourseFile;
private Project myProject;
public ValidationResult myValidationResult = new ValidationResult("selected course is not valid");
@Nls
@NotNull
@Override
public String getName() {
return "Educational";
}
public void setCourses(Map<CourseInfo, File> courses) {
myCourses = courses;
@@ -140,22 +124,7 @@ public class StudyDirectoryProjectGenerator extends PythonProjectGenerator imple
return null;
}
@Nullable
@Override
public Object showGenerationSettings(VirtualFile baseDir) throws ProcessCanceledException {
return null;
}
@Nullable
@Override
public Icon getLogo() {
return StudyIcons.EducationalProjectType;
}
@Override
public void generateProject(@NotNull final Project project, @NotNull final VirtualFile baseDir,
@Nullable Object settings, @NotNull Module module) {
public void generateProject(@NotNull final Project project, @NotNull final VirtualFile baseDir) {
myProject = project;
Reader reader = null;
@@ -336,42 +305,6 @@ public class StudyDirectoryProjectGenerator extends PythonProjectGenerator imple
return courseInfo;
}
@NotNull
@Override
public ValidationResult validate(@NotNull String s) {
return myValidationResult;
}
public void setValidationResult(ValidationResult validationResult) {
myValidationResult = validationResult;
}
/**
* @return courses from memory or from cash file or parses course directory
*/
public Map<CourseInfo, File> getCourses() {
if (!myCourses.isEmpty()) {
return myCourses;
}
if (myCoursesDir.exists()) {
File cacheFile = new File(myCoursesDir, CACHE_NAME);
if (cacheFile.exists()) {
myCourses = getCoursesFromCache(cacheFile);
if (!myCourses.isEmpty()) {
return myCourses;
}
}
myCourses = loadCourses();
if (!myCourses.isEmpty()) {
return myCourses;
}
}
downloadAndUnzip(false);
myCourses = loadCourses();
flushCache();
return myCourses;
}
/**
* Writes courses to cash file {@link com.jetbrains.python.edu.StudyDirectoryProjectGenerator#CACHE_NAME}
*/
@@ -417,7 +350,7 @@ public class StudyDirectoryProjectGenerator extends PythonProjectGenerator imple
Map<CourseInfo, File> coursesFromCash = new HashMap<CourseInfo, File>();
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(new FileInputStream(cashFile)));
reader = new BufferedReader(new InputStreamReader(new FileInputStream(cashFile)));
String line;
while ((line = reader.readLine()) != null) {
@@ -446,18 +379,43 @@ public class StudyDirectoryProjectGenerator extends PythonProjectGenerator imple
return coursesFromCash;
}
@Nullable
@Override
public JPanel extendBasePanel() throws ProcessCanceledException {
StudyNewProjectPanel settingsPanel = new StudyNewProjectPanel(this);
settingsPanel.registerValidators(new FacetValidatorsManager() {
public void registerValidator(FacetEditorValidator validator, JComponent... componentsToWatch) {
throw new UnsupportedOperationException();
/**
* @return courses from memory or from cash file or parses course directory
*/
public Map<CourseInfo, File> getCourses() {
if (!myCourses.isEmpty()) {
return myCourses;
}
if (myCoursesDir.exists()) {
File cacheFile = new File(myCoursesDir, CACHE_NAME);
if (cacheFile.exists()) {
myCourses = getCoursesFromCache(cacheFile);
if (!myCourses.isEmpty()) {
return myCourses;
}
}
public void validate() {
fireStateChanged();
myCourses = loadCourses();
if (!myCourses.isEmpty()) {
return myCourses;
}
});
return settingsPanel.getContentPanel();
}
downloadAndUnzip(false);
myCourses = loadCourses();
flushCache();
return myCourses;
}
public void addSettingsStateListener(@NotNull SettingsListener listener) {
myListeners.add(listener);
}
public interface SettingsListener {
void stateChanged(ValidationResult result);
}
public void fireStateChanged(ValidationResult result) {
for (SettingsListener listener : myListeners) {
listener.stateChanged(result);
}
}
}
@@ -1,11 +1,11 @@
package com.jetbrains.python.edu;
package com.jetbrains.edu.learning;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.vfs.VirtualFile;
import com.jetbrains.python.edu.course.Task;
import com.jetbrains.python.edu.course.TaskFile;
import com.jetbrains.python.edu.editor.StudyEditor;
import com.jetbrains.edu.learning.course.Task;
import com.jetbrains.edu.learning.course.TaskFile;
import com.jetbrains.edu.learning.editor.StudyEditor;
public class StudyState {
private final StudyEditor myStudyEditor;
@@ -1,4 +1,4 @@
package com.jetbrains.python.edu;
package com.jetbrains.edu.learning;
import com.intellij.ide.BrowserUtil;
import com.intellij.ide.ui.UISettings;
@@ -32,13 +32,13 @@ import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.openapi.wm.*;
import com.intellij.util.ui.update.UiNotifyConnector;
import com.intellij.util.xmlb.XmlSerializer;
import com.jetbrains.python.edu.actions.*;
import com.jetbrains.python.edu.course.Course;
import com.jetbrains.python.edu.course.Lesson;
import com.jetbrains.python.edu.course.Task;
import com.jetbrains.python.edu.course.TaskFile;
import com.jetbrains.python.edu.ui.StudyCondition;
import com.jetbrains.python.edu.ui.StudyToolWindowFactory;
import com.jetbrains.edu.learning.actions.*;
import com.jetbrains.edu.learning.course.Course;
import com.jetbrains.edu.learning.course.Lesson;
import com.jetbrains.edu.learning.course.Task;
import com.jetbrains.edu.learning.course.TaskFile;
import com.jetbrains.edu.learning.ui.StudyCondition;
import com.jetbrains.edu.learning.ui.StudyToolWindowFactory;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -201,10 +201,7 @@ public class StudyTaskManager implements ProjectComponent, PersistentStateCompon
@Override
public void run() {
if (PropertiesComponent.getInstance().getBoolean("StudyShowPopup", true)) {
String content = "<html>If you'd like to learn" +
" more about PyCharm " +
"Educational Edition, " +
"click <a href=\"https://www.jetbrains.com/pycharm-educational/quickstart/\">here</a> to watch a tutorial</html>";
String content = StudyUtils.getLinkToTutorial();
final Notification notification =
new Notification("Watch Tutorials!", "", content, NotificationType.INFORMATION, new UrlOpeningListener(true));
Notifications.Bus.notify(notification);
@@ -0,0 +1,38 @@
package com.jetbrains.edu.learning;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.process.ProcessOutput;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.jetbrains.edu.learning.course.Task;
import org.jetbrains.annotations.NotNull;
public abstract class StudyTestRunner {
public static final String STUDY_PREFIX="#educational_plugin";
public static final String TEST_OK = "test OK";
private static final String TEST_FAILED = "FAILED + ";
protected final Task myTask;
protected final VirtualFile myTaskDir;
public StudyTestRunner(@NotNull final Task task, @NotNull final VirtualFile taskDir) {
myTask = task;
myTaskDir = taskDir;
}
public abstract Process createCheckProcess(Project project, String executablePath) throws ExecutionException;
@NotNull
public String getTestsOutput(@NotNull final ProcessOutput processOutput) {
for (String line : processOutput.getStdoutLines()) {
if (line.contains(STUDY_PREFIX)) {
if (line.contains(TEST_OK)) {
continue;
}
int messageStart = line.indexOf(TEST_FAILED);
return line.substring(messageStart + TEST_FAILED.length());
}
}
return TEST_OK;
}
}
@@ -1,5 +1,8 @@
package com.jetbrains.python.edu;
package com.jetbrains.edu.learning;
import com.intellij.execution.RunContentExecutor;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.execution.process.ProcessHandler;
import com.intellij.ide.SaveAndSyncHandlerImpl;
import com.intellij.ide.projectView.actions.MarkRootActionBase;
import com.intellij.openapi.actionSystem.AnActionEvent;
@@ -11,7 +14,6 @@ import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileEditor.FileEditor;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
@@ -24,10 +26,9 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.openapi.wm.ToolWindowManager;
import com.intellij.util.ui.UIUtil;
import com.jetbrains.python.edu.course.*;
import com.jetbrains.python.edu.editor.StudyEditor;
import com.jetbrains.python.edu.ui.StudyToolWindowFactory;
import com.jetbrains.python.sdk.PythonSdkType;
import com.jetbrains.edu.learning.course.*;
import com.jetbrains.edu.learning.editor.StudyEditor;
import com.jetbrains.edu.learning.ui.StudyToolWindowFactory;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -35,6 +36,9 @@ import java.io.*;
import java.util.Collection;
public class StudyUtils {
private StudyUtils() {
}
private static final Logger LOG = Logger.getInstance(StudyUtils.class.getName());
public static void closeSilently(Closeable stream) {
@@ -199,8 +203,13 @@ public class StudyUtils {
}
@Nullable
public static Sdk findPythonSdk(@NotNull final Project project) {
return PythonSdkType.findPythonSdk(ModuleManager.getInstance(project).getModules()[0]);
public static Sdk findSdk(@NotNull final Project project) {
final StudyUtilsExtensionPoint[] extensions =
ApplicationManager.getApplication().getExtensions(StudyUtilsExtensionPoint.EP_NAME);
if (extensions.length > 0) {
return extensions[0].findSdk(project);
}
return null;
}
public static void markDirAsSourceRoot(@NotNull final VirtualFile dir, @NotNull final Project project) {
@@ -224,4 +233,43 @@ public class StudyUtils {
}
});
}
public static StudyTestRunner getTestRunner(@NotNull final Task task, @NotNull final VirtualFile taskDir) {
final StudyUtilsExtensionPoint[] extensions =
ApplicationManager.getApplication().getExtensions(StudyUtilsExtensionPoint.EP_NAME);
if (extensions.length > 0) {
return extensions[0].getTestRunner(task, taskDir);
}
return null;
}
public static String getLinkToTutorial() {
final StudyUtilsExtensionPoint[] extensions =
ApplicationManager.getApplication().getExtensions(StudyUtilsExtensionPoint.EP_NAME);
if (extensions.length > 0) {
return extensions[0].getLinkToTutorial();
}
return null;
}
public static RunContentExecutor getExecutor(@NotNull final Project project, @NotNull final ProcessHandler handler) {
final StudyUtilsExtensionPoint[] extensions =
ApplicationManager.getApplication().getExtensions(StudyUtilsExtensionPoint.EP_NAME);
if (extensions.length > 0) {
return extensions[0].getExecutor(project, handler);
}
return null;
}
public static void setCommandLineParameters(@NotNull final GeneralCommandLine cmd,
@NotNull final Project project,
@NotNull final String filePath,
@NotNull final String pythonPath,
@NotNull final Task currentTask) {
final StudyUtilsExtensionPoint[] extensions =
ApplicationManager.getApplication().getExtensions(StudyUtilsExtensionPoint.EP_NAME);
if (extensions.length > 0) {
extensions[0].setCommandLineParameters(cmd, project, filePath, pythonPath, currentTask);
}
}
}
@@ -0,0 +1,46 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jetbrains.edu.learning;
import com.intellij.execution.RunContentExecutor;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.execution.process.ProcessHandler;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.vfs.VirtualFile;
import com.jetbrains.edu.learning.course.Task;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public interface StudyUtilsExtensionPoint {
ExtensionPointName<StudyUtilsExtensionPoint> EP_NAME = ExtensionPointName.create("Edu.StudyUtils");
@Nullable
abstract Sdk findSdk(@NotNull final Project project);
abstract String getLinkToTutorial();
abstract StudyTestRunner getTestRunner(@NotNull final Task task, @NotNull final VirtualFile taskDir);
public RunContentExecutor getExecutor(@NotNull final Project project, @NotNull final ProcessHandler handler);
public void setCommandLineParameters(@NotNull final GeneralCommandLine cmd,
@NotNull final Project project,
@NotNull final String filePath,
@NotNull final String pythonPath,
@NotNull final Task currentTask);
}
@@ -1,4 +1,4 @@
package com.jetbrains.python.edu;
package com.jetbrains.edu.learning;
import com.intellij.codeInsight.hint.HintManager;
import com.intellij.openapi.editor.Editor;
@@ -1,4 +1,4 @@
package com.jetbrains.python.edu.actions;
package com.jetbrains.edu.learning.actions;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.process.CapturingProcessHandler;
@@ -33,15 +33,15 @@ import com.intellij.openapi.wm.IdeFrame;
import com.intellij.openapi.wm.WindowManager;
import com.intellij.openapi.wm.ex.StatusBarEx;
import com.intellij.openapi.wm.ex.WindowManagerEx;
import com.jetbrains.python.edu.StudyDocumentListener;
import com.jetbrains.python.edu.StudyState;
import com.jetbrains.python.edu.StudyTestRunner;
import com.jetbrains.python.edu.StudyUtils;
import com.jetbrains.python.edu.course.StudyStatus;
import com.jetbrains.python.edu.course.Task;
import com.jetbrains.python.edu.course.TaskFile;
import com.jetbrains.python.edu.course.TaskWindow;
import com.jetbrains.python.edu.editor.StudyEditor;
import com.jetbrains.edu.learning.StudyDocumentListener;
import com.jetbrains.edu.learning.StudyState;
import com.jetbrains.edu.learning.StudyTestRunner;
import com.jetbrains.edu.learning.StudyUtils;
import com.jetbrains.edu.learning.course.StudyStatus;
import com.jetbrains.edu.learning.course.Task;
import com.jetbrains.edu.learning.course.TaskFile;
import com.jetbrains.edu.learning.course.TaskWindow;
import com.jetbrains.edu.learning.editor.StudyEditor;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
@@ -133,7 +133,7 @@ public class StudyCheckAction extends DumbAwareAction {
final Task task = studyState.getTask();
final VirtualFile taskDir = studyState.getTaskDir();
flushWindows(task, taskDir);
Sdk sdk = StudyUtils.findPythonSdk(project);
final Sdk sdk = StudyUtils.findSdk(project);
if (sdk == null) {
createNoPythonInterpreterPopUp(project);
return;
@@ -149,7 +149,8 @@ public class StudyCheckAction extends DumbAwareAction {
IdeFocusManager.getInstance(project).requestFocus(studyState.getEditor().getComponent(), true);
}
});
final StudyTestRunner testRunner = new StudyTestRunner(task, taskDir);
final StudyTestRunner testRunner = StudyUtils.getTestRunner(task, taskDir);
Process testProcess = null;
try {
final VirtualFile executablePath = getTaskVirtualFile(studyState, task, taskDir);
@@ -1,4 +1,4 @@
package com.jetbrains.python.edu.actions;
package com.jetbrains.edu.learning.actions;
import com.intellij.icons.AllIcons;
import com.intellij.ide.ui.UISettings;
@@ -20,13 +20,13 @@ import com.intellij.ui.tabs.TabInfo;
import com.intellij.ui.tabs.TabsListener;
import com.intellij.ui.tabs.impl.JBEditorTabs;
import com.intellij.util.PlatformIcons;
import com.jetbrains.python.edu.StudyTaskManager;
import com.jetbrains.python.edu.StudyUtils;
import com.jetbrains.python.edu.course.Task;
import com.jetbrains.python.edu.course.TaskFile;
import com.jetbrains.python.edu.course.UserTest;
import com.jetbrains.python.edu.editor.StudyEditor;
import com.jetbrains.python.edu.ui.StudyTestContentPanel;
import com.jetbrains.edu.learning.StudyTaskManager;
import com.jetbrains.edu.learning.StudyUtils;
import com.jetbrains.edu.learning.course.Task;
import com.jetbrains.edu.learning.course.TaskFile;
import com.jetbrains.edu.learning.course.UserTest;
import com.jetbrains.edu.learning.editor.StudyEditor;
import com.jetbrains.edu.learning.ui.StudyTestContentPanel;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
@@ -154,7 +154,7 @@ public class StudyEditInputAction extends DumbAwareAction {
showInput(e.getProject());
}
private class HintClosedListener extends JBPopupAdapter {
private static class HintClosedListener extends JBPopupAdapter {
private final Task myTask;
private HintClosedListener(@NotNull final Task task) {
myTask = task;
@@ -1,7 +1,7 @@
package com.jetbrains.python.edu.actions;
package com.jetbrains.edu.learning.actions;
import com.jetbrains.python.edu.editor.StudyEditor;
import com.jetbrains.python.edu.course.Task;
import com.jetbrains.edu.learning.course.Task;
import com.jetbrains.edu.learning.editor.StudyEditor;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
@@ -1,8 +1,8 @@
package com.jetbrains.python.edu.actions;
package com.jetbrains.edu.learning.actions;
import com.intellij.icons.AllIcons;
import com.jetbrains.python.edu.StudyUtils;
import com.jetbrains.python.edu.course.TaskWindow;
import com.jetbrains.edu.learning.StudyUtils;
import com.jetbrains.edu.learning.course.TaskWindow;
import org.jetbrains.annotations.NotNull;
import java.util.List;
@@ -1,8 +1,8 @@
package com.jetbrains.python.edu.actions;
package com.jetbrains.edu.learning.actions;
import com.jetbrains.python.edu.StudyUtils;
import com.jetbrains.python.edu.course.TaskWindow;
import icons.StudyIcons;
import com.jetbrains.edu.learning.StudyUtils;
import com.jetbrains.edu.learning.course.TaskWindow;
import icons.InteractiveLearningIcons;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -17,7 +17,7 @@ public class StudyPrevWindowAction extends StudyWindowNavigationAction {
public static final String SHORTCUT = "ctrl shift pressed COMMA";
public StudyPrevWindowAction() {
super("Navigate to the Previous Answer Placeholder", "Navigate to the previous answer placeholder", StudyIcons.Prev);
super("Navigate to the Previous Answer Placeholder", "Navigate to the previous answer placeholder", InteractiveLearningIcons.Prev);
}
@@ -1,8 +1,8 @@
package com.jetbrains.python.edu.actions;
package com.jetbrains.edu.learning.actions;
import com.jetbrains.python.edu.editor.StudyEditor;
import com.jetbrains.python.edu.course.Task;
import com.jetbrains.edu.learning.course.Task;
import com.jetbrains.edu.learning.editor.StudyEditor;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
@@ -1,4 +1,4 @@
package com.jetbrains.python.edu.actions;
package com.jetbrains.edu.learning.actions;
import com.intellij.ide.projectView.ProjectView;
import com.intellij.openapi.actionSystem.AnActionEvent;
@@ -18,11 +18,11 @@ import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.wm.IdeFocusManager;
import com.jetbrains.python.edu.StudyDocumentListener;
import com.jetbrains.python.edu.StudyTaskManager;
import com.jetbrains.python.edu.StudyUtils;
import com.jetbrains.python.edu.course.*;
import com.jetbrains.python.edu.editor.StudyEditor;
import com.jetbrains.edu.learning.StudyDocumentListener;
import com.jetbrains.edu.learning.StudyTaskManager;
import com.jetbrains.edu.learning.StudyUtils;
import com.jetbrains.edu.learning.course.*;
import com.jetbrains.edu.learning.editor.StudyEditor;
import org.jetbrains.annotations.NotNull;
import java.io.File;
@@ -0,0 +1,82 @@
package com.jetbrains.edu.learning.actions;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.RunContentExecutor;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.execution.process.OSProcessHandler;
import com.intellij.execution.process.ProcessHandler;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.vfs.VirtualFile;
import com.jetbrains.edu.learning.StudyTaskManager;
import com.jetbrains.edu.learning.StudyUtils;
import com.jetbrains.edu.learning.course.Task;
import com.jetbrains.edu.learning.course.TaskFile;
import com.jetbrains.edu.learning.editor.StudyEditor;
import org.jetbrains.annotations.NotNull;
public class StudyRunAction extends DumbAwareAction {
private static final Logger LOG = Logger.getInstance(StudyRunAction.class.getName());
public static final String ACTION_ID = "StudyRunAction";
private ProcessHandler myHandler;
public void run(@NotNull final Project project, @NotNull final Sdk sdk) {
if (myHandler != null && !myHandler.isProcessTerminated()) return;
Editor selectedEditor = StudyEditor.getSelectedEditor(project);
FileDocumentManager fileDocumentManager = FileDocumentManager.getInstance();
assert selectedEditor != null;
VirtualFile openedFile = fileDocumentManager.getFile(selectedEditor.getDocument());
if (openedFile != null && openedFile.getCanonicalPath() != null) {
String filePath = openedFile.getCanonicalPath();
executeFile(project, sdk, openedFile, filePath);
}
}
private void executeFile(@NotNull final Project project, @NotNull final Sdk sdk,
@NotNull final VirtualFile openedFile, @NotNull final String filePath) {
StudyTaskManager taskManager = StudyTaskManager.getInstance(project);
GeneralCommandLine cmd = new GeneralCommandLine();
cmd.withWorkDirectory(openedFile.getParent().getCanonicalPath());
String sdkHomePath = sdk.getHomePath();
if (sdkHomePath != null) {
cmd.setExePath(sdkHomePath);
TaskFile selectedTaskFile = taskManager.getTaskFile(openedFile);
assert selectedTaskFile != null;
Task currentTask = selectedTaskFile.getTask();
Process process;
StudyUtils.setCommandLineParameters(cmd, project, filePath, sdkHomePath, currentTask);
try {
process = cmd.createProcess();
}
catch (ExecutionException e) {
LOG.error(e);
return;
}
myHandler = new OSProcessHandler(process);
RunContentExecutor executor = StudyUtils.getExecutor(project, myHandler);
Disposer.register(project, executor);
executor.run();
}
}
public void actionPerformed(@NotNull AnActionEvent e) {
Project project = e.getProject();
if (project == null) {
return;
}
Sdk sdk = StudyUtils.findSdk(project);
if (sdk == null) {
return;
}
run(project, sdk);
}
}
@@ -1,4 +1,4 @@
package com.jetbrains.python.edu.actions;
package com.jetbrains.edu.learning.actions;
import com.intellij.codeInsight.documentation.DocumentationComponent;
import com.intellij.codeInsight.documentation.DocumentationManager;
@@ -13,13 +13,13 @@ import com.intellij.openapi.util.Disposer;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.jetbrains.python.edu.StudyState;
import com.jetbrains.python.edu.StudyTaskManager;
import com.jetbrains.python.edu.StudyUtils;
import com.jetbrains.python.edu.course.Course;
import com.jetbrains.python.edu.course.TaskWindow;
import com.jetbrains.python.edu.editor.StudyEditor;
import icons.StudyIcons;
import com.jetbrains.edu.learning.StudyState;
import com.jetbrains.edu.learning.StudyTaskManager;
import com.jetbrains.edu.learning.StudyUtils;
import com.jetbrains.edu.learning.course.Course;
import com.jetbrains.edu.learning.course.TaskWindow;
import com.jetbrains.edu.learning.editor.StudyEditor;
import icons.InteractiveLearningIcons;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -32,7 +32,7 @@ public class StudyShowHintAction extends DumbAwareAction {
public static final String HINT_NOT_AVAILABLE = "There is no hint for this answer placeholder";
public StudyShowHintAction() {
super("Show hint", "Show hint", StudyIcons.ShowHint);
super("Show hint", "Show hint", InteractiveLearningIcons.ShowHint);
}
public void actionPerformed(@NotNull AnActionEvent e) {
@@ -1,4 +1,4 @@
package com.jetbrains.python.edu.actions;
package com.jetbrains.edu.learning.actions;
import com.intellij.ide.projectView.ProjectView;
import com.intellij.openapi.actionSystem.AnActionEvent;
@@ -14,11 +14,11 @@ import com.intellij.openapi.wm.ToolWindow;
import com.intellij.openapi.wm.ToolWindowId;
import com.intellij.openapi.wm.ToolWindowManager;
import com.intellij.util.ui.tree.TreeUtil;
import com.jetbrains.python.edu.StudyState;
import com.jetbrains.python.edu.course.Lesson;
import com.jetbrains.python.edu.course.Task;
import com.jetbrains.python.edu.course.TaskFile;
import com.jetbrains.python.edu.editor.StudyEditor;
import com.jetbrains.edu.learning.StudyState;
import com.jetbrains.edu.learning.course.Lesson;
import com.jetbrains.edu.learning.course.Task;
import com.jetbrains.edu.learning.course.TaskFile;
import com.jetbrains.edu.learning.editor.StudyEditor;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
@@ -1,4 +1,4 @@
package com.jetbrains.python.edu.actions;
package com.jetbrains.edu.learning.actions;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.editor.Editor;
@@ -6,11 +6,11 @@ import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.jetbrains.python.edu.StudyTaskManager;
import com.jetbrains.python.edu.StudyUtils;
import com.jetbrains.python.edu.course.TaskFile;
import com.jetbrains.python.edu.course.TaskWindow;
import com.jetbrains.python.edu.editor.StudyEditor;
import com.jetbrains.edu.learning.StudyTaskManager;
import com.jetbrains.edu.learning.StudyUtils;
import com.jetbrains.edu.learning.course.TaskFile;
import com.jetbrains.edu.learning.course.TaskWindow;
import com.jetbrains.edu.learning.editor.StudyEditor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -1,4 +1,4 @@
package com.jetbrains.python.edu.course;
package com.jetbrains.edu.learning.course;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
@@ -1,4 +1,4 @@
package com.jetbrains.python.edu.course;
package com.jetbrains.edu.learning.course;
/**
* Implementation of class which contains information to be shawn in course description in tool window
@@ -1,4 +1,4 @@
package com.jetbrains.python.edu.course;
package com.jetbrains.edu.learning.course;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
@@ -58,7 +58,7 @@ public class Lesson implements Stateful {
*
* @param courseDir project directory of course
* @param resourceRoot directory where original lesson stored
* @throws java.io.IOException
* @throws IOException
*/
public void create(@NotNull final VirtualFile courseDir, @NotNull final File resourceRoot,
@NotNull final Project project) throws IOException {
@@ -1,4 +1,4 @@
package com.jetbrains.python.edu.course;
package com.jetbrains.edu.learning.course;
/**
* Implementation of class which contains information about student progress in current lesson
@@ -1,4 +1,4 @@
package com.jetbrains.python.edu.course;
package com.jetbrains.edu.learning.course;
public interface Stateful {
StudyStatus getStatus();
@@ -1,4 +1,4 @@
package com.jetbrains.python.edu.course;
package com.jetbrains.edu.learning.course;
/**
* @see {@link TaskWindow#myStatus}
@@ -1,10 +1,10 @@
package com.jetbrains.python.edu.course;
package com.jetbrains.edu.learning.course;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.xmlb.annotations.Transient;
import com.jetbrains.python.edu.StudyUtils;
import com.jetbrains.edu.learning.StudyUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -83,7 +83,7 @@ public class Task implements Stateful {
*
* @param lessonDir project directory of lesson which task belongs to
* @param resourceRoot directory where original task file stored
* @throws java.io.IOException
* @throws IOException
*/
public void create(@NotNull final VirtualFile lessonDir, @NotNull final File resourceRoot,
@NotNull final Project project) throws IOException {
@@ -1,4 +1,4 @@
package com.jetbrains.python.edu.course;
package com.jetbrains.edu.learning.course;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
@@ -13,8 +13,8 @@ import com.intellij.openapi.editor.markup.RangeHighlighter;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.xmlb.annotations.Transient;
import com.jetbrains.python.edu.StudyUtils;
import com.jetbrains.python.edu.TaskWindowDeleteHandler;
import com.jetbrains.edu.learning.StudyUtils;
import com.jetbrains.edu.learning.TaskWindowDeleteHandler;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -85,7 +85,7 @@ public class TaskFile implements Stateful {
*
* @param taskDir project directory of task which task file belongs to
* @param resourceRoot directory where original task file stored
* @throws java.io.IOException
* @throws IOException
*/
public void create(@NotNull final VirtualFile taskDir, @NotNull final File resourceRoot,
@NotNull final String name) throws IOException {
@@ -1,4 +1,4 @@
package com.jetbrains.python.edu.course;
package com.jetbrains.edu.learning.course;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.process.CapturingProcessHandler;
@@ -18,9 +18,9 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.JBColor;
import com.jetbrains.python.edu.StudyDocumentListener;
import com.jetbrains.python.edu.StudyTestRunner;
import com.jetbrains.python.edu.StudyUtils;
import com.jetbrains.edu.learning.StudyDocumentListener;
import com.jetbrains.edu.learning.StudyTestRunner;
import com.jetbrains.edu.learning.StudyUtils;
import org.jetbrains.annotations.NotNull;
import java.io.File;
@@ -1,4 +1,4 @@
package com.jetbrains.python.edu.course;
package com.jetbrains.edu.learning.course;
public class UserTest {
private String input;
@@ -1,4 +1,4 @@
package com.jetbrains.python.edu.editor;
package com.jetbrains.edu.learning.editor;
import com.intellij.codeHighlighting.BackgroundEditorHighlighter;
import com.intellij.icons.AllIcons;
@@ -34,13 +34,13 @@ import com.intellij.ui.HideableTitledPanel;
import com.intellij.ui.JBColor;
import com.intellij.util.ui.EmptyClipboardOwner;
import com.intellij.util.ui.UIUtil;
import com.jetbrains.python.edu.StudyDocumentListener;
import com.jetbrains.python.edu.StudyTaskManager;
import com.jetbrains.python.edu.StudyUtils;
import com.jetbrains.python.edu.actions.*;
import com.jetbrains.python.edu.course.Task;
import com.jetbrains.python.edu.course.TaskFile;
import icons.StudyIcons;
import com.jetbrains.edu.learning.StudyDocumentListener;
import com.jetbrains.edu.learning.StudyTaskManager;
import com.jetbrains.edu.learning.StudyUtils;
import com.jetbrains.edu.learning.actions.*;
import com.jetbrains.edu.learning.course.Task;
import com.jetbrains.edu.learning.course.TaskFile;
import icons.InteractiveLearningIcons;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -205,13 +205,13 @@ public class StudyEditor implements TextEditor {
}
private void initializeButtons(@NotNull final JPanel taskActionsPanel, @NotNull final TaskFile taskFile) {
myCheckButton = addButton(taskActionsPanel, StudyCheckAction.ACTION_ID, StudyIcons.Resolve, StudyCheckAction.SHORTCUT);
myPrevTaskButton = addButton(taskActionsPanel, StudyPreviousStudyTaskAction.ACTION_ID, StudyIcons.Prev, StudyPreviousStudyTaskAction.SHORTCUT);
myCheckButton = addButton(taskActionsPanel, StudyCheckAction.ACTION_ID, InteractiveLearningIcons.Resolve, StudyCheckAction.SHORTCUT);
myPrevTaskButton = addButton(taskActionsPanel, StudyPreviousStudyTaskAction.ACTION_ID, InteractiveLearningIcons.Prev, StudyPreviousStudyTaskAction.SHORTCUT);
myNextTaskButton = addButton(taskActionsPanel, StudyNextStudyTaskAction.ACTION_ID, AllIcons.Actions.Forward, StudyNextStudyTaskAction.SHORTCUT);
myRefreshButton = addButton(taskActionsPanel, StudyRefreshTaskFileAction.ACTION_ID, AllIcons.Actions.Refresh, StudyRefreshTaskFileAction.SHORTCUT);
JButton myShowHintButton = addButton(taskActionsPanel, StudyShowHintAction.ACTION_ID, StudyIcons.ShowHint, StudyShowHintAction.SHORTCUT);
JButton myShowHintButton = addButton(taskActionsPanel, StudyShowHintAction.ACTION_ID, InteractiveLearningIcons.ShowHint, StudyShowHintAction.SHORTCUT);
if (!taskFile.getTask().getUserTests().isEmpty()) {
final Sdk sdk = StudyUtils.findPythonSdk(myProject);
final Sdk sdk = StudyUtils.findSdk(myProject);
if (sdk != null) {
JButton runButton = addButton(taskActionsPanel, StudyRunAction.ACTION_ID, AllIcons.General.Run, null);
runButton.addActionListener(new ActionListener() {
@@ -221,7 +221,7 @@ public class StudyEditor implements TextEditor {
studyRunAction.run(myProject, sdk);
}
});
JButton watchInputButton = addButton(taskActionsPanel, "WatchInputAction", StudyIcons.WatchInput, null);
JButton watchInputButton = addButton(taskActionsPanel, "WatchInputAction", InteractiveLearningIcons.WatchInput, null);
watchInputButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
@@ -1,4 +1,4 @@
package com.jetbrains.python.edu.editor;
package com.jetbrains.edu.learning.editor;
import com.intellij.openapi.fileEditor.FileEditor;
import com.intellij.openapi.fileEditor.FileEditorPolicy;
@@ -8,10 +8,10 @@ import com.intellij.openapi.fileEditor.impl.text.TextEditorProvider;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.jetbrains.edu.learning.StudyTaskManager;
import com.jetbrains.edu.learning.course.TaskFile;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import com.jetbrains.python.edu.StudyTaskManager;
import com.jetbrains.python.edu.course.TaskFile;
/**
* User: lia
@@ -1,4 +1,4 @@
package com.jetbrains.python.edu.projectView;
package com.jetbrains.edu.learning.projectView;
import com.intellij.ide.projectView.PresentationData;
import com.intellij.ide.projectView.ProjectView;
@@ -11,10 +11,10 @@ import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiElement;
import com.intellij.ui.JBColor;
import com.intellij.ui.SimpleTextAttributes;
import com.jetbrains.python.edu.StudyTaskManager;
import com.jetbrains.python.edu.StudyUtils;
import com.jetbrains.python.edu.course.*;
import icons.StudyIcons;
import com.jetbrains.edu.learning.StudyTaskManager;
import com.jetbrains.edu.learning.StudyUtils;
import com.jetbrains.edu.learning.course.*;
import icons.InteractiveLearningIcons;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
@@ -35,7 +35,7 @@ public class StudyDirectoryNode extends PsiDirectoryNode {
@Override
protected void updateImpl(PresentationData data) {
data.setIcon(StudyIcons.Task);
data.setIcon(InteractiveLearningIcons.Task);
String valueName = myValue.getName();
StudyTaskManager studyTaskManager = StudyTaskManager.getInstance(myProject);
Course course = studyTaskManager.getCourse();
@@ -72,7 +72,7 @@ public class StudyDirectoryNode extends PsiDirectoryNode {
if (myValue.getParent() != null) {
if (!myValue.getParent().getName().contains(Course.SANDBOX_DIR)) {
data.setPresentableText(Course.SANDBOX_DIR);
data.setIcon(StudyIcons.Sandbox);
data.setIcon(InteractiveLearningIcons.Sandbox);
return;
}
}
@@ -94,16 +94,16 @@ public class StudyDirectoryNode extends PsiDirectoryNode {
StudyStatus taskStatus = stateful.getStatus();
switch (taskStatus) {
case Unchecked: {
updatePresentation(data, additionalName, JBColor.BLACK, stateful instanceof Lesson ? StudyIcons.Lesson : StudyIcons.Task);
updatePresentation(data, additionalName, JBColor.BLACK, stateful instanceof Lesson ? InteractiveLearningIcons.Lesson : InteractiveLearningIcons.Task);
break;
}
case Solved: {
updatePresentation(data, additionalName, new JBColor(new Color(0, 134, 0), new Color(98, 150, 85)),
stateful instanceof Lesson ? StudyIcons.LessonCompl : StudyIcons.TaskCompl);
stateful instanceof Lesson ? InteractiveLearningIcons.LessonCompl : InteractiveLearningIcons.TaskCompl);
break;
}
case Failed: {
updatePresentation(data, additionalName, JBColor.RED, stateful instanceof Lesson ? StudyIcons.Lesson : StudyIcons.TaskProbl);
updatePresentation(data, additionalName, JBColor.RED, stateful instanceof Lesson ? InteractiveLearningIcons.Lesson : InteractiveLearningIcons.TaskProbl);
}
}
}
@@ -1,4 +1,4 @@
package com.jetbrains.python.edu.projectView;
package com.jetbrains.edu.learning.projectView;
import com.intellij.ide.projectView.TreeStructureProvider;
import com.intellij.ide.projectView.ViewSettings;
@@ -8,10 +8,10 @@ import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDirectory;
import com.jetbrains.python.edu.StudyTaskManager;
import com.jetbrains.python.edu.course.Course;
import com.jetbrains.python.edu.course.Task;
import com.jetbrains.python.edu.course.TaskFile;
import com.jetbrains.edu.learning.StudyTaskManager;
import com.jetbrains.edu.learning.course.Course;
import com.jetbrains.edu.learning.course.Task;
import com.jetbrains.edu.learning.course.TaskFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -1,9 +1,9 @@
package com.jetbrains.python.edu.ui;
package com.jetbrains.edu.learning.ui;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Condition;
import com.jetbrains.python.edu.StudyTaskManager;
import com.jetbrains.edu.learning.StudyTaskManager;
/**
* author: liana
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.jetbrains.python.edu.ui.StudyNewProjectPanel">
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.jetbrains.edu.learning.ui.StudyNewProjectPanel">
<grid id="27dc6" binding="myContentPanel" layout-manager="GridLayoutManager" row-count="2" column-count="4" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
@@ -1,4 +1,4 @@
package com.jetbrains.python.edu.ui;
package com.jetbrains.edu.learning.ui;
import com.intellij.facet.ui.FacetValidatorsManager;
import com.intellij.facet.ui.ValidationResult;
@@ -7,9 +7,9 @@ import com.intellij.openapi.fileChooser.FileChooser;
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.Consumer;
import com.jetbrains.python.edu.StudyDirectoryProjectGenerator;
import com.jetbrains.python.edu.StudyUtils;
import com.jetbrains.python.edu.course.CourseInfo;
import com.jetbrains.edu.learning.StudyProjectGenerator;
import com.jetbrains.edu.learning.StudyUtils;
import com.jetbrains.edu.learning.course.CourseInfo;
import javax.swing.*;
import java.awt.event.ActionEvent;
@@ -33,12 +33,12 @@ public class StudyNewProjectPanel{
private JLabel myAuthorLabel;
private JLabel myDescriptionLabel;
private JLabel myLabel;
private final StudyDirectoryProjectGenerator myGenerator;
private final StudyProjectGenerator myGenerator;
private static final String CONNECTION_ERROR = "<html>Failed to download courses.<br>Check your Internet connection.</html>";
private static final String INVALID_COURSE = "Selected course is invalid";
private FacetValidatorsManager myValidationManager;
public StudyNewProjectPanel(StudyDirectoryProjectGenerator generator) {
public StudyNewProjectPanel(StudyProjectGenerator generator) {
myGenerator = generator;
Map<CourseInfo, File> courses = myGenerator.getCourses();
if (courses.isEmpty()) {
@@ -110,14 +110,14 @@ public class StudyNewProjectPanel{
}
private void setError(String errorMessage) {
myGenerator.setValidationResult(new ValidationResult(errorMessage));
myGenerator.fireStateChanged(new ValidationResult(errorMessage));
if (myValidationManager != null) {
myValidationManager.validate();
}
}
private void setOK() {
myGenerator.setValidationResult(ValidationResult.OK);
myGenerator.fireStateChanged(ValidationResult.OK);
if (myValidationManager != null) {
myValidationManager.validate();
}
@@ -196,4 +196,5 @@ public class StudyNewProjectPanel{
setOK();
}
}
}
@@ -1,4 +1,4 @@
package com.jetbrains.python.edu.ui;
package com.jetbrains.edu.learning.ui;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.ui.GraphicsConfig;
@@ -1,9 +1,9 @@
package com.jetbrains.python.edu.ui;
package com.jetbrains.edu.learning.ui;
import com.intellij.ui.DocumentAdapter;
import com.intellij.ui.components.JBScrollPane;
import com.jetbrains.edu.learning.course.UserTest;
import org.jetbrains.annotations.NotNull;
import com.jetbrains.python.edu.course.UserTest;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
@@ -1,4 +1,4 @@
package com.jetbrains.python.edu.ui;
package com.jetbrains.edu.learning.ui;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
@@ -8,11 +8,11 @@ import com.intellij.ui.JBColor;
import com.intellij.ui.content.Content;
import com.intellij.ui.content.ContentFactory;
import com.intellij.util.ui.UIUtil;
import com.jetbrains.python.edu.StudyTaskManager;
import com.jetbrains.python.edu.course.Course;
import com.jetbrains.python.edu.course.Lesson;
import com.jetbrains.python.edu.course.LessonInfo;
import com.jetbrains.python.edu.course.StudyStatus;
import com.jetbrains.edu.learning.StudyTaskManager;
import com.jetbrains.edu.learning.course.Course;
import com.jetbrains.edu.learning.course.Lesson;
import com.jetbrains.edu.learning.course.LessonInfo;
import com.jetbrains.edu.learning.course.StudyStatus;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;