/*
* Copyright (C) 2015-2017 PÂRIS Quentin
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package org.phoenicis.javafx.views.mainwindow.apps;
import javafx.animation.PauseTransition;
import javafx.application.Platform;
import javafx.beans.binding.Bindings;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.collections.transformation.FilteredList;
import javafx.collections.transformation.SortedList;
import javafx.event.EventHandler;
import javafx.scene.input.MouseEvent;
import javafx.util.Duration;
import org.phoenicis.apps.dto.ApplicationDTO;
import org.phoenicis.apps.dto.CategoryDTO;
import org.phoenicis.apps.dto.ScriptDTO;
import org.phoenicis.javafx.views.common.ExpandedList;
import org.phoenicis.javafx.views.common.ThemeManager;
import org.phoenicis.javafx.views.common.widget.MiniatureListWidget;
import org.phoenicis.javafx.views.mainwindow.MainWindowView;
import org.phoenicis.settings.SettingsManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Comparator;
import java.util.List;
import java.util.function.Consumer;
public class ViewApps extends MainWindowView<ApplicationSideBar> {
private final Logger LOGGER = LoggerFactory.getLogger(ViewApps.class);
private ApplicationSideBar sideBar;
private final MiniatureListWidget<ApplicationDTO> availableApps;
private final ApplicationFilter<ApplicationDTO> filter;
private Consumer<ScriptDTO> onSelectScript = (script) -> {
};
private ObservableList<CategoryDTO> categories;
private FilteredList<CategoryDTO> installableCategories;
private SortedList<CategoryDTO> sortedCategories;
private ObservableList<ApplicationDTO> applications;
private FilteredList<ApplicationDTO> filteredApplications;
private SortedList<ApplicationDTO> sortedApplications;
private PauseTransition pause = new PauseTransition(Duration.seconds(0.5));
public ViewApps(ThemeManager themeManager, SettingsManager settingsManager) {
super("Apps", themeManager);
this.sideBar = new ApplicationSideBar();
this.availableApps = MiniatureListWidget.create(MiniatureListWidget.Element::create,
(element, event) -> showAppDetails(element.getValue(), settingsManager));
// initialising the category lists
this.categories = FXCollections.observableArrayList();
this.installableCategories = this.categories
.filtered(category -> category.getType() == CategoryDTO.CategoryType.INSTALLERS);
this.sortedCategories = this.installableCategories.sorted(Comparator.comparing(CategoryDTO::getName));
// initialising the application lists
this.applications = new ExpandedList<ApplicationDTO, CategoryDTO>(this.installableCategories,
CategoryDTO::getApplications);
this.filteredApplications = new FilteredList<ApplicationDTO>(this.applications);
this.sortedApplications = this.filteredApplications.sorted(Comparator.comparing(ApplicationDTO::getName));
this.filter = new ApplicationFilter<ApplicationDTO>(filteredApplications,
(filterText, application) -> application.getName().toLowerCase().contains(filterText));
// create the bindings between the visual components and the observable lists
this.sideBar.bindCategories(this.sortedCategories);
Bindings.bindContent(this.availableApps.getItems(), this.sortedApplications);
// set the filter event consumers
this.sideBar.setOnFilterTextEnter(this::processFilterText);
this.sideBar.setOnFilterClear(this::clearFilterText);
// set the category selection consumers
this.sideBar.setOnCategorySelection(category -> {
filter.setFilters(category.getApplications()::contains);
showAvailableApps();
});
this.sideBar.setOnAllCategorySelection(() -> {
filter.clearFilters();
showAvailableApps();
});
this.setSideBar(sideBar);
this.showWait();
}
public void setOnSelectScript(Consumer<ScriptDTO> onSelectScript) {
this.onSelectScript = onSelectScript;
}
/**
* Show available apps panel
*/
public void showAvailableApps() {
this.closeDetailsView();
setCenter(availableApps);
}
/**
* Populate with a list of categories containing apps, and then scripts
*
* @param categories CategoryDTO
*/
public void populate(List<CategoryDTO> categories) {
Platform.runLater(() -> {
this.categories.setAll(categories);
this.filter.clearAll();
this.sideBar.selectAllCategories();
this.showAvailableApps();
});
}
public void setOnRetryButtonClicked(EventHandler<? super MouseEvent> event) {
getFailurePanel().getRetryButton().setOnMouseClicked(event);
}
private void showAppDetails(ApplicationDTO application, SettingsManager settingsManager) {
final AppPanel appPanel = new AppPanel(application, themeManager, settingsManager);
appPanel.setOnScriptInstall(this::installScript);
appPanel.setMaxWidth(400);
this.showDetailsView(appPanel);
}
private void installScript(ScriptDTO scriptDTO) {
this.onSelectScript.accept(scriptDTO);
}
private void clearFilterText() {
this.filter.setFilterText("");
this.showAvailableApps();
}
private void processFilterText(String filterText) {
this.pause.setOnFinished(event -> {
String text = filterText.toLowerCase();
if (text != null && text.length() >= 3) {
filter.setFilterText(text);
} else {
filter.setFilterText("");
}
});
this.pause.playFromStart();
this.showAvailableApps();
}
}