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:
61: import ;
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:
79:
82: public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
83: {
84:
91: public class FocusHandler extends FocusAdapter
92: {
93:
98: public void focusGained(FocusEvent e)
99: {
100:
101: }
102:
103:
108: public void focusLost(FocusEvent e)
109: {
110:
111: }
112: }
113:
114:
123: public class MouseHandler extends MouseAdapter
124: {
125:
131: public void mousePressed(MouseEvent e)
132: {
133: int x = e.getX();
134: int y = e.getY();
135: int tabCount = tabPane.getTabCount();
136:
137: if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT)
138: {
139: if (e.getSource() == incrButton)
140: {
141: if (++currentScrollLocation >= tabCount)
142: currentScrollLocation = tabCount - 1;
143:
144: int width = 0;
145: for (int i = currentScrollLocation - 1; i < tabCount; i++)
146: width += rects[i].width;
147: if (width < viewport.getWidth())
148:
149:
150: currentScrollLocation--;
151: else if (! decrButton.isEnabled())
152: decrButton.setEnabled(true);
153: tabPane.revalidate();
154: tabPane.repaint();
155: return;
156: }
157: else if (e.getSource() == decrButton)
158: {
159: if (--currentScrollLocation < 0)
160: currentScrollLocation = 0;
161: if (currentScrollLocation == 0)
162: decrButton.setEnabled(false);
163: else if (! incrButton.isEnabled())
164: incrButton.setEnabled(true);
165: tabPane.revalidate();
166: tabPane.repaint();
167: return;
168: }
169: }
170:
171: int index = tabForCoordinate(tabPane, x, y);
172:
173:
174:
175: if (index != -1 && tabPane.isEnabledAt(index))
176: tabPane.setSelectedIndex(index);
177: tabPane.revalidate();
178: tabPane.repaint();
179: }
180: }
181:
182:
189: public class PropertyChangeHandler implements PropertyChangeListener
190: {
191:
197: public void propertyChange(PropertyChangeEvent e)
198: {
199: if (e.getPropertyName().equals("tabLayoutPolicy"))
200: {
201: layoutManager = createLayoutManager();
202:
203: tabPane.setLayout(layoutManager);
204: }
205: else if (e.getPropertyName().equals("tabPlacement")
206: && tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT)
207: {
208: incrButton = createIncreaseButton();
209: decrButton = createDecreaseButton();
210: }
211: tabPane.revalidate();
212: tabPane.repaint();
213: }
214: }
215:
216:
225: public class TabbedPaneLayout implements LayoutManager
226: {
227:
233: public void addLayoutComponent(String name, Component comp)
234: {
235:
236: }
237:
238:
242: public void calculateLayoutInfo()
243: {
244: assureRectsCreated(tabPane.getTabCount());
245: contentRect = SwingUtilities.calculateInnerArea(tabPane, contentRect);
246:
247: calculateTabRects(tabPane.getTabPlacement(), tabPane.getTabCount());
248:
249: if (tabPane.getSelectedIndex() != -1)
250: {
251: Component visible = getVisibleComponent();
252: Insets insets = getContentBorderInsets(tabPane.getTabPlacement());
253: if (visible != null)
254: visible.setBounds(contentRect.x + insets.left,
255: contentRect.y + insets.top,
256: contentRect.width - insets.left - insets.right,
257: contentRect.height - insets.top - insets.bottom);
258: }
259: }
260:
261:
269: protected Dimension calculateSize(boolean minimum)
270: {
271: int tabPlacement = tabPane.getTabPlacement();
272: int width = 0;
273: int height = 0;
274:
275: int componentHeight = 0;
276: int componentWidth = 0;
277: Component c;
278: Dimension dims;
279: for (int i = 0; i < tabPane.getTabCount(); i++)
280: {
281: c = tabPane.getComponentAt(i);
282: if (c == null)
283: continue;
284: calcRect = c.getBounds();
285: dims = c.getPreferredSize();
286: if (dims != null)
287: {
288: componentHeight = Math.max(componentHeight, dims.height);
289: componentWidth = Math.max(componentWidth, dims.width);
290: }
291: }
292: if (tabPlacement == SwingConstants.TOP
293: || tabPlacement == SwingConstants.BOTTOM)
294: {
295: int min = calculateMaxTabWidth(tabPlacement);
296: width = Math.max(min, componentWidth);
297:
298: int tabAreaHeight = preferredTabAreaHeight(tabPlacement, width);
299: height = tabAreaHeight + componentHeight;
300: }
301: else
302: {
303: int min = calculateMaxTabHeight(tabPlacement);
304: height = Math.max(min, componentHeight);
305:
306: int tabAreaWidth = preferredTabAreaWidth(tabPlacement, height);
307: width = tabAreaWidth + componentWidth;
308: }
309:
310: return new Dimension(width, height);
311: }
312:
313:
314:
315:
316:
317:
318:
319:
320:
321:
322:
331: protected void calculateTabRects(int tabPlacement, int tabCount)
332: {
333: if (tabCount == 0)
334: return;
335:
336: FontMetrics fm = getFontMetrics();
337: SwingUtilities.calculateInnerArea(tabPane, calcRect);
338: Insets tabAreaInsets = getTabAreaInsets(tabPlacement);
339: Insets insets = tabPane.getInsets();
340: int max = 0;
341: int runs = 0;
342: int start = getTabRunIndent(tabPlacement, 1);
343: if (tabPlacement == SwingConstants.TOP
344: || tabPlacement == SwingConstants.BOTTOM)
345: {
346: int maxHeight = calculateMaxTabHeight(tabPlacement);
347:
348: calcRect.width -= tabAreaInsets.left + tabAreaInsets.right;
349: max = calcRect.width + tabAreaInsets.left + insets.left;
350: start += tabAreaInsets.left + insets.left;
351: int width = 0;
352: int runWidth = start;
353:
354: for (int i = 0; i < tabCount; i++)
355: {
356: width = calculateTabWidth(tabPlacement, i, fm);
357: if (runWidth + width > max)
358: {
359: runWidth = tabAreaInsets.left + insets.left
360: + getTabRunIndent(tabPlacement, ++runs);
361: rects[i] = new Rectangle(runWidth,
362: insets.top + tabAreaInsets.top,
363: width, maxHeight);
364: runWidth += width;
365: if (runs > tabRuns.length - 1)
366: expandTabRunsArray();
367: tabRuns[runs] = i;
368: }
369: else
370: {
371: rects[i] = new Rectangle(runWidth,
372: insets.top + tabAreaInsets.top,
373: width, maxHeight);
374: runWidth += width;
375: }
376: }
377: runs++;
378: tabAreaRect.width = tabPane.getWidth() - insets.left - insets.right;
379: tabAreaRect.height = runs * maxTabHeight
380: - (runs - 1) * tabRunOverlay
381: + tabAreaInsets.top + tabAreaInsets.bottom;
382: contentRect.width = tabAreaRect.width;
383: contentRect.height = tabPane.getHeight() - insets.top
384: - insets.bottom - tabAreaRect.height;
385: contentRect.x = insets.left;
386: tabAreaRect.x = insets.left;
387: if (tabPlacement == SwingConstants.BOTTOM)
388: {
389: contentRect.y = insets.top;
390: tabAreaRect.y = contentRect.y + contentRect.height;
391: }
392: else
393: {
394: tabAreaRect.y = insets.top;
395: contentRect.y = tabAreaRect.y + tabAreaRect.height;
396: }
397: }
398: else
399: {
400: int maxWidth = calculateMaxTabWidth(tabPlacement);
401: calcRect.height -= tabAreaInsets.top + tabAreaInsets.bottom;
402: max = calcRect.height + tabAreaInsets.top + insets.top;
403:
404: int height = 0;
405: start += tabAreaInsets.top + insets.top;
406: int runHeight = start;
407:
408: int fontHeight = fm.getHeight();
409:
410: for (int i = 0; i < tabCount; i++)
411: {
412: height = calculateTabHeight(tabPlacement, i, fontHeight);
413: if (runHeight + height > max)
414: {
415: runHeight = tabAreaInsets.top + insets.top
416: + getTabRunIndent(tabPlacement, ++runs);
417: rects[i] = new Rectangle(insets.left + tabAreaInsets.left,
418: runHeight, maxWidth, height);
419: runHeight += height;
420: if (runs > tabRuns.length - 1)
421: expandTabRunsArray();
422: tabRuns[runs] = i;
423: }
424: else
425: {
426: rects[i] = new Rectangle(insets.left + tabAreaInsets.left,
427: runHeight, maxWidth, height);
428: runHeight += height;
429: }
430: }
431: runs++;
432:
433: tabAreaRect.width = runs * maxTabWidth - (runs - 1) * tabRunOverlay
434: + tabAreaInsets.left + tabAreaInsets.right;
435: tabAreaRect.height = tabPane.getHeight() - insets.top
436: - insets.bottom;
437: tabAreaRect.y = insets.top;
438: contentRect.width = tabPane.getWidth() - insets.left - insets.right
439: - tabAreaRect.width;
440: contentRect.height = tabAreaRect.height;
441: contentRect.y = insets.top;
442: if (tabPlacement == SwingConstants.LEFT)
443: {
444: tabAreaRect.x = insets.left;
445: contentRect.x = tabAreaRect.x + tabAreaRect.width;
446: }
447: else
448: {
449: contentRect.x = insets.left;
450: tabAreaRect.x = contentRect.x + contentRect.width;
451: }
452: }
453: runCount = runs;
454:
455: tabRuns[0] = 0;
456: normalizeTabRuns(tabPlacement, tabCount, start, max);
457: selectedRun = getRunForTab(tabCount, tabPane.getSelectedIndex());
458: if (shouldRotateTabRuns(tabPlacement))
459: rotateTabRuns(tabPlacement, selectedRun);
460:
461:
462: for (int i = 0; i < runCount; i++)
463: {
464: int first = lastTabInRun(tabCount, getPreviousTabRun(i)) + 1;
465: if (first == tabCount)
466: first = 0;
467: int last = lastTabInRun(tabCount, i);
468: if (shouldPadTabRun(tabPlacement, i))
469: padTabRun(tabPlacement, first, last, max);
470:
471:
472: if (tabPlacement == SwingConstants.TOP && i > 0)
473: {
474: for (int j = first; j <= last; j++)
475: rects[j].y += (runCount - i) * maxTabHeight
476: - (runCount - i) * tabRunOverlay;
477: }
478:
479: if (tabPlacement == SwingConstants.BOTTOM)
480: {
481: int height = tabPane.getBounds().height - insets.bottom
482: - tabAreaInsets.bottom;
483: int adjustment;
484: if (i == 0)
485: adjustment = height - maxTabHeight;
486: else
487: adjustment = height - (runCount - i + 1) * maxTabHeight
488: - (runCount - i) * tabRunOverlay;
489:
490: for (int j = first; j <= last; j++)
491: rects[j].y = adjustment;
492: }
493:
494: if (tabPlacement == SwingConstants.LEFT && i > 0)
495: {
496: for (int j = first; j <= last; j++)
497: rects[j].x += (runCount - i) * maxTabWidth
498: - (runCount - i) * tabRunOverlay;
499: }
500:
501: if (tabPlacement == SwingConstants.RIGHT)
502: {
503: int width = tabPane.getBounds().width - insets.right
504: - tabAreaInsets.right;
505: int adjustment;
506: if (i == 0)
507: adjustment = width - maxTabWidth;
508: else
509: adjustment = width - (runCount - i + 1) * maxTabWidth
510: + (runCount - i) * tabRunOverlay;
511:
512: for (int j = first; j <= last; j++)
513: rects[j].x = adjustment;
514: }
515: }
516: padSelectedTab(tabPlacement, tabPane.getSelectedIndex());
517: }
518:
519:
526: public void layoutContainer(Container parent)
527: {
528: calculateLayoutInfo();
529: }
530:
531:
538: public Dimension minimumLayoutSize(Container parent)
539: {
540: return calculateSize(false);
541: }
542:
543:
544:
545:
546:
547:
548:
549:
550:
551:
560: protected void normalizeTabRuns(int tabPlacement, int tabCount, int start,
561: int max)
562: {
563: Insets tabAreaInsets = getTabAreaInsets(tabPlacement);
564: if (tabPlacement == SwingUtilities.TOP
565: || tabPlacement == SwingUtilities.BOTTOM)
566: {
567:
568:
569: for (int i = 1; i < runCount; i++)
570: {
571: Rectangle currRun = rects[lastTabInRun(tabCount, i)];
572: Rectangle nextRun = rects[lastTabInRun(tabCount, getNextTabRun(i))];
573: int spaceInCurr = currRun.x + currRun.width;
574: int spaceInNext = nextRun.x + nextRun.width;
575:
576: int diffNow = spaceInCurr - spaceInNext;
577: int diffLater = (spaceInCurr - currRun.width)
578: - (spaceInNext + currRun.width);
579: while (Math.abs(diffLater) < Math.abs(diffNow)
580: && spaceInNext + currRun.width < max)
581: {
582: tabRuns[i]--;
583: spaceInNext += currRun.width;
584: spaceInCurr -= currRun.width;
585: currRun = rects[lastTabInRun(tabCount, i)];
586: diffNow = spaceInCurr - spaceInNext;
587: diffLater = (spaceInCurr - currRun.width)
588: - (spaceInNext + currRun.width);
589: }
590:
591:
592: int first = lastTabInRun(tabCount, i) + 1;
593: int last = lastTabInRun(tabCount, getNextTabRun(i));
594: int currX = tabAreaInsets.left;
595: for (int j = first; j <= last; j++)
596: {
597: rects[j].x = currX;
598: currX += rects[j].width;
599: }
600: }
601: }
602: else
603: {
604: for (int i = 1; i < runCount; i++)
605: {
606: Rectangle currRun = rects[lastTabInRun(tabCount, i)];
607: Rectangle nextRun = rects[lastTabInRun(tabCount, getNextTabRun(i))];
608: int spaceInCurr = currRun.y + currRun.height;
609: int spaceInNext = nextRun.y + nextRun.height;
610:
611: int diffNow = spaceInCurr - spaceInNext;
612: int diffLater = (spaceInCurr - currRun.height)
613: - (spaceInNext + currRun.height);
614: while (Math.abs(diffLater) < Math.abs(diffNow)
615: && spaceInNext + currRun.height < max)
616: {
617: tabRuns[i]--;
618: spaceInNext += currRun.height;
619: spaceInCurr -= currRun.height;
620: currRun = rects[lastTabInRun(tabCount, i)];
621: diffNow = spaceInCurr - spaceInNext;
622: diffLater = (spaceInCurr - currRun.height)
623: - (spaceInNext + currRun.height);
624: }
625:
626: int first = lastTabInRun(tabCount, i) + 1;
627: int last = lastTabInRun(tabCount, getNextTabRun(i));
628: int currY = tabAreaInsets.top;
629: for (int j = first; j <= last; j++)
630: {
631: rects[j].y = currY;
632: currY += rects[j].height;
633: }
634: }
635: }
636: }
637:
638:
645: protected void padSelectedTab(int tabPlacement, int selectedIndex)
646: {
647: Insets insets = getSelectedTabPadInsets(tabPlacement);
648: rects[selectedIndex].x -= insets.left;
649: rects[selectedIndex].y -= insets.top;
650: rects[selectedIndex].width += insets.left + insets.right;
651: rects[selectedIndex].height += insets.top + insets.bottom;
652: }
653:
654:
655:
656:
657:
658:
659:
660:
670: protected void padTabRun(int tabPlacement, int start, int end, int max)
671: {
672: if (tabPlacement == SwingConstants.TOP
673: || tabPlacement == SwingConstants.BOTTOM)
674: {
675: int runWidth = rects[end].x + rects[end].width;
676: int spaceRemaining = max - runWidth;
677: int numTabs = end - start + 1;
678:
679:
680: int spaceAllocated = spaceRemaining / numTabs;
681: int currX = rects[start].x;
682: for (int i = start; i <= end; i++)
683: {
684: rects[i].x = currX;
685: rects[i].width += spaceAllocated;
686: currX += rects[i].width;
687:
688:
689:
690:
691: if (i == end && rects[i].x + rects[i].width != max)
692: rects[i].width = max - rects[i].x;
693: }
694: }
695: else
696: {
697: int runHeight = rects[end].y + rects[end].height;
698: int spaceRemaining = max - runHeight;
699: int numTabs = end - start + 1;
700:
701: int spaceAllocated = spaceRemaining / numTabs;
702: int currY = rects[start].y;
703: for (int i = start; i <= end; i++)
704: {
705: rects[i].y = currY;
706: rects[i].height += spaceAllocated;
707: currY += rects[i].height;
708: if (i == end && rects[i].y + rects[i].height != max)
709: rects[i].height = max - rects[i].y;
710: }
711: }
712: }
713:
714:
721: public Dimension preferredLayoutSize(Container parent)
722: {
723: return calculateSize(false);
724: }
725:
726:
735: protected int preferredTabAreaHeight(int tabPlacement, int width)
736: {
737: if (tabPane.getTabCount() == 0)
738: return calculateTabAreaHeight(tabPlacement, 0, 0);
739:
740: int runs = 0;
741: int runWidth = 0;
742: int tabWidth = 0;
743:
744: FontMetrics fm = getFontMetrics();
745:
746: Insets tabAreaInsets = getTabAreaInsets(tabPlacement);
747: Insets insets = tabPane.getInsets();
748:
749:
750: width -= tabAreaInsets.left + tabAreaInsets.right + insets.left
751: + insets.right;
752:
753:
754:
755:
756:
757:
758: for (int i = 0; i < tabPane.getTabCount(); i++)
759: {
760: tabWidth = calculateTabWidth(tabPlacement, i, fm);
761: if (runWidth + tabWidth > width)
762: {
763: runWidth = tabWidth;
764: runs++;
765: }
766: else
767: runWidth += tabWidth;
768: }
769: runs++;
770:
771: int maxTabHeight = calculateMaxTabHeight(tabPlacement);
772: int tabAreaHeight = calculateTabAreaHeight(tabPlacement, runs,
773: maxTabHeight);
774: return tabAreaHeight;
775: }
776:
777:
786: protected int preferredTabAreaWidth(int tabPlacement, int height)
787: {
788: if (tabPane.getTabCount() == 0)
789: return calculateTabAreaHeight(tabPlacement, 0, 0);
790:
791: int runs = 0;
792: int runHeight = 0;
793: int tabHeight = 0;
794:
795: FontMetrics fm = getFontMetrics();
796:
797: Insets tabAreaInsets = getTabAreaInsets(tabPlacement);
798: Insets insets = tabPane.getInsets();
799:
800: height -= tabAreaInsets.top + tabAreaInsets.bottom + insets.top
801: + insets.bottom;
802: int fontHeight = fm.getHeight();
803:
804: for (int i = 0; i < tabPane.getTabCount(); i++)
805: {
806: tabHeight = calculateTabHeight(tabPlacement, i, fontHeight);
807: if (runHeight + tabHeight > height)
808: {
809: runHeight = tabHeight;
810: runs++;
811: }
812: else
813: runHeight += tabHeight;
814: }
815: runs++;
816:
817: int maxTabWidth = calculateMaxTabWidth(tabPlacement);
818: int tabAreaWidth = calculateTabAreaWidth(tabPlacement, runs, maxTabWidth);
819: return tabAreaWidth;
820: }
821:
822:
830: protected void rotateTabRuns(int tabPlacement, int selectedRun)
831: {
832: if (runCount == 1 || selectedRun == 1 || selectedRun == -1)
833: return;
834: int[] newTabRuns = new int[tabRuns.length];
835: int currentRun = selectedRun;
836: int i = 1;
837: do
838: {
839: newTabRuns[i] = tabRuns[currentRun];
840: currentRun = getNextTabRun(currentRun);
841: i++;
842: }
843: while (i < runCount);
844: if (runCount > 1)
845: newTabRuns[0] = tabRuns[currentRun];
846:
847: tabRuns = newTabRuns;
848: BasicTabbedPaneUI.this.selectedRun = 1;
849: }
850:
851:
857: public void removeLayoutComponent(Component comp)
858: {
859:
860: }
861: }
862:
863:
867: private class TabbedPaneScrollLayout extends TabbedPaneLayout
868: {
869:
876: public Dimension preferredLayoutSize(Container parent)
877: {
878: return super.calculateSize(true);
879: }
880:
881:
888: public Dimension minimumLayoutSize(Container parent)
889: {
890: return super.calculateSize(true);
891: }
892:
893:
901: protected int preferredTabAreaHeight(int tabPlacement, int width)
902: {
903: if (tabPane.getTabCount() == 0)
904: return calculateTabAreaHeight(tabPlacement, 0, 0);
905:
906: int runs = 1;
907:
908: int maxTabHeight = calculateMaxTabHeight(tabPlacement);
909: int tabAreaHeight = calculateTabAreaHeight(tabPlacement, runs,
910: maxTabHeight);
911: return tabAreaHeight;
912: }
913:
914:
922: protected int preferredTabAreaWidth(int tabPlacement, int height)
923: {
924: if (tabPane.getTabCount() == 0)
925: return calculateTabAreaHeight(tabPlacement, 0, 0);
926:
927: int runs = 1;
928:
929: int maxTabWidth = calculateMaxTabWidth(tabPlacement);
930: int tabAreaWidth = calculateTabAreaWidth(tabPlacement, runs, maxTabWidth);
931: return tabAreaWidth;
932: }
933:
934:
943: protected void calculateTabRects(int tabPlacement, int tabCount)
944: {
945: if (tabCount == 0)
946: return;
947:
948: FontMetrics fm = getFontMetrics();
949: SwingUtilities.calculateInnerArea(tabPane, calcRect);
950: Insets tabAreaInsets = getTabAreaInsets(tabPlacement);
951: Insets insets = tabPane.getInsets();
952: int runs = 1;
953: int start = 0;
954: int top = 0;
955: if (tabPlacement == SwingConstants.TOP
956: || tabPlacement == SwingConstants.BOTTOM)
957: {
958: int maxHeight = calculateMaxTabHeight(tabPlacement);
959: calcRect.width -= tabAreaInsets.left + tabAreaInsets.right;
960: start = tabAreaInsets.left + insets.left;
961: int width = 0;
962: int runWidth = start;
963: top = insets.top + tabAreaInsets.top;
964: for (int i = 0; i < tabCount; i++)
965: {
966: width = calculateTabWidth(tabPlacement, i, fm);
967:
968: rects[i] = new Rectangle(runWidth, top, width, maxHeight);
969: runWidth += width;
970: }
971: tabAreaRect.width = tabPane.getWidth() - insets.left - insets.right;
972: tabAreaRect.height = runs * maxTabHeight
973: - (runs - 1) * tabRunOverlay
974: + tabAreaInsets.top + tabAreaInsets.bottom;
975: contentRect.width = tabAreaRect.width;
976: contentRect.height = tabPane.getHeight() - insets.top
977: - insets.bottom - tabAreaRect.height;
978: contentRect.x = insets.left;
979: tabAreaRect.x = insets.left;
980: if (tabPlacement == SwingConstants.BOTTOM)
981: {
982: contentRect.y = insets.top;
983: tabAreaRect.y = contentRect.y + contentRect.height;
984: }
985: else
986: {
987: tabAreaRect.y = insets.top;
988: contentRect.y = tabAreaRect.y + tabAreaRect.height;
989: }
990: }
991: else
992: {
993: int maxWidth = calculateMaxTabWidth(tabPlacement);
994:
995: calcRect.height -= tabAreaInsets.top + tabAreaInsets.bottom;
996: int height = 0;
997: start = tabAreaInsets.top + insets.top;
998: int runHeight = start;
999: int fontHeight = fm.getHeight();
1000: top = insets.left + tabAreaInsets.left;
1001: for (int i = 0; i < tabCount; i++)
1002: {
1003: height = calculateTabHeight(tabPlacement, i, fontHeight);
1004: rects[i] = new Rectangle(top, runHeight, maxWidth, height);
1005: runHeight += height;
1006: }
1007: tabAreaRect.width = runs * maxTabWidth - (runs - 1) * tabRunOverlay
1008: + tabAreaInsets.left + tabAreaInsets.right;
1009: tabAreaRect.height = tabPane.getHeight() - insets.top
1010: - insets.bottom;
1011: tabAreaRect.y = insets.top;
1012: contentRect.width = tabPane.getWidth() - insets.left - insets.right
1013: - tabAreaRect.width;
1014: contentRect.height = tabAreaRect.height;
1015: contentRect.y = insets.top;
1016: if (tabPlacement == SwingConstants.LEFT)
1017: {
1018: tabAreaRect.x = insets.left;
1019: contentRect.x = tabAreaRect.x + tabAreaRect.width;
1020: }
1021: else
1022: {
1023: contentRect.x = insets.left;
1024: tabAreaRect.x = contentRect.x + contentRect.width;
1025: }
1026: }
1027: runCount = runs;
1028:
1029: padSelectedTab(tabPlacement, tabPane.getSelectedIndex());
1030: }
1031:
1032:
1039: public void layoutContainer(Container pane)
1040: {
1041: super.layoutContainer(pane);
1042: int tabCount = tabPane.getTabCount();
1043: Point p = null;
1044: if (tabCount == 0)
1045: return;
1046: int tabPlacement = tabPane.getTabPlacement();
1047: incrButton.setVisible(false);
1048: decrButton.setVisible(false);
1049: if (tabPlacement == SwingConstants.TOP
1050: || tabPlacement == SwingConstants.BOTTOM)
1051: {
1052: if (tabAreaRect.x + tabAreaRect.width < rects[tabCount - 1].x
1053: + rects[tabCount - 1].width)
1054: {
1055: Dimension incrDims = incrButton.getPreferredSize();
1056: Dimension decrDims = decrButton.getPreferredSize();
1057:
1058: decrButton.setBounds(tabAreaRect.x + tabAreaRect.width
1059: - incrDims.width - decrDims.width,
1060: tabAreaRect.y, decrDims.width,
1061: tabAreaRect.height);
1062: incrButton.setBounds(tabAreaRect.x + tabAreaRect.width
1063: - incrDims.width, tabAreaRect.y,
1064: decrDims.width, tabAreaRect.height);
1065:
1066: tabAreaRect.width -= decrDims.width + incrDims.width;
1067: incrButton.setVisible(true);
1068: decrButton.setVisible(true);
1069: }
1070: }
1071:
1072: if (tabPlacement == SwingConstants.LEFT
1073: || tabPlacement == SwingConstants.RIGHT)
1074: {
1075: if (tabAreaRect.y + tabAreaRect.height < rects[tabCount - 1].y
1076: + rects[tabCount - 1].height)
1077: {
1078: Dimension incrDims = incrButton.getPreferredSize();
1079: Dimension decrDims = decrButton.getPreferredSize();
1080:
1081: decrButton.setBounds(tabAreaRect.x,
1082: tabAreaRect.y + tabAreaRect.height
1083: - incrDims.height - decrDims.height,
1084: tabAreaRect.width, decrDims.height);
1085: incrButton.setBounds(tabAreaRect.x,
1086: tabAreaRect.y + tabAreaRect.height
1087: - incrDims.height, tabAreaRect.width,
1088: incrDims.height);
1089:
1090: tabAreaRect.height -= decrDims.height + incrDims.height;
1091: incrButton.setVisible(true);
1092: decrButton.setVisible(true);
1093: }
1094: }
1095: viewport.setBounds(tabAreaRect.x, tabAreaRect.y, tabAreaRect.width,
1096: tabAreaRect.height);
1097: int tabC = tabPane.getTabCount() - 1;
1098: if (tabCount > 0)
1099: {
1100: int w = Math.max(rects[tabC].width + rects[tabC].x, tabAreaRect.width);
1101: int h = Math.max(rects[tabC].height, tabAreaRect.height);
1102: p = findPointForIndex(currentScrollLocation);
1103:
1104:
1105:
1106: panel.setSize(w + p.x, h + p.y);
1107: }
1108: viewport.setViewPosition(p);
1109: viewport.repaint();
1110: }
1111: }
1112:
1113:
1120: public class TabSelectionHandler implements ChangeListener
1121: {
1122:
1128: public void stateChanged(ChangeEvent e)
1129: {
1130: selectedRun = getRunForTab(tabPane.getTabCount(),
1131: tabPane.getSelectedIndex());
1132: tabPane.revalidate();
1133: tabPane.repaint();
1134: }
1135: }
1136:
1137:
1142: private class ScrollingPanel extends JPanel
1143: {
1144:
1147: private class ScrollingPanelUI extends BasicPanelUI
1148: {
1149:
1156: public void paint(Graphics g, JComponent c)
1157: {
1158: paintTabArea(g, tabPane.getTabPlacement(), tabPane.getSelectedIndex());
1159: }
1160: }
1161:
1162:
1166: public void updateUI()
1167: {
1168: setUI((PanelUI) new ScrollingPanelUI());
1169: }
1170: }
1171:
1172:
1178: private class ScrollingViewport extends JViewport implements UIResource
1179: {
1180:
1181: }
1182:
1183:
1187: private class ScrollingButton extends BasicArrowButton implements UIResource
1188: {
1189:
1194: public ScrollingButton(int dir)
1195: {
1196: super(dir);
1197: }
1198: }
1199:
1200:
1202: transient ScrollingButton incrButton;
1203:
1204:
1206: transient ScrollingButton decrButton;
1207:
1208:
1210: transient ScrollingViewport viewport;
1211:
1212:
1214: transient ScrollingPanel panel;
1215:
1216:
1218: transient int currentScrollLocation;
1219:
1220:
1221: protected Rectangle calcRect;
1222:
1223:
1224: protected Rectangle[] rects;
1225:
1226:
1227: protected Insets contentBorderInsets;
1228:
1229:
1230: protected Insets selectedTabPadInsets;
1231:
1232:
1233: protected Insets tabAreaInsets;
1234:
1235:
1236: protected Insets tabInsets;
1237:
1238:
1242: protected Color darkShadow;
1243:
1244:
1245: protected Color focus;
1246:
1247:
1248: protected Color highlight;
1249:
1250:
1251: protected Color lightHighlight;
1252:
1253:
1254: protected Color shadow;
1255:
1256:
1257: protected int maxTabHeight;
1258:
1259:
1260: protected int maxTabWidth;
1261:
1262:
1263: protected int runCount;
1264:
1265:
1266: protected int selectedRun;
1267:
1268:
1269: protected int tabRunOverlay;
1270:
1271:
1272: protected int textIconGap;
1273:
1274:
1275:
1276:
1277:
1278:
1279:
1280:
1281:
1282:
1283:
1284: protected int[] tabRuns;
1285:
1286:
1291: protected KeyStroke downKey;
1292:
1293:
1298: protected KeyStroke leftKey;
1299:
1300:
1305: protected KeyStroke rightKey;
1306:
1307:
1312: protected KeyStroke upKey;
1313:
1314:
1315: protected FocusListener focusListener;
1316:
1317:
1318: protected MouseListener mouseListener;
1319:
1320:
1321: protected PropertyChangeListener propertyChangeListener;
1322:
1323:
1324: protected ChangeListener tabChangeListener;
1325:
1326:
1327: protected JTabbedPane tabPane;
1328:
1329:
1331: transient LayoutManager layoutManager;
1332:
1333:
1335: transient Rectangle tabAreaRect;
1336:
1337:
1339: transient Rectangle contentRect;
1340:
1341:
1344: public BasicTabbedPaneUI()
1345: {
1346: super();
1347: rects = new Rectangle[0];
1348: tabRuns = new int[10];
1349: }
1350:
1351:
1358: ScrollingButton createIncreaseButton()
1359: {
1360: if (incrButton == null)
1361: incrButton = new ScrollingButton(SwingConstants.NORTH);
1362: if (tabPane.getTabPlacement() == SwingConstants.TOP
1363: || tabPane.getTabPlacement() == SwingConstants.BOTTOM)
1364: incrButton.setDirection(SwingConstants.EAST);
1365: else
1366: incrButton.setDirection(SwingConstants.SOUTH);
1367: return incrButton;
1368: }
1369:
1370:
1377: ScrollingButton createDecreaseButton()
1378: {
1379: if (decrButton == null)
1380: decrButton = new ScrollingButton(SwingConstants.SOUTH);
1381: if (tabPane.getTabPlacement() == SwingConstants.TOP
1382: || tabPane.getTabPlacement() == SwingConstants.BOTTOM)
1383: decrButton.setDirection(SwingConstants.WEST);
1384: else
1385: decrButton.setDirection(SwingConstants.NORTH);
1386: return decrButton;
1387: }
1388:
1389:
1398: Point findPointForIndex(int index)
1399: {
1400: int tabPlacement = tabPane.getTabPlacement();
1401: int selectedIndex = tabPane.getSelectedIndex();
1402: Insets insets = getSelectedTabPadInsets(tabPlacement);
1403: int w = 0;
1404: int h = 0;
1405:
1406: if (tabPlacement == TOP || tabPlacement == BOTTOM)
1407: {
1408: if (index > 0)
1409: {
1410: w += rects[index - 1].x + rects[index - 1].width;
1411: if (index > selectedIndex)
1412: w -= insets.left + insets.right;
1413: }
1414: }
1415:
1416: else
1417: {
1418: if (index > 0)
1419: {
1420: h += rects[index - 1].y + rects[index - 1].height;
1421: if (index > selectedIndex)
1422: h -= insets.top + insets.bottom;
1423: }
1424: }
1425:
1426: Point p = new Point(w, h);
1427: return p;
1428: }
1429:
1430:
1437: public static ComponentUI createUI(JComponent c)
1438: {
1439: return new BasicTabbedPaneUI();
1440: }
1441:
1442:
1447: public void installUI(JComponent c)
1448: {
1449: super.installUI(c);
1450: if (c instanceof JTabbedPane)
1451: {
1452: tabPane = (JTabbedPane) c;
1453:
1454: installComponents();
1455: installDefaults();
1456: installListeners();
1457: installKeyboardActions();
1458:
1459: layoutManager = createLayoutManager();
1460: tabPane.setLayout(layoutManager);
1461: }
1462: }
1463:
1464:
1469: public void uninstallUI(JComponent c)
1470: {
1471: layoutManager = null;
1472:
1473: uninstallKeyboardActions();
1474: uninstallListeners();
1475: uninstallDefaults();
1476: uninstallComponents();
1477:
1478: tabPane = null;
1479: }
1480:
1481:
1489: protected LayoutManager createLayoutManager()
1490: {
1491: if (tabPane.getTabLayoutPolicy() == JTabbedPane.WRAP_TAB_LAYOUT)
1492: return new TabbedPaneLayout();
1493: else
1494: {
1495: incrButton = createIncreaseButton();
1496: decrButton = createDecreaseButton();
1497: viewport = new ScrollingViewport();
1498: viewport.setLayout(null);
1499: panel = new ScrollingPanel();
1500: viewport.setView(panel);
1501: tabPane.add(incrButton);
1502: tabPane.add(decrButton);
1503: tabPane.add(viewport);
1504: currentScrollLocation = 0;
1505: decrButton.setEnabled(false);
1506: panel.addMouseListener(mouseListener);
1507: incrButton.addMouseListener(mouseListener);
1508: decrButton.addMouseListener(mouseListener);
1509: viewport.setBackground(Color.LIGHT_GRAY);
1510:
1511: return new TabbedPaneScrollLayout();
1512: }
1513: }
1514:
1515:
1518: protected void installComponents()
1519: {
1520:
1521: }
1522:
1523:
1526: protected void uninstallComponents()
1527: {
1528:
1529: }
1530:
1531:
1534: protected void installDefaults()
1535: {
1536: LookAndFeel.installColorsAndFont(tabPane, "TabbedPane.background",
1537: "TabbedPane.foreground",
1538: "TabbedPane.font");
1539: tabPane.setOpaque(false);
1540:
1541: highlight = UIManager.getColor("TabbedPane.highlight");
1542: lightHighlight = UIManager.getColor("TabbedPane.lightHighlight");
1543:
1544: shadow = UIManager.getColor("TabbedPane.shadow");
1545: darkShadow = UIManager.getColor("TabbedPane.darkShadow");
1546:
1547: focus = UIManager.getColor("TabbedPane.focus");
1548:
1549: textIconGap = UIManager.getInt("TabbedPane.textIconGap");
1550: tabRunOverlay = UIManager.getInt("TabbedPane.tabRunOverlay");
1551:
1552: tabInsets = UIManager.getInsets("TabbedPane.tabInsets");
1553: selectedTabPadInsets = UIManager.getInsets("TabbedPane.tabbedPaneTabPadInsets");
1554: tabAreaInsets = UIManager.getInsets("TabbedPane.tabAreaInsets");
1555: contentBorderInsets = UIManager.getInsets("TabbedPane.tabbedPaneContentBorderInsets");
1556:
1557: calcRect = new Rectangle();
1558: tabRuns = new int[10];
1559: tabAreaRect = new Rectangle();
1560: contentRect = new Rectangle();
1561: }
1562:
1563:
1566: protected void uninstallDefaults()
1567: {
1568: calcRect = null;
1569: tabAreaRect = null;
1570: contentRect = null;
1571: tabRuns = null;
1572:
1573: contentBorderInsets = null;
1574: tabAreaInsets = null;
1575: selectedTabPadInsets = null;
1576: tabInsets = null;
1577:
1578: focus = null;
1579: darkShadow = null;
1580: shadow = null;
1581: lightHighlight = null;
1582: highlight = null;
1583:
1584: tabPane.setBackground(null);
1585: tabPane.setForeground(null);
1586: tabPane.setFont(null);
1587: }
1588:
1589:
1592: protected void installListeners()
1593: {
1594: mouseListener = createMouseListener();
1595: tabChangeListener = createChangeListener();
1596: propertyChangeListener = createPropertyChangeListener();
1597: focusListener = createFocusListener();
1598:
1599: tabPane.addMouseListener(mouseListener);
1600: tabPane.addChangeListener(tabChangeListener);
1601: tabPane.addPropertyChangeListener(propertyChangeListener);
1602: tabPane.addFocusListener(focusListener);
1603: }
1604:
1605:
1608: protected void uninstallListeners()
1609: {
1610: tabPane.removeFocusListener(focusListener);
1611: tabPane.removePropertyChangeListener(propertyChangeListener);
1612: tabPane.removeChangeListener(tabChangeListener);
1613: tabPane.removeMouseListener(mouseListener);
1614:
1615: focusListener = null;
1616: propertyChangeListener = null;
1617: tabChangeListener = null;
1618: mouseListener = null;
1619: }
1620:
1621:
1626: protected MouseListener createMouseListener()
1627: {
1628: return new MouseHandler();
1629: }
1630:
1631:
1636: protected FocusListener createFocusListener()
1637: {
1638: return new FocusHandler();
1639: }
1640:
1641:
1646: protected ChangeListener createChangeListener()
1647: {
1648: return new TabSelectionHandler();
1649: }
1650:
1651:
1656: protected PropertyChangeListener createPropertyChangeListener()
1657: {
1658: return new PropertyChangeHandler();
1659: }
1660:
1661:
1664: protected void installKeyboardActions()
1665: {
1666:
1667: }
1668:
1669:
1672: protected void uninstallKeyboardActions()
1673: {
1674:
1675: }
1676:
1677:
1684: public Dimension getMinimumSize(JComponent c)
1685: {
1686: return layoutManager.minimumLayoutSize(tabPane);
1687: }
1688:
1689:
1696: public Dimension getMaximumSize(JComponent c)
1697: {
1698: return new Dimension(Short.MAX_VALUE, Short.MAX_VALUE);
1699: }
1700:
1701:
1707: public void paint(Graphics g, JComponent c)
1708: {
1709: if (tabPane.getTabCount() == 0)
1710: return;
1711: if (tabPane.getTabLayoutPolicy() == JTabbedPane.WRAP_TAB_LAYOUT)
1712: paintTabArea(g, tabPane.getTabPlacement(), tabPane.getSelectedIndex());
1713: paintContentBorder(g, tabPane.getTabPlacement(), tabPane.getSelectedIndex());
1714: }
1715:
1716:
1724: protected void paintTabArea(Graphics g, int tabPlacement, int selectedIndex)
1725: {
1726: Rectangle ir = new Rectangle();
1727: Rectangle tr = new Rectangle();
1728:
1729: boolean isScroll = tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT;
1730:
1731:
1732:
1733: int tabCount = tabPane.getTabCount();
1734: int currRun = 1;
1735:
1736: if (tabCount > runCount)
1737: runCount = tabCount;
1738:
1739: if (tabCount < 1)
1740: return;
1741:
1742: if (runCount > 1)
1743: currRun = 0;
1744: for (int i = 0; i < runCount; i++)
1745: {
1746: int first = lastTabInRun(tabCount, getPreviousTabRun(currRun)) + 1;
1747: if (isScroll)
1748: first = currentScrollLocation;
1749: else if (first == tabCount)
1750: first = 0;
1751: int last = lastTabInRun(tabCount, currRun);
1752: if (isScroll)
1753: {
1754: for (int k = first; k < tabCount; k++)
1755: {
1756: if (rects[k].x + rects[k].width - rects[first].x > viewport
1757: .getWidth())
1758: {
1759: last = k;
1760: break;
1761: }
1762: }
1763: }
1764:
1765: for (int j = first; j <= last; j++)
1766: {
1767: if (j != selectedIndex || isScroll)
1768: paintTab(g, tabPlacement, rects, j, ir, tr);
1769: }
1770: currRun = getPreviousTabRun(currRun);
1771: }
1772: if (! isScroll)
1773: paintTab(g, tabPlacement, rects, selectedIndex, ir, tr);
1774: }
1775:
1776:
1787: protected void paintTab(Graphics g, int tabPlacement, Rectangle[] rects,
1788: int tabIndex, Rectangle iconRect, Rectangle textRect)
1789: {
1790: FontMetrics fm = getFontMetrics();
1791: Icon icon = getIconForTab(tabIndex);
1792: String title = tabPane.getTitleAt(tabIndex);
1793: boolean isSelected = tabIndex == tabPane.getSelectedIndex();
1794: calcRect = getTabBounds(tabPane, tabIndex);
1795:
1796: int x = calcRect.x;
1797: int y = calcRect.y;
1798: int w = calcRect.width;
1799: int h = calcRect.height;
1800: if (getRunForTab(tabPane.getTabCount(), tabIndex) == 1)
1801: {
1802: Insets insets = getTabAreaInsets(tabPlacement);
1803: switch (tabPlacement)
1804: {
1805: case TOP:
1806: h += insets.bottom;
1807: break;
1808: case LEFT:
1809: w += insets.right;
1810: break;
1811: case BOTTOM:
1812: y -= insets.top;
1813: h += insets.top;
1814: break;
1815: case RIGHT:
1816: x -= insets.left;
1817: w += insets.left;
1818: break;
1819: }
1820: }
1821:
1822: layoutLabel(tabPlacement, fm, tabIndex, title, icon, calcRect, iconRect,
1823: textRect, isSelected);
1824: paintTabBackground(g, tabPlacement, tabIndex, x, y, w, h, isSelected);
1825: paintTabBorder(g, tabPlacement, tabIndex, x, y, w, h, isSelected);
1826:
1827:
1828: if (icon != null)
1829: paintIcon(g, tabPlacement, tabIndex, icon, iconRect, isSelected);
1830: if (title != null && ! title.equals(""))
1831: paintText(g, tabPlacement, tabPane.getFont(), fm, tabIndex, title,
1832: textRect, isSelected);
1833: }
1834:
1835:
1849: protected void layoutLabel(int tabPlacement, FontMetrics metrics,
1850: int tabIndex, String title, Icon icon,
1851: Rectangle tabRect, Rectangle iconRect,
1852: Rectangle textRect, boolean isSelected)
1853: {
1854: SwingUtilities.layoutCompoundLabel(metrics, title, icon,
1855: SwingConstants.CENTER,
1856: SwingConstants.CENTER,
1857: SwingConstants.CENTER,
1858: SwingConstants.RIGHT, tabRect,
1859: iconRect, textRect, textIconGap);
1860:
1861: int shiftX = getTabLabelShiftX(tabPlacement, tabIndex, isSelected);
1862: int shiftY = getTabLabelShiftY(tabPlacement, tabIndex, isSelected);
1863:
1864: iconRect.x += shiftX;
1865: iconRect.y += shiftY;
1866:
1867: textRect.x += shiftX;
1868: textRect.y += shiftY;
1869: }
1870:
1871:
1881: protected void paintIcon(Graphics g, int tabPlacement, int tabIndex,
1882: Icon icon, Rectangle iconRect, boolean isSelected)
1883: {
1884: if (icon != null)
1885: icon.paintIcon(tabPane, g, iconRect.x, iconRect.y);
1886: }
1887:
1888:
1900: protected void paintText(Graphics g, int tabPlacement, Font font,
1901: FontMetrics metrics, int tabIndex, String title,
1902: Rectangle textRect, boolean isSelected)
1903: {
1904: View textView = getTextViewForTab(tabIndex);
1905: if (textView != null)
1906: {
1907: textView.paint(g, textRect);
1908: return;
1909: }
1910:
1911: Color fg = tabPane.getForegroundAt(tabIndex);
1912: if (fg == null)
1913: fg = tabPane.getForeground();
1914: Color bg = tabPane.getBackgroundAt(tabIndex);
1915: if (bg == null)
1916: bg = tabPane.getBackground();
1917:
1918: Color saved_color = g.getColor();
1919: Font f = g.getFont();
1920: g.setFont(font);
1921:
1922: if (tabPane.isEnabledAt(tabIndex))
1923: {
1924: g.setColor(fg);
1925:
1926: int mnemIndex = tabPane.getDisplayedMnemonicIndexAt(tabIndex);
1927:
1928: if (mnemIndex != -1)
1929: BasicGraphicsUtils.drawStringUnderlineCharAt(g, title, mnemIndex,
1930: textRect.x,
1931: textRect.y
1932: + metrics.getAscent());
1933: else
1934: g.drawString(title, textRect.x, textRect.y + metrics.getAscent());
1935: }
1936: else
1937: {
1938: g.setColor(bg.brighter());
1939:
1940: int mnemIndex = tabPane.getDisplayedMnemonicIndexAt(tabIndex);
1941:
1942: if (mnemIndex != -1)
1943: BasicGraphicsUtils.drawStringUnderlineCharAt(g, title, mnemIndex,
1944: textRect.x, textRect.y);
1945: else
1946: g.drawString(title, textRect.x, textRect.y);
1947:
1948: g.setColor(bg.darker());
1949: if (mnemIndex != -1)
1950: BasicGraphicsUtils.drawStringUnderlineCharAt(g, title, mnemIndex,
1951: textRect.x + 1,
1952: textRect.y + 1);
1953: else
1954: g.drawString(title, textRect.x + 1, textRect.y + 1);
1955: }
1956:
1957: g.setColor(saved_color);
1958: g.setFont(f);
1959: }
1960:
1961:
1971: protected int getTabLabelShiftX(int tabPlacement, int tabIndex,
1972: boolean isSelected)
1973: {
1974:
1975: return 0;
1976: }
1977:
1978:
1988: protected int getTabLabelShiftY(int tabPlacement, int tabIndex,
1989: boolean isSelected)
1990: {
1991:
1992: return 0;
1993: }
1994:
1995:
2006: protected void paintFocusIndicator(Graphics g, int tabPlacement,
2007: Rectangle[] rects, int tabIndex,
2008: Rectangle iconRect, Rectangle textRect,
2009: boolean isSelected)
2010: {
2011: Color saved = g.getColor();
2012: calcRect = iconRect.union(textRect);
2013:
2014: g.setColor(focus);
2015:
2016: g.drawRect(calcRect.x, calcRect.y, calcRect.width, calcRect.height);
2017:
2018: g.setColor(saved);
2019: }
2020:
2021:
2033: protected void paintTabBorder(Graphics g, int tabPlacement, int tabIndex,
2034: int x, int y, int w, int h, boolean isSelected)
2035: {
2036: Color saved = g.getColor();
2037:
2038: if (! isSelected || tabPlacement != SwingConstants.TOP)
2039: {
2040: g.setColor(shadow);
2041: g.drawLine(x + 1, y + h - 1, x + w - 1, y + h - 1);
2042: g.setColor(darkShadow);
2043: g.drawLine(x, y + h, x + w, y + h);
2044: }
2045:
2046: if (! isSelected || tabPlacement != SwingConstants.LEFT)
2047: {
2048: g.setColor(darkShadow);
2049: g.drawLine(x + w, y, x + w, y + h);
2050: g.setColor(shadow);
2051: g.drawLine(x + w - 1, y + 1, x + w - 1, y + h - 1);
2052: }
2053:
2054: if (! isSelected || tabPlacement != SwingConstants.RIGHT)
2055: {
2056: g.setColor(lightHighlight);
2057: g.drawLine(x, y, x, y + h);
2058: }
2059:
2060: if (! isSelected || tabPlacement != SwingConstants.BOTTOM)
2061: {
2062: g.setColor(lightHighlight);
2063: g.drawLine(x, y, x + w, y);
2064: }
2065:
2066: g.setColor(saved);
2067: }
2068:
2069:
2081: protected void paintTabBackground(Graphics g, int tabPlacement,
2082: int tabIndex, int x, int y, int w, int h,
2083: boolean isSelected)
2084: {
2085: Color saved = g.getColor();
2086: if (isSelected)
2087: g.setColor(Color.LIGHT_GRAY);
2088: else
2089: {
2090: Color bg = tabPane.getBackgroundAt(tabIndex);
2091: if (bg == null)
2092: bg = Color.GRAY;
2093: g.setColor(bg);
2094: }
2095:
2096: g.fillRect(x, y, w, h);
2097:
2098: g.setColor(saved);
2099: }
2100:
2101:
2108: protected void paintContentBorder(Graphics g, int tabPlacement,
2109: int selectedIndex)
2110: {
2111: int x = contentRect.x;
2112: int y = contentRect.y;
2113: int w = contentRect.width;
2114: int h = contentRect.height;
2115: paintContentBorderTopEdge(g, tabPlacement, selectedIndex, x, y, w, h);
2116: paintContentBorderLeftEdge(g, tabPlacement, selectedIndex, x, y, w, h);
2117: paintContentBorderBottomEdge(g, tabPlacement, selectedIndex, x, y, w, h);
2118: paintContentBorderRightEdge(g, tabPlacement, selectedIndex, x, y, w, h);
2119: }
2120:
2121:
2132: protected void paintContentBorderTopEdge(Graphics g, int tabPlacement,
2133: int selectedIndex, int x, int y,
2134: int w, int h)
2135: {
2136: Color saved = g.getColor();
2137: g.setColor(lightHighlight);
2138:
2139: int startgap = rects[selectedIndex].x;
2140: int endgap = rects[selectedIndex].x + rects[selectedIndex].width;
2141:
2142: int diff = 0;
2143:
2144: if (tabPlacement == SwingConstants.TOP)
2145: {
2146: if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT)
2147: {
2148: Point p = findPointForIndex(currentScrollLocation);
2149: diff = p.x;
2150: }
2151:
2152: g.drawLine(x, y, startgap - diff, y);
2153: g.drawLine(endgap - diff, y, x + w, y);
2154: }
2155: else
2156: g.drawLine(x, y, x + w, y);
2157:
2158: g.setColor(saved);
2159: }
2160:
2161:
2172: protected void paintContentBorderLeftEdge(Graphics g, int tabPlacement,
2173: int selectedIndex, int x, int y,
2174: int w, int h)
2175: {
2176: Color saved = g.getColor();
2177: g.setColor(lightHighlight);
2178:
2179: int startgap = rects[selectedIndex].y;
2180: int endgap = rects[selectedIndex].y + rects[selectedIndex].height;
2181:
2182: int diff = 0;
2183:
2184: if (tabPlacement == SwingConstants.LEFT)
2185: {
2186: if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT)
2187: {
2188: Point p = findPointForIndex(currentScrollLocation);
2189: diff = p.y;
2190: }
2191:
2192: g.drawLine(x, y, x, startgap - diff);
2193: g.drawLine(x, endgap - diff, x, y + h);
2194: }
2195: else
2196: g.drawLine(x, y, x, y + h);
2197:
2198: g.setColor(saved);
2199: }
2200:
2201:
2212: protected void paintContentBorderBottomEdge(Graphics g, int tabPlacement,
2213: int selectedIndex, int x, int y,
2214: int w, int h)
2215: {
2216: Color saved = g.getColor();
2217:
2218: int startgap = rects[selectedIndex].x;
2219: int endgap = rects[selectedIndex].x + rects[selectedIndex].width;
2220:
2221: int diff = 0;
2222:
2223: if (tabPlacement == SwingConstants.BOTTOM)
2224: {
2225: if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT)
2226: {
2227: Point p = findPointForIndex(currentScrollLocation);
2228: diff = p.x;
2229: }
2230:
2231: g.setColor(shadow);
2232: g.drawLine(x + 1, y + h - 1, startgap - diff, y + h - 1);
2233: g.drawLine(endgap - diff, y + h - 1, x + w - 1, y + h - 1);
2234:
2235: g.setColor(darkShadow);
2236: g.drawLine(x, y + h, startgap - diff, y + h);
2237: g.drawLine(endgap - diff, y + h, x + w, y + h);
2238: }
2239: else
2240: {
2241: g.setColor(shadow);
2242: g.drawLine(x + 1, y + h - 1, x + w - 1, y + h - 1);
2243: g.setColor(darkShadow);
2244: g.drawLine(x, y + h, x + w, y + h);
2245: }
2246:
2247: g.setColor(saved);
2248: }
2249:
2250:
2261: protected void paintContentBorderRightEdge(Graphics g, int tabPlacement,
2262: int selectedIndex, int x, int y,
2263: int w, int h)
2264: {
2265: Color saved = g.getColor();
2266: int startgap = rects[selectedIndex].y;
2267: int endgap = rects[selectedIndex].y + rects[selectedIndex].height;
2268:
2269: int diff = 0;
2270:
2271: if (tabPlacement == SwingConstants.RIGHT)
2272: {
2273: if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT)
2274: {
2275: Point p = findPointForIndex(currentScrollLocation);
2276: diff = p.y;
2277: }
2278:
2279: g.setColor(shadow);
2280: g.drawLine(x + w - 1, y + 1, x + w - 1, startgap - diff);
2281: g.drawLine(x + w - 1, endgap - diff, x + w - 1, y + h - 1);
2282:
2283: g.setColor(darkShadow);
2284: g.drawLine(x + w, y, x + w, startgap - diff);
2285: g.drawLine(x + w, endgap - diff, x + w, y + h);
2286: }
2287: else
2288: {
2289: g.setColor(shadow);
2290: g.drawLine(x + w - 1, y + 1, x + w - 1, y + h - 1);
2291: g.setColor(darkShadow);
2292: g.drawLine(x + w, y, x + w, y + h);
2293: }
2294:
2295: g.setColor(saved);
2296: }
2297:
2298:
2306: public Rectangle getTabBounds(JTabbedPane pane, int i)
2307: {
2308: return rects[i];
2309: }
2310:
2311:
2318: public int getTabRunCount(JTabbedPane pane)
2319: {
2320: return runCount;
2321: }
2322:
2323:
2332: public int tabForCoordinate(JTabbedPane pane, int x, int y)
2333: {
2334: Point p = new Point(x, y);
2335: int tabCount = tabPane.getTabCount();
2336: int currRun = 1;
2337: for (int i = 0; i < runCount; i++)
2338: {
2339: int first = lastTabInRun(tabCount, getPreviousTabRun(currRun)) + 1;
2340: if (first == tabCount)
2341: first = 0;
2342: int last = lastTabInRun(tabCount, currRun);
2343: for (int j = first; j <= last; j++)
2344: {
2345: if (getTabBounds(pane, j).contains(p))
2346: return j;
2347: }
2348: currRun = getNextTabRun(currRun);
2349: }
2350: return -1;
2351: }
2352:
2353:
2361: protected Rectangle getTabBounds(int tabIndex, Rectangle dest)
2362: {
2363: dest.setBounds(getTabBounds(tabPane, tabIndex));
2364: return dest;
2365: }
2366:
2367:
2372: protected Component getVisibleComponent()
2373: {
2374: return tabPane.getComponentAt(tabPane.getSelectedIndex());
2375: }
2376:
2377:
2382: protected void setVisibleComponent(Component component)
2383: {
2384: component.setVisible(true);
2385: tabPane.setSelectedComponent(component);
2386: }
2387:
2388:
2394: protected void assureRectsCreated(int tabCount)
2395: {
2396: if (rects.length < tabCount)
2397: {
2398: Rectangle[] old = rects;
2399: rects = new Rectangle[tabCount];
2400: System.arraycopy(old, 0, rects, 0, old.length);
2401: for (int i = old.length; i < rects.length; i++)
2402: rects[i] = new Rectangle();
2403: }
2404: }
2405:
2406:
2410: protected void expandTabRunsArray()
2411: {
2412:
2413: if (tabRuns == null)
2414: tabRuns = new int[10];
2415: else
2416: {
2417: int[] newRuns = new int[tabRuns.length + 10];
2418: System.arraycopy(tabRuns, 0, newRuns, 0, tabRuns.length);
2419: tabRuns = newRuns;
2420: }
2421: }
2422:
2423:
2431: protected int getRunForTab(int tabCount, int tabIndex)
2432: {
2433: if (runCount == 1 && tabIndex < tabCount && tabIndex >= 0)
2434: return 1;
2435: for (int i = 0; i < runCount; i++)
2436: {
2437: int first = lastTabInRun(tabCount, getPreviousTabRun(i)) + 1;
2438: if (first == tabCount)
2439: first = 0;
2440: int last = lastTabInRun(tabCount, i);
2441: if (last >= tabIndex && first <= tabIndex)
2442: return i;
2443: }
2444: return -1;
2445: }
2446:
2447:
2455: protected int lastTabInRun(int tabCount, int run)
2456: {
2457: if (tabRuns[run] == 0)
2458: return tabCount - 1;
2459: else
2460: return tabRuns[run] - 1;
2461: }
2462:
2463:
2470: protected int getTabRunOverlay(int tabPlacement)
2471: {
2472: return tabRunOverlay;
2473: }
2474:
2475:
2484: protected int getTabRunIndent(int tabPlacement, int run)
2485: {
2486: return 0;
2487: }
2488:
2489:
2497: protected boolean shouldPadTabRun(int tabPlacement, int run)
2498: {
2499: return true;
2500: }
2501:
2502:
2509: protected boolean shouldRotateTabRuns(int tabPlacement)
2510: {
2511: return true;
2512: }
2513:
2514:
2523: protected Icon getIconForTab(int tabIndex)
2524: {
2525: if (tabPane.isEnabledAt(tabIndex))
2526: return tabPane.getIconAt(tabIndex);
2527: else
2528: return tabPane.getDisabledIconAt(tabIndex);
2529: }
2530:
2531:
2538: protected View getTextViewForTab(int tabIndex)
2539: {
2540: return null;
2541: }
2542:
2543:
2553: protected int calculateTabHeight(int tabPlacement, int tabIndex,
2554: int fontHeight)
2555: {
2556: Icon icon = getIconForTab(tabIndex);
2557: Insets insets = getTabInsets(tabPlacement, tabIndex);
2558:
2559: int height = 0;
2560: if (icon != null)
2561: {
2562: Rectangle vr = new Rectangle();
2563: Rectangle ir = new Rectangle();
2564: Rectangle tr = new Rectangle();
2565: layoutLabel(tabPlacement, getFontMetrics(), tabIndex,
2566: tabPane.getTitleAt(tabIndex), icon, vr, ir, tr,
2567: tabIndex == tabPane.getSelectedIndex());
2568: height = tr.union(ir).height;
2569: }
2570: else
2571: height = fontHeight;
2572:
2573: height += insets.top + insets.bottom;
2574: return height;
2575: }
2576:
2577:
2584: protected int calculateMaxTabHeight(int tabPlacement)
2585: {
2586: maxTabHeight = 0;
2587:
2588: FontMetrics fm = getFontMetrics();
2589: int fontHeight = fm.getHeight();
2590:
2591: for (int i = 0; i < tabPane.getTabCount(); i++)
2592: maxTabHeight = Math.max(calculateTabHeight(tabPlacement, i, fontHeight),
2593: maxTabHeight);
2594:
2595: return maxTabHeight;
2596: }
2597:
2598:
2608: protected int calculateTabWidth(int tabPlacement, int tabIndex,
2609: FontMetrics metrics)
2610: {
2611: Icon icon = getIconForTab(tabIndex);
2612: Insets insets = getTabInsets(tabPlacement, tabIndex);
2613:
2614: int width = 0;
2615: if (icon != null)
2616: {
2617: Rectangle vr = new Rectangle();
2618: Rectangle ir = new Rectangle();
2619: Rectangle tr = new Rectangle();
2620: layoutLabel(tabPlacement, getFontMetrics(), tabIndex,
2621: tabPane.getTitleAt(tabIndex), icon, vr, ir, tr,
2622: tabIndex == tabPane.getSelectedIndex());
2623: width = tr.union(ir).width;
2624: }
2625: else
2626: width = metrics.stringWidth(tabPane.getTitleAt(tabIndex));
2627:
2628: width += insets.left + insets.right;
2629: return width;
2630: }
2631:
2632:
2639: protected int calculateMaxTabWidth(int tabPlacement)
2640: {
2641: maxTabWidth = 0;
2642:
2643: FontMetrics fm = getFontMetrics();
2644:
2645: for (int i = 0; i < tabPane.getTabCount(); i++)
2646: maxTabWidth = Math.max(calculateTabWidth(tabPlacement, i, fm),
2647: maxTabWidth);
2648:
2649: return maxTabWidth;
2650: }
2651:
2652:
2662: protected int calculateTabAreaHeight(int tabPlacement, int horizRunCount,
2663: int maxTabHeight)
2664: {
2665: Insets insets = getTabAreaInsets(tabPlacement);
2666: int tabAreaHeight = horizRunCount * maxTabHeight
2667: - (horizRunCount - 1) * tabRunOverlay;
2668:
2669: tabAreaHeight += insets.top + insets.bottom;
2670:
2671: return tabAreaHeight;
2672: }
2673:
2674:
2684: protected int calculateTabAreaWidth(int tabPlacement, int vertRunCount,
2685: int maxTabWidth)
2686: {
2687: Insets insets = getTabAreaInsets(tabPlacement);
2688: int tabAreaWidth = vertRunCount * maxTabWidth
2689: - (vertRunCount - 1) * tabRunOverlay;
2690:
2691: tabAreaWidth += insets.left + insets.right;
2692:
2693: return tabAreaWidth;
2694: }
2695:
2696:
2704: protected Insets getTabInsets(int tabPlacement, int tabIndex)
2705: {
2706: Insets target = new Insets(0, 0, 0, 0);
2707: rotateInsets(tabInsets, target, tabPlacement);
2708: return target;
2709: }
2710:
2711:
2718: protected Insets getSelectedTabPadInsets(int tabPlacement)
2719: {
2720: Insets target = new Insets(0, 0, 0, 0);
2721: rotateInsets(selectedTabPadInsets, target, tabPlacement);
2722: return target;
2723: }
2724:
2725:
2732: protected Insets getTabAreaInsets(int tabPlacement)
2733: {
2734: Insets target = new Insets(0, 0, 0, 0);
2735: rotateInsets(tabAreaInsets, target, tabPlacement);
2736: return target;
2737: }
2738:
2739:
2746: protected Insets getContentBorderInsets(int tabPlacement)
2747: {
2748: Insets target = new Insets(0, 0, 0, 0);
2749: rotateInsets(contentBorderInsets, target, tabPlacement);
2750: return target;
2751: }
2752:
2753:
2758: protected FontMetrics getFontMetrics()
2759: {
2760: FontMetrics fm = tabPane.getFontMetrics(tabPane.getFont());
2761: return fm;
2762: }
2763:
2764:
2770: protected void navigateSelectedTab(int direction)
2771: {
2772: int tabPlacement = tabPane.getTabPlacement();
2773: if (tabPlacement == SwingConstants.TOP
2774: || tabPlacement == SwingConstants.BOTTOM)
2775: {
2776: if (direction == SwingConstants.WEST)
2777: selectPreviousTabInRun(tabPane.getSelectedIndex());
2778: else if (direction == SwingConstants.EAST)
2779: selectNextTabInRun(tabPane.getSelectedIndex());
2780:
2781: else
2782: {
2783: int offset = getTabRunOffset(tabPlacement, tabPane.getTabCount(),
2784: tabPane.getSelectedIndex(),
2785: (tabPlacement == SwingConstants.RIGHT)
2786: ? true : false);
2787: selectAdjacentRunTab(tabPlacement, tabPane.getSelectedIndex(),
2788: offset);
2789: }
2790: }
2791: if (tabPlacement == SwingConstants.LEFT
2792: || tabPlacement == SwingConstants.RIGHT)
2793: {
2794: if (direction == SwingConstants.NORTH)
2795: selectPreviousTabInRun(tabPane.getSelectedIndex());
2796: else if (direction == SwingConstants.SOUTH)
2797: selectNextTabInRun(tabPane.getSelectedIndex());
2798: else
2799: {
2800: int offset = getTabRunOffset(tabPlacement, tabPane.getTabCount(),
2801: tabPane.getSelectedIndex(),
2802: (tabPlacement == SwingConstants.RIGHT)
2803: ? true : false);
2804: selectAdjacentRunTab(tabPlacement, tabPane.getSelectedIndex(),
2805: offset);
2806: }
2807: }
2808: }
2809:
2810:
2815: protected void selectNextTabInRun(int current)
2816: {
2817: tabPane.setSelectedIndex(getNextTabIndexInRun(tabPane.getTabCount(),
2818: current));
2819: }
2820:
2821:
2826: protected void selectPreviousTabInRun(int current)
2827: {
2828: tabPane.setSelectedIndex(getPreviousTabIndexInRun(tabPane.getTabCount(),
2829: current));
2830: }
2831:
2832:
2837: protected void selectNextTab(int current)
2838: {
2839: tabPane.setSelectedIndex(getNextTabIndex(current));
2840: }
2841:
2842:
2847: protected void selectPreviousTab(int current)
2848: {
2849: tabPane.setSelectedIndex(getPreviousTabIndex(current));
2850: }
2851:
2852:
2863: protected void selectAdjacentRunTab(int tabPlacement, int tabIndex,
2864: int offset)
2865: {
2866: int x = rects[tabIndex].x + rects[tabIndex].width / 2;
2867: int y = rects[tabIndex].y + rects[tabIndex].height / 2;
2868:
2869: switch (tabPlacement)
2870: {
2871: case SwingConstants.TOP:
2872: case SwingConstants.BOTTOM:
2873: y += offset;
2874: break;
2875: case SwingConstants.RIGHT:
2876: case SwingConstants.LEFT:
2877: x += offset;
2878: break;
2879: }
2880:
2881: int index = tabForCoordinate(tabPane, x, y);
2882: if (index != -1)
2883: tabPane.setSelectedIndex(index);
2884: }
2885:
2886:
2887:
2888:
2889:
2890:
2891:
2892:
2907: protected int getTabRunOffset(int tabPlacement, int tabCount, int tabIndex,
2908: boolean forward)
2909: {
2910: int currRun = getRunForTab(tabCount, tabIndex);
2911: int offset;
2912: int nextRun = (forward) ? getNextTabRun(currRun) : getPreviousTabRun(currRun);
2913: if (tabPlacement == SwingConstants.TOP
2914: || tabPlacement == SwingConstants.BOTTOM)
2915: offset = rects[lastTabInRun(tabCount, nextRun)].y
2916: - rects[lastTabInRun(tabCount, currRun)].y;
2917: else
2918: offset = rects[lastTabInRun(tabCount, nextRun)].x
2919: - rects[lastTabInRun(tabCount, currRun)].x;
2920: return offset;
2921: }
2922:
2923:
2930: protected int getPreviousTabIndex(int base)
2931: {
2932: base--;
2933: if (base < 0)
2934: return tabPane.getTabCount() - 1;
2935: return base;
2936: }
2937:
2938:
2945: protected int getNextTabIndex(int base)
2946: {
2947: base++;
2948: if (base == tabPane.getTabCount())
2949: return 0;
2950: return base;
2951: }
2952:
2953:
2962: protected int getNextTabIndexInRun(int tabCount, int base)
2963: {
2964: int index = getNextTabIndex(base);
2965: int run = getRunForTab(tabCount, base);
2966: if (index == lastTabInRun(tabCount, run) + 1)
2967: index = lastTabInRun(tabCount, getPreviousTabRun(run)) + 1;
2968: return getNextTabIndex(base);
2969: }
2970:
2971:
2980: protected int getPreviousTabIndexInRun(int tabCount, int base)
2981: {
2982: int index = getPreviousTabIndex(base);
2983: int run = getRunForTab(tabCount, base);
2984: if (index == lastTabInRun(tabCount, getPreviousTabRun(run)))
2985: index = lastTabInRun(tabCount, run);
2986: return getPreviousTabIndex(base);
2987: }
2988:
2989:
2996: protected int getPreviousTabRun(int baseRun)
2997: {
2998: if (getTabRunCount(tabPane) == 1)
2999: return 1;
3000:
3001: int prevRun = --baseRun;
3002: if (prevRun < 0)
3003: prevRun = getTabRunCount(tabPane) - 1;
3004: return prevRun;
3005: }
3006:
3007:
3014: protected int getNextTabRun(int baseRun)
3015: {
3016: if (getTabRunCount(tabPane) == 1)
3017: return 1;
3018:
3019: int nextRun = ++baseRun;
3020: if (nextRun == getTabRunCount(tabPane))
3021: nextRun = 0;
3022: return nextRun;
3023: }
3024:
3025:
3037: protected static void rotateInsets(Insets topInsets, Insets targetInsets,
3038: int targetPlacement)
3039: {
3040:
3041:
3042: switch (targetPlacement)
3043: {
3044: case SwingConstants.TOP:
3045: targetInsets.top = topInsets.top;
3046: targetInsets.left = topInsets.left;
3047: targetInsets.right = topInsets.right;
3048: targetInsets.bottom = topInsets.bottom;
3049: break;
3050: case SwingConstants.LEFT:
3051: targetInsets.left = topInsets.top;
3052: targetInsets.top = topInsets.left;
3053: targetInsets.right = topInsets.bottom;
3054: targetInsets.bottom = topInsets.right;
3055: break;
3056: case SwingConstants.BOTTOM:
3057: targetInsets.top = topInsets.bottom;
3058: targetInsets.bottom = topInsets.top;
3059: targetInsets.left = topInsets.left;
3060: targetInsets.right = topInsets.right;
3061: break;
3062: case SwingConstants.RIGHT:
3063: targetInsets.top = topInsets.left;
3064: targetInsets.left = topInsets.bottom;
3065: targetInsets.bottom = topInsets.right;
3066: targetInsets.right = topInsets.top;
3067: break;
3068: }
3069: }
3070: }