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

org.assertj.swing.monitor.Context Maven / Gradle / Ivy

There is a newer version: 3.17.1
Show newest version
/**
 * 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 2012-2015 the original author or authors.
 */
package org.assertj.swing.monitor;

import static org.assertj.core.util.Lists.newArrayList;
import static org.assertj.core.util.Sets.newLinkedHashSet;
import static org.assertj.swing.edt.GuiActionRunner.execute;

import java.awt.Component;
import java.awt.EventQueue;
import java.awt.Frame;
import java.awt.Toolkit;
import java.awt.Window;
import java.util.Collection;
import java.util.Set;

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

import org.assertj.swing.annotation.RunsInEDT;

/**
 * Monitor that maps event queues to GUI components and GUI components to event event queues.
 *
 * @author Alex Ruiz
 */
@ThreadSafe
class Context {
  /** Maps unique event queues to the set of root windows found on each queue. */
  @GuardedBy("lock")
  private final WindowEventQueueMapping windowEventQueueMapping;

  /** Maps components to their corresponding event queues. */
  @GuardedBy("lock")
  private final EventQueueMapping eventQueueMapping;

  private final Object lock = new Object();

  Context(@Nonnull Toolkit toolkit) {
    this(toolkit, new WindowEventQueueMapping(), new EventQueueMapping());
  }

  Context(@Nonnull Toolkit toolkit, @Nonnull WindowEventQueueMapping windowEventQueueMapping,
          @Nonnull EventQueueMapping eventQueueMapping) {
    this.windowEventQueueMapping = windowEventQueueMapping;
    this.eventQueueMapping = eventQueueMapping;
    this.windowEventQueueMapping.addQueueFor(toolkit);
  }

  /**
   * Return all available root {@code Window}s. A root {@code Window} is one that has a {@code null} parent. Nominally
   * this means a list similar to that returned by {@code Frame.getFrames()}, but in the case of an {@code Applet} may
   * return a few dialogs as well.
   *
   * @return all available root {@code Window}s.
   */
  @Nonnull
  Collection rootWindows() {
    Set rootWindows = newLinkedHashSet();
    synchronized (lock) {
      rootWindows.addAll(windowEventQueueMapping.windows());
    }
    rootWindows.addAll(newArrayList(Frame.getFrames()));
    rootWindows.addAll(newArrayList(Window.getOwnerlessWindows()));
    return rootWindows;
  }

  @Nullable
  EventQueue storedQueueFor(@Nonnull Component c) {
    synchronized (lock) {
      return eventQueueMapping.storedQueueFor(c);
    }
  }

  void removeContextFor(@Nonnull Component component) {
    synchronized (lock) {
      windowEventQueueMapping.removeMappingFor(component);
    }
  }

  void addContextFor(@Nonnull Component component) {
    synchronized (lock) {
      windowEventQueueMapping.addQueueFor(component);
      eventQueueMapping.addQueueFor(component);
    }
  }

  /**
   * Return the event queue corresponding to the given AWT or Swing {@code Component}. In most cases, this is the same
   * as {@link java.awt.Toolkit#getSystemEventQueue()}, but in the case of applets will bypass the {@code AppContext}
   * and provide the real event queue.
   *
   * @param c the given {@code Component}.
   * @return the event queue corresponding to the given {@code Component}.
   */
  @RunsInEDT
  @Nullable
  EventQueue eventQueueFor(@Nonnull Component c) {
    Component component = topParentOf(c);
    if (component == null) {
      return null;
    }
    synchronized (lock) {
      return eventQueueMapping.queueFor(component);
    }
  }

  @RunsInEDT
  private static @Nullable Component topParentOf(final @Nonnull Component c) {
    return execute(() -> {
      Component parent = c;
      // Components above the applet in the hierarchy may or may not share the same context with the applet itself.
      while (!(parent instanceof java.applet.Applet) && parent.getParent() != null) {
        parent = parent.getParent();
      }
      return parent;
    });
  }

  /**
   * @return all known event queues.
   */
  @Nonnull
  Collection allEventQueues() {
    Set eventQueues = newLinkedHashSet();
    synchronized (lock) {
      eventQueues.addAll(windowEventQueueMapping.eventQueues());
      eventQueues.addAll(eventQueueMapping.eventQueues());
    }
    return eventQueues;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy