/** * 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.jide.grids.driver; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.util.Strings.concat; import static org.assertj.core.util.Strings.quote; import static org.assertj.swing.edt.GuiActionRunner.execute; import java.awt.Component; import java.util.ArrayList; import javax.swing.ComboBoxModel; import javax.swing.JList; import javax.swing.text.JTextComponent; import org.assertj.core.presentation.StandardRepresentation; import org.assertj.swing.annotation.RunsInEDT; import org.assertj.swing.core.Robot; import org.assertj.swing.driver.ComponentPreconditions; import org.assertj.swing.driver.JListDriver; import org.assertj.swing.edt.GuiActionRunner; import org.assertj.swing.edt.GuiQuery; import org.assertj.swing.exception.LocationUnavailableException; import com.jidesoft.combobox.AbstractComboBox; import com.jidesoft.combobox.ListComboBox; import com.jidesoft.combobox.PopupPanel; import com.jidesoft.converter.ConverterContext; import com.jidesoft.converter.ObjectConverter; /** * A driver to allow us to interact with a {@link com.jidesoft.combobox.ListComboBox}. * * @author Peter Murray */ public class ListComboBoxDriver extends AbstractComboBoxDriver { private final JListDriver _listDriver; private AbstractComboBoxDropDownListFinder _listFinder; public ListComboBoxDriver(Robot robot) { super(robot); _listDriver = new JListDriver(robot); _listFinder = new AbstractComboBoxDropDownListFinder(robot); } public JList getList(ListComboBox comboBox) { PopupPanel panel = showPopup(comboBox); return _listFinder.findDropDownList(panel); } public void requireItemCount(final ListComboBox comboBox, int expected) { Integer count = execute(() -> comboBox.getModel().getSize()); assertThat(count).as("ItemCount").isEqualTo(expected); } /** * Selects the item under the given index in the <code>{@link ListComboBox}</code>. * * @param comboBox the target <code>ListComboBox</code>. * @param index the given index. * @throws IllegalStateException if the <code>JComboBox</code> is disabled. * @throws IllegalStateException if the <code>JComboBox</code> is not showing on the screen. * @throws IndexOutOfBoundsException if the given index is negative or greater than the index of the last item in the * <code>JComboBox</code>. */ @RunsInEDT public void selectItem(final ListComboBox comboBox, int index) { validateCanSelectItem(comboBox, index); selectItemAtIndex(comboBox, index); hidePopupIfVisible(comboBox); } public void requireText(final ListComboBox comboBox, String value) { GuiQuery<String> query = new GuiQuery<String>() { @Override protected String executeInEDT() throws Throwable { Component editorComp = comboBox.getEditor().getEditorComponent(); if (editorComp instanceof JTextComponent) { return ((JTextComponent) editorComp).getText(); } return null; } }; String actualValue = GuiActionRunner.execute(query); assertThat(actualValue).isEqualTo(value); } /** * Selects the first item matching the given text in the <code>{@link * ListComboBox}</code>. * * @param comboBox the target <code>ListComboBox</code>. * @param toSelect the text to match * @throws LocationUnavailableException if an element matching the given text cannot be found. */ public void selectItem(ListComboBox comboBox, String toSelect) { if (areEqual(comboBox, convertElementToString(comboBox, comboBox.getSelectedItem()), toSelect)) { return; } int itemCount = size(comboBox); for (int i = 0; i < itemCount; i++) { if (areEqual(comboBox, convertElementToString(comboBox, itemAt(comboBox, i)), toSelect)) { selectItem(comboBox, i); return; } } // While actions are supposed to represent real user actions, it's possible that the current environment does not // match sufficiently, so we need to throw an appropriate exception that can be used to diagnose the problem. throw new LocationUnavailableException(concat("Unable to find item ", quote(toSelect), " among the ListComboBox contents (", new StandardRepresentation().toStringOf(contentsOf(comboBox)), ")")); } /** * Returns the <code>String</code> representation of the element under the given index, using this driver's * <code>{@link AbstractComboBoxCellReader}</code>. * * @param comboBox the target <code>AbstractComboBox</code>. * @param index the given index. * @return the value of the element under the given index. * @throws org.assertj.swing.exception.LocationUnavailableException if the given index is negative or greater than the * index of the last item in the <code>AbstractComboBox</code>. * @see #cellReader(AbstractComboBoxCellReader) */ public String value(AbstractComboBox comboBox, int index) { validateIndex(comboBox, index); return _cellReader.valueAt(comboBox, index); } /** * Returns an array of <code>String</code>s that represent the <code>{@link * ListComboBox}</code> list. Note that the current selection might not be included, since it's possible to have a * custom (edited) entry there that is not included in the default contents. * * @param comboBox the target <code>ListComboBox</code>. * @return an array of <code>String</code>s that represent the <code>ListComboBox</code> list. */ public String[] contentsOf(ListComboBox comboBox) { int itemCount = size(comboBox); String[] items = new String[itemCount]; for (int i = 0; i < itemCount; i++) { items[i] = itemAt(comboBox, i).toString(); } return items; } public String[] getContents(ListComboBox target) { ComboBoxModel model = target.getModel(); ConverterContext context = target.getConverterContext(); ObjectConverter converter = target.getConverter(); java.util.List<String> contents = new ArrayList<String>(model.getSize()); for (int i = 0; i < model.getSize(); i++) { if (converter == null) { contents.add(String.valueOf(model.getElementAt(i))); } else { contents.add(converter.toString(model.getElementAt(i), context)); } } return contents.toArray(new String[contents.size()]); } public String getValueAsString(ListComboBox target, int index) { Object o = target.getModel().getElementAt(index); ObjectConverter converter = target.getConverter(); if (converter == null) { return String.valueOf(o); } return converter.toString(o, target.getConverterContext()); } @RunsInEDT private void selectItemAtIndex(final ListComboBox comboBox, final int index) { if (!comboBox.isPopupVisible()) { clickPopupButton(comboBox); } PopupPanel panel = showPopup(comboBox); JList dropDownList = _listFinder.findDropDownList(panel); if (dropDownList != null) { _listDriver.selectItem(dropDownList, index); } else { ListComboBoxSetSelectedIndexTask.setSelectedIndex(comboBox, index); robot.waitForIdle(); } } @RunsInEDT private static void validateCanSelectItem(final AbstractComboBox comboBox, final int index) { execute(() -> { ComponentPreconditions.checkEnabledAndShowing(comboBox); AbstractComboBoxItemIndexValidator.validateIndex(comboBox, index); }); } @RunsInEDT private void hidePopupIfVisible(AbstractComboBox comboBox) { dropDownVisibleThroughComponent(comboBox, false); } }