/* * Copyright (c) 2007, 2011, 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.core.ui; import com.sun.tools.visualvm.core.datasource.DataSource; import com.sun.tools.visualvm.core.ui.components.DataViewComponent; import com.sun.tools.visualvm.uisupport.UISupport; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.Insets; import java.awt.Toolkit; import javax.swing.ImageIcon; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.ArrayList; import java.util.List; import javax.swing.BorderFactory; import javax.swing.JPanel; import javax.swing.JTabbedPane; import javax.swing.UIManager; import org.openide.awt.TabbedPaneFactory; /** * TabbedPane container allowing to control if tabs can be closed or not * * @author Jiri Sedlacek * */ class DataSourceWindowTabbedPane extends JPanel { private final JTabbedPane tabpane; // --- Workaround to use the correct Close button on Windows 10 -------------- static { if (isWindows10() && isWindowsXPLaF()) { UIManager.put( "nb.close.tab.icon.enabled.name", "org/openide/awt/resources/win8_bigclose_enabled.png"); // NOI18N UIManager.put( "nb.close.tab.icon.pressed.name", "org/openide/awt/resources/win8_bigclose_pressed.png"); // NOI18N UIManager.put( "nb.close.tab.icon.rollover.name", "org/openide/awt/resources/win8_bigclose_rollover.png"); // NOI18N } } private static boolean isWindows10() { String osName = System.getProperty ("os.name"); // NOI18N return osName.indexOf("Windows 10") >= 0 // NOI18N || (osName.equals( "Windows NT (unknown)" ) && "10.0".equals( System.getProperty("os.version") )); // NOI18N } private static boolean isWindowsXPLaF() { Boolean isXP = (Boolean)Toolkit.getDefaultToolkit(). getDesktopProperty("win.xpstyle.themeActive"); // NOI18N return isWindowsLaF() && (isXP == null ? false : isXP.booleanValue()); } private static boolean isWindowsLaF () { String lfID = UIManager.getLookAndFeel().getID(); return lfID.endsWith("Windows"); // NOI18N } // --------------------------------------------------------------------------- DataSourceWindowTabbedPane() { super(new BorderLayout()); tabpane = TabbedPaneFactory.createCloseButtonTabbedPane(); tabpane.setTabLayoutPolicy(JTabbedPane.WRAP_TAB_LAYOUT); // Clear default border for fill up the entire DataSourceWindow tabpane.setOpaque(false); if (UIManager.getLookAndFeel().getID().equals("Aqua")) { // NOI18N tabpane.setBorder(BorderFactory.createEmptyBorder(0, -11, -13, -10)); } else { tabpane.setBorder(BorderFactory.createEmptyBorder()); Insets i = UIManager.getInsets("TabbedPane.contentBorderInsets"); // NOI18N if (i != null) tabpane.setBorder(BorderFactory.createEmptyBorder(0, -i.left, -i.bottom, -i.right)); } add(tabpane, BorderLayout.CENTER); } public final boolean requestFocusInWindow() { Component sel = tabpane.getSelectedComponent(); if (sel != null) return sel.requestFocusInWindow(); else return super.requestFocusInWindow(); } public void addView(DataSource dataSource, DataSourceView view) { ViewContainer container = new ViewContainer(new DataSourceCaption(dataSource), view); String viewName = view.getName(); if (view.isClosable()) { if (viewName.indexOf("</html>") == -1) viewName += " "; // NOI18N else viewName.replace("</html>", " </html>"); // NOI18N } tabpane.addTab(viewName, new ImageIcon(view.getImage()), container); } public void removeView(int index) { ViewContainer container = (ViewContainer)tabpane.getComponentAt(index); tabpane.removeTabAt(index); container.getCaption().finish(); } public DataSourceView getView(ViewContainer container) { return container.getView(); } public int indexOfView(final DataSourceView view) { final int[] index = new int[1]; index[0] = -1; UISupport.runInEventDispatchThreadAndWait(new Runnable() { public void run() { for (int i = 0; i < tabpane.getTabCount(); i++) if (((ViewContainer)tabpane.getComponentAt(i)).getViewComponent() == view.getView()) index[0] = i; } }); return index[0]; } public List<DataSourceView> getViews() { List<DataSourceView> views = new ArrayList(); for (int i = 0; i < tabpane.getTabCount(); i++) { ViewContainer container = (ViewContainer)tabpane.getComponentAt(i); views.add(container.getView()); } return views; } public void setViewIndex(int index) { tabpane.setSelectedIndex(index); } public void setViewBackground(int index, Color background) { tabpane.setBackgroundAt(index, background); } public void addCloseListener(PropertyChangeListener l) { tabpane.addPropertyChangeListener(TabbedPaneFactory.PROP_CLOSE, l); } public void removeCloseListener(PropertyChangeListener l) { tabpane.removePropertyChangeListener(TabbedPaneFactory.PROP_CLOSE, l); } public boolean isCloseEvent(PropertyChangeEvent evt) { return TabbedPaneFactory.PROP_CLOSE.equals(evt.getPropertyName()); } static class ViewContainer extends JPanel { private DataSourceCaption caption; private DataSourceView view; private DataViewComponent viewComponent; public ViewContainer(DataSourceCaption caption, DataSourceView view) { Color backgroundColor = UISupport.getDefaultBackground(); this.caption = caption; this.view = view; this.viewComponent = view.getView(); setLayout(new BorderLayout()); setBorder(BorderFactory.createMatteBorder(5, 5, 5, 5, backgroundColor)); setBackground(backgroundColor); setFocusable(false); add(viewComponent, BorderLayout.CENTER); if (caption != null) { caption.setBorder(BorderFactory.createEmptyBorder(0, 0, 5, 0)); caption.setBackground(backgroundColor); add(caption, BorderLayout.NORTH); } putClientProperty(TabbedPaneFactory.NO_CLOSE_BUTTON, !view.isClosable()); } public final boolean requestFocusInWindow() { if (getComponentCount() > 0) return getComponent(0).requestFocusInWindow(); else return super.requestFocusInWindow(); } public DataSourceCaption getCaption() { return caption; } public DataSourceView getView() { return view; } public DataViewComponent getViewComponent() { return viewComponent; } } }