/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright 1997-2014 Oracle and/or its affiliates. All rights reserved. * * Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners. * * The contents of this file are subject to the terms of either the GNU * General Public License Version 2 only ("GPL") or the Common * Development and Distribution License("CDDL") (collectively, the * "License"). You may not use this file except in compliance with the * License. You can obtain a copy of the License at * http://www.netbeans.org/cddl-gplv2.html * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the * specific language governing permissions and limitations under the * License. When distributing the software, include this License Header * Notice in each file and include the License file at * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the GPL Version 2 section of the License file that * accompanied this code. If applicable, add the following below the * License Header, with the fields enclosed by brackets [] replaced by * your own identifying information: * "Portions Copyrighted [year] [name of copyright owner]" * * Contributor(s): * The Original Software is NetBeans. The Initial Developer of the Original * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun * Microsystems, Inc. All Rights Reserved. * * If you wish your version of this file to be governed by only the CDDL * or only the GPL Version 2, indicate your decision by adding * "[Contributor] elects to include this software in this distribution * under the [CDDL or GPL Version 2] license." If you do not indicate a * single choice of license, a recipient has the option to distribute * your version of this file under either the CDDL, the GPL Version 2 or * to extend the choice of license to its licensees as provided above. * However, if you add GPL Version 2 code and therefore, elected the GPL * Version 2 license, then the option applies only if the new code is * made subject to such option by the copyright holder. */ package org.graalvm.visualvm.lib.profiler.v2; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.Font; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.KeyboardFocusManager; import java.awt.event.ActionEvent; import java.awt.event.ComponentEvent; import java.awt.event.ComponentListener; import java.awt.event.HierarchyEvent; import java.awt.event.HierarchyListener; import java.awt.event.ItemEvent; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Properties; import java.util.Set; import javax.accessibility.AccessibleContext; import javax.accessibility.AccessibleRole; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.ActionMap; import javax.swing.BorderFactory; import javax.swing.InputMap; import javax.swing.JButton; import javax.swing.JCheckBoxMenuItem; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JMenuItem; import javax.swing.JPanel; import javax.swing.JToggleButton; import javax.swing.SwingUtilities; import javax.swing.Timer; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import org.graalvm.visualvm.lib.common.AttachSettings; import org.graalvm.visualvm.lib.common.Profiler; import org.graalvm.visualvm.lib.common.ProfilingSettings; import org.graalvm.visualvm.lib.common.event.SimpleProfilingStateAdapter; import org.graalvm.visualvm.lib.ui.UIUtils; import org.graalvm.visualvm.lib.ui.components.ProfilerToolbar; import org.graalvm.visualvm.lib.ui.swing.GrayLabel; import org.graalvm.visualvm.lib.ui.swing.PopupButton; import org.graalvm.visualvm.lib.ui.swing.ProfilerPopup; import org.graalvm.visualvm.lib.ui.swing.SearchUtils; import org.graalvm.visualvm.lib.ui.swing.StayOpenPopupMenu; import org.graalvm.visualvm.lib.profiler.ProfilerTopComponent; import org.graalvm.visualvm.lib.profiler.actions.HeapDumpAction; import org.graalvm.visualvm.lib.profiler.actions.RunGCAction; import org.graalvm.visualvm.lib.profiler.actions.TakeThreadDumpAction; import org.graalvm.visualvm.lib.profiler.api.ActionsSupport; import org.graalvm.visualvm.lib.profiler.api.ProfilerDialogs; import org.graalvm.visualvm.lib.profiler.api.ProfilerIDESettings; import org.graalvm.visualvm.lib.profiler.api.ProfilerStorage; import org.graalvm.visualvm.lib.profiler.api.ProjectUtilities; import org.graalvm.visualvm.lib.profiler.api.icons.GeneralIcons; import org.graalvm.visualvm.lib.profiler.api.icons.Icons; import org.graalvm.visualvm.lib.profiler.api.icons.ProfilerIcons; import org.graalvm.visualvm.lib.profiler.attach.AttachWizard; import org.graalvm.visualvm.lib.profiler.v2.impl.FeaturesView; import org.graalvm.visualvm.lib.profiler.v2.impl.ProfilerStatus; import org.graalvm.visualvm.lib.profiler.v2.impl.WelcomePanel; import org.graalvm.visualvm.lib.profiler.v2.ui.DropdownButton; import org.graalvm.visualvm.lib.profiler.v2.ui.ToggleButtonMenuItem; import org.openide.filesystems.FileObject; import org.openide.util.Exceptions; import org.openide.util.HelpCtx; import org.openide.util.Lookup; import org.openide.util.NbBundle; import org.openide.util.RequestProcessor; import org.openide.windows.Mode; import org.openide.windows.WindowManager; /** * * @author Jiri Sedlacek */ @NbBundle.Messages({ "ProfilerWindow_captionProject={0}", "ProfilerWindow_captionFile={0} | {1}", "ProfilerWindow_captionExternal=Profile External Process", "ProfilerWindow_configure=Configure Session", "ProfilerWindow_profile=Profile", "ProfilerWindow_attach=Attach", "ProfilerWindow_profileTooltip=Start profiling session", "ProfilerWindow_profileRunningTooltip=Start profiling session (already running)", "ProfilerWindow_configureTooltip=Configure profiling session", "ProfilerWindow_terminateCaption=Terminate Profiling Session", "ProfilerWindow_terminateMsg=Terminate profiling session?", "ProfilerWindow_loadingSession=Creating session...", "ProfilerWindow_settings=Settings", "ProfilerWindow_application=Process:", "ProfilerWindow_threadDump=Thread Dump", "ProfilerWindow_heapDump=Heap Dump", "ProfilerWindow_gc=GC", "ProfilerWindow_setupAttachProject=Setup Attach to Project...", "ProfilerWindow_setupAttachProcess=Setup Attach to Process...", "ProfilerWindow_multipleFeatures=Enable Multiple Modes", "ProfilerWindow_usePPoints=Use Defined Profiling Points", "ProfilerWindow_targetSection=Target:", "ProfilerWindow_profileSection=Profile:", "ProfilerWindow_settingsSection=Settings:", "ProfilerWindow_pluginsSection=Plugins:", "#NOI18N", "ProfilerWindow_mode=editor", "ProfilerWindow_noFeature=<html><b>No profiling feature selected.</b><br><br>Please select at least one profiling feature for the session.</html>", "ProfilerWindow_accessName=Profiler Window for {0}" }) class ProfilerWindow extends ProfilerTopComponent { // --- Constructor --------------------------------------------------------- private final ProfilerSession session; ProfilerWindow(ProfilerSession session) { this.session = session; updateWindowName(); updateWindowIcon(); createUI(); } // --- API ----------------------------------------------------------------- void updateSession() { updateWindowName(); if (start != null) start.setText(session.isAttach() ? Bundle.ProfilerWindow_attach() : Bundle.ProfilerWindow_profile()); } void selectFeature(ProfilerFeature feature) { if (featuresView != null) featuresView.selectFeature(feature); } // --- Implementation ------------------------------------------------------ private ProfilerFeatures features; private ProfilerPlugins plugins; private ProfilerToolbar toolbar; private ProfilerToolbar featureToolbar; private ProfilerToolbar applicationToolbar; // private ProfilerToolbar statusBar; private JPanel container; private FeaturesView featuresView; private PopupButton configure; private DropdownButton start; private JButton stop; private SettingsPresenter settingsButton; private AttachSettings attachSettings; private ProfilerStatus status; // private String preselectItem; private void createUI() { setLayout(new BorderLayout(0, 0)); setFocusable(false); toolbar = ProfilerToolbar.create(true); add(toolbar.getComponent(), BorderLayout.NORTH); final JLabel loading = new JLabel(Bundle.ProfilerWindow_loadingSession()); loading.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 5)); toolbar.add(loading); RequestProcessor.getDefault().post(new Runnable() { public void run() { loadSessionSettings(); SwingUtilities.invokeLater(new Runnable() { public void run() { toolbar.remove(loading); popupulateUI(); } }); } }); } private void loadSessionSettings() { features = session.getFeatures(); plugins = session.getPlugins(); Properties p = new Properties(); try { ProfilerStorage.loadProjectProperties(p, session.getProject(), "attach"); // NOI18N } catch (IOException ex) { Exceptions.printStackTrace(ex); } if (!p.isEmpty()) { attachSettings = new AttachSettings(); attachSettings.load(p); } } private void popupulateUI() { configure = new PopupButton(Bundle.ProfilerWindow_configure()) { protected void displayPopup() { displayPopupImpl(); } }; configure.setToolTipText(Bundle.ProfilerWindow_configureTooltip()); if (UIUtils.isAquaLookAndFeel()) configure.putClientProperty("JComponent.sizeVariant", "regular"); // NOI18N toolbar.add(configure); String command = session.isAttach() ? Bundle.ProfilerWindow_attach() : Bundle.ProfilerWindow_profile(); start = new DropdownButton(command, Icons.getIcon(GeneralIcons.START), true) { public void displayPopup() { displayPopupImpl(); } protected void performAction() { performStartImpl(); } }; start.setToolTipText(Bundle.ProfilerWindow_profileTooltip()); start.setPushedToolTipText(Bundle.ProfilerWindow_profileRunningTooltip()); start.setPopupToolTipText(Bundle.ProfilerWindow_configureTooltip()); toolbar.add(start); stop = new JButton(ProfilerSessions.StopAction.getInstance()); stop.setHideActionText(true); toolbar.add(stop); // statusBar = new ProfilerStatus(session).getToolbar(); // statusBar.getComponent().setVisible(false); // TODO: read last state // toolbar.add(statusBar); toolbar.addFiller(); settingsButton = new SettingsPresenter(); toolbar.add(settingsButton); container = new JPanel(new BorderLayout(0, 0)); add(container, BorderLayout.CENTER); JPanel welcomePanel = new WelcomePanel(configure.getText(), start.getText(), features.getAvailable()) { public void highlightItem(final String text) { SwingUtilities.invokeLater(new Runnable() { public void run() { configure.doClick(85); } }); } }; boolean showHint = ProfilerIDESettings.getInstance().getShowNoDataHint(); featuresView = new FeaturesView(welcomePanel, showHint ? command : null); container.add(featuresView, BorderLayout.CENTER); features.addListener(new ProfilerFeatures.Listener() { void featuresChanged(ProfilerFeature changed) { updateFeatures(changed); } void settingsChanged(boolean valid) { updateSettings(valid); } }); updateFeatures(null); updateSettings(features.settingsValid()); featuresView.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { updateFeatureToolbar(); } }); updateFeatureToolbar(); session.addListener(new SimpleProfilingStateAdapter() { public void update() { updateWindowIcon(); updateButtons(); } }); updateButtons(); registerActions(); status = ProfilerStatus.forSession(session); addHierarchyListener(new HierarchyListener() { public void hierarchyChanged(HierarchyEvent e) { if ((e.getChangeFlags() & HierarchyEvent.SHOWING_CHANGED) != 0) { if (isShowing()) status.startSessionLogging(); else status.stopSessionLogging(); } } }); if (isShowing()) status.startSessionLogging(); } private void registerActions() { InputMap inputMap = getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); ActionMap actionMap = getActionMap(); final String filterKey = org.graalvm.visualvm.lib.ui.swing.FilterUtils.FILTER_ACTION_KEY; Action filterAction = new AbstractAction() { public void actionPerformed(ActionEvent e) { ProfilerFeature feature = featuresView.getSelectedFeature(); JPanel resultsUI = feature == null ? null : feature.getResultsUI(); if (resultsUI == null) return; Action action = resultsUI.getActionMap().get(filterKey); if (action != null && action.isEnabled()) action.actionPerformed(e); } }; ActionsSupport.registerAction(filterKey, filterAction, actionMap, inputMap); final String findKey = SearchUtils.FIND_ACTION_KEY; Action findAction = new AbstractAction() { public void actionPerformed(ActionEvent e) { ProfilerFeature feature = featuresView.getSelectedFeature(); JPanel resultsUI = feature == null ? null : feature.getResultsUI(); if (resultsUI == null) return; Action action = resultsUI.getActionMap().get(findKey); if (action != null && action.isEnabled()) action.actionPerformed(e); } }; ActionsSupport.registerAction(findKey, findAction, actionMap, inputMap); } private void updateWindowName() { Lookup.Provider project = session.getProject(); if (project == null) { setDisplayName(Bundle.ProfilerWindow_captionExternal()); } else { String projectN = ProjectUtilities.getDisplayName(project); FileObject file = session.getFile(); setDisplayName(file == null ? Bundle.ProfilerWindow_captionProject(projectN) : Bundle.ProfilerWindow_captionFile(projectN, file.getNameExt())); } } private void updateWindowIcon() { UIUtils.runInEventDispatchThread(new Runnable() { public void run() { if (session.inProgress()) setIcon(Icons.getImage(ProfilerIcons.PROFILE_RUNNING)); else setIcon(Icons.getImage(ProfilerIcons.PROFILE_INACTIVE)); } }); } private void updateButtons() { int state = session.getState(); start.setPushed(state != Profiler.PROFILING_INACTIVE); start.setPopupEnabled(state != Profiler.PROFILING_IN_TRANSITION); } private void updateFeatures(ProfilerFeature changed) { // TODO: optimize! // TODO: restore focused component if possible ProfilerFeature restore = featuresView.getSelectedFeature(); featuresView.removeFeatures(); Set<ProfilerFeature> selected = features.getActivated(); for (ProfilerFeature feature : selected) featuresView.addFeature(feature); if (changed != null && selected.contains(changed)) featuresView.selectFeature(changed); else featuresView.selectFeature(restore); featuresView.repaint(); } private void updateSettings(boolean valid) { start.setEnabled(valid); boolean _configure = features.getActivated().isEmpty(); start.setVisible(!_configure); stop.setVisible(!_configure); configure.setVisible(_configure); new Timer(0, null) { { setRepeats(false); setInitialDelay(50); } protected void fireActionPerformed(ActionEvent e) { updateFocus(); } }.start(); if (session.inProgress()) session.doModify(features.getSettings()); } private void updateFocus() { SwingUtilities.invokeLater(new Runnable() { public void run() { Component focused = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); // Do not change focus for these special cases: if (focused != null) { if (profilePopupVisible) return; // focus in the Profile popup if (ProfilerPopup.isInPopup(focused)) return; // focus in a profiler popup if (ProfilerWindow.this.isAncestorOf(focused)) return; // focus inside the ProfilerWindow } final Component foc = configure.isVisible() ? configure : start; SwingUtilities.invokeLater(new Runnable() { public void run() { foc.requestFocusInWindow(); } }); } }); } private void updateFeatureToolbar() { if (featureToolbar != null) toolbar.remove(featureToolbar); if (applicationToolbar != null) toolbar.remove(applicationToolbar); ProfilerFeature selected = featuresView.getSelectedFeature(); featureToolbar = selected == null ? null : selected.getToolbar(); if (featureToolbar != null) toolbar.add(featureToolbar, toolbar.getComponentCount() - 2); // add before filler & settingsButton settingsButton.setFeature(selected); if (selected != null) toolbar.add(getApplicationToolbar(), toolbar.getComponentCount() - 2); // add before filler & settingsButton else applicationToolbar = null; doLayout(); repaint(); } private ProfilerToolbar getApplicationToolbar() { if (applicationToolbar == null) { applicationToolbar = ProfilerToolbar.create(true); applicationToolbar.addSpace(2); applicationToolbar.addSeparator(); applicationToolbar.addSpace(5); JLabel apLabel = new GrayLabel(Bundle.ProfilerWindow_application()); applicationToolbar.add(apLabel); applicationToolbar.addSpace(2); JButton apThreadDumpButton = new JButton(TakeThreadDumpAction.getInstance()); apThreadDumpButton.setHideActionText(true); // apThreadDumpButton.setText(Bundle.ProfilerWindow_threadDump()); applicationToolbar.add(apThreadDumpButton); applicationToolbar.addSpace(3); JButton apHeapDumpButton = new JButton(HeapDumpAction.getInstance()); apHeapDumpButton.setHideActionText(true); // apHeapDumpButton.setText(Bundle.ProfilerWindow_heapDump()); applicationToolbar.add(apHeapDumpButton); applicationToolbar.addSpace(3); JButton apGCButton = new JButton(RunGCAction.getInstance()); apGCButton.setHideActionText(true); // apGCButton.setText(Bundle.ProfilerWindow_gc()); applicationToolbar.add(apGCButton); } return applicationToolbar; } private boolean configureAttachSettings(boolean partially) { AttachSettings settings = AttachWizard.getDefault().configure(attachSettings, partially); if (settings == null) return false; // cancelled by the user attachSettings = settings; final AttachSettings as = new AttachSettings(); attachSettings.copyInto(as); final Lookup.Provider lp = session.getProject(); RequestProcessor.getDefault().post(new Runnable() { public void run() { Properties p = new Properties(); as.store(p); try { ProfilerStorage.saveProjectProperties(p, lp, "attach"); // NOI18N } catch (IOException ex) { Exceptions.printStackTrace(ex); } } }); return true; } private void performStartImpl() { featuresView.resetNoDataHint(); start.setPushed(true); final ProfilingSettings _profilingSettings = features.getSettings(); if (_profilingSettings == null) { // #250237 ? ProfilerDialogs.displayError(Bundle.ProfilerWindow_noFeature()); start.setPushed(false); return; } if (session.isAttach()) { RequestProcessor.getDefault().post(new Runnable() { public void run() { if (AttachWizard.getDefault().configured(attachSettings)) { performDoStartImpl(_profilingSettings, attachSettings); } else { SwingUtilities.invokeLater(new Runnable() { public void run() { if (!configureAttachSettings(false)) start.setPushed(false); else performDoStartImpl(_profilingSettings, attachSettings); } }); } } }); } else { performDoStartImpl(_profilingSettings, null); } } private void performDoStartImpl(final ProfilingSettings ps, final AttachSettings as) { UIUtils.runInEventDispatchThread(new Runnable() { public void run() { if (!session.doStart(ps, as)) start.setPushed(false); } }); } // --- Profile/Attach popup ------------------------------------------------ private boolean profilePopupVisible; private void displayPopupImpl() { final Set<ProfilerFeature> _features = features.getAvailable(); final Set<ProfilerFeature> _selected = features.getActivated(); final List<ToggleButtonMenuItem> _items = new ArrayList(); // --- Features listener --- final ProfilerFeatures.Listener listener = new ProfilerFeatures.Listener() { void featuresChanged(ProfilerFeature changed) { int index = 0; for (ProfilerFeature feature : _features) { ToggleButtonMenuItem item = _items.get(index++); if (item == null) item = _items.get(index++); item.setPressed(_selected.contains(feature)); } } void settingsChanged(boolean valid) {} }; // --- Popup menu --- final StayOpenPopupMenu popup = new StayOpenPopupMenu() { public void setVisible(boolean visible) { if (visible) features.addListener(listener); else features.removeListener(listener); super.setVisible(visible); profilePopupVisible = visible; if (!visible) updateFocus(); } }; popup.setLayout(new GridBagLayout()); if (!UIUtils.isAquaLookAndFeel()) { popup.setForceBackground(true); Color background = UIUtils.getProfilerResultsBackground(); popup.setBackground(new Color(background.getRGB())); // JPopupMenu doesn't seem to follow ColorUIResource } // --- Feature items --- int lastPosition = -1; for (final ProfilerFeature feature : _features) { int currentPosition = feature.getPosition(); if (lastPosition == -1) lastPosition = currentPosition; if (currentPosition - lastPosition > 1) _items.add(null); lastPosition = currentPosition; _items.add(new ToggleButtonMenuItem(feature.getName(), feature.getIcon()) { { setPressed(_selected.contains(feature)); } protected void fireActionPerformed(ActionEvent e) { features.toggleActivated(feature); if (features.isSingleFeatured() && isPressed()) /*if (session.inProgress())*/ popup.setVisible(false); } }); } // --- Other controls --- final boolean _project = session.getProject() != null; // final boolean _file = session.getFile() != null; final boolean _attach = session.isAttach(); // JMenuItem attachProject = null; if (_attach) { String nameA = _project ? Bundle.ProfilerWindow_setupAttachProject() : Bundle.ProfilerWindow_setupAttachProcess(); attachProject = new JMenuItem(nameA) { { setEnabled(!session.inProgress()); } protected void fireActionPerformed(ActionEvent event) { configureAttachSettings(true); } }; } JCheckBoxMenuItem singleFeature = new StayOpenPopupMenu.CheckBoxItem(Bundle.ProfilerWindow_multipleFeatures()) { { setSelected(!features.isSingleFeatured()); } protected void fireItemStateChanged(ItemEvent event) { features.setSingleFeatured(!isSelected()); } }; JCheckBoxMenuItem usePPoints = new StayOpenPopupMenu.CheckBoxItem(Bundle.ProfilerWindow_usePPoints()) { { setSelected(features.getUseProfilingPoints()); setEnabled(!session.inProgress()); } protected void fireItemStateChanged(ItemEvent event) { features.setUseProfilingPoints(isSelected()); } }; // --- Popup crowding --- int left = 12; int labl = 5; int y = 0; GridBagConstraints c; if (_attach) { JLabel projectL = new JLabel(Bundle.ProfilerWindow_targetSection(), JLabel.LEADING); projectL.setFont(popup.getFont().deriveFont(Font.BOLD)); c = new GridBagConstraints(); c.gridy = y++; c.insets = new Insets(5, labl, 5, 5); c.fill = GridBagConstraints.HORIZONTAL; popup.add(projectL, c); c = new GridBagConstraints(); c.gridy = y++; c.gridx = 0; c.insets = new Insets(0, left, 0, 5); c.gridwidth = 1; c.fill = GridBagConstraints.HORIZONTAL; popup.add(attachProject, c); } JLabel profileL = new JLabel(Bundle.ProfilerWindow_profileSection(), JLabel.LEADING); profileL.setFont(popup.getFont().deriveFont(Font.BOLD)); c = new GridBagConstraints(); c.gridy = y++; c.insets = new Insets(_attach ? 8 : 5, labl, 5, 5); c.fill = GridBagConstraints.HORIZONTAL; popup.add(profileL, c); for (ToggleButtonMenuItem item : _items) { if (item == null) { JPanel p = new JPanel(null); p.setOpaque(false); c = new GridBagConstraints(); c.gridy = y++; c.insets = new Insets(5, 0, 5, 0); c.fill = GridBagConstraints.HORIZONTAL; popup.add(p, c); } else { c = new GridBagConstraints(); c.gridy = y++; c.insets = new Insets(0, left, 0, 5); c.fill = GridBagConstraints.HORIZONTAL; popup.add(item, c); } } JLabel settingsL = new JLabel(Bundle.ProfilerWindow_settingsSection(), JLabel.LEADING); settingsL.setFont(popup.getFont().deriveFont(Font.BOLD)); c = new GridBagConstraints(); c.gridy = y++; c.insets = new Insets(8, labl, 5, 5); c.fill = GridBagConstraints.HORIZONTAL; popup.add(settingsL, c); c = new GridBagConstraints(); c.gridy = y++; c.insets = new Insets(0, left, 0, 5); c.fill = GridBagConstraints.HORIZONTAL; popup.add(singleFeature, c); if (_project) { c = new GridBagConstraints(); c.gridy = y++; c.insets = new Insets(0, left, 0, 5); c.fill = GridBagConstraints.HORIZONTAL; popup.add(usePPoints, c); } if (plugins.hasPlugins()) { JLabel pluginsL = new JLabel(Bundle.ProfilerWindow_pluginsSection(), JLabel.LEADING); pluginsL.setFont(popup.getFont().deriveFont(Font.BOLD)); c = new GridBagConstraints(); c.gridy = y++; c.insets = new Insets(8, labl, 5, 5); c.fill = GridBagConstraints.HORIZONTAL; popup.add(pluginsL, c); for (JMenuItem menu : plugins.menuItems()) { c = new GridBagConstraints(); c.gridy = y++; c.insets = new Insets(0, left, 0, 5); c.fill = GridBagConstraints.HORIZONTAL; popup.add(menu, c); } } JPanel footer = new JPanel(null); footer.setOpaque(false); c = new GridBagConstraints(); c.gridy = y++; c.weightx = 1; c.weighty = 1; c.insets = new Insets(3, 0, 0, 0); c.anchor = GridBagConstraints.NORTHWEST; c.fill = GridBagConstraints.BOTH; popup.add(footer, c); // MenuElement preselect = null; // if (preselectItem != null) { // for (Component comp : popup.getComponents()) { // if (comp instanceof JMenuItem) { // JMenuItem mi = (JMenuItem)comp; // if (mi.getText().contains(preselectItem)) { // preselect = mi; // break; // } // } // } // preselectItem = null; // } // // if (preselect instanceof JRadioButtonMenuItem) // ((JRadioButtonMenuItem)preselect).setSelected(true); JComponent button = start.isVisible() ? start : configure; popup.show(button, 0, button.getHeight()); // if (preselect != null) MenuSelectionManager.defaultManager().setSelectedPath( // new MenuElement[] { popup, preselect }); } // --- ProfilerTopComponent ------------------------------------------------ protected Component defaultFocusOwner() { if (configure != null && configure.isVisible()) return configure; else if (start != null) return start; else return null; } // --- TopComponent -------------------------------------------------------- private final String ID = "ProfilerWindow"; // NOI18N boolean closing = false; public boolean canClose() { if (closing) return true; if (!super.canClose()) return false; closing = true; closing = session.close(); return closing; } public void open() { WindowManager windowManager = WindowManager.getDefault(); if (windowManager.findMode(this) == null) { // needs docking Mode mode = windowManager.findMode(Bundle.ProfilerWindow_mode()); if (mode != null) mode.dockInto(this); } super.open(); } protected void componentOpened() { super.componentOpened(); SnapshotsWindow.instance().sessionOpened(session); } protected void componentShowing() { super.componentShowing(); SnapshotsWindow.instance().sessionActivated(session); } protected void componentHidden() { super.componentHidden(); SnapshotsWindow.instance().sessionDeactivated(session); } protected void componentClosed() { super.componentOpened(); SnapshotsWindow.instance().sessionClosed(session); } protected void componentActivated() { super.componentActivated(); if (status != null) status.startSessionLogging(); } public int getPersistenceType() { return PERSISTENCE_NEVER; } protected String preferredID() { return ID; } public HelpCtx getHelpCtx() { ProfilerFeature selected = featuresView == null ? null : featuresView.getSelectedFeature(); JPanel selectedUI = selected == null ? null : selected.getResultsUI(); if (selectedUI == null && selected != null) selectedUI = selected.getSettingsUI(); String helpCtx = selectedUI == null ? null : (String)selectedUI.getClientProperty("HelpCtx.Key"); // NOI18N if (helpCtx == null) helpCtx = "ProfileWindow.HelpCtx"; // NOI18N return new HelpCtx(helpCtx); } // --- Accessibility ------------------------------------------------------- private AccessibleContext accessibleContext; public AccessibleContext getAccessibleContext() { if (accessibleContext == null) { accessibleContext = new JComponent.AccessibleJComponent() { public AccessibleRole getAccessibleRole() { return AccessibleRole.PANEL; } public String getAccessibleName() { return Bundle.ProfilerWindow_accessName(getDisplayName()); } public String getAccessibleDescription() { ProfilerFeature selected = featuresView == null ? null : featuresView.getSelectedFeature(); return selected == null ? WelcomePanel.CAPTION : (selected.getName() + " " + selected.getDescription()); // NOI18N } }; } return accessibleContext; } // --- Private classes ----------------------------------------------------- private static final class SettingsPresenter extends JToggleButton implements ComponentListener { private JPanel settings; SettingsPresenter() { super(Icons.getIcon(GeneralIcons.SETTINGS)); setToolTipText(Bundle.ProfilerWindow_settings()); updateVisibility(false); } void setFeature(ProfilerFeature feature) { if (settings != null) settings.removeComponentListener(this); settings = feature == null ? null : feature.getSettingsUI(); updateVisibility(false); if (settings != null) settings.addComponentListener(this); } protected void fireActionPerformed(ActionEvent e) { if (settings != null) { settings.setVisible(isSelected()); settings.getParent().setVisible(isSelected()); } } void cleanup() { settings.removeComponentListener(this); } private void updateVisibility(boolean parent) { setVisible(settings != null); setSelected(settings != null && settings.isVisible()); if (parent) settings.getParent().setVisible(settings.isVisible()); } public void componentShown(ComponentEvent e) { updateVisibility(true); } public void componentHidden(ComponentEvent e) { updateVisibility(true); } public void componentResized(ComponentEvent e) {} public void componentMoved(ComponentEvent e) {} } }