/*
* 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.profiling.presets;
import com.sun.tools.visualvm.core.ui.components.SectionSeparator;
import com.sun.tools.visualvm.core.options.UISupport;
import com.sun.tools.visualvm.profiling.presets.ProfilerPresets.PresetsModel;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.FocusEvent;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
import javax.swing.BorderFactory;
import javax.swing.DefaultListModel;
import javax.swing.DefaultListSelectionModel;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
import org.openide.awt.Mnemonics;
import org.openide.util.ImageUtilities;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
/**
*
* @author Jiri Sedlacek
*/
final class ProfilingOptionsPanel extends JPanel {
// final private static Logger LOGGER =
// Logger.getLogger("com.sun.tools.visualvm.profiling.options"); // NOI18N
private final ProfilingOptionsPanelController controller;
private final SamplerCPUSettings samplerCpuSettings;
private final SamplerMemorySettings samplerMemorySettings;
private final ProfilerCPUSettings profilerCpuSettings;
private final ProfilerMemorySettings profilerMemorySettings;
private PresetsModel listModel;
private final ListDataListener listModelListener;
private boolean internalChange;
private boolean nameValid = true;
ProfilingOptionsPanel(ProfilingOptionsPanelController controller) {
this.controller = controller;
Runnable validator = new Runnable() {
public void run() {
ProfilerPreset preset = (ProfilerPreset)list.getSelectedValue();
if (preset == null) return;
preset.setValid(samplerCpuSettings.valid() &&
profilerCpuSettings.valid());
ProfilingOptionsPanel.this.controller.changed();
}
};
samplerCpuSettings = new SamplerCPUSettings(validator);
samplerMemorySettings = new SamplerMemorySettings();
profilerCpuSettings = new ProfilerCPUSettings(validator);
profilerMemorySettings = new ProfilerMemorySettings();
listModelListener = new ListDataListener() {
public void intervalAdded(ListDataEvent e) {
updateComponents();
}
public void intervalRemoved(ListDataEvent e) {
updateComponents();
}
public void contentsChanged(ListDataEvent e) {}
};
initComponents();
}
private void updateComponents() {
int selectedIndex = listModel.isEmpty() ? -1 : list.getSelectedIndex();
if (selectedIndex == listModel.getSize()) return; // isAdjusting
removeButton.setEnabled(selectedIndex != -1);
upButton.setEnabled(selectedIndex > 0);
downButton.setEnabled(selectedIndex < listModel.getSize() - 1);
refreshPreset(selectedIndex);
}
private String createPresetName() {
Set<String> names = new HashSet();
Enumeration presetsE = listModel.elements();
while (presetsE.hasMoreElements())
names.add(presetsE.nextElement().toString());
int presetIndex = 1;
String name = NbBundle.getMessage(ProfilingOptionsPanel.class, "MSG_Preset") + " "; // NOI18N
while (names.contains(name + presetIndex)) presetIndex++;
return name + presetIndex;
}
private void createPreset() {
ProfilerPreset preset = new ProfilerPreset(createPresetName(), ""); // NOI18N
listModel.addPreset(preset);
list.setSelectedIndex(listModel.getSize() - 1);
preselectNameField();
}
private void preselectNameField() {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
nameField.requestFocusInWindow();
nameField.selectAll();
}
});
}
private void deletePreset() {
int selectedIndex = list.getSelectedIndex();
listModel.removePreset(selectedIndex);
if (listModel.getSize() > 0)
list.setSelectedIndex(selectedIndex == listModel.getSize() ?
selectedIndex - 1 : selectedIndex);
}
private void movePresetUp() {
int selectedIndex = list.getSelectedIndex();
listModel.movePresetUp(selectedIndex);
list.setSelectedIndex(selectedIndex - 1);
}
private void movePresetDown() {
int selectedIndex = list.getSelectedIndex();
listModel.movePresetDown(selectedIndex);
list.setSelectedIndex(selectedIndex + 1);
}
private void refreshPreset(int presetIndex) {
ProfilerPreset preset = presetIndex == -1 ? new ProfilerPreset("", "") : // NOI18N
(ProfilerPreset)listModel.get(presetIndex);
internalChange = true;
nameField.setText(preset.getName());
targetField.setText(preset.getSelector());
internalChange = false;
samplerCpuSettings.setPreset(preset);
samplerMemorySettings.setPreset(preset);
profilerCpuSettings.setPreset(preset);
profilerMemorySettings.setPreset(preset);
presetsPanel.setEnabled(presetIndex != -1);
}
private void updatePreset() {
if (internalChange) return;
ProfilerPreset preset = (ProfilerPreset)listModel.get(list.getSelectedIndex());
preset.setName(nameField.getText());
preset.setSelector(targetField.getText());
nameValid = !nameField.getText().isEmpty();
controller.changed();
}
private void initComponents() {
final boolean nimbusLaF =
com.sun.tools.visualvm.uisupport.UISupport.isNimbusLookAndFeel();
GridBagConstraints c;
setLayout(new GridBagLayout());
// --- Presets ---------------------------------------------------------
SectionSeparator presetsSection = UISupport.createSectionSeparator(
NbBundle.getMessage(ProfilingOptionsPanel.class, "CAPTION_Presets")); // NOI18N
c = new GridBagConstraints();
c.gridy = 0;
c.gridwidth = GridBagConstraints.REMAINDER;
c.anchor = GridBagConstraints.WEST;
c.fill = GridBagConstraints.HORIZONTAL;
c.insets = new Insets(0, 0, 5, 0);
add(presetsSection, c);
JPanel listPanel = new JPanel(new BorderLayout());
c = new GridBagConstraints();
c.gridx = 0;
c.gridy = 1;
c.gridwidth = 1;
c.weighty = 0.5;
c.anchor = GridBagConstraints.NORTHWEST;
c.fill = GridBagConstraints.BOTH;
c.insets = new Insets(3, 15, 3, 0);
add(listPanel, c);
list = new JList();
list.setSelectionModel(new DefaultListSelectionModel() {
public void setSelectionInterval(int index0, int index1) {
super.setSelectionInterval(index0, index1);
updateComponents();
}
public void removeSelectionInterval(int i1, int i2) {}
});
list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
final Dimension oneDim = new Dimension(1, 1);
final JLabel noPresetsLabel = new JLabel(NbBundle.getMessage(
ProfilingOptionsPanel.class, "MSG_No_presets"), JLabel.CENTER); // NOI18N
noPresetsLabel.setEnabled(false);
noPresetsLabel.setSize(noPresetsLabel.getPreferredSize());
JScrollPane listScroll = new JScrollPane(list) {
public Dimension getPreferredSize() {
return oneDim;
}
public Dimension getMinimumSize() {
return getPreferredSize();
}
protected void paintChildren(Graphics g) {
super.paintChildren(g);
if (listModel == null || listModel.getSize() == 0) {
int x = (getWidth() - noPresetsLabel.getWidth()) / 2;
int y = (getHeight() - noPresetsLabel.getHeight()) / 2;
g.translate(x, y);
noPresetsLabel.paint(g);
g.translate(-x, -y);
}
}
};
listPanel.add(listScroll, BorderLayout.CENTER);
addButton = new JButton() {
protected void fireActionPerformed(ActionEvent e) {
createPreset();
}
};
addButton.setIcon(new ImageIcon(ImageUtilities.loadImage(
"com/sun/tools/visualvm/profiler/resources/add.png", true))); // NOI18N
addButton.setToolTipText(NbBundle.getMessage(ProfilingOptionsPanel.class,
"TOOLTIP_Create_preset")); // NOI18N
Insets margin = addButton.getMargin();
int mar = nimbusLaF ? 0 : 8;
margin.left = mar;
margin.right = mar;
addButton.setMargin(margin);
removeButton = new JButton() {
protected void fireActionPerformed(ActionEvent e) {
deletePreset();
}
};
removeButton.setIcon(new ImageIcon(ImageUtilities.loadImage(
"com/sun/tools/visualvm/profiler/resources/remove.png", true))); // NOI18N
removeButton.setToolTipText(NbBundle.getMessage(ProfilingOptionsPanel.class,
"TOOLTIP_Delete_preset")); // NOI18N
removeButton.setMargin(margin);
upButton = new JButton() {
protected void fireActionPerformed(ActionEvent e) {
movePresetUp();
}
};
upButton.setIcon(new ImageIcon(ImageUtilities.loadImage(
"com/sun/tools/visualvm/profiler/resources/up.png", true))); // NOI18N
upButton.setToolTipText(NbBundle.getMessage(ProfilingOptionsPanel.class,
"TOOLTIP_preset_up")); // NOI18N
upButton.setMargin(margin);
downButton = new JButton() {
protected void fireActionPerformed(ActionEvent e) {
movePresetDown();
}
};
downButton.setIcon(new ImageIcon(ImageUtilities.loadImage(
"com/sun/tools/visualvm/profiler/resources/down.png", true))); // NOI18N
downButton.setToolTipText(NbBundle.getMessage(ProfilingOptionsPanel.class,
"TOOLTIP_preset_down")); // NOI18N
downButton.setMargin(margin);
JPanel controlsPanel = new JPanel(new GridLayout(1, 4, 5, 0)) {
public void setEnabled(boolean enabled) {
super.setEnabled(enabled);
for (Component c : getComponents())
c.setEnabled(enabled);
}
};
controlsPanel.setBorder(BorderFactory.createEmptyBorder(5, 0, 0, 0));
controlsPanel.add(addButton);
controlsPanel.add(removeButton);
controlsPanel.add(upButton);
controlsPanel.add(downButton);
listPanel.add(controlsPanel, BorderLayout.SOUTH);
JPanel headerPanel = new JPanel(new GridBagLayout()) {
public void setEnabled(boolean enabled) {
super.setEnabled(enabled);
for (Component c : getComponents())
c.setEnabled(enabled);
}
};
JLabel nameLabel = new JLabel();
Mnemonics.setLocalizedText(nameLabel, NbBundle.getMessage(
ProfilingOptionsPanel.class, "LBL_Preset_name")); // NOI18N
c = new GridBagConstraints();
c.gridx = 0;
c.gridy = 0;
c.gridwidth = 1;
c.anchor = GridBagConstraints.WEST;
c.fill = GridBagConstraints.NONE;
c.insets = new Insets(3, 3, 3, 0);
headerPanel.add(nameLabel, c);
nameField = new JTextField();
nameLabel.setLabelFor(nameField);
nameField.getDocument().addDocumentListener(new DocumentListener() {
public void insertUpdate(DocumentEvent e) { updatePreset(); listModel.fireItemChanged(list.getSelectedIndex()); }
public void removeUpdate(DocumentEvent e) { updatePreset(); listModel.fireItemChanged(list.getSelectedIndex()); }
public void changedUpdate(DocumentEvent e) { updatePreset(); listModel.fireItemChanged(list.getSelectedIndex()); }
});
c = new GridBagConstraints();
c.gridx = 1;
c.gridy = 0;
c.weightx = 1;
c.weighty = 1;
c.gridwidth = GridBagConstraints.REMAINDER;
c.anchor = GridBagConstraints.WEST;
c.fill = GridBagConstraints.HORIZONTAL;
c.insets = new Insets(3, 5, 3, 0);
headerPanel.add(nameField, c);
JLabel targetLabel = new JLabel();
Mnemonics.setLocalizedText(targetLabel, NbBundle.getMessage(
ProfilingOptionsPanel.class, "LBL_Preselect_for")); // NOI18N
c = new GridBagConstraints();
c.gridx = 0;
c.gridy = 1;
c.gridwidth = 1;
c.anchor = GridBagConstraints.WEST;
c.fill = GridBagConstraints.NONE;
c.insets = new Insets(3, 3, 13, 0);
headerPanel.add(targetLabel, c);
final JLabel noTargetLabel = new JLabel(NbBundle.getMessage(
ProfilingOptionsPanel.class, "LBL_Optional_class"), JLabel.CENTER); // NOI18N
noTargetLabel.setEnabled(false);
noTargetLabel.setSize(noTargetLabel.getPreferredSize());
targetField = new JTextField() {
protected void paintChildren(Graphics g) {
super.paintChildren(g);
String text = getText();
if (!isFocusOwner() && (text == null || text.isEmpty())) {
int x = nimbusLaF ? 6 : 2;
int y = (getHeight() - noTargetLabel.getHeight()) / 2;
g.translate(x, y);
noTargetLabel.paint(g);
g.translate(-x, -y);
}
}
protected void processFocusEvent(FocusEvent e) {
super.processFocusEvent(e);
repaint();
}
};
targetLabel.setLabelFor(targetField);
targetField.getDocument().addDocumentListener(new DocumentListener() {
public void insertUpdate(DocumentEvent e) { updatePreset(); }
public void removeUpdate(DocumentEvent e) { updatePreset(); }
public void changedUpdate(DocumentEvent e) { updatePreset(); }
});
c = new GridBagConstraints();
c.gridx = 1;
c.gridy = 1;
c.gridwidth = GridBagConstraints.REMAINDER;
c.anchor = GridBagConstraints.WEST;
c.fill = GridBagConstraints.HORIZONTAL;
c.insets = new Insets(3, 5, 13, 0);
headerPanel.add(targetField, c);
JTabbedPane settingsPanel = new JTabbedPane() {
public void setEnabled(boolean enabled) {
super.setEnabled(enabled);
for (Component c : getComponents())
c.setEnabled(enabled);
}
};
settingsPanel.addTab(NbBundle.getMessage(ProfilingOptionsPanel.class,
"LBL_Sampler_cpu"), new ImageIcon(ImageUtilities.loadImage( // NOI18N
"com/sun/tools/visualvm/profiling/resources/sampler.png", true)), // NOI18N
samplerCpuSettings);
settingsPanel.addTab(NbBundle.getMessage(ProfilingOptionsPanel.class,
"LBL_Sampler_memory"), new ImageIcon(ImageUtilities.loadImage( // NOI18N
"com/sun/tools/visualvm/profiling/resources/sampler.png", true)), // NOI18N
samplerMemorySettings);
settingsPanel.addTab(NbBundle.getMessage(ProfilingOptionsPanel.class,
"LBL_Profiler_cpu"), new ImageIcon(ImageUtilities.loadImage( // NOI18N
"com/sun/tools/visualvm/profiling/resources/profiler.png", true)), // NOI18N
profilerCpuSettings);
settingsPanel.addTab(NbBundle.getMessage(ProfilingOptionsPanel.class,
"LBL_Profiler_memory"), new ImageIcon(ImageUtilities.loadImage( // NOI18N
"com/sun/tools/visualvm/profiling/resources/profiler.png", true)), // NOI18N
profilerMemorySettings);
presetsPanel = new JPanel(new BorderLayout()) {
public void setEnabled(boolean enabled) {
super.setEnabled(enabled);
for (Component c : getComponents())
c.setEnabled(enabled);
}
};
presetsPanel.add(headerPanel, BorderLayout.NORTH);
presetsPanel.add(settingsPanel, BorderLayout.CENTER);
c = new GridBagConstraints();
c.gridx = 1;
c.gridy = 1;
c.weightx = 1;
c.gridwidth = GridBagConstraints.REMAINDER;
c.anchor = GridBagConstraints.NORTHWEST;
c.fill = GridBagConstraints.BOTH;
c.insets = new Insets(3, 8, 3, 0);
add(presetsPanel, c);
// --- Misellaneous ----------------------------------------------------
int gridy = 50;
for (ProfilingOptionsSectionProvider provider : Lookup.getDefault().lookupAll(
ProfilingOptionsSectionProvider.class)) {
SectionSeparator section = UISupport.createSectionSeparator(provider.getSectionName());
c = new GridBagConstraints();
c.gridy = gridy++;
c.gridwidth = GridBagConstraints.REMAINDER;
c.anchor = GridBagConstraints.NORTHWEST;
c.fill = GridBagConstraints.HORIZONTAL;
c.insets = new Insets(15, 0, 5, 0);
add(section, c);
c = new GridBagConstraints();
c.gridy = gridy++;
c.gridwidth = GridBagConstraints.REMAINDER;
c.anchor = GridBagConstraints.WEST;
c.fill = GridBagConstraints.HORIZONTAL;
c.insets = new Insets(2, 15, 3, 0);
add(provider.getSection(), c);
}
}
void load() {
listModel = ProfilerPresets.getInstance().getPresets();
listModel.addListDataListener(listModelListener);
list.setModel(listModel);
int items = listModel.getSize();
ProfilerPreset toCreate = ProfilerPresets.getInstance().presetToCreate();
if (toCreate != null) {
toCreate.setName(createPresetName());
listModel.addElement(toCreate);
list.setSelectedIndex(items);
} else if (listModel.size() > 0) {
ProfilerPreset select = ProfilerPresets.getInstance().presetToSelect();
String toSelect = select == null ? null : select.getName();
int indexToSelect = 0;
if (toSelect != null) {
for (int i = 0; i < items; i++) {
ProfilerPreset preset = (ProfilerPreset)listModel.get(i);
if (preset.getName().equals(toSelect)) {
indexToSelect = i;
break;
}
}
}
list.setSelectedIndex(indexToSelect);
}
updateComponents();
if (toCreate != null) preselectNameField();
}
void store() {
ProfilerPresets.getInstance().savePresets(listModel);
ProfilerPreset selected = (ProfilerPreset)list.getSelectedValue();
ProfilerPresets.getInstance().optionsSubmitted(selected);
}
void closed() {
if (listModel != null) listModel.removeListDataListener(listModelListener);
list.setModel(new DefaultListModel());
}
boolean valid() {
return nameValid && presetsValid();
}
private boolean presetsValid() {
Enumeration presets = listModel.elements();
while (presets.hasMoreElements()) {
ProfilerPreset preset = (ProfilerPreset)presets.nextElement();
if (!preset.isValid()) return false;
}
return true;
}
private JPanel presetsPanel;
private JList list;
private JButton addButton;
private JButton removeButton;
private JButton upButton;
private JButton downButton;
private JTextField nameField;
private JTextField targetField;
}