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-2007 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: package com.sun.jsfcl.std.property;
042:
043: import java.awt.Dimension;
044: import java.awt.GridBagConstraints;
045: import java.awt.event.ActionEvent;
046: import java.beans.VetoableChangeListener;
047: import java.util.Iterator;
048: import java.util.regex.Pattern;
049: import java.util.regex.PatternSyntaxException;
050: import javax.swing.Box;
051: import javax.swing.BoxLayout;
052: import javax.swing.DefaultListModel;
053: import javax.swing.JButton;
054: import javax.swing.JLabel;
055: import javax.swing.JList;
056: import javax.swing.JPanel;
057: import javax.swing.JScrollPane;
058: import javax.swing.JTextField;
059: import javax.swing.ListSelectionModel;
060: import javax.swing.event.DocumentEvent;
061: import javax.swing.event.ListSelectionEvent;
062: import com.sun.jsfcl.std.reference.CompositeReferenceData;
063: import com.sun.jsfcl.std.reference.ReferenceDataItem;
064: import com.sun.rave.designtime.DesignProperty;
065: import java.beans.PropertyChangeEvent;
066: import java.beans.PropertyVetoException;
067: import org.openide.explorer.propertysheet.PropertyEnv;
068:
069: /**
070: * @author eric
071: *
072: * TODO To change the template for this generated type comment go to
073: * Window - Preferences - Java - Code Generation - Code and Comments
074: */
075: public class ChooseOneReferenceDataPanel extends AbstractPropertyJPanel {
076:
077: protected static final String ADD_ACTION = "add"; //NOI18N
078: protected static final String REMOVE_ACTION = "remove"; //NOI18N
079: protected static final String CLEAR_FILTER_ACTION = "clearFilter"; //NOI18N
080: protected static final int MIN_ITEMS_FOR_FILTER = 15;
081:
082: protected JButton addJButton;
083: protected JList choicesJList;
084: protected DefaultListModel choicesJListModel;
085: protected JScrollPane choicesJListScrollPane;
086: protected JButton clearFilterButton;
087: protected Pattern filterPattern;
088: protected JTextField filterTextControl;
089: protected JButton removeJButton;
090: protected ReferenceDataItem selectedChoice;
091:
092: private PanelSubmissionListener panelSubmissionListener;
093:
094: public ChooseOneReferenceDataPanel(
095: ChooseOneReferenceDataPropertyEditor propertyEditor,
096: DesignProperty liveProperty) {
097: super (propertyEditor, liveProperty);
098: PropertyEnv propertyEnv = propertyEditor.getEnv();
099: if (propertyEnv != null) {
100: propertyEnv.setState(PropertyEnv.STATE_NEEDS_VALIDATION);
101: panelSubmissionListener = new PanelSubmissionListener(
102: propertyEditor);
103: propertyEnv
104: .addVetoableChangeListener(panelSubmissionListener);
105: this .propertyEditor = propertyEditor;
106: }
107: }
108:
109: public void actionPerformed(ActionEvent event) {
110: super .actionPerformed(event);
111: if (ADD_ACTION.equals(event.getActionCommand())) {
112: handleAddAction(event);
113: return;
114: }
115: if (REMOVE_ACTION.equals(event.getActionCommand())) {
116: handleRemoveAction(event);
117: return;
118: }
119: if (CLEAR_FILTER_ACTION.equals(event.getActionCommand())) {
120: handleClearFilterAction(event);
121: return;
122: }
123: }
124:
125: protected java.util.List getChoices() {
126: return getChooseFromReferenceDataPropertyEditor().getItems();
127: }
128:
129: protected ChooseOneReferenceDataPropertyEditor getChooseFromReferenceDataPropertyEditor() {
130: return (ChooseOneReferenceDataPropertyEditor) getPropertyEditor();
131: }
132:
133: protected CompositeReferenceData getCompositeReferenceData() {
134: return getChooseFromReferenceDataPropertyEditor()
135: .getCompositeReferenceData();
136: }
137:
138: protected int getListSelectionStyle() {
139: return ListSelectionModel.SINGLE_SELECTION;
140: }
141:
142: public Object getPropertyValue() {
143: if (selectedChoice == null) {
144: return null;
145: } else {
146: return selectedChoice.getValue();
147: }
148: }
149:
150: protected ReferenceDataItem getSelectedChoice() {
151: return selectedChoice;
152: }
153:
154: protected String getTopLabel() {
155: return getCompositeReferenceData().getChooseOneTitle();
156: }
157:
158: protected int getValueLabelGridWidth() {
159: return 2;
160: }
161:
162: protected void grabCurrentValueFromPropertyEditor() {
163: selectedChoice = getChooseFromReferenceDataPropertyEditor()
164: .getValueReferenceDataItem();
165: }
166:
167: protected void handleAddAction(ActionEvent event) {
168: ReferenceDataItem item = (new NewReferenceDataItemDialog(
169: getCompositeReferenceData())).showDialog(this );
170: if (item == null) {
171: return;
172: }
173: populateChoicesJListModel();
174: choicesJList.setSelectedValue(item, true);
175: }
176:
177: protected void handleChoicesJListSelectionChanged(
178: ListSelectionEvent event) {
179: if (event.getValueIsAdjusting()) {
180: return;
181: }
182: if (choicesJList.getSelectedIndices().length == 0) {
183: selectedChoice = null;
184: } else {
185: selectedChoice = (ReferenceDataItem) choicesJList
186: .getSelectedValue();
187: }
188: updateButtonsState();
189: }
190:
191: public void handleClearFilterAction(ActionEvent action) {
192: filterTextControl.setText("");
193: }
194:
195: public void handleFilterChanged() {
196: String string = filterTextControl.getText().trim();
197: clearFilterButton.setEnabled(string.length() > 0);
198: if (string.length() == 0) {
199: filterPattern = null;
200: } else {
201: try {
202: filterPattern = Pattern
203: .compile(".*" + string + ".*",
204: Pattern.CASE_INSENSITIVE
205: | Pattern.UNICODE_CASE);
206: } catch (PatternSyntaxException e) {
207: filterPattern = null;
208: }
209: }
210: populateChoicesJListModel();
211: }
212:
213: protected void handleRemoveAction(ActionEvent event) {
214: int index = choicesJList.getMinSelectionIndex();
215: getCompositeReferenceData().remove(getSelectedChoice());
216: populateChoicesJListModel();
217: if (choicesJListModel.size() > 0) {
218: if (index >= choicesJListModel.size()) {
219: index = choicesJListModel.size() - 1;
220: }
221: choicesJList.setSelectedIndex(index);
222: choicesJList.ensureIndexIsVisible(index);
223: }
224: }
225:
226: protected boolean includeInChoicesJList(ReferenceDataItem item) {
227: return filterPattern == null
228: || item.matchesPattern(filterPattern);
229: }
230:
231: protected void initializeComponents() {
232: GridBagConstraints gridBagConstraints;
233:
234: setLayout(new java.awt.GridBagLayout());
235:
236: // add top label
237: JLabel label = new javax.swing.JLabel();
238: label.setText(getTopLabel());
239: gridBagConstraints = new java.awt.GridBagConstraints();
240: gridBagConstraints.gridx = 0;
241: gridBagConstraints.gridy = 0;
242: gridBagConstraints.gridwidth = getValueLabelGridWidth();
243: gridBagConstraints.fill = GridBagConstraints.HORIZONTAL;
244: gridBagConstraints.anchor = GridBagConstraints.PAGE_START;
245: gridBagConstraints.weightx = 1.0;
246: gridBagConstraints.insets = new java.awt.Insets(10, 10, 0, 10);
247: add(label, gridBagConstraints);
248:
249: if (getChoices().size() > MIN_ITEMS_FOR_FILTER) {
250: JPanel filterPanel = new JPanel();
251: filterPanel.setLayout(new BoxLayout(filterPanel,
252: BoxLayout.LINE_AXIS));
253:
254: label = new javax.swing.JLabel();
255: label.setText(BundleHolder.bundle.getMessage("Filter")); //NOI18N
256: filterPanel.add(label);
257: filterPanel.add(Box.createRigidArea(new Dimension(5, 0)));
258:
259: // add filter entry field
260: filterTextControl = new javax.swing.JTextField();
261: filterTextControl.setColumns(10);
262: filterTextControl.getDocument().addDocumentListener(this );
263: filterPanel.add(filterTextControl);
264: filterPanel.add(Box.createRigidArea(new Dimension(5, 0)));
265:
266: clearFilterButton = new JButton(BundleHolder.bundle
267: .getMessage("CLEAR_BUTTON_TXT"));
268: clearFilterButton.setEnabled(false);
269: clearFilterButton.setActionCommand(CLEAR_FILTER_ACTION);
270: clearFilterButton.addActionListener(this );
271: filterPanel.add(clearFilterButton);
272:
273: gridBagConstraints = new java.awt.GridBagConstraints();
274: gridBagConstraints.gridx = 0;
275: gridBagConstraints.gridy = 2;
276: gridBagConstraints.gridwidth = 2;
277: gridBagConstraints.fill = GridBagConstraints.HORIZONTAL;
278: gridBagConstraints.anchor = GridBagConstraints.CENTER;
279: gridBagConstraints.insets = new java.awt.Insets(10, 10, 0,
280: 10);
281: add(filterPanel, gridBagConstraints);
282: }
283:
284: // add the choices list control
285: choicesJListModel = new DefaultListModel();
286: choicesJList = new JList(choicesJListModel);
287: choicesJList.setSelectionMode(getListSelectionStyle());
288: choicesJList.setLayoutOrientation(JList.VERTICAL);
289: choicesJList.setVisibleRowCount(-1);
290: choicesJList.addListSelectionListener(this );
291: choicesJList
292: .setCellRenderer(new ReferenceDataTwoColumnListCellRenderer());
293: populateChoicesJListModel();
294: updateChoicesJListSelection();
295: // wrap the list control in scrolling pane
296: choicesJListScrollPane = new JScrollPane(choicesJList);
297: choicesJListScrollPane
298: .setPreferredSize(new Dimension(200, 200));
299:
300: gridBagConstraints = new java.awt.GridBagConstraints();
301: gridBagConstraints.gridx = 0;
302: gridBagConstraints.gridy = 3;
303: gridBagConstraints.gridwidth = 2;
304: gridBagConstraints.fill = GridBagConstraints.BOTH;
305: gridBagConstraints.weightx = 0.5;
306: gridBagConstraints.weighty = 1.0;
307: gridBagConstraints.insets = new java.awt.Insets(10, 10, 0, 10);
308: add(choicesJListScrollPane, gridBagConstraints);
309:
310: if (getCompositeReferenceData().canAddRemoveItems()) {
311: JPanel buttonPanel = new JPanel();
312: buttonPanel.setLayout(new BoxLayout(buttonPanel,
313: BoxLayout.X_AXIS));
314:
315: // Add add/remove buttons
316: addJButton = new JButton(BundleHolder.bundle
317: .getMessage("New")); //NOI18N
318: addJButton.setActionCommand(ADD_ACTION);
319: addJButton.addActionListener(this );
320: buttonPanel.add(addJButton);
321: buttonPanel.add(Box.createRigidArea(new Dimension(5, 0)));
322:
323: removeJButton = new JButton(BundleHolder.bundle
324: .getMessage("remove")); //NOI18N
325: removeJButton.setActionCommand(REMOVE_ACTION);
326: removeJButton.addActionListener(this );
327: buttonPanel.add(removeJButton);
328:
329: gridBagConstraints = new java.awt.GridBagConstraints();
330: gridBagConstraints.gridx = 0;
331: gridBagConstraints.gridy = 4;
332: gridBagConstraints.gridwidth = 3;
333: gridBagConstraints.anchor = GridBagConstraints.FIRST_LINE_START;
334: gridBagConstraints.insets = new java.awt.Insets(5, 10, 0, 0);
335: add(buttonPanel, gridBagConstraints);
336: }
337: }
338:
339: public void documentEvent(DocumentEvent event) {
340: if (event.getDocument() == filterTextControl.getDocument()) {
341: handleFilterChanged();
342: }
343: }
344:
345: public void doLayout() {
346: super .doLayout();
347: choicesJList.ensureIndexIsVisible(choicesJList
348: .getSelectedIndex());
349: updateButtonsState();
350: }
351:
352: protected void populateChoicesJListModel() {
353: choicesJListModel.clear();
354: ReferenceDataTwoColumnListCellRenderer renderer = (ReferenceDataTwoColumnListCellRenderer) choicesJList
355: .getCellRenderer();
356: renderer.resetLeftColumnWidth();
357: for (Iterator iterator = getChoices().iterator(); iterator
358: .hasNext();) {
359: ReferenceDataItem item;
360:
361: item = (ReferenceDataItem) iterator.next();
362: if (includeInChoicesJList(item)) {
363: choicesJListModel.addElement(item);
364: renderer.getListCellRendererComponent(choicesJList,
365: item, -1, false, false);
366: renderer.adjustLeftColumnWidthIfNecessary();
367: }
368: }
369: }
370:
371: protected void updateButtonsState() {
372: if (removeJButton != null) {
373: ReferenceDataItem item;
374:
375: item = getSelectedChoice();
376: removeJButton
377: .setEnabled(item != null && item.isRemovable());
378: }
379: }
380:
381: protected void updateChoicesJListSelection() {
382: choicesJList.setSelectedValue(getSelectedChoice(), true);
383: }
384:
385: public void valueChanged(ListSelectionEvent event) {
386: super .valueChanged(event);
387: if (event.getSource() == choicesJList) {
388: handleChoicesJListSelectionChanged(event);
389: }
390: }
391:
392: protected void finalize() throws Throwable {
393: if (panelSubmissionListener != null)
394: ((ChooseOneReferenceDataPropertyEditor) this .propertyEditor)
395: .getEnv().removeVetoableChangeListener(
396: panelSubmissionListener);
397: super .finalize();
398: }
399:
400: class PanelSubmissionListener implements VetoableChangeListener {
401:
402: ChooseOneReferenceDataPropertyEditor propertyEditor;
403:
404: PanelSubmissionListener(
405: ChooseOneReferenceDataPropertyEditor propertyEditor) {
406: this .propertyEditor = propertyEditor;
407: }
408:
409: public final void vetoableChange(PropertyChangeEvent event)
410: throws PropertyVetoException {
411: if (PropertyEnv.PROP_STATE.equals(event.getPropertyName())) {
412: propertyEditor.setValue(getPropertyValue());
413: propertyEditor.getEnv().setState(
414: PropertyEnv.STATE_VALID);
415: }
416: }
417: }
418:
419: }
|