[prev in list] [next in list] [prev in thread] [next in thread] 

List:       apache-logging-general
Subject:    svn commit: r595870 - in
From:       sdeboy () apache ! org
Date:       2007-11-16 23:31:44
Message-ID: 20071116233144.ECAD21A9832 () eris ! apache ! org
[Download RAW message or body]

Author: sdeboy
Date: Fri Nov 16 15:31:40 2007
New Revision: 595870

URL: http://svn.apache.org/viewvc?rev=595870&view=rev
Log:
Scroll-to-bottom now works as expected:
- Click of the scroll to bottom button works for cyclic, filtered, etc
- Click on any row deselects scroll to bottom button and maintains selection as long \
                as the row isn't filtered out or nuked from cyclic buffer
- Ensure that updates to the table model cause selection changes within the same call \
                (table model update is on EDT, selection change is made while still \
                in same call)
- Goto-line now scrolls to first column of row (was going to 2nd)

Much thanks to Jeff Kinzer for the help in getting selection working (and lots of \
testing!)

Modified:
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/ChainsawCyclicBufferTableModel.java
  logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/EventContainer.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/JSortTable.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LogPanel.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/helper/SwingHelper.java


Modified: logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/ChainsawCyclicBufferTableModel.java
                
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4 \
j/chainsaw/ChainsawCyclicBufferTableModel.java?rev=595870&r1=595869&r2=595870&view=diff
 ==============================================================================
--- logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/ChainsawCyclicBufferTableModel.java \
                (original)
+++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/ChainsawCyclicBufferTableModel.java \
Fri Nov 16 15:31:40 2007 @@ -28,6 +28,7 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
+import java.awt.EventQueue;
 
 import javax.swing.ProgressMonitor;
 import javax.swing.SwingUtilities;
@@ -36,6 +37,7 @@
 
 import org.apache.log4j.LogManager;
 import org.apache.log4j.Logger;
+import org.apache.log4j.chainsaw.helper.SwingHelper;
 import org.apache.log4j.helpers.Constants;
 import org.apache.log4j.rule.Rule;
 import org.apache.log4j.spi.LoggingEvent;
@@ -135,7 +137,7 @@
           }
         }
       } finally {
-      	SwingUtilities.invokeLater(new Runnable() {
+      	SwingHelper.invokeOnEDT(new Runnable() {
       		public void run() {
       			if (filteredList.size() > 0) {
 	      			if (previousSize == filteredList.size()) {
@@ -262,7 +264,7 @@
             currentSortAscending));
       }
 
-     	SwingUtilities.invokeLater(new Runnable() {
+     	SwingHelper.invokeOnEDT(new Runnable() {
      		public void run() {
       			fireTableRowsUpdated(0, Math.max(filteredList.size() - 1, 0));
       		}
@@ -295,7 +297,7 @@
       uniqueRow = 0;
     }
 
-    SwingUtilities.invokeLater(new Runnable() {
+    SwingHelper.invokeOnEDT(new Runnable() {
     	public void run() {
     	    fireTableDataChanged();
     	}
@@ -445,7 +447,7 @@
     return "";
   }
 
-  public boolean isAddRow(LoggingEvent e, boolean valueIsAdjusting) {
+  public boolean isAddRow(LoggingEvent e) {
     boolean rowAdded = false;
 
     Object id = e.getProperty(Constants.LOG4J_ID_KEY);
@@ -494,7 +496,7 @@
       }
     }
 
-    if (!valueIsAdjusting) {
+    if (rowAdded) {
       int lastAdded = getLastAdded();
       fireTableEvent(lastAdded, lastAdded, 1);
     }
@@ -506,16 +508,16 @@
     int last = 0;
 
     if (cyclic) {
-      last = ((CyclicBufferList) filteredList).getLast();
+      last = ((CyclicBufferList) filteredList).getLast() - 1;
     } else {
-      last = filteredList.size();
+      last = filteredList.size() - 1;
     }
 
-    return last;
+    return Math.max(0, last);
   }
 
   public void fireTableEvent(final int begin, final int end, final int count) {
-  	SwingUtilities.invokeLater(new Runnable() {
+  	SwingHelper.invokeOnEDT(new Runnable() {
   		public void run() {
     if (cyclic) {
       if (!reachedCapacity) {

Modified: logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/EventContainer.java
                
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/EventContainer.java?rev=595870&r1=595869&r2=595870&view=diff
 ==============================================================================
--- logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/EventContainer.java \
                (original)
+++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/EventContainer.java \
Fri Nov 16 15:31:40 2007 @@ -17,13 +17,12 @@
 
 package org.apache.log4j.chainsaw;
 
-import org.apache.log4j.rule.Rule;
-import org.apache.log4j.spi.LoggingEvent;
-
 import java.beans.PropertyChangeListener;
-
 import java.util.List;
 
+import org.apache.log4j.rule.Rule;
+import org.apache.log4j.spi.LoggingEvent;
+
 
 /**
  * To allow pluggable TableModel implementations for Chainsaw, this interface has \
been factored out. @@ -132,10 +131,9 @@
   /**
    * Adds a row to the model.
    * @param e event
-   * @param valueIsAdjusting
    * @return flag representing whether or not the row is being displayed (not \
                filtered)
    */
-  boolean isAddRow(LoggingEvent e, boolean valueIsAdjusting);
+  boolean isAddRow(LoggingEvent e);
 
   /**
    * Fire appropriate table update events for the range.

Modified: logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/JSortTable.java
                
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/JSortTable.java?rev=595870&r1=595869&r2=595870&view=diff
 ==============================================================================
--- logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/JSortTable.java \
                (original)
+++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/JSortTable.java \
Fri Nov 16 15:31:40 2007 @@ -23,10 +23,11 @@
 
 import javax.swing.JTable;
 import javax.swing.ListSelectionModel;
-import javax.swing.SwingUtilities;
 import javax.swing.table.JTableHeader;
 import javax.swing.table.TableColumnModel;
 
+import org.apache.log4j.chainsaw.helper.SwingHelper;
+
 
 /**
  * A Sortable JTable implementation that allows a user to click on a
@@ -92,36 +93,23 @@
     getTableHeader().resizeAndRepaint();
   }
 
-  public void scrollToRow(final int row, final int col) {
-    SwingUtilities.invokeLater(
-      new Runnable() {
-        public void run() {
-          if ((row > -1) && (row < getRowCount())) {
-            try {
-              setRowSelectionInterval(row, row);
-              scrollRectToVisible(getCellRect(row, col +1, true));
-            } catch (IllegalArgumentException iae) {
-            }
-             //ignore..out of bounds
-          }
-        }
-      });
-  }
-
-  public void scrollToBottom(final int col) {
-    SwingUtilities.invokeLater(
-      new Runnable() {
-        public void run() {
-          int row = getRowCount() - 1;
-
+  public void scrollTo(final int row, final int col) {
+    SwingHelper.invokeOnEDT(new Runnable() {
+      public void run() {
+        if ((row > -1) && (row < getRowCount())) {
           try {
             setRowSelectionInterval(row, row);
-            scrollRectToVisible(getCellRect(row, col + 1, true));
+            scrollRectToVisible(getCellRect(row, col, true));
           } catch (IllegalArgumentException iae) {
+            //ignore..out of bounds
           }
-           //ignore..out of bounds
         }
-      });
+      }
+    });
+  }
+
+  public void scrollToRow(int row) {
+    scrollTo(row, columnAtPoint(getVisibleRect().getLocation()));
   }
 
   public boolean isSortedColumnAscending() {

Modified: logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LogPanel.java
                
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LogPanel.java?rev=595870&r1=595869&r2=595870&view=diff
 ==============================================================================
--- logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LogPanel.java \
                (original)
+++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LogPanel.java Fri \
Nov 16 15:31:40 2007 @@ -112,6 +112,9 @@
 import javax.swing.table.TableColumnModel;
 import javax.swing.text.Document;
 
+import com.thoughtworks.xstream.XStream;
+import com.thoughtworks.xstream.io.xml.DomDriver;
+
 import org.apache.log4j.LogManager;
 import org.apache.log4j.Logger;
 import org.apache.log4j.PatternLayout;
@@ -129,15 +132,13 @@
 import org.apache.log4j.chainsaw.prefs.SaveSettingsEvent;
 import org.apache.log4j.chainsaw.prefs.SettingsManager;
 import org.apache.log4j.chainsaw.xstream.TableColumnConverter;
+import org.apache.log4j.chainsaw.helper.SwingHelper;
 import org.apache.log4j.helpers.Constants;
 import org.apache.log4j.rule.ExpressionRule;
 import org.apache.log4j.rule.Rule;
 import org.apache.log4j.spi.LoggingEvent;
 import org.apache.log4j.spi.LoggingEventFieldResolver;
 
-import com.thoughtworks.xstream.XStream;
-import com.thoughtworks.xstream.io.xml.DomDriver;
-
 
 /**
  * A LogPanel provides a view to a collection of LoggingEvents.<br>
@@ -533,7 +534,7 @@
           boolean value = ((Boolean) evt.getNewValue()).booleanValue();
           menuItemScrollBottom.setSelected(value);
           if (value) {
-          	table.scrollToBottom(table.columnAtPoint(table.getVisibleRect().getLocation()));
 +            scrollToBottom();
           }
         }
       });
@@ -690,33 +691,42 @@
 
     table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
 
+    table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
+        public void valueChanged(ListSelectionEvent evt) {
+            if (((evt.getFirstIndex() == evt.getLastIndex())
+                && (evt.getFirstIndex() > 0)) || (evt.getValueIsAdjusting())) {
+              return;
+            }
+            boolean lastIndexOnLastRow = (evt.getLastIndex() == (table.getRowCount() \
- 1)); +            boolean lastIndexSame = (previousLastIndex == \
evt.getLastIndex()); +
+            /*
+             * when scroll-to-bottom is active, here is what events look like:
+             * rowcount-1: 227, last: 227, previous last: 191..first: 191
+             *
+             * when the user has unselected the bottom row, here is what the events \
look like: +             * rowcount-1: 227, last: 227, previous last: 227..first: 222
+             *
+             * note: previouslast is set after it is evaluated in the bypass scroll \
check +            */
+           //System.out.println("rowcount: " + (table.getRowCount() - 1) + ", last: \
" + evt.getLastIndex() +", previous last: " + previousLastIndex + "..first: " + \
evt.getFirstIndex() + ", isadjusting: " + evt.getValueIsAdjusting()); +
+            boolean disableScrollToBottom = (lastIndexOnLastRow && lastIndexSame && \
previousLastIndex != evt.getFirstIndex()); +            if (disableScrollToBottom && \
isScrollToBottom() && table.getRowCount() > 0) { +              \
preferenceModel.setScrollToBottom(false); +            }
+            previousLastIndex = evt.getLastIndex();
+          }
+        }
+    );
+
     table.getSelectionModel().addListSelectionListener(
       new ListSelectionListener() {
         public void valueChanged(ListSelectionEvent evt) {
-          if (
-            ((evt.getFirstIndex() == evt.getLastIndex())
+          if (((evt.getFirstIndex() == evt.getLastIndex())
               && (evt.getFirstIndex() > 0)) || (evt.getValueIsAdjusting())) {
             return;
           }
-          boolean lastIndexOnLastRow = (evt.getLastIndex() == (table.getRowCount() - \
                1));
-          boolean lastIndexSame = (previousLastIndex == evt.getLastIndex());
-
-          /*
-           * when scroll-to-bottom is active, here is what events look like:
-           * rowcount-1: 227, last: 227, previous last: 191..first: 191
-           * 
-           * when the user has unselected the bottom row, here is what the events \
                look like:
-           * rowcount-1: 227, last: 227, previous last: 227..first: 222
-           * 
-           * note: previouslast is set after it is evaluated in the bypass scroll \
                check
-          */
-         //System.out.println("rowcount: " + (table.getRowCount() - 1) + ", last: " \
+ evt.getLastIndex() +", previous last: " + previousLastIndex + "..first: " + \
                evt.getFirstIndex() + ", isadjusting: " + evt.getValueIsAdjusting());
-          
-          boolean disableScrollToBottom = (lastIndexOnLastRow && lastIndexSame && \
                previousLastIndex != evt.getFirstIndex());
-          if (disableScrollToBottom && isScrollToBottom() && table.getRowCount() > \
                0) {
-          	preferenceModel.setScrollToBottom(false);
-          }
-          previousLastIndex = evt.getLastIndex();
 
           final ListSelectionModel lsm = (ListSelectionModel) evt.getSource();
 
@@ -798,8 +808,7 @@
           }
 
           detailDialog.setLocation(lowerPanel.getLocationOnScreen());
-          SwingUtilities.invokeLater(
-            new Runnable() {
+          SwingHelper.invokeOnEDT(new Runnable() {
               public void run() {
                 detailDialog.setVisible(true);
               }
@@ -814,7 +823,7 @@
     tableModel.addNewKeyListener(
       new NewKeyListener() {
         public void newKeyAdded(final NewKeyEvent e) {
-        	SwingUtilities.invokeLater(new Runnable() {
+        	SwingHelper.invokeOnEDT(new Runnable() {
         		public void run() {
            // don't add the column if we already know about it, this could be if \
                we've seen it before and saved the column preferences
             //this may throw an illegalargexception - ignore it because we need to \
add only if not already added @@ -1347,6 +1356,10 @@
   	preferenceModel.setScrollToBottom(!preferenceModel.isScrollToBottom());
   }
   
+  private void scrollToBottom() {
+    table.scrollToRow(tableModel.getRowCount() - 1);
+  }
+
   /**
    * Accessor
    *
@@ -1376,51 +1389,60 @@
    * @param ident identifier shared by events
    * @param events list of LoggingEvent objects
    */
-  public void receiveEventBatch(String ident, List events) {
-    /*
-     * if this panel is paused, we totally ignore events
-     */
-    if (isPaused()) {
-      return;
-    }
+  public void receiveEventBatch(String ident, final List events) {
 
-    //table.getSelectionModel().setValueIsAdjusting(true);
-    boolean rowAdded = false;
+    SwingHelper.invokeOnEDT(new Runnable() {
+      public void run() {
+        /*
+        * if this panel is paused, we totally ignore events
+        */
+        if (isPaused()) {
+          return;
+        }
 
-    int first = tableModel.getLastAdded() + 1;
+        final int selectedRow = table.getSelectedRow();
+        final LoggingEvent selectedEvent;
+        if (selectedRow >= 0) {
+          selectedEvent = tableModel.getRow(selectedRow);
+        } else {
+          selectedEvent = null;
+        }
 
-    for (Iterator iter = events.iterator(); iter.hasNext();) {
-      LoggingEvent event = (LoggingEvent) iter.next();
+        boolean rowAdded = false;
 
-      updateOtherModels(event);
+        for (Iterator iter = events.iterator(); iter.hasNext();) {
+          LoggingEvent event = (LoggingEvent) iter.next();
 
-      boolean isCurrentRowAdded = tableModel.isAddRow(event, true);
-      rowAdded = rowAdded ? true : isCurrentRowAdded;
-    }
+          updateOtherModels(event);
 
-    table.getSelectionModel().setValueIsAdjusting(false);
+          rowAdded = rowAdded || tableModel.isAddRow(event);
+        }
 
-    //tell the model to notify the count listeners
-    tableModel.notifyCountListeners();
+        //tell the model to notify the count listeners
+        tableModel.notifyCountListeners();
 
-    if (rowAdded) {
-      if (tableModel.isSortEnabled()) {
-        tableModel.sort();
-      }
+        if (rowAdded) {
+          if (tableModel.isSortEnabled()) {
+            tableModel.sort();
+          }
 
-      tableModel.fireTableEvent(
-        first, tableModel.getLastAdded(), events.size());
+          //always update detail pane (since we may be using a cyclic buffer which \
is full) +          detailPaneUpdater.setSelectedRow(table.getSelectedRow());
+        }
 
-      if (isScrollToBottom()) {
-        table.scrollToBottom(
-          table.columnAtPoint(table.getVisibleRect().getLocation()));
+        if (isScrollToBottom()) {
+          scrollToBottom();
+        } else if (selectedEvent != null) {
+          final int newIndex = tableModel.getRowIndex(selectedEvent);
+          if (newIndex >= 0) {
+            // Don't scroll, just maintain selection...
+            table.setRowSelectionInterval(newIndex, newIndex);
+          }
+        }
       }
-
-      //always update detail pane (since we may be using a cyclic buffer which is \
                full)
-      detailPaneUpdater.setSelectedRow(table.getSelectedRow());
-    }
+    });
   }
-  
+
   /**
    * Load settings from the panel preference model
    *
@@ -1676,7 +1698,7 @@
     dockingAction.putValue(Action.NAME, "Dock");
     dockingAction.putValue(Action.SMALL_ICON, ChainsawIcons.ICON_DOCK);
     if (row > -1) {
-    	table.scrollToRow(row, \
table.columnAtPoint(table.getVisibleRect().getLocation())); +    \
table.scrollToRow(row);  }
   }
 
@@ -1715,7 +1737,7 @@
    * @param eventNumber
    */
   void setSelectedEvent(int eventNumber){
-      table.scrollToRow(eventNumber - 1, 0);
+      table.scrollTo(eventNumber - 1, 0);
   }
 
   /**
@@ -2053,7 +2075,7 @@
    * Update the status bar with current selected row and row count
    */
   private void updateStatusBar() {
-    SwingUtilities.invokeLater(
+    SwingHelper.invokeOnEDT(
       new Runnable() {
         public void run() {
           statusBar.setSelectedLine(
@@ -2113,8 +2135,7 @@
           tableModel.find(findRule, table.getSelectedRow() + 1, true);
 
         if (nextRow > -1) {
-          table.scrollToRow(
-            nextRow, table.columnAtPoint(table.getVisibleRect().getLocation()));
+          table.scrollToRow(nextRow);
           findField.setToolTipText("Enter an expression");
         }
       } catch (IllegalArgumentException iae) {
@@ -2138,9 +2159,7 @@
           tableModel.find(findRule, table.getSelectedRow() - 1, false);
 
         if (previousRow > -1) {
-          table.scrollToRow(
-            previousRow,
-            table.columnAtPoint(table.getVisibleRect().getLocation()));
+          table.scrollToRow(previousRow);
           findField.setToolTipText("Enter an expression");
         }
       } catch (IllegalArgumentException iae) {
@@ -2165,7 +2184,7 @@
     dockingAction.putValue(Action.NAME, "Undock");
     dockingAction.putValue(Action.SMALL_ICON, ChainsawIcons.ICON_UNDOCK);
     if (row > -1) {
-    	table.scrollToRow(row, \
table.columnAtPoint(table.getVisibleRect().getLocation())); +    \
table.scrollToRow(row);  }
   }
 
@@ -2612,7 +2631,7 @@
 		          	try {
 		          		final Document doc = detail.getEditorKit().createDefaultDocument();
 		          		detail.getEditorKit().read(new StringReader(buf.toString()), doc, 0);
-				      	SwingUtilities.invokeLater(new Runnable() {
+				      	SwingHelper.invokeOnEDT(new Runnable() {
 				      		public void run() {
 				      			detail.setDocument(doc);
 				      			detail.setCaretPosition(0);
@@ -2627,7 +2646,7 @@
           	try {
           		final Document doc = detail.getEditorKit().createDefaultDocument();
           		detail.getEditorKit().read(new StringReader("<html>Nothing \
                selected</html>"), doc, 0);
-		      	SwingUtilities.invokeLater(new Runnable() {
+		      	SwingHelper.invokeOnEDT(new Runnable() {
 		      		public void run() {
 		      			detail.setDocument(doc);
 		      			detail.setCaretPosition(0);

Modified: logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/helper/SwingHelper.java
                
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/helper/SwingHelper.java?rev=595870&r1=595869&r2=595870&view=diff
 ==============================================================================
--- logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/helper/SwingHelper.java \
                (original)
+++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/helper/SwingHelper.java \
Fri Nov 16 15:31:40 2007 @@ -20,6 +20,7 @@
 import java.awt.Component;
 import java.awt.Dimension;
 import java.awt.Toolkit;
+import java.awt.EventQueue;
 import java.awt.event.ActionEvent;
 import java.awt.event.KeyEvent;
 
@@ -72,5 +73,13 @@
     cancelButton.setAction(closeAction);
     dialog.getRootPane().getActionMap().put(CANCEL_ACTION_KEY, closeAction);
     
+  }
+
+  public static void invokeOnEDT(Runnable runnable) {
+    if (EventQueue.isDispatchThread()) {
+      runnable.run();
+    } else {
+      EventQueue.invokeLater(runnable);
+    }
   }
 }


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic