Path: blob/master/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFrameDockIconUI.java
41154 views
/*1* Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package com.apple.laf;2627import java.awt.*;28import java.awt.event.*;29import java.awt.geom.Rectangle2D;30import java.awt.image.BufferedImage;31import java.beans.PropertyVetoException;3233import javax.swing.*;34import javax.swing.plaf.*;3536import sun.swing.SwingUtilities2;3738/**39* From MacDockIconUI40*41* A JRSUI L&F implementation of JInternalFrame.JDesktopIcon42*/43public final class AquaInternalFrameDockIconUI extends DesktopIconUI44implements MouseListener, MouseMotionListener {4546private JInternalFrame.JDesktopIcon fDesktopIcon;47private JInternalFrame fFrame;48private ScaledImageLabel fIconPane;49private DockLabel fDockLabel;50private boolean fTrackingIcon;5152public static ComponentUI createUI(final JComponent c) {53return new AquaInternalFrameDockIconUI();54}5556@Override57public void installUI(final JComponent c) {58fDesktopIcon = (JInternalFrame.JDesktopIcon)c;59installComponents();60installListeners();61}6263@Override64public void uninstallUI(final JComponent c) {65uninstallComponents();66uninstallListeners();67fDesktopIcon = null;68fFrame = null;69}7071private void installComponents() {72fFrame = fDesktopIcon.getInternalFrame();73fIconPane = new ScaledImageLabel();74fDesktopIcon.setLayout(new BorderLayout());75fDesktopIcon.add(fIconPane, BorderLayout.CENTER);76}7778private void uninstallComponents() {79fDesktopIcon.setLayout(null);80fDesktopIcon.remove(fIconPane);81}8283private void installListeners() {84fDesktopIcon.addMouseListener(this);85fDesktopIcon.addMouseMotionListener(this);86}8788private void uninstallListeners() {89fDesktopIcon.removeMouseMotionListener(this);90fDesktopIcon.removeMouseListener(this);91}9293@Override94public Dimension getMinimumSize(final JComponent c) {95return new Dimension(32, 32);96}9798@Override99public Dimension getMaximumSize(final JComponent c) {100return new Dimension(128, 128);101}102103@Override104public Dimension getPreferredSize(final JComponent c) {105return new Dimension(64, 64); //$ Dock preferred size106}107108void updateIcon() {109fIconPane.updateIcon();110}111112@Override113public void mousePressed(final MouseEvent e) {114fTrackingIcon = fIconPane.mouseInIcon(e);115if (fTrackingIcon) fIconPane.repaint();116}117118@Override119public void mouseReleased(final MouseEvent e) {// only when it's actually in the image120if (fFrame.isIconifiable() && fFrame.isIcon()) {121if (fTrackingIcon) {122fTrackingIcon = false;123if (fIconPane.mouseInIcon(e)) {124if (fDockLabel != null) fDockLabel.hide();125try {126fFrame.setIcon(false);127} catch(final PropertyVetoException e2) {}128} else {129fIconPane.repaint();130}131}132}133134// if the mouse was completely outside fIconPane, hide the label135if (fDockLabel != null && !fIconPane.getBounds().contains(e.getX(), e.getY())) fDockLabel.hide();136}137138@Override139@SuppressWarnings("deprecation")140public void mouseEntered(final MouseEvent e) {141if ((e.getModifiers() & InputEvent.BUTTON1_MASK) != 0) return;142String title = fFrame.getTitle();143if (title == null || title.isEmpty()) title = "Untitled";144fDockLabel = new DockLabel(title);145fDockLabel.show(fDesktopIcon);146}147148@Override149@SuppressWarnings("deprecation")150public void mouseExited(final MouseEvent e) {151if (fDockLabel != null && (e.getModifiers() & InputEvent.BUTTON1_MASK) == 0) fDockLabel.hide();152}153154@Override155public void mouseClicked(final MouseEvent e) { }156157@Override158public void mouseDragged(final MouseEvent e) { }159160@Override161public void mouseMoved(final MouseEvent e) { }162163@SuppressWarnings("serial") // Superclass is not serializable across versions164private final class ScaledImageLabel extends JLabel {165ScaledImageLabel() {166super(null, null, CENTER);167}168169void updateIcon() {170int width = fFrame.getWidth();171int height = fFrame.getHeight();172173// Protect us from unsized frames, like in JCK test DefaultDesktopManager2008174if (width <= 0 || height <= 0) {175width = 128;176height = 128;177}178179final Image fImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB_PRE);180final Graphics g = fImage.getGraphics();181fFrame.paint(g);182g.dispose();183184final float scale = (float)fDesktopIcon.getWidth() / (float)Math.max(width, height) * 0.89f;185// Sending in -1 for width xor height causes it to maintain aspect ratio186setIcon(new ImageIcon(fImage.getScaledInstance((int)(width * scale), -1, Image.SCALE_SMOOTH)));187}188189@Override190public void paint(final Graphics g) {191if (getIcon() == null) updateIcon();192193g.translate(0, 2);194195if (!fTrackingIcon) {196super.paint(g);197return;198}199200final ImageIcon prev = (ImageIcon)getIcon();201final ImageIcon pressedIcon = new ImageIcon(AquaUtils.generateSelectedDarkImage(prev.getImage()));202setIcon(pressedIcon);203super.paint(g);204setIcon(prev);205}206207boolean mouseInIcon(final MouseEvent e) {208return getBounds().contains(e.getX(), e.getY());209}210211@Override212public Dimension getPreferredSize() {213return new Dimension(64, 64); //$ Dock preferred size214}215}216217@SuppressWarnings("serial") // Superclass is not serializable across versions218private static final class DockLabel extends JLabel {219static final int NUB_HEIGHT = 7;220static final int ROUND_ADDITIONAL_HEIGHT = 8;221static final int ROUND_ADDITIONAL_WIDTH = 12;222223DockLabel(final String text) {224super(text);225setBorder(null);226setOpaque(false);227setFont(AquaFonts.getDockIconFont());228229final FontMetrics metrics = getFontMetrics(getFont());230setSize(SwingUtilities.computeStringWidth(metrics, getText()) + ROUND_ADDITIONAL_WIDTH * 2, metrics.getAscent() + NUB_HEIGHT + ROUND_ADDITIONAL_HEIGHT);231}232233@Override234public void paint(final Graphics g) {235final int width = getWidth();236final int height = getHeight();237238final Font font = getFont();239final FontMetrics metrics = getFontMetrics(font);240g.setFont(font);241242final String text = getText().trim();243final int ascent = metrics.getAscent();244245final Rectangle2D stringBounds = metrics.getStringBounds(text, g);246final int halfway = width / 2;247248final int x = (halfway - (int)stringBounds.getWidth() / 2);249250final Graphics2D g2d = g instanceof Graphics2D ? (Graphics2D)g : null;251if (g2d != null) {252g.setColor(UIManager.getColor("DesktopIcon.labelBackground"));253final Object origAA = g2d.getRenderingHint(RenderingHints.KEY_ANTIALIASING);254g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);255256final int roundHeight = height - ROUND_ADDITIONAL_HEIGHT + 1;257g.fillRoundRect(0, 0, width, roundHeight, roundHeight, roundHeight);258259final int[] xpts = { halfway, halfway + NUB_HEIGHT, halfway - NUB_HEIGHT };260final int[] ypts = { height, height - NUB_HEIGHT, height - NUB_HEIGHT };261g.fillPolygon(xpts, ypts, 3);262263g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, origAA);264}265266g.setColor(Color.black);267SwingUtilities2.drawString(this, g, text, x, 2 + ascent);268g.setColor(Color.white);269SwingUtilities2.drawString(this, g, text, x, 1 + ascent);270}271272public void show(final Component invoker) {273final int desiredLocationX = (invoker.getWidth() - getWidth()) / 2;274final int desiredLocationY = -(getHeight() + 6);275276Container parent = invoker.getParent();277278for (Container p = parent; p != null; p = p.getParent()) {279if (p instanceof JRootPane) {280if (p.getParent() instanceof JInternalFrame) continue;281parent = ((JRootPane)p).getLayeredPane();282for (p = parent.getParent(); p != null && (!(p instanceof java.awt.Window)); p = p.getParent());283break;284}285}286287final Point p = SwingUtilities.convertPoint(invoker, desiredLocationX, desiredLocationY, parent);288setLocation(p.x, p.y);289if (parent instanceof JLayeredPane) {290((JLayeredPane)parent).add(this, JLayeredPane.POPUP_LAYER, 0);291}292}293294@Override295@Deprecated296public void hide() {297final Container parent = getParent();298final Rectangle r = this.getBounds();299if (parent == null) return;300parent.remove(this);301parent.repaint(r.x, r.y, r.width, r.height);302}303}304}305306307