1 7 8 package javax.swing.plaf.synth; 9 10 import javax.swing.*; 11 import javax.swing.event.*; 12 import javax.swing.plaf.*; 13 import javax.swing.plaf.basic.*; 14 import javax.swing.text.View ; 15 16 import java.awt.*; 17 import java.awt.event.*; 18 import java.beans.PropertyChangeListener ; 19 import java.beans.PropertyChangeEvent ; 20 import java.util.Vector ; 21 import java.util.Hashtable ; 22 import sun.swing.plaf.synth.SynthUI; 23 import com.sun.java.swing.SwingUtilities2; 24 25 31 35 class SynthTabbedPaneUI extends BasicTabbedPaneUI implements SynthUI, PropertyChangeListener { 36 private SynthContext tabAreaContext; 37 private SynthContext tabContext; 38 private SynthContext tabContentContext; 39 40 private SynthStyle style; 41 private SynthStyle tabStyle; 42 private SynthStyle tabAreaStyle; 43 private SynthStyle tabContentStyle; 44 45 private Rectangle tabAreaBounds = new Rectangle(); 46 47 public static ComponentUI createUI(JComponent c) { 48 return new SynthTabbedPaneUI (); 49 } 50 51 private boolean scrollableTabLayoutEnabled() { 52 return (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT); 53 } 54 55 protected void installDefaults() { 56 updateStyle(tabPane); 57 } 58 59 private void updateStyle(JTabbedPane c) { 60 SynthContext context = getContext(c, ENABLED); 61 SynthStyle oldStyle = style; 62 style = SynthLookAndFeel.updateStyle(context, this); 63 if (style != oldStyle) { 66 tabRunOverlay = 67 style.getInt(context, "TabbedPane.tabRunOverlay", 0); 68 textIconGap = style.getInt(context, "TabbedPane.textIconGap", 0); 69 selectedTabPadInsets = (Insets)style.get(context, 70 "TabbedPane.selectedTabPadInsets"); 71 if (selectedTabPadInsets == null) { 72 selectedTabPadInsets = new Insets(0, 0, 0, 0); 73 } 74 if (oldStyle != null) { 75 uninstallKeyboardActions(); 76 installKeyboardActions(); 77 } 78 } 79 context.dispose(); 80 81 if (tabContext != null) { 82 tabContext.dispose(); 83 } 84 tabContext = getContext(c, Region.TABBED_PANE_TAB, ENABLED); 85 this.tabStyle = SynthLookAndFeel.updateStyle(tabContext, this); 86 tabInsets = tabStyle.getInsets(tabContext, null); 87 88 89 if (tabAreaContext != null) { 90 tabAreaContext.dispose(); 91 } 92 tabAreaContext = getContext(c, Region.TABBED_PANE_TAB_AREA, ENABLED); 93 this.tabAreaStyle = SynthLookAndFeel.updateStyle(tabAreaContext, this); 94 tabAreaInsets = tabAreaStyle.getInsets(tabAreaContext, null); 95 96 97 if (tabContentContext != null) { 98 tabContentContext.dispose(); 99 } 100 tabContentContext = getContext(c, Region.TABBED_PANE_CONTENT, ENABLED); 101 this.tabContentStyle = SynthLookAndFeel.updateStyle(tabContentContext, 102 this); 103 contentBorderInsets = 104 tabContentStyle.getInsets(tabContentContext, null); 105 } 106 107 protected void installListeners() { 108 super.installListeners(); 109 tabPane.addPropertyChangeListener(this); 110 } 111 112 protected void uninstallListeners() { 113 super.uninstallListeners(); 114 tabPane.removePropertyChangeListener(this); 115 } 116 117 protected void uninstallDefaults() { 118 SynthContext context = getContext(tabPane, ENABLED); 119 style.uninstallDefaults(context); 120 context.dispose(); 121 style = null; 122 123 tabStyle.uninstallDefaults(tabContext); 124 tabContext.dispose(); 125 tabContext = null; 126 tabStyle = null; 127 128 tabAreaStyle.uninstallDefaults(tabAreaContext); 129 tabAreaContext.dispose(); 130 tabAreaContext = null; 131 tabAreaStyle = null; 132 133 tabContentStyle.uninstallDefaults(tabContentContext); 134 tabContentContext.dispose(); 135 tabContentContext = null; 136 tabContentStyle = null; 137 } 138 139 public SynthContext getContext(JComponent c) { 140 return getContext(c, getComponentState(c)); 141 } 142 143 public SynthContext getContext(JComponent c, int state) { 144 return SynthContext.getContext(SynthContext .class, c, 145 SynthLookAndFeel.getRegion(c),style, state); 146 } 147 148 public SynthContext getContext(JComponent c, Region subregion) { 149 return getContext(c, subregion, getComponentState(c)); 150 } 151 152 private SynthContext getContext(JComponent c, Region subregion, int state){ 153 SynthStyle style = null; 154 Class klass = SynthContext .class; 155 156 if (subregion == Region.TABBED_PANE_TAB) { 157 style = tabStyle; 158 } 159 else if (subregion == Region.TABBED_PANE_TAB_AREA) { 160 style = tabAreaStyle; 161 } 162 else if (subregion == Region.TABBED_PANE_CONTENT) { 163 style = tabContentStyle; 164 } 165 return SynthContext.getContext(klass, c, subregion, style, state); 166 } 167 168 private Region getRegion(JComponent c) { 169 return SynthLookAndFeel.getRegion(c); 170 } 171 172 private int getComponentState(JComponent c) { 173 return SynthLookAndFeel.getComponentState(c); 174 } 175 176 protected JButton createScrollButton(int direction) { 177 return new SynthScrollableTabButton(direction); 178 } 179 180 public void propertyChange(PropertyChangeEvent e) { 181 if (SynthLookAndFeel.shouldUpdateStyle(e)) { 182 updateStyle(tabPane); 183 } 184 } 185 186 public void update(Graphics g, JComponent c) { 187 SynthContext context = getContext(c); 188 189 SynthLookAndFeel.update(context, g); 190 context.getPainter().paintTabbedPaneBackground(context, 191 g, 0, 0, c.getWidth(), c.getHeight()); 192 paint(context, g); 193 context.dispose(); 194 } 195 196 public void paintBorder(SynthContext context, Graphics g, int x, 197 int y, int w, int h) { 198 context.getPainter().paintTabbedPaneBorder(context, g, x, y, w, h); 199 } 200 201 public void paint(Graphics g, JComponent c) { 202 SynthContext context = getContext(c); 203 204 paint(context, g); 205 context.dispose(); 206 } 207 208 protected void paint(SynthContext context, Graphics g) { 209 int selectedIndex = tabPane.getSelectedIndex(); 210 int tabPlacement = tabPane.getTabPlacement(); 211 212 ensureCurrentLayout(); 213 214 if (!scrollableTabLayoutEnabled()) { Insets insets = tabPane.getInsets(); 220 int x = insets.left; 221 int y = insets.top; 222 int width = tabPane.getWidth() - insets.left - insets.right; 223 int height = tabPane.getHeight() - insets.top - insets.bottom; 224 int size; 225 switch(tabPlacement) { 226 case LEFT: 227 width = calculateTabAreaWidth(tabPlacement, runCount, 228 maxTabWidth); 229 break; 230 case RIGHT: 231 size = calculateTabAreaWidth(tabPlacement, runCount, 232 maxTabWidth); 233 x = x + width - size; 234 width = size; 235 break; 236 case BOTTOM: 237 size = calculateTabAreaHeight(tabPlacement, runCount, 238 maxTabHeight); 239 y = y + height - size; 240 height = size; 241 break; 242 case TOP: 243 default: 244 height = calculateTabAreaHeight(tabPlacement, runCount, 245 maxTabHeight); 246 } 247 248 tabAreaBounds.setBounds(x, y, width, height); 249 250 if (g.getClipBounds().intersects(tabAreaBounds)) { 251 paintTabArea(tabAreaContext, g, tabPlacement, 252 selectedIndex, tabAreaBounds); 253 } 254 } 255 256 paintContentBorder(tabContentContext, g, tabPlacement, selectedIndex); 258 } 259 260 261 protected void paintTabArea(Graphics g, int tabPlacement, 262 int selectedIndex) { 263 Insets insets = tabPane.getInsets(); 265 int x = insets.left; 266 int y = insets.top; 267 int width = tabPane.getWidth() - insets.left - insets.right; 268 int height = tabPane.getHeight() - insets.top - insets.bottom; 269 270 paintTabArea(tabAreaContext, g, tabPlacement, selectedIndex, 271 new Rectangle(x, y, width, height)); 272 } 273 274 protected void paintTabArea(SynthContext ss, Graphics g, 275 int tabPlacement, int selectedIndex, 276 Rectangle tabAreaBounds) { 277 Rectangle clipRect = g.getClipBounds(); 278 279 SynthLookAndFeel.updateSubregion(ss, g, tabAreaBounds); 281 ss.getPainter().paintTabbedPaneTabAreaBackground(ss, g, 282 tabAreaBounds.x, tabAreaBounds.y, tabAreaBounds.width, 283 tabAreaBounds.height); 284 ss.getPainter().paintTabbedPaneTabAreaBorder(ss, g, tabAreaBounds.x, 285 tabAreaBounds.y, tabAreaBounds.width, tabAreaBounds.height); 286 287 int tabCount = tabPane.getTabCount(); 288 289 Rectangle iconRect = new Rectangle(), 290 textRect = new Rectangle(); 291 292 for (int i = runCount - 1; i >= 0; i--) { 294 int start = tabRuns[i]; 295 int next = tabRuns[(i == runCount - 1)? 0 : i + 1]; 296 int end = (next != 0? next - 1: tabCount - 1); 297 for (int j = start; j <= end; j++) { 298 if (rects[j].intersects(clipRect) && selectedIndex != j) { 299 paintTab(tabContext, g, tabPlacement, rects, j, iconRect, 300 textRect); 301 } 302 } 303 } 304 305 if (selectedIndex >= 0) { 306 if (rects[selectedIndex].intersects(clipRect)) { 307 paintTab(tabContext, g, tabPlacement, rects, selectedIndex, 308 iconRect, textRect); 309 } 310 } 311 } 312 313 protected void paintTab(SynthContext ss, Graphics g, 314 int tabPlacement, Rectangle[] rects, int tabIndex, 315 Rectangle iconRect, Rectangle textRect) { 316 Rectangle tabRect = rects[tabIndex]; 317 int selectedIndex = tabPane.getSelectedIndex(); 318 boolean isSelected = selectedIndex == tabIndex; 319 updateTabContext(tabIndex, isSelected, false, 320 (getFocusIndex() == tabIndex)); 321 322 SynthLookAndFeel.updateSubregion(ss, g, tabRect); 323 tabContext.getPainter().paintTabbedPaneTabBackground(tabContext, 324 g, tabRect.x, tabRect.y, tabRect.width, 325 tabRect.height, tabIndex); 326 tabContext.getPainter().paintTabbedPaneTabBorder(tabContext, g, 327 tabRect.x, tabRect.y, tabRect.width, tabRect.height, 328 tabIndex); 329 330 String title = tabPane.getTitleAt(tabIndex); 331 Font font = ss.getStyle().getFont(ss); 332 FontMetrics metrics = SwingUtilities2.getFontMetrics(tabPane, g, font); 333 Icon icon = getIconForTab(tabIndex); 334 335 layoutLabel(ss, tabPlacement, metrics, tabIndex, title, icon, 336 tabRect, iconRect, textRect, isSelected); 337 338 paintText(ss, g, tabPlacement, font, metrics, 339 tabIndex, title, textRect, isSelected); 340 341 paintIcon(g, tabPlacement, tabIndex, icon, iconRect, isSelected); 342 } 343 344 protected void layoutLabel(SynthContext ss, int tabPlacement, 345 FontMetrics metrics, int tabIndex, 346 String title, Icon icon, 347 Rectangle tabRect, Rectangle iconRect, 348 Rectangle textRect, boolean isSelected ) { 349 View v = getTextViewForTab(tabIndex); 350 if (v != null) { 351 tabPane.putClientProperty("html", v); 352 } 353 354 textRect.x = textRect.y = iconRect.x = iconRect.y = 0; 355 356 ss.getStyle().getGraphicsUtils(ss).layoutText(ss, metrics, title, 357 icon, SwingUtilities.CENTER, SwingUtilities.CENTER, 358 SwingUtilities.LEADING, SwingUtilities.TRAILING, 359 tabRect, iconRect, textRect, textIconGap); 360 361 tabPane.putClientProperty("html", null); 362 363 int xNudge = getTabLabelShiftX(tabPlacement, tabIndex, isSelected); 364 int yNudge = getTabLabelShiftY(tabPlacement, tabIndex, isSelected); 365 iconRect.x += xNudge; 366 iconRect.y += yNudge; 367 textRect.x += xNudge; 368 textRect.y += yNudge; 369 } 370 371 protected void paintText(SynthContext ss, 372 Graphics g, int tabPlacement, 373 Font font, FontMetrics metrics, int tabIndex, 374 String title, Rectangle textRect, 375 boolean isSelected) { 376 g.setFont(font); 377 378 View v = getTextViewForTab(tabIndex); 379 if (v != null) { 380 v.paint(g, textRect); 382 } else { 383 int mnemIndex = tabPane.getDisplayedMnemonicIndexAt(tabIndex); 385 386 g.setColor(ss.getStyle().getColor(ss, ColorType.TEXT_FOREGROUND)); 387 ss.getStyle().getGraphicsUtils(ss).paintText(ss, g, title, 388 textRect, mnemIndex); 389 } 390 } 391 392 393 protected void paintContentBorder(SynthContext ss, Graphics g, 394 int tabPlacement, int selectedIndex) { 395 int width = tabPane.getWidth(); 396 int height = tabPane.getHeight(); 397 Insets insets = tabPane.getInsets(); 398 399 int x = insets.left; 400 int y = insets.top; 401 int w = width - insets.right - insets.left; 402 int h = height - insets.top - insets.bottom; 403 404 switch(tabPlacement) { 405 case LEFT: 406 x += calculateTabAreaWidth(tabPlacement, runCount, maxTabWidth); 407 w -= (x - insets.left); 408 break; 409 case RIGHT: 410 w -= calculateTabAreaWidth(tabPlacement, runCount, maxTabWidth); 411 break; 412 case BOTTOM: 413 h -= calculateTabAreaHeight(tabPlacement, runCount, maxTabHeight); 414 break; 415 case TOP: 416 default: 417 y += calculateTabAreaHeight(tabPlacement, runCount, maxTabHeight); 418 h -= (y - insets.top); 419 } 420 SynthLookAndFeel.updateSubregion(ss, g, new Rectangle(x, y, w, h)); 421 ss.getPainter().paintTabbedPaneContentBackground(ss, g, x, y, 422 w, h); 423 ss.getPainter().paintTabbedPaneContentBorder(ss, g, x, y, w, h); 424 } 425 426 private void ensureCurrentLayout() { 427 if (!tabPane.isValid()) { 428 tabPane.validate(); 429 } 430 434 if (!tabPane.isValid()) { 435 TabbedPaneLayout layout = (TabbedPaneLayout)tabPane.getLayout(); 436 layout.calculateLayoutInfo(); 437 } 438 } 439 440 441 protected int calculateMaxTabHeight(int tabPlacement) { 442 FontMetrics metrics = getFontMetrics(tabContext.getStyle().getFont( 443 tabContext)); 444 int tabCount = tabPane.getTabCount(); 445 int result = 0; 446 int fontHeight = metrics.getHeight(); 447 for(int i = 0; i < tabCount; i++) { 448 result = Math.max(calculateTabHeight(tabPlacement, i, fontHeight), result); 449 } 450 return result; 451 } 452 453 protected int calculateTabWidth(int tabPlacement, int tabIndex, 454 FontMetrics metrics) { 455 Icon icon = getIconForTab(tabIndex); 456 Insets tabInsets = getTabInsets(tabPlacement, tabIndex); 457 int width = tabInsets.left + tabInsets.right + 3; 458 459 if (icon != null) { 460 width += icon.getIconWidth() + textIconGap; 461 } 462 View v = getTextViewForTab(tabIndex); 463 if (v != null) { 464 width += (int)v.getPreferredSpan(View.X_AXIS); 466 } else { 467 String title = tabPane.getTitleAt(tabIndex); 469 width += tabContext.getStyle().getGraphicsUtils(tabContext). 470 computeStringWidth(tabContext, metrics.getFont(), 471 metrics, title); 472 } 473 474 return width; 475 } 476 477 protected int calculateMaxTabWidth(int tabPlacement) { 478 FontMetrics metrics = getFontMetrics(tabContext.getStyle().getFont( 479 tabContext)); 480 int tabCount = tabPane.getTabCount(); 481 int result = 0; 482 for(int i = 0; i < tabCount; i++) { 483 result = Math.max(calculateTabWidth(tabPlacement, i, metrics), 484 result); 485 } 486 return result; 487 } 488 489 protected Insets getTabInsets(int tabPlacement, int tabIndex) { 490 updateTabContext(tabIndex, false, false, 491 (getFocusIndex() == tabIndex)); 492 return tabInsets; 493 } 494 495 protected FontMetrics getFontMetrics() { 496 return getFontMetrics(tabContext.getStyle().getFont(tabContext)); 497 } 498 499 protected FontMetrics getFontMetrics(Font font) { 500 return tabPane.getFontMetrics(font); 501 } 502 503 private void updateTabContext(int index, boolean selected, 504 boolean isMouseOver, boolean hasFocus) { 505 int state = 0; 506 if (!tabPane.isEnabledAt(index)) { 507 state |= SynthConstants.DISABLED; 508 } 509 else if (selected) { 510 state |= (SynthConstants.ENABLED | SynthConstants.SELECTED); 511 } 512 else if (isMouseOver) { 513 state |= (SynthConstants.ENABLED | SynthConstants.MOUSE_OVER); 514 } 515 else { 516 state = SynthLookAndFeel.getComponentState(tabPane); 517 state &= ~SynthConstants.FOCUSED; } 519 if (hasFocus && tabPane.hasFocus()) { 520 state |= SynthConstants.FOCUSED; } 522 tabContext.setComponentState(state); 523 } 524 525 private class SynthScrollableTabButton extends SynthArrowButton implements 526 UIResource { 527 public SynthScrollableTabButton(int direction) { 528 super(direction); 529 } 530 } 531 } 532 | Popular Tags |