/* * 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 java.awt.Color; 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 javax.swing.AbstractButton; import javax.swing.BorderFactory; import javax.swing.ButtonGroup; import javax.swing.JCheckBox; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JRadioButton; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.UIManager; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import org.netbeans.lib.profiler.client.ClientUtils; import org.netbeans.lib.profiler.common.ProfilingSettings; import org.netbeans.lib.profiler.common.ProfilingSettingsPresets; import org.netbeans.lib.profiler.common.filters.FilterUtils; import org.netbeans.lib.profiler.common.filters.SimpleFilter; import org.netbeans.lib.profiler.global.CommonConstants; import org.openide.awt.Mnemonics; import org.openide.util.NbBundle; /** * * @author Jiri Sedlacek */ public abstract class ProfilerCPUPanel extends JPanel { private JLabel rootClassesLabel; private TextAreaComponent rootsArea; private JCheckBox runnablesCheckBox; private JRadioButton inclFilterRadioButton; private JRadioButton exclFilterRadioButton; private TextAreaComponent filtersArea; private final Runnable validator; private boolean rootsValid = true; private boolean filtersValid = true; private boolean internalChange; public ProfilerCPUPanel() { this(null, false); } ProfilerCPUPanel(Runnable validator, boolean mnemonics) { this.validator = validator; initComponents(mnemonics); } public ProfilingSettings getSettings() { ProfilingSettings settings = ProfilingSettingsPresets.createCPUPreset(ProfilingSettings.PROFILE_CPU_ENTIRE); settings.setInstrScheme(CommonConstants.INSTRSCHEME_LAZY); String instrFilterString = getFilterValue(); SimpleFilter instrFilter = (instrFilterString.isEmpty() || "*".equals(instrFilterString)) ? SimpleFilter.NO_FILTER : // NOI18N new SimpleFilter(instrFilterString, inclFilterRadioButton.isSelected() ? SimpleFilter.SIMPLE_FILTER_INCLUSIVE : SimpleFilter.SIMPLE_FILTER_EXCLUSIVE, instrFilterString); settings.setSelectedInstrumentationFilter(instrFilter); String[] rootValues = getRootValue().split(","); // NOI18N ClientUtils.SourceCodeSelection[] roots = (rootValues.length == 1 && rootValues[0].isEmpty()) ? new ClientUtils.SourceCodeSelection[0] : new ClientUtils.SourceCodeSelection[rootValues.length]; for (int i = 0; i < roots.length; i++) roots[i] = new ClientUtils.SourceCodeSelection(rootValues[i], "*", null); // NOI18N settings.setInstrumentationRootMethods(roots); settings.setInstrumentSpawnedThreads(runnablesCheckBox.isSelected()); return settings; } public boolean settingsValid() { return rootsValid && filtersValid; } public void loadFromPreset(ProfilerPreset preset) { if (preset == null) return; internalChange = true; rootsArea.getTextArea().setText(preset.getRootsP()); runnablesCheckBox.setSelected(preset.getRunnablesP()); inclFilterRadioButton.setSelected(!preset.getFilterModeP()); exclFilterRadioButton.setSelected(preset.getFilterModeP()); filtersArea.getTextArea().setText(preset.getFilterP()); internalChange = false; } public void saveToPreset(ProfilerPreset preset) { if (preset == null) return; preset.setRootsP(rootsArea.getTextArea().getText()); preset.setRunnablesP(runnablesCheckBox.isSelected()); preset.setFilterModeP(exclFilterRadioButton.isSelected()); preset.setFilterP(filtersArea.getTextArea().getText()); } public abstract void settingsChanged(); private void syncUI() { if (internalChange) return; settingsChanged(); } private void checkRootValidity() { rootsValid = isRootValueValid(); rootsArea.getTextArea().setForeground(rootsValid ? UIManager.getColor("TextArea.foreground") : Color.RED); // NOI18N if (validator != null) validator.run(); } public boolean isRootValueValid() { String[] rootParts = FilterUtils.getSeparateFilters(getRootValue()); for (int i = 0; i < rootParts.length; i++) if (!FilterUtils.isValidProfilerFilter(rootParts[i])) if (rootParts[i].endsWith("**")) { // NOI18N if (!FilterUtils.isValidProfilerFilter(rootParts[i].substring(0, rootParts[i].length() - 1))) return false; } else { return false; } return true; } private String getRootValue() { StringBuilder convertedValue = new StringBuilder(); String[] rootValues = getRootsValues(); for (int i = 0; i < rootValues.length; i++) { String filterValue = rootValues[i].trim(); if ((i != (rootValues.length - 1)) && !filterValue.endsWith(",")) { // NOI18N filterValue = filterValue + ","; // NOI18N } convertedValue.append(filterValue); } return convertedValue.toString(); } private String[] getRootsValues() { return rootsArea.getTextArea().getText().split("\\n"); // NOI18N } private void checkFilterValidity() { filtersValid = isFilterValueValid(); filtersArea.getTextArea().setForeground(filtersValid ? UIManager.getColor("TextArea.foreground") : Color.RED); // NOI18N if (validator != null) validator.run(); } public boolean isFilterValueValid() { String[] filterParts = FilterUtils.getSeparateFilters(getFilterValue()); for (int i = 0; i < filterParts.length; i++) if (!FilterUtils.isValidProfilerFilter(filterParts[i])) return false; return true; } private String getFilterValue() { StringBuilder convertedValue = new StringBuilder(); String[] filterValues = getFilterValues(); for (int i = 0; i < filterValues.length; i++) { String filterValue = filterValues[i].trim(); if ((i != (filterValues.length - 1)) && !filterValue.endsWith(",")) { // NOI18N filterValue = filterValue + ", "; // NOI18N } convertedValue.append(filterValue); } return convertedValue.toString(); } private String[] getFilterValues() { return filtersArea.getTextArea().getText().split("\\n"); // NOI18N } public void setEnabled(boolean enabled) { super.setEnabled(enabled); for (Component c : getComponents()) c.setEnabled(enabled); } private void initComponents(boolean mnemonics) { setOpaque(false); setLayout(new GridBagLayout()); ButtonGroup filterRadiosGroup = new ButtonGroup(); GridBagConstraints constraints; rootClassesLabel = new JLabel(); setText(rootClassesLabel, NbBundle.getMessage(ProfilerCPUSettings.class, "LBL_Root_Classes"), mnemonics); Dimension d = rootClassesLabel.getPreferredSize(); JRadioButton refRadion = new JRadioButton(NbBundle.getMessage(ProfilerCPUSettings.class, "LBL_Root_Classes")); // NOI18N refRadion.setBorder(rootClassesLabel.getBorder()); d.height = Math.max(d.height, refRadion.getPreferredSize().height); rootClassesLabel.setPreferredSize(d); rootClassesLabel.setToolTipText(NbBundle.getMessage(ProfilerCPUSettings.class, "TOOLTIP_Root_Classes")); // NOI18N rootClassesLabel.setOpaque(false); constraints = new GridBagConstraints(); constraints.gridx = 0; constraints.gridy = 1; constraints.gridwidth = GridBagConstraints.REMAINDER; constraints.anchor = GridBagConstraints.WEST; constraints.fill = GridBagConstraints.NONE; constraints.insets = new Insets(10, 10, 5, 10); add(rootClassesLabel, constraints); rootsArea = createTextArea(2); rootClassesLabel.setLabelFor(rootsArea.getTextArea()); rootsArea.getTextArea().setToolTipText(NbBundle.getMessage(ProfilerCPUSettings.class, "TOOLTIP_Root_Classes")); // NOI18N rootsArea.getTextArea().getDocument().addDocumentListener(new DocumentListener() { public void insertUpdate(DocumentEvent e) { checkRootValidity(); syncUI(); } public void removeUpdate(DocumentEvent e) { checkRootValidity(); syncUI(); } public void changedUpdate(DocumentEvent e) { checkRootValidity(); syncUI(); } }); constraints = new GridBagConstraints(); constraints.gridx = 0; constraints.gridy = 2; constraints.weightx = 1; constraints.weighty = 0.65; constraints.gridwidth = GridBagConstraints.REMAINDER; constraints.anchor = GridBagConstraints.NORTHWEST; constraints.fill = GridBagConstraints.BOTH; constraints.insets = new Insets(0, 10, 7, 10); add(rootsArea, constraints); runnablesCheckBox = new JCheckBox() { protected void fireActionPerformed(ActionEvent e) { syncUI(); } }; setText(runnablesCheckBox, NbBundle.getMessage(ProfilerCPUSettings.class, "LBL_Profile_Runnables"), mnemonics); runnablesCheckBox.setToolTipText(NbBundle.getMessage(ProfilerCPUSettings.class, "TOOLTIP_New_Runnables")); // NOI18N runnablesCheckBox.setOpaque(false); runnablesCheckBox.setBorder(rootClassesLabel.getBorder()); constraints = new GridBagConstraints(); constraints.gridx = 0; constraints.gridy = 3; constraints.gridwidth = GridBagConstraints.REMAINDER; constraints.anchor = GridBagConstraints.WEST; constraints.fill = GridBagConstraints.NONE; constraints.insets = new Insets(0, 10, 10, 10); add(runnablesCheckBox, constraints); inclFilterRadioButton = new JRadioButton() { protected void fireActionPerformed(ActionEvent e) { syncUI(); } }; setText(inclFilterRadioButton, NbBundle.getMessage(ProfilerCPUSettings.class, "LBL_Profile_Incl"), mnemonics); inclFilterRadioButton.setToolTipText(NbBundle.getMessage(ProfilerCPUSettings.class, "TOOLTIP_Inclusive_Filter")); // NOI18N inclFilterRadioButton.setOpaque(false); inclFilterRadioButton.setBorder(rootClassesLabel.getBorder()); filterRadiosGroup.add(inclFilterRadioButton); constraints = new GridBagConstraints(); constraints.gridx = 0; constraints.gridy = 4; constraints.gridwidth = 1; constraints.anchor = GridBagConstraints.WEST; constraints.fill = GridBagConstraints.NONE; constraints.insets = new Insets(5, 10, 5, 5); add(inclFilterRadioButton, constraints); exclFilterRadioButton = new JRadioButton() { protected void fireActionPerformed(ActionEvent e) { syncUI(); } }; setText(exclFilterRadioButton, NbBundle.getMessage(ProfilerCPUSettings.class, "LBL_Profile_Excl"), mnemonics); exclFilterRadioButton.setToolTipText(NbBundle.getMessage(ProfilerCPUSettings.class, "TOOLTIP_Exclusive_Filter")); // NOI18N exclFilterRadioButton.setOpaque(false); exclFilterRadioButton.setBorder(rootClassesLabel.getBorder()); filterRadiosGroup.add(exclFilterRadioButton); constraints = new GridBagConstraints(); constraints.gridx = 1; constraints.gridy = 4; constraints.gridwidth = 1; constraints.anchor = GridBagConstraints.WEST; constraints.fill = GridBagConstraints.NONE; constraints.insets = new Insets(5, 5, 5, 10); add(exclFilterRadioButton, constraints); filtersArea = createTextArea(2); filtersArea.getTextArea().setToolTipText(NbBundle.getMessage(ProfilerCPUSettings.class, "TOOLTIP_Instrumentation_Filter")); // NOI18N filtersArea.getTextArea().getDocument().addDocumentListener(new DocumentListener() { public void insertUpdate(DocumentEvent e) { checkFilterValidity(); syncUI(); } public void removeUpdate(DocumentEvent e) { checkFilterValidity(); syncUI(); } public void changedUpdate(DocumentEvent e) { checkFilterValidity(); syncUI(); } }); constraints = new GridBagConstraints(); constraints.gridx = 0; constraints.gridy = 5; constraints.weighty = 0.35; constraints.gridwidth = GridBagConstraints.REMAINDER; constraints.anchor = GridBagConstraints.NORTHWEST; constraints.fill = GridBagConstraints.BOTH; constraints.insets = new Insets(0, 10, 10, 10); add(filtersArea, constraints); } private static void setText(JLabel l, String text, boolean mnemonics) { if (mnemonics) Mnemonics.setLocalizedText(l, text); else l.setText(text.replace("&", "")); // NOI18N } private static void setText(AbstractButton b, String text, boolean mnemonics) { if (mnemonics) Mnemonics.setLocalizedText(b, text); else b.setText(text.replace("&", "")); // NOI18N } private static TextAreaComponent createTextArea(int rows) { final JTextArea rootsArea = new JTextArea(); rootsArea.setFont(new Font("Monospaced", Font.PLAIN, UIManager.getFont("Label.font").getSize())); // NOI18N TextAreaComponent rootsAreaScrollPane = new TextAreaComponent(rootsArea, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED) { public Dimension getMinimumSize() { return getPreferredSize(); } public void setEnabled(boolean enabled) { super.setEnabled(enabled); rootsArea.setEnabled(enabled); } }; rootsAreaScrollPane.setBorder(BorderFactory.createLineBorder(Color.GRAY)); JTextArea referenceArea = new JTextArea("X"); // NOI18N referenceArea.setFont(rootsArea.getFont()); referenceArea.setRows(rows); Insets insets = rootsAreaScrollPane.getInsets(); rootsAreaScrollPane.setPreferredSize(new Dimension(1, referenceArea.getPreferredSize().height + (insets != null ? insets.top + insets.bottom : 0))); return rootsAreaScrollPane; } private static class TextAreaComponent extends JScrollPane { public TextAreaComponent(JTextArea textArea, int vPolicy, int hPolicy) { super(textArea, vPolicy, hPolicy); } public JTextArea getTextArea() { return (JTextArea)getViewport().getView(); } } }