001: /*
002: * GNetWatch
003: * Copyright 2006, 2007 Alexandre Fenyo
004: * gnetwatch@fenyo.net
005: *
006: * This file is part of GNetWatch.
007: *
008: * GNetWatch is free software; you can redistribute it and/or modify
009: * it under the terms of the GNU General Public License as published by
010: * the Free Software Foundation; either version 2 of the License, or
011: * (at your option) any later version.
012: *
013: * GNetWatch is distributed in the hope that it will be useful,
014: * but WITHOUT ANY WARRANTY; without even the implied warranty of
015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
016: * GNU General Public License for more details.
017: *
018: * You should have received a copy of the GNU General Public License
019: * along with GNetWatch; if not, write to the Free Software
020: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
021: */
022:
023: package net.fenyo.gnetwatch.GUI;
024:
025: import net.fenyo.gnetwatch.*;
026: import net.fenyo.gnetwatch.activities.*;
027: import net.fenyo.gnetwatch.targets.*;
028:
029: import org.apache.commons.logging.Log;
030: import org.apache.commons.logging.LogFactory;
031:
032: import java.net.*;
033: import java.util.*;
034:
035: import org.eclipse.swt.*;
036: import org.eclipse.swt.widgets.*;
037: import org.eclipse.swt.layout.*;
038: import org.eclipse.swt.custom.*;
039: import org.eclipse.swt.events.*;
040: import org.eclipse.swt.graphics.*;
041:
042: /**
043: * Class derivated from VisualElement can be displayed in the main tree of the GNetWatch GUI.
044: * @author Alexandre Fenyo
045: * @version $Id: VisualElement.java,v 1.37 2007/03/12 05:04:15 fenyo Exp $
046: */
047:
048: // pour la synchro : ne pas s'appuyer sur le fait qu'on fait qqchose dans thread GUI car il y a pas
049: // forcément un thread GUI
050: public class VisualElement {
051: private static Log log = LogFactory.getLog(VisualElement.class);
052:
053: // Since many classes may run in a VM without a GUI (GNetWatch server mode),
054: // we do not instanciate at startup the private fields to save memory & CPU.
055:
056: // initialized protects agains two initializations at the same time
057: private Boolean initialized = false;
058: private GUI gui = null;
059:
060: private Boolean disposed;
061:
062: private java.util.List<TreeItem> treeItems = null;
063: private java.util.List<VisualElement> children = null;
064: private java.util.List<VisualElement> parents = null;
065:
066: private String item = null;
067: private String type = null;
068: private String description = null;
069: private Image image = null;
070:
071: private boolean is_selected = false;
072:
073: private int progress = 0;
074:
075: /**
076: * Constructor.
077: * @param none.
078: */
079: // GUI & main thread
080: public VisualElement() {
081: }
082:
083: /**
084: * Initializes this element.
085: * @param gui current GUI instance.
086: * @return void.
087: */
088: // We do not make this job at construction time since an object that is derived
089: // from a VisualElement may never be seen (background mode without GUI).
090: // main, Queue & GUI threads
091: // sync path: initialize() << initialized
092: protected void initialize(final GUI gui) {
093: synchronized (initialized) {
094: if (initialized == false) {
095: this .gui = gui;
096: if (item == null)
097: item = "uninitialized";
098: if (type == null)
099: type = "";
100: if (description == null)
101: description = "";
102: treeItems = new LinkedList<TreeItem>();
103: parents = new LinkedList<VisualElement>();
104: children = new LinkedList<VisualElement>();
105: initialized = true;
106: disposed = false;
107: }
108: // needed when the text fields are set before a GUI is defined
109: else if (this .gui == null)
110: this .gui = gui;
111: }
112: }
113:
114: /**
115: * Expands or merge the associated tree items.
116: * @param doit true to expand.
117: * @return void.
118: */
119: public void expandTreeItems(final boolean doit) {
120: for (final TreeItem item : treeItems)
121: item.setExpanded(doit);
122: }
123:
124: /**
125: * Checks that this element is disposed.
126: * @param none.
127: * @return boolean true if this element is disposed.
128: */
129: public boolean isDisposed() {
130: return disposed;
131: }
132:
133: /**
134: * Returns the current GUI instance.
135: * @param none.
136: * @return GUI current GUI instance.
137: */
138: // Queue & GUI threads
139: // could be any thread
140: final protected GUI getGUI() {
141: return gui;
142: }
143:
144: /**
145: * Sets the "exec" icon to this element.
146: * @param none.
147: * @return void.
148: */
149: public void setImageExec() {
150: setImage(getGUI().getImageExec());
151: }
152:
153: /**
154: * Sets the "folder" icon to this element.
155: * @param none.
156: * @return void.
157: */
158: public void setImageFolder() {
159: setImage(getGUI().getImageFolder());
160: }
161:
162: /**
163: * Sets the "oscilloscope" icon to this element.
164: * @param none.
165: * @return void.
166: */
167: public void setImageOscillo() {
168: setImage(getGUI().getImageOscillo());
169: }
170:
171: /**
172: * Sets the "multirow" icon to this element.
173: * @param none.
174: * @return void.
175: */
176: public void setImageMultiRow() {
177: setImage(getGUI().getImageMultiRow());
178: }
179:
180: /**
181: * Sets the "watch" icon to this element.
182: * @param none.
183: * @return void.
184: */
185: public void setImageWatch() {
186: setImage(getGUI().getImageWatch());
187: }
188:
189: /**
190: * Sets the "IPv4 host" icon to this element.
191: * @param none.
192: * @return void.
193: */
194: public void setImageHost() {
195: setImage(getGUI().getImageHost());
196: }
197:
198: /**
199: * Sets the "IPv6 host" icon to this element.
200: * @param none.
201: * @return void.
202: */
203: public void setImageHost6() {
204: setImage(getGUI().getImageHost6());
205: }
206:
207: /**
208: * Sets the "inteface" icon to this element.
209: * @param none.
210: * @return void.
211: */
212: public void setImageInterface() {
213: setImage(getGUI().getImageInterface());
214: }
215:
216: /**
217: * Sets the "queue" icon to this element.
218: * @param none.
219: * @return void.
220: */
221: public void setImageQueue() {
222: setImage(getGUI().getImageQueue());
223: }
224:
225: /**
226: * Sets the "network" icon to this element.
227: * @param none.
228: * @return void.
229: */
230: public void setImageNetwork() {
231: setImage(getGUI().getImageNetwork());
232: }
233:
234: /**
235: * Sets the "snmp ipv4 host" icon to this element.
236: * @param none.
237: * @return void.
238: */
239: public void setImageHostSNMP() {
240: setImage(getGUI().getImageHostSNMP());
241: }
242:
243: /**
244: * Sets the "snmp ipv6 host" icon to this element.
245: * @param none.
246: * @return void.
247: */
248: public void setImageHost6SNMP() {
249: setImage(getGUI().getImageHost6SNMP());
250: }
251:
252: /**
253: * Returns the list of tree items that represent this element.
254: * @param none.
255: * @return java.util.List<TreeItem> list of tree items.
256: */
257: // GUI thread
258: protected java.util.List<TreeItem> getTreeItems() {
259: return treeItems;
260: }
261:
262: /**
263: * Checks that a tree item represents this element.
264: * @param item tree item.
265: * @return boolean true if this tree item represents this element.
266: */
267: protected boolean isThisOurTreeItem(final TreeItem item) {
268: return treeItems.contains(item);
269: }
270:
271: /**
272: * Adds a tree item to represent this element.
273: * @param treeItem tree item to add.
274: * @return void.
275: */
276: // GUI thread
277: private void addTreeItem(final TreeItem treeItem) {
278: treeItem.setData(VisualElement.class.toString(), this );
279: if (image != null)
280: treeItem.setImage(image);
281: else
282: treeItem.setImage(gui.getImageFolder());
283: treeItems.add(treeItem);
284: treeItem.setText(new String[] { item, type, description });
285: }
286:
287: /**
288: * Recursively duplicates this element and its descendants under each of the destination tree items.
289: * @param destination_tree_items destination tree items.
290: * @return void.
291: */
292: private void duplicateTreeItem(
293: final java.util.List<TreeItem> destination_tree_items) {
294: final java.util.List<TreeItem> new_tree_items = new LinkedList<TreeItem>();
295:
296: for (final TreeItem destination_tree_item : destination_tree_items) {
297: final TreeItem my_tree_item_copy = new TreeItem(
298: destination_tree_item, SWT.NONE);
299: new_tree_items.add(my_tree_item_copy);
300: addTreeItem(my_tree_item_copy);
301: }
302:
303: for (final VisualElement child : children)
304: child.duplicateTreeItem(new_tree_items);
305: }
306:
307: /**
308: * Attaches this element to the root of a tree.
309: * @param gui current GUI instance.
310: * @param parent root of the destination tree.
311: * @return void.
312: */
313: // GUI thread
314: protected void setParent(final GUI gui, final Tree parent) {
315: initialize(gui);
316: addTreeItem(new TreeItem(parent, SWT.NONE));
317: }
318:
319: /**
320: * Attaches this item under another element.
321: * @param gui current GUI instance.
322: * @param parent parent element.
323: * @return void.
324: */
325: // GUI thread
326: public void setParent(final GUI gui, final VisualElement parent) {
327: initialize(gui);
328:
329: duplicateTreeItem(parent.getTreeItems());
330:
331: parents.add(parent);
332: parent.addChild(this );
333: }
334:
335: /**
336: * Recursively detaches an item from this element and its descendants.
337: * @param item item to detach.
338: * @return void.
339: */
340: private void disposeSubItems(final TreeItem item) {
341: for (final VisualElement child : children)
342: for (final TreeItem child_item : new LinkedList<TreeItem>(
343: child.getTreeItems()))
344: if (item.equals(child_item.getParentItem()))
345: child.disposeSubItems(child_item);
346: item.dispose();
347: treeItems.remove(item);
348: }
349:
350: /**
351: * Detaches this element from one of its parents.
352: * @param parent parent.
353: * @return void.
354: */
355: private void unsetParent(final VisualElement parent) {
356: parent.getChildren().remove(this );
357: parents.remove(parent);
358:
359: for (final TreeItem item : new LinkedList<TreeItem>(treeItems))
360: if (parent.isThisOurTreeItem(item.getParentItem()))
361: disposeSubItems(item);
362:
363: if (parents.size() == 0)
364: disposed();
365: }
366:
367: /**
368: * Adds a sub element.
369: * @param child element to add.
370: * @return void.
371: */
372: // GUI thread
373: private void addChild(VisualElement child) {
374: children.add(child);
375: }
376:
377: /**
378: * Returns children elements.
379: * @param none.
380: * @return java.util.List<VisualElement> children.
381: */
382: // GUI thread
383: public java.util.List<VisualElement> getChildren() {
384: return children;
385: }
386:
387: /**
388: * Returns parents of this element.
389: * @return java.util.List<VisualElement> parents.
390: */
391: public java.util.List<VisualElement> getParents() {
392: return parents;
393: }
394:
395: /**
396: * Checks that the parameter is a children.
397: * @param elt element to check.
398: * @return true if the parameter is a children.
399: */
400: // GUI thread
401: public boolean contains(final VisualElement elt) {
402: return children.contains(elt);
403: }
404:
405: /**
406: * Updates the displayed text (item name) of this element.
407: * @param none.
408: * @return void.
409: */
410: // main, Queue & GUI threads
411: private void updateText() {
412: initialize(null);
413:
414: final Runnable r = new Runnable() {
415: public void run() {
416: try {
417: final Object sync = (gui != null) ? gui.sync_tree
418: : new Object();
419: synchronized (sync) {
420: for (final TreeItem tree_item : treeItems)
421: if (tree_item != null)
422: tree_item.setText(new String[] { item,
423: type, description });
424: }
425: } catch (final SWTException ex) {
426: // widget is disposed
427: }
428: }
429: };
430:
431: if (gui != null)
432: gui.asyncExecIfNeeded(r);
433: else
434: r.run();
435: }
436:
437: /**
438: * Updates the displayed icon of this element.
439: * @param none.
440: * @return void.
441: */
442: // GUI thread
443: private void updateImage() {
444: initialize(null);
445:
446: final Runnable r = new Runnable() {
447: public void run() {
448: try {
449: synchronized (gui.sync_tree) {
450: for (final TreeItem tree_item : treeItems)
451: if (tree_item != null)
452: tree_item.setImage(image);
453: }
454: } catch (final SWTException ex) {
455: // widget is disposed
456: }
457: }
458: };
459:
460: if (gui != null)
461: gui.asyncExecIfNeeded(r);
462: else
463: r.run();
464: }
465:
466: /**
467: * Sets the item name (displayed text).
468: * @param item item name.
469: * @return void.
470: */
471: // main, Queue & GUI threads
472: protected void setItem(final String item) {
473: this .item = item;
474: updateText();
475: }
476:
477: /**
478: * Returns the item name.
479: * @param none.
480: * @return void.
481: */
482: public String getItem() {
483: return item;
484: }
485:
486: /**
487: * Sets the displayed type.
488: * @param type type to display.
489: * @return void.
490: */
491: // main, Queue & GUI threads
492: public void setType(final String type) {
493: this .type = type;
494: updateText();
495: }
496:
497: /**
498: * Sets the description.
499: * @param description description.
500: * @return void.
501: */
502: // main, Queue & GUI threads
503: public void setDescription(final String description) {
504: this .description = description;
505: updateText();
506: }
507:
508: /**
509: * Sets the icon.
510: * @param image icon.
511: * @return void.
512: */
513: // GUI thread
514: protected void setImage(final Image image) {
515: initialize(null);
516: this .image = image;
517: updateImage();
518: }
519:
520: /**
521: * Called when selected by the user.
522: * @param none.
523: * @return void.
524: */
525: // GUI thread
526: public void informSelected() {
527: }
528:
529: /**
530: * Called when disposed.
531: * @param none.
532: * @return void.
533: */
534: // GUI thread
535: protected void disposed() {
536: disposed = true;
537: }
538:
539: /**
540: * Gets sub elements of a given type.
541: * @param clazz type.
542: * @param elts list that will be updated.
543: * @return void.
544: */
545: private void getSubElements(final Class clazz,
546: final java.util.List<VisualElement> elts) {
547: for (final VisualElement elt : getChildren())
548: elt.getSubElements(clazz, elts);
549: if (clazz.isInstance(this ))
550: elts.add(this );
551: }
552:
553: /**
554: * Gets sub elements of a given type.
555: * @param clazz type.
556: * @return java.util.List<VisualElement> elts list that will be updated.
557: */
558: // les éléments sont retournés tels que les plus bas dans l'arbre sont après ceux plus haut
559: public java.util.List<VisualElement> getSubElements(
560: final Class clazz) {
561: final java.util.List<VisualElement> elts = new java.util.LinkedList<VisualElement>();
562: getSubElements(clazz, elts);
563: return elts;
564: }
565:
566: /**
567: * Gets sub elements of a given type.
568: * @param clazz type.
569: * @return java.util.List<VisualElement> elts list that will be updated.
570: */
571: // les éléments sont retournés tels que les plus bas dans l'arbre sont après ceux plus haut
572: static public java.util.List<VisualElement> getSubElements(
573: final TreeItem item, final Class clazz) {
574: return ((VisualElement) item.getData(VisualElement.class
575: .toString())).getSubElements(clazz);
576: }
577:
578: /**
579: * Returns every ascendant of this element, restricted to a given type.
580: * @param clazz type.
581: * @param elts elts list that will be updated.
582: */
583: private void getAllParents(final Class clazz,
584: final java.util.List<VisualElement> elts) {
585: for (final VisualElement elt : getParents())
586: elt.getAllParents(clazz, elts);
587: if (clazz.isInstance(this ))
588: elts.add(this );
589: }
590:
591: /**
592: * Returns every ascendant of this element, restricted to a given type.
593: * @param clazz type.
594: * @return java.util.List<VisualElement> elts list that will be updated to give the results.
595: */
596: public java.util.List<VisualElement> getAllParents(final Class clazz) {
597: final java.util.List<VisualElement> elts = new java.util.LinkedList<VisualElement>();
598: getAllParents(clazz, elts);
599: return elts;
600: }
601:
602: /**
603: * Checks that the parameter can be attached to this element.
604: * @param visual_element parameter to check.
605: * @return true if the parameter can be attached to this element.
606: */
607: public boolean canManageThisChild(final VisualElement visual_element) {
608: return true;
609: }
610:
611: /**
612: * Builds the subgraph rooted at the parent parameter.
613: * @param parent root of the subgraph.
614: * @param graph empty graph that will be updated to give the results.
615: * @return void.
616: */
617: private void getSubGraph(
618: final VisualElement parent,
619: final java.util.List<Pair<VisualElement, VisualElement>> graph) {
620: for (final VisualElement child : children)
621: child.getSubGraph(this , graph);
622: final Pair<VisualElement, VisualElement> link = new Pair<VisualElement, VisualElement>(
623: this , parent);
624: if (!graph.contains(link))
625: graph.add(new Pair<VisualElement, VisualElement>(this ,
626: parent));
627: }
628:
629: /**
630: * Builds the subgraph rooted at the parent parameter.
631: * @param parent root of the subgraph.
632: * @return java.util.List<Pair<VisualElement, VisualElement>> resulting graph.
633: */
634: private java.util.List<Pair<VisualElement, VisualElement>> getSubGraph(
635: final VisualElement parent) {
636: final java.util.List<Pair<VisualElement, VisualElement>> graph = new LinkedList<Pair<VisualElement, VisualElement>>();
637:
638: getSubGraph(parent, graph);
639: return graph;
640: }
641:
642: /**
643: * Builds the subgraph rooted at the parent parameter, but not containing some links of another graph.
644: * @param parent root of the subgraph.
645: * @param graph empty graph that will be updated to give the results.
646: * @param except_links another graph.
647: * @return void.
648: */
649: private void getSubGraphExceptLinks(
650: final VisualElement parent,
651: final java.util.List<Pair<VisualElement, VisualElement>> graph,
652: final java.util.List<Pair<VisualElement, VisualElement>> except_links) {
653: for (final VisualElement child : children)
654: if (!except_links
655: .contains(new Pair<VisualElement, VisualElement>(
656: child, this )))
657: child.getSubGraphExceptLinks(this , graph, except_links);
658:
659: final Pair<VisualElement, VisualElement> link = new Pair<VisualElement, VisualElement>(
660: this , parent);
661: if (!graph.contains(link))
662: graph.add(link);
663: }
664:
665: /**
666: * Builds the subgraph rooted at the parent parameter, but not containing some links of another graph.
667: * @param parent root of the subgraph.
668: * @param graph empty graph that will be updated to give the results.
669: * @return java.util.List<Pair<VisualElement, VisualElement>> resulting graph.
670: */
671: private java.util.List<Pair<VisualElement, VisualElement>> getSubGraphExceptLinks(
672: final VisualElement parent,
673: final java.util.List<Pair<VisualElement, VisualElement>> except_links) {
674: final java.util.List<Pair<VisualElement, VisualElement>> graph = new LinkedList<Pair<VisualElement, VisualElement>>();
675:
676: getSubGraphExceptLinks(parent, graph, except_links);
677: return graph;
678: }
679:
680: /**
681: * Detaches this element from one of its parents and removes children that have become orphan.
682: * @param visual_parent parent.
683: * @return void.
684: */
685: public void removeVisualElements(final VisualElement visual_parent) {
686: removeVisualElements(visual_parent, false);
687: }
688:
689: /**
690: * Detaches this element from one of its parents and removes children that have become orphan.
691: * @param visual_parent parent.
692: * @param bypass bypass some verifications.
693: * @return void.
694: */
695: private void removeVisualElements(
696: final VisualElement visual_parent, final boolean bypass) {
697: if (bypass == false) {
698: if (equals(gui.getVisualTransient()))
699: return;
700: if (equals(gui.getVisualThisHost()))
701: return;
702: if (equals(gui.getVisualTransientAll()))
703: return;
704: if (equals(gui.getVisualTransientNetworks()))
705: return;
706: if (visual_parent.equals(gui.getVisualThisHost()))
707: return;
708: if (visual_parent.equals(gui.getVisualTransientAll()))
709: return;
710: if (visual_parent.equals(gui.getVisualTransientNetworks()))
711: return;
712: }
713:
714: final java.util.List<Pair<VisualElement, VisualElement>> subgraph = getSubGraph(visual_parent);
715:
716: final java.util.List<Pair<VisualElement, VisualElement>> except_links = new LinkedList<Pair<VisualElement, VisualElement>>();
717: except_links.add(new Pair<VisualElement, VisualElement>(this ,
718: visual_parent));
719:
720: final java.util.List<Pair<VisualElement, VisualElement>> graph = gui
721: .getVisualTransient().getSubGraphExceptLinks(null,
722: except_links);
723:
724: GenericTools.substractGraph(subgraph, graph);
725:
726: for (final Pair<VisualElement, VisualElement> p : subgraph)
727: p.former().unsetParent(p.latter());
728:
729: for (final VisualElement host : new LinkedList<VisualElement>(
730: gui.getVisualTransientAll().getChildren()))
731: if (host.getParents().size() == 1)
732: host.removeVisualElements(gui.getVisualTransientAll(),
733: true);
734: }
735:
736: /**
737: * Sets the progress bar position.
738: * @param progress position.
739: * @return void.
740: */
741: public void setProgress(final int progress) {
742: this .progress = progress;
743: if (is_selected == true && gui != null)
744: gui.setProgress(progress);
745: }
746:
747: /**
748: * Gets the progress bar position for this visual element.
749: * @param none.
750: * @return progress position.
751: */
752: public int getProgress() {
753: return progress;
754: }
755:
756: /**
757: * Called when this element has been selected.
758: * @param none.
759: * @return void.
760: */
761: public void selected() {
762: is_selected = true;
763: }
764:
765: /**
766: * Called when this element has been unselected.
767: * @param none.
768: * @return void.
769: */
770: public void unselected() {
771: is_selected = false;
772: }
773: }
|