All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.pepsoft.util.AwtUtils Maven / Gradle / Ivy

The newest version!
/*
 * WorldPainter, a graphical and interactive map generator for Minecraft.
 * Copyright © 2011-2015  pepsoft.org, The Netherlands
 *
 * 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 .
 */

package org.pepsoft.util;

import org.pepsoft.util.mdc.MDCCapturingRuntimeException;

import javax.swing.*;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Callable;

/**
 * Utility methods for working with the AWT.
 *
 * Created by pepijn on 16-04-15.
 */
public class AwtUtils {
    /**
     * Execute a task on the event dispatch thread and return the result. The
     * task may be executed on a different thread, so it must be
     * thread-safe. Since it will block the event thread it should be short and
     * to the point.
     *
     * @param task The task to execute.
     * @param  The type of the result to return.
     * @return The result of the task.
     */
    @SuppressWarnings("unchecked") // Responsibility of caller
    public static  T resultOfOnEventThread(final Callable task) {
        if (SwingUtilities.isEventDispatchThread()) {
            try {
                return task.call();
            } catch (Exception e) {
                if (e instanceof RuntimeException) {
                    throw (RuntimeException) e;
                } else {
                    throw new MDCCapturingRuntimeException(e.getClass().getSimpleName() + " thrown by task", e);
                }
            }
        } else {
            final Object[] result = new Object[1];
            final Exception[] exception = new Exception[1];
            try {
                SwingUtilities.invokeAndWait(() -> {
                    try {
                        synchronized (result) {
                            result[0] = task.call();
                        }
                    } catch (Exception e) {
                        synchronized (exception) {
                            exception[0] = e;
                        }
                    }
                });
            } catch (InterruptedException e) {
                throw new MDCCapturingRuntimeException("Thread interrupted while waiting for task to execute on event dispatch thread", e);
            } catch (InvocationTargetException e) {
                Throwable cause = e.getTargetException();
                throw new MDCCapturingRuntimeException(cause.getClass().getSimpleName() + " thrown by task on event dispatch thread", cause);
            }
            synchronized (exception) {
                if (exception[0] != null) {
                    throw new MDCCapturingRuntimeException(exception[0].getClass().getSimpleName() + " thrown by task on event dispatch thread", exception[0]);
                }
            }
            synchronized (result) {
                return (T) result[0];
            }
        }
    }

    /**
     * Execute a task on the even dispatch thread. The task may be
     * executed on a different thread, so it must be thread-safe. Since it will
     * block the event thread it should be short and to the point. If the
     * current thread is not the event dispatch thread this method does
     * not wait for the task to finish.
     *
     * @param task The task to execute.
     */
    public static void doOnEventThread(Runnable task) {
        if (SwingUtilities.isEventDispatchThread()) {
            task.run();
        } else {
            SwingUtilities.invokeLater(task);
        }
    }

    /**
     * Execute a task on the even dispatch thread and wait for it to finish. The
     * task may be executed on a different thread, so it must be
     * thread-safe. Since it will block the event thread it should be short and
     * to the point.
     *
     * @param task The task to execute.
     */
    public static void doOnEventThreadAndWait(Runnable task) {
        if (SwingUtilities.isEventDispatchThread()) {
            task.run();
        } else {
            try {
                SwingUtilities.invokeAndWait(task);
            } catch (InterruptedException e) {
                throw new MDCCapturingRuntimeException("Thread interrupted while waiting for task to execute on event dispatch thread", e);
            } catch (InvocationTargetException e) {
                Throwable cause = e.getTargetException();
                throw new MDCCapturingRuntimeException(cause.getClass().getSimpleName() + " thrown by task on event dispatch thread", cause);
            }
        }
    }

    /**
     * Schedule a task for later execution on the event dispatch thread and return immediately. The task may be
     * executed on a different thread, so it must be thread-safe. Since it will block the event thread it should be
     * short and to the point.
     *
     * @param task The task to execute.
     */
    public static void doLaterOnEventThread(Runnable task) {
        SwingUtilities.invokeLater(task);
    }

    /**
     * Schedule a task for later execution on the event dispatch thread and return immediately. The task may be
     * executed on a different thread, so it must be thread-safe. Since it will block the event thread it should be
     * short and to the point.
     *
     * 

If a task with the same key is already scheduled and has not yet executed that will be superseded. * * @param key The unique key of the task. Scheduling a task will supersede a task with the same key that is already * scheduled. * @param delay The minimum number of milliseconds after which the task should be executed. * @param task The task to execute. */ public static void doLaterOnEventThread(String key, int delay, Runnable task) { doOnEventThreadAndWait(() -> { if (TIMERS.containsKey(key)) { TIMERS.get(key).stop(); TIMERS.remove(key); } Timer timer = new Timer(delay, e -> { task.run(); TIMERS.remove(key); }); timer.setRepeats(false); TIMERS.put(key, timer); timer.start(); }); } private static final Map TIMERS = new HashMap<>(); }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy