- 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/TreeModel.java
r99 r100 1 1 package com.framsticks.gui.tree; 2 2 3 //import java.util.Enumeration;3 import java.util.Enumeration; 4 4 import java.util.Iterator; 5 5 import java.util.LinkedList; 6 6 import java.util.List; 7 7 8 import javax.annotation.Nullable; 8 9 import javax.swing.event.TreeModelEvent; 9 10 import javax.swing.event.TreeModelListener; 10 11 import javax.swing.tree.TreePath; 11 12 12 import org.apache.log4j.Logger; 13 14 13 import org.apache.logging.log4j.Logger; 14 import org.apache.logging.log4j.LogManager; 15 16 import com.framsticks.core.ListChange; 15 17 import com.framsticks.core.Node; 16 18 import com.framsticks.core.Path; 17 import com.framsticks.core.Tree;18 19 import com.framsticks.core.TreeOperations; 19 20 import com.framsticks.gui.Frame; 20 import com.framsticks.params.AccessInterface; 21 import com.framsticks.params.Access; 22 import com.framsticks.params.CompositeParam; 23 import com.framsticks.params.EventListener; 24 import com.framsticks.params.ListAccess; 25 import com.framsticks.params.PrimitiveParam; 26 import com.framsticks.params.Util; 27 import com.framsticks.params.ValueParam; 28 import com.framsticks.params.types.EventParam; 21 29 import com.framsticks.util.FramsticksException; 30 import com.framsticks.util.Misc; 22 31 import com.framsticks.util.UnsupportedOperationException; 23 32 import com.framsticks.util.dispatching.FutureHandler; 24 33 import com.framsticks.util.lang.Casting; 25 34 35 import static com.framsticks.core.TreeOperations.*; 36 26 37 public class TreeModel implements javax.swing.tree.TreeModel { 27 private static final Logger log = Log ger.getLogger(TreeModel.class);38 private static final Logger log = LogManager.getLogger(TreeModel.class); 28 39 29 40 30 41 protected List<TreeModelListener> listeners = new LinkedList<>(); 42 31 43 32 44 protected final Frame frame; … … 45 57 46 58 @Override 47 public AbstractNodegetChild(Object parent, int number) {48 return Casting. assertCast(AbstractNode.class, parent).getChild(number);59 public Object getChild(Object parent, int number) { 60 return Casting.throwCast(AbstractNode.class, parent).getChild(number); 49 61 } 50 62 51 63 @Override 52 64 public int getChildCount(Object parent) { 53 return Casting. assertCast(AbstractNode.class, parent).getChildCount();65 return Casting.throwCast(AbstractNode.class, parent).getChildCount(); 54 66 } 55 67 … … 59 71 return -1; 60 72 } 61 return Casting. assertCast(AbstractNode.class, parent).getIndexOfChild(Casting.assertCast(AbstractNode.class, child));73 return Casting.throwCast(AbstractNode.class, parent).getIndexOfChild(child); 62 74 } 63 75 … … 69 81 @Override 70 82 public boolean isLeaf(Object node) { 71 return Casting. assertCast(AbstractNode.class, node).isLeaf();83 return Casting.throwCast(AbstractNode.class, node).isLeaf(); 72 84 } 73 85 … … 85 97 protected boolean changing = false; 86 98 87 public void nodeStructureChanged(TreePath treePath) { 99 public void treeNodesInserted(TreeModelEvent event) { 100 assert frame.isActive(); 101 try { 102 for (TreeModelListener listener : listeners) { 103 listener.treeNodesInserted(event); 104 } 105 } catch (ArrayIndexOutOfBoundsException e) { 106 } 107 } 108 109 public void treeNodesRemoved(TreeModelEvent event) { 110 assert frame.isActive(); 111 try { 112 for (TreeModelListener listener : listeners) { 113 listener.treeNodesRemoved(event); 114 } 115 } catch (ArrayIndexOutOfBoundsException e) { 116 } 117 } 118 119 public void treeNodesChanged(TreeModelEvent event) { 120 try { 121 for (TreeModelListener listener : listeners) { 122 listener.treeNodesChanged(event); 123 } 124 } catch (ArrayIndexOutOfBoundsException e) { 125 } 126 } 127 128 public TreeModelEvent prepareModelEvent(TreePath treePath, int number, TreeNode node) { 129 return new TreeModelEvent(this, treePath, new int[] {number}, new Object[] { node }); 130 } 131 132 133 public TreeModelEvent prepareModelEventRegarding(Access access, String id, TreePath treeListPath) { 134 135 int number = Util.getNumberOfCompositeParamChild(access, access.get(id, Object.class)); 136 if (number == -1) { 137 log.debug("encountered minor tree inconsistency in {}", treeListPath); 138 return null; 139 } 140 TreeNode node = Casting.throwCast(TreeNode.class, Casting.throwCast(TreeNode.class, treeListPath.getLastPathComponent()).getChild(number)); 141 return prepareModelEvent(treeListPath, number, node); 142 } 143 144 public void treeStructureChanged(TreePath treePath) { 145 88 146 if (treePath == null) { 89 147 return; … … 92 150 93 151 changing = true; 94 log.debug("changing : " +treePath);95 // Enumeration<TreePath> expanded = frame.jtree.getExpandedDescendants(treePath);152 log.debug("changing structure: {}", treePath); 153 Enumeration<TreePath> expanded = frame.getJtree().getExpandedDescendants(treePath); 96 154 TreePath selection = frame.getJtree().getSelectionPath(); 97 155 98 for (TreeModelListener listener : listeners) { 99 listener.treeStructureChanged(new TreeModelEvent(this, treePath)); 100 } 101 // if (expanded != null) { 102 // while (expanded.hasMoreElements()) { 103 // TreePath expansion = expanded.nextElement(); 104 // // log.info("reexpanding: " + expansion); 105 // frame.jtree.expandPath(expansion); 106 // } 107 // } 156 try { 157 for (TreeModelListener listener : listeners) { 158 listener.treeStructureChanged(new TreeModelEvent(this, treePath)); 159 } 160 } catch (ArrayIndexOutOfBoundsException e) { 161 } 162 163 164 if (expanded != null) { 165 while (expanded.hasMoreElements()) { 166 TreePath expansion = expanded.nextElement(); 167 // log.info("reexpanding: {}", expansion); 168 frame.getJtree().expandPath(expansion); 169 } 170 } 171 108 172 if (selection != null) { 109 173 frame.getJtree().setSelectionPath(selection); … … 112 176 } 113 177 114 public Path convertToPath(TreePath treePath) { 178 /** 179 * 180 * This method may return null on conversion failure, which may happen in highload situations. 181 */ 182 public @Nullable Path convertToPath(TreePath treePath) { 115 183 final Object[] components = treePath.getPath(); 116 184 assert components[0] == frame.getRootNode(); … … 128 196 Node node = treeNode.tryCreateNode(); 129 197 if (node == null) { 130 throw new FramsticksException().msg("failed to recreate path").arg("treePath", treePath); 198 return null; 199 // throw new FramsticksException().msg("failed to recreate path").arg("treePath", treePath); 131 200 } 132 201 nodes.add(node); … … 137 206 } 138 207 139 public TreePath convertToTreePath(Path path ) {208 public TreePath convertToTreePath(Path path, boolean forceComplete) { 140 209 assert frame.isActive(); 141 210 … … 143 212 accumulator.add(getRoot()); 144 213 145 for ( AbstractNoder : getRoot().getChildren()) {214 for (Object r : getRoot().getChildren()) { 146 215 if (r instanceof TreeNode) { 147 216 TreeNode root = (TreeNode) r; 148 217 if (root.getTree() == path.getTree()) { 218 Iterator<Node> n = path.getNodes().iterator(); 219 TreeNode treeNode = root; 149 220 accumulator.add(root); 150 151 Iterator<Node> i = path.getNodes().iterator(); 152 i.next(); 153 TreeNode treeNode = root; 154 155 while (i.hasNext()) { 156 Node node = i.next(); 157 treeNode = treeNode.getTreeNodeForChild(node.getObject()); 221 n.next(); 222 while (n.hasNext()) { 223 Node node = n.next(); 224 treeNode = treeNode.prepareTreeNodeForChild(Path.build().tree(path.getTree()).buildUpTo(path.getNodes(), node).finish()); 158 225 if (treeNode == null) { 159 226 break; … … 161 228 accumulator.add(treeNode); 162 229 } 163 164 230 break; 165 231 } … … 167 233 } 168 234 return new TreePath(accumulator.toArray()); 235 } 236 237 /** 238 * @return the listeners 239 */ 240 public List<TreeModelListener> getListeners() { 241 return listeners; 169 242 } 170 243 … … 180 253 return; 181 254 } 182 Access Interfaceaccess = TreeOperations.bindAccess(path);255 Access access = TreeOperations.bindAccess(path); 183 256 184 257 int count = access.getCompositeParamCount(); … … 193 266 return; 194 267 } 195 if ( path.isResolved() && !reload) {268 if (!reload && path.isResolved() && isMarked(path.getTree(), path.getTopObject(), FETCHED_MARK, false)) { 196 269 return; 197 270 } … … 199 272 @Override 200 273 protected void result(Path result) { 201 final TreePath treePath = convertToTreePath(result); 202 203 nodeStructureChanged(treePath); 204 frame.updatePanelIfIsLeadSelection(treePath, result); 274 final TreePath treePath = convertToTreePath(result, true); 275 276 277 if (treePath != null) { 278 treeStructureChanged(treePath); 279 frame.updatePanelIfIsLeadSelection(result); 280 } 205 281 } 206 282 }); 207 283 } 208 284 209 public void chooseTreeNode(finalTreePath treePath) {285 public void expandTreeNode(TreePath treePath) { 210 286 assert frame.isActive(); 211 287 if (treePath == null) { … … 215 291 return; 216 292 } 217 218 293 Path path = convertToPath(treePath); 219 294 if (path == null) { 220 295 return; 221 296 } 297 loadChildren(path.assureResolved(), false); 298 } 299 300 public void chooseTreeNode(final TreePath treePath) { 301 assert frame.isActive(); 302 if (treePath == null) { 303 return; 304 } 305 if (isChanging()) { 306 return; 307 } 308 309 Path path = convertToPath(treePath); 310 if (path == null) { 311 return; 312 } 222 313 path = path.assureResolved(); 223 final Tree tree = path.getTree(); 224 225 frame.getTreeAtFrames().get(tree).useOrCreatePanel(treePath); 226 loadChildren(path, false); 227 228 } 314 315 log.debug("choosing {}", path); 316 frame.showPanelForTreePath(treePath); 317 loadPath(path, false); 318 319 } 320 321 322 protected void registerForEventParam(final TreeNode treeNode, Path path, final EventParam eventParam, ValueParam valueParam) { 323 /** TODO make this listener not bind hold the reference to this TreeNode, maybe hold WeakReference internally */ 324 if (valueParam instanceof PrimitiveParam) { 325 326 treeNode.tryAddListener(path, eventParam, Object.class, new EventListener<Object>() { 327 @Override 328 public void action(Object argument) { 329 loadPath(treeNode.assurePath(), true); 330 } 331 }); 332 333 } else if (valueParam instanceof CompositeParam) { 334 335 final CompositeParam compositeParam = (CompositeParam) valueParam; 336 337 treeNode.tryAddListener(path, eventParam, ListChange.class, new EventListener<ListChange>() { 338 @Override 339 public void action(ListChange listChange) { 340 assert treeNode.getTree().isActive(); 341 342 Path parentPath = treeNode.assurePath(); 343 final Path listPath = parentPath.appendParam(compositeParam).tryFindResolution(); 344 if (!listPath.isResolved()) { 345 /** that situation is quietly ignored - it may happen if first event comes before the container was resolved */ 346 return; 347 } 348 349 log.debug("reacting to change {} in {}", listChange, listPath); 350 final TreePath treeListPath = convertToTreePath(listPath, true); 351 if (treeListPath == null) { 352 throw new FramsticksException().msg("path was not fully converted").arg("path", listPath); 353 } 354 355 if ((listChange.getAction().equals(ListChange.Action.Modify)) && (listChange.getPosition() == -1)) { 356 // get(listPath, future); 357 // treeModel.nodeStructureChanged(treePath); 358 // frame.updatePanelIfIsLeadSelection(treePath, result); 359 return; 360 } 361 final String id = listChange.getBestIdentifier(); 362 363 final ListAccess access = (ListAccess) bindAccess(listPath); 364 switch (listChange.getAction()) { 365 case Add: { 366 Path childPath = listPath.appendParam(access.prepareParamFor(id)).tryFindResolution(); 367 if (!childPath.isResolved()) { 368 childPath = create(childPath); 369 370 TreeModelEvent event = prepareModelEventRegarding(access, id, treeListPath); 371 if (event != null) { 372 treeNodesInserted(event); 373 } else { 374 treeStructureChanged(treeListPath); 375 } 376 frame.updatePanelIfIsLeadSelection(listPath); 377 } 378 379 listPath.getTree().get(childPath, new FutureHandler<Path>(frame) { 380 @Override 381 protected void result(Path result) { 382 if (!result.isResolved()) { 383 log.warn("inconsistency after addition list change: {}", result); 384 } 385 assert frame.isActive(); 386 final TreePath treePath = Misc.throwIfNull(frame.getTreeModel().convertToTreePath(result, true)); 387 388 // treeModel.nodeStructureChanged(treePath); 389 frame.updatePanelIfIsLeadSelection(result); 390 391 log.debug("added {}({}) updated {}", id, result, treePath); 392 } 393 }); 394 break; 395 } 396 case Remove: { 397 398 TreeModelEvent event = prepareModelEventRegarding(access, id, treeListPath); 399 access.set(id, null); 400 if (event != null) { 401 treeNodesRemoved(event); 402 } else { 403 treeStructureChanged(treeListPath); 404 } 405 406 frame.updatePanelIfIsLeadSelection(listPath); 407 408 break; 409 } 410 case Modify: { 411 Path childPath = listPath.appendParam(access.prepareParamFor(id)).tryResolveIfNeeded(); 412 listPath.getTree().get(childPath, new FutureHandler<Path>(frame) { 413 @Override 414 protected void result(Path result) { 415 assert frame.isActive(); 416 // final TreePath treePath = frame.getTreeModel().convertToTreePath(result, true); 417 418 TreeModelEvent event = prepareModelEventRegarding(access, id, treeListPath); 419 if (event != null) { 420 treeNodesChanged(event); 421 } else { 422 treeStructureChanged(treeListPath); 423 } 424 425 frame.updatePanelIfIsLeadSelection(listPath); 426 frame.updatePanelIfIsLeadSelection(result); 427 } 428 }); 429 break; 430 } 431 } 432 } 433 }); 434 } 435 436 } 437 438 439 440 protected final Object createdTag = new Object(); 441 442 443 229 444 }
Note: See TracChangeset
for help on using the changeset viewer.