1 /* 2 * Copyright (c) 2002, 2010, 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 javax.swing.plaf.synth; 27 28 import javax.swing.*; 29 import javax.swing.border.*; 30 import javax.swing.plaf.*; 31 import javax.swing.plaf.basic.BasicDesktopPaneUI; 32 import java.beans.*; 33 import java.awt.event.*; 34 import java.awt.*; 35 36 /** 37 * Provides the Synth L&F UI delegate for 38 * {@link javax.swing.JDesktopPane}. 39 * 40 * @author Joshua Outwater 41 * @author Steve Wilson 42 * @since 1.7 43 */ 44 public class SynthDesktopPaneUI extends BasicDesktopPaneUI implements 45 PropertyChangeListener, SynthUI { 46 private SynthStyle style; 47 private TaskBar taskBar; 48 private DesktopManager oldDesktopManager; 49 50 /** 51 * Creates a new UI object for the given component. 52 * 53 * @param c component to create UI object for 54 * @return the UI object 55 */ 56 public static ComponentUI createUI(JComponent c) { 57 return new SynthDesktopPaneUI(); 58 } 59 60 /** 61 * @inheritDoc 62 */ 63 @Override 64 protected void installListeners() { 65 super.installListeners(); 66 desktop.addPropertyChangeListener(this); 67 if (taskBar != null) { 68 // Listen for desktop being resized 69 desktop.addComponentListener(taskBar); 70 // Listen for frames being added to desktop 71 desktop.addContainerListener(taskBar); 72 } 73 } 74 75 /** 76 * @inheritDoc 77 */ 78 @Override 79 protected void installDefaults() { 80 updateStyle(desktop); 81 82 if (UIManager.getBoolean("InternalFrame.useTaskBar")) { 83 taskBar = new TaskBar(); 84 85 for (Component comp : desktop.getComponents()) { 86 JInternalFrame.JDesktopIcon desktopIcon; 87 88 if (comp instanceof JInternalFrame.JDesktopIcon) { 89 desktopIcon = (JInternalFrame.JDesktopIcon)comp; 90 } else if (comp instanceof JInternalFrame) { 91 desktopIcon = ((JInternalFrame)comp).getDesktopIcon(); 92 } else { 93 continue; 94 } 95 // Move desktopIcon from desktop to taskBar 96 if (desktopIcon.getParent() == desktop) { 97 desktop.remove(desktopIcon); 98 } 99 if (desktopIcon.getParent() != taskBar) { 100 taskBar.add(desktopIcon); 101 desktopIcon.getInternalFrame().addComponentListener( 102 taskBar); 103 } 104 } 105 taskBar.setBackground(desktop.getBackground()); 106 desktop.add(taskBar, 107 Integer.valueOf(JLayeredPane.PALETTE_LAYER.intValue() + 1)); 108 if (desktop.isShowing()) { 109 taskBar.adjustSize(); 110 } 111 } 112 } 113 114 private void updateStyle(JDesktopPane c) { 115 SynthStyle oldStyle = style; 116 SynthContext context = getContext(c, ENABLED); 117 style = SynthLookAndFeel.updateStyle(context, this); 118 if (oldStyle != null) { 119 uninstallKeyboardActions(); 120 installKeyboardActions(); 121 } 122 context.dispose(); 123 } 124 125 /** 126 * @inheritDoc 127 */ 128 @Override 129 protected void uninstallListeners() { 130 if (taskBar != null) { 131 desktop.removeComponentListener(taskBar); 132 desktop.removeContainerListener(taskBar); 133 } 134 desktop.removePropertyChangeListener(this); 135 super.uninstallListeners(); 136 } 137 138 /** 139 * @inheritDoc 140 */ 141 @Override 142 protected void uninstallDefaults() { 143 SynthContext context = getContext(desktop, ENABLED); 144 145 style.uninstallDefaults(context); 146 context.dispose(); 147 style = null; 148 149 if (taskBar != null) { 150 for (Component comp : taskBar.getComponents()) { 151 JInternalFrame.JDesktopIcon desktopIcon = 152 (JInternalFrame.JDesktopIcon)comp; 153 taskBar.remove(desktopIcon); 154 desktopIcon.setPreferredSize(null); 155 JInternalFrame f = desktopIcon.getInternalFrame(); 156 if (f.isIcon()) { 157 desktop.add(desktopIcon); 158 } 159 f.removeComponentListener(taskBar); 160 } 161 desktop.remove(taskBar); 162 taskBar = null; 163 } 164 } 165 166 /** 167 * @inheritDoc 168 */ 169 @Override 170 protected void installDesktopManager() { 171 if (UIManager.getBoolean("InternalFrame.useTaskBar")) { 172 desktopManager = oldDesktopManager = desktop.getDesktopManager(); 173 if (!(desktopManager instanceof SynthDesktopManager)) { 174 desktopManager = new SynthDesktopManager(); 175 desktop.setDesktopManager(desktopManager); 176 } 177 } else { 178 super.installDesktopManager(); 179 } 180 } 181 182 /** 183 * @inheritDoc 184 */ 185 @Override 186 protected void uninstallDesktopManager() { 187 if (oldDesktopManager != null && !(oldDesktopManager instanceof UIResource)) { 188 desktopManager = desktop.getDesktopManager(); 189 if (desktopManager == null || desktopManager instanceof UIResource) { 190 desktop.setDesktopManager(oldDesktopManager); 191 } 192 } 193 oldDesktopManager = null; 194 super.uninstallDesktopManager(); 195 } 196 197 static class TaskBar extends JPanel implements ComponentListener, ContainerListener { 198 TaskBar() { 199 setOpaque(true); 200 setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0) { 201 public void layoutContainer(Container target) { 202 // First shrink buttons to fit 203 Component[] comps = target.getComponents(); 204 int n = comps.length; 205 if (n > 0) { 206 // Start with the largest preferred width 207 int prefWidth = 0; 208 for (Component c : comps) { 209 c.setPreferredSize(null); 210 Dimension prefSize = c.getPreferredSize(); 211 if (prefSize.width > prefWidth) { 212 prefWidth = prefSize.width; 213 } 214 } 215 // Shrink equally to fit if needed 216 Insets insets = target.getInsets(); 217 int tw = target.getWidth() - insets.left - insets.right; 218 int w = Math.min(prefWidth, Math.max(10, tw/n)); 219 for (Component c : comps) { 220 Dimension prefSize = c.getPreferredSize(); 221 c.setPreferredSize(new Dimension(w, prefSize.height)); 222 } 223 } 224 super.layoutContainer(target); 225 } 226 }); 227 228 // PENDING: This should be handled by the painter 229 setBorder(new BevelBorder(BevelBorder.RAISED) { 230 protected void paintRaisedBevel(Component c, Graphics g, 231 int x, int y, int w, int h) { 232 Color oldColor = g.getColor(); 233 g.translate(x, y); 234 g.setColor(getHighlightOuterColor(c)); 235 g.drawLine(0, 0, 0, h-2); 236 g.drawLine(1, 0, w-2, 0); 237 g.setColor(getShadowOuterColor(c)); 238 g.drawLine(0, h-1, w-1, h-1); 239 g.drawLine(w-1, 0, w-1, h-2); 240 g.translate(-x, -y); 241 g.setColor(oldColor); 242 } 243 }); 244 } 245 246 void adjustSize() { 247 JDesktopPane desktop = (JDesktopPane)getParent(); 248 if (desktop != null) { 249 int height = getPreferredSize().height; 250 Insets insets = getInsets(); 251 if (height == insets.top + insets.bottom) { 252 if (getHeight() <= height) { 253 // Initial size, because we have no buttons yet 254 height += 21; 255 } else { 256 // We already have a good height 257 height = getHeight(); 258 } 259 } 260 setBounds(0, desktop.getHeight() - height, desktop.getWidth(), height); 261 revalidate(); 262 repaint(); 263 } 264 } 265 266 // ComponentListener interface 267 268 public void componentResized(ComponentEvent e) { 269 if (e.getSource() instanceof JDesktopPane) { 270 adjustSize(); 271 } 272 } 273 274 public void componentMoved(ComponentEvent e){} 275 276 public void componentShown(ComponentEvent e) { 277 if (e.getSource() instanceof JInternalFrame) { 278 adjustSize(); 279 } 280 } 281 282 public void componentHidden(ComponentEvent e) { 283 if (e.getSource() instanceof JInternalFrame) { 284 ((JInternalFrame)e.getSource()).getDesktopIcon().setVisible(false); 285 revalidate(); 286 } 287 } 288 289 // ContainerListener interface 290 291 public void componentAdded(ContainerEvent e) { 292 if (e.getChild() instanceof JInternalFrame) { 293 JDesktopPane desktop = (JDesktopPane)e.getSource(); 294 JInternalFrame f = (JInternalFrame)e.getChild(); 295 JInternalFrame.JDesktopIcon desktopIcon = f.getDesktopIcon(); 296 for (Component comp : getComponents()) { 297 if (comp == desktopIcon) { 298 // We have it already 299 return; 300 } 301 } 302 add(desktopIcon); 303 f.addComponentListener(this); 304 if (getComponentCount() == 1) { 305 adjustSize(); 306 } 307 } 308 } 309 310 public void componentRemoved(ContainerEvent e) { 311 if (e.getChild() instanceof JInternalFrame) { 312 JInternalFrame f = (JInternalFrame)e.getChild(); 313 if (!f.isIcon()) { 314 // Frame was removed without using setClosed(true) 315 remove(f.getDesktopIcon()); 316 f.removeComponentListener(this); 317 revalidate(); 318 repaint(); 319 } 320 } 321 } 322 } 323 324 325 class SynthDesktopManager extends DefaultDesktopManager implements UIResource { 326 327 public void maximizeFrame(JInternalFrame f) { 328 if (f.isIcon()) { 329 try { 330 f.setIcon(false); 331 } catch (PropertyVetoException e2) { 332 } 333 } else { 334 f.setNormalBounds(f.getBounds()); 335 Component desktop = f.getParent(); 336 setBoundsForFrame(f, 0, 0, 337 desktop.getWidth(), 338 desktop.getHeight() - taskBar.getHeight()); 339 } 340 341 try { 342 f.setSelected(true); 343 } catch (PropertyVetoException e2) { 344 } 345 } 346 347 public void iconifyFrame(JInternalFrame f) { 348 JInternalFrame.JDesktopIcon desktopIcon; 349 Container c = f.getParent(); 350 JDesktopPane d = f.getDesktopPane(); 351 boolean findNext = f.isSelected(); 352 353 if (c == null) { 354 return; 355 } 356 357 desktopIcon = f.getDesktopIcon(); 358 359 if (!f.isMaximum()) { 360 f.setNormalBounds(f.getBounds()); 361 } 362 c.remove(f); 363 c.repaint(f.getX(), f.getY(), f.getWidth(), f.getHeight()); 364 try { 365 f.setSelected(false); 366 } catch (PropertyVetoException e2) { 367 } 368 369 // Get topmost of the remaining frames 370 if (findNext) { 371 for (Component comp : c.getComponents()) { 372 if (comp instanceof JInternalFrame) { 373 try { 374 ((JInternalFrame)comp).setSelected(true); 375 } catch (PropertyVetoException e2) { 376 } 377 ((JInternalFrame)comp).moveToFront(); 378 return; 379 } 380 } 381 } 382 } 383 384 385 public void deiconifyFrame(JInternalFrame f) { 386 JInternalFrame.JDesktopIcon desktopIcon = f.getDesktopIcon(); 387 Container c = desktopIcon.getParent(); 388 if (c != null) { 389 c = c.getParent(); 390 if (c != null) { 391 c.add(f); 392 if (f.isMaximum()) { 393 int w = c.getWidth(); 394 int h = c.getHeight() - taskBar.getHeight(); 395 if (f.getWidth() != w || f.getHeight() != h) { 396 setBoundsForFrame(f, 0, 0, w, h); 397 } 398 } 399 if (f.isSelected()) { 400 f.moveToFront(); 401 } else { 402 try { 403 f.setSelected(true); 404 } catch (PropertyVetoException e2) { 405 } 406 } 407 } 408 } 409 } 410 411 protected void removeIconFor(JInternalFrame f) { 412 super.removeIconFor(f); 413 taskBar.validate(); 414 } 415 416 public void setBoundsForFrame(JComponent f, int newX, int newY, int newWidth, int newHeight) { 417 super.setBoundsForFrame(f, newX, newY, newWidth, newHeight); 418 if (taskBar != null && newY >= taskBar.getY()) { 419 f.setLocation(f.getX(), taskBar.getY()-f.getInsets().top); 420 } 421 } 422 } 423 424 /** 425 * @inheritDoc 426 */ 427 @Override 428 public SynthContext getContext(JComponent c) { 429 return getContext(c, getComponentState(c)); 430 } 431 432 private SynthContext getContext(JComponent c, int state) { 433 return SynthContext.getContext(SynthContext.class, c, 434 SynthLookAndFeel.getRegion(c), style, state); 435 } 436 437 private int getComponentState(JComponent c) { 438 return SynthLookAndFeel.getComponentState(c); 439 } 440 441 /** 442 * Notifies this UI delegate to repaint the specified component. 443 * This method paints the component background, then calls 444 * the {@link #paint(SynthContext,Graphics)} method. 445 * 446 * <p>In general, this method does not need to be overridden by subclasses. 447 * All Look and Feel rendering code should reside in the {@code paint} method. 448 * 449 * @param g the {@code Graphics} object used for painting 450 * @param c the component being painted 451 * @see #paint(SynthContext,Graphics) 452 */ 453 @Override 454 public void update(Graphics g, JComponent c) { 455 SynthContext context = getContext(c); 456 457 SynthLookAndFeel.update(context, g); 458 context.getPainter().paintDesktopPaneBackground(context, g, 0, 0, 459 c.getWidth(), c.getHeight()); 460 paint(context, g); 461 context.dispose(); 462 } 463 464 /** 465 * Paints the specified component according to the Look and Feel. 466 * <p>This method is not used by Synth Look and Feel. 467 * Painting is handled by the {@link #paint(SynthContext,Graphics)} method. 468 * 469 * @param g the {@code Graphics} object used for painting 470 * @param c the component being painted 471 * @see #paint(SynthContext,Graphics) 472 */ 473 @Override 474 public void paint(Graphics g, JComponent c) { 475 SynthContext context = getContext(c); 476 477 paint(context, g); 478 context.dispose(); 479 } 480 481 /** 482 * Paints the specified component. This implementation does nothing. 483 * 484 * @param context context for the component being painted 485 * @param g the {@code Graphics} object used for painting 486 * @see #update(Graphics,JComponent) 487 */ 488 protected void paint(SynthContext context, Graphics g) { 489 } 490 491 /** 492 * @inheritDoc 493 */ 494 @Override 495 public void paintBorder(SynthContext context, Graphics g, int x, 496 int y, int w, int h) { 497 context.getPainter().paintDesktopPaneBorder(context, g, x, y, w, h); 498 } 499 500 /** 501 * @inheritDoc 502 */ 503 @Override 504 public void propertyChange(PropertyChangeEvent evt) { 505 if (SynthLookAndFeel.shouldUpdateStyle(evt)) { 506 updateStyle((JDesktopPane)evt.getSource()); 507 } 508 if (evt.getPropertyName() == "ancestor" && taskBar != null) { 509 taskBar.adjustSize(); 510 } 511 } 512 }