psmith 2003/09/03 22:45:16 Modified: src/java/org/apache/log4j/chainsaw/layout EventDetailLayout.java src/java/org/apache/log4j/chainsaw LogUI.java Added: src/java/org/apache/log4j/chainsaw/layout DefaultLayoutFactory.java LayoutEditorPane.java Log: added support for a PatternLayout Editor dialog which edits and sets the Layout used in the Event detail pane. Allows user to Edit pattern text and shows a running preview of the result in a preview pane as you type. Refactored the loading of the default html pattern text into a separate class. Revision Changes Path 1.2 +7 -52 jakarta-log4j/src/java/org/apache/log4j/chainsaw/layout/EventDetailLayout.java Index: EventDetailLayout.java =================================================================== RCS file: /home/cvs/jakarta-log4j/src/java/org/apache/log4j/chainsaw/layout/EventDetailLayout.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- EventDetailLayout.java 4 Sep 2003 02:30:28 -0000 1.1 +++ EventDetailLayout.java 4 Sep 2003 05:45:16 -0000 1.2 @@ -52,80 +52,35 @@ import org.apache.log4j.Layout; import org.apache.log4j.Logger; import org.apache.log4j.PatternLayout; -import org.apache.log4j.helpers.LogLog; import org.apache.log4j.spi.LocationInfo; import org.apache.log4j.spi.LoggingEvent; -import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStreamReader; import java.io.Writer; -import java.net.URL; - import java.util.Hashtable; import java.util.Iterator; import java.util.Set; -import javax.swing.text.html.HTMLEditorKit; - /** * This layout is used for formatting HTML text for use inside * the Chainsaw Event Detail Panel, and the tooltip used - * when mouse-over on a particular log event row + * when mouse-over on a particular log event row. + * + * It relies an an internal PatternLayout to accomplish this, but ensures HTML characters + * from any LoggingEvent are escaped first. * * @author Paul Smith <[EMAIL PROTECTED]> */ public class EventDetailLayout extends Layout { - private PatternLayout patternLayout = - new PatternLayout(PatternLayout.TTCC_CONVERSION_PATTERN); + private PatternLayout patternLayout = new PatternLayout(); public EventDetailLayout() { - URL defaultLayoutURL = - this.getClass().getClassLoader().getResource( - "org/apache/log4j/chainsaw/layout/DefaultDetailLayout.html"); - - if (defaultLayoutURL == null) { - LogLog.warn( - "Could not locate the default Layout for Event Details and Tooltips"); - } else { - HTMLEditorKit kit = new HTMLEditorKit(); - - try { - StringBuffer content = new StringBuffer(); - BufferedReader reader = null; - - try { - reader = - new BufferedReader( - new InputStreamReader(defaultLayoutURL.openStream())); - - String line = ""; - - while ((line = reader.readLine()) != null) { - content.append(line); - } - } finally { - if (reader != null) { - reader.close(); - } - } - - if (content != null) { - LogLog.debug("Loaded layout content:\n" + content); - patternLayout.setConversionPattern(content.toString()); - } else { - LogLog.warn("No Layout content retrieved, using default"); - } - } catch (Exception e) { - LogLog.error("Failed to read in the Layout", e); - } - } } - public void setConverionPatter(String conversionPatter) { - patternLayout.setConversionPattern(conversionPatter); + public void setConversionPattern(String conversionPattern) { + patternLayout.setConversionPattern(conversionPattern); } public String getConversionPattern() { 1.1 jakarta-log4j/src/java/org/apache/log4j/chainsaw/layout/DefaultLayoutFactory.java Index: DefaultLayoutFactory.java =================================================================== /* * ============================================================================ * The Apache Software License, Version 1.1 * ============================================================================ * * Copyright (C) 1999 The Apache Software Foundation. All rights reserved. * * Redistribution and use in source and binary forms, with or without modifica- * tion, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * 3. The end-user documentation included with the redistribution, if any, must * include the following acknowledgment: "This product includes software * developed by the Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, if * and wherever such third-party acknowledgments normally appear. * * 4. The names "log4j" and "Apache Software Foundation" must not be used to * endorse or promote products derived from this software without prior * written permission. For written permission, please contact * [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache", nor may * "Apache" appear in their name, without prior written permission of the * Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- * DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * This software consists of voluntary contributions made by many individuals * on behalf of the Apache Software Foundation. For more information on the * Apache Software Foundation, please see <http://www.apache.org/>. * */ package org.apache.log4j.chainsaw.layout; import org.apache.log4j.PatternLayout; import org.apache.log4j.helpers.LogLog; import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.URL; /** * Factory class to load and cache Layout information from resources. * * @author Paul Smith <[EMAIL PROTECTED]> */ public class DefaultLayoutFactory { private static String defaultPatternLayout = null; private DefaultLayoutFactory() { } public static String getDefaultPatternLayout() { if (defaultPatternLayout == null) { StringBuffer content = new StringBuffer(); URL defaultLayoutURL = DefaultLayoutFactory.class.getClassLoader().getResource( "org/apache/log4j/chainsaw/layout/DefaultDetailLayout.html"); if (defaultLayoutURL == null) { LogLog.warn( "Could not locate the default Layout for Event Details and Tooltips"); } else { try { BufferedReader reader = null; try { reader = new BufferedReader( new InputStreamReader(defaultLayoutURL.openStream())); String line = ""; while ((line = reader.readLine()) != null) { content.append(line).append("\n"); } } finally { if (reader != null) { reader.close(); } } } catch (Exception e) { content = new StringBuffer(PatternLayout.TTCC_CONVERSION_PATTERN); } defaultPatternLayout = content.toString(); } } return defaultPatternLayout; } } 1.1 jakarta-log4j/src/java/org/apache/log4j/chainsaw/layout/LayoutEditorPane.java Index: LayoutEditorPane.java =================================================================== /* * ============================================================================ * The Apache Software License, Version 1.1 * ============================================================================ * * Copyright (C) 1999 The Apache Software Foundation. All rights reserved. * * Redistribution and use in source and binary forms, with or without modifica- * tion, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * 3. The end-user documentation included with the redistribution, if any, must * include the following acknowledgment: "This product includes software * developed by the Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, if * and wherever such third-party acknowledgments normally appear. * * 4. The names "log4j" and "Apache Software Foundation" must not be used to * endorse or promote products derived from this software without prior * written permission. For written permission, please contact * [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache", nor may * "Apache" appear in their name, without prior written permission of the * Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- * DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * This software consists of voluntary contributions made by many individuals * on behalf of the Apache Software Foundation. For more information on the * Apache Software Foundation, please see <http://www.apache.org/>. * */ package org.apache.log4j.chainsaw.layout; import org.apache.log4j.Logger; import org.apache.log4j.chainsaw.ChainsawConstants; import org.apache.log4j.chainsaw.icons.ChainsawIcons; import org.apache.log4j.spi.LocationInfo; import org.apache.log4j.spi.LoggingEvent; import org.apache.log4j.spi.ThrowableInformation; import java.awt.Dimension; import java.awt.Frame; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.Date; import java.util.Hashtable; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.BorderFactory; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JEditorPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JToolBar; import javax.swing.event.CaretEvent; import javax.swing.event.CaretListener; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; /** * An editor Pane that allows a user to Edit a Pattern Layout and preview the output it would * generate with an example LoggingEvent * * @author Paul Smith <[EMAIL PROTECTED]> * */ public final class LayoutEditorPane extends JPanel { private final Action copyAction; private final Action cutAction; private final JToolBar editorToolbar = new JToolBar(); private final JToolBar okCancelToolbar = new JToolBar(); private final JButton okButton = new JButton("Ok"); private final JButton cancelButton = new JButton("Cancel"); // private final JButton applyButton = new JButton(); private final JEditorPane patternEditor = new JEditorPane("text/plain", ""); private final JEditorPane previewer = new JEditorPane(ChainsawConstants.DETAIL_CONTENT_TYPE, ""); private final JScrollPane patternEditorScroll = new JScrollPane( JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); private final JScrollPane previewEditorScroll = new JScrollPane( JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); private LoggingEvent event; private EventDetailLayout layout = new EventDetailLayout(); /** * */ public LayoutEditorPane() { super(); setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); createEvent(); copyAction = createCopyAction(); cutAction = createCutAction(); initComponents(); setupListeners(); } /** * @return */ private Action createCutAction() { final Action action = new AbstractAction("Cut", ChainsawIcons.ICON_CUT) { public void actionPerformed(ActionEvent e) { // TODO Auto-generated method stub } }; action.setEnabled(false); return action; } /** * @return */ private Action createCopyAction() { final Action action = new AbstractAction("Copy", ChainsawIcons.ICON_COPY) { public void actionPerformed(ActionEvent e) { // TODO Auto-generated method stub } }; action.setEnabled(false); return action; } /** * */ private void setupListeners() { patternEditor.getDocument().addDocumentListener( new DocumentListener() { public void changedUpdate(DocumentEvent e) { updatePreview(); } public void insertUpdate(DocumentEvent e) { updatePreview(); } public void removeUpdate(DocumentEvent e) { updatePreview(); } }); patternEditor.addCaretListener( new CaretListener() { public void caretUpdate(CaretEvent e) { updateTextActions(e.getMark() != e.getDot()); } }); } private void updatePreview() { String pattern = patternEditor.getText(); layout.setConversionPattern(pattern); previewer.setText(layout.format(event)); } /** * */ private void updateTextActions(boolean enabled) { cutAction.setEnabled(enabled); copyAction.setEnabled(enabled); } /** * */ private void createEvent() { Hashtable hashTable = new Hashtable(); hashTable.put("key1", "val1"); hashTable.put("key2", "val2"); hashTable.put("key3", "val3"); LocationInfo li = new LocationInfo( "myfile.java", "com.mycompany.util.MyClass", "myMethod", "321"); ThrowableInformation tsr = new ThrowableInformation(new Exception()); event = new LoggingEvent( "com.mycompany.mylogger", Logger.getLogger("com.mycompany.mylogger"), new Date().getTime(), org.apache.log4j.Level.DEBUG, "Thread-1", "The quick brown fox jumped over the lazy dog", "NDC string", hashTable, tsr.getThrowableStrRep(), li, hashTable); } /** * */ private void initComponents() { editorToolbar.setFloatable(false); okCancelToolbar.setFloatable(false); okButton.setToolTipText("Accepts the current Pattern layout and will apply it to the Log Panel"); cancelButton.setToolTipText("Closes this dialog and discards your changes"); previewer.setEditable(false); patternEditor.setPreferredSize(new Dimension(240, 240)); patternEditor.setMaximumSize(new Dimension(320, 240)); previewer.setPreferredSize(new Dimension(360, 240)); patternEditorScroll.setViewportView(patternEditor); previewEditorScroll.setViewportView(previewer); patternEditor.setToolTipText("Edit the Pattern here"); previewer.setToolTipText( "The result of the layout of the pattern is shown here"); patternEditorScroll.setBorder( BorderFactory.createTitledBorder( BorderFactory.createEtchedBorder(), "Pattern Editor")); previewEditorScroll.setBorder( BorderFactory.createTitledBorder( BorderFactory.createEtchedBorder(), "Pattern Preview")); // editorToolbar.add(new JButton(copyAction)); // editorToolbar.add(new JButton(cutAction)); editorToolbar.add(Box.createHorizontalGlue()); okCancelToolbar.add(Box.createHorizontalGlue()); okCancelToolbar.add(okButton); okCancelToolbar.addSeparator(); okCancelToolbar.add(cancelButton); // okCancelToolbar.addSeparator(); // okCancelToolbar.add(applyButton); add(editorToolbar); add(patternEditorScroll); add(previewEditorScroll); add(okCancelToolbar); } public void setConversionPattern(String pattern) { patternEditor.setText(pattern); } public String getConversionPattern() { return patternEditor.getText(); } public void addOkActionListener(ActionListener l) { okButton.addActionListener(l); } public void addCancelActionListener(ActionListener l) { cancelButton.addActionListener(l); } public static void main(String[] args) { JDialog dialog = new JDialog((Frame) null, "Pattern Editor"); dialog.getContentPane().add(new LayoutEditorPane()); dialog.setResizable(true); dialog.setDefaultCloseOperation(JDialog.EXIT_ON_CLOSE); // dialog.pack(); dialog.setSize(new Dimension(640, 480)); dialog.setVisible(true); } } 1.19 +78 -1 jakarta-log4j/src/java/org/apache/log4j/chainsaw/LogUI.java Index: LogUI.java =================================================================== RCS file: /home/cvs/jakarta-log4j/src/java/org/apache/log4j/chainsaw/LogUI.java,v retrieving revision 1.18 retrieving revision 1.19 diff -u -r1.18 -r1.19 --- LogUI.java 4 Sep 2003 02:30:28 -0000 1.18 +++ LogUI.java 4 Sep 2003 05:45:16 -0000 1.19 @@ -52,10 +52,13 @@ import org.apache.log4j.Layout; import org.apache.log4j.Level; import org.apache.log4j.LogManager; +import org.apache.log4j.PatternLayout; import org.apache.log4j.Priority; import org.apache.log4j.UtilLoggingLevel; import org.apache.log4j.chainsaw.icons.ChainsawIcons; +import org.apache.log4j.chainsaw.layout.DefaultLayoutFactory; import org.apache.log4j.chainsaw.layout.EventDetailLayout; +import org.apache.log4j.chainsaw.layout.LayoutEditorPane; import org.apache.log4j.chainsaw.prefs.LoadSettingsEvent; import org.apache.log4j.chainsaw.prefs.SaveSettingsEvent; import org.apache.log4j.chainsaw.prefs.SettingsListener; @@ -1227,6 +1230,11 @@ public LogPanel(final String ident, String eventType) { identifier = ident; + setDetailPaneConversionPattern( + DefaultLayoutFactory.getDefaultPatternLayout()); + ((EventDetailLayout) toolTipLayout).setConversionPattern( + DefaultLayoutFactory.getDefaultPatternLayout()); + Map map = new HashMap(); entryMap.put(ident, map); @@ -1586,11 +1594,45 @@ final JToolBar detailToolbar = new JToolBar(JToolBar.HORIZONTAL); detailToolbar.setFloatable(false); + final LayoutEditorPane layoutEditorPane = new LayoutEditorPane(); + final JDialog layoutEditorDialog = + new JDialog(LogUI.this, "Pattern Editor"); + layoutEditorDialog.getContentPane().add(layoutEditorPane); + layoutEditorDialog.setSize(640, 480); + + layoutEditorPane.addCancelActionListener( + new ActionListener() { + public void actionPerformed(ActionEvent e) { + layoutEditorDialog.setVisible(false); + } + }); + + layoutEditorPane.addOkActionListener( + new ActionListener() { + public void actionPerformed(ActionEvent e) { + setDetailPaneConversionPattern( + layoutEditorPane.getConversionPattern()); + layoutEditorDialog.setVisible(false); + } + }); + Action editDetailAction = new AbstractAction( "Edit...", new ImageIcon(ChainsawIcons.ICON_EDIT_RECEIVER)) { public void actionPerformed(ActionEvent e) { - // TODO Auto-generated method stub + layoutEditorPane.setConversionPattern( + getDetailPaneConversionPattern()); + + Dimension size = Toolkit.getDefaultToolkit().getScreenSize(); + Point p = + new Point( + ((int) ((size.getWidth() / 2) + - (layoutEditorDialog.getSize().getWidth() / 2))), + ((int) ((size.getHeight() / 2) + - (layoutEditorDialog.getSize().getHeight() / 2)))); + layoutEditorDialog.setLocation(p); + + layoutEditorDialog.setVisible(true); } }; @@ -1606,6 +1648,32 @@ // detailToolbar.add(Box.createHorizontalStrut(5)); detailPanel.add(detailToolbar, BorderLayout.NORTH); + JPopupMenu editDetailPopupMenu = new JPopupMenu(); + editDetailPopupMenu.add(editDetailAction); + editDetailPopupMenu.addSeparator(); + + editDetailPopupMenu.add( + new AbstractAction("Set to Default Layout") { + public void actionPerformed(ActionEvent e) { + setDetailPaneConversionPattern( + DefaultLayoutFactory.getDefaultPatternLayout()); + } + }); + + editDetailPopupMenu.addSeparator(); + + editDetailPopupMenu.add( + new AbstractAction("Set to TCCLayout") { + public void actionPerformed(ActionEvent e) { + setDetailPaneConversionPattern( + PatternLayout.TTCC_CONVERSION_PATTERN); + } + }); + + PopupListener editDetailPopupListener = + new PopupListener(editDetailPopupMenu); + detail.addMouseListener(editDetailPopupListener); + lowerPanel = new JSplitPane( JSplitPane.VERTICAL_SPLIT, eventsAndStatusPanel, detailPanel); @@ -1976,6 +2044,15 @@ table.getSelectedRow() + 1, table.getModel().getRowCount()); } }); + } + + void setDetailPaneConversionPattern(String conversionPattern) { + ((EventDetailLayout) detailPaneLayout).setConversionPattern( + conversionPattern); + } + + String getDetailPaneConversionPattern() { + return ((EventDetailLayout) detailPaneLayout).getConversionPattern(); } void showPreferences() {
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]