mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
+1
-1
@@ -30,7 +30,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
public class DefaultLightProjectDescriptor implements LightProjectDescriptor {
|
||||
public class DefaultLightProjectDescriptor extends LightProjectDescriptor {
|
||||
@NotNull
|
||||
@Override
|
||||
public ModuleType getModuleType() {
|
||||
|
||||
@@ -53,7 +53,6 @@ import com.intellij.openapi.fileTypes.FileTypeManager;
|
||||
import com.intellij.openapi.fileTypes.impl.FileTypeManagerImpl;
|
||||
import com.intellij.openapi.module.EmptyModuleType;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleManager;
|
||||
import com.intellij.openapi.module.ModuleType;
|
||||
import com.intellij.openapi.project.ModuleAdapter;
|
||||
import com.intellij.openapi.project.Project;
|
||||
@@ -61,18 +60,19 @@ import com.intellij.openapi.project.ProjectManager;
|
||||
import com.intellij.openapi.project.ex.ProjectManagerEx;
|
||||
import com.intellij.openapi.project.impl.ProjectManagerImpl;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.roots.*;
|
||||
import com.intellij.openapi.roots.ModuleRootManager;
|
||||
import com.intellij.openapi.roots.OrderRootType;
|
||||
import com.intellij.openapi.startup.StartupManager;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.EmptyRunnable;
|
||||
import com.intellij.openapi.util.ShutDownTracker;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.*;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VfsUtilCore;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.encoding.EncodingManager;
|
||||
import com.intellij.openapi.vfs.encoding.EncodingManagerImpl;
|
||||
import com.intellij.openapi.vfs.ex.temp.TempFileSystem;
|
||||
import com.intellij.openapi.vfs.impl.VirtualFilePointerManagerImpl;
|
||||
import com.intellij.openapi.vfs.newvfs.persistent.PersistentFS;
|
||||
import com.intellij.openapi.vfs.newvfs.persistent.PersistentFSImpl;
|
||||
@@ -92,19 +92,17 @@ import com.intellij.psi.impl.PsiManagerImpl;
|
||||
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageManagerImpl;
|
||||
import com.intellij.psi.templateLanguages.TemplateDataLanguageMappings;
|
||||
import com.intellij.testFramework.fixtures.impl.CodeInsightTestFixtureImpl;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.GCUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.LocalTimeCounter;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.indexing.FileBasedIndex;
|
||||
import com.intellij.util.indexing.IndexableFileSet;
|
||||
import com.intellij.util.messages.MessageBusConnection;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import gnu.trove.THashMap;
|
||||
import junit.framework.TestCase;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.TestOnly;
|
||||
|
||||
import javax.swing.*;
|
||||
@@ -119,8 +117,6 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import static com.intellij.openapi.roots.ModuleRootModificationUtil.updateModel;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
@@ -228,11 +224,6 @@ public abstract class LightPlatformTestCase extends UsefulTestCase implements Da
|
||||
((PersistentFSImpl)PersistentFS.getInstance()).cleanPersistedContents();
|
||||
}
|
||||
|
||||
public static boolean isLight(@NotNull Project project) {
|
||||
String creationPlace = project.getUserData(CREATION_PLACE);
|
||||
return creationPlace != null && StringUtil.startsWith(creationPlace, LIGHT_PROJECT_MARK);
|
||||
}
|
||||
|
||||
private static void initProject(@NotNull final LightProjectDescriptor descriptor) throws Exception {
|
||||
ourProjectDescriptor = descriptor;
|
||||
|
||||
@@ -261,78 +252,10 @@ public abstract class LightPlatformTestCase extends UsefulTestCase implements Da
|
||||
registerShutdownHook();
|
||||
}
|
||||
ourPsiManager = null;
|
||||
ourModule = createMainModule(descriptor.getModuleType());
|
||||
|
||||
if (descriptor instanceof LightProjectDescriptorEx) {
|
||||
((LightProjectDescriptorEx)descriptor).setupModule(ourModule);
|
||||
|
||||
if(!((LightProjectDescriptorEx)descriptor).shouldConfigureModule()) return;
|
||||
}
|
||||
|
||||
VirtualFile dummyRoot = VirtualFileManager.getInstance().findFileByUrl("temp:///");
|
||||
assert dummyRoot != null;
|
||||
dummyRoot.refresh(false, false);
|
||||
|
||||
try {
|
||||
ourSourceRoot = dummyRoot.createChildDirectory(this, "src");
|
||||
cleanSourceRoot();
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
final IndexableFileSet indexableFileSet = new IndexableFileSet() {
|
||||
@Override
|
||||
public boolean isInSet(@NotNull final VirtualFile file) {
|
||||
return ourSourceRoot != null &&
|
||||
file.getFileSystem() == ourSourceRoot.getFileSystem() &&
|
||||
ourProject != null &&
|
||||
ourProject.isOpen();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void iterateIndexableFilesIn(@NotNull final VirtualFile file, @NotNull final ContentIterator iterator) {
|
||||
VfsUtilCore.visitChildrenRecursively(file, new VirtualFileVisitor() {
|
||||
@Override
|
||||
public boolean visitFile(@NotNull VirtualFile file) {
|
||||
iterator.processFile(file);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
FileBasedIndex.getInstance().registerIndexableSet(indexableFileSet, null);
|
||||
Disposer.register(ourProject, new Disposable() {
|
||||
@Override
|
||||
public void dispose() {
|
||||
FileBasedIndex.getInstance().removeIndexableSet(indexableFileSet);
|
||||
}
|
||||
});
|
||||
|
||||
updateModel(ourModule, new Consumer<ModifiableRootModel>() {
|
||||
@Override
|
||||
public void consume(ModifiableRootModel model) {
|
||||
final Sdk sdk = descriptor.getSdk();
|
||||
if (sdk != null) {
|
||||
model.setSdk(sdk);
|
||||
}
|
||||
|
||||
ContentEntry contentEntry = model.addContentEntry(ourSourceRoot);
|
||||
contentEntry.addSourceFolder(ourSourceRoot, false);
|
||||
|
||||
descriptor.configureModule(ourModule, model, contentEntry);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void cleanSourceRoot() throws IOException {
|
||||
TempFileSystem tempFs = (TempFileSystem)ourSourceRoot.getFileSystem();
|
||||
for (VirtualFile child : ourSourceRoot.getChildren()) {
|
||||
if (!tempFs.exists(child)) {
|
||||
tempFs.createChildFile(this, ourSourceRoot, child.getName());
|
||||
}
|
||||
child.delete(this);
|
||||
}
|
||||
LightProjectDescriptor.ProjectInfo projectInfo = ourProjectDescriptor.setUpProject(ourProject);
|
||||
ourModule = projectInfo.module;
|
||||
ourSourceRoot = projectInfo.moduleSourcesRoot;
|
||||
}
|
||||
}.execute().throwException();
|
||||
|
||||
@@ -340,15 +263,6 @@ public abstract class LightPlatformTestCase extends UsefulTestCase implements Da
|
||||
((VirtualFilePointerManagerImpl)VirtualFilePointerManager.getInstance()).storePointers();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected static Module createMainModule(@NotNull final ModuleType moduleType) {
|
||||
return ApplicationManager.getApplication().runWriteAction(new Computable<Module>() {
|
||||
@Override
|
||||
public Module compute() {
|
||||
return ModuleManager.getInstance(ourProject).newModule("light_idea_test_case.iml", moduleType.getId());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The only source root
|
||||
@@ -838,11 +752,11 @@ public abstract class LightPlatformTestCase extends UsefulTestCase implements Da
|
||||
});
|
||||
}
|
||||
|
||||
private static class SimpleLightProjectDescriptor implements LightProjectDescriptor {
|
||||
private static class SimpleLightProjectDescriptor extends LightProjectDescriptor {
|
||||
@NotNull private final ModuleType myModuleType;
|
||||
private final Sdk mySdk;
|
||||
@Nullable private final Sdk mySdk;
|
||||
|
||||
SimpleLightProjectDescriptor(@NotNull ModuleType moduleType, Sdk sdk) {
|
||||
SimpleLightProjectDescriptor(@NotNull ModuleType moduleType, @Nullable Sdk sdk) {
|
||||
myModuleType = moduleType;
|
||||
mySdk = sdk;
|
||||
}
|
||||
@@ -853,15 +767,12 @@ public abstract class LightPlatformTestCase extends UsefulTestCase implements Da
|
||||
return myModuleType;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Sdk getSdk() {
|
||||
return mySdk;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configureModule(@NotNull Module module, @NotNull ModifiableRootModel model, @NotNull ContentEntry contentEntry) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
|
||||
+124
-19
@@ -15,39 +15,144 @@
|
||||
*/
|
||||
package com.intellij.testFramework;
|
||||
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.module.EmptyModuleType;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleManager;
|
||||
import com.intellij.openapi.module.ModuleType;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.roots.ContentEntry;
|
||||
import com.intellij.openapi.roots.ContentIterator;
|
||||
import com.intellij.openapi.roots.ModifiableRootModel;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.vfs.VfsUtilCore;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.VirtualFileManager;
|
||||
import com.intellij.openapi.vfs.VirtualFileVisitor;
|
||||
import com.intellij.openapi.vfs.ex.temp.TempFileSystem;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.indexing.FileBasedIndex;
|
||||
import com.intellij.util.indexing.IndexableFileSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static com.intellij.openapi.roots.ModuleRootModificationUtil.updateModel;
|
||||
|
||||
|
||||
public class LightProjectDescriptor {
|
||||
public static final LightProjectDescriptor EMPTY_PROJECT_DESCRIPTOR = new LightProjectDescriptor();
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
public interface LightProjectDescriptor {
|
||||
@NotNull
|
||||
ModuleType getModuleType();
|
||||
Sdk getSdk();
|
||||
void configureModule(@NotNull Module module, @NotNull ModifiableRootModel model, @NotNull ContentEntry contentEntry);
|
||||
public ProjectInfo setUpProject(@NotNull Project project) throws Exception {
|
||||
Module module = createMainModule(project);
|
||||
VirtualFile contentRoot = createSourcesRoot(module);
|
||||
return new ProjectInfo(module, contentRoot);
|
||||
}
|
||||
|
||||
class Empty implements LightProjectDescriptor {
|
||||
@NotNull
|
||||
@Override
|
||||
public ModuleType getModuleType() {
|
||||
return EmptyModuleType.getInstance();
|
||||
@NotNull
|
||||
public Module createMainModule(@NotNull final Project project) {
|
||||
return ApplicationManager.getApplication().runWriteAction(new Computable<Module>() {
|
||||
@Override
|
||||
public Module compute() {
|
||||
return ModuleManager.getInstance(project).newModule("light_idea_test_case.iml", getModuleType().getId());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ModuleType getModuleType() {
|
||||
return EmptyModuleType.getInstance();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public VirtualFile createSourcesRoot(@NotNull final Module module) {
|
||||
VirtualFile dummyRoot = VirtualFileManager.getInstance().findFileByUrl("temp:///");
|
||||
assert dummyRoot != null;
|
||||
dummyRoot.refresh(false, false);
|
||||
|
||||
final VirtualFile srcRoot;
|
||||
try {
|
||||
srcRoot = dummyRoot.createChildDirectory(this, "src");
|
||||
cleanSourceRoot(srcRoot);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Sdk getSdk() {
|
||||
return null;
|
||||
}
|
||||
final IndexableFileSet indexableFileSet = new IndexableFileSet() {
|
||||
@Override
|
||||
public boolean isInSet(@NotNull final VirtualFile file) {
|
||||
return file.getFileSystem() == srcRoot.getFileSystem() &&
|
||||
module.getProject().isOpen();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configureModule(@NotNull Module module, @NotNull ModifiableRootModel model, @NotNull ContentEntry contentEntry) {
|
||||
@Override
|
||||
public void iterateIndexableFilesIn(@NotNull final VirtualFile file, @NotNull final ContentIterator iterator) {
|
||||
VfsUtilCore.visitChildrenRecursively(file, new VirtualFileVisitor() {
|
||||
@Override
|
||||
public boolean visitFile(@NotNull VirtualFile file) {
|
||||
iterator.processFile(file);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
FileBasedIndex.getInstance().registerIndexableSet(indexableFileSet, null);
|
||||
Disposer.register(module.getProject(), new Disposable() {
|
||||
@Override
|
||||
public void dispose() {
|
||||
FileBasedIndex.getInstance().removeIndexableSet(indexableFileSet);
|
||||
}
|
||||
});
|
||||
|
||||
updateModel(module, new Consumer<ModifiableRootModel>() {
|
||||
@Override
|
||||
public void consume(ModifiableRootModel model) {
|
||||
Sdk sdk = getSdk();
|
||||
if (sdk != null) {
|
||||
model.setSdk(sdk);
|
||||
}
|
||||
|
||||
ContentEntry contentEntry = model.addContentEntry(srcRoot);
|
||||
contentEntry.addSourceFolder(srcRoot, false);
|
||||
|
||||
configureModule(module, model, contentEntry);
|
||||
}
|
||||
});
|
||||
|
||||
return srcRoot;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Sdk getSdk() {
|
||||
return null;
|
||||
}
|
||||
|
||||
private void cleanSourceRoot(@NotNull VirtualFile contentRoot) throws IOException {
|
||||
TempFileSystem tempFs = (TempFileSystem)contentRoot.getFileSystem();
|
||||
for (VirtualFile child : contentRoot.getChildren()) {
|
||||
if (!tempFs.exists(child)) {
|
||||
tempFs.createChildFile(this, contentRoot, child.getName());
|
||||
}
|
||||
child.delete(this);
|
||||
}
|
||||
}
|
||||
|
||||
LightProjectDescriptor EMPTY_PROJECT_DESCRIPTOR = new Empty();
|
||||
protected void configureModule(@NotNull Module module, @NotNull ModifiableRootModel model, @NotNull ContentEntry contentEntry) {
|
||||
}
|
||||
|
||||
public static class ProjectInfo {
|
||||
@NotNull public final Module module;
|
||||
@Nullable public final VirtualFile moduleSourcesRoot;
|
||||
|
||||
public ProjectInfo(@NotNull Module module, @Nullable VirtualFile moduleSourcesRoot) {
|
||||
this.module = module;
|
||||
this.moduleSourcesRoot = moduleSourcesRoot;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2015 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.intellij.testFramework;
|
||||
|
||||
import com.intellij.openapi.module.Module;
|
||||
|
||||
public interface LightProjectDescriptorEx extends LightProjectDescriptor {
|
||||
boolean shouldConfigureModule();
|
||||
|
||||
void setupModule(Module module);
|
||||
}
|
||||
@@ -50,9 +50,9 @@
|
||||
description="Navigate to the next answer holder">
|
||||
</action>
|
||||
<action id="PreviousTaskAction" class="com.jetbrains.edu.learning.actions.StudyPreviousStudyTaskAction" text="Previous Task"
|
||||
description="Navigate to previous task"/>
|
||||
description="Navigate to the previous task"/>
|
||||
<action id="NextTaskAction" class="com.jetbrains.edu.learning.actions.StudyNextStudyTaskAction" text="Next Task"
|
||||
description="Navigate to next task"/>
|
||||
description="Navigate to the next task"/>
|
||||
<action id="RefreshTaskAction" class="com.jetbrains.edu.learning.actions.StudyRefreshTaskFileAction" text="Reset Task File"
|
||||
description="Refresh current task"/>
|
||||
<action id="WatchInputAction" class="com.jetbrains.edu.learning.actions.StudyEditInputAction" text="Watch Test Input"
|
||||
@@ -65,7 +65,7 @@
|
||||
</actions>
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<toolWindow id="Course Description" anchor="right" factoryClass="com.jetbrains.edu.learning.ui.StudyToolWindowFactory" conditionClass="com.jetbrains.edu.learning.ui.StudyCondition"/>
|
||||
<toolWindow id="Task Description" anchor="right" factoryClass="com.jetbrains.edu.learning.ui.StudyToolWindowFactory" conditionClass="com.jetbrains.edu.learning.ui.StudyCondition"/>
|
||||
<fileEditorProvider implementation="com.jetbrains.edu.learning.editor.StudyFileEditorProvider"/>
|
||||
<treeStructureProvider implementation="com.jetbrains.edu.learning.projectView.StudyTreeStructureProvider"/>
|
||||
<applicationService serviceInterface="com.intellij.openapi.fileEditor.impl.EditorEmptyTextPainter"
|
||||
|
||||
+3
-17
@@ -33,7 +33,6 @@ import com.jetbrains.edu.courseFormat.Task;
|
||||
import com.jetbrains.edu.courseFormat.TaskFile;
|
||||
import com.jetbrains.edu.learning.actions.*;
|
||||
import com.jetbrains.edu.learning.editor.StudyEditorFactoryListener;
|
||||
import com.jetbrains.edu.learning.ui.StudyCondition;
|
||||
import com.jetbrains.edu.learning.ui.StudyToolWindowFactory;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -41,7 +40,6 @@ import org.jetbrains.annotations.Nullable;
|
||||
import javax.swing.*;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -134,19 +132,9 @@ public class StudyProjectComponent implements ProjectComponent {
|
||||
}
|
||||
|
||||
private void registerToolWindow(@NotNull final ToolWindowManager toolWindowManager) {
|
||||
try {
|
||||
Method method = toolWindowManager.getClass().getDeclaredMethod("registerToolWindow", String.class,
|
||||
JComponent.class,
|
||||
ToolWindowAnchor.class,
|
||||
boolean.class, boolean.class, boolean.class);
|
||||
method.setAccessible(true);
|
||||
method.invoke(toolWindowManager, StudyToolWindowFactory.STUDY_TOOL_WINDOW, null, ToolWindowAnchor.LEFT, true, true, true);
|
||||
}
|
||||
catch (Exception e) {
|
||||
final ToolWindow toolWindow = toolWindowManager.getToolWindow(StudyToolWindowFactory.STUDY_TOOL_WINDOW);
|
||||
if (toolWindow == null) {
|
||||
toolWindowManager.registerToolWindow(StudyToolWindowFactory.STUDY_TOOL_WINDOW, true, ToolWindowAnchor.RIGHT, myProject, true);
|
||||
}
|
||||
final ToolWindow toolWindow = toolWindowManager.getToolWindow(StudyToolWindowFactory.STUDY_TOOL_WINDOW);
|
||||
if (toolWindow == null) {
|
||||
toolWindowManager.registerToolWindow(StudyToolWindowFactory.STUDY_TOOL_WINDOW, true, ToolWindowAnchor.RIGHT, myProject, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -218,8 +206,6 @@ public class StudyProjectComponent implements ProjectComponent {
|
||||
|
||||
@Override
|
||||
public void projectClosed() {
|
||||
//noinspection AssignmentToStaticFieldFromInstanceMethod
|
||||
StudyCondition.VALUE = false;
|
||||
final Course course = StudyTaskManager.getInstance(myProject).getCourse();
|
||||
if (course != null) {
|
||||
ToolWindowManager.getInstance(myProject).getToolWindow(StudyToolWindowFactory.STUDY_TOOL_WINDOW).getContentManager()
|
||||
|
||||
+61
-4
@@ -6,13 +6,17 @@ import com.intellij.execution.process.ProcessHandler;
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.Presentation;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.RangeMarker;
|
||||
import com.intellij.openapi.editor.actionSystem.EditorActionManager;
|
||||
import com.intellij.openapi.editor.colors.EditorColors;
|
||||
import com.intellij.openapi.editor.impl.DocumentImpl;
|
||||
import com.intellij.openapi.fileEditor.FileEditor;
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager;
|
||||
import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.ui.popup.Balloon;
|
||||
@@ -21,6 +25,7 @@ import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.wm.ToolWindowManager;
|
||||
import com.intellij.ui.JBColor;
|
||||
import com.intellij.ui.awt.RelativePoint;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.jetbrains.edu.EduAnswerPlaceholderDeleteHandler;
|
||||
import com.jetbrains.edu.EduAnswerPlaceholderPainter;
|
||||
@@ -34,7 +39,7 @@ import com.jetbrains.edu.learning.ui.StudyToolWindowFactory;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.io.*;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
@@ -181,13 +186,22 @@ public class StudyUtils {
|
||||
* shows pop up in the center of "check task" button in study editor
|
||||
*/
|
||||
public static void showCheckPopUp(@NotNull final Project project, @NotNull final Balloon balloon) {
|
||||
final StudyEditor studyEditor = StudyEditor.getSelectedStudyEditor(project);
|
||||
final StudyEditor studyEditor = getSelectedStudyEditor(project);
|
||||
assert studyEditor != null;
|
||||
final JButton checkButton = studyEditor.getCheckButton();
|
||||
balloon.showInCenterOf(checkButton);
|
||||
|
||||
balloon.show(computeLocation(studyEditor.getEditor()), Balloon.Position.above);
|
||||
Disposer.register(project, balloon);
|
||||
}
|
||||
|
||||
public static RelativePoint computeLocation(Editor editor){
|
||||
|
||||
final Rectangle visibleRect = editor.getComponent().getVisibleRect();
|
||||
Point point = new Point(visibleRect.x + visibleRect.width + 10,
|
||||
visibleRect.y + 10);
|
||||
return new RelativePoint(editor.getComponent(), point);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* returns language manager which contains all the information about language specific file names
|
||||
*/
|
||||
@@ -246,4 +260,47 @@ public class StudyUtils {
|
||||
editor.getColorsScheme().setColor(EditorColors.READONLY_FRAGMENT_BACKGROUND_COLOR, null);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static StudyEditor getSelectedStudyEditor(@NotNull final Project project) {
|
||||
try {
|
||||
final FileEditor fileEditor = FileEditorManagerEx.getInstanceEx(project).getSplitters().getCurrentWindow().
|
||||
getSelectedEditor().getSelectedEditorWithProvider().getFirst();
|
||||
if (fileEditor instanceof StudyEditor) {
|
||||
return (StudyEditor)fileEditor;
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static Editor getSelectedEditor(@NotNull final Project project) {
|
||||
final StudyEditor studyEditor = getSelectedStudyEditor(project);
|
||||
if (studyEditor != null) {
|
||||
return studyEditor.getEditor();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void deleteGuardedBlocks(@NotNull final Document document) {
|
||||
if (document instanceof DocumentImpl) {
|
||||
final DocumentImpl documentImpl = (DocumentImpl)document;
|
||||
List<RangeMarker> blocks = documentImpl.getGuardedBlocks();
|
||||
for (final RangeMarker block : blocks) {
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
document.removeGuardedBlock(block);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+18
-5
@@ -6,6 +6,7 @@ import com.intellij.execution.process.ProcessOutput;
|
||||
import com.intellij.ide.projectView.ProjectView;
|
||||
import com.intellij.openapi.actionSystem.ActionManager;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.KeyboardShortcut;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.command.CommandProcessor;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
@@ -14,6 +15,7 @@ import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.fileEditor.FileEditor;
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager;
|
||||
import com.intellij.openapi.keymap.KeymapUtil;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.progress.TaskInfo;
|
||||
@@ -43,9 +45,11 @@ import com.jetbrains.edu.learning.editor.StudyEditor;
|
||||
import com.jetbrains.edu.learning.navigation.StudyNavigator;
|
||||
import com.jetbrains.edu.learning.run.StudySmartChecker;
|
||||
import com.jetbrains.edu.learning.run.StudyTestRunner;
|
||||
import icons.InteractiveLearningIcons;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
@@ -58,6 +62,11 @@ public class StudyCheckAction extends DumbAwareAction {
|
||||
public static final String ACTION_ID = "CheckAction";
|
||||
public static final String SHORTCUT = "ctrl alt pressed ENTER";
|
||||
|
||||
boolean checkInProgress = false;
|
||||
|
||||
public StudyCheckAction() {
|
||||
super("Check Task (" + KeymapUtil.getShortcutText(new KeyboardShortcut(KeyStroke.getKeyStroke(SHORTCUT), null)) + ")", "Check current task", InteractiveLearningIcons.Resolve);
|
||||
}
|
||||
|
||||
private static void flushWindows(@NotNull final Task task, @NotNull final VirtualFile taskDir) {
|
||||
for (Map.Entry<String, TaskFile> entry : task.getTaskFiles().entrySet()) {
|
||||
@@ -115,7 +124,7 @@ public class StudyCheckAction extends DumbAwareAction {
|
||||
CommandProcessor.getInstance().runUndoTransparentAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final StudyEditor selectedEditor = StudyEditor.getSelectedStudyEditor(project);
|
||||
final StudyEditor selectedEditor = StudyUtils.getSelectedStudyEditor(project);
|
||||
if (selectedEditor == null) return;
|
||||
final StudyState studyState = new StudyState(selectedEditor);
|
||||
if (!studyState.isValid()) {
|
||||
@@ -158,7 +167,7 @@ public class StudyCheckAction extends DumbAwareAction {
|
||||
if (testProcess == null) {
|
||||
return;
|
||||
}
|
||||
selectedEditor.getCheckButton().setEnabled(false);
|
||||
checkInProgress = true;
|
||||
ProgressManager.getInstance().run(getCheckTask(studyState, testRunner, testProcess, project, selectedEditor));
|
||||
}
|
||||
});
|
||||
@@ -202,14 +211,14 @@ public class StudyCheckAction extends DumbAwareAction {
|
||||
drawAllPlaceholders(project, task, taskDir);
|
||||
ProjectView.getInstance(project).refresh();
|
||||
deleteWindowDescriptions(task, taskDir);
|
||||
selectedEditor.getCheckButton().setEnabled(true);
|
||||
checkInProgress = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel() {
|
||||
taskManager.setStatus(task, statusBeforeCheck);
|
||||
deleteWindowDescriptions(task, taskDir);
|
||||
selectedEditor.getCheckButton().setEnabled(true);
|
||||
checkInProgress = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -382,7 +391,6 @@ public class StudyCheckAction extends DumbAwareAction {
|
||||
StudyUtils.showCheckPopUp(project, balloon);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void actionPerformed(@NotNull AnActionEvent e) {
|
||||
Project project = e.getProject();
|
||||
@@ -390,4 +398,9 @@ public class StudyCheckAction extends DumbAwareAction {
|
||||
check(project);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(AnActionEvent e) {
|
||||
e.getPresentation().setEnabled(!checkInProgress);
|
||||
}
|
||||
}
|
||||
|
||||
+22
-2
@@ -29,6 +29,7 @@ import com.jetbrains.edu.learning.StudyUtils;
|
||||
import com.jetbrains.edu.learning.courseFormat.UserTest;
|
||||
import com.jetbrains.edu.learning.editor.StudyEditor;
|
||||
import com.jetbrains.edu.learning.ui.StudyTestContentPanel;
|
||||
import icons.InteractiveLearningIcons;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
@@ -46,8 +47,12 @@ public class StudyEditInputAction extends DumbAwareAction {
|
||||
private JBEditorTabs tabbedPane;
|
||||
private Map<TabInfo, UserTest> myEditableTabs = new HashMap<TabInfo, UserTest>();
|
||||
|
||||
public StudyEditInputAction() {
|
||||
super("Watch Test Input", "Watch test input", InteractiveLearningIcons.WatchInput);
|
||||
}
|
||||
|
||||
public void showInput(final Project project) {
|
||||
final Editor selectedEditor = StudyEditor.getSelectedEditor(project);
|
||||
final Editor selectedEditor = StudyUtils.getSelectedEditor(project);
|
||||
if (selectedEditor != null) {
|
||||
FileDocumentManager fileDocumentManager = FileDocumentManager.getInstance();
|
||||
final VirtualFile openedFile = fileDocumentManager.getFile(selectedEditor.getDocument());
|
||||
@@ -100,7 +105,7 @@ public class StudyEditInputAction extends DumbAwareAction {
|
||||
.setMovable(true)
|
||||
.setRequestFocus(true)
|
||||
.createPopup();
|
||||
StudyEditor selectedStudyEditor = StudyEditor.getSelectedStudyEditor(project);
|
||||
StudyEditor selectedStudyEditor = StudyUtils.getSelectedStudyEditor(project);
|
||||
assert selectedStudyEditor != null;
|
||||
hint.showInCenterOf(selectedStudyEditor.getComponent());
|
||||
hint.addListener(new HintClosedListener(currentTask, studyTaskManager));
|
||||
@@ -219,4 +224,19 @@ public class StudyEditInputAction extends DumbAwareAction {
|
||||
}
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void update(final AnActionEvent e) {
|
||||
EduUtils.enableAction(e, false);
|
||||
|
||||
final Project project = e.getProject();
|
||||
if (project != null) {
|
||||
StudyEditor studyEditor = StudyUtils.getSelectedStudyEditor(project);
|
||||
if (studyEditor != null) {
|
||||
final List<UserTest> userTests = StudyTaskManager.getInstance(project).getUserTests(studyEditor.getTaskFile().getTask());
|
||||
if (!userTests.isEmpty()) {
|
||||
EduUtils.enableAction(e, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+5
-4
@@ -1,7 +1,9 @@
|
||||
package com.jetbrains.edu.learning.actions;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.openapi.actionSystem.KeyboardShortcut;
|
||||
import com.intellij.openapi.keymap.KeymapUtil;
|
||||
import com.jetbrains.edu.courseFormat.Task;
|
||||
import com.jetbrains.edu.learning.editor.StudyEditor;
|
||||
import com.jetbrains.edu.learning.navigation.StudyNavigator;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -12,9 +14,8 @@ public class StudyNextStudyTaskAction extends StudyTaskNavigationAction {
|
||||
public static final String ACTION_ID = "NextTaskAction";
|
||||
public static final String SHORTCUT = "ctrl pressed PERIOD";
|
||||
|
||||
@Override
|
||||
protected JButton getButton(@NotNull final StudyEditor selectedStudyEditor) {
|
||||
return selectedStudyEditor.getNextTaskButton();
|
||||
public StudyNextStudyTaskAction() {
|
||||
super("Next Task (" + KeymapUtil.getShortcutText(new KeyboardShortcut(KeyStroke.getKeyStroke(SHORTCUT), null)) + ")", "Navigate to the next task", AllIcons.Actions.Forward);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+6
-5
@@ -1,21 +1,22 @@
|
||||
package com.jetbrains.edu.learning.actions;
|
||||
|
||||
|
||||
import com.intellij.openapi.actionSystem.KeyboardShortcut;
|
||||
import com.intellij.openapi.keymap.KeymapUtil;
|
||||
import com.jetbrains.edu.courseFormat.Task;
|
||||
import com.jetbrains.edu.learning.editor.StudyEditor;
|
||||
import com.jetbrains.edu.learning.navigation.StudyNavigator;
|
||||
import icons.InteractiveLearningIcons;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
public class StudyPreviousStudyTaskAction extends StudyTaskNavigationAction {
|
||||
public StudyPreviousStudyTaskAction() {
|
||||
super("Previous Task (" + KeymapUtil.getShortcutText(new KeyboardShortcut(KeyStroke.getKeyStroke(SHORTCUT), null)) + ")", "Navigate to the previous task", InteractiveLearningIcons.Prev);
|
||||
}
|
||||
|
||||
public static final String ACTION_ID = "PreviousTaskAction";
|
||||
public static final String SHORTCUT = "ctrl pressed COMMA";
|
||||
@Override
|
||||
protected JButton getButton(@NotNull final StudyEditor selectedStudyEditor) {
|
||||
return selectedStudyEditor.getPrevTaskButton();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getNavigationFinishedMessage() {
|
||||
|
||||
+14
-6
@@ -1,13 +1,16 @@
|
||||
package com.jetbrains.edu.learning.actions;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.ide.projectView.ProjectView;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.KeyboardShortcut;
|
||||
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.editor.Editor;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.keymap.KeymapUtil;
|
||||
import com.intellij.openapi.project.DumbAwareAction;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.MessageType;
|
||||
@@ -35,6 +38,7 @@ import com.jetbrains.edu.learning.editor.StudyEditor;
|
||||
import com.jetbrains.edu.learning.navigation.StudyNavigator;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.io.File;
|
||||
|
||||
public class StudyRefreshTaskFileAction extends DumbAwareAction {
|
||||
@@ -42,6 +46,10 @@ public class StudyRefreshTaskFileAction extends DumbAwareAction {
|
||||
public static final String SHORTCUT = "ctrl shift pressed X";
|
||||
private static final Logger LOG = Logger.getInstance(StudyRefreshTaskFileAction.class.getName());
|
||||
|
||||
public StudyRefreshTaskFileAction() {
|
||||
super("Reset Task File (" + KeymapUtil.getShortcutText(new KeyboardShortcut(KeyStroke.getKeyStroke(SHORTCUT), null)) + ")", "Refresh current task", AllIcons.Actions.Refresh);
|
||||
}
|
||||
|
||||
public static void refresh(@NotNull final Project project) {
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
@Override
|
||||
@@ -50,7 +58,7 @@ public class StudyRefreshTaskFileAction extends DumbAwareAction {
|
||||
@SuppressWarnings("IOResourceOpenedButNotSafelyClosed")
|
||||
@Override
|
||||
public void run() {
|
||||
StudyEditor studyEditor = StudyEditor.getSelectedStudyEditor(project);
|
||||
StudyEditor studyEditor = StudyUtils.getSelectedStudyEditor(project);
|
||||
StudyState studyState = new StudyState(studyEditor);
|
||||
if (studyEditor == null || !studyState.isValid()) {
|
||||
LOG.info("RefreshTaskFileAction was invoked outside of Study Editor");
|
||||
@@ -101,9 +109,9 @@ public class StudyRefreshTaskFileAction extends DumbAwareAction {
|
||||
BalloonBuilder balloonBuilder =
|
||||
JBPopupFactory.getInstance().createHtmlTextBalloonBuilder(text, messageType, null);
|
||||
final Balloon balloon = balloonBuilder.createBalloon();
|
||||
StudyEditor selectedStudyEditor = StudyEditor.getSelectedStudyEditor(project);
|
||||
StudyEditor selectedStudyEditor = StudyUtils.getSelectedStudyEditor(project);
|
||||
assert selectedStudyEditor != null;
|
||||
balloon.showInCenterOf(selectedStudyEditor.getRefreshButton());
|
||||
balloon.show(StudyUtils.computeLocation(selectedStudyEditor.getEditor()), Balloon.Position.above);
|
||||
Disposer.register(project, balloon);
|
||||
}
|
||||
|
||||
@@ -120,7 +128,7 @@ public class StudyRefreshTaskFileAction extends DumbAwareAction {
|
||||
@NotNull final Document document,
|
||||
@NotNull final TaskFile taskFile,
|
||||
String fileName) {
|
||||
StudyEditor.deleteGuardedBlocks(document);
|
||||
StudyUtils.deleteGuardedBlocks(document);
|
||||
taskFile.setTrackChanges(false);
|
||||
clearDocument(document);
|
||||
Task task = taskFile.getTask();
|
||||
@@ -167,14 +175,14 @@ public class StudyRefreshTaskFileAction extends DumbAwareAction {
|
||||
|
||||
@Override
|
||||
public void update(AnActionEvent event) {
|
||||
EduUtils.enableAction(event, false);
|
||||
final Project project = event.getProject();
|
||||
if (project != null) {
|
||||
StudyEditor studyEditor = StudyEditor.getSelectedStudyEditor(project);
|
||||
StudyEditor studyEditor = StudyUtils.getSelectedStudyEditor(project);
|
||||
StudyState studyState = new StudyState(studyEditor);
|
||||
if (studyState.isValid()) {
|
||||
EduUtils.enableAction(event, true);
|
||||
}
|
||||
}
|
||||
EduUtils.enableAction(event, false);
|
||||
}
|
||||
}
|
||||
|
||||
+27
-1
@@ -5,6 +5,7 @@ import com.intellij.execution.RunContentExecutor;
|
||||
import com.intellij.execution.configurations.GeneralCommandLine;
|
||||
import com.intellij.execution.process.OSProcessHandler;
|
||||
import com.intellij.execution.process.ProcessHandler;
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
@@ -14,20 +15,29 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.jetbrains.edu.EduUtils;
|
||||
import com.jetbrains.edu.courseFormat.Task;
|
||||
import com.jetbrains.edu.courseFormat.TaskFile;
|
||||
import com.jetbrains.edu.learning.StudyTaskManager;
|
||||
import com.jetbrains.edu.learning.StudyUtils;
|
||||
import com.jetbrains.edu.learning.courseFormat.UserTest;
|
||||
import com.jetbrains.edu.learning.editor.StudyEditor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class StudyRunAction extends DumbAwareAction {
|
||||
private static final Logger LOG = Logger.getInstance(StudyRunAction.class.getName());
|
||||
public static final String ACTION_ID = "StudyRunAction";
|
||||
private ProcessHandler myHandler;
|
||||
|
||||
public StudyRunAction() {
|
||||
super("Run File With Tests", "Run your code with tests", AllIcons.General.Run);
|
||||
}
|
||||
|
||||
public void run(@NotNull final Project project) {
|
||||
if (myHandler != null && !myHandler.isProcessTerminated()) return;
|
||||
Editor selectedEditor = StudyEditor.getSelectedEditor(project);
|
||||
Editor selectedEditor = StudyUtils.getSelectedEditor(project);
|
||||
FileDocumentManager fileDocumentManager = FileDocumentManager.getInstance();
|
||||
assert selectedEditor != null;
|
||||
VirtualFile openedFile = fileDocumentManager.getFile(selectedEditor.getDocument());
|
||||
@@ -79,4 +89,20 @@ public class StudyRunAction extends DumbAwareAction {
|
||||
run(project);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(AnActionEvent e) {
|
||||
EduUtils.enableAction(e, false);
|
||||
|
||||
final Project project = e.getProject();
|
||||
if (project != null) {
|
||||
StudyEditor studyEditor = StudyUtils.getSelectedStudyEditor(project);
|
||||
if (studyEditor != null) {
|
||||
final List<UserTest> userTests = StudyTaskManager.getInstance(project).getUserTests(studyEditor.getTaskFile().getTask());
|
||||
if (!userTests.isEmpty()) {
|
||||
EduUtils.enableAction(e, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+6
-3
@@ -3,8 +3,10 @@ package com.jetbrains.edu.learning.actions;
|
||||
import com.intellij.codeInsight.documentation.DocumentationComponent;
|
||||
import com.intellij.codeInsight.documentation.DocumentationManager;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.KeyboardShortcut;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.LogicalPosition;
|
||||
import com.intellij.openapi.keymap.KeymapUtil;
|
||||
import com.intellij.openapi.project.DumbAwareAction;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.popup.JBPopup;
|
||||
@@ -18,10 +20,11 @@ import com.jetbrains.edu.courseFormat.Course;
|
||||
import com.jetbrains.edu.learning.StudyState;
|
||||
import com.jetbrains.edu.learning.StudyTaskManager;
|
||||
import com.jetbrains.edu.learning.StudyUtils;
|
||||
import com.jetbrains.edu.learning.editor.StudyEditor;
|
||||
import icons.InteractiveLearningIcons;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
public class StudyShowHintAction extends DumbAwareAction {
|
||||
public static final String ACTION_ID = "ShowHintAction";
|
||||
public static final String SHORTCUT = "ctrl pressed 7";
|
||||
@@ -29,7 +32,7 @@ public class StudyShowHintAction extends DumbAwareAction {
|
||||
public static final String HINT_NOT_AVAILABLE = "There is no hint for this answer placeholder";
|
||||
|
||||
public StudyShowHintAction() {
|
||||
super("Show hint", "Show hint", InteractiveLearningIcons.ShowHint);
|
||||
super("Show hint (" + KeymapUtil.getShortcutText(new KeyboardShortcut(KeyStroke.getKeyStroke(SHORTCUT), null)) + ")", "Show hint", InteractiveLearningIcons.ShowHint);
|
||||
}
|
||||
|
||||
public void actionPerformed(@NotNull AnActionEvent e) {
|
||||
@@ -45,7 +48,7 @@ public class StudyShowHintAction extends DumbAwareAction {
|
||||
if (course == null) {
|
||||
return;
|
||||
}
|
||||
StudyState studyState = new StudyState(StudyEditor.getSelectedStudyEditor(project));
|
||||
StudyState studyState = new StudyState(StudyUtils.getSelectedStudyEditor(project));
|
||||
if (!studyState.isValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
+8
-4
@@ -18,8 +18,10 @@ import com.jetbrains.edu.EduNames;
|
||||
import com.jetbrains.edu.courseFormat.Task;
|
||||
import com.jetbrains.edu.courseFormat.TaskFile;
|
||||
import com.jetbrains.edu.learning.StudyState;
|
||||
import com.jetbrains.edu.learning.StudyUtils;
|
||||
import com.jetbrains.edu.learning.editor.StudyEditor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.tree.TreePath;
|
||||
@@ -27,8 +29,12 @@ import java.util.Map;
|
||||
|
||||
|
||||
abstract public class StudyTaskNavigationAction extends DumbAwareAction {
|
||||
public StudyTaskNavigationAction(@Nullable String text, @Nullable String description, @Nullable Icon icon) {
|
||||
super(text, description, icon);
|
||||
}
|
||||
|
||||
public void navigateTask(@NotNull final Project project) {
|
||||
StudyEditor studyEditor = StudyEditor.getSelectedStudyEditor(project);
|
||||
StudyEditor studyEditor = StudyUtils.getSelectedStudyEditor(project);
|
||||
StudyState studyState = new StudyState(studyEditor);
|
||||
if (!studyState.isValid()) {
|
||||
return;
|
||||
@@ -39,7 +45,7 @@ abstract public class StudyTaskNavigationAction extends DumbAwareAction {
|
||||
JBPopupFactory.getInstance().createHtmlTextBalloonBuilder(getNavigationFinishedMessage(), MessageType.INFO, null);
|
||||
Balloon balloon = balloonBuilder.createBalloon();
|
||||
assert studyEditor != null;
|
||||
balloon.showInCenterOf(getButton(studyEditor));
|
||||
balloon.show(StudyUtils.computeLocation(studyEditor.getEditor()), Balloon.Position.above);
|
||||
return;
|
||||
}
|
||||
for (VirtualFile file : FileEditorManager.getInstance(project).getOpenFiles()) {
|
||||
@@ -90,8 +96,6 @@ abstract public class StudyTaskNavigationAction extends DumbAwareAction {
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract JButton getButton(@NotNull final StudyEditor selectedStudyEditor);
|
||||
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
Project project = e.getProject();
|
||||
|
||||
+1
-2
@@ -9,7 +9,6 @@ import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.jetbrains.edu.courseFormat.AnswerPlaceholder;
|
||||
import com.jetbrains.edu.courseFormat.TaskFile;
|
||||
import com.jetbrains.edu.learning.StudyUtils;
|
||||
import com.jetbrains.edu.learning.editor.StudyEditor;
|
||||
import com.jetbrains.edu.learning.navigation.StudyNavigator;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -23,7 +22,7 @@ abstract public class StudyWindowNavigationAction extends DumbAwareAction {
|
||||
}
|
||||
|
||||
private void navigateToPlaceholder(@NotNull final Project project) {
|
||||
final Editor selectedEditor = StudyEditor.getSelectedEditor(project);
|
||||
final Editor selectedEditor = StudyUtils.getSelectedEditor(project);
|
||||
if (selectedEditor != null) {
|
||||
final FileDocumentManager fileDocumentManager = FileDocumentManager.getInstance();
|
||||
final VirtualFile openedFile = fileDocumentManager.getFile(selectedEditor.getDocument());
|
||||
|
||||
+2
-413
@@ -1,405 +1,38 @@
|
||||
package com.jetbrains.edu.learning.editor;
|
||||
|
||||
import com.intellij.codeHighlighting.BackgroundEditorHighlighter;
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.ide.structureView.StructureViewBuilder;
|
||||
import com.intellij.openapi.actionSystem.ActionManager;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.KeyboardShortcut;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.EditorFactory;
|
||||
import com.intellij.openapi.editor.RangeMarker;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsManager;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsScheme;
|
||||
import com.intellij.openapi.editor.impl.DocumentImpl;
|
||||
import com.intellij.openapi.fileEditor.*;
|
||||
import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx;
|
||||
import com.intellij.openapi.fileEditor.impl.text.PsiAwareTextEditorImpl;
|
||||
import com.intellij.openapi.fileEditor.impl.text.TextEditorProvider;
|
||||
import com.intellij.openapi.keymap.KeymapUtil;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.wm.IdeFocusManager;
|
||||
import com.intellij.openapi.wm.ToolWindow;
|
||||
import com.intellij.openapi.wm.ToolWindowId;
|
||||
import com.intellij.openapi.wm.ToolWindowManager;
|
||||
import com.intellij.pom.Navigatable;
|
||||
import com.intellij.ui.BrowserHyperlinkListener;
|
||||
import com.intellij.ui.HideableTitledPanel;
|
||||
import com.intellij.ui.JBColor;
|
||||
import com.intellij.util.ui.EmptyClipboardOwner;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.jetbrains.edu.EduDocumentListener;
|
||||
import com.jetbrains.edu.courseFormat.Task;
|
||||
import com.jetbrains.edu.courseFormat.TaskFile;
|
||||
import com.jetbrains.edu.learning.StudyTaskManager;
|
||||
import com.jetbrains.edu.learning.StudyUtils;
|
||||
import com.jetbrains.edu.learning.actions.*;
|
||||
import com.jetbrains.edu.learning.courseFormat.UserTest;
|
||||
import icons.InteractiveLearningIcons;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import javax.swing.text.MutableAttributeSet;
|
||||
import javax.swing.text.StyleConstants;
|
||||
import javax.swing.text.StyledDocument;
|
||||
import java.awt.*;
|
||||
import java.awt.datatransfer.StringSelection;
|
||||
import java.awt.event.*;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Implementation of StudyEditor which has panel with special buttons and task text
|
||||
* also @see {@link StudyFileEditorProvider}
|
||||
*/
|
||||
public class StudyEditor implements TextEditor {
|
||||
private static final String TASK_TEXT_HEADER = "Task Text";
|
||||
private final FileEditor myDefaultEditor;
|
||||
private final JComponent myComponent;
|
||||
public class StudyEditor extends PsiAwareTextEditorImpl {
|
||||
private final TaskFile myTaskFile;
|
||||
private JButton myCheckButton;
|
||||
private JButton myNextTaskButton;
|
||||
private JButton myPrevTaskButton;
|
||||
private JButton myRefreshButton;
|
||||
private static final Map<Document, EduDocumentListener> myDocumentListeners = new HashMap<Document, EduDocumentListener>();
|
||||
private final Project myProject;
|
||||
|
||||
public JButton getCheckButton() {
|
||||
return myCheckButton;
|
||||
}
|
||||
|
||||
public JButton getPrevTaskButton() {
|
||||
return myPrevTaskButton;
|
||||
}
|
||||
|
||||
public TaskFile getTaskFile() {
|
||||
return myTaskFile;
|
||||
}
|
||||
|
||||
private static JButton addButton(@NotNull final JComponent parentComponent, @NotNull final String actionID,
|
||||
@NotNull final Icon icon, @Nullable String defaultShortcutString) {
|
||||
final AnAction action = ActionManager.getInstance().getAction(actionID);
|
||||
String toolTipText = KeymapUtil.createTooltipText(action.getTemplatePresentation().getText(), action);
|
||||
if (!toolTipText.contains("(") && defaultShortcutString != null) {
|
||||
KeyboardShortcut shortcut = new KeyboardShortcut(KeyStroke.getKeyStroke(defaultShortcutString), null);
|
||||
toolTipText += " (" + KeymapUtil.getShortcutText(shortcut) + ")";
|
||||
}
|
||||
final JButton newButton = new JButton();
|
||||
newButton.setToolTipText(toolTipText);
|
||||
newButton.setIcon(icon);
|
||||
newButton.setSize(new Dimension(icon.getIconWidth(), icon.getIconHeight()));
|
||||
parentComponent.add(newButton);
|
||||
return newButton;
|
||||
}
|
||||
|
||||
public static void addDocumentListener(@NotNull final Document document, @NotNull final EduDocumentListener listener) {
|
||||
document.addDocumentListener(listener);
|
||||
myDocumentListeners.put(document, listener);
|
||||
}
|
||||
|
||||
public StudyEditor(@NotNull final Project project, @NotNull final VirtualFile file) {
|
||||
myProject = project;
|
||||
myDefaultEditor = TextEditorProvider.getInstance().createEditor(myProject, file);
|
||||
myComponent = myDefaultEditor.getComponent();
|
||||
final JPanel studyPanel = new JPanel();
|
||||
studyPanel.setLayout(new BoxLayout(studyPanel, BoxLayout.Y_AXIS));
|
||||
super(project, file, TextEditorProvider.getInstance());
|
||||
myTaskFile = StudyUtils.getTaskFile(project, file);
|
||||
if (myTaskFile != null) {
|
||||
final Task currentTask = myTaskFile.getTask();
|
||||
final String taskText = currentTask.getText();
|
||||
//initializeTaskText(studyPanel, taskText);
|
||||
final JPanel studyButtonPanel = new JPanel(new GridLayout(1, 2));
|
||||
final JPanel taskActionsPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
|
||||
studyButtonPanel.add(taskActionsPanel);
|
||||
studyButtonPanel.add(new JPanel());
|
||||
initializeButtons(taskActionsPanel, myTaskFile);
|
||||
studyPanel.add(studyButtonPanel);
|
||||
myComponent.add(studyPanel, BorderLayout.NORTH);
|
||||
}
|
||||
}
|
||||
|
||||
class CopyListener extends MouseAdapter {
|
||||
final JTextPane myTextPane;
|
||||
|
||||
public CopyListener(@NotNull final JTextPane textPane) {
|
||||
myTextPane = textPane;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseReleased(MouseEvent e) {
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final ToolWindow projectView = ToolWindowManager.getInstance(myProject).getToolWindow(ToolWindowId.PROJECT_VIEW);
|
||||
if (projectView == null) {
|
||||
return;
|
||||
}
|
||||
final Component focusComponent = projectView.getComponent();
|
||||
IdeFocusManager.getInstance(myProject).requestFocus(focusComponent, true);
|
||||
final String text = myTextPane.getSelectedText();
|
||||
if (text == null) {
|
||||
return;
|
||||
}
|
||||
KeyAdapter keyAdapter = new KeyAdapter() {
|
||||
@Override
|
||||
public void keyPressed(KeyEvent ev) {
|
||||
if (ev.getKeyCode() == KeyEvent.VK_C
|
||||
&& ev.getModifiers() == InputEvent.CTRL_MASK) {
|
||||
final StringSelection selection = new StringSelection(text);
|
||||
Toolkit.getDefaultToolkit().getSystemClipboard().setContents(selection, EmptyClipboardOwner.INSTANCE);
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
IdeFocusManager.getInstance(myProject).requestFocus(myDefaultEditor.getComponent(), true);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
focusComponent.addKeyListener(keyAdapter);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeTaskText(@NotNull final JPanel studyPanel, @Nullable final String taskText) {
|
||||
final JTextPane taskTextPane = new JTextPane();
|
||||
taskTextPane.addMouseListener(new CopyListener(taskTextPane));
|
||||
taskTextPane.setContentType("text/html");
|
||||
taskTextPane.setEditable(false);
|
||||
taskTextPane.setText(taskText);
|
||||
taskTextPane.addHyperlinkListener(BrowserHyperlinkListener.INSTANCE);
|
||||
final EditorColorsScheme editorColorsScheme = EditorColorsManager.getInstance().getGlobalScheme();
|
||||
int fontSize = editorColorsScheme.getEditorFontSize();
|
||||
final String fontName = editorColorsScheme.getEditorFontName();
|
||||
setJTextPaneFont(taskTextPane, new Font(fontName, Font.PLAIN, fontSize));
|
||||
taskTextPane.setBackground(UIUtil.getPanelBackground());
|
||||
taskTextPane.setBorder(new EmptyBorder(15, 20, 0, 100));
|
||||
final HideableTitledPanel taskTextPanel = new HideableTitledPanel(TASK_TEXT_HEADER, taskTextPane, true);
|
||||
taskTextPanel.setBorder(new EmptyBorder(10, 10, 10, 10));
|
||||
studyPanel.add(taskTextPanel);
|
||||
}
|
||||
|
||||
private static void setJTextPaneFont(@NotNull final JTextPane textPane, @NotNull final Font font) {
|
||||
final MutableAttributeSet attrs = textPane.getInputAttributes();
|
||||
StyleConstants.setFontFamily(attrs, font.getFamily());
|
||||
StyleConstants.setFontSize(attrs, font.getSize());
|
||||
StyleConstants.setItalic(attrs, (font.getStyle() & Font.ITALIC) != 0);
|
||||
StyleConstants.setBold(attrs, (font.getStyle() & Font.BOLD) != 0);
|
||||
StyleConstants.setForeground(attrs, JBColor.BLACK);
|
||||
StyledDocument doc = textPane.getStyledDocument();
|
||||
doc.setCharacterAttributes(0, doc.getLength() + 1, attrs, false);
|
||||
}
|
||||
|
||||
private void initializeButtons(@NotNull final JPanel taskActionsPanel, @NotNull final TaskFile taskFile) {
|
||||
myCheckButton = addButton(taskActionsPanel, StudyCheckAction.ACTION_ID, InteractiveLearningIcons.Resolve, StudyCheckAction.SHORTCUT);
|
||||
myPrevTaskButton = addButton(taskActionsPanel, StudyPreviousStudyTaskAction.ACTION_ID, InteractiveLearningIcons.Prev, StudyPreviousStudyTaskAction.SHORTCUT);
|
||||
myNextTaskButton = addButton(taskActionsPanel, StudyNextStudyTaskAction.ACTION_ID, AllIcons.Actions.Forward, StudyNextStudyTaskAction.SHORTCUT);
|
||||
myRefreshButton = addButton(taskActionsPanel, StudyRefreshTaskFileAction.ACTION_ID, AllIcons.Actions.Refresh, StudyRefreshTaskFileAction.SHORTCUT);
|
||||
final JButton myShowHintButton = addButton(taskActionsPanel, StudyShowHintAction.ACTION_ID, InteractiveLearningIcons.ShowHint, StudyShowHintAction.SHORTCUT);
|
||||
final List<UserTest> userTests = StudyTaskManager.getInstance(myProject).getUserTests(taskFile.getTask());
|
||||
if (!userTests.isEmpty()) {
|
||||
final JButton runButton = addButton(taskActionsPanel, StudyRunAction.ACTION_ID, AllIcons.General.Run, null);
|
||||
runButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
StudyRunAction studyRunAction = (StudyRunAction)ActionManager.getInstance().getAction("StudyRunAction");
|
||||
studyRunAction.run(myProject);
|
||||
}
|
||||
});
|
||||
final JButton watchInputButton = addButton(taskActionsPanel, "WatchInputAction", InteractiveLearningIcons.WatchInput, null);
|
||||
watchInputButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
StudyEditInputAction studyEditInputAction =
|
||||
(StudyEditInputAction)ActionManager.getInstance().getAction("WatchInputAction");
|
||||
studyEditInputAction.showInput(myProject);
|
||||
}
|
||||
});
|
||||
}
|
||||
initializeButtonActions(myShowHintButton);
|
||||
}
|
||||
|
||||
protected void initializeButtonActions(JButton myShowHintButton) {
|
||||
myCheckButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
StudyCheckAction studyCheckAction = (StudyCheckAction)ActionManager.getInstance().getAction("CheckAction");
|
||||
studyCheckAction.check(myProject);
|
||||
}
|
||||
});
|
||||
|
||||
myNextTaskButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
StudyNextStudyTaskAction studyNextTaskAction =
|
||||
(StudyNextStudyTaskAction)ActionManager.getInstance().getAction("NextTaskAction");
|
||||
studyNextTaskAction.navigateTask(myProject);
|
||||
}
|
||||
});
|
||||
myPrevTaskButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
StudyPreviousStudyTaskAction
|
||||
prevTaskAction = (StudyPreviousStudyTaskAction)ActionManager.getInstance().getAction("PreviousTaskAction");
|
||||
prevTaskAction.navigateTask(myProject);
|
||||
}
|
||||
});
|
||||
myRefreshButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
StudyRefreshTaskFileAction.refresh(myProject);
|
||||
}
|
||||
});
|
||||
|
||||
myShowHintButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
StudyShowHintAction.showHint(myProject);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public JButton getNextTaskButton() {
|
||||
return myNextTaskButton;
|
||||
}
|
||||
|
||||
public JButton getRefreshButton() {
|
||||
return myRefreshButton;
|
||||
}
|
||||
|
||||
private FileEditor getDefaultEditor() {
|
||||
return myDefaultEditor;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JComponent getComponent() {
|
||||
return myComponent;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public JComponent getPreferredFocusedComponent() {
|
||||
return myDefaultEditor.getPreferredFocusedComponent();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Study Editor";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public FileEditorState getState(@NotNull FileEditorStateLevel level) {
|
||||
return myDefaultEditor.getState(level);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setState(@NotNull FileEditorState state) {
|
||||
myDefaultEditor.setState(state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isModified() {
|
||||
return myDefaultEditor.isModified();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
return myDefaultEditor.isValid();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectNotify() {
|
||||
myDefaultEditor.selectNotify();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deselectNotify() {
|
||||
myDefaultEditor.deselectNotify();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addPropertyChangeListener(@NotNull PropertyChangeListener listener) {
|
||||
myDefaultEditor.addPropertyChangeListener(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removePropertyChangeListener(@NotNull PropertyChangeListener listener) {
|
||||
myDefaultEditor.removePropertyChangeListener(listener);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BackgroundEditorHighlighter getBackgroundHighlighter() {
|
||||
return myDefaultEditor.getBackgroundHighlighter();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public FileEditorLocation getCurrentLocation() {
|
||||
return myDefaultEditor.getCurrentLocation();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public StructureViewBuilder getStructureViewBuilder() {
|
||||
return myDefaultEditor.getStructureViewBuilder();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
Disposer.dispose(myDefaultEditor);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public <T> T getUserData(@NotNull Key<T> key) {
|
||||
return myDefaultEditor.getUserData(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void putUserData(@NotNull Key<T> key, @Nullable T value) {
|
||||
myDefaultEditor.putUserData(key, value);
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
public static StudyEditor getSelectedStudyEditor(@NotNull final Project project) {
|
||||
try {
|
||||
final FileEditor fileEditor = FileEditorManagerEx.getInstanceEx(project).getSplitters().getCurrentWindow().
|
||||
getSelectedEditor().getSelectedEditorWithProvider().getFirst();
|
||||
if (fileEditor instanceof StudyEditor) {
|
||||
return (StudyEditor)fileEditor;
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static Editor getSelectedEditor(@NotNull final Project project) {
|
||||
final StudyEditor studyEditor = getSelectedStudyEditor(project);
|
||||
if (studyEditor != null) {
|
||||
FileEditor defaultEditor = studyEditor.getDefaultEditor();
|
||||
if (defaultEditor instanceof PsiAwareTextEditorImpl) {
|
||||
return ((PsiAwareTextEditorImpl)defaultEditor).getEditor();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void removeListener(Document document) {
|
||||
@@ -409,48 +42,4 @@ public class StudyEditor implements TextEditor {
|
||||
}
|
||||
myDocumentListeners.remove(document);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Editor getEditor() {
|
||||
if (myDefaultEditor instanceof TextEditor) {
|
||||
return ((TextEditor)myDefaultEditor).getEditor();
|
||||
}
|
||||
return EditorFactory.getInstance().createViewer(new DocumentImpl(""), myProject);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canNavigateTo(@NotNull Navigatable navigatable) {
|
||||
if (myDefaultEditor instanceof TextEditor) {
|
||||
((TextEditor)myDefaultEditor).canNavigateTo(navigatable);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void navigateTo(@NotNull Navigatable navigatable) {
|
||||
if (myDefaultEditor instanceof TextEditor) {
|
||||
((TextEditor)myDefaultEditor).navigateTo(navigatable);
|
||||
}
|
||||
}
|
||||
|
||||
public static void deleteGuardedBlocks(@NotNull final Document document) {
|
||||
if (document instanceof DocumentImpl) {
|
||||
final DocumentImpl documentImpl = (DocumentImpl)document;
|
||||
List<RangeMarker> blocks = documentImpl.getGuardedBlocks();
|
||||
for (final RangeMarker block : blocks) {
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
document.removeGuardedBlock(block);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+10
@@ -9,11 +9,14 @@ 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 com.intellij.openapi.wm.ToolWindow;
|
||||
import com.intellij.openapi.wm.ToolWindowManager;
|
||||
import com.intellij.problems.WolfTheProblemSolver;
|
||||
import com.jetbrains.edu.EduDocumentListener;
|
||||
import com.jetbrains.edu.courseFormat.TaskFile;
|
||||
import com.jetbrains.edu.learning.StudyUtils;
|
||||
import com.jetbrains.edu.learning.navigation.StudyNavigator;
|
||||
import com.jetbrains.edu.learning.ui.StudyToolWindowFactory;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
|
||||
@@ -43,6 +46,13 @@ public class StudyEditorFactoryListener implements EditorFactoryListener {
|
||||
StudyEditor.addDocumentListener(document, new EduDocumentListener(taskFile));
|
||||
WolfTheProblemSolver.getInstance(project).clearProblems(openedFile);
|
||||
StudyUtils.drawAllWindows(editor, taskFile);
|
||||
|
||||
final ToolWindow studyToolWindow = ToolWindowManager.getInstance(project).getToolWindow(StudyToolWindowFactory.STUDY_TOOL_WINDOW);
|
||||
if (studyToolWindow != null) {
|
||||
StudyUtils.updateStudyToolWindow(project);
|
||||
studyToolWindow.show(null);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-11
@@ -1,26 +1,15 @@
|
||||
package com.jetbrains.edu.learning.ui;
|
||||
|
||||
import com.intellij.openapi.project.DumbAware;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.jetbrains.edu.learning.StudyTaskManager;
|
||||
|
||||
/**
|
||||
* author: liana
|
||||
* data: 7/29/14.
|
||||
*/
|
||||
public class StudyCondition implements Condition, DumbAware {
|
||||
public static boolean VALUE = false;
|
||||
@Override
|
||||
public boolean value(Object o) {
|
||||
if (o instanceof Project) {
|
||||
Project project = (Project) o;
|
||||
StudyTaskManager taskManager = StudyTaskManager.getInstance(project);
|
||||
if (taskManager.getCourse() != null) {
|
||||
//noinspection AssignmentToStaticFieldFromInstanceMethod
|
||||
VALUE = true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
+136
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.jetbrains.edu.learning.ui;
|
||||
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.actionSystem.ActionManager;
|
||||
import com.intellij.openapi.actionSystem.ActionToolbar;
|
||||
import com.intellij.openapi.actionSystem.DataProvider;
|
||||
import com.intellij.openapi.actionSystem.DefaultActionGroup;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsManager;
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager;
|
||||
import com.intellij.openapi.fileEditor.FileEditorManagerEvent;
|
||||
import com.intellij.openapi.fileEditor.FileEditorManagerListener;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.SimpleToolWindowPanel;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.ui.BrowserHyperlinkListener;
|
||||
import com.intellij.util.ui.JBUI;
|
||||
import com.jetbrains.edu.courseFormat.Task;
|
||||
import com.jetbrains.edu.courseFormat.TaskFile;
|
||||
import com.jetbrains.edu.learning.StudyUtils;
|
||||
import com.jetbrains.edu.learning.actions.*;
|
||||
import com.jetbrains.edu.learning.editor.StudyEditor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
|
||||
public class StudyToolWindow extends SimpleToolWindowPanel implements DataProvider, Disposable {
|
||||
|
||||
public StudyToolWindow(final Project project) {
|
||||
super(true, true);
|
||||
JPanel toolbarPanel = createToolbarPanel();
|
||||
setToolbar(toolbarPanel);
|
||||
|
||||
final StudyEditor studyEditor = StudyUtils.getSelectedStudyEditor(project);
|
||||
if (studyEditor == null) return;
|
||||
Task task = studyEditor.getTaskFile().getTask();
|
||||
|
||||
if (task != null) {
|
||||
final String taskText = task.getText();
|
||||
|
||||
final JTextPane taskTextPane = new JTextPane();
|
||||
taskTextPane.setContentType("text/html");
|
||||
taskTextPane.setEditable(false);
|
||||
taskTextPane.setText(taskText);
|
||||
taskTextPane.addHyperlinkListener(BrowserHyperlinkListener.INSTANCE);
|
||||
taskTextPane.setBackground(EditorColorsManager.getInstance().getGlobalScheme().getDefaultBackground());
|
||||
taskTextPane.setBorder(new EmptyBorder(15, 20, 0, 100));
|
||||
setContent(taskTextPane);
|
||||
|
||||
final FileEditorManagerListener listener = new StudyFileEditorManagerListener(project, taskTextPane);
|
||||
project.getMessageBus().connect().subscribe(FileEditorManagerListener.FILE_EDITOR_MANAGER, listener);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
}
|
||||
|
||||
private static JPanel createToolbarPanel() {
|
||||
final DefaultActionGroup group = new DefaultActionGroup();
|
||||
group.add(new StudyCheckAction());
|
||||
group.add(new StudyPreviousStudyTaskAction());
|
||||
group.add(new StudyNextStudyTaskAction());
|
||||
group.add(new StudyRefreshTaskFileAction());
|
||||
group.add(new StudyShowHintAction());
|
||||
|
||||
group.add(new StudyRunAction());
|
||||
group.add(new StudyEditInputAction());
|
||||
|
||||
final ActionToolbar actionToolBar = ActionManager.getInstance().createActionToolbar("Study", group, true);
|
||||
return JBUI.Panels.simplePanel(actionToolBar.getComponent());
|
||||
}
|
||||
|
||||
static class StudyFileEditorManagerListener implements FileEditorManagerListener {
|
||||
private Project myProject;
|
||||
private JTextPane myTaskTextPane;
|
||||
|
||||
StudyFileEditorManagerListener(@NotNull final Project project, JTextPane taskTextPane){
|
||||
myProject = project;
|
||||
myTaskTextPane = taskTextPane;
|
||||
}
|
||||
@Override
|
||||
public void fileOpened (@NotNull FileEditorManager source, @NotNull VirtualFile file){
|
||||
Task task = getTask(file);
|
||||
setTaskText(task);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fileClosed (@NotNull FileEditorManager source, @NotNull VirtualFile file){
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectionChanged (@NotNull FileEditorManagerEvent event){
|
||||
VirtualFile file = event.getNewFile();
|
||||
if (file != null) {
|
||||
Task task = getTask(file);
|
||||
setTaskText(task);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Task getTask (@NotNull VirtualFile file){
|
||||
TaskFile taskFile = StudyUtils.getTaskFile(myProject, file);
|
||||
if (taskFile != null) {
|
||||
return taskFile.getTask();
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void setTaskText(@Nullable final Task task) {
|
||||
if (task == null) {
|
||||
return;
|
||||
}
|
||||
String text = task.getText();
|
||||
myTaskTextPane.setText(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
+10
-69
@@ -2,90 +2,31 @@ package com.jetbrains.edu.learning.ui;
|
||||
|
||||
import com.intellij.openapi.project.DumbAware;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.wm.ToolWindow;
|
||||
import com.intellij.openapi.wm.ToolWindowFactory;
|
||||
import com.intellij.ui.content.Content;
|
||||
import com.intellij.ui.content.ContentFactory;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.intellij.ui.content.ContentManager;
|
||||
import com.jetbrains.edu.courseFormat.Course;
|
||||
import com.jetbrains.edu.courseFormat.Lesson;
|
||||
import com.jetbrains.edu.courseFormat.Task;
|
||||
import com.jetbrains.edu.learning.StudyTaskManager;
|
||||
import com.jetbrains.edu.learning.courseFormat.StudyStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.util.List;
|
||||
|
||||
public class StudyToolWindowFactory implements ToolWindowFactory, DumbAware {
|
||||
public static final String STUDY_TOOL_WINDOW = "Course Description";
|
||||
public static final String STUDY_TOOL_WINDOW = "Task Description";
|
||||
|
||||
|
||||
@Override
|
||||
public void createToolWindowContent(@NotNull final Project project, @NotNull final ToolWindow toolWindow) {
|
||||
JPanel contentPanel = new JPanel();
|
||||
StudyTaskManager taskManager = StudyTaskManager.getInstance(project);
|
||||
if (taskManager.getCourse() != null) {
|
||||
contentPanel.setLayout(new BoxLayout(contentPanel, BoxLayout.PAGE_AXIS));
|
||||
contentPanel.add(Box.createRigidArea(new Dimension(10, 0)));
|
||||
final Course course = taskManager.getCourse();
|
||||
if (course != null) {
|
||||
final StudyToolWindow studyToolWindow = new StudyToolWindow(project);
|
||||
final ContentManager contentManager = toolWindow.getContentManager();
|
||||
final Content content = contentManager.getFactory().createContent(studyToolWindow, null, false);
|
||||
contentManager.addContent(content);
|
||||
Disposer.register(project, studyToolWindow);
|
||||
|
||||
Course course = taskManager.getCourse();
|
||||
if (course == null) {
|
||||
return;
|
||||
}
|
||||
String courseName = UIUtil.toHtml("<h1>" + course.getName() + "</h1>", 10);
|
||||
String description = UIUtil.toHtml(course.getDescription(), 5);
|
||||
String authorLabel = UIUtil.toHtml("<b>Author: </b>" + Course.getAuthorsString(course.getAuthors()), 5);
|
||||
contentPanel.add(new JLabel(courseName));
|
||||
contentPanel.add(new JLabel(authorLabel));
|
||||
contentPanel.add(Box.createRigidArea(new Dimension(0, 10)));
|
||||
contentPanel.add(new JLabel(description));
|
||||
contentPanel.add(Box.createRigidArea(new Dimension(0, 10)));
|
||||
int taskNum = 0;
|
||||
int taskSolved = 0;
|
||||
int lessonsCompleted = 0;
|
||||
List<Lesson> lessons = course.getLessons();
|
||||
for (Lesson lesson : lessons) {
|
||||
StudyStatus status = taskManager.getStatus(lesson);
|
||||
if (status == StudyStatus.Solved) {
|
||||
lessonsCompleted++;
|
||||
}
|
||||
taskNum += lesson.getTaskList().size();
|
||||
taskSolved += getSolvedTasks(lesson, taskManager);
|
||||
}
|
||||
String completedLessons = String.format("%d of %d lessons completed", lessonsCompleted, course.getLessons().size());
|
||||
String completedTasks = String.format("%d of %d tasks completed", taskSolved, taskNum);
|
||||
String tasksLeft = String.format("%d of %d tasks left", taskNum - taskSolved, taskNum);
|
||||
contentPanel.add(Box.createVerticalStrut(10));
|
||||
addStatistics(completedLessons, contentPanel);
|
||||
addStatistics(completedTasks, contentPanel);
|
||||
|
||||
double percent = (taskSolved * 100.0) / taskNum;
|
||||
contentPanel.add(Box.createRigidArea(new Dimension(0, 10)));
|
||||
StudyProgressBar studyProgressBar = new StudyProgressBar(percent / 100, 40, 10);
|
||||
contentPanel.add(studyProgressBar);
|
||||
addStatistics(tasksLeft, contentPanel);
|
||||
ContentFactory contentFactory = ContentFactory.SERVICE.getInstance();
|
||||
Content content = contentFactory.createContent(contentPanel, "", true);
|
||||
toolWindow.getContentManager().addContent(content);
|
||||
}
|
||||
}
|
||||
|
||||
private static int getSolvedTasks(@NotNull final Lesson lesson, StudyTaskManager taskManager) {
|
||||
int solved = 0;
|
||||
for (Task task : lesson.getTaskList()) {
|
||||
if (taskManager.getStatus(task) == StudyStatus.Solved) {
|
||||
solved += 1;
|
||||
}
|
||||
}
|
||||
return solved;
|
||||
}
|
||||
|
||||
private static void addStatistics(String statistics, JPanel contentPanel) {
|
||||
String labelText = UIUtil.toHtml(statistics, 5);
|
||||
contentPanel.add(Box.createRigidArea(new Dimension(0, 10)));
|
||||
JLabel statisticLabel = new JLabel(labelText);
|
||||
contentPanel.add(statisticLabel);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,10 +16,8 @@
|
||||
package com.jetbrains.python.fixtures;
|
||||
|
||||
import com.intellij.openapi.application.PathManager;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleType;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.roots.ContentEntry;
|
||||
import com.intellij.openapi.roots.ModifiableRootModel;
|
||||
import com.intellij.openapi.roots.OrderRootType;
|
||||
import com.intellij.openapi.roots.libraries.Library;
|
||||
@@ -34,7 +32,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
* Project descriptor (extracted from {@link com.jetbrains.python.fixtures.PyTestCase}) and should be used with it.
|
||||
* @author Ilya.Kazakevich
|
||||
*/
|
||||
public class PyLightProjectDescriptor implements LightProjectDescriptor {
|
||||
public class PyLightProjectDescriptor extends LightProjectDescriptor {
|
||||
private final String myPythonVersion;
|
||||
|
||||
public PyLightProjectDescriptor(String pythonVersion) {
|
||||
@@ -52,10 +50,6 @@ public class PyLightProjectDescriptor implements LightProjectDescriptor {
|
||||
return PythonMockSdk.findOrCreate(myPythonVersion);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configureModule(@NotNull Module module, @NotNull ModifiableRootModel model, @NotNull ContentEntry contentEntry) {
|
||||
}
|
||||
|
||||
protected void createLibrary(ModifiableRootModel model, final String name, final String path) {
|
||||
final Library.ModifiableModel modifiableModel = model.getModuleLibraryTable().createLibrary(name).getModifiableModel();
|
||||
final VirtualFile home =
|
||||
|
||||
Reference in New Issue
Block a user