Package org.fest.swing.listener

Source Code of org.fest.swing.listener.EventDispatchThreadedEventListener

/*
* Created on Mar 27, 2008
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* Copyright @2008-2013 the original author or authors.
*/
package org.fest.swing.listener;

import static javax.swing.SwingUtilities.invokeLater;
import static javax.swing.SwingUtilities.isEventDispatchThread;
import static org.fest.util.Lists.newArrayList;
import static org.fest.util.Preconditions.checkNotNull;

import java.awt.AWTEvent;
import java.awt.event.AWTEventListener;
import java.util.List;

import javax.annotation.Nonnull;
import javax.annotation.concurrent.GuardedBy;
import javax.annotation.concurrent.ThreadSafe;

/**
* <p>
* AWT event listener that ensures all events are handled on the event dispatch thread (EDT.)
* </p>
*
* <p>
* NOTE from Abbot: {@code Applet} runners may run several simultaneous event dispatch threads when displaying multiple
* {@code Applet}s simultaneously. If this listener is installed in the parent context of those dispatch threads, it
* will be invoked on each of those threads, possibly simultaneously.
* </p>
*
* @author Yvonne Wang
* @author Alex Ruiz
*/
@ThreadSafe
public abstract class EventDispatchThreadedEventListener implements AWTEventListener {
  @GuardedBy("lock")
  private final List<AWTEvent> deferredEvents = newArrayList();

  private final Object lock = new Object();

  private final Runnable processDeferredEventsTask = new Runnable() {
    @Override
    public void run() {
      processDeferredEvents();
    }
  };

  /**
   * If this method is called in the event dispatch thread, it processes the given event and the queued ones. Otherwise
   * it will add the given event to the queue and process all the events in the queue in the event dispatch thread (EDT.)
   *
   * @param event the event to process.
   */
  @Override
  public void eventDispatched(AWTEvent event) {
    if (!isEventDispatchThread()) {
      // Often the application under test will invoke Window.show, which spawns hierarchy events. We want to ensure we
      // respond to those events on the dispatch thread to avoid deadlock.
      synchronized (lock) {
        deferredEvents.add(event);
      }
      // Ensure that in the absence of any subsequent event thread events deferred events still get processed.
      // If regular events are received before this action is run, the deferred events will be processed prior to those
      // events and the action will do nothing.
      invokeLater(processDeferredEventsTask);
      return;
    }
    // Ensure any deferred events are processed prior to subsequently posted events.
    processDeferredEvents();
    processEvent(checkNotNull(event));
  }

  /** Processes any events that were generated off the event queue but not immediately handled. */
  protected void processDeferredEvents() {
    // Make a copy of the deferred events and empty the queue
    List<AWTEvent> queue = newArrayList();
    synchronized (lock) {
      // In the rare case where there are multiple simultaneous dispatch threads, it's possible for deferred events to
      // get posted while another event is being processed. At most this will mean a few events get processed out of
      // order, but they will likely be from different event dispatch contexts, so it shouldn't matter.
      queue.addAll(deferredEvents);
      deferredEvents.clear();
    }
    while (queue.size() > 0) {
      AWTEvent event = queue.get(0);
      queue.remove(0);
      processEvent(checkNotNull(event));
    }
  }

  /**
   * This method is not protected by any synchronization locks (nor should it be); in the presence of multiple
   * simultaneous event dispatch threads, the listener must be thread-safe.
   *
   * @param event the event to process.
   */
  protected abstract void processEvent(@Nonnull AWTEvent event);
}
TOP

Related Classes of org.fest.swing.listener.EventDispatchThreadedEventListener

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.