Skip to content

Commit

Permalink
Dynamically show ToolWindow after submitting an exercise
Browse files Browse the repository at this point in the history
  • Loading branch information
thepieterdc committed Nov 5, 2019
1 parent 45006e1 commit e381747
Show file tree
Hide file tree
Showing 19 changed files with 219 additions and 67 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,11 @@ public class SubmitAction extends AnAction {
@Override
public void actionPerformed(@NotNull final AnActionEvent e) {
// Get the document.
final Optional<Document> optDocument =
SubmitAction.getDocument(e.getProject());
final Optional<Document> optDocument = getDocument(e.getProject());

// Get the code.
final Optional<String> optCode = optDocument
.flatMap(doc -> SubmitAction.getPsiFile(e.getProject(), doc))
.flatMap(doc -> getPsiFile(e.getProject(), doc))
.map(PsiElement::getText);

// Create a new SubmitTask and execute it.
Expand Down Expand Up @@ -98,8 +97,6 @@ private static Optional<PsiFile> getPsiFile(@Nullable final Project project,

@Override
public void update(@NotNull final AnActionEvent e) {
e.getPresentation().setEnabled(
SubmitAction.getDocument(e.getProject()).isPresent()
);
e.getPresentation().setEnabled(getDocument(e.getProject()).isPresent());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,15 @@
import com.intellij.openapi.components.State;
import com.intellij.openapi.components.Storage;
import com.intellij.openapi.project.Project;
import com.intellij.util.messages.MessageBus;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;

import javax.annotation.Nonnull;
import java.util.Optional;

import static io.github.thepieterdc.dodona.plugin.settings.listeners.ProjectCourseListener.CHANGED_TOPIC;

/**
* Project-specific plugin settings.
*/
Expand All @@ -33,6 +36,17 @@ public class DodonaProjectSettings implements PersistentStateComponent<DodonaPro

private State state = new State();

private final MessageBus bus;

/**
* DodonaProjectSettings constructor.
*
* @param project the current project
*/
public DodonaProjectSettings(final Project project) {
this.bus = project.getMessageBus();
}

/**
* Gets the course id if set.
*
Expand Down Expand Up @@ -72,6 +86,7 @@ public void loadState(@NotNull final State newState) {
*/
public void setCourseId(final long id) {
this.state.course_id = id;
this.bus.syncPublisher(CHANGED_TOPIC).onCourseChanged(id);
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright (c) 2018-2019. All rights reserved.
*
* @author Pieter De Clercq
* @author Tobiah Lissens
*
* https://github.com/thepieterdc/dodona-plugin-jetbrains/
*/

package io.github.thepieterdc.dodona.plugin.settings.listeners;

import com.intellij.util.messages.Topic;

/**
* The course of the project was either set or modified.
*/
@FunctionalInterface
public interface ProjectCourseListener {
Topic<ProjectCourseListener> CHANGED_TOPIC =
Topic.create("Project course changed", ProjectCourseListener.class);

/**
* Called when the course of the project has been set.
*
* @param course the course
*/
void onCourseChanged(Long course);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
* Copyright (c) 2018-2019. All rights reserved.
*
* @author Pieter De Clercq
* @author Tobiah Lissens
*
* https://github.com/thepieterdc/dodona-plugin-jetbrains/
*/

/**
* Listeners for changes in project settings.
*/
@ParametersAreNonnullByDefault
package io.github.thepieterdc.dodona.plugin.settings.listeners;

import javax.annotation.ParametersAreNonnullByDefault;
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import io.github.thepieterdc.dodona.plugin.exercise.identification.IdentificationService;
import io.github.thepieterdc.dodona.plugin.feedback.FeedbackService;
import io.github.thepieterdc.dodona.plugin.notifications.ErrorReporter;
import io.github.thepieterdc.dodona.plugin.settings.DodonaProjectSettings;
import io.github.thepieterdc.dodona.resources.Exercise;
import io.github.thepieterdc.dodona.resources.submissions.Submission;
import org.jetbrains.annotations.NotNull;
Expand All @@ -45,6 +46,7 @@ public class SubmitSolutionTask extends AbstractDodonaBackgroundTask {

private final DodonaExecutor executor;
private final FeedbackService feedback;
private final DodonaProjectSettings projectSettings;

/**
* SubmitSolutionTask constructor.
Expand All @@ -61,6 +63,7 @@ private SubmitSolutionTask(final Project project,
this.executor = DodonaAuthenticator.getInstance().getExecutor();
this.feedback = FeedbackService.getInstance(project);
this.identification = exercise;
this.projectSettings = DodonaProjectSettings.getInstance(project);
}

/**
Expand Down Expand Up @@ -121,23 +124,43 @@ private Submission awaitEvaluation(final ProgressIndicator progress,
/**
* Creates a code submission task from the given code.
*
* @param project the current project
* @param identification the exercise to submit the solution to
* @param code the code to submit
* @return the task
*/
@Nonnull
public static DodonaBackgroundTask create(final Project project,
final Identification identification,
final String code) {
return new SubmitSolutionTask(project, identification, code);
}

/**
* Identifies the exercise and creates a code submission task from the given
* code.
*
* @param project the current project
* @param code the code to submit
* @return the task
*/
@Nonnull
public static DodonaBackgroundTask create(final Project project, final String code) {
public static DodonaBackgroundTask create(final Project project,
final String code) {
// Attempt to identify the exercise, otherwise return a new task to
// perform this job.
return IdentificationService.getInstance()
.identify(code)
.map(result -> new SubmitSolutionTask(project, result, code))
.map(result -> create(project, result, code))
.orElseThrow(RuntimeException::new);
}

@Override
public void run(@NotNull final ProgressIndicator progress) {
try {
// Set the project course if this had not been set yet.
this.identification.getCourse().ifPresent(this.projectSettings::setCourseId);

// Update the progress bar.
progress.setIndeterminate(true);
progress.setText(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,34 @@
* https://github.com/thepieterdc/dodona-plugin-jetbrains/
*/

package io.github.thepieterdc.dodona.plugin.toolwindows;
package io.github.thepieterdc.dodona.plugin.toolwindow;

import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.wm.ToolWindow;
import com.intellij.openapi.wm.ToolWindowFactory;
import io.github.thepieterdc.dodona.plugin.DodonaBundle;
import io.github.thepieterdc.dodona.plugin.Icons;
import io.github.thepieterdc.dodona.plugin.api.DodonaExecutor;
import io.github.thepieterdc.dodona.plugin.authentication.DodonaAuthenticator;
import io.github.thepieterdc.dodona.plugin.settings.DodonaProjectSettings;
import io.github.thepieterdc.dodona.plugin.toolwindows.tabs.DeadlinesTab;
import io.github.thepieterdc.dodona.plugin.toolwindow.tabs.DeadlinesTab;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;

import javax.annotation.Nullable;
import java.util.Optional;

/**
* Creates the tool window.
*/
public class DodonaToolWindowFactory implements DumbAware, ToolWindowFactory {
public class DodonaToolWindowFactory implements Condition<Project>, DumbAware,
ToolWindowFactory {

@NonNls
static final String TOOL_WINDOW_ID = "Dodona";

@Override
public void createToolWindowContent(@NotNull final Project project,
@NotNull final ToolWindow toolWindow) {
Expand All @@ -45,7 +56,19 @@ public void createToolWindowContent(@NotNull final Project project,
settings.getCourseId().orElse(0L)
);

// Set the ToolWindow.
toolWindow.setIcon(Icons.DODONA);
toolWindow.setTitle(DodonaBundle.message("toolwindow.title"));

// Append all tabs to the content.
toolWindow.getContentManager().addContent(deadlines.getContent());
deadlines.setup(toolWindow);
}

@Override
public boolean value(@Nullable final Project project) {
return Optional.ofNullable(project)
.map(DodonaProjectSettings::getInstance)
.flatMap(DodonaProjectSettings::getCourseId)
.isPresent();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* Copyright (c) 2018-2019. All rights reserved.
*
* @author Pieter De Clercq
* @author Tobiah Lissens
*
* https://github.com/thepieterdc/dodona-plugin-jetbrains/
*/

package io.github.thepieterdc.dodona.plugin.toolwindow;

import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.DumbAwareRunnable;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.wm.ToolWindow;
import com.intellij.openapi.wm.ToolWindowAnchor;
import com.intellij.openapi.wm.ToolWindowEP;
import com.intellij.openapi.wm.ToolWindowFactory;
import com.intellij.openapi.wm.ToolWindowManager;
import io.github.thepieterdc.dodona.plugin.settings.listeners.ProjectCourseListener;

/**
* Displays or hides the tool window.
*/
public class ToolWindowSynchronizer {
private final Project project;

/**
* ToolWindowSynchronizer constructor.
*
* @param project the current active project
*/
public ToolWindowSynchronizer(final Project project) {
this.project = project;
this.project.getMessageBus().connect().subscribe(
ProjectCourseListener.CHANGED_TOPIC,
id -> this.update()
);
}

/**
* Updates the state of the ToolWindow visibility.
*/
private void update() {
ApplicationManager.getApplication().invokeLater((DumbAwareRunnable) () -> {
for (final ToolWindowEP ep : ToolWindowEP.EP_NAME.getExtensions()) {
if (DodonaToolWindowFactory.class.isAssignableFrom(ep.getFactoryClass())) {
final ToolWindowFactory factory = ep.getToolWindowFactory();
final ToolWindowManager mgr = ToolWindowManager.getInstance(this.project);
if (mgr.getToolWindow(DodonaToolWindowFactory.TOOL_WINDOW_ID) == null) {
final ToolWindow toolWindow = mgr.registerToolWindow(
DodonaToolWindowFactory.TOOL_WINDOW_ID,
true,
ToolWindowAnchor.RIGHT,
this.project,
false,
true
);
factory.createToolWindowContent(this.project, toolWindow);
}
}
}
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@
* Dodona ToolWindow, shown at the right side of the IDE.
*/
@ParametersAreNonnullByDefault
package io.github.thepieterdc.dodona.plugin.toolwindows;
package io.github.thepieterdc.dodona.plugin.toolwindow;

import javax.annotation.ParametersAreNonnullByDefault;
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@
* https://github.com/thepieterdc/dodona-plugin-jetbrains/
*/

package io.github.thepieterdc.dodona.plugin.toolwindows.tabs;
package io.github.thepieterdc.dodona.plugin.toolwindow.tabs;

import com.intellij.openapi.wm.ToolWindow;
import com.intellij.ui.content.Content;
import com.intellij.ui.content.ContentFactory;
import com.intellij.ui.content.ContentManager;
import org.jetbrains.annotations.Nls;

import javax.annotation.Nonnull;
Expand Down Expand Up @@ -41,14 +42,20 @@ protected AbstractTab(@Nls(capitalization = Nls.Capitalization.Title) final Stri
abstract JComponent createContent();

/**
* Gets the content pane.
* Appends the tab to the tool window.
*
* @return the content pane
* @param toolWindow the tool window
*/
@Nonnull
public Content getContent() {
final Content ret = ContentFactory.SERVICE.getInstance().createContent(this.createContent(), this.title, false);
ret.setCloseable(false);
return ret;
public void setup(final ToolWindow toolWindow) {
final ContentManager contentMgr = toolWindow.getContentManager();

final Content content = contentMgr.getFactory().createContent(
this.createContent(),
this.title,
false
);
content.setCloseable(false);

contentMgr.addContent(content);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@
* https://github.com/thepieterdc/dodona-plugin-jetbrains/
*/

package io.github.thepieterdc.dodona.plugin.toolwindows.tabs;
package io.github.thepieterdc.dodona.plugin.toolwindow.tabs;

import io.github.thepieterdc.dodona.DodonaClient;
import io.github.thepieterdc.dodona.plugin.DodonaBundle;
import io.github.thepieterdc.dodona.plugin.api.DodonaExecutor;
import io.github.thepieterdc.dodona.plugin.toolwindows.ui.deadlines.DeadlinesPanel;
import io.github.thepieterdc.dodona.plugin.toolwindow.ui.deadlines.DeadlinesPanel;
import io.github.thepieterdc.dodona.resources.Course;
import io.github.thepieterdc.dodona.responses.RootResponse;
import org.jetbrains.annotations.NotNull;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@
* Tabs in the tool window.
*/
@ParametersAreNonnullByDefault
package io.github.thepieterdc.dodona.plugin.toolwindows.tabs;
package io.github.thepieterdc.dodona.plugin.toolwindow.tabs;

import javax.annotation.ParametersAreNonnullByDefault;
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@
* https://github.com/thepieterdc/dodona-plugin-jetbrains/
*/

package io.github.thepieterdc.dodona.plugin.toolwindows.ui.deadlines;
package io.github.thepieterdc.dodona.plugin.toolwindow.ui.deadlines;

import com.intellij.util.ui.JBUI;
import com.intellij.util.ui.UIUtil;
import io.github.thepieterdc.dodona.plugin.DodonaBundle;
import io.github.thepieterdc.dodona.plugin.toolwindows.tabs.DeadlinesTab;
import io.github.thepieterdc.dodona.plugin.toolwindow.tabs.DeadlinesTab;
import io.github.thepieterdc.dodona.plugin.ui.AbstractListCellRenderer;
import io.github.thepieterdc.dodona.plugin.ui.util.FontUtils;
import org.jetbrains.annotations.Nls;
Expand Down
Loading

0 comments on commit e381747

Please sign in to comment.