/*******************************************************************************
* Copyright (c) 2012 BREDEX GmbH.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* BREDEX GmbH - initial API and implementation
*******************************************************************************/
package org.eclipse.jubula.rc.swt.tester.adapter;
import org.apache.commons.lang.Validate;
import org.eclipse.jubula.rc.common.driver.ClickOptions;
import org.eclipse.jubula.rc.common.driver.IRunnable;
import org.eclipse.jubula.rc.common.exception.StepExecutionException;
import org.eclipse.jubula.rc.common.logger.AutServerLogger;
import org.eclipse.jubula.rc.common.tester.adapter.interfaces.IComboComponent;
import org.eclipse.jubula.rc.swt.utils.SwtUtils;
import org.eclipse.jubula.tools.internal.objects.event.EventFactory;
import org.eclipse.jubula.tools.internal.objects.event.TestErrorEvent;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Widget;
/**
* Implementation of the Interface <code>IComboBoxAdapter</code> as a abstract
* adapter for the SWT Combo Boxes. This class needs specific methods of its
* subclasses therefore it is abstract.
*
* @author BREDEX GmbH
*
*/
public abstract class AbstractComboBoxAdapter extends ControlAdapter
implements IComboComponent {
/** number of clicks to give focus without selecting any text */
public static final int CLICK_COUNT_FOR_SELECTING_NONE = 3;
/** the logger */
private static AutServerLogger log = new AutServerLogger(
AbstractComboBoxAdapter.class);
/**
*
* @param objectToAdapt
*/
protected AbstractComboBoxAdapter(Object objectToAdapt) {
super(objectToAdapt);
}
/**
* {@inheritDoc}
*/
public void select(int index) {
int comboItemCount = getItemCount();
if (index >= comboItemCount
|| index < 0) {
throw new StepExecutionException("Combo Box index '" + index //$NON-NLS-1$
+ "' is out of range", //$NON-NLS-1$
EventFactory.createActionError(TestErrorEvent.INVALID_INDEX));
}
if (isComboEnabled()) {
// FIXME zeb: Needs special handling if style is not DROP_DOWN
openDropdownList();
selectImpl(index);
}
}
/**
* @return <code>true</code> if the combo box is currently enabled.
*/
protected abstract boolean isComboEnabled();
/**
*
* @param index idx
*/
protected abstract void selectImpl(int index);
/**
* Opens the combobox dropdown list. May also be
* called if the list is already visible.
*/
protected abstract void openDropdownList();
/**
* Returns the number of items contained in the combo list.
* @return the number of items.
*/
protected abstract int getItemCount();
/**
* {@inheritDoc}
*/
public void input(String text, boolean replace)
throws StepExecutionException, IllegalArgumentException {
Validate.notNull(text, "text must not be null"); //$NON-NLS-1$
Control editor = (Control) getRealComponent();
if (editor == null) {
throw new StepExecutionException("could not find editor", //$NON-NLS-1$
EventFactory.createActionError(TestErrorEvent.COMP_NOT_FOUND));
}
if (replace) {
selectAll();
} else {
selectNone();
}
getRobot().type(editor, text);
getRobot().keyType(null, SWT.KEYPAD_CR);
}
/**
* {@inheritDoc}
*/
public void click(Integer count) {
Control editor = (Control) getRealComponent();
if (editor == null) {
throw new StepExecutionException("no editor found", //$NON-NLS-1$
EventFactory.createActionError(TestErrorEvent.COMP_NOT_FOUND));
}
getRobot().click(editor, null, ClickOptions.create().setClickCount(
count.intValue()));
}
/**
* Give the text field focus without selecting any of the text.
*/
public void selectNone() {
// FIXME zeb: This places the caret at the center of the component,
// which may or may not be correct. Where should the text
// be inserted?
click(new Integer(
CLICK_COUNT_FOR_SELECTING_NONE));
}
/**
* Toggles the combobox dropdown list by clicking on the combo box.
*/
protected void toggleDropdownList() {
// Click in the center of the pulldown button
Rectangle r = findArrowIconArea();
if (log.isDebugEnabled()) {
log.debug("Toggling dropdown by clicking on rectangle: " + r //$NON-NLS-1$
+ "within component: " + getRealComponent()); //$NON-NLS-1$
}
getRobot().click(getRealComponent(), r,
ClickOptions.create().setScrollToVisible(true)
.setConfirmClick(false));
}
/**
* @return a rectangle, where the arrow icon is expected, relative to the
* combo box's location.
*/
protected Rectangle findArrowIconArea() {
final Control editor = (Control) getRealComponent();
Rectangle r = null;
if (editor == null) {
throw new StepExecutionException("could not find editor", //$NON-NLS-1$
EventFactory.createActionError(TestErrorEvent.COMP_NOT_FOUND));
}
r = getEventThreadQueuer().invokeAndWait(
AbstractComboBoxAdapter.class.getName()
+ "findArrowIconArea", new IRunnable<Rectangle>() { //$NON-NLS-1$
public Rectangle run() throws StepExecutionException {
return SwtUtils.getRelativeWidgetBounds(editor, editor);
}
});
// Assume that the arrow icon is approximately square
r.x += r.width - r.height;
r.width = r.height;
return r;
}
/**
* @return true, if combo is not read_only
*/
private boolean isComboEditable() {
Integer comboStyle = getEventThreadQueuer().invokeAndWait(
AbstractComboBoxAdapter.class.getName()
+ "isComboEditable", new IRunnable<Integer>() { //$NON-NLS-1$
public Integer run() throws StepExecutionException {
return ((Widget)getRealComponent()).getStyle();
}
});
return ((comboStyle.intValue() & SWT.READ_ONLY) == 0);
}
/**
* {@inheritDoc}
*/
public boolean isEditable() {
return isComboEditable();
}
}