1 30 31 package com.jgoodies.looks.windows; 32 33 import java.awt.FontMetrics ; 34 import java.awt.Graphics ; 35 import java.awt.Insets ; 36 import java.awt.Rectangle ; 37 import java.beans.PropertyChangeEvent ; 38 import java.beans.PropertyChangeListener ; 39 40 import javax.swing.Icon ; 41 import javax.swing.JComponent ; 42 import javax.swing.SwingConstants ; 43 import javax.swing.SwingUtilities ; 44 import javax.swing.plaf.ComponentUI ; 45 import javax.swing.plaf.basic.BasicGraphicsUtils ; 46 import javax.swing.plaf.basic.BasicTabbedPaneUI ; 47 import javax.swing.text.View ; 48 49 import com.jgoodies.looks.Options; 50 51 60 public final class WindowsTabbedPaneUI extends com.sun.java.swing.plaf.windows.WindowsTabbedPaneUI { 61 62 private static final Insets EMPTY_INSETS = new Insets (0, 0, 0, 0); 63 private static final Insets NORTH_INSETS = new Insets (1, 0, 0, 0); 64 private static final Insets WEST_INSETS = new Insets (0, 1, 0, 0); 65 private static final Insets SOUTH_INSETS = new Insets (0, 0, 1, 0); 66 private static final Insets EAST_INSETS = new Insets (0, 0, 0, 1); 67 68 69 72 private static boolean isTabIconsEnabled = Options.isTabIconsEnabled(); 73 74 81 private Boolean noContentBorder; 82 83 91 private Boolean embeddedTabs; 92 93 98 public static ComponentUI createUI(JComponent x) { 99 return new WindowsTabbedPaneUI(); 100 } 101 102 103 108 public void installUI(JComponent c) { 109 super.installUI(c); 110 embeddedTabs = (Boolean ) c.getClientProperty(Options.EMBEDDED_TABS_KEY); 111 noContentBorder = (Boolean ) c.getClientProperty(Options.NO_CONTENT_BORDER_KEY); 112 } 113 114 115 120 private boolean hasNoContentBorder() { 121 return hasEmbeddedTabs() || Boolean.TRUE.equals(noContentBorder); 122 } 123 124 127 private boolean hasEmbeddedTabs() { 128 return embeddedTabs == null 129 ? false 130 : embeddedTabs.booleanValue(); 131 } 132 133 138 protected PropertyChangeListener createPropertyChangeListener() { 139 return new MyPropertyChangeHandler(); 140 } 141 142 private void doLayout() { 143 tabPane.revalidate(); 144 tabPane.repaint(); 145 } 146 147 151 private void embeddedTabsPropertyChanged(Boolean newValue) { 152 embeddedTabs = newValue; 153 doLayout(); 154 } 155 156 161 private void noContentBorderPropertyChanged(Boolean newValue) { 162 noContentBorder = newValue; 163 doLayout(); 164 } 165 166 167 168 173 protected Icon getIconForTab(int tabIndex) { 174 String title = tabPane.getTitleAt(tabIndex); 175 boolean hasTitle = (title != null) && (title.length() > 0); 176 return !isTabIconsEnabled && hasTitle 177 ? null 178 : super.getIconForTab(tabIndex); 179 } 180 181 protected Insets getContentBorderInsets(int tabPlacement) { 182 if (!hasNoContentBorder()) 183 return contentBorderInsets; 184 else if (hasEmbeddedTabs()) 185 return EMPTY_INSETS; 186 else { 187 switch (tabPlacement) { 188 case RIGHT : 189 return EAST_INSETS; 190 case LEFT : 191 return WEST_INSETS; 192 case TOP : 193 return NORTH_INSETS; 194 case BOTTOM : 195 default : 196 return SOUTH_INSETS; 197 } 198 } 199 } 200 201 protected int getTabLabelShiftX(int tabPlacement, int tabIndex, boolean isSelected) { 202 switch (tabPlacement) { 203 case RIGHT : 204 return isSelected ? 2 : 0; 205 case LEFT : 206 return isSelected ? -2 : 0; 207 case TOP : 208 case BOTTOM : 209 default : 210 return 0; 211 } 212 } 213 214 protected int getTabLabelShiftY(int tabPlacement, int tabIndex, boolean isSelected) { 215 return 0; 216 } 217 218 protected Insets getSelectedTabPadInsets(int tabPlacement) { 219 if (hasEmbeddedTabs()) { 220 return EMPTY_INSETS; 221 } else if (hasNoContentBorder()) { 222 switch (tabPlacement) { 223 case LEFT: return new Insets (1,2,1,0); 224 case RIGHT: return new Insets (1,0,1,2); 225 case TOP: return new Insets (2,2,0,2); 226 case BOTTOM: return new Insets (0,2,2,2); 227 default: return EMPTY_INSETS; 228 } 229 } else { 230 Insets superInsets = super.getSelectedTabPadInsets(tabPlacement); 231 int equalized = superInsets.left + superInsets.right / 2; 232 superInsets.left = superInsets.right = equalized; 233 return superInsets; 234 } 235 } 236 237 238 protected Insets getTabAreaInsets(int tabPlacement) { 239 return hasEmbeddedTabs() 240 ? EMPTY_INSETS 241 : super.getTabAreaInsets(tabPlacement); 242 } 243 244 247 protected void paintContentBorderTopEdge(Graphics g, int tabPlacement, 248 int selectedIndex, 249 int x, int y, int w, int h) { 250 if (hasNoContentBorder() && tabPlacement != TOP) { 251 return; 252 } 253 Rectangle selRect = selectedIndex < 0 254 ? null 255 : getTabBounds(selectedIndex, calcRect); 256 if (tabPlacement != TOP || selectedIndex < 0 || 257 (selRect.y + selRect.height + 1 < y) || 258 (selRect.x < x || selRect.x > x + w)) { 259 super.paintContentBorderTopEdge(g, tabPlacement, selectedIndex, x, y, w, h); 261 } else { 262 g.setColor(lightHighlight); 263 g.fillRect(x, y, selRect.x + 1-x, 1); 264 g.fillRect(selRect.x + selRect.width, y, 265 x+w-2 -selRect.x-selRect.width, 1); 266 } 267 } 268 269 272 protected void paintContentBorderBottomEdge(Graphics g, int tabPlacement, 273 int selectedIndex, 274 int x, int y, int w, int h) { 275 if (!hasNoContentBorder()) { 276 Rectangle selRect = selectedIndex < 0? null : 277 getTabBounds(selectedIndex, calcRect); 278 if (tabPlacement != BOTTOM || selectedIndex < 0 || 279 (selRect.y - 1 > h + y) || 280 (selRect.x < x || selRect.x > x + w)) { 281 super.paintContentBorderBottomEdge(g, tabPlacement, selectedIndex, x, y, w, h); 283 } else { 284 g.setColor(lightHighlight); 285 g.fillRect(x,y+h-1,1,1); 286 g.setColor(shadow); 287 g.fillRect(x+1, y+h-2, selRect.x - 1-x, 1); 288 g.fillRect(selRect.x + selRect.width, y+h-2, x+w-2-selRect.x-selRect.width, 1); 289 g.setColor(darkShadow); 290 g.fillRect(x, y+h-1, selRect.x - x, 1); 291 g.fillRect(selRect.x + selRect.width -1, y+h-1, x+w-selRect.x-selRect.width, 1); 292 } 293 } else if (!(tabPlacement == BOTTOM)) { 294 } else { 297 g.setColor(shadow); 298 g.fillRect(x,y+h,w,1); 299 } 300 } 301 302 305 protected void paintContentBorderLeftEdge(Graphics g, int tabPlacement, 306 int selectedIndex, 307 int x, int y, int w, int h) { 308 if (!hasNoContentBorder()) { 309 Rectangle selRect = selectedIndex < 0? null : 310 getTabBounds(selectedIndex, calcRect); 311 if (tabPlacement != LEFT || selectedIndex < 0 || 312 (selRect.x + selRect.width + 1 < x) || 313 (selRect.y < y || selRect.y > y + h)) { 314 super.paintContentBorderLeftEdge(g, tabPlacement, selectedIndex, x, y, w, h); 316 } else { 317 g.setColor(lightHighlight); 318 g.fillRect(x, y, 1, selRect.y + 1 - y); 319 g.fillRect(x, selRect.y + selRect.height, 320 1, y+h-1-selRect.y-selRect.height); 321 322 } 323 } else if (!(tabPlacement == LEFT)) { 324 } else { 327 g.setColor(shadow); 328 g.fillRect(x,y,1,h); 329 } 330 } 331 332 335 protected void paintContentBorderRightEdge(Graphics g, int tabPlacement, 336 int selectedIndex, 337 int x, int y, int w, int h) { 338 if (!hasNoContentBorder()) { 339 Rectangle selRect = selectedIndex < 0? null : 340 getTabBounds(selectedIndex, calcRect); 341 if (tabPlacement != RIGHT || selectedIndex < 0 || 342 (selRect.x - 1 > x+w) || 343 (selRect.y < y || selRect.y > y + h)) { 344 super.paintContentBorderRightEdge(g, tabPlacement, selectedIndex, x, y, w, h); 346 } else { 347 g.setColor(lightHighlight); 348 g.fillRect(x+w-1, y,1,1); 349 g.setColor(shadow); 350 g.fillRect(x+w-2, y+1, 1, selRect.y - 1-y); 351 g.fillRect(x+w-2, selRect.y + selRect.height, 352 1, y+h-1-selRect.y- selRect.height); 353 g.setColor(darkShadow); 354 g.fillRect(x+w-1, y, 1, selRect.y - y); 355 g.fillRect(x+w-1, selRect.y + selRect.height-1, 356 1, y+h-selRect.y-selRect.height); 357 358 } 359 } else if (!(tabPlacement == RIGHT)) { 360 } else { 363 g.setColor(shadow); 364 g.fillRect(x+w,y,1,h); 365 } 366 } 367 368 369 372 protected void paintTabBorder( 373 Graphics g, 374 int tabPlacement, 375 int tabIndex, 376 int x, 377 int y, 378 int w, 379 int h, 380 boolean isSelected) { 381 if (!hasEmbeddedTabs()) { 382 super.paintTabBorder(g, tabPlacement, tabIndex, x, y, w, h, isSelected); 383 return; 384 } 385 g.translate(x - 1, y - 1); 386 int w1, w2, w3; 387 int h1, h2, h3; 388 switch (tabPlacement) { 389 case TOP : 390 w1 = 1; 391 w2 = w - 2; 392 w3 = 1; 393 h1 = 1; 394 h2 = h - 1; 395 h3 = 0; 396 break; 397 case BOTTOM : 398 w1 = 1; 399 w2 = w - 2; 400 w3 = 1; 401 h1 = 0; 402 h2 = h - 1; 403 h3 = 1; 404 break; 405 case LEFT : 406 w1 = 1; 407 w2 = w - 1; 408 w3 = 0; 409 h1 = 1; 410 h2 = h - 3; 411 h3 = 1; 412 break; 413 case RIGHT : 414 default : 415 w1 = 0; 416 w2 = w - 1; 417 w3 = 1; 418 h1 = 1; 419 h2 = h - 3; 420 h3 = 1; 421 } 422 if (isSelected) { 423 g.setColor(lightHighlight); 424 g.drawRect(w1, h1, w1 + w2 + w3, h1 + h2 + h3); 425 g.setColor(shadow); 426 g.fillRect(1 + w1, 0, w2, h1); 427 g.fillRect(0, 1 + h1, w1, h2); 428 g.fillRect(2 * w1 + w2 + 2 * w3, 1 + h1, w3, h2); 429 g.fillRect(1 + w1, 2 * h1 + h2 + 2 * h3, w2, h3); 430 g.fillRect(1, 1, w1, h1); 431 g.fillRect(2 * w1 + w2 + w3, 1, w3, h1); 432 g.fillRect(1, 2 * h1 + h2 + h3, w1, h3); 433 g.fillRect(2 * w1 + w2 + w3, 2 * h1 + h2 + h3, w3, h3); 434 } else { 435 g.setColor(shadow); 436 g.fillRect(w1 + w2 + 2 * w3, h3 * h2 /2, w3, h2* 2 /3); 437 g.fillRect(w3*w2 /2, h1 + h2 + 2 * h3, w2/2 +2, h3); 438 } 439 g.translate(-x + 1, -y + 1); 440 } 441 442 protected void paintFocusIndicator( 443 Graphics g, 444 int tabPlacement, 445 Rectangle [] rectangles, 446 int tabIndex, 447 Rectangle iconRect, 448 Rectangle textRect, 449 boolean isSelected) { 450 if (!hasEmbeddedTabs()) { 451 super.paintFocusIndicator(g, tabPlacement, rectangles, tabIndex, iconRect, textRect, isSelected); 452 return; 453 } 454 if (tabPane.hasFocus() && isSelected) { 455 g.setColor(focus); 456 BasicGraphicsUtils.drawDashedRect(g, textRect.x - 2, textRect.y, textRect.width + 3, textRect.height); 457 } 458 } 459 460 protected boolean shouldRotateTabRuns(int tabPlacement) { 461 return !hasEmbeddedTabs(); 462 } 463 464 468 protected void layoutLabel( 469 int tabPlacement, 470 FontMetrics metrics, 471 int tabIndex, 472 String title, 473 Icon icon, 474 Rectangle tabRect, 475 Rectangle iconRect, 476 Rectangle textRect, 477 boolean isSelected) { 478 textRect.x = textRect.y = iconRect.x = iconRect.y = 0; 479 480 View v = getTextViewForTab(tabIndex); 482 if (v != null) { 483 tabPane.putClientProperty("html", v); 484 } 485 486 int xNudge = getTabLabelShiftX(tabPlacement, tabIndex, isSelected); 487 int yNudge = getTabLabelShiftY(tabPlacement, tabIndex, isSelected); 488 if ((tabPlacement == RIGHT || tabPlacement == LEFT) && icon != null && title != null && !title.equals("")) { 489 490 SwingUtilities.layoutCompoundLabel( 491 tabPane, 492 metrics, 493 title, 494 icon, 495 SwingConstants.CENTER, 496 SwingConstants.LEFT, 497 SwingConstants.CENTER, 498 SwingConstants.TRAILING, 499 tabRect, 500 iconRect, 501 textRect, 502 textIconGap); 503 xNudge += 4; 504 } else { 505 SwingUtilities.layoutCompoundLabel( 506 tabPane, 507 metrics, 508 title, 509 icon, 510 SwingConstants.CENTER, 511 SwingConstants.CENTER, 512 SwingConstants.CENTER, 513 SwingConstants.TRAILING, 514 tabRect, 515 iconRect, 516 textRect, 517 textIconGap); 518 } 519 520 tabPane.putClientProperty("html", null); 522 523 iconRect.x += xNudge; 524 iconRect.y += yNudge; 525 textRect.x += xNudge; 526 textRect.y += yNudge; 527 } 528 529 530 535 private class MyPropertyChangeHandler extends BasicTabbedPaneUI.PropertyChangeHandler { 536 public void propertyChange(PropertyChangeEvent e) { 537 super.propertyChange(e); 538 539 String pName = e.getPropertyName(); 540 if (null == pName) { 541 return; 542 } 543 if (pName.equals(Options.EMBEDDED_TABS_KEY)) { 544 embeddedTabsPropertyChanged((Boolean )e.getNewValue()); 545 return; 546 } 547 if (pName.equals(Options.NO_CONTENT_BORDER_KEY)) { 548 noContentBorderPropertyChanged((Boolean )e.getNewValue()); 549 return; 550 } 551 552 } 553 554 } 555 556 557 558 } | Popular Tags |