191 /**
192 * Combined listeners.
193 */
194 private Handler handler;
195
196 /**
197 * Index of the tab the mouse is over.
198 */
199 private int rolloverTabIndex;
200
201 /**
202 * This is set to true when a component is added/removed from the tab
203 * pane and set to false when layout happens. If true it indicates that
204 * tabRuns is not valid and shouldn't be used.
205 */
206 private boolean isRunsDirty;
207
208 private boolean calculatedBaseline;
209 private int baseline;
210
211 // UI creation
212
213 /**
214 * Create a UI.
215 * @param c a component
216 * @return a UI
217 */
218 public static ComponentUI createUI(JComponent c) {
219 return new BasicTabbedPaneUI();
220 }
221
222 static void loadActionMap(LazyActionMap map) {
223 map.put(new Actions(Actions.NEXT));
224 map.put(new Actions(Actions.PREVIOUS));
225 map.put(new Actions(Actions.RIGHT));
226 map.put(new Actions(Actions.LEFT));
227 map.put(new Actions(Actions.UP));
228 map.put(new Actions(Actions.DOWN));
229 map.put(new Actions(Actions.PAGE_UP));
230 map.put(new Actions(Actions.PAGE_DOWN));
398 selectedTabPadInsets = UIManager.getInsets("TabbedPane.selectedTabPadInsets");
399 tabAreaInsets = UIManager.getInsets("TabbedPane.tabAreaInsets");
400 tabsOverlapBorder = UIManager.getBoolean("TabbedPane.tabsOverlapBorder");
401 contentBorderInsets = UIManager.getInsets("TabbedPane.contentBorderInsets");
402 tabRunOverlay = UIManager.getInt("TabbedPane.tabRunOverlay");
403 tabsOpaque = UIManager.getBoolean("TabbedPane.tabsOpaque");
404 contentOpaque = UIManager.getBoolean("TabbedPane.contentOpaque");
405 Object opaque = UIManager.get("TabbedPane.opaque");
406 if (opaque == null) {
407 opaque = Boolean.FALSE;
408 }
409 LookAndFeel.installProperty(tabPane, "opaque", opaque);
410
411 // Fix for 6711145 BasicTabbedPanuUI should not throw a NPE if these
412 // keys are missing. So we are setting them to there default values here
413 // if the keys are missing.
414 if (tabInsets == null) tabInsets = new Insets(0,4,1,4);
415 if (selectedTabPadInsets == null) selectedTabPadInsets = new Insets(2,2,2,1);
416 if (tabAreaInsets == null) tabAreaInsets = new Insets(3,2,0,2);
417 if (contentBorderInsets == null) contentBorderInsets = new Insets(2,2,3,3);
418 }
419
420 /**
421 * Uninstall the defaults.
422 */
423 protected void uninstallDefaults() {
424 highlight = null;
425 lightHighlight = null;
426 shadow = null;
427 darkShadow = null;
428 focus = null;
429 tabInsets = null;
430 selectedTabPadInsets = null;
431 tabAreaInsets = null;
432 contentBorderInsets = null;
433 }
434
435 /**
436 * Install the listeners.
437 */
438 protected void installListeners() {
439 if ((propertyChangeListener = createPropertyChangeListener()) != null) {
440 tabPane.addPropertyChangeListener(propertyChangeListener);
441 }
442 if ((tabChangeListener = createChangeListener()) != null) {
443 tabPane.addChangeListener(tabChangeListener);
444 }
445 if ((mouseListener = createMouseListener()) != null) {
446 tabPane.addMouseListener(mouseListener);
447 }
448 tabPane.addMouseMotionListener(getHandler());
449 if ((focusListener = createFocusListener()) != null) {
450 tabPane.addFocusListener(focusListener);
451 }
452 tabPane.addContainerListener(getHandler());
925 }
926
927 paintTabBorder(g, tabPlacement, tabIndex, tabRect.x, tabRect.y,
928 tabRect.width, tabRect.height, isSelected);
929
930 String title = tabPane.getTitleAt(tabIndex);
931 Font font = tabPane.getFont();
932 FontMetrics metrics = SwingUtilities2.getFontMetrics(tabPane, g, font);
933 Icon icon = getIconForTab(tabIndex);
934
935 layoutLabel(tabPlacement, metrics, tabIndex, title, icon,
936 tabRect, iconRect, textRect, isSelected);
937
938 if (tabPane.getTabComponentAt(tabIndex) == null) {
939 String clippedTitle = title;
940
941 if (scrollableTabLayoutEnabled() && tabScroller.croppedEdge.isParamsSet() &&
942 tabScroller.croppedEdge.getTabIndex() == tabIndex && isHorizontalTabPlacement()) {
943 int availTextWidth = tabScroller.croppedEdge.getCropline() -
944 (textRect.x - tabRect.x) - tabScroller.croppedEdge.getCroppedSideWidth();
945 clippedTitle = SwingUtilities2.clipStringIfNecessary(null, metrics, title, availTextWidth);
946 } else if (!scrollableTabLayoutEnabled() && isHorizontalTabPlacement()) {
947 clippedTitle = SwingUtilities2.clipStringIfNecessary(null, metrics, title, textRect.width);
948 }
949
950 paintText(g, tabPlacement, font, metrics,
951 tabIndex, clippedTitle, textRect, isSelected);
952
953 paintIcon(g, tabPlacement, tabIndex, icon, iconRect, isSelected);
954 }
955 paintFocusIndicator(g, tabPlacement, rects, tabIndex,
956 iconRect, textRect, isSelected);
957 }
958
959 private boolean isHorizontalTabPlacement() {
960 return tabPane.getTabPlacement() == TOP || tabPane.getTabPlacement() == BOTTOM;
961 }
962
963 /* This method will create and return a polygon shape for the given tab rectangle
964 * which has been cropped at the specified cropline with a torn edge visual.
965 * e.g. A "File" tab which has cropped been cropped just after the "i":
966 * -------------
967 * | ..... |
1161 g.setFont(font);
1162
1163 View v = getTextViewForTab(tabIndex);
1164 if (v != null) {
1165 // html
1166 v.paint(g, textRect);
1167 } else {
1168 // plain text
1169 int mnemIndex = tabPane.getDisplayedMnemonicIndexAt(tabIndex);
1170
1171 if (tabPane.isEnabled() && tabPane.isEnabledAt(tabIndex)) {
1172 Color fg = tabPane.getForegroundAt(tabIndex);
1173 if (isSelected && (fg instanceof UIResource)) {
1174 Color selectedFG = UIManager.getColor(
1175 "TabbedPane.selectedForeground");
1176 if (selectedFG != null) {
1177 fg = selectedFG;
1178 }
1179 }
1180 g.setColor(fg);
1181 SwingUtilities2.drawStringUnderlineCharAt(tabPane, g,
1182 title, mnemIndex,
1183 textRect.x, textRect.y + metrics.getAscent());
1184
1185 } else { // tab disabled
1186 g.setColor(tabPane.getBackgroundAt(tabIndex).brighter());
1187 SwingUtilities2.drawStringUnderlineCharAt(tabPane, g,
1188 title, mnemIndex,
1189 textRect.x, textRect.y + metrics.getAscent());
1190 g.setColor(tabPane.getBackgroundAt(tabIndex).darker());
1191 SwingUtilities2.drawStringUnderlineCharAt(tabPane, g,
1192 title, mnemIndex,
1193 textRect.x - 1, textRect.y + metrics.getAscent() - 1);
1194
1195 }
1196 }
1197 }
1198
1199 /**
1200 * Returns the tab label shift x.
1201 * @param tabPlacement the tab placement
1202 * @param tabIndex the tab index
1203 * @param isSelected selection status
1204 * @return the tab label shift x
1205 */
1206 protected int getTabLabelShiftX(int tabPlacement, int tabIndex, boolean isSelected) {
1207 Rectangle tabRect = rects[tabIndex];
1208 String propKey = (isSelected ? "selectedLabelShift" : "labelShift");
1209 int nudge = DefaultLookup.getInt(
1210 tabPane, this, "TabbedPane." + propKey, 1);
1211
2009 * @return the tab width
2010 */
2011 protected int calculateTabWidth(int tabPlacement, int tabIndex, FontMetrics metrics) {
2012 Insets tabInsets = getTabInsets(tabPlacement, tabIndex);
2013 int width = tabInsets.left + tabInsets.right + 3;
2014 Component tabComponent = tabPane.getTabComponentAt(tabIndex);
2015 if (tabComponent != null) {
2016 width += tabComponent.getPreferredSize().width;
2017 } else {
2018 Icon icon = getIconForTab(tabIndex);
2019 if (icon != null) {
2020 width += icon.getIconWidth() + textIconGap;
2021 }
2022 View v = getTextViewForTab(tabIndex);
2023 if (v != null) {
2024 // html
2025 width += (int) v.getPreferredSpan(View.X_AXIS);
2026 } else {
2027 // plain text
2028 String title = tabPane.getTitleAt(tabIndex);
2029 width += SwingUtilities2.stringWidth(tabPane, metrics, title);
2030 }
2031 }
2032 return width;
2033 }
2034
2035 /**
2036 * Calculates the maximum tab width.
2037 * @param tabPlacement the placement (left, right, bottom, top) of the tab
2038 * @return the maximum tab width
2039 */
2040 protected int calculateMaxTabWidth(int tabPlacement) {
2041 FontMetrics metrics = getFontMetrics();
2042 int tabCount = tabPane.getTabCount();
2043 int result = 0;
2044 for(int i = 0; i < tabCount; i++) {
2045 result = Math.max(calculateTabWidth(tabPlacement, i, metrics), result);
2046 }
2047 return result;
2048 }
2049
|
191 /**
192 * Combined listeners.
193 */
194 private Handler handler;
195
196 /**
197 * Index of the tab the mouse is over.
198 */
199 private int rolloverTabIndex;
200
201 /**
202 * This is set to true when a component is added/removed from the tab
203 * pane and set to false when layout happens. If true it indicates that
204 * tabRuns is not valid and shouldn't be used.
205 */
206 private boolean isRunsDirty;
207
208 private boolean calculatedBaseline;
209 private int baseline;
210
211 private TextUIDrawing textUIDrawing;
212
213 // UI creation
214
215 /**
216 * Create a UI.
217 * @param c a component
218 * @return a UI
219 */
220 public static ComponentUI createUI(JComponent c) {
221 return new BasicTabbedPaneUI();
222 }
223
224 static void loadActionMap(LazyActionMap map) {
225 map.put(new Actions(Actions.NEXT));
226 map.put(new Actions(Actions.PREVIOUS));
227 map.put(new Actions(Actions.RIGHT));
228 map.put(new Actions(Actions.LEFT));
229 map.put(new Actions(Actions.UP));
230 map.put(new Actions(Actions.DOWN));
231 map.put(new Actions(Actions.PAGE_UP));
232 map.put(new Actions(Actions.PAGE_DOWN));
400 selectedTabPadInsets = UIManager.getInsets("TabbedPane.selectedTabPadInsets");
401 tabAreaInsets = UIManager.getInsets("TabbedPane.tabAreaInsets");
402 tabsOverlapBorder = UIManager.getBoolean("TabbedPane.tabsOverlapBorder");
403 contentBorderInsets = UIManager.getInsets("TabbedPane.contentBorderInsets");
404 tabRunOverlay = UIManager.getInt("TabbedPane.tabRunOverlay");
405 tabsOpaque = UIManager.getBoolean("TabbedPane.tabsOpaque");
406 contentOpaque = UIManager.getBoolean("TabbedPane.contentOpaque");
407 Object opaque = UIManager.get("TabbedPane.opaque");
408 if (opaque == null) {
409 opaque = Boolean.FALSE;
410 }
411 LookAndFeel.installProperty(tabPane, "opaque", opaque);
412
413 // Fix for 6711145 BasicTabbedPanuUI should not throw a NPE if these
414 // keys are missing. So we are setting them to there default values here
415 // if the keys are missing.
416 if (tabInsets == null) tabInsets = new Insets(0,4,1,4);
417 if (selectedTabPadInsets == null) selectedTabPadInsets = new Insets(2,2,2,1);
418 if (tabAreaInsets == null) tabAreaInsets = new Insets(3,2,0,2);
419 if (contentBorderInsets == null) contentBorderInsets = new Insets(2,2,3,3);
420 textUIDrawing = SwingUtilities2.getTextUIDrawing(textUIDrawing);
421 }
422
423 /**
424 * Uninstall the defaults.
425 */
426 protected void uninstallDefaults() {
427 highlight = null;
428 lightHighlight = null;
429 shadow = null;
430 darkShadow = null;
431 focus = null;
432 tabInsets = null;
433 selectedTabPadInsets = null;
434 tabAreaInsets = null;
435 contentBorderInsets = null;
436 if (textUIDrawing != SwingUtilities2.DEFAULT_UI_TEXT_DRAWING
437 && textUIDrawing instanceof UIResource) {
438 textUIDrawing = SwingUtilities2.DEFAULT_UI_TEXT_DRAWING;
439 }
440 }
441
442 /**
443 * Install the listeners.
444 */
445 protected void installListeners() {
446 if ((propertyChangeListener = createPropertyChangeListener()) != null) {
447 tabPane.addPropertyChangeListener(propertyChangeListener);
448 }
449 if ((tabChangeListener = createChangeListener()) != null) {
450 tabPane.addChangeListener(tabChangeListener);
451 }
452 if ((mouseListener = createMouseListener()) != null) {
453 tabPane.addMouseListener(mouseListener);
454 }
455 tabPane.addMouseMotionListener(getHandler());
456 if ((focusListener = createFocusListener()) != null) {
457 tabPane.addFocusListener(focusListener);
458 }
459 tabPane.addContainerListener(getHandler());
932 }
933
934 paintTabBorder(g, tabPlacement, tabIndex, tabRect.x, tabRect.y,
935 tabRect.width, tabRect.height, isSelected);
936
937 String title = tabPane.getTitleAt(tabIndex);
938 Font font = tabPane.getFont();
939 FontMetrics metrics = SwingUtilities2.getFontMetrics(tabPane, g, font);
940 Icon icon = getIconForTab(tabIndex);
941
942 layoutLabel(tabPlacement, metrics, tabIndex, title, icon,
943 tabRect, iconRect, textRect, isSelected);
944
945 if (tabPane.getTabComponentAt(tabIndex) == null) {
946 String clippedTitle = title;
947
948 if (scrollableTabLayoutEnabled() && tabScroller.croppedEdge.isParamsSet() &&
949 tabScroller.croppedEdge.getTabIndex() == tabIndex && isHorizontalTabPlacement()) {
950 int availTextWidth = tabScroller.croppedEdge.getCropline() -
951 (textRect.x - tabRect.x) - tabScroller.croppedEdge.getCroppedSideWidth();
952 clippedTitle = textUIDrawing.getClippedString(null, metrics, title, availTextWidth);
953 } else if (!scrollableTabLayoutEnabled() && isHorizontalTabPlacement()) {
954 clippedTitle = textUIDrawing.getClippedString(null, metrics, title, textRect.width);
955 }
956
957 paintText(g, tabPlacement, font, metrics,
958 tabIndex, clippedTitle, textRect, isSelected);
959
960 paintIcon(g, tabPlacement, tabIndex, icon, iconRect, isSelected);
961 }
962 paintFocusIndicator(g, tabPlacement, rects, tabIndex,
963 iconRect, textRect, isSelected);
964 }
965
966 private boolean isHorizontalTabPlacement() {
967 return tabPane.getTabPlacement() == TOP || tabPane.getTabPlacement() == BOTTOM;
968 }
969
970 /* This method will create and return a polygon shape for the given tab rectangle
971 * which has been cropped at the specified cropline with a torn edge visual.
972 * e.g. A "File" tab which has cropped been cropped just after the "i":
973 * -------------
974 * | ..... |
1168 g.setFont(font);
1169
1170 View v = getTextViewForTab(tabIndex);
1171 if (v != null) {
1172 // html
1173 v.paint(g, textRect);
1174 } else {
1175 // plain text
1176 int mnemIndex = tabPane.getDisplayedMnemonicIndexAt(tabIndex);
1177
1178 if (tabPane.isEnabled() && tabPane.isEnabledAt(tabIndex)) {
1179 Color fg = tabPane.getForegroundAt(tabIndex);
1180 if (isSelected && (fg instanceof UIResource)) {
1181 Color selectedFG = UIManager.getColor(
1182 "TabbedPane.selectedForeground");
1183 if (selectedFG != null) {
1184 fg = selectedFG;
1185 }
1186 }
1187 g.setColor(fg);
1188 textUIDrawing.drawStringUnderlineCharAt(tabPane, g,
1189 title, mnemIndex,
1190 textRect.x, textRect.y + metrics.getAscent());
1191
1192 } else { // tab disabled
1193 g.setColor(tabPane.getBackgroundAt(tabIndex).brighter());
1194 textUIDrawing.drawStringUnderlineCharAt(tabPane, g,
1195 title, mnemIndex,
1196 textRect.x, textRect.y + metrics.getAscent());
1197 g.setColor(tabPane.getBackgroundAt(tabIndex).darker());
1198 textUIDrawing.drawStringUnderlineCharAt(tabPane, g,
1199 title, mnemIndex,
1200 textRect.x - 1, textRect.y + metrics.getAscent() - 1);
1201
1202 }
1203 }
1204 }
1205
1206 /**
1207 * Returns the tab label shift x.
1208 * @param tabPlacement the tab placement
1209 * @param tabIndex the tab index
1210 * @param isSelected selection status
1211 * @return the tab label shift x
1212 */
1213 protected int getTabLabelShiftX(int tabPlacement, int tabIndex, boolean isSelected) {
1214 Rectangle tabRect = rects[tabIndex];
1215 String propKey = (isSelected ? "selectedLabelShift" : "labelShift");
1216 int nudge = DefaultLookup.getInt(
1217 tabPane, this, "TabbedPane." + propKey, 1);
1218
2016 * @return the tab width
2017 */
2018 protected int calculateTabWidth(int tabPlacement, int tabIndex, FontMetrics metrics) {
2019 Insets tabInsets = getTabInsets(tabPlacement, tabIndex);
2020 int width = tabInsets.left + tabInsets.right + 3;
2021 Component tabComponent = tabPane.getTabComponentAt(tabIndex);
2022 if (tabComponent != null) {
2023 width += tabComponent.getPreferredSize().width;
2024 } else {
2025 Icon icon = getIconForTab(tabIndex);
2026 if (icon != null) {
2027 width += icon.getIconWidth() + textIconGap;
2028 }
2029 View v = getTextViewForTab(tabIndex);
2030 if (v != null) {
2031 // html
2032 width += (int) v.getPreferredSpan(View.X_AXIS);
2033 } else {
2034 // plain text
2035 String title = tabPane.getTitleAt(tabIndex);
2036 width += textUIDrawing.getStringWidth(tabPane, metrics, title);
2037 }
2038 }
2039 return width;
2040 }
2041
2042 /**
2043 * Calculates the maximum tab width.
2044 * @param tabPlacement the placement (left, right, bottom, top) of the tab
2045 * @return the maximum tab width
2046 */
2047 protected int calculateMaxTabWidth(int tabPlacement) {
2048 FontMetrics metrics = getFontMetrics();
2049 int tabCount = tabPane.getTabCount();
2050 int result = 0;
2051 for(int i = 0; i < tabCount; i++) {
2052 result = Math.max(calculateTabWidth(tabPlacement, i, metrics), result);
2053 }
2054 return result;
2055 }
2056
|