1 /* 2 * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.java.swing.plaf.motif; 27 28 import sun.swing.SwingUtilities2; 29 import java.awt.*; 30 import java.awt.event.*; 31 import javax.swing.*; 32 import javax.swing.border.*; 33 import javax.swing.plaf.*; 34 import javax.swing.plaf.basic.*; 35 import java.beans.*; 36 import java.util.EventListener; 37 import java.io.Serializable; 38 39 40 /** 41 * Motif rendition of the component. 42 * 43 * @author Thomas Ball 44 * @author Rich Schiavi 45 */ 46 public class MotifDesktopIconUI extends BasicDesktopIconUI 47 { 48 protected DesktopIconActionListener desktopIconActionListener; 49 protected DesktopIconMouseListener desktopIconMouseListener; 50 51 protected Icon defaultIcon; 52 protected IconButton iconButton; 53 protected IconLabel iconLabel; 54 55 // This is only used for its system menu, but we need a reference to it so 56 // we can remove its listeners. 57 private MotifInternalFrameTitlePane sysMenuTitlePane; 58 59 JPopupMenu systemMenu; 60 EventListener mml; 61 62 final static int LABEL_HEIGHT = 18; 63 final static int LABEL_DIVIDER = 4; // padding between icon and label 64 65 final static Font defaultTitleFont = 66 new Font(Font.SANS_SERIF, Font.PLAIN, 12); 67 68 public static ComponentUI createUI(JComponent c) { 69 return new MotifDesktopIconUI(); 70 } 71 72 public MotifDesktopIconUI() { 73 } 74 75 protected void installDefaults(){ 76 super.installDefaults(); 77 setDefaultIcon(UIManager.getIcon("DesktopIcon.icon")); 78 iconButton = createIconButton(defaultIcon); 79 // An underhanded way of creating a system popup menu. 80 sysMenuTitlePane = new MotifInternalFrameTitlePane(frame); 81 systemMenu = sysMenuTitlePane.getSystemMenu(); 82 83 MotifBorders.FrameBorder border = new MotifBorders.FrameBorder(desktopIcon); 84 desktopIcon.setLayout(new BorderLayout()); 85 iconButton.setBorder(border); 86 desktopIcon.add(iconButton, BorderLayout.CENTER); 87 iconLabel = createIconLabel(frame); 88 iconLabel.setBorder(border); 89 desktopIcon.add(iconLabel, BorderLayout.SOUTH); 90 desktopIcon.setSize(desktopIcon.getPreferredSize()); 91 desktopIcon.validate(); 92 JLayeredPane.putLayer(desktopIcon, JLayeredPane.getLayer(frame)); 93 } 94 95 protected void installComponents(){ 96 } 97 98 protected void uninstallComponents(){ 99 } 100 101 protected void installListeners(){ 102 super.installListeners(); 103 desktopIconActionListener = createDesktopIconActionListener(); 104 desktopIconMouseListener = createDesktopIconMouseListener(); 105 iconButton.addActionListener(desktopIconActionListener); 106 iconButton.addMouseListener(desktopIconMouseListener); 107 iconLabel.addMouseListener(desktopIconMouseListener); 108 } 109 110 JInternalFrame.JDesktopIcon getDesktopIcon(){ 111 return desktopIcon; 112 } 113 114 void setDesktopIcon(JInternalFrame.JDesktopIcon d){ 115 desktopIcon = d; 116 } 117 118 JInternalFrame getFrame(){ 119 return frame; 120 } 121 122 void setFrame(JInternalFrame f){ 123 frame = f ; 124 } 125 126 protected void showSystemMenu(){ 127 systemMenu.show(iconButton, 0, getDesktopIcon().getHeight()); 128 } 129 130 protected void hideSystemMenu(){ 131 systemMenu.setVisible(false); 132 } 133 134 protected IconLabel createIconLabel(JInternalFrame frame){ 135 return new IconLabel(frame); 136 } 137 138 protected IconButton createIconButton(Icon i){ 139 return new IconButton(i); 140 } 141 142 protected DesktopIconActionListener createDesktopIconActionListener(){ 143 return new DesktopIconActionListener(); 144 } 145 146 protected DesktopIconMouseListener createDesktopIconMouseListener(){ 147 return new DesktopIconMouseListener(); 148 } 149 150 protected void uninstallDefaults(){ 151 super.uninstallDefaults(); 152 desktopIcon.setLayout(null); 153 desktopIcon.remove(iconButton); 154 desktopIcon.remove(iconLabel); 155 } 156 157 protected void uninstallListeners(){ 158 super.uninstallListeners(); 159 iconButton.removeActionListener(desktopIconActionListener); 160 iconButton.removeMouseListener(desktopIconMouseListener); 161 sysMenuTitlePane.uninstallListeners(); 162 } 163 164 public Dimension getMinimumSize(JComponent c) { 165 JInternalFrame iframe = desktopIcon.getInternalFrame(); 166 167 int w = defaultIcon.getIconWidth(); 168 int h = defaultIcon.getIconHeight() + LABEL_HEIGHT + LABEL_DIVIDER; 169 170 Border border = iframe.getBorder(); 171 if(border != null) { 172 w += border.getBorderInsets(iframe).left + 173 border.getBorderInsets(iframe).right; 174 h += border.getBorderInsets(iframe).bottom + 175 border.getBorderInsets(iframe).top; 176 } 177 178 return new Dimension(w, h); 179 } 180 181 public Dimension getPreferredSize(JComponent c) { 182 return getMinimumSize(c); 183 } 184 185 public Dimension getMaximumSize(JComponent c){ 186 return getMinimumSize(c); 187 } 188 189 /** 190 * Returns the default desktop icon. 191 */ 192 public Icon getDefaultIcon() { 193 return defaultIcon; 194 } 195 196 /** 197 * Sets the icon used as the default desktop icon. 198 */ 199 public void setDefaultIcon(Icon newIcon) { 200 defaultIcon = newIcon; 201 } 202 203 @SuppressWarnings("serial") // Superclass is not serializable across versions 204 protected class IconLabel extends JPanel { 205 JInternalFrame frame; 206 207 IconLabel(JInternalFrame f) { 208 super(); 209 this.frame = f; 210 setFont(defaultTitleFont); 211 212 // Forward mouse events to titlebar for moves. 213 addMouseMotionListener(new MouseMotionListener() { 214 public void mouseDragged(MouseEvent e) { 215 forwardEventToParent(e); 216 } 217 public void mouseMoved(MouseEvent e) { 218 forwardEventToParent(e); 219 } 220 }); 221 addMouseListener(new MouseListener() { 222 public void mouseClicked(MouseEvent e) { 223 forwardEventToParent(e); 224 } 225 public void mousePressed(MouseEvent e) { 226 forwardEventToParent(e); 227 } 228 public void mouseReleased(MouseEvent e) { 229 forwardEventToParent(e); 230 } 231 public void mouseEntered(MouseEvent e) { 232 forwardEventToParent(e); 233 } 234 public void mouseExited(MouseEvent e) { 235 forwardEventToParent(e); 236 } 237 }); 238 } 239 240 void forwardEventToParent(MouseEvent e) { 241 getParent().dispatchEvent(new MouseEvent( 242 getParent(), e.getID(), e.getWhen(), e.getModifiers(), 243 e.getX(), e.getY(), e.getXOnScreen(), 244 e.getYOnScreen(), e.getClickCount(), 245 e.isPopupTrigger(), MouseEvent.NOBUTTON)); 246 } 247 248 @SuppressWarnings("deprecation") 249 public boolean isFocusTraversable() { 250 return false; 251 } 252 253 public Dimension getMinimumSize() { 254 return new Dimension(defaultIcon.getIconWidth() + 1, 255 LABEL_HEIGHT + LABEL_DIVIDER); 256 } 257 258 public Dimension getPreferredSize() { 259 String title = frame.getTitle(); 260 FontMetrics fm = frame.getFontMetrics(defaultTitleFont); 261 int w = 4; 262 if (title != null) { 263 w += SwingUtilities2.stringWidth(frame, fm, title); 264 } 265 return new Dimension(w, LABEL_HEIGHT + LABEL_DIVIDER); 266 } 267 268 public void paint(Graphics g) { 269 super.paint(g); 270 271 // touch-up frame 272 int maxX = getWidth() - 1; 273 Color shadow = 274 UIManager.getColor("inactiveCaptionBorder").darker().darker(); 275 g.setColor(shadow); 276 g.setClip(0, 0, getWidth(), getHeight()); 277 g.drawLine(maxX - 1, 1, maxX - 1, 1); 278 g.drawLine(maxX, 0, maxX, 0); 279 280 // fill background 281 g.setColor(UIManager.getColor("inactiveCaption")); 282 g.fillRect(2, 1, maxX - 3, LABEL_HEIGHT + 1); 283 284 // draw text -- clipping to truncate text like CDE/Motif 285 g.setClip(2, 1, maxX - 4, LABEL_HEIGHT); 286 int y = LABEL_HEIGHT - SwingUtilities2.getFontMetrics(frame, g). 287 getDescent(); 288 g.setColor(UIManager.getColor("inactiveCaptionText")); 289 String title = frame.getTitle(); 290 if (title != null) { 291 SwingUtilities2.drawString(frame, g, title, 4, y); 292 } 293 } 294 } 295 296 @SuppressWarnings("serial") // Superclass is not serializable across versions 297 protected class IconButton extends JButton { 298 Icon icon; 299 300 IconButton(Icon icon) { 301 super(icon); 302 this.icon = icon; 303 // Forward mouse events to titlebar for moves. 304 addMouseMotionListener(new MouseMotionListener() { 305 public void mouseDragged(MouseEvent e) { 306 forwardEventToParent(e); 307 } 308 public void mouseMoved(MouseEvent e) { 309 forwardEventToParent(e); 310 } 311 }); 312 addMouseListener(new MouseListener() { 313 public void mouseClicked(MouseEvent e) { 314 forwardEventToParent(e); 315 } 316 public void mousePressed(MouseEvent e) { 317 forwardEventToParent(e); 318 } 319 public void mouseReleased(MouseEvent e) { 320 if (!systemMenu.isShowing()) { 321 forwardEventToParent(e); 322 } 323 } 324 public void mouseEntered(MouseEvent e) { 325 forwardEventToParent(e); 326 } 327 public void mouseExited(MouseEvent e) { 328 forwardEventToParent(e); 329 } 330 }); 331 } 332 333 void forwardEventToParent(MouseEvent e) { 334 getParent().dispatchEvent(new MouseEvent( 335 getParent(), e.getID(), e.getWhen(), e.getModifiers(), 336 e.getX(), e.getY(), e.getXOnScreen(), e.getYOnScreen(), 337 e.getClickCount(), e.isPopupTrigger(), MouseEvent.NOBUTTON )); 338 } 339 340 @SuppressWarnings("deprecation") 341 public boolean isFocusTraversable() { 342 return false; 343 } 344 } 345 346 347 protected class DesktopIconActionListener implements ActionListener { 348 public void actionPerformed(ActionEvent e){ 349 systemMenu.show(iconButton, 0, getDesktopIcon().getHeight()); 350 } 351 } 352 353 protected class DesktopIconMouseListener extends MouseAdapter { 354 // if we drag or move we should deengage the popup 355 public void mousePressed(MouseEvent e){ 356 if (e.getClickCount() > 1) { 357 try { 358 getFrame().setIcon(false); 359 } catch (PropertyVetoException e2){ } 360 systemMenu.setVisible(false); 361 /* the mouse release will not get reported correctly, 362 because the icon will no longer be in the hierarchy; 363 maybe that should be fixed, but until it is, we need 364 to do the required cleanup here. */ 365 getFrame().getDesktopPane().getDesktopManager().endDraggingFrame((JComponent)e.getSource()); 366 } 367 } 368 } 369 }