All Downloads are FREE. Search and download functionalities are using the official Maven repository.

eu.webtoolkit.jwt.WTreeNode Maven / Gradle / Ivy

There is a newer version: 3.2.0
Show newest version
/*
 * Copyright (C) 2009 Emweb bvba, Leuven, Belgium.
 *
 * See the LICENSE file for terms of use.
 */
package eu.webtoolkit.jwt;

import java.util.*;
import java.util.regex.*;
import java.io.*;
import java.lang.ref.*;
import java.util.concurrent.locks.ReentrantLock;
import javax.servlet.http.*;
import javax.servlet.*;
import eu.webtoolkit.jwt.*;
import eu.webtoolkit.jwt.chart.*;
import eu.webtoolkit.jwt.utils.*;
import eu.webtoolkit.jwt.servlet.*;

/**
 * A single node in a tree.
 * 

* * A tree list is constructed by combining several tree node objects in a tree * hierarchy, by passing the parent tree node as the last argument in the child * node constructor, or by using {@link WTreeNode#addChildNode(WTreeNode node) * addChildNode()}, to add a child to its parent. *

* Each tree node has a label, and optionally a label icon pair. The icon pair * offers the capability to show a different icon depending on the state of the * node (expanded or collapsed). When the node has any children, a child count * may be displayed next to the label using * {@link WTreeNode#setChildCountPolicy(WTreeNode.ChildCountPolicy policy) * setChildCountPolicy()}. *

* Expanding a tree node it will collapse all its children, so that a user may * collapse/expand a node as a short-cut to collapsing all children. *

* The treenode provides several policies to communicate the current contents of * the tree to the client (if possible): *

    *
  • * {@link WTreeNode.LoadPolicy#PreLoading}: the entire tree is transmitted to * the client, and all tree navigation requires no further communication.
  • *
  • * {@link WTreeNode.LoadPolicy#LazyLoading}: only the minimum is transmitted to * the client. When expanding a node for the first time, only then it is * transmitted to the client, and this may thus have some latency.
  • *
  • * {@link WTreeNode.LoadPolicy#NextLevelLoading}: all leafs of visible children * are transmitted, but not their children. This provides a good trade-off * between bandwith use and interactivity, since expanding any tree node will * happen instantly, and at the same time trigger some communication in the * back-ground to load the next level of invisible nodes.
  • *
*

* The default policy is {@link WTreeNode.LoadPolicy#LazyLoading}. Another load * policy may be specified using * {@link WTreeNode#setLoadPolicy(WTreeNode.LoadPolicy loadPolicy) * setLoadPolicy()} on the root node and before adding any children. The load * policy is inherited by all children in the tree. *

* There are a few scenarios where it makes sense to specialize the WTreeNode * class. One scenario is create a tree that is populated dynamically while * browsing. For this purpose you should reimplement the * {@link WTreeNode#populate() populate()} method, whose default implementation * does nothing. This method is called when 'loading' the node. The * exact moment for loading a treenode depends on the LoadPolicy. *

* A second scenario that is if you want to customize the look of the tree label * (see {@link WTreeNode#getLabelArea() getLabelArea()}) or if you want to * modify or augment the event collapse/expand event handling (see * {@link WTreeNode#doExpand() doExpand()} and {@link WTreeNode#doCollapse() * doCollapse()}). *

* See {@link WTree} for a usage example. *

*

CSS

*

* The tree is styled by the current CSS theme. The look can be overridden using * the Wt-tree CSS class and the following selectors: *

*

* *
 * .Wt-tree .Wt-trunk          : vertical line, trunk
 * .Wt-tree .Wt-end            : vertical line, last item
 * .Wt-tree .Wt-collapse       : collapse icon (img *)
 * .Wt-tree .Wt-expand         : expand icon (img *)
 * .Wt-tree .Wt-noexpand       : leaf icon
 * 
 * .Wt-tree .Wt-label          : the node label
 * .Wt-tree .Wt-childcount     : the node child count
 * .Wt-tree .Wt-node           : the node's table row
 * 
* *
* The collapse and expand icons are fetched themselves as images, * nav-plus.gif and nav-minus.gif. *

* * @see WTree * @see WTreeTableNode */ public class WTreeNode extends WCompositeWidget { /** * An enumeration for the policy to load children. */ public enum LoadPolicy { /** * Load-on-demand of child nodes. */ LazyLoading, /** * Pre-load all child nodes. */ PreLoading, /** * Pre-load one level of child nodes. */ NextLevelLoading; /** * Returns the numerical representation of this enum. */ public int getValue() { return ordinal(); } } /** * An enumeration for the policy to display the child count. */ public enum ChildCountPolicy { /** * Do not display a child count. */ Disabled, /** * Always display a child count. */ Enabled, /** * Only display a child count when the node is populated. */ Lazy; /** * Returns the numerical representation of this enum. */ public int getValue() { return ordinal(); } } /** * Creates a tree node with the given label. *

* The labelIcon, if specified, will appear just before the label and its * state reflect the expand/collapse state of the node. *

* The node is initialized to be collapsed. */ public WTreeNode(CharSequence labelText, WIconPair labelIcon, WTreeNode parent) { super(); this.childNodes_ = new ArrayList(); this.collapsed_ = true; this.selectable_ = true; this.visible_ = true; this.childrenDecorated_ = true; this.parentNode_ = null; this.childCountPolicy_ = WTreeNode.ChildCountPolicy.Disabled; this.labelIcon_ = labelIcon; this.labelText_ = new WText(labelText); this.childrenLoaded_ = false; this.populated_ = false; this.interactive_ = true; this.selected_ = new Signal1(this); this.clickedConnection_ = new AbstractSignal.Connection(); this.create(); if (parent != null) { parent.addChildNode(this); } } /** * Creates a tree node with the given label. *

* Calls * {@link #WTreeNode(CharSequence labelText, WIconPair labelIcon, WTreeNode parent) * this(labelText, (WIconPair)null, (WTreeNode)null)} */ public WTreeNode(CharSequence labelText) { this(labelText, (WIconPair) null, (WTreeNode) null); } /** * Creates a tree node with the given label. *

* Calls * {@link #WTreeNode(CharSequence labelText, WIconPair labelIcon, WTreeNode parent) * this(labelText, labelIcon, (WTreeNode)null)} */ public WTreeNode(CharSequence labelText, WIconPair labelIcon) { this(labelText, labelIcon, (WTreeNode) null); } /** * Destructor. */ public void remove() { for (int i = 0; i < this.childNodes_.size(); ++i) { if (this.childNodes_.get(i) != null) this.childNodes_.get(i).remove(); } if (this.noExpandIcon_ != null) this.noExpandIcon_.remove(); if (this.expandIcon_ != null) this.expandIcon_.remove(); super.remove(); } /** * Returns the tree. *

* By default if this node has no parent the result will be 0. */ public WTree getTree() { return this.parentNode_ != null ? this.parentNode_.getTree() : null; } /** * Returns the label. */ public WText getLabel() { return this.labelText_; } /** * Returns the label icon. */ public WIconPair getLabelIcon() { return this.labelIcon_; } /** * Sets the label icon. */ public void setLabelIcon(WIconPair labelIcon) { if (this.labelIcon_ != null) this.labelIcon_.remove(); this.labelIcon_ = labelIcon; if (this.labelIcon_ != null) { if (this.labelText_ != null) { this.layout_.getElementAt(0, 1).insertBefore(this.labelIcon_, this.labelText_); } else { this.layout_.getElementAt(0, 1).addWidget(this.labelIcon_); } this.labelIcon_.setState(this.isExpanded() ? 1 : 0); } } /** * Inserts a child node. *

* Inserts the node node at index index. */ public void insertChildNode(int index, WTreeNode node) { this.childNodes_.add(0 + index, node); node.parentNode_ = this; if (this.childrenLoaded_) { this.layout_.getElementAt(1, 1).insertWidget(index, node); } else { node.setParent((WObject) null); } this.descendantAdded(node); if (this.loadPolicy_ != node.loadPolicy_) { node.setLoadPolicy(this.loadPolicy_); } if (this.childCountPolicy_ != node.childCountPolicy_) { node.setChildCountPolicy(this.childCountPolicy_); } if (index == (int) this.childNodes_.size() - 1 && this.childNodes_.size() > 1) { this.childNodes_.get(this.childNodes_.size() - 2).update(); } node.update(); this.update(); this.resetLearnedSlots(); } /** * Adds a child node. *

* Equivalent to:

* *
	 * insertChildNode(childNodes().size(), node);
	 * 
* *
*

* * @see WTreeNode#insertChildNode(int index, WTreeNode node) */ public void addChildNode(WTreeNode node) { this.insertChildNode(this.childNodes_.size(), node); } /** * Removes a child node. */ public void removeChildNode(WTreeNode node) { this.childNodes_.remove(node); node.parentNode_ = null; if (this.childrenLoaded_) { this.layout_.getElementAt(1, 1).removeWidget(node); } this.descendantRemoved(node); this.updateChildren(); } /** * Returns the list of children. */ public List getChildNodes() { return this.childNodes_; } /** * Returns the number of children that should be displayed. *

* This is used to display the count in the count label. The default * implementation simply returns {@link WTreeNode#getChildNodes() * getChildNodes()}.size(). */ public int getDisplayedChildCount() { return this.childNodes_.size(); } /** * Configures how and when the child count should be displayed. *

* By default, no child count indication is disabled (this is the behaviour * since 2.1.1). Use this method to enable child count indications. *

* The child count policy is inherited by all children in the tree. */ public void setChildCountPolicy(WTreeNode.ChildCountPolicy policy) { if (policy != WTreeNode.ChildCountPolicy.Disabled && !(this.childCountLabel_ != null)) { this.childCountLabel_ = new WText(); this.childCountLabel_.setMargin(new WLength(7), EnumSet .of(Side.Left)); this.childCountLabel_ .setStyleClass("Wt-childcount treenodechildcount"); this.layout_.getElementAt(0, 1).addWidget(this.childCountLabel_); } this.childCountPolicy_ = policy; if (this.childCountPolicy_ == WTreeNode.ChildCountPolicy.Enabled) { WTreeNode parent = this.getParentNode(); if (parent != null && parent.isExpanded()) { if (this.isDoPopulate()) { this.update(); } } } if (this.childCountPolicy_ != WTreeNode.ChildCountPolicy.Disabled) { for (int i = 0; i < this.childNodes_.size(); ++i) { this.childNodes_.get(i).setChildCountPolicy( this.childCountPolicy_); } } } /** * Returns the child count policy. *

* * @see WTreeNode#setChildCountPolicy(WTreeNode.ChildCountPolicy policy) */ public WTreeNode.ChildCountPolicy getChildCountPolicy() { return this.childCountPolicy_; } /** * Sets the image pack for this (sub)tree (deprecated). *

* * @deprecated This method does not do anything since JWt 3.1.1, as the tree * is now styled based on the current CSS theme. */ public void setImagePack(String url) { } /** * Sets the load policy for this tree. *

* This may only be set on the root of a tree, and before adding any * children. */ public void setLoadPolicy(WTreeNode.LoadPolicy loadPolicy) { this.loadPolicy_ = loadPolicy; switch (loadPolicy) { case PreLoading: this.loadChildren(); break; case NextLevelLoading: if (this.isExpanded()) { this.loadChildren(); this.loadGrandChildren(); } else { WTreeNode parent = this.getParentNode(); if (parent != null && parent.isExpanded()) { this.loadChildren(); } this.expandIcon_.icon1Clicked().addListener(this, new Signal1.Listener() { public void trigger(WMouseEvent e1) { WTreeNode.this.loadGrandChildren(); } }); } break; case LazyLoading: if (this.isExpanded()) { this.loadChildren(); } else { if (this.childCountPolicy_ == WTreeNode.ChildCountPolicy.Enabled) { WTreeNode parent = this.getParentNode(); if (parent != null && parent.isExpanded()) { this.isDoPopulate(); } } this.expandIcon_.icon1Clicked().addListener(this, new Signal1.Listener() { public void trigger(WMouseEvent e1) { WTreeNode.this.expand(); } }); } } if (this.loadPolicy_ != WTreeNode.LoadPolicy.LazyLoading) { for (int i = 0; i < this.childNodes_.size(); ++i) { this.childNodes_.get(i).setLoadPolicy(this.loadPolicy_); } } } /** * Returns whether this node is expanded. */ public boolean isExpanded() { return !this.collapsed_; } /** * Allows this node to be selected. *

* By default, all nodes may be selected. *

* * @see WTreeNode#isSelectable() * @see WTree#select(WTreeNode node, boolean selected) */ public void setSelectable(boolean selectable) { this.selectable_ = selectable; } /** * Returns if this node may be selected. *

* * @see WTreeNode#setSelectable(boolean selectable) */ public boolean isSelectable() { return this.selectable_; } /** * Returns the parent node. *

* * @see WTreeNode#getChildNodes() */ public WTreeNode getParentNode() { return this.parentNode_; } /** * Sets the visibility of the node itself. *

* If false, then the node itself is not displayed, but only * its children. This is typically used to hide the root node of a tree. */ public void setNodeVisible(boolean visible) { this.visible_ = visible; this.updateChildren(false); } /** * Sets whether this node's children are decorated. *

* By default, node's children have expand/collapse and other lines to * display their linkage and offspring. *

* By setting decorated to false, you can hide the * decorations for the node's children. */ public void setChildrenDecorated(boolean decorated) { this.childrenDecorated_ = decorated; this.updateChildren(false); } /** * Sets whether this node is interactive. *

* Interactive nodes can be clicked upon and will populate a list of * children when clicked. By disabling the interactivity, a node will not * react to a click event. */ public void setInteractive(boolean interactive) { this.interactive_ = interactive; } /** * Expands this node. *

* Besides the actual expansion of the node, this may also trigger the * loading and population of the node children, or of the children's * children. *

* * @see WTreeNode#collapse() * @see WTreeNode#doExpand() */ public void expand() { if (!this.isExpanded()) { if (!this.childrenLoaded_) { this.loadChildren(); } if (this.getParentNode() != null && this.childNodes_.isEmpty()) { this.getParentNode().resetLearnedSlots(); this.update(); return; } if (this.loadPolicy_ == WTreeNode.LoadPolicy.NextLevelLoading) { this.loadGrandChildren(); } this.doExpand(); this.updateChildren(); } } /** * Collapses this node. *

* * @see WTreeNode#expand() * @see WTreeNode#doCollapse() */ public void collapse() { if (this.isExpanded()) { this.doCollapse(); } } /** * Signal emitted when the node is expanded by the user. *

* * @see WTreeNode#collapsed() */ public EventSignal1 expanded() { return this.expandIcon_.icon1Clicked(); } /** * Signal emitted when the node is collapsed by the user. *

* * @see WTreeNode#expanded() */ public EventSignal1 collapsed() { return this.expandIcon_.icon2Clicked(); } /** * Signal that is emitted when the node is added or removed from the * selection *

* * @see WTree#itemSelectionChanged() */ public Signal1 selected() { return this.selected_; } /** * Creates a tree node with empty {@link WTreeNode#getLabelArea() * getLabelArea()}. *

* This tree node has no label or labelicon, and is therefore ideally suited * to provide a custom look. */ protected WTreeNode(WTreeNode parent) { super(); this.childNodes_ = new ArrayList(); this.collapsed_ = true; this.selectable_ = true; this.visible_ = true; this.childrenDecorated_ = true; this.parentNode_ = null; this.childCountPolicy_ = WTreeNode.ChildCountPolicy.Disabled; this.labelIcon_ = null; this.labelText_ = null; this.childrenLoaded_ = false; this.populated_ = false; this.interactive_ = true; this.selected_ = new Signal1(this); this.clickedConnection_ = new AbstractSignal.Connection(); this.create(); if (parent != null) { parent.addChildNode(this); } } /** * Creates a tree node with empty {@link WTreeNode#getLabelArea() * getLabelArea()}. *

* Calls {@link #WTreeNode(WTreeNode parent) this((WTreeNode)null)} */ protected WTreeNode() { this((WTreeNode) null); } /** * Accesses the container widget that holds the label area. *

* Use this to customize how the label should look like. */ protected WTableCell getLabelArea() { return this.layout_.getElementAt(0, 1); } /** * Populates the node dynamically on loading. *

* Reimplement this method if you want to populate the widget dynamically, * as the tree is being browsed and therefore loaded. This is only usefull * with LazyLoading or NextLevelLoading strategies. */ protected void populate() { } /** * Returns whether this node has already been populated. *

* * @see WTreeNode#populate() */ protected boolean isPopulated() { return this.populated_; } /** * Returns whether this node can be expanded. *

* The default implementation populates the node if necessary, and then * checks if there are any child nodes. *

* You may wish to reimplement this method if you reimplement * {@link WTreeNode#populate() populate()}, and you have a quick default for * determining whether a node may be expanded (which does not require * populating the node). *

* * @see WTreeNode#populate() */ protected boolean isExpandable() { if (this.interactive_) { this.isDoPopulate(); return !this.childNodes_.isEmpty(); } else { return false; } } /** * Renders the node to be selected. *

* The default implementation changes the style class of the * {@link WTreeNode#getLabelArea() getLabelArea()} to "selected". */ protected void renderSelected(boolean isSelected) { this.layout_.getRowAt(0).setStyleClass( isSelected ? "Wt-selected selected" : ""); this.selected().trigger(isSelected); } /** * The image pack that is used for this tree node (deprecated). *

* * @deprecated This method returns "" since JWt 3.1.1, as the * image pack is no longer used in favour of the CSS themes. */ protected String getImagePack() { return ""; } /** * Reacts to the removal of a descendant node. *

* Reimplement this method if you wish to react on the removal of a * descendant node. The default implementation simply propagates the event * to the parent. */ protected void descendantRemoved(WTreeNode node) { WTreeNode parent = this.getParentNode(); if (parent != null) { parent.descendantRemoved(node); } } /** * Reacts to the addition of a descendant node. *

* Reimplement this method if you wish to react on the addition of a * descendant node. The default implementation simply propagates the event * to the parent. */ protected void descendantAdded(WTreeNode node) { WTreeNode parent = this.getParentNode(); if (parent != null) { parent.descendantAdded(node); } } /** * The actual expand. *

* This method, which is implemented as a stateless slot, performs the * actual expansion of the node. *

* You may want to reimplement this function (and * {@link WTreeNode#undoDoExpand() undoDoExpand()}) if you wish to do * additional things on node expansion. *

* * @see WTreeNode#doCollapse() * @see WTreeNode#expand() */ protected void doExpand() { this.wasCollapsed_ = !this.isExpanded(); this.collapsed_ = false; if (!this.childNodes_.isEmpty()) { this.expandIcon_.setState(1); this.layout_.getRowAt(1).show(); if (this.labelIcon_ != null) { this.labelIcon_.setState(1); } } for (int i = 0; i < this.childNodes_.size(); ++i) { this.childNodes_.get(i).doCollapse(); } } /** * The actual collapse. *

* This method, which is implemented as a stateless slot, performs the * actual collapse of the node. *

* You may want to reimplement this function (and * {@link WTreeNode#undoDoCollapse() undoDoCollapse()}) if you wish to do * additional things on node expansion. *

* * @see WTreeNode#doExpand() * @see WTreeNode#collapse() */ protected void doCollapse() { this.wasCollapsed_ = !this.isExpanded(); this.collapsed_ = true; this.expandIcon_.setState(0); this.layout_.getRowAt(1).hide(); if (this.labelIcon_ != null) { this.labelIcon_.setState(0); } } /** * Undo method for {@link WTreeNode#doCollapse() doCollapse()} stateless * implementation. *

* * @see WTreeNode#doCollapse() */ protected void undoDoExpand() { if (this.wasCollapsed_) { this.expandIcon_.setState(0); this.layout_.getRowAt(1).hide(); if (this.labelIcon_ != null) { this.labelIcon_.setState(0); } this.collapsed_ = true; } for (int i = 0; i < this.childNodes_.size(); ++i) { this.childNodes_.get(i).undoDoCollapse(); } } /** * Undo method for {@link WTreeNode#doCollapse() doCollapse()} stateless * implementation. *

* * @see WTreeNode#doExpand() */ protected void undoDoCollapse() { if (!this.wasCollapsed_) { this.expandIcon_.setState(1); this.layout_.getRowAt(1).show(); if (this.labelIcon_ != null) { this.labelIcon_.setState(1); } this.collapsed_ = false; } } WTable getImpl() { return this.layout_; } private List childNodes_; private boolean collapsed_; private boolean selectable_; private boolean visible_; private boolean childrenDecorated_; private WTreeNode parentNode_; private WTreeNode.LoadPolicy loadPolicy_; private WTreeNode.ChildCountPolicy childCountPolicy_; private WTable layout_; private WIconPair expandIcon_; private WText noExpandIcon_; private WIconPair labelIcon_; private WText labelText_; private WText childCountLabel_; private boolean childrenLoaded_; private boolean populated_; private boolean interactive_; private Signal1 selected_; private void loadChildren() { if (!this.childrenLoaded_) { this.isDoPopulate(); for (int i = 0; i < this.childNodes_.size(); ++i) { this.layout_.getElementAt(1, 1).addWidget( this.childNodes_.get(i)); } this.expandIcon_.icon1Clicked().addListener(this, new Signal1.Listener() { public void trigger(WMouseEvent e1) { WTreeNode.this.doExpand(); } }); this.expandIcon_.icon2Clicked().addListener(this, new Signal1.Listener() { public void trigger(WMouseEvent e1) { WTreeNode.this.doCollapse(); } }); this.resetLearnedSlots(); this.childrenLoaded_ = true; } } private void loadGrandChildren() { for (int i = 0; i < this.childNodes_.size(); ++i) { this.childNodes_.get(i).loadChildren(); } } private void create() { this.setImplementation(this.layout_ = new WTable()); this.setStyleClass("Wt-tree"); this.layout_.setSelectable(false); if (WApplication.getInstance().getEnvironment().agentIsOpera()) { this.layout_.setAttributeValue("style", "table-layout: auto"); } // this.implementStateless(WTreeNode.doExpand,WTreeNode.undoDoExpand); // this.implementStateless(WTreeNode.doCollapse,WTreeNode.undoDoCollapse); WApplication app = WApplication.getInstance(); this.expandIcon_ = new WIconPair(WApplication.getResourcesUrl() + "themes/" + app.getCssTheme() + "/" + imagePlus_, WApplication.getResourcesUrl() + "themes/" + app.getCssTheme() + "/" + imageMin_); this.noExpandIcon_ = new WText(); this.noExpandIcon_.setStyleClass("Wt-noexpand"); this.layout_.getRowAt(1).hide(); if (this.labelText_ != null) { this.labelText_.setStyleClass("Wt-label treenodelabel"); } this.childCountLabel_ = null; this.layout_.getElementAt(0, 0).setStyleClass("Wt-trunk"); this.layout_.getElementAt(0, 0).addWidget(this.noExpandIcon_); if (this.labelIcon_ != null) { this.layout_.getElementAt(0, 1).addWidget(this.labelIcon_); this.labelIcon_.setVerticalAlignment(AlignmentFlag.AlignMiddle); } if (this.labelText_ != null) { this.layout_.getElementAt(0, 1).addWidget(this.labelText_); } this.layout_.getElementAt(0, 0).setContentAlignment( EnumSet.of(AlignmentFlag.AlignLeft, AlignmentFlag.AlignTop)); this.layout_.getElementAt(0, 1).setContentAlignment( EnumSet.of(AlignmentFlag.AlignLeft, AlignmentFlag.AlignMiddle)); this.layout_.getRowAt(0).setStyleClass("Wt-node"); this.childrenLoaded_ = false; this.setLoadPolicy(WTreeNode.LoadPolicy.LazyLoading); } private void update() { boolean isLast = this.isLastChildNode(); if (!this.visible_) { this.layout_.getRowAt(0).hide(); this.expandIcon_.hide(); this.layout_.getElementAt(0, 0) .resize(new WLength(0), WLength.Auto); this.layout_.getElementAt(1, 0) .resize(new WLength(0), WLength.Auto); } else { this.layout_.getRowAt(0).show(); this.expandIcon_.show(); this.layout_.getElementAt(0, 0).resize(WLength.Auto, WLength.Auto); this.layout_.getElementAt(1, 0).resize(WLength.Auto, WLength.Auto); } WTreeNode parent = this.getParentNode(); if (parent != null && !parent.childrenDecorated_) { this.layout_.getElementAt(0, 0).hide(); this.layout_.getElementAt(1, 0).hide(); } if (this.expandIcon_.getState() != (this.isExpanded() ? 1 : 0)) { this.expandIcon_.setState(this.isExpanded() ? 1 : 0); } if (this.layout_.getRowAt(1).isHidden() != !this.isExpanded()) { this.layout_.getRowAt(1).setHidden(!this.isExpanded()); } if (this.labelIcon_ != null && this.labelIcon_.getState() != (this.isExpanded() ? 1 : 0)) { this.labelIcon_.setState(this.isExpanded() ? 1 : 0); } if (isLast) { this.layout_.getElementAt(0, 0).setStyleClass("Wt-end"); this.layout_.getElementAt(1, 0).setStyleClass(""); } else { this.layout_.getElementAt(0, 0).setStyleClass("Wt-trunk"); this.layout_.getElementAt(1, 0).setStyleClass("Wt-trunk"); } if (!(this.getParentNode() != null) || this.getParentNode().isExpanded()) { if (this.childCountPolicy_ == WTreeNode.ChildCountPolicy.Enabled && !this.populated_) { this.isDoPopulate(); } if (!this.isExpandable()) { if (this.noExpandIcon_.getParent() == null) { this.layout_.getElementAt(0, 0).addWidget( this.noExpandIcon_); this.layout_.getElementAt(0, 0).removeWidget( this.expandIcon_); } } else { if (this.expandIcon_.getParent() == null) { this.layout_.getElementAt(0, 0).addWidget(this.expandIcon_); this.layout_.getElementAt(0, 0).removeWidget( this.noExpandIcon_); } } } if (this.childCountPolicy_ != WTreeNode.ChildCountPolicy.Disabled && this.populated_ && this.childCountLabel_ != null) { int n = this.getDisplayedChildCount(); if (n != 0) { this.childCountLabel_.setText(new WString("(" + String.valueOf(n) + ")")); } else { this.childCountLabel_.setText(new WString()); } } } private boolean isLastChildNode() { WTreeNode parent = this.getParentNode(); if (parent != null) { return parent.childNodes_.get(parent.childNodes_.size() - 1) == this; } else { return true; } } private void updateChildren(boolean recursive) { for (int i = 0; i < this.childNodes_.size(); ++i) { if (recursive) { this.childNodes_.get(i).updateChildren(recursive); } else { this.childNodes_.get(i).update(); } } this.update(); this.resetLearnedSlots(); } private final void updateChildren() { updateChildren(false); } private boolean wasCollapsed_; private boolean isDoPopulate() { if (!this.populated_) { this.populated_ = true; this.populate(); return true; } else { return false; } } AbstractSignal.Connection clickedConnection_; private static String imagePlus_ = "nav-plus.gif"; private static String imageMin_ = "nav-minus.gif"; }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy