/* * 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.common.widget; import javafx.beans.binding.Bindings; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.geometry.Pos; import javafx.scene.CacheHint; import javafx.scene.Node; import javafx.scene.control.Label; import javafx.scene.control.ScrollPane; import javafx.scene.control.Tooltip; import javafx.scene.effect.ColorAdjust; import javafx.scene.image.Image; import javafx.scene.input.MouseEvent; import javafx.scene.layout.FlowPane; import javafx.scene.layout.Pane; import javafx.scene.layout.VBox; import javafx.scene.shape.Rectangle; import org.apache.commons.lang.builder.EqualsBuilder; import org.apache.commons.lang.builder.HashCodeBuilder; import org.phoenicis.apps.dto.ApplicationDTO; import org.phoenicis.containers.dto.ContainerDTO; import org.phoenicis.engines.dto.EngineVersionDTO; import org.phoenicis.javafx.views.common.MappedList; import org.phoenicis.library.dto.ShortcutDTO; import java.io.ByteArrayInputStream; import java.util.List; import java.util.function.BiConsumer; import java.util.function.Function; public final class MiniatureListWidget<E> extends ScrollPane { private final Pane content; private Element selectedItem; private ObservableList<E> items; private ObservableList<Element<E>> mappedElements; private MiniatureListWidget(Pane content, Function<E, Element> converter, BiConsumer<Element<E>, MouseEvent> setOnMouseClicked) { super(content); this.content = content; this.items = FXCollections.observableArrayList(); this.mappedElements = new MappedList<Element<E>, E>(items, value -> { Element newElement = converter.apply(value); newElement.setOnMouseClicked(event -> { unselectAll(); setOnMouseClicked.accept(newElement, event); select(newElement); }); return newElement; }); Bindings.bindContent(content.getChildren(), this.mappedElements); this.getStyleClass().add("rightPane"); this.content.getStyleClass().addAll("miniatureList"); this.getChildren().add(this.content); this.setCache(true); this.setCacheHint(CacheHint.QUALITY); this.content.prefWidthProperty().bind(this.widthProperty()); this.setHbarPolicy(ScrollBarPolicy.NEVER); } /** * Creates a new @class MiniatureListWidget of type @type <T>. * * @param converter A converter function that converts values of type @type T to Element * @param setOnMouseClicked A mouse listener function, that is called whenever a user clicks on an element. * This listener function receives the element, which has been clicked, and the event as parameters * @param <T> The type of items to be added to this MiniatureListWidget * @return */ public static <T> MiniatureListWidget<T> create(Function<T, Element> converter, BiConsumer<Element<T>, MouseEvent> setOnMouseClicked) { return new MiniatureListWidget<T>(new FlowPane(), converter, setOnMouseClicked); } public ObservableList<E> getItems() { return this.items; } public void setItems(List<E> items) { this.items.setAll(items); } public List<Element<E>> getElements() { return this.mappedElements; } public void unselectAll() { getElements().forEach(element -> element.getStyleClass().remove("selected")); this.selectedItem = null; } public void select(Element selectedItem) { selectedItem.getStyleClass().add("selected"); this.selectedItem = selectedItem; } public Element getSelectedItem() { return selectedItem; } public static class Element<E> extends VBox { private final String elementName; private final E value; public Element(E value, String elementName, Node miniature) { super(); this.getStyleClass().add("miniatureListElement"); this.setAlignment(Pos.CENTER); this.elementName = elementName; this.value = value; this.widthProperty().addListener((observable, oldValue, newValue) -> { final Rectangle clip = new Rectangle(this.getWidth(), this.getHeight()); this.setClip(clip); }); this.heightProperty().addListener((observable, oldValue, newValue) -> { final Rectangle clip = new Rectangle(this.getWidth(), this.getHeight()); this.setClip(clip); }); final Label label = new Label(elementName); label.getStyleClass().add("miniatureText"); this.getChildren().add(miniature); this.getChildren().add(label); final Tooltip tooltip = new Tooltip(elementName); Tooltip.install(miniature, tooltip); } public Element(String appsItem, Node miniature) { this(null, appsItem, miniature); } public Element(String elementName) { this(elementName, new StaticMiniature()); } public static Element<ApplicationDTO> create(ApplicationDTO application) { return new Element<ApplicationDTO>(application, application.getName(), application.getMiniatures().isEmpty() ? new StaticMiniature() : new StaticMiniature(application.getMiniatures().get(0))); } public static Element<ContainerDTO> create(ContainerDTO container) { return new Element<ContainerDTO>(container, container.getName(), new StaticMiniature(StaticMiniature.CONTAINER_MINIATURE)); } public static Element<ShortcutDTO> create(ShortcutDTO shortcut) { return new Element<ShortcutDTO>(shortcut, shortcut.getName(), shortcut.getMiniature() == null ? new StaticMiniature() : new StaticMiniature(shortcut.getMiniature())); } public static Element<EngineVersionDTO> create(EngineVersionDTO engineVersion, boolean installed) { Element<EngineVersionDTO> result = new Element<EngineVersionDTO>(engineVersion, engineVersion.getVersion(), new StaticMiniature(StaticMiniature.WINE_MINIATURE)); if (!installed) { ColorAdjust grayscale = new ColorAdjust(); grayscale.setSaturation(-1); result.setEffect(grayscale); } return result; } public E getValue() { return this.value; } public String getName() { return elementName; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } Element<?> that = (Element<?>) o; EqualsBuilder builder = new EqualsBuilder(); builder.append(value, that.value); return builder.isEquals(); } @Override public int hashCode() { HashCodeBuilder builder = new HashCodeBuilder(); builder.append(value); return builder.toHashCode(); } } }