/* * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package com.sun.tools.visualvm.modules.startup.dialogs; import java.awt.BorderLayout; import java.awt.Container; import java.awt.Frame; import java.awt.Image; import java.awt.Window; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; import java.awt.event.HierarchyEvent; import java.awt.event.HierarchyListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.ArrayList; import java.util.List; import javax.swing.JDialog; import javax.swing.JOptionPane; import javax.swing.JRootPane; import javax.swing.UIManager; import org.openide.util.ImageUtilities; /** * * Utility class to create dialogs displayed on VisualVM startup before the main window is shown. * Ensures that the dialog shows on top and its presenter is displayed in Windows taskbar. * * @author Jiri Sedlacek * @since VisualVM 1.3.6 */ public final class StartupDialog { public static JDialog create(String caption, String message, int messageType) { // Bugfix #361, set the JDialog to appear in the Taskbar on Windows (ModalityType.APPLICATION_MODAL) Window[] windows = Window.getWindows(); final JDialog d = windows == null || windows.length == 0 ? new JDialog(null, caption, JDialog.ModalityType.APPLICATION_MODAL) : new JDialog((Frame)null, caption, true); if (message != null) initDialog(d, message, messageType); // Bugfix #361, JDialog should use the VisualVM icon for better identification List<Image> icons = new ArrayList(); icons.add(ImageUtilities.loadImage("org/netbeans/core/startup/frame.gif", true)); // NOI18N icons.add(ImageUtilities.loadImage("org/netbeans/core/startup/frame24.gif", true)); // NOI18N icons.add(ImageUtilities.loadImage("org/netbeans/core/startup/frame32.gif", true)); // NOI18N icons.add(ImageUtilities.loadImage("org/netbeans/core/startup/frame48.gif", true)); // NOI18N d.setIconImages(icons); d.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); d.setResizable(false); d.setLocationRelativeTo(null); // Bugfix #361, ensure that the dialog will be the topmost visible window after opening d.addHierarchyListener(new HierarchyListener() { public void hierarchyChanged(HierarchyEvent e) { if ((e.getChangeFlags() & HierarchyEvent.SHOWING_CHANGED) != 0) { if (d.isShowing()) { // For some reason the dialog created with defined JDialog.ModalityType // isn't displayed on Windows when opened by the NetBeans launcher. This // code seems to workaround it while not breaking anything elsewhere. // Disabled to fix jigsaw, the problem is not reproducible using Java7u80@Win7 // ComponentPeer peer = d.getPeer(); // if (peer != null) peer.setVisible(true); d.removeHierarchyListener(this); d.setAlwaysOnTop(true); d.toFront(); d.setAlwaysOnTop(false); } } } }); return d; } private static void initDialog(final JDialog dialog, String message, int messageType) { final JOptionPane content = new JOptionPane(message, messageType); Container contentPane = dialog.getContentPane(); contentPane.setLayout(new BorderLayout()); contentPane.add(content, BorderLayout.CENTER); dialog.setResizable(false); if (JDialog.isDefaultLookAndFeelDecorated()) { boolean supportsWindowDecorations = UIManager.getLookAndFeel().getSupportsWindowDecorations(); if (supportsWindowDecorations) { dialog.setUndecorated(true); content.getRootPane().setWindowDecorationStyle( styleFromMessageType(messageType)); } } dialog.pack(); final PropertyChangeListener listener = new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent event) { // Let the defaultCloseOperation handle the closing // if the user closed the window without selecting a button // (newValue = null in that case). Otherwise, close the dialog. if (dialog.isVisible() && event.getSource() == content && (event.getPropertyName().equals(JOptionPane.VALUE_PROPERTY)) && event.getNewValue() != null && event.getNewValue() != JOptionPane.UNINITIALIZED_VALUE) { dialog.setVisible(false); } } }; WindowAdapter adapter = new WindowAdapter() { private boolean gotFocus = false; public void windowClosing(WindowEvent we) { content.setValue(null); } public void windowClosed(WindowEvent e) { content.removePropertyChangeListener(listener); dialog.getContentPane().removeAll(); } public void windowGainedFocus(WindowEvent we) { // Once window gets focus, set initial focus if (!gotFocus) { content.selectInitialValue(); gotFocus = true; } } }; dialog.addWindowListener(adapter); dialog.addWindowFocusListener(adapter); dialog.addComponentListener(new ComponentAdapter() { public void componentShown(ComponentEvent ce) { // reset value to ensure closing works properly content.setValue(JOptionPane.UNINITIALIZED_VALUE); } }); content.addPropertyChangeListener(listener); } private static int styleFromMessageType(int messageType) { switch (messageType) { case JOptionPane.ERROR_MESSAGE: return JRootPane.ERROR_DIALOG; case JOptionPane.QUESTION_MESSAGE: return JRootPane.QUESTION_DIALOG; case JOptionPane.WARNING_MESSAGE: return JRootPane.WARNING_DIALOG; case JOptionPane.INFORMATION_MESSAGE: return JRootPane.INFORMATION_DIALOG; case JOptionPane.PLAIN_MESSAGE: default: return JRootPane.PLAIN_DIALOG; } } }