package org.peerbox.app.activity;
import java.net.URL;
import java.util.Comparator;
import java.util.ResourceBundle;
import java.util.function.Predicate;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.transformation.FilteredList;
import javafx.collections.transformation.SortedList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.control.TextField;
import javafx.util.Callback;
import javax.swing.SwingUtilities;
import org.peerbox.utils.AppData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.inject.Inject;
/**
* Controller for the Activity View.
* Responsible for filtering and sorting the activity items.
*
* @author albrecht
*
*/
public class ActivityController implements Initializable {
private final static Logger logger = LoggerFactory.getLogger(ActivityController.class);
@FXML
private TextField txtFilter;
@FXML
private ListView<ActivityItem> lstActivityLog;
private final ActivityLogger activityLogger;
@Inject
public ActivityController(final ActivityLogger activityLogger) {
this.activityLogger = activityLogger;
}
@Override
public void initialize(URL location, ResourceBundle resources) {
loadItems();
Platform.runLater(() -> {
// request focus works only after initialization
lstActivityLog.requestFocus();
});
}
/**
* Wires the list view with the items source and configures filtering and sorting of the items.
*/
private void loadItems() {
// filtering -- default show all
FilteredList<ActivityItem> filteredItems = new FilteredList<>(activityLogger.getActivityItems(), p -> true);
txtFilter.textProperty().addListener(new ChangeListener<String>() {
@Override
public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
// filter on predicate
filteredItems.setPredicate(new ActivityItemFilterPredicate(newValue));
}
});
// sorting
SortedList<ActivityItem> sortedItems = new SortedList<>(filteredItems, new ActivityItemTimeComparator());
// set item source
lstActivityLog.setItems(sortedItems);
lstActivityLog
.setCellFactory(new Callback<ListView<ActivityItem>, ListCell<ActivityItem>>() {
@Override
public ListCell<ActivityItem> call(ListView<ActivityItem> param) {
return new ActivityItemCell();
}
});
}
/**
* Clears the activity list view by clearing the underlying list.
*
* @param event that was fired
*/
@FXML
public void clearAction(ActionEvent event) {
activityLogger.clearActivityItems();
logger.debug("Clear activity items.");
}
protected ListView<ActivityItem> getActivityLogListView() {
return lstActivityLog;
}
/**
* Opens the folder in the file browser where the log files are stored.
*
* @param event that was fired
*/
@FXML
public void openLogAction(ActionEvent event) {
Runnable open = new Runnable() {
@Override
public void run() {
try {
java.awt.Desktop.getDesktop().open(AppData.getLogFolder().toFile());
logger.debug("Open log folder... '{}'", AppData.getLogFolder());
} catch (Exception e) {
logger.warn("Could not open log folder: {}", e.getMessage(), e);
}
}
};
// use of swing utilities here because of java.awt.Desktop usage!
SwingUtilities.invokeLater(open);
}
/**
* Filter predicate that matches a filter string on title and description
*/
private class ActivityItemFilterPredicate implements Predicate<ActivityItem> {
/* the filter value */
private final String newValue;
protected ActivityItemFilterPredicate(String newValue) {
this.newValue = newValue;
}
@Override
public boolean test(ActivityItem t) {
if (newValue == null) {
return true;
}
String trimmed = newValue.trim();
if (trimmed.isEmpty()) {
return true;
}
String lower = trimmed.toLowerCase();
boolean match = t.getTitle().toLowerCase().contains(lower)
|| t.getDescription().toLowerCase().contains(lower);
return match;
}
}
/**
* Sorts by time in reverse order, i.e. most recent element first
*/
private class ActivityItemTimeComparator implements Comparator<ActivityItem> {
@Override
public int compare(ActivityItem o1, ActivityItem o2) {
return Long.compare(o2.getTimestamp(), o1.getTimestamp());
}
}
}