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 import sun.awt.AWTAccessor; 40 import sun.awt.AWTAccessor.MouseEventAccessor; 41 42 /** 43 * Motif rendition of the component. 44 * 45 * @author Thomas Ball 46 * @author Rich Schiavi 47 */ 48 public class MotifDesktopIconUI extends BasicDesktopIconUI 49 { 50 protected DesktopIconActionListener desktopIconActionListener; 51 protected DesktopIconMouseListener desktopIconMouseListener; 52 53 protected Icon defaultIcon; 54 protected IconButton iconButton; 55 protected IconLabel iconLabel; 56 57 // This is only used for its system menu, but we need a reference to it so 58 // we can remove its listeners. 59 private MotifInternalFrameTitlePane sysMenuTitlePane; 60 61 JPopupMenu systemMenu; 62 EventListener mml; 63 64 static final int LABEL_HEIGHT = 18; 65 static final int LABEL_DIVIDER = 4; // padding between icon and label 66 67 static final Font defaultTitleFont = 68 new Font(Font.SANS_SERIF, Font.PLAIN, 12); 69 70 public static ComponentUI createUI(JComponent c) { 71 return new MotifDesktopIconUI(); 72 } 73 74 public MotifDesktopIconUI() { 75 } 76 77 protected void installDefaults(){ 78 super.installDefaults(); 79 setDefaultIcon(UIManager.getIcon("DesktopIcon.icon")); 80 iconButton = createIconButton(defaultIcon); 81 // An underhanded way of creating a system popup menu. 82 sysMenuTitlePane = new MotifInternalFrameTitlePane(frame); 83 systemMenu = sysMenuTitlePane.getSystemMenu(); 84 85 MotifBorders.FrameBorder border = new MotifBorders.FrameBorder(desktopIcon); 86 desktopIcon.setLayout(new BorderLayout()); 87 iconButton.setBorder(border); 88 desktopIcon.add(iconButton, BorderLayout.CENTER); 89 iconLabel = createIconLabel(frame); 90 iconLabel.setBorder(border); 91 desktopIcon.add(iconLabel, BorderLayout.SOUTH); 92 desktopIcon.setSize(desktopIcon.getPreferredSize()); 93 desktopIcon.validate(); 94 JLayeredPane.putLayer(desktopIcon, JLayeredPane.getLayer(frame)); 95 } 96 97 protected void installComponents(){ 98 } 99 100 protected void uninstallComponents(){ 101 } 102 103 protected void installListeners(){ 104 super.installListeners(); 105 desktopIconActionListener = createDesktopIconActionListener(); 106 desktopIconMouseListener = createDesktopIconMouseListener(); 107 iconButton.addActionListener(desktopIconActionListener); 108 iconButton.addMouseListener(desktopIconMouseListener); 109 iconLabel.addMouseListener(desktopIconMouseListener); 110 } 111 112 JInternalFrame.JDesktopIcon getDesktopIcon(){ 113 return desktopIcon; 114 } 115 116 void setDesktopIcon(JInternalFrame.JDesktopIcon d){ 117 desktopIcon = d; 118 } 119 120 JInternalFrame getFrame(){ 121 return frame; 122 } 123 124 void setFrame(JInternalFrame f){ 125 frame = f ; 126 } 127 128 protected void showSystemMenu(){ 129 systemMenu.show(iconButton, 0, getDesktopIcon().getHeight()); 130 } 131 132 protected void hideSystemMenu(){ 133 systemMenu.setVisible(false); 134 } 135 136 protected IconLabel createIconLabel(JInternalFrame frame){ 137 return new IconLabel(frame); 138 } 139 140 protected IconButton createIconButton(Icon i){ 141 return new IconButton(i); 142 } 143 144 protected DesktopIconActionListener createDesktopIconActionListener(){ 145 return new DesktopIconActionListener(); 146 } 147 148 protected DesktopIconMouseListener createDesktopIconMouseListener(){ 149 return new DesktopIconMouseListener(); 150 } 151 152 protected void uninstallDefaults(){ 153 super.uninstallDefaults(); 154 desktopIcon.setLayout(null); 155 desktopIcon.remove(iconButton); 156 desktopIcon.remove(iconLabel); 157 } 158 159 protected void uninstallListeners(){ 160 super.uninstallListeners(); 161 iconButton.removeActionListener(desktopIconActionListener); 162 iconButton.removeMouseListener(desktopIconMouseListener); 163 sysMenuTitlePane.uninstallListeners(); 164 } 165 166 public Dimension getMinimumSize(JComponent c) { 167 JInternalFrame iframe = desktopIcon.getInternalFrame(); 168 169 int w = defaultIcon.getIconWidth(); 170 int h = defaultIcon.getIconHeight() + LABEL_HEIGHT + LABEL_DIVIDER; 171 172 Border border = iframe.getBorder(); 173 if(border != null) { 174 w += border.getBorderInsets(iframe).left + 175 border.getBorderInsets(iframe).right; 176 h += border.getBorderInsets(iframe).bottom + 177 border.getBorderInsets(iframe).top; 178 } 179 180 return new Dimension(w, h); 181 } 182 183 public Dimension getPreferredSize(JComponent c) { 184 return getMinimumSize(c); 185 } 186 187 public Dimension getMaximumSize(JComponent c){ 188 return getMinimumSize(c); 189 } 190 191 /** 192 * Returns the default desktop icon. 193 */ 194 public Icon getDefaultIcon() { 195 return defaultIcon; 196 } 197 198 /** 199 * Sets the icon used as the default desktop icon. 200 */ 201 public void setDefaultIcon(Icon newIcon) { 202 defaultIcon = newIcon; 203 } 204 205 @SuppressWarnings("serial") // Superclass is not serializable across versions 206 protected class IconLabel extends JPanel { 207 JInternalFrame frame; 208 209 IconLabel(JInternalFrame f) { 210 super(); 211 this.frame = f; 212 setFont(defaultTitleFont); 213 214 // Forward mouse events to titlebar for moves. 215 addMouseMotionListener(new MouseMotionListener() { 216 public void mouseDragged(MouseEvent e) { 217 forwardEventToParent(e); 218 } 219 public void mouseMoved(MouseEvent e) { 220 forwardEventToParent(e); 221 } 222 }); 223 addMouseListener(new MouseListener() { 224 public void mouseClicked(MouseEvent e) { 225 forwardEventToParent(e); 226 } 227 public void mousePressed(MouseEvent e) { 228 forwardEventToParent(e); 229 } 230 public void mouseReleased(MouseEvent e) { 231 forwardEventToParent(e); 232 } 233 public void mouseEntered(MouseEvent e) { 234 forwardEventToParent(e); 235 } 236 public void mouseExited(MouseEvent e) { 237 forwardEventToParent(e); 238 } 239 }); 240 } 241 @SuppressWarnings("deprecation") 242 void forwardEventToParent(MouseEvent e) { 243 MouseEvent newEvent = new MouseEvent( 244 getParent(), e.getID(), e.getWhen(), e.getModifiers(), 245 e.getX(), e.getY(), e.getXOnScreen(), 246 e.getYOnScreen(), e.getClickCount(), 247 e.isPopupTrigger(), MouseEvent.NOBUTTON); 248 MouseEventAccessor meAccessor = AWTAccessor.getMouseEventAccessor(); 249 meAccessor.setCausedByTouchEvent(newEvent, 250 meAccessor.isCausedByTouchEvent(e)); 251 getParent().dispatchEvent(newEvent); 252 } 253 254 @SuppressWarnings("deprecation") 255 public boolean isFocusTraversable() { 256 return false; 257 } 258 259 public Dimension getMinimumSize() { 260 return new Dimension(defaultIcon.getIconWidth() + 1, 261 LABEL_HEIGHT + LABEL_DIVIDER); 262 } 263 264 public Dimension getPreferredSize() { 265 String title = frame.getTitle(); 266 FontMetrics fm = frame.getFontMetrics(defaultTitleFont); 267 int w = 4; 268 if (title != null) { 269 w += SwingUtilities2.stringWidth(frame, fm, title); 270 } 271 return new Dimension(w, LABEL_HEIGHT + LABEL_DIVIDER); 272 } 273 274 public void paint(Graphics g) { 275 super.paint(g); 276 277 // touch-up frame 278 int maxX = getWidth() - 1; 279 Color shadow = 280 UIManager.getColor("inactiveCaptionBorder").darker().darker(); 281 g.setColor(shadow); 282 g.setClip(0, 0, getWidth(), getHeight()); 283 g.drawLine(maxX - 1, 1, maxX - 1, 1); 284 g.drawLine(maxX, 0, maxX, 0); 285 286 // fill background 287 g.setColor(UIManager.getColor("inactiveCaption")); 288 g.fillRect(2, 1, maxX - 3, LABEL_HEIGHT + 1); 289 290 // draw text -- clipping to truncate text like CDE/Motif 291 g.setClip(2, 1, maxX - 4, LABEL_HEIGHT); 292 int y = LABEL_HEIGHT - SwingUtilities2.getFontMetrics(frame, g). 293 getDescent(); 294 g.setColor(UIManager.getColor("inactiveCaptionText")); 295 String title = frame.getTitle(); 296 if (title != null) { 297 SwingUtilities2.drawString(frame, g, title, 4, y); 298 } 299 } 300 } 301 302 @SuppressWarnings("serial") // Superclass is not serializable across versions 303 protected class IconButton extends JButton { 304 Icon icon; 305 306 IconButton(Icon icon) { 307 super(icon); 308 this.icon = icon; 309 // Forward mouse events to titlebar for moves. 310 addMouseMotionListener(new MouseMotionListener() { 311 public void mouseDragged(MouseEvent e) { 312 forwardEventToParent(e); 313 } 314 public void mouseMoved(MouseEvent e) { 315 forwardEventToParent(e); 316 } 317 }); 318 addMouseListener(new MouseListener() { 319 public void mouseClicked(MouseEvent e) { 320 forwardEventToParent(e); 321 } 322 public void mousePressed(MouseEvent e) { 323 forwardEventToParent(e); 324 } 325 public void mouseReleased(MouseEvent e) { 326 if (!systemMenu.isShowing()) { 327 forwardEventToParent(e); 328 } 329 } 330 public void mouseEntered(MouseEvent e) { 331 forwardEventToParent(e); 332 } 333 public void mouseExited(MouseEvent e) { 334 forwardEventToParent(e); 335 } 336 }); 337 } 338 @SuppressWarnings("deprecation") 339 void forwardEventToParent(MouseEvent e) { 340 MouseEvent newEvent = new MouseEvent( 341 getParent(), e.getID(), e.getWhen(), e.getModifiers(), 342 e.getX(), e.getY(), e.getXOnScreen(), e.getYOnScreen(), 343 e.getClickCount(), e.isPopupTrigger(), MouseEvent.NOBUTTON ); 344 MouseEventAccessor meAccessor = AWTAccessor.getMouseEventAccessor(); 345 meAccessor.setCausedByTouchEvent(newEvent, 346 meAccessor.isCausedByTouchEvent(e)); 347 getParent().dispatchEvent(newEvent); 348 } 349 350 @SuppressWarnings("deprecation") 351 public boolean isFocusTraversable() { 352 return false; 353 } 354 } 355 356 357 protected class DesktopIconActionListener implements ActionListener { 358 public void actionPerformed(ActionEvent e){ 359 systemMenu.show(iconButton, 0, getDesktopIcon().getHeight()); 360 } 361 } 362 363 protected class DesktopIconMouseListener extends MouseAdapter { 364 // if we drag or move we should deengage the popup 365 public void mousePressed(MouseEvent e){ 366 if (e.getClickCount() > 1) { 367 try { 368 getFrame().setIcon(false); 369 } catch (PropertyVetoException e2){ } 370 systemMenu.setVisible(false); 371 /* the mouse release will not get reported correctly, 372 because the icon will no longer be in the hierarchy; 373 maybe that should be fixed, but until it is, we need 374 to do the required cleanup here. */ 375 getFrame().getDesktopPane().getDesktopManager().endDraggingFrame((JComponent)e.getSource()); 376 } 377 } 378 } 379 }