Skip to content

Commit

Permalink
assessment buttons, links between highlighters & table entries, bette…
Browse files Browse the repository at this point in the history
…r workflow
  • Loading branch information
Feuermagier committed Sep 13, 2024
1 parent 70b7685 commit e446d66
Show file tree
Hide file tree
Showing 20 changed files with 645 additions and 1,324 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package edu.kit.kastel.extensions.guis;

import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
import com.intellij.openapi.ui.SimpleToolWindowPanel;
import com.intellij.ui.ScrollPaneFactory;
import com.intellij.ui.table.JBTable;
import edu.kit.kastel.state.PluginState;
import edu.kit.kastel.utils.EditorUtil;

import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Arrays;

public class AnnotationsListPanel extends SimpleToolWindowPanel {
private JBTable table;
private AnnotationsTableModel model;

public AnnotationsListPanel() {
super(true, true);

model = new AnnotationsTableModel();
table = new JBTable(model);
setContent(ScrollPaneFactory.createScrollPane(table));

table.addKeyListener(new KeyAdapter() {
@Override
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_DELETE) {
// First collect all annotations to delete, then delete them
// If delete them one by one, the row indices change and the wrong annotations are deleted
var annotationsToDelete = Arrays.stream(table.getSelectedRows())
.filter(row -> row >= 0)
.mapToObj(model::get)
.toList();

var assessment = PluginState.getInstance().getActiveAssessment().orElseThrow();
for (var annotation : annotationsToDelete) {
assessment.deleteAnnotation(annotation);
}
}
}
});
table.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
int row = table.rowAtPoint(e.getPoint());
if (e.getClickCount() == 2 && row >= 0) {
var annotation = model.get(row);

var file = EditorUtil.getAnnotationFile(annotation);
var document = FileDocumentManager.getInstance().getDocument(file);
int offset = document.getLineStartOffset(annotation.getStartLine());
FileEditorManager.getInstance(EditorUtil.getActiveProject()).openTextEditor(
new OpenFileDescriptor(EditorUtil.getActiveProject(), file, offset),
true);
}
}
});

PluginState.getInstance()
.registerAssessmentStartedListener(
assessment -> assessment.registerAnnotationsUpdatedListener(annotations -> {
AnnotationsTableModel model = ((AnnotationsTableModel) table.getModel());
model.setAnnotations(annotations);
table.updateUI();
}));

PluginState.getInstance().registerAssessmentClosedListener(() -> {
AnnotationsTableModel model = ((AnnotationsTableModel) table.getModel());
model.clearAnnotations();
table.updateUI();
});
}
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
/* Licensed under EPL-2.0 2024. */
package edu.kit.kastel.extensions.guis;

import com.intellij.DynamicBundle;
import edu.kit.kastel.sdq.artemis4j.grading.Annotation;

import javax.swing.table.AbstractTableModel;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import javax.swing.table.AbstractTableModel;

import com.intellij.DynamicBundle;
import edu.kit.kastel.sdq.artemis4j.grading.Annotation;
import edu.kit.kastel.state.PluginState;

/**
* The table model for the annotations table.
*/
Expand Down Expand Up @@ -68,9 +66,8 @@ public void clearAnnotations() {
this.annotations.clear();
}

public void deleteItem(int itemIndex) {
Annotation annotation = this.annotations.get(itemIndex);
PluginState.getInstance().getActiveAssessment().orElseThrow().deleteAnnotation(annotation);
public Annotation get(int index) {
return annotations.get(index);
}

private String formatLines(Annotation annotation) {
Expand Down

This file was deleted.

This file was deleted.

111 changes: 111 additions & 0 deletions src/main/java/edu/kit/kastel/extensions/guis/AssessmentPanel.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
package edu.kit.kastel.extensions.guis;

import com.intellij.DynamicBundle;
import com.intellij.openapi.ui.SimpleToolWindowPanel;
import com.intellij.ui.JBColor;
import com.intellij.ui.ScrollPaneFactory;
import com.intellij.ui.components.JBLabel;
import com.intellij.ui.components.JBPanel;
import com.intellij.util.ui.JBFont;
import edu.kit.kastel.extensions.settings.ArtemisSettingsState;
import edu.kit.kastel.sdq.artemis4j.grading.penalty.MistakeType;
import edu.kit.kastel.sdq.artemis4j.grading.penalty.RatingGroup;
import edu.kit.kastel.state.ActiveAssessment;
import edu.kit.kastel.state.PluginState;
import net.miginfocom.swing.MigLayout;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.border.TitledBorder;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.util.IdentityHashMap;
import java.util.Locale;
import java.util.Map;

public class AssessmentPanel extends SimpleToolWindowPanel {
private static final Locale LOCALE = DynamicBundle.getLocale();

private final JPanel content;
private final Map<RatingGroup, TitledBorder> ratingGroupBorders = new IdentityHashMap<>();
private final Map<MistakeType, JButton> mistakeTypeButtons = new IdentityHashMap<>();

public AssessmentPanel() {
super(true, true);

content = new JBPanel<>(new MigLayout("wrap 1", "[grow]"));
setContent(ScrollPaneFactory.createScrollPane(content));

this.showNoActiveAssessment();
PluginState.getInstance().registerAssessmentStartedListener(this::createMistakeButtons);
PluginState.getInstance().registerAssessmentClosedListener(this::showNoActiveAssessment);
}

private void createMistakeButtons(ActiveAssessment assessment) {
content.removeAll();

int buttonsPerRow = ArtemisSettingsState.getInstance().getColumnsPerRatingGroup();
for (var ratingGroup : assessment.getGradingConfig().getRatingGroups()) {
if (ratingGroup.getMistakeTypes().isEmpty()) {
continue;
}

var panel = new JBPanel<>(new MigLayout("wrap " + buttonsPerRow));

var border = BorderFactory.createTitledBorder(
BorderFactory.createLineBorder(JBColor.border()),
String.format(getRatingGroupTitle(assessment, ratingGroup))
);
border.setTitleFont(JBFont.h3().asBold());
panel.setBorder(border);
this.ratingGroupBorders.put(ratingGroup, border);

for (var mistakeType : ratingGroup.getMistakeTypes()) {
var button = new JButton(mistakeType.getButtonText().translateTo(LOCALE));

if (mistakeType.getReporting().shouldScore()) {
button.setForeground(JBColor.GREEN);
} else {
button.setBackground(JBColor.RED);
}

button.addActionListener(a -> assessment.addAnnotationAtCaret(mistakeType, (a.getModifiers() & ActionEvent.CTRL_MASK) == ActionEvent.CTRL_MASK));
panel.add(button);
this.mistakeTypeButtons.put(mistakeType, button);
}

this.content.add(panel, "growx");
}

assessment.registerAnnotationsUpdatedListener(annotations -> {
// Update rating group titles
for (var entry : this.ratingGroupBorders.entrySet()) {
var ratingGroup = entry.getKey();
var border = entry.getValue();
border.setTitle(getRatingGroupTitle(assessment, ratingGroup));
}
});

this.updateUI();
}

private void showNoActiveAssessment() {
this.ratingGroupBorders.clear();
this.mistakeTypeButtons.clear();

content.removeAll();
content.add(new JBLabel("No active assessment"), "growx");
this.updateUI();
}

private String getRatingGroupTitle(ActiveAssessment assessment, RatingGroup ratingGroup) {
var points = assessment.getAssessment().calculatePointsForRatingGroup(ratingGroup);
return "%s (%.1f of [%.1f, %.1f])".formatted(
ratingGroup.getDisplayName().translateTo(LOCALE),
points.score(),
ratingGroup.getMinPenalty(),
ratingGroup.getMaxPenalty()
);
}
}
Loading

0 comments on commit e446d66

Please sign in to comment.