Fix bug preventing properties from not being displayed correctly in the table
Add  'marker' column to the table when a marker is set
Changed default text in marker column to 'set'
Marker column is now editable (double-click cell)
(Marker values are re-loaded if events are saved & reopened later)

git-svn-id: https://svn.apache.org/repos/asf/logging/chainsaw/trunk@829702 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/main/java/org/apache/log4j/chainsaw/ChainsawCyclicBufferTableModel.java b/src/main/java/org/apache/log4j/chainsaw/ChainsawCyclicBufferTableModel.java
index 75caed4..8d30cd4 100644
--- a/src/main/java/org/apache/log4j/chainsaw/ChainsawCyclicBufferTableModel.java
+++ b/src/main/java/org/apache/log4j/chainsaw/ChainsawCyclicBufferTableModel.java
@@ -342,7 +342,7 @@
             LoggingEvent event = (LoggingEvent)filteredList.get(i);
             Object result = event.removeProperty(propName);
             if (result != null) {
-                fireRowUpdated(i);
+                fireRowUpdated(i, false);
             }
         }
     }
@@ -501,34 +501,39 @@
       }
     }
 
-    /**
-     * Is this a new Property key we haven't seen before?  Remember that now MDC has been merged
-     * into the Properties collection
-     */
-    boolean newColumn = uniquePropertyKeys.addAll(e.getPropertyKeySet());
-
-    if (newColumn) {
-      /**
-       * If so, we should add them as columns and notify listeners.
-       */
-      for (Iterator iter = e.getPropertyKeySet().iterator(); iter.hasNext();) {
-        String key = iter.next().toString().toUpperCase();
-
-        //add all keys except the 'log4jid' key (columnNames is all-caps)
-        if (!columnNames.contains(key) && !(Constants.LOG4J_ID_KEY.equalsIgnoreCase(key))) {
-          columnNames.add(key);
-          logger.debug("Adding col '" + key + "', columnNames=" + columnNames);
-          fireNewKeyColumnAdded(
-            new NewKeyEvent(
-              this, columnNames.indexOf(key), key, e.getProperty(key)));
-        }
-      }
-    }
+    checkForNewColumn(e);
 
     return rowAdded;
   }
 
-  public int getLastAdded() {
+   private void checkForNewColumn(LoggingEvent e)
+   {
+      /**
+       * Is this a new Property key we haven't seen before?  Remember that now MDC has been merged
+       * into the Properties collection
+       */
+      boolean newColumn = uniquePropertyKeys.addAll(e.getPropertyKeySet());
+
+      if (newColumn) {
+        /**
+         * If so, we should add them as columns and notify listeners.
+         */
+        for (Iterator iter = e.getPropertyKeySet().iterator(); iter.hasNext();) {
+          String key = iter.next().toString().toUpperCase();
+
+          //add all keys except the 'log4jid' key (columnNames is all-caps)
+          if (!columnNames.contains(key) && !(Constants.LOG4J_ID_KEY.equalsIgnoreCase(key))) {
+            columnNames.add(key);
+            logger.debug("Adding col '" + key + "', columnNames=" + columnNames);
+            fireNewKeyColumnAdded(
+              new NewKeyEvent(
+                this, columnNames.indexOf(key), key, e.getProperty(key)));
+          }
+        }
+      }
+   }
+
+    public int getLastAdded() {
     int last = 0;
 
     if (cyclic) {
@@ -563,8 +568,12 @@
   }});
   }
 
-    public void fireRowUpdated(int row) {
+    public void fireRowUpdated(int row, boolean checkForNewColumns) {
         fireTableRowsUpdated(row, row);
+        if (checkForNewColumns) {
+            //row may have had a column added..if so, make sure a column is added
+            checkForNewColumn(getRow(row));
+        }
     }
 
     /**
@@ -617,10 +626,23 @@
     case ChainsawColumns.INDEX_THROWABLE_COL_NAME:
       return true;
     }
+    String columnName = getColumnName(columnIndex);
+    if (columnName.toLowerCase().equals(ChainsawConstants.MARKER_PROPERTY_NAME)) {
+      return true;
+    }
 
     return super.isCellEditable(rowIndex, columnIndex);
   }
 
+    public void setValueAt(Object value, int rowIndex, int columnIndex)
+    {
+        String columnName = getColumnName(columnIndex);
+        if (columnName.toLowerCase().equals(ChainsawConstants.MARKER_PROPERTY_NAME)) {
+            LoggingEvent event = getRow(rowIndex);
+            event.setProperty(ChainsawConstants.MARKER_PROPERTY_NAME, value.toString());
+        }
+    }
+
   /* (non-Javadoc)
    * @see org.apache.log4j.chainsaw.EventContainer#setCyclic(boolean)
    */
diff --git a/src/main/java/org/apache/log4j/chainsaw/EventContainer.java b/src/main/java/org/apache/log4j/chainsaw/EventContainer.java
index 086aedc..15fd026 100644
--- a/src/main/java/org/apache/log4j/chainsaw/EventContainer.java
+++ b/src/main/java/org/apache/log4j/chainsaw/EventContainer.java
@@ -143,8 +143,9 @@
     /**
      * A row was updated
      * @param row
+     * @param checkForNewColumns
      */
-  void fireRowUpdated(int row);
+  void fireRowUpdated(int row, boolean checkForNewColumns);
   /**
    * Allow a forced notification of the EventCountListeners
    *
diff --git a/src/main/java/org/apache/log4j/chainsaw/LogPanel.java b/src/main/java/org/apache/log4j/chainsaw/LogPanel.java
index b8e65c1..18a8e94 100644
--- a/src/main/java/org/apache/log4j/chainsaw/LogPanel.java
+++ b/src/main/java/org/apache/log4j/chainsaw/LogPanel.java
@@ -2513,11 +2513,12 @@
           LoggingEvent event = tableModel.getRow(row);
           Object marker = event.getProperty(ChainsawConstants.MARKER_PROPERTY_NAME);
           if (marker == null) {
-              event.setProperty(ChainsawConstants.MARKER_PROPERTY_NAME, "true");
+              event.setProperty(ChainsawConstants.MARKER_PROPERTY_NAME, "set");
           } else {
               event.removeProperty(ChainsawConstants.MARKER_PROPERTY_NAME);
           }
-          tableModel.fireRowUpdated(row);
+          //if marker -was- null, it no longer is (may need to add the column)
+          tableModel.fireRowUpdated(row, (marker == null));
         }
     }
 
@@ -2647,11 +2648,12 @@
                 LoggingEvent event = tableModel.getRow(row);
                 Object marker = event.getProperty(ChainsawConstants.MARKER_PROPERTY_NAME);
                 if (marker == null) {
-                    event.setProperty(ChainsawConstants.MARKER_PROPERTY_NAME, "true");
+                    event.setProperty(ChainsawConstants.MARKER_PROPERTY_NAME, "set");
                 } else {
                     event.removeProperty(ChainsawConstants.MARKER_PROPERTY_NAME);
                 }
-                tableModel.fireRowUpdated(row);
+                //if marker -was- null, it no longer is (may need to add the column)
+                tableModel.fireRowUpdated(row, (marker == null));
               }
           }
       }
diff --git a/src/main/java/org/apache/log4j/chainsaw/TableColorizingRenderer.java b/src/main/java/org/apache/log4j/chainsaw/TableColorizingRenderer.java
index 4c056ff..cb92e54 100644
--- a/src/main/java/org/apache/log4j/chainsaw/TableColorizingRenderer.java
+++ b/src/main/java/org/apache/log4j/chainsaw/TableColorizingRenderer.java
@@ -22,7 +22,9 @@
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
 import java.util.Date;
+import java.util.Iterator;
 import java.util.Map;
+import java.util.Set;
 import java.util.TimeZone;
 
 import javax.swing.BorderFactory;
@@ -32,6 +34,7 @@
 import javax.swing.JTable;
 import javax.swing.SwingConstants;
 import javax.swing.table.DefaultTableCellRenderer;
+import javax.swing.table.TableColumn;
 
 import org.apache.log4j.chainsaw.color.Colorizer;
 import org.apache.log4j.chainsaw.icons.ChainsawIcons;
@@ -91,7 +94,9 @@
 
     JLabel c = (JLabel)super.getTableCellRendererComponent(table, value, 
         isSelected, hasFocus, row, col);
-    int colIndex = table.getColumnModel().getColumn(col).getModelIndex() + 1;
+
+    TableColumn tableColumn = table.getColumnModel().getColumn(col);
+    int colIndex = tableColumn.getModelIndex() + 1;
 
     EventContainer container = (EventContainer) table.getModel();
     LoggingEvent event = container.getRow(row);
@@ -126,6 +131,16 @@
 
     c.setText(logger.substring(startPos + 1));
       break;
+    case ChainsawColumns.INDEX_CLASS_COL_NAME:
+    case ChainsawColumns.INDEX_FILE_COL_NAME:
+    case ChainsawColumns.INDEX_LINE_COL_NAME:
+    case ChainsawColumns.INDEX_MESSAGE_COL_NAME:
+    case ChainsawColumns.INDEX_NDC_COL_NAME:
+    case ChainsawColumns.INDEX_THREAD_COL_NAME:
+    case ChainsawColumns.INDEX_TIMESTAMP_COL_NAME:
+    case ChainsawColumns.INDEX_METHOD_COL_NAME:
+      c.setText(value.toString());
+      break;
 
     case ChainsawColumns.INDEX_LEVEL_COL_NAME:
       if (levelUseIcons) {
@@ -153,11 +168,26 @@
       c = levelComponent;
       break;
 
+    //remaining entries are properties
     default:
-      break;
+        Set propertySet = event.getPropertyKeySet();
+        String headerName = tableColumn.getHeaderValue().toString().toLowerCase();
+        String thisProp = null;
+        //find the property in the property set...case-sensitive
+        for (Iterator iter = propertySet.iterator();iter.hasNext();) {
+            String entry = iter.next().toString();
+            if (entry.toLowerCase().equals(headerName)) {
+                thisProp = entry;
+                break;
+            }
+        }
+        if (thisProp != null) {
+            c.setText(event.getProperty(headerName));
+        }
+        break;
     }
-    //set the 'info' icon next to the zeroth column if marker is set
-    if (col == 0 && event.getProperty("log4j.marker") != null) {
+    //set the 'marker' icon next to the zeroth column if marker is set
+    if (col == 0 && event.getProperty(ChainsawConstants.MARKER_PROPERTY_NAME) != null) {
         c.setIcon(markerIcon);
     } else {
         c.setIcon(null);