/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.log4j.chainsaw;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Toolkit;
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;
import javax.swing.BoxLayout;
import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.JTextPane;
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.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.rule.Rule;
import org.apache.log4j.spi.LoggingEventFieldResolver;


/**
 * A specific TableCellRenderer that colourizes a particular cell based on
 * some ColourFilters that have been stored according to the value for the row
 *
 * @author Claude Duguay
 * @author Scott Deboy &lt;sdeboy@apache.org&gt;
 * @author Paul Smith &lt;psmith@apache.org&gt;
 *
 */
public class TableColorizingRenderer extends DefaultTableCellRenderer {
  private static final DateFormat DATE_FORMATTER = new SimpleDateFormat(Constants.SIMPLE_TIME_PATTERN);
  private static final Map iconMap = LevelIconFactory.getInstance().getLevelToIconMap();
  private RuleColorizer colorizer;
  private boolean levelUseIcons = false;
  private boolean wrap = false;
  private boolean highlightSearchMatchText;
  private DateFormat dateFormatInUse = DATE_FORMATTER;
  private int loggerPrecision = 0;
  private boolean toolTipsVisible;
  private String dateFormatTZ;
  private boolean useRelativeTimesToFixedTime = false;
  private long relativeTimestampBase;

  private static int borderWidth = ChainsawConstants.TABLE_BORDER_WIDTH;

  private final Color borderColor;

  private final JTextPane levelTextPane = new JTextPane();
  private JTextPane singleLineTextPane = new JTextPane();

  private final JPanel multiLinePanel = new JPanel(new BorderLayout());
  private final JPanel generalPanel = new JPanel(new BorderLayout());
  private final JPanel levelPanel = new JPanel(new BorderLayout());
  private ApplicationPreferenceModel applicationPreferenceModel;
  private JTextPane multiLineTextPane;
  private MutableAttributeSet boldAttributeSet;
  private TabSet tabs;
  private int maxHeight;
  private boolean useRelativeTimesToPrevious;
  private EventContainer eventContainer;
  private LogPanelPreferenceModel logPanelPreferenceModel;
  private SimpleAttributeSet insetAttributeSet;
  private boolean colorizeSearch;

  /**
   * Creates a new TableColorizingRenderer object.
   */
  public TableColorizingRenderer(RuleColorizer colorizer, ApplicationPreferenceModel applicationPreferenceModel,
                                 EventContainer eventContainer, LogPanelPreferenceModel logPanelPreferenceModel,
                                 boolean colorizeSearch) {
    this.applicationPreferenceModel = applicationPreferenceModel;
    this.logPanelPreferenceModel = logPanelPreferenceModel;
    this.eventContainer = eventContainer;
    this.colorizeSearch = colorizeSearch;
    multiLinePanel.setLayout(new BoxLayout(multiLinePanel, BoxLayout.Y_AXIS));
    generalPanel.setLayout(new BoxLayout(generalPanel, BoxLayout.Y_AXIS));
    levelPanel.setLayout(new BoxLayout(levelPanel, BoxLayout.Y_AXIS));
    maxHeight = Toolkit.getDefaultToolkit().getScreenSize().height;

    if (UIManager.get("Table.selectionBackground") != null) {
        borderColor = (Color)UIManager.get("Table.selectionBackground");
    } else {
        borderColor = Color.BLUE;
    }
    //define the 'bold' attributeset
    boldAttributeSet = new SimpleAttributeSet();
    StyleConstants.setBold(boldAttributeSet, true);

    insetAttributeSet = new SimpleAttributeSet();
    StyleConstants.setLeftIndent(insetAttributeSet, 6);
    //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});

    levelTextPane.setOpaque(true);
    levelTextPane.setText("");

    levelPanel.add(levelTextPane);

    this.colorizer = colorizer;
    multiLineTextPane = new JTextPane();
    multiLineTextPane.setEditorKit(new StyledEditorKit());

    singleLineTextPane.setEditorKit(new OneLineEditorKit());
    levelTextPane.setEditorKit(new OneLineEditorKit());

    multiLineTextPane.setEditable(false);
    multiLineTextPane.setFont(levelTextPane.getFont());

    multiLineTextPane.setParagraphAttributes(insetAttributeSet, false);
    singleLineTextPane.setParagraphAttributes(insetAttributeSet, false);
    levelTextPane.setParagraphAttributes(insetAttributeSet, false);
  }

  public void setToolTipsVisible(boolean toolTipsVisible) {
      this.toolTipsVisible = toolTipsVisible;
  }

  public Component getTableCellRendererComponent(
    final JTable table, Object value, boolean isSelected, boolean hasFocus,
    int row, int col) {
    EventContainer container = (EventContainer) table.getModel();
    LogEventWrapper logEventWrapper = container.getRow(row);
    value = formatField(value, logEventWrapper);
    TableColumn tableColumn = table.getColumnModel().getColumn(col);
    int width = tableColumn.getWidth();
    JLabel label = (JLabel)super.getTableCellRendererComponent(table, value,
        isSelected, hasFocus, row, col);
    //chainsawcolumns uses one-based indexing
    int colIndex = tableColumn.getModelIndex() + 1;

    //no event, use default renderer
    if (logEventWrapper == null) {
        return super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col);
    }
    long delta = 0;
    if (row > 0) {
        LogEventWrapper previous = eventContainer.getRow(row - 1);
        delta = Math.min(ChainsawConstants.MILLIS_DELTA_RENDERING_HEIGHT_MAX, Math.max(0, (long) ((logEventWrapper.getLogEvent().getTimeStamp() - previous.getLogEvent().getTimeStamp()) * ChainsawConstants.MILLIS_DELTA_RENDERING_FACTOR)));
    }

    Map matches = logEventWrapper.getSearchMatches();

    JComponent component;
    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) {
              singleLineTextPane.setText(((String[])value)[0]);
              boldAll((StyledDocument) singleLineTextPane.getDocument());
          } else {
              singleLineTextPane.setText(((String[])value)[0]);
          }
      } else {
        singleLineTextPane.setText("");
      }
      layoutRenderingPanel(generalPanel, singleLineTextPane, delta, isSelected, width, col, table);
      component = generalPanel;
      break;
    case ChainsawColumns.INDEX_LOGGER_COL_NAME:
      String logger = value.toString();
      int startPos = -1;

      for (int i = 0; i < loggerPrecision; i++) {
        startPos = logger.indexOf(".", startPos + 1);
        if (startPos < 0) {
          break;
        }
      }
        singleLineTextPane.setText(logger.substring(startPos + 1));
        setHighlightAttributesInternal(matches.get(LoggingEventFieldResolver.LOGGER_FIELD), (StyledDocument) singleLineTextPane.getDocument());
        layoutRenderingPanel(generalPanel, singleLineTextPane, delta, isSelected, width, col, table);
        component = generalPanel;
      break;
    case ChainsawColumns.INDEX_ID_COL_NAME:
        singleLineTextPane.setText(value.toString());
        setHighlightAttributesInternal(matches.get(LoggingEventFieldResolver.PROP_FIELD + "LOG4JID"), (StyledDocument) singleLineTextPane.getDocument());
        layoutRenderingPanel(generalPanel, singleLineTextPane, delta, isSelected, width, col, table);
        component = generalPanel;
        break;
    case ChainsawColumns.INDEX_CLASS_COL_NAME:
        singleLineTextPane.setText(value.toString());
        setHighlightAttributesInternal(matches.get(LoggingEventFieldResolver.CLASS_FIELD), (StyledDocument) singleLineTextPane.getDocument());
        layoutRenderingPanel(generalPanel, singleLineTextPane, delta, isSelected, width, col, table);
        component = generalPanel;
        break;
    case ChainsawColumns.INDEX_FILE_COL_NAME:
        singleLineTextPane.setText(value.toString());
        setHighlightAttributesInternal(matches.get(LoggingEventFieldResolver.FILE_FIELD), (StyledDocument) singleLineTextPane.getDocument());
        layoutRenderingPanel(generalPanel, singleLineTextPane, delta, isSelected, width, col, table);
        component = generalPanel;
        break;
    case ChainsawColumns.INDEX_LINE_COL_NAME:
        singleLineTextPane.setText(value.toString());
        setHighlightAttributesInternal(matches.get(LoggingEventFieldResolver.LINE_FIELD), (StyledDocument) singleLineTextPane.getDocument());
        layoutRenderingPanel(generalPanel, singleLineTextPane, delta, isSelected, width, col, table);
        component = generalPanel;
        break;
    case ChainsawColumns.INDEX_NDC_COL_NAME:
        singleLineTextPane.setText(value.toString());
        setHighlightAttributesInternal(matches.get(LoggingEventFieldResolver.NDC_FIELD), (StyledDocument) singleLineTextPane.getDocument());
        layoutRenderingPanel(generalPanel, singleLineTextPane, delta, isSelected, width, col, table);
        component = generalPanel;
        break;
    case ChainsawColumns.INDEX_THREAD_COL_NAME:
        singleLineTextPane.setText(value.toString());
        setHighlightAttributesInternal(matches.get(LoggingEventFieldResolver.THREAD_FIELD), (StyledDocument) singleLineTextPane.getDocument());
        layoutRenderingPanel(generalPanel, singleLineTextPane, delta, isSelected, width, col, table);
        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) {
            singleLineTextPane.setText(value.toString());
            boldAll((StyledDocument) singleLineTextPane.getDocument());
        } else {
            singleLineTextPane.setText(value.toString());
        }
        layoutRenderingPanel(generalPanel, singleLineTextPane, delta, isSelected, width, col, table);
        component = generalPanel;
        break;
    case ChainsawColumns.INDEX_METHOD_COL_NAME:
        singleLineTextPane.setText(value.toString());
        setHighlightAttributesInternal(matches.get(LoggingEventFieldResolver.METHOD_FIELD), (StyledDocument) singleLineTextPane.getDocument());
        layoutRenderingPanel(generalPanel, singleLineTextPane, delta, isSelected, width, col, table);
        component = generalPanel;
        break;
    case ChainsawColumns.INDEX_LOG4J_MARKER_COL_NAME:
    case ChainsawColumns.INDEX_MESSAGE_COL_NAME:
        String thisString = value.toString().trim();
        JTextPane textPane = wrap ? multiLineTextPane : singleLineTextPane;
        JComponent textPaneContainer = wrap ? multiLinePanel : generalPanel;
        textPane.setText(thisString);

        if (colIndex == ChainsawColumns.INDEX_LOG4J_MARKER_COL_NAME) {
            //property keys are set as all uppercase
            setHighlightAttributesInternal(matches.get(LoggingEventFieldResolver.PROP_FIELD + ChainsawConstants.LOG4J_MARKER_COL_NAME_LOWERCASE.toUpperCase()), (StyledDocument) textPane.getDocument());
        } else {
            setHighlightAttributesInternal(matches.get(LoggingEventFieldResolver.MSG_FIELD), (StyledDocument) textPane.getDocument());
        }
        textPaneContainer.removeAll();
        if (delta > 0 && logPanelPreferenceModel.isShowMillisDeltaAsGap()) {
            JPanel newPanel = new JPanel();
            newPanel.setOpaque(true);
            newPanel.setBackground(applicationPreferenceModel.getDeltaColor());
            newPanel.setPreferredSize(new Dimension(width, (int) delta));
            textPaneContainer.add(newPanel, BorderLayout.NORTH);
        }
        textPaneContainer.add(textPane, BorderLayout.SOUTH);

        if (delta == 0 || !logPanelPreferenceModel.isShowMillisDeltaAsGap()) {
          if (col == 0) {
            textPane.setBorder(getLeftBorder(isSelected, delta));
          } else if (col == table.getColumnCount() - 1) {
            textPane.setBorder(getRightBorder(isSelected, delta));
          } else {
            textPane.setBorder(getMiddleBorder(isSelected, delta));
          }
        } else {
            if (col == 0) {
              textPane.setBorder(getLeftBorder(isSelected, 0));
            } else if (col == table.getColumnCount() - 1) {
              textPane.setBorder(getRightBorder(isSelected, 0));
            } else {
              textPane.setBorder(getMiddleBorder(isSelected, 0));
            }
        }
        int currentMarkerHeight = logEventWrapper.getMarkerHeight();
        int currentMsgHeight = logEventWrapper.getMsgHeight();
        int newRowHeight = ChainsawConstants.DEFAULT_ROW_HEIGHT;
        boolean setHeight = false;

        if (wrap) {
            /*
            calculating the height -would- be the correct thing to do, but setting the size to screen size works as well and
            doesn't incur massive overhead, like calculateHeight does
            Map paramMap = new HashMap();
            paramMap.put(TextAttribute.FONT, multiLineTextPane.getFont());

            int calculatedHeight = calculateHeight(thisString, width, paramMap);
             */
            //instead, set size to max height
            textPane.setSize(new Dimension(width, maxHeight));
            int multiLinePanelPrefHeight = textPaneContainer.getPreferredSize().height;
            newRowHeight = Math.max(ChainsawConstants.DEFAULT_ROW_HEIGHT, multiLinePanelPrefHeight);

        }
        if (!wrap && logPanelPreferenceModel.isShowMillisDeltaAsGap()) {
            textPane.setSize(new Dimension(Integer.MAX_VALUE, ChainsawConstants.DEFAULT_ROW_HEIGHT));
            newRowHeight = (int) (ChainsawConstants.DEFAULT_ROW_HEIGHT + delta);
        }

        if (colIndex == ChainsawColumns.INDEX_LOG4J_MARKER_COL_NAME) {
            logEventWrapper.setMarkerHeight(newRowHeight);
            if (newRowHeight != currentMarkerHeight && newRowHeight >= logEventWrapper.getMsgHeight()) {
                setHeight = true;
            }
        }

        if (colIndex == ChainsawColumns.INDEX_MESSAGE_COL_NAME) {
            logEventWrapper.setMsgHeight(newRowHeight);
            if (newRowHeight != currentMsgHeight && newRowHeight >= logEventWrapper.getMarkerHeight()) {
                setHeight = true;
            }
        }
        if (setHeight) {
            table.setRowHeight(row, newRowHeight);
        }

        component = textPaneContainer;
        break;
    case ChainsawColumns.INDEX_LEVEL_COL_NAME:
      if (levelUseIcons) {
        levelTextPane.setText("");
        levelTextPane.insertIcon((Icon) iconMap.get(value.toString()));
        if (!toolTipsVisible) {
          levelTextPane.setToolTipText(value.toString());
        }
      } else {
        levelTextPane.setText(value.toString());
        setHighlightAttributesInternal(matches.get(LoggingEventFieldResolver.LEVEL_FIELD), (StyledDocument) levelTextPane.getDocument());
        if (!toolTipsVisible) {
            levelTextPane.setToolTipText(null);
        }
      }
      if (toolTipsVisible) {
          levelTextPane.setToolTipText(label.getToolTipText());
      }
      levelTextPane.setForeground(label.getForeground());
      levelTextPane.setBackground(label.getBackground());
      layoutRenderingPanel(levelPanel, levelTextPane, delta, isSelected, width, col, table);
      component = levelPanel;
      break;

    //remaining entries are properties
    default:
        Set propertySet = logEventWrapper.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.equalsIgnoreCase(headerName)) {
                thisProp = entry;
                break;
            }
        }
        if (thisProp != null) {
            String propKey = LoggingEventFieldResolver.PROP_FIELD + thisProp.toUpperCase();
            Set propKeyMatches = (Set)matches.get(propKey);
            singleLineTextPane.setText(logEventWrapper.getLogEvent().getProperty(thisProp));
            setHighlightAttributesInternal(propKeyMatches, (StyledDocument) singleLineTextPane.getDocument());
        } else {
            singleLineTextPane.setText("");
        }
        layoutRenderingPanel(generalPanel, singleLineTextPane, delta, isSelected, width, col, table);
        component = generalPanel;
        break;
    }

    Color background;
    Color foreground;
    Rule loggerRule = colorizer.getLoggerRule();
    //use logger colors in table instead of event colors if event passes logger rule
    if (loggerRule != null && loggerRule.evaluate(logEventWrapper.getLogEvent(), null)) {
        background = applicationPreferenceModel.getSearchBackgroundColor();
        foreground = applicationPreferenceModel.getSearchForegroundColor();
    } else {
        if (colorizeSearch && !applicationPreferenceModel.isBypassSearchColors()) {
          background = logEventWrapper.isSearchMatch()?applicationPreferenceModel.getSearchBackgroundColor(): logEventWrapper.getBackground();
          foreground = logEventWrapper.isSearchMatch()?applicationPreferenceModel.getSearchForegroundColor(): logEventWrapper.getForeground();
        } else {
          background = logEventWrapper.getBackground();
          foreground = logEventWrapper.getForeground();
        }
    }

    /**
     * Colourize background based on row striping if the event still has default foreground and background color
     */
    if (background.equals(ChainsawConstants.COLOR_DEFAULT_BACKGROUND) && foreground.equals(ChainsawConstants.COLOR_DEFAULT_FOREGROUND) && (row % 2) != 0) {
      background = applicationPreferenceModel.getAlternatingColorBackgroundColor();
      foreground = applicationPreferenceModel.getAlternatingColorForegroundColor();
    }

    component.setBackground(background);
    component.setForeground(foreground);

    //update the background & foreground of the jtextpane using styles
    if (multiLineTextPane != null)
    {
        updateColors(multiLineTextPane, background, foreground);
    }
    updateColors(levelTextPane, background, foreground);
    updateColors(singleLineTextPane, background, foreground);

    return component;
  }

    private void layoutRenderingPanel(JComponent container, JComponent bottomComponent, long delta, boolean isSelected,
                                      int width, int col, JTable table) {
        container.removeAll();
        if (delta == 0 || !logPanelPreferenceModel.isShowMillisDeltaAsGap()) {
          if (col == 0) {
            bottomComponent.setBorder(getLeftBorder(isSelected, delta));
          } else if (col == table.getColumnCount() - 1) {
            bottomComponent.setBorder(getRightBorder(isSelected, delta));
          } else {
            bottomComponent.setBorder(getMiddleBorder(isSelected, delta));
          }
        } else {
            JPanel newPanel = new JPanel();
            newPanel.setOpaque(true);
            newPanel.setBackground(applicationPreferenceModel.getDeltaColor());
            newPanel.setPreferredSize(new Dimension(width, (int) delta));
            container.add(newPanel, BorderLayout.NORTH);
            if (col == 0) {
              bottomComponent.setBorder(getLeftBorder(isSelected, 0));
            } else if (col == table.getColumnCount() - 1) {
              bottomComponent.setBorder(getRightBorder(isSelected, 0));
            } else {
              bottomComponent.setBorder(getMiddleBorder(isSelected, 0));
            }
        }

        container.add(bottomComponent, BorderLayout.SOUTH);
    }

    private Border getLeftBorder(boolean isSelected, long delta) {
        Border LEFT_BORDER = BorderFactory.createMatteBorder(borderWidth, borderWidth, borderWidth, 0, borderColor);
        Border LEFT_EMPTY_BORDER = BorderFactory.createEmptyBorder(borderWidth, borderWidth, borderWidth, 0);

        Border innerBorder =isSelected?LEFT_BORDER : LEFT_EMPTY_BORDER;
        if (delta == 0 || !wrap || !logPanelPreferenceModel.isShowMillisDeltaAsGap()) {
            return innerBorder;
        } else {
            Border outerBorder = BorderFactory.createMatteBorder((int) Math.max(borderWidth, delta), 0, 0, 0, applicationPreferenceModel.getDeltaColor());
            return BorderFactory.createCompoundBorder(outerBorder, innerBorder);
        }
    }

    private Border getRightBorder(boolean isSelected, long delta) {
        Border RIGHT_BORDER = BorderFactory.createMatteBorder(borderWidth, 0, borderWidth, borderWidth, borderColor);
        Border RIGHT_EMPTY_BORDER = BorderFactory.createEmptyBorder(borderWidth, 0, borderWidth, borderWidth);
        Border innerBorder =isSelected?RIGHT_BORDER : RIGHT_EMPTY_BORDER;
        if (delta == 0 || !wrap || !logPanelPreferenceModel.isShowMillisDeltaAsGap()) {
            return innerBorder;
        } else {
            Border outerBorder = BorderFactory.createMatteBorder((int) Math.max(borderWidth, delta), 0, 0, 0, applicationPreferenceModel.getDeltaColor());
            return BorderFactory.createCompoundBorder(outerBorder, innerBorder);
        }
    }

    private Border getMiddleBorder(boolean isSelected, long delta) {
        Border MIDDLE_BORDER = BorderFactory.createMatteBorder(borderWidth, 0, borderWidth, 0, borderColor);
        Border MIDDLE_EMPTY_BORDER = BorderFactory.createEmptyBorder(borderWidth, 0, borderWidth, 0);
        Border innerBorder =isSelected ?MIDDLE_BORDER : MIDDLE_EMPTY_BORDER;
        if (delta == 0 || !wrap || !logPanelPreferenceModel.isShowMillisDeltaAsGap()) {
            return innerBorder;
        } else {
            Border outerBorder = BorderFactory.createMatteBorder((int)Math.max(borderWidth, delta), 0, 0, 0, applicationPreferenceModel.getDeltaColor());
            return BorderFactory.createCompoundBorder(outerBorder, innerBorder);
        }
    }

    private void updateColors(JTextPane textPane, Color background, Color foreground)
    {
        StyledDocument styledDocument = textPane.getStyledDocument();
        MutableAttributeSet attributes = textPane.getInputAttributes();
        StyleConstants.setForeground(attributes, foreground);
        styledDocument.setCharacterAttributes(0, styledDocument.getLength() + 1, attributes, false);
        textPane.setBackground(background);
    }

  /**
   * Changes the Date Formatting object to be used for rendering dates.
   * @param formatter
   */
  void setDateFormatter(DateFormat formatter) {
    this.dateFormatInUse = formatter;
    if (dateFormatInUse != null && dateFormatTZ != null && !("".equals(dateFormatTZ))) {
      dateFormatInUse.setTimeZone(TimeZone.getTimeZone(dateFormatTZ));
    } else {
      dateFormatInUse.setTimeZone(TimeZone.getDefault());
    }
  }

  /**
   * Changes the Logger precision.
   * @param loggerPrecisionText
   */
  void setLoggerPrecision(String loggerPrecisionText) {
    try {
      loggerPrecision = Integer.parseInt(loggerPrecisionText);
    } catch (NumberFormatException nfe) {
        loggerPrecision = 0;
    }
  }

  /**
   *Format date field
   *
   * @param field object
   *
   * @return formatted object
   */
  private Object formatField(Object field, LogEventWrapper logEventWrapper) {
    if (!(field instanceof Date)) {
      return (field == null ? "" : field);
    }

    //handle date field
    if (useRelativeTimesToFixedTime) {
        return "" + (((Date)field).getTime() - relativeTimestampBase);
    }
    if (useRelativeTimesToPrevious) {
        return logEventWrapper.getLogEvent().getProperty(ChainsawConstants.MILLIS_DELTA_COL_NAME_LOWERCASE);
    }

    return dateFormatInUse.format((Date) field);
  }

    /**
    * Sets the property which determines whether to wrap the message
    * @param wrapMsg
    */
   public void setWrapMessage(boolean wrapMsg) {
     this.wrap = wrapMsg;
   }

   /**
   * Sets the property which determines whether to use Icons or text
   * for the Level column
   * @param levelUseIcons
   */
  public void setLevelUseIcons(boolean levelUseIcons) {
    this.levelUseIcons = levelUseIcons;
  }

  public void setTimeZone(String dateFormatTZ) {
    this.dateFormatTZ = dateFormatTZ;

    if (dateFormatInUse != null && dateFormatTZ != null && !("".equals(dateFormatTZ))) {
      dateFormatInUse.setTimeZone(TimeZone.getTimeZone(dateFormatTZ));
    } else {
      dateFormatInUse.setTimeZone(TimeZone.getDefault());
    }
  }

  public void setUseRelativeTimes(long timeStamp) {
    useRelativeTimesToFixedTime = true;
    useRelativeTimesToPrevious = false;
    relativeTimestampBase = timeStamp;
  }

  public void setUseRelativeTimesToPreviousRow() {
     useRelativeTimesToFixedTime = false;
     useRelativeTimesToPrevious = true;
  }

  public void setUseNormalTimes() {
    useRelativeTimesToFixedTime = false;
    useRelativeTimesToPrevious = false;
  }

  /*
   private int calculateHeight(String string, int width, Map paramMap) {
     if (string.trim().length() == 0) {
         return ChainsawConstants.DEFAULT_ROW_HEIGHT;
     }
     AttributedCharacterIterator paragraph = new AttributedString(string, paramMap).getIterator();
     LineBreakMeasurer lineMeasurer = new LineBreakMeasurer(paragraph, new FontRenderContext(null, true, true));
     float height = 0;
     lineMeasurer.setPosition(paragraph.getBeginIndex());
     TextLayout layout;
     while (lineMeasurer.getPosition() < paragraph.getEndIndex()) {
       layout = lineMeasurer.nextLayout(width);
         float layoutHeight = layout.getAscent() + layout.getDescent() + layout.getLeading();
         height += layoutHeight;
     }
     return Math.max(ChainsawConstants.DEFAULT_ROW_HEIGHT, (int) height);
    }
    */

    private void setHighlightAttributesInternal(Object matchSet, StyledDocument styledDocument) {
        if (!highlightSearchMatchText) {
            return;
        }
        setHighlightAttributes(matchSet, styledDocument);
    }

    public void setHighlightAttributes(Object matchSet, StyledDocument styledDocument) {
        if (matchSet instanceof Set) {
            Set thisSet = (Set)matchSet;
            for (Iterator iter = thisSet.iterator();iter.hasNext();) {
                String thisEntry = iter.next().toString();
                bold(thisEntry, styledDocument);
            }
        }
    }

    private void boldAll(StyledDocument styledDocument) {
        if (!highlightSearchMatchText) {
            return;
        }
        styledDocument.setCharacterAttributes(0, styledDocument.getLength(), boldAttributeSet, false);
    }
    
    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;
            while ((currentIndex = lowerInput.indexOf(lowerTextToBold, firstIndex)) > -1) {
                styledDocument.setCharacterAttributes(currentIndex, textToBoldLength, boldAttributeSet, false);
                firstIndex = currentIndex + textToBoldLength;
            }
        }
        catch (BadLocationException e) {
            //ignore
        }
    }

    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;
        }
    }
}
