001: /*
002: * CONFIDENTIAL AND PROPRIETARY SOURCE CODE OF
003: * NETSCAPE COMMUNICATIONS CORPORATION
004: *
005: * Copyright (c) 1996 Netscape Communications Corporation.
006: * All Rights Reserved.
007: * Use of this Source Code is subject to the terms of the applicable
008: * license agreement from Netscape Communications Corporation.
009: */
010:
011: package graphical;
012:
013: import netscape.application.InternalWindow;
014: import netscape.application.ListItem;
015: import netscape.application.Target;
016: import netscape.application.View;
017:
018: import java.util.Enumeration;
019: import java.util.Vector;
020:
021: import util.BTreeNode;
022:
023: /**
024: TreeViewGroup.
025: <p>
026: <b>Open Issues</b>
027: <ul>
028: <li>
029: </ul>
030: *
031: */
032: public class TreeViewGroup {
033: public final static int ADDNODE = 101;
034: public final static int DELETENODE = 102;
035: /**
036: * Update relevant ListItems based on data in BinaryTree.
037: */
038: public final static int UPDATENODE = 103;
039: /**
040: * Update details based on data in BinaryTree.
041: * See explanation under UPDATETHRUTVG.
042: */
043: public final static int UPDATEDETAIL = 104;
044: /**
045: * Update relevant ListItems based on passed title rather
046: * than data in BinaryTree which is not necessarily updated
047: * yet.
048: */
049: public final static int UPDATETITLE = 105;
050: /**
051: * Force removal of all ListItems.
052: */
053: public final static int CLEAR = 106;
054: /**
055: * Clear change flag.
056: */
057: public final static int CLEARCHANGE = 107;
058:
059: /**
060: * Send performCommand( UPDATETHRUTVG, btn ) to targeted TreeViews.
061: * This is so TreeView subclasses that have details associated with
062: * individual nodes can transmit data about changes to the details.
063: * This is done as part of and UPDATENODE action and is the sole
064: * purpose of and UPDATEDETAIL action.
065: */
066: public final static String UPDATETHRUTVG = "UPDATETHRUTVG";
067:
068: private Vector vector;
069:
070: public TreeViewGroup() {
071: vector = new Vector();
072: }
073:
074: public void addTreeView(TreeView treeView) {
075: vector.addElement(treeView);
076: }
077:
078: public void removeTreeView(TreeView treeView) {
079: vector.removeElement(treeView);
080: }
081:
082: public void sendAction(TreeView treeView, int action, BTreeNode btn) {
083: sendAction(treeView, action, btn, null);
084: }
085:
086: // SGP: add explanation of UPDATEDETAIL.
087: /**
088: * When performing certain actions, mimic those actions
089: * in TreeViews showing the same data.
090: * If the action to be performed is ADDNODE
091: * the BTreeNode target is actually the <i>parent</i> of the
092: * node to be affected.
093: * Since drawing children depends on knowing the parent and
094: * whether the parent is open or not and since in the
095: * ADDNODE instance a new ListItem needs to be created
096: * and therefore cannot be found, the parent is the target
097: * for these actions.
098: * DELETENODE targets the node itself because the BTreeNode
099: * instance still exists, referenced in the local ListItem's
100: * data() block (if there is a local ListItem).
101: * It is also necessary to determine if the TreeView is rooted
102: * at or below a deleted item, in which case the TreeView is
103: * marked dead.
104: * Otherwise, the parent is located and if displayed handled
105: * the same way an ADDNODE is.
106: * Both the update actions, UPDATENODE and UPDATETITLE target
107: * the node itself.
108: * UPDATENODE forces the node to be updated based on the data
109: * in the corresponding BTreeNode.
110: * This would be done typically when editing focus for that
111: * node is lost in the originating TreeView.
112: * UPDATETITLE is a special case which allows the title of
113: * ListItems and the floating TextField to be modified without
114: * reference to the BTreeNode.
115: * It is necessary to do this because changing the key of the
116: * BTreeNode is delayed to prevent sorting while the user is
117: * typing.
118: * @param treeView the treeView instance initiating the action
119: * @param action the action to be performed
120: * @param btn the BTreeNode the action affects
121: * @param s string used for UPDATETITLE
122: */
123: public void sendAction(TreeView treeView, int action,
124: BTreeNode btn, String s) {
125: // System.out.println( "TreeViewGroup action " + action );
126:
127: if ((action == UPDATETITLE) && (s == null)) {
128: throw new IllegalArgumentException(
129: Messages.UNKNOWNTVGACTION);
130: }
131:
132: if ((action != ADDNODE) && (action != DELETENODE)
133: && (action != UPDATENODE) && (action != UPDATEDETAIL)
134: && (action != UPDATETITLE) && (action != CLEAR)
135: && (action != CLEARCHANGE)) {
136: throw new IllegalArgumentException(
137: Messages.UNKNOWNTVGACTION + ": " + action);
138: }
139:
140: int counter = 0;
141: Enumeration e = vector.elements();
142: while (e.hasMoreElements()) {
143: // System.out.println( "---< " + counter + " >---" );
144: counter++;
145: TreeView tv = (TreeView) e.nextElement();
146: if (tv != treeView) {
147: if (action == DELETENODE) {
148: BTreeNode rbtn = tv.getBinaryTreeRooted();
149: if ((btn == rbtn) || (rbtn.hasAncestor(btn))) {
150: tv.deepSix();
151: // SGP: a little hokey, might be better
152: // to cruise up the hierarchy looking
153: // for IW.
154: View v1 = tv.super view();
155: if (v1 != null) {
156: View v2 = v1.super view();
157: if (v2 != null) {
158: if (v2 instanceof InternalWindow) {
159: // SGP: shouldn't
160: // be hide().
161: ((InternalWindow) v2).hide();
162: }
163: }
164: }
165: }
166: }
167:
168: BTListItem li = (BTListItem) tv.listView
169: .itemForData(btn);
170:
171: if (action == CLEAR) {
172: // System.out.println( "CLEAR" );
173: tv.listView.removeAllItems();
174: tv.listView.setDirty(true);
175: } else if (action == CLEARCHANGE) {
176: // System.out.println( "CLEARCHANGE" );
177: tv.clearChanged();
178: } else if (li != null) {
179: if (action == ADDNODE) {
180: // System.out.println( "ADDNODE" );
181: // SGP: should be smarter,
182: // you close stuff this way
183: if (li.getState() == BTListItem.OPEN) {
184: tv.childReorganize(li);
185: // tv.openAndClose( li );
186: // tv.openAndClose( li );
187: tv.listView.sizeListView();
188: tv.listView.setDirty(true);
189: }
190: } else if (action == DELETENODE) {
191: // SGP: should be smarter,
192: // you close stuff this way
193: // System.out.println( "DELETENODE " );
194: BTListItem pli = tv.getUnaryParentItem(li);
195: tv.childReorganize(pli);
196: // tv.openAndClose( pli );
197: // tv.openAndClose( pli );
198: tv.listView.sizeListView();
199: tv.listView.setDirty(true);
200: if (tv.listView.count() == 0) {
201: }
202: } else if (action == UPDATENODE) {
203: // System.out.println( "UPDATENODE " );
204: li.setTitle((String) btn.getKey());
205: tv.listView.clipSortAndPaste(li);
206: tv.listView.sizeListView();
207: tv.performCommand(UPDATETHRUTVG, btn);
208: tv.listView.setDirty(true);
209: } else if (action == UPDATEDETAIL) {
210: // System.out.println( "UPDATEDETAIL " );
211: tv.performCommand(UPDATETHRUTVG, btn);
212: tv.listView.setDirty(true);
213: } else if (action == UPDATETITLE) {
214: // System.out.println( "UPDATETITLE " + s );
215: li.setTitle(s);
216: tv.listView.sizeListView();
217: tv.listView.setDirty(true);
218: }
219: }
220: }
221: }
222:
223: if (action == CLEARCHANGE) {
224: // Taxonomy has been changed, notify Desktop applications
225:
226: // System.out.println("Broadcasting Tax Chg======\n" + "\n=======");
227:
228: if (treeView != null) {
229: Target target = ((IconInternalWindow) treeView.window())
230: .desktopBroadcastTarget();
231: String command = ((IconInternalWindow) treeView
232: .window()).desktopBroadcastCommand();
233:
234: if (target != null) {
235: target.performCommand(command,
236: applications.Messages.CMD_TAX_CHG);
237: }
238:
239: // Needed here as the above loop skips the current current treeView.
240: treeView.clearChanged();
241: }
242: }
243: }
244:
245: }
|