|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
|
|
package javax.swing.plaf.metal; |
|
|
|
import sun.swing.SwingUtilities2; |
|
import java.awt.*; |
|
import java.awt.event.*; |
|
import javax.swing.*; |
|
import javax.swing.border.*; |
|
import javax.swing.event.InternalFrameEvent; |
|
import java.util.EventListener; |
|
import java.beans.PropertyChangeListener; |
|
import java.beans.PropertyChangeEvent; |
|
import javax.swing.plaf.basic.BasicInternalFrameTitlePane; |
|
|
|
|
|
/** |
|
* Class that manages a JLF title bar |
|
* @author Steve Wilson |
|
* @author Brian Beck |
|
* @since 1.3 |
|
*/ |
|
|
|
public class MetalInternalFrameTitlePane extends BasicInternalFrameTitlePane { |
|
|
|
protected boolean isPalette = false; |
|
protected Icon paletteCloseIcon; |
|
protected int paletteTitleHeight; |
|
|
|
private static final Border handyEmptyBorder = new EmptyBorder(0,0,0,0); |
|
|
|
|
|
|
|
|
|
*/ |
|
private String selectedBackgroundKey; |
|
|
|
|
|
|
|
*/ |
|
private String selectedForegroundKey; |
|
|
|
|
|
|
|
*/ |
|
private String selectedShadowKey; |
|
|
|
|
|
|
|
*/ |
|
private boolean wasClosable; |
|
|
|
int buttonsWidth = 0; |
|
|
|
MetalBumps activeBumps |
|
= new MetalBumps( 0, 0, |
|
MetalLookAndFeel.getPrimaryControlHighlight(), |
|
MetalLookAndFeel.getPrimaryControlDarkShadow(), |
|
(UIManager.get("InternalFrame.activeTitleGradient") != null) ? null : |
|
MetalLookAndFeel.getPrimaryControl() ); |
|
MetalBumps inactiveBumps |
|
= new MetalBumps( 0, 0, |
|
MetalLookAndFeel.getControlHighlight(), |
|
MetalLookAndFeel.getControlDarkShadow(), |
|
(UIManager.get("InternalFrame.inactiveTitleGradient") != null) ? null : |
|
MetalLookAndFeel.getControl() ); |
|
MetalBumps paletteBumps; |
|
|
|
private Color activeBumpsHighlight = MetalLookAndFeel. |
|
getPrimaryControlHighlight(); |
|
private Color activeBumpsShadow = MetalLookAndFeel. |
|
getPrimaryControlDarkShadow(); |
|
|
|
public MetalInternalFrameTitlePane(JInternalFrame f) { |
|
super( f ); |
|
} |
|
|
|
public void addNotify() { |
|
super.addNotify(); |
|
// This is done here instead of in installDefaults as I was worried |
|
// that the BasicInternalFrameUI might not be fully initialized, and |
|
// that if this resets the closable state the BasicInternalFrameUI |
|
|
|
updateOptionPaneState(); |
|
} |
|
|
|
protected void installDefaults() { |
|
super.installDefaults(); |
|
setFont( UIManager.getFont("InternalFrame.titleFont") ); |
|
paletteTitleHeight |
|
= UIManager.getInt("InternalFrame.paletteTitleHeight"); |
|
paletteCloseIcon = UIManager.getIcon("InternalFrame.paletteCloseIcon"); |
|
wasClosable = frame.isClosable(); |
|
selectedForegroundKey = selectedBackgroundKey = null; |
|
if (MetalLookAndFeel.usingOcean()) { |
|
setOpaque(true); |
|
} |
|
} |
|
|
|
protected void uninstallDefaults() { |
|
super.uninstallDefaults(); |
|
if (wasClosable != frame.isClosable()) { |
|
frame.setClosable(wasClosable); |
|
} |
|
} |
|
|
|
protected void createButtons() { |
|
super.createButtons(); |
|
|
|
Boolean paintActive = frame.isSelected() ? Boolean.TRUE:Boolean.FALSE; |
|
iconButton.putClientProperty("paintActive", paintActive); |
|
iconButton.setBorder(handyEmptyBorder); |
|
|
|
maxButton.putClientProperty("paintActive", paintActive); |
|
maxButton.setBorder(handyEmptyBorder); |
|
|
|
closeButton.putClientProperty("paintActive", paintActive); |
|
closeButton.setBorder(handyEmptyBorder); |
|
|
|
// The palette close icon isn't opaque while the regular close icon is. |
|
|
|
closeButton.setBackground(MetalLookAndFeel.getPrimaryControlShadow()); |
|
|
|
if (MetalLookAndFeel.usingOcean()) { |
|
iconButton.setContentAreaFilled(false); |
|
maxButton.setContentAreaFilled(false); |
|
closeButton.setContentAreaFilled(false); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
protected void assembleSystemMenu() {} |
|
|
|
|
|
|
|
|
|
*/ |
|
protected void addSystemMenuItems(JMenu systemMenu) {} |
|
|
|
|
|
|
|
|
|
*/ |
|
protected void showSystemMenu() {} |
|
|
|
|
|
|
|
|
|
*/ |
|
protected void addSubComponents() { |
|
add(iconButton); |
|
add(maxButton); |
|
add(closeButton); |
|
} |
|
|
|
protected PropertyChangeListener createPropertyChangeListener() { |
|
return new MetalPropertyChangeHandler(); |
|
} |
|
|
|
protected LayoutManager createLayout() { |
|
return new MetalTitlePaneLayout(); |
|
} |
|
|
|
class MetalPropertyChangeHandler |
|
extends BasicInternalFrameTitlePane.PropertyChangeHandler |
|
{ |
|
public void propertyChange(PropertyChangeEvent evt) { |
|
String prop = evt.getPropertyName(); |
|
if( prop.equals(JInternalFrame.IS_SELECTED_PROPERTY) ) { |
|
Boolean b = (Boolean)evt.getNewValue(); |
|
iconButton.putClientProperty("paintActive", b); |
|
closeButton.putClientProperty("paintActive", b); |
|
maxButton.putClientProperty("paintActive", b); |
|
} |
|
else if ("JInternalFrame.messageType".equals(prop)) { |
|
updateOptionPaneState(); |
|
frame.repaint(); |
|
} |
|
super.propertyChange(evt); |
|
} |
|
} |
|
|
|
class MetalTitlePaneLayout extends TitlePaneLayout { |
|
public void addLayoutComponent(String name, Component c) {} |
|
public void removeLayoutComponent(Component c) {} |
|
public Dimension preferredLayoutSize(Container c) { |
|
return minimumLayoutSize(c); |
|
} |
|
|
|
public Dimension minimumLayoutSize(Container c) { |
|
|
|
int width = 30; |
|
if (frame.isClosable()) { |
|
width += 21; |
|
} |
|
if (frame.isMaximizable()) { |
|
width += 16 + (frame.isClosable() ? 10 : 4); |
|
} |
|
if (frame.isIconifiable()) { |
|
width += 16 + (frame.isMaximizable() ? 2 : |
|
(frame.isClosable() ? 10 : 4)); |
|
} |
|
FontMetrics fm = frame.getFontMetrics(getFont()); |
|
String frameTitle = frame.getTitle(); |
|
int title_w = frameTitle != null ? SwingUtilities2.stringWidth( |
|
frame, fm, frameTitle) : 0; |
|
int title_length = frameTitle != null ? frameTitle.length() : 0; |
|
|
|
if (title_length > 2) { |
|
int subtitle_w = SwingUtilities2.stringWidth(frame, fm, |
|
frame.getTitle().substring(0, 2) + "..."); |
|
width += (title_w < subtitle_w) ? title_w : subtitle_w; |
|
} |
|
else { |
|
width += title_w; |
|
} |
|
|
|
|
|
int height; |
|
if (isPalette) { |
|
height = paletteTitleHeight; |
|
} else { |
|
int fontHeight = fm.getHeight(); |
|
fontHeight += 7; |
|
Icon icon = frame.getFrameIcon(); |
|
int iconHeight = 0; |
|
if (icon != null) { |
|
|
|
iconHeight = Math.min(icon.getIconHeight(), 16); |
|
} |
|
iconHeight += 5; |
|
height = Math.max(fontHeight, iconHeight); |
|
} |
|
|
|
return new Dimension(width, height); |
|
} |
|
|
|
public void layoutContainer(Container c) { |
|
boolean leftToRight = MetalUtils.isLeftToRight(frame); |
|
|
|
int w = getWidth(); |
|
int x = leftToRight ? w : 0; |
|
int y = 2; |
|
int spacing; |
|
|
|
// assumes all buttons have the same dimensions |
|
|
|
int buttonHeight = closeButton.getIcon().getIconHeight(); |
|
int buttonWidth = closeButton.getIcon().getIconWidth(); |
|
|
|
if(frame.isClosable()) { |
|
if (isPalette) { |
|
spacing = 3; |
|
x += leftToRight ? -spacing -(buttonWidth+2) : spacing; |
|
closeButton.setBounds(x, y, buttonWidth+2, getHeight()-4); |
|
if( !leftToRight ) x += (buttonWidth+2); |
|
} else { |
|
spacing = 4; |
|
x += leftToRight ? -spacing -buttonWidth : spacing; |
|
closeButton.setBounds(x, y, buttonWidth, buttonHeight); |
|
if( !leftToRight ) x += buttonWidth; |
|
} |
|
} |
|
|
|
if(frame.isMaximizable() && !isPalette ) { |
|
spacing = frame.isClosable() ? 10 : 4; |
|
x += leftToRight ? -spacing -buttonWidth : spacing; |
|
maxButton.setBounds(x, y, buttonWidth, buttonHeight); |
|
if( !leftToRight ) x += buttonWidth; |
|
} |
|
|
|
if(frame.isIconifiable() && !isPalette ) { |
|
spacing = frame.isMaximizable() ? 2 |
|
: (frame.isClosable() ? 10 : 4); |
|
x += leftToRight ? -spacing -buttonWidth : spacing; |
|
iconButton.setBounds(x, y, buttonWidth, buttonHeight); |
|
if( !leftToRight ) x += buttonWidth; |
|
} |
|
|
|
buttonsWidth = leftToRight ? w - x : x; |
|
} |
|
} |
|
|
|
public void paintPalette(Graphics g) { |
|
boolean leftToRight = MetalUtils.isLeftToRight(frame); |
|
|
|
int width = getWidth(); |
|
int height = getHeight(); |
|
|
|
if (paletteBumps == null) { |
|
paletteBumps |
|
= new MetalBumps(0, 0, |
|
MetalLookAndFeel.getPrimaryControlHighlight(), |
|
MetalLookAndFeel.getPrimaryControlInfo(), |
|
MetalLookAndFeel.getPrimaryControlShadow() ); |
|
} |
|
|
|
Color background = MetalLookAndFeel.getPrimaryControlShadow(); |
|
Color darkShadow = MetalLookAndFeel.getPrimaryControlDarkShadow(); |
|
|
|
g.setColor(background); |
|
g.fillRect(0, 0, width, height); |
|
|
|
g.setColor( darkShadow ); |
|
g.drawLine ( 0, height - 1, width, height -1); |
|
|
|
int xOffset = leftToRight ? 4 : buttonsWidth + 4; |
|
int bumpLength = width - buttonsWidth -2*4; |
|
int bumpHeight = getHeight() - 4; |
|
paletteBumps.setBumpArea( bumpLength, bumpHeight ); |
|
paletteBumps.paintIcon( this, g, xOffset, 2); |
|
} |
|
|
|
public void paintComponent(Graphics g) { |
|
if(isPalette) { |
|
paintPalette(g); |
|
return; |
|
} |
|
|
|
boolean leftToRight = MetalUtils.isLeftToRight(frame); |
|
boolean isSelected = frame.isSelected(); |
|
|
|
int width = getWidth(); |
|
int height = getHeight(); |
|
|
|
Color background = null; |
|
Color foreground = null; |
|
Color shadow = null; |
|
|
|
MetalBumps bumps; |
|
String gradientKey; |
|
|
|
if (isSelected) { |
|
if (!MetalLookAndFeel.usingOcean()) { |
|
closeButton.setContentAreaFilled(true); |
|
maxButton.setContentAreaFilled(true); |
|
iconButton.setContentAreaFilled(true); |
|
} |
|
if (selectedBackgroundKey != null) { |
|
background = UIManager.getColor(selectedBackgroundKey); |
|
} |
|
if (background == null) { |
|
background = MetalLookAndFeel.getWindowTitleBackground(); |
|
} |
|
if (selectedForegroundKey != null) { |
|
foreground = UIManager.getColor(selectedForegroundKey); |
|
} |
|
if (selectedShadowKey != null) { |
|
shadow = UIManager.getColor(selectedShadowKey); |
|
} |
|
if (shadow == null) { |
|
shadow = MetalLookAndFeel.getPrimaryControlDarkShadow(); |
|
} |
|
if (foreground == null) { |
|
foreground = MetalLookAndFeel.getWindowTitleForeground(); |
|
} |
|
activeBumps.setBumpColors(activeBumpsHighlight, activeBumpsShadow, |
|
UIManager.get("InternalFrame.activeTitleGradient") != |
|
null ? null : background); |
|
bumps = activeBumps; |
|
gradientKey = "InternalFrame.activeTitleGradient"; |
|
} else { |
|
if (!MetalLookAndFeel.usingOcean()) { |
|
closeButton.setContentAreaFilled(false); |
|
maxButton.setContentAreaFilled(false); |
|
iconButton.setContentAreaFilled(false); |
|
} |
|
background = MetalLookAndFeel.getWindowTitleInactiveBackground(); |
|
foreground = MetalLookAndFeel.getWindowTitleInactiveForeground(); |
|
shadow = MetalLookAndFeel.getControlDarkShadow(); |
|
bumps = inactiveBumps; |
|
gradientKey = "InternalFrame.inactiveTitleGradient"; |
|
} |
|
|
|
if (!MetalUtils.drawGradient(this, g, gradientKey, 0, 0, width, |
|
height, true)) { |
|
g.setColor(background); |
|
g.fillRect(0, 0, width, height); |
|
} |
|
|
|
g.setColor( shadow ); |
|
g.drawLine ( 0, height - 1, width, height -1); |
|
g.drawLine ( 0, 0, 0 ,0); |
|
g.drawLine ( width - 1, 0 , width -1, 0); |
|
|
|
|
|
int titleLength; |
|
int xOffset = leftToRight ? 5 : width - 5; |
|
String frameTitle = frame.getTitle(); |
|
|
|
Icon icon = frame.getFrameIcon(); |
|
if ( icon != null ) { |
|
if( !leftToRight ) |
|
xOffset -= icon.getIconWidth(); |
|
int iconY = ((height / 2) - (icon.getIconHeight() /2)); |
|
icon.paintIcon(frame, g, xOffset, iconY); |
|
xOffset += leftToRight ? icon.getIconWidth() + 5 : -5; |
|
} |
|
|
|
if(frameTitle != null) { |
|
Font f = getFont(); |
|
g.setFont(f); |
|
FontMetrics fm = SwingUtilities2.getFontMetrics(frame, g, f); |
|
int fHeight = fm.getHeight(); |
|
|
|
g.setColor(foreground); |
|
|
|
int yOffset = ( (height - fm.getHeight() ) / 2 ) + fm.getAscent(); |
|
|
|
Rectangle rect = new Rectangle(0, 0, 0, 0); |
|
if (frame.isIconifiable()) { rect = iconButton.getBounds(); } |
|
else if (frame.isMaximizable()) { rect = maxButton.getBounds(); } |
|
else if (frame.isClosable()) { rect = closeButton.getBounds(); } |
|
int titleW; |
|
|
|
if( leftToRight ) { |
|
if (rect.x == 0) { |
|
rect.x = frame.getWidth()-frame.getInsets().right-2; |
|
} |
|
titleW = rect.x - xOffset - 4; |
|
frameTitle = getTitle(frameTitle, fm, titleW); |
|
} else { |
|
titleW = xOffset - rect.x - rect.width - 4; |
|
frameTitle = getTitle(frameTitle, fm, titleW); |
|
xOffset -= SwingUtilities2.stringWidth(frame, fm, frameTitle); |
|
} |
|
|
|
titleLength = SwingUtilities2.stringWidth(frame, fm, frameTitle); |
|
SwingUtilities2.drawString(frame, g, frameTitle, xOffset, yOffset); |
|
xOffset += leftToRight ? titleLength + 5 : -5; |
|
} |
|
|
|
int bumpXOffset; |
|
int bumpLength; |
|
if( leftToRight ) { |
|
bumpLength = width - buttonsWidth - xOffset - 5; |
|
bumpXOffset = xOffset; |
|
} else { |
|
bumpLength = xOffset - buttonsWidth - 5; |
|
bumpXOffset = buttonsWidth + 5; |
|
} |
|
int bumpYOffset = 3; |
|
int bumpHeight = getHeight() - (2 * bumpYOffset); |
|
bumps.setBumpArea( bumpLength, bumpHeight ); |
|
bumps.paintIcon(this, g, bumpXOffset, bumpYOffset); |
|
} |
|
|
|
public void setPalette(boolean b) { |
|
isPalette = b; |
|
|
|
if (isPalette) { |
|
closeButton.setIcon(paletteCloseIcon); |
|
if( frame.isMaximizable() ) |
|
remove(maxButton); |
|
if( frame.isIconifiable() ) |
|
remove(iconButton); |
|
} else { |
|
closeButton.setIcon(closeIcon); |
|
if( frame.isMaximizable() ) |
|
add(maxButton); |
|
if( frame.isIconifiable() ) |
|
add(iconButton); |
|
} |
|
revalidate(); |
|
repaint(); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
private void updateOptionPaneState() { |
|
int type = -2; |
|
boolean closable = wasClosable; |
|
Object obj = frame.getClientProperty("JInternalFrame.messageType"); |
|
|
|
if (obj == null) { |
|
|
|
return; |
|
} |
|
if (obj instanceof Integer) { |
|
type = ((Integer) obj).intValue(); |
|
} |
|
switch (type) { |
|
case JOptionPane.ERROR_MESSAGE: |
|
selectedBackgroundKey = |
|
"OptionPane.errorDialog.titlePane.background"; |
|
selectedForegroundKey = |
|
"OptionPane.errorDialog.titlePane.foreground"; |
|
selectedShadowKey = "OptionPane.errorDialog.titlePane.shadow"; |
|
closable = false; |
|
break; |
|
case JOptionPane.QUESTION_MESSAGE: |
|
selectedBackgroundKey = |
|
"OptionPane.questionDialog.titlePane.background"; |
|
selectedForegroundKey = |
|
"OptionPane.questionDialog.titlePane.foreground"; |
|
selectedShadowKey = |
|
"OptionPane.questionDialog.titlePane.shadow"; |
|
closable = false; |
|
break; |
|
case JOptionPane.WARNING_MESSAGE: |
|
selectedBackgroundKey = |
|
"OptionPane.warningDialog.titlePane.background"; |
|
selectedForegroundKey = |
|
"OptionPane.warningDialog.titlePane.foreground"; |
|
selectedShadowKey = "OptionPane.warningDialog.titlePane.shadow"; |
|
closable = false; |
|
break; |
|
case JOptionPane.INFORMATION_MESSAGE: |
|
case JOptionPane.PLAIN_MESSAGE: |
|
selectedBackgroundKey = selectedForegroundKey = selectedShadowKey = |
|
null; |
|
closable = false; |
|
break; |
|
default: |
|
selectedBackgroundKey = selectedForegroundKey = selectedShadowKey = |
|
null; |
|
break; |
|
} |
|
if (closable != frame.isClosable()) { |
|
frame.setClosable(closable); |
|
} |
|
} |
|
} |