blob: 48818cc7c2d15f9f1b4e42834f06a6d1831076bb [file] [log] [blame]
/*
* Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.netbeans.jemmy.drivers.text;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import org.netbeans.jemmy.CharBindingMap;
import org.netbeans.jemmy.QueueTool;
import org.netbeans.jemmy.Timeout;
import org.netbeans.jemmy.drivers.DriverManager;
import org.netbeans.jemmy.drivers.KeyDriver;
import org.netbeans.jemmy.drivers.LightSupportiveDriver;
import org.netbeans.jemmy.drivers.TextDriver;
import org.netbeans.jemmy.operators.ComponentOperator;
/**
* Superclass for all TextDrivers using keyboard.
*
* @author Alexandre Iline(alexandre.iline@oracle.com)
*/
public abstract class TextKeyboardDriver extends LightSupportiveDriver implements TextDriver {
/**
* Constructs a TextKeyboardDriver.
*
* @param supported an array of supported class names
*/
public TextKeyboardDriver(String[] supported) {
super(supported);
}
@Override
public void changeCaretPosition(ComponentOperator oper, int position) {
DriverManager.getFocusDriver(oper).giveFocus(oper);
checkSupported(oper);
changeCaretPosition(oper, position, 0);
}
@Override
public void selectText(ComponentOperator oper, int startPosition, int finalPosition) {
changeCaretPosition(oper, startPosition);
DriverManager.getKeyDriver(oper).pressKey(oper, KeyEvent.VK_SHIFT, 0);
changeCaretPosition(oper, finalPosition, InputEvent.SHIFT_MASK);
DriverManager.getKeyDriver(oper).releaseKey(oper, KeyEvent.VK_SHIFT, 0);
}
@Override
public void clearText(ComponentOperator oper) {
DriverManager.getFocusDriver(oper).giveFocus(oper);
checkSupported(oper);
KeyDriver kdriver = DriverManager.getKeyDriver(oper);
Timeout pushTime = oper.getTimeouts().create("ComponentOperator.PushKeyTimeout");
Timeout betweenTime = getBetweenTimeout(oper);
while (getCaretPosition(oper) > 0) {
kdriver.typeKey(oper, KeyEvent.VK_BACK_SPACE, (char) KeyEvent.VK_BACK_SPACE, 0, pushTime);
betweenTime.sleep();
}
while (getText(oper).length() > 0) {
kdriver.pushKey(oper, KeyEvent.VK_DELETE, 0, pushTime);
betweenTime.sleep();
}
}
@Override
public void typeText(ComponentOperator oper, String text, int caretPosition) {
changeCaretPosition(oper, caretPosition);
KeyDriver kDriver = DriverManager.getKeyDriver(oper);
CharBindingMap map = oper.getCharBindingMap();
Timeout pushTime = oper.getTimeouts().create("ComponentOperator.PushKeyTimeout");
Timeout betweenTime = getBetweenTimeout(oper);
char[] crs = text.toCharArray();
for (char cr : crs) {
kDriver.typeKey(oper, map.getCharKey(cr), cr, map.getCharModifiers(cr), pushTime);
betweenTime.sleep();
}
}
@Override
public void changeText(ComponentOperator oper, String text) {
clearText(oper);
typeText(oper, text, 0);
}
@Override
public void enterText(ComponentOperator oper, String text) {
changeText(oper, text);
DriverManager.getKeyDriver(oper).pushKey(oper, KeyEvent.VK_ENTER, 0,
new Timeout("", 0));
}
/**
* Returns operator's text.
*
* @param oper an operator.
* @return string representing component text.
*/
public abstract String getText(ComponentOperator oper);
/**
* Returns current caret position.
*
* @param oper an operator.
* @return int represnting current operator's caret position.
*/
public abstract int getCaretPosition(ComponentOperator oper);
/**
* Returns a caret position of selection start.
*
* @param oper an operator.
* @return int represnting index of operator's selection start.
*/
public abstract int getSelectionStart(ComponentOperator oper);
/**
* Returns a caret position of selection end.
*
* @param oper an operator.
* @return int represnting index of operator's selection end.
*/
public abstract int getSelectionEnd(ComponentOperator oper);
/**
* Returns an array of navigation keys.
*
* @param oper an operator.
* @return an array on NavigationKey instances.
*/
public abstract NavigationKey[] getKeys(ComponentOperator oper);
/**
* Returns a timeout to sleep between text typing and caret operations.
*
* @param oper an operator.
* @return a Timeout instance.
*/
public abstract Timeout getBetweenTimeout(ComponentOperator oper);
/**
* Changes current caret position to specifyed.
*
* @param oper an operator.
* @param position new caret position
* @param preModifiers a modifiers (combination of
* {@code InputEvent.*_MASK} fields) pushed before caret moving (like
* shift during text selection).
*/
protected void changeCaretPosition(ComponentOperator oper, final int position, final int preModifiers) {
NavigationKey[] keys = getKeys(oper);
for (int i = keys.length - 1; i >= 0; i--) {
if (keys[i] instanceof OffsetKey) {
moveCaret(oper, (OffsetKey) keys[i], position, preModifiers);
} else {
moveCaret(oper, (GoAndBackKey) keys[i], position, preModifiers);
}
}
}
private int difference(int one, int two) {
if (one >= two) {
return one - two;
} else {
return two - one;
}
}
private void push(ComponentOperator oper, NavigationKey key, int preModifiers) {
DriverManager.getKeyDriver(oper).
pushKey(oper, key.getKeyCode(), key.getModifiers() | preModifiers,
oper.getTimeouts().create("ComponentOperator.PushKeyTimeout"));
getBetweenTimeout(oper).sleep();
}
private final void moveCaret(ComponentOperator oper, GoAndBackKey key, int position, int preModifiers) {
int newDiff = difference(position, getCaretPosition(oper));
int oldDiff = newDiff;
QueueTool qTool = new QueueTool();
qTool.setOutput(oper.getOutput().createErrorOutput());
while (key.getDirection() * (position - getCaretPosition(oper)) > 0) {
oldDiff = newDiff;
push(oper, key, preModifiers);
qTool.waitEmpty();
newDiff = difference(position, getCaretPosition(oper));
if (newDiff == oldDiff) {
return;
}
}
if (newDiff > oldDiff) {
push(oper, key.getBackKey(), preModifiers);
}
}
private final void moveCaret(ComponentOperator oper, OffsetKey key, int position, int preModifiers) {
if (gotToGo(oper, position, key.getExpectedPosition())) {
push(oper, key, preModifiers);
}
}
private boolean gotToGo(ComponentOperator oper, int point, int offset) {
return difference(point, offset) < difference(point, getCaretPosition(oper));
}
}