1 19 20 package org.netbeans.modules.tasklist.core; 21 22 23 import java.io.ObjectInput ; 24 import java.io.ObjectOutput ; 25 26 import java.awt.*; 27 import java.awt.image.BufferedImage ; 28 import java.beans.PropertyVetoException ; 29 import java.io.IOException ; 30 import java.util.*; 31 import java.util.List ; 32 import java.lang.ref.WeakReference ; 33 import java.lang.ref.Reference ; 34 import java.util.logging.Level ; 35 import java.util.logging.Logger ; 36 import javax.swing.*; 37 import javax.swing.table.TableColumn ; 38 import javax.swing.table.TableColumnModel ; 39 import javax.swing.tree.TreeNode ; 40 41 import org.netbeans.modules.tasklist.core.columns.ColumnsConfiguration; 42 import org.netbeans.modules.tasklist.core.filter.Filter; 43 import org.netbeans.modules.tasklist.core.filter.FilterAction; 44 import org.netbeans.modules.tasklist.core.filter.FilterRepository; 45 import org.netbeans.modules.tasklist.core.filter.FilteredTopComponent; 46 import org.netbeans.modules.tasklist.core.filter.RemoveFilterAction; 47 import org.openide.filesystems.FileObject; 48 import org.openide.filesystems.Repository; 49 import org.openide.explorer.ExplorerManager; 50 import org.openide.nodes.FilterNode; 51 import org.openide.nodes.Node; 52 import org.openide.util.HelpCtx; 53 import org.openide.util.Lookup; 54 import org.openide.util.NbBundle; 55 import org.openide.awt.StatusDisplayer; 56 import org.openide.ErrorManager; 57 import org.openide.explorer.ExplorerUtils; 58 import org.openide.explorer.view.Visualizer; 59 import org.openide.actions.FindAction; 60 import org.openide.cookies.InstanceCookie; 61 import org.openide.filesystems.FileSystem; 62 import org.openide.loaders.DataObject; 63 import org.openide.loaders.DataObjectNotFoundException; 64 import org.openide.util.actions.SystemAction; 65 import org.openide.windows.Mode; 66 import org.openide.windows.WindowManager; 67 import org.openide.windows.TopComponent; 68 69 70 71 76 public abstract class TaskListView extends TopComponent 77 implements TaskListener, ExplorerManager.Provider, TaskSelector, 78 FilteredTopComponent 79 { 80 81 private static final long serialVersionUID = 1; 82 83 private static final Logger LOGGER = TLUtils.getLogger(TaskListView.class); 84 85 static { 86 LOGGER.setLevel(Level.OFF); 87 } 88 89 92 private transient static Map views = null; 93 94 95 private static int TOOLBAR_HEIGHT_ADJUSTMENT = 4; 96 97 98 private static int toolbarHeight = -1; 99 100 public static final String DEFAULT_FILTER_NAME = 101 NbBundle.getMessage(TaskListView.class, "default-filter-name"); 102 103 104 109 protected static void registerTaskListView(TaskListView view) { 110 synchronized (TaskListView.class) { 111 if (views == null) { 112 views = new HashMap(); 113 } 114 views.put(view.category, new WeakReference (view)); 115 } 116 } 117 118 public static TaskListView getTaskListView(String category) { 119 assert category != null; 120 121 if (views == null) { 122 return null; 123 } 124 125 Reference ref = (Reference ) views.get(category); 126 if (ref == null) return null; 127 return (TaskListView) ref.get(); 128 } 129 130 131 public static final String PROP_TASK_SUMMARY = "taskDesc"; 133 134 private static Map defColumns = new HashMap(); 135 136 transient protected Node rootNode = null; 137 transient protected MyTreeTableView treeTable; 138 139 protected transient ColumnProperty[] columns = null; 140 141 transient private boolean initialized = false; 142 143 transient protected String category = null; 144 145 protected transient ObservableList tasklist = null; 146 147 transient protected FilterRepository filters = null; 148 transient protected Filter activeFilter = null; 149 150 151 transient protected TaskAnnotation taskMarker = null; 152 153 private transient Component centerCmp; 154 155 transient private JPanel centerPanel; 156 transient private Component northCmp; 157 transient private boolean northCmpCreated; 158 transient private JLabel miniStatus; 159 160 private transient ExplorerManager manager; 161 162 protected boolean persistent = false; 163 164 175 public TaskListView() { 176 init_(); 177 } 178 179 183 protected TaskListView(String category, String title, Image icon, 184 boolean persistent, ObservableList tasklist) { 185 init_(); 186 187 assert category != null : "category == null"; 188 189 this.category = category; 190 setName(title); 191 this.persistent = persistent; 192 setIcon(icon); 193 194 registerTaskListView(this); 195 setModel(tasklist); 196 } 197 198 201 private void init_() { 202 manager = new ExplorerManager(); 203 ActionMap map = getActionMap(); 204 map.put(javax.swing.text.DefaultEditorKit.copyAction, 205 ExplorerUtils.actionCopy(manager)); 206 map.put(javax.swing.text.DefaultEditorKit.cutAction, 207 ExplorerUtils.actionCut(manager)); 208 map.put(javax.swing.text.DefaultEditorKit.pasteAction, 209 ExplorerUtils.actionPaste(manager)); 210 map.put("delete", ExplorerUtils.actionDelete(manager, true)); 212 map.put("jumpNext", new PrevNextAction (false)); map.put("jumpPrev", new PrevNextAction (true)); 215 associateLookup(ExplorerUtils.createLookup(manager, map)); 217 } 218 219 public int getPersistenceType() { 220 if (persistent) { 221 return TopComponent.PERSISTENCE_ONLY_OPENED; 223 } else { 224 return TopComponent.PERSISTENCE_NEVER; 225 } 226 227 } 228 229 public ExplorerManager getExplorerManager() { 230 return manager; 231 } 232 233 236 public void updateFilterCount() { 237 JLabel filterLabel = (JLabel) getMiniStatus(); 238 if (getFilter() == null) { 239 filterLabel.setText(""); 240 } else { 241 int all = TLUtils.getChildrenCountRecursively(rootNode); 242 int shown = TLUtils.getChildrenCountRecursively( 243 getExplorerManager().getExploredContext()); 244 filterLabel.setText(NbBundle.getMessage(TaskListView.class, 245 "FilterCount", new Integer (shown), new Integer (all))); } 247 } 248 249 254 protected void setNorthComponentVisible(boolean v) { 255 if (v) { 256 Component cmp = getNorthComponent(); 257 if (cmp != null) { 258 centerPanel.add(cmp, BorderLayout.NORTH); 259 centerPanel.validate(); 260 } 261 } else { 262 if (northCmp != null && northCmp.getParent() != null) { 263 northCmp.getParent().remove(northCmp); 264 } 265 } 266 } 267 268 274 public boolean isNorthComponentVisible() { 275 return northCmp != null && northCmp.getParent() != null; 276 } 277 278 283 protected Component getNorthComponent() { 284 if (!northCmpCreated) { 285 northCmp = createNorthComponent(); 286 northCmpCreated = true; 287 } 288 return northCmp; 289 } 290 291 296 protected Component createNorthComponent() { 297 return new JLabel(""); } 299 300 303 protected JLabel getMiniStatus() { 304 if (miniStatus == null) { 305 miniStatus = createMiniStatus(); 306 } 307 return miniStatus; 308 } 309 310 private JLabel createMiniStatus() { 311 JLabel ret = new JLabel(); 312 Dimension dim = ret.getPreferredSize(); 313 dim.height = getToolbarHeight(); 314 ret.setPreferredSize(dim); 315 return ret; 316 } 317 318 protected final void setMiniStatus(String text) { 319 getMiniStatus().setText(text); 320 } 321 322 326 public static int getToolbarHeight() { 327 328 if (toolbarHeight == -1) { 329 BufferedImage image = new BufferedImage (1,1,BufferedImage.TYPE_BYTE_GRAY); 330 Graphics2D g = image.createGraphics(); 331 UIDefaults def = UIManager.getLookAndFeelDefaults(); 332 333 int height = 0; 334 String [] fonts = {"Label.font", "Button.font", "ToggleButton.font"}; for (int i=0; i<fonts.length; i++) { 336 Font f = def.getFont(fonts[i]); 337 FontMetrics fm = g.getFontMetrics(f); 338 height = Math.max(height, fm.getHeight()); 339 } 340 toolbarHeight = height + TOOLBAR_HEIGHT_ADJUSTMENT; 341 } 342 343 return toolbarHeight; 344 } 345 346 347 private TaskEditorListener annotationManager = TaskEditorListener.getDefault(); 351 352 360 public void showTaskInEditor(Task item, TaskAnnotation annotation) { 361 if (annotation == null) annotation = getAnnotation(item); 362 annotationManager.showTask(item, annotation); 363 } 364 365 371 public void hideTaskInEditor() { 372 annotationManager.hideTask(); 373 } 374 375 379 protected SystemAction[] getToolBarActions() { 380 return null; 381 } 382 383 387 protected SystemAction[] getGlobalToolBarActions() { 388 return null; 389 } 390 391 397 public TableColumnModel getColumnModel() { 398 return treeTable.getHeaderModel(); 399 } 400 401 406 public final ColumnProperty[] getColumns() { 407 if (columns == null) 408 columns = createColumns(); 409 return columns; 410 } 411 412 417 protected ColumnsConfiguration getDefaultColumns() { 418 ColumnsConfiguration cc = (ColumnsConfiguration) defColumns.get(category); 419 if (cc != null) 420 return cc; 421 422 FileSystem fs = Repository.getDefault().getDefaultFileSystem(); 423 FileObject fo = fs.findResource("TaskList/" + category + "/columns.settings"); assert fo != null : "Missing config TaskList/" + category + "/columns.settings"; 426 try { 427 DataObject dobj = DataObject.find(fo); 428 InstanceCookie ic = (InstanceCookie) dobj.getCookie(InstanceCookie.class); 429 cc = (ColumnsConfiguration) ic.instanceCreate(); 430 } catch (ClassNotFoundException e) { 431 ErrorManager.getDefault().notify(e); 432 } catch (DataObjectNotFoundException e) { 433 ErrorManager.getDefault().notify(e); 434 } catch (IOException e) { 435 ErrorManager.getDefault().notify(e); 436 } 437 return cc; 438 } 439 440 441 442 protected void loadFilters() { 443 FileSystem fs = Repository.getDefault().getDefaultFileSystem(); 444 FileObject fo = fs.findResource("TaskList/" + category + "/filters.settings"); assert fo != null : "Missing config TaskList/" + category + "/filters.settings"; 447 try { 448 DataObject dobj = DataObject.find(fo); 449 InstanceCookie ic = (InstanceCookie) dobj.getCookie(InstanceCookie.class); 450 filters = (FilterRepository) ic.instanceCreate(); 451 452 filters.setActive(null); 461 462 if (filters.size() == 0) { 464 Filter f = createFilter(); 465 f.setName(DEFAULT_FILTER_NAME); 466 filters.add(f); 467 } 468 469 } catch (ClassNotFoundException e) { 470 ErrorManager.getDefault().notify(e); 471 } catch (DataObjectNotFoundException e) { 472 ErrorManager.getDefault().notify(e); 473 } catch (IOException e) { 474 ErrorManager.getDefault().notify(e); 475 } 476 477 } 478 479 484 protected void componentOpened() { 485 LOGGER.fine(""); 486 490 if (initialized) { 491 return; 492 } 493 initialized = true; 494 495 FindAction find = (FindAction) FindAction.get(FindAction.class); 496 FilterAction filter = (FilterAction) FilterAction.get(FilterAction.class); 497 getActionMap().put(find.getActionMapKey(), filter); 498 499 setLayout(new BorderLayout()); 500 501 centerPanel = new JPanel(); 502 centerPanel.setLayout(new BorderLayout()); 503 centerCmp = createCenterComponent(); 504 505 centerPanel.add(centerCmp, BorderLayout.CENTER); 506 add(centerPanel, BorderLayout.CENTER); 507 508 loadColumnsConfiguration(); 509 510 Component north = getNorthComponent(); 511 if (north != null) 512 add(north, BorderLayout.NORTH); 513 514 JPanel toolbars = new JPanel(); 515 toolbars.setLayout(new FlowLayout(FlowLayout.LEADING, 0, 0)); 516 517 SystemAction[] actions = getGlobalToolBarActions(); 518 if (actions != null) { 519 JToolBar toolbar = SystemAction.createToolbarPresenter(actions); 520 toolbar.setFloatable(false); 521 toolbar.putClientProperty("JToolBar.isRollover", Boolean.TRUE); toolbar.setOrientation(JToolBar.VERTICAL); 523 toolbars.add(toolbar); 524 } 525 526 actions = getToolBarActions(); 527 if (actions != null) { 528 JToolBar toolbar = SystemAction.createToolbarPresenter(actions); 529 toolbar.setFloatable(false); 530 toolbar.putClientProperty("JToolBar.isRollover", Boolean.TRUE); toolbar.setOrientation(JToolBar.VERTICAL); 532 toolbars.add(toolbar); 533 } 534 535 536 add(toolbars, BorderLayout.WEST); 537 538 setModel(tasklist); 540 } 541 542 547 protected Component createCenterComponent() { 548 treeTable = new MyTreeTableView(); 549 if (columns == null) { 550 columns = createColumns(); 551 } 552 treeTable.setProperties(columns); 553 554 treeTable.setTreePreferredWidth(columns[0].getWidth()); 559 TableColumnModel tcm = treeTable.getHeaderModel(); 560 LOGGER.fine("number of columns " + tcm.getColumnCount()); 561 for (int i = 0; i < tcm.getColumnCount(); i++) { 562 TableColumn tc = tcm.getColumn(i); 563 ColumnProperty cp = null; 564 for (int j = 0; j < columns.length; j++) { 565 if (columns[j].getDisplayName().equals(tc.getHeaderValue())) { 566 cp = columns[j]; 567 break; 568 } 569 } 570 if (cp != null) 571 tc.setPreferredWidth(cp.width); 572 } 573 574 treeTable.getTable().getTableHeader().setReorderingAllowed(false); 575 treeTable.setRootVisible(false); 576 treeTable.setVerticalScrollBarPolicy( 577 JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); 578 treeTable.setHorizontalScrollBarPolicy( 579 JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); 580 581 return (Component) treeTable; 582 } 583 584 585 protected void componentClosed() { 586 hideTaskInEditor(); 587 hideList(); 588 589 if (unshowItem != null) { 591 removedTask(null, unshowItem, 0); } 593 594 unregisterListeners(); 596 597 storeColumnsConfiguration(); 598 } 599 600 protected void componentActivated() { 601 super.componentActivated(); 602 assert initialized : 603 "#37438 dangling componentActivated event, no componentOpened()" + " called at " + this; 605 ExplorerUtils.activateActions(manager, true); 606 RemoveFilterAction removeFilter = 607 (RemoveFilterAction) SystemAction.get(RemoveFilterAction.class); 608 removeFilter.enable(); 609 } 610 611 protected void componentDeactivated() { 612 super.componentDeactivated(); 613 assert initialized : "#37438 dangling componentDeactivated event, no componentOpened() called at " + this; 614 ExplorerUtils.activateActions(manager, false); 615 storeColumnsConfiguration(); 616 } 617 618 621 protected void storeColumnsConfiguration() { 622 ColumnsConfiguration columns = getDefaultColumns(); 623 ColumnsConfiguration.loadColumnsFrom(this, columns); 624 } 625 626 629 protected void loadColumnsConfiguration() { 630 ColumnsConfiguration cc = getDefaultColumns(); 631 ColumnsConfiguration.configureColumns(this, cc); 632 } 633 634 635 abstract protected Node createRootNode(); 636 637 642 protected void setModel(ObservableList list) { 643 hideList(); 644 tasklist = list; 645 if (list != null) { 646 getModel().addTaskListener(this); 647 setRoot(); 648 } 649 } 650 651 private void setRoot() { 652 rootNode = createRootNode(); 653 rootNode.setDisplayName(getMainColumn(-1).getDisplayName()); 656 657 LOGGER.fine("root created " + rootNode); 658 659 Node prevRoot = getExplorerManager().getRootContext(); 660 661 if (isFiltered()) { 662 FilteredTaskChildren children = 664 new FilteredTaskChildren(this, rootNode, getFilter()); 665 FilterNode n = new FilterTaskNode(rootNode, children, false); 666 getExplorerManager().setRootContext(n); 667 } else { 668 getExplorerManager().setRootContext(rootNode); 669 } 670 671 try { 672 if (prevRoot != null) prevRoot.destroy(); 673 } catch (IOException ex) { 674 throw new IllegalStateException ("Unexpected IOex in " + prevRoot); } 676 } 677 678 protected void hideList() { 679 ObservableList prev = getModel(); 680 if (prev != null) { 681 prev.removeTaskListener(this); 682 } 683 } 684 685 690 public Node getRootNode() { 691 return rootNode; 692 } 693 694 697 public HelpCtx getHelpCtx() { 698 return getHelpCtx( 699 getExplorerManager().getSelectedNodes(), 700 getExplorerManager().getRootContext().getHelpCtx() 701 ); 702 } 703 704 private static HelpCtx getHelpCtx(Node [] sel, HelpCtx def) { 706 HelpCtx result = null; 707 for (int i = 0; i < sel.length; i++) { 708 HelpCtx attempt = sel[i].getHelpCtx(); 709 if (attempt != null && !attempt.equals(HelpCtx.DEFAULT_HELP)) { 710 if (result == null || result.equals(attempt)) { 711 result = attempt; 712 } else { 713 result = null; 715 break; 716 } 717 } 718 } 719 if (result != null) 720 return result; 721 else 722 return def; 723 } 724 725 726 731 public JTable getTable() { 732 return treeTable.getTable(); 733 } 734 735 744 public void readExternal(ObjectInput objectInput) throws IOException , java.lang.ClassNotFoundException { 745 749 int ver = objectInput.read(); 750 752 String selUID = (String ) objectInput.readObject(); 755 756 if (ver == 4) 757 return; 758 759 int sortingColumn = objectInput.read(); 760 int sortAscendingInt = objectInput.read(); 761 int numVisible = objectInput.read(); 762 763 if (sortingColumn == 255) { 765 sortingColumn = -1; 766 } 767 768 774 775 if (numVisible > 0) { 776 if (columns == null) { 777 columns = createColumns(); 778 } 779 int numColumns = columns.length; 780 boolean[] columnVisible = new boolean[numColumns]; 781 for (int i = 0; i < numColumns; i++) { 782 columnVisible[i] = false; 783 } 784 for (int i = 0; i < numVisible; i++) { 785 int uid = objectInput.read(); 786 if ((uid < numColumns) && (columns[uid].uid == uid)) { 788 } else { 792 for (int j = 0; j < numColumns; j++) { 795 if (columns[j].uid == uid) { 796 break; 798 } 799 } 800 } 801 802 818 } 819 820 840 } 842 843 if (ver >= 2) { 844 category = (String ) objectInput.readObject(); 845 objectInput.readObject(); int persistentInt = objectInput.read(); 847 persistent = (persistentInt != 0); 848 } else { 849 category = TaskList.USER_CATEGORY; } 851 852 synchronized (TaskListView.class) { 853 if (views == null) { 854 views = new HashMap(); 855 } 856 views.put(category, new WeakReference (this)); 857 } 858 } 859 860 868 public void writeExternal(ObjectOutput objectOutput) throws IOException { 869 if (!persistent) { 870 ErrorManager.getDefault().log( 871 ErrorManager.INFORMATIONAL, 872 "Warning: This tasklist window (" + getName() + ") should not have been persisted!"); 873 return; 874 } 875 876 888 895 901 904 objectOutput.write(4); 907 objectOutput.writeObject(null); 910 } 916 917 920 abstract protected ColumnProperty[] createColumns(); 921 922 protected ColumnProperty getMainColumn(int width) { 923 return new ColumnProperty( 926 0, PROP_TASK_SUMMARY, 928 NbBundle.getMessage(TaskListView.class, "Description"), NbBundle.getMessage(TaskListView.class, "Description"), true, 931 width 932 ); 933 } 934 935 private Task unshowItem = null; 936 937 942 956 957 958 975 976 980 public void select(final Task item) { 981 982 if (isShowing() == false) return; 983 984 986 SwingUtilities.invokeLater(new Runnable () { 1000 public void run() { 1001 Node n = TaskNode.find(getExplorerManager().getRootContext(), 1002 item); 1003 1004 Node [] sel; 1005 if (n == null) { 1006 sel = new Node [0]; 1007 } else { 1008 sel = new Node []{n}; 1009 } 1010 try { 1011 getExplorerManager().setSelectedNodes(sel); 1012 } catch (PropertyVetoException e) { 1013 ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e); 1014 } 1015 } 1016 }); } 1018 1019 public void expandAll() { 1020 if (treeTable != null) { 1021 treeTable.expandAll(); 1022 } 1023 } 1024 1025 1039 public static TaskListView getCurrent() { 1040 1041 TopComponent activated = WindowManager.getDefault().getRegistry().getActivated(); 1042 if (activated instanceof TaskListView) { 1043 return (TaskListView) activated; 1044 } 1045 1046 if (views == null) { 1049 return null; 1050 } 1051 Collection vs = views.values(); 1052 Iterator it = vs.iterator(); 1053 TaskListView first = null; 1054 while (it.hasNext()) { 1055 Reference ref = (Reference ) it.next(); 1056 TaskListView tlv = (TaskListView) ref.get(); 1057 if (tlv == null) continue; if (tlv.isShowing()) { 1059 return tlv; 1060 } 1061 1062 if (first == null) { 1065 first = tlv; 1066 } 1067 } 1068 return first; 1069 } 1070 1071 1073 private List listeningViews = null; 1074 1075 protected final List getListeningViews() { 1076 return (listeningViews == null) ? Collections.EMPTY_LIST : listeningViews; 1077 } 1078 1079 1091 void registerListeners() { 1092 Lookup l = Lookup.getDefault(); 1095 Lookup.Template template = new Lookup.Template(TaskViewListener.class); 1096 Iterator it = l.lookup(template).allInstances().iterator(); 1097 if (it.hasNext()) { 1098 listeningViews = new ArrayList(4); 1099 } 1100 while (it.hasNext()) { 1101 TaskViewListener tl = (TaskViewListener) it.next(); 1102 listeningViews.add(tl); 1103 } 1104 } 1105 1106 1108 private void unregisterListeners() { 1109 listeningViews = null; 1110 } 1111 1112 public void showInMode() { 1115 if (!isOpened()) { 1116 Mode mode = WindowManager.getDefault().findMode("output"); if (mode != null) { 1118 mode.dockInto(TaskListView.this); 1119 } 1120 } 1121 open(); 1122 requestVisible(); 1123 requestActive(); 1124 } 1125 1126 1133 public void selectedTask(Task item) { 1134 if (listeningViews != null) { 1135 unshowItem = item; 1138 int n = listeningViews.size(); 1139 for (int i = 0; i < n; i++) { 1140 TaskViewListener tl = (TaskViewListener) listeningViews.get(i); 1141 tl.showTask(item, getAnnotation(item)); 1142 } 1143 } 1144 } 1145 1146 1151 public void warpedTask(Task item) { 1152 if (listeningViews != null) { 1154 unshowItem = item; 1157 int n = listeningViews.size(); 1158 for (int i = 0; i < n; i++) { 1159 TaskViewListener tl = (TaskViewListener) listeningViews.get(i); 1160 tl.showTask(item, null); 1161 } 1162 } 1163 } 1164 1165 public void addedTask(Task t) { 1166 } 1168 1169 public void removedTask(Task pt, Task task, int index) { 1170 if ((task == unshowItem) && (listeningViews != null)) { 1171 unshowItem = null; 1172 int n = listeningViews.size(); 1173 for (int i = 0; i < n; i++) { 1174 TaskViewListener tl = (TaskViewListener) listeningViews.get(i); 1175 tl.hideTask(); 1176 } 1177 } 1178 } 1179 1180 public void structureChanged(Task t) { 1181 } 1182 1183 1186 public TaskList getList() { 1187 ObservableList model = getModel(); 1189 assert model instanceof TaskList : "CCE " + model; 1190 return (TaskList) model; 1191 } 1192 1193 public ObservableList getModel() { 1194 return tasklist; 1195 } 1196 1197 1201 private synchronized Comparator getRowComparator( 1202 final Node.Property sortedByProperty, 1203 final boolean sortAscending, 1204 final boolean sortedByName, 1205 final boolean noSorting) { 1206 Comparator rowComparator = new Comparator() { 1207 public int compare(Object o1, Object o2) { 1208 if (o1 == o2) { 1209 return -1; 1210 } 1211 1212 Node n1 = (Node ) o1; 1213 Node n2 = (Node ) o2; 1214 1215 if (sortedByProperty == null && !sortedByName) { 1216 Node [] nodes = n1.getParentNode().getChildren().getNodes(); 1217 for (int i = 0; i < nodes.length; i++) { 1218 if (nodes[i].equals(n1)) 1219 return -1; 1220 else if (nodes[i].equals(n2)) 1221 return 1; 1222 } 1223 return 0; 1224 } 1225 1226 int res; 1227 if (sortedByName) { 1228 res = n1.getDisplayName().compareTo(n2.getDisplayName()); 1229 return sortAscending ? res : -res; 1230 } 1231 1232 Node.Property p1 = getNodeProperty(n1, sortedByProperty); 1233 Node.Property p2 = getNodeProperty(n2, sortedByProperty); 1234 1235 if (p1 == null && p2 == null) 1236 return 0; 1237 1238 try { 1239 if (p1 == null) 1240 res = -1; 1241 else if (p2 == null) 1242 res = 1; 1243 else { 1244 Object v1 = p1.getValue(); 1245 Object v2 = p2.getValue(); 1246 if (v1 == null && v2 == null) 1247 return 0; 1248 else if (v1 == null) 1249 res = -1; 1250 else if (v2 == null) 1251 res = 1; 1252 else { 1253 if (v1.getClass() != v2.getClass() || !(v1 instanceof Comparable )) { 1254 v1 = v1.toString(); 1255 v2 = v2.toString(); 1256 } 1257 res = ((Comparable ) v1).compareTo(v2); 1258 } 1259 } 1260 return sortAscending ? res : -res; 1261 } catch (Exception ex) { 1262 return 0; 1264 } 1265 } 1266 }; 1267 return rowComparator; 1268 } 1269 1270 private Node.Property getNodeProperty(Node node, Node.Property prop) { 1271 Node.PropertySet [] propsets = node.getPropertySets(); 1272 for (int i = 0, n = propsets.length; i < n; i++) { 1273 Node.Property [] props = propsets[i].getProperties(); 1274 1275 for (int j = 0, m = props.length; j < m; j++) { 1276 if (props[j].equals(prop)) { 1277 return props[j]; 1278 } 1279 } 1280 } 1281 return null; 1282 } 1283 1284 1285 1287 1293 public final Filter getFilter() { 1294 return activeFilter; 1296 } 1297 1298 1302 public FilterRepository getFilters() { 1303 if (filters == null) loadFilters(); 1304 assert filters != null : "Missing FilterRepository"; 1306 return filters; 1307 } 1308 1309 1310 public abstract Filter createFilter(); 1311 1312 1313 public final boolean isFiltered() { 1314 return getFilter() != null; 1315 } 1316 1317 protected void setFiltered() { 1318 if (getFilter() != null) { 1319 ((RemoveFilterAction) SystemAction.get(RemoveFilterAction.class)).enable(); 1320 } 1321 1322 1324 try { 1325 getExplorerManager().setSelectedNodes(new Node [0]); 1326 } catch (PropertyVetoException e) { 1327 ErrorManager.getDefault().notify(e); 1328 } 1329 1330 setRoot(); 1331 updateFilterCount(); 1332 } 1333 1334 1338 public void setFilter(Filter filter) { 1339 if (filter == null || getFilters().contains(filter)) { 1340 getFilters().setActive(filter); 1341 } 1342 1343 this.activeFilter = filter; 1344 setFiltered(); 1345 } 1346 1347 1350 public List getSortedChildren(Node node, 1351 Node.Property sortedByProperty, 1352 boolean sortAscending, 1353 boolean sortedByName, 1354 boolean noSorting) { 1355 Node [] firstNodes = node.getChildren().getNodes(); 1357 ArrayList nodes = new ArrayList(firstNodes.length); 1358 for (int i = 0; i < firstNodes.length; i++) { 1359 nodes.add(firstNodes[i]); 1360 } 1361 1362 Comparator comparator = getRowComparator(sortedByProperty, 1363 sortAscending, 1364 sortedByName, 1365 noSorting); 1366 Collections.sort(nodes, comparator); 1367 return nodes; 1368 } 1369 1370 private boolean lookupAttempted = false; 1371 1372 private static void invokeLater(Runnable runnable) { 1373 if (SwingUtilities.isEventDispatchThread()) { 1374 runnable.run(); 1375 } else { 1376 SwingUtilities.invokeLater(runnable); 1377 } 1378 } 1379 1380 1381 private boolean wrapWarned = false; 1382 1383 1384 private TreeNode findNextVisitable(TreeNode last, boolean wrapAround) { 1385 1386 1388 TreeNode next = null; 1389 if (last.getChildCount() > 0) { 1390 next = last.getChildAt(0); 1391 } else { 1392 TreeNode parent = last.getParent(); 1393 if (parent == null) { 1394 if (parent.getChildCount() > 0) { 1395 next = parent.getChildAt(0); 1396 } 1397 } else { 1398 int index = parent.getIndex(last); 1399 assert index != -1; 1400 index++; 1401 if (index < last.getParent().getChildCount()) { 1402 next = last.getParent().getChildAt(index); 1403 } 1404 } 1405 } 1406 1407 1409 if (next == null && wrapAround) { 1410 TreeNode parent = last; 1411 while (parent.getParent() != null) { 1412 parent = parent.getParent(); 1413 } 1414 if (parent.getChildCount() > 0) { 1415 next = parent.getChildAt(0); 1416 } 1417 } 1418 1419 if (next == null) return null; 1420 1421 1423 if (isVisitable(next)) { 1424 return next; 1425 } else { 1426 return findNextVisitable(next, wrapAround); 1427 } 1428 1429 } 1430 1431 1432 private static boolean isVisitable(TreeNode node) { 1433 Node nextNode = Visualizer.findNode(node); 1434 if (nextNode == null) return false; 1435 Task task = (Task) nextNode.getCookie(Task.class); 1436 return task != null && task.isVisitable(); 1437 } 1438 1439 1440 private void selectNode(Node node) { 1441 if (node != null) { 1442 Task nextTask = (Task) node.getCookie(Task.class); 1443 if (nextTask.getLine() != null) { 1444 TaskAnnotation anno = getAnnotation(nextTask); 1445 if (anno != null) { 1446 showTaskInEditor(nextTask, anno); 1447 } 1448 } 1449 select(nextTask); } 1451 } 1452 1453 1454 private static boolean isChildOf(TreeNode child, TreeNode root) { 1455 if (child == null) return false; 1456 if (child == root) return true; 1457 TreeNode parent = child.getParent(); 1458 while (parent != null) { 1459 if (parent == root) return true; 1460 parent = parent.getParent(); 1461 } 1462 return false; 1463 } 1464 1465 private TreeNode nextCandidate; 1468 private TreeNode prevCandidate; 1469 1470 1475 private Node currentlySelected(boolean tail) { 1476 Node [] selected = getExplorerManager().getSelectedNodes(); 1477 if (selected != null && selected.length != 0) { 1478 if (tail) { 1479 return selected[selected.length -1]; 1480 } else { 1481 return selected[0]; 1482 } 1483 } else { 1484 return null; 1485 } 1486 } 1487 1488 1489 protected final void nextTask() { 1490 1491 Node currentlySelected = currentlySelected(true); 1492 Node next = null; 1493 TreeNode nextVisitable = null; 1494 1495 if (currentlySelected == null) { 1496 1497 1499 TreeNode root = Visualizer.findVisualizer(getExplorerManager().getRootContext()); 1500 if (isChildOf(nextCandidate, root)) { 1501 if (isVisitable(nextCandidate)) { 1502 nextVisitable = nextCandidate; 1503 } else { 1504 nextVisitable = findNextVisitable(nextCandidate, wrapWarned); 1505 } 1506 } else { 1507 Node [] all = getExplorerManager().getRootContext().getChildren().getNodes(); 1509 if (all != null && all.length > 0) { 1510 nextVisitable = Visualizer.findVisualizer(all[0]); 1511 } 1512 } 1513 } else { 1514 TreeNode curr = Visualizer.findVisualizer(currentlySelected); 1515 prevCandidate = curr; 1516 nextVisitable = findNextVisitable(curr, wrapWarned); 1517 } 1518 1519 if (nextVisitable != null) { 1520 nextCandidate = findNextVisitable(nextVisitable, false); 1521 next = Visualizer.findNode(nextVisitable); 1522 } else { 1523 nextCandidate = null; 1524 } 1525 1526 if ((next == null) && !wrapWarned) { 1527 String msg = NbBundle.getBundle(TaskListView.class). 1528 getString("MSG_AtLastError"); StatusDisplayer.getDefault().setStatusText(msg); 1530 Toolkit.getDefaultToolkit().beep(); 1531 wrapWarned = true; 1532 } else { 1533 wrapWarned = false; 1534 } 1535 1536 selectNode(next); 1537 } 1538 1539 1540 private TreeNode findPrevVisitable(TreeNode last, boolean wrapAround) { 1541 1542 1544 TreeNode prev; 1545 int index = last.getParent().getIndex(last); 1546 assert index != -1; 1547 index--; 1548 if (index >= 0) { 1549 prev = last.getParent().getChildAt(index); 1550 } else { 1551 prev = last.getParent(); 1552 if (prev.getParent() == null) { 1553 prev = null; } 1555 } 1556 1557 1559 if (prev == null && wrapAround) { 1560 TreeNode parent = last; 1561 while (parent.getParent() != null) { 1562 parent = parent.getParent(); 1563 } 1564 prev = parent; 1565 while (prev.getChildCount() > 0) { 1566 prev = prev.getChildAt(prev.getChildCount() -1); 1567 } 1568 } 1569 1570 if (prev == null) return null; 1571 1572 1574 if (isVisitable(prev)) { 1575 return prev; 1576 } else { 1577 return findPrevVisitable(prev, wrapAround); 1578 } 1579 } 1580 1581 1582 protected final void prevTask() { 1583 1584 Node currentlySelected = currentlySelected(false); 1585 Node prev = null; 1586 TreeNode prevVisitable = null; 1587 1588 if (currentlySelected == null) { 1589 1590 1592 TreeNode root = Visualizer.findVisualizer(getExplorerManager().getRootContext()); 1593 if (isChildOf(prevCandidate, root)) { 1594 if (isVisitable(prevCandidate)) { 1595 prevVisitable = prevCandidate; 1596 } else { 1597 prevVisitable = findPrevVisitable(prevCandidate, wrapWarned); 1598 } 1599 } else { 1600 Node [] all = getExplorerManager().getRootContext().getChildren().getNodes(); 1602 if (all != null && all.length > 0) { 1603 prevVisitable = Visualizer.findVisualizer(all[all.length-1]); 1604 } 1605 } 1606 } else { 1607 TreeNode curr = Visualizer.findVisualizer(currentlySelected); 1608 nextCandidate = curr; 1609 prevVisitable = findPrevVisitable(curr, wrapWarned); 1610 } 1611 1612 if (prevVisitable != null) { 1613 prevCandidate = findNextVisitable(prevVisitable, false); 1614 prev = Visualizer.findNode(prevVisitable); 1615 } else { 1616 prevCandidate = null; 1617 } 1618 1619 if ((prev == null) && !wrapWarned) { 1620 String msg = NbBundle.getBundle(TaskListView.class). 1621 getString("MSG_AtFirstError"); StatusDisplayer.getDefault().setStatusText(msg); 1623 Toolkit.getDefaultToolkit().beep(); 1624 wrapWarned = true; 1625 } else { 1626 wrapWarned = false; 1627 } 1628 1629 selectNode(prev); 1630 } 1631 1632 1637 protected TaskAnnotation getAnnotation(Task task) { 1638 return new TaskAnnotation(task, this); 1639 } 1640 1641 protected void componentHidden() { 1642 hideTaskInEditor(); 1643 } 1644 1645 1646 protected final boolean isExpanded(Node n) { 1647 return treeTable.isExpanded(n); 1648 } 1649 1650 1651 protected final void setExpanded(Node n, boolean expanded) { 1652 if (expanded) { 1653 treeTable.expandNode(n); 1654 } else { 1655 treeTable.collapseNode(n); 1656 } 1657 } 1658 1659 1664 public final Node getEffectiveRoot() { 1665 return getExplorerManager().getRootContext(); 1666 } 1667 1668 1677 public void scheduleNodeExpansion(final Task target, 1678 final int hops) { 1679 SwingUtilities.invokeLater(new Runnable () { 1680 public void run() { 1681 Node n = TaskNode.find(getEffectiveRoot(), target); 1684 if (n != null) { 1685 setExpanded(n, true); 1686 } else if (hops < 50) { 1687 scheduleNodeExpansion(target, hops + 1); 1688 } 1689 } 1690 }); 1691 } 1692 1693 public void requestActive() { 1694 super.requestActive(); 1695 if (treeTable != null) { 1696 treeTable.getTable().requestFocus(); 1697 } 1698 } 1699 1700 1705 public final ColumnProperty[] getVisibleColumns() { 1706 TableColumnModel tcm = getTable().getColumnModel(); 1707 ColumnProperty[] all = getColumns(); 1708 List ret = new ArrayList(); 1709 ret.add(all[0]); 1710 for (int i = 0; i < tcm.getColumnCount(); i++) { 1711 String title = tcm.getColumn(i).getHeaderValue().toString(); 1712 for (int j = 1; j < all.length; j++) { 1713 if (title.equalsIgnoreCase(all[j].getDisplayName())) { 1714 ret.add(all[j]); 1715 break; 1716 } 1717 } 1718 } 1719 return (ColumnProperty[]) ret.toArray(new ColumnProperty[ret.size()]); 1720 } 1721 1722 1724 private final class PrevNextAction extends javax.swing.AbstractAction { 1725 private boolean prev; 1726 1727 public PrevNextAction (boolean prev) { 1728 this.prev = prev; 1729 } 1730 1731 public void actionPerformed (java.awt.event.ActionEvent actionEvent) { 1732 if (prev) { 1733 prevTask (); 1734 } else { 1735 nextTask (); 1736 } 1737 } 1738 1739 1740 } 1741} 1742 | Popular Tags |