- Timestamp:
- 07/12/13 23:41:06 (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
java/main/src/main/java/com/framsticks/gui/tree/TreeNode.java
r99 r100 5 5 import java.util.LinkedList; 6 6 import java.util.List; 7 import java.util.concurrent.atomic.AtomicInteger; 8 9 import javax.swing.ImageIcon; 10 import javax.swing.tree.TreePath; 11 12 import org.apache.log4j.Logger; 13 14 import com.framsticks.core.ListChange; 7 8 import org.apache.logging.log4j.LogManager; 9 import org.apache.logging.log4j.Logger; 10 15 11 import com.framsticks.core.Node; 16 12 import com.framsticks.core.Path; … … 19 15 import com.framsticks.gui.ImageProvider; 20 16 import com.framsticks.gui.TreeAtFrame; 21 import com.framsticks.params.AccessInterface; 17 import com.framsticks.gui.TreePanel; 18 import com.framsticks.params.Access; 22 19 import com.framsticks.params.CompositeParam; 23 20 import com.framsticks.params.EventListener; 24 21 import com.framsticks.params.FramsClass; 25 import com.framsticks.params.PrimitiveParam;26 22 import com.framsticks.params.ValueParam; 27 23 import com.framsticks.params.types.EventParam; … … 32 28 import com.framsticks.util.lang.Casting; 33 29 import com.framsticks.util.lang.Containers; 34 import com.framsticks.util.lang.Pair;35 30 import com.framsticks.util.swing.TooltipConstructor; 31 36 32 import static com.framsticks.core.TreeOperations.*; 37 33 38 34 public class TreeNode extends AbstractNode { 39 private static final Logger log = Logger.getLogger(TreeNode.class); 40 41 42 protected static final AtomicInteger counter = new AtomicInteger(); 35 36 private static final Logger log = LogManager.getLogger(TreeNode.class); 43 37 44 38 protected final WeakReference<Object> reference; 39 protected final int hashCode; 40 protected final TreeAtFrame treeAtFrame; 41 protected final String textual; 45 42 protected final CompositeParam param; 46 protected final TreeAtFrame treeAtFrame;47 protected final List<Pair<WeakReference<Object>, WeakReference<TreeNode>>> children = new LinkedList<>(); 48 p rotected final int number;49 protected final String textualPath;50 protected final ImageIcon imageIcon;51 protected final TreeModel treeModel; 52 53 protected final List<EventListener<?>> listeners = new LinkedList<>();54 43 protected TreePanel panel; 44 45 public TreeModel getTreeModel() { 46 return treeAtFrame.getFrame().getTreeModel(); 47 } 48 49 /** 50 * @param reference 51 */ 55 52 public TreeNode(TreeAtFrame treeAtFrame, Path path) { 56 53 path.assureResolved(); 57 this.textualPath = path.getTextual(); 54 55 this.reference = new WeakReference<Object>(path.getTopObject()); 56 this.textual = path.getTextual(); 57 this.treeAtFrame = treeAtFrame; 58 58 this.param = path.getTop().getParam(); 59 this.treeAtFrame = treeAtFrame; 60 this.treeModel = treeAtFrame.getFrame().getTreeModel(); 61 this.imageIcon = ImageProvider.loadImage(TreeCellRenderer.findIconName(param)); 62 63 reference = new WeakReference<Object>(path.getTop().getObject()); 64 number = counter.getAndIncrement(); 59 hashCode = System.identityHashCode(path.getTopObject()); 60 61 if (getTree().getSideNote(path.getTopObject(), getTreeModel().createdTag, Object.class) == getTreeModel().createdTag) { 62 return; 63 } 64 65 // path.getTree().putSideNote(path.getTopObject(), Textual.class, path.getTextual()); 66 path.getTree().putSideNote(path.getTopObject(), getTreeModel().createdTag, getTreeModel().createdTag); 65 67 66 68 /** Iterate over all EventParams and for matching ValueParams register listeners. */ 67 if (pa raminstanceof ObjectParam) {68 Access Interfaceaccess = bindAccess(path);69 if (path.getTop().getParam() instanceof ObjectParam) { 70 Access access = bindAccess(path); 69 71 FramsClass framsClass = access.getFramsClass(); 70 72 for (EventParam eventParam : Containers.filterInstanceof(framsClass.getParamEntries(), EventParam.class)) { … … 77 79 continue; 78 80 } 79 registerForEventParam(path, eventParam, valueParam); 80 } 81 } 82 } 83 84 protected <A> void tryAddListener(final Path path, final EventParam eventParam, Class<A> argumentType, final EventListener<A> listener) { 85 treeAtFrame.getTree().addListener(path, eventParam, listener, argumentType, new FutureHandler<Void>(treeAtFrame.getFrame()) { 86 @Override 87 protected void result(Void result) { 88 assert treeAtFrame.getFrame().isActive(); 89 log.debug("registered gui listener for " + eventParam + " at " + path); 90 listeners.add(listener); 91 } 92 }); 93 } 94 95 protected void registerForEventParam(Path path, EventParam eventParam, ValueParam valueParam) { 96 /** TODO make this listener not bind hold the reference to this TreeNode, maybe hold WeakReference internally */ 97 if (valueParam instanceof PrimitiveParam) { 98 99 tryAddListener(path, eventParam, Object.class, new EventListener<Object>() { 100 @Override 101 public void action(Object argument) { 102 treeModel.loadPath(assurePath(), true); 103 } 104 }); 105 106 } else if (valueParam instanceof CompositeParam) { 107 108 final CompositeParam compositeParam = (CompositeParam) valueParam; 109 110 tryAddListener(path, eventParam, ListChange.class, new EventListener<ListChange>() { 111 @Override 112 public void action(ListChange listChange) { 113 assert treeAtFrame.getTree().isActive(); 114 115 final Path listPath = assurePath().appendParam(compositeParam).tryFindResolution().assureResolved(); 116 log.debug("reacting to change " + listChange + " in " + listPath); 117 118 if ((listChange.getAction().equals(ListChange.Action.Modify)) && (listChange.getPosition() == -1)) { 119 // get(listPath, future); 120 return; 121 } 122 final String id = listChange.getBestIdentifier(); 123 124 AccessInterface access = bindAccess(listPath); 125 switch (listChange.getAction()) { 126 case Add: { 127 tryGet(listPath.getTree(), Path.appendString(listPath.getTextual(), id), new FutureHandler<Path>(treeAtFrame.getFrame()) { 128 @Override 129 protected void result(Path result) { 130 final Frame frame = treeAtFrame.getFrame(); 131 assert frame.isActive(); 132 final TreePath treePath = frame.getTreeModel().convertToTreePath(listPath); 133 treeModel.nodeStructureChanged(treePath); 134 frame.updatePanelIfIsLeadSelection(treePath, listPath); 135 log.debug("added " + id + "(" + result + ") updated " + treePath); 136 } 137 }); 138 break; 139 } 140 case Remove: { 141 access.set(id, null); 142 Frame frame = treeAtFrame.getFrame(); 143 treeModel.nodeStructureChanged(frame.getTreeModel().convertToTreePath(listPath)); 144 break; 145 } 146 case Modify: { 147 tryGet(listPath.getTree(), Path.appendString(listPath.getTextual(), id), new FutureHandler<Path>(treeAtFrame.getFrame()) { 148 @Override 149 protected void result(Path result) { 150 final Frame frame = treeAtFrame.getFrame(); 151 assert frame.isActive(); 152 final TreePath treePath = frame.getTreeModel().convertToTreePath(result); 153 treeModel.nodeStructureChanged(treePath); 154 frame.updatePanelIfIsLeadSelection(treePath, listPath); 155 } 156 }); 157 break; 158 } 159 } 160 } 161 }); 162 } 163 164 } 165 166 protected Path assurePath() { 167 return Path.to(treeAtFrame.getTree(), textualPath).assureResolved(); 168 } 169 170 public Node tryCreateNode() { 171 Object child = lock(); 172 if (child == null) { 173 return null; 174 } 175 return Path.to(treeAtFrame.getTree(), textualPath).assureResolved().getTop(); 176 } 177 178 @Override 179 public int getChildCount() { 180 Object referent = lock(); 181 if (referent == null) { 182 return 0; 183 } 184 AccessInterface access = bindAccessFor(referent); 185 final int count = access.getCompositeParamCount(); 186 return count; 187 } 188 189 public TreeNode getTreeNodeForChild(Object child) { 190 Iterator<Pair<WeakReference<Object>, WeakReference<TreeNode>>> i = children.iterator(); 191 while (i.hasNext()) { 192 Pair<WeakReference<Object>, WeakReference<TreeNode>> p = i.next(); 193 Object object = p.first.get(); 194 if (object == null) { 195 i.remove(); 196 continue; 197 } 198 TreeNode treeNode = p.second.get(); 199 if (treeNode == null) { 200 i.remove(); 201 continue; 202 } 203 if (object == child) { 204 return treeNode; 205 } 206 } 207 return null; 208 209 // WeakReference<GuiTreeNode> resultReference = children.get(child); 210 // if (resultReference == null) { 211 // return null; 212 // } 213 // return resultReference.get(); 81 getTreeModel().registerForEventParam(this, path, eventParam, valueParam); 82 } 83 } 84 } 85 86 @Override 87 public int hashCode() { 88 return hashCode; 89 } 90 91 @Override 92 public boolean equals(Object obj) { 93 if (obj instanceof TreeNode) { 94 return lock() == ((TreeNode) obj).lock(); 95 } 96 return false; 214 97 } 215 98 … … 220 103 throw new FramsticksException().msg("invalid state - missing referent"); 221 104 } 222 AccessInterface access = bindAccessFor(referent); 105 Tree tree = getTree(); 106 Access access = bindAccessForTreeObject(referent); 223 107 224 108 final int count = access.getCompositeParamCount(); … … 227 111 } 228 112 113 /** textual path may be not valid anymore*/ 229 114 CompositeParam childParam = access.getCompositeParam(number); 230 Object child = access.get(childParam, Object.class); 231 if (child == null) { 232 log.debug("returning dummy node for " + childParam + " in " + referent); 233 return new EmptyNode(childParam); 234 } 235 236 TreeNode result = getTreeNodeForChild(child); 237 if (result != null) { 238 return result; 239 } 240 Path path = Path.to(treeAtFrame.getTree(), Path.appendString(textualPath, childParam.getId())).assureResolved(); 241 result = new TreeNode(treeAtFrame, path); 242 243 children.add(Pair.make(new WeakReference<Object>(child), new WeakReference<TreeNode>(result))); 244 245 return result; 246 115 116 try { 117 Path path = Path.to(tree, getTextual()).appendParam(childParam).tryFindResolution(); 118 if (!path.isResolved()) { 119 path = create(path); 120 } 121 return prepareTreeNodeForChild(path); 122 } catch (FramsticksException e) { 123 } 124 return new EmptyNode(getFrame(), childParam); 125 126 } 127 128 public TreeNode prepareTreeNodeForChild(Path path) { 129 assert path.getTree() == getTree(); 130 Object parent = lock(); 131 Iterator<Node> n = path.getNodes().iterator(); 132 while (n.hasNext()) { 133 if (n.next().getObject() == parent) { 134 break; 135 } 136 } 137 if (!n.hasNext()) { 138 return null; 139 // throw new FramsticksException().msg("tree node is not on path (or is last)").arg("path", path).arg("node", this); 140 } 141 return new TreeNode(treeAtFrame, path); 247 142 } 248 143 … … 252 147 253 148 @Override 254 public int getIndexOfChild( AbstractNodechild) {149 public int getIndexOfChild(Object child) { 255 150 final TreeNode treeChild = Casting.tryCast(TreeNode.class, child); 256 151 if (treeChild == null) { … … 262 157 return -1; 263 158 } 264 final Access Interface access = bindAccessFor(parentObject);159 final Access access = bindAccessForTreeObject(parentObject); 265 160 266 161 final int count = access.getCompositeParamCount(); … … 271 166 } 272 167 } 273 log.debug( child + " not found in " +this);168 log.debug("{} not found in {}", child, this); 274 169 return -1; 275 170 } 276 171 277 /** 278 * @return the param 279 */ 280 public CompositeParam getParam() { 281 return param; 282 } 283 284 /** 285 * @return the tree 286 */ 172 public Frame getFrame() { 173 return getTreeAtFrame().getFrame(); 174 } 175 176 public TreeAtFrame getTreeAtFrame() { 177 return treeAtFrame; 178 } 179 287 180 public Tree getTree() { 288 return treeAtFrame.getTree(); 289 } 290 181 return getTreeAtFrame().getTree(); 182 } 183 184 protected Path assurePath() { 185 return Path.to(getTree(), getTextual()).assureResolved(); 186 } 291 187 292 188 @Override 293 189 public String toString() { 294 return param.toString(); 295 } 296 297 public static Node tryGetNode(TreePath treePath) { 298 return Casting.throwCast(TreeNode.class, treePath.getLastPathComponent()).tryCreateNode(); 190 return getTextual(); 191 } 192 193 public Node tryCreateNode() { 194 Object child = lock(); 195 if (child == null) { 196 return null; 197 } 198 String textual = getTextual(); 199 Path path = Path.tryTo(getTree(), textual); 200 if (path.isResolved(textual)) { 201 return path.getTop(); 202 } 203 return null; 204 } 205 206 @Override 207 public int getChildCount() { 208 Object referent = lock(); 209 if (referent == null) { 210 return 0; 211 } 212 Access access = bindAccessForTreeObject(referent); 213 final int count = access.getCompositeParamCount(); 214 return count; 299 215 } 300 216 … … 305 221 return true; 306 222 } 307 return bindAccessFor (referent).getCompositeParamCount() == 0;308 } 309 310 protected Access Interface bindAccessFor(Object child) {311 return treeAtFrame.getTree().prepareAccess(param).select(child);223 return bindAccessForTreeObject(referent).getCompositeParamCount() == 0; 224 } 225 226 protected Access bindAccessForTreeObject(Object child) { 227 return bindAccessFromSideNote(getTree(), child); 312 228 } 313 229 314 230 @Override 315 231 public void render(TreeCellRenderer renderer) { 232 233 Object child = lock(); 234 if (child == null) { 235 renderer.setToolTipText("?"); 236 renderer.setText("?"); 237 renderer.setIcon(ImageProvider.loadImage(ImageProvider.FOLDER_CLOSED)); 238 return; 239 } 240 Access access = bindAccessForTreeObject(child); 241 CompositeParam param = getTree().getSideNote(child, CompositeParam.class, CompositeParam.class); 316 242 String name = param.getId(); 317 243 318 Object child = lock(); 319 if (child != null) { 320 AccessInterface access = bindAccessFor(child); 321 322 StringParam nameParam = Casting.tryCast(StringParam.class, access.getParam("name")); 323 324 if (nameParam != null) { 325 name = access.get(nameParam, String.class); 326 } 327 328 renderer.setToolTipText(new TooltipConstructor() 244 StringParam nameParam = Casting.tryCast(StringParam.class, access.getParam("name")); 245 246 if (nameParam != null) { 247 name = access.get(nameParam, String.class); 248 } 249 250 renderer.setToolTipText(new TooltipConstructor() 329 251 .append("frams", access.getId()) 330 252 .append("java", child.getClass().getCanonicalName()) … … 333 255 .append("id", param.getId()) 334 256 .append("object", Integer.toHexString(System.identityHashCode(child))) 335 .append("number", number) 336 .append("textual path", textualPath) 257 .append("size", access.getCompositeParamCount()) 337 258 .build()); 338 } else { 339 renderer.setToolTipText(new TooltipConstructor() 340 .append("param", param) 341 .append("textual path", textualPath) 342 .build()); 343 } 259 260 renderer.setIcon(ImageProvider.loadImage(TreeCellRenderer.findIconName(param))); 344 261 renderer.setText(name); 345 renderer.setIcon(imageIcon); 346 262 } 263 264 // public static class Textual { 265 // } 266 267 public String getTextual() { 268 return textual; 269 // return getTree().getSideNote(lock(), Textual.class, String.class); 270 } 271 272 protected final Object listenersTag = new Object(); 273 274 public List<EventListener<?>> getListeners() { 275 @SuppressWarnings("unchecked") 276 List<EventListener<?>> result = getTree().getSideNote(lock(), listenersTag, List.class); 277 if (result == null) { 278 result = new LinkedList<>(); 279 getTree().putSideNote(lock(), listenersTag, result); 280 } 281 282 return result; 283 } 284 285 protected <A> void tryAddListener(final Path path, final EventParam eventParam, Class<A> argumentType, final EventListener<A> listener) { 286 getTree().addListener(path, eventParam, listener, argumentType, new FutureHandler<Void>(getFrame()) { 287 @Override 288 protected void result(Void result) { 289 assert getFrame().isActive(); 290 log.debug("registered gui listener for {} at {}", eventParam, path); 291 getListeners().add(listener); 292 } 293 }); 294 } 295 296 @Override 297 public TreePanel getPanel() { 298 if (panel != null) { 299 return panel; 300 } 301 panel = getTreeAtFrame().preparePanel(param); 302 return panel; 347 303 } 348 304
Note: See TracChangeset
for help on using the changeset viewer.