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.netbeans.beaninfo.editors;
043:
044: import java.awt.event.ActionEvent;
045: import java.awt.event.ActionListener;
046: import java.awt.event.KeyAdapter;
047: import java.awt.event.KeyEvent;
048: import java.util.ArrayList;
049: import java.util.Enumeration;
050: import java.util.List;
051: import java.util.ResourceBundle;
052: import java.util.StringTokenizer;
053:
054: import javax.swing.*;
055: import javax.swing.border.*;
056: import org.openide.loaders.ExtensionList;
057:
058: import org.openide.util.NbBundle;
059:
060: /** A custom editor for array of Strings.
061: *
062: * @author Ian Formanek
063: */
064: public class ExtensionListCustomEditor extends javax.swing.JPanel {
065:
066: private ExtensionList value;
067: private ExtensionListEditor editor;
068:
069: static final long serialVersionUID = -4347656479280614636L;
070:
071: @SuppressWarnings("unchecked")
072: private String[] getStrings() {
073: List<String> l = new ArrayList<String>();
074: if (value == null)
075: return new String[0];
076:
077: Enumeration<String> e = (Enumeration<String>) value
078: .extensions();
079: while (e.hasMoreElements())
080: l.add(e.nextElement());
081:
082: e = (Enumeration<String>) value.mimeTypes();
083: while (e.hasMoreElements())
084: l.add(e.nextElement());
085:
086: return l.toArray(new String[l.size()]);
087: }
088:
089: /** Initializes the Form */
090: public ExtensionListCustomEditor(ExtensionListEditor ed) {
091: editor = ed;
092: value = (ExtensionList) ((ExtensionList) editor.getValue())
093: .clone();
094: initComponents();
095: itemList.setCellRenderer(new EmptyStringListCellRenderer());
096: itemList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
097: itemList.setListData(getStrings());
098:
099: ResourceBundle bundle = NbBundle
100: .getBundle(ExtensionListCustomEditor.class);
101:
102: getAccessibleContext().setAccessibleDescription(
103: bundle.getString("ACSD_ELCE"));
104: itemField.getAccessibleContext().setAccessibleDescription(
105: bundle.getString("ACSD_ELCE_Item"));
106: itemList.getAccessibleContext().setAccessibleDescription(
107: bundle.getString("ACSD_ELCE_ItemList"));
108: addButton.getAccessibleContext().setAccessibleDescription(
109: bundle.getString("ACSD_ELCE_Add"));
110: changeButton.getAccessibleContext().setAccessibleDescription(
111: bundle.getString("ACSD_ELCE_Change"));
112: removeButton.getAccessibleContext().setAccessibleDescription(
113: bundle.getString("ACSD_ELCE_Remove"));
114:
115: if (!editor.isEditable()) {
116: // set read-only
117: itemField.setEnabled(false);
118: addButton.setEnabled(false);
119: changeButton.setEnabled(false);
120: removeButton.setEnabled(false);
121: }
122: updateButtons();
123: itemField.addKeyListener(new KeyAdapter() {
124: public void keyReleased(KeyEvent event) {
125: boolean containsCurrent = containsCurrent();
126: String txt = itemField.getText().trim();
127: boolean en = itemField.isEnabled() && txt.length() > 0
128: && !containsCurrent;
129: addButton.setEnabled(en);
130: changeButton.setEnabled(en
131: && itemList.getSelectedIndex() != -1);
132: if (containsCurrent) {
133: itemList.setSelectedIndex(idxOfCurrent());
134: }
135: }
136: });
137: itemField.addActionListener(new ActionListener() {
138: public void actionPerformed(ActionEvent ae) {
139: if (addButton.isEnabled()) {
140: doAdd();
141: }
142: }
143: });
144: addButton.setEnabled(false);
145: changeButton.setEnabled(false);
146: }
147:
148: /** Determine if the text of the text field matches an item in the
149: * list */
150: private boolean containsCurrent() {
151: return idxOfCurrent() != -1;
152: }
153:
154: private int idxOfCurrent() {
155: String txt = itemField.getText().trim();
156: if (txt.length() > 0) {
157: int max = itemList.getModel().getSize();
158: for (int i = 0; i < max; i++) {
159: if (txt.equals(itemList.getModel().getElementAt(i)))
160: return i;
161: }
162: }
163: return -1;
164: }
165:
166: /** This method is called from within the constructor to
167: * initialize the form.
168: * WARNING: Do NOT modify this code. The content of this method is
169: * always regenerated by the FormEditor.
170: */
171: private void initComponents() {//GEN-BEGIN:initComponents
172: java.awt.GridBagConstraints gridBagConstraints;
173:
174: addButton = new javax.swing.JButton();
175: changeButton = new javax.swing.JButton();
176: removeButton = new javax.swing.JButton();
177: itemListScroll = new javax.swing.JScrollPane();
178: itemList = new javax.swing.JList();
179: itemLabel = new javax.swing.JLabel();
180: itemField = new javax.swing.JTextField();
181: itemListLabel = new javax.swing.JLabel();
182:
183: setLayout(new java.awt.GridBagLayout());
184:
185: org.openide.awt.Mnemonics.setLocalizedText(addButton,
186: org.openide.util.NbBundle.getMessage(
187: ExtensionListCustomEditor.class,
188: "CTL_ELCE_Add", new Object[] {}));
189: addButton
190: .addActionListener(new java.awt.event.ActionListener() {
191: public void actionPerformed(
192: java.awt.event.ActionEvent evt) {
193: addButtonActionPerformed(evt);
194: }
195: });
196:
197: gridBagConstraints = new java.awt.GridBagConstraints();
198: gridBagConstraints.gridx = 3;
199: gridBagConstraints.gridy = 0;
200: gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
201: gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
202: gridBagConstraints.insets = new java.awt.Insets(4, 8, 0, 8);
203: add(addButton, gridBagConstraints);
204:
205: org.openide.awt.Mnemonics.setLocalizedText(changeButton,
206: org.openide.util.NbBundle.getMessage(
207: ExtensionListCustomEditor.class,
208: "CTL_ELCE_Change", new Object[] {}));
209: changeButton
210: .addActionListener(new java.awt.event.ActionListener() {
211: public void actionPerformed(
212: java.awt.event.ActionEvent evt) {
213: changeButtonActionPerformed(evt);
214: }
215: });
216:
217: gridBagConstraints = new java.awt.GridBagConstraints();
218: gridBagConstraints.gridx = 3;
219: gridBagConstraints.gridy = 1;
220: gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
221: gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH;
222: gridBagConstraints.insets = new java.awt.Insets(8, 8, 0, 8);
223: add(changeButton, gridBagConstraints);
224:
225: org.openide.awt.Mnemonics.setLocalizedText(removeButton,
226: org.openide.util.NbBundle.getMessage(
227: ExtensionListCustomEditor.class,
228: "CTL_ELCE_Remove", new Object[] {}));
229: removeButton
230: .addActionListener(new java.awt.event.ActionListener() {
231: public void actionPerformed(
232: java.awt.event.ActionEvent evt) {
233: removeButtonActionPerformed(evt);
234: }
235: });
236:
237: gridBagConstraints = new java.awt.GridBagConstraints();
238: gridBagConstraints.gridx = 3;
239: gridBagConstraints.gridy = 2;
240: gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH;
241: gridBagConstraints.insets = new java.awt.Insets(8, 8, 8, 8);
242: add(removeButton, gridBagConstraints);
243:
244: itemList
245: .addListSelectionListener(new javax.swing.event.ListSelectionListener() {
246: public void valueChanged(
247: javax.swing.event.ListSelectionEvent evt) {
248: itemListValueChanged(evt);
249: }
250: });
251:
252: itemListScroll.setViewportView(itemList);
253:
254: gridBagConstraints = new java.awt.GridBagConstraints();
255: gridBagConstraints.gridx = 0;
256: gridBagConstraints.gridy = 2;
257: gridBagConstraints.gridwidth = 2;
258: gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
259: gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTHWEST;
260: gridBagConstraints.insets = new java.awt.Insets(0, 8, 0, 0);
261: add(itemListScroll, gridBagConstraints);
262:
263: itemLabel.setLabelFor(itemField);
264: org.openide.awt.Mnemonics.setLocalizedText(itemLabel,
265: org.openide.util.NbBundle.getMessage(
266: ExtensionListCustomEditor.class,
267: "CTL_ELCE_Item", new Object[] {}));
268: gridBagConstraints = new java.awt.GridBagConstraints();
269: gridBagConstraints.gridx = 0;
270: gridBagConstraints.gridy = 0;
271: gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
272: gridBagConstraints.insets = new java.awt.Insets(4, 8, 0, 8);
273: add(itemLabel, gridBagConstraints);
274:
275: itemField.setColumns(10);
276: gridBagConstraints = new java.awt.GridBagConstraints();
277: gridBagConstraints.gridx = 1;
278: gridBagConstraints.gridy = 0;
279: gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
280: gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
281: gridBagConstraints.weightx = 1.0;
282: gridBagConstraints.insets = new java.awt.Insets(4, 0, 0, 0);
283: add(itemField, gridBagConstraints);
284:
285: itemListLabel.setLabelFor(itemList);
286: org.openide.awt.Mnemonics.setLocalizedText(itemListLabel,
287: org.openide.util.NbBundle.getMessage(
288: ExtensionListCustomEditor.class,
289: "CTL_ItemList", new Object[] {}));
290: gridBagConstraints = new java.awt.GridBagConstraints();
291: gridBagConstraints.gridx = 0;
292: gridBagConstraints.gridy = 1;
293: gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTHWEST;
294: gridBagConstraints.insets = new java.awt.Insets(0, 8, 0, 0);
295: add(itemListLabel, gridBagConstraints);
296:
297: }//GEN-END:initComponents
298:
299: private String addTexts() {
300: StringTokenizer st = new StringTokenizer(itemField.getText(),
301: ",. \n\t"); // NOI18N
302: String last = null;
303: while (st.hasMoreTokens()) {
304: last = st.nextToken();
305: if (last.indexOf('/') >= 0) { // mime type!?
306: value.addMimeType(last);
307: } else {
308: value.addExtension(last);
309: }
310: }
311: return last;
312: }
313:
314: private void changeButtonActionPerformed(
315: java.awt.event.ActionEvent evt) {//GEN-FIRST:event_changeButtonActionPerformed
316: int sel = itemList.getSelectedIndex();
317: String s = (String) itemList.getModel().getElementAt(sel);
318: if (s.indexOf('/') >= 0) { // mime type!?
319: value.removeMimeType(s);
320: } else {
321: value.removeExtension(s);
322: }
323: doAdd();
324: }//GEN-LAST:event_changeButtonActionPerformed
325:
326: private int indexOf(String[] array, String item) {
327: for (int i = 0; i < array.length; i++) {
328: if (array[i].equals(item))
329: return i;
330: }
331: return -1;
332: }
333:
334: private void removeButtonActionPerformed(
335: java.awt.event.ActionEvent evt) {//GEN-FIRST:event_removeButtonActionPerformed
336: int sel = itemList.getSelectedIndex();
337: String s = (String) itemList.getModel().getElementAt(sel);
338: if (s.indexOf('/') >= 0) { // mime type!?
339: value.removeMimeType(s);
340: } else {
341: value.removeExtension(s);
342: }
343: itemList.setListData(getStrings());
344:
345: int count = itemList.getModel().getSize();
346: // set new selection
347: if (count != 0) {
348: if (sel >= count)
349: sel = count - 1;
350: itemList.setSelectedIndex(sel);
351: }
352:
353: itemList.repaint();
354: updateValue();
355: }//GEN-LAST:event_removeButtonActionPerformed
356:
357: private void itemListValueChanged(
358: javax.swing.event.ListSelectionEvent evt) {//GEN-FIRST:event_itemListValueChanged
359: // Add your handling code here:
360: updateButtons();
361: int sel = itemList.getSelectedIndex();
362: if (sel != -1) {
363: itemField.setText((String) itemList.getModel()
364: .getElementAt(sel));
365: changeButton.setEnabled(false);
366: addButton.setEnabled(false);
367: }
368: }//GEN-LAST:event_itemListValueChanged
369:
370: private void doAdd() {
371: String last = addTexts();
372: String[] values = getStrings();
373: int index = indexOf(values, last);
374: itemList.setListData(values);
375: if (index >= 0)
376: itemList.setSelectedIndex(index);
377: itemList.repaint();
378: updateValue();
379: }
380:
381: private void addButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addButtonActionPerformed
382: doAdd();
383: }//GEN-LAST:event_addButtonActionPerformed
384:
385: private void updateButtons() {
386: int sel = itemList.getSelectedIndex();
387: if (sel == -1 || !editor.isEditable()) {
388: removeButton.setEnabled(false);
389: changeButton.setEnabled(false);
390: } else {
391: removeButton.setEnabled(true);
392: changeButton.setEnabled(true);
393: }
394: // #62803: String[] editor keeps text in the textfield after removing all items
395: boolean containsCurrent = containsCurrent();
396: String txt = itemField.getText().trim();
397: boolean en = itemField.isEnabled() && txt.length() > 0
398: && !containsCurrent;
399: addButton.setEnabled(en);
400: }
401:
402: private void updateValue() {
403: editor.setValue(value);
404: }
405:
406: // Variables declaration - do not modify//GEN-BEGIN:variables
407: private javax.swing.JButton addButton;
408: private javax.swing.JButton changeButton;
409: private javax.swing.JTextField itemField;
410: private javax.swing.JLabel itemLabel;
411: private javax.swing.JList itemList;
412: private javax.swing.JLabel itemListLabel;
413: private javax.swing.JScrollPane itemListScroll;
414: private javax.swing.JButton removeButton;
415:
416: // End of variables declaration//GEN-END:variables
417:
418: static class EmptyStringListCellRenderer extends JLabel implements
419: ListCellRenderer {
420:
421: protected static Border hasFocusBorder;
422: protected static Border noFocusBorder;
423:
424: static {
425: hasFocusBorder = new LineBorder(UIManager
426: .getColor("List.focusCellHighlight")); // NOI18N
427: noFocusBorder = new EmptyBorder(1, 1, 1, 1);
428: }
429:
430: static final long serialVersionUID = 487512296465844339L;
431:
432: /** Creates a new NodeListCellRenderer */
433: public EmptyStringListCellRenderer() {
434: setOpaque(true);
435: setBorder(noFocusBorder);
436: }
437:
438: /** This is the only method defined by ListCellRenderer. We just
439: * reconfigure the Jlabel each time we're called.
440: */
441: public java.awt.Component getListCellRendererComponent(
442: JList list, Object value, // value to display
443: int index, // cell index
444: boolean isSelected, // is the cell selected
445: boolean cellHasFocus) // the list and the cell have the focus
446: {
447: if (!(value instanceof String))
448: return this ;
449: String text = (String) value;
450: if ("".equals(text))
451: text = NbBundle.getMessage(
452: ExtensionListCustomEditor.class,
453: "CTL_ELCE_Empty");
454:
455: setText(text);
456: if (isSelected) {
457: setBackground(UIManager
458: .getColor("List.selectionBackground")); // NOI18N
459: setForeground(UIManager
460: .getColor("List.selectionForeground")); // NOI18N
461: } else {
462: setBackground(list.getBackground());
463: setForeground(list.getForeground());
464: }
465:
466: setBorder(cellHasFocus ? hasFocusBorder : noFocusBorder);
467:
468: return this;
469: }
470: }
471: }
|