1:
37:
38:
39: package ;
40:
41: import ;
42: import ;
43: import ;
44: import ;
45: import ;
46: import ;
47: import ;
48: import ;
49: import ;
50: import ;
51: import ;
52: import ;
53: import ;
54: import ;
55: import ;
56: import ;
57: import ;
58: import ;
59: import ;
60: import ;
61:
62: import ;
63: import ;
64: import ;
65: import ;
66: import ;
67: import ;
68: import ;
69: import ;
70: import ;
71: import ;
72: import ;
73: import ;
74: import ;
75: import ;
76: import ;
77: import ;
78: import ;
79: import ;
80: import ;
81: import ;
82: import ;
83:
84:
92: public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
93: {
94:
95: static class NavigateAction extends AbstractAction
96: {
97: int direction;
98:
99: NavigateAction(String name, int dir)
100: {
101: super(name);
102: direction = dir;
103: }
104:
105: public void actionPerformed(ActionEvent event)
106: {
107: JTabbedPane tp = (JTabbedPane) event.getSource();
108: BasicTabbedPaneUI ui = (BasicTabbedPaneUI) tp.getUI();
109:
110: ui.navigateSelectedTab(direction);
111: }
112:
113: }
114:
115: static class NavigatePageDownAction extends AbstractAction
116: {
117:
118: public NavigatePageDownAction()
119: {
120: super("navigatePageDown");
121: }
122:
123: public void actionPerformed(ActionEvent event)
124: {
125: JTabbedPane tp = (JTabbedPane) event.getSource();
126: BasicTabbedPaneUI ui = (BasicTabbedPaneUI) tp.getUI();
127:
128: int i = tp.getSelectedIndex();
129:
130: if (i < 0)
131: i = 0;
132:
133: ui.selectNextTabInRun(i);
134: }
135:
136: }
137:
138: static class NavigatePageUpAction extends AbstractAction
139: {
140:
141: public NavigatePageUpAction()
142: {
143: super("navigatePageUp");
144: }
145:
146: public void actionPerformed(ActionEvent event)
147: {
148: JTabbedPane tp = (JTabbedPane) event.getSource();
149: BasicTabbedPaneUI ui = (BasicTabbedPaneUI) tp.getUI();
150:
151: int i = tp.getSelectedIndex();
152:
153: if (i < 0)
154: i = 0;
155:
156: ui.selectPreviousTabInRun(i);
157:
158: }
159: }
160:
161: static class RequestFocusAction extends AbstractAction
162: {
163:
164: public RequestFocusAction()
165: {
166: super("requestFocus");
167: }
168:
169: public void actionPerformed(ActionEvent event)
170: {
171: ((JTabbedPane) event.getSource()).requestFocus();
172: }
173:
174: }
175:
176: static class RequestFocusForVisibleComponentAction extends AbstractAction
177: {
178:
179: public RequestFocusForVisibleComponentAction()
180: {
181: super("requestFocusForVisibleComponent");
182: }
183:
184: public void actionPerformed(ActionEvent event)
185: {
186: JTabbedPane tp = (JTabbedPane) event.getSource();
187:
188:
189:
190:
191:
192: tp.getSelectedComponent().requestFocus();
193: }
194:
195: }
196:
197:
212: public class FocusHandler extends FocusAdapter
213: {
214:
219: public void focusGained(FocusEvent e)
220: {
221: Object source = e.getSource();
222: if (source == panel )
223: tabPane.requestFocus();
224: else if (source == tabPane)
225: tabPane.repaint();
226: }
227:
228:
233: public void focusLost(FocusEvent e)
234: {
235: if (e.getOppositeComponent() == tabPane.getSelectedComponent())
236: tabPane.requestFocus();
237: else if (e.getSource() == tabPane)
238: tabPane.repaint();
239: }
240: }
241:
242:
251: public class MouseHandler extends MouseAdapter
252: {
253: public void mouseReleased(MouseEvent e)
254: {
255:
256: }
257:
258:
264: public void mousePressed(MouseEvent e)
265: {
266: Object s = e.getSource();
267: int placement = tabPane.getTabPlacement();
268:
269: if (s == incrButton)
270: {
271: if(!incrButton.isEnabled())
272: return;
273:
274: currentScrollLocation++;
275:
276: switch (placement)
277: {
278: case JTabbedPane.TOP:
279: case JTabbedPane.BOTTOM:
280: currentScrollOffset = getTabAreaInsets(placement).left;
281: for (int i = 0; i < currentScrollLocation; i++)
282: currentScrollOffset += rects[i].width;
283: break;
284: default:
285: currentScrollOffset = getTabAreaInsets(placement).top;
286: for (int i = 0; i < currentScrollLocation; i++)
287: currentScrollOffset += rects[i].height;
288: break;
289: }
290:
291: updateViewPosition();
292: updateButtons();
293:
294: tabPane.repaint();
295: }
296: else if (s == decrButton)
297: {
298: if(!decrButton.isEnabled())
299: return;
300:
301:
302:
303:
304: if (currentScrollLocation > 0)
305: currentScrollLocation--;
306:
307:
308: currentScrollOffset = 0;
309:
310: switch (placement)
311: {
312: case JTabbedPane.TOP:
313: case JTabbedPane.BOTTOM:
314:
315: if (currentScrollLocation > 0)
316: currentScrollOffset = getTabAreaInsets(placement).left;
317:
318: for (int i = 0; i < currentScrollLocation; i++)
319: currentScrollOffset += rects[i].width;
320: break;
321: default:
322:
323: if (currentScrollLocation > 0)
324: currentScrollOffset = getTabAreaInsets(placement).top;
325:
326: for (int i = 0; i < currentScrollLocation; i++)
327: currentScrollOffset += rects[i].height;
328: }
329:
330: updateViewPosition();
331: updateButtons();
332:
333: tabPane.repaint();
334: } else if (tabPane.isEnabled())
335: {
336: int index = tabForCoordinate(tabPane, e.getX(), e.getY());
337: if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT
338: && s == panel)
339: scrollTab(index, placement);
340:
341: tabPane.setSelectedIndex(index);
342: }
343:
344: }
345:
346:
352: public void mouseEntered(MouseEvent ev)
353: {
354: int tabIndex = tabForCoordinate(tabPane, ev.getX(), ev.getY());
355: setRolloverTab(tabIndex);
356: }
357:
358:
364: public void mouseExited(MouseEvent ev)
365: {
366: setRolloverTab(-1);
367: }
368:
369:
375: public void mouseMoved(MouseEvent ev)
376: {
377: int tabIndex = tabForCoordinate(tabPane, ev.getX(), ev.getY());
378: setRolloverTab(tabIndex);
379: }
380: }
381:
382:
389: public class PropertyChangeHandler implements PropertyChangeListener
390: {
391:
397: public void propertyChange(PropertyChangeEvent e)
398: {
399: if (e.getPropertyName().equals("tabLayoutPolicy"))
400: {
401: currentScrollLocation = currentScrollOffset = 0;
402:
403: layoutManager = createLayoutManager();
404:
405: tabPane.setLayout(layoutManager);
406: }
407: else if (e.getPropertyName().equals("tabPlacement")
408: && tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT)
409: {
410: incrButton = createIncreaseButton();
411: decrButton = createDecreaseButton();
412: }
413: tabPane.revalidate();
414: tabPane.repaint();
415: }
416: }
417:
418:
427: public class TabbedPaneLayout implements LayoutManager
428: {
429:
435: public void addLayoutComponent(String name, Component comp)
436: {
437:
438: }
439:
440:
444: public void calculateLayoutInfo()
445: {
446: int count = tabPane.getTabCount();
447: assureRectsCreated(count);
448: calculateTabRects(tabPane.getTabPlacement(), count);
449: tabRunsDirty = false;
450: }
451:
452:
460: protected Dimension calculateSize(boolean minimum)
461: {
462: int tabPlacement = tabPane.getTabPlacement();
463:
464: int width = 0;
465: int height = 0;
466: Component c;
467: Dimension dims;
468:
469:
470:
471: int count = tabPane.getTabCount();
472: for (int i = 0; i < count; i++)
473: {
474: c = tabPane.getComponentAt(i);
475: if (c == null)
476: continue;
477: dims = minimum ? c.getMinimumSize() : c.getPreferredSize();
478: if (dims != null)
479: {
480: height = Math.max(height, dims.height);
481: width = Math.max(width, dims.width);
482: }
483: }
484:
485: Insets tabAreaInsets = getTabAreaInsets(tabPlacement);
486: if (tabPlacement == SwingConstants.TOP
487: || tabPlacement == SwingConstants.BOTTOM)
488: {
489: width = Math.max(calculateMaxTabWidth(tabPlacement), width);
490:
491: height += preferredTabAreaHeight(tabPlacement,
492: width - tabAreaInsets.left
493: - tabAreaInsets.right);
494: }
495: else
496: {
497: height = Math.max(calculateMaxTabHeight(tabPlacement), height);
498:
499: width += preferredTabAreaWidth(tabPlacement,
500: height - tabAreaInsets.top
501: - tabAreaInsets.bottom);
502: }
503:
504: Insets tabPaneInsets = tabPane.getInsets();
505: return new Dimension(width + tabPaneInsets.left + tabPaneInsets.right,
506: height + tabPaneInsets.top + tabPaneInsets.bottom);
507: }
508:
509:
510:
511:
512:
513:
514:
515:
516:
517:
518:
519:
528: protected void calculateTabRects(int tabPlacement, int tabCount)
529: {
530: Insets insets = tabPane.getInsets();
531: Insets tabAreaInsets = getTabAreaInsets(tabPlacement);
532: Dimension size = tabPane.getSize();
533:
534:
535: int x;
536: int y;
537:
538: int breakAt;
539:
540:
541: switch (tabPlacement)
542: {
543: case LEFT:
544: maxTabWidth = calculateMaxTabWidth(tabPlacement);
545: x = insets.left + tabAreaInsets.left;
546: y = insets.top + tabAreaInsets.top;
547: breakAt = size.height - (insets.bottom + tabAreaInsets.bottom);
548: break;
549: case RIGHT:
550: maxTabWidth = calculateMaxTabWidth(tabPlacement);
551: x = size.width - (insets.right + tabAreaInsets.right)
552: - maxTabWidth - 1;
553: y = insets.top + tabAreaInsets.top;
554: breakAt = size.height - (insets.bottom + tabAreaInsets.bottom);
555: break;
556: case BOTTOM:
557: maxTabHeight = calculateMaxTabHeight(tabPlacement);
558: x = insets.left + tabAreaInsets.left;
559: y = size.height - (insets.bottom + tabAreaInsets.bottom)
560: - maxTabHeight - 1;
561: breakAt = size.width - (insets.right + tabAreaInsets.right);
562: break;
563: case TOP:
564: default:
565: maxTabHeight = calculateMaxTabHeight(tabPlacement);
566: x = insets.left + tabAreaInsets.left;
567: y = insets.top + tabAreaInsets.top;
568: breakAt = size.width - (insets.right + tabAreaInsets.right);
569: break;
570: }
571:
572: if (tabCount == 0)
573: return;
574:
575: FontMetrics fm = getFontMetrics();
576: runCount = 0;
577: selectedRun = -1;
578: int selectedIndex = tabPane.getSelectedIndex();
579: if (selectedIndex < 0)
580: selectedIndex = 0;
581:
582: Rectangle rect;
583:
584:
585: if (tabPlacement == SwingConstants.TOP
586: || tabPlacement == SwingConstants.BOTTOM)
587: {
588: for (int i = 0; i < tabCount; i++)
589: {
590: rect = rects[i];
591: if (i > 0)
592: {
593: rect.x = rects[i - 1].x + rects[i - 1].width;
594: }
595: else
596: {
597: tabRuns[0] = 0;
598: runCount = 1;
599: maxTabWidth = 0;
600: rect.x = x;
601: }
602: rect.width = calculateTabWidth(tabPlacement, i, fm);
603: maxTabWidth = Math.max(maxTabWidth, rect.width);
604:
605: if (rect.x != 2 + insets.left && rect.x + rect.width > breakAt)
606: {
607: if (runCount > tabRuns.length - 1)
608: expandTabRunsArray();
609: tabRuns[runCount] = i;
610: runCount++;
611: rect.x = x;
612: }
613:
614: rect.y = y;
615: rect.height = maxTabHeight;
616: if (i == selectedIndex)
617: selectedRun = runCount - 1;
618: }
619: }
620: else
621: {
622: for (int i = 0; i < tabCount; i++)
623: {
624: rect = rects[i];
625: if (i > 0)
626: {
627: rect.y = rects[i - 1].y + rects[i - 1].height;
628: }
629: else
630: {
631: tabRuns[0] = 0;
632: runCount = 1;
633: maxTabHeight = 0;
634: rect.y = y;
635: }
636: rect.height = calculateTabHeight(tabPlacement, i,
637: fm.getHeight());
638: maxTabHeight = Math.max(maxTabHeight, rect.height);
639:
640: if (rect.y != 2 + insets.top && rect.y + rect.height > breakAt)
641: {
642: if (runCount > tabRuns.length - 1)
643: expandTabRunsArray();
644: tabRuns[runCount] = i;
645: runCount++;
646: rect.y = y;
647: }
648:
649: rect.x = x;
650: rect.width = maxTabWidth;
651:
652: if (i == selectedIndex)
653: selectedRun = runCount - 1;
654: }
655: }
656:
657: if (runCount > 1)
658: {
659: int start;
660: if (tabPlacement == SwingConstants.TOP
661: || tabPlacement == SwingConstants.BOTTOM)
662: start = x;
663: else
664: start = y;
665: normalizeTabRuns(tabPlacement, tabCount, start, breakAt);
666: selectedRun = getRunForTab(tabCount, selectedIndex);
667: if (shouldRotateTabRuns(tabPlacement))
668: {
669: rotateTabRuns(tabPlacement, selectedRun);
670: }
671: }
672:
673:
674: if (runCount == 1)
675: return;
676:
677:
678: int tabRunOverlay = getTabRunOverlay(tabPlacement);
679: for (int i = runCount - 1; i >= 0; --i)
680: {
681: int start = tabRuns[i];
682: int nextIndex;
683: if (i == runCount - 1)
684: nextIndex = 0;
685: else
686: nextIndex = i + 1;
687: int next = tabRuns[nextIndex];
688: int end = next != 0 ? next - 1 : tabCount - 1;
689: if (tabPlacement == SwingConstants.TOP
690: || tabPlacement == SwingConstants.BOTTOM)
691: {
692: for (int j = start; j <= end; ++j)
693: {
694: rect = rects[j];
695: rect.y = y;
696: rect.x += getTabRunIndent(tabPlacement, i);
697: }
698: if (shouldPadTabRun(tabPlacement, i))
699: {
700: padTabRun(tabPlacement, start, end, breakAt);
701: }
702: if (tabPlacement == BOTTOM)
703: y -= maxTabHeight - tabRunOverlay;
704: else
705: y += maxTabHeight - tabRunOverlay;
706: }
707: else
708: {
709: for (int j = start; j <= end; ++j)
710: {
711: rect = rects[j];
712: rect.x = x;
713: rect.y += getTabRunIndent(tabPlacement, i);
714: }
715: if (shouldPadTabRun(tabPlacement, i))
716: {
717: padTabRun(tabPlacement, start, end, breakAt);
718: }
719: if (tabPlacement == RIGHT)
720: x -= maxTabWidth - tabRunOverlay;
721: else
722: x += maxTabWidth - tabRunOverlay;
723:
724: }
725: }
726: padSelectedTab(tabPlacement, selectedIndex);
727: }
728:
729:
736: public void layoutContainer(Container parent)
737: {
738: calculateLayoutInfo();
739:
740: int tabPlacement = tabPane.getTabPlacement();
741: Insets insets = tabPane.getInsets();
742:
743: int selectedIndex = tabPane.getSelectedIndex();
744:
745: Component selectedComponent = null;
746: if (selectedIndex >= 0)
747: selectedComponent = tabPane.getComponentAt(selectedIndex);
748:
749:
750:
751: if (selectedComponent != null)
752: {
753: setVisibleComponent(selectedComponent);
754: }
755:
756: int childCount = tabPane.getComponentCount();
757: if (childCount > 0)
758: {
759: int compX;
760: int compY;
761: int tabAreaWidth = 0;
762: int tabAreaHeight = 0;
763: switch (tabPlacement)
764: {
765: case LEFT:
766: tabAreaWidth = calculateTabAreaWidth(tabPlacement, runCount,
767: maxTabWidth);
768: compX = tabAreaWidth + insets.left + contentBorderInsets.left;
769: compY = insets.top + contentBorderInsets.top;
770: break;
771: case RIGHT:
772: tabAreaWidth = calculateTabAreaWidth(tabPlacement, runCount,
773: maxTabWidth);
774: compX = insets.left + contentBorderInsets.left;
775: compY = insets.top + contentBorderInsets.top;
776: break;
777: case BOTTOM:
778: tabAreaHeight = calculateTabAreaHeight(tabPlacement, runCount,
779: maxTabHeight);
780: compX = insets.left + contentBorderInsets.left;
781: compY = insets.top + contentBorderInsets.top;
782: break;
783: case TOP:
784: default:
785: tabAreaHeight = calculateTabAreaHeight(tabPlacement, runCount,
786: maxTabHeight);
787: compX = insets.left + contentBorderInsets.left;
788: compY = tabAreaHeight + insets.top + contentBorderInsets.top;
789: }
790: Rectangle bounds = tabPane.getBounds();
791: int compWidth = bounds.width - tabAreaWidth - insets.left
792: - insets.right - contentBorderInsets.left
793: - contentBorderInsets.right;
794: int compHeight = bounds.height - tabAreaHeight - insets.top
795: - insets.bottom - contentBorderInsets.top
796: - contentBorderInsets.bottom;
797:
798:
799: for (int i = 0; i < childCount; ++i)
800: {
801: Component c = tabPane.getComponent(i);
802: c.setBounds(compX, compY, compWidth, compHeight);
803: }
804: }
805: }
806:
807:
814: public Dimension minimumLayoutSize(Container parent)
815: {
816: return calculateSize(true);
817: }
818:
819:
820:
821:
822:
823:
824:
825:
826:
827:
828:
829:
838: protected void normalizeTabRuns(int tabPlacement, int tabCount, int start,
839: int max)
840: {
841: Insets tabAreaInsets = getTabAreaInsets(tabPlacement);
842: if (tabPlacement == SwingUtilities.TOP
843: || tabPlacement == SwingUtilities.BOTTOM)
844: {
845:
846:
847: for (int i = 1; i < runCount; i++)
848: {
849: Rectangle currRun = rects[lastTabInRun(tabCount, i)];
850: Rectangle nextRun = rects[lastTabInRun(tabCount,
851: getNextTabRun(i))];
852: int spaceInCurr = currRun.x + currRun.width;
853: int spaceInNext = nextRun.x + nextRun.width;
854:
855: int diffNow = spaceInCurr - spaceInNext;
856: int diffLater = (spaceInCurr - currRun.width)
857: - (spaceInNext + currRun.width);
858:
859: while (Math.abs(diffLater) < Math.abs(diffNow)
860: && spaceInNext + currRun.width < max)
861: {
862: tabRuns[i]--;
863: spaceInNext += currRun.width;
864: spaceInCurr -= currRun.width;
865: currRun = rects[lastTabInRun(tabCount, i)];
866: diffNow = spaceInCurr - spaceInNext;
867: diffLater = (spaceInCurr - currRun.width)
868: - (spaceInNext + currRun.width);
869: }
870:
871:
872:
873: int first = tabRuns[i];
874: int last = lastTabInRun(tabCount, i);
875: int currX = start;
876: for (int j = first; j <= last; j++)
877: {
878: rects[j].x = currX;
879: currX += rects[j].width;
880: }
881: }
882: }
883: else
884: {
885: for (int i = 1; i < runCount; i++)
886: {
887: Rectangle currRun = rects[lastTabInRun(tabCount, i)];
888: Rectangle nextRun = rects[lastTabInRun(tabCount,
889: getNextTabRun(i))];
890: int spaceInCurr = currRun.y + currRun.height;
891: int spaceInNext = nextRun.y + nextRun.height;
892:
893: int diffNow = spaceInCurr - spaceInNext;
894: int diffLater = (spaceInCurr - currRun.height)
895: - (spaceInNext + currRun.height);
896: while (Math.abs(diffLater) < Math.abs(diffNow)
897: && spaceInNext + currRun.height < max)
898: {
899: tabRuns[i]--;
900: spaceInNext += currRun.height;
901: spaceInCurr -= currRun.height;
902: currRun = rects[lastTabInRun(tabCount, i)];
903: diffNow = spaceInCurr - spaceInNext;
904: diffLater = (spaceInCurr - currRun.height)
905: - (spaceInNext + currRun.height);
906: }
907:
908:
909: int first = tabRuns[i];
910: int last = lastTabInRun(tabCount, i);
911: int currY = start;
912: for (int j = first; j <= last; j++)
913: {
914: rects[j].y = currY;
915: currY += rects[j].height;
916: }
917: }
918: }
919: }
920:
921:
928: protected void padSelectedTab(int tabPlacement, int selectedIndex)
929: {
930: Insets insets = getSelectedTabPadInsets(tabPlacement);
931: rects[selectedIndex].x -= insets.left;
932: rects[selectedIndex].y -= insets.top;
933: rects[selectedIndex].width += insets.left + insets.right;
934: rects[selectedIndex].height += insets.top + insets.bottom;
935: }
936:
937:
938:
939:
940:
941:
942:
943:
944:
954: protected void padTabRun(int tabPlacement, int start, int end, int max)
955: {
956: if (tabPlacement == SwingConstants.TOP
957: || tabPlacement == SwingConstants.BOTTOM)
958: {
959: int runWidth = rects[end].x + rects[end].width;
960: int spaceRemaining = max - runWidth;
961: int numTabs = end - start + 1;
962:
963:
964: int spaceAllocated = spaceRemaining / numTabs;
965: int currX = rects[start].x;
966: for (int i = start; i <= end; i++)
967: {
968: rects[i].x = currX;
969: rects[i].width += spaceAllocated;
970:
971: currX += rects[i].width;
972:
973:
974:
975:
976:
977: if (i == end && rects[i].x + rects[i].width != max)
978: rects[i].width = max - rects[i].x;
979: }
980: }
981: else
982: {
983: int runHeight = rects[end].y + rects[end].height;
984: int spaceRemaining = max - runHeight;
985: int numTabs = end - start + 1;
986:
987: int spaceAllocated = spaceRemaining / numTabs;
988: int currY = rects[start].y;
989: for (int i = start; i <= end; i++)
990: {
991: rects[i].y = currY;
992: rects[i].height += spaceAllocated;
993: currY += rects[i].height;
994: if (i == end && rects[i].y + rects[i].height != max)
995: rects[i].height = max - rects[i].y;
996: }
997: }
998: }
999:
1000:
1007: public Dimension preferredLayoutSize(Container parent)
1008: {
1009: return calculateSize(false);
1010: }
1011:
1012:
1021: protected int preferredTabAreaHeight(int tabPlacement, int width)
1022: {
1023: if (tabPane.getTabCount() == 0)
1024: return calculateTabAreaHeight(tabPlacement, 0, 0);
1025:
1026: int runs = 0;
1027: int runWidth = 0;
1028: int tabWidth = 0;
1029:
1030: FontMetrics fm = getFontMetrics();
1031:
1032: Insets tabAreaInsets = getTabAreaInsets(tabPlacement);
1033: Insets insets = tabPane.getInsets();
1034:
1035:
1036: width -= tabAreaInsets.left + tabAreaInsets.right + insets.left
1037: + insets.right;
1038:
1039:
1040:
1041:
1042:
1043:
1044: for (int i = 0; i < tabPane.getTabCount(); i++)
1045: {
1046: tabWidth = calculateTabWidth(tabPlacement, i, fm);
1047: if (runWidth + tabWidth > width)
1048: {
1049: runWidth = tabWidth;
1050: runs++;
1051: }
1052: else
1053: runWidth += tabWidth;
1054: }
1055: runs++;
1056:
1057: int maxTabHeight = calculateMaxTabHeight(tabPlacement);
1058: int tabAreaHeight = calculateTabAreaHeight(tabPlacement, runs,
1059: maxTabHeight);
1060: return tabAreaHeight;
1061: }
1062:
1063:
1072: protected int preferredTabAreaWidth(int tabPlacement, int height)
1073: {
1074: if (tabPane.getTabCount() == 0)
1075: return calculateTabAreaHeight(tabPlacement, 0, 0);
1076:
1077: int runs = 0;
1078: int runHeight = 0;
1079: int tabHeight = 0;
1080:
1081: FontMetrics fm = getFontMetrics();
1082:
1083: Insets tabAreaInsets = getTabAreaInsets(tabPlacement);
1084: Insets insets = tabPane.getInsets();
1085:
1086: height -= tabAreaInsets.top + tabAreaInsets.bottom + insets.top
1087: + insets.bottom;
1088: int fontHeight = fm.getHeight();
1089:
1090: for (int i = 0; i < tabPane.getTabCount(); i++)
1091: {
1092: tabHeight = calculateTabHeight(tabPlacement, i, fontHeight);
1093: if (runHeight + tabHeight > height)
1094: {
1095: runHeight = tabHeight;
1096: runs++;
1097: }
1098: else
1099: runHeight += tabHeight;
1100: }
1101: runs++;
1102:
1103: int maxTabWidth = calculateMaxTabWidth(tabPlacement);
1104: int tabAreaWidth = calculateTabAreaWidth(tabPlacement, runs,
1105: maxTabWidth);
1106: return tabAreaWidth;
1107: }
1108:
1109:
1117: protected void rotateTabRuns(int tabPlacement, int selectedRun)
1118: {
1119: if (runCount == 1 || selectedRun == 0 || selectedRun == -1)
1120: return;
1121: int[] newTabRuns = new int[tabRuns.length];
1122: int currentRun = selectedRun;
1123: int i = 0;
1124: do
1125: {
1126: newTabRuns[i] = tabRuns[currentRun];
1127: currentRun = getNextTabRun(currentRun);
1128: i++;
1129: }
1130: while (i < runCount);
1131:
1132: tabRuns = newTabRuns;
1133: BasicTabbedPaneUI.this.selectedRun = 1;
1134: }
1135:
1136:
1142: public void removeLayoutComponent(Component comp)
1143: {
1144:
1145: }
1146: }
1147:
1148:
1152: private class TabbedPaneScrollLayout extends TabbedPaneLayout
1153: {
1154:
1161: public Dimension preferredLayoutSize(Container parent)
1162: {
1163: return super.calculateSize(false);
1164: }
1165:
1166:
1173: public Dimension minimumLayoutSize(Container parent)
1174: {
1175: return super.calculateSize(true);
1176: }
1177:
1178:
1186: protected int preferredTabAreaHeight(int tabPlacement, int width)
1187: {
1188: if (tabPane.getTabCount() == 0)
1189: return calculateTabAreaHeight(tabPlacement, 0, 0);
1190:
1191: int runs = 1;
1192:
1193: int maxTabHeight = calculateMaxTabHeight(tabPlacement);
1194: int tabAreaHeight = calculateTabAreaHeight(tabPlacement, runs,
1195: maxTabHeight);
1196: return tabAreaHeight;
1197: }
1198:
1199:
1207: protected int preferredTabAreaWidth(int tabPlacement, int height)
1208: {
1209: if (tabPane.getTabCount() == 0)
1210: return calculateTabAreaHeight(tabPlacement, 0, 0);
1211:
1212: int runs = 1;
1213:
1214: int maxTabWidth = calculateMaxTabWidth(tabPlacement);
1215: int tabAreaWidth = calculateTabAreaWidth(tabPlacement, runs, maxTabWidth);
1216: return tabAreaWidth;
1217: }
1218:
1219:
1228: protected void calculateTabRects(int tabPlacement, int tabCount)
1229: {
1230: if (tabCount == 0)
1231: return;
1232:
1233: FontMetrics fm = getFontMetrics();
1234: SwingUtilities.calculateInnerArea(tabPane, calcRect);
1235: Insets tabAreaInsets = getTabAreaInsets(tabPlacement);
1236: Insets insets = tabPane.getInsets();
1237: if (tabPlacement == SwingConstants.TOP
1238: || tabPlacement == SwingConstants.BOTTOM)
1239: {
1240: int maxHeight = calculateMaxTabHeight(tabPlacement);
1241: calcRect.width -= tabAreaInsets.left + tabAreaInsets.right;
1242: int width = 0;
1243: int runWidth = tabAreaInsets.left + insets.left;
1244: int top = insets.top + tabAreaInsets.top;
1245: for (int i = 0; i < tabCount; i++)
1246: {
1247: width = calculateTabWidth(tabPlacement, i, fm);
1248:
1249:
1250:
1251: rects[i].setBounds(runWidth, top, width, maxHeight);
1252:
1253: runWidth += width;
1254: }
1255: tabAreaRect.width = tabPane.getWidth() - insets.left - insets.right;
1256: tabAreaRect.height = maxTabHeight + tabAreaInsets.top
1257: + tabAreaInsets.bottom;
1258: contentRect.width = tabAreaRect.width;
1259: contentRect.height = tabPane.getHeight() - insets.top
1260: - insets.bottom - tabAreaRect.height;
1261: contentRect.x = insets.left;
1262: tabAreaRect.x = insets.left;
1263: if (tabPlacement == SwingConstants.BOTTOM)
1264: {
1265: contentRect.y = insets.top;
1266: tabAreaRect.y = contentRect.y + contentRect.height;
1267: }
1268: else
1269: {
1270: tabAreaRect.y = insets.top;
1271: contentRect.y = tabAreaRect.y + tabAreaRect.height;
1272: }
1273: }
1274: else
1275: {
1276: int maxWidth = calculateMaxTabWidth(tabPlacement);
1277:
1278: calcRect.height -= tabAreaInsets.top + tabAreaInsets.bottom;
1279: int height = 0;
1280: int runHeight = tabAreaInsets.top + insets.top;;
1281: int fontHeight = fm.getHeight();
1282: int left = insets.left + tabAreaInsets.left;
1283: for (int i = 0; i < tabCount; i++)
1284: {
1285: height = calculateTabHeight(tabPlacement, i, fontHeight);
1286:
1287:
1288:
1289: rects[i].setBounds(left, runHeight, maxWidth, height);
1290: runHeight += height;
1291: }
1292: tabAreaRect.width = maxTabWidth + tabAreaInsets.left
1293: + tabAreaInsets.right;
1294: tabAreaRect.height = tabPane.getHeight() - insets.top
1295: - insets.bottom;
1296: tabAreaRect.y = insets.top;
1297: contentRect.width = tabPane.getWidth() - insets.left - insets.right
1298: - tabAreaRect.width;
1299: contentRect.height = tabAreaRect.height;
1300: contentRect.y = insets.top;
1301: if (tabPlacement == SwingConstants.LEFT)
1302: {
1303: tabAreaRect.x = insets.left;
1304: contentRect.x = tabAreaRect.x + tabAreaRect.width;
1305: }
1306: else
1307: {
1308: contentRect.x = insets.left;
1309: tabAreaRect.x = contentRect.x + contentRect.width;
1310: }
1311: }
1312:
1313:
1314:
1315: }
1316:
1317:
1324: public void layoutContainer(Container pane)
1325: {
1326: super.layoutContainer(pane);
1327: int tabCount = tabPane.getTabCount();
1328: Point p = null;
1329: if (tabCount == 0)
1330: return;
1331: int tabPlacement = tabPane.getTabPlacement();
1332:
1333: if (tabPlacement == SwingConstants.TOP
1334: || tabPlacement == SwingConstants.BOTTOM)
1335: {
1336: if (tabAreaRect.x + tabAreaRect.width < rects[tabCount - 1].x
1337: + rects[tabCount - 1].width)
1338: {
1339: Dimension incrDims = incrButton.getPreferredSize();
1340: Dimension decrDims = decrButton.getPreferredSize();
1341:
1342: if (tabPlacement == SwingConstants.BOTTOM)
1343: {
1344:
1345:
1346: decrButton.setBounds(tabAreaRect.x + tabAreaRect.width
1347: - incrDims.width - decrDims.width,
1348: tabAreaRect.y, decrDims.width,
1349: decrDims.height);
1350: incrButton.setBounds(tabAreaRect.x + tabAreaRect.width
1351: - incrDims.width, tabAreaRect.y,
1352: incrDims.width, incrDims.height);
1353: }
1354: else
1355: {
1356:
1357:
1358: decrButton.setBounds(tabAreaRect.x + tabAreaRect.width
1359: - incrDims.width - decrDims.width,
1360: tabAreaRect.y + tabAreaRect.height
1361: - decrDims.height, decrDims.width,
1362: decrDims.height);
1363: incrButton.setBounds(tabAreaRect.x + tabAreaRect.width
1364: - incrDims.width,
1365: tabAreaRect.y + tabAreaRect.height
1366: - incrDims.height,
1367: incrDims.width, incrDims.height);
1368: }
1369:
1370: tabAreaRect.width -= decrDims.width + incrDims.width;
1371:
1372: updateButtons();
1373:
1374: incrButton.setVisible(true);
1375: decrButton.setVisible(true);
1376: }
1377: else
1378: {
1379: incrButton.setVisible(false);
1380: decrButton.setVisible(false);
1381:
1382: currentScrollOffset = 0;
1383: currentScrollLocation = 0;
1384: }
1385: }
1386:
1387: if (tabPlacement == SwingConstants.LEFT
1388: || tabPlacement == SwingConstants.RIGHT)
1389: {
1390: if (tabAreaRect.y + tabAreaRect.height < rects[tabCount - 1].y
1391: + rects[tabCount - 1].height)
1392: {
1393: Dimension incrDims = incrButton.getPreferredSize();
1394: Dimension decrDims = decrButton.getPreferredSize();
1395:
1396: if (tabPlacement == SwingConstants.RIGHT)
1397: {
1398:
1399:
1400: decrButton.setBounds(tabAreaRect.x,
1401: tabAreaRect.y + tabAreaRect.height
1402: - incrDims.height - decrDims.height,
1403: decrDims.width, decrDims.height);
1404: incrButton.setBounds(tabAreaRect.x,
1405: tabAreaRect.y + tabAreaRect.height
1406: - incrDims.height, incrDims.width,
1407: incrDims.height);
1408: }
1409: else
1410: {
1411:
1412:
1413: decrButton.setBounds(tabAreaRect.x + tabAreaRect.width
1414: - decrDims.width,
1415: tabAreaRect.y + tabAreaRect.height
1416: - incrDims.height - decrDims.height,
1417: decrDims.width, decrDims.height);
1418: incrButton.setBounds(tabAreaRect.x + tabAreaRect.width
1419: - incrDims.width,
1420: tabAreaRect.y + tabAreaRect.height
1421: - incrDims.height, incrDims.width,
1422: incrDims.height);
1423: }
1424:
1425: tabAreaRect.height -= decrDims.height + incrDims.height;
1426:
1427: incrButton.setVisible(true);
1428: decrButton.setVisible(true);
1429: }
1430: else
1431: {
1432: incrButton.setVisible(false);
1433: decrButton.setVisible(false);
1434:
1435: currentScrollOffset = 0;
1436: currentScrollLocation = 0;
1437: }
1438: }
1439: viewport.setBounds(tabAreaRect.x, tabAreaRect.y, tabAreaRect.width,
1440: tabAreaRect.height);
1441:
1442: updateViewPosition();
1443:
1444: viewport.repaint();
1445: }
1446: }
1447:
1448:
1455: public class TabSelectionHandler implements ChangeListener
1456: {
1457:
1463: public void stateChanged(ChangeEvent e)
1464: {
1465: selectedRun = getRunForTab(tabPane.getTabCount(),
1466: tabPane.getSelectedIndex());
1467:
1468: if (tabPane.getTabLayoutPolicy() == JTabbedPane.WRAP_TAB_LAYOUT)
1469: tabPane.revalidate();
1470: tabPane.repaint();
1471: }
1472: }
1473:
1474:
1479: private class ScrollingPanel extends JPanel
1480: {
1481:
1484: private class ScrollingPanelUI extends BasicPanelUI
1485: {
1486:
1493: public void paint(Graphics g, JComponent c)
1494: {
1495: int placement = tabPane.getTabPlacement();
1496: g.setColor(highlight);
1497: if (placement == SwingUtilities.TOP
1498: || placement == SwingUtilities.BOTTOM)
1499: g.fillRect(currentScrollOffset, 0,
1500: tabAreaRect.width, tabAreaRect.height);
1501: else
1502: g.fillRect(0, currentScrollOffset,
1503: tabAreaRect.width, tabAreaRect.height);
1504:
1505: paintTabArea(g, placement, tabPane.getSelectedIndex());
1506: }
1507: }
1508:
1509:
1513: public void updateUI()
1514: {
1515: setUI((PanelUI) new ScrollingPanelUI());
1516: }
1517: }
1518:
1519:
1525: private class ScrollingViewport extends JViewport implements UIResource
1526: {
1527:
1528: }
1529:
1530:
1534: private class ScrollingButton extends BasicArrowButton implements UIResource
1535: {
1536:
1541: public ScrollingButton(int dir)
1542: {
1543: super(dir);
1544: }
1545: }
1546:
1547:
1549: transient ScrollingButton incrButton;
1550:
1551:
1553: transient ScrollingButton decrButton;
1554:
1555:
1557: transient ScrollingViewport viewport;
1558:
1559:
1561: transient ScrollingPanel panel;
1562:
1563:
1565: transient int currentScrollLocation;
1566:
1567: transient int currentScrollOffset;
1568:
1569:
1570: protected Rectangle calcRect;
1571:
1572:
1573: protected Rectangle[] rects;
1574:
1575:
1576: protected Insets contentBorderInsets;
1577:
1578:
1579: protected Insets selectedTabPadInsets;
1580:
1581:
1582: protected Insets tabAreaInsets;
1583:
1584:
1585: protected Insets tabInsets;
1586:
1587:
1591: protected Color darkShadow;
1592:
1593:
1594: protected Color focus;
1595:
1596:
1597: protected Color highlight;
1598:
1599:
1600: protected Color lightHighlight;
1601:
1602:
1603: protected Color shadow;
1604:
1605:
1606: protected int maxTabHeight;
1607:
1608:
1609: protected int maxTabWidth;
1610:
1611:
1612: protected int runCount;
1613:
1614:
1615: protected int selectedRun;
1616:
1617:
1618: protected int tabRunOverlay;
1619:
1620:
1621: protected int textIconGap;
1622:
1623:
1628: protected int[] tabRuns;
1629:
1630:
1634: boolean tabRunsDirty;
1635:
1636:
1641: protected KeyStroke downKey;
1642:
1643:
1648: protected KeyStroke leftKey;
1649:
1650:
1655: protected KeyStroke rightKey;
1656:
1657:
1662: protected KeyStroke upKey;
1663:
1664:
1665: protected FocusListener focusListener;
1666:
1667:
1668: protected MouseListener mouseListener;
1669:
1670:
1671: protected PropertyChangeListener propertyChangeListener;
1672:
1673:
1674: protected ChangeListener tabChangeListener;
1675:
1676:
1677: protected JTabbedPane tabPane;
1678:
1679:
1681: transient LayoutManager layoutManager;
1682:
1683:
1685: transient Rectangle tabAreaRect;
1686:
1687:
1689: transient Rectangle contentRect;
1690:
1691:
1694: private int rolloverTab;
1695:
1696:
1700: private boolean tabsOpaque;
1701:
1702:
1705: private Component visibleComponent;
1706:
1707: private Color selectedColor;
1708:
1709: private Rectangle tempTextRect = new Rectangle();
1710:
1711: private Rectangle tempIconRect = new Rectangle();
1712:
1713:
1716: public BasicTabbedPaneUI()
1717: {
1718: super();
1719: rects = new Rectangle[0];
1720: tabRuns = new int[10];
1721: }
1722:
1723:
1730: ScrollingButton createIncreaseButton()
1731: {
1732: if (incrButton == null)
1733: incrButton = new ScrollingButton(SwingConstants.NORTH);
1734: if (tabPane.getTabPlacement() == SwingConstants.TOP
1735: || tabPane.getTabPlacement() == SwingConstants.BOTTOM)
1736: incrButton.setDirection(SwingConstants.EAST);
1737: else
1738: incrButton.setDirection(SwingConstants.SOUTH);
1739: return incrButton;
1740: }
1741:
1742:
1749: ScrollingButton createDecreaseButton()
1750: {
1751: if (decrButton == null)
1752: decrButton = new ScrollingButton(SwingConstants.SOUTH);
1753: if (tabPane.getTabPlacement() == SwingConstants.TOP
1754: || tabPane.getTabPlacement() == SwingConstants.BOTTOM)
1755: decrButton.setDirection(SwingConstants.WEST);
1756: else
1757: decrButton.setDirection(SwingConstants.NORTH);
1758: return decrButton;
1759: }
1760:
1761:
1770: Point findPointForIndex(int index)
1771: {
1772: int tabPlacement = tabPane.getTabPlacement();
1773: int selectedIndex = tabPane.getSelectedIndex();
1774: Insets insets = getSelectedTabPadInsets(tabPlacement);
1775: int w = 0;
1776: int h = 0;
1777:
1778: if (tabPlacement == TOP || tabPlacement == BOTTOM)
1779: {
1780: if (index > 0)
1781: {
1782: w += rects[index - 1].x + rects[index - 1].width;
1783: if (index > selectedIndex)
1784: w -= insets.left + insets.right;
1785: }
1786: }
1787:
1788: else
1789: {
1790: if (index > 0)
1791: {
1792: h += rects[index - 1].y + rects[index - 1].height;
1793: if (index > selectedIndex)
1794: h -= insets.top + insets.bottom;
1795: }
1796: }
1797:
1798: Point p = new Point(w, h);
1799: return p;
1800: }
1801:
1802:
1808: final void scrollTab(int index, int placement)
1809: {
1810: int diff;
1811: if (index >= 0 && tabPane.isEnabledAt(index))
1812: {
1813:
1814:
1815:
1816: switch (placement)
1817: {
1818: case JTabbedPane.TOP:
1819: case JTabbedPane.BOTTOM:
1820: if ((diff = rects[index].x
1821: + rects[index].width
1822: - decrButton.getX() - currentScrollOffset) > 0)
1823: currentScrollOffset += diff;
1824: else if ((diff = rects[index].x - currentScrollOffset) < 0)
1825: {
1826: if (index == 0)
1827: currentScrollOffset = 0;
1828: else
1829: currentScrollOffset += diff;
1830: }
1831:
1832: currentScrollLocation = tabForCoordinate(tabPane,
1833: currentScrollOffset,
1834: rects[index].y);
1835: break;
1836: default:
1837: if ((diff = rects[index].y + rects[index].height
1838: - decrButton.getY() - currentScrollOffset) > 0)
1839: currentScrollOffset += diff;
1840: else if ((diff = rects[index].y - currentScrollOffset) < 0)
1841: {
1842: if (index == 0)
1843: currentScrollOffset = 0;
1844: else
1845: currentScrollOffset += diff;
1846: }
1847:
1848: currentScrollLocation = tabForCoordinate(tabPane,
1849: rects[index].x,
1850: currentScrollOffset);
1851: }
1852:
1853: updateViewPosition();
1854: updateButtons();
1855: }
1856: }
1857:
1858:
1862: final void updateButtons()
1863: {
1864: int tc = tabPane.getTabCount();
1865:
1866:
1867:
1868:
1869: switch (tabPane.getTabPlacement())
1870: {
1871: case JTabbedPane.BOTTOM:
1872: case JTabbedPane.TOP:
1873: incrButton.setEnabled(currentScrollLocation + 1 < tc
1874: && rects[tc-1].x + rects[tc-1].width
1875: - currentScrollOffset > decrButton.getX());
1876: break;
1877: default:
1878: incrButton.setEnabled(currentScrollLocation + 1 < tc
1879: && rects[tc-1].y + rects[tc-1].height
1880: - currentScrollOffset > decrButton.getY());
1881: }
1882:
1883:
1884: decrButton.setEnabled(currentScrollOffset > 0);
1885:
1886: }
1887:
1888:
1892: final void updateViewPosition()
1893: {
1894: Point p = viewport.getViewPosition();
1895:
1896: switch (tabPane.getTabPlacement())
1897: {
1898: case JTabbedPane.LEFT:
1899: case JTabbedPane.RIGHT:
1900: p.y = currentScrollOffset;
1901: break;
1902: default:
1903: p.x = currentScrollOffset;
1904: }
1905:
1906: viewport.setViewPosition(p);
1907: }
1908:
1909:
1916: public static ComponentUI createUI(JComponent c)
1917: {
1918: return new BasicTabbedPaneUI();
1919: }
1920:
1921:
1926: public void installUI(JComponent c)
1927: {
1928: super.installUI(c);
1929: if (c instanceof JTabbedPane)
1930: {
1931: tabPane = (JTabbedPane) c;
1932:
1933: installComponents();
1934: installDefaults();
1935: installListeners();
1936: installKeyboardActions();
1937:
1938: layoutManager = createLayoutManager();
1939: tabPane.setLayout(layoutManager);
1940: }
1941: }
1942:
1943:
1948: public void uninstallUI(JComponent c)
1949: {
1950: layoutManager = null;
1951:
1952: uninstallKeyboardActions();
1953: uninstallListeners();
1954: uninstallDefaults();
1955: uninstallComponents();
1956:
1957: tabPane = null;
1958: }
1959:
1960:
1968: protected LayoutManager createLayoutManager()
1969: {
1970: if (tabPane.getTabLayoutPolicy() == JTabbedPane.WRAP_TAB_LAYOUT)
1971: return new TabbedPaneLayout();
1972: else
1973: {
1974: runCount = 1;
1975: tabRuns[0] = 0;
1976:
1977: incrButton = createIncreaseButton();
1978: incrButton.addMouseListener(mouseListener);
1979:
1980: decrButton = createDecreaseButton();
1981: decrButton.addMouseListener(mouseListener);
1982: decrButton.setEnabled(false);
1983:
1984: panel = new ScrollingPanel();
1985: panel.setSize(Integer.MAX_VALUE, Integer.MAX_VALUE);
1986: panel.addMouseListener(mouseListener);
1987: panel.addFocusListener(focusListener);
1988:
1989: viewport = new ScrollingViewport();
1990: viewport.setBackground(Color.LIGHT_GRAY);
1991: viewport.setView(panel);
1992: viewport.setLayout(null);
1993:
1994: tabPane.add(incrButton);
1995: tabPane.add(decrButton);
1996: tabPane.add(viewport);
1997:
1998: return new TabbedPaneScrollLayout();
1999: }
2000: }
2001:
2002:
2005: protected void installComponents()
2006: {
2007:
2008: }
2009:
2010:
2013: protected void uninstallComponents()
2014: {
2015: if (incrButton != null)
2016: tabPane.remove(incrButton);
2017:
2018: if (decrButton != null)
2019: tabPane.remove(decrButton);
2020:
2021: if (viewport != null)
2022: tabPane.remove(viewport);
2023: }
2024:
2025:
2028: protected void installDefaults()
2029: {
2030: LookAndFeel.installColorsAndFont(tabPane, "TabbedPane.background",
2031: "TabbedPane.foreground",
2032: "TabbedPane.font");
2033: tabPane.setOpaque(false);
2034:
2035: lightHighlight = UIManager.getColor("TabbedPane.highlight");
2036: highlight = UIManager.getColor("TabbedPane.light");
2037:
2038: shadow = UIManager.getColor("TabbedPane.shadow");
2039: darkShadow = UIManager.getColor("TabbedPane.darkShadow");
2040:
2041: focus = UIManager.getColor("TabbedPane.focus");
2042:
2043: textIconGap = UIManager.getInt("TabbedPane.textIconGap");
2044: tabRunOverlay = UIManager.getInt("TabbedPane.tabRunOverlay");
2045:
2046: tabInsets = UIManager.getInsets("TabbedPane.tabInsets");
2047: selectedTabPadInsets
2048: = UIManager.getInsets("TabbedPane.selectedTabPadInsets");
2049: tabAreaInsets = UIManager.getInsets("TabbedPane.tabAreaInsets");
2050: contentBorderInsets
2051: = UIManager.getInsets("TabbedPane.contentBorderInsets");
2052: tabsOpaque = UIManager.getBoolean("TabbedPane.tabsOpaque");
2053:
2054:
2055:
2056: selectedColor = UIManager.getColor("TabbedPane.contentAreaColor");
2057: if (selectedColor == null)
2058: selectedColor = UIManager.getColor("control");
2059:
2060: calcRect = new Rectangle();
2061: tabRuns = new int[10];
2062: tabAreaRect = new Rectangle();
2063: contentRect = new Rectangle();
2064: }
2065:
2066:
2069: protected void uninstallDefaults()
2070: {
2071: calcRect = null;
2072: tabAreaRect = null;
2073: contentRect = null;
2074: tabRuns = null;
2075:
2076: tempIconRect = null;
2077: tempTextRect = null;
2078:
2079: contentBorderInsets = null;
2080: tabAreaInsets = null;
2081: selectedTabPadInsets = null;
2082: tabInsets = null;
2083:
2084: focus = null;
2085: darkShadow = null;
2086: shadow = null;
2087: lightHighlight = null;
2088: highlight = null;
2089:
2090: selectedColor = null;
2091: }
2092:
2093:
2096: protected void installListeners()
2097: {
2098: mouseListener = createMouseListener();
2099: tabChangeListener = createChangeListener();
2100: propertyChangeListener = createPropertyChangeListener();
2101: focusListener = createFocusListener();
2102:
2103: tabPane.addMouseListener(mouseListener);
2104: tabPane.addChangeListener(tabChangeListener);
2105: tabPane.addPropertyChangeListener(propertyChangeListener);
2106: tabPane.addFocusListener(focusListener);
2107: }
2108:
2109:
2112: protected void uninstallListeners()
2113: {
2114: tabPane.removeFocusListener(focusListener);
2115: tabPane.removePropertyChangeListener(propertyChangeListener);
2116: tabPane.removeChangeListener(tabChangeListener);
2117: tabPane.removeMouseListener(mouseListener);
2118:
2119: if (incrButton != null)
2120: incrButton.removeMouseListener(mouseListener);
2121:
2122: if (decrButton != null)
2123: decrButton.removeMouseListener(mouseListener);
2124:
2125: if (panel != null)
2126: {
2127: panel.removeMouseListener(mouseListener);
2128: panel.removeFocusListener(focusListener);
2129: }
2130:
2131: focusListener = null;
2132: propertyChangeListener = null;
2133: tabChangeListener = null;
2134: mouseListener = null;
2135: }
2136:
2137:
2142: protected MouseListener createMouseListener()
2143: {
2144: return new MouseHandler();
2145: }
2146:
2147:
2152: protected FocusListener createFocusListener()
2153: {
2154: return new FocusHandler();
2155: }
2156:
2157:
2162: protected ChangeListener createChangeListener()
2163: {
2164: return new TabSelectionHandler();
2165: }
2166:
2167:
2172: protected PropertyChangeListener createPropertyChangeListener()
2173: {
2174: return new PropertyChangeHandler();
2175: }
2176:
2177:
2180: protected void installKeyboardActions()
2181: {
2182: InputMap keyMap = (InputMap) UIManager.get("TabbedPane.focusInputMap");
2183: SwingUtilities.replaceUIInputMap(tabPane, JComponent.WHEN_FOCUSED, keyMap);
2184:
2185: keyMap = (InputMap) UIManager.get("TabbedPane.ancestorInputMap");
2186: SwingUtilities
2187: .replaceUIInputMap(tabPane,
2188: JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT,
2189: keyMap);
2190:
2191: ActionMap map = getActionMap();
2192: SwingUtilities.replaceUIActionMap(tabPane, map);
2193: }
2194:
2195:
2198: protected void uninstallKeyboardActions()
2199: {
2200: SwingUtilities.replaceUIActionMap(tabPane, null);
2201: SwingUtilities.replaceUIInputMap(tabPane, JComponent.WHEN_FOCUSED, null);
2202: SwingUtilities
2203: .replaceUIInputMap(tabPane,
2204: JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT,
2205: null);
2206: }
2207:
2208:
2215: public Dimension getMinimumSize(JComponent c)
2216: {
2217: return layoutManager.minimumLayoutSize(tabPane);
2218: }
2219:
2220:
2227: public Dimension getMaximumSize(JComponent c)
2228: {
2229: return new Dimension(Short.MAX_VALUE, Short.MAX_VALUE);
2230: }
2231:
2232:
2238: public void paint(Graphics g, JComponent c)
2239: {
2240: if (!tabPane.isValid())
2241: tabPane.validate();
2242:
2243: if (tabPane.getTabCount() == 0)
2244: return;
2245:
2246: int index = tabPane.getSelectedIndex();
2247: if (index < 0)
2248: index = 0;
2249:
2250: int tabPlacement = tabPane.getTabPlacement();
2251:
2252:
2253:
2254:
2255: if (tabPane.getTabLayoutPolicy() == JTabbedPane.WRAP_TAB_LAYOUT)
2256: {
2257: g.setColor(highlight);
2258: g.fillRect(tabAreaRect.x, tabAreaRect.y,
2259: tabAreaRect.width, tabAreaRect.height);
2260: paintTabArea(g, tabPlacement, index);
2261: }
2262:
2263: paintContentBorder(g, tabPlacement, index);
2264: }
2265:
2266:
2274: protected void paintTabArea(Graphics g, int tabPlacement, int selectedIndex)
2275: {
2276:
2277:
2278:
2279:
2280: int tabCount = tabPane.getTabCount();
2281:
2282: for (int i = runCount - 1; i >= 0; --i)
2283: {
2284: int start = tabRuns[i];
2285: int next;
2286: if (i == runCount - 1)
2287: next = tabRuns[0];
2288: else
2289: next = tabRuns[i + 1];
2290: int end = next != 0 ? next - 1 : tabCount - 1;
2291: for (int j = start; j <= end; ++j)
2292: {
2293: if (j != selectedIndex)
2294: {
2295: paintTab(g, tabPlacement, rects, j,
2296: tempIconRect, tempTextRect);
2297: }
2298: }
2299: }
2300:
2301:
2302: if (selectedIndex >= 0)
2303: paintTab(g, tabPlacement, rects, selectedIndex,
2304: tempIconRect, tempTextRect);
2305: }
2306:
2307:
2318: protected void paintTab(Graphics g, int tabPlacement, Rectangle[] rects,
2319: int tabIndex, Rectangle iconRect, Rectangle textRect)
2320: {
2321: Rectangle rect = rects[tabIndex];
2322: boolean isSelected = tabIndex == tabPane.getSelectedIndex();
2323:
2324: if (tabsOpaque || tabPane.isOpaque())
2325: {
2326: paintTabBackground(g, tabPlacement, tabIndex, rect.x, rect.y,
2327: rect.width, rect.height, isSelected);
2328: }
2329:
2330:
2331: paintTabBorder(g, tabPlacement, tabIndex, rect.x, rect.y, rect.width,
2332: rect.height, isSelected);
2333:
2334:
2335:
2336: FontMetrics fm = getFontMetrics();
2337: Icon icon = getIconForTab(tabIndex);
2338: String title = tabPane.getTitleAt(tabIndex);
2339: layoutLabel(tabPlacement, fm, tabIndex, title, icon, rect, iconRect,
2340: textRect, isSelected);
2341:
2342: paintText(g, tabPlacement, tabPane.getFont(), fm, tabIndex, title,
2343: textRect, isSelected);
2344:
2345:
2346: paintIcon(g, tabPlacement, tabIndex, icon, iconRect, isSelected);
2347:
2348:
2349: paintFocusIndicator(g, tabPlacement, rects, tabIndex, iconRect, textRect,
2350: isSelected);
2351: }
2352:
2353:
2367: protected void layoutLabel(int tabPlacement, FontMetrics metrics,
2368: int tabIndex, String title, Icon icon,
2369: Rectangle tabRect, Rectangle iconRect,
2370: Rectangle textRect, boolean isSelected)
2371: {
2372: SwingUtilities.layoutCompoundLabel(metrics, title, icon,
2373: SwingConstants.CENTER,
2374: SwingConstants.CENTER,
2375: SwingConstants.CENTER,
2376: SwingConstants.RIGHT, tabRect,
2377: iconRect, textRect, textIconGap);
2378:
2379: int shiftX = getTabLabelShiftX(tabPlacement, tabIndex, isSelected);
2380: int shiftY = getTabLabelShiftY(tabPlacement, tabIndex, isSelected);
2381:
2382: iconRect.x += shiftX;
2383: iconRect.y += shiftY;
2384:
2385: textRect.x += shiftX;
2386: textRect.y += shiftY;
2387: }
2388:
2389:
2399: protected void paintIcon(Graphics g, int tabPlacement, int tabIndex,
2400: Icon icon, Rectangle iconRect, boolean isSelected)
2401: {
2402: if (icon != null)
2403: icon.paintIcon(tabPane, g, iconRect.x, iconRect.y);
2404: }
2405:
2406:
2418: protected void paintText(Graphics g, int tabPlacement, Font font,
2419: FontMetrics metrics, int tabIndex, String title,
2420: Rectangle textRect, boolean isSelected)
2421: {
2422: g.setFont(font);
2423: View textView = getTextViewForTab(tabIndex);
2424: if (textView != null)
2425: {
2426: textView.paint(g, textRect);
2427: return;
2428: }
2429:
2430: int ascent = metrics.getAscent();
2431:
2432: int mnemIndex = tabPane.getDisplayedMnemonicIndexAt(tabIndex);
2433: if (tabPane.isEnabled() && tabPane.isEnabledAt(tabIndex))
2434: {
2435: Color fg = tabPane.getForegroundAt(tabIndex);
2436: if (isSelected && (fg instanceof UIResource))
2437: {
2438: Color selectionForeground =
2439: UIManager.getColor("TabbedPane.selectionForeground");
2440: if (selectionForeground != null)
2441: fg = selectionForeground;
2442: }
2443: g.setColor(fg);
2444:
2445: if (mnemIndex != -1)
2446: BasicGraphicsUtils.drawStringUnderlineCharAt(g, title, mnemIndex,
2447: textRect.x,
2448: textRect.y + ascent);
2449: else
2450: g.drawString(title, textRect.x, textRect.y + ascent);
2451: }
2452: else
2453: {
2454: Color bg = tabPane.getBackgroundAt(tabIndex);
2455: g.setColor(bg.brighter());
2456: if (mnemIndex != -1)
2457: BasicGraphicsUtils.drawStringUnderlineCharAt(g, title, mnemIndex,
2458: textRect.x, textRect.y
2459: + ascent);
2460: else
2461: g.drawString(title, textRect.x, textRect.y + ascent);
2462:
2463: g.setColor(bg.darker());
2464: if (mnemIndex != -1)
2465: BasicGraphicsUtils.drawStringUnderlineCharAt(g, title, mnemIndex,
2466: textRect.x + 1,
2467: textRect.y + 1
2468: + ascent);
2469: else
2470: g.drawString(title, textRect.x + 1, textRect.y + 1 + ascent);
2471: }
2472: }
2473:
2474:
2484: protected int getTabLabelShiftX(int tabPlacement, int tabIndex,
2485: boolean isSelected)
2486: {
2487: switch (tabPlacement)
2488: {
2489: default:
2490: case SwingUtilities.TOP:
2491: case SwingUtilities.BOTTOM:
2492: return 1;
2493: case SwingUtilities.LEFT:
2494: return (isSelected) ? -1 : 1;
2495: case SwingUtilities.RIGHT:
2496: return (isSelected) ? 1 : -1;
2497: }
2498: }
2499:
2500:
2510: protected int getTabLabelShiftY(int tabPlacement, int tabIndex,
2511: boolean isSelected)
2512: {
2513: switch (tabPlacement)
2514: {
2515: default:
2516: case SwingUtilities.TOP:
2517: return (isSelected) ? -1 : 1;
2518: case SwingUtilities.BOTTOM:
2519: return (isSelected) ? 1 : -1;
2520: case SwingUtilities.LEFT:
2521: case SwingUtilities.RIGHT:
2522: return 0;
2523: }
2524: }
2525:
2526:
2537: protected void paintFocusIndicator(Graphics g, int tabPlacement,
2538: Rectangle[] rects, int tabIndex,
2539: Rectangle iconRect, Rectangle textRect,
2540: boolean isSelected)
2541: {
2542: if (tabPane.hasFocus() && isSelected)
2543: {
2544: Rectangle rect = rects[tabIndex];
2545:
2546: int x;
2547: int y;
2548: int w;
2549: int h;
2550:
2551: g.setColor(focus);
2552: switch (tabPlacement)
2553: {
2554: case LEFT:
2555: x = rect.x + 3;
2556: y = rect.y + 3;
2557: w = rect.width - 5;
2558: h = rect.height - 6;
2559: break;
2560: case RIGHT:
2561: x = rect.x + 2;
2562: y = rect.y + 3;
2563: w = rect.width - 6;
2564: h = rect.height - 5;
2565: break;
2566: case BOTTOM:
2567: x = rect.x + 3;
2568: y = rect.y + 2;
2569: w = rect.width - 6;
2570: h = rect.height - 5;
2571: break;
2572: case TOP:
2573: default:
2574: x = rect.x + 3;
2575: y = rect.y + 3;
2576: w = rect.width - 6;
2577: h = rect.height - 5;
2578: }
2579:
2580: BasicGraphicsUtils.drawDashedRect(g, x, y, w, h);
2581: }
2582: }
2583:
2584:
2596: protected void paintTabBorder(Graphics g, int tabPlacement, int tabIndex,
2597: int x, int y, int w, int h, boolean isSelected)
2598: {
2599: Color saved = g.getColor();
2600:
2601: switch (tabPlacement)
2602: {
2603: case SwingConstants.TOP:
2604: g.setColor(shadow);
2605:
2606: g.drawLine(x + w - 2, y + 2, x + w - 2, y + h);
2607:
2608: g.setColor(darkShadow);
2609:
2610: g.drawLine(x + w - 1, y + 2, x + w - 1, y + h);
2611:
2612:
2613: g.drawLine(x + w - 2, y + 1, x + w - 1, y + 2);
2614:
2615: g.setColor(lightHighlight);
2616:
2617:
2618: g.drawLine(x, y + 3, x, y + h);
2619:
2620:
2621: g.drawLine(x + 3, y, x + w - 3, y);
2622:
2623:
2624: g.drawLine(x, y + 2, x + 2, y);
2625:
2626: break;
2627: case SwingConstants.LEFT:
2628: g.setColor(lightHighlight);
2629:
2630: g.drawLine(x + 3, y, x + w - 1, y);
2631:
2632:
2633: g.drawLine(x + 2, y, x, y + 2);
2634:
2635:
2636: g.drawLine(x, y + 3, x, y + h - 4);
2637:
2638:
2639: g.drawLine(x, y + h - 3, x + 1, y + h - 2);
2640:
2641: g.setColor(darkShadow);
2642:
2643: g.drawLine(x + 2, y + h - 1, x + w - 1, y + h - 1);
2644:
2645: g.setColor(shadow);
2646:
2647: g.drawLine(x + 2, y + h - 2, x + w - 1, y + h - 2);
2648:
2649: break;
2650: case SwingConstants.BOTTOM:
2651: g.setColor(shadow);
2652:
2653: g.drawLine(x + w - 2, y, x + w - 2, y + h - 2);
2654:
2655:
2656: g.drawLine(x + 2, y + h - 1, x + w - 3, y + h - 1);
2657:
2658: g.setColor(darkShadow);
2659:
2660: g.drawLine(x + w - 1, y, x + w - 1, y + h - 3);
2661:
2662:
2663: g.drawLine(x + w - 1, y + h - 2, x + w - 3, y + h);
2664:
2665:
2666: g.drawLine(x + 2, y + h, x + w - 4, y + h);
2667:
2668: g.setColor(lightHighlight);
2669:
2670: g.drawLine(x, y, x, y + h - 3);
2671:
2672:
2673: g.drawLine(x, y + h - 2, x + 1, y + h - 1);
2674: break;
2675: case SwingConstants.RIGHT:
2676: g.setColor(lightHighlight);
2677:
2678: g.drawLine(x, y, x + w - 3, y);
2679:
2680: g.setColor(darkShadow);
2681:
2682: g.drawLine(x + w - 2, y + 1, x + w - 1, y + 2);
2683:
2684:
2685: g.drawLine(x + w - 1, y + 3, x + w - 1, y + h - 3);
2686:
2687:
2688: g.drawLine(x + w - 2, y + h - 2, x + w - 3, y + h - 1);
2689:
2690:
2691: g.drawLine(x, y + h - 1, x + w - 4, y + h - 1);
2692:
2693: g.setColor(shadow);
2694:
2695:
2696: g.drawLine(x + w - 2, y + 2, x + w - 2, y + h - 3);
2697:
2698:
2699: g.drawLine(x, y + h - 2, x + w - 3, y + h - 2);
2700:
2701: break;
2702: }
2703:
2704: g.setColor(saved);
2705: }
2706:
2707:
2719: protected void paintTabBackground(Graphics g, int tabPlacement,
2720: int tabIndex, int x, int y, int w, int h,
2721: boolean isSelected)
2722: {
2723: Color saved = g.getColor();
2724:
2725: if (isSelected)
2726: g.setColor(selectedColor);
2727: else
2728: {
2729: Color bg = tabPane.getBackgroundAt(tabIndex);
2730: if (bg == null)
2731: bg = Color.LIGHT_GRAY;
2732: g.setColor(bg);
2733: }
2734:
2735: switch (tabPlacement)
2736: {
2737: case SwingConstants.TOP:
2738: g.fillRect(x + 1, y + 1, w - 1, h - 1);
2739: break;
2740: case SwingConstants.BOTTOM:
2741: g.fillRect(x, y, w - 1, h - 1);
2742: break;
2743: case SwingConstants.LEFT:
2744: g.fillRect(x + 1, y + 1, w - 1, h - 2);
2745: break;
2746: case SwingConstants.RIGHT:
2747: g.fillRect(x, y + 1, w - 1, h - 2);
2748: break;
2749: }
2750:
2751: g.setColor(saved);
2752: }
2753:
2754:
2761: protected void paintContentBorder(Graphics g, int tabPlacement,
2762: int selectedIndex)
2763: {
2764: int width = tabPane.getWidth();
2765: int height = tabPane.getHeight();
2766: Insets insets = tabPane.getInsets();
2767: Insets tabAreaInsets = getTabAreaInsets(tabPlacement);
2768:
2769:
2770: int x = insets.left;
2771: int y = insets.top;
2772: int w = width - insets.left - insets.right;
2773: int h = height - insets.top - insets.bottom;
2774:
2775: switch (tabPlacement)
2776: {
2777: case LEFT:
2778: x += calculateTabAreaWidth(tabPlacement, runCount, maxTabWidth);
2779: w -= x - insets.left;
2780: break;
2781: case RIGHT:
2782: w -= calculateTabAreaWidth(tabPlacement, runCount, maxTabWidth);
2783: break;
2784: case BOTTOM:
2785: h -= calculateTabAreaHeight(tabPlacement, runCount, maxTabHeight);
2786: break;
2787: case TOP:
2788: default:
2789: y += calculateTabAreaHeight(tabPlacement, runCount, maxTabHeight);
2790: h -= y - insets.top;
2791: }
2792:
2793:
2794: if (tabPane.isOpaque())
2795: {
2796: Color bg = UIManager.getColor("TabbedPane.contentAreaColor");
2797: g.setColor(bg);
2798: g.fillRect(x, y, w, h);
2799: }
2800:
2801:
2802: paintContentBorderTopEdge(g, tabPlacement, selectedIndex, x, y, w, h);
2803: paintContentBorderLeftEdge(g, tabPlacement, selectedIndex, x, y, w, h);
2804: paintContentBorderBottomEdge(g, tabPlacement, selectedIndex, x, y, w, h);
2805: paintContentBorderRightEdge(g, tabPlacement, selectedIndex, x, y, w, h);
2806: }
2807:
2808:
2819: protected void paintContentBorderTopEdge(Graphics g, int tabPlacement,
2820: int selectedIndex, int x, int y,
2821: int w, int h)
2822: {
2823: Color saved = g.getColor();
2824: g.setColor(lightHighlight);
2825:
2826: int startgap = rects[selectedIndex].x - currentScrollOffset;
2827: int endgap = rects[selectedIndex].x + rects[selectedIndex].width
2828: - currentScrollOffset;
2829:
2830:
2831:
2832: if (tabPlacement == SwingConstants.TOP && startgap >= 0)
2833: {
2834: g.drawLine(x, y, startgap, y);
2835: g.drawLine(endgap, y, x + w - 1, y);
2836:
2837: g.setColor(selectedColor);
2838: g.drawLine(startgap, y, endgap - 1, y);
2839: }
2840: else
2841: g.drawLine(x, y, x + w, y);
2842:
2843: g.setColor(selectedColor);
2844: g.drawLine(x, y + 1, x + w - 1, y + 1);
2845: g.drawLine(x, y + 2, x + w - 1, y + 2);
2846:
2847: g.setColor(saved);
2848: }
2849:
2850:
2861: protected void paintContentBorderLeftEdge(Graphics g, int tabPlacement,
2862: int selectedIndex, int x, int y,
2863: int w, int h)
2864: {
2865: Color saved = g.getColor();
2866: g.setColor(lightHighlight);
2867:
2868: int startgap = rects[selectedIndex].y - currentScrollOffset;
2869: int endgap = rects[selectedIndex].y + rects[selectedIndex].height
2870: - currentScrollOffset;
2871:
2872: int diff = 0;
2873:
2874: if (tabPlacement == SwingConstants.LEFT && startgap >= 0)
2875: {
2876: g.drawLine(x, y, x, startgap);
2877: g.drawLine(x, endgap, x, y + h - 1);
2878:
2879: g.setColor(selectedColor);
2880: g.drawLine(x, startgap, x, endgap - 1);
2881: }
2882: else
2883: g.drawLine(x, y, x, y + h - 1);
2884:
2885: g.setColor(selectedColor);
2886: g.drawLine(x + 1, y + 1, x + 1, y + h - 4);
2887:
2888: g.setColor(saved);
2889: }
2890:
2891:
2902: protected void paintContentBorderBottomEdge(Graphics g, int tabPlacement,
2903: int selectedIndex, int x, int y,
2904: int w, int h)
2905: {
2906: Color saved = g.getColor();
2907:
2908: int startgap = rects[selectedIndex].x - currentScrollOffset;
2909: int endgap = rects[selectedIndex].x + rects[selectedIndex].width
2910: - currentScrollOffset;
2911:
2912: if (tabPlacement == SwingConstants.BOTTOM && startgap >= 0)
2913: {
2914: g.setColor(shadow);
2915: g.drawLine(x + 1, y + h - 2, startgap, y + h - 2);
2916: g.drawLine(endgap, y + h - 2, x + w - 2, y + h - 2);
2917:
2918: g.setColor(darkShadow);
2919: g.drawLine(x, y + h - 1, startgap , y + h - 1);
2920: g.drawLine(endgap, y + h - 1, x + w - 1, y + h - 1);
2921:
2922: g.setColor(selectedColor);
2923: g.drawLine(startgap, y + h - 1, endgap - 1, y + h - 1);
2924: g.drawLine(startgap, y + h - 2, endgap - 1, y + h - 2);
2925: }
2926: else
2927: {
2928: g.setColor(shadow);
2929: g.drawLine(x + 1, y + h - 2, x + w - 1, y + h - 2);
2930: g.setColor(darkShadow);
2931: g.drawLine(x, y + h - 1, x + w - 1, y + h - 1);
2932: }
2933:
2934: g.setColor(selectedColor);
2935: g.drawLine(x + 1, y + h - 3, x + w - 2, y + h - 3);
2936:
2937: g.setColor(saved);
2938: }
2939:
2940:
2951: protected void paintContentBorderRightEdge(Graphics g, int tabPlacement,
2952: int selectedIndex, int x, int y,
2953: int w, int h)
2954: {
2955: Color saved = g.getColor();
2956: int startgap = rects[selectedIndex].y - currentScrollOffset;
2957: int endgap = rects[selectedIndex].y + rects[selectedIndex].height
2958: - currentScrollOffset;
2959:
2960: int diff = 0;
2961:
2962: if (tabPlacement == SwingConstants.RIGHT && startgap >= 0)
2963: {
2964: g.setColor(shadow);
2965: g.drawLine(x + w - 2, y + 1, x + w - 2, startgap);
2966: g.drawLine(x + w - 2, endgap, x + w - 2, y + h - 2);
2967:
2968: g.setColor(darkShadow);
2969: g.drawLine(x + w - 1, y, x + w - 1, startgap);
2970: g.drawLine(x + w - 1, endgap, x + w - 1, y + h - 2);
2971:
2972: g.setColor(selectedColor);
2973: g.drawLine(x + w - 2, startgap, x + w - 2, endgap - 1);
2974: g.drawLine(x + w - 1, startgap, x + w - 1, endgap - 1);
2975: }
2976: else
2977: {
2978: g.setColor(shadow);
2979: g.drawLine(x + w - 2, y + 1, x + w - 2, y + h - 2);
2980: g.setColor(darkShadow);
2981: g.drawLine(x + w - 1, y, x + w - 1, y + h - 2);
2982: }
2983:
2984: g.setColor(selectedColor);
2985: g.drawLine(x + w - 3, y + 1, x + w - 3, y + h - 4);
2986:
2987: g.setColor(saved);
2988: }
2989:
2990:
2998: public Rectangle getTabBounds(JTabbedPane pane, int i)
2999: {
3000:
3001: if (i >= rects.length)
3002: layoutManager.layoutContainer(pane);
3003: return rects[i];
3004: }
3005:
3006:
3013: public int getTabRunCount(JTabbedPane pane)
3014: {
3015: return runCount;
3016: }
3017:
3018:
3027: public int tabForCoordinate(JTabbedPane pane, int x, int y)
3028: {
3029:
3030: if (! tabPane.isValid())
3031: tabPane.validate();
3032:
3033: int tabCount = tabPane.getTabCount();
3034:
3035:
3036:
3037: int index = tabPane.getSelectedIndex();
3038: for (int i = 0; i < tabCount; ++i)
3039: {
3040: if (rects[i].contains(x, y))
3041: {
3042: index = i;
3043: break;
3044: }
3045: }
3046:
3047: return index;
3048: }
3049:
3050:
3058: protected Rectangle getTabBounds(int tabIndex, Rectangle dest)
3059: {
3060: dest.setBounds(getTabBounds(tabPane, tabIndex));
3061: return dest;
3062: }
3063:
3064:
3069: protected Component getVisibleComponent()
3070: {
3071: return visibleComponent;
3072: }
3073:
3074:
3079: protected void setVisibleComponent(Component component)
3080: {
3081:
3082: if (visibleComponent != null && visibleComponent != component
3083: && visibleComponent.getParent() == tabPane)
3084: {
3085: visibleComponent.setVisible(false);
3086: }
3087:
3088:
3089: if (component != null && ! component.isVisible())
3090: {
3091: component.setVisible(true);
3092: }
3093: visibleComponent = component;
3094: }
3095:
3096:
3102: protected void assureRectsCreated(int tabCount)
3103: {
3104: if (rects.length < tabCount)
3105: {
3106: Rectangle[] old = rects;
3107: rects = new Rectangle[tabCount];
3108: System.arraycopy(old, 0, rects, 0, old.length);
3109: for (int i = old.length; i < rects.length; i++)
3110: rects[i] = new Rectangle();
3111: }
3112: }
3113:
3114:
3118: protected void expandTabRunsArray()
3119: {
3120:
3121: if (tabRuns == null)
3122: tabRuns = new int[10];
3123: else
3124: {
3125: int[] newRuns = new int[tabRuns.length + 10];
3126: System.arraycopy(tabRuns, 0, newRuns, 0, tabRuns.length);
3127: tabRuns = newRuns;
3128: }
3129: }
3130:
3131:
3139: protected int getRunForTab(int tabCount, int tabIndex)
3140: {
3141: if (runCount == 1 && tabIndex < tabCount && tabIndex >= 0)
3142: return 0;
3143: for (int i = 0; i < runCount; i++)
3144: {
3145: int first = lastTabInRun(tabCount, getPreviousTabRun(i)) + 1;
3146: if (first == tabCount)
3147: first = 0;
3148: int last = lastTabInRun(tabCount, i);
3149: if (last >= tabIndex && first <= tabIndex)
3150: return i;
3151: }
3152: return -1;
3153: }
3154:
3155:
3163: protected int lastTabInRun(int tabCount, int run)
3164: {
3165: int lastTab;
3166: if (runCount == 1)
3167: lastTab = tabCount - 1;
3168: else
3169: {
3170: int nextRun;
3171: if (run == runCount - 1)
3172: nextRun = 0;
3173: else
3174: nextRun = run + 1;
3175:
3176: if (tabRuns[nextRun] == 0)
3177: lastTab = tabCount - 1;
3178: else
3179: lastTab = tabRuns[nextRun] - 1;
3180: }
3181: return lastTab;
3182: }
3183:
3184:
3191: protected int getTabRunOverlay(int tabPlacement)
3192: {
3193: return tabRunOverlay;
3194: }
3195:
3196:
3205: protected int getTabRunIndent(int tabPlacement, int run)
3206: {
3207: return 0;
3208: }
3209:
3210:
3218: protected boolean shouldPadTabRun(int tabPlacement, int run)
3219: {
3220: return true;
3221: }
3222:
3223:
3230: protected boolean shouldRotateTabRuns(int tabPlacement)
3231: {
3232: return true;
3233: }
3234:
3235:
3244: protected Icon getIconForTab(int tabIndex)
3245: {
3246: if (tabPane.isEnabledAt(tabIndex))
3247: return tabPane.getIconAt(tabIndex);
3248: else
3249: return tabPane.getDisabledIconAt(tabIndex);
3250: }
3251:
3252:
3259: protected View getTextViewForTab(int tabIndex)
3260: {
3261:
3262:
3263: return null;
3264: }
3265:
3266:
3276: protected int calculateTabHeight(int tabPlacement, int tabIndex,
3277: int fontHeight)
3278: {
3279:
3280:
3281: int height = fontHeight;
3282: Icon icon = getIconForTab(tabIndex);
3283: Insets tabInsets = getTabInsets(tabPlacement, tabIndex);
3284: if (icon != null)
3285: height = Math.max(height, icon.getIconHeight());
3286: height += tabInsets.top + tabInsets.bottom + 2;
3287: return height;
3288: }
3289:
3290:
3297: protected int calculateMaxTabHeight(int tabPlacement)
3298: {
3299: maxTabHeight = 0;
3300:
3301: FontMetrics fm = getFontMetrics();
3302: int fontHeight = fm.getHeight();
3303:
3304: for (int i = 0; i < tabPane.getTabCount(); i++)
3305: maxTabHeight = Math.max(calculateTabHeight(tabPlacement, i, fontHeight),
3306: maxTabHeight);
3307:
3308: return maxTabHeight;
3309: }
3310:
3311:
3321: protected int calculateTabWidth(int tabPlacement, int tabIndex,
3322: FontMetrics metrics)
3323: {
3324: Icon icon = getIconForTab(tabIndex);
3325: Insets insets = getTabInsets(tabPlacement, tabIndex);
3326:
3327: int width = 0;
3328: if (icon != null)
3329: {
3330: Rectangle vr = new Rectangle();
3331: Rectangle ir = new Rectangle();
3332: Rectangle tr = new Rectangle();
3333: layoutLabel(tabPlacement, getFontMetrics(), tabIndex,
3334: tabPane.getTitleAt(tabIndex), icon, vr, ir, tr,
3335: tabIndex == tabPane.getSelectedIndex());
3336: width = tr.union(ir).width;
3337: }
3338: else
3339: width = metrics.stringWidth(tabPane.getTitleAt(tabIndex));
3340:
3341: width += insets.left + insets.right;
3342: return width;
3343: }
3344:
3345:
3352: protected int calculateMaxTabWidth(int tabPlacement)
3353: {
3354: maxTabWidth = 0;
3355:
3356: FontMetrics fm = getFontMetrics();
3357:
3358: for (int i = 0; i < tabPane.getTabCount(); i++)
3359: maxTabWidth = Math.max(calculateTabWidth(tabPlacement, i, fm),
3360: maxTabWidth);
3361:
3362: return maxTabWidth;
3363: }
3364:
3365:
3375: protected int calculateTabAreaHeight(int tabPlacement, int horizRunCount,
3376: int maxTabHeight)
3377: {
3378: Insets insets = getTabAreaInsets(tabPlacement);
3379: int tabAreaHeight = horizRunCount * maxTabHeight
3380: - (horizRunCount - 1) * tabRunOverlay;
3381:
3382: tabAreaHeight += insets.top + insets.bottom;
3383:
3384: return tabAreaHeight;
3385: }
3386:
3387:
3397: protected int calculateTabAreaWidth(int tabPlacement, int vertRunCount,
3398: int maxTabWidth)
3399: {
3400: Insets insets = getTabAreaInsets(tabPlacement);
3401: int tabAreaWidth = vertRunCount * maxTabWidth
3402: - (vertRunCount - 1) * tabRunOverlay;
3403:
3404: tabAreaWidth += insets.left + insets.right;
3405:
3406: return tabAreaWidth;
3407: }
3408:
3409:
3417: protected Insets getTabInsets(int tabPlacement, int tabIndex)
3418: {
3419: return tabInsets;
3420: }
3421:
3422:
3429: protected Insets getSelectedTabPadInsets(int tabPlacement)
3430: {
3431: Insets target = new Insets(0, 0, 0, 0);
3432: rotateInsets(selectedTabPadInsets, target, tabPlacement);
3433: return target;
3434: }
3435:
3436:
3443: protected Insets getTabAreaInsets(int tabPlacement)
3444: {
3445: Insets target = new Insets(0, 0, 0, 0);
3446: rotateInsets(tabAreaInsets, target, tabPlacement);
3447: return target;
3448: }
3449:
3450:
3457: protected Insets getContentBorderInsets(int tabPlacement)
3458: {
3459: Insets target = new Insets(0, 0, 0, 0);
3460: rotateInsets(contentBorderInsets, target, tabPlacement);
3461: return target;
3462: }
3463:
3464:
3469: protected FontMetrics getFontMetrics()
3470: {
3471: FontMetrics fm = tabPane.getFontMetrics(tabPane.getFont());
3472: return fm;
3473: }
3474:
3475:
3481: protected void navigateSelectedTab(int direction)
3482: {
3483: int tabPlacement = tabPane.getTabPlacement();
3484: if (tabPlacement == SwingConstants.TOP
3485: || tabPlacement == SwingConstants.BOTTOM)
3486: {
3487: if (direction == SwingConstants.WEST)
3488: selectPreviousTabInRun(tabPane.getSelectedIndex());
3489: else if (direction == SwingConstants.EAST)
3490: selectNextTabInRun(tabPane.getSelectedIndex());
3491:
3492: else
3493: {
3494: int offset = getTabRunOffset(tabPlacement, tabPane.getTabCount(),
3495: tabPane.getSelectedIndex(),
3496: (tabPlacement == SwingConstants.TOP)
3497: ? direction == SwingConstants.NORTH
3498: : direction == SwingConstants.SOUTH);
3499: selectAdjacentRunTab(tabPlacement, tabPane.getSelectedIndex(),
3500: offset);
3501: }
3502: }
3503: if (tabPlacement == SwingConstants.LEFT
3504: || tabPlacement == SwingConstants.RIGHT)
3505: {
3506: if (direction == SwingConstants.NORTH)
3507: selectPreviousTabInRun(tabPane.getSelectedIndex());
3508: else if (direction == SwingConstants.SOUTH)
3509: selectNextTabInRun(tabPane.getSelectedIndex());
3510: else
3511: {
3512: int offset = getTabRunOffset(tabPlacement, tabPane.getTabCount(),
3513: tabPane.getSelectedIndex(),
3514: (tabPlacement == SwingConstants.LEFT)
3515: ? direction == SwingConstants.WEST
3516: : direction == SwingConstants.EAST);
3517: selectAdjacentRunTab(tabPlacement, tabPane.getSelectedIndex(),
3518: offset);
3519: }
3520: }
3521: }
3522:
3523:
3528: protected void selectNextTabInRun(int current)
3529: {
3530: current = getNextTabIndexInRun(tabPane.getTabCount(),
3531: current);
3532:
3533: if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT)
3534: scrollTab(current, tabPane.getTabPlacement());
3535:
3536: tabPane.setSelectedIndex(current);
3537: }
3538:
3539:
3544: protected void selectPreviousTabInRun(int current)
3545: {
3546: current = getPreviousTabIndexInRun(tabPane.getTabCount(),
3547: current);
3548:
3549: if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT)
3550: scrollTab(current, tabPane.getTabPlacement());
3551:
3552: tabPane.setSelectedIndex(current);
3553: }
3554:
3555:
3560: protected void selectNextTab(int current)
3561: {
3562: current = getNextTabIndex(current);
3563:
3564: if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT)
3565: scrollTab(current, tabPane.getTabPlacement());
3566:
3567: tabPane.setSelectedIndex(current);
3568: }
3569:
3570:
3575: protected void selectPreviousTab(int current)
3576: {
3577: current = getPreviousTabIndex(current);
3578:
3579: if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT)
3580: scrollTab(current, tabPane.getTabPlacement());
3581:
3582: tabPane.setSelectedIndex(current);
3583: }
3584:
3585:
3596: protected void selectAdjacentRunTab(int tabPlacement, int tabIndex,
3597: int offset)
3598: {
3599: int x = rects[tabIndex].x + rects[tabIndex].width / 2;
3600: int y = rects[tabIndex].y + rects[tabIndex].height / 2;
3601:
3602: switch (tabPlacement)
3603: {
3604: case SwingConstants.TOP:
3605: case SwingConstants.BOTTOM:
3606: y += offset;
3607: break;
3608: case SwingConstants.RIGHT:
3609: case SwingConstants.LEFT:
3610: x += offset;
3611: break;
3612: }
3613:
3614: int index = tabForCoordinate(tabPane, x, y);
3615: if (index != -1)
3616: {
3617: if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT)
3618: scrollTab(index, tabPlacement);
3619: tabPane.setSelectedIndex(index);
3620: }
3621: }
3622:
3623:
3624:
3625:
3626:
3627:
3628:
3629:
3644: protected int getTabRunOffset(int tabPlacement, int tabCount, int tabIndex,
3645: boolean forward)
3646: {
3647: int currRun = getRunForTab(tabCount, tabIndex);
3648: int offset;
3649: int nextRun = forward ? getNextTabRun(currRun) : getPreviousTabRun(currRun);
3650: if (tabPlacement == SwingConstants.TOP
3651: || tabPlacement == SwingConstants.BOTTOM)
3652: offset = rects[lastTabInRun(tabCount, nextRun)].y
3653: - rects[lastTabInRun(tabCount, currRun)].y;
3654: else
3655: offset = rects[lastTabInRun(tabCount, nextRun)].x
3656: - rects[lastTabInRun(tabCount, currRun)].x;
3657:
3658: return offset;
3659: }
3660:
3661:
3668: protected int getPreviousTabIndex(int base)
3669: {
3670: base--;
3671: if (base < 0)
3672: return tabPane.getTabCount() - 1;
3673: return base;
3674: }
3675:
3676:
3683: protected int getNextTabIndex(int base)
3684: {
3685: base++;
3686: if (base == tabPane.getTabCount())
3687: return 0;
3688: return base;
3689: }
3690:
3691:
3700: protected int getNextTabIndexInRun(int tabCount, int base)
3701: {
3702: int index = getNextTabIndex(base);
3703: int run = getRunForTab(tabCount, base);
3704: if (base == lastTabInRun(tabCount, run))
3705: index = (run > 0)
3706: ? lastTabInRun(tabCount, getPreviousTabRun(run)) + 1
3707: : 0;
3708:
3709: return index;
3710: }
3711:
3712:
3721: protected int getPreviousTabIndexInRun(int tabCount, int base)
3722: {
3723: int index = getPreviousTabIndex(base);
3724: int run = getRunForTab(tabCount, base);
3725: if (index == lastTabInRun(tabCount, getPreviousTabRun(run)))
3726: index = lastTabInRun(tabCount, run);
3727:
3728: return index;
3729: }
3730:
3731:
3738: protected int getPreviousTabRun(int baseRun)
3739: {
3740: if (getTabRunCount(tabPane) == 1)
3741: return 1;
3742:
3743: int prevRun = --baseRun;
3744: if (prevRun < 0)
3745: prevRun = getTabRunCount(tabPane) - 1;
3746: return prevRun;
3747: }
3748:
3749:
3756: protected int getNextTabRun(int baseRun)
3757: {
3758: if (getTabRunCount(tabPane) == 1)
3759: return 1;
3760:
3761: int nextRun = ++baseRun;
3762: if (nextRun == getTabRunCount(tabPane))
3763: nextRun = 0;
3764: return nextRun;
3765: }
3766:
3767:
3779: protected static void rotateInsets(Insets topInsets, Insets targetInsets,
3780: int targetPlacement)
3781: {
3782:
3783:
3784: switch (targetPlacement)
3785: {
3786: default:
3787: case SwingConstants.TOP:
3788: targetInsets.top = topInsets.top;
3789: targetInsets.left = topInsets.left;
3790: targetInsets.right = topInsets.right;
3791: targetInsets.bottom = topInsets.bottom;
3792: break;
3793: case SwingConstants.LEFT:
3794: targetInsets.left = topInsets.top;
3795: targetInsets.top = topInsets.left;
3796: targetInsets.right = topInsets.bottom;
3797: targetInsets.bottom = topInsets.right;
3798: break;
3799: case SwingConstants.BOTTOM:
3800: targetInsets.top = topInsets.bottom;
3801: targetInsets.bottom = topInsets.top;
3802: targetInsets.left = topInsets.left;
3803: targetInsets.right = topInsets.right;
3804: break;
3805: case SwingConstants.RIGHT:
3806: targetInsets.top = topInsets.left;
3807: targetInsets.left = topInsets.bottom;
3808: targetInsets.bottom = topInsets.right;
3809: targetInsets.right = topInsets.top;
3810: break;
3811: }
3812: }
3813:
3814: ActionMap getActionMap()
3815: {
3816: ActionMap map = (ActionMap) UIManager.get("TabbedPane.actionMap");
3817:
3818: if (map == null)
3819: {
3820: map = createActionMap();
3821: if (map != null)
3822: UIManager.put("TabbedPane.actionMap", map);
3823: }
3824: return map;
3825: }
3826:
3827: ActionMap createActionMap()
3828: {
3829: ActionMap map = new ActionMapUIResource();
3830:
3831: map.put("navigatePageDown", new NavigatePageDownAction());
3832: map.put("navigatePageUp", new NavigatePageUpAction());
3833: map.put("navigateDown",
3834: new NavigateAction("navigateDown", SwingConstants.SOUTH));
3835:
3836: map.put("navigateUp",
3837: new NavigateAction("navigateUp", SwingConstants.NORTH));
3838:
3839: map.put("navigateLeft",
3840: new NavigateAction("navigateLeft", SwingConstants.WEST));
3841:
3842: map.put("navigateRight",
3843: new NavigateAction("navigateRight", SwingConstants.EAST));
3844:
3845: map.put("requestFocusForVisibleComponent",
3846: new RequestFocusForVisibleComponentAction());
3847: map.put("requestFocus", new RequestFocusAction());
3848:
3849: return map;
3850: }
3851:
3852:
3862: protected void setRolloverTab(int index)
3863: {
3864: rolloverTab = index;
3865: }
3866:
3867:
3876: protected int getRolloverTab()
3877: {
3878: return rolloverTab;
3879: }
3880: }