38 |
|
|
39 |
package javax.swing.plaf.metal; |
package javax.swing.plaf.metal; |
40 |
|
|
41 |
|
import java.awt.Color; |
42 |
import java.awt.Graphics; |
import java.awt.Graphics; |
43 |
import java.awt.LayoutManager; |
import java.awt.LayoutManager; |
44 |
|
import java.awt.Rectangle; |
45 |
|
|
46 |
import javax.swing.JComponent; |
import javax.swing.JComponent; |
47 |
import javax.swing.JTabbedPane; |
import javax.swing.JTabbedPane; |
48 |
|
import javax.swing.UIManager; |
49 |
import javax.swing.plaf.ComponentUI; |
import javax.swing.plaf.ComponentUI; |
50 |
import javax.swing.plaf.basic.BasicTabbedPaneUI; |
import javax.swing.plaf.basic.BasicTabbedPaneUI; |
51 |
|
|
104 |
} |
} |
105 |
|
|
106 |
/** |
/** |
107 |
|
* The minimum tab width. |
108 |
|
*/ |
109 |
|
protected int minTabWidth; |
110 |
|
|
111 |
|
/** |
112 |
|
* The color for the selected tab. |
113 |
|
*/ |
114 |
|
protected Color selectColor; |
115 |
|
|
116 |
|
/** |
117 |
|
* The color for a highlighted selected tab. |
118 |
|
*/ |
119 |
|
protected Color selectHighlight; |
120 |
|
|
121 |
|
/** |
122 |
|
* The background color used for the tab area. |
123 |
|
*/ |
124 |
|
protected Color tabAreaBackground; |
125 |
|
|
126 |
|
/** The graphics to draw the highlight below the tab. */ |
127 |
|
private Graphics hg; |
128 |
|
|
129 |
|
/** |
130 |
* Constructs a new instance of MetalTabbedPaneUI. |
* Constructs a new instance of MetalTabbedPaneUI. |
131 |
*/ |
*/ |
132 |
public MetalTabbedPaneUI() |
public MetalTabbedPaneUI() |
153 |
*/ |
*/ |
154 |
protected LayoutManager createLayoutManager() |
protected LayoutManager createLayoutManager() |
155 |
{ |
{ |
156 |
return new TabbedPaneLayout(); |
return super.createLayoutManager(); |
157 |
} |
} |
158 |
|
|
159 |
/** |
/** |
201 |
protected void paintTopTabBorder(int tabIndex, Graphics g, int x, int y, |
protected void paintTopTabBorder(int tabIndex, Graphics g, int x, int y, |
202 |
int w, int h, int btm, int rght, boolean isSelected) |
int w, int h, int btm, int rght, boolean isSelected) |
203 |
{ |
{ |
204 |
|
int currentRun = getRunForTab(tabPane.getTabCount(), tabIndex); |
205 |
|
if (shouldFillGap(currentRun, tabIndex, x, y)) |
206 |
|
{ |
207 |
|
g.translate(x, y); |
208 |
|
g.setColor(getColorForGap(currentRun, x, y)); |
209 |
|
g.fillRect(1, 0, 5, 3); |
210 |
|
g.fillRect(1, 3, 2, 2); |
211 |
|
g.translate(-x, -y); |
212 |
|
} |
213 |
|
|
214 |
if (isSelected) |
if (isSelected) |
215 |
{ |
{ |
216 |
g.setColor(MetalLookAndFeel.getControlHighlight()); |
g.setColor(MetalLookAndFeel.getControlHighlight()); |
303 |
protected void paintBottomTabBorder(int tabIndex, Graphics g, int x, int y, |
protected void paintBottomTabBorder(int tabIndex, Graphics g, int x, int y, |
304 |
int w, int h, int btm, int rght, boolean isSelected) |
int w, int h, int btm, int rght, boolean isSelected) |
305 |
{ |
{ |
306 |
|
int currentRun = getRunForTab(tabPane.getTabCount(), tabIndex); |
307 |
|
if (shouldFillGap(currentRun, tabIndex, x, y)) |
308 |
|
{ |
309 |
|
g.translate(x, y); |
310 |
|
g.setColor(getColorForGap(currentRun, x, y)); |
311 |
|
g.fillRect(1, h - 5, 3, 5); |
312 |
|
g.fillRect(4, h - 2, 2, 2); |
313 |
|
g.translate(-x, -y); |
314 |
|
} |
315 |
|
|
316 |
if (isSelected) |
if (isSelected) |
317 |
{ |
{ |
318 |
g.setColor(MetalLookAndFeel.getControlHighlight()); |
g.setColor(MetalLookAndFeel.getControlHighlight()); |
343 |
int tabIndex, int x, int y, int w, int h, boolean isSelected) |
int tabIndex, int x, int y, int w, int h, boolean isSelected) |
344 |
{ |
{ |
345 |
if (isSelected) |
if (isSelected) |
346 |
g.setColor(MetalLookAndFeel.getControl()); |
g.setColor(UIManager.getColor("TabbedPane.selected")); |
347 |
else |
else |
348 |
g.setColor(MetalLookAndFeel.getControlShadow()); |
{ |
349 |
|
// This is only present in the OceanTheme, so we must check if it |
350 |
|
// is actually there |
351 |
|
Color background = UIManager.getColor("TabbedPane.unselectedBackground"); |
352 |
|
if (background == null) |
353 |
|
background = UIManager.getColor("TabbedPane.background"); |
354 |
|
g.setColor(background); |
355 |
|
} |
356 |
int[] px, py; |
int[] px, py; |
357 |
if (tabPlacement == TOP) |
if (tabPlacement == TOP) |
358 |
{ |
{ |
377 |
else |
else |
378 |
throw new AssertionError("Unrecognised 'tabPlacement' argument."); |
throw new AssertionError("Unrecognised 'tabPlacement' argument."); |
379 |
g.fillPolygon(px, py, 5); |
g.fillPolygon(px, py, 5); |
380 |
|
hg = g; |
381 |
|
paintHighlightBelowTab(); |
382 |
} |
} |
383 |
|
|
384 |
/** |
/** |
397 |
// (which is drawn at the very top for tabPlacement == TOP) |
// (which is drawn at the very top for tabPlacement == TOP) |
398 |
return run < this.runCount - 1; |
return run < this.runCount - 1; |
399 |
} |
} |
400 |
|
|
401 |
|
/** |
402 |
|
* Installs the defaults for this UI. This method calls super.installDefaults |
403 |
|
* and then loads the Metal specific defaults for TabbedPane. |
404 |
|
*/ |
405 |
|
protected void installDefaults() |
406 |
|
{ |
407 |
|
super.installDefaults(); |
408 |
|
selectColor = UIManager.getColor("TabbedPane.selected"); |
409 |
|
selectHighlight = UIManager.getColor("TabbedPane.selectHighlight"); |
410 |
|
tabAreaBackground = UIManager.getColor("TabbedPane.tabAreaBackground"); |
411 |
|
minTabWidth = 0; |
412 |
|
} |
413 |
|
|
414 |
|
/** |
415 |
|
* Returns the color for the gap. |
416 |
|
* |
417 |
|
* @param currentRun - The current run to return the color for |
418 |
|
* @param x - The x position of the current run |
419 |
|
* @param y - The y position of the current run |
420 |
|
* |
421 |
|
* @return the color for the gap in the current run. |
422 |
|
*/ |
423 |
|
protected Color getColorForGap(int currentRun, int x, int y) |
424 |
|
{ |
425 |
|
int index = tabForCoordinate(tabPane, x, y); |
426 |
|
int selected = tabPane.getSelectedIndex(); |
427 |
|
if (selected == index) |
428 |
|
return selectColor; |
429 |
|
return tabAreaBackground; |
430 |
|
} |
431 |
|
|
432 |
|
/** |
433 |
|
* Returns true if the gap should be filled in. |
434 |
|
* |
435 |
|
* @param currentRun - The current run |
436 |
|
* @param tabIndex - The current tab |
437 |
|
* @param x - The x position of the tab |
438 |
|
* @param y - The y position of the tab |
439 |
|
* |
440 |
|
* @return true if the gap at the current run should be filled |
441 |
|
*/ |
442 |
|
protected boolean shouldFillGap(int currentRun, int tabIndex, int x, int y) |
443 |
|
{ |
444 |
|
// As far as I can tell, the gap is never filled in. |
445 |
|
return false; |
446 |
|
} |
447 |
|
|
448 |
|
/** |
449 |
|
* Paints the highlight below the tab, if there is one. |
450 |
|
*/ |
451 |
|
protected void paintHighlightBelowTab() |
452 |
|
{ |
453 |
|
int selected = tabPane.getSelectedIndex(); |
454 |
|
int tabPlacement = tabPane.getTabPlacement(); |
455 |
|
Rectangle bounds = getTabBounds(tabPane, selected); |
456 |
|
|
457 |
|
hg.setColor(selectColor); |
458 |
|
int x = bounds.x; |
459 |
|
int y = bounds.y; |
460 |
|
int w = bounds.width; |
461 |
|
int h = bounds.height; |
462 |
|
|
463 |
|
if (tabPlacement == TOP) |
464 |
|
hg.fillRect(x, y + h - 2, w, 30); |
465 |
|
else if (tabPlacement == LEFT) |
466 |
|
hg.fillRect(x + w - 1, y, 20, h); |
467 |
|
else if (tabPlacement == BOTTOM) |
468 |
|
hg.fillRect(x, y - h + 2, w, 30); |
469 |
|
else if (tabPlacement == RIGHT) |
470 |
|
hg.fillRect(x - 18, y, 20, h); |
471 |
|
else |
472 |
|
throw new AssertionError("Unrecognised 'tabPlacement' argument."); |
473 |
|
hg = null; |
474 |
|
} |
475 |
|
|
476 |
|
/** |
477 |
|
* Returns true if we should rotate the tab runs. |
478 |
|
* |
479 |
|
* @param tabPlacement - The current tab placement. |
480 |
|
* @param selectedRun - The selected run. |
481 |
|
* |
482 |
|
* @return true if the tab runs should be rotated. |
483 |
|
*/ |
484 |
|
protected boolean shouldRotateTabRuns(int tabPlacement, |
485 |
|
int selectedRun) |
486 |
|
{ |
487 |
|
// false because tab runs are not rotated in the MetalLookAndFeel |
488 |
|
return false; |
489 |
|
} |
490 |
} |
} |