001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: * The Original Software is NetBeans. The Initial Developer of the Original
026: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
027: * Microsystems, Inc. All Rights Reserved.
028: *
029: * If you wish your version of this file to be governed by only the CDDL
030: * or only the GPL Version 2, indicate your decision by adding
031: * "[Contributor] elects to include this software in this distribution
032: * under the [CDDL or GPL Version 2] license." If you do not indicate a
033: * single choice of license, a recipient has the option to distribute
034: * your version of this file under either the CDDL, the GPL Version 2 or
035: * to extend the choice of license to its licensees as provided above.
036: * However, if you add GPL Version 2 code and therefore, elected the GPL
037: * Version 2 license, then the option applies only if the new code is
038: * made subject to such option by the copyright holder.
039: */
040:
041: package org.netbeans.modules.profiler.ui.panels;
042:
043: import org.netbeans.api.project.Project;
044: import org.netbeans.api.project.ui.OpenProjects;
045: import org.netbeans.lib.profiler.client.ClientUtils;
046: import org.netbeans.lib.profiler.ui.UIUtils;
047: import org.netbeans.lib.profiler.ui.components.HTMLTextArea;
048: import org.netbeans.lib.profiler.utils.formatting.DefaultMethodNameFormatter;
049: import org.netbeans.lib.profiler.utils.formatting.MethodNameFormatter;
050: import org.netbeans.lib.profiler.utils.formatting.MethodNameFormatterFactory;
051: import org.netbeans.modules.profiler.selector.ui.RootSelectorNode;
052: import org.netbeans.modules.profiler.selector.ui.RootSelectorTree;
053: import org.netbeans.modules.profiler.ui.ManualMethodSelect;
054: import org.netbeans.modules.profiler.ui.ProfilerDialogs;
055: import org.netbeans.modules.profiler.utilities.trees.TreeDecimator;
056: import org.netbeans.modules.profiler.utilities.trees.TreeDecimator.NodeFilter;
057: import org.openide.DialogDescriptor;
058: import org.openide.util.NbBundle;
059: import org.openide.util.RequestProcessor;
060: import java.awt.*;
061: import java.awt.event.ActionEvent;
062: import java.awt.event.ActionListener;
063: import java.util.ArrayList;
064: import java.util.Iterator;
065: import javax.swing.*;
066: import javax.swing.event.ListSelectionEvent;
067: import javax.swing.event.ListSelectionListener;
068:
069: /**
070: * @author Tomas Hurka
071: * @author Ian Formanek
072: * @author Misha Dmitriev
073: */
074: public final class RootMethodsPanel extends JPanel implements
075: ActionListener, ListSelectionListener {
076: //~ Static fields/initializers -----------------------------------------------------------------------------------------------
077:
078: // -----
079: // I18N String constants
080: private static final String ROOT_METHODS_LABEL_TEXT = NbBundle
081: .getMessage(RootMethodsPanel.class,
082: "RootMethodsPanel_RootMethodsLabelText"); //NOI18N
083: private static final String ADD_FROM_PROJECTBUTTON_TEXT = NbBundle
084: .getMessage(RootMethodsPanel.class,
085: "RootMethodsPanel_AddButtonText"); //NOI18N
086: private static final String ADD_MANUAL_BUTTON_TEXT = NbBundle
087: .getMessage(RootMethodsPanel.class,
088: "RootMethodsPanel_AddManualButtonText"); //NOI18N
089: private static final String REMOVE_BUTTON_TEXT = NbBundle
090: .getMessage(RootMethodsPanel.class,
091: "RootMethodsPanel_RemoveButtonText"); //NOI18N
092: private static final String MESSAGE_AREA_TEXT = NbBundle
093: .getMessage(RootMethodsPanel.class,
094: "RootMethodsPanel_MessageAreaText"); //NOI18N
095: private static final String SPECIFY_ROOT_METHODS_DIALOG_CAPTION = NbBundle
096: .getMessage(RootMethodsPanel.class,
097: "RootMethodsPanel_SpecifyRootMethodsDialogCaption"); //NOI18N
098: private static final String ROOTS_LIST_ACCESS_NAME = NbBundle
099: .getMessage(RootMethodsPanel.class,
100: "RootMethodsPanel_RootsListAccessName"); //NOI18N
101: private static final String ADD_FROM_PROJECT_BUTTON_ACCESS_DESCR = NbBundle
102: .getMessage(RootMethodsPanel.class,
103: "RootMethodsPanel_AddFromProjectButtonAccessDescr"); //NOI18N
104: private static final String ADD_MANUALLY_BUTTON_ACCESS_DESCR = NbBundle
105: .getMessage(RootMethodsPanel.class,
106: "RootMethodsPanel_AddManuallyButtonAccessDescr"); //NOI18N
107: private static final String REMOVE_BUTTON_ACCESS_DESCR = NbBundle
108: .getMessage(RootMethodsPanel.class,
109: "RootMethodsPanel_RemoveButtonAccessDescr"); //NOI18N
110: // -----
111: private static RootMethodsPanel defaultInstance;
112: private static MethodNameFormatterFactory formatterFactory = MethodNameFormatterFactory
113: .getDefault(new DefaultMethodNameFormatter(
114: DefaultMethodNameFormatter.VERBOSITY_FULLCLASSMETHOD));
115:
116: //~ Instance fields ----------------------------------------------------------------------------------------------------------
117:
118: private ArrayList selectedRoots = new ArrayList();
119: private DefaultListModel rootsListModel;
120: private HTMLTextArea hintArea;
121: private JButton addFromProjectButton;
122: private JButton addManualButton;
123: private JButton removeButton;
124: private JList rootsList;
125: private Project project;
126: private boolean globalAttach = false;
127:
128: //~ Constructors -------------------------------------------------------------------------------------------------------------
129:
130: /**
131: * Creates new form RootMethodsPanel
132: */
133: private RootMethodsPanel() {
134: super ();
135: initComponents();
136: }
137:
138: //~ Methods ------------------------------------------------------------------------------------------------------------------
139:
140: public static ClientUtils.SourceCodeSelection[] getSelectedRootMethods(
141: ClientUtils.SourceCodeSelection[] roots, Project project) {
142: final RootMethodsPanel rm = getDefault();
143: rm.project = project;
144: rm.globalAttach = rm.project == null;
145: rm.addFromProjectButton
146: .setEnabled(!rm.globalAttach
147: || (OpenProjects.getDefault().getOpenProjects().length > 0));
148: rm.refreshList(roots);
149:
150: return performDisplay(rm);
151: }
152:
153: /**
154: * Invoked when an action occurs.
155: */
156: public void actionPerformed(final ActionEvent e) {
157: if (e.getSource() == addFromProjectButton) {
158: RequestProcessor.getDefault().post(new Runnable() {
159: public void run() {
160: final ClientUtils.SourceCodeSelection[] sel = ProjectSelectRootMethodsPanel
161: .getDefault()
162: .getRootMethods(
163: project,
164: (ClientUtils.SourceCodeSelection[]) selectedRoots
165: .toArray(new ClientUtils.SourceCodeSelection[] {
166:
167: }));
168:
169: if (sel != null) {
170: addNewRootMethods(sel, true);
171: }
172: }
173: });
174: } else if (e.getSource() == addManualButton) {
175: final ClientUtils.SourceCodeSelection scs = ManualMethodSelect
176: .selectMethod();
177:
178: if (scs != null) {
179: if (!selectedRoots.contains(scs)) {
180: selectedRoots.add(scs);
181:
182: String newItem = formatterFactory.getFormatter()
183: .formatMethodName(scs).toFormatted();
184: rootsListModel.addElement(newItem);
185: rootsList.setSelectedValue(newItem, true);
186: }
187: }
188: } else if (e.getSource() == removeButton) {
189: final int[] selectedSessionIndices = rootsList
190: .getSelectedIndices();
191:
192: for (int i = selectedSessionIndices.length - 1; i >= 0; i--) {
193: rootsListModel.remove(selectedSessionIndices[i]);
194: selectedRoots.remove(selectedSessionIndices[i]);
195: }
196:
197: int toSelect = -1;
198:
199: if (selectedSessionIndices.length > 0) {
200: toSelect = selectedSessionIndices[0];
201: }
202:
203: if (toSelect >= rootsListModel.size()) {
204: toSelect = rootsListModel.size() - 1;
205: }
206:
207: rootsList.setSelectedIndex(toSelect);
208: updateButtons();
209: }
210: }
211:
212: /**
213: * Called whenever the value of the selection changes.
214: *
215: * @param e the event that characterizes the change.
216: */
217: public void valueChanged(final ListSelectionEvent e) {
218: updateButtons();
219: }
220:
221: private static RootMethodsPanel getDefault() {
222: if (defaultInstance == null) {
223: defaultInstance = new RootMethodsPanel();
224: }
225:
226: return defaultInstance;
227: }
228:
229: // ---------------------------------------------------------------------------
230: private static ClientUtils.SourceCodeSelection[] performDisplay(
231: final RootMethodsPanel rm) {
232: final DialogDescriptor dd = new DialogDescriptor(rm,
233: SPECIFY_ROOT_METHODS_DIALOG_CAPTION);
234: final Dialog d = ProfilerDialogs.createDialog(dd);
235:
236: if (rm.addFromProjectButton.isEnabled()) {
237: rm.addFromProjectButton.grabFocus();
238: }
239:
240: d.setVisible(true);
241:
242: if (dd.getValue() == DialogDescriptor.OK_OPTION) {
243: ClientUtils.SourceCodeSelection[] ret = new ClientUtils.SourceCodeSelection[rm.selectedRoots
244: .size()];
245: rm.selectedRoots.toArray(ret);
246:
247: return ret;
248: }
249:
250: return null;
251: }
252:
253: private void addNewRootMethods(
254: ClientUtils.SourceCodeSelection[] sel, boolean clean) {
255: if (clean) {
256: selectedRoots.clear();
257: rootsListModel.clear();
258: }
259:
260: MethodNameFormatter formatter = formatterFactory.getFormatter();
261:
262: for (int i = 0; i < sel.length; i++) {
263: final ClientUtils.SourceCodeSelection scs = sel[i];
264:
265: if (!selectedRoots.contains(scs)) {
266: selectedRoots.add(scs);
267: rootsListModel.addElement(formatter.formatMethodName(
268: scs).toFormatted());
269:
270: // new MethodNameFormatter(
271: // scs.getClassName(), scs.getMethodName(), scs.getMethodSignature()
272: // ).getFullFormattedClassAndMethod()
273: // );
274: }
275: }
276: }
277:
278: private void initComponents() {
279: GridBagConstraints gridBagConstraints;
280: setLayout(new GridBagLayout());
281: gridBagConstraints = new GridBagConstraints();
282: gridBagConstraints.insets = new Insets(12, 12, 12, 12);
283:
284: JLabel label = new JLabel();
285: JScrollPane rootsScrollPane = new JScrollPane();
286: rootsList = new JList();
287:
288: JPanel buttonPanel = new JPanel();
289: addFromProjectButton = new JButton();
290: addManualButton = new JButton();
291: removeButton = new JButton();
292: hintArea = new HTMLTextArea() {
293: public Dimension getPreferredSize() { // Workaround to force the text area not to consume horizontal space to fit the contents to just one line
294:
295: return new Dimension(1, super .getPreferredSize().height);
296: }
297: };
298:
299: org.openide.awt.Mnemonics.setLocalizedText(label,
300: ROOT_METHODS_LABEL_TEXT);
301: label.setLabelFor(rootsList);
302: label.setIconTextGap(10);
303: gridBagConstraints = new GridBagConstraints();
304: gridBagConstraints.gridx = 0;
305: gridBagConstraints.gridy = 0;
306: gridBagConstraints.gridwidth = GridBagConstraints.REMAINDER;
307: gridBagConstraints.fill = GridBagConstraints.HORIZONTAL;
308: gridBagConstraints.anchor = GridBagConstraints.NORTHWEST;
309: gridBagConstraints.insets = new Insets(12, 12, 5, 12);
310: add(label, gridBagConstraints);
311:
312: rootsList.getAccessibleContext().setAccessibleName(
313: ROOTS_LIST_ACCESS_NAME);
314:
315: rootsScrollPane.setViewportView(rootsList);
316: rootsScrollPane.setPreferredSize(new Dimension(330,
317: rootsScrollPane.getPreferredSize().height));
318: gridBagConstraints = new GridBagConstraints();
319: gridBagConstraints.gridx = 0;
320: gridBagConstraints.gridy = 3;
321: gridBagConstraints.gridwidth = 2;
322: gridBagConstraints.fill = GridBagConstraints.BOTH;
323: gridBagConstraints.anchor = GridBagConstraints.NORTHWEST;
324: gridBagConstraints.weightx = 1.0;
325: gridBagConstraints.weighty = 1.0;
326: gridBagConstraints.insets = new Insets(0, 24, 0, 12);
327: add(rootsScrollPane, gridBagConstraints);
328:
329: buttonPanel.setLayout(new GridLayout(4, 1, 0, 5));
330:
331: buttonPanel.setOpaque(false);
332:
333: org.openide.awt.Mnemonics.setLocalizedText(
334: addFromProjectButton, ADD_FROM_PROJECTBUTTON_TEXT);
335: addFromProjectButton.getAccessibleContext()
336: .setAccessibleDescription(
337: ADD_FROM_PROJECT_BUTTON_ACCESS_DESCR);
338: buttonPanel.add(addFromProjectButton);
339:
340: org.openide.awt.Mnemonics.setLocalizedText(addManualButton,
341: ADD_MANUAL_BUTTON_TEXT);
342: addManualButton.getAccessibleContext()
343: .setAccessibleDescription(
344: ADD_MANUALLY_BUTTON_ACCESS_DESCR);
345: buttonPanel.add(addManualButton);
346:
347: org.openide.awt.Mnemonics.setLocalizedText(removeButton,
348: REMOVE_BUTTON_TEXT);
349: removeButton.getAccessibleContext().setAccessibleDescription(
350: REMOVE_BUTTON_ACCESS_DESCR);
351: buttonPanel.add(removeButton);
352:
353: gridBagConstraints = new GridBagConstraints();
354: gridBagConstraints.gridx = 2;
355: gridBagConstraints.gridy = 3;
356: gridBagConstraints.anchor = GridBagConstraints.NORTH;
357: gridBagConstraints.insets = new Insets(0, 0, 0, 12);
358: add(buttonPanel, gridBagConstraints);
359:
360: Color panelBackground = UIManager.getColor("Panel.background"); //NOI18N
361: Color hintBackground = UIUtils.getSafeColor(panelBackground
362: .getRed() - 10, panelBackground.getGreen() - 10,
363: panelBackground.getBlue() - 10);
364:
365: // hintArea
366: hintArea.setText(MESSAGE_AREA_TEXT); // NOI18N
367: hintArea.setEnabled(false);
368: hintArea.setDisabledTextColor(Color.darkGray);
369: hintArea.setBackground(hintBackground);
370: hintArea.setBorder(BorderFactory.createMatteBorder(10, 10, 10,
371: 10, hintBackground));
372: gridBagConstraints = new GridBagConstraints();
373: gridBagConstraints.gridx = 0;
374: gridBagConstraints.gridy = 4;
375: gridBagConstraints.weightx = 1;
376: gridBagConstraints.gridwidth = GridBagConstraints.REMAINDER;
377: gridBagConstraints.insets = new Insets(12, 12, 0, 12);
378: gridBagConstraints.anchor = GridBagConstraints.NORTHWEST;
379: gridBagConstraints.fill = GridBagConstraints.BOTH;
380: add(hintArea, gridBagConstraints);
381:
382: addFromProjectButton.addActionListener(this );
383: addManualButton.addActionListener(this );
384: removeButton.addActionListener(this );
385: rootsList.addListSelectionListener(this );
386: }
387:
388: private void refreshList(
389: final ClientUtils.SourceCodeSelection[] roots) {
390: selectedRoots.clear();
391:
392: for (int i = 0; i < roots.length; i++) {
393: ClientUtils.SourceCodeSelection root = roots[i];
394:
395: if (root != null) {
396: selectedRoots.add(root);
397: }
398: }
399:
400: rootsListModel = new DefaultListModel();
401: updateList();
402: rootsList.setModel(rootsListModel);
403:
404: updateButtons();
405: }
406:
407: private void updateButtons() {
408: removeButton
409: .setEnabled(rootsList.getSelectedIndices().length > 0);
410: }
411:
412: private void updateList() {
413: rootsListModel.removeAllElements();
414:
415: MethodNameFormatter formatter = formatterFactory.getFormatter();
416:
417: for (Iterator it = selectedRoots.iterator(); it.hasNext();) {
418: final ClientUtils.SourceCodeSelection scs = (ClientUtils.SourceCodeSelection) it
419: .next();
420: rootsListModel.addElement(formatter.formatMethodName(scs)
421: .toFormatted());
422:
423: // new MethodNameFormatter(
424: // scs.getClassName(), scs.getMethodName(), scs.getMethodSignature()
425: // ).getFullFormattedClassAndMethod()
426: // );
427: }
428: }
429: }
|