/**
   * Selects the cell of the Table.<br>
   * With the xPos, yPos, xUnits and yUnits the click position inside the cell can be defined.
   *
   * @param row The row of the cell.
   * @param rowOperator The row header operator
   * @param col The column of the cell.
   * @param colOperator The column header operator
   * @param clickCount The number of clicks with the right mouse button
   * @param xPos what x position
   * @param xUnits should x position be pixel or percent values
   * @param yPos what y position
   * @param yUnits should y position be pixel or percent values
   * @param extendSelection Should this selection be part of a multiple selection
   * @param button what mouse button should be used
   * @throws StepExecutionException If the row or the column is invalid
   */
  public void rcSelectCell(
      final String row,
      final String rowOperator,
      final String col,
      final String colOperator,
      final int clickCount,
      final int xPos,
      final String xUnits,
      final int yPos,
      final String yUnits,
      final String extendSelection,
      int button)
      throws StepExecutionException {
    TreeTableOperationContext adapter = getContext();
    final int implRow = adapter.getRowFromString(row, rowOperator);
    final int implCol = adapter.getColumnFromString(col, colOperator, implRow != -1);
    final boolean isExtendSelection = extendSelection.equals(ValueSets.BinaryChoice.yes.rcValue());
    if (log.isDebugEnabled()) {
      log.debug("Selecting row, col: " + row + ", " + col); // $NON-NLS-1$//$NON-NLS-2$
    }

    Rectangle cellBounds;
    Object source = getRealComponent();
    // if row is header and col is existing
    if (implRow == -1 && implCol > -1) {
      cellBounds = adapter.getHeaderBounds(implCol);
      source = adapter.getTableHeader();
    } else {
      cellBounds = adapter.scrollCellToVisible(implRow, implCol);
    }
    ClickOptions clickOptions = ClickOptions.create();
    clickOptions.setClickCount(clickCount).setScrollToVisible(false);
    clickOptions.setMouseButton(button);
    try {
      if (isExtendSelection) {
        getRobot().keyPress(getRealComponent(), getExtendSelectionModifier());
      }
      getRobot()
          .click(
              source,
              cellBounds,
              clickOptions,
              xPos,
              xUnits.equalsIgnoreCase(ValueSets.Unit.pixel.rcValue()),
              yPos,
              yUnits.equalsIgnoreCase(ValueSets.Unit.pixel.rcValue()));
    } finally {
      if (isExtendSelection) {
        getRobot().keyRelease(getRealComponent(), getExtendSelectionModifier());
      }
    }
  }
  /** {@inheritDoc} */
  public void selectAll() {
    final String totalText = getText();

    // fix for http://bugzilla.bredex.de/201
    // The keystroke "command + a" sometimes causes an "a" to be entered
    // into the text field instead of selecting all text (or having no
    // effect).
    if (!EnvironmentUtils.isMacOS()) {
      try {
        getRobot().keyStroke(getRobot().getSystemModifierSpec() + " A"); // $NON-NLS-1$
      } catch (StepExecutionException see) {
        /*This might happen under certain circumstances e.g. on MacOS X see
        bug http://eclip.se/342691 */
        log.warn(see);
      }
    }

    if (!totalText.equals(getSelectionText())) {
      // the selection failed for some reason
      getEventThreadQueuer()
          .invokeAndWait(
              "text.selectAll", //$NON-NLS-1$
              new IRunnable<Void>() {
                public Void run() {
                  m_styledText.selectAll();
                  return null;
                }
              });
    }

    String selectionText = getSelectionText();
    if (!totalText.equals(selectionText)) {
      log.warn(
          "SelectAll failed!\n" //$NON-NLS-1$
              + "Total text: '"
              + totalText
              + "'\n" //$NON-NLS-1$//$NON-NLS-2$
              + "Selected text: '"
              + selectionText
              + "'"); //$NON-NLS-1$ //$NON-NLS-2$
    }
  }
  /**
   * Takes a screenshot and saves the image to disk. This method will attempt to encode the image
   * according to the file extension of the given output file. If this is not possible (because the
   * encoding type is not supported), then the default encoding type will be used. If the default
   * encoding type is used, an appropriate extension will be added to the filename.
   *
   * @param captureRect Rect to capture in screen coordinates.
   * @param scaleFactor Degree to which the image should be scaled, in percent. A <code>scaleFactor
   *     </code> of <code>100</code> produces an unscaled image. This value must be greater than
   *     <code>0</code> and less than or equal to <code>200</code>.
   * @param outputFile Path and filename for the created image.
   */
  public void takeScreenshot(Rectangle captureRect, double scaleFactor, File outputFile) {
    // Create screenshot
    java.awt.Robot robot;
    File out = outputFile;

    try {
      robot = new java.awt.Robot();
      BufferedImage image = robot.createScreenCapture(captureRect);

      int scaledWidth = (int) Math.floor(image.getWidth() * scaleFactor);
      int scaledHeight = (int) Math.floor(image.getHeight() * scaleFactor);
      BufferedImage imageOut =
          new BufferedImage(scaledWidth, scaledHeight, BufferedImage.TYPE_INT_RGB);
      // Scale it to the new size on-the-fly
      Graphics2D graphics2D = imageOut.createGraphics();
      graphics2D.setRenderingHint(
          RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
      graphics2D.drawImage(image, 0, 0, scaledWidth, scaledHeight, null);

      // Save captured image using given format, if supported.
      String extension = getExtension(out.getName());
      if (extension.length() == 0
          || !ImageIO.getImageWritersBySuffix(extension).hasNext()
          || !ImageIO.write(imageOut, extension, out)) {

        // Otherwise, save using default format
        out = new File(outputFile.getPath() + EXTENSION_SEPARATOR + DEFAULT_IMAGE_FORMAT);
        if (!ImageIO.write(imageOut, DEFAULT_IMAGE_FORMAT, out)) {

          // This should never happen, so log as error if it does.
          // In this situation, the screenshot will not be saved, but
          // the test step will still be marked as successful.
          log.error(
              "Screenshot could not be saved. "
                  + //$NON-NLS-1$
                  "Default image format ("
                  + DEFAULT_IMAGE_FORMAT //$NON-NLS-1$
                  + ") is not supported."); //$NON-NLS-1$
        }
      }

    } catch (AWTException e) {
      throw new RobotException(e);
    } catch (IOException e) {
      throw new StepExecutionException(
          "Screenshot could not be saved", //$NON-NLS-1$
          EventFactory.createActionError(TestErrorEvent.FILE_IO_ERROR));
    }
  }