logging-log4j-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From sde...@apache.org
Subject cvs commit: jakarta-log4j-sandbox/src/java/org/apache/log4j/chainsaw LogUI.java
Date Mon, 05 May 2003 02:10:59 GMT
sdeboy      2003/05/04 19:10:59

  Modified:    src/java/org/apache/log4j/chainsaw LogUI.java
  Log:
  Corrected split pane problem where bottom pane was filling the window.
  
  Revision  Changes    Path
  1.21      +1331 -1274jakarta-log4j-sandbox/src/java/org/apache/log4j/chainsaw/LogUI.java
  
  Index: LogUI.java
  ===================================================================
  RCS file: /home/cvs/jakarta-log4j-sandbox/src/java/org/apache/log4j/chainsaw/LogUI.java,v
  retrieving revision 1.20
  retrieving revision 1.21
  diff -u -r1.20 -r1.21
  --- LogUI.java	5 May 2003 00:59:05 -0000	1.20
  +++ LogUI.java	5 May 2003 02:10:59 -0000	1.21
  @@ -130,1280 +130,1337 @@
    */
   public class LogUI extends JFrame implements ChainsawViewer {
   
  -  JTabbedPane tabbedPane;
  -  JToolBar toolbar;
  -  
  -  private final Map tableModelMap = new HashMap();
  -  private final Map tableMap = new HashMap();
  -  private final List names = new ArrayList();
  -  final List pausedList = new Vector();
  -  private final List levelList = new ArrayList();
  -  private final List filterableColumns = new ArrayList();
  -  private final Map entryMap = new HashMap();
  -  private final Map panelMap = new HashMap();
  -  private final Map lostMap = new HashMap();
  -  private final Map scrollMap = new HashMap();
  -  private final Map eventBorderMap = new HashMap();
  -  ChainsawAppenderHandler handler;
  -
  -  /**
  -   * Constructor which builds up all the visual elements of the frame
  -   * including the Menu bar
  -   */
  -  public LogUI() {
  -    super("Log Viewer");
  -  }
  -
  -  /**
  -   * Starts Chainsaw by attaching a new instance to the Log4J
  -   * main root Logger via a ChainsawAppender, and activates itself
  -   * @param args
  -   */
  -  public static void main(String[] args) {
  -    LogUI logUI = new LogUI();
  -    logUI.handler = new ChainsawAppenderHandler(logUI);
  -    LogManager.getRootLogger().addAppender(logUI.handler);
  -    logUI.activateViewer();
  -  }
  -
  -  public void activateViewer(ChainsawAppender appender) {
  -    handler = new ChainsawAppenderHandler(this, appender);
  -    activateViewer();
  -  }
  -
  -
  -  
  -  /**
  -   * Initialises the menu's and toolbars, but does not actually
  -   * create any of the main panel components.
  -   *
  -   */
  -  private void initGUI() {
  -	ChainsawToolBarAndMenus tbms = new ChainsawToolBarAndMenus(this);
  -	toolbar = tbms.getToolbar();
  -	setJMenuBar(tbms.getMenubar());
  -  }
  -  
  -  /**
  -   * Activates itself as a viewer by configuring Size, and location of
  -   * itself, and configures the default Tabbed Pane elements with the correct
  -   * layout, table columns, and sets itself viewable.
  -   */
  -  public void activateViewer() {
  -	initGUI();
  -    setSize(new Dimension(500, 500));
  -    setLocation(500, 150);
  -
  -    names.add(ChainsawConstants.LOGGER_COL_NAME);
  -    names.add(ChainsawConstants.TIMESTAMP_COL_NAME);
  -    names.add(ChainsawConstants.LEVEL_COL_NAME);
  -    names.add(ChainsawConstants.THREAD_COL_NAME);
  -    names.add(ChainsawConstants.MESSAGE_COL_NAME);
  -    names.add(ChainsawConstants.NDC_COL_NAME);
  -    names.add(ChainsawConstants.MDC_COL_NAME);
  -    names.add(ChainsawConstants.THROWABLE_COL_NAME);
  -    names.add(ChainsawConstants.CLASS_COL_NAME);
  -    names.add(ChainsawConstants.METHOD_COL_NAME);
  -    names.add(ChainsawConstants.FILE_COL_NAME);
  -    names.add(ChainsawConstants.LINE_COL_NAME);
  -    names.add(ChainsawConstants.PROPERTIES_COL_NAME);
  -
  -    //NOTE:  ID must ALWAYS be last field because the model adds this value itself as an identifier to the end of the consructed vector
  -    names.add(ChainsawConstants.ID_COL_NAME);
  -	List levels=UtilLoggingLevel.getAllPossibleLevels();
  -	Iterator iter=levels.iterator();
  -	while (iter.hasNext()) {
  -	    levelList.add(iter.next().toString());
  -	}
  -
  -    filterableColumns.add(ChainsawConstants.LEVEL_COL_NAME);
  -    filterableColumns.add(ChainsawConstants.LOGGER_COL_NAME);
  -    filterableColumns.add(ChainsawConstants.THREAD_COL_NAME);
  -    filterableColumns.add(ChainsawConstants.NDC_COL_NAME);
  -    filterableColumns.add(ChainsawConstants.MDC_COL_NAME);
  -    filterableColumns.add(ChainsawConstants.CLASS_COL_NAME);
  -    filterableColumns.add(ChainsawConstants.METHOD_COL_NAME);
  -    filterableColumns.add(ChainsawConstants.FILE_COL_NAME);
  -    filterableColumns.add(ChainsawConstants.NONE_COL_NAME);
  -
  -    JPanel panePanel = new JPanel();
  -    panePanel.setLayout(new BorderLayout());
  -
  -    getContentPane().setLayout(new BorderLayout());
  -
  -    tabbedPane = new JTabbedPane();
  -    tabbedPane.add("Welcome", new WelcomePanel());
  -    panePanel.add(tabbedPane);
  -
  -    getContentPane().add(toolbar, BorderLayout.NORTH);
  -    getContentPane().add(panePanel, BorderLayout.CENTER);
  -
  -    addWindowListener(
  -      new WindowAdapter() {
  -        public void windowClosing(WindowEvent event) {
  -          System.exit(0);
  -        }
  -      });
  -    
  -    setVisible(true);
  -  }
  -
  -  /**
  -   * Shutsdown by ensuring the Appender gets a chance to close.
  -   */
  -  private void shutdown() {
  -    handler.close();
  -  }
  -
  -  /**
  -   * Returns the currently selected LogPanel, if there is one, otherwise null
  -   * @return
  -   */
  -  LogPanel getCurrentLogPanel() {
  -  	Component selectedTab = tabbedPane.getSelectedComponent();
  -  	if(selectedTab instanceof LogPanel) {
  -  		return (LogPanel)selectedTab;
  -  	}else {
  -//  		System.out.println(selectedTab);
  -  	}
  -  	return null;
  -  }
  -  
  -  public String getActiveTabName() {
  -	int index=tabbedPane.getSelectedIndex();
  -	if (index==-1) {
  +	JTabbedPane tabbedPane;
  +	JToolBar toolbar;
  +
  +	private final Map tableModelMap = new HashMap();
  +	private final Map tableMap = new HashMap();
  +	private final List names = new ArrayList();
  +	final List pausedList = new Vector();
  +	private final List levelList = new ArrayList();
  +	private final List filterableColumns = new ArrayList();
  +	private final Map entryMap = new HashMap();
  +	private final Map panelMap = new HashMap();
  +	private final Map lostMap = new HashMap();
  +	private final Map scrollMap = new HashMap();
  +	private final Map eventBorderMap = new HashMap();
  +	ChainsawAppenderHandler handler;
  +
  +	/**
  +	 * Constructor which builds up all the visual elements of the frame
  +	 * including the Menu bar
  +	 */
  +	public LogUI() {
  +		super("Log Viewer");
  +	}
  +
  +	/**
  +	 * Starts Chainsaw by attaching a new instance to the Log4J
  +	 * main root Logger via a ChainsawAppender, and activates itself
  +	 * @param args
  +	 */
  +	public static void main(String[] args) {
  +		LogUI logUI = new LogUI();
  +		logUI.handler = new ChainsawAppenderHandler(logUI);
  +		LogManager.getRootLogger().addAppender(logUI.handler);
  +		logUI.activateViewer();
  +	}
  +
  +	public void activateViewer(ChainsawAppender appender) {
  +		handler = new ChainsawAppenderHandler(this, appender);
  +		activateViewer();
  +	}
  +
  +	/**
  +	 * Initialises the menu's and toolbars, but does not actually
  +	 * create any of the main panel components.
  +	 *
  +	 */
  +	private void initGUI() {
  +		ChainsawToolBarAndMenus tbms = new ChainsawToolBarAndMenus(this);
  +		toolbar = tbms.getToolbar();
  +		setJMenuBar(tbms.getMenubar());
  +	}
  +
  +	/**
  +	 * Activates itself as a viewer by configuring Size, and location of
  +	 * itself, and configures the default Tabbed Pane elements with the correct
  +	 * layout, table columns, and sets itself viewable.
  +	 */
  +	public void activateViewer() {
  +		initGUI();
  +		setSize(new Dimension(500, 500));
  +		setLocation(500, 150);
  +
  +		names.add(ChainsawConstants.LOGGER_COL_NAME);
  +		names.add(ChainsawConstants.TIMESTAMP_COL_NAME);
  +		names.add(ChainsawConstants.LEVEL_COL_NAME);
  +		names.add(ChainsawConstants.THREAD_COL_NAME);
  +		names.add(ChainsawConstants.MESSAGE_COL_NAME);
  +		names.add(ChainsawConstants.NDC_COL_NAME);
  +		names.add(ChainsawConstants.MDC_COL_NAME);
  +		names.add(ChainsawConstants.THROWABLE_COL_NAME);
  +		names.add(ChainsawConstants.CLASS_COL_NAME);
  +		names.add(ChainsawConstants.METHOD_COL_NAME);
  +		names.add(ChainsawConstants.FILE_COL_NAME);
  +		names.add(ChainsawConstants.LINE_COL_NAME);
  +		names.add(ChainsawConstants.PROPERTIES_COL_NAME);
  +
  +		//NOTE:  ID must ALWAYS be last field because the model adds this value itself as an identifier to the end of the consructed vector
  +		names.add(ChainsawConstants.ID_COL_NAME);
  +		List levels = UtilLoggingLevel.getAllPossibleLevels();
  +		Iterator iter = levels.iterator();
  +		while (iter.hasNext()) {
  +			levelList.add(iter.next().toString());
  +		}
  +
  +		filterableColumns.add(ChainsawConstants.LEVEL_COL_NAME);
  +		filterableColumns.add(ChainsawConstants.LOGGER_COL_NAME);
  +		filterableColumns.add(ChainsawConstants.THREAD_COL_NAME);
  +		filterableColumns.add(ChainsawConstants.NDC_COL_NAME);
  +		filterableColumns.add(ChainsawConstants.MDC_COL_NAME);
  +		filterableColumns.add(ChainsawConstants.CLASS_COL_NAME);
  +		filterableColumns.add(ChainsawConstants.METHOD_COL_NAME);
  +		filterableColumns.add(ChainsawConstants.FILE_COL_NAME);
  +		filterableColumns.add(ChainsawConstants.NONE_COL_NAME);
  +
  +		JPanel panePanel = new JPanel();
  +		panePanel.setLayout(new BorderLayout());
  +
  +		getContentPane().setLayout(new BorderLayout());
  +
  +		tabbedPane = new JTabbedPane();
  +		tabbedPane.add("Welcome", new WelcomePanel());
  +		panePanel.add(tabbedPane);
  +
  +		getContentPane().add(toolbar, BorderLayout.NORTH);
  +		getContentPane().add(panePanel, BorderLayout.CENTER);
  +
  +		addWindowListener(new WindowAdapter() {
  +			public void windowClosing(WindowEvent event) {
  +				System.exit(0);
  +			}
  +		});
  +
  +		setVisible(true);
  +	}
  +
  +	/**
  +	 * Shutsdown by ensuring the Appender gets a chance to close.
  +	 */
  +	private void shutdown() {
  +		handler.close();
  +	}
  +
  +	/**
  +	 * Returns the currently selected LogPanel, if there is one, otherwise null
  +	 * @return
  +	 */
  +	LogPanel getCurrentLogPanel() {
  +		Component selectedTab = tabbedPane.getSelectedComponent();
  +		if (selectedTab instanceof LogPanel) {
  +			return (LogPanel) selectedTab;
  +		} else {
  +			//  		System.out.println(selectedTab);
  +		}
   		return null;
  -	} else {
  -		return tabbedPane.getTitleAt(index);
   	}
  -  }
  -  
  -  /**
  -   * Determines an appropriate title for the Tab for the Tab Pane
  -   * by locating a the log4jmachinename property
  -   * @param v
  -   * @return
  -   */
  -  private String getTabIdentifier(Vector v) {
  -    int fieldIndex = names.indexOf(ChainsawConstants.PROPERTIES_COL_NAME);
  -    String properties = (String) v.get(fieldIndex);
  -
  -    String machinekey = ChainsawConstants.LOG4J_MACHINE_KEY + "=";
  -    String machinename = null;
  -    int machineposition = properties.indexOf(machinekey) + machinekey.length();
  -    int machinelength = properties.indexOf(",", machineposition);
  -
  -    if (machinelength == -1) {
  -      machinelength = properties.length();
  -    }
  -
  -    if (machineposition >= machinekey.length()) {
  -      machinename = properties.substring(machineposition, machinelength);
  -
  -      int dotposition = machinename.indexOf(".");
  -      boolean isnumeric = true;
  -
  -      if (dotposition > -1) {
  -        char[] firstdotpart =
  -          machinename.substring(0, dotposition).toCharArray();
  -
  -        for (int i = 0; i < firstdotpart.length; i++) {
  -          isnumeric = isnumeric && Character.isDigit(firstdotpart[i]);
  -        }
  -
  -        if (!isnumeric) {
  -          machinename = machinename.substring(0, dotposition);
  -        }
  -      }
  -    }
  -
  -    String appkey = ChainsawConstants.LOG4J_APP_KEY + "=";
  -    String appname = null;
  -    int appposition = properties.indexOf(appkey) + appkey.length();
  -
  -    if (appposition >= appkey.length()) {
  -      int applength = properties.indexOf(",", appposition);
  -
  -      if (applength == -1) {
  -        applength = properties.length();
  -      }
  -
  -      appname = properties.substring(appposition, applength);
  -    }
  -
  -    StringBuffer ident = new StringBuffer();
  -
  -    if (machinename != null) {
  -      ident.append(machinename);
  -    }
  -
  -    if (appname != null) {
  -      ident.append("-");
  -      ident.append(appname);
  -    }
  -
  -    if (ident.length() == 0) {
  -      ident.append(ChainsawConstants.UNKNOWN_TAB_NAME);
  -    }
  -
  -    return ident.toString();
  -  }
  -
  -  /**
  -   * Routes a Vector of Logging Event elements into the approprate Tabbed Pane
  -   * @param v
  -   */
  -  public void receiveEvent(Vector v) {
  -    String ident = getTabIdentifier(v);
  -
  -    if (!pausedList.contains(ident)) {
  -      addRow(ident, formatFields(v));
  -    }
  -  }
  -
  -  public Vector getAllEvents(String ident) {
  -  	return ((DefaultSortTableModel)tableModelMap.get(ident)).getAllEvents();
  -  }
  -  
  -  public Vector getDisplayedEvents(String ident) {
  -    return ((DefaultSortTableModel)tableModelMap.get(ident)).getDisplayedEvents();
  -  }	
  -  /**
  -   * Formats the individual elements of an LoggingEvent by ensuring that
  -   * there are no null bits, replacing them with EMPTY_STRING
  -   * @param v
  -   * @return
  -   */
  -  private Vector formatFields(Vector v) {
  -    for (int i = 0; i < v.size(); i++) {
  -      if (v.get(i) == null) {
  -        v.set(i, ChainsawConstants.EMPTY_STRING);
  -      }
  -    }
  -
  -    return v;
  -  }
  -
  -  /**
  -   * Regurgitates a DisplayFilter for a specific machine identifier
  -   * by deserializing the settings from a file.
  -   * @param ident
  -   * @return
  -   */
  -  private DisplayFilter loadDisplayFilter(String ident) {
  -    DisplayFilter d = null;
  -    ObjectInputStream s = null;
  -
  -    try {
  -      s = new ObjectInputStream(
  -          new BufferedInputStream(
  -            new FileInputStream(new File(ident + ChainsawConstants.SETTINGS_EXTENSION))));
  -      d = (DisplayFilter) s.readObject();
  -    } catch (IOException ioe) {
  -    } catch (ClassNotFoundException cnfe) {
  -    } finally {
  -      if (s != null) {
  -        try {
  -          s.close();
  -        } catch (IOException ioe) {
  -        }
  -      }
  -    }
  -
  -    if (d == null) {
  -      d = new DisplayFilter(names);
  -    }
  -
  -    return d;
  -  }
  -
  -  /**
  -   * Adds a specific row to a specific Tabbed Pane's TableModel.
  -   *
  -   * If there is currently no Tabbed Pane for the identifier, then a new
  -   * one is created and added to this current Frames Tabbed Pane infrastructure
  -   * @param ident
  -   * @param v
  -   */
  -  private void addRow(final String ident, Vector v) {
  -    final DefaultSortTableModel tableModel;
  -    final JSortTable table;
  -    final ScrollToBottom scrollToBottom;
  -    HashMap map = null;
  -
  -    if (tableModelMap.containsKey(ident)) {
  -      tableModel = (DefaultSortTableModel) tableModelMap.get(ident);
  -      map = (HashMap) entryMap.get(ident);
  -      scrollToBottom = (ScrollToBottom) scrollMap.get(ident);
  -      table = (JSortTable) tableMap.get(ident);
  -    } else {
  -      tableModel = new DefaultSortTableModel(new Vector(), new Vector(names));
  -      map = new HashMap();
  -      table = new JSortTable(tableModel);
  -      scrollToBottom = new ScrollToBottom(true);
  -      LogPanel thisPanel=new LogPanel(ident, tableModel, table, scrollToBottom, map);
  -//      tabbedPane.add(ident, thisPanel);
  -	  tabbedPane.insertTab(ident, null, thisPanel, null, 0);
  -      System.out.println("Creating tab " + ident);
  -    }
  -
  -    ((HashSet) map.get(ChainsawConstants.LOGGER_COL_NAME)).add(
  -      v.get(names.indexOf(ChainsawConstants.LOGGER_COL_NAME)));
  -    ((HashSet) map.get(ChainsawConstants.LEVEL_COL_NAME)).add(
  -      v.get(names.indexOf(ChainsawConstants.LEVEL_COL_NAME)));
  -    ((HashSet) map.get(ChainsawConstants.THREAD_COL_NAME)).add(
  -      v.get(names.indexOf(ChainsawConstants.THREAD_COL_NAME)));
  -    ((HashSet) map.get(ChainsawConstants.NDC_COL_NAME)).add(v.get(names.indexOf(ChainsawConstants.NDC_COL_NAME)));
  -    ((HashSet) map.get(ChainsawConstants.MDC_COL_NAME)).add(v.get(names.indexOf(ChainsawConstants.MDC_COL_NAME)));
  -    ((HashSet) map.get(ChainsawConstants.CLASS_COL_NAME)).add(
  -      v.get(names.indexOf(ChainsawConstants.CLASS_COL_NAME)));
  -    ((HashSet) map.get(ChainsawConstants.METHOD_COL_NAME)).add(
  -      v.get(names.indexOf(ChainsawConstants.METHOD_COL_NAME)));
  -    ((HashSet) map.get(ChainsawConstants.FILE_COL_NAME)).add(
  -      v.get(names.indexOf(ChainsawConstants.FILE_COL_NAME)));
  -
  -    table.getSelectionModel().setValueIsAdjusting(true);
  -
  -    if (tableModel.isAddRow(v)) {
  -      if (scrollToBottom.isScrolled() && !scrollToBottom.isBypassed()) {
  -        table.scrollToBottom(
  -          table.columnAtPoint(table.getVisibleRect().getLocation()));
  -      }
  -    }
  -  }
  -
  -  /**
  -   * An implementation of the EventCountListener that modifies
  -   * the border of a panel with the new counter information
  -   */
  -  class EventCountListenerImpl implements EventCountListener {
  -    private String ident;
  -    private DefaultSortTableModel model;
  -
  -    public EventCountListenerImpl(String ident) {
  -      this.ident = ident;
  -      model = (DefaultSortTableModel) tableModelMap.get(ident);
  -    }
  -
  -    public void eventCountChanged(int current, int total) {
  -      TitledBorder eventBorder = (TitledBorder) eventBorderMap.get(ident);
  -      JPanel panel = (JPanel) panelMap.get(ident);
  -      String title = "Events - showing " + current + " of " + total;
  -      eventBorder.setTitle(title);
  -      panel.repaint(panel.getVisibleRect());
  -    }
  -  }
  -
  -  /**
  -   * Ensures that a specific popupMenu is displayed when the relevant
  -   * mouse events are trapped.
  -   */
  -  class PopupListener extends MouseAdapter {
  -    final JPopupMenu popupMenu;
  -
  -    PopupListener(JPopupMenu popupMenu) {
  -      this.popupMenu = popupMenu;
  -    }
  -
  -    public void mousePressed(MouseEvent e) {
  -      checkPopup(e);
  -    }
  -
  -    public void mouseReleased(MouseEvent e) {
  -      checkPopup(e);
  -    }
  -
  -    private void checkPopup(MouseEvent e) {
  -      if (e.isPopupTrigger()) {
  -        popupMenu.show(e.getComponent(), e.getX(), e.getY());
  -      }
  -    }
  -  }
  -
  -  /**
  -   * LogPanel encapsulates all the necessary bits and pieces of a
  -   * floating window of Events coming from a specific Location.
  -   *
  -   * This is where most of the Swing components are constructed and laid out.
  -   */
  -  class LogPanel extends DockablePanel {
  -    final ColorFilter colorFilter = new ColorFilter();
  -    final DisplayFilter displayFilter;
  -    boolean isDocked = true;
  -    String identifier;
  -    final Map columnDisplayMap = new HashMap();
  -    final Map colorDisplayMap = new HashMap();
  -    final Set loggerSet = new HashSet();
  -    final ColorDisplaySelector colorDisplaySelector;
  -    Set levelSet = new HashSet();
  -    Set MDCSet = new HashSet();
  -    Set NDCSet = new HashSet();
  -    Set threadSet = new HashSet();
  -    Set classSet = new HashSet();
  -    Set methodSet = new HashSet();
  -    Set fileSet = new HashSet();
  -
  -    //used for consistency - stays empty - used to allow none set in the colordisplay selector and right click
  -    Set noneSet = new HashSet();
  -    Point currentPoint;
  -
  -    public LogPanel(
  -      final String ident, final DefaultSortTableModel tableModel,
  -      final JSortTable table, final ScrollToBottom scrollToBottom,
  -      final Map map) {
  -      	
  -      identifier = ident;
  -      map.put(ChainsawConstants.LEVEL_COL_NAME, levelSet);
  -      levelSet.addAll(levelList);
  -
  -      map.put(ChainsawConstants.LOGGER_COL_NAME, loggerSet);
  -      map.put(ChainsawConstants.THREAD_COL_NAME, threadSet);
  -      map.put(ChainsawConstants.NDC_COL_NAME, NDCSet);
  -      map.put(ChainsawConstants.MDC_COL_NAME, MDCSet);
  -      map.put(ChainsawConstants.CLASS_COL_NAME, classSet);
  -      map.put(ChainsawConstants.METHOD_COL_NAME, methodSet);
  -      map.put(ChainsawConstants.FILE_COL_NAME, fileSet);
  -      map.put(ChainsawConstants.NONE_COL_NAME, noneSet);
  -
  -      setLayout(new BorderLayout());
  -      displayFilter = loadDisplayFilter(ident);
  -      tableModel.setDisplayFilter(displayFilter);
  -      displayFilter.addFilterChangedListener(tableModel);
  -
  -      scrollMap.put(ident, scrollToBottom);
  -
  -      TableColorizingRenderer renderer = new TableColorizingRenderer();
  -      renderer.setColorFilter(colorFilter);
  -
  -      colorFilter.addFilterChangedListener(renderer);
  -      displayFilter.addFilterChangedListener(renderer);
  -
  -      table.setDefaultRenderer(Object.class, renderer);
  -
  -      final DetailFieldSelector detailFieldSelector =
  -        new DetailFieldSelector(new Vector(names), displayFilter);
  -
  -      final ColumnSelector columnSelector =
  -        new ColumnSelector(new Vector(names), table, displayFilter);
  -
  -      JMenu menuColumnDisplayFilter =
  -        new JMenu("Apply display filter for column");
  -
  -      JMenu menuColumnColorFilter = new JMenu("Apply color filter for column");
  -
  -      ButtonGroup bg = new ButtonGroup();
  -      Iterator iter = filterableColumns.iterator();
  -
  -      while (iter.hasNext()) {
  -        final String colName = (String) iter.next();
  -        JRadioButtonMenuItem thisItem = new JRadioButtonMenuItem(colName);
  -        thisItem.setFont(thisItem.getFont().deriveFont(Font.PLAIN));
  -        thisItem.addActionListener(
  -          new ActionListener() {
  -            public void actionPerformed(ActionEvent evt) {
  -              colorDisplaySelector.applyColorUpdateForColumn(colName);
  -              colorDisplaySelector.applyColorFilters(colName);
  -            }
  -          });
  -        bg.add(thisItem);
  -        menuColumnColorFilter.add(thisItem);
  -        colorDisplayMap.put(colName, thisItem);
  -      }
  -
  -      ButtonGroup bg2 = new ButtonGroup();
  -      Iterator iter2 = filterableColumns.iterator();
  -
  -      while (iter2.hasNext()) {
  -        final String colName = (String) iter2.next();
  -        JRadioButtonMenuItem thisItem = new JRadioButtonMenuItem(colName);
  -        thisItem.setFont(thisItem.getFont().deriveFont(Font.PLAIN));
  -        thisItem.addActionListener(
  -          new ActionListener() {
  -            public void actionPerformed(ActionEvent evt) {
  -              colorDisplaySelector.applyDisplayUpdateForColumn(colName);
  -              colorDisplaySelector.applyDisplayFilters(colName);
  -            }
  -          });
  -        bg2.add(thisItem);
  -        menuColumnDisplayFilter.add(thisItem);
  -        columnDisplayMap.put(colName, thisItem);
  -      }
  -
  -      colorDisplaySelector =
  -        new ColorDisplaySelector(
  -          ident, map, colorFilter, displayFilter, colorDisplayMap,
  -          columnDisplayMap, names, filterableColumns, levelList);
  -
  -      table.addMouseMotionListener(
  -        new MouseMotionAdapter() {
  -          int currentRow = -1;
  -
  -          public void mouseMoved(MouseEvent evt) {
  -            currentPoint = evt.getPoint();
  -
  -            if (displayFilter.isToolTipsEnabled()) {
  -              int row = table.rowAtPoint(evt.getPoint());
  -
  -              if ((row == currentRow) || (row == -1)) {
  -                return;
  -              }
  -
  -              currentRow = row;
  -
  -              table.setToolTipText(
  -                ((DefaultSortTableModel) table.getModel()).getDetailText(row));
  -            } else {
  -              table.setToolTipText(null);
  -            }
  -          }
  -        });
  -
  -      //HACK - fix the way columns are sized..should be saved off and loaded later
  -      table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
  -
  -      int colCount = table.getColumnModel().getColumnCount();
  -      int curCol = 1;
  -
  -      //assumes there's at least one column showing..
  -      TableColumn col = table.getColumnModel().getColumn(0);
  -      col.setPreferredWidth(120);
  -
  -      if (curCol++ < colCount) {
  -        col = table.getColumnModel().getColumn(1);
  -        col.setPreferredWidth(100);
  -      }
  -
  -      if (curCol++ < colCount) {
  -        col = table.getColumnModel().getColumn(2);
  -        col.setPreferredWidth(100);
  -      }
  -
  -      if (curCol++ < colCount) {
  -        col = table.getColumnModel().getColumn(3);
  -        col.setPreferredWidth(150);
  -      }
  -
  -      if (curCol++ < colCount) {
  -        col = table.getColumnModel().getColumn(4);
  -        col.setPreferredWidth(300);
  -      }
  -
  -      if (curCol++ < colCount) {
  -        col = table.getColumnModel().getColumn(5);
  -        col.setPreferredWidth(100);
  -      }
  -
  -      if (curCol++ < colCount) {
  -        col = table.getColumnModel().getColumn(6);
  -        col.setPreferredWidth(250);
  -      }
  -
  -      if (curCol++ < colCount) {
  -        col = table.getColumnModel().getColumn(7);
  -        col.setPreferredWidth(200);
  -      }
  -
  -      if (curCol++ < colCount) {
  -        col = table.getColumnModel().getColumn(8);
  -        col.setPreferredWidth(300);
  -      }
  -
  -      if (curCol++ < colCount) {
  -        col = table.getColumnModel().getColumn(9);
  -        col.setPreferredWidth(150);
  -      }
  -
  -      if (curCol++ < colCount) {
  -        col = table.getColumnModel().getColumn(10);
  -        col.setPreferredWidth(120);
  -      }
  -
  -      if (curCol++ < colCount) {
  -        col = table.getColumnModel().getColumn(11);
  -        col.setPreferredWidth(50);
  -      }
  -
  -      if (curCol++ < colCount) {
  -        col = table.getColumnModel().getColumn(12);
  -        col.setPreferredWidth(300);
  -      }
  -
  -      final JEditorPane detail = new JEditorPane(ChainsawConstants.DETAIL_CONTENT_TYPE, "");
  -      detail.setEditable(false);
  -
  -      final DetailThread detailThread = new DetailThread(detail, tableModel);
  -      detailThread.start();
  -
  -      
  -      GridBagLayout gridbag = new GridBagLayout();
  -      GridBagConstraints gbc = new GridBagConstraints();
  -
  -      final JPanel upperPanel = new JPanel(gridbag);
  -      upperPanel.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
  -
  -      gbc.gridx = 0;
  -      gbc.gridy = 0;
  -      gbc.weightx = 0;
  -
  -      final JLabel filterLabel = new JLabel("Filter: ");
  -      gbc.gridx = 1;
  -      gbc.gridy = 0;
  -      gbc.weightx = 0;
  -      gridbag.setConstraints(filterLabel, gbc);
  -      upperPanel.add(filterLabel);
  -
  -      final JComboBox customFilterList = new JComboBox(names.toArray());
  -
  -      final JTextField filterText = new JTextField();
  -
  -      filterText.getDocument().addDocumentListener(
  -        new DocumentListener() {
  -          public void insertUpdate(DocumentEvent e) {
  -            setFilter();
  -          }
  -
  -          public void removeUpdate(DocumentEvent e) {
  -            setFilter();
  -          }
  -
  -          public void changedUpdate(DocumentEvent e) {
  -            setFilter();
  -          }
  -
  -          public void setFilter() {
  -            if (filterText.getText().equals("")) {
  -              displayFilter.setCustomFilter(null);
  -            } else {
  -              synchronized (detail) {
  -                detailThread.setSelectedRow(-1);
  -                detail.notify();
  -              }
  -
  -              displayFilter.setCustomFilter(
  -                new DisplayFilterEntry(
  -                  (String) customFilterList.getSelectedItem(),
  -                  filterText.getText(), ChainsawConstants.GLOBAL_MATCH, Boolean.TRUE));
  -            }
  -          }
  -        });
  -
  -      gbc.gridx = 4;
  -      gbc.gridy = 0;
  -      gbc.weightx = 1;
  -      gbc.fill = GridBagConstraints.HORIZONTAL;
  -      gridbag.setConstraints(filterText, gbc);
  -
  -      String evaluator =
  -        ExpressionEvaluatorFactory.newInstance().getEvaluatorClassName();
  -      filterText.setToolTipText(
  -        "See " + evaluator + " documentation for expression rules");
  -
  -      customFilterList.setMaximumRowCount(15);
  -      gbc.gridx = 2;
  -      gbc.gridy = 0;
  -      gbc.weightx = 0;
  -      gridbag.setConstraints(customFilterList, gbc);
  -      upperPanel.add(customFilterList);
  -
  -      customFilterList.addActionListener(
  -        new ActionListener() {
  -          public void actionPerformed(ActionEvent evt) {
  -            if (!(filterText.getText().equals(""))) {
  -              displayFilter.setCustomFilter(
  -                new DisplayFilterEntry(
  -                  (String) customFilterList.getSelectedItem(),
  -                  filterText.getText(), "*", Boolean.TRUE));
  -            }
  -          }
  -        });
  -
  -      final JCheckBox override = new JCheckBox("Override");
  -      gbc.gridx = 3;
  -      gbc.gridy = 0;
  -      gbc.weightx = 0;
  -      gridbag.setConstraints(override, gbc);
  -      upperPanel.add(override);
  -      override.addActionListener(
  -        new ActionListener() {
  -          public void actionPerformed(ActionEvent evt) {
  -            displayFilter.setCustomFilterOverride(override.isSelected());
  -          }
  -        });
  -
  -      upperPanel.add(filterText);
  -
  -      JLabel findLabel = new JLabel("Find: ");
  -      gbc.gridx = 5;
  -      gbc.gridy = 0;
  -      gbc.weightx = 0;
  -      gridbag.setConstraints(findLabel, gbc);
  -      upperPanel.add(findLabel);
  -
  -      final JTextField findText = new JTextField();
  -      
  -      
  -      gbc.gridx = 6;
  -      gbc.gridy = 0;
  -      gbc.weightx = 1;
  -      gbc.fill = GridBagConstraints.HORIZONTAL;
  -      gridbag.setConstraints(findText, gbc);
  -      findText.setToolTipText(
  -        "Performs a case-insensitive search across all columns");
  -      upperPanel.add(findText);
  -
  -      findText.getDocument().addDocumentListener(
  -        new DocumentListener() {
  -          public void insertUpdate(DocumentEvent e) {
  -            find();
  -          }
  -
  -          public void removeUpdate(DocumentEvent e) {
  -            find();
  -          }
  -
  -          public void changedUpdate(DocumentEvent e) {
  -            find();
  -          }
  -
  -          public void find() {
  -            final int row = tableModel.find(0, findText.getText());
  -
  -            if (findText.getDocument().getLength() == 0) {
  -              scrollToBottom.bypass(false);
  -            } else {
  -              scrollToBottom.bypass(true);
  -            }
  -
  -            table.scrollToRow(
  -              row, table.columnAtPoint(table.getVisibleRect().getLocation()));
  -          }
  -        });
  -
  -      String findNextActionLabel = "Find next";
  -      Action findNextAction = new AbstractAction(findNextActionLabel) {
  -        public void actionPerformed(ActionEvent evt) {
  -          final int row =
  -            tableModel.find(table.getSelectedRow() + 1, findText.getText());
  -          table.scrollToRow(
  -            row,
  -            table.columnAtPoint(table.getVisibleRect().getLocation()));
  -        }
  -      };
  -      
  -      findNextAction.putValue(Action.SHORT_DESCRIPTION, "Finds the next match");
  -      
  -      JButton findButton = new JButton(findNextAction);
  -      findButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("F3"), findNextActionLabel);
  -      findButton.getActionMap().put(findNextAction.getValue(Action.NAME), findNextAction);
  -          
  -      gbc.gridx = 7;
  -      gbc.gridy = 0;
  -      gbc.weightx = 0;
  -      gridbag.setConstraints(findButton, gbc);
  -
  -      upperPanel.add(findButton);
  -
  -      final JScrollPane eventsPane = new JScrollPane(table);
  -      eventsPane.setPreferredSize(new Dimension(900, 300));
  -
  -      TitledBorder eventsBorder = BorderFactory.createTitledBorder("Events");
  -      eventsPane.setBorder(eventsBorder);
  -      eventBorderMap.put(ident, eventsBorder);
  -
  -      final JPanel detailPanel = new JPanel(new BorderLayout());
  -
  -      //set valueisadjusting if holding down a key - don't process setdetail events
  -      table.addKeyListener(
  -        new KeyListener() {
  -          public void keyTyped(KeyEvent e) {
  -          }
  -
  -          public void keyPressed(KeyEvent e) {
  -            synchronized (detail) {
  -              table.getSelectionModel().setValueIsAdjusting(true);
  -              detail.notify();
  -            }
  -          }
  -
  -          public void keyReleased(KeyEvent e) {
  -            synchronized (detail) {
  -              table.getSelectionModel().setValueIsAdjusting(false);
  -              detail.notify();
  -            }
  -          }
  -        });
  -
  -      final JScrollPane detailPane = new JScrollPane(detail);
  -      detailPane.setPreferredSize(new Dimension(900, 50));
  -
  -      detailPanel.add(detailPane, BorderLayout.CENTER);
  -
  -      final JSplitPane lowerPanel =
  -        new JSplitPane(JSplitPane.VERTICAL_SPLIT, eventsPane, detailPanel);
  -      add(upperPanel, BorderLayout.NORTH);
  -      add(lowerPanel, BorderLayout.CENTER);
  -      lowerPanel.setOneTouchExpandable(true);
  -      table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
  -
  -      final ScrollDetailThread scrollDetailThread =
  -        new ScrollDetailThread(detail, tableModel);
  -      scrollDetailThread.start();
  -
  -      table.getSelectionModel().addListSelectionListener(
  -        new ListSelectionListener() {
  -          public void valueChanged(ListSelectionEvent evt) {
  -            if (((ScrollToBottom) scrollMap.get(ident)).isScrolled()) {
  -              scrollDetailThread.setScrolledRow(table.getSelectedRow());
  -            } else {
  -              scrollDetailThread.setScrolledRow(-1);
  -            }
  -
  -            if (evt.getValueIsAdjusting()) {
  -              return;
  -            }
  -
  -            final ListSelectionModel lsm =
  -              (ListSelectionModel) evt.getSource();
  -
  -            if (lsm.isSelectionEmpty()) {
  -              if (detail.getDocument().getDefaultRootElement() != null) {
  -                synchronized (detail) {
  -                  detailThread.setSelectedRow(-1);
  -                  detail.notify();
  -                }
  -              }
  -            } else {
  -              if (table.getSelectedRow() > -1) {
  -                int selectedRow = table.getSelectedRow();
  -
  -                try {
  -                  if (tableModel.getRowCount() >= selectedRow) {
  -                    synchronized (detail) {
  -                      detailThread.setSelectedRow(table.getSelectedRow());
  -                      detail.notify();
  -                    }
  -                  } else {
  -                    synchronized (detail) {
  -                      detailThread.setSelectedRow(-1);
  -                      detail.notify();
  -                    }
  -                  }
  -                } catch (Exception e) {
  -                  e.printStackTrace();
  -
  -                  synchronized (detail) {
  -                    detailThread.setSelectedRow(-1);
  -                    detail.notify();
  -                  }
  -                }
  -              }
  -            }
  -          }
  -        });
  -
  -      final JMenuItem menuItemToggleDock = new JMenuItem("Undock/dock");
  -
  -      final JFrame f = new JFrame(ident);
  -      final DockablePanel externalPanel = new DockablePanel();
  -      externalPanel.setLayout(new BorderLayout());
  -      f.setSize(new Dimension(500, 500));
  -      f.getContentPane().add(externalPanel);
  -
  -      f.addWindowListener(
  -        new WindowAdapter() {
  -          public void windowClosing(WindowEvent event) {
  -            HashMap m = new HashMap();
  -            m.put(ChainsawConstants.MAIN_PANEL, LogPanel.this);
  -            m.put(ChainsawConstants.UPPER_PANEL, upperPanel);
  -            m.put(ChainsawConstants.LOWER_PANEL, lowerPanel);
  -            lostMap.put(ident, m);
  -          }
  -        });
  -
  -      menuItemToggleDock.addActionListener(
  -        new ActionListener() {
  -          public void actionPerformed(ActionEvent evt) {
  -            if (isDocked()) {
  -              externalPanel.removeAll();
  -              externalPanel.add(upperPanel, BorderLayout.NORTH);
  -              externalPanel.add(lowerPanel, BorderLayout.CENTER);
  -              tabbedPane.remove(LogPanel.this);
  -              externalPanel.setDocked(false);
  -              setDocked(false);
  -              panelMap.put(ident, externalPanel);
  -              f.setVisible(true);
  -            } else {
  -              f.setVisible(false);
  -              removeAll();
  -              add(upperPanel, BorderLayout.NORTH);
  -              add(lowerPanel, BorderLayout.CENTER);
  -              panelMap.put(ident, LogPanel.this);
  -              tabbedPane.add(ident, LogPanel.this);
  -              externalPanel.setDocked(true);
  -              setDocked(true);
  -            }
  -          }
  -        });
  -
  -      JMenuItem menuItemDisplayFilter =
  -        new JMenuItem("Define display and color filters...");
  -      menuItemDisplayFilter.addActionListener(
  -        new ActionListener() {
  -          public void actionPerformed(ActionEvent evt) {
  -            colorDisplaySelector.show();
  -          }
  -        });
  -
  -
  -//      final Boolean initialToggling = (lowerPanel.getDividerLocation() != (lowerPanel.getHeight()- lowerPanel.getDividerSize())          
  -      Action toggleDetailPaneAction = new AbstractAction("Show Detail Pane") {
  -        boolean enabled = true;
  -        public void actionPerformed(ActionEvent evt) {
  -          if (enabled) {
  -            lowerPanel.setDividerLocation(lowerPanel.getLastDividerLocation());
  -          } else {
  -            int lastPosition = lowerPanel.getDividerLocation();
  -            lowerPanel.setDividerLocation(1.0d);
  -            lowerPanel.setLastDividerLocation(lastPosition);
  -          }
  -        }
  -      };
  -      toggleDetailPaneAction.putValue("enabled",Boolean.TRUE) ;
  -      toggleDetailPaneAction.putValue(Action.ACCELERATOR_KEY,KeyStroke.getKeyStroke(KeyEvent.VK_D, InputEvent.ALT_MASK)) ;
  -      toggleDetailPaneAction.putValue(Action.SHORT_DESCRIPTION, "Hides/Shows the Detail Pane") ;
  -        
  -      JCheckBoxMenuItem menuItemToggleDetails = new JCheckBoxMenuItem(toggleDetailPaneAction);
  -//      TODO this hot key doesn't seem to work just yet
  -//      menuItemToggleDetails.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_D, InputEvent.ALT_MASK), toggleDetailPaneAction.getValue(Action.NAME));
  -//      menuItemToggleDetails.getActionMap().put(toggleDetailPaneAction.getValue(Action.NAME), toggleDetailPaneAction);
  -
  -      menuItemToggleDetails.setSelected(true);
  -            
  -      final JCheckBoxMenuItem menuItemToggleToolTips =
  -        new JCheckBoxMenuItem(
  -          "Show ToolTips", displayFilter.isToolTipsEnabled());
  -      menuItemToggleToolTips.addActionListener(
  -        new ActionListener() {
  -          public void actionPerformed(ActionEvent evt) {
  -            displayFilter.enableToolTips(menuItemToggleToolTips.isSelected());
  -          }
  -        });
  -
  -      final JMenuItem menuDefineCustomFilter =
  -        new JMenuItem("Custom filter from mouse location");
  -      menuDefineCustomFilter.addActionListener(
  -        new ActionListener() {
  -          public void actionPerformed(ActionEvent evt) {
  -            if (currentPoint != null) {
  -              int column = table.columnAtPoint(currentPoint);
  -              int row = table.rowAtPoint(currentPoint);
  -              String colName = tableModel.getColumnName(column);
  -              String value = "";
  -
  -              if (colName.equalsIgnoreCase(ChainsawConstants.TIMESTAMP_COL_NAME)) {
  -                JComponent comp =
  -                  (JComponent) table.getCellRenderer(row, column);
  -
  -                if (comp instanceof JLabel) {
  -                  value = ((JLabel) comp).getText();
  -                }
  -              } else {
  -                value = table.getValueAt(row, column).toString();
  -              }
  -
  -              customFilterList.setSelectedItem(colName);
  -              filterText.setText(value);
  -            }
  -          }
  -        });
  -
  -      final JCheckBoxMenuItem menuItemScrollBottom =
  -        new JCheckBoxMenuItem("Scroll to bottom", scrollToBottom.isScrolled());
  -      menuItemScrollBottom.addActionListener(
  -        new ActionListener() {
  -          public void actionPerformed(ActionEvent evt) {
  -            scrollToBottom.scroll(menuItemScrollBottom.isSelected());
  -          }
  -        });
  -
  -      JMenuItem menuItemClear =
  -        new JMenuItem("Clear all entries for this panel");
  -      menuItemClear.addActionListener(
  -        new ActionListener() {
  -          public void actionPerformed(ActionEvent evt) {
  -            TableModel model = table.getModel();
  -
  -            if (model instanceof DefaultSortTableModel) {
  -              ((DefaultSortTableModel) model).setRowCount(0);
  -
  -              synchronized (detail) {
  -                detailThread.setSelectedRow(-1);
  -                detail.notify();
  -              }
  -            }
  -          }
  -        });
  -
  -      JMenuItem menuItemRecoverPanes = new JMenuItem("Recover closed panes");
  -      menuItemRecoverPanes.addActionListener(
  -        new ActionListener() {
  -          public void actionPerformed(ActionEvent evt) {
  -            Set s = lostMap.entrySet();
  -            Iterator iter = s.iterator();
  -
  -            while (iter.hasNext()) {
  -              Map.Entry m = (Map.Entry) iter.next();
  -              String title = (String) m.getKey();
  -              HashMap map = (HashMap) m.getValue();
  -              JSplitPane lower = (JSplitPane) map.get(ChainsawConstants.LOWER_PANEL);
  -              JPanel upper = (JPanel) map.get(ChainsawConstants.UPPER_PANEL);
  -              DockablePanel thisPanel = (DockablePanel) map.get(ChainsawConstants.MAIN_PANEL);
  -              thisPanel.add(upper, BorderLayout.NORTH);
  -              thisPanel.add(lower, BorderLayout.CENTER);
  -              panelMap.put(title, thisPanel);
  -              tabbedPane.add(title, thisPanel);
  -              thisPanel.setDocked(true);
  -            }
  -
  -            lostMap.clear();
  -          }
  -        });
  -
  -      JMenuItem menuItemRemoveColorFilter =
  -        new JMenuItem("Remove all color filters");
  -      menuItemRemoveColorFilter.addActionListener(
  -        new ActionListener() {
  -          public void actionPerformed(ActionEvent evt) {
  -            colorDisplaySelector.clearColors();
  -            colorFilter.clear();
  -          }
  -        });
  -
  -      JMenuItem menuItemDetailFieldSelector =
  -        new JMenuItem("Select tooltip/detail columns...");
  -      menuItemDetailFieldSelector.addActionListener(
  -        new ActionListener() {
  -          public void actionPerformed(ActionEvent evt) {
  -            detailFieldSelector.show();
  -          }
  -        });
  -
  -      JMenuItem menuItemColumnSelector =
  -        new JMenuItem("Select display columns...");
  -      menuItemColumnSelector.addActionListener(
  -        new ActionListener() {
  -          public void actionPerformed(ActionEvent evt) {
  -            columnSelector.show();
  -          }
  -        });
  -
  -      JMenuItem menuItemRemoveDisplayFilter =
  -        new JMenuItem("Remove all display filters");
  -      menuItemRemoveDisplayFilter.addActionListener(
  -        new ActionListener() {
  -          public void actionPerformed(ActionEvent evt) {
  -            colorDisplaySelector.clearDisplay();
  -            displayFilter.clear();
  -          }
  -        });
  -
  -      final JPopupMenu p = new JPopupMenu();
  -
  -      p.add(menuItemToggleDock);
  -      p.add(new JSeparator());
  -
  -      p.add(menuItemDisplayFilter);
  -      p.add(menuColumnDisplayFilter);
  -      p.add(menuColumnColorFilter);
  -      p.add(new JSeparator());
  -
  -      p.add(menuDefineCustomFilter);
  -      p.add(new JSeparator());
  -
  -      p.add(menuItemColumnSelector);
  -      p.add(menuItemDetailFieldSelector);
  -      p.add(new JSeparator());
  -
  -      p.add(menuItemToggleDetails);
  -      p.add(new JSeparator());
  -
  -      p.add(menuItemToggleToolTips);
  -      p.add(new JSeparator());
  -
  -      p.add(menuItemScrollBottom);
  -      p.add(new JSeparator());
  -
  -      p.add(menuItemRemoveColorFilter);
  -      p.add(menuItemRemoveDisplayFilter);
  -      p.add(new JSeparator());
  -
  -      p.add(menuItemClear);
  -      p.add(new JSeparator());
  -
  -      p.add(menuItemRecoverPanes);
  -
  -      final PopupListener popupListener = new PopupListener(p);
  -
  -      eventsPane.addMouseListener(popupListener);
  -      table.addMouseListener(popupListener);
  -      detail.addMouseListener(popupListener);
  -
  -      tableMap.put(ident, table);
  -      tableModelMap.put(ident, tableModel);
  -      tabbedPane.add(ident, this);
  -      panelMap.put(ident, this);
  -      entryMap.put(ident, map);
  -
  -      tableModel.setEventCountListener(new EventCountListenerImpl(ident));
  -    }
  -    
  -    String getIdentifier() { 
  -    	return identifier;
  -    }
  -  }
  -
  -  /**
  -     * A thread ensuring that the JTable stays looking at the last entry
  -     * in the TableModel if it's been selected, effectively 'tail -f'
  -     * the streaming log events.
  -     */
  -    class ScrollDetailThread extends Thread {
  -      private Object mutex = new Object();
  -      private int scrolledRow = -1;
  -      private int lastRow = -1;
  -      private final JEditorPane pane;
  -      private final DefaultSortTableModel model;
  -
  -      public ScrollDetailThread(JEditorPane pane, DefaultSortTableModel model) {
  -        this.pane = pane;
  -        this.model = model;
  -        setDaemon(true);
  -      }
  -
  -      public void setScrolledRow(int row) {
  -        scrolledRow = row;
  -      }
  -
  -      public void run() {
  -        boolean setDetail = false;
  -
  -        while (true) {
  -          if (scrolledRow != lastRow) {
  -            setDetail = true;
  -          }
  -
  -          if (setDetail && (scrolledRow > -1) && (scrolledRow == lastRow)) {
  -            lastRow = scrolledRow;
  -
  -            String text = model.getDetailText(scrolledRow);
  -
  -            if (!((text != null) && !text.equals(""))) {
  -              text = "Nothing selected";
  -            }
  -
  -            final String text2 = text;
  -            setDetail = false;
  -            SwingUtilities.invokeLater(
  -              new Runnable() {
  -                public void run() {
  -                  pane.setText(text2);
  -                }
  -              });
  -          }
  -
  -          lastRow = scrolledRow;
  -
  -          synchronized (mutex) {
  -            try {
  -              mutex.wait(1000);
  -            } catch (InterruptedException ie) {
  -            }
  -          }
  -        }
  -      }
  -    }
  -
  -    /**
  -     * Thread that periodically checks if the selected row has changed, and if
  -     * it was, updates the Detail Panel with the detailed Logging information
  -     */
  -    class DetailThread extends Thread {
  -      private int selectedRow = -1;
  -      private int lastRow;
  -      private final JEditorPane pane;
  -      private final DefaultSortTableModel model;
  -
  -      public DetailThread(JEditorPane pane, DefaultSortTableModel model) {
  -        this.pane = pane;
  -        this.model = model;
  -        setDaemon(true);
  -      }
  -
  -      public void setSelectedRow(int row) {
  -        if (row==-1) {
  -          lastRow=0;
  -        }        
  -        selectedRow = row;
  -      }
  -
  -      public void run() {
  -        while (true) {
  -          String text = null;
  -
  -          if (selectedRow != lastRow) {
  -            if (selectedRow == -1) {
  -              text = "Nothing selected";
  -            } else {
  -              text = model.getDetailText(selectedRow);
  -            }
  -
  -            if (!((text != null) && !text.equals(""))) {
  -              text = "Nothing selected";
  -            }
  -
  -            lastRow = selectedRow;
  -
  -            final String text2 = text;
  -            SwingUtilities.invokeLater(
  -              new Runnable() {
  -                public void run() {
  -                  pane.setText(text2);
  -                }
  -              });
  -          }
  -
  -          synchronized (pane) {
  -            try {
  -              pane.wait();
  -            } catch (InterruptedException ie) {
  -            }
  -          }
  -        }
  -      }
  -    }
  -
  -  class ScrollToBottom extends Thread {
  -    boolean scrollToBottom;
  -    boolean bypassed;
  -
  -    public ScrollToBottom(boolean scrollToBottom) {
  -      this.scrollToBottom = scrollToBottom;
  -    }
  -
  -    public void scroll(boolean scrollToBottom) {
  -      this.scrollToBottom = scrollToBottom;
  -    }
  -
  -    public boolean isScrolled() {
  -      return scrollToBottom;
  -    }
  -
  -    public void bypass(boolean bypassed) {
  -      this.bypassed = bypassed;
  -    }
  -
  -    public boolean isBypassed() {
  -      return bypassed;
  -    }
  -  }
  +
  +	public String getActiveTabName() {
  +		int index = tabbedPane.getSelectedIndex();
  +		if (index == -1) {
  +			return null;
  +		} else {
  +			return tabbedPane.getTitleAt(index);
  +		}
  +	}
  +
  +	/**
  +	 * Determines an appropriate title for the Tab for the Tab Pane
  +	 * by locating a the log4jmachinename property
  +	 * @param v
  +	 * @return
  +	 */
  +	private String getTabIdentifier(Vector v) {
  +		int fieldIndex = names.indexOf(ChainsawConstants.PROPERTIES_COL_NAME);
  +		String properties = (String) v.get(fieldIndex);
  +
  +		String machinekey = ChainsawConstants.LOG4J_MACHINE_KEY + "=";
  +		String machinename = null;
  +		int machineposition =
  +			properties.indexOf(machinekey) + machinekey.length();
  +		int machinelength = properties.indexOf(",", machineposition);
  +
  +		if (machinelength == -1) {
  +			machinelength = properties.length();
  +		}
  +
  +		if (machineposition >= machinekey.length()) {
  +			machinename = properties.substring(machineposition, machinelength);
  +
  +			int dotposition = machinename.indexOf(".");
  +			boolean isnumeric = true;
  +
  +			if (dotposition > -1) {
  +				char[] firstdotpart =
  +					machinename.substring(0, dotposition).toCharArray();
  +
  +				for (int i = 0; i < firstdotpart.length; i++) {
  +					isnumeric = isnumeric && Character.isDigit(firstdotpart[i]);
  +				}
  +
  +				if (!isnumeric) {
  +					machinename = machinename.substring(0, dotposition);
  +				}
  +			}
  +		}
  +
  +		String appkey = ChainsawConstants.LOG4J_APP_KEY + "=";
  +		String appname = null;
  +		int appposition = properties.indexOf(appkey) + appkey.length();
  +
  +		if (appposition >= appkey.length()) {
  +			int applength = properties.indexOf(",", appposition);
  +
  +			if (applength == -1) {
  +				applength = properties.length();
  +			}
  +
  +			appname = properties.substring(appposition, applength);
  +		}
  +
  +		StringBuffer ident = new StringBuffer();
  +
  +		if (machinename != null) {
  +			ident.append(machinename);
  +		}
  +
  +		if (appname != null) {
  +			ident.append("-");
  +			ident.append(appname);
  +		}
  +
  +		if (ident.length() == 0) {
  +			ident.append(ChainsawConstants.UNKNOWN_TAB_NAME);
  +		}
  +
  +		return ident.toString();
  +	}
  +
  +	/**
  +	 * Routes a Vector of Logging Event elements into the approprate Tabbed Pane
  +	 * @param v
  +	 */
  +	public void receiveEvent(Vector v) {
  +		String ident = getTabIdentifier(v);
  +
  +		if (!pausedList.contains(ident)) {
  +			addRow(ident, formatFields(v));
  +		}
  +	}
  +
  +	public Vector getAllEvents(String ident) {
  +		return ((DefaultSortTableModel) tableModelMap.get(ident))
  +			.getAllEvents();
  +	}
  +
  +	public Vector getDisplayedEvents(String ident) {
  +		return ((DefaultSortTableModel) tableModelMap.get(ident))
  +			.getDisplayedEvents();
  +	}
  +	/**
  +	 * Formats the individual elements of an LoggingEvent by ensuring that
  +	 * there are no null bits, replacing them with EMPTY_STRING
  +	 * @param v
  +	 * @return
  +	 */
  +	private Vector formatFields(Vector v) {
  +		for (int i = 0; i < v.size(); i++) {
  +			if (v.get(i) == null) {
  +				v.set(i, ChainsawConstants.EMPTY_STRING);
  +			}
  +		}
  +
  +		return v;
  +	}
  +
  +	/**
  +	 * Regurgitates a DisplayFilter for a specific machine identifier
  +	 * by deserializing the settings from a file.
  +	 * @param ident
  +	 * @return
  +	 */
  +	private DisplayFilter loadDisplayFilter(String ident) {
  +		DisplayFilter d = null;
  +		ObjectInputStream s = null;
  +
  +		try {
  +			s =
  +				new ObjectInputStream(
  +					new BufferedInputStream(
  +						new FileInputStream(
  +							new File(
  +								ident
  +									+ ChainsawConstants.SETTINGS_EXTENSION))));
  +			d = (DisplayFilter) s.readObject();
  +		} catch (IOException ioe) {
  +		} catch (ClassNotFoundException cnfe) {
  +		} finally {
  +			if (s != null) {
  +				try {
  +					s.close();
  +				} catch (IOException ioe) {
  +				}
  +			}
  +		}
  +
  +		if (d == null) {
  +			d = new DisplayFilter(names);
  +		}
  +
  +		return d;
  +	}
  +
  +	/**
  +	 * Adds a specific row to a specific Tabbed Pane's TableModel.
  +	 *
  +	 * If there is currently no Tabbed Pane for the identifier, then a new
  +	 * one is created and added to this current Frames Tabbed Pane infrastructure
  +	 * @param ident
  +	 * @param v
  +	 */
  +	private void addRow(final String ident, Vector v) {
  +		final DefaultSortTableModel tableModel;
  +		final JSortTable table;
  +		final ScrollToBottom scrollToBottom;
  +		HashMap map = null;
  +
  +		if (tableModelMap.containsKey(ident)) {
  +			tableModel = (DefaultSortTableModel) tableModelMap.get(ident);
  +			map = (HashMap) entryMap.get(ident);
  +			scrollToBottom = (ScrollToBottom) scrollMap.get(ident);
  +			table = (JSortTable) tableMap.get(ident);
  +		} else {
  +			tableModel =
  +				new DefaultSortTableModel(new Vector(), new Vector(names));
  +			map = new HashMap();
  +			table = new JSortTable(tableModel);
  +			scrollToBottom = new ScrollToBottom(true);
  +			LogPanel thisPanel =
  +				new LogPanel(ident, tableModel, table, scrollToBottom, map);
  +			//      tabbedPane.add(ident, thisPanel);
  +			tabbedPane.insertTab(ident, null, thisPanel, null, 0);
  +			System.out.println("Creating tab " + ident);
  +		}
  +
  +		((HashSet) map.get(ChainsawConstants.LOGGER_COL_NAME)).add(
  +			v.get(names.indexOf(ChainsawConstants.LOGGER_COL_NAME)));
  +		((HashSet) map.get(ChainsawConstants.LEVEL_COL_NAME)).add(
  +			v.get(names.indexOf(ChainsawConstants.LEVEL_COL_NAME)));
  +		((HashSet) map.get(ChainsawConstants.THREAD_COL_NAME)).add(
  +			v.get(names.indexOf(ChainsawConstants.THREAD_COL_NAME)));
  +		((HashSet) map.get(ChainsawConstants.NDC_COL_NAME)).add(
  +			v.get(names.indexOf(ChainsawConstants.NDC_COL_NAME)));
  +		((HashSet) map.get(ChainsawConstants.MDC_COL_NAME)).add(
  +			v.get(names.indexOf(ChainsawConstants.MDC_COL_NAME)));
  +		((HashSet) map.get(ChainsawConstants.CLASS_COL_NAME)).add(
  +			v.get(names.indexOf(ChainsawConstants.CLASS_COL_NAME)));
  +		((HashSet) map.get(ChainsawConstants.METHOD_COL_NAME)).add(
  +			v.get(names.indexOf(ChainsawConstants.METHOD_COL_NAME)));
  +		((HashSet) map.get(ChainsawConstants.FILE_COL_NAME)).add(
  +			v.get(names.indexOf(ChainsawConstants.FILE_COL_NAME)));
  +
  +		table.getSelectionModel().setValueIsAdjusting(true);
  +
  +		if (tableModel.isAddRow(v)) {
  +			if (scrollToBottom.isScrolled() && !scrollToBottom.isBypassed()) {
  +				table.scrollToBottom(
  +					table.columnAtPoint(table.getVisibleRect().getLocation()));
  +			}
  +		}
  +	}
  +
  +	/**
  +	 * An implementation of the EventCountListener that modifies
  +	 * the border of a panel with the new counter information
  +	 */
  +	class EventCountListenerImpl implements EventCountListener {
  +		private String ident;
  +		private DefaultSortTableModel model;
  +
  +		public EventCountListenerImpl(String ident) {
  +			this.ident = ident;
  +			model = (DefaultSortTableModel) tableModelMap.get(ident);
  +		}
  +
  +		public void eventCountChanged(int current, int total) {
  +			TitledBorder eventBorder = (TitledBorder) eventBorderMap.get(ident);
  +			JPanel panel = (JPanel) panelMap.get(ident);
  +			String title = "Events - showing " + current + " of " + total;
  +			eventBorder.setTitle(title);
  +			panel.repaint(panel.getVisibleRect());
  +		}
  +	}
  +
  +	/**
  +	 * Ensures that a specific popupMenu is displayed when the relevant
  +	 * mouse events are trapped.
  +	 */
  +	class PopupListener extends MouseAdapter {
  +		final JPopupMenu popupMenu;
  +
  +		PopupListener(JPopupMenu popupMenu) {
  +			this.popupMenu = popupMenu;
  +		}
  +
  +		public void mousePressed(MouseEvent e) {
  +			checkPopup(e);
  +		}
  +
  +		public void mouseReleased(MouseEvent e) {
  +			checkPopup(e);
  +		}
  +
  +		private void checkPopup(MouseEvent e) {
  +			if (e.isPopupTrigger()) {
  +				popupMenu.show(e.getComponent(), e.getX(), e.getY());
  +			}
  +		}
  +	}
  +
  +	/**
  +	 * LogPanel encapsulates all the necessary bits and pieces of a
  +	 * floating window of Events coming from a specific Location.
  +	 *
  +	 * This is where most of the Swing components are constructed and laid out.
  +	 */
  +	class LogPanel extends DockablePanel {
  +		final ColorFilter colorFilter = new ColorFilter();
  +		final DisplayFilter displayFilter;
  +		boolean isDocked = true;
  +		String identifier;
  +		final Map columnDisplayMap = new HashMap();
  +		final Map colorDisplayMap = new HashMap();
  +		final Set loggerSet = new HashSet();
  +		final ColorDisplaySelector colorDisplaySelector;
  +		Set levelSet = new HashSet();
  +		Set MDCSet = new HashSet();
  +		Set NDCSet = new HashSet();
  +		Set threadSet = new HashSet();
  +		Set classSet = new HashSet();
  +		Set methodSet = new HashSet();
  +		Set fileSet = new HashSet();
  +
  +		//used for consistency - stays empty - used to allow none set in the colordisplay selector and right click
  +		Set noneSet = new HashSet();
  +		Point currentPoint;
  +
  +		public LogPanel(
  +			final String ident,
  +			final DefaultSortTableModel tableModel,
  +			final JSortTable table,
  +			final ScrollToBottom scrollToBottom,
  +			final Map map) {
  +
  +			identifier = ident;
  +			map.put(ChainsawConstants.LEVEL_COL_NAME, levelSet);
  +			levelSet.addAll(levelList);
  +
  +			map.put(ChainsawConstants.LOGGER_COL_NAME, loggerSet);
  +			map.put(ChainsawConstants.THREAD_COL_NAME, threadSet);
  +			map.put(ChainsawConstants.NDC_COL_NAME, NDCSet);
  +			map.put(ChainsawConstants.MDC_COL_NAME, MDCSet);
  +			map.put(ChainsawConstants.CLASS_COL_NAME, classSet);
  +			map.put(ChainsawConstants.METHOD_COL_NAME, methodSet);
  +			map.put(ChainsawConstants.FILE_COL_NAME, fileSet);
  +			map.put(ChainsawConstants.NONE_COL_NAME, noneSet);
  +
  +			setLayout(new BorderLayout());
  +			displayFilter = loadDisplayFilter(ident);
  +			tableModel.setDisplayFilter(displayFilter);
  +			displayFilter.addFilterChangedListener(tableModel);
  +
  +			scrollMap.put(ident, scrollToBottom);
  +
  +			TableColorizingRenderer renderer = new TableColorizingRenderer();
  +			renderer.setColorFilter(colorFilter);
  +
  +			colorFilter.addFilterChangedListener(renderer);
  +			displayFilter.addFilterChangedListener(renderer);
  +
  +			table.setDefaultRenderer(Object.class, renderer);
  +
  +			final DetailFieldSelector detailFieldSelector =
  +				new DetailFieldSelector(new Vector(names), displayFilter);
  +
  +			final ColumnSelector columnSelector =
  +				new ColumnSelector(new Vector(names), table, displayFilter);
  +
  +			JMenu menuColumnDisplayFilter =
  +				new JMenu("Apply display filter for column");
  +
  +			JMenu menuColumnColorFilter =
  +				new JMenu("Apply color filter for column");
  +
  +			ButtonGroup bg = new ButtonGroup();
  +			Iterator iter = filterableColumns.iterator();
  +
  +			while (iter.hasNext()) {
  +				final String colName = (String) iter.next();
  +				JRadioButtonMenuItem thisItem =
  +					new JRadioButtonMenuItem(colName);
  +				thisItem.setFont(thisItem.getFont().deriveFont(Font.PLAIN));
  +				thisItem.addActionListener(new ActionListener() {
  +					public void actionPerformed(ActionEvent evt) {
  +						colorDisplaySelector.applyColorUpdateForColumn(colName);
  +						colorDisplaySelector.applyColorFilters(colName);
  +					}
  +				});
  +				bg.add(thisItem);
  +				menuColumnColorFilter.add(thisItem);
  +				colorDisplayMap.put(colName, thisItem);
  +			}
  +
  +			ButtonGroup bg2 = new ButtonGroup();
  +			Iterator iter2 = filterableColumns.iterator();
  +
  +			while (iter2.hasNext()) {
  +				final String colName = (String) iter2.next();
  +				JRadioButtonMenuItem thisItem =
  +					new JRadioButtonMenuItem(colName);
  +				thisItem.setFont(thisItem.getFont().deriveFont(Font.PLAIN));
  +				thisItem.addActionListener(new ActionListener() {
  +					public void actionPerformed(ActionEvent evt) {
  +						colorDisplaySelector.applyDisplayUpdateForColumn(
  +							colName);
  +						colorDisplaySelector.applyDisplayFilters(colName);
  +					}
  +				});
  +				bg2.add(thisItem);
  +				menuColumnDisplayFilter.add(thisItem);
  +				columnDisplayMap.put(colName, thisItem);
  +			}
  +
  +			colorDisplaySelector =
  +				new ColorDisplaySelector(
  +					ident,
  +					map,
  +					colorFilter,
  +					displayFilter,
  +					colorDisplayMap,
  +					columnDisplayMap,
  +					names,
  +					filterableColumns,
  +					levelList);
  +
  +			table.addMouseMotionListener(new MouseMotionAdapter() {
  +				int currentRow = -1;
  +
  +				public void mouseMoved(MouseEvent evt) {
  +					currentPoint = evt.getPoint();
  +
  +					if (displayFilter.isToolTipsEnabled()) {
  +						int row = table.rowAtPoint(evt.getPoint());
  +
  +						if ((row == currentRow) || (row == -1)) {
  +							return;
  +						}
  +
  +						currentRow = row;
  +
  +						table.setToolTipText(
  +							(
  +								(DefaultSortTableModel) table
  +									.getModel())
  +									.getDetailText(
  +								row));
  +					} else {
  +						table.setToolTipText(null);
  +					}
  +				}
  +			});
  +
  +			//HACK - fix the way columns are sized..should be saved off and loaded later
  +			table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
  +
  +			int colCount = table.getColumnModel().getColumnCount();
  +			int curCol = 1;
  +
  +			//assumes there's at least one column showing..
  +			TableColumn col = table.getColumnModel().getColumn(0);
  +			col.setPreferredWidth(120);
  +
  +			if (curCol++ < colCount) {
  +				col = table.getColumnModel().getColumn(1);
  +				col.setPreferredWidth(100);
  +			}
  +
  +			if (curCol++ < colCount) {
  +				col = table.getColumnModel().getColumn(2);
  +				col.setPreferredWidth(100);
  +			}
  +
  +			if (curCol++ < colCount) {
  +				col = table.getColumnModel().getColumn(3);
  +				col.setPreferredWidth(150);
  +			}
  +
  +			if (curCol++ < colCount) {
  +				col = table.getColumnModel().getColumn(4);
  +				col.setPreferredWidth(300);
  +			}
  +
  +			if (curCol++ < colCount) {
  +				col = table.getColumnModel().getColumn(5);
  +				col.setPreferredWidth(100);
  +			}
  +
  +			if (curCol++ < colCount) {
  +				col = table.getColumnModel().getColumn(6);
  +				col.setPreferredWidth(250);
  +			}
  +
  +			if (curCol++ < colCount) {
  +				col = table.getColumnModel().getColumn(7);
  +				col.setPreferredWidth(200);
  +			}
  +
  +			if (curCol++ < colCount) {
  +				col = table.getColumnModel().getColumn(8);
  +				col.setPreferredWidth(300);
  +			}
  +
  +			if (curCol++ < colCount) {
  +				col = table.getColumnModel().getColumn(9);
  +				col.setPreferredWidth(150);
  +			}
  +
  +			if (curCol++ < colCount) {
  +				col = table.getColumnModel().getColumn(10);
  +				col.setPreferredWidth(120);
  +			}
  +
  +			if (curCol++ < colCount) {
  +				col = table.getColumnModel().getColumn(11);
  +				col.setPreferredWidth(50);
  +			}
  +
  +			if (curCol++ < colCount) {
  +				col = table.getColumnModel().getColumn(12);
  +				col.setPreferredWidth(300);
  +			}
  +
  +			final JEditorPane detail =
  +				new JEditorPane(ChainsawConstants.DETAIL_CONTENT_TYPE, "");
  +			detail.setEditable(false);
  +
  +			final DetailThread detailThread =
  +				new DetailThread(detail, tableModel);
  +			detailThread.start();
  +
  +			GridBagLayout gridbag = new GridBagLayout();
  +			GridBagConstraints gbc = new GridBagConstraints();
  +
  +			final JPanel upperPanel = new JPanel(gridbag);
  +			upperPanel.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
  +
  +			gbc.gridx = 0;
  +			gbc.gridy = 0;
  +			gbc.weightx = 0;
  +
  +			final JLabel filterLabel = new JLabel("Filter: ");
  +			gbc.gridx = 1;
  +			gbc.gridy = 0;
  +			gbc.weightx = 0;
  +			gridbag.setConstraints(filterLabel, gbc);
  +			upperPanel.add(filterLabel);
  +
  +			final JComboBox customFilterList = new JComboBox(names.toArray());
  +
  +			final JTextField filterText = new JTextField();
  +
  +			filterText
  +				.getDocument()
  +				.addDocumentListener(new DocumentListener() {
  +				public void insertUpdate(DocumentEvent e) {
  +					setFilter();
  +				}
  +
  +				public void removeUpdate(DocumentEvent e) {
  +					setFilter();
  +				}
  +
  +				public void changedUpdate(DocumentEvent e) {
  +					setFilter();
  +				}
  +
  +				public void setFilter() {
  +					if (filterText.getText().equals("")) {
  +						displayFilter.setCustomFilter(null);
  +					} else {
  +						synchronized (detail) {
  +							detailThread.setSelectedRow(-1);
  +							detail.notify();
  +						}
  +
  +						displayFilter.setCustomFilter(
  +							new DisplayFilterEntry(
  +								(String) customFilterList.getSelectedItem(),
  +								filterText.getText(),
  +								ChainsawConstants.GLOBAL_MATCH,
  +								Boolean.TRUE));
  +					}
  +				}
  +			});
  +
  +			gbc.gridx = 4;
  +			gbc.gridy = 0;
  +			gbc.weightx = 1;
  +			gbc.fill = GridBagConstraints.HORIZONTAL;
  +			gridbag.setConstraints(filterText, gbc);
  +
  +			String evaluator =
  +				ExpressionEvaluatorFactory
  +					.newInstance()
  +					.getEvaluatorClassName();
  +			filterText.setToolTipText(
  +				"See " + evaluator + " documentation for expression rules");
  +
  +			customFilterList.setMaximumRowCount(15);
  +			gbc.gridx = 2;
  +			gbc.gridy = 0;
  +			gbc.weightx = 0;
  +			gridbag.setConstraints(customFilterList, gbc);
  +			upperPanel.add(customFilterList);
  +
  +			customFilterList.addActionListener(new ActionListener() {
  +				public void actionPerformed(ActionEvent evt) {
  +					if (!(filterText.getText().equals(""))) {
  +						displayFilter.setCustomFilter(
  +							new DisplayFilterEntry(
  +								(String) customFilterList.getSelectedItem(),
  +								filterText.getText(),
  +								"*",
  +								Boolean.TRUE));
  +					}
  +				}
  +			});
  +
  +			final JCheckBox override = new JCheckBox("Override");
  +			gbc.gridx = 3;
  +			gbc.gridy = 0;
  +			gbc.weightx = 0;
  +			gridbag.setConstraints(override, gbc);
  +			upperPanel.add(override);
  +			override.addActionListener(new ActionListener() {
  +				public void actionPerformed(ActionEvent evt) {
  +					displayFilter.setCustomFilterOverride(
  +						override.isSelected());
  +				}
  +			});
  +
  +			upperPanel.add(filterText);
  +
  +			JLabel findLabel = new JLabel("Find: ");
  +			gbc.gridx = 5;
  +			gbc.gridy = 0;
  +			gbc.weightx = 0;
  +			gridbag.setConstraints(findLabel, gbc);
  +			upperPanel.add(findLabel);
  +
  +			final JTextField findText = new JTextField();
  +
  +			gbc.gridx = 6;
  +			gbc.gridy = 0;
  +			gbc.weightx = 1;
  +			gbc.fill = GridBagConstraints.HORIZONTAL;
  +			gridbag.setConstraints(findText, gbc);
  +			findText.setToolTipText(
  +				"Performs a case-insensitive search across all columns");
  +			upperPanel.add(findText);
  +
  +			findText.getDocument().addDocumentListener(new DocumentListener() {
  +				public void insertUpdate(DocumentEvent e) {
  +					find();
  +				}
  +
  +				public void removeUpdate(DocumentEvent e) {
  +					find();
  +				}
  +
  +				public void changedUpdate(DocumentEvent e) {
  +					find();
  +				}
  +
  +				public void find() {
  +					final int row = tableModel.find(0, findText.getText());
  +
  +					if (findText.getDocument().getLength() == 0) {
  +						scrollToBottom.bypass(false);
  +					} else {
  +						scrollToBottom.bypass(true);
  +					}
  +
  +					table.scrollToRow(
  +						row,
  +						table.columnAtPoint(
  +							table.getVisibleRect().getLocation()));
  +				}
  +			});
  +
  +			String findNextActionLabel = "Find next";
  +			Action findNextAction = new AbstractAction(findNextActionLabel) {
  +				public void actionPerformed(ActionEvent evt) {
  +					final int row =
  +						tableModel.find(
  +							table.getSelectedRow() + 1,
  +							findText.getText());
  +					table.scrollToRow(
  +						row,
  +						table.columnAtPoint(
  +							table.getVisibleRect().getLocation()));
  +				}
  +			};
  +
  +			findNextAction.putValue(
  +				Action.SHORT_DESCRIPTION,
  +				"Finds the next match");
  +
  +			JButton findButton = new JButton(findNextAction);
  +			findButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
  +				KeyStroke.getKeyStroke("F3"),
  +				findNextActionLabel);
  +			findButton.getActionMap().put(
  +				findNextAction.getValue(Action.NAME),
  +				findNextAction);
  +
  +			gbc.gridx = 7;
  +			gbc.gridy = 0;
  +			gbc.weightx = 0;
  +			gridbag.setConstraints(findButton, gbc);
  +
  +			upperPanel.add(findButton);
  +
  +			final JScrollPane eventsPane = new JScrollPane(table);
  +			eventsPane.setPreferredSize(new Dimension(900, 300));
  +
  +			TitledBorder eventsBorder =
  +				BorderFactory.createTitledBorder("Events");
  +			eventsPane.setBorder(eventsBorder);
  +			eventBorderMap.put(ident, eventsBorder);
  +
  +			final JPanel detailPanel = new JPanel(new BorderLayout());
  +
  +			//set valueisadjusting if holding down a key - don't process setdetail events
  +			table.addKeyListener(new KeyListener() {
  +				public void keyTyped(KeyEvent e) {
  +				}
  +
  +				public void keyPressed(KeyEvent e) {
  +					synchronized (detail) {
  +						table.getSelectionModel().setValueIsAdjusting(true);
  +						detail.notify();
  +					}
  +				}
  +
  +				public void keyReleased(KeyEvent e) {
  +					synchronized (detail) {
  +						table.getSelectionModel().setValueIsAdjusting(false);
  +						detail.notify();
  +					}
  +				}
  +			});
  +
  +			final JScrollPane detailPane = new JScrollPane(detail);
  +			detailPane.setPreferredSize(new Dimension(900, 50));
  +
  +			detailPanel.add(detailPane, BorderLayout.CENTER);
  +
  +			final JSplitPane lowerPanel =
  +				new JSplitPane(
  +					JSplitPane.VERTICAL_SPLIT,
  +					eventsPane,
  +					detailPanel);
  +			lowerPanel.setDividerLocation(150);
  +			lowerPanel.setOneTouchExpandable(true);
  +
  +			add(upperPanel, BorderLayout.NORTH);
  +			add(lowerPanel, BorderLayout.CENTER);
  +
  +			table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
  +
  +			final ScrollDetailThread scrollDetailThread =
  +				new ScrollDetailThread(detail, tableModel);
  +			scrollDetailThread.start();
  +
  +			table
  +				.getSelectionModel()
  +				.addListSelectionListener(new ListSelectionListener() {
  +				public void valueChanged(ListSelectionEvent evt) {
  +					if (((ScrollToBottom) scrollMap.get(ident)).isScrolled()) {
  +						scrollDetailThread.setScrolledRow(
  +							table.getSelectedRow());
  +					} else {
  +						scrollDetailThread.setScrolledRow(-1);
  +					}
  +
  +					if (evt.getValueIsAdjusting()) {
  +						return;
  +					}
  +
  +					final ListSelectionModel lsm =
  +						(ListSelectionModel) evt.getSource();
  +
  +					if (lsm.isSelectionEmpty()) {
  +						if (detail.getDocument().getDefaultRootElement()
  +							!= null) {
  +							synchronized (detail) {
  +								detailThread.setSelectedRow(-1);
  +								detail.notify();
  +							}
  +						}
  +					} else {
  +						if (table.getSelectedRow() > -1) {
  +							int selectedRow = table.getSelectedRow();
  +
  +							try {
  +								if (tableModel.getRowCount() >= selectedRow) {
  +									synchronized (detail) {
  +										detailThread.setSelectedRow(
  +											table.getSelectedRow());
  +										detail.notify();
  +									}
  +								} else {
  +									synchronized (detail) {
  +										detailThread.setSelectedRow(-1);
  +										detail.notify();
  +									}
  +								}
  +							} catch (Exception e) {
  +								e.printStackTrace();
  +
  +								synchronized (detail) {
  +									detailThread.setSelectedRow(-1);
  +									detail.notify();
  +								}
  +							}
  +						}
  +					}
  +				}
  +			});
  +
  +			final JMenuItem menuItemToggleDock = new JMenuItem("Undock/dock");
  +
  +			final JFrame f = new JFrame(ident);
  +			final DockablePanel externalPanel = new DockablePanel();
  +			externalPanel.setLayout(new BorderLayout());
  +			f.setSize(new Dimension(500, 500));
  +			f.getContentPane().add(externalPanel);
  +
  +			f.addWindowListener(new WindowAdapter() {
  +				public void windowClosing(WindowEvent event) {
  +					HashMap m = new HashMap();
  +					m.put(ChainsawConstants.MAIN_PANEL, LogPanel.this);
  +					m.put(ChainsawConstants.UPPER_PANEL, upperPanel);
  +					m.put(ChainsawConstants.LOWER_PANEL, lowerPanel);
  +					lostMap.put(ident, m);
  +				}
  +			});
  +
  +			menuItemToggleDock.addActionListener(new ActionListener() {
  +				public void actionPerformed(ActionEvent evt) {
  +					if (isDocked()) {
  +						externalPanel.removeAll();
  +						externalPanel.add(upperPanel, BorderLayout.NORTH);
  +						externalPanel.add(lowerPanel, BorderLayout.CENTER);
  +						tabbedPane.remove(LogPanel.this);
  +						externalPanel.setDocked(false);
  +						setDocked(false);
  +						panelMap.put(ident, externalPanel);
  +						f.setVisible(true);
  +					} else {
  +						f.setVisible(false);
  +						removeAll();
  +						add(upperPanel, BorderLayout.NORTH);
  +						add(lowerPanel, BorderLayout.CENTER);
  +						panelMap.put(ident, LogPanel.this);
  +						tabbedPane.add(ident, LogPanel.this);
  +						externalPanel.setDocked(true);
  +						setDocked(true);
  +					}
  +				}
  +			});
  +
  +			JMenuItem menuItemDisplayFilter =
  +				new JMenuItem("Define display and color filters...");
  +			menuItemDisplayFilter.addActionListener(new ActionListener() {
  +				public void actionPerformed(ActionEvent evt) {
  +					colorDisplaySelector.show();
  +				}
  +			});
  +
  +			//      final Boolean initialToggling = (lowerPanel.getDividerLocation() != (lowerPanel.getHeight()- lowerPanel.getDividerSize())          
  +			Action toggleDetailPaneAction =
  +				new AbstractAction("Show Detail Pane") {
  +				boolean enabled = true;
  +				public void actionPerformed(ActionEvent evt) {
  +					if (enabled) {
  +						lowerPanel.setDividerLocation(
  +							lowerPanel.getLastDividerLocation());
  +					} else {
  +						int lastPosition = lowerPanel.getDividerLocation();
  +						lowerPanel.setDividerLocation(1.0d);
  +						lowerPanel.setLastDividerLocation(lastPosition);
  +					}
  +				}
  +			};
  +			toggleDetailPaneAction.putValue("enabled", Boolean.TRUE);
  +			toggleDetailPaneAction.putValue(
  +				Action.ACCELERATOR_KEY,
  +				KeyStroke.getKeyStroke(KeyEvent.VK_D, InputEvent.ALT_MASK));
  +			toggleDetailPaneAction.putValue(
  +				Action.SHORT_DESCRIPTION,
  +				"Hides/Shows the Detail Pane");
  +
  +			JCheckBoxMenuItem menuItemToggleDetails =
  +				new JCheckBoxMenuItem(toggleDetailPaneAction);
  +			//      TODO this hot key doesn't seem to work just yet
  +			//      menuItemToggleDetails.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_D, InputEvent.ALT_MASK), toggleDetailPaneAction.getValue(Action.NAME));
  +			//      menuItemToggleDetails.getActionMap().put(toggleDetailPaneAction.getValue(Action.NAME), toggleDetailPaneAction);
  +
  +			menuItemToggleDetails.setSelected(true);
  +
  +			final JCheckBoxMenuItem menuItemToggleToolTips =
  +				new JCheckBoxMenuItem(
  +					"Show ToolTips",
  +					displayFilter.isToolTipsEnabled());
  +			menuItemToggleToolTips.addActionListener(new ActionListener() {
  +				public void actionPerformed(ActionEvent evt) {
  +					displayFilter.enableToolTips(
  +						menuItemToggleToolTips.isSelected());
  +				}
  +			});
  +
  +			final JMenuItem menuDefineCustomFilter =
  +				new JMenuItem("Custom filter from mouse location");
  +			menuDefineCustomFilter.addActionListener(new ActionListener() {
  +				public void actionPerformed(ActionEvent evt) {
  +					if (currentPoint != null) {
  +						int column = table.columnAtPoint(currentPoint);
  +						int row = table.rowAtPoint(currentPoint);
  +						String colName = tableModel.getColumnName(column);
  +						String value = "";
  +
  +						if (colName
  +							.equalsIgnoreCase(
  +								ChainsawConstants.TIMESTAMP_COL_NAME)) {
  +							JComponent comp =
  +								(JComponent) table.getCellRenderer(row, column);
  +
  +							if (comp instanceof JLabel) {
  +								value = ((JLabel) comp).getText();
  +							}
  +						} else {
  +							value = table.getValueAt(row, column).toString();
  +						}
  +
  +						customFilterList.setSelectedItem(colName);
  +						filterText.setText(value);
  +					}
  +				}
  +			});
  +
  +			final JCheckBoxMenuItem menuItemScrollBottom =
  +				new JCheckBoxMenuItem(
  +					"Scroll to bottom",
  +					scrollToBottom.isScrolled());
  +			menuItemScrollBottom.addActionListener(new ActionListener() {
  +				public void actionPerformed(ActionEvent evt) {
  +					scrollToBottom.scroll(menuItemScrollBottom.isSelected());
  +				}
  +			});
  +
  +			JMenuItem menuItemClear =
  +				new JMenuItem("Clear all entries for this panel");
  +			menuItemClear.addActionListener(new ActionListener() {
  +				public void actionPerformed(ActionEvent evt) {
  +					TableModel model = table.getModel();
  +
  +					if (model instanceof DefaultSortTableModel) {
  +						((DefaultSortTableModel) model).setRowCount(0);
  +
  +						synchronized (detail) {
  +							detailThread.setSelectedRow(-1);
  +							detail.notify();
  +						}
  +					}
  +				}
  +			});
  +
  +			JMenuItem menuItemRecoverPanes =
  +				new JMenuItem("Recover closed panes");
  +			menuItemRecoverPanes.addActionListener(new ActionListener() {
  +				public void actionPerformed(ActionEvent evt) {
  +					Set s = lostMap.entrySet();
  +					Iterator iter = s.iterator();
  +
  +					while (iter.hasNext()) {
  +						Map.Entry m = (Map.Entry) iter.next();
  +						String title = (String) m.getKey();
  +						HashMap map = (HashMap) m.getValue();
  +						JSplitPane lower =
  +							(JSplitPane) map.get(ChainsawConstants.LOWER_PANEL);
  +						JPanel upper =
  +							(JPanel) map.get(ChainsawConstants.UPPER_PANEL);
  +						DockablePanel thisPanel =
  +							(DockablePanel) map.get(
  +								ChainsawConstants.MAIN_PANEL);
  +						thisPanel.add(upper, BorderLayout.NORTH);
  +						thisPanel.add(lower, BorderLayout.CENTER);
  +						panelMap.put(title, thisPanel);
  +						tabbedPane.add(title, thisPanel);
  +						thisPanel.setDocked(true);
  +					}
  +
  +					lostMap.clear();
  +				}
  +			});
  +
  +			JMenuItem menuItemRemoveColorFilter =
  +				new JMenuItem("Remove all color filters");
  +			menuItemRemoveColorFilter.addActionListener(new ActionListener() {
  +				public void actionPerformed(ActionEvent evt) {
  +					colorDisplaySelector.clearColors();
  +					colorFilter.clear();
  +				}
  +			});
  +
  +			JMenuItem menuItemDetailFieldSelector =
  +				new JMenuItem("Select tooltip/detail columns...");
  +			menuItemDetailFieldSelector
  +				.addActionListener(new ActionListener() {
  +				public void actionPerformed(ActionEvent evt) {
  +					detailFieldSelector.show();
  +				}
  +			});
  +
  +			JMenuItem menuItemColumnSelector =
  +				new JMenuItem("Select display columns...");
  +			menuItemColumnSelector.addActionListener(new ActionListener() {
  +				public void actionPerformed(ActionEvent evt) {
  +					columnSelector.show();
  +				}
  +			});
  +
  +			JMenuItem menuItemRemoveDisplayFilter =
  +				new JMenuItem("Remove all display filters");
  +			menuItemRemoveDisplayFilter
  +				.addActionListener(new ActionListener() {
  +				public void actionPerformed(ActionEvent evt) {
  +					colorDisplaySelector.clearDisplay();
  +					displayFilter.clear();
  +				}
  +			});
  +
  +			final JPopupMenu p = new JPopupMenu();
  +
  +			p.add(menuItemToggleDock);
  +			p.add(new JSeparator());
  +
  +			p.add(menuItemDisplayFilter);
  +			p.add(menuColumnDisplayFilter);
  +			p.add(menuColumnColorFilter);
  +			p.add(new JSeparator());
  +
  +			p.add(menuDefineCustomFilter);
  +			p.add(new JSeparator());
  +
  +			p.add(menuItemColumnSelector);
  +			p.add(menuItemDetailFieldSelector);
  +			p.add(new JSeparator());
  +
  +			p.add(menuItemToggleDetails);
  +			p.add(new JSeparator());
  +
  +			p.add(menuItemToggleToolTips);
  +			p.add(new JSeparator());
  +
  +			p.add(menuItemScrollBottom);
  +			p.add(new JSeparator());
  +
  +			p.add(menuItemRemoveColorFilter);
  +			p.add(menuItemRemoveDisplayFilter);
  +			p.add(new JSeparator());
  +
  +			p.add(menuItemClear);
  +			p.add(new JSeparator());
  +
  +			p.add(menuItemRecoverPanes);
  +
  +			final PopupListener popupListener = new PopupListener(p);
  +
  +			eventsPane.addMouseListener(popupListener);
  +			table.addMouseListener(popupListener);
  +			detail.addMouseListener(popupListener);
  +
  +			tableMap.put(ident, table);
  +			tableModelMap.put(ident, tableModel);
  +			tabbedPane.add(ident, this);
  +			panelMap.put(ident, this);
  +			entryMap.put(ident, map);
  +
  +			tableModel.setEventCountListener(new EventCountListenerImpl(ident));
  +		}
  +
  +		String getIdentifier() {
  +			return identifier;
  +		}
  +	}
  +
  +	/**
  +	   * A thread ensuring that the JTable stays looking at the last entry
  +	   * in the TableModel if it's been selected, effectively 'tail -f'
  +	   * the streaming log events.
  +	   */
  +	class ScrollDetailThread extends Thread {
  +		private Object mutex = new Object();
  +		private int scrolledRow = -1;
  +		private int lastRow = -1;
  +		private final JEditorPane pane;
  +		private final DefaultSortTableModel model;
  +
  +		public ScrollDetailThread(
  +			JEditorPane pane,
  +			DefaultSortTableModel model) {
  +			this.pane = pane;
  +			this.model = model;
  +			setDaemon(true);
  +		}
  +
  +		public void setScrolledRow(int row) {
  +			scrolledRow = row;
  +		}
  +
  +		public void run() {
  +			boolean setDetail = false;
  +
  +			while (true) {
  +				if (scrolledRow != lastRow) {
  +					setDetail = true;
  +				}
  +
  +				if (setDetail
  +					&& (scrolledRow > -1)
  +					&& (scrolledRow == lastRow)) {
  +					lastRow = scrolledRow;
  +
  +					String text = model.getDetailText(scrolledRow);
  +
  +					if (!((text != null) && !text.equals(""))) {
  +						text = "Nothing selected";
  +					}
  +
  +					final String text2 = text;
  +					setDetail = false;
  +					SwingUtilities.invokeLater(new Runnable() {
  +						public void run() {
  +							pane.setText(text2);
  +						}
  +					});
  +				}
  +
  +				lastRow = scrolledRow;
  +
  +				synchronized (mutex) {
  +					try {
  +						mutex.wait(1000);
  +					} catch (InterruptedException ie) {
  +					}
  +				}
  +			}
  +		}
  +	}
  +
  +	/**
  +	 * Thread that periodically checks if the selected row has changed, and if
  +	 * it was, updates the Detail Panel with the detailed Logging information
  +	 */
  +	class DetailThread extends Thread {
  +		private int selectedRow = -1;
  +		private int lastRow;
  +		private final JEditorPane pane;
  +		private final DefaultSortTableModel model;
  +
  +		public DetailThread(JEditorPane pane, DefaultSortTableModel model) {
  +			this.pane = pane;
  +			this.model = model;
  +			setDaemon(true);
  +		}
  +
  +		public void setSelectedRow(int row) {
  +			if (row == -1) {
  +				lastRow = 0;
  +			}
  +			selectedRow = row;
  +		}
  +
  +		public void run() {
  +			while (true) {
  +				String text = null;
  +
  +				if (selectedRow != lastRow) {
  +					if (selectedRow == -1) {
  +						text = "Nothing selected";
  +					} else {
  +						text = model.getDetailText(selectedRow);
  +					}
  +
  +					if (!((text != null) && !text.equals(""))) {
  +						text = "Nothing selected";
  +					}
  +
  +					lastRow = selectedRow;
  +
  +					final String text2 = text;
  +					SwingUtilities.invokeLater(new Runnable() {
  +						public void run() {
  +							pane.setText(text2);
  +						}
  +					});
  +				}
  +
  +				synchronized (pane) {
  +					try {
  +						pane.wait();
  +					} catch (InterruptedException ie) {
  +					}
  +				}
  +			}
  +		}
  +	}
  +
  +	class ScrollToBottom extends Thread {
  +		boolean scrollToBottom;
  +		boolean bypassed;
  +
  +		public ScrollToBottom(boolean scrollToBottom) {
  +			this.scrollToBottom = scrollToBottom;
  +		}
  +
  +		public void scroll(boolean scrollToBottom) {
  +			this.scrollToBottom = scrollToBottom;
  +		}
  +
  +		public boolean isScrolled() {
  +			return scrollToBottom;
  +		}
  +
  +		public void bypass(boolean bypassed) {
  +			this.bypassed = bypassed;
  +		}
  +
  +		public boolean isBypassed() {
  +			return bypassed;
  +		}
  +	}
   }
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: log4j-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: log4j-dev-help@jakarta.apache.org


Mime
View raw message