package eu.ggnet.saft.core.swing; import java.awt.*; import java.awt.Dialog.ModalityType; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.*; import java.lang.reflect.InvocationTargetException; import java.util.*; import java.util.concurrent.*; import java.util.function.Consumer; import java.util.stream.Collectors; import javax.swing.*; import javafx.stage.Modality; import org.slf4j.LoggerFactory; import eu.ggnet.saft.api.ui.ClosedListener; import eu.ggnet.saft.api.ui.Initialiser; import eu.ggnet.saft.core.all.OkCancelResult; import eu.ggnet.saft.core.all.UiUtil; /** * * @author oliver.guenther */ public class SwingSaft { /** * A simple wrapper for the name generation to discover icons. * The name is build like this: * <ol> * <li>If the referencing class ends with one of {@link IconConfig#VIEW_SUFFIXES} remove that part</li> * <li>Generate name by permuting "Rest of referencing class * name"{@link IconConfig#ICON_SUFFIXES}{@link IconConfig#SIZE_SUFFIXES}{@link IconConfig#FILES}</li> * <li></li> * <li></li> * </ol> */ private final static class IconConfig { private final static java.util.List<String> VIEW_SUFFIXES = Arrays.asList("Controller", "View", "ViewCask"); private final static java.util.List<String> ICON_SUFFIXES = Arrays.asList("Icon"); private final static java.util.List<String> SIZE_SUFFIXES = Arrays.asList("", "_016", "_024", "_032", "_048", "_064", "_128", "_256", "_512"); private final static java.util.List<String> FILES = Arrays.asList(".png", ".jpg", ".gif"); private static Set<String> possibleIcons(Class<?> clazz) { String head = VIEW_SUFFIXES .stream() .filter(s -> clazz.getSimpleName().endsWith(s)) .map(s -> clazz.getSimpleName().substring(0, clazz.getSimpleName().length() - s.length())) .findFirst() .orElse(clazz.getSimpleName()); return ICON_SUFFIXES.stream() .map(e -> head + e) .flatMap(h -> SIZE_SUFFIXES.stream().map(e -> h + e)) .flatMap(h -> FILES.stream().map(e -> h + e)) .collect(Collectors.toCollection(() -> new TreeSet<String>())); } } public static <T, R extends JPanel> R construct(Class<R> panelClazz, T parameter) throws Exception { return dispatch(() -> { R panel = panelClazz.getConstructor().newInstance(); if ( panel instanceof Initialiser ) { ((Initialiser)panel).initialise(); } if ( parameter != null && panel instanceof Consumer ) { try { ((Consumer<T>)panel).accept(parameter); } catch (ClassCastException e) { LoggerFactory.getLogger(SwingSaft.class).warn(panel.getClass() + " implements Consumer, but not of type " + parameter.getClass()); } } return panel; }); } public static <T, R, P extends JComponent> OkCancelResult<R> wrapInChoiceAndShow(Window parent, P panel, Modality modality, R payload) throws ExecutionException, InterruptedException, InvocationTargetException { return dispatch(() -> { OkCancelDialog<P> dialog = new OkCancelDialog<>(parent, panel); dialog.setTitle(UiUtil.title(payload.getClass())); dialog.setModalityType(UiUtil.toSwing(modality).orElse(ModalityType.APPLICATION_MODAL)); dialog.pack(); dialog.setLocationRelativeTo(parent); dialog.setVisible(true); return new OkCancelResult<>(payload, dialog.isOk()); }); } public static <T> T dispatch(Callable<T> callable) throws ExecutionException, InterruptedException, InvocationTargetException { FutureTask<T> task = new FutureTask(callable); if ( EventQueue.isDispatchThread() ) task.run(); else EventQueue.invokeAndWait(task); return task.get(); } public static void execute(Runnable runnable) { if ( EventQueue.isDispatchThread() ) runnable.run(); else try { EventQueue.invokeAndWait(runnable); } catch (InterruptedException | InvocationTargetException ex) { throw new RuntimeException(ex.getClass().getSimpleName() + " in execute:" + ex.getLocalizedMessage(), ex); } } public static void enableCloser(Window window, Object uiElement) { if ( uiElement instanceof ClosedListener ) { window.addWindowListener(new WindowAdapter() { @Override public void windowClosed(WindowEvent e) { ((ClosedListener)uiElement).closed(); } }); } } public static java.util.List<Image> loadIcons(Class<?> reference) throws IOException { Toolkit toolkit = Toolkit.getDefaultToolkit(); return IconConfig.possibleIcons(reference).stream() .map(n -> reference.getResource(n)) .filter(u -> u != null) .map(t -> toolkit.getImage(t)) .collect(Collectors.toList()); } }