/* * Copyright (C) 2014 GG-Net GmbH * * 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 3 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, see <http://www.gnu.org/licenses/>. */ package eu.ggnet.saft.core.ops; import java.util.*; import java.util.concurrent.ForkJoinPool; import java.util.stream.Collectors; import javafx.application.Platform; import javafx.event.EventHandler; import javafx.scene.control.*; import javafx.scene.input.MouseButton; import javafx.scene.input.MouseEvent; import eu.ggnet.saft.api.Accessable; import eu.ggnet.saft.core.Client; import eu.ggnet.saft.core.all.DescriptiveConsumerRunner; import eu.ggnet.saft.core.all.SelectionEnhancer; import eu.ggnet.saft.core.authorisation.Guardian; import eu.ggnet.saft.core.fx.FxSaft; /** * Java Fx features of Ops. * <p> * @author oliver.guenther */ public class FxOps { /** * Returns a EventHandler useful for Lists to active the global default handling. * <p> * @param <T> * @param selectionModel the selection model. * @return a event handler, which will call the default action on double click. */ public static <T> EventHandler<MouseEvent> defaultMouseEventOf(SelectionModel<T> selectionModel) { return (mouseEvent) -> { if ( !selectionModel.isEmpty() && mouseEvent.getButton().equals(MouseButton.PRIMARY) && mouseEvent.getClickCount() == 2 ) { T item = selectionModel.getSelectedItem(); Optional<DescriptiveConsumerRunner<T>> optionalRunner = Ops.defaultOf(item); if ( optionalRunner.isPresent() && authorised(optionalRunner.get()) ) optionalRunner.get().run(); } }; } public static <T> ContextMenu contextMenuOf(SelectionModel<T> selectionModel) { return contextMenuOf(selectionModel, null); } public static <T> ContextMenu contextMenuOf(SelectionModel<T> selectionModel, SelectionEnhancer<T> filter) { ContextMenu menu = FxSaft.dispatch(() -> new ContextMenu()); final MenuItem noAction = new MenuItem("No Context Action"); noAction.setDisable(true); menu.getItems().add(noAction); final List<MenuItem> lastItems = Collections.synchronizedList(new ArrayList<>()); menu.setOnHidden(e -> { menu.getItems().removeAll(lastItems); if ( menu.getItems().isEmpty() ) menu.getItems().add(noAction); }); menu.setOnShowing((ev) -> { if ( selectionModel.isEmpty() ) return; T t = selectionModel.getSelectedItem(); List<DescriptiveConsumerRunner<?>> actions = Ops.staticOf(t, filter); lastItems.clear(); if ( !actions.isEmpty() ) menu.getItems().remove(noAction); List<MenuItem> menuItems = actions .stream() .filter(a -> authorised(a.consumer())) .map(a -> toMenuItem(a)) .collect(Collectors.toList()); // -- Nice, a progress bar for the factories. ProgressIndicator bar = new ProgressIndicator(); bar.setPrefHeight(18); MenuItem progressItem = new CustomMenuItem(bar); menuItems.add(progressItem); lastItems.addAll(menuItems); menu.getItems().addAll(menuItems); bar.prefWidthProperty().bind(menu.getScene().widthProperty().subtract(50)); ForkJoinPool.commonPool().execute(() -> { List<MenuItem> dynamicItems = Ops .dynamicOf(t, filter) .stream() .filter(a -> authorised(a.consumer())) .map(a -> toMenuItem(a)) .collect(Collectors.toList()); Platform.runLater(() -> { if ( !menu.getItems().containsAll(menuItems) ) return; // The menu is all ready invisible again. don't do anything. menu.getItems().remove(progressItem); lastItems.remove(progressItem); bar.prefWidthProperty().unbind(); if ( !dynamicItems.isEmpty() ) menu.getItems().remove(noAction); lastItems.addAll(dynamicItems); menu.getItems().addAll(dynamicItems); }); }); }); return menu; } private static MenuItem toMenuItem(DescriptiveConsumerRunner action) { MenuItem item = new MenuItem(action.title()); item.setOnAction(e -> action.run()); return item; } private static boolean authorised(Object o) { if ( !(o instanceof Accessable) ) return true; // Not even something with rights. if ( !Client.hasFound(Guardian.class) ) return true; // No guardian, rights are ignored. return Client.lookup(Guardian.class).getRights().contains(((Accessable)o).getNeededRight()); } }