logging-general mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From sde...@apache.org
Subject svn commit: r955150 - in /logging/chainsaw/trunk/src/main: java/org/apache/log4j/chainsaw/LogPanel.java java/org/apache/log4j/chainsaw/TableColorizingRenderer.java resources/org/apache/log4j/chainsaw/help/release-notes.html
Date Wed, 16 Jun 2010 07:43:55 GMT
Author: sdeboy
Date: Wed Jun 16 07:43:55 2010
New Revision: 955150

URL: http://svn.apache.org/viewvc?rev=955150&view=rev
Log:
Added 'copy value under pointer to clipboard' log panel context menu item.
Fixed a number of table rendering issues, including bolding and line wrapping (line wrap mode
correctly displays the entire event).

Table rendering now uses styleddocuments instead of htmldocuments to facilitate multi-line
rendering + bolding..multi-line mode previously cut off long lines of text without spaces,
multi-line mode now works as expected..

Modified:
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LogPanel.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/TableColorizingRenderer.java
    logging/chainsaw/trunk/src/main/resources/org/apache/log4j/chainsaw/help/release-notes.html

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=955150&r1=955149&r2=955150&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 Wed Jun 16
07:43:55 2010
@@ -30,6 +30,8 @@ import java.awt.Graphics;
 import java.awt.Point;
 import java.awt.Toolkit;
 import java.awt.Window;
+import java.awt.datatransfer.Clipboard;
+import java.awt.datatransfer.StringSelection;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.awt.event.FocusEvent;
@@ -96,7 +98,6 @@ import javax.swing.JScrollPane;
 import javax.swing.JSeparator;
 import javax.swing.JSplitPane;
 import javax.swing.JTable;
-import javax.swing.JTextArea;
 import javax.swing.JTextField;
 import javax.swing.JToolBar;
 import javax.swing.KeyStroke;
@@ -1423,7 +1424,7 @@ public class LogPanel extends DockablePa
                 value = ((JLabel) comp).getText();
               }
             } else {
-              Object o = table.getValueAt(row, column).toString();
+              Object o = table.getValueAt(row, column);
 
               if (o instanceof String[] && ((String[])o).length > 0) {
                 value = ((String[]) o)[0];
@@ -1463,7 +1464,7 @@ public class LogPanel extends DockablePa
                 value = ((JLabel) comp).getText();
               }
             } else {
-              Object o = table.getValueAt(row, column).toString();
+              Object o = table.getValueAt(row, column);
 
               if (o instanceof String[] && ((String[])o).length > 0) {
                 value = ((String[]) o)[0];
@@ -1494,6 +1495,47 @@ public class LogPanel extends DockablePa
         }
       };
 
+    final Action copyAction =
+      new AbstractAction("Copy value under pointer to clipboard") {
+        public void actionPerformed(ActionEvent e) {
+                      if (currentPoint != null) {
+            int column = table.columnAtPoint(currentPoint);
+            int row = table.rowAtPoint(currentPoint);
+            String colName = table.getColumnName(column).toUpperCase();
+            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 {
+              Object o = table.getValueAt(row, column);
+              //exception - build message + throwable
+              if (o != null) {
+                  if (o instanceof String[]) {
+                      String[] ti = (String[])o;
+                      if (ti.length > 0 && (!(ti.length == 1 && ti[0].equals(""))))
{
+                        ExtendedLoggingEvent event = tableModel.getRow(row);
+                        value = event.getMessage().toString();
+                        for (int i=0;i<((String[])o).length;i++) {
+                            value = value + "\n" + ((String[]) o)[i];
+                        }
+                      }
+                  } else {
+                    value = o.toString();
+                  }
+              }
+            }
+            StringSelection selection = new StringSelection(value);
+            Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
+            clipboard.setContents(selection, null);
+        }
+      }
+      };
+
     final JMenuItem menuItemToggleDock = new JMenuItem("Undock/dock");
 
     dockingAction =
@@ -1609,6 +1651,7 @@ public class LogPanel extends DockablePa
     p.add(new JSeparator());
 
     p.add(menuBuildColorRule);
+    p.add(copyAction);
     p.add(new JSeparator());
         
     p.add(menuItemToggleDetails);

Modified: logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/TableColorizingRenderer.java
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/TableColorizingRenderer.java?rev=955150&r1=955149&r2=955150&view=diff
==============================================================================
--- logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/TableColorizingRenderer.java
(original)
+++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/TableColorizingRenderer.java
Wed Jun 16 07:43:55 2010
@@ -20,7 +20,7 @@ package org.apache.log4j.chainsaw;
 import java.awt.Color;
 import java.awt.Component;
 import java.awt.Dimension;
-import java.awt.Font;
+import java.awt.Insets;
 import java.awt.font.FontRenderContext;
 import java.awt.font.LineBreakMeasurer;
 import java.awt.font.TextAttribute;
@@ -44,21 +44,32 @@ import javax.swing.JLabel;
 import javax.swing.JPanel;
 import javax.swing.JTable;
 import javax.swing.JTextPane;
-import javax.swing.SwingConstants;
 import javax.swing.UIManager;
 import javax.swing.border.Border;
 import javax.swing.table.DefaultTableCellRenderer;
 import javax.swing.table.TableColumn;
+import javax.swing.text.AbstractDocument;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.BoxView;
+import javax.swing.text.ComponentView;
+import javax.swing.text.Element;
+import javax.swing.text.IconView;
+import javax.swing.text.LabelView;
 import javax.swing.text.MutableAttributeSet;
+import javax.swing.text.ParagraphView;
+import javax.swing.text.SimpleAttributeSet;
+import javax.swing.text.Style;
 import javax.swing.text.StyleConstants;
 import javax.swing.text.StyledDocument;
-import javax.swing.text.html.HTMLDocument;
-import javax.swing.text.html.HTMLEditorKit;
+import javax.swing.text.StyledEditorKit;
+import javax.swing.text.TabSet;
+import javax.swing.text.TabStop;
+import javax.swing.text.View;
+import javax.swing.text.ViewFactory;
 
 import org.apache.log4j.chainsaw.color.RuleColorizer;
 import org.apache.log4j.chainsaw.icons.LevelIconFactory;
 import org.apache.log4j.helpers.Constants;
-import org.apache.log4j.helpers.Transform;
 import org.apache.log4j.rule.Rule;
 import org.apache.log4j.spi.LoggingEventFieldResolver;
 
@@ -97,14 +108,16 @@ public class TableColorizingRenderer ext
   private static final Border MIDDLE_EMPTY_BORDER = BorderFactory.createEmptyBorder(borderWidth,
0, borderWidth, 0);
   private static final Border RIGHT_EMPTY_BORDER = BorderFactory.createEmptyBorder(borderWidth,
0, borderWidth, borderWidth);
 
-  private final JLabel levelLabel = new JLabel();
-  private JLabel generalLabel = new JLabel();
+  private final JTextPane levelTextPane = new JTextPane();
+  private JTextPane singleLineTextPane = new JTextPane();
 
   private final JPanel multiLinePanel = new JPanel();
   private final JPanel generalPanel = new JPanel();
   private final JPanel levelPanel = new JPanel();
   private ApplicationPreferenceModel applicationPreferenceModel;
   private JTextPane multiLineTextPane;
+  private MutableAttributeSet boldAttributeSet;
+  private TabSet tabs;
 
     /**
    * Creates a new TableColorizingRenderer object.
@@ -115,24 +128,36 @@ public class TableColorizingRenderer ext
     generalPanel.setLayout(new BoxLayout(generalPanel, BoxLayout.Y_AXIS));
     levelPanel.setLayout(new BoxLayout(levelPanel, BoxLayout.Y_AXIS));
 
-    multiLinePanel.setAlignmentX(TOP_ALIGNMENT);
-    generalPanel.setAlignmentX(TOP_ALIGNMENT);
-    levelPanel.setAlignmentX(TOP_ALIGNMENT);
-
-    generalLabel.setVerticalAlignment(SwingConstants.TOP);
-    levelLabel.setVerticalAlignment(SwingConstants.TOP);
-    levelLabel.setOpaque(true);
-    levelLabel.setText("");
+    //define the 'bold' attributeset
+    boldAttributeSet = new SimpleAttributeSet();
+    StyleConstants.setBold(boldAttributeSet, true);
+
+    //throwable col may have a tab..if so, render the tab as col zero
+    int pos = 0;
+    int align = TabStop.ALIGN_LEFT;
+    int leader = TabStop.LEAD_NONE;
+    TabStop tabStop = new TabStop(pos, align, leader);
+    tabs = new TabSet(new TabStop[]{tabStop});
 
-    generalPanel.add(generalLabel);
-    levelPanel.add(levelLabel);
+    levelTextPane.setOpaque(true);
+    levelTextPane.setText("");
+
+    generalPanel.add(singleLineTextPane);
+    levelPanel.add(levelTextPane);
 
     this.colorizer = colorizer;
     multiLineTextPane = new JTextPane();
-    multiLineTextPane.setEditorKit(new HTMLEditorKit());
-    multiLineTextPane.setMargin(null);
+    multiLineTextPane.setEditorKit(new StyledEditorKit());
+
+    singleLineTextPane.setEditorKit(new OneLineEditorKit());
+    levelTextPane.setEditorKit(new OneLineEditorKit());
+
     multiLineTextPane.setEditable(false);
-    multiLineTextPane.setFont(levelLabel.getFont());
+    multiLineTextPane.setFont(levelTextPane.getFont());
+    Insets leftRightInsets = new Insets(0, 5, 0, 5);
+    multiLineTextPane.setMargin(leftRightInsets);
+    singleLineTextPane.setMargin(leftRightInsets);
+    levelTextPane.setMargin(leftRightInsets);
   }
 
   public void setToolTipsVisible(boolean toolTipsVisible) {
@@ -162,15 +187,20 @@ public class TableColorizingRenderer ext
     switch (colIndex) {
     case ChainsawColumns.INDEX_THROWABLE_COL_NAME:
       if (value instanceof String[] && ((String[])value).length > 0){
+          Style tabStyle = singleLineTextPane.getLogicalStyle();
+          StyleConstants.setTabSet(tabStyle, tabs);
+          //set the 1st tab at position 3
+          singleLineTextPane.setLogicalStyle(tabStyle);
           //exception string is split into an array..just highlight the first line completely
if anything in the exception matches if we have a match for the exception field
           Set exceptionMatches = (Set)matches.get(LoggingEventFieldResolver.EXCEPTION_FIELD);
           if (exceptionMatches != null && exceptionMatches.size() > 0) {
-              generalLabel.setText(bold(((String[])value)[0]));
+              singleLineTextPane.setText(((String[])value)[0]);
+              boldAll((StyledDocument) singleLineTextPane.getDocument());
           } else {
-              generalLabel.setText(((String[])value)[0]);
+              singleLineTextPane.setText(((String[])value)[0]);
           }
       } else {
-        generalLabel.setText("");
+        singleLineTextPane.setText("");
       }
       component = generalPanel;
       break;
@@ -184,68 +214,72 @@ public class TableColorizingRenderer ext
           break;
         }
       }
-      generalLabel.setText(buildHighlightString(matches.get(LoggingEventFieldResolver.LOGGER_FIELD),
logger.substring(startPos + 1)));
+      singleLineTextPane.setText(logger.substring(startPos + 1));
+      setHighlightAttributesInternal(matches.get(LoggingEventFieldResolver.LOGGER_FIELD),
(StyledDocument) singleLineTextPane.getDocument());
       component = generalPanel;
       break;
     case ChainsawColumns.INDEX_ID_COL_NAME:
-        generalLabel.setText(buildHighlightString(matches.get(LoggingEventFieldResolver.PROP_FIELD
+ "LOG4JID"), value.toString()));
+        singleLineTextPane.setText(value.toString());
+        setHighlightAttributesInternal(matches.get(LoggingEventFieldResolver.PROP_FIELD +
"LOG4JID"), (StyledDocument) singleLineTextPane.getDocument());
         component = generalPanel;
         break;
     case ChainsawColumns.INDEX_CLASS_COL_NAME:
-        generalLabel.setText(buildHighlightString(matches.get(LoggingEventFieldResolver.CLASS_FIELD),
value.toString()));
+        singleLineTextPane.setText(value.toString());
+        setHighlightAttributesInternal(matches.get(LoggingEventFieldResolver.CLASS_FIELD),
(StyledDocument) singleLineTextPane.getDocument());
         component = generalPanel;
         break;
     case ChainsawColumns.INDEX_FILE_COL_NAME:
-        generalLabel.setText(buildHighlightString(matches.get(LoggingEventFieldResolver.FILE_FIELD),
value.toString()));
+        singleLineTextPane.setText(value.toString());
+        setHighlightAttributesInternal(matches.get(LoggingEventFieldResolver.FILE_FIELD),
(StyledDocument) singleLineTextPane.getDocument());
         component = generalPanel;
         break;
     case ChainsawColumns.INDEX_LINE_COL_NAME:
-        generalLabel.setText(buildHighlightString(matches.get(LoggingEventFieldResolver.LINE_FIELD),
value.toString()));
+        singleLineTextPane.setText(value.toString());
+        setHighlightAttributesInternal(matches.get(LoggingEventFieldResolver.LINE_FIELD),
(StyledDocument) singleLineTextPane.getDocument());
         component = generalPanel;
         break;
     case ChainsawColumns.INDEX_NDC_COL_NAME:
-        generalLabel.setText(buildHighlightString(matches.get(LoggingEventFieldResolver.NDC_FIELD),
value.toString()));
+        singleLineTextPane.setText(value.toString());
+        setHighlightAttributesInternal(matches.get(LoggingEventFieldResolver.NDC_FIELD),
(StyledDocument) singleLineTextPane.getDocument());
         component = generalPanel;
         break;
     case ChainsawColumns.INDEX_THREAD_COL_NAME:
-        generalLabel.setText(buildHighlightString(matches.get(LoggingEventFieldResolver.THREAD_FIELD),
value.toString()));
+        singleLineTextPane.setText(value.toString());
+        setHighlightAttributesInternal(matches.get(LoggingEventFieldResolver.THREAD_FIELD),
(StyledDocument) singleLineTextPane.getDocument());
         component = generalPanel;
         break;
     case ChainsawColumns.INDEX_TIMESTAMP_COL_NAME:
         //timestamp matches contain the millis..not the display text..just highlight if we
have a match for the timestamp field
         Set timestampMatches = (Set)matches.get(LoggingEventFieldResolver.TIMESTAMP_FIELD);
         if (timestampMatches != null && timestampMatches.size() > 0) {
-            generalLabel.setText(bold(value.toString()));
+            singleLineTextPane.setText(value.toString());
+            boldAll((StyledDocument) singleLineTextPane.getDocument());
         } else {
-            generalLabel.setText(value.toString());
+            singleLineTextPane.setText(value.toString());
         }
         component = generalPanel;
         break;
     case ChainsawColumns.INDEX_METHOD_COL_NAME:
-        generalLabel.setText(buildHighlightString(matches.get(LoggingEventFieldResolver.METHOD_FIELD),
value.toString()));
+        singleLineTextPane.setText(value.toString());
+        setHighlightAttributesInternal(matches.get(LoggingEventFieldResolver.METHOD_FIELD),
(StyledDocument) singleLineTextPane.getDocument());
         component = generalPanel;
         break;
     case ChainsawColumns.INDEX_LOG4J_MARKER_COL_NAME:
     case ChainsawColumns.INDEX_MESSAGE_COL_NAME:
+        String thisString = value.toString().trim();
+        multiLineTextPane.setText(thisString);
         int width = tableColumn.getWidth();
 
-        String thisString;
         if (colIndex == ChainsawColumns.INDEX_LOG4J_MARKER_COL_NAME) {
             //property keys are set as all uppercase
-            thisString = buildHighlightString(matches.get(LoggingEventFieldResolver.PROP_FIELD
+ ChainsawConstants.LOG4J_MARKER_COL_NAME_LOWERCASE.toUpperCase()), value.toString().trim());
+            setHighlightAttributesInternal(matches.get(LoggingEventFieldResolver.PROP_FIELD
+ ChainsawConstants.LOG4J_MARKER_COL_NAME_LOWERCASE.toUpperCase()), (StyledDocument) multiLineTextPane.getDocument());
         } else {
-            thisString = buildHighlightString(matches.get(LoggingEventFieldResolver.MSG_FIELD),
value.toString().trim());
+            setHighlightAttributesInternal(matches.get(LoggingEventFieldResolver.MSG_FIELD),
(StyledDocument) multiLineTextPane.getDocument());
         }
         int tableRowHeight = table.getRowHeight(row);
-        setText(thisString);
         multiLinePanel.removeAll();
         multiLinePanel.add(multiLineTextPane);
-        HTMLDocument document = new HTMLDocument();
-        multiLineTextPane.setDocument(document);
-        Font font = label.getFont();
-        String bodyRule = "body { font-family: " + font.getFamily() + "; font-size: " + (font.getSize())
+ "pt; }";
-        ((HTMLDocument)multiLineTextPane.getDocument()).getStyleSheet().addRule(bodyRule);
-        multiLineTextPane.setText(thisString);
+
         if (wrap) {
             Map paramMap = new HashMap();
             paramMap.put(TextAttribute.FONT, multiLineTextPane.getFont());
@@ -263,26 +297,23 @@ public class TableColorizingRenderer ext
         break;
     case ChainsawColumns.INDEX_LEVEL_COL_NAME:
       if (levelUseIcons) {
-        levelLabel.setIcon((Icon) iconMap.get(value.toString()));
-
-        if (levelLabel.getIcon() != null) {
-          levelLabel.setText("");
-        }
+        levelTextPane.insertIcon((Icon) iconMap.get(value.toString()));
+        levelTextPane.setText("");
         if (!toolTipsVisible) {
-          levelLabel.setToolTipText(value.toString());
+          levelTextPane.setToolTipText(value.toString());
         }
       } else {
-        levelLabel.setIcon(null);
-        levelLabel.setText(buildHighlightString(matches.get(LoggingEventFieldResolver.LEVEL_FIELD),
value.toString()));
+        levelTextPane.setText(value.toString());
+        setHighlightAttributesInternal(matches.get(LoggingEventFieldResolver.LEVEL_FIELD),
(StyledDocument) levelTextPane.getDocument());
         if (!toolTipsVisible) {
-            levelLabel.setToolTipText(null);
+            levelTextPane.setToolTipText(null);
         }
       }
       if (toolTipsVisible) {
-          levelLabel.setToolTipText(label.getToolTipText());
+          levelTextPane.setToolTipText(label.getToolTipText());
       }
-      levelLabel.setForeground(label.getForeground());
-      levelLabel.setBackground(label.getBackground());
+      levelTextPane.setForeground(label.getForeground());
+      levelTextPane.setBackground(label.getBackground());
       component = levelPanel;
       break;
 
@@ -302,9 +333,10 @@ public class TableColorizingRenderer ext
         if (thisProp != null) {
             String propKey = LoggingEventFieldResolver.PROP_FIELD + thisProp.toUpperCase();
             Set propKeyMatches = (Set)matches.get(propKey);
-            generalLabel.setText(buildHighlightString(propKeyMatches, loggingEvent.getProperty(thisProp)));
+            singleLineTextPane.setText(loggingEvent.getProperty(thisProp));
+            setHighlightAttributesInternal(propKeyMatches, (StyledDocument) singleLineTextPane.getDocument());
         } else {
-            generalLabel.setText("");
+            singleLineTextPane.setText("");
         }
         component = generalPanel;
         break;
@@ -344,10 +376,10 @@ public class TableColorizingRenderer ext
         styledDocument.setCharacterAttributes(0, styledDocument.getLength() + 1, attributes,
false);
         multiLineTextPane.setBackground(background);
     }
-    levelLabel.setBackground(background);
-    levelLabel.setForeground(foreground);
-    generalLabel.setBackground(background);
-    generalLabel.setForeground(foreground);
+    levelTextPane.setBackground(background);
+    levelTextPane.setForeground(foreground);
+    singleLineTextPane.setBackground(background);
+    singleLineTextPane.setForeground(foreground);
 
     if (isSelected) {
       if (col == 0) {
@@ -468,89 +500,90 @@ public class TableColorizingRenderer ext
      return Math.max(ChainsawConstants.DEFAULT_ROW_HEIGHT, (int) height);
     }
 
-    private String buildHighlightString(Object matchSet, String input) {
+    private void setHighlightAttributesInternal(Object matchSet, StyledDocument styledDocument)
{
         if (!highlightSearchMatchText) {
-            return fixLeadingSlash(Transform.escapeTags(input));
+            return;
         }
+        setHighlightAttributes(matchSet, styledDocument);
+    }
+
+    public void setHighlightAttributes(Object matchSet, StyledDocument styledDocument) {
         if (matchSet instanceof Set) {
             Set thisSet = (Set)matchSet;
-            //start with result as input and replace each time
-            String result = input;
             for (Iterator iter = thisSet.iterator();iter.hasNext();) {
                 String thisEntry = iter.next().toString();
-                result = bold(result, thisEntry);
+                bold(thisEntry, styledDocument);
             }
-            return "<html>" + fixLeadingSlash(escapeAllButBoldTags(result)) + "</html>";
         }
-        return fixLeadingSlash(Transform.escapeTags(input));
     }
 
-    /*
-        Weird Swing HTML/table cell renderer issue - if first character is a forward slash,
-        the text isn't displayed at all.  
-        Workaround is to render the leading slash character using the ASCII html code for
forward slash (&#47;)
-    */
-    private String fixLeadingSlash(String input) {
-        if (input.length() > 0 && input.charAt(0) == '/') {
-            return "&#47;" + input.substring(1);
+    private void boldAll(StyledDocument styledDocument) {
+        if (!highlightSearchMatchText) {
+            return;
         }
-        return input;
+        styledDocument.setCharacterAttributes(0, styledDocument.getLength(), boldAttributeSet,
false);
     }
-
-    private String escapeAllButBoldTags(String input) {
-            if (!highlightSearchMatchText) {
-                return Transform.escapeTags(input);
-            }
-            String lowerInput = input.toLowerCase();
-            String lowerBoldStart = "<b>";
-            String lowerBoldEnd = "</b>";
-            int boldStartLength = lowerBoldStart.length();
-            int boldEndLength = lowerBoldEnd.length();
+    
+    private void bold(String textToBold, StyledDocument styledDocument) {
+        try {
+            String lowerInput = styledDocument.getText(0, styledDocument.getLength()).toLowerCase();
+            String lowerTextToBold = textToBold.toLowerCase();
+            int textToBoldLength = textToBold.length();
             int firstIndex = 0;
-            int currentIndex = 0;
-            StringBuffer newString = new StringBuffer("");
-            while ((currentIndex = lowerInput.indexOf(lowerBoldStart, firstIndex)) > -1)
{
-                newString.append(Transform.escapeTags(input.substring(firstIndex, currentIndex)));
-                newString.append(lowerBoldStart);
-                firstIndex = currentIndex + boldStartLength;
-                currentIndex = lowerInput.indexOf(lowerBoldEnd, firstIndex);
-                if (currentIndex > -1) {
-                    newString.append(Transform.escapeTags(input.substring(firstIndex, currentIndex)));
-                    newString.append(lowerBoldEnd);
-                    firstIndex = currentIndex + boldEndLength;
-                }
+            int currentIndex;
+            while ((currentIndex = lowerInput.indexOf(lowerTextToBold, firstIndex)) >
-1) {
+                styledDocument.setCharacterAttributes(currentIndex, textToBoldLength, boldAttributeSet,
false);
+                firstIndex = currentIndex + textToBoldLength;
             }
-            newString.append(Transform.escapeTags(input.substring(firstIndex, input.length())));
-            return newString.toString();
         }
-
-    private String bold(String input) {
-        if (!highlightSearchMatchText) {
-            return Transform.escapeTags(input);
+        catch (BadLocationException e) {
+            //ignore
         }
-        return "<html><b>" + Transform.escapeTags(input) + "</b></html>";
-    }
-    
-    private String bold(String input, String textToBold) {
-        String lowerInput = input.toLowerCase();
-        String lowerTextToBold = textToBold.toLowerCase();
-        int textToBoldLength = textToBold.length();
-        int firstIndex = 0;
-        int currentIndex = 0;
-        StringBuffer newString = new StringBuffer("");
-        while ((currentIndex = lowerInput.indexOf(lowerTextToBold, firstIndex)) > -1)
{
-            newString.append(input.substring(firstIndex, currentIndex));
-            newString.append("<b>");
-            newString.append(input.substring(currentIndex, currentIndex + textToBoldLength));
-            newString.append("</b>");
-            firstIndex = currentIndex + textToBoldLength;
-        }
-        newString.append(input.substring(firstIndex, input.length()));
-        return newString.toString();
     }
 
     public void setHighlightSearchMatchText(boolean highlightSearchMatchText)
     {
         this.highlightSearchMatchText = highlightSearchMatchText;
     }
+
+    private class OneLineEditorKit extends StyledEditorKit {
+        private ViewFactory viewFactoryImpl = new ViewFactoryImpl();
+
+        public ViewFactory getViewFactory() {
+            return viewFactoryImpl;
+        }
+    }
+
+    private class ViewFactoryImpl implements ViewFactory {
+        public View create(Element elem)
+        {
+            String elementName = elem.getName();
+            if (elementName != null)
+            {
+                if (elementName.equals(AbstractDocument.ParagraphElementName)) {
+                    return new OneLineParagraphView(elem);
+                } else  if (elementName.equals(AbstractDocument.ContentElementName)) {
+                    return new LabelView(elem);
+                } else if (elementName.equals(AbstractDocument.SectionElementName)) {
+                    return new BoxView(elem, View.Y_AXIS);
+                } else if (elementName.equals(StyleConstants.ComponentElementName)) {
+                    return new ComponentView(elem);
+                } else if (elementName.equals(StyleConstants.IconElementName)) {
+                    return new IconView(elem);
+                }
+            }
+            return new LabelView(elem);
+        }
+    }
+
+    private class OneLineParagraphView extends ParagraphView {
+        public OneLineParagraphView(Element elem) {
+            super(elem);
+        }
+
+        //this is the main fix - set the flow span to be max val
+        public int getFlowSpan(int index) {
+            return Integer.MAX_VALUE;
+        }
+    }
 }

Modified: logging/chainsaw/trunk/src/main/resources/org/apache/log4j/chainsaw/help/release-notes.html
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/resources/org/apache/log4j/chainsaw/help/release-notes.html?rev=955150&r1=955149&r2=955150&view=diff
==============================================================================
--- logging/chainsaw/trunk/src/main/resources/org/apache/log4j/chainsaw/help/release-notes.html
(original)
+++ logging/chainsaw/trunk/src/main/resources/org/apache/log4j/chainsaw/help/release-notes.html
Wed Jun 16 07:43:55 2010
@@ -10,6 +10,11 @@
 <b>NOTE:</b> The mechanism and format used to persist settings in Chainsaw is
subject to change.  If you are experiencing problems displaying events in Chainsaw, please
delete everything in the $user.dir/.chainsaw directory and restart Chainsaw.
 <br>
 <h1>2.1</h1>
+<h2>15 Jun 2010</h2>
+<ul>
+<li>Added 'copy value under pointer to clipboard' log panel context menu item.</li>
+<li>Fixed a number of table rendering issues, including bolding and line wrapping (line
wrap mode correctly displays the entire event).</li>
+</ul>
 <h2>14 Jun 2010</h2>
 <ul>
 <li>Updated initial 'You have no receivers defined' dialog to clarify what configuration
options are available, including the fact that Chainsaw always saves the receiver configuration
defined through the Receiver configuration panel, and that receiver configuration can be auto-loaded
by Chainsaw.</li>



Mime
View raw message