Search code examples
javajdesktoppane

Icons similar to desktop shortcuts inside JDesktopPane


As we are using JDesktopPane with JInternalFrames for our software, I am wondering if we can have Shortcut Icons (to particular Frame) placed inside the desktop pane (Similar to Windows desktop shortcuts). I searched for this but no luck.

Any idea guys to make this happen??


Solution

  • The following is not a "good" solution, but maybe OK-ish for certain application cases. The main difficult is that the central class that comes into play here is JInternalFrame.JDesktopIcon, and the documentation of this class contains a

    Warning:

    This API should NOT BE USED by Swing applications, as it will go away in future versions of Swing as its functionality is moved into JInternalFrame.

    However, the corresponding functionality in JInternalFrame simply is not there. And although one has to accept that the JDesktopIcon class might be removed in future versions, it seems very unlikely for me, considering the broad usage of this class in the internal Swing UI implementations.

    However: One option to achieve this is to create a custom extension of the BasicDesktopIconUI. Fortunately, this class handles most of the janitorial work, like dragging support and un-iconifying the frame on double clicks.

    As a result, one can easily sneak custom icons into such an implementation (I only used a placeholder here: A red cross on a black background. But it can be an arbitrary Image.)

    Internal Frame Icons

    This is implemented here as a MCVE. The general UI handling may be different in an actual application, but the basic idea is to create the custom UI class and assign it to the internal frame icons.

    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.Graphics2D;
    import java.awt.GridLayout;
    import java.awt.LayoutManager;
    import java.awt.image.BufferedImage;
    
    import javax.swing.Icon;
    import javax.swing.ImageIcon;
    import javax.swing.JComponent;
    import javax.swing.JDesktopPane;
    import javax.swing.JFrame;
    import javax.swing.JInternalFrame;
    import javax.swing.JLabel;
    import javax.swing.SwingConstants;
    import javax.swing.SwingUtilities;
    import javax.swing.plaf.basic.BasicDesktopIconUI;
    
    class SimpleDesktopIconUI extends BasicDesktopIconUI
    {
        private final Icon icon;
    
        SimpleDesktopIconUI(Icon icon)
        {
            this.icon = icon;
        }
    
        @Override
        protected void installComponents()
        {
            frame = desktopIcon.getInternalFrame();
            String title = frame.getTitle();
    
            JLabel label = new JLabel(title, icon, SwingConstants.CENTER);
            label.setVerticalTextPosition(JLabel.BOTTOM);
            label.setHorizontalTextPosition(JLabel.CENTER);
    
            desktopIcon.setBorder(null);
            desktopIcon.setOpaque(false);
            desktopIcon.setLayout(new GridLayout(1, 1));
            desktopIcon.add(label);
        }
    
        @Override
        protected void uninstallComponents()
        {
            desktopIcon.setLayout(null);
            desktopIcon.removeAll();
            frame = null;
        }
    
        @Override
        public Dimension getMinimumSize(JComponent c)
        {
    
            LayoutManager layout = desktopIcon.getLayout();
            Dimension size = layout.minimumLayoutSize(desktopIcon);
            return new Dimension(size.width + 15, size.height + 15);
        }
    
        @Override
        public Dimension getPreferredSize(JComponent c)
        {
            return getMinimumSize(c);
        }
    
        @Override
        public Dimension getMaximumSize(JComponent c)
        {
            return getMinimumSize(c);
        }
    }
    
    public class InternalFrameIconTest
    {
        public static void main(String[] args)
        {
            SwingUtilities.invokeLater(() -> createAndShowGUI());
        }
    
        private static void createAndShowGUI()
        {
            JFrame f = new JFrame();
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
            Icon icon = new ImageIcon(createImage());
    
            JDesktopPane desktopPane = new JDesktopPane();
    
            for (int i = 0; i < 5; i++)
            {
                String title = "Test " + i;
                if (i == 2)
                {
                    title = "Test 2 with longer title";
                }
                JInternalFrame internalFrame =
                    new JInternalFrame(title, true, true, true, true);
                internalFrame.setBounds(20 + 50 * i, 300 - 40 * i, 160, 80);
                internalFrame.setVisible(true);
                desktopPane.add(internalFrame);
    
                internalFrame.getDesktopIcon().setUI(new SimpleDesktopIconUI(icon));
            }
    
            f.getContentPane().add(desktopPane);
            f.setSize(600, 600);
            f.setLocationRelativeTo(null);
            f.setVisible(true);
        }
    
        private static BufferedImage createImage()
        {
            int w = 50;
            int h = 50;
            BufferedImage image =
                new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
            Graphics2D g = image.createGraphics();
            g.setColor(Color.BLACK);
            g.fillRect(0, 0, w, h);
            g.setColor(Color.RED);
            g.drawLine(0, 0, w, h);
            g.drawLine(0, h, w, 0);
            g.dispose();
            return image;
        }
    }