You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
497 lines
17 KiB
497 lines
17 KiB
/*
|
|
* Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
|
|
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*/
|
|
|
|
package javax.swing.plaf.synth;
|
|
|
|
import java.awt.*;
|
|
import java.awt.event.*;
|
|
import javax.swing.*;
|
|
import javax.swing.plaf.*;
|
|
import javax.swing.plaf.basic.BasicInternalFrameTitlePane;
|
|
import java.beans.PropertyChangeListener;
|
|
import java.beans.PropertyChangeEvent;
|
|
import java.beans.PropertyVetoException;
|
|
import sun.swing.SwingUtilities2;
|
|
|
|
/**
|
|
* The class that manages a synth title bar
|
|
*
|
|
* @author David Kloba
|
|
* @author Joshua Outwater
|
|
* @author Steve Wilson
|
|
*/
|
|
class SynthInternalFrameTitlePane extends BasicInternalFrameTitlePane
|
|
implements SynthUI, PropertyChangeListener {
|
|
|
|
protected JPopupMenu systemPopupMenu;
|
|
protected JButton menuButton;
|
|
|
|
private SynthStyle style;
|
|
private int titleSpacing;
|
|
private int buttonSpacing;
|
|
// Alignment for the title, one of SwingConstants.(LEADING|TRAILING|CENTER)
|
|
private int titleAlignment;
|
|
|
|
public SynthInternalFrameTitlePane(JInternalFrame f) {
|
|
super(f);
|
|
}
|
|
|
|
public String getUIClassID() {
|
|
return "InternalFrameTitlePaneUI";
|
|
}
|
|
|
|
public SynthContext getContext(JComponent c) {
|
|
return getContext(c, getComponentState(c));
|
|
}
|
|
|
|
public SynthContext getContext(JComponent c, int state) {
|
|
return SynthContext.getContext(c, style, state);
|
|
}
|
|
|
|
private Region getRegion(JComponent c) {
|
|
return SynthLookAndFeel.getRegion(c);
|
|
}
|
|
|
|
private int getComponentState(JComponent c) {
|
|
if (frame != null) {
|
|
if (frame.isSelected()) {
|
|
return SELECTED;
|
|
}
|
|
}
|
|
return SynthLookAndFeel.getComponentState(c);
|
|
}
|
|
|
|
protected void addSubComponents() {
|
|
menuButton.setName("InternalFrameTitlePane.menuButton");
|
|
iconButton.setName("InternalFrameTitlePane.iconifyButton");
|
|
maxButton.setName("InternalFrameTitlePane.maximizeButton");
|
|
closeButton.setName("InternalFrameTitlePane.closeButton");
|
|
|
|
add(menuButton);
|
|
add(iconButton);
|
|
add(maxButton);
|
|
add(closeButton);
|
|
}
|
|
|
|
protected void installListeners() {
|
|
super.installListeners();
|
|
frame.addPropertyChangeListener(this);
|
|
addPropertyChangeListener(this);
|
|
}
|
|
|
|
protected void uninstallListeners() {
|
|
frame.removePropertyChangeListener(this);
|
|
removePropertyChangeListener(this);
|
|
super.uninstallListeners();
|
|
}
|
|
|
|
private void updateStyle(JComponent c) {
|
|
SynthContext context = getContext(this, ENABLED);
|
|
SynthStyle oldStyle = style;
|
|
style = SynthLookAndFeel.updateStyle(context, this);
|
|
if (style != oldStyle) {
|
|
maxIcon =
|
|
style.getIcon(context,"InternalFrameTitlePane.maximizeIcon");
|
|
minIcon =
|
|
style.getIcon(context,"InternalFrameTitlePane.minimizeIcon");
|
|
iconIcon =
|
|
style.getIcon(context,"InternalFrameTitlePane.iconifyIcon");
|
|
closeIcon =
|
|
style.getIcon(context,"InternalFrameTitlePane.closeIcon");
|
|
titleSpacing = style.getInt(context,
|
|
"InternalFrameTitlePane.titleSpacing", 2);
|
|
buttonSpacing = style.getInt(context,
|
|
"InternalFrameTitlePane.buttonSpacing", 2);
|
|
String alignString = (String)style.get(context,
|
|
"InternalFrameTitlePane.titleAlignment");
|
|
titleAlignment = SwingConstants.LEADING;
|
|
if (alignString != null) {
|
|
alignString = alignString.toUpperCase();
|
|
if (alignString.equals("TRAILING")) {
|
|
titleAlignment = SwingConstants.TRAILING;
|
|
}
|
|
else if (alignString.equals("CENTER")) {
|
|
titleAlignment = SwingConstants.CENTER;
|
|
}
|
|
}
|
|
}
|
|
context.dispose();
|
|
}
|
|
|
|
protected void installDefaults() {
|
|
super.installDefaults();
|
|
updateStyle(this);
|
|
}
|
|
|
|
protected void uninstallDefaults() {
|
|
SynthContext context = getContext(this, ENABLED);
|
|
style.uninstallDefaults(context);
|
|
context.dispose();
|
|
style = null;
|
|
JInternalFrame.JDesktopIcon di = frame.getDesktopIcon();
|
|
if(di != null && di.getComponentPopupMenu() == systemPopupMenu) {
|
|
// Release link to systemMenu from the JInternalFrame
|
|
di.setComponentPopupMenu(null);
|
|
}
|
|
super.uninstallDefaults();
|
|
}
|
|
|
|
private static class JPopupMenuUIResource extends JPopupMenu implements
|
|
UIResource { }
|
|
|
|
protected void assembleSystemMenu() {
|
|
systemPopupMenu = new JPopupMenuUIResource();
|
|
addSystemMenuItems(systemPopupMenu);
|
|
enableActions();
|
|
menuButton = createNoFocusButton();
|
|
updateMenuIcon();
|
|
menuButton.addMouseListener(new MouseAdapter() {
|
|
public void mousePressed(MouseEvent e) {
|
|
try {
|
|
frame.setSelected(true);
|
|
} catch(PropertyVetoException pve) {
|
|
}
|
|
showSystemMenu();
|
|
}
|
|
});
|
|
JPopupMenu p = frame.getComponentPopupMenu();
|
|
if (p == null || p instanceof UIResource) {
|
|
frame.setComponentPopupMenu(systemPopupMenu);
|
|
}
|
|
if (frame.getDesktopIcon() != null) {
|
|
p = frame.getDesktopIcon().getComponentPopupMenu();
|
|
if (p == null || p instanceof UIResource) {
|
|
frame.getDesktopIcon().setComponentPopupMenu(systemPopupMenu);
|
|
}
|
|
}
|
|
setInheritsPopupMenu(true);
|
|
}
|
|
|
|
protected void addSystemMenuItems(JPopupMenu menu) {
|
|
JMenuItem mi = menu.add(restoreAction);
|
|
mi.setMnemonic(getButtonMnemonic("restore"));
|
|
mi = menu.add(moveAction);
|
|
mi.setMnemonic(getButtonMnemonic("move"));
|
|
mi = menu.add(sizeAction);
|
|
mi.setMnemonic(getButtonMnemonic("size"));
|
|
mi = menu.add(iconifyAction);
|
|
mi.setMnemonic(getButtonMnemonic("minimize"));
|
|
mi = menu.add(maximizeAction);
|
|
mi.setMnemonic(getButtonMnemonic("maximize"));
|
|
menu.add(new JSeparator());
|
|
mi = menu.add(closeAction);
|
|
mi.setMnemonic(getButtonMnemonic("close"));
|
|
}
|
|
|
|
private static int getButtonMnemonic(String button) {
|
|
try {
|
|
return Integer.parseInt(UIManager.getString(
|
|
"InternalFrameTitlePane." + button + "Button.mnemonic"));
|
|
} catch (NumberFormatException e) {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
protected void showSystemMenu() {
|
|
Insets insets = frame.getInsets();
|
|
if (!frame.isIcon()) {
|
|
systemPopupMenu.show(frame, menuButton.getX(), getY() + getHeight());
|
|
} else {
|
|
systemPopupMenu.show(menuButton,
|
|
getX() - insets.left - insets.right,
|
|
getY() - systemPopupMenu.getPreferredSize().height -
|
|
insets.bottom - insets.top);
|
|
}
|
|
}
|
|
|
|
// SynthInternalFrameTitlePane has no UI, we'll invoke paint on it.
|
|
public void paintComponent(Graphics g) {
|
|
SynthContext context = getContext(this);
|
|
SynthLookAndFeel.update(context, g);
|
|
context.getPainter().paintInternalFrameTitlePaneBackground(context,
|
|
g, 0, 0, getWidth(), getHeight());
|
|
paint(context, g);
|
|
context.dispose();
|
|
}
|
|
|
|
protected void paint(SynthContext context, Graphics g) {
|
|
String title = frame.getTitle();
|
|
|
|
if (title != null) {
|
|
SynthStyle style = context.getStyle();
|
|
|
|
g.setColor(style.getColor(context, ColorType.TEXT_FOREGROUND));
|
|
g.setFont(style.getFont(context));
|
|
|
|
// Center text vertically.
|
|
FontMetrics fm = SwingUtilities2.getFontMetrics(frame, g);
|
|
int baseline = (getHeight() + fm.getAscent() - fm.getLeading() -
|
|
fm.getDescent()) / 2;
|
|
JButton lastButton = null;
|
|
if (frame.isIconifiable()) {
|
|
lastButton = iconButton;
|
|
}
|
|
else if (frame.isMaximizable()) {
|
|
lastButton = maxButton;
|
|
}
|
|
else if (frame.isClosable()) {
|
|
lastButton = closeButton;
|
|
}
|
|
int maxX;
|
|
int minX;
|
|
boolean ltr = SynthLookAndFeel.isLeftToRight(frame);
|
|
int titleAlignment = this.titleAlignment;
|
|
if (ltr) {
|
|
if (lastButton != null) {
|
|
maxX = lastButton.getX() - titleSpacing;
|
|
}
|
|
else {
|
|
maxX = frame.getWidth() - frame.getInsets().right -
|
|
titleSpacing;
|
|
}
|
|
minX = menuButton.getX() + menuButton.getWidth() +
|
|
titleSpacing;
|
|
}
|
|
else {
|
|
if (lastButton != null) {
|
|
minX = lastButton.getX() + lastButton.getWidth() +
|
|
titleSpacing;
|
|
}
|
|
else {
|
|
minX = frame.getInsets().left + titleSpacing;
|
|
}
|
|
maxX = menuButton.getX() - titleSpacing;
|
|
if (titleAlignment == SwingConstants.LEADING) {
|
|
titleAlignment = SwingConstants.TRAILING;
|
|
}
|
|
else if (titleAlignment == SwingConstants.TRAILING) {
|
|
titleAlignment = SwingConstants.LEADING;
|
|
}
|
|
}
|
|
String clippedTitle = getTitle(title, fm, maxX - minX);
|
|
if (clippedTitle == title) {
|
|
// String fit, align as necessary.
|
|
if (titleAlignment == SwingConstants.TRAILING) {
|
|
minX = maxX - style.getGraphicsUtils(context).
|
|
computeStringWidth(context, g.getFont(), fm, title);
|
|
}
|
|
else if (titleAlignment == SwingConstants.CENTER) {
|
|
int width = style.getGraphicsUtils(context).
|
|
computeStringWidth(context, g.getFont(), fm, title);
|
|
minX = Math.max(minX, (getWidth() - width) / 2);
|
|
minX = Math.min(maxX - width, minX);
|
|
}
|
|
}
|
|
style.getGraphicsUtils(context).paintText(
|
|
context, g, clippedTitle, minX, baseline - fm.getAscent(), -1);
|
|
}
|
|
}
|
|
|
|
public void paintBorder(SynthContext context, Graphics g, int x,
|
|
int y, int w, int h) {
|
|
context.getPainter().paintInternalFrameTitlePaneBorder(context,
|
|
g, x, y, w, h);
|
|
}
|
|
|
|
protected LayoutManager createLayout() {
|
|
SynthContext context = getContext(this);
|
|
LayoutManager lm =
|
|
(LayoutManager)style.get(context, "InternalFrameTitlePane.titlePaneLayout");
|
|
context.dispose();
|
|
return (lm != null) ? lm : new SynthTitlePaneLayout();
|
|
}
|
|
|
|
public void propertyChange(PropertyChangeEvent evt) {
|
|
if (evt.getSource() == this) {
|
|
if (SynthLookAndFeel.shouldUpdateStyle(evt)) {
|
|
updateStyle(this);
|
|
}
|
|
}
|
|
else {
|
|
// Changes for the internal frame
|
|
if (evt.getPropertyName() == JInternalFrame.FRAME_ICON_PROPERTY) {
|
|
updateMenuIcon();
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Resets the menuButton icon to match that of the frame.
|
|
*/
|
|
private void updateMenuIcon() {
|
|
Icon frameIcon = frame.getFrameIcon();
|
|
SynthContext context = getContext(this);
|
|
if (frameIcon != null) {
|
|
Dimension maxSize = (Dimension)context.getStyle().get(context,
|
|
"InternalFrameTitlePane.maxFrameIconSize");
|
|
int maxWidth = 16;
|
|
int maxHeight = 16;
|
|
if (maxSize != null) {
|
|
maxWidth = maxSize.width;
|
|
maxHeight = maxSize.height;
|
|
}
|
|
if ((frameIcon.getIconWidth() > maxWidth ||
|
|
frameIcon.getIconHeight() > maxHeight) &&
|
|
(frameIcon instanceof ImageIcon)) {
|
|
frameIcon = new ImageIcon(((ImageIcon)frameIcon).
|
|
getImage().getScaledInstance(maxWidth, maxHeight,
|
|
Image.SCALE_SMOOTH));
|
|
}
|
|
}
|
|
context.dispose();
|
|
menuButton.setIcon(frameIcon);
|
|
}
|
|
|
|
|
|
class SynthTitlePaneLayout implements LayoutManager {
|
|
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) {
|
|
SynthContext context = getContext(
|
|
SynthInternalFrameTitlePane.this);
|
|
int width = 0;
|
|
int height = 0;
|
|
|
|
int buttonCount = 0;
|
|
Dimension pref;
|
|
|
|
if (frame.isClosable()) {
|
|
pref = closeButton.getPreferredSize();
|
|
width += pref.width;
|
|
height = Math.max(pref.height, height);
|
|
buttonCount++;
|
|
}
|
|
if (frame.isMaximizable()) {
|
|
pref = maxButton.getPreferredSize();
|
|
width += pref.width;
|
|
height = Math.max(pref.height, height);
|
|
buttonCount++;
|
|
}
|
|
if (frame.isIconifiable()) {
|
|
pref = iconButton.getPreferredSize();
|
|
width += pref.width;
|
|
height = Math.max(pref.height, height);
|
|
buttonCount++;
|
|
}
|
|
pref = menuButton.getPreferredSize();
|
|
width += pref.width;
|
|
height = Math.max(pref.height, height);
|
|
|
|
width += Math.max(0, (buttonCount - 1) * buttonSpacing);
|
|
|
|
FontMetrics fm = SynthInternalFrameTitlePane.this.getFontMetrics(
|
|
getFont());
|
|
SynthGraphicsUtils graphicsUtils = context.getStyle().
|
|
getGraphicsUtils(context);
|
|
String frameTitle = frame.getTitle();
|
|
int title_w = frameTitle != null ? graphicsUtils.
|
|
computeStringWidth(context, fm.getFont(),
|
|
fm, frameTitle) : 0;
|
|
int title_length = frameTitle != null ? frameTitle.length() : 0;
|
|
|
|
// Leave room for three characters in the title.
|
|
if (title_length > 3) {
|
|
int subtitle_w = graphicsUtils.computeStringWidth(context,
|
|
fm.getFont(), fm, frameTitle.substring(0, 3) + "...");
|
|
width += (title_w < subtitle_w) ? title_w : subtitle_w;
|
|
} else {
|
|
width += title_w;
|
|
}
|
|
|
|
height = Math.max(fm.getHeight() + 2, height);
|
|
|
|
width += titleSpacing + titleSpacing;
|
|
|
|
Insets insets = getInsets();
|
|
height += insets.top + insets.bottom;
|
|
width += insets.left + insets.right;
|
|
context.dispose();
|
|
return new Dimension(width, height);
|
|
}
|
|
|
|
private int center(Component c, Insets insets, int x,
|
|
boolean trailing) {
|
|
Dimension pref = c.getPreferredSize();
|
|
if (trailing) {
|
|
x -= pref.width;
|
|
}
|
|
c.setBounds(x, insets.top +
|
|
(getHeight() - insets.top - insets.bottom -
|
|
pref.height) / 2, pref.width, pref.height);
|
|
if (pref.width > 0) {
|
|
if (trailing) {
|
|
return x - buttonSpacing;
|
|
}
|
|
return x + pref.width + buttonSpacing;
|
|
}
|
|
return x;
|
|
}
|
|
|
|
public void layoutContainer(Container c) {
|
|
Insets insets = c.getInsets();
|
|
Dimension pref;
|
|
|
|
if (SynthLookAndFeel.isLeftToRight(frame)) {
|
|
center(menuButton, insets, insets.left, false);
|
|
int x = getWidth() - insets.right;
|
|
if (frame.isClosable()) {
|
|
x = center(closeButton, insets, x, true);
|
|
}
|
|
if (frame.isMaximizable()) {
|
|
x = center(maxButton, insets, x, true);
|
|
}
|
|
if (frame.isIconifiable()) {
|
|
x = center(iconButton, insets, x, true);
|
|
}
|
|
}
|
|
else {
|
|
center(menuButton, insets, getWidth() - insets.right,
|
|
true);
|
|
int x = insets.left;
|
|
if (frame.isClosable()) {
|
|
x = center(closeButton, insets, x, false);
|
|
}
|
|
if (frame.isMaximizable()) {
|
|
x = center(maxButton, insets, x, false);
|
|
}
|
|
if (frame.isIconifiable()) {
|
|
x = center(iconButton, insets, x, false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private JButton createNoFocusButton() {
|
|
JButton button = new JButton();
|
|
button.setFocusable(false);
|
|
button.setMargin(new Insets(0,0,0,0));
|
|
return button;
|
|
}
|
|
}
|