001: /**
002: * Caption: Zaval Java Resource Editor
003: * $Revision: 0.37 $
004: * $Date: 2002/03/28 9:24:42 $
005: *
006: * @author: Victor Krapivin
007: * @version: 1.3
008: *
009: * Zaval JRC Editor is a visual editor which allows you to manipulate
010: * localization strings for all Java based software with appropriate
011: * support embedded.
012: *
013: * For more info on this product read Zaval Java Resource Editor User's Guide
014: * (It comes within this package).
015: * The latest product version is always available from the product's homepage:
016: * http://www.zaval.org/products/jrc-editor/
017: * and from the SourceForge:
018: * http://sourceforge.net/projects/zaval0002/
019: *
020: * Contacts:
021: * Support : support@zaval.org
022: * Change Requests : change-request@zaval.org
023: * Feedback : feedback@zaval.org
024: * Other : info@zaval.org
025: *
026: * Copyright (C) 2001-2002 Zaval Creative Engineering Group (http://www.zaval.org)
027: *
028: * This program is free software; you can redistribute it and/or
029: * modify it under the terms of the GNU General Public License
030: * (version 2) as published by the Free Software Foundation.
031: *
032: * This program is distributed in the hope that it will be useful,
033: * but WITHOUT ANY WARRANTY; without even the implied warranty of
034: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
035: * GNU General Public License for more details.
036: *
037: * You should have received a copy of the GNU General Public License
038: * along with this program; if not, write to the Free Software
039: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
040: *
041: */package org.zaval.awt;
042:
043: import org.zaval.awt.*;
044: import java.util.*;
045: import org.zaval.awt.peer.*;
046:
047: // ========================================================================
048: // 08/08/97 Added function CAF
049: // ========================================================================
050: //
051: // public TreeNode getNode (String name)
052: // public boolean insertChild (String name, String addname)
053: // public boolean insertChild (String name, String addname, String im1, String im2)
054: // public boolean insertNext (String name, String addname)
055: // public boolean insertNext (String name, String addname, String im1, String im2)
056: // public boolean insertRoot (String addname)
057: // public boolean insertRoot (String addname, String im1, String im2)
058: // public boolean setImages (String name, String img1, String img2)
059: // public boolean setImageOpen (String name, String img)
060: // public boolean setImageClose(String name, String img)
061: // public boolean changeText (String name, String newname)
062: //
063: // ========================================================================
064: // ========================================================================
065:
066: public class LevelTree {
067: // constants for insertion
068: public static final int CHILD = 0;
069: public static final int NEXT = CHILD + 1;
070: public static final int LAST = CHILD + 2;
071:
072: public Vector e = new Vector(); // e is vector of existing nodes
073: public Vector v = new Vector(); // v is vector of viewable nodes
074: private TreeNode rootNode; // root node of tree
075: private ImageResolver imgres; // To autosetup
076:
077: private int count = 0; // Number of nodes in the tree
078: private int viewCount = 0;// Number of viewable nodes in the tree
079: // (A node is viewable if all of its
080: // parents are expanded.)
081:
082: private String treeStructure[];
083: String delim = ".";
084:
085: private String selectedNode;
086: private Hashtable nameCache = new Hashtable();
087:
088: // constructors
089: public LevelTree() {
090: count = 0;
091: }
092:
093: public LevelTree(TreeNode head) {
094: this ();
095: rootNode = head;
096: setResolver(rootNode, imgres);
097: count = 1;
098: }
099:
100: public String getNamesDelim() {
101: return delim;
102: }
103:
104: public int getViewCount() {
105: return viewCount;
106: }
107:
108: // Insert a new node relative to a node in the tree.
109: // position = CHILD inserts the new node as a child of the node
110: // position = NEXT inserts the new node as the next sibling
111: // position = PREVIOUS inserts the new node as the previous sibling
112: public void insert(TreeNode newNode, TreeNode relativeNode,
113: int position) {
114: if (newNode == null || relativeNode == null) {
115: return;
116: }
117: if (exists(relativeNode) == false) {
118: return;
119: }
120: switch (position) {
121: case CHILD:
122: addChild(newNode, relativeNode);
123: break;
124:
125: case NEXT:
126: addSibling(newNode, relativeNode);
127: break;
128:
129: case LAST:
130: addSibling(newNode, relativeNode);
131: break;
132:
133: default:
134: // invalid position
135: return;
136: }
137: setResolver(rootNode, imgres);
138: nameCache.put(newNode.text, newNode);
139: }
140:
141: public TreeNode getRootNode() {
142: return rootNode;
143: }
144:
145: public int getCount() {
146: return count;
147: }
148:
149: boolean viewable(TreeNode node) {
150: for (int i = 0; i < viewCount; i++)
151: if (node == v.elementAt(i))
152: return true;
153: return false;
154: }
155:
156: boolean viewable(String s) {
157: if (s == null)
158: return false;
159: for (int i = 0; i < viewCount; i++) {
160: TreeNode tn = (TreeNode) v.elementAt(i);
161: if (tn.text != null && s.equals(tn.text))
162: return true;
163: }
164: return false;
165: }
166:
167: public boolean exists(TreeNode node) {
168: if (nameCache.get(node.text) != null)
169: return true;
170: for (int i = 0; i < count; i++)
171: if (node == e.elementAt(i))
172: return true;
173: return false;
174: }
175:
176: public boolean exists(String s) {
177: if (s == null)
178: return false;
179: if (nameCache.get(s) != null)
180: return true;
181:
182: for (int i = 0; i < count; i++) {
183: TreeNode tn = (TreeNode) e.elementAt(i);
184: if (tn.text != null && s.equals(tn.text))
185: return true;
186: }
187: return false;
188: }
189:
190: // ========================================================================
191: // This functions will be added on caf
192: // ========================================================================
193:
194: public TreeNode getNode(String name) {
195: if (name == null)
196: return null;
197: if (nameCache.get(name) != null)
198: return (TreeNode) nameCache.get(name);
199: for (int i = 0; i < count; i++) {
200: TreeNode tn = (TreeNode) e.elementAt(i);
201: if (tn.text != null && name.equals(tn.text))
202: return tn;
203: }
204: return null;
205: }
206:
207: // ========================================================================
208:
209: public boolean insertChild(String name, String addname) {
210: return insertChild(name, addname, null, null);
211: }
212:
213: // ========================================================================
214:
215: public boolean insertChild(String name, String addname, String im1,
216: String im2) {
217: if ((name == null) || (addname == null))
218: return false;
219: TreeNode tn = getNode(name);
220: if (tn == null)
221: return false;
222: insert(new TreeNode(addname, im1, im2), tn, LevelTree.CHILD);
223: return true;
224: }
225:
226: // ========================================================================
227:
228: public boolean insertNext(String name, String addname) {
229: return insertNext(name, addname, null, null);
230: }
231:
232: // ========================================================================
233:
234: public boolean insertNext(String name, String addname, String im1,
235: String im2) {
236: if ((name == null) || (addname == null))
237: return false;
238: TreeNode tn = getNode(name);
239: TreeNode root = getRootNode();
240: if ((tn == null) || (root == null)
241: || (tn.text.equals(root.text)))
242: return false;
243: insert(new TreeNode(addname, im1, im2), tn, LevelTree.NEXT);
244: return true;
245: }
246:
247: // ========================================================================
248:
249: public boolean insertRoot(String addname) {
250: return insertRoot(addname, null, null);
251: }
252:
253: // ========================================================================
254:
255: public boolean insertRoot(String addname, String im1, String im2) {
256: if (addname == null)
257: return false;
258: if (getRootNode() == null)
259: append(new TreeNode("root"));
260: return insertChild(rootNode.text, addname, im1, im2);
261: }
262:
263: // ========================================================================
264:
265: public boolean setImages(String name, String img1, String img2) {
266: return setImageOpen(name, img1) && setImageClose(name, img2);
267: }
268:
269: // ========================================================================
270:
271: public boolean setImageOpen(String name, String img) {
272: if ((name == null) || (img == null))
273: return false;
274: TreeNode tn = getNode(name);
275: if (tn == null)
276: return false;
277: tn.setExpandedImage(img);
278: return true;
279: }
280:
281: // ========================================================================
282:
283: public boolean setImageClose(String name, String img) {
284: if ((name == null) || (img == null))
285: return false;
286: TreeNode tn = getNode(name);
287: if (tn == null)
288: return false;
289: tn.setCollapsedImage(img);
290: return true;
291: }
292:
293: // ========================================================================
294:
295: public boolean changeText(String name, String newname) {
296: if ((name == null) || (newname == null))
297: return false;
298: TreeNode tn = getNode(name);
299: tn.setText(newname);
300: return true;
301: }
302:
303: // ========================================================================
304:
305: public void setNamesDelim(String delim) {
306: this .delim = delim;
307: }
308:
309: // ========================================================================
310: // end add
311: // ========================================================================
312:
313: // add new node to level 0
314: public void append(TreeNode newNode) {
315: if (rootNode == null) {
316: rootNode = newNode;
317: rootNode.setDepth(0);
318: rootNode.setStringProperty("PATH", "");
319: e.addElement(rootNode);
320: count = 1;
321: } else {
322: addSibling(newNode, rootNode);
323: }
324: setResolver(newNode, imgres);
325: }
326:
327: void addChild(TreeNode newNode, TreeNode relativeNode) {
328: if (relativeNode.child == null) {
329: relativeNode.child = newNode;
330: newNode.parent = relativeNode;
331: newNode.setDepth(relativeNode.getDepth() + 1);
332: String prop = relativeNode.getStringProperty("PATH");
333: if (prop.length() > 0)
334: prop += delim;
335: newNode.setStringProperty("PATH", prop + newNode.text);
336: e.addElement(newNode);
337: count++;
338: } else {
339: addSibling(newNode, relativeNode.child);
340: }
341:
342: ++relativeNode.numberOfChildren;
343: setResolver(newNode, imgres);
344: }
345:
346: protected void addBefore(TreeNode whereNode, TreeNode newNode,
347: TreeNode mark) {
348: if (whereNode == null || newNode == null || mark == null)
349: return;
350:
351: TreeNode rel = whereNode;
352: if (whereNode.child == mark || whereNode.child == null) {
353: newNode.sibling = whereNode.child;
354: whereNode.child = newNode;
355: } else {
356: whereNode = whereNode.child;
357: while (whereNode.sibling != null
358: && whereNode.sibling != mark)
359: whereNode = whereNode.sibling;
360: ;
361: if (whereNode.sibling != null)
362: newNode.sibling = whereNode.sibling;
363: whereNode.sibling = newNode;
364: }
365: setResolver(newNode, imgres);
366: ++rel.numberOfChildren;
367: newNode.parent = rel;
368: newNode.setDepth(rel.getDepth() + 1);
369:
370: String prop = whereNode.getStringProperty("PATH");
371:
372: if (prop.length() > 0)
373: prop += delim;
374: newNode.setStringProperty("PATH", prop + newNode.text);
375: e.insertElementAt(newNode, e.indexOf(mark));
376: count++;
377: }
378:
379: void addSibling(TreeNode newNode, TreeNode siblingNode) {
380: TreeNode tempNode;
381: tempNode = siblingNode;
382:
383: String s = siblingNode.getStringProperty("PATH");
384: int index = s.lastIndexOf(delim);
385: if (index >= 0)
386: newNode.setStringProperty("PATH", s.substring(0, index)
387: + delim + newNode.text);
388: else
389: newNode.setStringProperty("PATH", newNode.text);
390: while (tempNode.sibling != null)
391: tempNode = tempNode.sibling;
392: tempNode.sibling = newNode;
393: newNode.parent = tempNode.parent;
394: newNode.setDepth(tempNode.getDepth());
395: e.addElement(newNode);
396: count++;
397: setResolver(newNode, imgres);
398: }
399:
400: public TreeNode remove(String s) {
401: recount();
402: for (int i = 0; i < count; i++) {
403: TreeNode tn = (TreeNode) e.elementAt(i);
404:
405: if (tn.text != null) {
406: if (s.equals(tn.text)) {
407: remove(tn);
408: return tn;
409: }
410: }
411: }
412: return null;
413: }
414:
415: public void remove(TreeNode node) {
416: if (!exists(node)) {
417: return;
418: }
419: nameCache.remove(node.text);
420:
421: // remove node and its decendents
422: if (node.parent != null) {
423: if (node.parent.child == node) {
424: if (node.sibling != null) {
425: node.parent.child = node.sibling;
426: } else {
427: node.parent.child = null;
428: node.parent.collapse();
429: }
430: } else {
431: TreeNode tn = node.parent.child;
432:
433: while (tn.sibling != node) {
434: tn = tn.sibling;
435: }
436:
437: if (node.sibling != null) {
438: tn.sibling = node.sibling;
439: } else {
440: tn.sibling = null;
441: }
442: }
443: } else {
444: if (node == rootNode) {
445: if (node.sibling == null) {
446: rootNode = null;
447: } else {
448: rootNode = node.sibling;
449: }
450: } else {
451: TreeNode tn = rootNode;
452:
453: while (tn.sibling != node) {
454: tn = tn.sibling;
455: }
456:
457: if (node.sibling != null) {
458: tn.sibling = node.sibling;
459: } else {
460: tn.sibling = null;
461: }
462: }
463: }
464:
465: recount();
466: }
467:
468: private void recount() {
469: count = 0;
470: e = new Vector();
471: nameCache = new Hashtable();
472:
473: if (rootNode != null) {
474: rootNode.depth = 0;
475: traverse(rootNode);
476: }
477: }
478:
479: private void traverse(TreeNode node) {
480: count++;
481: e.addElement(node);
482: nameCache.put(node.text, node);
483:
484: if (node.child != null) {
485: node.child.depth = node.depth + 1;
486: traverse(node.child);
487: }
488: if (node.sibling != null) {
489: node.sibling.depth = node.depth;
490: traverse(node.sibling);
491: }
492: }
493:
494: public void resetVector() {
495: // Traverses tree to put nodes into vector v
496: // for internal processing. Depths of nodes are set,
497: // and viewCount and viewWidest is set.
498: v = new Vector(count);
499: // nameCache = new Hashtable();
500:
501: if (count < 1) {
502: viewCount = 0;
503: return;
504: }
505: rootNode.depth = 0;
506: vectorize(rootNode.child);
507: viewCount = v.size();
508: }
509:
510: private void vectorize(TreeNode node) {
511: if (node == null)
512: return;
513: nameCache.put(node.text, node);
514:
515: if (!node.hidden) {
516: v.addElement(node);
517: if (node.isExpanded()) {
518: if (node.child != null) {
519: node.child.depth = node.depth + 1;
520: vectorize(node.child);
521: }
522: }
523: }
524:
525: if (node.sibling != null) {
526: node.sibling.depth = node.depth;
527: vectorize(node.sibling);
528: }
529: }
530:
531: public void setTreeStructure(String s[]) {
532: rootNode = null;
533: treeStructure = s;
534: try {
535: parseTreeStructure();
536: } catch (InvalidTreeNodeException e) {
537: System.out.println(e);
538: }
539: }
540:
541: public String[] getTreeStructure() {
542: return (treeStructure);
543: }
544:
545: private void parseTreeStructure() throws InvalidTreeNodeException {
546: String tempStructure[] = null;
547: String entry = null;
548: TreeNode node;
549:
550: tempStructure = treeStructure;
551:
552: //entry = tempStructure[0];
553:
554: // if(findLastPreSpace(entry) > -1)
555: // {
556: // throw new InvalidTreeNodeException();
557: // }
558:
559: // node = new TreeNode(entry.trim());
560: // node.setDepth(0);
561: // append(node);
562:
563: node = new TreeNode("root");
564: node.setDepth(0);
565: append(node);
566:
567: for (int i = 0; i < tempStructure.length; i++) {
568: TreeNode currentNode;
569: int indentLevel;
570:
571: entry = tempStructure[i];
572: indentLevel = findLastPreSpace(entry) + 1;
573:
574: if (indentLevel == -1) {
575: throw new InvalidTreeNodeException();
576: }
577:
578: currentNode = rootNode;
579:
580: for (int j = 1; j < indentLevel; j++) {
581: TreeNode tempNode;
582: int numberOfChildren;
583:
584: numberOfChildren = currentNode.numberOfChildren;
585: tempNode = null;
586:
587: if (numberOfChildren > 0) {
588: tempNode = currentNode.child;
589:
590: while (tempNode.sibling != null) {
591: tempNode = tempNode.sibling;
592: }
593: }
594:
595: if (tempNode != null) {
596: currentNode = tempNode;
597: } else {
598: break;
599: }
600: }
601:
602: int diff;
603:
604: diff = indentLevel - currentNode.getDepth();
605:
606: if (diff > 1) {
607: throw new InvalidTreeNodeException();
608: }
609:
610: node = new TreeNode(entry.trim());
611: node.setDepth(indentLevel);
612:
613: if (diff == 1) {
614: insert(node, currentNode, CHILD);
615: } else {
616: insert(node, currentNode, NEXT);
617: }
618: }
619: // topVisibleNode = rootNode.child;
620: }
621:
622: private int findLastPreSpace(String s) {
623: int length;
624:
625: length = s.length();
626:
627: if (s.charAt(0) != ' ' && s.charAt(0) != '\t') {
628: return 0;
629: }
630:
631: for (int i = 1; i < length; i++) {
632: if (s.charAt(i) != ' ' && s.charAt(i) != '\t') {
633: return i;
634: }
635: }
636:
637: return -1;
638: }
639:
640: public void setResolver(ImageResolver imgres) {
641: this .imgres = imgres;
642: TreeNode t = getRootNode();
643: setResolver(t, imgres);
644: }
645:
646: private void setResolver(TreeNode t, ImageResolver imgres) {
647: if (t != null)
648: t.setResolver(imgres);
649: int i;
650: for (i = 0; i < e.size(); ++i) {
651: TreeNode c = (TreeNode) e.elementAt(i);
652: c.setResolver(imgres);
653: }
654: }
655:
656: public void show(String name) {
657: TreeNode t = getNode(name);
658: if (t != null)
659: t.setHide(false);
660: }
661:
662: public void hide(String name) {
663: TreeNode t = getNode(name);
664: if (t != null)
665: t.setHide(true);
666: }
667:
668: public void setCaption(String name, String caption) {
669: TreeNode t = getNode(name);
670: if (t == null)
671: return;
672: t.setCaption(caption);
673: }
674:
675: public void openNode(String name) {
676: TreeNode t = getNode(name);
677: if (t == null)
678: return;
679: if (t.isExpandable() && !t.isExpanded())
680: t.toggle();
681: }
682:
683: public void closeNode(String name) {
684: TreeNode t = getNode(name);
685: if (t == null)
686: return;
687: if (t.isExpandable() && t.isExpanded())
688: t.toggle();
689: }
690:
691: public void toggleNode(String name) {
692: TreeNode t = getNode(name);
693: if (t == null)
694: return;
695: if (t.isExpandable())
696: t.toggle();
697: }
698:
699: public boolean isHidden(String name) {
700: TreeNode t = getNode(name);
701: if (t == null)
702: return false;
703: return t.getHide();
704: }
705:
706: // ========================================================================
707:
708: public void expandAll() {
709: recount();
710: if (e == null)
711: return;
712: for (int i = 0; i < e.size(); i++) {
713: TreeNode tn = (TreeNode) e.elementAt(i);
714: tn.expand();
715: }
716: }
717:
718: public void collapseAll() {
719: recount();
720: if (e == null)
721: return;
722: for (int i = 0; i < e.size(); i++) {
723: TreeNode tn = (TreeNode) e.elementAt(i);
724: tn.collapse();
725: }
726: }
727:
728: // ========================================================================
729:
730: public TreeNode findNode(String name, String d) {
731: recount();
732:
733: TreeNode r = getRootNode();
734: if (r == null)
735: return null;
736:
737: TreeNode ch = r.child;
738: StringTokenizer st = new StringTokenizer(name, d);
739:
740: if (!st.hasMoreElements())
741: return null;
742:
743: String n = (String) st.nextElement();
744: while (ch != null) {
745: if (ch.caption != null && ch.caption.equalsIgnoreCase(n)) {
746: if (!st.hasMoreElements())
747: return ch;
748: else {
749: n = (String) st.nextElement();
750: ch = ch.child;
751: }
752: } else
753: ch = ch.sibling;
754: }
755: return null;
756: }
757:
758: public void view(TreeNode r, String s) {
759: recount();
760: if (r == null)
761: return;
762:
763: System.out.println(s + r.caption);
764: view(r.child, s + " ");
765: view(r.sibling, s);
766: }
767:
768: // ========================================================================
769:
770: public TreeNode getNode2(String name) {
771: recount();
772: StringTokenizer st = new StringTokenizer(name, this .delim);
773: TreeNode parent = null;
774: if (st.hasMoreElements()) {
775: parent = getNode(st.nextToken());
776: } else
777: return null;
778: while (st.hasMoreElements()) {
779: String childName = st.nextToken();
780: TreeNode child = getChild(parent, childName);
781: if (child == null)
782: return null;
783: parent = child;
784: }
785: return parent;
786: }
787:
788: // ========================================================================
789:
790: protected int getNumChild(TreeNode parent) {
791: recount();
792: if (parent == null)
793: return -1;
794: TreeNode next = parent.child;
795: int count = 0;
796: while (next != null) {
797: count++;
798: next = next.sibling;
799: }
800: return count;
801: }
802:
803: // ========================================================================
804:
805: protected TreeNode getChild(TreeNode parent, String nameChild) {
806: recount();
807: if (parent == null || parent.child == null || nameChild == null)
808: return null;
809: int size = getNumChild(parent);
810: TreeNode next = parent.child;
811: for (int i = 0; i < size; i++) {
812: if (nameChild.equalsIgnoreCase(next.getText()))
813: return next;
814: next = next.sibling;
815: }
816: return null;
817: }
818:
819: // ========================================================================
820:
821: public TreeNode[] enumChild(String name) {
822: recount();
823: StringTokenizer st = new StringTokenizer(name, this .delim);
824: TreeNode parent = null;
825: if (st.hasMoreElements())
826: parent = getNode(st.nextToken());
827: while (st.hasMoreElements()) {
828: String childName = st.nextToken();
829: TreeNode child = getChild(parent, childName);
830: if (child == null)
831: return null;
832: parent = child;
833: }
834: return enumChild(parent);
835: }
836:
837: // ========================================================================
838:
839: public TreeNode[] enumChild(TreeNode tn) {
840: recount();
841: if (tn == null || tn.child == null)
842: return null;
843: int size = getNumChild(tn);
844: TreeNode tns[] = new TreeNode[size];
845: TreeNode next = tn.child;
846: for (int i = 0; i < size; i++) {
847: tns[i] = next;
848: next = next.sibling;
849: }
850: return tns;
851: }
852:
853: public void insertNode(String top, String news, String before) {
854: TreeNode a = top == null ? rootNode : getNode(top);
855: TreeNode b = new TreeNode(news);
856: TreeNode c = getNode(before);
857: addBefore(a, b, c);
858: }
859: }
|