package bluej.groupwork.ui;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.SortedSet;
import java.util.TreeSet;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.control.ButtonType;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.ScrollPane.ScrollBarPolicy;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import bluej.Config;
import bluej.collect.DataCollector;
import bluej.groupwork.HistoryInfo;
import bluej.groupwork.LogHistoryListener;
import bluej.groupwork.Repository;
import bluej.groupwork.TeamUtils;
import bluej.groupwork.TeamworkCommand;
import bluej.groupwork.TeamworkCommandResult;
import bluej.pkgmgr.PkgMgrFrame;
import bluej.pkgmgr.Project;
import bluej.utility.DialogManager;
import bluej.utility.FXWorker;
import bluej.utility.javafx.FXCustomizedDialog;
import bluej.utility.javafx.JavaFXUtil;
import threadchecker.OnThread;
import threadchecker.Tag;
| A frame to display the commit history, including dates, users, revisions
| and commit comments.
|
| @author Davin McCall
| @author Amjad Altadmri
|
@OnThread(Tag.FXPlatform)
public class HistoryFrame extends FXCustomizedDialog<Void>{
private Project project;
private HistoryWorker worker;
private List<HistoryInfo> historyInfoList;
private ObservableList<HistoryInfo> listModel = FXCollections.observableArrayList();
private ListView<HistoryInfo> historyList = new ListView<>(listModel);
private ComboBox<String> fileFilterCombo = new ComboBox<>();
private ComboBox<String> userFilterCombo = new ComboBox<>();
private ActivityIndicator activityBar = new ActivityIndicator();
| Create a new HistoryFrame.
|
public HistoryFrame(PkgMgrFrame pmf)
{
super(pmf.getFXWindow(), "team.history.title", "team-history");
project = pmf.getProject();
prepareData();
prepareButtonPane();
getDialogPane().setContent(makeMainPane());
DialogManager.centreDialog(this);
}
| Construct the main pane UI components.
|
private Pane makeMainPane()
{
historyList.setCellFactory(param -> new HistoryCell());
ScrollPane historyPane = new ScrollPane(historyList);
historyPane.setVbarPolicy(ScrollBarPolicy.AS_NEEDED);
historyPane.setFitToWidth(true);
historyPane.setFitToHeight(true);
HBox filterBox = new HBox();
filterBox.setAlignment(Pos.BASELINE_LEFT);
filterBox.getChildren().addAll(new Label(Config.getString("team.history.filefilter") + " "), fileFilterCombo,
new Label(Config.getString("team.history.userfilter") + " "), userFilterCombo,
activityBar);
HBox.setMargin(fileFilterCombo, new Insets(0, 40, 0, 0));
HBox.setMargin(userFilterCombo, new Insets(0, 40, 0, 0));
VBox mainPane = new VBox();
JavaFXUtil.addStyleClass(mainPane, "main-pane");
mainPane.getChildren().addAll(historyPane, filterBox);
VBox.setVgrow(historyPane, Priority.ALWAYS);
return mainPane;
}
| Create the button panel with a Close button
|
private void prepareButtonPane()
{
getDialogPane().getButtonTypes().setAll(ButtonType.CLOSE);
this.setOnCloseRequest(event -> {
if (worker != null) {
worker.abort();
}
});
}
private void prepareData()
{
Repository repository;
if (project.getTeamSettingsController().isDVCS()){
repository = project.getTeamSettingsController().trytoEstablishRepository(false);
}
else {
repository = project.getRepository();
}
if (repository != null) {
worker = new HistoryWorker(repository);
worker.start();
activityBar.setRunning(true);
}
}
| Filter the history info list according to the selected file and user
| filters. The filtered list is then displayed.
|
private void refilter()
{
String user = null;
if (userFilterCombo.getSelectionModel().getSelectedIndex() > 0) {
user = userFilterCombo.getSelectionModel().getSelectedItem();
}
String file = null;
if (fileFilterCombo.getSelectionModel().getSelectedIndex() > 0) {
file = fileFilterCombo.getSelectionModel().getSelectedItem();
}
List<HistoryInfo> displayList;
if (user == null && file == null) {
displayList = historyInfoList;
}
else {
displayList = new ArrayList<>();
for (HistoryInfo info : historyInfoList) {
if (user != null && !info.getUser().equals(user)) {
continue;
}
if (file != null && !historyInfoHasFile(info, file)) {
continue;
}
displayList.add(info);
}
}
listModel.setAll(displayList);
}
| Check whether a history item pertains at all to a particular file
|
private boolean historyInfoHasFile(HistoryInfo info, String file)
{
return Arrays.stream(info.getFiles()).anyMatch(f -> f.equals(file));
}
| Reset the filter boxes (user filter and file filter), adding a complete list
| of all users and files.
|
private void resetFilterBoxes()
{
SortedSet<String> files = new TreeSet<>();
SortedSet<String> users = new TreeSet<>();
for (HistoryInfo info : historyInfoList) {
users.add(info.getUser());
Collections.addAll(files, info.getFiles());
}
fileFilterCombo.getItems().clear();
fileFilterCombo.getItems().add(Config.getString("team.history.allFiles"));
fileFilterCombo.getItems().addAll(files);
fileFilterCombo.getSelectionModel().selectFirst();
fileFilterCombo.setOnAction(e -> refilter());
userFilterCombo.getItems().clear();
userFilterCombo.getItems().add(Config.getString("team.history.allUsers"));
userFilterCombo.getItems().addAll(users);
userFilterCombo.getSelectionModel().selectFirst();
userFilterCombo.setOnAction(e -> refilter());
}
| A worker class to fetch the required information from the repository
| in the background.
|
private class HistoryWorker
extends FXWorker implements LogHistoryListener
{
private List<HistoryInfo> responseList;
private Repository repository;
private TeamworkCommand command;
private TeamworkCommandResult response;
public HistoryWorker(Repository repository)
{
this.responseList = new ArrayList<>();
command = repository.getLogHistory(this);
this.repository = repository;
}
@OnThread(Tag.Worker)
public Object construct()
{
response = command.getResult();
return response;
}
@OnThread(Tag.Any)
public void logInfoAvailable(HistoryInfo hInfo)
{
responseList.add(hInfo);
}
public void finished()
{
if (command != null) {
activityBar.setRunning(false);
command = null;
if (response.isError()) {
HistoryFrame.this.dialogThenHide(() -> TeamUtils.handleServerResponseFX(response, HistoryFrame.this.asWindow()));
}
else {
responseList.sort(new DateCompare());
historyList.setPrefSize(-1, -1);
listModel.setAll(responseList);
historyInfoList = responseList;
resetFilterBoxes();
DataCollector.teamHistoryProject(project, repository);
}
}
}
public void abort()
{
activityBar.setRunning(false);
if (command != null) {
command.cancel();
command = null;
}
}
}
}
| A comparator to sort HistoryInfo objects by date.
|
| @author Davin McCall
|
class DateCompare implements Comparator<HistoryInfo>{
public int compare(HistoryInfo hi0, HistoryInfo hi1)
{
return hi1.getDate().compareTo(hi0.getDate());
}
}
. HistoryFrame
. makeMainPane
. prepareButtonPane
. prepareData
. refilter
. historyInfoHasFile
. resetFilterBoxes
top,
use,
map,
class HistoryWorker
. HistoryWorker
. construct
. logInfoAvailable
. finished
. abort
. compare
310 neLoCode
+ 16 LoComm