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.Component;
044: import java.awt.Dimension;
045: import java.awt.GridBagConstraints;
046: import java.awt.event.ActionEvent;
047: import java.util.ArrayList;
048: import java.util.Enumeration;
049: import java.util.IdentityHashMap;
050: import java.util.Iterator;
051: import java.util.List;
052: import javax.swing.Box;
053: import javax.swing.BoxLayout;
054: import javax.swing.JButton;
055: import javax.swing.JPanel;
056: import javax.swing.JTree;
057: import javax.swing.event.ListSelectionEvent;
058: import javax.swing.event.TreeSelectionEvent;
059: import javax.swing.event.TreeSelectionListener;
060: import javax.swing.tree.DefaultMutableTreeNode;
061: import javax.swing.tree.DefaultTreeModel;
062: import javax.swing.tree.TreePath;
063: import javax.swing.tree.TreeSelectionModel;
064: import com.sun.jsfcl.std.reference.ReferenceDataItem;
065: import com.sun.rave.designtime.DesignProperty;
066:
067: /**
068: * @author eric
069: *
070: * TODO To change the template for this generated type comment go to
071: * Window - Preferences - Java - Code Generation - Code and Comments
072: */
073: public class ChooseManyOfManyReferenceDataPanel extends
074: ChooseManyReferenceDataPanel implements TreeSelectionListener {
075: protected static final String ADD_LIST_ACTION = "add list";
076: protected static final String DELETE_LIST_ACTION = "delete list";
077:
078: protected JButton deleteListJButton;
079: protected JTree selectedJTree;
080: protected DefaultTreeModel selectedJTreeModel;
081: protected DefaultMutableTreeNode selectedRootNode;
082:
083: public ChooseManyOfManyReferenceDataPanel(
084: ChooseManyOfManyReferenceDataPropertyEditor propertyEditor,
085: DesignProperty liveProperty) {
086:
087: super (propertyEditor, liveProperty);
088: }
089:
090: public void actionPerformed(ActionEvent event) {
091:
092: super .actionPerformed(event);
093: if (ADD_LIST_ACTION.equals(event.getActionCommand())) {
094: handleAddListAction(event);
095: return;
096: }
097: if (DELETE_LIST_ACTION.equals(event.getActionCommand())) {
098: handleDeleteListAction(event);
099: return;
100: }
101: }
102:
103: protected ChooseManyOfManyReferenceDataPropertyEditor getChooseManyOfManyReferenceDataPropertyEditor() {
104:
105: return (ChooseManyOfManyReferenceDataPropertyEditor) getPropertyEditor();
106: }
107:
108: protected void adjustLeftColumnWidthIfNecessary(
109: DefaultMutableTreeNode node) {
110:
111: ChooseManyOfManyNodeDataTwoColumnTreeCellRenderer renderer = (ChooseManyOfManyNodeDataTwoColumnTreeCellRenderer) selectedJTree
112: .getCellRenderer();
113: renderer.getTreeCellRendererComponent(selectedJTree, node,
114: false, false, false, -1, false);
115: renderer.adjustLeftColumnWidthIfNecessary();
116: }
117:
118: protected ChooseManyOfManyNodeData getSelectedData() {
119: DefaultMutableTreeNode node;
120: ChooseManyOfManyNodeData data;
121:
122: node = getSelectedNode();
123: if (node == null) {
124: return null;
125: }
126: data = (ChooseManyOfManyNodeData) node.getUserObject();
127: return data;
128: }
129:
130: protected DefaultMutableTreeNode getSelectedNode() {
131: TreePath paths[], path;
132: Object pathObjects[];
133: DefaultMutableTreeNode node;
134:
135: paths = selectedJTree.getSelectionModel().getSelectionPaths();
136: if (paths == null || paths.length == 0) {
137: return null;
138: }
139: path = paths[0];
140: return (DefaultMutableTreeNode) path.getLastPathComponent();
141: }
142:
143: public List getSelectedListOfListOfItems() {
144:
145: Enumeration rootChildrenEnum = selectedRootNode.children();
146: ArrayList manyOfManyList = new ArrayList();
147: while (rootChildrenEnum.hasMoreElements()) {
148: ArrayList manyList = new ArrayList(16);
149: DefaultMutableTreeNode node = (DefaultMutableTreeNode) rootChildrenEnum
150: .nextElement();
151: Enumeration nodeChildrenEnum = node.children();
152: while (nodeChildrenEnum.hasMoreElements()) {
153: DefaultMutableTreeNode nodeChild = (DefaultMutableTreeNode) nodeChildrenEnum
154: .nextElement();
155: ChooseManyOfManyNodeData nodeChildData = (ChooseManyOfManyNodeData) nodeChild
156: .getUserObject();
157: manyList.add(nodeChildData.getData());
158: }
159: manyOfManyList.add(manyList);
160: }
161: // remove the trailing empty groups
162: for (int i = manyOfManyList.size() - 1; i >= 0; i--) {
163: List list = (List) manyOfManyList.get(i);
164: if (list.size() == 0) {
165: manyOfManyList.remove(i);
166: } else {
167: break;
168: }
169: }
170: return manyOfManyList;
171: }
172:
173: protected String getListNodeNamePrefix() {
174:
175: return BundleHolder.bundle.getMessage("GroupPrefix") + " ";
176: }
177:
178: public Object getPropertyValue() {
179:
180: List selectedListOfListOfItems = getSelectedListOfListOfItems();
181: if (selectedListOfListOfItems == null
182: || selectedListOfListOfItems.size() == 0) {
183: return null;
184: } else {
185: String string = getChooseManyOfManyReferenceDataPropertyEditor()
186: .getStringForManyOfManyItems(
187: selectedListOfListOfItems);
188: return string;
189: }
190: }
191:
192: protected List getSelected_ItemsList() {
193: ChooseManyOfManyNodeData data;
194:
195: data = getSelectedData();
196: if (data == null) {
197: return null;
198: }
199: return (List) data.getData();
200: }
201:
202: protected String getTopLabel() {
203:
204: return getCompositeReferenceData().getChooseManyOfManyTitle();
205: }
206:
207: protected void handleAddListAction(ActionEvent event) {
208: ArrayList list;
209: DefaultMutableTreeNode node;
210: ChooseManyOfManyNodeData data;
211: TreePath path;
212:
213: list = new ArrayList();
214: data = new ChooseManyOfManyNodeData(null, list);
215: node = new DefaultMutableTreeNode(data, true);
216: selectedJTreeModel.insertNodeInto(node, selectedRootNode,
217: selectedRootNode.getChildCount());
218: path = new TreePath(node.getPath());
219: selectedJTree.scrollPathToVisible(path);
220: selectedJTree.setSelectionPath(path);
221: }
222:
223: protected void handleDeselectAllAction(ActionEvent event) {
224:
225: Enumeration parentEnum = selectedRootNode.children();
226: while (parentEnum.hasMoreElements()) {
227: DefaultMutableTreeNode parent = (DefaultMutableTreeNode) parentEnum
228: .nextElement();
229: parent.removeAllChildren();
230: }
231: selectedJTreeModel.reload();
232: updateTreeRelatedButtons();
233: }
234:
235: protected void handleChoicesJListSelectionChanged(
236: ListSelectionEvent event) {
237:
238: super .handleChoicesJListSelectionChanged(event);
239: if (event.getValueIsAdjusting()) {
240: return;
241: }
242: updateTreeRelatedButtons();
243: }
244:
245: protected void handleDeleteListAction(ActionEvent event) {
246:
247: TreePath paths[] = selectedJTree.getSelectionPaths();
248: if (paths == null) {
249: return;
250: }
251: DefaultMutableTreeNode sibling = null;
252: for (int i = 0; i < paths.length; i++) {
253: TreePath path = paths[i];
254: DefaultMutableTreeNode node = (DefaultMutableTreeNode) path
255: .getLastPathComponent();
256: sibling = node.getNextSibling();
257: if (sibling == null) {
258: sibling = node.getPreviousSibling();
259: }
260: removePath(path);
261: }
262: if (sibling != null) {
263: selectedJTree.setSelectionPath(new TreePath(sibling
264: .getPath()));
265: }
266: }
267:
268: protected void handleDeselectAction(ActionEvent event) {
269: TreePath paths[], path;
270:
271: paths = selectedJTree.getSelectionPaths();
272: for (int i = 0; i < paths.length; i++) {
273: path = paths[i];
274: removePath(path);
275: }
276: selectedJTree.setSelectionPaths(null);
277: }
278:
279: protected void handleDownAction(ActionEvent event) {
280:
281: TreePath[] paths = selectedJTree.getSelectionPaths();
282: sortTreePaths(paths);
283: for (int i = paths.length - 1; i >= 0; i--) {
284: TreePath path = paths[i];
285: DefaultMutableTreeNode node = (DefaultMutableTreeNode) path
286: .getLastPathComponent();
287: DefaultMutableTreeNode parent = (DefaultMutableTreeNode) node
288: .getParent();
289: int index = parent.getIndex(node);
290: if ((index + 1) == parent.getChildCount()) {
291: continue;
292: }
293: DefaultMutableTreeNode removed = (DefaultMutableTreeNode) parent
294: .getChildAt(index);
295: boolean wasExpanded = selectedJTree.isExpanded(path);
296: selectedJTreeModel.removeNodeFromParent(removed);
297: selectedJTreeModel.insertNodeInto(removed, parent,
298: index + 1);
299: if (wasExpanded && removed.getChildCount() > 0) {
300: DefaultMutableTreeNode firstChild = (DefaultMutableTreeNode) removed
301: .getFirstChild();
302: selectedJTree.makeVisible(new TreePath(firstChild
303: .getPath()));
304: }
305:
306: }
307: selectedJTree.setSelectionPaths(paths);
308: }
309:
310: protected void handleSelectAction(ActionEvent event) {
311: Object items[];
312: ReferenceDataItem item;
313:
314: TreePath[] selectionPaths = selectedJTree.getSelectionPaths();
315: for (int j = 0; j < selectionPaths.length; j++) {
316: TreePath selectionPath = selectionPaths[j];
317: DefaultMutableTreeNode node = (DefaultMutableTreeNode) selectionPath
318: .getLastPathComponent();
319: int insertIndex = -1;
320: if (node.getParent() != selectedRootNode) {
321: insertIndex = node.getParent().getIndex(node);
322: insertIndex++;
323: node = (DefaultMutableTreeNode) node.getParent();
324: }
325: items = choicesJList.getSelectedValues();
326: for (int i = 0; i < items.length; i++) {
327: item = (ReferenceDataItem) items[i];
328: Enumeration children = node.children();
329: boolean foundMatch = false;
330: if (!getChooseManyReferenceDataPropertyEditor()
331: .getAllowDuplicates()) {
332: while (children.hasMoreElements()) {
333: DefaultMutableTreeNode childNode = (DefaultMutableTreeNode) children
334: .nextElement();
335: ChooseManyOfManyNodeData data = (ChooseManyOfManyNodeData) childNode
336: .getUserObject();
337: ReferenceDataItem otherItem = (ReferenceDataItem) data
338: .getData();
339: if (item.equals(otherItem)) {
340: foundMatch = true;
341: break;
342: }
343: }
344: }
345: if (!foundMatch) {
346: DefaultMutableTreeNode itemNode = new DefaultMutableTreeNode(
347: new ChooseManyOfManyNodeData(item
348: .getDisplayString(), item), false);
349: int actualInsertIndex;
350: if (insertIndex == -1) {
351: actualInsertIndex = node.getChildCount();
352: } else {
353: actualInsertIndex = insertIndex;
354: insertIndex++;
355: }
356: selectedJTreeModel.insertNodeInto(itemNode, node,
357: actualInsertIndex);
358: selectedJTree.makeVisible(new TreePath(itemNode
359: .getPath()));
360: adjustLeftColumnWidthIfNecessary(itemNode);
361: }
362: }
363: }
364: // if (firstNode != null) {
365: // selectedJTree.scrollPathToVisible(new TreePath(firstNode.getPath()));
366: // }
367: updateTreeRelatedButtons();
368: }
369:
370: protected void handleSelectedJTreeSelectionChanged(
371: TreeSelectionEvent event) {
372:
373: updateTreeRelatedButtons();
374: }
375:
376: protected void handleUpAction(ActionEvent event) {
377:
378: TreePath paths[] = selectedJTree.getSelectionPaths();
379: sortTreePaths(paths);
380: for (int i = 0; i < paths.length; i++) {
381: TreePath path = paths[i];
382: DefaultMutableTreeNode node = (DefaultMutableTreeNode) path
383: .getLastPathComponent();
384: DefaultMutableTreeNode parent = (DefaultMutableTreeNode) node
385: .getParent();
386: int index = parent.getIndex(node);
387: if (index == 0) {
388: continue;
389: }
390: DefaultMutableTreeNode removed = (DefaultMutableTreeNode) parent
391: .getChildAt(index);
392: boolean wasExpanded = selectedJTree.isExpanded(path);
393: selectedJTreeModel.removeNodeFromParent(removed);
394: selectedJTreeModel.insertNodeInto(removed, parent,
395: index - 1);
396: if (wasExpanded && removed.getChildCount() > 0) {
397: DefaultMutableTreeNode firstChild = (DefaultMutableTreeNode) removed
398: .getFirstChild();
399: selectedJTree.makeVisible(new TreePath(firstChild
400: .getPath()));
401: }
402: }
403: selectedJTree.setSelectionPaths(paths);
404: }
405:
406: protected void initializeComponents() {
407: JButton addListJButton;
408: GridBagConstraints gridBagConstraints;
409:
410: super .initializeComponents();
411: JPanel buttonPanel = new JPanel();
412: buttonPanel.setLayout(new BoxLayout(buttonPanel,
413: BoxLayout.LINE_AXIS));
414:
415: // Add add/remove buttons
416: addListJButton = new JButton(BundleHolder.bundle
417: .getMessage("NewGroup")); //NOI18N
418: addListJButton.setActionCommand(ADD_LIST_ACTION);
419: addListJButton.addActionListener(this );
420: buttonPanel.add(addListJButton);
421: buttonPanel.add(Box.createRigidArea(new Dimension(5, 0)));
422:
423: deleteListJButton = new JButton(BundleHolder.bundle
424: .getMessage("RemoveGroup")); //NOI18N
425: deleteListJButton.setActionCommand(DELETE_LIST_ACTION);
426: deleteListJButton.addActionListener(this );
427: deleteListJButton.setEnabled(false);
428: buttonPanel.add(deleteListJButton);
429:
430: gridBagConstraints = new GridBagConstraints();
431: gridBagConstraints.gridx = 3;
432: gridBagConstraints.gridwidth = 2;
433: gridBagConstraints.anchor = GridBagConstraints.FIRST_LINE_END;
434: // gridBagConstraints.fill = GridBagConstraints.HORIZONTAL;
435: gridBagConstraints.insets = new java.awt.Insets(5, 10, 0, 10);
436: add(buttonPanel, gridBagConstraints);
437: updateTreeRelatedButtons();
438: }
439:
440: protected Component initializeSelectedListComponent() {
441:
442: ChooseManyOfManyNodeData data = new ChooseManyOfManyNodeData(
443: "root", null);
444: selectedRootNode = new DefaultMutableTreeNode(data, true);
445: selectedJTreeModel = new DefaultTreeModel(selectedRootNode);
446: selectedJTree = new JTree();
447: ChooseManyOfManyNodeDataTwoColumnTreeCellRenderer renderer = new ChooseManyOfManyNodeDataTwoColumnTreeCellRenderer(
448: getListNodeNamePrefix());
449: selectedJTree.setCellRenderer(renderer);
450: populateSelectedJTreeModel();
451: selectedJTree.setModel(selectedJTreeModel);
452: selectedJTree.setRootVisible(false);
453: selectedJTree.setShowsRootHandles(true);
454: selectedJTree.putClientProperty("JTree.lineStyle", "Angled"); // NOI18N
455: selectedJTree.getSelectionModel().setSelectionMode(
456: TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
457: selectedJTree.getSelectionModel()
458: .addTreeSelectionListener(this );
459: // expand all nodes
460: for (int i = 0; i < selectedJTree.getRowCount(); i++) {
461: selectedJTree.expandRow(i);
462: }
463: return selectedJTree;
464: }
465:
466: protected void populateSelectedJTreeModel() {
467: List manyOfManyList, manyList;
468: Iterator manyOfManyIterator, manyIterator;
469: ReferenceDataItem item;
470: DefaultMutableTreeNode listNode, itemNode;
471: int i;
472:
473: selectedRootNode.removeAllChildren();
474: selectedJTreeModel.reload();
475: ChooseManyOfManyNodeDataTwoColumnTreeCellRenderer renderer = (ChooseManyOfManyNodeDataTwoColumnTreeCellRenderer) selectedJTree
476: .getCellRenderer();
477: renderer.resetLeftColumnWidth();
478: manyOfManyList = getChooseManyOfManyReferenceDataPropertyEditor()
479: .getValueListOfManyOfManyReferenceDataItems();
480: if (manyOfManyList == null) {
481: return;
482: }
483: if (manyOfManyList.size() == 0) {
484: manyOfManyList.add(new ArrayList());
485: }
486: manyOfManyIterator = manyOfManyList.iterator();
487: i = 0;
488: while (manyOfManyIterator.hasNext()) {
489: manyList = (List) manyOfManyIterator.next();
490: listNode = new DefaultMutableTreeNode(
491: new ChooseManyOfManyNodeData(null, manyList), true);
492: selectedJTreeModel.insertNodeInto(listNode,
493: selectedRootNode, selectedRootNode.getChildCount());
494: manyIterator = manyList.iterator();
495: while (manyIterator.hasNext()) {
496: item = (ReferenceDataItem) manyIterator.next();
497: itemNode = new DefaultMutableTreeNode(
498: new ChooseManyOfManyNodeData(item
499: .getDisplayString(), item), false);
500: selectedJTreeModel.insertNodeInto(itemNode, listNode,
501: listNode.getChildCount());
502: renderer.getTreeCellRendererComponent(selectedJTree,
503: itemNode, false, false, false, -1, false);
504: renderer.adjustLeftColumnWidthIfNecessary();
505: }
506: i++;
507: }
508: }
509:
510: protected void removePath(TreePath path) {
511: DefaultMutableTreeNode node, parent, removed;
512: int index;
513:
514: node = (DefaultMutableTreeNode) path.getLastPathComponent();
515: parent = (DefaultMutableTreeNode) node.getParent();
516: index = parent.getIndex(node);
517: removed = (DefaultMutableTreeNode) parent.getChildAt(index);
518: selectedJTreeModel.removeNodeFromParent(removed);
519: }
520:
521: protected void sortTreePaths(TreePath[] paths) {
522:
523: IdentityHashMap selected = new IdentityHashMap();
524: for (int i = 0; i < paths.length; i++) {
525: TreePath path = paths[i];
526: DefaultMutableTreeNode node = (DefaultMutableTreeNode) path
527: .getLastPathComponent();
528: selected.put(node, path);
529: }
530: sortTreePaths(paths, selected, selectedRootNode, 0);
531: }
532:
533: protected int sortTreePaths(TreePath[] paths,
534: IdentityHashMap pathsNodes,
535: DefaultMutableTreeNode currentNode, int index) {
536:
537: if (pathsNodes.containsKey(currentNode)) {
538: paths[index] = (TreePath) pathsNodes.get(currentNode);
539: index++;
540: }
541: Enumeration enumer = currentNode.children();
542: while (enumer.hasMoreElements()) {
543: DefaultMutableTreeNode child = (DefaultMutableTreeNode) enumer
544: .nextElement();
545: index = sortTreePaths(paths, pathsNodes, child, index);
546: }
547: return index;
548: }
549:
550: protected void updateTreeRelatedButtons() {
551:
552: TreePath[] selected = selectedJTree.getSelectionPaths();
553: int selectedCount = selected == null ? 0 : selected.length;
554: if (selectedCount == 0 && !selectedRootNode.isLeaf()) {
555: selectedJTree.setSelectionRow(0);
556: return;
557: }
558: int groupCount = 0;
559: int itemCount = 0;
560: Enumeration enumer = selectedRootNode.breadthFirstEnumeration();
561: while (enumer.hasMoreElements()) {
562: DefaultMutableTreeNode node = (DefaultMutableTreeNode) enumer
563: .nextElement();
564: DefaultMutableTreeNode parent = (DefaultMutableTreeNode) node
565: .getParent();
566: if (parent == null) {
567:
568: } else if (parent == selectedRootNode) {
569: groupCount++;
570: } else {
571: itemCount++;
572: }
573: }
574: int groupsSelectedCount = 0;
575: boolean onlyGroupsSelected = true;
576: boolean anyChildAtTop = false;
577: boolean anyChildAtBottom = false;
578: for (int i = 0; i < selectedCount; i++) {
579: TreePath path = selected[i];
580: DefaultMutableTreeNode node = (DefaultMutableTreeNode) path
581: .getLastPathComponent();
582: if (node.getParent() == selectedRootNode) {
583: groupsSelectedCount++;
584: } else {
585: onlyGroupsSelected = false;
586: }
587: int childIndex = node.getParent().getIndex(node);
588: if (childIndex == 0) {
589: anyChildAtTop = true;
590: }
591: if (childIndex == (node.getParent().getChildCount() - 1)) {
592: anyChildAtBottom = true;
593: }
594: }
595: boolean choicesSelected = choicesJList.getSelectedIndices().length > 0;
596: selectJButton.setEnabled(selectedCount > 0 && choicesSelected);
597: deselectJButton.setEnabled(groupsSelectedCount == 0
598: && selectedCount > 0);
599: deleteListJButton.setEnabled(selectedCount > 0
600: && onlyGroupsSelected);
601: if (getCompositeReferenceData().canOrderItems()) {
602: upJButton.setEnabled(selectedCount > 0 && !anyChildAtTop);
603: downJButton.setEnabled(selectedCount > 0
604: && !anyChildAtBottom);
605: }
606: deselectAllJButton.setEnabled(itemCount > 0);
607: }
608:
609: public void valueChanged(TreeSelectionEvent event) {
610:
611: if (event.getSource() == selectedJTree.getSelectionModel()) {
612: handleSelectedJTreeSelectionChanged(event);
613: }
614: }
615:
616: }
|