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:
83:
91: public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
92: {
93:
94: static class NavigateAction extends AbstractAction
95: {
96: int direction;
97:
98: NavigateAction(String name, int dir)
99: {
100: super(name);
101: direction = dir;
102: }
103:
104: public void actionPerformed(ActionEvent event)
105: {
106: JTabbedPane tp = (JTabbedPane) event.getSource();
107: BasicTabbedPaneUI ui = (BasicTabbedPaneUI) tp.getUI();
108:
109: ui.navigateSelectedTab(direction);
110: }
111:
112: }
113:
114: static class NavigatePageDownAction extends AbstractAction
115: {
116:
117: public NavigatePageDownAction()
118: {
119: super("navigatePageDown");
120: }
121:
122: public void actionPerformed(ActionEvent event)
123: {
124: JTabbedPane tp = (JTabbedPane) event.getSource();
125: BasicTabbedPaneUI ui = (BasicTabbedPaneUI) tp.getUI();
126:
127: int i = tp.getSelectedIndex();
128:
129: if (i < 0)
130: i = 0;
131:
132: ui.selectNextTabInRun(i);
133: }
134:
135: }
136:
137: static class NavigatePageUpAction extends AbstractAction
138: {
139:
140: public NavigatePageUpAction()
141: {
142: super("navigatePageUp");
143: }
144:
145: public void actionPerformed(ActionEvent event)
146: {
147: JTabbedPane tp = (JTabbedPane) event.getSource();
148: BasicTabbedPaneUI ui = (BasicTabbedPaneUI) tp.getUI();
149:
150: int i = tp.getSelectedIndex();
151:
152: if (i < 0)
153: i = 0;
154:
155: ui.selectPreviousTabInRun(i);
156:
157: }
158: }
159:
160: static class RequestFocusAction extends AbstractAction
161: {
162:
163: public RequestFocusAction()
164: {
165: super("requestFocus");
166: }
167:
168: public void actionPerformed(ActionEvent event)
169: {
170: ((JTabbedPane) event.getSource()).requestFocus();
171: }
172:
173: }
174:
175: static class RequestFocusForVisibleComponentAction extends AbstractAction
176: {
177:
178: public RequestFocusForVisibleComponentAction()
179: {
180: super("requestFocusForVisibleComponent");
181: }
182:
183: public void actionPerformed(ActionEvent event)
184: {
185: JTabbedPane tp = (JTabbedPane) event.getSource();
186:
187:
188:
189:
190:
191: tp.getSelectedComponent().requestFocus();
192: }
193:
194: }
195:
196:
211: public class FocusHandler extends FocusAdapter
212: {
213:
218: public void focusGained(FocusEvent e)
219: {
220: Object source = e.getSource();
221: if (source == panel )
222: tabPane.requestFocus();
223: else if (source == tabPane)
224: tabPane.repaint();
225: }
226:
227:
232: public void focusLost(FocusEvent e)
233: {
234: if (e.getOppositeComponent() == tabPane.getSelectedComponent())
235: tabPane.requestFocus();
236: else if (e.getSource() == tabPane)
237: tabPane.repaint();
238: }
239: }
240:
241:
250: public class MouseHandler extends MouseAdapter
251: {
252: public void mouseReleased(MouseEvent e)
253: {
254: Object s = e.getSource();
255:
256:
257:
258:
259: if (tabPane != e.getSource())
260: {
261: redispatchEvent(e);
262: e.setSource(s);
263: }
264: }
265:
266:
272: public void mousePressed(MouseEvent e)
273: {
274: Object s = e.getSource();
275:
276:
277:
278:
279: if (tabPane != e.getSource())
280: {
281: redispatchEvent(e);
282: e.setSource(s);
283: }
284:
285: int placement = tabPane.getTabPlacement();
286:
287: if (s == incrButton)
288: {
289: if(!incrButton.isEnabled())
290: return;
291:
292: currentScrollLocation++;
293:
294: switch (placement)
295: {
296: case JTabbedPane.TOP:
297: case JTabbedPane.BOTTOM:
298: currentScrollOffset = getTabAreaInsets(placement).left;
299: for (int i = 0; i < currentScrollLocation; i++)
300: currentScrollOffset += rects[i].width;
301: break;
302: default:
303: currentScrollOffset = getTabAreaInsets(placement).top;
304: for (int i = 0; i < currentScrollLocation; i++)
305: currentScrollOffset += rects[i].height;
306: break;
307: }
308:
309: updateViewPosition();
310: updateButtons();
311:
312: tabPane.repaint();
313: }
314: else if (s == decrButton)
315: {
316: if(!decrButton.isEnabled())
317: return;
318:
319:
320:
321:
322: if (currentScrollLocation > 0)
323: currentScrollLocation--;
324:
325:
326: currentScrollOffset = 0;
327:
328: switch (placement)
329: {
330: case JTabbedPane.TOP:
331: case JTabbedPane.BOTTOM:
332:
333: if (currentScrollLocation > 0)
334: currentScrollOffset = getTabAreaInsets(placement).left;
335:
336: for (int i = 0; i < currentScrollLocation; i++)
337: currentScrollOffset += rects[i].width;
338: break;
339: default:
340:
341: if (currentScrollLocation > 0)
342: currentScrollOffset = getTabAreaInsets(placement).top;
343:
344: for (int i = 0; i < currentScrollLocation; i++)
345: currentScrollOffset += rects[i].height;
346: }
347:
348: updateViewPosition();
349: updateButtons();
350:
351: tabPane.repaint();
352: }
353: else if (tabPane.isEnabled())
354: {
355: int index = tabForCoordinate(tabPane, e.getX(), e.getY());
356: if (!tabPane.isEnabledAt(index))
357: return;
358:
359: if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT
360: && s == panel)
361: {
362: scrollTab(index, placement);
363:
364: tabPane.setSelectedIndex(index);
365: tabPane.repaint();
366: }
367: else
368: {
369: tabPane.setSelectedIndex(index);
370: tabPane.revalidate();
371: tabPane.repaint();
372: }
373:
374: }
375:
376: }
377:
378:
384: public void mouseEntered(MouseEvent e)
385: {
386: Object s = e.getSource();
387:
388:
389:
390:
391: if (tabPane != e.getSource())
392: {
393: redispatchEvent(e);
394: e.setSource(s);
395: }
396:
397: int tabIndex = tabForCoordinate(tabPane, e.getX(), e.getY());
398: setRolloverTab(tabIndex);
399: }
400:
401:
407: public void mouseExited(MouseEvent e)
408: {
409: Object s = e.getSource();
410:
411:
412:
413:
414: if (tabPane != e.getSource())
415: {
416: redispatchEvent(e);
417: e.setSource(s);
418: }
419:
420: setRolloverTab(-1);
421: }
422:
423:
429: public void mouseMoved(MouseEvent ev)
430: {
431: Object s = ev.getSource();
432:
433: if (tabPane != ev.getSource())
434: {
435: ev.setSource(tabPane);
436: tabPane.dispatchEvent(ev);
437:
438: ev.setSource(s);
439: }
440:
441: int tabIndex = tabForCoordinate(tabPane, ev.getX(), ev.getY());
442: setRolloverTab(tabIndex);
443: }
444:
445:
450: void redispatchEvent(MouseEvent me)
451: {
452: me.setSource(tabPane);
453: Point viewPos = viewport.getViewPosition();
454: viewPos.x -= viewport.getX();
455: viewPos.y -= viewport.getY();
456: me.translatePoint(-viewPos.x, -viewPos.y);
457: tabPane.dispatchEvent(me);
458:
459: me.translatePoint(viewPos.x, viewPos.y);
460: }
461:
462: }
463:
464:
471: public class PropertyChangeHandler implements PropertyChangeListener
472: {
473:
479: public void propertyChange(PropertyChangeEvent e)
480: {
481: out:
482: {
483: if (e.getPropertyName().equals("tabLayoutPolicy"))
484: {
485: currentScrollLocation = currentScrollOffset = 0;
486:
487: layoutManager = createLayoutManager();
488:
489: tabPane.setLayout(layoutManager);
490: }
491: else if (e.getPropertyName().equals("tabPlacement")
492: && tabPane.getTabLayoutPolicy()
493: == JTabbedPane.SCROLL_TAB_LAYOUT)
494: {
495: incrButton = createIncreaseButton();
496: decrButton = createDecreaseButton();
497:
498:
499:
500:
501:
502:
503:
504:
505:
506: int oldPlacement = ((Integer) e.getOldValue()).intValue();
507: int newPlacement = ((Integer) e.getNewValue()).intValue();
508: switch (newPlacement)
509: {
510: case JTabbedPane.TOP:
511: case JTabbedPane.BOTTOM:
512: if (oldPlacement == JTabbedPane.TOP
513: || oldPlacement == JTabbedPane.BOTTOM)
514: break out;
515:
516: currentScrollOffset = getTabAreaInsets(newPlacement).left;
517: break;
518: default:
519: if (oldPlacement == JTabbedPane.LEFT
520: || oldPlacement == JTabbedPane.RIGHT)
521: break out;
522:
523: currentScrollOffset = getTabAreaInsets(newPlacement).top;
524: }
525:
526: updateViewPosition();
527: updateButtons();
528: }
529: }
530:
531: tabPane.revalidate();
532: tabPane.repaint();
533: }
534: }
535:
536:
545: public class TabbedPaneLayout implements LayoutManager
546: {
547:
553: public void addLayoutComponent(String name, Component comp)
554: {
555:
556: }
557:
558:
562: public void calculateLayoutInfo()
563: {
564: int count = tabPane.getTabCount();
565: assureRectsCreated(count);
566: calculateTabRects(tabPane.getTabPlacement(), count);
567: tabRunsDirty = false;
568: }
569:
570:
578: protected Dimension calculateSize(boolean minimum)
579: {
580: int tabPlacement = tabPane.getTabPlacement();
581:
582: int width = 0;
583: int height = 0;
584: Component c;
585: Dimension dims;
586:
587:
588:
589: int count = tabPane.getTabCount();
590: for (int i = 0; i < count; i++)
591: {
592: c = tabPane.getComponentAt(i);
593: if (c == null)
594: continue;
595: dims = minimum ? c.getMinimumSize() : c.getPreferredSize();
596: if (dims != null)
597: {
598: height = Math.max(height, dims.height);
599: width = Math.max(width, dims.width);
600: }
601: }
602:
603: Insets tabAreaInsets = getTabAreaInsets(tabPlacement);
604: if (tabPlacement == SwingConstants.TOP
605: || tabPlacement == SwingConstants.BOTTOM)
606: {
607: width = Math.max(calculateMaxTabWidth(tabPlacement), width);
608:
609: height += preferredTabAreaHeight(tabPlacement,
610: width - tabAreaInsets.left
611: - tabAreaInsets.right);
612: }
613: else
614: {
615: height = Math.max(calculateMaxTabHeight(tabPlacement), height);
616:
617: width += preferredTabAreaWidth(tabPlacement,
618: height - tabAreaInsets.top
619: - tabAreaInsets.bottom);
620: }
621:
622: Insets tabPaneInsets = tabPane.getInsets();
623: return new Dimension(width + tabPaneInsets.left + tabPaneInsets.right,
624: height + tabPaneInsets.top + tabPaneInsets.bottom);
625: }
626:
627:
628:
629:
630:
631:
632:
633:
634:
635:
636:
637:
646: protected void calculateTabRects(int tabPlacement, int tabCount)
647: {
648: Insets insets = tabPane.getInsets();
649: Insets tabAreaInsets = getTabAreaInsets(tabPlacement);
650: Dimension size = tabPane.getSize();
651:
652:
653: int x;
654: int y;
655:
656: int breakAt;
657:
658:
659: switch (tabPlacement)
660: {
661: case LEFT:
662: maxTabWidth = calculateMaxTabWidth(tabPlacement);
663: x = insets.left + tabAreaInsets.left;
664: y = insets.top + tabAreaInsets.top;
665: breakAt = size.height - (insets.bottom + tabAreaInsets.bottom);
666: break;
667: case RIGHT:
668: maxTabWidth = calculateMaxTabWidth(tabPlacement);
669: x = size.width - (insets.right + tabAreaInsets.right)
670: - maxTabWidth - 1;
671: y = insets.top + tabAreaInsets.top;
672: breakAt = size.height - (insets.bottom + tabAreaInsets.bottom);
673: break;
674: case BOTTOM:
675: maxTabHeight = calculateMaxTabHeight(tabPlacement);
676: x = insets.left + tabAreaInsets.left;
677: y = size.height - (insets.bottom + tabAreaInsets.bottom)
678: - maxTabHeight - 1;
679: breakAt = size.width - (insets.right + tabAreaInsets.right);
680: break;
681: case TOP:
682: default:
683: maxTabHeight = calculateMaxTabHeight(tabPlacement);
684: x = insets.left + tabAreaInsets.left;
685: y = insets.top + tabAreaInsets.top;
686: breakAt = size.width - (insets.right + tabAreaInsets.right);
687: break;
688: }
689:
690: if (tabCount == 0)
691: return;
692:
693: FontMetrics fm = getFontMetrics();
694: runCount = 0;
695: selectedRun = -1;
696: int selectedIndex = tabPane.getSelectedIndex();
697: if (selectedIndex < 0)
698: selectedIndex = 0;
699:
700: Rectangle rect;
701:
702:
703: if (tabPlacement == SwingConstants.TOP
704: || tabPlacement == SwingConstants.BOTTOM)
705: {
706: for (int i = 0; i < tabCount; i++)
707: {
708: rect = rects[i];
709: if (i > 0)
710: {
711: rect.x = rects[i - 1].x + rects[i - 1].width;
712: }
713: else
714: {
715: tabRuns[0] = 0;
716: runCount = 1;
717: maxTabWidth = 0;
718: rect.x = x;
719: }
720: rect.width = calculateTabWidth(tabPlacement, i, fm);
721: maxTabWidth = Math.max(maxTabWidth, rect.width);
722:
723: if (rect.x != 2 + insets.left && rect.x + rect.width > breakAt)
724: {
725: if (runCount > tabRuns.length - 1)
726: expandTabRunsArray();
727: tabRuns[runCount] = i;
728: runCount++;
729: rect.x = x;
730: }
731:
732: rect.y = y;
733: rect.height = maxTabHeight;
734: if (i == selectedIndex)
735: selectedRun = runCount - 1;
736: }
737: }
738: else
739: {
740: for (int i = 0; i < tabCount; i++)
741: {
742: rect = rects[i];
743: if (i > 0)
744: {
745: rect.y = rects[i - 1].y + rects[i - 1].height;
746: }
747: else
748: {
749: tabRuns[0] = 0;
750: runCount = 1;
751: maxTabHeight = 0;
752: rect.y = y;
753: }
754: rect.height = calculateTabHeight(tabPlacement, i,
755: fm.getHeight());
756: maxTabHeight = Math.max(maxTabHeight, rect.height);
757:
758: if (rect.y != 2 + insets.top && rect.y + rect.height > breakAt)
759: {
760: if (runCount > tabRuns.length - 1)
761: expandTabRunsArray();
762: tabRuns[runCount] = i;
763: runCount++;
764: rect.y = y;
765: }
766:
767: rect.x = x;
768: rect.width = maxTabWidth;
769:
770: if (i == selectedIndex)
771: selectedRun = runCount - 1;
772: }
773: }
774:
775: if (runCount > 1)
776: {
777: int start;
778: if (tabPlacement == SwingConstants.TOP
779: || tabPlacement == SwingConstants.BOTTOM)
780: start = x;
781: else
782: start = y;
783: normalizeTabRuns(tabPlacement, tabCount, start, breakAt);
784: selectedRun = getRunForTab(tabCount, selectedIndex);
785: if (shouldRotateTabRuns(tabPlacement))
786: {
787: rotateTabRuns(tabPlacement, selectedRun);
788: }
789: }
790:
791:
792: if (runCount == 1)
793: return;
794:
795:
796: int tabRunOverlay = getTabRunOverlay(tabPlacement);
797: for (int i = runCount - 1; i >= 0; --i)
798: {
799: int start = tabRuns[i];
800: int nextIndex;
801: if (i == runCount - 1)
802: nextIndex = 0;
803: else
804: nextIndex = i + 1;
805: int next = tabRuns[nextIndex];
806: int end = next != 0 ? next - 1 : tabCount - 1;
807: if (tabPlacement == SwingConstants.TOP
808: || tabPlacement == SwingConstants.BOTTOM)
809: {
810: for (int j = start; j <= end; ++j)
811: {
812: rect = rects[j];
813: rect.y = y;
814: rect.x += getTabRunIndent(tabPlacement, i);
815: }
816: if (shouldPadTabRun(tabPlacement, i))
817: {
818: padTabRun(tabPlacement, start, end, breakAt);
819: }
820: if (tabPlacement == BOTTOM)
821: y -= maxTabHeight - tabRunOverlay;
822: else
823: y += maxTabHeight - tabRunOverlay;
824: }
825: else
826: {
827: for (int j = start; j <= end; ++j)
828: {
829: rect = rects[j];
830: rect.x = x;
831: rect.y += getTabRunIndent(tabPlacement, i);
832: }
833: if (shouldPadTabRun(tabPlacement, i))
834: {
835: padTabRun(tabPlacement, start, end, breakAt);
836: }
837: if (tabPlacement == RIGHT)
838: x -= maxTabWidth - tabRunOverlay;
839: else
840: x += maxTabWidth - tabRunOverlay;
841:
842: }
843: }
844: padSelectedTab(tabPlacement, selectedIndex);
845: }
846:
847:
854: public void layoutContainer(Container parent)
855: {
856: calculateLayoutInfo();
857:
858: int tabPlacement = tabPane.getTabPlacement();
859: Insets insets = tabPane.getInsets();
860:
861: int selectedIndex = tabPane.getSelectedIndex();
862:
863: Component selectedComponent = null;
864: if (selectedIndex >= 0)
865: selectedComponent = tabPane.getComponentAt(selectedIndex);
866:
867:
868:
869: if (selectedComponent != null)
870: {
871: setVisibleComponent(selectedComponent);
872: }
873:
874: int childCount = tabPane.getComponentCount();
875: if (childCount > 0)
876: {
877: int compX;
878: int compY;
879: int tabAreaWidth = 0;
880: int tabAreaHeight = 0;
881: switch (tabPlacement)
882: {
883: case LEFT:
884: tabAreaWidth = calculateTabAreaWidth(tabPlacement, runCount,
885: maxTabWidth);
886: compX = tabAreaWidth + insets.left + contentBorderInsets.left;
887: compY = insets.top + contentBorderInsets.top;
888: break;
889: case RIGHT:
890: tabAreaWidth = calculateTabAreaWidth(tabPlacement, runCount,
891: maxTabWidth);
892: compX = insets.left + contentBorderInsets.left;
893: compY = insets.top + contentBorderInsets.top;
894: break;
895: case BOTTOM:
896: tabAreaHeight = calculateTabAreaHeight(tabPlacement, runCount,
897: maxTabHeight);
898: compX = insets.left + contentBorderInsets.left;
899: compY = insets.top + contentBorderInsets.top;
900: break;
901: case TOP:
902: default:
903: tabAreaHeight = calculateTabAreaHeight(tabPlacement, runCount,
904: maxTabHeight);
905:
906: compX = insets.left + contentBorderInsets.left;
907: compY = tabAreaHeight + insets.top + contentBorderInsets.top;
908: }
909: Rectangle bounds = tabPane.getBounds();
910: int compWidth = bounds.width - tabAreaWidth - insets.left
911: - insets.right - contentBorderInsets.left
912: - contentBorderInsets.right;
913: int compHeight = bounds.height - tabAreaHeight - insets.top
914: - insets.bottom - contentBorderInsets.top
915: - contentBorderInsets.bottom;
916:
917:
918: for (int i = 0; i < childCount; ++i)
919: {
920: Component c = tabPane.getComponent(i);
921: c.setBounds(compX, compY, compWidth, compHeight);
922: }
923: }
924: }
925:
926:
933: public Dimension minimumLayoutSize(Container parent)
934: {
935: return calculateSize(true);
936: }
937:
938:
939:
940:
941:
942:
943:
944:
945:
946:
947:
948:
957: protected void normalizeTabRuns(int tabPlacement, int tabCount, int start,
958: int max)
959: {
960: boolean horizontal = tabPlacement == TOP || tabPlacement == BOTTOM;
961: int currentRun = runCount - 1;
962: double weight = 1.25;
963: for (boolean adjust = true; adjust == true;)
964: {
965: int last = lastTabInRun(tabCount, currentRun);
966: int prevLast = lastTabInRun(tabCount, currentRun - 1);
967: int end;
968: int prevLength;
969: if (horizontal)
970: {
971: end = rects[last].x + rects[last].width;
972: prevLength = (int) (maxTabWidth * weight);
973: }
974: else
975: {
976: end = rects[last].y + rects[last].height;
977: prevLength = (int) (maxTabWidth * weight * 2);
978: }
979: if (max - end > prevLength)
980: {
981: tabRuns[currentRun] = prevLast;
982: if (horizontal)
983: rects[prevLast].x = start;
984: else
985: rects[prevLast].y = start;
986: for (int i = prevLast + 1; i <= last; i++)
987: {
988: if (horizontal)
989: rects[i].x = rects[i - 1].x + rects[i - 1].width;
990: else
991: rects[i].y = rects[i - 1].y + rects[i - 1].height;
992: }
993: }
994: else if (currentRun == runCount - 1)
995: adjust = false;
996: if (currentRun - 1 > 0)
997: currentRun -= 1;
998: else
999: {
1000:
1001:
1002: currentRun = runCount - 1;
1003: weight += 0.25;
1004: }
1005: }
1006: }
1007:
1008:
1015: protected void padSelectedTab(int tabPlacement, int selectedIndex)
1016: {
1017: Insets insets = getSelectedTabPadInsets(tabPlacement);
1018: rects[selectedIndex].x -= insets.left;
1019: rects[selectedIndex].y -= insets.top;
1020: rects[selectedIndex].width += insets.left + insets.right;
1021: rects[selectedIndex].height += insets.top + insets.bottom;
1022: }
1023:
1024:
1025:
1026:
1027:
1028:
1029:
1030:
1031:
1041: protected void padTabRun(int tabPlacement, int start, int end, int max)
1042: {
1043: if (tabPlacement == SwingConstants.TOP
1044: || tabPlacement == SwingConstants.BOTTOM)
1045: {
1046: int runWidth = rects[end].x + rects[end].width;
1047: int spaceRemaining = max - runWidth;
1048: int numTabs = end - start + 1;
1049:
1050:
1051: int spaceAllocated = spaceRemaining / numTabs;
1052: int currX = rects[start].x;
1053: for (int i = start; i <= end; i++)
1054: {
1055: rects[i].x = currX;
1056: rects[i].width += spaceAllocated;
1057:
1058: currX += rects[i].width;
1059:
1060:
1061:
1062:
1063:
1064: if (i == end && rects[i].x + rects[i].width != max)
1065: rects[i].width = max - rects[i].x;
1066: }
1067: }
1068: else
1069: {
1070: int runHeight = rects[end].y + rects[end].height;
1071: int spaceRemaining = max - runHeight;
1072: int numTabs = end - start + 1;
1073:
1074: int spaceAllocated = spaceRemaining / numTabs;
1075: int currY = rects[start].y;
1076: for (int i = start; i <= end; i++)
1077: {
1078: rects[i].y = currY;
1079: rects[i].height += spaceAllocated;
1080: currY += rects[i].height;
1081: if (i == end && rects[i].y + rects[i].height != max)
1082: rects[i].height = max - rects[i].y;
1083: }
1084: }
1085: }
1086:
1087:
1094: public Dimension preferredLayoutSize(Container parent)
1095: {
1096: return calculateSize(false);
1097: }
1098:
1099:
1108: protected int preferredTabAreaHeight(int tabPlacement, int width)
1109: {
1110: if (tabPane.getTabCount() == 0)
1111: return calculateTabAreaHeight(tabPlacement, 0, 0);
1112:
1113: int runs = 0;
1114: int runWidth = 0;
1115: int tabWidth = 0;
1116:
1117: FontMetrics fm = getFontMetrics();
1118:
1119: Insets tabAreaInsets = getTabAreaInsets(tabPlacement);
1120: Insets insets = tabPane.getInsets();
1121:
1122:
1123: width -= tabAreaInsets.left + tabAreaInsets.right + insets.left
1124: + insets.right;
1125:
1126:
1127:
1128:
1129:
1130:
1131: for (int i = 0; i < tabPane.getTabCount(); i++)
1132: {
1133: tabWidth = calculateTabWidth(tabPlacement, i, fm);
1134: if (runWidth + tabWidth > width)
1135: {
1136: runWidth = tabWidth;
1137: runs++;
1138: }
1139: else
1140: runWidth += tabWidth;
1141: }
1142: runs++;
1143:
1144: int maxTabHeight = calculateMaxTabHeight(tabPlacement);
1145: int tabAreaHeight = calculateTabAreaHeight(tabPlacement, runs,
1146: maxTabHeight);
1147: return tabAreaHeight;
1148: }
1149:
1150:
1159: protected int preferredTabAreaWidth(int tabPlacement, int height)
1160: {
1161: if (tabPane.getTabCount() == 0)
1162: return calculateTabAreaHeight(tabPlacement, 0, 0);
1163:
1164: int runs = 0;
1165: int runHeight = 0;
1166: int tabHeight = 0;
1167:
1168: FontMetrics fm = getFontMetrics();
1169:
1170: Insets tabAreaInsets = getTabAreaInsets(tabPlacement);
1171: Insets insets = tabPane.getInsets();
1172:
1173: height -= tabAreaInsets.top + tabAreaInsets.bottom + insets.top
1174: + insets.bottom;
1175: int fontHeight = fm.getHeight();
1176:
1177: for (int i = 0; i < tabPane.getTabCount(); i++)
1178: {
1179: tabHeight = calculateTabHeight(tabPlacement, i, fontHeight);
1180: if (runHeight + tabHeight > height)
1181: {
1182: runHeight = tabHeight;
1183: runs++;
1184: }
1185: else
1186: runHeight += tabHeight;
1187: }
1188: runs++;
1189:
1190: int maxTabWidth = calculateMaxTabWidth(tabPlacement);
1191: int tabAreaWidth = calculateTabAreaWidth(tabPlacement, runs,
1192: maxTabWidth);
1193: return tabAreaWidth;
1194: }
1195:
1196:
1204: protected void rotateTabRuns(int tabPlacement, int selectedRun)
1205: {
1206: if (runCount == 1 || selectedRun == 0 || selectedRun == -1)
1207: return;
1208: int[] newTabRuns = new int[tabRuns.length];
1209: int currentRun = selectedRun;
1210: int i = 0;
1211: do
1212: {
1213: newTabRuns[i] = tabRuns[currentRun];
1214: currentRun = getNextTabRun(currentRun);
1215: i++;
1216: }
1217: while (i < runCount);
1218:
1219: tabRuns = newTabRuns;
1220: BasicTabbedPaneUI.this.selectedRun = 1;
1221: }
1222:
1223:
1229: public void removeLayoutComponent(Component comp)
1230: {
1231:
1232: }
1233: }
1234:
1235:
1239: private class TabbedPaneScrollLayout extends TabbedPaneLayout
1240: {
1241:
1248: public Dimension preferredLayoutSize(Container parent)
1249: {
1250: return super.calculateSize(false);
1251: }
1252:
1253:
1260: public Dimension minimumLayoutSize(Container parent)
1261: {
1262: return super.calculateSize(true);
1263: }
1264:
1265:
1273: protected int preferredTabAreaHeight(int tabPlacement, int width)
1274: {
1275: if (tabPane.getTabCount() == 0)
1276: return calculateTabAreaHeight(tabPlacement, 0, 0);
1277:
1278: int runs = 1;
1279:
1280: int maxTabHeight = calculateMaxTabHeight(tabPlacement);
1281: int tabAreaHeight = calculateTabAreaHeight(tabPlacement, runs,
1282: maxTabHeight);
1283: return tabAreaHeight;
1284: }
1285:
1286:
1294: protected int preferredTabAreaWidth(int tabPlacement, int height)
1295: {
1296: if (tabPane.getTabCount() == 0)
1297: return calculateTabAreaHeight(tabPlacement, 0, 0);
1298:
1299: int runs = 1;
1300:
1301: int maxTabWidth = calculateMaxTabWidth(tabPlacement);
1302: int tabAreaWidth = calculateTabAreaWidth(tabPlacement, runs, maxTabWidth);
1303: return tabAreaWidth;
1304: }
1305:
1306:
1315: protected void calculateTabRects(int tabPlacement, int tabCount)
1316: {
1317: if (tabCount == 0)
1318: return;
1319:
1320: FontMetrics fm = getFontMetrics();
1321: SwingUtilities.calculateInnerArea(tabPane, calcRect);
1322: Insets tabAreaInsets = getTabAreaInsets(tabPlacement);
1323: Insets insets = tabPane.getInsets();
1324: if (tabPlacement == SwingConstants.TOP
1325: || tabPlacement == SwingConstants.BOTTOM)
1326: {
1327: int maxHeight = calculateMaxTabHeight(tabPlacement);
1328: calcRect.width -= tabAreaInsets.left + tabAreaInsets.right;
1329: int width = 0;
1330: int runWidth = tabAreaInsets.left + insets.left;
1331: int top = insets.top + tabAreaInsets.top;
1332: for (int i = 0; i < tabCount; i++)
1333: {
1334: width = calculateTabWidth(tabPlacement, i, fm);
1335:
1336:
1337:
1338: rects[i].setBounds(runWidth, top, width, maxHeight);
1339:
1340: runWidth += width;
1341: }
1342: tabAreaRect.width = tabPane.getWidth() - insets.left - insets.right;
1343: tabAreaRect.height = maxTabHeight + tabAreaInsets.top
1344: + tabAreaInsets.bottom;
1345: contentRect.width = tabAreaRect.width;
1346: contentRect.height = tabPane.getHeight() - insets.top
1347: - insets.bottom - tabAreaRect.height;
1348: contentRect.x = insets.left;
1349: tabAreaRect.x = insets.left;
1350: if (tabPlacement == SwingConstants.BOTTOM)
1351: {
1352: contentRect.y = insets.top;
1353: tabAreaRect.y = contentRect.y + contentRect.height;
1354: }
1355: else
1356: {
1357: tabAreaRect.y = insets.top;
1358: contentRect.y = tabAreaRect.y + tabAreaRect.height;
1359: }
1360: }
1361: else
1362: {
1363: int maxWidth = calculateMaxTabWidth(tabPlacement);
1364:
1365: calcRect.height -= tabAreaInsets.top + tabAreaInsets.bottom;
1366: int height = 0;
1367: int runHeight = tabAreaInsets.top + insets.top;
1368: int fontHeight = fm.getHeight();
1369: int left = insets.left + tabAreaInsets.left;
1370: for (int i = 0; i < tabCount; i++)
1371: {
1372: height = calculateTabHeight(tabPlacement, i, fontHeight);
1373:
1374:
1375:
1376: rects[i].setBounds(left, runHeight, maxWidth, height);
1377: runHeight += height;
1378: }
1379: tabAreaRect.width = maxTabWidth + tabAreaInsets.left
1380: + tabAreaInsets.right;
1381: tabAreaRect.height = tabPane.getHeight() - insets.top
1382: - insets.bottom;
1383: tabAreaRect.y = insets.top;
1384: contentRect.width = tabPane.getWidth() - insets.left - insets.right
1385: - tabAreaRect.width;
1386: contentRect.height = tabAreaRect.height;
1387: contentRect.y = insets.top;
1388: if (tabPlacement == SwingConstants.LEFT)
1389: {
1390: tabAreaRect.x = insets.left;
1391: contentRect.x = tabAreaRect.x + tabAreaRect.width;
1392: }
1393: else
1394: {
1395: contentRect.x = insets.left;
1396: tabAreaRect.x = contentRect.x + contentRect.width;
1397: }
1398: }
1399:
1400:
1401:
1402: }
1403:
1404:
1411: public void layoutContainer(Container pane)
1412: {
1413: super.layoutContainer(pane);
1414: int tabCount = tabPane.getTabCount();
1415: if (tabCount == 0)
1416: return;
1417: int tabPlacement = tabPane.getTabPlacement();
1418:
1419: if (tabPlacement == SwingConstants.TOP
1420: || tabPlacement == SwingConstants.BOTTOM)
1421: {
1422: if (tabAreaRect.x + tabAreaRect.width < rects[tabCount - 1].x
1423: + rects[tabCount - 1].width)
1424: {
1425: Dimension incrDims = incrButton.getPreferredSize();
1426: Dimension decrDims = decrButton.getPreferredSize();
1427:
1428: if (tabPlacement == SwingConstants.BOTTOM)
1429: {
1430:
1431:
1432: decrButton.setBounds(tabAreaRect.x + tabAreaRect.width
1433: - incrDims.width - decrDims.width,
1434: tabAreaRect.y, decrDims.width,
1435: decrDims.height);
1436: incrButton.setBounds(tabAreaRect.x + tabAreaRect.width
1437: - incrDims.width, tabAreaRect.y,
1438: incrDims.width, incrDims.height);
1439: }
1440: else
1441: {
1442:
1443:
1444: decrButton.setBounds(tabAreaRect.x + tabAreaRect.width
1445: - incrDims.width - decrDims.width,
1446: tabAreaRect.y + tabAreaRect.height
1447: - decrDims.height, decrDims.width,
1448: decrDims.height);
1449: incrButton.setBounds(tabAreaRect.x + tabAreaRect.width
1450: - incrDims.width,
1451: tabAreaRect.y + tabAreaRect.height
1452: - incrDims.height,
1453: incrDims.width, incrDims.height);
1454: }
1455:
1456: tabAreaRect.width -= decrDims.width + incrDims.width;
1457:
1458: updateButtons();
1459:
1460: incrButton.setVisible(true);
1461: decrButton.setVisible(true);
1462: }
1463: else
1464: {
1465: incrButton.setVisible(false);
1466: decrButton.setVisible(false);
1467:
1468: currentScrollOffset = 0;
1469: currentScrollLocation = 0;
1470: }
1471: }
1472:
1473: if (tabPlacement == SwingConstants.LEFT
1474: || tabPlacement == SwingConstants.RIGHT)
1475: {
1476: if (tabAreaRect.y + tabAreaRect.height < rects[tabCount - 1].y
1477: + rects[tabCount - 1].height)
1478: {
1479: Dimension incrDims = incrButton.getPreferredSize();
1480: Dimension decrDims = decrButton.getPreferredSize();
1481:
1482: if (tabPlacement == SwingConstants.RIGHT)
1483: {
1484:
1485:
1486: decrButton.setBounds(tabAreaRect.x,
1487: tabAreaRect.y + tabAreaRect.height
1488: - incrDims.height - decrDims.height,
1489: decrDims.width, decrDims.height);
1490: incrButton.setBounds(tabAreaRect.x,
1491: tabAreaRect.y + tabAreaRect.height
1492: - incrDims.height, incrDims.width,
1493: incrDims.height);
1494: }
1495: else
1496: {
1497:
1498:
1499: decrButton.setBounds(tabAreaRect.x + tabAreaRect.width
1500: - decrDims.width,
1501: tabAreaRect.y + tabAreaRect.height
1502: - incrDims.height - decrDims.height,
1503: decrDims.width, decrDims.height);
1504: incrButton.setBounds(tabAreaRect.x + tabAreaRect.width
1505: - incrDims.width,
1506: tabAreaRect.y + tabAreaRect.height
1507: - incrDims.height, incrDims.width,
1508: incrDims.height);
1509: }
1510:
1511: tabAreaRect.height -= decrDims.height + incrDims.height;
1512:
1513: incrButton.setVisible(true);
1514: decrButton.setVisible(true);
1515: }
1516: else
1517: {
1518: incrButton.setVisible(false);
1519: decrButton.setVisible(false);
1520:
1521: currentScrollOffset = 0;
1522: currentScrollLocation = 0;
1523: }
1524: }
1525: viewport.setBounds(tabAreaRect.x, tabAreaRect.y, tabAreaRect.width,
1526: tabAreaRect.height);
1527:
1528: updateViewPosition();
1529:
1530: viewport.repaint();
1531: }
1532: }
1533:
1534:
1541: public class TabSelectionHandler implements ChangeListener
1542: {
1543:
1549: public void stateChanged(ChangeEvent e)
1550: {
1551: selectedRun = getRunForTab(tabPane.getTabCount(),
1552: tabPane.getSelectedIndex());
1553:
1554: if (tabPane.getTabLayoutPolicy() == JTabbedPane.WRAP_TAB_LAYOUT)
1555: tabPane.revalidate();
1556: tabPane.repaint();
1557: }
1558: }
1559:
1560:
1565: private class ScrollingPanel extends JPanel
1566: {
1567:
1570: private class ScrollingPanelUI extends BasicPanelUI
1571: {
1572:
1579: public void paint(Graphics g, JComponent c)
1580: {
1581: int placement = tabPane.getTabPlacement();
1582: g.setColor(highlight);
1583: if (placement == SwingUtilities.TOP
1584: || placement == SwingUtilities.BOTTOM)
1585: g.fillRect(currentScrollOffset, 0,
1586: tabAreaRect.width, tabAreaRect.height);
1587: else
1588: g.fillRect(0, currentScrollOffset,
1589: tabAreaRect.width, tabAreaRect.height);
1590:
1591: paintTabArea(g, placement, tabPane.getSelectedIndex());
1592: }
1593: }
1594:
1595:
1599: public void updateUI()
1600: {
1601: setUI(new ScrollingPanelUI());
1602: }
1603: }
1604:
1605:
1611: private class ScrollingViewport extends JViewport implements UIResource
1612: {
1613:
1614: }
1615:
1616:
1620: private class ScrollingButton extends BasicArrowButton implements UIResource
1621: {
1622:
1627: public ScrollingButton(int dir)
1628: {
1629: super(dir);
1630: }
1631: }
1632:
1633:
1635: transient ScrollingButton incrButton;
1636:
1637:
1639: transient ScrollingButton decrButton;
1640:
1641:
1643: transient ScrollingViewport viewport;
1644:
1645:
1647: transient ScrollingPanel panel;
1648:
1649:
1651: transient int currentScrollLocation;
1652:
1653: transient int currentScrollOffset;
1654:
1655:
1656: protected Rectangle calcRect;
1657:
1658:
1659: protected Rectangle[] rects;
1660:
1661:
1662: protected Insets contentBorderInsets;
1663:
1664:
1665: protected Insets selectedTabPadInsets;
1666:
1667:
1668: protected Insets tabAreaInsets;
1669:
1670:
1671: protected Insets tabInsets;
1672:
1673:
1677: protected Color darkShadow;
1678:
1679:
1680: protected Color focus;
1681:
1682:
1683: protected Color highlight;
1684:
1685:
1686: protected Color lightHighlight;
1687:
1688:
1689: protected Color shadow;
1690:
1691:
1692: protected int maxTabHeight;
1693:
1694:
1695: protected int maxTabWidth;
1696:
1697:
1698: protected int runCount;
1699:
1700:
1701: protected int selectedRun;
1702:
1703:
1704: protected int tabRunOverlay;
1705:
1706:
1707: protected int textIconGap;
1708:
1709:
1714: protected int[] tabRuns;
1715:
1716:
1720: boolean tabRunsDirty;
1721:
1722:
1727: protected KeyStroke downKey;
1728:
1729:
1734: protected KeyStroke leftKey;
1735:
1736:
1741: protected KeyStroke rightKey;
1742:
1743:
1748: protected KeyStroke upKey;
1749:
1750:
1751: protected FocusListener focusListener;
1752:
1753:
1754: protected MouseListener mouseListener;
1755:
1756:
1757: protected PropertyChangeListener propertyChangeListener;
1758:
1759:
1760: protected ChangeListener tabChangeListener;
1761:
1762:
1763: protected JTabbedPane tabPane;
1764:
1765:
1767: transient LayoutManager layoutManager;
1768:
1769:
1771: transient Rectangle tabAreaRect;
1772:
1773:
1775: transient Rectangle contentRect;
1776:
1777:
1780: private int rolloverTab;
1781:
1782:
1786: private boolean tabsOpaque;
1787:
1788:
1791: private Component visibleComponent;
1792:
1793: private Color selectedColor;
1794:
1795: private Rectangle tempTextRect = new Rectangle();
1796:
1797: private Rectangle tempIconRect = new Rectangle();
1798:
1799:
1802: public BasicTabbedPaneUI()
1803: {
1804: super();
1805: rects = new Rectangle[0];
1806: tabRuns = new int[10];
1807: }
1808:
1809:
1816: ScrollingButton createIncreaseButton()
1817: {
1818: if (incrButton == null)
1819: incrButton = new ScrollingButton(SwingConstants.NORTH);
1820: if (tabPane.getTabPlacement() == SwingConstants.TOP
1821: || tabPane.getTabPlacement() == SwingConstants.BOTTOM)
1822: incrButton.setDirection(SwingConstants.EAST);
1823: else
1824: incrButton.setDirection(SwingConstants.SOUTH);
1825: return incrButton;
1826: }
1827:
1828:
1835: ScrollingButton createDecreaseButton()
1836: {
1837: if (decrButton == null)
1838: decrButton = new ScrollingButton(SwingConstants.SOUTH);
1839: if (tabPane.getTabPlacement() == SwingConstants.TOP
1840: || tabPane.getTabPlacement() == SwingConstants.BOTTOM)
1841: decrButton.setDirection(SwingConstants.WEST);
1842: else
1843: decrButton.setDirection(SwingConstants.NORTH);
1844: return decrButton;
1845: }
1846:
1847:
1856: Point findPointForIndex(int index)
1857: {
1858: int tabPlacement = tabPane.getTabPlacement();
1859: int selectedIndex = tabPane.getSelectedIndex();
1860: Insets insets = getSelectedTabPadInsets(tabPlacement);
1861: int w = 0;
1862: int h = 0;
1863:
1864: if (tabPlacement == TOP || tabPlacement == BOTTOM)
1865: {
1866: if (index > 0)
1867: {
1868: w += rects[index - 1].x + rects[index - 1].width;
1869: if (index > selectedIndex)
1870: w -= insets.left + insets.right;
1871: }
1872: }
1873:
1874: else
1875: {
1876: if (index > 0)
1877: {
1878: h += rects[index - 1].y + rects[index - 1].height;
1879: if (index > selectedIndex)
1880: h -= insets.top + insets.bottom;
1881: }
1882: }
1883:
1884: Point p = new Point(w, h);
1885: return p;
1886: }
1887:
1888:
1894: final void scrollTab(int index, int placement)
1895: {
1896: int diff;
1897: if (index >= 0 && tabPane.isEnabledAt(index))
1898: {
1899:
1900:
1901:
1902: switch (placement)
1903: {
1904: case JTabbedPane.TOP:
1905: case JTabbedPane.BOTTOM:
1906: if ((diff = rects[index].x
1907: + rects[index].width
1908: - decrButton.getX() - currentScrollOffset) > 0)
1909: currentScrollOffset += diff;
1910: else if ((diff = rects[index].x - currentScrollOffset) < 0)
1911: {
1912: if (index == 0)
1913: currentScrollOffset = 0;
1914: else
1915: currentScrollOffset += diff;
1916: }
1917:
1918: currentScrollLocation = tabForCoordinate(tabPane,
1919: currentScrollOffset,
1920: rects[index].y);
1921: break;
1922: default:
1923: if ((diff = rects[index].y + rects[index].height
1924: - decrButton.getY() - currentScrollOffset) > 0)
1925: currentScrollOffset += diff;
1926: else if ((diff = rects[index].y - currentScrollOffset) < 0)
1927: {
1928: if (index == 0)
1929: currentScrollOffset = 0;
1930: else
1931: currentScrollOffset += diff;
1932: }
1933:
1934: currentScrollLocation = tabForCoordinate(tabPane,
1935: rects[index].x,
1936: currentScrollOffset);
1937: }
1938:
1939: updateViewPosition();
1940: updateButtons();
1941: }
1942: }
1943:
1944:
1948: final void updateButtons()
1949: {
1950: int tc = tabPane.getTabCount();
1951:
1952:
1953:
1954:
1955: switch (tabPane.getTabPlacement())
1956: {
1957: case JTabbedPane.BOTTOM:
1958: case JTabbedPane.TOP:
1959: incrButton.setEnabled(currentScrollLocation + 1 < tc
1960: && rects[tc-1].x + rects[tc-1].width
1961: - currentScrollOffset > decrButton.getX());
1962: break;
1963: default:
1964: incrButton.setEnabled(currentScrollLocation + 1 < tc
1965: && rects[tc-1].y + rects[tc-1].height
1966: - currentScrollOffset > decrButton.getY());
1967: }
1968:
1969:
1970: decrButton.setEnabled(currentScrollOffset > 0);
1971:
1972: }
1973:
1974:
1978: final void updateViewPosition()
1979: {
1980: Point p = viewport.getViewPosition();
1981:
1982:
1983:
1984: switch (tabPane.getTabPlacement())
1985: {
1986: case JTabbedPane.LEFT:
1987: case JTabbedPane.RIGHT:
1988: p.x = 0;
1989: p.y = currentScrollOffset;
1990: break;
1991: default:
1992: p.x = currentScrollOffset;
1993: p.y = 0;
1994: }
1995:
1996: viewport.setViewPosition(p);
1997: }
1998:
1999:
2006: public static ComponentUI createUI(JComponent c)
2007: {
2008: return new BasicTabbedPaneUI();
2009: }
2010:
2011:
2016: public void installUI(JComponent c)
2017: {
2018: super.installUI(c);
2019: if (c instanceof JTabbedPane)
2020: {
2021: tabPane = (JTabbedPane) c;
2022:
2023: installComponents();
2024: installDefaults();
2025: installListeners();
2026: installKeyboardActions();
2027:
2028: layoutManager = createLayoutManager();
2029: tabPane.setLayout(layoutManager);
2030: }
2031: }
2032:
2033:
2038: public void uninstallUI(JComponent c)
2039: {
2040: layoutManager = null;
2041:
2042: uninstallKeyboardActions();
2043: uninstallListeners();
2044: uninstallDefaults();
2045: uninstallComponents();
2046:
2047: tabPane = null;
2048: }
2049:
2050:
2058: protected LayoutManager createLayoutManager()
2059: {
2060: if (tabPane.getTabLayoutPolicy() == JTabbedPane.WRAP_TAB_LAYOUT)
2061: return new TabbedPaneLayout();
2062: else
2063: {
2064: runCount = 1;
2065: tabRuns[0] = 0;
2066:
2067: incrButton = createIncreaseButton();
2068: incrButton.addMouseListener(mouseListener);
2069:
2070: decrButton = createDecreaseButton();
2071: decrButton.addMouseListener(mouseListener);
2072: decrButton.setEnabled(false);
2073:
2074: panel = new ScrollingPanel();
2075: panel.setSize(Integer.MAX_VALUE, Integer.MAX_VALUE);
2076: panel.addMouseListener(mouseListener);
2077: panel.addFocusListener(focusListener);
2078:
2079: viewport = new ScrollingViewport();
2080: viewport.setBackground(Color.LIGHT_GRAY);
2081: viewport.setView(panel);
2082: viewport.setLayout(null);
2083:
2084: tabPane.add(incrButton);
2085: tabPane.add(decrButton);
2086: tabPane.add(viewport);
2087:
2088: return new TabbedPaneScrollLayout();
2089: }
2090: }
2091:
2092:
2095: protected void installComponents()
2096: {
2097:
2098: }
2099:
2100:
2103: protected void uninstallComponents()
2104: {
2105: if (incrButton != null)
2106: tabPane.remove(incrButton);
2107:
2108: if (decrButton != null)
2109: tabPane.remove(decrButton);
2110:
2111: if (viewport != null)
2112: tabPane.remove(viewport);
2113: }
2114:
2115:
2118: protected void installDefaults()
2119: {
2120: LookAndFeel.installColorsAndFont(tabPane, "TabbedPane.background",
2121: "TabbedPane.foreground",
2122: "TabbedPane.font");
2123: tabPane.setOpaque(false);
2124:
2125: lightHighlight = UIManager.getColor("TabbedPane.highlight");
2126: highlight = UIManager.getColor("TabbedPane.light");
2127:
2128: shadow = UIManager.getColor("TabbedPane.shadow");
2129: darkShadow = UIManager.getColor("TabbedPane.darkShadow");
2130:
2131: focus = UIManager.getColor("TabbedPane.focus");
2132:
2133: textIconGap = UIManager.getInt("TabbedPane.textIconGap");
2134: tabRunOverlay = UIManager.getInt("TabbedPane.tabRunOverlay");
2135:
2136: tabInsets = UIManager.getInsets("TabbedPane.tabInsets");
2137: selectedTabPadInsets
2138: = UIManager.getInsets("TabbedPane.selectedTabPadInsets");
2139: tabAreaInsets = UIManager.getInsets("TabbedPane.tabAreaInsets");
2140: contentBorderInsets
2141: = UIManager.getInsets("TabbedPane.contentBorderInsets");
2142: tabsOpaque = UIManager.getBoolean("TabbedPane.tabsOpaque");
2143:
2144:
2145:
2146: selectedColor = UIManager.getColor("TabbedPane.contentAreaColor");
2147: if (selectedColor == null)
2148: selectedColor = UIManager.getColor("control");
2149:
2150: calcRect = new Rectangle();
2151: tabRuns = new int[10];
2152: tabAreaRect = new Rectangle();
2153: contentRect = new Rectangle();
2154: }
2155:
2156:
2159: protected void uninstallDefaults()
2160: {
2161: calcRect = null;
2162: tabAreaRect = null;
2163: contentRect = null;
2164: tabRuns = null;
2165:
2166: tempIconRect = null;
2167: tempTextRect = null;
2168:
2169: contentBorderInsets = null;
2170: tabAreaInsets = null;
2171: selectedTabPadInsets = null;
2172: tabInsets = null;
2173:
2174: focus = null;
2175: darkShadow = null;
2176: shadow = null;
2177: lightHighlight = null;
2178: highlight = null;
2179:
2180: selectedColor = null;
2181: }
2182:
2183:
2186: protected void installListeners()
2187: {
2188: mouseListener = createMouseListener();
2189: tabChangeListener = createChangeListener();
2190: propertyChangeListener = createPropertyChangeListener();
2191: focusListener = createFocusListener();
2192:
2193: tabPane.addMouseListener(mouseListener);
2194: tabPane.addChangeListener(tabChangeListener);
2195: tabPane.addPropertyChangeListener(propertyChangeListener);
2196: tabPane.addFocusListener(focusListener);
2197: }
2198:
2199:
2202: protected void uninstallListeners()
2203: {
2204: tabPane.removeFocusListener(focusListener);
2205: tabPane.removePropertyChangeListener(propertyChangeListener);
2206: tabPane.removeChangeListener(tabChangeListener);
2207: tabPane.removeMouseListener(mouseListener);
2208:
2209: if (incrButton != null)
2210: incrButton.removeMouseListener(mouseListener);
2211:
2212: if (decrButton != null)
2213: decrButton.removeMouseListener(mouseListener);
2214:
2215: if (panel != null)
2216: {
2217: panel.removeMouseListener(mouseListener);
2218: panel.removeFocusListener(focusListener);
2219: }
2220:
2221: focusListener = null;
2222: propertyChangeListener = null;
2223: tabChangeListener = null;
2224: mouseListener = null;
2225: }
2226:
2227:
2232: protected MouseListener createMouseListener()
2233: {
2234: return new MouseHandler();
2235: }
2236:
2237:
2242: protected FocusListener createFocusListener()
2243: {
2244: return new FocusHandler();
2245: }
2246:
2247:
2252: protected ChangeListener createChangeListener()
2253: {
2254: return new TabSelectionHandler();
2255: }
2256:
2257:
2262: protected PropertyChangeListener createPropertyChangeListener()
2263: {
2264: return new PropertyChangeHandler();
2265: }
2266:
2267:
2270: protected void installKeyboardActions()
2271: {
2272: InputMap keyMap = (InputMap) UIManager.get("TabbedPane.focusInputMap");
2273: SwingUtilities.replaceUIInputMap(tabPane, JComponent.WHEN_FOCUSED, keyMap);
2274:
2275: keyMap = (InputMap) UIManager.get("TabbedPane.ancestorInputMap");
2276: SwingUtilities
2277: .replaceUIInputMap(tabPane,
2278: JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT,
2279: keyMap);
2280:
2281: ActionMap map = getActionMap();
2282: SwingUtilities.replaceUIActionMap(tabPane, map);
2283: }
2284:
2285:
2288: protected void uninstallKeyboardActions()
2289: {
2290: SwingUtilities.replaceUIActionMap(tabPane, null);
2291: SwingUtilities.replaceUIInputMap(tabPane, JComponent.WHEN_FOCUSED, null);
2292: SwingUtilities
2293: .replaceUIInputMap(tabPane,
2294: JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT,
2295: null);
2296: }
2297:
2298:
2305: public Dimension getMinimumSize(JComponent c)
2306: {
2307: return layoutManager.minimumLayoutSize(tabPane);
2308: }
2309:
2310:
2317: public Dimension getMaximumSize(JComponent c)
2318: {
2319: return new Dimension(Short.MAX_VALUE, Short.MAX_VALUE);
2320: }
2321:
2322:
2328: public void paint(Graphics g, JComponent c)
2329: {
2330: if (!tabPane.isValid())
2331: tabPane.validate();
2332:
2333: if (tabPane.getTabCount() == 0)
2334: return;
2335:
2336: int index = tabPane.getSelectedIndex();
2337: if (index < 0)
2338: index = 0;
2339:
2340: int tabPlacement = tabPane.getTabPlacement();
2341:
2342:
2343:
2344:
2345: if (tabPane.getTabLayoutPolicy() == JTabbedPane.WRAP_TAB_LAYOUT)
2346: {
2347: g.setColor(highlight);
2348: g.fillRect(tabAreaRect.x, tabAreaRect.y,
2349: tabAreaRect.width, tabAreaRect.height);
2350: paintTabArea(g, tabPlacement, index);
2351: }
2352:
2353: paintContentBorder(g, tabPlacement, index);
2354: }
2355:
2356:
2364: protected void paintTabArea(Graphics g, int tabPlacement, int selectedIndex)
2365: {
2366:
2367:
2368:
2369:
2370: int tabCount = tabPane.getTabCount();
2371:
2372: for (int i = runCount - 1; i >= 0; --i)
2373: {
2374: int start = tabRuns[i];
2375: int next;
2376: if (i == runCount - 1)
2377: next = tabRuns[0];
2378: else
2379: next = tabRuns[i + 1];
2380: int end = next != 0 ? next - 1 : tabCount - 1;
2381: for (int j = start; j <= end; ++j)
2382: {
2383: if (j != selectedIndex)
2384: {
2385: paintTab(g, tabPlacement, rects, j,
2386: tempIconRect, tempTextRect);
2387: }
2388: }
2389: }
2390:
2391:
2392: if (selectedIndex >= 0)
2393: paintTab(g, tabPlacement, rects, selectedIndex,
2394: tempIconRect, tempTextRect);
2395: }
2396:
2397:
2408: protected void paintTab(Graphics g, int tabPlacement, Rectangle[] rects,
2409: int tabIndex, Rectangle iconRect, Rectangle textRect)
2410: {
2411: Rectangle rect = rects[tabIndex];
2412: boolean isSelected = tabIndex == tabPane.getSelectedIndex();
2413:
2414: if (tabsOpaque || tabPane.isOpaque())
2415: {
2416: paintTabBackground(g, tabPlacement, tabIndex, rect.x, rect.y,
2417: rect.width, rect.height, isSelected);
2418: }
2419:
2420:
2421: paintTabBorder(g, tabPlacement, tabIndex, rect.x, rect.y, rect.width,
2422: rect.height, isSelected);
2423:
2424:
2425: FontMetrics fm = getFontMetrics();
2426: Icon icon = getIconForTab(tabIndex);
2427: String title = tabPane.getTitleAt(tabIndex);
2428: layoutLabel(tabPlacement, fm, tabIndex, title, icon, rect, iconRect,
2429: textRect, isSelected);
2430:
2431: paintText(g, tabPlacement, tabPane.getFont(), fm, tabIndex, title,
2432: textRect, isSelected);
2433:
2434:
2435: paintIcon(g, tabPlacement, tabIndex, icon, iconRect, isSelected);
2436:
2437:
2438: paintFocusIndicator(g, tabPlacement, rects, tabIndex, iconRect, textRect,
2439: isSelected);
2440: }
2441:
2442:
2456: protected void layoutLabel(int tabPlacement, FontMetrics metrics,
2457: int tabIndex, String title, Icon icon,
2458: Rectangle tabRect, Rectangle iconRect,
2459: Rectangle textRect, boolean isSelected)
2460: {
2461:
2462:
2463: textRect.x = 0;
2464: textRect.y = 0;
2465: textRect.width = 0;
2466: textRect.height = 0;
2467: iconRect.x = 0;
2468: iconRect.y = 0;
2469: iconRect.width = 0;
2470: iconRect.height = 0;
2471: SwingUtilities.layoutCompoundLabel(tabPane, metrics, title, icon,
2472: SwingConstants.CENTER,
2473: SwingConstants.CENTER,
2474: SwingConstants.CENTER,
2475: SwingConstants.RIGHT, tabRect,
2476: iconRect, textRect, textIconGap);
2477:
2478: int shiftX = getTabLabelShiftX(tabPlacement, tabIndex, isSelected);
2479: int shiftY = getTabLabelShiftY(tabPlacement, tabIndex, isSelected);
2480:
2481: iconRect.x += shiftX;
2482: iconRect.y += shiftY;
2483:
2484: textRect.x += shiftX;
2485: textRect.y += shiftY;
2486: }
2487:
2488:
2498: protected void paintIcon(Graphics g, int tabPlacement, int tabIndex,
2499: Icon icon, Rectangle iconRect, boolean isSelected)
2500: {
2501: if (icon != null)
2502: icon.paintIcon(tabPane, g, iconRect.x, iconRect.y);
2503: }
2504:
2505:
2517: protected void paintText(Graphics g, int tabPlacement, Font font,
2518: FontMetrics metrics, int tabIndex, String title,
2519: Rectangle textRect, boolean isSelected)
2520: {
2521: g.setFont(font);
2522: View textView = getTextViewForTab(tabIndex);
2523: if (textView != null)
2524: {
2525: textView.paint(g, textRect);
2526: return;
2527: }
2528:
2529: int ascent = metrics.getAscent();
2530:
2531: int mnemIndex = tabPane.getDisplayedMnemonicIndexAt(tabIndex);
2532: if (tabPane.isEnabled() && tabPane.isEnabledAt(tabIndex))
2533: {
2534: Color fg = tabPane.getForegroundAt(tabIndex);
2535: if (isSelected && (fg instanceof UIResource))
2536: {
2537: Color selectionForeground =
2538: UIManager.getColor("TabbedPane.selectionForeground");
2539: if (selectionForeground != null)
2540: fg = selectionForeground;
2541: }
2542: g.setColor(fg);
2543:
2544: if (mnemIndex != -1)
2545: BasicGraphicsUtils.drawStringUnderlineCharAt(g, title, mnemIndex,
2546: textRect.x,
2547: textRect.y + ascent);
2548: else
2549: g.drawString(title, textRect.x, textRect.y + ascent);
2550: }
2551: else
2552: {
2553: Color bg = tabPane.getBackgroundAt(tabIndex);
2554: g.setColor(bg.brighter());
2555: if (mnemIndex != -1)
2556: BasicGraphicsUtils.drawStringUnderlineCharAt(g, title, mnemIndex,
2557: textRect.x, textRect.y
2558: + ascent);
2559: else
2560: g.drawString(title, textRect.x, textRect.y + ascent);
2561:
2562: g.setColor(bg.darker());
2563: if (mnemIndex != -1)
2564: BasicGraphicsUtils.drawStringUnderlineCharAt(g, title, mnemIndex,
2565: textRect.x + 1,
2566: textRect.y + 1
2567: + ascent);
2568: else
2569: g.drawString(title, textRect.x + 1, textRect.y + 1 + ascent);
2570: }
2571: }
2572:
2573:
2583: protected int getTabLabelShiftX(int tabPlacement, int tabIndex,
2584: boolean isSelected)
2585: {
2586: switch (tabPlacement)
2587: {
2588: default:
2589: case SwingUtilities.TOP:
2590: case SwingUtilities.BOTTOM:
2591: return 1;
2592: case SwingUtilities.LEFT:
2593: return (isSelected) ? -1 : 1;
2594: case SwingUtilities.RIGHT:
2595: return (isSelected) ? 1 : -1;
2596: }
2597: }
2598:
2599:
2609: protected int getTabLabelShiftY(int tabPlacement, int tabIndex,
2610: boolean isSelected)
2611: {
2612: switch (tabPlacement)
2613: {
2614: default:
2615: case SwingUtilities.TOP:
2616: return (isSelected) ? -1 : 1;
2617: case SwingUtilities.BOTTOM:
2618: return (isSelected) ? 1 : -1;
2619: case SwingUtilities.LEFT:
2620: case SwingUtilities.RIGHT:
2621: return 0;
2622: }
2623: }
2624:
2625:
2636: protected void paintFocusIndicator(Graphics g, int tabPlacement,
2637: Rectangle[] rects, int tabIndex,
2638: Rectangle iconRect, Rectangle textRect,
2639: boolean isSelected)
2640: {
2641: if (tabPane.hasFocus() && isSelected)
2642: {
2643: Rectangle rect = rects[tabIndex];
2644:
2645: int x;
2646: int y;
2647: int w;
2648: int h;
2649:
2650: g.setColor(focus);
2651: switch (tabPlacement)
2652: {
2653: case LEFT:
2654: x = rect.x + 3;
2655: y = rect.y + 3;
2656: w = rect.width - 5;
2657: h = rect.height - 6;
2658: break;
2659: case RIGHT:
2660: x = rect.x + 2;
2661: y = rect.y + 3;
2662: w = rect.width - 6;
2663: h = rect.height - 5;
2664: break;
2665: case BOTTOM:
2666: x = rect.x + 3;
2667: y = rect.y + 2;
2668: w = rect.width - 6;
2669: h = rect.height - 5;
2670: break;
2671: case TOP:
2672: default:
2673: x = rect.x + 3;
2674: y = rect.y + 3;
2675: w = rect.width - 6;
2676: h = rect.height - 5;
2677: }
2678:
2679: BasicGraphicsUtils.drawDashedRect(g, x, y, w, h);
2680: }
2681: }
2682:
2683:
2695: protected void paintTabBorder(Graphics g, int tabPlacement, int tabIndex,
2696: int x, int y, int w, int h, boolean isSelected)
2697: {
2698: Color saved = g.getColor();
2699:
2700: switch (tabPlacement)
2701: {
2702: case SwingConstants.TOP:
2703: g.setColor(shadow);
2704:
2705: g.drawLine(x + w - 2, y + 2, x + w - 2, y + h);
2706:
2707: g.setColor(darkShadow);
2708:
2709: g.drawLine(x + w - 1, y + 2, x + w - 1, y + h);
2710:
2711:
2712: g.drawLine(x + w - 2, y + 1, x + w - 1, y + 2);
2713:
2714: g.setColor(lightHighlight);
2715:
2716:
2717: g.drawLine(x, y + 3, x, y + h);
2718:
2719:
2720: g.drawLine(x + 3, y, x + w - 3, y);
2721:
2722:
2723: g.drawLine(x, y + 2, x + 2, y);
2724:
2725: break;
2726: case SwingConstants.LEFT:
2727: g.setColor(lightHighlight);
2728:
2729: g.drawLine(x + 3, y, x + w - 1, y);
2730:
2731:
2732: g.drawLine(x + 2, y, x, y + 2);
2733:
2734:
2735: g.drawLine(x, y + 3, x, y + h - 4);
2736:
2737:
2738: g.drawLine(x, y + h - 3, x + 1, y + h - 2);
2739:
2740: g.setColor(darkShadow);
2741:
2742: g.drawLine(x + 2, y + h - 1, x + w - 1, y + h - 1);
2743:
2744: g.setColor(shadow);
2745:
2746: g.drawLine(x + 2, y + h - 2, x + w - 1, y + h - 2);
2747:
2748: break;
2749: case SwingConstants.BOTTOM:
2750: g.setColor(shadow);
2751:
2752: g.drawLine(x + w - 2, y, x + w - 2, y + h - 2);
2753:
2754:
2755: g.drawLine(x + 2, y + h - 1, x + w - 3, y + h - 1);
2756:
2757: g.setColor(darkShadow);
2758:
2759: g.drawLine(x + w - 1, y, x + w - 1, y + h - 3);
2760:
2761:
2762: g.drawLine(x + w - 1, y + h - 2, x + w - 3, y + h);
2763:
2764:
2765: g.drawLine(x + 2, y + h, x + w - 4, y + h);
2766:
2767: g.setColor(lightHighlight);
2768:
2769: g.drawLine(x, y, x, y + h - 3);
2770:
2771:
2772: g.drawLine(x, y + h - 2, x + 1, y + h - 1);
2773: break;
2774: case SwingConstants.RIGHT:
2775: g.setColor(lightHighlight);
2776:
2777: g.drawLine(x, y, x + w - 3, y);
2778:
2779: g.setColor(darkShadow);
2780:
2781: g.drawLine(x + w - 2, y + 1, x + w - 1, y + 2);
2782:
2783:
2784: g.drawLine(x + w - 1, y + 3, x + w - 1, y + h - 3);
2785:
2786:
2787: g.drawLine(x + w - 2, y + h - 2, x + w - 3, y + h - 1);
2788:
2789:
2790: g.drawLine(x, y + h - 1, x + w - 4, y + h - 1);
2791:
2792: g.setColor(shadow);
2793:
2794:
2795: g.drawLine(x + w - 2, y + 2, x + w - 2, y + h - 3);
2796:
2797:
2798: g.drawLine(x, y + h - 2, x + w - 3, y + h - 2);
2799:
2800: break;
2801: }
2802:
2803: g.setColor(saved);
2804: }
2805:
2806:
2818: protected void paintTabBackground(Graphics g, int tabPlacement,
2819: int tabIndex, int x, int y, int w, int h,
2820: boolean isSelected)
2821: {
2822: Color saved = g.getColor();
2823:
2824: if (isSelected)
2825: g.setColor(selectedColor);
2826: else
2827: {
2828: Color bg = tabPane.getBackgroundAt(tabIndex);
2829: if (bg == null)
2830: bg = Color.LIGHT_GRAY;
2831: g.setColor(bg);
2832: }
2833:
2834: switch (tabPlacement)
2835: {
2836: case SwingConstants.TOP:
2837: g.fillRect(x + 1, y + 1, w - 1, h - 1);
2838: break;
2839: case SwingConstants.BOTTOM:
2840: g.fillRect(x, y, w - 1, h - 1);
2841: break;
2842: case SwingConstants.LEFT:
2843: g.fillRect(x + 1, y + 1, w - 1, h - 2);
2844: break;
2845: case SwingConstants.RIGHT:
2846: g.fillRect(x, y + 1, w - 1, h - 2);
2847: break;
2848: }
2849:
2850: g.setColor(saved);
2851: }
2852:
2853:
2860: protected void paintContentBorder(Graphics g, int tabPlacement,
2861: int selectedIndex)
2862: {
2863: int width = tabPane.getWidth();
2864: int height = tabPane.getHeight();
2865: Insets insets = tabPane.getInsets();
2866:
2867:
2868: int x = insets.left;
2869: int y = insets.top;
2870: int w = width - insets.left - insets.right;
2871: int h = height - insets.top - insets.bottom;
2872:
2873: switch (tabPlacement)
2874: {
2875: case LEFT:
2876: x += calculateTabAreaWidth(tabPlacement, runCount, maxTabWidth);
2877: w -= x - insets.left;
2878: break;
2879: case RIGHT:
2880: w -= calculateTabAreaWidth(tabPlacement, runCount, maxTabWidth);
2881: break;
2882: case BOTTOM:
2883: h -= calculateTabAreaHeight(tabPlacement, runCount, maxTabHeight);
2884: break;
2885: case TOP:
2886: default:
2887: y += calculateTabAreaHeight(tabPlacement, runCount, maxTabHeight);
2888: h -= y - insets.top;
2889: }
2890:
2891:
2892: if (tabPane.isOpaque())
2893: {
2894: Color bg = UIManager.getColor("TabbedPane.contentAreaColor");
2895: g.setColor(bg);
2896: g.fillRect(x, y, w, h);
2897: }
2898:
2899:
2900: paintContentBorderTopEdge(g, tabPlacement, selectedIndex, x, y, w, h);
2901: paintContentBorderLeftEdge(g, tabPlacement, selectedIndex, x, y, w, h);
2902: paintContentBorderBottomEdge(g, tabPlacement, selectedIndex, x, y, w, h);
2903: paintContentBorderRightEdge(g, tabPlacement, selectedIndex, x, y, w, h);
2904: }
2905:
2906:
2917: protected void paintContentBorderTopEdge(Graphics g, int tabPlacement,
2918: int selectedIndex, int x, int y,
2919: int w, int h)
2920: {
2921: Color saved = g.getColor();
2922: g.setColor(lightHighlight);
2923:
2924: int startgap = rects[selectedIndex].x - currentScrollOffset;
2925: int endgap = rects[selectedIndex].x + rects[selectedIndex].width
2926: - currentScrollOffset;
2927:
2928:
2929:
2930: if (tabPlacement == SwingConstants.TOP && startgap >= 0)
2931: {
2932: g.drawLine(x, y, startgap, y);
2933: g.drawLine(endgap, y, x + w - 1, y);
2934:
2935: g.setColor(selectedColor);
2936: g.drawLine(startgap, y, endgap - 1, y);
2937: }
2938: else
2939: g.drawLine(x, y, x + w, y);
2940:
2941: g.setColor(selectedColor);
2942: g.drawLine(x, y + 1, x + w - 1, y + 1);
2943: g.drawLine(x, y + 2, x + w - 1, y + 2);
2944:
2945: g.setColor(saved);
2946: }
2947:
2948:
2959: protected void paintContentBorderLeftEdge(Graphics g, int tabPlacement,
2960: int selectedIndex, int x, int y,
2961: int w, int h)
2962: {
2963: Color saved = g.getColor();
2964: g.setColor(lightHighlight);
2965:
2966: int startgap = rects[selectedIndex].y - currentScrollOffset;
2967: int endgap = rects[selectedIndex].y + rects[selectedIndex].height
2968: - currentScrollOffset;
2969:
2970: if (tabPlacement == SwingConstants.LEFT && startgap >= 0)
2971: {
2972: g.drawLine(x, y, x, startgap);
2973: g.drawLine(x, endgap, x, y + h - 1);
2974:
2975: g.setColor(selectedColor);
2976: g.drawLine(x, startgap, x, endgap - 1);
2977: }
2978: else
2979: g.drawLine(x, y, x, y + h - 1);
2980:
2981: g.setColor(selectedColor);
2982: g.drawLine(x + 1, y + 1, x + 1, y + h - 4);
2983:
2984: g.setColor(saved);
2985: }
2986:
2987:
2998: protected void paintContentBorderBottomEdge(Graphics g, int tabPlacement,
2999: int selectedIndex, int x, int y,
3000: int w, int h)
3001: {
3002: Color saved = g.getColor();
3003:
3004: int startgap = rects[selectedIndex].x - currentScrollOffset;
3005: int endgap = rects[selectedIndex].x + rects[selectedIndex].width
3006: - currentScrollOffset;
3007:
3008: if (tabPlacement == SwingConstants.BOTTOM && startgap >= 0)
3009: {
3010: g.setColor(shadow);
3011: g.drawLine(x + 1, y + h - 2, startgap, y + h - 2);
3012: g.drawLine(endgap, y + h - 2, x + w - 2, y + h - 2);
3013:
3014: g.setColor(darkShadow);
3015: g.drawLine(x, y + h - 1, startgap , y + h - 1);
3016: g.drawLine(endgap, y + h - 1, x + w - 1, y + h - 1);
3017:
3018: g.setColor(selectedColor);
3019: g.drawLine(startgap, y + h - 1, endgap - 1, y + h - 1);
3020: g.drawLine(startgap, y + h - 2, endgap - 1, y + h - 2);
3021: }
3022: else
3023: {
3024: g.setColor(shadow);
3025: g.drawLine(x + 1, y + h - 2, x + w - 1, y + h - 2);
3026: g.setColor(darkShadow);
3027: g.drawLine(x, y + h - 1, x + w - 1, y + h - 1);
3028: }
3029:
3030: g.setColor(selectedColor);
3031: g.drawLine(x + 1, y + h - 3, x + w - 2, y + h - 3);
3032:
3033: g.setColor(saved);
3034: }
3035:
3036:
3047: protected void paintContentBorderRightEdge(Graphics g, int tabPlacement,
3048: int selectedIndex, int x, int y,
3049: int w, int h)
3050: {
3051: Color saved = g.getColor();
3052: int startgap = rects[selectedIndex].y - currentScrollOffset;
3053: int endgap = rects[selectedIndex].y + rects[selectedIndex].height
3054: - currentScrollOffset;
3055:
3056: if (tabPlacement == SwingConstants.RIGHT && startgap >= 0)
3057: {
3058: g.setColor(shadow);
3059: g.drawLine(x + w - 2, y + 1, x + w - 2, startgap);
3060: g.drawLine(x + w - 2, endgap, x + w - 2, y + h - 2);
3061:
3062: g.setColor(darkShadow);
3063: g.drawLine(x + w - 1, y, x + w - 1, startgap);
3064: g.drawLine(x + w - 1, endgap, x + w - 1, y + h - 2);
3065:
3066: g.setColor(selectedColor);
3067: g.drawLine(x + w - 2, startgap, x + w - 2, endgap - 1);
3068: g.drawLine(x + w - 1, startgap, x + w - 1, endgap - 1);
3069: }
3070: else
3071: {
3072: g.setColor(shadow);
3073: g.drawLine(x + w - 2, y + 1, x + w - 2, y + h - 2);
3074: g.setColor(darkShadow);
3075: g.drawLine(x + w - 1, y, x + w - 1, y + h - 2);
3076: }
3077:
3078: g.setColor(selectedColor);
3079: g.drawLine(x + w - 3, y + 1, x + w - 3, y + h - 4);
3080:
3081: g.setColor(saved);
3082: }
3083:
3084:
3097: public Rectangle getTabBounds(JTabbedPane pane, int i)
3098: {
3099:
3100: if (i >= rects.length)
3101: layoutManager.layoutContainer(pane);
3102:
3103:
3104:
3105: if (pane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT)
3106: {
3107: Rectangle r = new Rectangle(rects[i]);
3108:
3109: switch(pane.getTabPlacement())
3110: {
3111: case SwingConstants.TOP:
3112: case SwingConstants.BOTTOM:
3113: r.x -= currentScrollOffset;
3114: break;
3115: default:
3116: r.y -= currentScrollOffset;
3117: }
3118:
3119: return r;
3120: }
3121:
3122: return rects[i];
3123: }
3124:
3125:
3132: public int getTabRunCount(JTabbedPane pane)
3133: {
3134: return runCount;
3135: }
3136:
3137:
3146: public int tabForCoordinate(JTabbedPane pane, int x, int y)
3147: {
3148:
3149: if (! tabPane.isValid())
3150: tabPane.validate();
3151:
3152: int tabCount = tabPane.getTabCount();
3153:
3154:
3155:
3156: int index = tabPane.getSelectedIndex();
3157: for (int i = 0; i < tabCount; ++i)
3158: {
3159: if (rects[i].contains(x, y))
3160: {
3161: index = i;
3162: break;
3163: }
3164: }
3165:
3166: return index;
3167: }
3168:
3169:
3180: protected Rectangle getTabBounds(int tabIndex, Rectangle dest)
3181: {
3182: dest.setBounds(getTabBounds(tabPane, tabIndex));
3183: return dest;
3184: }
3185:
3186:
3191: protected Component getVisibleComponent()
3192: {
3193: return visibleComponent;
3194: }
3195:
3196:
3201: protected void setVisibleComponent(Component component)
3202: {
3203:
3204: if (visibleComponent != null && visibleComponent != component
3205: && visibleComponent.getParent() == tabPane)
3206: {
3207: visibleComponent.setVisible(false);
3208: }
3209:
3210:
3211: if (component != null && ! component.isVisible())
3212: {
3213: component.setVisible(true);
3214: }
3215: visibleComponent = component;
3216: }
3217:
3218:
3224: protected void assureRectsCreated(int tabCount)
3225: {
3226: if (rects.length < tabCount)
3227: {
3228: Rectangle[] old = rects;
3229: rects = new Rectangle[tabCount];
3230: System.arraycopy(old, 0, rects, 0, old.length);
3231: for (int i = old.length; i < rects.length; i++)
3232: rects[i] = new Rectangle();
3233: }
3234: }
3235:
3236:
3240: protected void expandTabRunsArray()
3241: {
3242:
3243: if (tabRuns == null)
3244: tabRuns = new int[10];
3245: else
3246: {
3247: int[] newRuns = new int[tabRuns.length + 10];
3248: System.arraycopy(tabRuns, 0, newRuns, 0, tabRuns.length);
3249: tabRuns = newRuns;
3250: }
3251: }
3252:
3253:
3261: protected int getRunForTab(int tabCount, int tabIndex)
3262: {
3263: if (runCount == 1 && tabIndex < tabCount && tabIndex >= 0)
3264: return 0;
3265: for (int i = 0; i < runCount; i++)
3266: {
3267: int first = lastTabInRun(tabCount, getPreviousTabRun(i)) + 1;
3268: if (first == tabCount)
3269: first = 0;
3270: int last = lastTabInRun(tabCount, i);
3271: if (last >= tabIndex && first <= tabIndex)
3272: return i;
3273: }
3274: return -1;
3275: }
3276:
3277:
3285: protected int lastTabInRun(int tabCount, int run)
3286: {
3287: int lastTab;
3288: if (runCount == 1)
3289: lastTab = tabCount - 1;
3290: else
3291: {
3292: int nextRun;
3293: if (run == runCount - 1)
3294: nextRun = 0;
3295: else
3296: nextRun = run + 1;
3297:
3298: if (tabRuns[nextRun] == 0)
3299: lastTab = tabCount - 1;
3300: else
3301: lastTab = tabRuns[nextRun] - 1;
3302: }
3303: return lastTab;
3304: }
3305:
3306:
3313: protected int getTabRunOverlay(int tabPlacement)
3314: {
3315: return tabRunOverlay;
3316: }
3317:
3318:
3327: protected int getTabRunIndent(int tabPlacement, int run)
3328: {
3329: return 0;
3330: }
3331:
3332:
3340: protected boolean shouldPadTabRun(int tabPlacement, int run)
3341: {
3342: return true;
3343: }
3344:
3345:
3352: protected boolean shouldRotateTabRuns(int tabPlacement)
3353: {
3354: return true;
3355: }
3356:
3357:
3366: protected Icon getIconForTab(int tabIndex)
3367: {
3368: if (tabPane.isEnabledAt(tabIndex))
3369: return tabPane.getIconAt(tabIndex);
3370: else
3371: return tabPane.getDisabledIconAt(tabIndex);
3372: }
3373:
3374:
3381: protected View getTextViewForTab(int tabIndex)
3382: {
3383:
3384:
3385: return null;
3386: }
3387:
3388:
3398: protected int calculateTabHeight(int tabPlacement, int tabIndex,
3399: int fontHeight)
3400: {
3401:
3402:
3403: int height = fontHeight;
3404: Icon icon = getIconForTab(tabIndex);
3405: Insets tabInsets = getTabInsets(tabPlacement, tabIndex);
3406: if (icon != null)
3407: height = Math.max(height, icon.getIconHeight());
3408: height += tabInsets.top + tabInsets.bottom + 2;
3409: return height;
3410: }
3411:
3412:
3419: protected int calculateMaxTabHeight(int tabPlacement)
3420: {
3421: maxTabHeight = 0;
3422:
3423: FontMetrics fm = getFontMetrics();
3424: int fontHeight = fm.getHeight();
3425:
3426: for (int i = 0; i < tabPane.getTabCount(); i++)
3427: maxTabHeight = Math.max(calculateTabHeight(tabPlacement, i, fontHeight),
3428: maxTabHeight);
3429:
3430: return maxTabHeight;
3431: }
3432:
3433:
3443: protected int calculateTabWidth(int tabPlacement, int tabIndex,
3444: FontMetrics metrics)
3445: {
3446: Icon icon = getIconForTab(tabIndex);
3447: Insets insets = getTabInsets(tabPlacement, tabIndex);
3448:
3449: int width = insets.bottom + insets.right + 3;
3450: if (icon != null)
3451: {
3452: width += icon.getIconWidth() + textIconGap;
3453: }
3454:
3455: View v = getTextViewForTab(tabIndex);
3456: if (v != null)
3457: width += v.getPreferredSpan(View.X_AXIS);
3458: else
3459: {
3460: String label = tabPane.getTitleAt(tabIndex);
3461: width += metrics.stringWidth(label);
3462: }
3463: return width;
3464: }
3465:
3466:
3473: protected int calculateMaxTabWidth(int tabPlacement)
3474: {
3475: maxTabWidth = 0;
3476:
3477: FontMetrics fm = getFontMetrics();
3478:
3479: for (int i = 0; i < tabPane.getTabCount(); i++)
3480: maxTabWidth = Math.max(calculateTabWidth(tabPlacement, i, fm),
3481: maxTabWidth);
3482:
3483: return maxTabWidth;
3484: }
3485:
3486:
3496: protected int calculateTabAreaHeight(int tabPlacement, int horizRunCount,
3497: int maxTabHeight)
3498: {
3499: Insets insets = getTabAreaInsets(tabPlacement);
3500: int tabAreaHeight = horizRunCount * maxTabHeight
3501: - (horizRunCount - 1)
3502: * getTabRunOverlay(tabPlacement);
3503:
3504: tabAreaHeight += insets.top + insets.bottom;
3505:
3506: return tabAreaHeight;
3507: }
3508:
3509:
3519: protected int calculateTabAreaWidth(int tabPlacement, int vertRunCount,
3520: int maxTabWidth)
3521: {
3522: Insets insets = getTabAreaInsets(tabPlacement);
3523: int tabAreaWidth = vertRunCount * maxTabWidth
3524: - (vertRunCount - 1)
3525: * getTabRunOverlay(tabPlacement);
3526:
3527: tabAreaWidth += insets.left + insets.right;
3528:
3529: return tabAreaWidth;
3530: }
3531:
3532:
3540: protected Insets getTabInsets(int tabPlacement, int tabIndex)
3541: {
3542: return tabInsets;
3543: }
3544:
3545:
3552: protected Insets getSelectedTabPadInsets(int tabPlacement)
3553: {
3554: Insets target = new Insets(0, 0, 0, 0);
3555: rotateInsets(selectedTabPadInsets, target, tabPlacement);
3556: return target;
3557: }
3558:
3559:
3566: protected Insets getTabAreaInsets(int tabPlacement)
3567: {
3568: Insets target = new Insets(0, 0, 0, 0);
3569: rotateInsets(tabAreaInsets, target, tabPlacement);
3570: return target;
3571: }
3572:
3573:
3580: protected Insets getContentBorderInsets(int tabPlacement)
3581: {
3582: Insets target = new Insets(0, 0, 0, 0);
3583: rotateInsets(contentBorderInsets, target, tabPlacement);
3584: return target;
3585: }
3586:
3587:
3592: protected FontMetrics getFontMetrics()
3593: {
3594: FontMetrics fm = tabPane.getFontMetrics(tabPane.getFont());
3595: return fm;
3596: }
3597:
3598:
3604: protected void navigateSelectedTab(int direction)
3605: {
3606: int tabPlacement = tabPane.getTabPlacement();
3607: if (tabPlacement == SwingConstants.TOP
3608: || tabPlacement == SwingConstants.BOTTOM)
3609: {
3610: if (direction == SwingConstants.WEST)
3611: selectPreviousTabInRun(tabPane.getSelectedIndex());
3612: else if (direction == SwingConstants.EAST)
3613: selectNextTabInRun(tabPane.getSelectedIndex());
3614:
3615: else
3616: {
3617: int offset = getTabRunOffset(tabPlacement, tabPane.getTabCount(),
3618: tabPane.getSelectedIndex(),
3619: (tabPlacement == SwingConstants.TOP)
3620: ? direction == SwingConstants.NORTH
3621: : direction == SwingConstants.SOUTH);
3622: selectAdjacentRunTab(tabPlacement, tabPane.getSelectedIndex(),
3623: offset);
3624: }
3625: }
3626: if (tabPlacement == SwingConstants.LEFT
3627: || tabPlacement == SwingConstants.RIGHT)
3628: {
3629: if (direction == SwingConstants.NORTH)
3630: selectPreviousTabInRun(tabPane.getSelectedIndex());
3631: else if (direction == SwingConstants.SOUTH)
3632: selectNextTabInRun(tabPane.getSelectedIndex());
3633: else
3634: {
3635: int offset = getTabRunOffset(tabPlacement, tabPane.getTabCount(),
3636: tabPane.getSelectedIndex(),
3637: (tabPlacement == SwingConstants.LEFT)
3638: ? direction == SwingConstants.WEST
3639: : direction == SwingConstants.EAST);
3640: selectAdjacentRunTab(tabPlacement, tabPane.getSelectedIndex(),
3641: offset);
3642: }
3643: }
3644: }
3645:
3646:
3651: protected void selectNextTabInRun(int current)
3652: {
3653: current = getNextTabIndexInRun(tabPane.getTabCount(),
3654: current);
3655:
3656: if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT)
3657: scrollTab(current, tabPane.getTabPlacement());
3658:
3659: tabPane.setSelectedIndex(current);
3660: }
3661:
3662:
3667: protected void selectPreviousTabInRun(int current)
3668: {
3669: current = getPreviousTabIndexInRun(tabPane.getTabCount(),
3670: current);
3671:
3672: if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT)
3673: scrollTab(current, tabPane.getTabPlacement());
3674:
3675: tabPane.setSelectedIndex(current);
3676: }
3677:
3678:
3683: protected void selectNextTab(int current)
3684: {
3685: current = getNextTabIndex(current);
3686:
3687: if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT)
3688: scrollTab(current, tabPane.getTabPlacement());
3689:
3690: tabPane.setSelectedIndex(current);
3691: }
3692:
3693:
3698: protected void selectPreviousTab(int current)
3699: {
3700: current = getPreviousTabIndex(current);
3701:
3702: if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT)
3703: scrollTab(current, tabPane.getTabPlacement());
3704:
3705: tabPane.setSelectedIndex(current);
3706: }
3707:
3708:
3719: protected void selectAdjacentRunTab(int tabPlacement, int tabIndex,
3720: int offset)
3721: {
3722: int x = rects[tabIndex].x + rects[tabIndex].width / 2;
3723: int y = rects[tabIndex].y + rects[tabIndex].height / 2;
3724:
3725: switch (tabPlacement)
3726: {
3727: case SwingConstants.TOP:
3728: case SwingConstants.BOTTOM:
3729: y += offset;
3730: break;
3731: case SwingConstants.RIGHT:
3732: case SwingConstants.LEFT:
3733: x += offset;
3734: break;
3735: }
3736:
3737: int index = tabForCoordinate(tabPane, x, y);
3738: if (index != -1)
3739: {
3740: if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT)
3741: scrollTab(index, tabPlacement);
3742: tabPane.setSelectedIndex(index);
3743: }
3744: }
3745:
3746:
3747:
3748:
3749:
3750:
3751:
3752:
3767: protected int getTabRunOffset(int tabPlacement, int tabCount, int tabIndex,
3768: boolean forward)
3769: {
3770: int currRun = getRunForTab(tabCount, tabIndex);
3771: int offset;
3772: int nextRun = forward ? getNextTabRun(currRun) : getPreviousTabRun(currRun);
3773: if (tabPlacement == SwingConstants.TOP
3774: || tabPlacement == SwingConstants.BOTTOM)
3775: offset = rects[lastTabInRun(tabCount, nextRun)].y
3776: - rects[lastTabInRun(tabCount, currRun)].y;
3777: else
3778: offset = rects[lastTabInRun(tabCount, nextRun)].x
3779: - rects[lastTabInRun(tabCount, currRun)].x;
3780:
3781: return offset;
3782: }
3783:
3784:
3791: protected int getPreviousTabIndex(int base)
3792: {
3793: base--;
3794: if (base < 0)
3795: return tabPane.getTabCount() - 1;
3796: return base;
3797: }
3798:
3799:
3806: protected int getNextTabIndex(int base)
3807: {
3808: base++;
3809: if (base == tabPane.getTabCount())
3810: return 0;
3811: return base;
3812: }
3813:
3814:
3823: protected int getNextTabIndexInRun(int tabCount, int base)
3824: {
3825: int index = getNextTabIndex(base);
3826: int run = getRunForTab(tabCount, base);
3827: if (base == lastTabInRun(tabCount, run))
3828: index = (run > 0)
3829: ? lastTabInRun(tabCount, getPreviousTabRun(run)) + 1
3830: : 0;
3831:
3832: return index;
3833: }
3834:
3835:
3844: protected int getPreviousTabIndexInRun(int tabCount, int base)
3845: {
3846: int index = getPreviousTabIndex(base);
3847: int run = getRunForTab(tabCount, base);
3848: if (index == lastTabInRun(tabCount, getPreviousTabRun(run)))
3849: index = lastTabInRun(tabCount, run);
3850:
3851: return index;
3852: }
3853:
3854:
3861: protected int getPreviousTabRun(int baseRun)
3862: {
3863: if (getTabRunCount(tabPane) == 1)
3864: return 1;
3865:
3866: int prevRun = --baseRun;
3867: if (prevRun < 0)
3868: prevRun = getTabRunCount(tabPane) - 1;
3869: return prevRun;
3870: }
3871:
3872:
3879: protected int getNextTabRun(int baseRun)
3880: {
3881: if (getTabRunCount(tabPane) == 1)
3882: return 1;
3883:
3884: int nextRun = ++baseRun;
3885: if (nextRun == getTabRunCount(tabPane))
3886: nextRun = 0;
3887: return nextRun;
3888: }
3889:
3890:
3902: protected static void rotateInsets(Insets topInsets, Insets targetInsets,
3903: int targetPlacement)
3904: {
3905:
3906:
3907: switch (targetPlacement)
3908: {
3909: default:
3910: case SwingConstants.TOP:
3911: targetInsets.top = topInsets.top;
3912: targetInsets.left = topInsets.left;
3913: targetInsets.right = topInsets.right;
3914: targetInsets.bottom = topInsets.bottom;
3915: break;
3916: case SwingConstants.LEFT:
3917: targetInsets.left = topInsets.top;
3918: targetInsets.top = topInsets.left;
3919: targetInsets.right = topInsets.bottom;
3920: targetInsets.bottom = topInsets.right;
3921: break;
3922: case SwingConstants.BOTTOM:
3923: targetInsets.top = topInsets.bottom;
3924: targetInsets.bottom = topInsets.top;
3925: targetInsets.left = topInsets.left;
3926: targetInsets.right = topInsets.right;
3927: break;
3928: case SwingConstants.RIGHT:
3929: targetInsets.top = topInsets.left;
3930: targetInsets.left = topInsets.bottom;
3931: targetInsets.bottom = topInsets.right;
3932: targetInsets.right = topInsets.top;
3933: break;
3934: }
3935: }
3936:
3937: ActionMap getActionMap()
3938: {
3939: ActionMap map = (ActionMap) UIManager.get("TabbedPane.actionMap");
3940:
3941: if (map == null)
3942: {
3943: map = createActionMap();
3944: if (map != null)
3945: UIManager.put("TabbedPane.actionMap", map);
3946: }
3947: return map;
3948: }
3949:
3950: ActionMap createActionMap()
3951: {
3952: ActionMap map = new ActionMapUIResource();
3953:
3954: map.put("navigatePageDown", new NavigatePageDownAction());
3955: map.put("navigatePageUp", new NavigatePageUpAction());
3956: map.put("navigateDown",
3957: new NavigateAction("navigateDown", SwingConstants.SOUTH));
3958:
3959: map.put("navigateUp",
3960: new NavigateAction("navigateUp", SwingConstants.NORTH));
3961:
3962: map.put("navigateLeft",
3963: new NavigateAction("navigateLeft", SwingConstants.WEST));
3964:
3965: map.put("navigateRight",
3966: new NavigateAction("navigateRight", SwingConstants.EAST));
3967:
3968: map.put("requestFocusForVisibleComponent",
3969: new RequestFocusForVisibleComponentAction());
3970: map.put("requestFocus", new RequestFocusAction());
3971:
3972: return map;
3973: }
3974:
3975:
3985: protected void setRolloverTab(int index)
3986: {
3987: rolloverTab = index;
3988: }
3989:
3990:
3999: protected int getRolloverTab()
4000: {
4001: return rolloverTab;
4002: }
4003: }