1 3 27 28 30 package de.qfs.apps.qflog.logview; 31 32 34 import java.awt.BorderLayout ; 35 import java.awt.Color ; 36 import java.awt.Component ; 37 import java.awt.Frame ; 38 import java.awt.Dimension ; 39 import java.awt.Point ; 40 import java.awt.Rectangle ; 41 import java.awt.Toolkit ; 42 import java.awt.Window ; 43 import java.awt.event.ActionEvent ; 44 import java.awt.event.ActionListener ; 45 import java.awt.event.FocusAdapter ; 46 import java.awt.event.FocusEvent ; 47 import java.awt.event.KeyAdapter ; 48 import java.awt.event.KeyEvent ; 49 import java.awt.event.MouseAdapter ; 50 import java.awt.event.MouseEvent ; 51 52 import java.util.Enumeration ; 53 import java.util.Hashtable ; 54 import java.util.Observable ; 55 import java.util.Observer ; 56 import java.util.ResourceBundle ; 57 58 import javax.swing.Action ; 59 import javax.swing.AbstractAction ; 60 import javax.swing.BorderFactory ; 61 import javax.swing.ButtonModel ; 62 import javax.swing.Icon ; 63 import javax.swing.KeyStroke ; 64 import javax.swing.JCheckBoxMenuItem ; 65 import javax.swing.JLabel ; 66 import javax.swing.JMenu ; 67 import javax.swing.JMenuItem ; 68 import javax.swing.JPanel ; 69 import javax.swing.JPopupMenu ; 70 import javax.swing.JScrollPane ; 71 import javax.swing.JSplitPane ; 72 import javax.swing.JTable ; 73 import javax.swing.JViewport ; 74 import javax.swing.SwingUtilities ; 75 import javax.swing.border.Border ; 76 import javax.swing.event.ListSelectionEvent ; 77 import javax.swing.event.TableModelEvent ; 78 import javax.swing.event.TableModelListener ; 79 import javax.swing.table.DefaultTableCellRenderer ; 80 import javax.swing.table.JTableHeader ; 81 import javax.swing.table.TableColumnModel ; 82 import javax.swing.table.TableModel ; 83 import java.awt.datatransfer.StringSelection ; 84 85 import de.qfs.lib.command.CommandDistributor; 86 import de.qfs.lib.config.Configurator; 87 import de.qfs.lib.config.ConfigWrapper; 88 import de.qfs.lib.config.JSplitPaneConfigWrapper; 89 import de.qfs.lib.gui.DelayedListSelectionListener; 90 import de.qfs.lib.gui.FilteredAndSortedTableModel; 91 import de.qfs.lib.gui.Message; 92 import de.qfs.lib.gui.MultiPane; 93 import de.qfs.lib.gui.MultiPaneEvent; 94 import de.qfs.lib.gui.MultiPaneListener; 95 import de.qfs.lib.gui.SortedTableHelper; 96 import de.qfs.lib.gui.SortedTableHeaderCellRenderer; 97 import de.qfs.lib.gui.StatusLine; 98 import de.qfs.lib.gui.SwingUtil; 99 import de.qfs.lib.gui.TableModelFilter; 100 import de.qfs.lib.log.Log; 101 import de.qfs.lib.log.LogEntry; 102 import de.qfs.lib.log.LogFilter; 103 import de.qfs.lib.log.Logger; 104 import de.qfs.lib.option.BooleanOption; 105 import de.qfs.lib.option.IntegerOption; 106 import de.qfs.lib.option.Option; 107 import de.qfs.lib.option.OptionDialog; 108 import de.qfs.lib.option.OptionSet; 109 import de.qfs.lib.util.DelayedAction; 110 import de.qfs.lib.util.MapResourceBundle; 111 112 114 135 public class LogTableView 136 extends JPanel 137 implements Observer 138 { 139 141 144 private final static Logger logger = new Logger (LogTableView.class); 145 146 149 private final static String iconNames[] = { 150 "logTableView.icon.err", "logTableView.icon.errDetail", 151 "logTableView.icon.wrn", "logTableView.icon.wrnDetail", 152 "logTableView.icon.msg", "logTableView.icon.msgDetail", 153 "logTableView.icon.mtd", "logTableView.icon.mtdDetail", 154 "logTableView.icon.dbg", "logTableView.icon.dbgDetail"}; 155 156 159 private final static Icon [] icons = new Icon [iconNames.length]; 160 161 164 private transient LogTableModel model; 165 166 169 private transient boolean initialized; 170 171 174 private JLabel titleLabel; 175 176 179 private String titleBase; 180 181 184 private transient JTable table; 185 186 189 private transient JScrollPane tablePane; 190 191 194 private transient LogSorter sorter; 195 196 199 private transient LogTableFilter filter; 200 201 204 private transient boolean filterEnabled[] = 205 new boolean [LogTableModel.NUM_COLUMNS]; 206 207 210 private transient SortedTableHelper tableHelper; 211 212 215 private transient CellSelectionListener selListener; 216 217 220 private transient InitialFocusListener focusListener; 221 222 225 private transient TableKeyListener tableKeyListener; 226 227 230 private transient PopupListener popupListener; 231 232 235 private Markers markers; 236 237 240 private transient LogDetailView detailView; 241 242 245 private transient MultiPane multiPane; 246 247 251 private transient StatusLine statusLine; 252 253 256 private transient Search search; 257 258 261 private transient Configurator configurator = 262 new Configurator ("LogTable"); 263 264 267 private transient CommandDistributor commandDistributor; 268 269 272 private transient MapResourceBundle resources; 273 274 277 private OptionSet options = new OptionSet ("Options"); 278 279 282 private transient JPopupMenu popup; 283 284 287 private transient JMenu setMenu; 288 289 292 private transient JMenu goMenu; 293 294 297 private OptionDialog optionDialog; 298 299 302 private transient boolean logging; 303 304 308 311 private Action copySelectedAction; 312 313 316 private Action copyVisibleAction; 317 318 321 private Action copyAllAction; 322 323 326 private Action clearAction; 327 328 331 private Action reduceToVisibleAction; 332 333 336 private Action removeVisibleAction; 337 338 341 private Action toggleColumnFilterAction; 342 343 346 private Action clearColumnFiltersAction; 347 348 351 private Action setSortColumnAction; 352 353 356 private Action [] setMarkerActions; 357 358 361 private Action [] gotoMarkerActions; 362 363 366 private Action editOptionsAction; 367 368 370 372 377 public LogTableView(LogTableModel model) 378 { 379 this.model = model; 380 resources = new MapResourceBundle (); 381 resources.fetchProperties 382 ("/de/qfs/apps/qflog/logview/resources/properties/logtableview", 383 LogTableView.class); 384 } 385 386 388 393 398 public void init() 399 { 400 if (initialized) { 401 return; 402 } 403 initialized = true; 404 405 Option option = 406 new IntegerOption ("MaxRows", 3000, true, false); 407 option.addObserver(this); 408 options.add(option); 409 410 option = new BooleanOption ("ShowLines", true); 411 option.addObserver(this); 412 options.add(option); 413 414 initIcons(); 415 416 setLayout(new BorderLayout ()); 417 setBorder(null); 418 419 JPanel top = new JPanel (); 420 top.setLayout(new BorderLayout ()); 421 top.setBorder(null); 422 423 titleBase = resources.getString("logTableView.title", "Messages"); 424 titleLabel = new JLabel (titleBase); 425 titleLabel.setBorder(BorderFactory.createEtchedBorder()); 426 titleLabel.setHorizontalTextPosition(titleLabel.LEADING); 427 top.add(titleLabel, BorderLayout.NORTH); 428 429 String [] names = { 430 resources.getString("logTableView.table.level.title", "Level"), 431 resources.getString("logTableView.table.time.title", "Time"), 432 resources.getString("logTableView.table.thread.title", "Thread"), 433 resources.getString("logTableView.table.class.title", "Class"), 434 resources.getString("logTableView.table.method.title", "Method"), 435 resources.getString("logTableView.table.message.title", "Message") 436 }; 437 model.setColumnNames(names); 438 439 table = new JTable (model) { 440 public boolean isManagingFocus() 441 { 442 return false; 443 } 444 }; 445 JTableHeader header = new JTableHeader (table.getColumnModel()) { 446 public boolean isFocusTraversable() 447 { 448 return false; 449 } 450 }; 451 header.setRequestFocusEnabled(false); 452 table.setTableHeader(header); 453 table.setBorder(null); 454 setBackground(table.getBackground()); 455 table.setColumnSelectionAllowed(false); 456 table.setRowMargin(1); 457 table.setRowHeight(16); 458 sorter = new LogSorter ("Sorter"); 459 configurator.add(sorter); 460 461 table.setDefaultRenderer(Integer .class, new LevelRenderer (true)); 463 table.setDefaultRenderer(Object .class, new LevelRenderer (false)); 464 465 if (filter == null) { 466 filter = new LogTableFilter (); 467 filter.setLoggingEnabled(logging); 468 } 469 tableHelper = new SortedTableHelper (table, filter, sorter); 470 tableHelper.prepareTable(); 471 472 table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); 474 TableColumnModel tcm = table.getColumnModel(); 475 tcm.getColumn(model.COL_LEVEL).setIdentifier("Level"); 476 tcm.getColumn(model.COL_LEVEL).setPreferredWidth(24); 477 tcm.getColumn(model.COL_TIME).setIdentifier("Time"); 478 tcm.getColumn(model.COL_TIME).setPreferredWidth(94); 479 tcm.getColumn(model.COL_THREAD).setIdentifier("Thread"); 480 tcm.getColumn(model.COL_THREAD).setPreferredWidth(84); 481 tcm.getColumn(model.COL_CLASS).setIdentifier("Class"); 482 tcm.getColumn(model.COL_CLASS).setPreferredWidth(100); 483 tcm.getColumn(model.COL_METHOD).setIdentifier("Method"); 484 tcm.getColumn(model.COL_METHOD).setPreferredWidth(100); 485 tcm.getColumn(model.COL_DETAIL).setIdentifier("Message"); 486 tcm.getColumn(model.COL_DETAIL).setPreferredWidth(380); 487 488 configurator.add(ConfigWrapper.makeWrapper(table, "Table")); 489 490 table.getSelectionModel().setAnchorSelectionIndex(-1); 494 focusListener = new InitialFocusListener (); 495 table.addFocusListener(focusListener); 496 tableHelper.saveSelection(true); 497 tableHelper.setHeaderCellRenderer (new HeaderRenderer()); 498 tablePane = new JScrollPane (table); 499 SwingUtil.constrainScroll(tablePane); 500 tablePane.setBorder(BorderFactory.createLoweredBevelBorder()); 501 tablePane.getViewport().putClientProperty("EnableWindowBlit", "true"); 502 503 top.add(tablePane, BorderLayout.CENTER); 504 505 detailView = new LogDetailView (); 507 detailView.setLoggingEnabled(logging); 508 detailView.setResources(resources); 509 detailView.init(); 510 511 selListener = new CellSelectionListener (); 513 table.getSelectionModel().addListSelectionListener(selListener); 514 table.getColumnModel().getSelectionModel() 515 .addListSelectionListener(selListener); 516 table.getModel().addTableModelListener(selListener); 517 model.addTableModelListener(selListener); 518 519 markers = new Markers (); 521 model.addTableModelListener(markers); 522 523 multiPane = new MultiPane 525 ("MultiPane", MultiPane.VERTICAL, 526 top, detailView, 0.8, MultiPane.SHOW_BOTH); 527 configurator.add(multiPane); 528 add(multiPane, BorderLayout.CENTER); 529 530 tableKeyListener = new TableKeyListener (); 532 table.addKeyListener(tableKeyListener); 533 search = new Search (); 534 table.addKeyListener(search); 535 table.registerKeyboardAction 536 (search, "backsearch", 537 KeyStroke.getKeyStroke(KeyEvent.VK_BACK_SPACE, 0), 538 table.WHEN_FOCUSED); 539 table.registerKeyboardAction 540 (search, "copysearch", 541 KeyStroke.getKeyStroke(KeyEvent.VK_F2, 0), 542 table.WHEN_FOCUSED); 543 table.registerKeyboardAction 544 (search, "searchagain", 545 KeyStroke.getKeyStroke(KeyEvent.VK_F3, 0), 546 table.WHEN_FOCUSED); 547 table.registerKeyboardAction 548 (search, "clearsearch", 549 KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), 550 table.WHEN_FOCUSED); 551 table.registerKeyboardAction 552 (search, "revertsearch", 553 KeyStroke.getKeyStroke(KeyEvent.VK_R, KeyEvent.CTRL_MASK), 554 table.WHEN_FOCUSED); 555 556 setupActions(); 558 table.registerKeyboardAction 559 (toggleColumnFilterAction, "toggleFilter", 560 KeyStroke.getKeyStroke(KeyEvent.VK_F, KeyEvent.CTRL_MASK), 561 table.WHEN_FOCUSED); 562 563 table.registerKeyboardAction 564 (clearColumnFiltersAction, "clearFilters", 565 KeyStroke.getKeyStroke(KeyEvent.VK_K, KeyEvent.CTRL_MASK), 566 table.WHEN_FOCUSED); 567 568 table.registerKeyboardAction 569 (setSortColumnAction, "setSortColumn", 570 KeyStroke.getKeyStroke(KeyEvent.VK_S, KeyEvent.CTRL_MASK), 571 table.WHEN_FOCUSED); 572 573 popup = new JPopupMenu (); 575 fillMenu(popup); 576 popupListener = new PopupListener (); 577 table.addMouseListener(popupListener); 578 579 configurator.add(options); 580 } 581 582 585 588 public void cleanup() 589 { 590 if (logging && logger.level >= Log.MTD) { 591 logger.log(Log.MTD, "cleanup()", ""); 592 } 593 594 SwingUtil.cleanup(this); 595 596 statusLine = null; 597 598 table.removeFocusListener(focusListener); 599 focusListener = null; 600 601 table.getSelectionModel().removeListSelectionListener(selListener); 602 table.getColumnModel().getSelectionModel() 603 .removeListSelectionListener(selListener); 604 table.getModel().removeTableModelListener(selListener); 605 model.removeTableModelListener(selListener); 606 selListener = null; 607 608 model.removeTableModelListener(markers); 609 markers = null; 610 611 table.removeKeyListener(tableKeyListener); 612 tableKeyListener = null; 613 table.removeKeyListener(search); 614 search = null; 615 616 SwingUtil.cleanup(popup); 617 popup = null; 618 setMenu = null; 619 goMenu = null; 620 table.removeMouseListener(popupListener); 621 popupListener = null; 622 623 detailView.cleanup(); 624 detailView = null; 625 626 model.cleanup(); 627 model = null; 628 629 tableHelper = null; 630 table.resetKeyboardActions(); 631 table = null; 632 Option[] opts = options.getOptions(); 633 for (int i = 0; i < opts.length; i++) { 634 opts[i].deleteObservers(); 635 } 636 options = null; 637 resources = null; 638 } 639 640 643 646 public void finalize() 647 { 648 if (logging && logger.level >= Log.MTD) { 649 logger.log(Log.MTD, "finalize()", ""); 650 } 651 } 652 653 655 660 665 public final LogTableModel getModel() 666 { 667 return model; 668 } 669 670 673 678 public final JTable getTable() 679 { 680 return table; 681 } 682 683 686 691 public final MultiPane getMultiPane() 692 { 693 return multiPane; 694 } 695 696 699 704 public void fillMenu(JMenu menu) 705 { 706 JMenuItem mi = menu.add(copySelectedAction); 707 setMnemonic(mi, "copySelected"); 708 mi.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, 709 KeyEvent.CTRL_MASK)); 710 mi = menu.add(copyVisibleAction); 711 setMnemonic(mi, "copyVisible"); 712 mi = menu.add(copyAllAction); 713 setMnemonic(mi, "copyAll"); 714 715 mi = menu.add(clearAction); 716 setMnemonic(mi, "clear"); 717 mi.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_L, 718 KeyEvent.CTRL_MASK)); 719 mi = menu.add(reduceToVisibleAction); 720 setMnemonic(mi, "reduceToVisible"); 721 mi.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_I, 722 KeyEvent.CTRL_MASK)); 723 mi = menu.add(removeVisibleAction); 724 setMnemonic(mi, "removeVisible"); 725 menu.addSeparator(); 726 727 mi = menu.add(setSortColumnAction); 728 setMnemonic(mi, "setSortColumn"); 729 mi = menu.add(toggleColumnFilterAction); 730 setMnemonic(mi, "toggleColumnFilter"); 731 mi = menu.add(clearColumnFiltersAction); 732 setMnemonic(mi, "clearColumnFilters"); 733 734 menu.addSeparator(); 735 736 JMenu set = new JMenu (resources.getString 737 ("logTableView.action.setMarker.name", 738 "Set Mark")); 739 String mnemo = resources.getString 740 ("logTableView.action.setMarker.name", null); 741 if (mnemo != null) { 742 set.setMnemonic(mnemo.charAt(0)); 743 } 744 for (int i = 0; i <= 9; i++) { 745 mi = set.add(setMarkerActions[i]); 746 setMnemonic(mi, "setMarker" + i); 747 } 748 menu.add(set); 749 750 JMenu go = new JMenu (resources.getString 751 ("logTableView.action.gotoMarker.name", 752 "Goto Mark")); 753 mnemo = resources.getString 754 ("logTableView.action.gotoMarker.name", null); 755 if (mnemo != null) { 756 go.setMnemonic(mnemo.charAt(0)); 757 } 758 for (int i = 0; i <= 9; i++) { 759 mi = go.add(gotoMarkerActions[i]); 760 setMnemonic(mi, "gotoMarker" + i); 761 } 762 menu.add(go); 763 764 menu.addSeparator(); 765 766 mi = menu.add(editOptionsAction); 767 setMnemonic(mi, "editOptions"); 768 } 769 770 775 public void fillMenu(JPopupMenu menu) 776 { 777 menu.add(copySelectedAction); 778 menu.add(copyVisibleAction); 779 menu.add(copyAllAction); 780 781 menu.add(clearAction); 782 menu.add(reduceToVisibleAction); 783 menu.add(removeVisibleAction); 784 785 menu.addSeparator(); 786 787 menu.add(setSortColumnAction); 788 menu.add(toggleColumnFilterAction); 789 menu.add(clearColumnFiltersAction); 790 791 menu.addSeparator(); 792 793 setMenu = new JMenu (resources.getString 794 ("logTableView.action.setMarker.name", 795 "Set Mark")); 796 for (int i = 0; i <= 9; i++) { 797 setMenu.add(setMarkerActions[i]); 798 } 799 menu.add(setMenu); 800 801 goMenu = new JMenu (resources.getString 802 ("logTableView.action.gotoMarker.name", 803 "Goto Mark")); 804 for (int i = 0; i <= 9; i++) { 805 goMenu.add(gotoMarkerActions[i]); 806 } 807 menu.add(goMenu); 808 809 menu.addSeparator(); 810 811 menu.add(editOptionsAction); 812 } 813 814 817 823 public Configurator getConfigurator() 824 { 825 return configurator; 826 } 827 828 831 836 public final OptionSet getOptions() 837 { 838 return options; 839 } 840 841 842 845 857 public final void setLoggingEnabled(boolean enable) 858 { 859 logging = enable; 860 model.setLoggingEnabled(enable); 861 if (detailView != null) { 862 detailView.setLoggingEnabled(logging); 863 } 864 if (filter != null) { 865 filter.setLoggingEnabled(logging); 866 } 867 } 868 869 872 877 public void setStatusLine(StatusLine statusLine) 878 { 879 this.statusLine = statusLine; 880 if (search != null) { 881 search.setTitle(); 882 } 883 } 884 885 887 892 897 public void setCommandDistributor(CommandDistributor cd) 898 { 899 commandDistributor = cd; 900 } 901 902 905 910 private CommandDistributor getCommandDistributor() 911 { 912 return commandDistributor == null 913 ? CommandDistributor.getDefaultDistributor() 914 : commandDistributor; 915 } 916 917 920 926 public void setResources(ResourceBundle rb) 927 { 928 resources.addResources(rb); 929 } 930 931 932 935 940 public final void setFilter(TableModelFilter filter) 941 { 942 if (this.filter == null) { 943 this.filter = new LogTableFilter (filter); 944 this.filter.setLoggingEnabled(logging); 945 } else { 946 this.filter.setFilter(filter); 947 } 948 } 949 950 952 957 960 public void copySelectedToClipboard() 961 { 962 int[] rows = table.getSelectedRows(); 963 964 if (rows.length > 0) { 965 TableModel tm = table.getModel(); 966 StringBuffer sb = new StringBuffer (); 967 for (int i = 0; i < rows.length; i++) { 968 sb.append(((LogEntry) tm.getValueAt(rows[i], model.COL_ENTRY)) 969 .toString()); 970 sb.append("\n"); 971 } 972 StringSelection ss = new StringSelection (sb.toString()); 973 Toolkit.getDefaultToolkit().getSystemClipboard() 974 .setContents(ss, ss); 975 } 976 } 977 978 981 984 public void copyVisibleToClipboard() 985 { 986 if (table.getRowCount() > 0) { 987 TableModel tm = table.getModel(); 988 StringBuffer sb = new StringBuffer (); 989 for (int i = 0; i < table.getRowCount(); i++) { 990 sb.append(((LogEntry) tm.getValueAt(i, model.COL_ENTRY)) 991 .toString()); 992 sb.append("\n"); 993 } 994 StringSelection ss = new StringSelection (sb.toString()); 995 Toolkit.getDefaultToolkit().getSystemClipboard() 996 .setContents(ss, ss); 997 } 998 } 999 1000 1003 1007 public void copyAllToClipboard() 1008 { 1009 LogEntry[] data = model.getData(); 1010 if (data.length > 0) { 1011 StringBuffer sb = new StringBuffer (); 1012 for (int i = 0; i < data.length; i++) { 1013 sb.append(data[i].toString()); 1014 sb.append("\n"); 1015 } 1016 StringSelection ss = new StringSelection (sb.toString()); 1017 Toolkit.getDefaultToolkit().getSystemClipboard() 1018 .setContents(ss, ss); 1019 } 1020 } 1021 1022 1023 1024 1026 1031 1034 public void clearAll() 1035 { 1036 selListener.forgetSavedRow(); 1037 model.setData(new LogEntry[0]); 1038 } 1039 1040 1043 1046 public void reduceToVisible() 1047 { 1048 selListener.forgetSavedRow(); 1049 model.reduceToVisible(filter); 1050 } 1051 1052 1055 1058 public void removeVisible() 1059 { 1060 selListener.forgetSavedRow(); 1061 model.removeVisible(filter); 1062 } 1063 1064 1066 1071 1076 public void showDetail(boolean show) 1077 { 1078 if (logging && logger.level >= Log.MTD) { 1079 logger.log(Log.MTD, "showDetail(boolean)", 1080 logger.level < Log.MTDDETAIL ? "" : 1081 "show: " + show); 1082 } 1083 multiPane.setShowing(show 1084 ? multiPane.SHOW_BOTH 1085 : multiPane.SHOW_FIRST); 1086 } 1087 1088 1091 1094 private void toggleDetail() 1095 { 1096 if (logging && logger.level >= Log.MTD) { 1097 logger.log(Log.MTD, "showDetail()", ""); 1098 } 1099 showDetail(multiPane.getShowing() != multiPane.SHOW_BOTH); 1100 } 1101 1102 1104 1109 1115 public void update(Observable obj, Object arg) 1116 { 1117 if (logging && logger.level >= Log.MTD) { 1118 logger.log(Log.MTD, "update(Observable,Object)", 1119 logger.level < Log.MTDDETAIL ? "" : 1120 "obj: " + obj + ", " + 1121 "arg: " + arg); 1122 } 1123 if (obj instanceof Option) { 1124 boolean excluded = ! logging; 1125 if (excluded) { 1126 Log.excludeThread(); 1127 } 1128 try { 1129 Option option = (Option) obj; 1130 if (option.getName().equals("MaxRows")) { 1131 model.setMaxRows(options.getInt("MaxRows", 0)); 1132 } else if (option.getName().equals("ShowLines")) { 1133 if (options.getBoolean("ShowLines", true)) { 1134 table.getColumnModel().setColumnMargin(1); 1135 table.setRowMargin(1); 1136 table.setRowHeight(16); 1137 table.setShowVerticalLines(true); 1138 table.setShowHorizontalLines(true); 1139 } else { 1140 table.getColumnModel().setColumnMargin(0); 1141 table.setRowMargin(0); 1142 table.setRowHeight(17); 1143 table.setShowVerticalLines(false); 1144 table.setShowHorizontalLines(false); 1145 } 1146 } 1147 } finally { 1148 if (excluded) { 1149 Log.includeThread(); 1150 } 1151 } 1152 } 1153 } 1154 1155 1157 1162 1165 private void initIcons() 1166 { 1167 if (icons[0] == null) { 1168 for (int i = 0; i < icons.length; i++) { 1169 icons[i] = resources.getIcon(iconNames[i], null); 1170 } 1171 } 1172 } 1173 1174 1177 1180 private void setupActions() 1181 { 1182 if (copySelectedAction == null) { 1184 copySelectedAction = new AbstractAction () { 1185 public void actionPerformed (ActionEvent e) { 1186 copySelectedToClipboard(); 1187 } 1188 }; 1189 setActionProperties(copySelectedAction, "copySelected"); 1190 1191 copyVisibleAction = new AbstractAction () { 1192 public void actionPerformed (ActionEvent e) { 1193 copyVisibleToClipboard(); 1194 } 1195 }; 1196 setActionProperties(copyVisibleAction, "copyVisible"); 1197 1198 copyAllAction = new AbstractAction () { 1199 public void actionPerformed (ActionEvent e) { 1200 copyAllToClipboard(); 1201 } 1202 }; 1203 setActionProperties(copyAllAction, "copyAll"); 1204 1205 clearAction = new AbstractAction () { 1206 public void actionPerformed (ActionEvent e) { 1207 clearAll(); 1208 } 1209 }; 1210 setActionProperties(clearAction, "clear"); 1211 1212 reduceToVisibleAction = new AbstractAction () { 1213 public void actionPerformed (ActionEvent e) { 1214 reduceToVisible(); 1215 } 1216 }; 1217 setActionProperties(reduceToVisibleAction, "reduceToVisible"); 1218 1219 removeVisibleAction = new AbstractAction () { 1220 public void actionPerformed (ActionEvent e) { 1221 removeVisible(); 1222 } 1223 }; 1224 setActionProperties(removeVisibleAction, "removeVisible"); 1225 1226 toggleColumnFilterAction = new AbstractAction () { 1227 public void actionPerformed (ActionEvent e) { 1228 int row = table.getSelectionModel() 1229 .getAnchorSelectionIndex(); 1230 int column = table.getColumnModel().getSelectionModel() 1231 .getAnchorSelectionIndex(); 1232 if (row == -1 || column == -1) { 1233 return; 1234 } 1235 int ccol = table.convertColumnIndexToModel(column); 1236 filterCell(row, ccol); 1237 } 1238 }; 1239 setActionProperties(toggleColumnFilterAction, 1240 "toggleColumnFilter"); 1241 1242 clearColumnFiltersAction = new AbstractAction () { 1243 public void actionPerformed (ActionEvent e) { 1244 filter.clearFilters(); 1245 for (int i = 0; i < filterEnabled.length; i++) { 1246 filterEnabled[i] = false; 1247 table.getTableHeader().repaint(); 1248 } 1249 } 1250 }; 1251 setActionProperties(clearColumnFiltersAction, 1252 "clearColumnFilters"); 1253 1254 setSortColumnAction = new AbstractAction () { 1255 public void actionPerformed (ActionEvent e) { 1256 boolean excluded = ! logging; 1257 if (excluded) { 1258 Log.excludeThread(); 1259 } 1260 try { 1261 int column = table.getColumnModel().getSelectionModel() 1262 .getAnchorSelectionIndex(); 1263 if (column == -1) { 1264 return; 1265 } 1266 int ccol = table.convertColumnIndexToModel(column); 1267 sorter.setSortColumn(ccol); 1268 } finally { 1269 if (excluded) { 1270 Log.includeThread(); 1271 } 1272 } 1273 } 1274 }; 1275 setActionProperties(setSortColumnAction, 1276 "setSortColumn"); 1277 1278 setMarkerActions = new Action [10]; 1279 gotoMarkerActions = new Action [10]; 1280 for (int i = 0; i <= 9; i++) { 1281 setMarkerActions[i] = new SetMarkerAction ("" + i); 1282 setActionProperties(setMarkerActions[i], "setMarker" + i); 1283 gotoMarkerActions[i] = new GotoMarkerAction ("" + i); 1284 setActionProperties(gotoMarkerActions[i], "gotoMarker" + i); 1285 } 1286 1287 editOptionsAction = new AbstractAction () { 1288 public void actionPerformed (ActionEvent e) { 1289 editOptions(); 1290 } 1291 }; 1292 setActionProperties(editOptionsAction, 1293 "editOptions"); 1294 1295 } 1296 } 1297 1298 1301 1307 private void setActionProperties(Action action, String resource) 1308 { 1309 String name = resources.getString 1310 ("logTableView.action." + resource + ".name", null); 1311 if (name != null) { 1312 action.putValue(Action.NAME, name); 1313 } 1314 1315 String iconName = resources.getString 1316 ("logTableView.action." + resource + ".icon", null); 1317 if (iconName != null) { 1318 Icon icon = resources.getIcon (iconName, null); 1319 if (icon != null) { 1320 action.putValue(Action.SMALL_ICON, icon); 1321 } 1322 } 1323 } 1324 1325 1328 1335 private void setMnemonic(JMenuItem mi, String resource) 1336 { 1337 String mnemo = resources.getString 1338 ("logTableView.action." + resource + ".mnemonic", null); 1339 if (mnemo != null) { 1340 mi.setMnemonic(mnemo.charAt(0)); 1341 } 1342 } 1343 1344 1347 1350 private void editOptions() 1351 { 1352 if (logging && logger.level >= Log.MTD) { 1353 logger.log(Log.MTD, "editOptions()", ""); 1354 } 1355 1356 boolean excluded = ! logging; 1357 if (excluded) { 1358 Log.excludeThread(); 1359 } 1360 try { 1361 Frame frame; 1362 Window win = SwingUtilities.windowForComponent(this); 1363 if (win instanceof Frame ) { 1364 frame = (Frame ) win; 1365 } else { 1366 frame = new Frame (); 1368 } 1369 if (optionDialog == null) { 1370 optionDialog = new OptionDialog 1371 (frame, resources.getString 1372 ("logTableView.optionDialog.title", "MISSING"), 1373 options, "tableview"); 1374 } else { 1375 optionDialog.update(options); 1376 } 1377 optionDialog.setLocationRelativeTo(this); 1378 optionDialog.doModal(); 1379 } finally { 1380 if (excluded) { 1381 Log.includeThread(); 1382 } 1383 } 1384 } 1385 1386 1388 1390 1397 private void restoreRow(int row, int column) 1398 { 1399 if (logging && logger.level >= Log.MTD) { 1400 logger.log(Log.MTD, "restoreRow(int,int)", 1401 logger.level < Log.MTDDETAIL ? "" : 1402 "row: " + row + ", " + 1403 "column: " + column); 1404 } 1405 if (row >= 0) { 1406 int i; 1407 FilteredAndSortedTableModel filteredTableModel = 1408 (FilteredAndSortedTableModel) table.getModel(); 1409 for (i = 0; i < filteredTableModel.getRowCount(); i++) { 1411 if (row == filteredTableModel.getMappedRow(i)) { 1412 break; 1413 } 1414 } 1415 if (i == filteredTableModel.getRowCount()) { 1417 for (i = 0; i < filteredTableModel.getRowCount(); i++) { 1418 if (sorter.compare 1419 (model, row, 1420 filteredTableModel.getMappedRow(i)) <= 0) { 1421 break; 1422 } 1423 } 1424 } 1425 1426 if (i == filteredTableModel.getRowCount()) { 1427 i--; 1428 } 1429 1430 jumpToRow(i, false); 1431 1432 if (column >= 0) { 1433 table.addColumnSelectionInterval(column, column); 1434 } 1435 } 1436 } 1437 1438 1441 1448 private void jumpToRow(int row, boolean always) 1449 { 1450 Rectangle rect = table.getCellRect(row, 0, false); 1452 JViewport vp = (JViewport ) table.getParent(); 1453 Dimension vs = vp.getSize(); 1454 Point pos = vp.getViewPosition(); 1455 if (!always) { 1456 if (pos.y <= rect.y 1457 && pos.y + vs.height >= rect.y + rect.height) { 1458 table.addRowSelectionInterval(row, row); 1460 return; 1461 } 1462 } 1463 Dimension size = table.getSize(); 1464 pos.y = rect.y - (vs.height - rect.height) / 2; 1465 if (pos.y + vs.height > size.height) { 1466 pos.y = size.height - vs.height; 1467 } 1468 if (pos.y < 0) { 1469 pos.y = 0; 1470 } 1471 ((JViewport ) table.getParent()).setViewPosition(pos); 1472 table.getParent().repaint(); 1473 1474 table.addRowSelectionInterval(row, row); 1475 table.getSelectionModel().setAnchorSelectionIndex(row); 1476 } 1477 1478 1481 1487 private void filterCell(int row, int column) 1488 { 1489 LogEntry entry = (LogEntry) table.getValueAt(row, model.COL_ENTRY); 1490 switch (column) { 1491 case model.COL_LEVEL: 1492 filter.setFilterLevel(entry.getLevel()); 1493 filterEnabled[model.COL_LEVEL] = ! filterEnabled[model.COL_LEVEL]; 1494 table.getTableHeader().repaint(); 1495 break; 1496 case model.COL_THREAD: 1497 filter.setFilterThread(entry.getThread()); 1498 filterEnabled[model.COL_THREAD] = 1499 ! filterEnabled[model.COL_THREAD]; 1500 table.getTableHeader().repaint(); 1501 break; 1502 case model.COL_CLASS: 1503 filter.setFilterClass(entry.getClazz()); 1504 filterEnabled[model.COL_CLASS] = ! filterEnabled[model.COL_CLASS]; 1505 table.getTableHeader().repaint(); 1506 break; 1507 case model.COL_METHOD: 1508 filter.setFilterMethod(entry.getMethod()); 1509 filterEnabled[model.COL_METHOD] = 1510 ! filterEnabled[model.COL_METHOD]; 1511 table.getTableHeader().repaint(); 1512 break; 1513 } 1514 } 1515 1516 1518 1523 1525 1528 private final static Logger mLogger = new Logger (Markers.class); 1529 1530 1532 1536 private class Markers 1537 implements TableModelListener 1538 { 1539 1541 1544 private Hashtable markers = new Hashtable (); 1545 1546 1548 1550 1553 public Markers () 1554 { 1555 } 1556 1557 1559 1561 1567 public void addMarker(String id, int row) 1568 { 1569 if (logging && mLogger.level >= Log.MTD) { 1570 mLogger.log(Log.MTD, "addMarker(String,int)", 1571 mLogger.level < Log.MTDDETAIL ? "" : 1572 "id: " + id + ", " + 1573 "row: " + row); 1574 } 1575 markers.put(id, new Integer (row)); 1576 if (statusLine != null) { 1577 statusLine.setTemporaryMessage 1578 (Message.format("logTableView.setMark", 1579 new String [] {id})); 1580 } 1581 } 1582 1583 1584 1587 1592 public void removeMarker(String id) 1593 { 1594 if (logging && mLogger.level >= Log.MTD) { 1595 mLogger.log(Log.MTD, "removeMarker(String)", 1596 mLogger.level < Log.MTDDETAIL ? "" : 1597 "id: " + id); 1598 } 1599 markers.remove(id); 1600 } 1601 1602 1605 1608 public void clearMarkers() 1609 { 1610 if (logging && mLogger.level >= Log.MTD) { 1611 mLogger.log(Log.MTD, "clearMarkers()", ""); 1612 } 1613 markers.clear(); 1614 } 1615 1616 1619 1624 public void jumpToMarker(String id) 1625 { 1626 if (logging && mLogger.level >= Log.MTD) { 1627 mLogger.log(Log.MTD, "jumpToMarker(String)", 1628 mLogger.level < Log.MTDDETAIL ? "" : 1629 "id: " + id); 1630 } 1631 Integer row = (Integer ) markers.get(id); 1632 if (row != null) { 1633 if (statusLine != null) { 1634 statusLine.setTemporaryMessage 1635 (Message.format("logTableView.jumpToMark", 1636 new String [] {id})); 1637 } 1638 table.clearSelection(); 1639 restoreRow(row.intValue(), -1); 1640 } 1641 } 1642 1643 1645 1647 1652 public void tableChanged(TableModelEvent event) 1653 { 1654 int start = event.getFirstRow(); 1655 int end = event.getLastRow(); 1656 if (logging && mLogger.level >= Log.MTD) { 1657 mLogger.log(Log.MTD, "tableChanged(TableModelEvent)", 1658 mLogger.level < Log.MTDDETAIL ? "" : 1659 ", start: " + start + 1660 ", end: " + end); 1661 } 1662 if (markers.size() >= 0) { 1663 int type = event.getType(); 1664 int diff = end - start + 1; 1665 if (start == event.HEADER_ROW 1666 || (start == 0 && end >= model.getRowCount() 1667 && type == event.UPDATE)) { 1668 if (logging && mLogger.level >= Log.DBG) { 1670 mLogger.log(Log.DBG, 1671 "tableChanged(TableModelEvent)", 1672 "markers cleared"); 1673 } 1674 clearMarkers(); 1675 } else if (type == event.INSERT) { 1676 for (Enumeration e = markers.keys(); 1677 e.hasMoreElements(); ) { 1678 String id = (String ) e.nextElement(); 1679 Integer row = (Integer ) markers.get(id); 1680 if (start <= row.intValue()) { 1681 markers.put(id, 1682 new Integer (row.intValue() + diff)); 1683 if (logging && mLogger.level >= Log.DBG) { 1684 mLogger.log(Log.DBG, 1685 "tableChanged(TableModelEvent)", 1686 "marker " + id + " moved up"); 1687 } 1688 } 1689 } 1690 } else if (type == event.DELETE) { 1691 for (Enumeration e = markers.keys(); 1692 e.hasMoreElements(); ) { 1693 String id = (String ) e.nextElement(); 1694 Integer row = (Integer ) markers.get(id); 1695 if (start <= row.intValue()) { 1696 if (end >= row.intValue()) { 1697 markers.remove(id); 1698 if (logging && mLogger.level >= Log.DBG) { 1699 mLogger.log(Log.DBG, 1700 "tableChanged(TableModelEvent)", 1701 "marker " + id + " removed"); 1702 } 1703 } else { 1704 markers.put(id, new Integer 1705 (row.intValue() - diff)); 1706 if (logging && mLogger.level >= Log.DBG) { 1707 mLogger.log(Log.DBG, 1708 "tableChanged(TableModelEvent)", 1709 "marker " + id + " moved down"); 1710 } 1711 } 1712 } 1713 } 1714 } 1715 } 1716 } 1717 1718 } 1720 1721 1724 private class SetMarkerAction 1725 extends AbstractAction 1726 { 1727 1730 private String marker; 1731 1732 1734 public SetMarkerAction (String marker) 1735 { 1736 this.marker = marker; 1737 } 1738 1739 1741 1743 1748 public void actionPerformed(ActionEvent e) 1749 { 1750 int row = table.getSelectionModel().getAnchorSelectionIndex(); 1751 if (row >= 0) { 1752 row = ((FilteredAndSortedTableModel) table.getModel()) 1753 .getMappedRow(row); 1754 markers.addMarker(marker, row); 1755 } 1756 } 1757 1758 } 1760 1761 1764 private class GotoMarkerAction 1765 extends AbstractAction 1766 { 1767 1770 private String marker; 1771 1772 1774 public GotoMarkerAction (String marker) 1775 { 1776 this.marker = marker; 1777 } 1778 1779 1781 1783 1788 public void actionPerformed(ActionEvent e) 1789 { 1790 int row = table.getSelectionModel().getAnchorSelectionIndex(); 1791 markers.jumpToMarker(marker); 1792 } 1793 1794 } 1796 1797 1799 1804 1806 1809 private final static int KEY_MASK = 1810 KeyEvent.SHIFT_MASK | KeyEvent.CTRL_MASK | KeyEvent.ALT_MASK; 1811 1812 1817 protected class TableKeyListener 1818 extends KeyAdapter 1819 { 1820 1822 1826 private int row = -1; 1827 1828 1831 DelayedAction delayed = new DelayedAction (300); 1832 1833 1836 private Runnable restoreSel = new Runnable () { 1837 public void run() 1838 { 1839 if (row >= 0) { 1840 table.getSelectionModel().setSelectionInterval(row, row); 1841 row = -1; 1842 } 1843 } 1844 }; 1845 1846 1848 1850 1855 public void keyPressed(KeyEvent e) { 1856 if (e.getKeyCode() == e.VK_UP 1857 && (e.getModifiers() & KEY_MASK) == e.ALT_MASK) { 1858 e.consume(); 1859 fastUp(); 1860 } else if (e.getKeyCode() == e.VK_DOWN 1861 && (e.getModifiers() & KEY_MASK) == e.ALT_MASK) { 1862 e.consume(); 1863 fastDown(); 1864 } else if (e.getKeyCode() >= e.VK_0 && e.getKeyCode() <= e.VK_9 1865 && (e.getModifiers() & KEY_MASK) == e.ALT_MASK) { 1866 e.consume(); 1868 int row = table.getSelectionModel().getAnchorSelectionIndex(); 1869 if (row >= 0) { 1870 row = ((FilteredAndSortedTableModel) table.getModel()) 1871 .getMappedRow(row); 1872 char c = (char) ('0' + e.getKeyCode() - e.VK_0); 1873 markers.addMarker("" + c, row); 1874 } 1875 } else if (e.getKeyCode() >= e.VK_0 && e.getKeyCode() <= e.VK_9 1876 && (e.getModifiers() & KEY_MASK) == e.CTRL_MASK) { 1877 e.consume(); 1878 char c = (char) ('0' + e.getKeyCode() - e.VK_0); 1879 markers.jumpToMarker("" + c); 1880 } 1881 } 1882 1883 1885 1887 private void fastUp() 1888 { 1889 if (row < 0) { 1890 row = table.getSelectionModel().getAnchorSelectionIndex(); 1891 } 1892 if (row == 0) { 1893 return; 1894 } 1895 row--; 1896 JViewport vp = tablePane.getViewport(); 1897 Point pos = vp.getViewPosition(); 1898 if (pos.y > 0) { 1899 pos.y -= table.getRowHeight() + table.getRowMargin(); 1900 if (pos.y < 0) { 1901 pos.y = 0; 1902 } 1903 vp.setViewPosition(pos); 1904 delayed.perform(restoreSel); 1905 } else { 1906 table.getSelectionModel() 1907 .setSelectionInterval(row, row); 1908 row = -1; 1909 } 1910 } 1911 1912 1915 private void fastDown() 1916 { 1917 if (row < 0) { 1918 row = table.getSelectionModel().getAnchorSelectionIndex(); 1919 } 1920 if (row == table.getRowCount() - 1) { 1921 return; 1922 } 1923 row++; 1924 JViewport vp = tablePane.getViewport(); 1925 Point pos = vp.getViewPosition(); 1926 Dimension vs = vp.getViewSize(); 1927 if (pos.y + vp.getSize().height < vs.height) { 1928 pos.y += table.getRowHeight() + table.getRowMargin(); 1929 if (pos.y + vp.getSize().height > vs.height) { 1930 pos.y = vs.height - vp.getSize().height; 1931 } 1932 vp.setViewPosition(pos); 1933 delayed.perform(restoreSel); 1934 } else { 1935 table.getSelectionModel() 1936 .setSelectionInterval(row, row); 1937 row = -1; 1938 } 1939 } 1940 1941 } 1943 1944 1947 1950 private class Search 1951 extends KeyAdapter 1952 implements ActionListener 1953 { 1954 1956 1959 private long lastTimestamp = 0; 1960 1961 1964 private StringBuffer search = new StringBuffer (); 1965 1966 1969 private int lastLevel = -1; 1970 1971 1974 private boolean reverse = false; 1975 1976 1979 private boolean wrapped = false; 1980 1981 1984 private boolean found = false; 1985 1986 1989 private String searchTitle = 1990 resources.getString("logTableView.search.title", "search"); 1991 1992 1995 private String rsearchTitle = 1996 resources.getString("logTableView.rsearch.title", "rsearch"); 1997 1998 2001 private String wrappedTitle = 2002 resources.getString("logTableView.wrapped.title", "wrapped"); 2003 2004 2007 private String notFoundTitle = 2008 resources.getString("logTableView.notFound.title", "not found"); 2009 2010 2012 2014 2019 public void keyPressed(KeyEvent e) 2020 { 2021 char c = e.getKeyChar(); 2022 if ((e.getModifiers() & (e.ALT_MASK | e.CTRL_MASK)) == 0 2023 && c != e.CHAR_UNDEFINED 2024 && ! Character.isISOControl(c)) { 2025 e.consume(); 2026 2027 c = Character.toLowerCase(c); 2028 2029 int row = table.getSelectionModel().getAnchorSelectionIndex(); 2030 int column = table.getColumnModel().getSelectionModel() 2031 .getAnchorSelectionIndex(); 2032 if (row == -1 || column == -1) { 2033 return; 2034 } 2035 2036 int ccol = table.convertColumnIndexToModel(column); 2037 wrapped = false; 2038 if (ccol == model.COL_LEVEL) { 2039 if (Character.isDigit(c)) { 2040 lastLevel = c == '0' ? 10 : c - '0'; 2041 searchRow(row, lastLevel, reverse); 2042 } 2043 search.setLength(0); 2044 } else { 2045 lastLevel = -1; 2046 search.append(c); 2047 searchRow(row, column, search.toString(), true, reverse); 2049 } 2050 lastTimestamp = e.getWhen(); 2051 setTitle(); 2052 } 2053 } 2054 2055 2058 2063 public void actionPerformed (ActionEvent event) 2064 { 2065 int pos = event.paramString().lastIndexOf ("="); 2066 if (pos == -1) { 2067 return; 2068 } 2069 2070 int row = table.getSelectionModel().getAnchorSelectionIndex(); 2071 int column = table.getColumnModel().getSelectionModel() 2072 .getAnchorSelectionIndex(); 2073 if (row == -1 || column == -1) { 2074 return; 2075 } 2076 int ccol = table.convertColumnIndexToModel(column); 2077 2078 boolean excluded = ! logging; 2079 if (excluded) { 2080 Log.excludeThread(); 2081 } 2082 try { 2083 String cmd = event.paramString().substring (pos + 1); 2084 if (cmd.equals("backsearch")) { 2085 wrapped = false; 2086 found = true; 2087 if (ccol != model.COL_LEVEL && search.length() > 0) { 2088 search.setLength(search.length() - 1); 2089 } 2090 setTitle(); 2091 } else if (cmd.equals("copysearch")) { 2092 if (ccol != model.COL_LEVEL) { 2093 wrapped = false; 2094 found = true; 2095 search = new StringBuffer 2096 (((String ) table.getValueAt(row, column)) 2097 .toLowerCase()); 2098 setTitle(); 2099 } 2100 } else if (cmd.equals("searchagain")) { 2101 if (ccol == model.COL_LEVEL) { 2102 if (lastLevel >= 0) { 2103 wrapped = false; 2104 searchRow(row, lastLevel, reverse); 2105 setTitle(); 2106 } 2107 } else if (search.length() > 0) { 2108 wrapped = false; 2109 searchRow(row, column, search.toString(), false, 2110 reverse); 2111 setTitle(); 2112 } 2113 } else if (cmd.equals("clearsearch")) { 2114 wrapped = false; 2115 search.setLength(0); 2116 lastLevel = -1; 2117 setTitle(); 2118 } else if (cmd.equals("revertsearch")) { 2119 wrapped = false; 2120 found = true; 2121 reverse = !reverse; 2122 setTitle(); 2123 } 2124 } finally { 2125 if (excluded) { 2126 Log.includeThread(); 2127 } 2128 } 2129 } 2130 2131 2133 2135 2145 private void searchRow(int row, int column, String find, 2146 boolean expand, boolean reverse) 2147 { 2148 found = false; 2149 int len = find.length(); 2150 if (reverse) { 2151 for (int i = row - (expand ? 0 : 1); i >= 0; i--) { 2152 String val = (String ) table.getValueAt(i, column); 2153 if (val.length() >= len && 2154 val.toLowerCase().indexOf(find) >= 0) { 2155 jumpToRow(i, false); 2156 table.getSelectionModel().setSelectionInterval(i, i); 2157 found = true; 2158 break; 2159 } 2160 } 2161 for (int i = table.getRowCount() - 1; !found && i > row; i--) { 2162 String val = (String ) table.getValueAt(i, column); 2163 if (val.length() >= len && 2164 val.toLowerCase().indexOf(find) >= 0) { 2165 jumpToRow(i, false); 2166 table.getSelectionModel().setSelectionInterval(i, i); 2167 found = true; 2168 wrapped = true; 2169 break; 2170 } 2171 } 2172 } else { 2173 for (int i = row + (expand ? 0 : 1); 2174 i < table.getRowCount(); i++) { 2175 String val = (String ) table.getValueAt(i, column); 2176 if (val.length() >= len && 2177 val.toLowerCase().indexOf(find) >= 0) { 2178 jumpToRow(i, false); 2179 table.getSelectionModel().setSelectionInterval(i, i); 2180 found = true; 2181 break; 2182 } 2183 } 2184 for (int i = 0; !found && i < row; i++) { 2185 String val = (String ) table.getValueAt(i, column); 2186 if (val.length() >= len && 2187 val.toLowerCase().indexOf(find) >= 0) { 2188 jumpToRow(i, false); 2189 table.getSelectionModel().setSelectionInterval(i, i); 2190 found = true; 2191 wrapped = true; 2192 break; 2193 } 2194 } 2195 } 2196 } 2197 2198 2205 private void searchRow(int row, int level, boolean reverse) 2206 { 2207 found = false; 2208 if (reverse) { 2209 for (int i = row - 1; i >= 0; i--) { 2210 if (((LogEntry) table.getValueAt(i, model.COL_ENTRY)) 2211 .getLevel() == level) { 2212 jumpToRow(i, false); 2213 table.getSelectionModel().setSelectionInterval(i, i); 2214 found = true; 2215 break; 2216 } 2217 } 2218 for (int i = table.getRowCount() - 1; !found && i > row; i--) { 2219 if (((LogEntry) table.getValueAt(i, model.COL_ENTRY)) 2220 .getLevel() == level) { 2221 jumpToRow(i, false); 2222 table.getSelectionModel().setSelectionInterval(i, i); 2223 found = true; 2224 wrapped = true; 2225 break; 2226 } 2227 } 2228 } else { 2229 for (int i = row + 1; i < table.getRowCount(); i++) { 2230 if (((LogEntry) table.getValueAt(i, model.COL_ENTRY)) 2231 .getLevel() == level) { 2232 jumpToRow(i, false); 2233 table.getSelectionModel().setSelectionInterval(i, i); 2234 found = true; 2235 break; 2236 } 2237 } 2238 for (int i = 0; !found && i < row; i++) { 2239 if (((LogEntry) table.getValueAt(i, model.COL_ENTRY)) 2240 .getLevel() == level) { 2241 jumpToRow(i, false); 2242 table.getSelectionModel().setSelectionInterval(i, i); 2243 found = true; 2244 wrapped = true; 2245 break; 2246 } 2247 } 2248 } 2249 } 2250 2251 2254 2258 private void setTitle() 2259 { 2260 StringBuffer sb = new StringBuffer (); 2261 StatusLine statusLine = null; 2262 if (statusLine == null) { 2263 sb.append(titleBase); 2264 } 2265 if (lastLevel >= 0 2266 || search.length() > 0) { 2267 sb.append(" "); 2268 sb.append(reverse ? rsearchTitle : searchTitle); 2269 if (wrapped) { 2270 sb.append(" ("); 2271 sb.append(wrappedTitle); 2272 sb.append(")"); 2273 } else if (! found) { 2274 sb.append(" ("); 2275 sb.append(notFoundTitle); 2276 sb.append(")"); 2277 } 2278 sb.append(": "); 2279 if (lastLevel > 0) { 2280 if (statusLine == null) { 2281 titleLabel.setIcon(icons[lastLevel - 1]); 2282 } else { 2283 statusLine.getMessageLabel() 2284 .setIcon(icons[lastLevel - 1]); 2285 statusLine.getMessageLabel() 2286 .setHorizontalTextPosition(JLabel.LEADING); 2287 } 2288 } else { 2289 if (statusLine == null) { 2290 titleLabel.setIcon(null); 2291 } else { 2292 statusLine.getMessageLabel().setIcon(null); 2293 } 2294 sb.append(search); 2295 } 2296 } else if (statusLine == null) { 2297 titleLabel.setIcon(null); 2298 } 2299 if (statusLine == null) { 2300 titleLabel.setText(sb.toString()); 2301 } else { 2302 titleLabel.setText(titleBase); 2303 titleLabel.setIcon(null); 2304 if (sb.length() == 0) { 2305 statusLine.popMessage(); 2306 } else { 2307 statusLine.pushMessage(sb.toString()); 2308 } 2309 } 2310 } 2311 2312 } 2314 2315 2317 2322 2325 class PopupListener 2326 extends MouseAdapter 2327 { 2328 2333 public void mousePressed(MouseEvent event) 2334 { 2335 maybePopup(event); 2336 } 2337 2338 2343 public void mouseReleased(MouseEvent event) 2344 { 2345 maybePopup(event); 2346 } 2347 2348 2356 private void maybePopup(MouseEvent event) 2357 { 2358 if (event.isPopupTrigger()) { 2359 int row = table.rowAtPoint 2360 (new Point (event.getX(), event.getY())); 2361 int column = table.columnAtPoint 2362 (new Point (event.getX(), event.getY())); 2363 if (row >= 0) { 2364 if (! table.isRowSelected(row)) { 2365 table.setRowSelectionInterval(row, row); 2366 } 2367 } 2368 if (column >= 0) { 2369 table.setColumnSelectionInterval(column, column); 2370 } 2371 SwingUtil.showPopup(popup, table, event.getX(), event.getY(), 2372 false); 2373 } 2374 } 2375 } 2376 2377 2379 2384 2386 2389 private final static int DELAY = 200; 2390 2391 2394 private final static Logger cslLogger = 2395 new Logger (CellSelectionListener.class); 2396 2397 2399 2403 protected class CellSelectionListener 2404 extends DelayedListSelectionListener 2405 implements TableModelListener , Runnable 2406 { 2407 2409 2412 private DelayedAction delay; 2413 2414 2417 private int lastRow = -1; 2418 2419 2422 private int lastColumn; 2423 2424 2426 2428 2431 public CellSelectionListener() 2432 { 2433 super(DELAY); 2434 delay = new DelayedAction (DELAY); 2435 } 2436 2437 2439 2441 2444 public void forgetSavedRow() 2445 { 2446 lastRow = -1; 2447 } 2448 2449 2451 2453 2458 public void delayedValueChanged(ListSelectionEvent e) 2459 { 2460 if (logging && cslLogger.level >= Log.MTD) { 2461 cslLogger.log(Log.MTD, "delayedValueChanged(ListSelectionEvent)", 2462 cslLogger.level < Log.MTDDETAIL ? "" : 2463 "e: " + e); 2464 } 2465 if (e.getValueIsAdjusting()) { 2466 return; 2467 } 2468 int row = table.getSelectionModel().getAnchorSelectionIndex(); 2469 lastColumn = table.getColumnModel().getSelectionModel() 2470 .getAnchorSelectionIndex(); 2471 if (row >= 0 && row < table.getRowCount()) { 2472 detailView.setEntry((LogEntry) table.getModel().getValueAt 2473 (row, model.COL_ENTRY)); 2474 lastRow = ((FilteredAndSortedTableModel) table.getModel()) 2475 .getMappedRow(row); 2476 } else { 2477 lastRow = -1; 2478 } 2479 } 2480 2481 2484 2489 public void tableChanged(TableModelEvent e) 2490 { 2491 int start = e.getFirstRow(); 2492 int end = e.getLastRow(); 2493 if (logging && cslLogger.level >= Log.MTD) { 2494 cslLogger.log(Log.MTD, "tableChanged(TableModelEvent)", 2495 cslLogger.level < Log.MTDDETAIL ? "" : 2496 "source: " + 2497 (e.getSource() == model 2498 ? "model" : "filteredModel") + 2499 ", start: " + start + 2500 ", end: " + end + 2501 ", lastRow: " + lastRow); 2502 } 2503 if (e.getSource() == model) { 2504 if (lastRow >= 0) { 2506 int type = e.getType(); 2507 if (start == e.HEADER_ROW 2508 || (start == 0 && end >= model.getRowCount() 2509 && type == e.UPDATE)) { 2510 if (logging && cslLogger.level >= Log.DBG) { 2512 cslLogger.log(Log.DBG, 2513 "tableChanged(TableModelEvent)", 2514 "lastRow invalidated"); 2515 } 2516 lastRow = -1; 2517 } else if (type == e.INSERT) { 2518 if (start <= lastRow) { 2519 lastRow += end - start + 1; 2520 if (logging && cslLogger.level >= Log.DBG) { 2521 cslLogger.log(Log.DBG, 2522 "tableChanged(TableModelEvent)", 2523 "lastRow moved up"); 2524 } 2525 } 2526 } else if (type == e.DELETE) { 2527 if (start <= lastRow) { 2528 if (end >= lastRow) { 2529 lastRow = -1; 2530 if (logging && cslLogger.level >= Log.DBG) { 2531 cslLogger.log(Log.DBG, 2532 "tableChanged(TableModelEvent)", 2533 "lastRow invalidated"); 2534 } 2535 } else { 2536 lastRow -= end - start + 1; 2537 if (logging && cslLogger.level >= Log.DBG) { 2538 cslLogger.log(Log.DBG, 2539 "tableChanged(TableModelEvent)", 2540 "lastRow moved down"); 2541 } 2542 } 2543 } 2544 } 2545 } 2546 } else { 2547 delay.perform(this); 2549 } 2550 } 2551 2552 2555 2558 public void run() 2559 { 2560 if (logging && cslLogger.level >= Log.DBG) { 2561 cslLogger.log(Log.DBG, "run()", 2562 "lastRow: " + lastRow + 2563 ", lastColumn: " + lastColumn); 2564 } 2565 if (lastRow >= 0) { 2566 restoreRow(lastRow, lastColumn); 2567 } 2568 int row = table.getSelectedRow(); 2569 if (row >= 0 && row < table.getRowCount()) { 2570 detailView.setEntry 2571 ((LogEntry) table.getModel().getValueAt 2572 (row, model.COL_ENTRY)); 2573 } 2574 } 2575 2576 } 2578 2579 2581 2586 2590 private class InitialFocusListener 2591 extends FocusAdapter 2592 { 2593 2598 public void focusGained(FocusEvent e) { 2599 if (table.getSelectionModel().getAnchorSelectionIndex() < 0 2600 && table.getRowCount() > 0) { 2601 table.setRowSelectionInterval(0, 0); 2602 } 2603 } 2604 } 2605 2606 2608 2613 2617 public class LevelRenderer extends de.qfs.lib.gui.WindowsTableCellRenderer 2618 { 2619 2622 private boolean isLevel; 2623 2624 2627 private Border selectedFocusBorder; 2628 2629 2632 private Border focusBorder; 2633 2634 2636 2642 public LevelRenderer (boolean level) 2643 { 2644 isLevel = level; 2645 initIcons(); 2646 } 2647 2648 2650 2652 2665 public Component getTableCellRendererComponent 2666 (JTable table, Object value, boolean isSelected, 2667 boolean hasFocus, int row, int column) 2668 { 2669 JLabel label = (JLabel ) super.getTableCellRendererComponent 2670 (table, value, isSelected, hasFocus, row, column); 2671 if (isLevel) { 2672 int level = ((Integer ) value).intValue(); 2673 Icon icon = null; 2674 if (level >= Log.ERR && level <= Log.DBGDETAIL) { 2675 icon = icons[level - 1]; 2676 } 2677 if (icon != null) { 2678 label.setIcon(icon); 2679 label.setText(null); 2680 } 2681 } 2682 return label; 2698 } 2699 2700 } 2702 2703 2705 2710 2714 private class HeaderRenderer 2715 extends SortedTableHeaderCellRenderer 2716 { 2717 2719 2722 public HeaderRenderer() 2723 { 2724 super(LogTableView.this.table); 2725 } 2726 2727 2729 2731 2744 public Component getTableCellRendererComponent 2745 (JTable table, Object value, boolean isSelected, 2746 boolean hasFocus, int row, int column) 2747 { 2748 JLabel label = (JLabel ) super.getTableCellRendererComponent 2749 (table, value, isSelected, hasFocus, row, column); 2750 int idx = table.convertColumnIndexToModel(column); 2751 if (filterEnabled[idx]) { 2752 label.setForeground(Color.red); 2753 } else { 2754 label.setForeground(Color.black); 2755 } 2756 return label; 2757 } 2758 2759 } 2761 2762 } 2764 | Popular Tags |