0001: /*
0002: * CONFIDENTIAL AND PROPRIETARY SOURCE CODE OF
0003: * NETSCAPE COMMUNICATIONS CORPORATION
0004: *
0005: * Copyright (c) 1996 Netscape Communications Corporation.
0006: * All Rights Reserved.
0007: * Use of this Source Code is subject to the terms of the applicable
0008: * license agreement from Netscape Communications Corporation.
0009: */
0010:
0011: package graphical;
0012:
0013: import util.BinaryTree;
0014: import util.BTreeNode;
0015:
0016: import netscape.application.Application;
0017: import netscape.application.Alert;
0018: import netscape.application.BezelBorder;
0019: import netscape.application.Bitmap;
0020: import netscape.application.Border;
0021: import netscape.application.Button;
0022: import netscape.application.Color;
0023: import netscape.application.Event;
0024: import netscape.application.Image;
0025: import netscape.application.InternalWindow;
0026: import netscape.application.KeyEvent;
0027: import netscape.application.LineBorder;
0028: import netscape.application.ListItem;
0029: import netscape.application.ListView;
0030: import netscape.application.MouseEvent;
0031: import netscape.application.Point;
0032: import netscape.application.Rect;
0033: import netscape.application.ScrollGroup;
0034: import netscape.application.Size;
0035: import netscape.application.Target;
0036: import netscape.application.TextField;
0037: import netscape.application.TextFieldOwner;
0038: import netscape.application.Timer;
0039: import netscape.application.Window;
0040: import netscape.application.View;
0041: import netscape.util.Vector; // SGP?
0042:
0043: import java.awt.Dimension;
0044: import java.net.URL;
0045: import java.net.MalformedURLException;
0046: import java.util.Date;
0047: import java.util.Stack;
0048: import java.util.Enumeration;
0049:
0050: /**
0051: TreeView.
0052: <p>
0053: Using the BinaryTree enumeration as it's spine,
0054: this widget displays information in a file mangerish fashion.
0055: <p>
0056: It is important to note that a selected item in
0057: the TreeView does not correspond directly to the
0058: current position in the BinaryTree.
0059: The reason for this is to allow multiple TreeViews
0060: to view the same BinaryTree.
0061: <p>
0062: The "look" is configurable by passing appropriate images
0063: to the constructors.
0064: <p>
0065: <b>Open Issues</b>
0066: <ul>
0067: <li>Null trees not handled. Some code stubbed in, but
0068: basically on the floor.
0069: </ul>
0070: *
0071: */
0072: public class TreeView extends View implements Target, TextFieldOwner {
0073: /*---< declarations >------------------------------------------------*/
0074:
0075: private boolean editable;
0076: private boolean editableRoot;
0077: protected TreeViewGroup treeViewGroup;
0078:
0079: public ScrollGroup scrollGroup;
0080: public DragListView listView;
0081:
0082: private BTListItem currentListItem;
0083:
0084: public Button newPeerBtn;
0085: public Button newChildBtn;
0086: public Button delBtn;
0087: public Button cancelBtn;
0088: public Button saveBtn;
0089:
0090: protected TextField textField;
0091: protected TextFieldOwner textFieldOwner;
0092:
0093: protected BinaryTree binaryTree;
0094:
0095: private Point VFMPoint;
0096:
0097: private Dimension imageSize;
0098: private int pixelCount;
0099:
0100: private int spacePixels[];
0101: private int documentSelPixels[];
0102: private int documentPixels[];
0103: private int folderSelPixels[];
0104: private int folderPixels[];
0105: private int branchOpenSelPixels[];
0106: private int branchOpenPixels[];
0107: private int branchClosedSelPixels[];
0108: private int branchClosedPixels[];
0109:
0110: private boolean emptyAllowed;
0111: private boolean dupePeerNamesAllowed;
0112: private boolean changed;
0113:
0114: /**
0115: * If btRooted is null, it is assumed that the view is rooted
0116: * at the top of the tree.
0117: */
0118: private BTreeNode btRooted;
0119:
0120: private Target launcherTarget;
0121: private String launcherCommand;
0122:
0123: private int look;
0124: public final static int NSLOOK = 1;
0125: public final static int MACLOOK = 2;
0126:
0127: private int feel;
0128: public final static int NSFEEL = 1;
0129: public final static int MACFEEL = 2;
0130:
0131: /*--------------*/
0132: /* constructors */
0133: /*--------------*/
0134:
0135: // SGP: boolean not being checked on return, not even
0136: // clear that this is serious.
0137: private boolean checkLength(int base, int target) {
0138: if (base != target) {
0139: // SGP: error
0140: return false;
0141: }
0142:
0143: return true;
0144: }
0145:
0146: private void commonConstruction(boolean editable, int x, int y,
0147: int w, int h, int dragSourcePolicy,
0148: int dragDestinationPolicy, boolean sizeForWindow) {
0149: look = MACLOOK;
0150: feel = MACFEEL;
0151:
0152: editableRoot = true;
0153: emptyAllowed = true;
0154: dupePeerNamesAllowed = true;
0155: changed = false;
0156: treeViewGroup = null;
0157: textFieldOwner = null;
0158: launcherTarget = null;
0159: launcherCommand = null;
0160: this .editable = editable;
0161: VFMPoint = new Point(Integer.MIN_VALUE, Integer.MIN_VALUE);
0162:
0163: Size btnSize = new Size();
0164:
0165: listView = new DragListView(0, 0, 10, // SGP
0166: 500, // SGP
0167: dragSourcePolicy, dragDestinationPolicy, null);
0168: listView.setAllowsEmptySelection(true);
0169: listView.setTreeView(this );
0170:
0171: BTListItem listItem = new BTListItem();
0172: listItem.setData(null);
0173: listItem.setTitle(Messages.NEW);
0174:
0175: if (sizeForWindow) {
0176: scrollGroup = new ScrollGroup(Header.WIDGETHGAP,
0177: Header.WIDGETVGAP, w - (Header.WIDGETHGAP * 2), h
0178: - (Header.WIDGETVGAP * 2)
0179: - Header.CREEPYFUDGEGAP);
0180: } else {
0181: scrollGroup = new ScrollGroup(0, 0, w, h);
0182: }
0183: scrollGroup.setHasHorizScrollBar(true);
0184: scrollGroup.setHasVertScrollBar(true);
0185: scrollGroup.setBorder(new BezelBorder(BezelBorder.LOWERED,
0186: Color.lightGray));
0187: scrollGroup.setBuffered(true);
0188: scrollGroup.scrollView().setBackgroundColor(Color.white);
0189: scrollGroup.setHorizResizeInstruction(View.WIDTH_CAN_CHANGE);
0190: scrollGroup.setVertResizeInstruction(View.HEIGHT_CAN_CHANGE);
0191:
0192: listView.setPrototypeItem(listItem);
0193: listView.sizeToMinSize();
0194: listView.setTarget(this );
0195: listView.setCommand("clickCommand");
0196: listView.setDoubleCommand("doubleClickCommand");
0197: // SGP: this appears to do nothing (handled by TextFieldOwner methods)
0198: /*
0199: setCommandForKey(
0200: "completeEditing",
0201: null,
0202: 10, // SGP
0203: KeyEvent.NO_MODIFIERS_MASK,
0204: View.ALWAYS
0205: );
0206: */
0207: setCommandForKey("newWindow", null, 111, // SGP
0208: KeyEvent.CONTROL_MASK, View.ALWAYS);
0209: setCommandForKey("switchLookFeel", null, 27, // SGP
0210: KeyEvent.CONTROL_MASK, View.ALWAYS);
0211: /*
0212: setCommandForKey(
0213: "switchLookFeel",
0214: null,
0215: 55, // SGP
0216: KeyEvent.CONTROL_MASK | KeyEvent.SHIFT_MASK,
0217: View.ALWAYS
0218: );
0219: */
0220: listView.setBackgroundColor(Color.white);
0221: listView.setBuffered(true);
0222:
0223: scrollGroup.scrollView().setContentView(listView);
0224:
0225: if (editable) {
0226: textField = new TextField();
0227: textField.setOwner(this );
0228: // textField.setSelectionColor( Header.SELECTEDCOLOR );
0229: // textField.setBorder( null );
0230:
0231: newPeerBtn = Header.buttonMacro(Messages.CMD_NEWPEER, this );
0232: newChildBtn = Header.buttonMacro(Messages.CMD_NEWCHILD,
0233: this );
0234: delBtn = Header.buttonMacro(Messages.CMD_DELETE, this );
0235: cancelBtn = Header.buttonMacro(Messages.CMD_CANCEL, this );
0236: saveBtn = Header.buttonMacro(Messages.CMD_SAVE, this );
0237:
0238: btnSize.union(newPeerBtn.minSize());
0239: btnSize.union(newChildBtn.minSize());
0240: btnSize.union(delBtn.minSize());
0241: btnSize.union(cancelBtn.minSize());
0242: btnSize.union(saveBtn.minSize());
0243:
0244: newPeerBtn.setBounds(Header.WIDGETHGAP, Header.WIDGETVGAP,
0245: btnSize.width, btnSize.height);
0246: newChildBtn.setBounds(Header.WIDGETHGAP
0247: + ((btnSize.width + Header.WIDGETHGAP) * 1),
0248: Header.WIDGETVGAP, btnSize.width, btnSize.height);
0249: delBtn.setBounds(Header.WIDGETHGAP
0250: + ((btnSize.width + Header.WIDGETHGAP) * 2)
0251: + (Header.WIDGETHGAP * 3), // del spc
0252: Header.WIDGETVGAP, btnSize.width, btnSize.height);
0253:
0254: scrollGroup.setBounds(Header.WIDGETHGAP, btnSize.height
0255: + (Header.WIDGETVGAP * 2), scrollGroup.width(),
0256: scrollGroup.height() - btnSize.height * 2
0257: - Header.WIDGETVGAP - Header.DETAILVGAP);
0258:
0259: int leftX = scrollGroup.x() + scrollGroup.width()
0260: - scrollGroup.vertScrollBar().width()
0261: - scrollGroup.border().widthMargin();
0262:
0263: cancelBtn.setBounds(leftX
0264: - ((btnSize.width * 2) + Header.WIDGETHGAP),
0265: scrollGroup.y() + scrollGroup.height()
0266: + Header.WIDGETVGAP, btnSize.width,
0267: btnSize.height);
0268: cancelBtn
0269: .setHorizResizeInstruction(View.LEFT_MARGIN_CAN_CHANGE);
0270: cancelBtn
0271: .setVertResizeInstruction(View.TOP_MARGIN_CAN_CHANGE);
0272:
0273: saveBtn.setBounds(leftX - btnSize.width, scrollGroup.y()
0274: + scrollGroup.height() + Header.WIDGETVGAP,
0275: btnSize.width, btnSize.height);
0276: saveBtn
0277: .setHorizResizeInstruction(View.LEFT_MARGIN_CAN_CHANGE);
0278: saveBtn
0279: .setVertResizeInstruction(View.TOP_MARGIN_CAN_CHANGE);
0280:
0281: addSubview(newPeerBtn);
0282: addSubview(newChildBtn);
0283: addSubview(delBtn);
0284: addSubview(cancelBtn);
0285: addSubview(saveBtn);
0286: } else {
0287: // avoid null references
0288: newPeerBtn = new Button();
0289: newChildBtn = new Button();
0290: delBtn = new Button();
0291: cancelBtn = new Button();
0292: saveBtn = new Button();
0293: }
0294:
0295: setEditListItem();
0296: buttonEnablement();
0297:
0298: addSubview(scrollGroup);
0299: }
0300:
0301: /**
0302: * Construct instance of TreeView.
0303: * If the passed binary tree is null, a new one is created.
0304: * This constructor takes gifs as names and acquires them.
0305: * @param binaryTree passed binary tree
0306: * @param editable editable or not
0307: * @param x x
0308: * @param y y
0309: * @param w width
0310: * @param h height
0311: * @param dragSourcePolicy drag source policy
0312: * @param dragDestinationPolicy drag destination policy
0313: * @param sizeForWindow size for containment in a window or a view
0314: * @param nameSpace url for space image
0315: * @param nameDocumentSel url for selected document image
0316: * @param nameDocument url for document image
0317: * @param nameFolderSel url for selected folder image
0318: * @param nameFolder url for folder image
0319: * @param nameBranchOpenSel url for selected branch open image
0320: * @param nameBranchOpen url for branch open image
0321: * @param nameBranchClosedSel url for selected branch closed image
0322: * @param nameBranchClosed url for branch closed image
0323: */
0324: public TreeView(BinaryTree binaryTree, boolean editable, int x,
0325: int y, int w, int h, int dragSourcePolicy,
0326: int dragDestinationPolicy, boolean sizeForWindow,
0327: String nameSpace, String nameDocumentSel,
0328: String nameDocument, String nameFolderSel,
0329: String nameFolder, String nameBranchOpenSel,
0330: String nameBranchOpen, String nameBranchClosedSel,
0331: String nameBranchClosed) {
0332: super (x, y, w, h);
0333:
0334: Bitmap space = BitmapHandle.acquireBitmap(nameSpace);
0335: Bitmap documentSel = BitmapHandle
0336: .acquireBitmap(nameDocumentSel);
0337: Bitmap document = BitmapHandle.acquireBitmap(nameDocument);
0338: Bitmap folderSel = BitmapHandle.acquireBitmap(nameFolderSel);
0339: Bitmap folder = BitmapHandle.acquireBitmap(nameFolder);
0340: Bitmap branchOpenSel = BitmapHandle
0341: .acquireBitmap(nameBranchOpenSel);
0342: Bitmap branchOpen = BitmapHandle.acquireBitmap(nameBranchOpen);
0343: Bitmap branchClosedSel = BitmapHandle
0344: .acquireBitmap(nameBranchClosedSel);
0345: Bitmap branchClosed = BitmapHandle
0346: .acquireBitmap(nameBranchClosed);
0347:
0348: commonConstruction(editable, x, y, w, h, dragSourcePolicy,
0349: dragDestinationPolicy, sizeForWindow);
0350:
0351: imageSize = new Dimension(space.width(), space.height());
0352: pixelCount = space.height() * space.width();
0353:
0354: BitmapHandle.checkDimensions(space, imageSize);
0355: spacePixels = BitmapHandle.pixelGrab(space, pixelCount);
0356: BitmapHandle.checkDimensions(documentSel, imageSize);
0357: documentSelPixels = BitmapHandle.pixelGrab(documentSel,
0358: pixelCount);
0359: BitmapHandle.checkDimensions(document, imageSize);
0360: documentPixels = BitmapHandle.pixelGrab(document, pixelCount);
0361: BitmapHandle.checkDimensions(folderSel, imageSize);
0362: folderSelPixels = BitmapHandle.pixelGrab(folderSel, pixelCount);
0363: BitmapHandle.checkDimensions(folder, imageSize);
0364: folderPixels = BitmapHandle.pixelGrab(folder, pixelCount);
0365: BitmapHandle.checkDimensions(branchOpenSel, imageSize);
0366: branchOpenSelPixels = BitmapHandle.pixelGrab(branchOpenSel,
0367: pixelCount);
0368: BitmapHandle.checkDimensions(branchOpen, imageSize);
0369: branchOpenPixels = BitmapHandle.pixelGrab(branchOpen,
0370: pixelCount);
0371: BitmapHandle.checkDimensions(branchClosedSel, imageSize);
0372: branchClosedSelPixels = BitmapHandle.pixelGrab(branchClosedSel,
0373: pixelCount);
0374: BitmapHandle.checkDimensions(branchClosed, imageSize);
0375: branchClosedPixels = BitmapHandle.pixelGrab(branchClosed,
0376: pixelCount);
0377:
0378: listView.setDragImage(new Bitmap(folderPixels, imageSize.width,
0379: imageSize.height));
0380:
0381: setBinaryTree(binaryTree);
0382: }
0383:
0384: /**
0385: * Construct instance of TreeView.
0386: * If the passed binary tree is null, a new one is created.
0387: * @param binaryTree passed binary tree
0388: * @param editable editable or not
0389: * @param x x
0390: * @param y y
0391: * @param w width
0392: * @param h height
0393: * @param dragSourcePolicy drag source policy
0394: * @param dragDestinationPolicy drag destination policy
0395: * @param sizeForWindow size for containment in a window or a view
0396: * @param arraySpace pixel array for space
0397: * @param arrayDocumentSel pixel array for selected document
0398: * @param arrayDocument pixel array for document
0399: * @param arrayFolderSel pixel array for selected folder
0400: * @param arrayFolder pixel array for folder
0401: * @param arrayBranchOpenSel pixel array for selected branch open
0402: * @param arrayBranchOpen pixel array for branch open
0403: * @param arrayBranchClosedSel pixel array for selected branch closed
0404: * @param arrayBranchClosed pixel array for branch closed
0405: * @param imageSize the expected dimension for the tree images
0406: * @param pixelCount the expected pixel count for the tree images
0407: */
0408: public TreeView(BinaryTree binaryTree, boolean editable, int x,
0409: int y, int w, int h, int dragSourcePolicy,
0410: int dragDestinationPolicy, boolean sizeForWindow,
0411: int arraySpace[], int arrayDocumentSel[],
0412: int arrayDocument[], int arrayFolderSel[],
0413: int arrayFolder[], int arrayBranchOpenSel[],
0414: int arrayBranchOpen[], int arrayBranchClosedSel[],
0415: int arrayBranchClosed[], Dimension imageSize, int pixelCount) {
0416: super (x, y, w, h);
0417:
0418: commonConstruction(editable, x, y, w, h, dragSourcePolicy,
0419: dragDestinationPolicy, sizeForWindow);
0420:
0421: this .imageSize = imageSize;
0422: this .pixelCount = pixelCount;
0423:
0424: if ((imageSize.width * imageSize.height) != pixelCount) {
0425: // SGP: error
0426: }
0427:
0428: spacePixels = arraySpace;
0429: documentSelPixels = arrayDocumentSel;
0430: documentPixels = arrayDocument;
0431: folderSelPixels = arrayFolderSel;
0432: folderPixels = arrayFolder;
0433: branchOpenSelPixels = arrayBranchOpenSel;
0434: branchOpenPixels = arrayBranchOpen;
0435: branchClosedSelPixels = arrayBranchClosedSel;
0436: branchClosedPixels = arrayBranchClosed;
0437:
0438: checkLength(spacePixels.length, documentSelPixels.length);
0439: checkLength(spacePixels.length, documentPixels.length);
0440: checkLength(spacePixels.length, folderSelPixels.length);
0441: checkLength(spacePixels.length, folderPixels.length);
0442: checkLength(spacePixels.length, branchOpenSelPixels.length);
0443: checkLength(spacePixels.length, branchOpenPixels.length);
0444: checkLength(spacePixels.length, branchClosedSelPixels.length);
0445: checkLength(spacePixels.length, branchClosedPixels.length);
0446:
0447: listView.setDragImage(new Bitmap(folderPixels, imageSize.width,
0448: imageSize.height));
0449:
0450: setBinaryTree(binaryTree);
0451: }
0452:
0453: public void setDragSourcePolicy(int dragSourcePolicy) {
0454: listView.setDragSourcePolicy(dragSourcePolicy);
0455: }
0456:
0457: public void setDragDestinationPolicy(int dragDestinationPolicy) {
0458: listView.setDragDestinationPolicy(dragDestinationPolicy);
0459: }
0460:
0461: public void setDragDestinationTarget(Target dragDestinationTarget) {
0462: listView.setDestinationTarget(dragDestinationTarget);
0463: }
0464:
0465: public void setTreeViewGroup(TreeViewGroup treeViewGroup) {
0466: this .treeViewGroup = treeViewGroup;
0467: if (treeViewGroup == null) {
0468: treeViewGroup.removeTreeView(this );
0469: } else {
0470: treeViewGroup.addTreeView(this );
0471: }
0472: }
0473:
0474: public TreeViewGroup getTreeViewGroup() {
0475: return treeViewGroup;
0476: }
0477:
0478: public void setBinaryTree(BinaryTree binaryTree) {
0479: setBinaryTree(binaryTree, null);
0480: }
0481:
0482: public void setBinaryTree(BTreeNode btRooted) {
0483: setBinaryTree(binaryTree, btRooted);
0484: }
0485:
0486: // SGP
0487: /**
0488: * Note that if btRooted is not found in the tree, the tree
0489: * is silently assumed to be rooted at the top.
0490: * Behaviour may be changed later to throw an exception.
0491: * If btRooted is null, the top of the tree is also assumed.
0492: */
0493: public void setBinaryTree(BinaryTree binaryTree, BTreeNode btRooted) {
0494: if (binaryTree == null) {
0495: // SGP: this is probably broken. should create
0496: // at least the top node for an empty tree.
0497: // btRooted is going to need to always have
0498: // a value (unless i do something stupid),
0499: // and a tree w/ no nodes doesn't really get
0500: // you anywhere in the universe we are creating
0501: // here.
0502: this .binaryTree = new BinaryTree(BinaryTree.DEPTHFIRST);
0503: this .btRooted = null;
0504: } else {
0505: this .binaryTree = binaryTree;
0506: if (btRooted == null) {
0507: this .btRooted = binaryTree.getRoot();
0508: } else if (btRooted.hasAncestor(binaryTree.getRoot())) {
0509: this .btRooted = btRooted;
0510: } else {
0511: this .btRooted = binaryTree.getRoot();
0512: }
0513: }
0514:
0515: listView.removeAllItems();
0516:
0517: if (binaryTree != null) {
0518: // SGP: assuming this.btRooted could be null,
0519: // see doubts expressed above.
0520: if (this .btRooted != null) {
0521: if (this .btRooted.display) {
0522: listView.addItem(createBTListItem(this .btRooted));
0523: }
0524: }
0525: }
0526:
0527: listView.sizeListView();
0528: listView.setBinaryTree(this .binaryTree);
0529: setEditListItem();
0530: buttonEnablement();
0531: }
0532:
0533: /**
0534: * The current binary tree.
0535: */
0536: public BinaryTree getBinaryTree() {
0537: return binaryTree;
0538: }
0539:
0540: /**
0541: * Get the node where the binary tree is rooted for this view.
0542: */
0543: public BTreeNode getBinaryTreeRooted() {
0544: return btRooted;
0545: }
0546:
0547: /**
0548: * Set whether the root is editable or not.
0549: */
0550: public void setEditableRoot(boolean editableRoot) {
0551: this .editableRoot = editableRoot;
0552: buttonEnablement();
0553: }
0554:
0555: /**
0556: * Whether the TreeView instance is an editable one or not.
0557: */
0558: public boolean editable() {
0559: return editable;
0560: }
0561:
0562: /**
0563: * Controls whether a delete of the root leaves you
0564: * with an empty list or a "new" root.
0565: * Default is true.
0566: */
0567: public void setEmptyAllowed(boolean emptyAllowed) {
0568: this .emptyAllowed = emptyAllowed;
0569: buttonEnablement();
0570: // SGP: when setting to false, something should
0571: // be added to an empty list. hahahahaha.
0572: }
0573:
0574: /**
0575: * Current value of empty allowability.
0576: */
0577: public boolean emptyAllowed() {
0578: return emptyAllowed;
0579: }
0580:
0581: /**
0582: * Controls whether duplicate peer names are allowed.
0583: * Does not unduplicate if mistakes have already been made.
0584: * Default is true.
0585: */
0586: public void setDupePeerNamesAllowed(boolean dupePeerNamesAllowed) {
0587: this .dupePeerNamesAllowed = dupePeerNamesAllowed;
0588: }
0589:
0590: /**
0591: * Current status of whether duplicate peer names are allowed.
0592: */
0593: public boolean dupePeerNamesAllowed() {
0594: return dupePeerNamesAllowed;
0595: }
0596:
0597: /**
0598: * Turn off the floating TextField editor.
0599: */
0600: public void enableTextEdit(boolean b) {
0601: if (b) {
0602: textField = new TextField();
0603: } else {
0604: textField = null;
0605: }
0606: }
0607:
0608: /**
0609: * Notify target of key event processing in the floating
0610: * TextField editor.
0611: * Returns false if the TextField is null.
0612: * @param target target
0613: */
0614: public boolean notifyOfTFEvents(Target target) {
0615: if (textField == null) {
0616: return false;
0617: }
0618:
0619: return true;
0620: }
0621:
0622: /*-----------------*/
0623: /* manipulate list */
0624: /*-----------------*/
0625:
0626: /**
0627: * Create a new ListItem based on "current" in the binary
0628: * tree enumeration.
0629: */
0630: private BTListItem createBTListItem(BTreeNode btn) {
0631: BTListItem listItem = new BTListItem();
0632: updateBTListItem(listItem, btn);
0633: return listItem;
0634: }
0635:
0636: /**
0637: * Update a ListItem based on "current" in the binary
0638: * tree enumeration.
0639: */
0640: private void updateBTListItem(BTListItem listItem, BTreeNode btn) {
0641: listItem.setData(btn);
0642: listItem.setTitle((String) btn.getKey());
0643: listItem.setImage(determineImage(btn, listItem, false));
0644: listItem.setSelectedImage(determineImage(btn, listItem, true));
0645: }
0646:
0647: /*-------------*/
0648: /* image stuff */
0649: /*-------------*/
0650:
0651: public void setLook(int look) throws IllegalArgumentException {
0652: if ((look == NSLOOK) || (look == MACLOOK)) {
0653: this .look = look;
0654: } else {
0655: throw new IllegalArgumentException();
0656: }
0657: }
0658:
0659: public void setFeel(int feel) throws IllegalArgumentException {
0660: if ((feel == NSFEEL) || (feel == MACFEEL)) {
0661: this .feel = feel;
0662: } else {
0663: throw new IllegalArgumentException();
0664: }
0665: }
0666:
0667: public void doReimaging() {
0668: int lvc = listView.count();
0669: for (int i = 0; i < lvc; i++) {
0670: BTListItem li = (BTListItem) listView.itemAt(i);
0671: li
0672: .setImage(determineImage((BTreeNode) li.data(), li,
0673: false));
0674: li.setSelectedImage(determineImage((BTreeNode) li.data(),
0675: li, true));
0676: }
0677: listView.sizeListView();
0678: listView.setDirty(true);
0679: }
0680:
0681: public Image determineImage(BTreeNode btn, BTListItem listItem,
0682: boolean selected) {
0683: return determineImage(btn, listItem, selected, true);
0684: }
0685:
0686: public Image determineImage(BTreeNode btn, BTListItem listItem,
0687: boolean selected, boolean indent) {
0688: if (look == NSLOOK) {
0689: return determineNSImage(btn, listItem, selected, indent);
0690: }
0691: // ( look == MACLOOK )
0692: return determineMacImage(btn, listItem, selected, indent);
0693: }
0694:
0695: public Image determineNSImage(BTreeNode btn, BTListItem listItem,
0696: boolean selected, boolean indent) {
0697: // SGP: brutally, brutally hard coded sandtrap
0698: // SGP: be nice to have own Stack that had count()
0699: // SGP: clean up - a much better hack than what has
0700: // become determineMacImage, but still big macro
0701: // opportunities, etc.
0702: // System.out.println( "determinNSImage():" );
0703:
0704: Stack imageStack = new Stack();
0705: Stack widthStack = new Stack();
0706: int stackCount = 0;
0707: int nextliindex = listView.indexOfItem(listItem) + 1;
0708: int lvcount = listView.count();
0709:
0710: // container or terminal?
0711: if (btn.getChild(true) == null) {
0712: // SGP: since this is currently hardcoded
0713: // and the tax is the issue, we'll leave out
0714: // doc for now and put in folder closed.
0715: // imageStack.push( Header.nsdoc );
0716: imageStack.push(Header.nsfolderclosed);
0717: widthStack.push(new Integer(Header.NSLOOKWWIDE));
0718: stackCount++;
0719: } else {
0720: // container open or closed?
0721: if (listItem.getState() == BTListItem.CLOSED) {
0722: imageStack.push(Header.nsfolderclosed);
0723: widthStack.push(new Integer(Header.NSLOOKWWIDE));
0724: stackCount++;
0725: imageStack.push(Header.nsarrowclosed);
0726: widthStack.push(new Integer(Header.NSLOOKWNARROW));
0727: stackCount++;
0728: } else {
0729: imageStack.push(Header.nsfolderopen);
0730: widthStack.push(new Integer(Header.NSLOOKWWIDE));
0731: stackCount++;
0732: imageStack.push(Header.nsarrowopen);
0733: widthStack.push(new Integer(Header.NSLOOKWNARROW));
0734: stackCount++;
0735: }
0736: }
0737:
0738: // root, trailing peer or peer?
0739: if (btn == btRooted) {
0740: } else if (btn.getNext(true) == null) {
0741: imageStack.push(Header.nslineswoosh);
0742: widthStack.push(new Integer(Header.NSLOOKWWIDE));
0743: stackCount++;
0744: } else {
0745: imageStack.push(Header.nslinefork);
0746: widthStack.push(new Integer(Header.NSLOOKWWIDE));
0747: stackCount++;
0748: }
0749:
0750: for (int i = btn.getUnaryDepth() - 1; i > btRooted
0751: .getUnaryDepth(); i--) {
0752: imageStack.push(Header.nsspacearrow);
0753: widthStack.push(new Integer(Header.NSLOOKWNARROW));
0754: stackCount++;
0755:
0756: boolean b = false;
0757: for (int j = nextliindex; j < lvcount; j++) {
0758: if (i == ((BTreeNode) listView.itemAt(j).data())
0759: .getUnaryDepth())
0760:
0761: {
0762: b = true;
0763: break;
0764: }
0765: }
0766:
0767: if (b) {
0768: imageStack.push(Header.nslinevert);
0769: widthStack.push(new Integer(Header.NSLOOKWWIDE));
0770: stackCount++;
0771: } else {
0772: imageStack.push(Header.nsspace);
0773: widthStack.push(new Integer(Header.NSLOOKWWIDE));
0774: stackCount++;
0775: }
0776: }
0777:
0778: if (btn != btRooted) {
0779: imageStack.push(Header.nsspacearrow);
0780: widthStack.push(new Integer(Header.NSLOOKWNARROW));
0781: stackCount++;
0782: }
0783:
0784: imageStack.push(Header.nsspacearrow);
0785: widthStack.push(new Integer(Header.NSLOOKWNARROW));
0786: stackCount++;
0787:
0788: int maxPixelCount = Header.NSLOOKWWIDE * Header.NSLOOKWWIDE;
0789: int imageArr[][] = new int[stackCount][maxPixelCount];
0790: int widthArr[] = new int[stackCount];
0791: int pixelC = 0;
0792: int stackI = 0;
0793: int pixelTotal = 0;
0794: int widthTotal = 0;
0795:
0796: while (!imageStack.empty()) {
0797: imageArr[stackI] = (int[]) imageStack.pop();
0798: widthArr[stackI] = ((Integer) widthStack.pop()).intValue();
0799: pixelTotal += widthArr[stackI] * Header.NSLOOKH /* h */;
0800: widthTotal += widthArr[stackI];
0801: stackI++;
0802: }
0803:
0804: int pixels[] = new int[pixelTotal];
0805: int pixelI = 0;
0806: int y = 0;
0807: int imageI = 0;
0808: int x = 0;
0809: try {
0810: for (y = 0; y < Header.NSLOOKH /* h */; y++) {
0811: for (imageI = 0; imageI < stackCount; imageI++) {
0812: for (x = 0; x < widthArr[imageI]; x++) {
0813: pixels[pixelI] = imageArr[imageI][(widthArr[imageI] * y)
0814: + x];
0815: pixelI++;
0816: }
0817: }
0818: }
0819: } catch (ArrayIndexOutOfBoundsException e) {
0820: System.out
0821: .println("determinImage ArrayIndexOutOfBoundsException:"
0822: + "\n"
0823: + ", x: "
0824: + x
0825: + "y: "
0826: + y
0827: + ", imageI: "
0828: + imageI
0829: + ", imageN: "
0830: + stackCount // imageN
0831: + ", imageSize.height: "
0832: + Header.NSLOOKH // imageSize.height
0833: + ", imageSize.width: "
0834: + imageSize.width
0835: + ", pixelI: "
0836: + pixelI
0837: + ", pixelCount: "
0838: + pixelCount);
0839: }
0840:
0841: return new Bitmap(pixels, widthTotal, Header.NSLOOKH);
0842: }
0843:
0844: public Image determineMacImage(BTreeNode btn, BTListItem listItem,
0845: boolean selected, boolean indent) {
0846: int imageN = (indent) ? btn.getUnaryDepth() + 2
0847: - btRooted.getUnaryDepth() : 1;
0848:
0849: int pixelI = 0;
0850: int pixels[] = new int[imageN * pixelCount];
0851: int imageArr[][] = new int[imageN][pixelCount];
0852:
0853: if (selected) {
0854: if (btn.getChild(true) == null) {
0855: imageArr[0] = spacePixels;
0856: imageArr[imageN - 1] = documentSelPixels;
0857: } else {
0858: if (listItem.getState() == BTListItem.CLOSED) {
0859: imageArr[0] = branchClosedSelPixels;
0860: } else {
0861: imageArr[0] = branchOpenSelPixels;
0862: }
0863: imageArr[imageN - 1] = folderSelPixels;
0864: }
0865: } else {
0866: if (btn.getChild(true) == null) {
0867: imageArr[0] = spacePixels;
0868: imageArr[imageN - 1] = documentPixels;
0869: } else {
0870: if (listItem.getState() == BTListItem.CLOSED) {
0871: imageArr[0] = branchClosedPixels;
0872: } else {
0873: imageArr[0] = branchOpenPixels;
0874: }
0875: imageArr[imageN - 1] = folderPixels;
0876: }
0877: }
0878:
0879: for (int i = 1; i < (imageN - 1); i++) {
0880: imageArr[i] = spacePixels;
0881: }
0882:
0883: int y = 0;
0884: int imageI = 0;
0885: int x = 0;
0886: try {
0887: for (y = 0; y < imageSize.height; y++) {
0888: for (imageI = 0; imageI < imageN; imageI++) {
0889: for (x = 0; x < imageSize.width; x++) {
0890: pixels[pixelI] = imageArr[imageI][(imageSize.width * y)
0891: + x];
0892: pixelI++;
0893: }
0894: }
0895: }
0896: } catch (ArrayIndexOutOfBoundsException e) {
0897: System.out
0898: .println("determinImage ArrayIndexOutOfBoundsException:"
0899: + "\n"
0900: + ", x: "
0901: + x
0902: + "y: "
0903: + y
0904: + ", imageI: "
0905: + imageI
0906: + ", imageN: "
0907: + imageN
0908: + ", imageSize.height: "
0909: + imageSize.height
0910: + ", imageSize.width: "
0911: + imageSize.width
0912: + ", pixelI: "
0913: + pixelI
0914: + ", pixelCount: " + pixelCount);
0915: }
0916:
0917: return new Bitmap(pixels, imageSize.width * imageN,
0918: imageSize.height);
0919: }
0920:
0921: /*----------------*/
0922: /* TextFieldOwner */
0923: /*----------------*/
0924:
0925: public TextFieldOwner owner() {
0926: return textFieldOwner;
0927: }
0928:
0929: public void setOwner(TextFieldOwner object) {
0930: textFieldOwner = object;
0931: }
0932:
0933: public void textEditingDidBegin(TextField textfield) {
0934: if (textField != textfield) {
0935: return;
0936: }
0937: if (textFieldOwner != null) {
0938: textFieldOwner.textEditingDidBegin(textfield);
0939: }
0940: }
0941:
0942: public void completeEditing() {
0943: if (textField != null) {
0944: textField.completeEditing();
0945: }
0946: }
0947:
0948: public void textEditingDidEnd(TextField textfield,
0949: int endCondition, boolean contentsChanged) {
0950: if ((textField == textfield) && (currentListItem != null)) {
0951: String s = textField.stringValue().trim();
0952: currentListItem.setTitle(s);
0953: binaryTree.currentBackup();
0954: binaryTree.setEnumeration((BTreeNode) currentListItem
0955: .data());
0956: if (s.compareTo((String) binaryTree.getKey()) != 0) {
0957: binaryTree.setKey(s);
0958: BTListItem pli = getUnaryParentItem(currentListItem);
0959: if (pli != null) {
0960: childReorganize(pli);
0961: }
0962: // SGP: else? (top unary level has mult)
0963: }
0964: binaryTree.currentRestore();
0965: if (treeViewGroup != null) {
0966: treeViewGroup.sendAction(this ,
0967: TreeViewGroup.UPDATENODE,
0968: (BTreeNode) currentListItem.data());
0969: }
0970: textField.removeFromSuperview();
0971: if (endCondition == TextFieldOwner.RETURN_KEY) {
0972: // SGP: should use a modified buttonEnablement()
0973: delBtn.setEnabled(false);
0974: newPeerBtn.setEnabled(false);
0975: newChildBtn.setEnabled(false);
0976: delBtn.setDirty(true);
0977: newPeerBtn.setDirty(true);
0978: newChildBtn.setDirty(true);
0979: }
0980: scrollGroup.scrollView().setDirty(true);
0981: }
0982:
0983: if (textFieldOwner != null) {
0984: textFieldOwner.textEditingDidEnd(textfield, endCondition,
0985: contentsChanged);
0986: }
0987: }
0988:
0989: public boolean textEditingWillEnd(TextField tf, int endCondition,
0990: boolean contentsChanged) {
0991: if ((textField == tf) && (currentListItem != null)) {
0992: if (textField != tf) {
0993: return true;
0994: }
0995: int namecount = proposedPeerNameCheck(tf.stringValue());
0996: if (tf.stringValue().equals(
0997: (String) ((BTreeNode) currentListItem.data())
0998: .getKey())) {
0999: namecount--;
1000: }
1001:
1002: // duplicate error
1003: if (namecount > 0) {
1004: String dupTitle = tf.stringValue(); // Save duplicate name for error
1005: tf.cancelEditing();
1006: if (currentListItem != null) {
1007: if (currentListItem.data() != null) {
1008: currentListItem
1009: .setTitle((String) ((BTreeNode) currentListItem
1010: .data()).getKey());
1011: }
1012:
1013: // Bringing up the alert causes the edit field to lose focus
1014: // and this method will be re-entered. To prevent this, remove
1015: // the text field and refresh the view. (MCW)
1016: tf.removeFromSuperview();
1017: listView.sizeListView();
1018: listView.setDirty(true);
1019: Alert.runAlertExternally(Alert.warningImage(),
1020: Messages.TITLE_WARNING,
1021: Messages.ERR_DUPENAME + ": " + dupTitle,
1022: Messages.OKAY, null, null);
1023: }
1024:
1025: return true;
1026: }
1027:
1028: // blank error
1029: if (tf.stringValue().compareTo("") == 0) {
1030: tf.cancelEditing();
1031: if (currentListItem != null) {
1032: if (currentListItem.data() != null) {
1033: currentListItem
1034: .setTitle((String) ((BTreeNode) currentListItem
1035: .data()).getKey());
1036: }
1037:
1038: // Bringing up the alert causes the edit field to lose focus
1039: // and this method will be re-entered. To prevent this, remove
1040: // the text field and refresh the view. (MCW)
1041: tf.removeFromSuperview();
1042: listView.sizeListView();
1043: listView.setDirty(true);
1044: Alert.runAlertExternally(Alert.warningImage(),
1045: Messages.TITLE_WARNING,
1046: Messages.ERR_BLANKNAME, Messages.OKAY,
1047: null, null);
1048: }
1049:
1050: return true;
1051: }
1052: }
1053: if (textFieldOwner != null) {
1054: return textFieldOwner.textEditingWillEnd(tf, endCondition,
1055: contentsChanged);
1056: }
1057: return true;
1058: }
1059:
1060: public void textWasModified(TextField textfield) {
1061: if (textField != textfield) {
1062: return;
1063: }
1064: setChanged();
1065: if (textFieldOwner != null) {
1066: textFieldOwner.textWasModified(textfield);
1067: }
1068:
1069: currentListItem.setTitle(textField.stringValue().trim());
1070: listView.sizeListView();
1071: textFieldSizer();
1072: if (treeViewGroup != null) {
1073: treeViewGroup.sendAction(this , TreeViewGroup.UPDATETITLE,
1074: (BTreeNode) currentListItem.data(), textField
1075: .stringValue());
1076: }
1077: }
1078:
1079: public void textFieldSizer() {
1080: Rect r = new Rect();
1081:
1082: if (currentListItem != null) {
1083: int w = currentListItem.image().width();
1084: BTreeNode btn = (BTreeNode) currentListItem.data();
1085: Size s = textField.minSize();
1086: s.width += Header.SPACEPLUSCARETWIDTH;
1087:
1088: r = listView.rectForItem(currentListItem);
1089: if (r == null) {
1090: r = new Rect(0, 0, 0, 0);
1091: r.y = Integer.MIN_VALUE;
1092: }
1093: r.x += w;
1094: r.sizeTo(s.width, s.height);
1095: textField.setBounds(r);
1096: scrollGroup.scrollView().setDirty(true);
1097: textField.setDirty(true);
1098: }
1099: }
1100:
1101: private int proposedPeerNameCheck(String name) {
1102: if (currentListItem == null) {
1103: return 0;
1104: }
1105: return proposedPeerNameCheck(name, (BTreeNode) currentListItem
1106: .data());
1107: }
1108:
1109: private int proposedPeerNameCheck(String name, BTreeNode currBtn) {
1110: if (currBtn == null) {
1111: return 0;
1112: }
1113: if (dupePeerNamesAllowed) {
1114: return 0;
1115: }
1116:
1117: binaryTree.currentBackup();
1118: binaryTree.setEnumeration(currBtn);
1119: int count = binaryTree.countPeersByKey(name, true);
1120: binaryTree.currentRestore();
1121:
1122: return count;
1123: }
1124:
1125: public void setEditListItem() {
1126: setEditListItem((BTListItem) listView.selectedItem());
1127: }
1128:
1129: public void setEditListItem(BTListItem li) {
1130: if (textField != null) {
1131: textField.completeEditing();
1132: }
1133:
1134: currentListItem = li;
1135:
1136: if ((textField != null) && (currentListItem != null)) {
1137: if (!((listView.selectedIndex() == 0) && (!editableRoot))) {
1138: listView.addSubview(textField);
1139: }
1140: textField.setStringValue(currentListItem.title());
1141: textFieldSizer();
1142: textField.selectText();
1143: }
1144: }
1145:
1146: /**
1147: * Risky, provided to nullify currentListItem during a delete.
1148: * Shouldn't be used otherwise.
1149: */
1150: public void setCurrentListItem(BTListItem li) {
1151: currentListItem = li;
1152: }
1153:
1154: /*----------------*/
1155: /* performCommand */
1156: /*----------------*/
1157:
1158: public View viewForMouse(int x, int y) {
1159: View view = super .viewForMouse(x, y);
1160:
1161: if (view == listView) {
1162: VFMPoint = convertToView(listView, x, y);
1163: }
1164:
1165: return view;
1166: }
1167:
1168: /**
1169: * Badly named, determines current images and forces redraw.
1170: * No selection occurs.
1171: */
1172: public void selectAndDraw() {
1173: selectAndDraw((BTListItem) listView.selectedItem());
1174: }
1175:
1176: /**
1177: * Badly named, determines current images for target and forces redraw.
1178: * No selection occurs.
1179: * @param listItem target ListItem
1180: */
1181: public void selectAndDraw(BTListItem listItem) {
1182: if (listItem == null) {
1183: return;
1184: }
1185:
1186: BTreeNode btn = (BTreeNode) listItem.data();
1187:
1188: listItem.setImage(determineImage(btn, listItem, false));
1189: listItem.setSelectedImage(determineImage(btn, listItem, true));
1190: listView.sizeListView();
1191: }
1192:
1193: /**
1194: * For the target item, gets the unary parent.
1195: */
1196: public BTListItem getUnaryParentItem(BTListItem listItem) {
1197: if (listItem == null) {
1198: return null;
1199: }
1200: BTreeNode btn = (BTreeNode) listItem.data();
1201: int ud = btn.getUnaryDepth();
1202:
1203: for (int i = listView.indexOfItem(listItem); i >= 0; i--) {
1204: if (((BTreeNode) listView.itemAt(i).data()).getUnaryDepth() < ud) {
1205: return (BTListItem) listView.itemAt(i);
1206: }
1207: }
1208:
1209: return null;
1210: }
1211:
1212: private BTreeNode[] getOpenChildren(BTListItem listItem) {
1213: if (listItem == null) {
1214: return new BTreeNode[0];
1215: }
1216: int ud = ((BTreeNode) listItem.data()).getUnaryDepth();
1217: BTreeNode list[] = new BTreeNode[listView.count()];
1218: int listI = 0;
1219: for (int i = listView.indexOfItem(listItem) + 1; ((i < listView
1220: .count()) && (((BTreeNode) listView.itemAt(i).data())
1221: .getUnaryDepth() > ud)); i++) {
1222: if (((BTListItem) listView.itemAt(i)).getState() == BTListItem.OPEN) {
1223: list[listI] = (BTreeNode) listView.itemAt(i).data();
1224: listI++;
1225: }
1226: }
1227: return list;
1228: }
1229:
1230: private void openChildren(BTreeNode list[]) {
1231: boolean stillStuff = true;
1232: boolean changes = true;
1233: while (stillStuff && changes) {
1234: stillStuff = false;
1235: changes = false;
1236: for (int i = 0; i < list.length; i++) {
1237: if (list[i] != null) {
1238: stillStuff = true;
1239: int j = listView.getIndexWithData(list[i]);
1240: if (j >= 0) {
1241: openItem((BTListItem) listView.itemAt(j));
1242: list[i] = null;
1243: changes = true;
1244: }
1245: }
1246: }
1247: }
1248: }
1249:
1250: protected void childReorganize() {
1251: childReorganize((BTListItem) listView.selectedItem());
1252: }
1253:
1254: protected void childReorganize(BTListItem listItem) {
1255: if (listItem == null) {
1256: return;
1257: }
1258: BTreeNode childList[] = getOpenChildren(listItem);
1259: openAndClose(listItem);
1260: openAndClose(listItem);
1261: openChildren(childList);
1262: }
1263:
1264: /**
1265: * Get the current ListItem. This isn't quite the same as
1266: * the currently selected ListItem because some actions need
1267: * to occur during transitions from the previously selected
1268: * ListItem and the currently selected ListItem.
1269: */
1270: public BTListItem getCurrentListItem() {
1271: return currentListItem;
1272: }
1273:
1274: /**
1275: * If the selected item is open it is closed, if closed it is opened.
1276: * Done twice (when open), forces the child display to be updated
1277: * which is useful when the children are modified.
1278: */
1279: protected void openAndClose() {
1280: openAndClose((BTListItem) listView.selectedItem());
1281: }
1282:
1283: /**
1284: * If the passed item is open it is closed, if closed it is opened.
1285: * Done twice (when open), forces the child display to be updated
1286: * which is useful when the children are modified.
1287: */
1288: protected void openAndClose(BTListItem listItem) {
1289: if (listItem == null) {
1290: return;
1291: }
1292:
1293: // if the node is closed, open it
1294: if (listItem.getState() == BTListItem.CLOSED) {
1295: openItem(listItem);
1296: }
1297: // if the node is open, close it
1298: else {
1299: closeItem(listItem);
1300: }
1301: }
1302:
1303: private void closeItem(BTListItem listItem) {
1304: if (listItem == null) {
1305: return;
1306: }
1307:
1308: BTreeNode btn = (BTreeNode) listItem.data();
1309: int selIndex = listView.indexOfItem(listItem);
1310: int listViewN = listView.count();
1311: int selDepth = btn.getUnaryDepth();
1312:
1313: listItem.setState(BTListItem.CLOSED);
1314: for (int i = selIndex + 1; ((i < listViewN) && (((BTreeNode) listView
1315: .itemAt(i).data()).getUnaryDepth() > selDepth)); listViewN--) {
1316: listView.removeItemAt(i);
1317: }
1318: selectAndDraw(listItem);
1319: }
1320:
1321: private void openItem(BTListItem listItem) {
1322: if (listItem == null) {
1323: return;
1324: }
1325:
1326: BTreeNode btn = (BTreeNode) listItem.data();
1327: int selIndex = listView.indexOfItem(listItem);
1328: int listViewN = listView.count();
1329: int selDepth = btn.getUnaryDepth();
1330:
1331: if ((btn.getChild(true) != null)
1332: && ((btn.getVisibility() == BTreeNode.CHILDVISIBLE) || (btn
1333: .getVisibility() == BTreeNode.OPEN))) {
1334: listItem.setState(BTListItem.OPEN);
1335: binaryTree.currentBackup();
1336: binaryTree.setEnumeration(btn);
1337: int i = selIndex;
1338: while (binaryTree.hasMoreElements()) {
1339: BTreeNode btnI = (BTreeNode) binaryTree.nextElement();
1340: int iud = btnI.getUnaryDepth();
1341: if (iud <= selDepth) {
1342: break;
1343: }
1344: if ((iud == selDepth + 1) && (btnI.display )) {
1345: i++;
1346: listView.insertItemAt(createBTListItem(btnI), i);
1347: }
1348: }
1349: binaryTree.currentRestore();
1350: }
1351: selectAndDraw(listItem);
1352: }
1353:
1354: // SGP: needs better name
1355: public void deepSix() {
1356: listView.removeAllItems();
1357: delBtn.setEnabled(false);
1358: newPeerBtn.setEnabled(false);
1359: newChildBtn.setEnabled(false);
1360: }
1361:
1362: /**
1363: * Hides the default edit buttons.
1364: * Typically used by windows supplying their own menus and
1365: * calling the button action methods directly.
1366: * Expected to be done as part of construction rather than
1367: * during display, so no setDirty() and no showEditButtons().
1368: */
1369: public void hideEditButtons() {
1370: scrollGroup.setBounds(scrollGroup.x(), newPeerBtn.y(),
1371: scrollGroup.width(), scrollGroup.height()
1372: + (scrollGroup.y() - newPeerBtn.y()));
1373: newPeerBtn.moveTo(Integer.MIN_VALUE, newPeerBtn.y());
1374: newChildBtn.moveTo(Integer.MIN_VALUE, newChildBtn.y());
1375: delBtn.moveTo(Integer.MIN_VALUE, delBtn.y());
1376: }
1377:
1378: // SGP: so if you can hide them, you can't show them :-)
1379:
1380: public void buttonEnablement() {
1381: if (!editable) {
1382: delBtn.setEnabled(false);
1383: newPeerBtn.setEnabled(false);
1384: newChildBtn.setEnabled(false);
1385: } else if ((listView.selectedIndex() == 0) && (!editableRoot)) {
1386: delBtn.setEnabled(false);
1387: newPeerBtn.setEnabled(false);
1388: newChildBtn.setEnabled(false);
1389: } else if (listView.selectedIndex() == -1) {
1390: delBtn.setEnabled(false);
1391: newPeerBtn.setEnabled(false);
1392: newChildBtn.setEnabled(false);
1393: } else if (listView.selectedIndex() == 0) {
1394: if (emptyAllowed) {
1395: delBtn.setEnabled(true);
1396: } else {
1397: delBtn.setEnabled(false);
1398: }
1399: newPeerBtn.setEnabled(false);
1400: newChildBtn.setEnabled(true);
1401: } else {
1402: delBtn.setEnabled(true);
1403: newPeerBtn.setEnabled(true);
1404: newChildBtn.setEnabled(true);
1405: }
1406: }
1407:
1408: public boolean clickCommand() {
1409: BTListItem li = (BTListItem) listView.selectedItem();
1410: boolean result = false; // Def: Node selection
1411:
1412: if (li == null) {
1413: buttonEnablement();
1414: return false;
1415: }
1416:
1417: if (((VFMPoint.x < imageSize.width) && (feel == MACFEEL))
1418: || ((VFMPoint.x < li.image().width())
1419: && (VFMPoint.x > li.image().width() - 27) // SGP
1420: && (feel == NSFEEL))) {
1421: openAndClose();
1422:
1423: if (look == NSLOOK) {
1424: doReimaging();
1425: }
1426:
1427: result = true; // Tree manipulated
1428: }
1429:
1430: if (li == null) {
1431: return result;
1432: }
1433:
1434: if (editable) {
1435: if (VFMPoint.x <= li.image().width()) {
1436: if (textField != null) {
1437: removeSubview(textField);
1438: }
1439: }
1440: }
1441: setEditListItem();
1442:
1443: selectAndDraw();
1444: buttonEnablement();
1445: return result;
1446: }
1447:
1448: public void setLauncher(Target target, String command) {
1449: launcherTarget = target;
1450: launcherCommand = command;
1451: }
1452:
1453: public void doubleClickCommand() {
1454: buttonEnablement();
1455:
1456: BTListItem listItem = (BTListItem) listView.selectedItem();
1457: if (listItem == null) {
1458: return;
1459: }
1460: BTreeNode btn = (BTreeNode) listItem.data();
1461: int selDepth = btn.getUnaryDepth();
1462:
1463: if (btRooted != null) {
1464: selDepth -= btRooted.getUnaryDepth();
1465: }
1466:
1467: if ((VFMPoint.x < (imageSize.width * (selDepth + 2)))
1468: && (VFMPoint.x > (imageSize.width * (selDepth + 1)))) {
1469: if (launcherTarget != null) {
1470: launcherTarget.performCommand(launcherCommand, btn);
1471: } else {
1472: openAndClose();
1473: }
1474: }
1475:
1476: selectAndDraw();
1477: }
1478:
1479: public void newWindow() {
1480: if (launcherTarget == null) {
1481: return;
1482: }
1483:
1484: BTListItem listItem = (BTListItem) listView.selectedItem();
1485: if (listItem == null) {
1486: return;
1487: }
1488: BTreeNode btn = (BTreeNode) listItem.data();
1489:
1490: launcherTarget.performCommand(launcherCommand, btn);
1491: }
1492:
1493: public void newChildBtnPress() {
1494: newChild(new BTreeNode(Messages.NEW, null));
1495: }
1496:
1497: public void newChild(BTreeNode newBtn) {
1498: if (currentListItem == null) {
1499: return;
1500: }
1501: setChanged();
1502:
1503: BTListItem upi = getUnaryParentItem(currentListItem);
1504: BTreeNode upiBtn = (upi == null) ? null : (BTreeNode) upi
1505: .data();
1506: BTreeNode currBtn = (BTreeNode) currentListItem.data();
1507: if (proposedPeerNameCheck(Messages.NEW, currBtn.getChild()) > 0) {
1508: Alert.runAlertExternally(Alert.warningImage(),
1509: Messages.TITLE_WARNING, Messages.ERR_DUPENAME
1510: + ": " + Messages.NEW, Messages.OKAY, null,
1511: null);
1512: return;
1513: }
1514:
1515: completeEditing();
1516: currentListItem.setState(BTListItem.OPEN);
1517:
1518: binaryTree.currentBackup();
1519: binaryTree.setEnumeration(currBtn);
1520: binaryTree.insertChild(newBtn, BinaryTree.NEXT);
1521: binaryTree.currentRestore();
1522:
1523: childReorganize(upi);
1524: BTListItem ci = (BTListItem) listView.itemForData(currBtn);
1525: BTreeNode childList[] = getOpenChildren(ci);
1526: openAndClose(ci);
1527: if (ci.getState() == BTListItem.CLOSED) {
1528: openAndClose(ci);
1529: openChildren(childList);
1530: }
1531: listView.sizeListView();
1532:
1533: BTListItem newListItem = (BTListItem) listView
1534: .itemForData(newBtn);
1535: setEditListItem(newListItem);
1536: listView.selectItem(newListItem);
1537: scrollGroup.scrollView().scrollRectToVisible(
1538: listView.rectForItem(newListItem));
1539:
1540: buttonEnablement();
1541:
1542: if (treeViewGroup != null) {
1543: treeViewGroup.sendAction(this , TreeViewGroup.ADDNODE,
1544: currBtn);
1545: }
1546: }
1547:
1548: public void newPeerBtnPress() {
1549: newPeer(new BTreeNode(Messages.NEW, null));
1550: }
1551:
1552: public void newPeer(BTreeNode newBtn) {
1553: if (currentListItem == null) {
1554: return;
1555: }
1556: setChanged();
1557: int namecount = proposedPeerNameCheck(Messages.NEW);
1558: if ((!textField.stringValue().equals(
1559: (String) ((BTreeNode) currentListItem.data()).getKey()))
1560: && (Messages.NEW
1561: .equals((String) ((BTreeNode) currentListItem
1562: .data()).getKey()))) {
1563: namecount--;
1564: }
1565: if (namecount > 0) {
1566: Alert.runAlertExternally(Alert.warningImage(),
1567: Messages.TITLE_WARNING, Messages.ERR_DUPENAME
1568: + ": " + Messages.NEW, Messages.OKAY, null,
1569: null);
1570: return;
1571: }
1572:
1573: BTListItem upi = getUnaryParentItem(currentListItem);
1574: BTreeNode currBtn = (BTreeNode) currentListItem.data();
1575: BTreeNode upiBtn = (upi == null) ? currBtn // top of tree, untested
1576: : (BTreeNode) upi.data();
1577:
1578: completeEditing();
1579:
1580: binaryTree.currentBackup();
1581: binaryTree.setEnumeration(currBtn);
1582: binaryTree.insertNext(newBtn, BinaryTree.NEXT);
1583: binaryTree.currentRestore();
1584:
1585: childReorganize(upi);
1586: listView.sizeListView();
1587:
1588: BTListItem newListItem = (BTListItem) listView
1589: .itemForData(newBtn);
1590: setEditListItem(newListItem);
1591: listView.selectItem(newListItem);
1592: scrollGroup.scrollView().scrollRectToVisible(
1593: listView.rectForItem(newListItem));
1594:
1595: buttonEnablement();
1596:
1597: if (treeViewGroup != null) {
1598: treeViewGroup.sendAction(this , TreeViewGroup.ADDNODE,
1599: upiBtn);
1600: }
1601: }
1602:
1603: public void delBtnPress() {
1604: if (currentListItem == null) {
1605: return;
1606: }
1607: setChanged();
1608: int currListIndex = listView.indexOfItem(currentListItem);
1609: BTreeNode btn = (BTreeNode) currentListItem.data();
1610: BTreeNode pbtn = btn.getParent();
1611: BTListItem pli = getUnaryParentItem(currentListItem);
1612: setCurrentListItem(null);
1613:
1614: binaryTree.currentBackup();
1615: binaryTree.setEnumeration(pbtn);
1616: if (pbtn == null) {
1617: /* SGP: only TaxonomyTreeView currently requires
1618: ** this, and since that requires that the
1619: ** binary tree be set up as part of a new
1620: ** taxonomy, overriding this anyway, we'll
1621: ** leave completion of this for another day.
1622: binaryTree = new BinaryTree( BinaryTree.DEPTHFIRST );
1623: listView.removeAllItems();
1624: if ( emptyAllowed )
1625: {
1626: btn = new BTreeNode( Messages.NEW, null );
1627: }
1628: */
1629: } else {
1630: if (pbtn.getChild() == btn) {
1631: binaryTree.createChild(btn.getNext());
1632: } else {
1633: binaryTree.createNext(btn.getNext());
1634: }
1635:
1636: if (pli == null) {
1637: listView.removeAllItems();
1638: binaryTree.currentRestore();
1639: binaryTree.resetEnumeration();
1640: binaryTree.currentBackup();
1641: } else {
1642: listView.selectItem(pli);
1643: childReorganize();
1644: }
1645: }
1646: binaryTree.currentRestore();
1647: if (treeViewGroup != null) {
1648: treeViewGroup.sendAction(this , TreeViewGroup.DELETENODE,
1649: btn);
1650: }
1651:
1652: if (currListIndex >= (listView.count() - 1)) {
1653: currListIndex = listView.count() - 1;
1654: }
1655: if (currListIndex >= 0) {
1656: listView.selectItemAt(currListIndex);
1657: }
1658: listView.sizeListView();
1659:
1660: setEditListItem((BTListItem) listView.itemAt(currListIndex));
1661: buttonEnablement();
1662: }
1663:
1664: /**
1665: * stub to override
1666: */
1667: public void saveBtnPress() {
1668: }
1669:
1670: /**
1671: * stub to override
1672: */
1673: public void cancelBtnPress() {
1674: }
1675:
1676: private void setChanged() {
1677: changed = true;
1678: }
1679:
1680: public boolean getChanged() {
1681: return changed;
1682: }
1683:
1684: public void clearChanged() {
1685: changed = false;
1686: }
1687:
1688: /**
1689: * Drag dropped notification command, sent when Category dropped.
1690: */
1691: public void setDragDroppedNotificationCommand(String cmd) {
1692: listView.setDragDroppedNotificationCommand(cmd);
1693: }
1694:
1695: /**
1696: * Drag dropped notification target, sent when Category dropped.
1697: */
1698: public void setDragDroppedNotificationTarget(Target target) {
1699: listView.setDragDroppedNotificationTarget(target);
1700: }
1701:
1702: public void performCommand(String command, Object arg) {
1703: if ("clickCommand".equals(command)) {
1704: clickCommand();
1705: } else if ("doubleClickCommand".equals(command)) {
1706: doubleClickCommand();
1707: } else if ("newWindow".equals(command)) {
1708: newWindow();
1709: } else if (Messages.CMD_NEWCHILD.equals(command)) {
1710: newChildBtnPress();
1711: } else if (Messages.CMD_NEWPEER.equals(command)) {
1712: newPeerBtnPress();
1713: } else if (Messages.CMD_DELETE.equals(command)) {
1714: delBtnPress();
1715: } else if (Messages.CMD_SAVE.equals(command)) {
1716: saveBtnPress();
1717: } else if (Messages.CMD_CANCEL.equals(command)) {
1718: cancelBtnPress();
1719: }
1720: // SGP: this appears to do nothing
1721: else if ("completeEditing".equals(command)) {
1722: completeEditing();
1723: } else if ("switchLookFeel".equals(command)) {
1724: if (look == MACLOOK) {
1725: System.out.println("Netscape Look'n'Feel");
1726: look = NSLOOK;
1727: feel = NSFEEL;
1728: } else {
1729: System.out.println("Macintosh Look'n'Feel");
1730: look = MACLOOK;
1731: feel = MACFEEL;
1732: }
1733: completeEditing();
1734: doReimaging();
1735: } else if (TreeViewGroup.UPDATETHRUTVG.equals(command)) {
1736: }
1737: }
1738: }
|