001    /*
002     * Created on Apr 12, 2008
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
005     * in compliance with the License. You may obtain a copy of the License at
006     *
007     * http://www.apache.org/licenses/LICENSE-2.0
008     *
009     * Unless required by applicable law or agreed to in writing, software distributed under the License
010     * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
011     * or implied. See the License for the specific language governing permissions and limitations under
012     * the License.
013     *
014     * Copyright @2008-2010 the original author or authors.
015     */
016    package org.fest.swing.driver;
017    
018    import static org.fest.swing.driver.ModelValueToString.asText;
019    import static org.fest.swing.edt.GuiActionRunner.execute;
020    
021    import java.awt.Component;
022    
023    import javax.swing.*;
024    
025    import org.fest.swing.annotation.RunsInCurrentThread;
026    import org.fest.swing.cell.JComboBoxCellReader;
027    import org.fest.swing.edt.GuiQuery;
028    
029    /**
030     * Understands the default implementation of <code>{@link JComboBoxCellReader}</code>.
031     *
032     * @author Alex Ruiz
033     * @author Yvonne Wang
034     */
035    public class BasicJComboBoxCellReader implements JComboBoxCellReader {
036    
037      private static final JList REFERENCE_JLIST = newJList();
038    
039      private static JList newJList() {
040        return execute(new GuiQuery<JList>() {
041          protected JList executeInEDT() {
042            return new JList();
043          }
044        });
045      }
046    
047      private final CellRendererReader rendererReader;
048    
049      /**
050       * Creates a new </code>{@link BasicJComboBoxCellReader}</code> that uses a
051       * <code>{@link BasicCellRendererReader}</code> to read the value from the cell renderer component in a
052       * <code>JComboBox</code>.
053       */
054      public BasicJComboBoxCellReader() {
055        this(new BasicCellRendererReader());
056      }
057    
058      /**
059       * Creates a new </code>{@link BasicJComboBoxCellReader}</code>.
060       * @param rendererReader knows how to read values from the cell renderer component in a
061       * <code>JComboBox</code>.
062       * @throws NullPointerException if <code>r</code> is <code>null</code>.
063       */
064      public BasicJComboBoxCellReader(CellRendererReader rendererReader) {
065        if (rendererReader == null)
066          throw new NullPointerException("CellRendererReader should not be null");
067        this.rendererReader = rendererReader;
068      }
069    
070      /**
071       * Returns the internal value of a cell in a <code>{@link JComboBox}</code> as expected in a test.
072       * <p>
073       * <b>Note:</b> This method is <b>not</b> guaranteed to be executed in the event dispatch thread (EDT.) Clients are
074       * responsible for calling this method from the EDT.
075       * </p>
076       * @param comboBox the given <code>JComboBox</code>.
077       * @param index the index of the cell.
078       * @return the internal value of a cell in a <code>JComboBox</code> as expected in a test.
079       * @see CellRendererReader#valueFrom(Component)
080       */
081      @RunsInCurrentThread
082      public String valueAt(JComboBox comboBox, int index) {
083        Component c = cellRendererComponent(comboBox, index);
084        String value = (c != null) ? rendererReader.valueFrom(c) : null;
085        if (value != null) return value;
086        return asText(comboBox.getItemAt(index));
087      }
088    
089      @RunsInCurrentThread
090      private Component cellRendererComponent(JComboBox comboBox, int index) {
091        Object item = comboBox.getItemAt(index);
092        ListCellRenderer renderer = comboBox.getRenderer();
093        return renderer.getListCellRendererComponent(REFERENCE_JLIST, item, index, true, true);
094      }
095    }