1 19 20 package org.netbeans.modules.search; 21 22 import java.awt.EventQueue ; 23 import java.util.ArrayList ; 24 import java.util.List ; 25 import javax.swing.event.TreeModelEvent ; 26 import javax.swing.event.TreeModelListener ; 27 import javax.swing.tree.TreeModel ; 28 import javax.swing.tree.TreePath ; 29 import org.openide.nodes.Node; 30 31 36 final class ResultTreeModel implements TreeModel { 37 38 39 final ResultModel resultModel; 40 41 private final TreePath rootPath; 42 43 private String rootDisplayName; 44 45 private boolean selected = true; 46 47 private int objectsCount; 48 49 private List <TreeModelListener > treeModelListeners; 50 51 55 ResultTreeModel(ResultModel resultModel) { 56 this.resultModel = resultModel; 57 this.rootPath = new TreePath (this); 58 59 if (resultModel != null) { 60 resultModel.setObserver(this); 61 } 62 } 63 64 public Object getRoot() { 65 return this; 66 } 67 68 public Object getChild(Object parent, int index) { 69 assert EventQueue.isDispatchThread(); 70 71 if ((resultModel == null) || (index < 0)) { 72 return null; 73 } 74 75 Object ret; 76 if (parent == getRoot()) { 77 if (index >= objectsCount) { 78 ret = null; 79 } else { 80 try { 81 ret = resultModel.matchingObjects.get(index); 83 } catch (ArrayIndexOutOfBoundsException ex) { 84 assert false; 85 ret = null; 86 } 87 } 88 } else if (parent.getClass() == MatchingObject.class) { 89 if (!resultModel.canHaveDetails()) { 90 ret = null; 91 } else { 92 MatchingObject matchingObject = (MatchingObject) parent; 93 Node[] detailNodes 94 = resultModel.searchAndReplace 95 ? resultModel.fullTextSearchType.getDetails( 96 matchingObject.object) 97 : resultModel.getDetails(matchingObject); 98 if ((detailNodes == null) || (index >= detailNodes.length)) { 99 ret = null; 100 } else { 101 ret = detailNodes[index]; 102 } 103 } 104 } else { ret = null; 106 } 107 return ret; 108 } 109 110 public int getChildCount(Object parent) { 111 assert EventQueue.isDispatchThread(); 112 113 if (resultModel == null) { 114 return 0; 115 } 116 117 int ret; 118 if (parent == getRoot()) { 119 ret = objectsCount; 120 } else if (parent.getClass() == MatchingObject.class) { 121 if (resultModel.searchAndReplace) { 122 ret = resultModel.fullTextSearchType.getDetailsCount( 123 ((MatchingObject) parent).object); 124 } else if (resultModel.canHaveDetails() == Boolean.FALSE) { 125 ret = 0; 126 } else { 127 ret = resultModel.getDetailsCount((MatchingObject) parent); 128 } 129 } else { ret = 0; 131 } 132 return ret; 133 } 134 135 public boolean isLeaf(Object node) { 136 assert EventQueue.isDispatchThread(); 137 138 boolean ret; 139 if (node == getRoot()) { 140 ret = false; 141 } else if (node.getClass() == MatchingObject.class) { 142 Boolean hasDetails = resultModel.canHaveDetails(); 143 if (hasDetails != null) { 144 ret = !hasDetails.booleanValue(); 145 } else { 146 ret = !resultModel.hasDetails((MatchingObject) node); 147 } 148 } else { ret = true; 150 } 151 return ret; 152 } 153 154 public void valueForPathChanged(TreePath path, Object newValue) { 155 assert EventQueue.isDispatchThread(); 156 157 158 assert false; 159 } 160 161 public int getIndexOfChild(Object parent, Object child) { 162 assert EventQueue.isDispatchThread(); 163 164 if ((resultModel == null) || (parent == null) || (child == null)) { 165 return -1; 166 } 167 168 int ret; 169 if (parent == getRoot()) { 170 ret = (child.getClass() == MatchingObject.class) 171 ? resultModel.matchingObjects.indexOf(child) 172 : -1; 173 } else { 174 ret = -1; 175 if ((parent.getClass() == MatchingObject.class) 176 && resultModel.canHaveDetails() 177 && (child instanceof Node)) { 178 MatchingObject matchingObject = (MatchingObject) parent; 179 Node[] detailNodes 180 = resultModel.searchAndReplace 181 ? resultModel.fullTextSearchType.getDetails( 182 matchingObject.object) 183 : resultModel.getDetails(matchingObject); 184 if (detailNodes != null) { 185 for (int i = 0; i < detailNodes.length; i++) { 186 if (detailNodes[i].equals(child)) { 187 ret = i; 188 break; 189 } 190 } 191 } 192 } 193 } 194 return ret; 195 } 196 197 public void addTreeModelListener(TreeModelListener l) { 198 assert EventQueue.isDispatchThread(); 199 200 if (l == null) { 201 throw new IllegalArgumentException ("null"); } 203 204 if (treeModelListeners == null) { 205 treeModelListeners = new ArrayList <TreeModelListener >(4); 206 } 207 treeModelListeners.add(l); 208 } 209 210 public void removeTreeModelListener(TreeModelListener l) { 211 assert EventQueue.isDispatchThread(); 212 213 if (l == null) { 214 throw new IllegalArgumentException ("null"); } 216 217 if (treeModelListeners != null) { 218 treeModelListeners.remove(l); 219 } 220 } 221 222 224 void objectFound(MatchingObject object, int objectIndex) { 225 if (resultModel == null) { 226 throw new IllegalStateException ("resultModel is null"); } 228 new Task(object, objectIndex).run(); } 230 231 233 void objectBecameInvalid(MatchingObject object) { 234 if (resultModel == null) { 235 throw new IllegalStateException ("resultModel is null"); } 237 new Task(object).run(); 238 } 239 240 242 String getRootDisplayName() { 243 assert EventQueue.isDispatchThread(); 244 245 return rootDisplayName; 246 } 247 248 249 void setRootDisplayName(String displayName) { 250 assert EventQueue.isDispatchThread(); 251 252 this.rootDisplayName = displayName; 253 UPDATE_NAME_TASK.run(); } 255 256 258 boolean isSelected() { 259 return selected; 260 } 261 262 264 void setSelected(boolean selected) { 265 if (selected == this.selected) { 266 return; 267 } 268 269 this.selected = selected; 270 } 271 272 private final Task UPDATE_NAME_TASK = new Task(); 273 276 private final class Task implements Runnable { 277 private final MatchingObject foundObject; 278 private final int foundObjectIndex; 279 private Task() { 280 this.foundObject = null; 281 this.foundObjectIndex = -1; 282 } 283 private Task(MatchingObject object) { 284 this.foundObject = object; 285 this.foundObjectIndex = -1; 286 } 287 private Task(MatchingObject foundObject, int foundObjectIndex) { 288 assert (foundObject != null) && (foundObjectIndex >= 0); 289 this.foundObject = foundObject; 290 this.foundObjectIndex = foundObjectIndex; 291 } 292 public void run() { 293 if (!EventQueue.isDispatchThread()) { 294 EventQueue.invokeLater(this); 295 return; 296 } 297 298 assert EventQueue.isDispatchThread(); 299 if (foundObject != null) { 300 if (foundObjectIndex != -1) { 301 objectsCount++; 302 fireNodeAdded(foundObjectIndex, foundObject); 303 } else { 304 fireNodeChanged(foundObject); 305 } 306 } else { 307 fireRootNodeChanged(); 308 } 309 } 310 } 311 312 314 private void fireNodeAdded(int index, MatchingObject object) { 315 assert EventQueue.isDispatchThread(); 316 317 if ((treeModelListeners == null) || treeModelListeners.isEmpty()) { 318 return; 319 } 320 321 TreeModelEvent event = new TreeModelEvent (this, 322 rootPath, 323 new int[] { index }, 324 new Object [] { object }); 325 for (TreeModelListener l : treeModelListeners) { 326 l.treeNodesInserted(event); 327 } 328 } 329 330 332 private void fireNodeChanged(MatchingObject object) { 333 assert EventQueue.isDispatchThread(); 334 335 if ((treeModelListeners == null) || treeModelListeners.isEmpty()) { 336 return; 337 } 338 339 TreePath path = rootPath.pathByAddingChild(object); 340 TreeModelEvent event = new TreeModelEvent (this, path); 341 for (TreeModelListener l : treeModelListeners) { 342 l.treeStructureChanged(event); 343 } 344 } 345 346 348 void fireRootNodeChanged() { 349 assert EventQueue.isDispatchThread(); 350 351 if ((treeModelListeners == null) || treeModelListeners.isEmpty()) { 352 return; 353 } 354 355 TreeModelEvent event = new TreeModelEvent (this, rootPath, null, null); 356 for (TreeModelListener l : treeModelListeners) { 357 l.treeNodesChanged(event); 358 } 359 } 360 361 363 void fireFileNodesSelectionChanged(int[] indices, 364 MatchingObject[] matchingObjects) { 365 assert EventQueue.isDispatchThread(); 366 assert matchingObjects != null; 367 assert indices != null; 368 assert matchingObjects.length == indices.length; 369 370 if ((treeModelListeners == null) || treeModelListeners.isEmpty()) { 371 return; 372 } 373 374 TreeModelEvent event = new TreeModelEvent (this, 375 rootPath, 376 indices, 377 matchingObjects); 378 for (TreeModelListener l : treeModelListeners) { 379 l.treeNodesChanged(event); 380 } 381 } 382 383 393 void fireFileNodeSelectionChanged(MatchingObject matchingObj, 394 boolean includingSubnodes) { 395 assert EventQueue.isDispatchThread(); 396 397 if ((treeModelListeners == null) || treeModelListeners.isEmpty()) { 398 return; 399 } 400 401 final int index = resultModel.matchingObjects.indexOf(matchingObj); 402 403 404 TreeModelEvent event = new TreeModelEvent (this, 405 rootPath, 406 new int[] { index }, 407 new Object [] { matchingObj }); 408 for (TreeModelListener l : treeModelListeners) { 409 l.treeNodesChanged(event); 410 } 411 412 if (includingSubnodes) { 413 414 fireFileNodeChildrenSelectionChanged(matchingObj); 415 } 416 } 417 418 420 void fireFileNodeChildrenSelectionChanged(MatchingObject matchingObj) { 421 Node[] children = resultModel.fullTextSearchType 422 .getDetails(matchingObj.object); 423 int[] indices = new int[children.length]; 424 for (int i = 0; i < indices.length; i++) { 425 indices[i] = i; 426 } 427 final TreeModelEvent event = new TreeModelEvent ( 428 this, 429 new Object [] { getRoot(), matchingObj }, 430 indices, 431 children); 432 for (TreeModelListener l : treeModelListeners) { 433 l.treeNodesChanged(event); 434 } 435 } 436 437 439 void fireDetailNodeSelectionChanged(MatchingObject matchingObj, 440 int index) { 441 assert EventQueue.isDispatchThread(); 442 443 if ((treeModelListeners == null) || treeModelListeners.isEmpty()) { 444 return; 445 } 446 447 int[] changedIndices = new int[] { index }; 448 Node[] detailNodes = resultModel.fullTextSearchType 449 .getDetails(matchingObj.object); 450 Node[] changedNodes = (detailNodes.length == 1) 451 ? detailNodes 452 : new Node[] { detailNodes[index] }; 453 TreeModelEvent event = new TreeModelEvent ( 454 this, 455 new Object [] { getRoot(), matchingObj }, 456 changedIndices, 457 changedNodes); 458 for (TreeModelListener l : treeModelListeners) { 459 l.treeNodesChanged(event); 460 } 461 } 462 463 466 public String toString() { 467 return super.toString() + "[" + rootDisplayName + "]"; } 469 } 470 | Popular Tags |