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: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.apache.tools.ant.module.run;
043:
044: import java.awt.Component;
045: import java.text.Collator;
046: import java.util.Comparator;
047: import java.util.Map;
048: import java.util.SortedSet;
049: import java.util.TreeSet;
050: import javax.swing.DefaultListCellRenderer;
051: import javax.swing.DefaultListModel;
052: import javax.swing.JButton;
053: import javax.swing.JList;
054: import javax.swing.JPanel;
055: import javax.swing.event.ListSelectionEvent;
056: import javax.swing.event.ListSelectionListener;
057: import org.openide.DialogDescriptor;
058: import org.openide.DialogDisplayer;
059: import org.openide.NotifyDescriptor;
060: import org.openide.util.NbBundle;
061:
062: /**
063: * Displays an alert asking user to pick a running build to stop.
064: * @author Jesse Glick
065: */
066: final class StopBuildingAlert extends JPanel {
067:
068: /**
069: * Select one or more processes to kill among several choices.
070: * @param processesWithDisplayNames a list of possible threads to kill, mapped to display names
071: * @return the selection(s) (or empty if cancelled)
072: */
073: public static Thread[] selectProcessToKill(
074: final Map<Thread, String> processesWithDisplayNames) {
075: StopBuildingAlert alert = new StopBuildingAlert(
076: processesWithDisplayNames);
077: final JList list = alert.buildsList;
078: // Add all threads, sorted by display name.
079: DefaultListModel model = new DefaultListModel();
080: Comparator<Thread> comp = new Comparator<Thread>() {
081: private final Collator coll = Collator.getInstance();
082:
083: public int compare(Thread t1, Thread t2) {
084: String n1 = processesWithDisplayNames.get(t1);
085: String n2 = processesWithDisplayNames.get(t2);
086: int r = coll.compare(n1, n2);
087: if (r != 0) {
088: return r;
089: } else {
090: // Arbitrary. XXX Note that there is no way to predict which is
091: // which if you have more than one build running. Ideally it
092: // would be subsorted by creation time, probably.
093: return System.identityHashCode(t1)
094: - System.identityHashCode(t2);
095: }
096: }
097: };
098: SortedSet<Thread> threads = new TreeSet<Thread>(comp);
099: threads.addAll(processesWithDisplayNames.keySet());
100: for (Thread t : threads) {
101: model.addElement(t);
102: }
103: list.setModel(model);
104: list.setSelectedIndex(0);
105: // Make a dialog with buttons "Stop Building" and "Cancel".
106: DialogDescriptor dd = new DialogDescriptor(alert, NbBundle
107: .getMessage(StopBuildingAlert.class, "TITLE_SBA"));
108: dd.setMessageType(NotifyDescriptor.PLAIN_MESSAGE);
109: final JButton stopButton = new JButton(NbBundle.getMessage(
110: StopBuildingAlert.class, "LBL_SBA_stop"));
111: list.addListSelectionListener(new ListSelectionListener() {
112: public void valueChanged(ListSelectionEvent e) {
113: stopButton.setEnabled(list.getSelectedValue() != null);
114: }
115: });
116: dd.setOptions(new Object[] { stopButton,
117: DialogDescriptor.CANCEL_OPTION });
118: DialogDisplayer.getDefault().createDialog(dd).setVisible(true);
119: if (dd.getValue() == stopButton) {
120: Object[] _selectedThreads = list.getSelectedValues();
121: Thread[] selectedThreads = new Thread[_selectedThreads.length];
122: for (int i = 0; i < _selectedThreads.length; i++) {
123: selectedThreads[i] = (Thread) _selectedThreads[i];
124: }
125: return selectedThreads;
126: } else {
127: return new Thread[0];
128: }
129: }
130:
131: private final Map<Thread, String> processesWithDisplayNames;
132:
133: private StopBuildingAlert(
134: Map<Thread, String> processesWithDisplayNames) {
135: this .processesWithDisplayNames = processesWithDisplayNames;
136: initComponents();
137: buildsList.setCellRenderer(new ProcessCellRenderer());
138: }
139:
140: // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
141: private void initComponents() {
142: java.awt.GridBagConstraints gridBagConstraints;
143:
144: introLabel = new javax.swing.JLabel();
145: buildsLabel = new javax.swing.JLabel();
146: buildsScrollPane = new javax.swing.JScrollPane();
147: buildsList = new javax.swing.JList();
148:
149: org.openide.awt.Mnemonics.setLocalizedText(introLabel,
150: org.openide.util.NbBundle.getMessage(
151: StopBuildingAlert.class, "LBL_SBA_intro"));
152:
153: buildsLabel.setLabelFor(buildsList);
154: org.openide.awt.Mnemonics.setLocalizedText(buildsLabel,
155: org.openide.util.NbBundle.getMessage(
156: StopBuildingAlert.class, "LBL_SBA_select"));
157:
158: buildsScrollPane.setViewportView(buildsList);
159:
160: org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(
161: this );
162: this .setLayout(layout);
163: layout
164: .setHorizontalGroup(layout
165: .createParallelGroup(
166: org.jdesktop.layout.GroupLayout.LEADING)
167: .add(
168: org.jdesktop.layout.GroupLayout.LEADING,
169: layout
170: .createSequentialGroup()
171: .addContainerGap()
172: .add(
173: layout
174: .createParallelGroup(
175: org.jdesktop.layout.GroupLayout.LEADING,
176: false)
177: .add(
178: org.jdesktop.layout.GroupLayout.LEADING,
179: layout
180: .createSequentialGroup()
181: .add(
182: buildsScrollPane,
183: org.jdesktop.layout.GroupLayout.DEFAULT_SIZE,
184: 376,
185: Short.MAX_VALUE)
186: .addContainerGap())
187: .add(
188: org.jdesktop.layout.GroupLayout.LEADING,
189: layout
190: .createSequentialGroup()
191: .add(
192: layout
193: .createParallelGroup(
194: org.jdesktop.layout.GroupLayout.LEADING,
195: false)
196: .add(
197: buildsLabel)
198: .add(
199: introLabel,
200: org.jdesktop.layout.GroupLayout.DEFAULT_SIZE,
201: org.jdesktop.layout.GroupLayout.DEFAULT_SIZE,
202: Short.MAX_VALUE))
203: .add(
204: 28,
205: 28,
206: 28)))));
207: layout.setVerticalGroup(layout.createParallelGroup(
208: org.jdesktop.layout.GroupLayout.LEADING).add(
209: org.jdesktop.layout.GroupLayout.LEADING,
210: layout.createSequentialGroup().addContainerGap().add(
211: introLabel).addPreferredGap(
212: org.jdesktop.layout.LayoutStyle.RELATED).add(
213: buildsLabel).addPreferredGap(
214: org.jdesktop.layout.LayoutStyle.RELATED).add(
215: buildsScrollPane,
216: org.jdesktop.layout.GroupLayout.DEFAULT_SIZE,
217: 234, Short.MAX_VALUE).addContainerGap()));
218: }
219:
220: // </editor-fold>//GEN-END:initComponents
221:
222: // Variables declaration - do not modify//GEN-BEGIN:variables
223: public javax.swing.JLabel buildsLabel;
224: public javax.swing.JList buildsList;
225: public javax.swing.JScrollPane buildsScrollPane;
226: public javax.swing.JLabel introLabel;
227:
228: // End of variables declaration//GEN-END:variables
229:
230: private final class ProcessCellRenderer extends
231: DefaultListCellRenderer/*<Thread>*/{
232:
233: public ProcessCellRenderer() {
234: }
235:
236: @Override
237: public Component getListCellRendererComponent(JList list,
238: Object value, int index, boolean isSelected,
239: boolean cellHasFocus) {
240: Thread t = (Thread) value;
241: String displayName = processesWithDisplayNames.get(t);
242: return super.getListCellRendererComponent(list,
243: displayName, index, isSelected, cellHasFocus);
244: }
245:
246: }
247:
248: }
|