001: package abbot.tester;
002:
003: import java.awt.*;
004: import javax.swing.JTabbedPane;
005: import javax.swing.plaf.TabbedPaneUI;
006:
007: import abbot.Log;
008: import abbot.i18n.Strings;
009: import abbot.util.ExtendedComparator;
010:
011: /** Provides encapsulation of a location on a JTabbedPane (notably a tab).
012: Use the JTabbedPaneLocation#JTabbedPaneLocation(Point) ctor to indicate a
013: specific coordinate.
014: */
015:
016: public class JTabbedPaneLocation extends ComponentLocation {
017:
018: private String tabName = null;
019: private int index = -1;
020:
021: public JTabbedPaneLocation() {
022: }
023:
024: public JTabbedPaneLocation(String tabName) {
025: this .tabName = tabName;
026: }
027:
028: public JTabbedPaneLocation(int index) {
029: if (index < 0) {
030: String msg = Strings.get(
031: "tester.JTabbedPane.invalid_index",
032: new Object[] { new Integer(index) });
033: throw new LocationUnavailableException(msg);
034: }
035: this .index = index;
036: }
037:
038: public JTabbedPaneLocation(Point p) {
039: super (p);
040: }
041:
042: protected String badFormat(String encoded) {
043: return Strings.get("location.tab.bad_format",
044: new Object[] { encoded });
045: }
046:
047: /** Convert the given row, col into a coordinate pair. */
048: private Point indexToPoint(JTabbedPane tabs, int index) {
049: if (index < 0 || index >= tabs.getTabCount()) {
050: String msg = Strings.get(
051: "tester.JTabbedPane.invalid_index",
052: new Object[] { new Integer(index) });
053: throw new LocationUnavailableException(msg);
054: }
055: Log.debug("converting index " + index);
056: TabbedPaneUI ui = tabs.getUI();
057: Rectangle rect = ui.getTabBounds(tabs, index);
058: // TODO: figure out the effects of tab layout policy
059: // sometimes tabs are not directly visible
060: if (rect == null || rect.x < 0) {
061: throw new TabNotVisibleException(index);
062: }
063: return new Point(rect.x + rect.width / 2, rect.y + rect.height
064: / 2);
065: }
066:
067: /** Return the row, col of the first object matching the given String. */
068: private int tabNameToIndex(JTabbedPane tabs, String name) {
069: for (int i = 0; i < tabs.getTabCount(); i++) {
070: String value = tabs.getTitleAt(i);
071: if (ExtendedComparator.stringsMatch(name, value))
072: return i;
073: }
074: return -1;
075: }
076:
077: /** @throws TabNotVisibleException if the tab is not visible */
078: public Point getPoint(Component c) {
079: JTabbedPane tabs = (JTabbedPane) c;
080: int idx = index;
081: if (tabName != null) {
082: if ((idx = tabNameToIndex(tabs, tabName)) == -1) {
083: String msg = Strings.get(
084: "tester.JTabbedPane.invalid_name",
085: new Object[] { tabName });
086: throw new LocationUnavailableException(msg);
087: }
088: }
089: if (idx != -1) {
090: return indexToPoint(tabs, idx);
091: }
092: return super .getPoint(tabs);
093: }
094:
095: /** @throws TabNotVisibleException if the tab is not visible */
096: public Rectangle getBounds(Component c) {
097: JTabbedPane tabs = (JTabbedPane) c;
098: TabbedPaneUI ui = tabs.getUI();
099: // kinda hacky
100: Point p = getPoint(tabs);
101: int idx = ui.tabForCoordinate(tabs, p.x, p.y);
102: if (idx != -1) {
103: Rectangle bounds = ui.getTabBounds(tabs, idx);
104: if (bounds == null) {
105: throw new TabNotVisibleException(idx);
106: }
107: return bounds;
108: }
109: return super .getBounds(c);
110: }
111:
112: // FIXME if they correspond to the same tab, are they equal?
113: public boolean equals(Object o) {
114: if (o instanceof JTabbedPaneLocation) {
115: JTabbedPaneLocation loc = (JTabbedPaneLocation) o;
116: if (tabName != null)
117: return tabName.equals(loc.tabName);
118: if (index != -1)
119: return index == loc.index;
120: }
121: return super .equals(o);
122: }
123:
124: public String toString() {
125: if (tabName != null)
126: return encodeValue(tabName);
127: if (index != -1)
128: return encodeIndex(index);
129: return super .toString();
130: }
131:
132: public ComponentLocation parse(String encoded) {
133: encoded = encoded.trim();
134: if (isValue(encoded)) {
135: tabName = parseValue(encoded);
136: return this ;
137: }
138: if (isIndex(encoded)) {
139: index = parseIndex(encoded);
140: return this ;
141: }
142: return super .parse(encoded);
143: }
144:
145: /** This exception is thrown if a given tab is not currently visible.
146: Some LAFs may not display all tabs concurrently. OSX, for example,
147: puts tabs that don't fit into a popup menu.
148: */
149: class TabNotVisibleException extends LocationUnavailableException {
150: public int index;
151:
152: public TabNotVisibleException(int index) {
153: super ("Tab " + index + " not visible");
154: this.index = index;
155: }
156: }
157: }
|