001: /*
002: * This file is not part of the ItsNat framework.
003: *
004: * Original source code use and closed source derivatives are authorized
005: * to third parties with no restriction or fee.
006: * The original source code is owned by the author.
007: *
008: * This program is distributed AS IS in the hope that it will be useful,
009: * but WITHOUT ANY WARRANTY; without even the implied warranty of
010: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
011: *
012: * Author: Jose Maria Arranz Santamaria
013: * (C) Innowhere Software Services S.L., Spanish company, year 2007
014: */
015:
016: package org.itsnat.feashow;
017:
018: import javax.swing.event.TreeExpansionEvent;
019: import javax.swing.event.TreeExpansionListener;
020: import javax.swing.event.TreeModelEvent;
021: import javax.swing.event.TreeModelListener;
022: import javax.swing.event.TreeSelectionEvent;
023: import javax.swing.event.TreeSelectionListener;
024: import javax.swing.tree.TreeModel;
025: import javax.swing.tree.TreePath;
026: import javax.swing.tree.TreeSelectionModel;
027: import org.itsnat.comp.free.ItsNatFreeTree;
028: import org.itsnat.comp.ui.ItsNatTreeCellUI;
029: import org.itsnat.comp.ui.ItsNatTreeUI;
030: import org.w3c.dom.Element;
031: import org.w3c.dom.css.CSSStyleDeclaration;
032: import org.w3c.dom.css.ElementCSSInlineStyle;
033: import org.w3c.dom.html.HTMLElement;
034: import org.w3c.dom.html.HTMLImageElement;
035:
036: public class FreeTreeDecorator implements TreeModelListener,
037: TreeSelectionListener, TreeExpansionListener {
038: protected ItsNatFreeTree comp;
039:
040: public FreeTreeDecorator(ItsNatFreeTree comp) {
041: this .comp = comp;
042: }
043:
044: public void bind() {
045: TreeModel dataModel = comp.getTreeModel();
046: dataModel.addTreeModelListener(this ); // Added before to call setTreeModel again because it must be called last (the last registered is the first called, the component register a listener to add/remove DOM elements)
047: comp.setTreeModel(dataModel);// Resets the internal listeners, the internal TreeModelListener listener is called first
048: comp.addTreeExpansionListener(this );
049:
050: TreeSelectionModel selModel = comp.getTreeSelectionModel();
051: selModel.addTreeSelectionListener(this );
052: }
053:
054: public void treeNodesChanged(TreeModelEvent e) {
055: }
056:
057: public void treeNodesInserted(TreeModelEvent e) {
058: TreeModel dataModel = comp.getTreeModel();
059: TreePath parentPath = e.getTreePath();
060: updateHandleAndIconOfNode(parentPath);
061:
062: Object parentNode = parentPath.getLastPathComponent();
063: int[] indices = e.getChildIndices();
064: if ((indices != null) && (indices.length > 0)) {
065: for (int i = 0; i < indices.length; i++) {
066: int index = indices[i];
067: Object childNode = dataModel
068: .getChild(parentNode, index);
069: TreePath childPath = parentPath
070: .pathByAddingChild(childNode);
071: updateNodeTree(childPath);
072: }
073: }
074: }
075:
076: public void treeNodesRemoved(TreeModelEvent e) {
077: //TreeModel dataModel = comp.getTreeModel();
078: TreePath parentPath = e.getTreePath();
079: updateHandleAndIconOfNode(parentPath);
080: }
081:
082: public void treeStructureChanged(TreeModelEvent e) {
083: TreePath path = e.getTreePath();
084: if (path == null)
085: return; // Root case (removed)
086: updateNodeTree(path);
087: }
088:
089: public void updateNodeTree(TreePath path) {
090: updateHandleAndIconOfNode(path);
091: TreeModel dataModel = comp.getTreeModel();
092: Object dataNode = path.getLastPathComponent();
093: int len = dataModel.getChildCount(dataNode);
094: for (int i = 0; i < len; i++) {
095: Object childNode = dataModel.getChild(dataNode, i);
096: TreePath childPath = path.pathByAddingChild(childNode);
097: updateNodeTree(childPath);
098: }
099: }
100:
101: public void updateHandleAndIconOfNode(TreePath path) {
102: ItsNatTreeCellUI nodeInfo = comp.getItsNatTreeUI()
103: .getItsNatTreeCellUIFromTreePath(path);
104: if (nodeInfo == null)
105: return; // path is root and rootless mode
106: updateHandleAndIconOfNode(nodeInfo, path);
107: }
108:
109: public void updateHandleAndIconOfNode(ItsNatTreeCellUI nodeInfo,
110: TreePath path) {
111: TreeModel dataModel = comp.getTreeModel();
112: Object dataNode = path.getLastPathComponent();
113:
114: HTMLImageElement handle = (HTMLImageElement) nodeInfo
115: .getHandleElement();
116: HTMLImageElement icon = (HTMLImageElement) nodeInfo
117: .getIconElement();
118:
119: if (dataModel.isLeaf(dataNode)) {
120: setStyleProperty(handle, "display", "none");
121: icon.setSrc("img/tree/gear.gif");
122: } else {
123: removeStyleProperty(handle, "display");
124: if (nodeInfo.isExpanded())
125: icon.setSrc("img/tree/tree_folder_open.gif");
126: else
127: icon.setSrc("img/tree/tree_folder_close.gif");
128: }
129:
130: if (comp.isTreeTable()) {
131: Element contentParentElem = nodeInfo.getContentElement();
132: int margin = 15 * nodeInfo.getDeepLevel();
133: if (margin > 0)
134: setStyleProperty(contentParentElem, "padding-left",
135: margin + "px");
136: }
137: }
138:
139: public void valueChanged(TreeSelectionEvent e) {
140: //TreeSelectionModel selModel = (TreeSelectionModel)e.getSource();
141:
142: TreePath[] paths = e.getPaths();
143: for (int i = 0; i < paths.length; i++) {
144: boolean selected = e.isAddedPath(i);
145: decorateSelection(paths[i], selected);
146: }
147: }
148:
149: public void decorateSelection(TreePath path, boolean selected) {
150: if (path == null)
151: return; // Root case (removed)
152: Element labelElem = comp.getItsNatTreeUI()
153: .getLabelElementFromTreePath(path);
154: if (labelElem == null)
155: return;
156: decorateSelection(labelElem, selected);
157: }
158:
159: public void decorateSelection(Element elem, boolean selected) {
160: ElementCSSInlineStyle elemCSS = (ElementCSSInlineStyle) comp
161: .getItsNatDocument().getItsNatNode(elem);
162: CSSStyleDeclaration elemStyle = elemCSS.getStyle();
163:
164: if (selected) {
165: elemStyle.setProperty("background", "rgb(0,0,255)", null);
166: elemStyle.setProperty("color", "white", null);
167: } else {
168: elemStyle.removeProperty("background");
169: elemStyle.removeProperty("color");
170: }
171: }
172:
173: public void treeExpanded(TreeExpansionEvent event) {
174: expandCollapse(event, true);
175: }
176:
177: public void treeCollapsed(TreeExpansionEvent event) {
178: expandCollapse(event, false);
179: }
180:
181: public void expandCollapse(TreeExpansionEvent event, boolean expand) {
182: TreePath path = event.getPath();
183: ItsNatTreeUI compUI = comp.getItsNatTreeUI();
184: ItsNatTreeCellUI nodeInfo = compUI
185: .getItsNatTreeCellUIFromTreePath(path);
186: if (nodeInfo == null)
187: return; // path is root and rootless mode
188: updateTreeUIExpandCollapse(nodeInfo, path, expand);
189: }
190:
191: public boolean childNodesAreVisible(ItsNatTreeCellUI nodeInfo,
192: boolean visible) {
193: return nodeInfo.isExpanded() && visible;
194: }
195:
196: public void updateTreeUIExpandCollapse(ItsNatTreeCellUI nodeInfo,
197: TreePath path, boolean visible) {
198: HTMLElement handleElem = (HTMLElement) nodeInfo
199: .getHandleElement();
200: HTMLImageElement imgElem = (HTMLImageElement) handleElem;
201: if (nodeInfo.isExpanded())
202: imgElem.setSrc("img/tree/tree_node_expanded.gif");
203: else
204: imgElem.setSrc("img/tree/tree_node_collapse.gif");
205:
206: updateHandleAndIconOfNode(nodeInfo, path);
207:
208: updateChildVisibility(path, nodeInfo.isExpanded());
209: }
210:
211: public void updateChildVisibility(TreePath path,
212: boolean childrenVisible) {
213: // Hide/show child nodes
214: TreeModel dataModel = comp.getTreeModel();
215: Object parentNode = path.getLastPathComponent();
216: int len = dataModel.getChildCount(parentNode);
217: ItsNatTreeUI compUI = comp.getItsNatTreeUI();
218: for (int i = 0; i < len; i++) {
219: Object childNode = dataModel.getChild(parentNode, i);
220: TreePath childPath = path.pathByAddingChild(childNode);
221: ItsNatTreeCellUI childNodeInfo = compUI
222: .getItsNatTreeCellUIFromTreePath(childPath);
223: Element childElem = childNodeInfo.getParentElement();
224:
225: String display;
226: if (childrenVisible)
227: removeStyleProperty(childElem, "display"); // Show
228: else
229: setStyleProperty(childElem, "display", "none"); // Hide
230:
231: if (comp.isTreeTable()) {
232: // Child nodes are not inside the parent's DOM HTMLElement
233: // in this case
234: updateChildVisibility(childPath, childNodesAreVisible(
235: childNodeInfo, childrenVisible));
236: }
237: }
238: }
239:
240: public void setStyleProperty(Element elem, String name, String value) {
241: ElementCSSInlineStyle elemCSS = (ElementCSSInlineStyle) comp
242: .getItsNatDocument().getItsNatNode(elem);
243: CSSStyleDeclaration elemStyle = elemCSS.getStyle();
244: elemStyle.setProperty(name, value, null);
245: }
246:
247: public void removeStyleProperty(Element elem, String name) {
248: ElementCSSInlineStyle elemCSS = (ElementCSSInlineStyle) comp
249: .getItsNatDocument().getItsNatNode(elem);
250: CSSStyleDeclaration elemStyle = elemCSS.getStyle();
251: elemStyle.removeProperty(name);
252: }
253: }
|