/*
* 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.profiler;
import com.sun.tools.visualvm.application.Application;
import com.sun.tools.visualvm.core.datasupport.DataRemovedListener;
import com.sun.tools.visualvm.core.datasupport.Stateful;
import com.sun.tools.visualvm.core.ui.DataSourceView;
import com.sun.tools.visualvm.core.ui.DesktopUtils;
import com.sun.tools.visualvm.core.ui.components.DataViewComponent;
import com.sun.tools.visualvm.profiling.presets.PresetSelector;
import com.sun.tools.visualvm.profiling.presets.ProfilerPresets;
import com.sun.tools.visualvm.uisupport.HTMLLabel;
import com.sun.tools.visualvm.uisupport.HTMLTextArea;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.net.URL;
import java.text.MessageFormat;
import javax.swing.AbstractButton;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JToggleButton;
import javax.swing.JToolBar;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import org.netbeans.lib.profiler.TargetAppRunner;
import org.netbeans.lib.profiler.common.AttachSettings;
import org.netbeans.lib.profiler.common.ProfilingSettings;
import org.netbeans.lib.profiler.common.event.ProfilingStateEvent;
import org.netbeans.lib.profiler.common.event.ProfilingStateListener;
import org.netbeans.modules.profiler.LiveResultsWindow;
import org.netbeans.modules.profiler.NetBeansProfiler;
import org.netbeans.modules.profiler.ProfilerControlPanel2;
import org.netbeans.modules.profiler.api.ProfilerDialogs;
import org.netbeans.modules.profiler.utilities.ProfilerUtils;
import org.openide.util.ImageUtilities;
import org.openide.util.NbBundle;
import org.openide.util.RequestProcessor;
import org.openide.util.WeakListeners;
/**
*
* @author Jiri Sedlacek
*/
final class ApplicationProfilerView extends DataSourceView {
private static final String IMAGE_PATH =
"com/sun/tools/visualvm/profiler/resources/profiler.png"; // NOI18N
private MasterViewSupport masterViewSupport;
private CPUSettingsSupport cpuSettings;
private MemorySettingsSupport memorySettings;
private PresetSelector refSelector;
private boolean classSharingBreaksProfiling;
public ApplicationProfilerView(final Application application) {
super(application, NbBundle.getMessage(ApplicationProfilerView.class, "LBL_Profiler"), // NOI18N
new ImageIcon(ImageUtilities.loadImage(IMAGE_PATH, true)).getImage(), 40, false);
cpuSettings = new CPUSettingsSupport() {
public boolean presetValid() {
return cpuSettings.settingsValid() &&
memorySettings.settingsValid();
}
public PresetSelector createSelector(Runnable presetSynchronizer) {
return ApplicationProfilerView.this.createSelector(presetSynchronizer, application);
}
};
memorySettings = new MemorySettingsSupport() {
public boolean presetValid() {
return cpuSettings.settingsValid() &&
memorySettings.settingsValid();
}
public PresetSelector createSelector(Runnable presetSynchronizer) {
return ApplicationProfilerView.this.createSelector(presetSynchronizer, application);
}
};
}
void copySettings(CPUSettingsSupport cpuSettingsC, MemorySettingsSupport memorySettingsC) {
if (cpuSettingsC != null) cpuSettings.copySettings(cpuSettingsC);
if (memorySettingsC != null) memorySettings.copySettings(memorySettingsC);
}
private PresetSelector createSelector(Runnable presetSynchronizer, Application application) {
PresetSelector selector = ProfilerPresets.getInstance().createSelector(
application, refSelector, presetSynchronizer);
if (refSelector == null) refSelector = selector; else refSelector = null;
return selector;
}
protected DataViewComponent createComponent() {
Application application = (Application)getDataSource();
ProfilingResultsSupport profilingResultsSupport = new ProfilingResultsSupport();
masterViewSupport = new MasterViewSupport(application, profilingResultsSupport, cpuSettings, memorySettings, classSharingBreaksProfiling);
DataViewComponent dvc = new DataViewComponent(
masterViewSupport.getMasterView(),
new DataViewComponent.MasterViewConfiguration(false));
dvc.configureDetailsArea(new DataViewComponent.DetailsAreaConfiguration(NbBundle.getMessage(ApplicationProfilerView.class, "LBL_Profiling_results"), false), DataViewComponent.TOP_LEFT); // NOI18N
dvc.addDetailsView(profilingResultsSupport.getDetailsView(), DataViewComponent.TOP_LEFT);
dvc.configureDetailsArea(new DataViewComponent.DetailsAreaConfiguration(NbBundle.getMessage(ApplicationProfilerView.class, "LBL_Settings"), true), DataViewComponent.TOP_RIGHT); // NOI18N
dvc.addDetailsView(cpuSettings.getDetailsView(), DataViewComponent.TOP_RIGHT);
dvc.addDetailsView(memorySettings.getDetailsView(), DataViewComponent.TOP_RIGHT);
dvc.hideDetailsArea(DataViewComponent.TOP_RIGHT);
return dvc;
}
protected void willBeAdded() {
classSharingBreaksProfiling = ProfilerSupport.getInstance().classSharingBreaksProfiling((Application)getDataSource());
}
protected void removed() {
masterViewSupport.viewRemoved();
}
// --- General data --------------------------------------------------------
private static class MasterViewSupport extends JPanel implements ProfilingStateListener, DataRemovedListener<Application>, ActionListener, PropertyChangeListener {
private Application application;
private ProfilingResultsSupport profilingResultsView;
private CPUSettingsSupport cpuSettingsSupport;
private MemorySettingsSupport memorySettingsSupport;
private AttachSettings attachSettings;
private Timer timer;
private int lastInstrValue = -1;
private int state = -1;
private boolean internalChange = false;
private boolean applicationTerminated = false;
private boolean classSharingBreaksProfiling;
public MasterViewSupport(final Application application, ProfilingResultsSupport profilingResultsView,
CPUSettingsSupport cpuSettingsSupport, MemorySettingsSupport memorySettingsSupport, boolean classSharingBreaksProfiling) {
this.application = application;
this.profilingResultsView = profilingResultsView;
this.cpuSettingsSupport = cpuSettingsSupport;
this.memorySettingsSupport = memorySettingsSupport;
this.classSharingBreaksProfiling = classSharingBreaksProfiling;
initComponents();
initSettings();
refreshStatus();
timer = new Timer(1000, this);
timer.setInitialDelay(1000);
// prevent deadlock, issue #570
ProfilerControlPanel2.getDefault();
NetBeansProfiler.getDefaultNB().addProfilingStateListener(this);
// TODO: should listen for PROPERTY_AVAILABLE instead of DataSource removal
application.notifyWhenRemoved(this);
application.addPropertyChangeListener(Stateful.PROPERTY_STATE, WeakListeners.propertyChange(this,application));
}
public DataViewComponent.MasterView getMasterView() {
return new DataViewComponent.MasterView(NbBundle.getMessage(ApplicationProfilerView.class, "LBL_Profiler"), null, this); // NOI18N
}
public synchronized void dataRemoved(Application application) {
applicationTerminated = true;
timer.stop();
timer.removeActionListener(MasterViewSupport.this);
NetBeansProfiler.getDefaultNB().removeProfilingStateListener(MasterViewSupport.this);
ProfilerSupport.getInstance().setProfiledApplication(null);
lastInstrValue = -1;
SwingUtilities.invokeLater(new Runnable() {
public void run() {
resetControlButtons();
disableControlButtons();
statusValueLabel.setText(NbBundle.getMessage(ApplicationProfilerView.class, "MSG_application_terminated")); // NOI18N
enableSettings();
}
});
}
public void propertyChange(PropertyChangeEvent evt) {
dataRemoved(application);
}
public void viewRemoved() {
timer.stop();
timer.removeActionListener(MasterViewSupport.this);
NetBeansProfiler.getDefaultNB().removeProfilingStateListener(MasterViewSupport.this);
}
public void actionPerformed(ActionEvent e) {
updateRunningText();
}
private static JComponent getLiveResultsView() {
JComponent view = LiveResultsWindow.getDefault();
Component[] components = view.getComponents();
boolean buttonFound = false;
if (components.length > 0 && components[0] instanceof JPanel) {
components = ((JPanel)components[0]).getComponents();
if (components.length > 0 && components[0] instanceof JPanel) {
JPanel toolbarPanel = (JPanel)components[0];
components = toolbarPanel.getComponents();
if (components.length > 0 && components[0] instanceof JToolBar) {
JToolBar toolbar = (JToolBar)components[0];
components = toolbar.getComponents();
}
if (components.length > 5 && components[5] instanceof AbstractButton) {
AbstractButton takeSnapshot = (AbstractButton)components[5];
takeSnapshot.setText(NbBundle.getMessage(
ApplicationProfilerView.class, "LBL_Snapshot")); // NOI18N
buttonFound = true;
}
}
}
assert buttonFound : "Take Snapshot button was not found in the toolbar"; // NOI18N
view.setPreferredSize(new Dimension(1, 1));
return view;
}
private void handleCPUProfiling() {
if (internalChange) return;
if (cpuButton.isSelected()) {
internalChange = true;
memoryButton.setSelected(false);
internalChange = false;
if (!cpuSettingsSupport.settingsValid()) {
internalChange = true;
cpuButton.setSelected(false);
internalChange = false;
ProfilerDialogs.displayError(NbBundle.getMessage(ApplicationProfilerView.class, "MSG_Incorrect_CPU_settings")); // NOI18N
} else {
cpuSettingsSupport.saveSettings();
if (NetBeansProfiler.getDefaultNB().getProfilingState() == NetBeansProfiler.PROFILING_RUNNING) {
ProfilerUtils.runInProfilerRequestProcessor(new Runnable() {
public void run() { NetBeansProfiler.getDefaultNB().modifyCurrentProfiling(cpuSettingsSupport.getSettings()); }
});
} else {
disableControlButtons();
ProfilerSupport.getInstance().setProfiledApplication(application);
ProfilerUtils.runInProfilerRequestProcessor(new Runnable() {
public void run() { startProfiling(application, cpuSettingsSupport.getSettings()); }
});
}
}
}
}
private void handleMemoryProfiling() {
if (internalChange) return;
if (memoryButton.isSelected()) {
internalChange = true;
cpuButton.setSelected(false);
internalChange = false;
memorySettingsSupport.saveSettings();
if (NetBeansProfiler.getDefaultNB().getProfilingState() == NetBeansProfiler.PROFILING_RUNNING) {
ProfilerUtils.runInProfilerRequestProcessor(new Runnable() {
public void run() {
NetBeansProfiler.getDefaultNB().modifyCurrentProfiling(memorySettingsSupport.getSettings());
}
});
} else {
disableControlButtons();
ProfilerSupport.getInstance().setProfiledApplication(application);
ProfilerUtils.runInProfilerRequestProcessor(new Runnable() {
public void run() { startProfiling(application, memorySettingsSupport.getSettings()); }
});
}
}
}
private void startProfiling(Application application, ProfilingSettings pSettings) {
Runnable calibrationStartUpdater = new Runnable() {
public void run() {
ProfilerDialogs.displayInfo(NbBundle.getMessage(ApplicationProfilerView.class, "MSG_calibration")); // NOI18N
SwingUtilities.invokeLater(new Runnable() {
public void run() {
statusValueLabel.setText(NbBundle.getMessage(ApplicationProfilerView.class, "MSG_calibration_progress")); // NOI18N
}
});
}
};
if (CalibrationSupport.checkCalibration(application, calibrationStartUpdater, null)) {
NetBeansProfiler.getDefaultNB().attachToApp(pSettings, attachSettings);
} else {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
ProfilerSupport.getInstance().setProfiledApplication(null);
statusValueLabel.setText(NbBundle.getMessage(ApplicationProfilerView.class, "MSG_profiling_inactive")); // NOI18N
resetControlButtons();
enableControlButtons();
}
});
}
}
private void handleStopProfiling() {
if (internalChange) return;
disableControlButtons();
ProfilerUtils.runInProfilerRequestProcessor(new Runnable() {
public void run() {
NetBeansProfiler.getDefaultNB().detachFromApp();
}
});
}
public void profilingStateChanged(ProfilingStateEvent e) { refreshStatus(); }
public void threadsMonitoringChanged() { refreshStatus(); }
public void instrumentationChanged(int oldInstrType, int currentInstrType) { refreshStatus(); }
public void serverStateChanged(int serverState, int serverProgress) {}
public void lockContentionMonitoringChanged() {}
private synchronized void refreshStatus() {
final int newState = NetBeansProfiler.getDefaultNB().getProfilingState();
final Application profiledApplication = ProfilerSupport.getInstance().getProfiledApplication();
if (state != newState) {
state = newState;
SwingUtilities.invokeLater(new Runnable() {
public void run() {
switch (state) {
case NetBeansProfiler.PROFILING_INACTIVE:
lastInstrValue = -1;
if (!applicationTerminated) {
timer.stop();
statusValueLabel.setText(NbBundle.getMessage(ApplicationProfilerView.class, "MSG_profiling_inactive")); // NOI18N
resetControlButtons();
RequestProcessor.getDefault().post(new Runnable() {
public void run() {
ProfilerSupport.getInstance().setProfiledApplication(null);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
enableControlButtons();
enableSettings();
}
});
}
}, 500); // Wait for the application to finish
} else {
ProfilerSupport.getInstance().setProfiledApplication(null);
}
break;
case NetBeansProfiler.PROFILING_STARTED:
timer.stop();
disableControlButtons();
disableSettings();
statusValueLabel.setText(NbBundle.getMessage(ApplicationProfilerView.class, "MSG_profiling_started")); // NOI18N
break;
case NetBeansProfiler.PROFILING_PAUSED:
timer.stop();
statusValueLabel.setText(NbBundle.getMessage(ApplicationProfilerView.class, "MSG_profiling_paused")); // NOI18N
break;
case NetBeansProfiler.PROFILING_IN_TRANSITION:
timer.stop();
statusValueLabel.setText(NbBundle.getMessage(ApplicationProfilerView.class, "MSG_refreshing")); // NOI18N
disableControlButtons();
disableSettings();
break;
case NetBeansProfiler.PROFILING_RUNNING:
if (application.equals(profiledApplication)) {
updateRunningText();
timer.start();
enableControlButtons();
updateControlButtons();
disableSettings();
profilingResultsView.setProfilingResultsDisplay(getLiveResultsView());
} else {
statusValueLabel.setText(NbBundle.getMessage(ApplicationProfilerView.class, "MSG_profiling_of") + ProfilerSupport.getInstance().getProfiledApplicationName() + NbBundle.getMessage(ApplicationProfilerView.class, "MSG_in_progress")); // NOI18N
disableControlButtons();
profilingResultsView.setProfilingResultsDisplay(null);
}
profilingResultsView.revalidate();
profilingResultsView.repaint();
revalidate();
repaint();
break;
case NetBeansProfiler.PROFILING_STOPPED:
timer.stop();
statusValueLabel.setText(NbBundle.getMessage(ApplicationProfilerView.class, "MSG_profiling_stopped")); // NOI18N
break;
}
}
});
}
}
private void updateRunningText() {
ProfilingSettings currentSettings = NetBeansProfiler.getDefaultNB().getLastProfilingSettings();
int currentProfilingType = currentSettings != null ? currentSettings.getProfilingType() : Integer.MIN_VALUE;
if (cpuSettingsSupport.getSettings().getProfilingType() == currentProfilingType) {
int instrValue = TargetAppRunner.getDefault().getProfilingSessionStatus().getNInstrMethods();
if (lastInstrValue != instrValue)
statusValueLabel.setText(MessageFormat.format(NbBundle.getMessage(ApplicationProfilerView.class,
"MSG_profiling_running_methods"), new Object[] { instrValue })); // NOI18N
lastInstrValue = instrValue;
} else if (memorySettingsSupport.getSettings().getProfilingType() == currentProfilingType) {
int instrValue = TargetAppRunner.getDefault().getProfilingSessionStatus().getNInstrClasses();
if (lastInstrValue != instrValue) {
int allocEvery = currentSettings.getAllocTrackEvery();
switch (allocEvery) {
case 1:
statusValueLabel.setText(MessageFormat.format(NbBundle.getMessage(ApplicationProfilerView.class,
"MSG_profiling_running_classes_1"), new Object[] { instrValue, allocEvery })); // NOI18N
break;
case 2:
statusValueLabel.setText(MessageFormat.format(NbBundle.getMessage(ApplicationProfilerView.class,
"MSG_profiling_running_classes_2"), new Object[] { instrValue, allocEvery })); // NOI18N
break;
case 3:
statusValueLabel.setText(MessageFormat.format(NbBundle.getMessage(ApplicationProfilerView.class,
"MSG_profiling_running_classes_3"), new Object[] { instrValue, allocEvery })); // NOI18N
break;
default:
statusValueLabel.setText(MessageFormat.format(NbBundle.getMessage(ApplicationProfilerView.class,
"MSG_profiling_running_classes_N"), new Object[] { instrValue, allocEvery })); // NOI18N
}
}
lastInstrValue = instrValue;
}
}
private void enableSettings() {
cpuSettingsSupport.setEnabled(true);
memorySettingsSupport.setEnabled(true);
}
private void disableSettings() {
cpuSettingsSupport.setEnabled(false);
memorySettingsSupport.setEnabled(false);
}
private void resetControlButtons() {
internalChange = true;
cpuButton.setSelected(false);
memoryButton.setSelected(false);
internalChange = false;
}
private void updateControlButtons() {
ProfilingSettings currentSettings = NetBeansProfiler.getDefaultNB().getLastProfilingSettings();
int currentProfilingType = currentSettings != null ? currentSettings.getProfilingType() : Integer.MIN_VALUE;
if (cpuSettingsSupport.getSettings().getProfilingType() == currentProfilingType && !cpuButton.isSelected()) {
internalChange = true;
cpuButton.setSelected(true);
memoryButton.setSelected(false);
internalChange = false;
} else if (memorySettingsSupport.getSettings().getProfilingType() == currentProfilingType && !memoryButton.isSelected()) {
internalChange = true;
cpuButton.setSelected(false);
memoryButton.setSelected(true);
internalChange = false;
}
}
private void enableControlButtons() {
boolean enabled = ProfilerSupport.getInstance().supportsProfiling(application);
cpuButton.setEnabled(enabled);
memoryButton.setEnabled(enabled);
stopButton.setEnabled(NetBeansProfiler.getDefaultNB().getTargetAppRunner().targetAppIsRunning());
}
private void disableControlButtons() {
cpuButton.setEnabled(false);
memoryButton.setEnabled(false);
stopButton.setEnabled(false);
}
private void initSettings() {
// Attach settings default
attachSettings = new AttachSettings();
attachSettings.setDirect(false);
attachSettings.setDynamic16(true);
attachSettings.setPid(application.getPid());
}
private void initComponents() {
setLayout(new BorderLayout());
JPanel controlPanel = new JPanel();
controlPanel.setOpaque(false);
controlPanel.setLayout(new GridBagLayout());
controlPanel.setBorder(BorderFactory.createEmptyBorder(6, 0, 3, 0));
GridBagConstraints constraints;
// classShareWarningLabel
classShareWarningArea = new HTMLTextArea() {
protected void showURL(URL url) {
try { DesktopUtils.browse(url.toURI()); } catch (Exception e) {}
}
};
classShareWarningArea.setOpaque(true);
classShareWarningArea.setBackground(new java.awt.Color(255, 180, 180));
classShareWarningArea.setForeground(new java.awt.Color(0, 0, 0));
classShareWarningArea.setBorder(BorderFactory.createLineBorder(new java.awt.Color(180, 180, 180)));
classShareWarningArea.setBorder(BorderFactory.createCompoundBorder(classShareWarningArea.getBorder(),
BorderFactory.createMatteBorder(5, 5, 5, 5, classShareWarningArea.getBackground())));
classShareWarningArea.setVisible(classSharingBreaksProfiling);
if (classSharingBreaksProfiling) {
String link;
if (DesktopUtils.isBrowseAvailable()) {
link = NbBundle.getMessage(ApplicationProfilerView.class, "MSG_Class_Sharing_Link"); // NOI18N
} else {
link = NbBundle.getMessage(ApplicationProfilerView.class, "MSG_Class_Sharing_Nolink"); // NOI18N
}
String message = NbBundle.getMessage(ApplicationProfilerView.class, "MSG_Class_Sharing", link); // NOI18N
classShareWarningArea.setText(message);
}
constraints = new GridBagConstraints();
constraints.gridx = 0;
constraints.gridy = 1;
constraints.gridwidth = GridBagConstraints.REMAINDER;
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.anchor = GridBagConstraints.WEST;
constraints.insets = new Insets(4, 8, 10, 8);
controlPanel.add(classShareWarningArea, constraints);
// modeLabel
modeLabel = new JLabel(NbBundle.getMessage(ApplicationProfilerView.class, "LBL_Sample")); // NOI18N
modeLabel.setFont(modeLabel.getFont().deriveFont(Font.BOLD));
Dimension d = modeLabel.getPreferredSize();
modeLabel.setText(NbBundle.getMessage(ApplicationProfilerView.class, "LBL_Profile")); // NOI18N
d.width = Math.max(d.width, modeLabel.getPreferredSize().width);
modeLabel.setPreferredSize(d);
modeLabel.setOpaque(false);
constraints = new GridBagConstraints();
constraints.gridx = 0;
constraints.gridy = 2;
constraints.gridwidth = 1;
constraints.fill = GridBagConstraints.NONE;
constraints.anchor = GridBagConstraints.WEST;
constraints.insets = new Insets(4, 8, 0, 0);
controlPanel.add(modeLabel, constraints);
// cpuButton
cpuButton = new OneWayToggleButton(NbBundle.getMessage(ApplicationProfilerView.class, "LBL_Cpu")); // NOI18N
cpuButton.setIcon(new ImageIcon(ImageUtilities.loadImage("com/sun/tools/visualvm/profiler/resources/cpu.png", true))); // NOI18N
cpuButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { handleCPUProfiling(); }
});
constraints = new GridBagConstraints();
constraints.gridx = 2;
constraints.gridy = 2;
constraints.gridwidth = 1;
constraints.fill = GridBagConstraints.NONE;
constraints.anchor = GridBagConstraints.WEST;
constraints.insets = new Insets(4, 8, 0, 0);
controlPanel.add(cpuButton, constraints);
// memoryButton
memoryButton = new OneWayToggleButton(NbBundle.getMessage(ApplicationProfilerView.class, "LBL_Memory")); // NOI18N
memoryButton.setIcon(new ImageIcon(ImageUtilities.loadImage("com/sun/tools/visualvm/profiler/resources/memory.png", true))); // NOI18N
memoryButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { handleMemoryProfiling(); }
});
constraints = new GridBagConstraints();
constraints.gridx = 3;
constraints.gridy = 2;
constraints.gridwidth = 1;
constraints.fill = GridBagConstraints.NONE;
constraints.anchor = GridBagConstraints.WEST;
constraints.insets = new Insets(4, 8, 0, 0);
controlPanel.add(memoryButton, constraints);
// stopButton
stopButton = new JButton(NbBundle.getMessage(ApplicationProfilerView.class, "LBL_Stop")); // NOI18N
stopButton.setIcon(new ImageIcon(ImageUtilities.loadImage("com/sun/tools/visualvm/profiler/resources/stop.png", true))); // NOI18N
stopButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { handleStopProfiling(); }
});
stopButton.setEnabled(false);
stopButton.setDefaultCapable(false); // Button size
constraints = new GridBagConstraints();
constraints.gridx = 4;
constraints.gridy = 2;
constraints.gridwidth = 1;
constraints.fill = GridBagConstraints.NONE;
constraints.anchor = GridBagConstraints.WEST;
constraints.insets = new Insets(4, 8, 0, 0);
controlPanel.add(stopButton, constraints);
// filler
JPanel filler1 = new JPanel(new BorderLayout());
filler1.setOpaque(false);
constraints = new GridBagConstraints();
constraints.gridx = 5;
constraints.gridy = 2;
constraints.weightx = 1;
constraints.weighty = 1;
constraints.gridwidth = GridBagConstraints.REMAINDER;
constraints.fill = GridBagConstraints.BOTH;
constraints.anchor = GridBagConstraints.NORTHWEST;
constraints.insets = new Insets(0, 0, 0, 0);
controlPanel.add(filler1, constraints);
// statusLabel
statusLabel = new JLabel(NbBundle.getMessage(ApplicationProfilerView.class, "LBL_Status")); // NOI18N
statusLabel.setFont(statusLabel.getFont().deriveFont(Font.BOLD));
statusLabel.setOpaque(false);
constraints = new GridBagConstraints();
constraints.gridx = 0;
constraints.gridy = 3;
constraints.gridwidth = 1;
constraints.fill = GridBagConstraints.NONE;
constraints.anchor = GridBagConstraints.WEST;
constraints.insets = new Insets(6, 8, 4, 0);
controlPanel.add(statusLabel, constraints);
// statusValueLabel
statusValueLabel = new HTMLLabel() {
public void setText(String text) {
super.setText("<nobr>" + text + "</nobr>"); // NOI18N
}
protected void showURL(URL url) {
ProfilerSupport.getInstance().selectActiveProfilerView();
}
// NOTE: overriding dimensions prevents UI "jumping" when changing the link
public Dimension getPreferredSize() { return new Dimension(super.getPreferredSize().width, refLabelHeight); }
public Dimension getMinimumSize() { return getPreferredSize(); }
public Dimension getMaximumSize() { return getPreferredSize(); }
};
statusValueLabel.setOpaque(false);
constraints = new GridBagConstraints();
constraints.gridx = 1;
constraints.gridy = 3;
constraints.gridwidth = GridBagConstraints.REMAINDER;
constraints.fill = GridBagConstraints.NONE;
constraints.anchor = GridBagConstraints.WEST;
constraints.insets = new Insets(6, 8, 4, 8);
controlPanel.add(statusValueLabel, constraints);
// filler
JPanel filler2 = new JPanel(new BorderLayout());
filler2.setOpaque(false);
constraints = new GridBagConstraints();
constraints.gridx = 2;
constraints.gridy = 3;
constraints.weightx = 1;
constraints.weighty = 1;
constraints.gridwidth = GridBagConstraints.REMAINDER;
constraints.fill = GridBagConstraints.BOTH;
constraints.anchor = GridBagConstraints.NORTHWEST;
constraints.insets = new Insets(0, 0, 0, 0);
controlPanel.add(filler2, constraints);
Dimension cpuD = cpuButton.getPreferredSize();
Dimension memoryD = memoryButton.getPreferredSize();
Dimension stopD = stopButton.getPreferredSize();
Dimension maxD = new Dimension(Math.max(cpuD.width, memoryD.width), Math.max(cpuD.height, memoryD.height));
maxD = new Dimension(Math.max(maxD.width, stopD.width), Math.max(maxD.height, stopD.height));
cpuButton.setPreferredSize(maxD);
cpuButton.setMinimumSize(maxD);
memoryButton.setPreferredSize(maxD);
memoryButton.setMinimumSize(maxD);
stopButton.setPreferredSize(maxD);
stopButton.setMinimumSize(maxD);
setOpaque(false);
setLayout(new BorderLayout());
setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
add(controlPanel, BorderLayout.CENTER);
}
private HTMLTextArea classShareWarningArea;
private JLabel modeLabel;
private JToggleButton cpuButton;
private JToggleButton memoryButton;
private JButton stopButton;
private JLabel statusLabel;
private HTMLLabel statusValueLabel;
private static final int refLabelHeight = new HTMLLabel("X").getPreferredSize().height; // NOI18N
}
private static final class OneWayToggleButton extends JToggleButton {
public OneWayToggleButton(String text) {
super(text);
}
protected void processMouseEvent(MouseEvent e) {
if (!isSelected()) super.processMouseEvent(e);
}
}
}