added opportunity to create task files of all supported file types
authorLiana Bakradze <liana.bakradze@jetbrains.com>
Tue, 10 Feb 2015 15:14:41 +0000 (18:14 +0300)
committerLiana Bakradze <liana.bakradze@jetbrains.com>
Tue, 10 Feb 2015 15:14:41 +0000 (18:14 +0300)
13 files changed:
python/edu/course-creator-python/resources/META-INF/plugin.xml
python/edu/course-creator-python/resources/fileTemplates/internal/task.answer.py.ft [moved from python/edu/course-creator-python/resources/fileTemplates/internal/task.answer.ft with 100% similarity]
python/edu/course-creator-python/src/com/jetbrains/edu/coursecreator/PyCCAnswerFileTypeFactory.java [deleted file]
python/edu/course-creator-python/src/com/jetbrains/edu/coursecreator/PyCCProjectGenerator.java
python/edu/course-creator-python/src/com/jetbrains/edu/coursecreator/PyStudyLanguageManager.java [new file with mode: 0644]
python/educational/course-creator/resources/META-INF/plugin.xml
python/educational/course-creator/src/com/jetbrains/edu/coursecreator/StudyLanguageManager.java [new file with mode: 0644]
python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCCreateCourseArchive.java
python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCCreateTask.java
python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCCreateTaskFile.java
python/educational/course-creator/src/com/jetbrains/edu/coursecreator/format/Course.java
python/educational/course-creator/src/com/jetbrains/edu/coursecreator/ui/CreateTaskFileDialog.java [new file with mode: 0644]
python/educational/course-creator/src/com/jetbrains/edu/coursecreator/ui/CreateTaskFilePanel.form [new file with mode: 0644]

index b9148d8f1de220d7e59be593cd8fd9e309a73ca9..1b015984d136f2d0f73b6d57fee02c61cd0b3558 100644 (file)
 
   <extensions defaultExtensionNs="com.intellij">
     <directoryProjectGenerator implementation="com.jetbrains.edu.coursecreator.PyCCProjectGenerator"/>
-    <fileTypeFactory implementation="com.jetbrains.edu.coursecreator.PyCCAnswerFileTypeFactory" />
     <errorHandler implementation="com.intellij.diagnostic.ITNReporter"/>
   </extensions>
 
+  <extensions defaultExtensionNs="Edu">
+    <StudyLanguageManager implementationClass="com.jetbrains.edu.coursecreator.PyStudyLanguageManager" language="Python"/>
+  </extensions>
+
   <application-components>
     <!-- Add your application components here -->
   </application-components>
diff --git a/python/edu/course-creator-python/src/com/jetbrains/edu/coursecreator/PyCCAnswerFileTypeFactory.java b/python/edu/course-creator-python/src/com/jetbrains/edu/coursecreator/PyCCAnswerFileTypeFactory.java
deleted file mode 100644 (file)
index 4585963..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2000-2014 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.jetbrains.edu.coursecreator;
-
-
-import com.intellij.openapi.fileTypes.FileTypeConsumer;
-import com.intellij.openapi.fileTypes.FileTypeFactory;
-import com.jetbrains.python.PythonFileType;
-import org.jetbrains.annotations.NotNull;
-
-public class PyCCAnswerFileTypeFactory extends FileTypeFactory {
-  @Override
-  public void createFileTypes(@NotNull FileTypeConsumer fileTypeConsumer) {
-    fileTypeConsumer.consume(PythonFileType.INSTANCE, "answer");
-  }
-}
index 82477feb263632e367e9a7ab8bcaac5d34ac7539..d5f73de1e69e226f63b86695d3c254863d64c984 100644 (file)
@@ -64,6 +64,7 @@ public class PyCCProjectGenerator extends PythonProjectGenerator implements Dire
 
     final CCProjectService service = CCProjectService.getInstance(project);
     final Course course = new Course(name, author, description);
+    course.setLanguage("Python");
     service.setCourse(course);
 
     final PsiDirectory projectDir = PsiManager.getInstance(project).findDirectory(baseDir);
diff --git a/python/edu/course-creator-python/src/com/jetbrains/edu/coursecreator/PyStudyLanguageManager.java b/python/edu/course-creator-python/src/com/jetbrains/edu/coursecreator/PyStudyLanguageManager.java
new file mode 100644 (file)
index 0000000..1b711f8
--- /dev/null
@@ -0,0 +1,34 @@
+package com.jetbrains.edu.coursecreator;
+
+import com.intellij.ide.fileTemplates.FileTemplate;
+import com.intellij.ide.fileTemplates.FileTemplateManager;
+import com.intellij.openapi.project.Project;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public class PyStudyLanguageManager implements StudyLanguageManager {
+  @Nullable
+  @Override
+  public String getDefaultTaskFileExtension() {
+    return "py";
+  }
+
+  @Nullable
+  @Override
+  public FileTemplate getTaskFileTemplateForExtension(@NotNull final Project project, String extension) {
+    if (!extension.equals("py")) {
+      return null;
+    }
+    return getInternalTemplateByName(project, "task.answer.py");
+  }
+
+  @Nullable
+  @Override
+  public FileTemplate getTestsTemplate(@NotNull final Project project) {
+    return getInternalTemplateByName(project, "tests.py");
+  }
+
+  private static FileTemplate getInternalTemplateByName(@NotNull final Project project, String name) {
+    return FileTemplateManager.getInstance(project).getInternalTemplate(name);
+  }
+}
index 6fb2817bff05c4a7b90baf734a23f65f16de9e30..f15d2598fae954155bd4471d97b526b8e29e8c40 100644 (file)
     </component>
   </project-components>
 
+  <extensionPoints>
+    <extensionPoint qualifiedName="Edu.StudyLanguageManager" beanClass="com.intellij.lang.LanguageExtensionPoint">
+    </extensionPoint>
+  </extensionPoints>
+
   <actions>
     <action id="CreateLesson" class="com.jetbrains.edu.coursecreator.actions.CCCreateLesson">
       <add-to-group group-id="NewGroup" anchor="before" relative-to-action="NewFile"/>
diff --git a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/StudyLanguageManager.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/StudyLanguageManager.java
new file mode 100644 (file)
index 0000000..bdef802
--- /dev/null
@@ -0,0 +1,20 @@
+package com.jetbrains.edu.coursecreator;
+
+import com.intellij.ide.fileTemplates.FileTemplate;
+import com.intellij.lang.LanguageExtension;
+import com.intellij.openapi.project.Project;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public interface StudyLanguageManager {
+  LanguageExtension<StudyLanguageManager> INSTANCE = new LanguageExtension<StudyLanguageManager>("Edu.StudyLanguageManager");
+
+  @Nullable
+  String getDefaultTaskFileExtension();
+
+  @Nullable
+  FileTemplate getTaskFileTemplateForExtension(@NotNull final Project project, String extension);
+
+  @Nullable
+  FileTemplate getTestsTemplate(@NotNull final Project project);
+}
index 3741d52096fc6292a702ac7215c1726392df8275..f34aacba345f9b98306796aba948e8af9e73ae32 100644 (file)
@@ -15,6 +15,7 @@ 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.util.io.FileUtil;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.openapi.vfs.VirtualFileManager;
 import com.intellij.util.io.ZipUtil;
@@ -120,7 +121,7 @@ public class CCCreateCourseArchive extends DumbAwareAction {
 
     file = userFileDir.findChild(name);
     assert file != null;
-    String answerFileName = file.getNameWithoutExtension() + ".answer";
+    String answerFileName = file.getNameWithoutExtension() + ".answer." + file.getExtension();
     VirtualFile answerFile = answerFileDir.findChild(answerFileName);
     if (answerFile == null) {
       return;
@@ -143,7 +144,7 @@ public class CCCreateCourseArchive extends DumbAwareAction {
         ApplicationManager.getApplication().runWriteAction(new Runnable() {
           @Override
           public void run() {
-            document.replaceString(0, document.getTextLength(), answerDocument.getText());
+            document.replaceString(0, document.getTextLength(), answerDocument.getCharsSequence());
           }
         });
       }
@@ -156,6 +157,17 @@ public class CCCreateCourseArchive extends DumbAwareAction {
       final AnswerPlaceholder answerPlaceholder = taskFile.getTaskWindows().get(i);
       replaceTaskWindow(project, document, answerPlaceholder);
     }
+    CommandProcessor.getInstance().executeCommand(project, new Runnable() {
+      @Override
+      public void run() {
+        ApplicationManager.getApplication().runWriteAction(new Runnable() {
+          @Override
+          public void run() {
+            FileDocumentManager.getInstance().saveDocument(document);
+          }
+        });
+      }
+    }, "x", "qwe");
     document.removeDocumentListener(listener);
   }
 
@@ -204,7 +216,8 @@ public class CCCreateCourseArchive extends DumbAwareAction {
           @Override
           public boolean accept(File pathname) {
             String name = pathname.getName();
-            return !name.contains(".answer") && !name.contains("__pycache__") && !name.contains("_windows") && !name.contains(".pyc");
+            String nameWithoutExtension = FileUtil.getNameWithoutExtension(pathname);
+            return !nameWithoutExtension.endsWith(".answer") && !name.contains("__pycache__") && !name.contains("_windows") && !name.contains(".pyc");
           }
         }, null);
       }
index cd2c0791f8811f1dc16c4ffc4ff7a24f3d90cfcf..fefa795f4ff6cb7c7c09d9fb3617ad4b8a6df6e9 100644 (file)
@@ -7,11 +7,13 @@ 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.lang.Language;
 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.diagnostic.Logger;
 import com.intellij.openapi.fileEditor.FileEditorManager;
 import com.intellij.openapi.project.DumbAwareAction;
 import com.intellij.openapi.project.Project;
@@ -22,12 +24,16 @@ import com.intellij.psi.PsiElement;
 import com.intellij.util.PlatformIcons;
 import com.jetbrains.edu.coursecreator.CCProjectService;
 import com.jetbrains.edu.coursecreator.CCUtils;
+import com.jetbrains.edu.coursecreator.StudyLanguageManager;
 import com.jetbrains.edu.coursecreator.format.Course;
 import com.jetbrains.edu.coursecreator.format.Lesson;
 import com.jetbrains.edu.coursecreator.format.Task;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 public class CCCreateTask extends DumbAwareAction {
+  private static final Logger LOG = Logger.getInstance(CCCreateTask.class.getName());
+
   public CCCreateTask() {
     super("Task", "Create new Task", PlatformIcons.DIRECTORY_CLOSED_ICON);
   }
@@ -67,42 +73,64 @@ public class CCCreateTask extends DumbAwareAction {
       public void run() {
         final PsiDirectory taskDirectory = DirectoryUtil.createSubdirectories("task" + (size + 1), lessonDir, "\\/");
         if (taskDirectory != null) {
+          Language language = Language.findLanguageByID(course.getLanguage());
+          if (language == null) {
+            return;
+          }
+          final StudyLanguageManager studyLanguageManager = StudyLanguageManager.INSTANCE.forLanguage(language);
           CCUtils.markDirAsSourceRoot(taskDirectory.getVirtualFile(), project);
-          final FileTemplate template = FileTemplateManager.getInstance(project).getInternalTemplate("task.html");
-          final FileTemplate testsTemplate = FileTemplateManager.getInstance(project).getInternalTemplate("tests");
-          final FileTemplate taskTemplate = FileTemplateManager.getInstance(project).getInternalTemplate("task.answer");
-          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", null, taskDirectory);
 
-            final Task task = new Task(taskName);
-            task.addTaskFile("file1.py", size + 1);
-            task.setIndex(size + 1);
-            lesson.addTask(task, taskDirectory);
-            ApplicationManager.getApplication().invokeLater(new Runnable() {
-              @Override
-              public void run() {
-                FileEditorManager fileEditorManager = FileEditorManager.getInstance(project);
-                for (VirtualFile virtualFile : fileEditorManager.getOpenFiles()) {
-                  fileEditorManager.closeFile(virtualFile);
-                }
-                if (view != null) {
-                  EditorHelper.openInEditor(testsFile, false);
-                  EditorHelper.openInEditor(taskPyFile, false);
-                  view.selectElement(taskFile);
-                  EditorHelper.openInEditor(taskFile, false);
-                }
-              }
-            });
+          createFromTemplateAndOpen(taskDirectory, studyLanguageManager.getTestsTemplate(project), view);
+          createFromTemplateAndOpen(taskDirectory, FileTemplateManager.getInstance(project).getInternalTemplate("task.html"), view);
+          String defaultExtension = studyLanguageManager.getDefaultTaskFileExtension();
+          String taskFileName = null;
+          if (defaultExtension != null) {
+            FileTemplate taskFileTemplate = studyLanguageManager.getTaskFileTemplateForExtension(project,
+                                                                                          defaultExtension);
+            createFromTemplateAndOpen(taskDirectory, taskFileTemplate, view);
+            if (taskFileTemplate != null) {
+              taskFileName = taskFileTemplate.getName();
+            }
           }
-          catch (Exception ignored) {
+
+          final Task task = new Task(taskName);
+          task.setIndex(size + 1);
+          lesson.addTask(task, taskDirectory);
+          if (taskFileName != null) {
+            task.addTaskFile(taskFileName, size + 1);
           }
+          ApplicationManager.getApplication().invokeLater(new Runnable() {
+            @Override
+            public void run() {
+              FileEditorManager fileEditorManager = FileEditorManager.getInstance(project);
+              for (VirtualFile virtualFile : fileEditorManager.getOpenFiles()) {
+                fileEditorManager.closeFile(virtualFile);
+              }
+            }
+          });
         }
       }
     });
   }
 
+  private static void createFromTemplateAndOpen(@NotNull final PsiDirectory taskDirectory,
+                                                @Nullable final FileTemplate template,
+                                                @Nullable IdeView view) {
+    if (template == null) {
+      return;
+    }
+    try {
+      final PsiElement file = FileTemplateUtil.createFromTemplate(template, template.getName(), null, taskDirectory);
+      if (view != null) {
+        EditorHelper.openInEditor(file, false);
+        view.selectElement(file);
+      }
+    }
+    catch (Exception e) {
+      LOG.error(e);
+    }
+  }
+
   @Override
   public void update(@NotNull AnActionEvent event) {
     if (!CCProjectService.setCCActionAvailable(event)) {
index 6296ee839af43896a4b3fe8e2260d985f1ff93db..73b50d39b3bea8b841e24722d47b7089fcb24d58 100644 (file)
@@ -3,26 +3,33 @@ package com.jetbrains.edu.coursecreator.actions;
 import com.intellij.icons.AllIcons;
 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.projectView.ProjectView;
 import com.intellij.ide.util.DirectoryChooserUtil;
 import com.intellij.ide.util.EditorHelper;
+import com.intellij.lang.Language;
 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.fileEditor.FileEditorManager;
+import com.intellij.openapi.fileTypes.FileType;
 import com.intellij.openapi.project.DumbAwareAction;
 import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.Messages;
+import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.psi.PsiDirectory;
 import com.intellij.psi.PsiElement;
 import com.jetbrains.edu.coursecreator.CCProjectService;
+import com.jetbrains.edu.coursecreator.StudyLanguageManager;
 import com.jetbrains.edu.coursecreator.format.Course;
 import com.jetbrains.edu.coursecreator.format.Lesson;
 import com.jetbrains.edu.coursecreator.format.Task;
+import com.jetbrains.edu.coursecreator.ui.CreateTaskFileDialog;
 import org.jetbrains.annotations.NotNull;
 
+import static com.intellij.openapi.ui.DialogWrapper.OK_EXIT_CODE;
+
 public class CCCreateTaskFile extends DumbAwareAction {
 
   public CCCreateTaskFile() {
@@ -30,7 +37,7 @@ public class CCCreateTaskFile extends DumbAwareAction {
   }
 
   @Override
-  public void actionPerformed(AnActionEvent e) {
+  public void actionPerformed(final AnActionEvent e) {
     final IdeView view = e.getData(LangDataKeys.IDE_VIEW);
     final Project project = e.getData(CommonDataKeys.PROJECT);
 
@@ -50,26 +57,48 @@ public class CCCreateTaskFile extends DumbAwareAction {
 
     final int index = task.getTaskFiles().size() + 1;
     String generatedName = "file" + index;
-    final String taskFileName = Messages.showInputDialog("Name:", "Task File Name", null, generatedName, null);
+    CreateTaskFileDialog dialog = new CreateTaskFileDialog(project, generatedName);
+    dialog.show();
+    if (dialog.getExitCode() != OK_EXIT_CODE) {
+      return;
+    }
+    final String taskFileName = dialog.getFileName();
     if (taskFileName == null) return;
-
+    FileType type = dialog.getFileType();
+    if (type == null) {
+      return;
+    }
+    Language language = Language.findLanguageByID(course.getLanguage());
+    if (language == null) {
+      return;
+    }
+    final StudyLanguageManager studyLanguageManager = StudyLanguageManager.INSTANCE.forLanguage(language);
+    final String extension = type.getDefaultExtension();
     ApplicationManager.getApplication().runWriteAction(new Runnable() {
       @Override
       public void run() {
-          final FileTemplate taskTemplate = FileTemplateManager.getInstance(project).getInternalTemplate("task.answer");
-          try {
-            final PsiElement taskPyFile = FileTemplateUtil.createFromTemplate(taskTemplate, taskFileName, null, taskDir);
-            task.addTaskFile(taskFileName + ".py", index);
+        final FileTemplate taskTemplate = studyLanguageManager.getTaskFileTemplateForExtension(project, extension);
+        final String answerFileName = taskFileName + ".answer." + extension;
+        try {
+          if (taskTemplate == null) {
+            VirtualFile file = taskDir.getVirtualFile().createChildData(this, answerFileName);
+            ProjectView.getInstance(project).select(file, file, false);
+            FileEditorManager.getInstance(project).openFile(file, true);
+          }
+          else {
+            final PsiElement taskFile = FileTemplateUtil.createFromTemplate(taskTemplate, answerFileName, null, taskDir);
             ApplicationManager.getApplication().invokeLater(new Runnable() {
               @Override
               public void run() {
-                EditorHelper.openInEditor(taskPyFile, false);
-                view.selectElement(taskPyFile);
+                EditorHelper.openInEditor(taskFile, false);
+                view.selectElement(taskFile);
               }
             });
           }
-          catch (Exception ignored) {
-          }
+          task.addTaskFile(taskFileName + "." + extension, index);
+        }
+        catch (Exception ignored) {
+        }
       }
     });
   }
index d01f879f98f73cd33b39eccb0c4a8bd65faf2bc4..211aa517c54d7d7ad6e94c2a91be910a2f087246 100644 (file)
@@ -13,6 +13,8 @@ public class Course {
   @Expose private String name;
   @Expose private String author;
 
+  @Expose private String language;
+
   private Map<String, Lesson> myLessonsMap = new HashMap<String, Lesson>();
 
   public Map<String, Lesson> getLessonsMap() {
@@ -81,4 +83,12 @@ public class Course {
   public void setLessonsMap(Map<String, Lesson> lessonsMap) {
     myLessonsMap = lessonsMap;
   }
+
+  public String getLanguage() {
+    return language;
+  }
+
+  public void setLanguage(String language) {
+    this.language = language;
+  }
 }
diff --git a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/ui/CreateTaskFileDialog.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/ui/CreateTaskFileDialog.java
new file mode 100644 (file)
index 0000000..40abda1
--- /dev/null
@@ -0,0 +1,80 @@
+package com.jetbrains.edu.coursecreator.ui;
+
+import com.intellij.openapi.fileTypes.FileType;
+import com.intellij.openapi.fileTypes.FileTypeManager;
+import com.intellij.openapi.fileTypes.impl.FileTypeRenderer;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.DialogWrapper;
+import com.intellij.ui.DoubleClickListener;
+import com.intellij.ui.ListScrollingUtil;
+import com.intellij.ui.components.JBList;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+import java.awt.event.MouseEvent;
+
+public class CreateTaskFileDialog extends DialogWrapper {
+  private JPanel myPanel;
+  private JBList myList;
+  private JTextField myTextField;
+
+  @SuppressWarnings("unchecked")
+  public CreateTaskFileDialog(@Nullable Project project, String generatedFileName) {
+    super(project);
+    FileType[] fileTypes = FileTypeManager.getInstance().getRegisteredFileTypes();
+
+    DefaultListModel model = new DefaultListModel();
+    for (FileType type : fileTypes) {
+      if (!type.isReadOnly() && !type.getDefaultExtension().isEmpty()) {
+        model.addElement(type);
+      }
+    }
+    myList.setModel(model);
+    myTextField.setText(generatedFileName);
+    setTitle("Create New Task File");
+    init();
+  }
+
+  @Nullable
+  @Override
+  protected JComponent createCenterPanel() {
+    myList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+    myList.setCellRenderer(new FileTypeRenderer());
+
+    new DoubleClickListener() {
+      @Override
+      protected boolean onDoubleClick(MouseEvent e) {
+        doOKAction();
+        return true;
+      }
+    }.installOn(myList);
+
+    myList.getSelectionModel().addListSelectionListener(
+      new ListSelectionListener() {
+        @Override
+        public void valueChanged(ListSelectionEvent e) {
+          //TODO: do smth to check validness
+        }
+      }
+    );
+
+    ListScrollingUtil.selectItem(myList, FileTypeManager.getInstance().getFileTypeByExtension("py"));
+    return myPanel;
+  }
+
+  @Nullable
+  @Override
+  public JComponent getPreferredFocusedComponent() {
+    return myTextField;
+  }
+
+  public String getFileName() {
+    return myTextField.getText();
+  }
+
+  public FileType getFileType() {
+    return (FileType)myList.getSelectedValue();
+  }
+}
diff --git a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/ui/CreateTaskFilePanel.form b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/ui/CreateTaskFilePanel.form
new file mode 100644 (file)
index 0000000..84061a2
--- /dev/null
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.jetbrains.edu.coursecreator.ui.CreateTaskFileDialog">
+  <grid id="27dc6" binding="myPanel" layout-manager="GridLayoutManager" row-count="3" 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>
+      <component id="e3f" class="com.intellij.ui.components.JBLabel">
+        <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="File Name:"/>
+        </properties>
+      </component>
+      <component id="1f196" class="javax.swing.JTextField" binding="myTextField" default-binding="true">
+        <constraints>
+          <grid row="0" column="1" row-span="1" 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>
+      <scrollpane id="2c770" class="com.intellij.ui.components.JBScrollPane">
+        <constraints>
+          <grid row="2" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
+        </constraints>
+        <properties/>
+        <border type="none"/>
+        <children>
+          <component id="f5bb6" class="com.intellij.ui.components.JBList" binding="myList">
+            <constraints/>
+            <properties>
+              <layoutOrientation value="0"/>
+            </properties>
+          </component>
+        </children>
+      </scrollpane>
+      <grid id="22a58" 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="1" 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="ff15e" class="com.intellij.ui.components.JBLabel">
+            <constraints>
+              <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+            </constraints>
+            <properties>
+              <text value="Select File Type:"/>
+            </properties>
+          </component>
+        </children>
+      </grid>
+    </children>
+  </grid>
+</form>