001 /* 002 * Created on Jan 27, 2008 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 005 * 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 is distributed on 010 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 011 * specific language governing permissions and limitations under the License. 012 * 013 * Copyright @2008-2010 the original author or authors. 014 */ 015 package org.fest.swing.driver; 016 017 import static java.lang.String.valueOf; 018 import static org.fest.swing.driver.JTabbedPaneTabIndexQuery.indexOfTab; 019 import static org.fest.util.Strings.concat; 020 021 import java.awt.Point; 022 import java.awt.Rectangle; 023 024 import javax.swing.JTabbedPane; 025 026 import org.fest.swing.annotation.RunsInCurrentThread; 027 import org.fest.swing.exception.LocationUnavailableException; 028 import org.fest.swing.util.StringTextMatcher; 029 import org.fest.swing.util.TextMatcher; 030 import org.fest.util.VisibleForTesting; 031 032 /** 033 * Understands a location on a <code>{@link JTabbedPane}</code> (notably a tab). 034 * 035 * @author Alex Ruiz 036 * @author Yvonne Wang 037 */ 038 public class JTabbedPaneLocation { 039 040 /** 041 * Returns the index of the first tab that matches the given <code>String</code>. 042 * <p> 043 * <b>Note:</b> This method is <b>not</b> guaranteed to be executed in the event dispatch thread (EDT.) Clients are 044 * responsible for calling this method from the EDT. 045 * </p> 046 * @param tabbedPane the target <code>JTabbedPane</code>. 047 * @param title the title to match. 048 * @return the index of the first tab that matches the given <code>String</code>. 049 * @throws LocationUnavailableException if a tab matching the given title could not be found. 050 */ 051 @RunsInCurrentThread 052 public int indexOf(JTabbedPane tabbedPane, String title) { 053 return indexOf(tabbedPane, new StringTextMatcher(title)); 054 } 055 056 /** 057 * Returns the index of the first tab whose title matches the value in the given <code>{@link TextMatcher}</code>. 058 * <p> 059 * <b>Note:</b> This method is <b>not</b> guaranteed to be executed in the event dispatch thread (EDT.) Clients are 060 * responsible for calling this method from the EDT. 061 * </p> 062 * @param tabbedPane the target <code>JTabbedPane</code>. 063 * @param matcher indicates if the text of the <code>JTabbedPane</code> matches the value we are looking for. 064 * @return the index of the first tab that matches the given <code>String</code>. 065 * @throws LocationUnavailableException if a tab matching the given title could not be found. 066 */ 067 @RunsInCurrentThread 068 public int indexOf(final JTabbedPane tabbedPane, final TextMatcher matcher) { 069 int index = indexOfTab(tabbedPane, matcher); 070 if (index >= 0) return index; 071 throw new LocationUnavailableException(concat( 072 "Unable to find a tab with title matching ", matcher.description(), " ", matcher.formattedValues())); 073 } 074 075 /** 076 * Returns the coordinates of the tab under the given index. 077 * <p> 078 * <b>Note:</b> This method is <b>not</b> guaranteed to be executed in the event dispatch thread (EDT.) Clients are 079 * responsible for calling this method from the EDT. 080 * </p> 081 * @param tabbedPane the target <code>JTabbedPane</code>. 082 * @param index the given index. 083 * @return the coordinates of the tab under the given index. 084 * @throws IndexOutOfBoundsException if the given index is negative or out of bounds. 085 * @throws LocationUnavailableException if the tab under the given index is not visible. 086 */ 087 @RunsInCurrentThread 088 public Point pointAt(final JTabbedPane tabbedPane, final int index) { 089 validateIndex(tabbedPane, index); 090 Rectangle rect = tabbedPane.getUI().getTabBounds(tabbedPane, index); 091 // From Abbot: TODO figure out the effects of tab layout policy sometimes tabs are not directly visible 092 if (rect == null || rect.x < 0) 093 throw new LocationUnavailableException(concat("The tab '", valueOf(index), "' is not visible")); 094 return new Point(rect.x + rect.width / 2, rect.y + rect.height / 2); 095 } 096 097 @VisibleForTesting 098 @RunsInCurrentThread 099 void validateIndex(JTabbedPane tabbedPane, int index) { 100 int max = tabbedPane.getTabCount() - 1; 101 if (index >= 0 && index <= max) return; 102 throw new IndexOutOfBoundsException(concat( 103 "Index <", valueOf(index), "> is not within the JTabbedPane bounds of <0> and <", valueOf(max), "> (inclusive)")); 104 } 105 }