mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
moved course creation plugin to pycharm educational
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="PLUGIN_MODULE" version="4">
|
||||
<component name="DevKit.ModuleBuildProperties" url="file://$MODULE_DIR$/META-INF/plugin.xml" />
|
||||
<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$/pluginResources" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
<idea-plugin version="2">
|
||||
<id>org.jetbrains.plugins.coursecreator</id>
|
||||
<name>Cource Creator for PyCharm Education</name>
|
||||
<version>1.0</version>
|
||||
|
||||
<description><![CDATA[
|
||||
Plugin allows you to create new course for PyCharm Education Edition.
|
||||
]]></description>
|
||||
|
||||
<change-notes><![CDATA[
|
||||
]]>
|
||||
</change-notes>
|
||||
|
||||
<!-- please see http://confluence.jetbrains.com/display/IDEADEV/Build+Number+Ranges for description -->
|
||||
<idea-version since-build="138"/>
|
||||
|
||||
<!-- please see http://confluence.jetbrains.com/display/IDEADEV/Plugin+Compatibility+with+IntelliJ+Platform+Products
|
||||
on how to target different products -->
|
||||
<!-- uncomment to enable plugin in all products
|
||||
<depends>com.intellij.modules.lang</depends>
|
||||
-->
|
||||
|
||||
<depends>com.intellij.modules.python</depends>
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<directoryProjectGenerator implementation="org.jetbrains.plugins.coursecreator.CCProjectGenerator"/>
|
||||
<projectService serviceImplementation="org.jetbrains.plugins.coursecreator.CCProjectService"/>
|
||||
<codeInsight.lineMarkerProvider language="Python"
|
||||
implementationClass="org.jetbrains.plugins.coursecreator.highlighting.CCTaskLineMarkerProvider"/>
|
||||
<treeStructureProvider implementation="org.jetbrains.plugins.coursecreator.projectView.CCTreeStructureProvider"/>
|
||||
</extensions>
|
||||
|
||||
<application-components>
|
||||
<!-- Add your application components here -->
|
||||
</application-components>
|
||||
|
||||
<project-components>
|
||||
<!-- Add your project components here -->
|
||||
<component>
|
||||
<implementation-class>org.jetbrains.plugins.coursecreator.CCProjectComponent</implementation-class>
|
||||
</component>
|
||||
</project-components>
|
||||
|
||||
<actions>
|
||||
<action id="CreateLesson" class="org.jetbrains.plugins.coursecreator.actions.CreateLesson">
|
||||
<add-to-group group-id="NewGroup" anchor="before" relative-to-action="NewFile"/>
|
||||
</action>
|
||||
<action id="CreateTaskFile" class="org.jetbrains.plugins.coursecreator.actions.CreateTaskFile">
|
||||
<add-to-group group-id="NewGroup" anchor="before" relative-to-action="NewFile"/>
|
||||
</action>
|
||||
<action id="CreateTask" class="org.jetbrains.plugins.coursecreator.actions.CreateTask">
|
||||
<add-to-group group-id="NewGroup" anchor="before" relative-to-action="NewFile"/>
|
||||
</action>
|
||||
<action id="AddTaskWindow" class="org.jetbrains.plugins.coursecreator.actions.AddTaskWindow">
|
||||
<add-to-group group-id="EditorPopupMenu" anchor="before" relative-to-action="CopyReference"/>
|
||||
</action>
|
||||
<action id="PackCourse" class="org.jetbrains.plugins.coursecreator.actions.CreateCourseArchive">
|
||||
<add-to-group group-id="MainToolBar" anchor="last" />
|
||||
</action>
|
||||
</actions>
|
||||
|
||||
</idea-plugin>
|
||||
@@ -0,0 +1,4 @@
|
||||
<html>
|
||||
Write your task text here.
|
||||
<br>
|
||||
</html>
|
||||
@@ -0,0 +1 @@
|
||||
# TODO: type solution here
|
||||
@@ -0,0 +1,127 @@
|
||||
import sys
|
||||
|
||||
def get_file_text(path):
|
||||
""" get file text by path"""
|
||||
file_io = open(path, "r")
|
||||
text = file_io.read()
|
||||
file_io.close()
|
||||
return text
|
||||
|
||||
def get_file_output(path):
|
||||
# TODO: get file output by path
|
||||
return ""
|
||||
|
||||
def test_file_importable():
|
||||
""" tests there is no obvious syntax errors"""
|
||||
path = sys.argv[-1]
|
||||
try:
|
||||
import_file(path)
|
||||
except ImportError:
|
||||
failed("File contains syntax errors")
|
||||
return
|
||||
except SyntaxError:
|
||||
failed("File contains syntax errors")
|
||||
return
|
||||
except NameError:
|
||||
failed("File contains syntax errors")
|
||||
return
|
||||
|
||||
passed()
|
||||
|
||||
def import_file(path):
|
||||
""" returns imported file """
|
||||
import imp
|
||||
tmp = imp.load_source('tmp', path)
|
||||
return tmp
|
||||
|
||||
def import_task_file():
|
||||
""" returns imported file """
|
||||
path = sys.argv[-1]
|
||||
return import_file(path)
|
||||
|
||||
def test_is_not_empty():
|
||||
path = sys.argv[-1]
|
||||
file_text = get_file_text(path)
|
||||
|
||||
if len(file_text) > 0:
|
||||
passed()
|
||||
else:
|
||||
failed("The file is empty. Please, reload the task and try again.")
|
||||
|
||||
def test_is_initial_text(error_text="You should modify the file"):
|
||||
path = sys.argv[-1]
|
||||
text = get_initial_text(path)
|
||||
file_text = get_file_text(path)
|
||||
|
||||
if file_text.strip() == text:
|
||||
failed(error_text)
|
||||
else:
|
||||
passed()
|
||||
|
||||
def get_initial_text(path):
|
||||
course_lib = sys.argv[-2]
|
||||
|
||||
import os
|
||||
# path format is "project_root/lessonX/taskY/file.py"
|
||||
task_index = path.rfind(os.sep, 0, path.rfind(os.sep))
|
||||
index = path.rfind(os.sep, 0, task_index)
|
||||
relative_path = path[index+1:]
|
||||
initial_file_path = os.path.join(course_lib, relative_path)
|
||||
return get_file_text(initial_file_path)
|
||||
|
||||
|
||||
def test_text_equals(text, error_text):
|
||||
path = sys.argv[-1]
|
||||
file_text = get_file_text(path)
|
||||
|
||||
if file_text.strip() == text:
|
||||
passed()
|
||||
else:
|
||||
failed(error_text)
|
||||
|
||||
def test_window_text_deleted(error_text="Don't just delete task text"):
|
||||
windows = get_task_windows()
|
||||
|
||||
for window in windows:
|
||||
if len(window) == 0:
|
||||
failed(error_text)
|
||||
return
|
||||
passed()
|
||||
|
||||
|
||||
def failed(message="Please, reload the task and try again."):
|
||||
print("#study_plugin FAILED + " + message)
|
||||
|
||||
def passed():
|
||||
print("#study_plugin test OK")
|
||||
|
||||
def get_task_windows():
|
||||
prefix = "#study_plugin_window = "
|
||||
path = sys.argv[-1]
|
||||
import os
|
||||
windows_path = os.path.splitext(path)[0] + "_windows"
|
||||
windows = []
|
||||
f = open(windows_path, "r")
|
||||
window_text = ""
|
||||
first = True
|
||||
for line in f.readlines():
|
||||
if line.startswith(prefix):
|
||||
if not first:
|
||||
windows.append(window_text.strip())
|
||||
else:
|
||||
first = False
|
||||
window_text = line[len(prefix):]
|
||||
else:
|
||||
window_text += line
|
||||
|
||||
if window_text:
|
||||
windows.append(window_text.strip())
|
||||
|
||||
f.close()
|
||||
return windows
|
||||
|
||||
def run_common_tests(error_text="Please, reload file and try again"):
|
||||
test_file_importable()
|
||||
test_is_not_empty()
|
||||
test_is_initial_text(error_text)
|
||||
test_window_text_deleted(error_text)
|
||||
@@ -0,0 +1,17 @@
|
||||
from test_helper import run_common_tests, failed, passed, get_task_windows
|
||||
|
||||
|
||||
def test_task_windows():
|
||||
windows = get_task_windows()
|
||||
window = windows[0]
|
||||
if window != "": # TODO: your condition here
|
||||
passed()
|
||||
else:
|
||||
failed()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
run_common_tests()
|
||||
test_task_windows()
|
||||
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 500 B |
+80
@@ -0,0 +1,80 @@
|
||||
package org.jetbrains.plugins.coursecreator;
|
||||
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.event.EditorFactoryEvent;
|
||||
import com.intellij.openapi.editor.event.EditorFactoryListener;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.coursecreator.format.*;
|
||||
|
||||
public class CCEditorFactoryListener implements EditorFactoryListener {
|
||||
@Override
|
||||
public void editorCreated(@NotNull EditorFactoryEvent event) {
|
||||
Editor editor = event.getEditor();
|
||||
Project project = editor.getProject();
|
||||
if (project == null) {
|
||||
return;
|
||||
}
|
||||
VirtualFile virtualFile = FileDocumentManager.getInstance().getFile(editor.getDocument());
|
||||
if (virtualFile == null) {
|
||||
return;
|
||||
}
|
||||
Course course = CCProjectService.getInstance(project).getCourse();
|
||||
if (course == null) {
|
||||
return;
|
||||
}
|
||||
final VirtualFile taskDir = virtualFile.getParent();
|
||||
if (taskDir == null || !taskDir.getName().contains("task")) {
|
||||
return;
|
||||
}
|
||||
final VirtualFile lessonDir = taskDir.getParent();
|
||||
if (lessonDir == null) return;
|
||||
final Lesson lesson = course.getLesson(lessonDir.getName());
|
||||
final Task task = lesson.getTask(taskDir.getName());
|
||||
final TaskFile taskFile = task.getTaskFile(virtualFile.getName());
|
||||
TaskFileModificationListener listener = new TaskFileModificationListener(taskFile);
|
||||
CCProjectService.addDocumentListener(editor.getDocument(), listener);
|
||||
editor.getDocument().addDocumentListener(listener);
|
||||
CCProjectService.drawTaskWindows(virtualFile, editor, course);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void editorReleased(@NotNull EditorFactoryEvent event) {
|
||||
Editor editor = event.getEditor();
|
||||
Document document = editor.getDocument();
|
||||
StudyDocumentListener listener = CCProjectService.getListener(document);
|
||||
if (listener != null) {
|
||||
document.removeDocumentListener(listener);
|
||||
CCProjectService.removeListener(document);
|
||||
}
|
||||
editor.getMarkupModel().removeAllHighlighters();
|
||||
editor.getSelectionModel().removeSelection();
|
||||
}
|
||||
|
||||
private class TaskFileModificationListener extends StudyDocumentListener {
|
||||
|
||||
private final TaskFile myTaskFile;
|
||||
|
||||
public TaskFileModificationListener(TaskFile taskFile) {
|
||||
super(taskFile);
|
||||
myTaskFile = taskFile;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateTaskWindowLength(CharSequence fragment, TaskWindow taskWindow, int change) {
|
||||
int newLength = taskWindow.getReplacementLength() + change;
|
||||
taskWindow.setReplacementLength(newLength <= 0 ? 0 : newLength);
|
||||
if (fragment.equals("\n")) {
|
||||
taskWindow.setReplacementLength(taskWindow.getLength() + 1);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean needModify() {
|
||||
return myTaskFile.isTrackChanges();
|
||||
}
|
||||
}
|
||||
}
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
package org.jetbrains.plugins.coursecreator;
|
||||
|
||||
import com.intellij.openapi.components.ProjectComponent;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.EditorFactory;
|
||||
import com.intellij.openapi.editor.event.EditorFactoryEvent;
|
||||
import com.intellij.openapi.editor.impl.EditorFactoryImpl;
|
||||
import com.intellij.openapi.fileEditor.FileEditor;
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager;
|
||||
import com.intellij.openapi.fileEditor.impl.text.PsiAwareTextEditorImpl;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.project.ProjectManager;
|
||||
import com.intellij.openapi.startup.StartupManager;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.coursecreator.format.Course;
|
||||
|
||||
public class CCProjectComponent implements ProjectComponent {
|
||||
private final Project myProject;
|
||||
|
||||
public CCProjectComponent(Project project) {
|
||||
myProject = project;
|
||||
}
|
||||
|
||||
public void initComponent() {
|
||||
}
|
||||
|
||||
public void disposeComponent() {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getComponentName() {
|
||||
return "CCProjectComponent";
|
||||
}
|
||||
|
||||
public void projectOpened() {
|
||||
StartupManager.getInstance(myProject).runWhenProjectIsInitialized(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Course course = CCProjectService.getInstance(myProject).getCourse();
|
||||
if (course != null) {
|
||||
EditorFactory.getInstance().addEditorFactoryListener(new CCEditorFactoryListener(), myProject);
|
||||
VirtualFile[] files = FileEditorManager.getInstance(myProject).getOpenFiles();
|
||||
for (VirtualFile file : files) {
|
||||
FileEditor fileEditor = FileEditorManager.getInstance(myProject).getSelectedEditor(file);
|
||||
if (fileEditor instanceof PsiAwareTextEditorImpl) {
|
||||
Editor editor = ((PsiAwareTextEditorImpl)fileEditor).getEditor();
|
||||
new CCEditorFactoryListener().editorCreated(new EditorFactoryEvent(new EditorFactoryImpl(ProjectManager.getInstance()), editor ));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void projectClosed() {
|
||||
}
|
||||
}
|
||||
+101
@@ -0,0 +1,101 @@
|
||||
package org.jetbrains.plugins.coursecreator;
|
||||
|
||||
import com.intellij.facet.ui.FacetEditorValidator;
|
||||
import com.intellij.facet.ui.FacetValidatorsManager;
|
||||
import com.intellij.facet.ui.ValidationResult;
|
||||
import com.intellij.ide.fileTemplates.FileTemplate;
|
||||
import com.intellij.ide.fileTemplates.FileTemplateManager;
|
||||
import com.intellij.ide.fileTemplates.FileTemplateUtil;
|
||||
import com.intellij.ide.util.DirectoryUtil;
|
||||
import com.intellij.openapi.command.WriteCommandAction;
|
||||
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.intellij.psi.PsiDirectory;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.jetbrains.python.newProject.PythonProjectGenerator;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.coursecreator.format.Course;
|
||||
import org.jetbrains.plugins.coursecreator.ui.CCNewProjectPanel;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
|
||||
public class CCProjectGenerator extends PythonProjectGenerator implements DirectoryProjectGenerator {
|
||||
private CCNewProjectPanel mySettingsPanel;
|
||||
|
||||
@Nls
|
||||
@NotNull
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Course creation";
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Object showGenerationSettings(VirtualFile baseDir) throws ProcessCanceledException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Icon getLogo() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void generateProject(@NotNull final Project project, @NotNull final VirtualFile baseDir,
|
||||
@Nullable Object settings, @NotNull Module module) {
|
||||
|
||||
final CCProjectService service = CCProjectService.getInstance(project);
|
||||
final Course course = new Course(mySettingsPanel.getName(), mySettingsPanel.getAuthor(), mySettingsPanel.getDescription());
|
||||
service.setCourse(course);
|
||||
|
||||
final PsiDirectory projectDir = PsiManager.getInstance(project).findDirectory(baseDir);
|
||||
if (projectDir == null) return;
|
||||
new WriteCommandAction.Simple(project) {
|
||||
@Override
|
||||
protected void run() throws Throwable {
|
||||
final FileTemplate template = FileTemplateManager.getInstance().getInternalTemplate("test_helper");
|
||||
try {
|
||||
FileTemplateUtil.createFromTemplate(template, "test_helper.py", null, projectDir);
|
||||
}
|
||||
catch (Exception ignored) {
|
||||
}
|
||||
DirectoryUtil.createSubdirectories("hints", projectDir, "\\/");
|
||||
}
|
||||
}.execute();
|
||||
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ValidationResult validate(@NotNull String s) {
|
||||
String message = "";
|
||||
message = mySettingsPanel.getDescription().equals("") ? "Enter description" : message;
|
||||
message = mySettingsPanel.getAuthor().equals("") ? "Enter author name" : message;
|
||||
message = mySettingsPanel.getName().equals("") ? "Enter course name" : message;
|
||||
return message.equals("")? ValidationResult.OK : new ValidationResult(message) ;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public JPanel extendBasePanel() throws ProcessCanceledException {
|
||||
mySettingsPanel = new CCNewProjectPanel();
|
||||
mySettingsPanel.registerValidators(new FacetValidatorsManager() {
|
||||
public void registerValidator(FacetEditorValidator validator, JComponent... componentsToWatch) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void validate() {
|
||||
fireStateChanged();
|
||||
}
|
||||
});
|
||||
return mySettingsPanel.getMainPanel();
|
||||
}
|
||||
}
|
||||
+138
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Copyright 2000-2013 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 org.jetbrains.plugins.coursecreator;
|
||||
|
||||
import com.intellij.ide.projectView.ProjectView;
|
||||
import com.intellij.openapi.components.PersistentStateComponent;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.components.State;
|
||||
import com.intellij.openapi.components.Storage;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.VirtualFileManager;
|
||||
import com.intellij.util.xmlb.XmlSerializer;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.coursecreator.format.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@State(name = "CCProjectService",
|
||||
storages = {
|
||||
@Storage(file = "$PROJECT_CONFIG_DIR$/course_service.xml")
|
||||
}
|
||||
)
|
||||
public class CCProjectService implements PersistentStateComponent<Element> {
|
||||
|
||||
private static final Logger LOG = Logger.getInstance(CCProjectService.class.getName());
|
||||
public Course myCourse;
|
||||
public static final String COURSE_ELEMENT = "course";
|
||||
private static final Map<Document, StudyDocumentListener> myDocumentListeners = new HashMap<Document, StudyDocumentListener>();
|
||||
|
||||
public void setCourse(@NotNull final Course course) {
|
||||
myCourse = course;
|
||||
}
|
||||
|
||||
public Course getCourse() {
|
||||
return myCourse;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Element getState() {
|
||||
final Element el = new Element("CCProjectService");
|
||||
if (myCourse != null) {
|
||||
Element courseElement = new Element(COURSE_ELEMENT);
|
||||
XmlSerializer.serializeInto(myCourse, courseElement);
|
||||
el.addContent(courseElement);
|
||||
}
|
||||
return el;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadState(Element el) {
|
||||
myCourse = XmlSerializer.deserialize(el.getChild(COURSE_ELEMENT), Course.class);
|
||||
}
|
||||
|
||||
public static CCProjectService getInstance(@NotNull Project project) {
|
||||
return ServiceManager.getService(project, CCProjectService.class);
|
||||
}
|
||||
|
||||
public static void deleteProjectFile(File file, @NotNull final Project project) {
|
||||
if (!file.delete()) {
|
||||
LOG.info("Failed to delete file " + file.getPath());
|
||||
}
|
||||
VirtualFileManager.getInstance().refreshWithoutFileWatcher(true);
|
||||
ProjectView.getInstance(project).refresh();
|
||||
}
|
||||
|
||||
public static void drawTaskWindows(@NotNull final VirtualFile virtualFile, @NotNull final Editor editor, @NotNull final Course course) {
|
||||
VirtualFile taskDir = virtualFile.getParent();
|
||||
if (taskDir == null) {
|
||||
return;
|
||||
}
|
||||
String taskDirName = taskDir.getName();
|
||||
if (!taskDirName.contains("task")) {
|
||||
return;
|
||||
}
|
||||
VirtualFile lessonDir = taskDir.getParent();
|
||||
if (lessonDir == null) {
|
||||
return;
|
||||
}
|
||||
String lessonDirName = lessonDir.getName();
|
||||
if (!lessonDirName.contains("lesson")) {
|
||||
return;
|
||||
}
|
||||
Lesson lesson = course.getLessonsMap().get(lessonDirName);
|
||||
if (lesson == null) {
|
||||
return;
|
||||
}
|
||||
Task task = lesson.getTask(taskDirName);
|
||||
if (task == null) {
|
||||
return;
|
||||
}
|
||||
TaskFile taskFile = task.getTaskFile(virtualFile.getName());
|
||||
if (taskFile == null) {
|
||||
return;
|
||||
}
|
||||
List<TaskWindow> taskWindows = taskFile.getTaskWindows();
|
||||
for (TaskWindow taskWindow : taskWindows) {
|
||||
taskWindow.drawHighlighter(editor);
|
||||
}
|
||||
}
|
||||
|
||||
public static void addDocumentListener(Document document, StudyDocumentListener listener) {
|
||||
myDocumentListeners.put(document, listener);
|
||||
}
|
||||
|
||||
public static StudyDocumentListener getListener(Document document) {
|
||||
return myDocumentListeners.get(document);
|
||||
}
|
||||
|
||||
public static void removeListener(Document document) {
|
||||
myDocumentListeners.remove(document);
|
||||
}
|
||||
|
||||
public static boolean indexIsValid(int index, List<TaskWindow> collection) {
|
||||
int size = collection.size();
|
||||
return index >= 0 && index < size;
|
||||
}
|
||||
}
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
package org.jetbrains.plugins.coursecreator;
|
||||
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.LogicalPosition;
|
||||
import com.intellij.openapi.editor.event.DocumentAdapter;
|
||||
import com.intellij.openapi.editor.event.DocumentEvent;
|
||||
import com.intellij.openapi.editor.impl.event.DocumentEventImpl;
|
||||
import org.jetbrains.plugins.coursecreator.format.TaskFile;
|
||||
import org.jetbrains.plugins.coursecreator.format.TaskWindow;
|
||||
|
||||
/**
|
||||
* author: liana
|
||||
* data: 7/16/14.
|
||||
* Listens changes in study files and updates
|
||||
* coordinates of all the windows in current task file
|
||||
*/
|
||||
public abstract class StudyDocumentListener extends DocumentAdapter {
|
||||
private final TaskFile myTaskFile;
|
||||
private int oldLine;
|
||||
private int oldLineStartOffset;
|
||||
private TaskWindow myTaskWindow;
|
||||
|
||||
public StudyDocumentListener(TaskFile taskFile) {
|
||||
myTaskFile = taskFile;
|
||||
}
|
||||
|
||||
|
||||
//remembering old end before document change because of problems
|
||||
// with fragments containing "\n"
|
||||
@Override
|
||||
public void beforeDocumentChange(DocumentEvent e) {
|
||||
int offset = e.getOffset();
|
||||
int oldEnd = offset + e.getOldLength();
|
||||
Document document = e.getDocument();
|
||||
oldLine = document.getLineNumber(oldEnd);
|
||||
oldLineStartOffset = document.getLineStartOffset(oldLine);
|
||||
int line = document.getLineNumber(offset);
|
||||
int offsetInLine = offset - document.getLineStartOffset(line);
|
||||
LogicalPosition pos = new LogicalPosition(line, offsetInLine);
|
||||
myTaskWindow = myTaskFile.getTaskWindow(document, pos);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void documentChanged(DocumentEvent e) {
|
||||
if (e instanceof DocumentEventImpl) {
|
||||
if (!needModify()) {
|
||||
return;
|
||||
}
|
||||
DocumentEventImpl event = (DocumentEventImpl)e;
|
||||
Document document = e.getDocument();
|
||||
int offset = e.getOffset();
|
||||
int change = event.getNewLength() - event.getOldLength();
|
||||
if (myTaskWindow != null) {
|
||||
updateTaskWindowLength(e.getNewFragment(), myTaskWindow, change);
|
||||
}
|
||||
int newEnd = offset + event.getNewLength();
|
||||
int newLine = document.getLineNumber(newEnd);
|
||||
int lineChange = newLine - oldLine;
|
||||
myTaskFile.incrementLines(oldLine + 1, lineChange);
|
||||
int newEndOffsetInLine = offset + e.getNewLength() - document.getLineStartOffset(newLine);
|
||||
int oldEndOffsetInLine = offset + e.getOldLength() - oldLineStartOffset;
|
||||
myTaskFile.updateLine(lineChange, oldLine, newEndOffsetInLine, oldEndOffsetInLine);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void updateTaskWindowLength(CharSequence fragment, TaskWindow taskWindow, int change);
|
||||
|
||||
protected abstract boolean needModify();
|
||||
}
|
||||
|
||||
+105
@@ -0,0 +1,105 @@
|
||||
package org.jetbrains.plugins.coursecreator.actions;
|
||||
|
||||
import com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerImpl;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys;
|
||||
import com.intellij.openapi.actionSystem.Presentation;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.SelectionModel;
|
||||
import com.intellij.openapi.project.DumbAwareAction;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.psi.PsiDirectory;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import org.jetbrains.plugins.coursecreator.CCProjectService;
|
||||
import org.jetbrains.plugins.coursecreator.format.*;
|
||||
import org.jetbrains.plugins.coursecreator.ui.CreateTaskWindowDialog;
|
||||
|
||||
public class AddTaskWindow extends DumbAwareAction {
|
||||
public AddTaskWindow() {
|
||||
super("Add task window","Add task window", null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
final Project project = e.getData(CommonDataKeys.PROJECT);
|
||||
if (project == null) {
|
||||
return;
|
||||
}
|
||||
final PsiFile file = CommonDataKeys.PSI_FILE.getData(e.getDataContext());
|
||||
if (file == null) return;
|
||||
final Editor editor = CommonDataKeys.EDITOR.getData(e.getDataContext());
|
||||
if (editor == null) return;
|
||||
|
||||
final SelectionModel model = editor.getSelectionModel();
|
||||
final Document document = PsiDocumentManager.getInstance(project).getDocument(file);
|
||||
if (document == null) return;
|
||||
final int start = model.getSelectionStart();
|
||||
final int end = model.getSelectionEnd();
|
||||
final int lineNumber = document.getLineNumber(start);
|
||||
final int length = end - start;
|
||||
int realStart = start - document.getLineStartOffset(lineNumber);
|
||||
|
||||
final CCProjectService service = CCProjectService.getInstance(project);
|
||||
final Course course = service.getCourse();
|
||||
final PsiDirectory taskDir = file.getContainingDirectory();
|
||||
final PsiDirectory lessonDir = taskDir.getParent();
|
||||
if (lessonDir == null) return;
|
||||
|
||||
final Lesson lesson = course.getLesson(lessonDir.getName());
|
||||
final Task task = lesson.getTask(taskDir.getName());
|
||||
final TaskFile taskFile = task.getTaskFile(file.getName());
|
||||
final TaskWindow taskWindow = new TaskWindow(lineNumber, realStart, length, model.getSelectedText());
|
||||
CreateTaskWindowDialog dlg = new CreateTaskWindowDialog(project, taskWindow, lesson.getIndex(), task.getIndex(), file.getVirtualFile().getNameWithoutExtension(), taskFile.getTaskWindows().size() + 1);
|
||||
dlg.show();
|
||||
if (dlg.getExitCode() != DialogWrapper.OK_EXIT_CODE) {
|
||||
return;
|
||||
}
|
||||
int index = taskFile.getTaskWindows().size() + 1;
|
||||
taskFile.addTaskWindow(taskWindow, index);
|
||||
taskWindow.drawHighlighter(editor);
|
||||
DaemonCodeAnalyzerImpl.getInstance(project).restart(file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(AnActionEvent event) {
|
||||
final Presentation presentation = event.getPresentation();
|
||||
final Project project = event.getData(CommonDataKeys.PROJECT);
|
||||
if (project == null) {
|
||||
presentation.setVisible(false);
|
||||
presentation.setEnabled(false);
|
||||
return;
|
||||
}
|
||||
final Editor editor = CommonDataKeys.EDITOR.getData(event.getDataContext());
|
||||
final PsiFile file = CommonDataKeys.PSI_FILE.getData(event.getDataContext());
|
||||
if (editor == null || file == null) {
|
||||
presentation.setVisible(false);
|
||||
presentation.setEnabled(false);
|
||||
return;
|
||||
}
|
||||
if (!editor.getSelectionModel().hasSelection()) {
|
||||
presentation.setVisible(false);
|
||||
presentation.setEnabled(false);
|
||||
return;
|
||||
}
|
||||
|
||||
final CCProjectService service = CCProjectService.getInstance(project);
|
||||
final Course course = service.getCourse();
|
||||
final PsiDirectory taskDir = file.getContainingDirectory();
|
||||
final PsiDirectory lessonDir = taskDir.getParent();
|
||||
if (lessonDir == null) return;
|
||||
|
||||
final Lesson lesson = course.getLesson(lessonDir.getName());
|
||||
final Task task = lesson.getTask(taskDir.getName());
|
||||
if (task == null) {
|
||||
presentation.setVisible(false);
|
||||
presentation.setEnabled(false);
|
||||
return;
|
||||
}
|
||||
presentation.setVisible(true);
|
||||
presentation.setEnabled(true);
|
||||
|
||||
}
|
||||
}
|
||||
+198
@@ -0,0 +1,198 @@
|
||||
package org.jetbrains.plugins.coursecreator.actions;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.ide.projectView.ProjectView;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.command.CommandProcessor;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.project.DumbAwareAction;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.VirtualFileManager;
|
||||
import com.intellij.util.io.ZipUtil;
|
||||
import org.jetbrains.plugins.coursecreator.CCProjectService;
|
||||
import org.jetbrains.plugins.coursecreator.StudyDocumentListener;
|
||||
import org.jetbrains.plugins.coursecreator.format.*;
|
||||
import org.jetbrains.plugins.coursecreator.ui.CreateCourseArchiveDialog;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
public class CreateCourseArchive extends DumbAwareAction {
|
||||
private static final Logger LOG = Logger.getInstance(CreateCourseArchive.class.getName());
|
||||
String myZipName;
|
||||
String myLocationDir;
|
||||
|
||||
public void setZipName(String zipName) {
|
||||
myZipName = zipName;
|
||||
}
|
||||
|
||||
public void setLocationDir(String locationDir) {
|
||||
myLocationDir = locationDir;
|
||||
}
|
||||
|
||||
public CreateCourseArchive() {
|
||||
super("Generate course archive", "Generate course archive", AllIcons.FileTypes.Archive);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
final Project project = e.getData(CommonDataKeys.PROJECT);
|
||||
if (project == null) {
|
||||
return;
|
||||
}
|
||||
final CCProjectService service = CCProjectService.getInstance(project);
|
||||
final Course course = service.getCourse();
|
||||
if (course == null) return;
|
||||
CreateCourseArchiveDialog dlg = new CreateCourseArchiveDialog(project, this);
|
||||
dlg.show();
|
||||
if (dlg.getExitCode() != DialogWrapper.OK_EXIT_CODE) {
|
||||
return;
|
||||
}
|
||||
final VirtualFile baseDir = project.getBaseDir();
|
||||
final Map<String, Lesson> lessons = course.getLessonsMap();
|
||||
//List<FileEditor> editorList = new ArrayList<FileEditor>();
|
||||
Map<VirtualFile, TaskFile> taskFiles = new HashMap<VirtualFile, TaskFile>();
|
||||
for (Map.Entry<String, Lesson> lesson : lessons.entrySet()) {
|
||||
final VirtualFile lessonDir = baseDir.findChild(lesson.getKey());
|
||||
if (lessonDir == null) continue;
|
||||
for (Map.Entry<String, Task> task : lesson.getValue().myTasksMap.entrySet()) {
|
||||
final VirtualFile taskDir = lessonDir.findChild(task.getKey());
|
||||
if (taskDir == null) continue;
|
||||
for (Map.Entry<String, TaskFile> entry : task.getValue().task_files.entrySet()) {
|
||||
final VirtualFile file = taskDir.findChild(entry.getKey());
|
||||
if (file == null) continue;
|
||||
final Document document = FileDocumentManager.getInstance().getDocument(file);
|
||||
if (document == null) continue;
|
||||
final TaskFile taskFile = entry.getValue();
|
||||
document.addDocumentListener(new InsertionListener(taskFile));
|
||||
taskFiles.put(file, taskFile);
|
||||
taskFile.setTrackChanges(false);
|
||||
Collections.sort(taskFile.getTaskWindows());
|
||||
for (int i = taskFile.getTaskWindows().size() - 1; i >=0 ; i--) {
|
||||
final TaskWindow taskWindow = taskFile.getTaskWindows().get(i);
|
||||
final String taskText = taskWindow.getTaskText();
|
||||
final int lineStartOffset = document.getLineStartOffset(taskWindow.line);
|
||||
final int offset = lineStartOffset + taskWindow.start;
|
||||
CommandProcessor.getInstance().executeCommand(project, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
document.replaceString(offset, offset + taskWindow.getReplacementLength(), taskText);
|
||||
FileDocumentManager.getInstance().saveDocument(document);
|
||||
}
|
||||
});
|
||||
}
|
||||
}, "x", "qwe");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
generateJson(project);
|
||||
try {
|
||||
File zipFile = new File(myLocationDir, myZipName + ".zip");
|
||||
ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipFile)));
|
||||
|
||||
for (Map.Entry<String, Lesson> entry : lessons.entrySet()) {
|
||||
final VirtualFile lessonDir = baseDir.findChild(entry.getKey());
|
||||
if (lessonDir == null) continue;
|
||||
|
||||
ZipUtil.addFileOrDirRecursively(zos, null, new File(lessonDir.getPath()), lessonDir.getName(), null, null);
|
||||
}
|
||||
ZipUtil.addFileOrDirRecursively(zos, null, new File(baseDir.getPath(), "hints"), "hints", null, null);
|
||||
ZipUtil.addFileOrDirRecursively(zos, null, new File(baseDir.getPath(), "course.json"), "course.json", null, null);
|
||||
ZipUtil.addFileOrDirRecursively(zos, null, new File(baseDir.getPath(), "test_helper.py"), "test_helper.py", null, null);
|
||||
zos.close();
|
||||
Messages.showInfoMessage("Course archive was saved to " + zipFile.getPath(), "Course Archive Was Created Successfully");
|
||||
}
|
||||
catch (IOException e1) {
|
||||
LOG.error(e1);
|
||||
}
|
||||
|
||||
for (Map.Entry<VirtualFile, TaskFile> entry: taskFiles.entrySet()) {
|
||||
TaskFile value = entry.getValue();
|
||||
final Document document = FileDocumentManager.getInstance().getDocument(entry.getKey());
|
||||
if (document == null) {
|
||||
continue;
|
||||
}
|
||||
for (final TaskWindow taskWindow : value.getTaskWindows()){
|
||||
final int lineStartOffset = document.getLineStartOffset(taskWindow.line);
|
||||
final int offset = lineStartOffset + taskWindow.start;
|
||||
CommandProcessor.getInstance().executeCommand(project, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
document.replaceString(offset, offset + taskWindow.length, taskWindow.getPossibleAnswer());
|
||||
FileDocumentManager.getInstance().saveDocument(document);
|
||||
}
|
||||
});
|
||||
}
|
||||
}, "x", "qwe");
|
||||
}
|
||||
value.setTrackChanges(true);
|
||||
}
|
||||
VirtualFileManager.getInstance().refreshWithoutFileWatcher(true);
|
||||
ProjectView.getInstance(project).refresh();
|
||||
}
|
||||
|
||||
private void generateJson(Project project) {
|
||||
final CCProjectService service = CCProjectService.getInstance(project);
|
||||
final Course course = service.getCourse();
|
||||
final Gson gson = new GsonBuilder().setPrettyPrinting().excludeFieldsWithoutExposeAnnotation().create();
|
||||
final String json = gson.toJson(course);
|
||||
final File courseJson = new File(project.getBasePath(), "course.json");
|
||||
FileWriter writer = null;
|
||||
try {
|
||||
writer = new FileWriter(courseJson);
|
||||
writer.write(json);
|
||||
}
|
||||
catch (IOException e) {
|
||||
Messages.showErrorDialog(e.getMessage(), "Failed to Generate Json");
|
||||
LOG.info(e);
|
||||
}
|
||||
catch (Exception e) {
|
||||
Messages.showErrorDialog(e.getMessage(), "Failed to Generate Json");
|
||||
LOG.info(e);
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
if (writer != null) {
|
||||
writer.close();
|
||||
}
|
||||
}
|
||||
catch (IOException e1) {
|
||||
//close silently
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class InsertionListener extends StudyDocumentListener {
|
||||
|
||||
public InsertionListener(TaskFile taskFile) {
|
||||
super(taskFile);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateTaskWindowLength(CharSequence fragment, TaskWindow taskWindow, int change) {
|
||||
//we don't need to update task window length
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean needModify() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
package org.jetbrains.plugins.coursecreator.actions;
|
||||
|
||||
import com.intellij.ide.IdeView;
|
||||
import com.intellij.ide.util.DirectoryChooserUtil;
|
||||
import com.intellij.ide.util.DirectoryUtil;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys;
|
||||
import com.intellij.openapi.actionSystem.LangDataKeys;
|
||||
import com.intellij.openapi.actionSystem.Presentation;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.project.DumbAwareAction;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.psi.PsiDirectory;
|
||||
import com.intellij.util.PlatformIcons;
|
||||
import org.jetbrains.plugins.coursecreator.CCProjectService;
|
||||
import org.jetbrains.plugins.coursecreator.format.Course;
|
||||
import org.jetbrains.plugins.coursecreator.format.Lesson;
|
||||
|
||||
public class CreateLesson extends DumbAwareAction {
|
||||
public CreateLesson() {
|
||||
super("Lesson", "Create new Lesson", PlatformIcons.DIRECTORY_CLOSED_ICON);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
final IdeView view = e.getData(LangDataKeys.IDE_VIEW);
|
||||
final Project project = e.getData(CommonDataKeys.PROJECT);
|
||||
|
||||
if (view == null || project == null) {
|
||||
return;
|
||||
}
|
||||
final PsiDirectory directory = DirectoryChooserUtil.getOrChooseDirectory(view);
|
||||
if (directory == null) return;
|
||||
|
||||
final CCProjectService service = CCProjectService.getInstance(project);
|
||||
final Course course = service.getCourse();
|
||||
final int size = course.getLessons().size();
|
||||
final String lessonName = Messages.showInputDialog("Name:", "Lesson Name", null, "lesson" + (size+1), null);
|
||||
if (lessonName == null) return;
|
||||
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final PsiDirectory lessonDirectory = DirectoryUtil.createSubdirectories("lesson" + (size+1), directory, "\\/");
|
||||
if (lessonDirectory != null) {
|
||||
view.selectElement(lessonDirectory);
|
||||
final Lesson lesson = new Lesson(lessonName);
|
||||
lesson.setIndex(size + 1);
|
||||
course.addLesson(lesson, lessonDirectory);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(AnActionEvent event) {
|
||||
final Presentation presentation = event.getPresentation();
|
||||
final Project project = event.getData(CommonDataKeys.PROJECT);
|
||||
if (project == null) {
|
||||
presentation.setVisible(false);
|
||||
presentation.setEnabled(false);
|
||||
return;
|
||||
}
|
||||
|
||||
final IdeView view = event.getData(LangDataKeys.IDE_VIEW);
|
||||
if (view == null) {
|
||||
presentation.setVisible(false);
|
||||
presentation.setEnabled(false);
|
||||
return;
|
||||
}
|
||||
|
||||
final PsiDirectory[] directories = view.getDirectories();
|
||||
if (directories.length == 0) {
|
||||
presentation.setVisible(false);
|
||||
presentation.setEnabled(false);
|
||||
return;
|
||||
}
|
||||
final PsiDirectory directory = DirectoryChooserUtil.getOrChooseDirectory(view);
|
||||
if (directory != null && !project.getBaseDir().equals(directory.getVirtualFile())) {
|
||||
presentation.setVisible(false);
|
||||
presentation.setEnabled(false);
|
||||
return;
|
||||
}
|
||||
presentation.setVisible(true);
|
||||
presentation.setEnabled(true);
|
||||
|
||||
}
|
||||
}
|
||||
+122
@@ -0,0 +1,122 @@
|
||||
package org.jetbrains.plugins.coursecreator.actions;
|
||||
|
||||
import com.intellij.ide.IdeView;
|
||||
import com.intellij.ide.fileTemplates.FileTemplate;
|
||||
import com.intellij.ide.fileTemplates.FileTemplateManager;
|
||||
import com.intellij.ide.fileTemplates.FileTemplateUtil;
|
||||
import com.intellij.ide.util.DirectoryChooserUtil;
|
||||
import com.intellij.ide.util.DirectoryUtil;
|
||||
import com.intellij.ide.util.EditorHelper;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys;
|
||||
import com.intellij.openapi.actionSystem.LangDataKeys;
|
||||
import com.intellij.openapi.actionSystem.Presentation;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.project.DumbAwareAction;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.psi.PsiDirectory;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.util.PlatformIcons;
|
||||
import org.jetbrains.plugins.coursecreator.CCProjectService;
|
||||
import org.jetbrains.plugins.coursecreator.format.Course;
|
||||
import org.jetbrains.plugins.coursecreator.format.Lesson;
|
||||
import org.jetbrains.plugins.coursecreator.format.Task;
|
||||
|
||||
public class CreateTask extends DumbAwareAction {
|
||||
public CreateTask() {
|
||||
super("Task", "Create new Task", PlatformIcons.DIRECTORY_CLOSED_ICON);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
final IdeView view = e.getData(LangDataKeys.IDE_VIEW);
|
||||
final Project project = e.getData(CommonDataKeys.PROJECT);
|
||||
|
||||
if (view == null || project == null) {
|
||||
return;
|
||||
}
|
||||
final PsiDirectory directory = DirectoryChooserUtil.getOrChooseDirectory(view);
|
||||
|
||||
if (directory == null) return;
|
||||
final CCProjectService service = CCProjectService.getInstance(project);
|
||||
final Course course = service.getCourse();
|
||||
final Lesson lesson = course.getLesson(directory.getName());
|
||||
final int size = lesson.getTasklist().size();
|
||||
|
||||
final String taskName = Messages.showInputDialog("Name:", "Task Name", null, "task" + (size + 1), null);
|
||||
if (taskName == null) return;
|
||||
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final PsiDirectory taskDirectory = DirectoryUtil.createSubdirectories("task" + (size + 1), directory, "\\/");
|
||||
if (taskDirectory != null) {
|
||||
final FileTemplate template = FileTemplateManager.getInstance().getInternalTemplate("task.html");
|
||||
final FileTemplate testsTemplate = FileTemplateManager.getInstance().getInternalTemplate("tests");
|
||||
final FileTemplate taskTemplate = FileTemplateManager.getInstance().getInternalTemplate("task.py");
|
||||
try {
|
||||
final PsiElement taskFile = FileTemplateUtil.createFromTemplate(template, "task.html", null, taskDirectory);
|
||||
final PsiElement testsFile = FileTemplateUtil.createFromTemplate(testsTemplate, "tests.py", null, taskDirectory);
|
||||
final PsiElement taskPyFile = FileTemplateUtil.createFromTemplate(taskTemplate, "file1" + ".py", null, taskDirectory);
|
||||
|
||||
final Task task = new Task(taskName);
|
||||
task.addTaskFile(taskPyFile.getContainingFile().getName(), size + 1);
|
||||
task.setIndex(size + 1);
|
||||
lesson.addTask(task, taskDirectory);
|
||||
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
EditorHelper.openInEditor(testsFile, false);
|
||||
EditorHelper.openInEditor(taskPyFile, false);
|
||||
view.selectElement(taskFile);
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (Exception ignored) {
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(AnActionEvent event) {
|
||||
final Presentation presentation = event.getPresentation();
|
||||
final Project project = event.getData(CommonDataKeys.PROJECT);
|
||||
if (project == null) {
|
||||
presentation.setVisible(false);
|
||||
presentation.setEnabled(false);
|
||||
return;
|
||||
}
|
||||
|
||||
final IdeView view = event.getData(LangDataKeys.IDE_VIEW);
|
||||
if (view == null) {
|
||||
presentation.setVisible(false);
|
||||
presentation.setEnabled(false);
|
||||
return;
|
||||
}
|
||||
|
||||
final PsiDirectory[] directories = view.getDirectories();
|
||||
if (directories.length == 0) {
|
||||
presentation.setVisible(false);
|
||||
presentation.setEnabled(false);
|
||||
return;
|
||||
}
|
||||
final PsiDirectory directory = DirectoryChooserUtil.getOrChooseDirectory(view);
|
||||
final CCProjectService service = CCProjectService.getInstance(project);
|
||||
final Course course = service.getCourse();
|
||||
if (course != null && directory != null && course.getLesson(directory.getName()) == null) {
|
||||
presentation.setVisible(false);
|
||||
presentation.setEnabled(false);
|
||||
return;
|
||||
}
|
||||
|
||||
presentation.setVisible(true);
|
||||
presentation.setEnabled(true);
|
||||
|
||||
}
|
||||
}
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
package org.jetbrains.plugins.coursecreator.actions;
|
||||
|
||||
import com.intellij.ide.IdeView;
|
||||
import com.intellij.ide.fileTemplates.FileTemplate;
|
||||
import com.intellij.ide.fileTemplates.FileTemplateManager;
|
||||
import com.intellij.ide.fileTemplates.FileTemplateUtil;
|
||||
import com.intellij.ide.util.DirectoryChooserUtil;
|
||||
import com.intellij.ide.util.EditorHelper;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys;
|
||||
import com.intellij.openapi.actionSystem.LangDataKeys;
|
||||
import com.intellij.openapi.actionSystem.Presentation;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.project.DumbAwareAction;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.psi.PsiDirectory;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import icons.PythonPsiApiIcons;
|
||||
import org.jetbrains.plugins.coursecreator.CCProjectService;
|
||||
import org.jetbrains.plugins.coursecreator.format.Course;
|
||||
import org.jetbrains.plugins.coursecreator.format.Lesson;
|
||||
import org.jetbrains.plugins.coursecreator.format.Task;
|
||||
|
||||
public class CreateTaskFile extends DumbAwareAction {
|
||||
|
||||
public CreateTaskFile() {
|
||||
super("Task File", "Create new Task File", PythonPsiApiIcons.PythonFile);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
final IdeView view = e.getData(LangDataKeys.IDE_VIEW);
|
||||
final Project project = e.getData(CommonDataKeys.PROJECT);
|
||||
|
||||
if (view == null || project == null) {
|
||||
return;
|
||||
}
|
||||
final PsiDirectory taskDir = DirectoryChooserUtil.getOrChooseDirectory(view);
|
||||
if (taskDir == null) return;
|
||||
PsiDirectory lessonDir = taskDir.getParent();
|
||||
if (lessonDir == null) {
|
||||
return;
|
||||
}
|
||||
final CCProjectService service = CCProjectService.getInstance(project);
|
||||
final Course course = service.getCourse();
|
||||
final Lesson lesson = course.getLesson(lessonDir.getName());
|
||||
final Task task = lesson.getTask(taskDir.getName());
|
||||
|
||||
final int index = task.getTaskFiles().size() + 1;
|
||||
String generatedName = "file" + index;
|
||||
final String taskFileName = Messages.showInputDialog("Name:", "Task File Name", null, generatedName, null);
|
||||
if (taskFileName == null) return;
|
||||
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final FileTemplate taskTemplate = FileTemplateManager.getInstance().getInternalTemplate("task.py");
|
||||
try {
|
||||
final PsiElement taskPyFile = FileTemplateUtil.createFromTemplate(taskTemplate, taskFileName + ".py", null, taskDir);
|
||||
task.addTaskFile(taskPyFile.getContainingFile().getName(), index);
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
EditorHelper.openInEditor(taskPyFile, false);
|
||||
view.selectElement(taskPyFile);
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(AnActionEvent event) {
|
||||
final Presentation presentation = event.getPresentation();
|
||||
final Project project = event.getData(CommonDataKeys.PROJECT);
|
||||
if (project == null) {
|
||||
presentation.setVisible(false);
|
||||
presentation.setEnabled(false);
|
||||
return;
|
||||
}
|
||||
|
||||
final IdeView view = event.getData(LangDataKeys.IDE_VIEW);
|
||||
if (view == null) {
|
||||
presentation.setVisible(false);
|
||||
presentation.setEnabled(false);
|
||||
return;
|
||||
}
|
||||
|
||||
final PsiDirectory[] directories = view.getDirectories();
|
||||
if (directories.length == 0) {
|
||||
presentation.setVisible(false);
|
||||
presentation.setEnabled(false);
|
||||
return;
|
||||
}
|
||||
final PsiDirectory directory = DirectoryChooserUtil.getOrChooseDirectory(view);
|
||||
final CCProjectService service = CCProjectService.getInstance(project);
|
||||
final Course course = service.getCourse();
|
||||
if (course != null && directory != null && !directory.getName().contains("task")) {
|
||||
presentation.setVisible(false);
|
||||
presentation.setEnabled(false);
|
||||
return;
|
||||
}
|
||||
presentation.setVisible(true);
|
||||
presentation.setEnabled(true);
|
||||
}
|
||||
}
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
package org.jetbrains.plugins.coursecreator.actions;
|
||||
|
||||
import com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerImpl;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys;
|
||||
import com.intellij.openapi.actionSystem.PlatformDataKeys;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.DumbAwareAction;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiDirectory;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.coursecreator.CCProjectService;
|
||||
import org.jetbrains.plugins.coursecreator.format.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@SuppressWarnings("ComponentNotRegistered")
|
||||
public class DeleteTaskWindow extends DumbAwareAction {
|
||||
@NotNull
|
||||
private final TaskWindow myTaskWindow;
|
||||
|
||||
public DeleteTaskWindow(@NotNull final TaskWindow taskWindow) {
|
||||
super("Delete task window","Delete task window", null);
|
||||
myTaskWindow = taskWindow;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
final Project project = e.getData(PlatformDataKeys.PROJECT);
|
||||
if (project == null) return;
|
||||
final PsiFile file = CommonDataKeys.PSI_FILE.getData(e.getDataContext());
|
||||
if (file == null) return;
|
||||
final Editor editor = CommonDataKeys.EDITOR.getData(e.getDataContext());
|
||||
if (editor == null) {
|
||||
return;
|
||||
}
|
||||
final Document document = PsiDocumentManager.getInstance(project).getDocument(file);
|
||||
if (document == null) return;
|
||||
|
||||
final CCProjectService service = CCProjectService.getInstance(project);
|
||||
final Course course = service.getCourse();
|
||||
final PsiDirectory taskDir = file.getContainingDirectory();
|
||||
final PsiDirectory lessonDir = taskDir.getParent();
|
||||
if (lessonDir == null) return;
|
||||
|
||||
final Lesson lesson = course.getLesson(lessonDir.getName());
|
||||
final Task task = lesson.getTask(taskDir.getName());
|
||||
final TaskFile taskFile = task.getTaskFile(file.getName());
|
||||
final List<TaskWindow> taskWindows = taskFile.getTaskWindows();
|
||||
if (taskWindows.contains(myTaskWindow)) {
|
||||
myTaskWindow.removeResources(project);
|
||||
taskWindows.remove(myTaskWindow);
|
||||
editor.getMarkupModel().removeAllHighlighters();
|
||||
CCProjectService.drawTaskWindows(file.getVirtualFile(), editor, course);
|
||||
DaemonCodeAnalyzerImpl.getInstance(project).restart(file);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
package org.jetbrains.plugins.coursecreator.actions;
|
||||
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys;
|
||||
import com.intellij.openapi.actionSystem.PlatformDataKeys;
|
||||
import com.intellij.openapi.project.DumbAwareAction;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiDirectory;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.coursecreator.CCProjectService;
|
||||
import org.jetbrains.plugins.coursecreator.format.*;
|
||||
import org.jetbrains.plugins.coursecreator.ui.CreateTaskWindowDialog;
|
||||
|
||||
@SuppressWarnings("ComponentNotRegistered")
|
||||
public class ShowTaskWindowText extends DumbAwareAction {
|
||||
@NotNull
|
||||
private final TaskWindow myTaskWindow;
|
||||
|
||||
public ShowTaskWindowText(@NotNull final TaskWindow taskWindow) {
|
||||
super("Add task window","Add task window", null);
|
||||
myTaskWindow = taskWindow;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
final Project project = e.getData(PlatformDataKeys.PROJECT);
|
||||
if (project == null) return;
|
||||
final PsiFile file = CommonDataKeys.PSI_FILE.getData(e.getDataContext());
|
||||
if (file == null) return;
|
||||
final CCProjectService service = CCProjectService.getInstance(project);
|
||||
final Course course = service.getCourse();
|
||||
final PsiDirectory taskDir = file.getContainingDirectory();
|
||||
final PsiDirectory lessonDir = taskDir.getParent();
|
||||
if (lessonDir == null) return;
|
||||
|
||||
final Lesson lesson = course.getLesson(lessonDir.getName());
|
||||
final Task task = lesson.getTask(taskDir.getName());
|
||||
final TaskFile taskFile = task.getTaskFile(file.getName());
|
||||
//TODO: copy task window and return if modification canceled
|
||||
CreateTaskWindowDialog dlg = new CreateTaskWindowDialog(project, myTaskWindow, lesson.getIndex(), task.getIndex(), file.getVirtualFile().getNameWithoutExtension(), taskFile.getTaskWindows().size() + 1);
|
||||
dlg.show();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package org.jetbrains.plugins.coursecreator.format;
|
||||
|
||||
import com.google.gson.annotations.Expose;
|
||||
import com.intellij.psi.PsiDirectory;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class Course {
|
||||
@Expose public List<Lesson> lessons = new ArrayList<Lesson>();
|
||||
@Expose public String description;
|
||||
|
||||
@Expose public String name;
|
||||
@Expose public String author;
|
||||
|
||||
public Map<String, Lesson> myLessonsMap = new HashMap<String, Lesson>();
|
||||
|
||||
public Map<String, Lesson> getLessonsMap() {
|
||||
return myLessonsMap;
|
||||
}
|
||||
|
||||
public Lesson getLesson(@NotNull final String name) {
|
||||
return myLessonsMap.get(name);
|
||||
}
|
||||
|
||||
|
||||
public Course() {
|
||||
}
|
||||
|
||||
public Course(@NotNull final String name, @NotNull final String author, @NotNull final String description) {
|
||||
this.description = description;
|
||||
this.name = name;
|
||||
this.author = author;
|
||||
}
|
||||
|
||||
public List<Lesson> getLessons() {
|
||||
return lessons;
|
||||
}
|
||||
|
||||
public void addLesson(@NotNull final Lesson lesson, @NotNull final PsiDirectory directory) {
|
||||
lessons.add(lesson);
|
||||
myLessonsMap.put(directory.getName(), lesson);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package org.jetbrains.plugins.coursecreator.format;
|
||||
|
||||
import com.google.gson.annotations.Expose;
|
||||
import com.intellij.psi.PsiDirectory;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class Lesson {
|
||||
@Expose public String name;
|
||||
@Expose public List<Task> task_list = new ArrayList<Task>();
|
||||
|
||||
public int myIndex;
|
||||
public Map<String, Task> myTasksMap = new HashMap<String, Task>();
|
||||
|
||||
public Lesson() {}
|
||||
|
||||
public Lesson(@NotNull final String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void addTask(@NotNull final Task task, PsiDirectory taskDirectory) {
|
||||
myTasksMap.put(taskDirectory.getName(), task);
|
||||
task_list.add(task);
|
||||
}
|
||||
|
||||
public Task getTask(@NotNull final String name) {
|
||||
return myTasksMap.get(name);
|
||||
}
|
||||
|
||||
public List<Task> getTasklist() {
|
||||
return task_list;
|
||||
}
|
||||
|
||||
public void setIndex(int index) {
|
||||
myIndex = index;
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
return myIndex;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package org.jetbrains.plugins.coursecreator.format;
|
||||
|
||||
import com.google.gson.annotations.Expose;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class Task {
|
||||
@Expose public String name;
|
||||
@Expose public Map<String, TaskFile> task_files = new HashMap<String, TaskFile>();
|
||||
public int myIndex;
|
||||
|
||||
public Task() {}
|
||||
|
||||
public Task(@NotNull final String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
return myIndex;
|
||||
}
|
||||
|
||||
public void addTaskFile(@NotNull final String name, int index) {
|
||||
TaskFile taskFile = new TaskFile();
|
||||
taskFile.setIndex(index);
|
||||
task_files.put(name, taskFile);
|
||||
}
|
||||
|
||||
public TaskFile getTaskFile(@NotNull final String name) {
|
||||
return task_files.get(name);
|
||||
}
|
||||
|
||||
public void setIndex(int index) {
|
||||
myIndex = index;
|
||||
}
|
||||
|
||||
public Map<String, TaskFile> getTaskFiles() {
|
||||
return task_files;
|
||||
}
|
||||
}
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
package org.jetbrains.plugins.coursecreator.format;
|
||||
|
||||
import com.google.gson.annotations.Expose;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.LogicalPosition;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.coursecreator.CCProjectService;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class TaskFile {
|
||||
@Expose public List<TaskWindow> task_windows = new ArrayList<TaskWindow>();
|
||||
public int myIndex;
|
||||
public boolean myTrackChanges = true;
|
||||
|
||||
public boolean isTrackChanges() {
|
||||
return myTrackChanges;
|
||||
}
|
||||
|
||||
public void setTrackChanges(boolean trackChanges) {
|
||||
myTrackChanges = trackChanges;
|
||||
}
|
||||
|
||||
public TaskFile() {}
|
||||
|
||||
public void addTaskWindow(@NotNull final TaskWindow taskWindow, int index) {
|
||||
taskWindow.setIndex(index);
|
||||
task_windows.add(taskWindow);
|
||||
}
|
||||
|
||||
public List<TaskWindow> getTaskWindows() {
|
||||
return task_windows;
|
||||
}
|
||||
|
||||
public void setIndex(int index) {
|
||||
myIndex = index;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param pos position in editor
|
||||
* @return task window located in specified position or null if there is no task window in this position
|
||||
*/
|
||||
@Nullable
|
||||
public TaskWindow getTaskWindow(@NotNull final Document document, @NotNull final LogicalPosition pos) {
|
||||
int line = pos.line;
|
||||
if (line >= document.getLineCount()) {
|
||||
return null;
|
||||
}
|
||||
int column = pos.column;
|
||||
int offset = document.getLineStartOffset(line) + column;
|
||||
for (TaskWindow tw : task_windows) {
|
||||
if (tw.getLine() <= line) {
|
||||
int twStartOffset = tw.getRealStartOffset(document);
|
||||
final int length = tw.getReplacementLength() > 0 ? tw.getReplacementLength() : 0;
|
||||
int twEndOffset = twStartOffset + length;
|
||||
if (twStartOffset <= offset && offset <= twEndOffset) {
|
||||
return tw;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates task window lines
|
||||
*
|
||||
* @param startLine lines greater than this line and including this line will be updated
|
||||
* @param change change to be added to line numbers
|
||||
*/
|
||||
public void incrementLines(int startLine, int change) {
|
||||
for (TaskWindow taskTaskWindow : task_windows) {
|
||||
if (taskTaskWindow.getLine() >= startLine) {
|
||||
taskTaskWindow.setLine(taskTaskWindow.getLine() + change);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates windows in specific line
|
||||
*
|
||||
* @param lineChange change in line number
|
||||
* @param line line to be updated
|
||||
* @param newEndOffsetInLine distance from line start to end of inserted fragment
|
||||
* @param oldEndOffsetInLine distance from line start to end of changed fragment
|
||||
*/
|
||||
public void updateLine(int lineChange, int line, int newEndOffsetInLine, int oldEndOffsetInLine) {
|
||||
for (TaskWindow w : task_windows) {
|
||||
if ((w.getLine() == line) && (w.getStart() >= oldEndOffsetInLine)) {
|
||||
int distance = w.getStart() - oldEndOffsetInLine;
|
||||
boolean coveredByPrevTW = false;
|
||||
int prevIndex = w.getIndex() - 1;
|
||||
if (CCProjectService.indexIsValid(prevIndex, task_windows)) {
|
||||
TaskWindow prevTW = task_windows.get(prevIndex);
|
||||
if (prevTW.getLine() == line) {
|
||||
int endOffset = prevTW.getStart() + prevTW.getLength();
|
||||
if (endOffset >= newEndOffsetInLine) {
|
||||
coveredByPrevTW = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (lineChange != 0 || newEndOffsetInLine <= w.getStart() || coveredByPrevTW) {
|
||||
w.setStart(distance + newEndOffsetInLine);
|
||||
w.setLine(line + lineChange);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+133
@@ -0,0 +1,133 @@
|
||||
package org.jetbrains.plugins.coursecreator.format;
|
||||
|
||||
import com.google.gson.annotations.Expose;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.colors.EditorColors;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsManager;
|
||||
import com.intellij.openapi.editor.markup.HighlighterLayer;
|
||||
import com.intellij.openapi.editor.markup.HighlighterTargetArea;
|
||||
import com.intellij.openapi.editor.markup.RangeHighlighter;
|
||||
import com.intellij.openapi.editor.markup.TextAttributes;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.coursecreator.CCProjectService;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class TaskWindow implements Comparable{
|
||||
|
||||
@Expose public int line;
|
||||
@Expose public int start;
|
||||
@Expose public String hint;
|
||||
@Expose public String possible_answer;
|
||||
@Expose public int length;
|
||||
public String myTaskText;
|
||||
public int myReplacementLength;
|
||||
public int myIndex;
|
||||
|
||||
public TaskWindow() {}
|
||||
|
||||
public TaskWindow(int line, int start, int length, String selectedText) {
|
||||
this.line = line;
|
||||
this.start = start;
|
||||
myReplacementLength = length;
|
||||
this.possible_answer = selectedText;
|
||||
}
|
||||
|
||||
public void setTaskText(@NotNull final String taskText) {
|
||||
myTaskText = taskText;
|
||||
length = myTaskText.length();
|
||||
}
|
||||
|
||||
public String getTaskText() {
|
||||
return myTaskText;
|
||||
}
|
||||
|
||||
public int getReplacementLength() {
|
||||
return myReplacementLength;
|
||||
}
|
||||
|
||||
public void setHint(String hint) {
|
||||
this.hint = hint;
|
||||
}
|
||||
|
||||
public String getHintName() {
|
||||
return hint;
|
||||
}
|
||||
|
||||
public void removeResources(@NotNull final Project project) {
|
||||
if (hint != null) {
|
||||
VirtualFile hints = project.getBaseDir().findChild("hints");
|
||||
if (hints == null) {
|
||||
return;
|
||||
}
|
||||
File hintFile = new File(hints.getPath(), hint);
|
||||
CCProjectService.deleteProjectFile(hintFile, project);
|
||||
}
|
||||
}
|
||||
|
||||
public void drawHighlighter(@NotNull final Editor editor) {
|
||||
int startOffset = editor.getDocument().getLineStartOffset(line) + start;
|
||||
int endOffset = startOffset + myReplacementLength;
|
||||
TextAttributes defaultTestAttributes =
|
||||
EditorColorsManager.getInstance().getGlobalScheme().getAttributes(EditorColors.LIVE_TEMPLATE_ATTRIBUTES);
|
||||
RangeHighlighter highlighter =
|
||||
editor.getMarkupModel().addRangeHighlighter(startOffset, endOffset, HighlighterLayer.LAST + 1, defaultTestAttributes,
|
||||
HighlighterTargetArea.EXACT_RANGE);
|
||||
highlighter.setGreedyToLeft(true);
|
||||
highlighter.setGreedyToRight(true);
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
return myIndex;
|
||||
}
|
||||
|
||||
public void setIndex(int index) {
|
||||
|
||||
myIndex = index;
|
||||
}
|
||||
|
||||
public void setReplacementLength(int replacementLength) {
|
||||
myReplacementLength = replacementLength;
|
||||
}
|
||||
|
||||
public int getLine() {
|
||||
return line;
|
||||
}
|
||||
|
||||
public int getRealStartOffset(Document document) {
|
||||
return document.getLineStartOffset(line) + start;
|
||||
}
|
||||
|
||||
public void setLine(int line) {
|
||||
this.line = line;
|
||||
}
|
||||
|
||||
public int getStart() {
|
||||
return start;
|
||||
}
|
||||
|
||||
public void setStart(int start) {
|
||||
this.start = start;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Object o) {
|
||||
TaskWindow taskWindow = (TaskWindow)o;
|
||||
int lineDiff = line - taskWindow.line;
|
||||
if (lineDiff == 0) {
|
||||
return start - taskWindow.start;
|
||||
}
|
||||
return lineDiff;
|
||||
}
|
||||
|
||||
public String getPossibleAnswer() {
|
||||
return possible_answer;
|
||||
}
|
||||
|
||||
public int getLength() {
|
||||
return length;
|
||||
}
|
||||
}
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
package org.jetbrains.plugins.coursecreator.highlighting;
|
||||
|
||||
import com.intellij.codeHighlighting.Pass;
|
||||
import com.intellij.codeInsight.daemon.LineMarkerInfo;
|
||||
import com.intellij.codeInsight.daemon.LineMarkerProvider;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.markup.GutterIconRenderer;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.IconLoader;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.PsiDirectory;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.coursecreator.CCProjectService;
|
||||
import org.jetbrains.plugins.coursecreator.format.*;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public class CCTaskLineMarkerProvider implements LineMarkerProvider {
|
||||
private static final Logger LOG = Logger.getInstance(CCTaskLineMarkerProvider.class.getName());
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public LineMarkerInfo getLineMarkerInfo(@NotNull PsiElement element) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void collectSlowLineMarkers(@NotNull List<PsiElement> elements, @NotNull final Collection<LineMarkerInfo> result) {
|
||||
for (PsiElement element : elements) {
|
||||
if (element instanceof PsiFile) {
|
||||
final Project project = element.getProject();
|
||||
final Course course = CCProjectService.getInstance(project).getCourse();
|
||||
final String taskFileName = ((PsiFile) element).getName();
|
||||
final PsiDirectory taskDir = ((PsiFile) element).getParent();
|
||||
if (taskDir == null) continue;
|
||||
final String taskDirName = taskDir.getName();
|
||||
final PsiDirectory lessonDir = taskDir.getParentDirectory();
|
||||
if (lessonDir == null) continue;
|
||||
final String lessonDirName = lessonDir.getName();
|
||||
final Lesson lesson = course.getLesson(lessonDirName);
|
||||
if (lesson == null) continue;
|
||||
final Task task = lesson.getTask(taskDirName);
|
||||
final TaskFile taskFile = task.getTaskFile(taskFileName);
|
||||
if (taskFile == null) continue;
|
||||
final Document document = PsiDocumentManager.getInstance(project).getDocument((PsiFile) element);
|
||||
if (document == null) continue;
|
||||
for (final TaskWindow taskWindow : taskFile.getTaskWindows()) {
|
||||
if (taskWindow.line > document.getLineCount()) continue;
|
||||
final int lineStartOffset = document.getLineStartOffset(taskWindow.line);
|
||||
final int offset = lineStartOffset + taskWindow.start;
|
||||
if (offset > document.getTextLength()) continue;
|
||||
final TextRange textRange = TextRange.create(offset, offset + taskWindow.getReplacementLength());
|
||||
@SuppressWarnings("unchecked")
|
||||
final LineMarkerInfo info = new LineMarkerInfo(element, textRange,
|
||||
IconLoader.getIcon("/icons/gutter.png"), Pass.UPDATE_OVERRIDEN_MARKERS,
|
||||
null, null, GutterIconRenderer.Alignment.CENTER) {
|
||||
@Nullable
|
||||
@Override
|
||||
public GutterIconRenderer createGutterRenderer() {
|
||||
return new TaskTextGutter(taskWindow, this);
|
||||
}
|
||||
};
|
||||
result.add(info);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
package org.jetbrains.plugins.coursecreator.highlighting;
|
||||
|
||||
import com.intellij.codeInsight.daemon.LineMarkerInfo;
|
||||
import com.intellij.openapi.actionSystem.ActionGroup;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.DefaultActionGroup;
|
||||
import com.intellij.openapi.util.IconLoader;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.coursecreator.actions.DeleteTaskWindow;
|
||||
import org.jetbrains.plugins.coursecreator.actions.ShowTaskWindowText;
|
||||
import org.jetbrains.plugins.coursecreator.format.TaskWindow;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
public class TaskTextGutter extends LineMarkerInfo.LineMarkerGutterIconRenderer {
|
||||
@NotNull
|
||||
private final TaskWindow myTaskWindow;
|
||||
|
||||
public TaskTextGutter(@NotNull final TaskWindow taskWindow, LineMarkerInfo lineMarkerInfo) {
|
||||
super(lineMarkerInfo);
|
||||
myTaskWindow = taskWindow;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Icon getIcon() {
|
||||
return IconLoader.getIcon("/icons/gutter.png");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return this == o || o instanceof TaskTextGutter
|
||||
&& myTaskWindow.getTaskText().equals(((TaskTextGutter) o).getTaskWindow().getTaskText());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public TaskWindow getTaskWindow() {
|
||||
return myTaskWindow;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return myTaskWindow.hashCode();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public AnAction getClickAction() {
|
||||
return new ShowTaskWindowText(myTaskWindow);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public ActionGroup getPopupMenuActions() {
|
||||
DefaultActionGroup group = new DefaultActionGroup();
|
||||
group.add(new DeleteTaskWindow(myTaskWindow));
|
||||
return group;
|
||||
}
|
||||
}
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
package org.jetbrains.plugins.coursecreator.projectView;
|
||||
|
||||
import com.intellij.ide.projectView.PresentationData;
|
||||
import com.intellij.ide.projectView.ViewSettings;
|
||||
import com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiDirectory;
|
||||
import com.intellij.ui.SimpleTextAttributes;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.coursecreator.CCProjectService;
|
||||
import org.jetbrains.plugins.coursecreator.format.Course;
|
||||
import org.jetbrains.plugins.coursecreator.format.Lesson;
|
||||
import org.jetbrains.plugins.coursecreator.format.Task;
|
||||
|
||||
public class CCDirectoryNode extends PsiDirectoryNode {
|
||||
private final PsiDirectory myValue;
|
||||
private final Project myProject;
|
||||
|
||||
public CCDirectoryNode(@NotNull final Project project,
|
||||
PsiDirectory value,
|
||||
ViewSettings viewSettings) {
|
||||
super(project, value, viewSettings);
|
||||
myValue = value;
|
||||
myProject = project;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateImpl(PresentationData data) {
|
||||
String valueName = myValue.getName();
|
||||
final Course course = CCProjectService.getInstance(myProject).getCourse();
|
||||
if (course == null) return;
|
||||
if (myProject.getBaseDir().equals(myValue.getVirtualFile())) {
|
||||
data.clearText();
|
||||
data.addText(valueName, SimpleTextAttributes.REGULAR_ATTRIBUTES);
|
||||
data.addText(" (" + course.getName() + ")", SimpleTextAttributes.GRAYED_ATTRIBUTES);
|
||||
return;
|
||||
}
|
||||
final Lesson lesson = course.getLesson(valueName);
|
||||
if (lesson != null) {
|
||||
data.clearText();
|
||||
data.addText(valueName, SimpleTextAttributes.REGULAR_ATTRIBUTES);
|
||||
data.addText(" (" + lesson.name + ")", SimpleTextAttributes.GRAYED_ATTRIBUTES);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
final PsiDirectory parentDir = myValue.getParentDirectory();
|
||||
if (parentDir != null) {
|
||||
final Lesson parentLesson = course.getLesson(parentDir.getName());
|
||||
if (parentLesson != null) {
|
||||
final Task task = parentLesson.getTask(valueName);
|
||||
if (task != null) {
|
||||
data.clearText();
|
||||
data.addText(valueName, SimpleTextAttributes.REGULAR_ATTRIBUTES);
|
||||
data.addText(" (" + task.name + ")", SimpleTextAttributes.GRAYED_ATTRIBUTES);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
data.setPresentableText(valueName);
|
||||
}
|
||||
|
||||
}
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
package org.jetbrains.plugins.coursecreator.projectView;
|
||||
|
||||
import com.intellij.ide.projectView.TreeStructureProvider;
|
||||
import com.intellij.ide.projectView.ViewSettings;
|
||||
import com.intellij.ide.util.treeView.AbstractTreeNode;
|
||||
import com.intellij.openapi.project.DumbAware;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiDirectory;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.coursecreator.CCProjectService;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
public class CCTreeStructureProvider implements TreeStructureProvider, DumbAware {
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<AbstractTreeNode> modify(@NotNull AbstractTreeNode parent,
|
||||
@NotNull Collection<AbstractTreeNode> children,
|
||||
ViewSettings settings) {
|
||||
if (!needModify(parent)) {
|
||||
return children;
|
||||
}
|
||||
Collection<AbstractTreeNode> nodes = new ArrayList<AbstractTreeNode>();
|
||||
for (AbstractTreeNode node : children) {
|
||||
Project project = node.getProject();
|
||||
if (project != null) {
|
||||
if (node.getValue() instanceof PsiDirectory) {
|
||||
PsiDirectory directory = (PsiDirectory) node.getValue();
|
||||
nodes.add(new CCDirectoryNode(project, directory, settings));
|
||||
} else {
|
||||
nodes.add(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
return nodes;
|
||||
}
|
||||
|
||||
private static boolean needModify(@NotNull final AbstractTreeNode parent) {
|
||||
Project project = parent.getProject();
|
||||
if (project != null) {
|
||||
if (CCProjectService.getInstance(project).getCourse() == null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Object getData(Collection<AbstractTreeNode> selected, String dataName) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.jetbrains.plugins.coursecreator.ui.CCNewProjectPanel">
|
||||
<grid id="27dc6" binding="myPanel" layout-manager="GridLayoutManager" row-count="3" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<xy x="20" y="20" width="500" height="400"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="fd520" class="javax.swing.JLabel">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false">
|
||||
<preferred-size width="95" height="-1"/>
|
||||
</grid>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="Name:"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="7e88" class="javax.swing.JTextField" binding="myName">
|
||||
<constraints>
|
||||
<grid row="0" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
|
||||
<preferred-size width="150" height="-1"/>
|
||||
</grid>
|
||||
</constraints>
|
||||
<properties/>
|
||||
</component>
|
||||
<component id="ec56c" class="javax.swing.JLabel">
|
||||
<constraints>
|
||||
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="9" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="Description"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="2e2d7" class="javax.swing.JLabel">
|
||||
<constraints>
|
||||
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false">
|
||||
<preferred-size width="95" height="-1"/>
|
||||
</grid>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="Author:"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="41fe6" class="javax.swing.JTextField" binding="myAuthorField">
|
||||
<constraints>
|
||||
<grid row="1" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
|
||||
<preferred-size width="150" height="-1"/>
|
||||
</grid>
|
||||
</constraints>
|
||||
<properties/>
|
||||
</component>
|
||||
<grid id="12f06" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<grid row="2" column="1" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="line">
|
||||
<color color="-6709600"/>
|
||||
</border>
|
||||
<children>
|
||||
<component id="389a7" class="javax.swing.JTextArea" binding="myDescription">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false">
|
||||
<preferred-size width="150" height="50"/>
|
||||
</grid>
|
||||
</constraints>
|
||||
<properties/>
|
||||
</component>
|
||||
</children>
|
||||
</grid>
|
||||
</children>
|
||||
</grid>
|
||||
</form>
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
package org.jetbrains.plugins.coursecreator.ui;
|
||||
|
||||
import com.intellij.facet.ui.FacetValidatorsManager;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.ui.DocumentAdapter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
|
||||
public class CCNewProjectPanel {
|
||||
private JPanel myPanel;
|
||||
private JTextArea myDescription;
|
||||
private JTextField myName;
|
||||
private JTextField myAuthorField;
|
||||
private FacetValidatorsManager myValidationManager;
|
||||
|
||||
|
||||
public CCNewProjectPanel() {
|
||||
final String userName = System.getProperty("user.name");
|
||||
if (userName != null) {
|
||||
myAuthorField.setText(userName);
|
||||
}
|
||||
myName.getDocument().addDocumentListener(new MyValidator());
|
||||
myDescription.getDocument().addDocumentListener(new MyValidator());
|
||||
myAuthorField.getDocument().addDocumentListener(new MyValidator());
|
||||
}
|
||||
|
||||
public JPanel getMainPanel() {
|
||||
return myPanel;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getName() {
|
||||
return StringUtil.notNullize(myName.getText());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getDescription() {
|
||||
return StringUtil.notNullize(myDescription.getText());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getAuthor() {
|
||||
return StringUtil.notNullize(myAuthorField.getText());
|
||||
}
|
||||
|
||||
public void registerValidators(FacetValidatorsManager manager) {
|
||||
myValidationManager = manager;
|
||||
}
|
||||
|
||||
private class MyValidator extends DocumentAdapter {
|
||||
|
||||
@Override
|
||||
protected void textChanged(DocumentEvent e) {
|
||||
myValidationManager.validate();
|
||||
}
|
||||
}
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
package org.jetbrains.plugins.coursecreator.ui;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.coursecreator.actions.CreateCourseArchive;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
public class CreateCourseArchiveDialog extends DialogWrapper {
|
||||
|
||||
private CreateCourseArchivePanel myPanel;
|
||||
private CreateCourseArchive myAction;
|
||||
|
||||
public CreateCourseArchiveDialog(@NotNull final Project project, CreateCourseArchive action) {
|
||||
super(project);
|
||||
setTitle("Create Course Archive");
|
||||
myPanel = new CreateCourseArchivePanel(project, this);
|
||||
myAction = action;
|
||||
init();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected JComponent createCenterPanel() {
|
||||
return myPanel;
|
||||
}
|
||||
|
||||
public void enableOKAction(boolean isEnabled) {
|
||||
myOKAction.setEnabled(isEnabled);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doOKAction() {
|
||||
myAction.setZipName(myPanel.getZipName());
|
||||
myAction.setLocationDir(myPanel.getLocationPath());
|
||||
super.doOKAction();
|
||||
}
|
||||
}
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.jetbrains.plugins.coursecreator.ui.CreateCourseArchivePanel">
|
||||
<grid id="27dc6" binding="myPanel" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<xy x="20" y="20" width="500" height="400"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<grid id="a3b77" layout-manager="GridLayoutManager" row-count="4" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="786af" class="javax.swing.JLabel">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="Name:"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="160bb" class="javax.swing.JTextField" binding="myNameField" default-binding="true">
|
||||
<constraints>
|
||||
<grid row="0" column="1" row-span="2" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
|
||||
<preferred-size width="150" height="-1"/>
|
||||
</grid>
|
||||
</constraints>
|
||||
<properties/>
|
||||
</component>
|
||||
<component id="628ab" class="javax.swing.JLabel">
|
||||
<constraints>
|
||||
<grid row="1" column="0" row-span="2" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="Location:"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="aab8" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="myLocationField">
|
||||
<constraints>
|
||||
<grid row="2" column="1" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
</component>
|
||||
<grid id="29be7" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<grid row="3" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="4fa15" class="javax.swing.JLabel" binding="myErrorIcon">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value=""/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="4bdcf" class="javax.swing.JLabel" binding="myErrorLabel">
|
||||
<constraints>
|
||||
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value=""/>
|
||||
</properties>
|
||||
</component>
|
||||
</children>
|
||||
</grid>
|
||||
</children>
|
||||
</grid>
|
||||
</children>
|
||||
</grid>
|
||||
</form>
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
package org.jetbrains.plugins.coursecreator.ui;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
|
||||
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.File;
|
||||
|
||||
public class CreateCourseArchivePanel extends JPanel {
|
||||
private JPanel myPanel;
|
||||
private JTextField myNameField;
|
||||
private TextFieldWithBrowseButton myLocationField;
|
||||
private JLabel myErrorIcon;
|
||||
private JLabel myErrorLabel;
|
||||
private CreateCourseArchiveDialog myDlg;
|
||||
|
||||
public CreateCourseArchivePanel(@NotNull final Project project, CreateCourseArchiveDialog dlg) {
|
||||
setLayout(new BorderLayout());
|
||||
add(myPanel, BorderLayout.CENTER);
|
||||
myErrorIcon.setIcon(AllIcons.Actions.Lightning);
|
||||
setState(false);
|
||||
myDlg = dlg;
|
||||
myNameField.setText("course");
|
||||
myLocationField.setText(project.getBasePath());
|
||||
FileChooserDescriptor descriptor = FileChooserDescriptorFactory.createSingleFolderDescriptor();
|
||||
myLocationField.addBrowseFolderListener("Choose location folder", null, project, descriptor);
|
||||
myLocationField.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
String location = myLocationField.getText();
|
||||
File file = new File(location);
|
||||
if (!file.exists() || !file.isDirectory()) {
|
||||
myDlg.enableOKAction(false);
|
||||
setError("Invalid location");
|
||||
}
|
||||
myDlg.enableOKAction(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setState(boolean isVisible) {
|
||||
myErrorIcon.setVisible(isVisible);
|
||||
myErrorLabel.setVisible(isVisible);
|
||||
}
|
||||
|
||||
private void setError(String message) {
|
||||
myErrorLabel.setText(message);
|
||||
setState(true);
|
||||
}
|
||||
|
||||
public String getZipName() {
|
||||
return myNameField.getText();
|
||||
}
|
||||
|
||||
public String getLocationPath() {
|
||||
return myLocationField.getText();
|
||||
}
|
||||
}
|
||||
+153
@@ -0,0 +1,153 @@
|
||||
package org.jetbrains.plugins.coursecreator.ui;
|
||||
|
||||
import com.intellij.ide.projectView.ProjectView;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.ui.ValidationInfo;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.VirtualFileManager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.coursecreator.CCProjectService;
|
||||
import org.jetbrains.plugins.coursecreator.format.TaskWindow;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.io.*;
|
||||
|
||||
public class CreateTaskWindowDialog extends DialogWrapper {
|
||||
|
||||
public static final String TITLE = "New Task Window";
|
||||
private static final Logger LOG = Logger.getInstance(CreateTaskWindowDialog.class.getName());
|
||||
private final TaskWindow myTaskWindow;
|
||||
private final CreateTaskWindowPanel myPanel;
|
||||
private final Project myProject;
|
||||
|
||||
public Project getProject() {
|
||||
return myProject;
|
||||
}
|
||||
|
||||
public CreateTaskWindowDialog(@NotNull final Project project, @NotNull final TaskWindow taskWindow, int lessonIndex,
|
||||
int taskIndex, String taskFileName, int taskWindowIndex) {
|
||||
super(project, true);
|
||||
setTitle(TITLE);
|
||||
myTaskWindow = taskWindow;
|
||||
myPanel = new CreateTaskWindowPanel(this);
|
||||
String generatedHintName = "lesson" + lessonIndex + "task" + taskIndex + taskFileName + "_" + taskWindowIndex;
|
||||
myPanel.setGeneratedHintName(generatedHintName);
|
||||
if (taskWindow.getHintName() != null) {
|
||||
setHintText(project, taskWindow);
|
||||
}
|
||||
myProject = project;
|
||||
String taskWindowTaskText = taskWindow.getTaskText();
|
||||
myPanel.setTaskWindowText(taskWindowTaskText != null ? taskWindowTaskText : "");
|
||||
String hintName = taskWindow.getHintName();
|
||||
myPanel.setHintName(hintName != null ? hintName : "");
|
||||
init();
|
||||
initValidation();
|
||||
}
|
||||
|
||||
private void setHintText(Project project, TaskWindow taskWindow) {
|
||||
VirtualFile hints = project.getBaseDir().findChild("hints");
|
||||
if (hints != null) {
|
||||
File file = new File(hints.getPath(), taskWindow.getHintName());
|
||||
StringBuilder hintText = new StringBuilder();
|
||||
if (file.exists()) {
|
||||
try {
|
||||
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
|
||||
String line;
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
hintText.append(line).append("\n");
|
||||
}
|
||||
myPanel.doClick();
|
||||
//myPanel.enableHint(true);
|
||||
myPanel.setHintText(hintText.toString());
|
||||
}
|
||||
catch (FileNotFoundException e) {
|
||||
LOG.error("created hint was not found", e);
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doOKAction() {
|
||||
String taskWindowText = myPanel.getTaskWindowText();
|
||||
myTaskWindow.setTaskText(StringUtil.notNullize(taskWindowText));
|
||||
if (myPanel.createHint()) {
|
||||
String hintName = myPanel.getHintName();
|
||||
myTaskWindow.setHint(hintName);
|
||||
String hintText = myPanel.getHintText();
|
||||
createHint(hintName, hintText);
|
||||
}
|
||||
super.doOKAction();
|
||||
}
|
||||
|
||||
private void createHint(String hintName, String hintText) {
|
||||
VirtualFile hintsDir = myProject.getBaseDir().findChild("hints");
|
||||
if (hintsDir != null) {
|
||||
File hintFile = new File(hintsDir.getPath(), hintName);
|
||||
PrintWriter printWriter = null;
|
||||
try {
|
||||
printWriter = new PrintWriter(hintFile);
|
||||
printWriter.print(hintText);
|
||||
}
|
||||
catch (FileNotFoundException e) {
|
||||
//TODO:show error in UI
|
||||
return;
|
||||
}
|
||||
finally {
|
||||
if (printWriter != null) {
|
||||
printWriter.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
VirtualFileManager.getInstance().refreshWithoutFileWatcher(true);
|
||||
ProjectView.getInstance(myProject).refresh();
|
||||
}
|
||||
|
||||
public void deleteHint() {
|
||||
VirtualFile hintsDir = myProject.getBaseDir().findChild("hints");
|
||||
if (hintsDir != null) {
|
||||
String hintName = myTaskWindow.getHintName();
|
||||
if (hintName == null) {
|
||||
return;
|
||||
}
|
||||
File hintFile = new File(hintsDir.getPath(), hintName);
|
||||
if (hintFile.exists()) {
|
||||
CCProjectService.deleteProjectFile(hintFile, myProject);
|
||||
myTaskWindow.setHint(null);
|
||||
myPanel.resetHint();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected JComponent createCenterPanel() {
|
||||
return myPanel;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public ValidationInfo doValidate() {
|
||||
String name = myPanel.getHintName();
|
||||
VirtualFile hintsDir = myProject.getBaseDir().findChild("hints");
|
||||
if (hintsDir == null) {
|
||||
return null;
|
||||
}
|
||||
VirtualFile child = hintsDir.findChild(name);
|
||||
if (child == null) {
|
||||
return null;
|
||||
}
|
||||
return myTaskWindow.getHintName() != null ? null : new ValidationInfo("Hint file with such filename already exists");
|
||||
}
|
||||
|
||||
public void validateInput() {
|
||||
super.initValidation();
|
||||
}
|
||||
}
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.jetbrains.plugins.coursecreator.ui.CreateTaskWindowPanel">
|
||||
<grid id="27dc6" binding="myPanel" layout-manager="GridLayoutManager" row-count="4" 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>
|
||||
<xy x="20" y="20" width="500" height="400"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="aaa28" class="javax.swing.JLabel">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<labelFor value="b712"/>
|
||||
<text value="Text:"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="d2e2f" class="javax.swing.JLabel" binding="myHintNameLabel">
|
||||
<constraints>
|
||||
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<enabled value="true"/>
|
||||
<labelFor value="ddeb1"/>
|
||||
<text value="Hint name:"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="ddeb1" class="javax.swing.JTextField" binding="myHintName">
|
||||
<constraints>
|
||||
<grid row="2" column="1" row-span="1" col-span="3" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
|
||||
<preferred-size width="150" height="-1"/>
|
||||
</grid>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value=""/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="d322a" class="javax.swing.JLabel" binding="myHintTextLabel">
|
||||
<constraints>
|
||||
<grid row="3" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<labelFor value="d0efc"/>
|
||||
<text value="Hint text:"/>
|
||||
</properties>
|
||||
</component>
|
||||
<grid id="51a63" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<grid row="3" column="1" row-span="1" col-span="3" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="line">
|
||||
<color color="-6709600"/>
|
||||
</border>
|
||||
<children>
|
||||
<component id="d0efc" class="javax.swing.JTextArea" binding="myHintText">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false">
|
||||
<preferred-size width="300" height="100"/>
|
||||
</grid>
|
||||
</constraints>
|
||||
<properties/>
|
||||
</component>
|
||||
</children>
|
||||
</grid>
|
||||
<grid id="cbc70" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<grid row="0" column="1" row-span="1" col-span="3" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false">
|
||||
<minimum-size width="150" height="-1"/>
|
||||
<preferred-size width="150" height="-1"/>
|
||||
</grid>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="line">
|
||||
<color color="-6709600"/>
|
||||
</border>
|
||||
<children>
|
||||
<component id="b712" class="javax.swing.JTextArea" binding="myTaskWindowText">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false">
|
||||
<preferred-size width="300" height="100"/>
|
||||
</grid>
|
||||
</constraints>
|
||||
<properties/>
|
||||
</component>
|
||||
</children>
|
||||
</grid>
|
||||
<component id="f86b4" class="javax.swing.JCheckBox" binding="myCreateHintCheckBox" default-binding="true">
|
||||
<constraints>
|
||||
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="Create hint"/>
|
||||
</properties>
|
||||
</component>
|
||||
</children>
|
||||
</grid>
|
||||
</form>
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
package org.jetbrains.plugins.coursecreator.ui;
|
||||
|
||||
import com.intellij.ui.DocumentAdapter;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ItemEvent;
|
||||
import java.awt.event.ItemListener;
|
||||
|
||||
public class CreateTaskWindowPanel extends JPanel {
|
||||
|
||||
private final CreateTaskWindowDialog myDialog;
|
||||
private JPanel myPanel;
|
||||
private JTextArea myTaskWindowText;
|
||||
private JTextField myHintName;
|
||||
private JTextArea myHintText;
|
||||
private JCheckBox myCreateHintCheckBox;
|
||||
private JLabel myHintNameLabel;
|
||||
private JLabel myHintTextLabel;
|
||||
private String myGeneratedHintName = "";
|
||||
|
||||
public CreateTaskWindowPanel(CreateTaskWindowDialog dialog) {
|
||||
super(new BorderLayout());
|
||||
add(myPanel, BorderLayout.CENTER);
|
||||
myDialog = dialog;
|
||||
enableHint(false);
|
||||
myCreateHintCheckBox.addItemListener(new ItemListener() {
|
||||
@Override
|
||||
public void itemStateChanged(ItemEvent e) {
|
||||
int state = e.getStateChange();
|
||||
// 1 for checked
|
||||
enableHint(state == 1);
|
||||
if (state == 2) {
|
||||
myDialog.deleteHint();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
myHintName.getDocument().addDocumentListener(new DocumentAdapter() {
|
||||
@Override
|
||||
protected void textChanged(DocumentEvent e) {
|
||||
myDialog.validateInput();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void enableHint(boolean isEnable) {
|
||||
myHintName.setEnabled(isEnable);
|
||||
myHintText.setEnabled(isEnable);
|
||||
myHintNameLabel.setEnabled(isEnable);
|
||||
myHintTextLabel.setEnabled(isEnable);
|
||||
myHintName.setText(myGeneratedHintName);
|
||||
}
|
||||
|
||||
public void setTaskWindowText(String taskWindowText) {
|
||||
myTaskWindowText.setText(taskWindowText);
|
||||
}
|
||||
|
||||
public void setHintName(String hintName) {
|
||||
myHintName.setText(hintName);
|
||||
}
|
||||
|
||||
public void setHintText(String hintText) {
|
||||
myHintText.setText(hintText);
|
||||
}
|
||||
|
||||
public String getTaskWindowText() {
|
||||
return myTaskWindowText.getText();
|
||||
}
|
||||
|
||||
public String getHintName() {
|
||||
return myHintName.getText();
|
||||
}
|
||||
|
||||
public String getHintText() {
|
||||
return myHintText.getText();
|
||||
}
|
||||
|
||||
public boolean createHint() {
|
||||
return myHintName.isEnabled();
|
||||
}
|
||||
|
||||
public void doClick() {
|
||||
myCreateHintCheckBox.doClick();
|
||||
}
|
||||
|
||||
public void resetHint() {
|
||||
myHintName.setText("");
|
||||
myHintText.setText("");
|
||||
}
|
||||
|
||||
public void setGeneratedHintName(String generatedHintName) {
|
||||
myGeneratedHintName = generatedHintName;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.intellij.openapi.application;
|
||||
|
||||
import com.intellij.util.ThreeState;
|
||||
|
||||
// see com.intellij.openapi.application.ConfigImportHelper.getConfigImportSettings
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public class PyCharmEduConfigImportSettings extends ConfigImportSettings {
|
||||
|
||||
@Override
|
||||
protected String getProductName(ThreeState full) {
|
||||
return "WebStorm";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCustomPathsSelector() {
|
||||
return "WebIDE10";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getExecutableName() {
|
||||
return "webstorm";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getMainJarNames() {
|
||||
return new String[] { "webide", "webstorm"};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user