EventProcessor.java
package swingtree.threading;
/**
* One of Swing's biggest drawback is that it is single threaded. This means that all
* GUI events are processed on the same thread as the application logic. <br>
* This is problematic for several reasons:
* <ul>
* <li> The GUI is not responsive while the application logic is running.
* For example, if you have a long running task, the GUI will not be updated
* until the task is finished.
* <li> The GUI is not thread safe. If you try to update the GUI from a different thread
* than the GUI thread, you will get an exception.
* <li> The GUI is not decoupled from the application logic. This means that the GUI
* is tightly coupled to the application logic, which makes it hard to test the GUI.
* <li> Using your GUI thread not only for GUI events and rendering but also for application logic,
* will reduce the performance of your application.
* </ul>
*
* Swing-Tree fixes this mess by decoupling the GUI from the application by delegating
* the GUI events to a separate thread.
* This is done through implementations of this {@link EventProcessor} interface.
* <p>
* If you want to do proper decoupling, you can switch to the decoupled event processor like so: <br>
* <pre>{@code
* use(EventProcessor.DECOUPLED, ()->
* UI.panel("fill")
* .add( "shrink", UI.label( "Username:" ) )
* .add( "grow, pushx", UI.textField("User1234..42") )
* .add( label( "Password:" ) )
* .add( "grow, pushx", UI.passwordField("child-birthday") )
* .add( "span",
* UI.button("Login!").onClick( it -> {...} )
* )
* );
* }</pre>
* Note that by default, Swing-Tree uses a simple event processor which does not delegate GUI events to a separate thread.
* So if you want to activate this powerful feature you have to change the event processor. <br>
* See {@link EventProcessor#COUPLED}, {@link EventProcessor#COUPLED_STRICT} and {@link EventProcessor#DECOUPLED}.
*/
public interface EventProcessor
{
/**
* This event processor simply runs the events immediately without caring
* about the thread they are executed on.
* This means that events are executed on the GUI thread, which is the EDT in Swing.
* However, events may also be executed on other threads, which is why this event processor
* is usually used for testing.
* Make sure an application thread is registered through
* {@link DecoupledEventProcessor#join()} at {@link EventProcessor#DECOUPLED}
* when using this processor, otherwise events will not be handled.
*/
EventProcessor COUPLED = new LenientAWTEventProcessor();
/**
* This event processor runs the events immediately on the GUI thread.
* If the current thread is the GUI thread, the events are executed immediately,
* otherwise an exception is thrown, and it's stack trace is printed
* (but the application will not crash).
*/
EventProcessor COUPLED_STRICT = new AWTEventProcessor();
/**
* This event processor makes a distinction between application events and UI events.
* Application events are executed on the application thread, whereas UI events are
* executed on the GUI thread (AWT Event Dispatch Thread).
*/
DecoupledEventProcessor DECOUPLED = DecoupledEventProcessor.INSTANCE();
/**
* Adds the supplied task to an event queue for processing application events.
* The task is executed in the application thread, which may be the GUI thread
* (but shouldn't be if you are doing clean software development).
* This method returns immediately.
*
* @param runnable The task to be executed in the application thread.
*/
void registerAppEvent( Runnable runnable );
/**
* Adds the supplied task to an event queue for processing application events
* and then waits for the task to be processed on the application thread.
* The task is executed in the application thread, which, depending on your implementation,
* may also be the GUI thread (but shouldn't be if you are doing clean software development).
* This method returns when the task has been processed.
*
* @param runnable The task to be executed in the application thread.
*/
void registerAndRunAppEventNow(Runnable runnable);
/**
* Adds the supplied task to an event queue for processing UI events.
* The task is executed in the GUI thread, which is the EDT in Swing.
* This method returns immediately.
*
* @param runnable The task to be executed in the GUI thread.
*/
void registerUIEvent(Runnable runnable);
/**
* Adds the supplied task to an event queue for processing UI events
* and then waits for the task to be processed on the GUI thread.
* The task is executed in the GUI thread, which is the EDT in Swing.
* This method returns when the task has been processed.
*
* @param runnable The task to be executed in the GUI thread.
*/
void registerAndRunUIEventNow(Runnable runnable);
}