public Component getTableCellRendererComponent()

in src/main/java/org/apache/log4j/chainsaw/TableColorizingRenderer.java [153:441]


    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);
            long millisBetween = ChronoUnit.MILLIS.between( loggingEventWrapper.getLoggingEvent().m_timestamp, previous.getLoggingEvent().m_timestamp );
            delta = Math.min(ChainsawConstants.MILLIS_DELTA_RENDERING_HEIGHT_MAX, 
                    Math.max(0, (long) ((millisBetween) * 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();
        AbstractConfiguration configuration = SettingsManager.getInstance().getGlobalConfiguration();
        //use logger colors in table instead of event colors if event passes logger rule
        if (loggerRule != null && loggerRule.evaluate(loggingEventWrapper.getLoggingEvent(), null)) {
            background = configuration.get(Color.class, "searchBackgroundColor", ChainsawConstants.FIND_LOGGER_BACKGROUND);
            foreground = configuration.get(Color.class, "searchForegroundColor", ChainsawConstants.FIND_LOGGER_FOREGROUND);
        } else {
            if (colorizeSearch && !configuration.getBoolean("bypassSearchColors", false)) {
                background = loggingEventWrapper.isSearchMatch() ? configuration.get(Color.class, "searchBackgroundColor", ChainsawConstants.FIND_LOGGER_BACKGROUND) : loggingEventWrapper.getBackground();
                foreground = loggingEventWrapper.isSearchMatch() ? configuration.get(Color.class, "searchForegroundColor", ChainsawConstants.FIND_LOGGER_FOREGROUND) : 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 = configuration.get(Color.class, "alternatingColorBackground", ChainsawConstants.COLOR_ODD_ROW_BACKGROUND);
            foreground = configuration.get(Color.class, "alternatingColorForeground", ChainsawConstants.COLOR_ODD_ROW_FOREGROUND);
        }

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