/*
 * 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();
    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((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 = loggingEventWrapper.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(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 (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;
        }
    }
}
