001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package javax.swing;
019:
020: import java.awt.Color;
021: import java.awt.Component;
022: import java.awt.Point;
023: import java.awt.Rectangle;
024: import java.awt.event.InputEvent;
025: import java.awt.event.MouseEvent;
026: import java.io.Serializable;
027: import java.util.Vector;
028: import javax.accessibility.Accessible;
029: import javax.accessibility.AccessibleContext;
030: import javax.accessibility.AccessibleRole;
031: import javax.accessibility.AccessibleSelection;
032: import javax.swing.event.ChangeEvent;
033: import javax.swing.event.ChangeListener;
034: import javax.swing.plaf.TabbedPaneUI;
035: import javax.swing.plaf.UIResource;
036: import org.apache.harmony.luni.util.NotImplementedException;
037: import org.apache.harmony.x.swing.StringConstants;
038:
039: import org.apache.harmony.x.swing.internal.nls.Messages;
040:
041: /**
042: * <p>
043: * <i>JTabbedPane</i>
044: * </p>
045: * <h3>Implementation Notes:</h3>
046: * <ul>
047: * <li>The <code>serialVersionUID</code> fields are explicitly declared as a performance
048: * optimization, not as a guarantee of serialization compatibility.</li>
049: * </ul>
050: */
051: public class JTabbedPane extends JComponent implements Serializable,
052: Accessible, SwingConstants {
053: private static final long serialVersionUID = 1671634173365704280L;
054:
055: private static final int NOT_FOUND = -1;
056:
057: // TODO: implement
058: protected class AccessibleJTabbedPane extends AccessibleJComponent
059: implements AccessibleSelection, ChangeListener {
060: private static final long serialVersionUID = 8645220594633986096L;
061:
062: public AccessibleJTabbedPane() {
063: }
064:
065: public void addAccessibleSelection(int i)
066: throws NotImplementedException {
067: throw new NotImplementedException();
068: }
069:
070: public void clearAccessibleSelection()
071: throws NotImplementedException {
072: throw new NotImplementedException();
073: }
074:
075: @Override
076: public Accessible getAccessibleAt(Point p)
077: throws NotImplementedException {
078: throw new NotImplementedException();
079: }
080:
081: @Override
082: public Accessible getAccessibleChild(int i)
083: throws NotImplementedException {
084: throw new NotImplementedException();
085: }
086:
087: @Override
088: public int getAccessibleChildrenCount()
089: throws NotImplementedException {
090: throw new NotImplementedException();
091: }
092:
093: @Override
094: public AccessibleRole getAccessibleRole()
095: throws NotImplementedException {
096: throw new NotImplementedException();
097: }
098:
099: @Override
100: public AccessibleSelection getAccessibleSelection()
101: throws NotImplementedException {
102: throw new NotImplementedException();
103: }
104:
105: public Accessible getAccessibleSelection(int i)
106: throws NotImplementedException {
107: throw new NotImplementedException();
108: }
109:
110: public int getAccessibleSelectionCount()
111: throws NotImplementedException {
112: throw new NotImplementedException();
113: }
114:
115: public boolean isAccessibleChildSelected(int i)
116: throws NotImplementedException {
117: throw new NotImplementedException();
118: }
119:
120: public void removeAccessibleSelection(int i)
121: throws NotImplementedException {
122: throw new NotImplementedException();
123: }
124:
125: public void selectAllAccessibleSelection()
126: throws NotImplementedException {
127: throw new NotImplementedException();
128: }
129:
130: public void stateChanged(ChangeEvent e)
131: throws NotImplementedException {
132: throw new NotImplementedException();
133: }
134: }
135:
136: protected class ModelListener implements ChangeListener,
137: Serializable {
138: private static final long serialVersionUID = 1L;
139:
140: public void stateChanged(ChangeEvent e) {
141: fireStateChanged();
142: }
143: }
144:
145: private class JTabInfo extends AbstractButton {
146: private static final long serialVersionUID = 1L;
147:
148: private Component comp;
149:
150: private boolean enabled = true;
151:
152: private Icon disabledIcon;
153:
154: public JTabInfo(String title, Icon icon, Component comp,
155: String tip) {
156: setModel(new DefaultButtonModel());
157: setText(title);
158: setIcon(icon);
159: setComp(comp);
160: setToolTipText(tip);
161: setBackground(JTabbedPane.this .getBackground());
162: setForeground(JTabbedPane.this .getForeground());
163: setMnemonic(-1);
164: }
165:
166: public void setComp(Component comp) {
167: this .comp = comp;
168: }
169:
170: public Component getComp() {
171: return comp;
172: }
173:
174: @Override
175: public boolean isEnabled() {
176: return enabled;
177: }
178:
179: @Override
180: public void setEnabled(boolean enabled) {
181: this .enabled = enabled;
182: }
183:
184: @Override
185: public void setDisabledIcon(Icon icon) {
186: disabledIcon = icon;
187: }
188:
189: @Override
190: public Icon getDisabledIcon() {
191: return disabledIcon;
192: }
193: }
194:
195: public static final int SCROLL_TAB_LAYOUT = 1;
196:
197: public static final int WRAP_TAB_LAYOUT = 0;
198:
199: protected transient ChangeEvent changeEvent = new ChangeEvent(this );
200:
201: protected ChangeListener changeListener;
202:
203: protected SingleSelectionModel model;
204:
205: protected int tabPlacement = TOP;
206:
207: private int tabLayoutPolicy = WRAP_TAB_LAYOUT;
208:
209: private Vector<JTabInfo> tabInfos = new Vector<JTabInfo>(2);
210:
211: public JTabbedPane() {
212: this (TOP, WRAP_TAB_LAYOUT);
213: }
214:
215: public JTabbedPane(int tabPlacement) {
216: this (tabPlacement, WRAP_TAB_LAYOUT);
217: }
218:
219: public JTabbedPane(int tabPlacement, int tabLayoutPolicy) {
220: setModel(new DefaultSingleSelectionModel());
221: setTabPlacement(tabPlacement);
222: setTabLayoutPolicy(tabLayoutPolicy);
223: ToolTipManager.sharedInstance().registerComponent(this );
224: updateUI();
225: }
226:
227: /**
228: * If <code>component</code> is <code>instanceof UIResource</code>,
229: * it is added to the tabbed pane without creating a new tab. It can be
230: * used in UI's to add custom components.
231: */
232: @Override
233: public Component add(Component component) {
234: if (component instanceof UIResource) {
235: addImpl(component, null, -1);
236: } else {
237: insertTab(component.getName(), null, component, null,
238: getTabCount());
239: }
240: return component;
241: }
242:
243: @Override
244: public Component add(Component component, int index) {
245: insertTab(component.getName(), null, component, null, index);
246: return component;
247: }
248:
249: @Override
250: public void add(Component component, Object constraints) {
251: add(component, constraints, getTabCount());
252: }
253:
254: @Override
255: public void add(Component component, Object constraints, int index) {
256: Icon icon = null;
257: String title = null;
258: if (constraints instanceof Icon) {
259: icon = (Icon) constraints;
260: } else if (constraints instanceof String) {
261: title = (String) constraints;
262: } else {
263: title = component.getName();
264: }
265: insertTab(title, icon, component, null, index);
266: }
267:
268: @Override
269: public Component add(String title, Component component) {
270: insertTab(title, null, component, null, getTabCount());
271: return component;
272: }
273:
274: public void addTab(String title, Component component) {
275: insertTab(title, null, component, null, getTabCount());
276: }
277:
278: public void addTab(String title, Icon icon, Component component) {
279: insertTab(title, icon, component, null, getTabCount());
280: }
281:
282: public void addTab(String title, Icon icon, Component component,
283: String tip) {
284: insertTab(title, icon, component, tip, getTabCount());
285: }
286:
287: public void addChangeListener(ChangeListener l) {
288: listenerList.add(ChangeListener.class, l);
289: }
290:
291: public void removeChangeListener(ChangeListener l) {
292: listenerList.remove(ChangeListener.class, l);
293: }
294:
295: public ChangeListener[] getChangeListeners() {
296: return listenerList.getListeners(ChangeListener.class);
297: }
298:
299: protected ChangeListener createChangeListener() {
300: return new ModelListener();
301: }
302:
303: protected void fireStateChanged() {
304: ChangeListener[] listeners = getChangeListeners();
305: for (int i = 0; i < listeners.length; i++) {
306: listeners[i].stateChanged(changeEvent);
307: }
308: }
309:
310: @Override
311: public AccessibleContext getAccessibleContext() {
312: return accessibleContext == null ? (accessibleContext = new AccessibleJTabbedPane())
313: : accessibleContext;
314: }
315:
316: public Rectangle getBoundsAt(int index) {
317: return getUI() != null ? getUI().getTabBounds(this , index)
318: : null;
319: }
320:
321: public void setComponentAt(int index, Component comp) {
322: int oldIndex = indexOfComponent(comp);
323: if (oldIndex == index) {
324: return;
325: }
326: JTabInfo tabInfo = getTabAt(index);
327: if (oldIndex != NOT_FOUND) {
328: removeTabAt(oldIndex);
329: }
330: if (tabInfo.getComp() != comp) {
331: removeComponentFromContainer(tabInfo.getComp());
332: addComponentToContainer(comp);
333: }
334: tabInfo.setComp(comp);
335: }
336:
337: public Component getComponentAt(int index) {
338: return getTabAt(index).getComp();
339: }
340:
341: public int getTabCount() {
342: return tabInfos.size();
343: }
344:
345: public int getTabRunCount() {
346: return getUI() != null ? getUI().getTabRunCount(this ) : 0;
347: }
348:
349: public void setTitleAt(int index, String title) {
350: getTabAt(index).setText(title);
351: repaint();
352: }
353:
354: public String getTitleAt(int index) {
355: return getTabAt(index).getText();
356: }
357:
358: @Override
359: public String getToolTipText(MouseEvent event) {
360: int index = indexAtLocation(event.getX(), event.getY());
361: return index > NOT_FOUND ? getToolTipTextAt(index) : super
362: .getToolTipText(event);
363: }
364:
365: public void setToolTipTextAt(int index, String toolTipText) {
366: getTabAt(index).setToolTipText(toolTipText);
367: }
368:
369: public String getToolTipTextAt(int index) {
370: return getTabAt(index).getToolTipText();
371: }
372:
373: public int indexAtLocation(int x, int y) {
374: return getUI() != null ? getUI().tabForCoordinate(this , x, y)
375: : NOT_FOUND;
376: }
377:
378: public int indexOfComponent(Component comp) {
379: for (int i = 0; i < tabInfos.size(); i++) {
380: if (comp == getComponentAt(i)) {
381: return i;
382: }
383: }
384: return NOT_FOUND;
385: }
386:
387: public int indexOfTab(Icon icon) {
388: for (int i = 0; i < tabInfos.size(); i++) {
389: if (icon == getIconAt(i)) {
390: return i;
391: }
392: }
393: return -1;
394: }
395:
396: public int indexOfTab(String title) {
397: for (int i = 0; i < tabInfos.size(); i++) {
398: if (title == getTitleAt(i)) {
399: return i;
400: }
401: }
402: return -1;
403: }
404:
405: public void insertTab(String title, Icon icon, Component comp,
406: String tip, int index) {
407: int oldIndex = comp != null ? indexOfComponent(comp)
408: : NOT_FOUND;
409: if (oldIndex != NOT_FOUND) {
410: tabInfos.remove(oldIndex);
411: }
412: String realTitle = title == null ? "" : title;
413: JTabInfo tabInfo = new JTabInfo(realTitle, icon, comp, tip);
414: if (index == -1) {
415: index = tabInfos.size();
416: }
417: tabInfos.add(index, tabInfo);
418: if (oldIndex == NOT_FOUND) {
419: addComponentToContainer(comp);
420: }
421: if (getTabCount() == 1) {
422: setSelectedIndex(0);
423: } else if (index <= getSelectedIndex()
424: && (oldIndex == NOT_FOUND || oldIndex > getSelectedIndex())) {
425: setSelectedIndex(getSelectedIndex() + 1);
426: }
427: repaint();
428: }
429:
430: @Override
431: protected String paramString() {
432: return super .paramString();
433: }
434:
435: /**
436: * If <code>component</code> is <code>instanceof UIResource</code>,
437: * it is removed without removing any tab.
438: */
439: @Override
440: public void remove(Component comp) {
441: if (comp instanceof UIResource) {
442: removeComponentFromContainer(comp);
443: return;
444: }
445: int index = indexOfComponent(comp);
446: if (index != NOT_FOUND) {
447: removeTabAt(index);
448: }
449: }
450:
451: /**
452: * If <code>component</code> is <code>instanceof UIResource</code>,
453: * it is removed without removing any tab.
454: */
455: @Override
456: public void remove(int index) {
457: if (getComponent(index) instanceof UIResource) {
458: super .remove(index);
459: return;
460: }
461: removeTabAt(index);
462: }
463:
464: public void removeTabAt(int index) {
465: Component comp = getComponentAt(index);
466: if (getSelectedIndex() >= getTabCount() - 1) {
467: setSelectedIndex(getTabCount() - 2);
468: }
469: tabInfos.remove(index);
470: removeComponentFromContainer(comp);
471: comp.setVisible(true);
472: repaint();
473: }
474:
475: @Override
476: public void removeAll() {
477: super .removeAll();
478: tabInfos.removeAllElements();
479: }
480:
481: public void setBackgroundAt(int index, Color background) {
482: Color realBackground = background == null ? getBackground()
483: : background;
484: getTabAt(index).setBackground(realBackground);
485: repaint();
486: }
487:
488: public Color getBackgroundAt(int index) {
489: return getTabAt(index).getBackground();
490: }
491:
492: public void setForegroundAt(int index, Color foreground) {
493: Color realForeground = foreground == null ? getForeground()
494: : foreground;
495: getTabAt(index).setForeground(realForeground);
496: repaint();
497: }
498:
499: public Color getForegroundAt(int index) {
500: return getTabAt(index).getForeground();
501: }
502:
503: public void setDisabledIconAt(int index, Icon disabledIcon) {
504: getTabAt(index).setDisabledIcon(disabledIcon);
505: }
506:
507: public Icon getDisabledIconAt(int index) {
508: return getTabAt(index).getDisabledIcon();
509: }
510:
511: public void setDisplayedMnemonicIndexAt(int tabIndex,
512: int mnemonicIndex) {
513: getTabAt(tabIndex).setDisplayedMnemonicIndex(mnemonicIndex);
514: }
515:
516: public int getDisplayedMnemonicIndexAt(int index) {
517: return getTabAt(index).getDisplayedMnemonicIndex();
518: }
519:
520: public void setEnabledAt(int index, boolean enabled) {
521: getTabAt(index).setEnabled(enabled);
522: repaint();
523: }
524:
525: public boolean isEnabledAt(int index) {
526: return getTabAt(index).isEnabled();
527: }
528:
529: public void setIconAt(int index, Icon icon) {
530: getTabAt(index).setIcon(icon);
531: repaint();
532: }
533:
534: public Icon getIconAt(int index) {
535: return getTabAt(index).getIcon();
536: }
537:
538: public void setMnemonicAt(int tabIndex, int mnemonic) {
539: int oldValue = getMnemonicAt(tabIndex);
540: if (oldValue == mnemonic) {
541: return;
542: }
543: InputMap inputMap = getInputMap(WHEN_IN_FOCUSED_WINDOW, true);
544: inputMap.remove(KeyStroke.getKeyStroke(oldValue,
545: InputEvent.ALT_DOWN_MASK));
546: inputMap.put(KeyStroke.getKeyStroke(mnemonic,
547: InputEvent.ALT_DOWN_MASK),
548: StringConstants.MNEMONIC_ACTION);
549: getTabAt(tabIndex).setMnemonic(mnemonic);
550: repaint();
551: }
552:
553: public int getMnemonicAt(int index) {
554: return getTabAt(index).getMnemonic();
555: }
556:
557: public void setModel(SingleSelectionModel model) {
558: if (changeListener == null) {
559: changeListener = createChangeListener();
560: }
561: SingleSelectionModel oldValue = this .model;
562: if (oldValue != null) {
563: oldValue.removeChangeListener(changeListener);
564: }
565: this .model = model;
566: if (model != null) {
567: model.addChangeListener(changeListener);
568: }
569: firePropertyChange("model", oldValue, model);
570: }
571:
572: public SingleSelectionModel getModel() {
573: return model;
574: }
575:
576: public void setSelectedComponent(Component comp) {
577: int index = indexOfComponent(comp);
578: if (index == NOT_FOUND) {
579: throw new IllegalArgumentException(Messages
580: .getString("swing.34")); //$NON-NLS-1$
581: }
582: setSelectedIndex(index);
583: }
584:
585: public Component getSelectedComponent() {
586: return getModel().isSelected() ? getComponentAt(getSelectedIndex())
587: : null;
588: }
589:
590: public void setSelectedIndex(int index) {
591: if (index < -1 || index >= getTabCount()) {
592: throw new IndexOutOfBoundsException(Messages
593: .getString("swing.35")); //$NON-NLS-1$
594: }
595: getModel().setSelectedIndex(index);
596: }
597:
598: public int getSelectedIndex() {
599: return getModel().getSelectedIndex();
600: }
601:
602: public void setTabLayoutPolicy(int tabLayoutPolicy) {
603: if (tabLayoutPolicy != WRAP_TAB_LAYOUT
604: && tabLayoutPolicy != SCROLL_TAB_LAYOUT) {
605: throw new IllegalArgumentException(Messages
606: .getString("swing.36")); //$NON-NLS-1$
607: }
608: int oldValue = this .tabLayoutPolicy;
609: this .tabLayoutPolicy = tabLayoutPolicy;
610: firePropertyChange("tabLayoutPolicy", oldValue, tabLayoutPolicy);
611: }
612:
613: public int getTabLayoutPolicy() {
614: return tabLayoutPolicy;
615: }
616:
617: public void setTabPlacement(int tabPlacement) {
618: if (tabPlacement != TOP && tabPlacement != BOTTOM
619: && tabPlacement != LEFT && tabPlacement != RIGHT) {
620: throw new IllegalArgumentException(Messages
621: .getString("swing.37")); //$NON-NLS-1$
622: }
623: int oldValue = this .tabPlacement;
624: this .tabPlacement = tabPlacement;
625: firePropertyChange("tabPlacement", oldValue, tabPlacement);
626: }
627:
628: public int getTabPlacement() {
629: return tabPlacement;
630: }
631:
632: public void setUI(TabbedPaneUI ui) {
633: super .setUI(ui);
634: }
635:
636: public TabbedPaneUI getUI() {
637: return (TabbedPaneUI) ui;
638: }
639:
640: @Override
641: public String getUIClassID() {
642: return "TabbedPaneUI";
643: }
644:
645: @Override
646: public void updateUI() {
647: setUI((TabbedPaneUI) UIManager.getUI(this ));
648: }
649:
650: private JTabInfo getTabAt(int index) {
651: return tabInfos.get(index);
652: }
653:
654: private void addComponentToContainer(Component comp) {
655: if (comp != null) {
656: comp.setVisible(false);
657: if (getComponentZOrder(comp) == -1) {
658: addImpl(comp, null, -1);
659: }
660: }
661: }
662:
663: private void removeComponentFromContainer(Component comp) {
664: int componentIndex = getComponentZOrder(comp);
665: if (componentIndex != -1) {
666: super.remove(componentIndex);
667: }
668: }
669: }
|