Package org.fest.swing.driver

Source Code of org.fest.swing.driver.JInternalFrameDriver

/*
* Created on Feb 1, 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.driver;

import static org.fest.swing.driver.ComponentPreconditions.checkShowing;
import static org.fest.swing.driver.JInternalFrameAction.DEICONIFY;
import static org.fest.swing.driver.JInternalFrameAction.ICONIFY;
import static org.fest.swing.driver.JInternalFrameAction.MAXIMIZE;
import static org.fest.swing.driver.JInternalFrameAction.NORMALIZE;
import static org.fest.swing.driver.JInternalFrameIconQuery.isIconified;
import static org.fest.swing.driver.JInternalFrameSetIconTask.setIcon;
import static org.fest.swing.driver.JInternalFrameSetMaximumTask.setMaximum;
import static org.fest.swing.driver.WindowLikeContainers.closeButtonLocation;
import static org.fest.swing.driver.WindowLikeContainers.iconifyButtonLocation;
import static org.fest.swing.driver.WindowLikeContainers.maximizeButtonLocation;
import static org.fest.swing.edt.GuiActionRunner.execute;
import static org.fest.swing.exception.ActionFailedException.actionFailure;
import static org.fest.swing.format.Formatting.format;
import static org.fest.util.Preconditions.checkNotNull;

import java.awt.Container;
import java.awt.Dimension;
import java.awt.Point;
import java.beans.PropertyVetoException;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.swing.JInternalFrame;
import javax.swing.JInternalFrame.JDesktopIcon;

import org.fest.swing.annotation.RunsInCurrentThread;
import org.fest.swing.annotation.RunsInEDT;
import org.fest.swing.core.Robot;
import org.fest.swing.edt.GuiQuery;
import org.fest.swing.edt.GuiTask;
import org.fest.swing.exception.ActionFailedException;
import org.fest.swing.exception.UnexpectedException;
import org.fest.swing.util.Pair;
import org.fest.swing.util.Triple;
import org.fest.util.InternalApi;
import org.fest.util.VisibleForTesting;

/**
* <p>
* Supports functional testing of {@code JInternalFrame}s.
* </p>
*
* <p>
* <b>Note:</b> This class is intended for internal use only. Please use the classes in the package
* {@link org.fest.swing.fixture} in your tests.
* </p>
*
* @author Alex Ruiz
* @author Yvonne Wang
*/
@InternalApi
public class JInternalFrameDriver extends JComponentDriver {
  /**
   * Creates a new {@link JInternalFrameDriver}.
   *
   * @param robot the robot to use to simulate user input.
   */
  public JInternalFrameDriver(@Nonnull Robot robot) {
    super(robot);
  }

  /**
   * Brings the given {@code JInternalFrame} to the front.
   *
   * @param internalFrame the target {@code JInternalFrame}.
   */
  @RunsInEDT
  public void moveToFront(final @Nonnull JInternalFrame internalFrame) {
    execute(new GuiTask() {
      @Override
      protected void executeInEDT() {
        // it seems that moving to front always works, regardless if the internal frame is invisible and/or disabled.
        internalFrame.toFront();
      }
    });
  }

  /**
   * Brings the given {@code JInternalFrame} to the back.
   *
   * @param internalFrame the target {@code JInternalFrame}.
   */
  @RunsInEDT
  public void moveToBack(final @Nonnull JInternalFrame internalFrame) {
    execute(new GuiTask() {
      @Override
      protected void executeInEDT() {
        // it seems that moving to back always works, regardless if the internal frame is invisible and/or disabled.
        internalFrame.moveToBack();
      }
    });
  }

  /**
   * Maximizes the given {@code JInternalFrame}, deconifying it first if it is iconified.
   *
   * @param internalFrame the target {@code JInternalFrame}.
   * @throws IllegalStateException if the {@code JInternalFrame} is not maximizable.
   * @throws IllegalStateException if the {@code JInternalFrame} is not showing on the screen.
   * @throws ActionFailedException if the {@code JInternalFrame} vetoes the action.
   */
  @RunsInEDT
  public void maximize(@Nonnull JInternalFrame internalFrame) {
    Pair<Container, Point> maximizeLocation = maximizeLocationOf(internalFrame);
    maximizeOrNormalize(internalFrame, MAXIMIZE, maximizeLocation);
  }

  @RunsInEDT
  private static @Nonnull Pair<Container, Point> maximizeLocationOf(final @Nonnull JInternalFrame internalFrame) {
    Pair<Container, Point> result = execute(new GuiQuery<Pair<Container, Point>>() {
      @Override
      protected @Nullable Pair<Container, Point> executeInEDT() {
        checkCanMaximize(internalFrame);
        return findMaximizeLocation(internalFrame);
      }
    });
    return checkNotNull(result);
  }

  @RunsInCurrentThread
  private static void checkCanMaximize(@Nonnull JInternalFrame internalFrame) {
    checkShowingOrIconified(internalFrame);
    if (!internalFrame.isMaximizable()) {
      String msg = String.format("The JInternalFrame <%s> is not maximizable", format(internalFrame));
      throw new IllegalStateException(msg);
    }
  }

  /**
   * Normalizes the given {@code JInternalFrame}, deconifying it first if it is iconified.
   *
   * @param internalFrame the target {@code JInternalFrame}.
   * @throws IllegalStateException if the {@code JInternalFrame} is not showing on the screen.
   * @throws ActionFailedException if the {@code JInternalFrame} vetoes the action.
   */
  @RunsInEDT
  public void normalize(@Nonnull JInternalFrame internalFrame) {
    Pair<Container, Point> normalizeLocation = validateAndFindNormalizeLocation(internalFrame);
    maximizeOrNormalize(internalFrame, NORMALIZE, normalizeLocation);
  }

  @RunsInEDT
  private static Pair<Container, Point> validateAndFindNormalizeLocation(final @Nonnull JInternalFrame internalFrame) {
    return execute(new GuiQuery<Pair<Container, Point>>() {
      @Override
      protected Pair<Container, Point> executeInEDT() {
        checkShowingOrIconified(internalFrame);
        return findMaximizeLocation(internalFrame);
      }
    });
  }

  @RunsInCurrentThread
  private static void checkShowingOrIconified(@Nonnull JInternalFrame internalFrame) {
    if (!internalFrame.isIcon()) {
      checkShowing(internalFrame);
    }
  }

  @RunsInCurrentThread
  private static @Nonnull Pair<Container, Point> findMaximizeLocation(@Nonnull JInternalFrame internalFrame) {
    Container clickTarget = internalFrame.isIcon() ? internalFrame.getDesktopIcon() : internalFrame;
    Point location = maximizeButtonLocation(checkNotNull(clickTarget));
    return Pair.of(clickTarget, location);
  }

  @RunsInEDT
  private void maximizeOrNormalize(@Nonnull JInternalFrame internalFrame, @Nonnull JInternalFrameAction action,
      @Nonnull Pair<Container, Point> toMoveMouseTo) {
    moveMouseIgnoringAnyError(toMoveMouseTo.first, toMoveMouseTo.second);
    setMaximumProperty(internalFrame, action);
  }

  @RunsInEDT
  private void setMaximumProperty(@Nonnull JInternalFrame internalFrame, @Nonnull JInternalFrameAction action) {
    try {
      setMaximum(internalFrame, action);
      robot.waitForIdle();
    } catch (UnexpectedException unexpected) {
      failIfVetoed(internalFrame, action, unexpected);
    }
  }

  /**
   * Iconifies the given {@code JInternalFrame}.
   *
   * @param internalFrame the target {@code JInternalFrame}.
   * @throws IllegalStateException if the {@code JInternalFrame} is not showing on the screen.
   * @throws IllegalStateException if the {@code JInternalFrame} is not iconifiable.
   * @throws ActionFailedException if the {@code JInternalFrame} vetoes the action.
   */
  @RunsInEDT
  public void iconify(@Nonnull JInternalFrame internalFrame) {
    Pair<Boolean, Point> iconifyInfo = findIconifyInfo(internalFrame);
    if (iconifyInfo.first) {
      return; // internal frame is already iconified
    }
    moveMouseIgnoringAnyError(internalFrame, iconifyInfo.second);
    setIconProperty(internalFrame, ICONIFY);
  }

  @RunsInEDT
  private static @Nonnull Pair<Boolean, Point> findIconifyInfo(final @Nonnull JInternalFrame internalFrame) {
    Pair<Boolean, Point> result = execute(new GuiQuery<Pair<Boolean, Point>>() {
      @Override
      protected @Nullable Pair<Boolean, Point> executeInEDT() throws Throwable {
        checkShowingOrIconified(internalFrame);
        if (!internalFrame.isIconifiable()) {
          String msg = String.format("The JInternalFrame <%s> is not iconifiable.", format(internalFrame));
          throw new IllegalStateException(msg);
        }
        return iconifyInfo(internalFrame);
      }
    });
    return checkNotNull(result);
  }

  @RunsInCurrentThread
  private static @Nonnull Pair<Boolean, Point> iconifyInfo(@Nonnull JInternalFrame internalFrame) {
    boolean iconified = isIconified(internalFrame);
    if (iconified) {
      return Pair.of(true, null);
    }
    return Pair.of(iconified, findIconifyLocation(internalFrame));
  }

  /**
   * De-iconifies the given {@code JInternalFrame}.
   *
   * @param internalFrame the target {@code JInternalFrame}.
   * @throws IllegalStateException if the {@code JInternalFrame} is not showing on the screen.
   * @throws ActionFailedException if the {@code JInternalFrame} vetoes the action.
   */
  @RunsInEDT
  public void deiconify(@Nonnull JInternalFrame internalFrame) {
    Triple<Boolean, Container, Point> deiconifyInfo = validateAndfindDeiconifyInfo(internalFrame);
    if (deiconifyInfo.first) {
      return; // internal frame is already de-iconified
    }
    moveMouseIgnoringAnyError(deiconifyInfo.second, deiconifyInfo.third);
    setIconProperty(internalFrame, DEICONIFY);
  }

  @RunsInEDT
  private static @Nonnull Triple<Boolean, Container, Point> validateAndfindDeiconifyInfo(
      final @Nonnull JInternalFrame internalFrame) {
    Triple<Boolean, Container, Point> result = execute(new GuiQuery<Triple<Boolean, Container, Point>>() {
      @Override
      protected @Nullable Triple<Boolean, Container, Point> executeInEDT() throws Throwable {
        checkShowingOrIconified(internalFrame);
        return deiconifyInfo(internalFrame);
      }
    });
    return checkNotNull(result);
  }

  @RunsInCurrentThread
  private static @Nonnull Triple<Boolean, Container, Point> deiconifyInfo(@Nonnull JInternalFrame internalFrame) {
    boolean deiconified = !isIconified(internalFrame);
    if (deiconified) {
      return Triple.of(true, null, null);
    }
    Container desktopIcon = checkNotNull(internalFrame.getDesktopIcon());
    return Triple.of(deiconified, desktopIcon, iconifyButtonLocation(desktopIcon));
  }

  @RunsInCurrentThread
  private static @Nonnull Point findIconifyLocation(JInternalFrame internalFrame) {
    JDesktopIcon desktopIcon = checkNotNull(internalFrame.getDesktopIcon());
    return iconifyButtonLocation(desktopIcon);
  }

  @RunsInEDT
  private void setIconProperty(@Nonnull JInternalFrame internalFrame, @Nonnull JInternalFrameAction action) {
    try {
      setIcon(internalFrame, action);
      robot.waitForIdle();
    } catch (UnexpectedException unexpected) {
      failIfVetoed(internalFrame, action, unexpected);
    }
  }

  @VisibleForTesting
  void failIfVetoed(@Nonnull JInternalFrame internalFrame, @Nonnull JInternalFrameAction action,
      @Nonnull UnexpectedException unexpected) {
    PropertyVetoException vetoError = vetoFrom(unexpected);
    if (vetoError == null) {
      return;
    }
    String msg = String.format("%s of %s was vetoed: <%s>", action.name, format(internalFrame), vetoError.getMessage());
    throw actionFailure(msg);
  }

  private @Nullable PropertyVetoException vetoFrom(@Nonnull UnexpectedException unexpected) {
    Throwable cause = unexpected.getCause();
    if (!(cause instanceof PropertyVetoException)) {
      return null;
    }
    return (PropertyVetoException) cause;
  }

  /**
   * Resizes the {@code JInternalFrame} horizontally.
   *
   * @param internalFrame the target {@code JInternalFrame}.
   * @param width the width that the {@code JInternalFrame} should have after being resized.
   * @throws IllegalStateException if the {@code JInternalFrame} is not showing on the screen.
   * @throws IllegalStateException if the {@code JInternalFrame} is not resizable by the user.
   */
  @RunsInEDT
  public void resizeWidth(@Nonnull JInternalFrame internalFrame, int width) {
    doResizeWidth(internalFrame, width);
  }

  /**
   * Resizes the {@code JInternalFrame} vertically.
   *
   * @param w the target {@code JInternalFrame}.
   * @param height the height that the {@code JInternalFrame} should have after being resized.
   * @throws IllegalStateException if the {@code JInternalFrame} is not showing on the screen.
   * @throws IllegalStateException if the {@code JInternalFrame} is not resizable by the user.
   */
  @RunsInEDT
  public void resizeHeight(@Nonnull JInternalFrame w, int height) {
    doResizeHeight(w, height);
  }

  /**
   * Resizes the {@code JInternalFrame} to the given size.
   *
   * @param internalFrame the target {@code JInternalFrame}.
   * @param size the size to resize the {@code JInternalFrame} to.
   * @throws IllegalStateException if the {@code JInternalFrame} is not showing on the screen.
   * @throws IllegalStateException if the {@code JInternalFrame} is not resizable by the user.
   */
  @RunsInEDT
  public void resizeTo(@Nonnull JInternalFrame internalFrame, @Nonnull Dimension size) {
    resize(internalFrame, size.width, size.height);
  }

  /**
   * Moves the {@code JInternalFrame} to the given location.
   *
   * @param internalFrame the target {@code JInternalFrame}.
   * @param where the location to move the {@code JInternalFrame} to.
   * @throws IllegalStateException if the {@code JInternalFrame} is not showing on the screen.
   */
  @RunsInEDT
  public void move(@Nonnull JInternalFrame internalFrame, @Nonnull Point where) {
    move(internalFrame, where.x, where.y);
  }

  /**
   * Closes the given {@code JInternalFrame}.
   *
   * @param internalFrame the target {@code JInternalFrame}.
   * @throws IllegalStateException if the {@code JInternalFrame} is not showing on the screen.
   * @throws IllegalStateException if the {@code JInternalFrame} is not closable.
   */
  @RunsInEDT
  public void close(@Nonnull JInternalFrame internalFrame) {
    Point closeButtonLocation = findCloseButtonLocation(internalFrame);
    if (closeButtonLocation == null) {
      return; // internal frame is already closed
    }
    moveMouseIgnoringAnyError(internalFrame, closeButtonLocation);
    JInternalFrameCloseTask.close(internalFrame);
    robot.waitForIdle();
  }

  @RunsInEDT
  private static @Nullable Point findCloseButtonLocation(final @Nonnull JInternalFrame internalFrame) {
    return execute(new GuiQuery<Point>() {
      @Override
      protected @Nullable Point executeInEDT() {
        checkShowing(internalFrame);
        if (!internalFrame.isClosable()) {
          String msg = String.format("The JInternalFrame <%s> is not closable", format(internalFrame));
          throw new IllegalStateException(msg);
        }
        if (internalFrame.isClosed()) {
          return null;
        }
        return closeButtonLocation(internalFrame);
      }
    });
  }
}
TOP

Related Classes of org.fest.swing.driver.JInternalFrameDriver

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.