/*
 * 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.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<String, Icon> 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();
    LoggingEventWrapper loggingEventWrapper = container.getRow(row);
    value = formatField(value, loggingEventWrapper);
    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 (loggingEventWrapper == null) {
        return super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col);
    }
    long delta = 0;
    if (row > 0) {
        LoggingEventWrapper previous = eventContainer.getRow(row - 1);
        delta = Math.min(ChainsawConstants.MILLIS_DELTA_RENDERING_HEIGHT_MAX, Math.max(0, (long) ((loggingEventWrapper.getLoggingEvent().getTimeStamp() - previous.getLoggingEvent().getTimeStamp()) * ChainsawConstants.MILLIS_DELTA_RENDERING_FACTOR)));
    }

    Map matches = loggingEventWrapper.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 = loggingEventWrapper.getMarkerHeight();
        int currentMsgHeight = loggingEventWrapper.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) {
            loggingEventWrapper.setMarkerHeight(newRowHeight);
            if (newRowHeight != currentMarkerHeight && newRowHeight >= loggingEventWrapper.getMsgHeight()) {
                setHeight = true;
            }
        }

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

        component = textPaneContainer;
        break;
    case ChainsawColumns.INDEX_LEVEL_COL_NAME:
      if (levelUseIcons) {
        levelTextPane.setText("");
        levelTextPane.insertIcon(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 = loggingEventWrapper.getPropertyKeySet();
        String headerName = tableColumn.getHeaderValue().toString().toLowerCase();
        String thisProp = null;
        //find the property in the property set...case-sensitive
        for (Object aPropertySet : propertySet) {
            String entry = aPropertySet.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(loggingEventWrapper.getLoggingEvent().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(loggingEventWrapper.getLoggingEvent(), null)) {
        background = applicationPreferenceModel.getSearchBackgroundColor();
        foreground = applicationPreferenceModel.getSearchForegroundColor();
    } else {
        if (colorizeSearch && !applicationPreferenceModel.isBypassSearchColors()) {
          background = loggingEventWrapper.isSearchMatch()?applicationPreferenceModel.getSearchBackgroundColor():loggingEventWrapper.getBackground();
          foreground = loggingEventWrapper.isSearchMatch()?applicationPreferenceModel.getSearchForegroundColor():loggingEventWrapper.getForeground();
        } else {
          background = loggingEventWrapper.getBackground();
          foreground = loggingEventWrapper.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, LoggingEventWrapper loggingEventWrapper) {
    if (!(field instanceof Date)) {
      return (field == null ? "" : field);
    }

    //handle date field
    if (useRelativeTimesToFixedTime) {
        return "" + (((Date)field).getTime() - relativeTimestampBase);
    }
    if (useRelativeTimesToPrevious) {
        return loggingEventWrapper.getLoggingEvent().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 (Object aThisSet : thisSet) {
                String thisEntry = aThisSet.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)
            {
                switch (elementName) {
                    case AbstractDocument.ParagraphElementName:
                        return new OneLineParagraphView(elem);
                    case AbstractDocument.ContentElementName:
                        return new LabelView(elem);
                    case AbstractDocument.SectionElementName:
                        return new BoxView(elem, View.Y_AXIS);
                    case StyleConstants.ComponentElementName:
                        return new ComponentView(elem);
                    case 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;
        }
    }
}
