in src/main/java/org/apache/log4j/chainsaw/LogPanel.java [191:1820]
public LogPanel(final ChainsawStatusBar statusBar,
final String identifier,
int cyclicBufferSize,
Map<String, RuleColorizer> allColorizers,
final ApplicationPreferenceModel applicationPreferenceModel,
RuleColorizer globalRuleColorizer) {
this.identifier = identifier;
this.statusBar = statusBar;
this.applicationPreferenceModel = applicationPreferenceModel;
this.logPanelPreferencesPanel = new LogPanelPreferencePanel(identifier);
this.colorizer = globalRuleColorizer;
this.m_globalColorizer = globalRuleColorizer;
this.m_allColorizers = allColorizers;
logger.debug("creating logpanel for {}", identifier);
m_configuration = SettingsManager.getInstance().getCombinedSettingsForRecevierTab(identifier);
AbstractConfiguration tabConfig = SettingsManager.getInstance().getSettingsForReceiverTab(identifier);
setLayout(new BorderLayout());
String prototypeValue = "1231231231231231231231";
filterCombo = new AutoFilterComboBox();
findCombo = new AutoFilterComboBox();
filterCombo.setPrototypeDisplayValue(prototypeValue);
buildCombo(filterCombo, true, findCombo.model);
findCombo.setPrototypeDisplayValue(prototypeValue);
buildCombo(findCombo, false, filterCombo.model);
final Map<Object, String> columnNameKeywordMap = new HashMap<>();
columnNameKeywordMap.put(ChainsawConstants.CLASS_COL_NAME, LoggingEventFieldResolver.CLASS_FIELD);
columnNameKeywordMap.put(ChainsawConstants.FILE_COL_NAME, LoggingEventFieldResolver.FILE_FIELD);
columnNameKeywordMap.put(ChainsawConstants.LEVEL_COL_NAME, LoggingEventFieldResolver.LEVEL_FIELD);
columnNameKeywordMap.put(ChainsawConstants.LINE_COL_NAME, LoggingEventFieldResolver.LINE_FIELD);
columnNameKeywordMap.put(ChainsawConstants.LOGGER_COL_NAME, LoggingEventFieldResolver.LOGGER_FIELD);
columnNameKeywordMap.put(ChainsawConstants.NDC_COL_NAME, LoggingEventFieldResolver.NDC_FIELD);
columnNameKeywordMap.put(ChainsawConstants.MESSAGE_COL_NAME, LoggingEventFieldResolver.MSG_FIELD);
columnNameKeywordMap.put(ChainsawConstants.THREAD_COL_NAME, LoggingEventFieldResolver.THREAD_FIELD);
columnNameKeywordMap.put(ChainsawConstants.THROWABLE_COL_NAME, LoggingEventFieldResolver.EXCEPTION_FIELD);
columnNameKeywordMap.put(ChainsawConstants.TIMESTAMP_COL_NAME, LoggingEventFieldResolver.TIMESTAMP_FIELD);
columnNameKeywordMap.put(ChainsawConstants.ID_COL_NAME.toUpperCase(), LoggingEventFieldResolver.PROP_FIELD + Constants.LOG4J_ID_KEY);
columnNameKeywordMap.put(ChainsawConstants.LOG4J_MARKER_COL_NAME_LOWERCASE.toUpperCase(), LoggingEventFieldResolver.PROP_FIELD + ChainsawConstants.LOG4J_MARKER_COL_NAME_LOWERCASE);
columnNameKeywordMap.put(ChainsawConstants.MILLIS_DELTA_COL_NAME_LOWERCASE.toUpperCase(), LoggingEventFieldResolver.PROP_FIELD + ChainsawConstants.MILLIS_DELTA_COL_NAME_LOWERCASE);
logPanelPreferencesFrame.setTitle("'" + identifier + "' Log Panel Preferences");
logPanelPreferencesFrame.setIconImage(
((ImageIcon) ChainsawIcons.ICON_PREFERENCES).getImage());
logPanelPreferencesFrame.getContentPane().add(new JScrollPane(logPanelPreferencesPanel));
logPanelPreferencesFrame.setSize(740, 520);
logPanelPreferencesPanel.setOkCancelActionListener(
e -> logPanelPreferencesFrame.setVisible(false));
KeyStroke escape = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0, false);
Action closeLogPanelPreferencesFrameAction = new AbstractAction() {
public void actionPerformed(ActionEvent e) {
logPanelPreferencesFrame.setVisible(false);
}
};
logPanelPreferencesFrame.getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(escape, "ESCAPE");
logPanelPreferencesFrame.getRootPane().
getActionMap().put("ESCAPE", closeLogPanelPreferencesFrameAction);
setDetailPaneConversionPattern(
DefaultLayoutFactory.getDefaultPatternLayout());
detailLayout.setConversionPattern(
DefaultLayoutFactory.getDefaultPatternLayout());
undockedFrame = new JFrame(identifier);
undockedFrame.setDefaultCloseOperation(
WindowConstants.DO_NOTHING_ON_CLOSE);
if (ChainsawIcons.UNDOCKED_ICON != null) {
undockedFrame.setIconImage(
new ImageIcon(ChainsawIcons.UNDOCKED_ICON).getImage());
}
externalPanel = new DockablePanel();
externalPanel.setLayout(new BorderLayout());
undockedFrame.addWindowListener(
new WindowAdapter() {
public void windowClosing(WindowEvent e) {
dock();
}
});
undockedToolbar = createDockwindowToolbar();
externalPanel.add(undockedToolbar, BorderLayout.NORTH);
undockedFrame.getContentPane().add(externalPanel);
undockedFrame.setSize(new Dimension(1024, 768));
undockedFrame.pack();
tabConfig.addEventListener(ConfigurationEvent.SET_PROPERTY,
evt -> {
if( evt.getPropertyName().equals( "scrollToBottom" ) ){
boolean value = (Boolean) evt.getPropertyValue();
if (value) {
scrollToBottom();
}
}
});
/*
* Menus on which the preferencemodels rely
*/
/**
* Setup a popup menu triggered for Timestamp column to allow time stamp
* format changes
*/
final JPopupMenu dateFormatChangePopup = new JPopupMenu();
final JRadioButtonMenuItem isoButton =
new JRadioButtonMenuItem(
new AbstractAction("Use ISO8601Format") {
public void actionPerformed(ActionEvent e) {
// preferenceModel.setDateFormatPattern("ISO8601");
}
});
final JRadioButtonMenuItem simpleTimeButton =
new JRadioButtonMenuItem(
new AbstractAction("Use simple time") {
public void actionPerformed(ActionEvent e) {
// preferenceModel.setDateFormatPattern("HH:mm:ss");
}
});
ButtonGroup dfBG = new ButtonGroup();
dfBG.add(isoButton);
dfBG.add(simpleTimeButton);
simpleTimeButton.setSelected(true);
dateFormatChangePopup.add(isoButton);
dateFormatChangePopup.add(simpleTimeButton);
final JCheckBoxMenuItem menuItemLoggerTree =
new JCheckBoxMenuItem("Show Logger Tree");
menuItemLoggerTree.addActionListener(
e -> { m_configuration.setProperty("logpanel.logTreePanelVisible",
menuItemLoggerTree.isSelected());});
menuItemLoggerTree.setIcon(new ImageIcon(ChainsawIcons.WINDOW_ICON));
final JCheckBoxMenuItem menuItemToggleDetails =
new JCheckBoxMenuItem("Show Detail Pane");
menuItemToggleDetails.addActionListener(
e -> { m_configuration.setProperty("logpanel.detailColumnVisible",
menuItemToggleDetails.isSelected());});
menuItemToggleDetails.setIcon(new ImageIcon(ChainsawIcons.INFO));
/*
* add preferencemodel listeners
*/
// preferenceModel.addPropertyChangeListener("levelIcons",
// new PropertyChangeListener() {
// public void propertyChange(PropertyChangeEvent evt) {
// boolean useIcons = (Boolean) evt.getNewValue();
// renderer.setLevelUseIcons(useIcons);
// table.tableChanged(new TableModelEvent(tableModel));
// searchRenderer.setLevelUseIcons(useIcons);
// searchTable.tableChanged(new TableModelEvent(searchModel));
// }
// });
/*
* add preferencemodel listeners
*/
m_configuration.addEventListener(ConfigurationEvent.SET_PROPERTY,
new org.apache.commons.configuration2.event.EventListener<ConfigurationEvent>(){
@Override
public void onEvent(ConfigurationEvent evt) {
if( evt.getPropertyName().equals( "logpanel.wrapMessage" ) ){
boolean wrap = (Boolean) evt.getPropertyValue();
renderer.setWrapMessage(wrap);
table.tableChanged(new TableModelEvent(tableModel));
searchRenderer.setWrapMessage(wrap);
searchTable.tableChanged(new TableModelEvent(searchModel));
}
}
} );
m_configuration.addEventListener(ConfigurationEvent.SET_PROPERTY,
new org.apache.commons.configuration2.event.EventListener<ConfigurationEvent>(){
@Override
public void onEvent(ConfigurationEvent evt) {
if( evt.getPropertyName().equals( "logpanel.searchResultsVisible" ) ){
boolean displaySearchResultsInDetailsIfAvailable = (Boolean) evt.getPropertyValue();
if (displaySearchResultsInDetailsIfAvailable) {
showSearchResults();
} else {
hideSearchResults();
}
}
}
} );
m_configuration.addEventListener(ConfigurationEvent.SET_PROPERTY,
new org.apache.commons.configuration2.event.EventListener<ConfigurationEvent>(){
@Override
public void onEvent(ConfigurationEvent evt) {
if( evt.getPropertyName().equals( "logpanel.highlightSearchMatchText" ) ){
boolean highlightText = (Boolean) evt.getPropertyValue();
renderer.setHighlightSearchMatchText(highlightText);
table.tableChanged(new TableModelEvent(tableModel));
searchRenderer.setHighlightSearchMatchText(highlightText);
searchTable.tableChanged(new TableModelEvent(searchModel));
}
}
} );
tabConfig.addEventListener(ConfigurationEvent.SET_PROPERTY,
new org.apache.commons.configuration2.event.EventListener<ConfigurationEvent>(){
@Override
public void onEvent(ConfigurationEvent evt) {
if( evt.getPropertyName().equals( "logpanel.detailColumnVisible" ) ){
boolean detailPaneVisible = (Boolean) evt.getPropertyValue();
if (detailPaneVisible) {
showDetailPane();
} else {
//don't hide the detail pane if search results are being displayed
if (!searchResultsDisplayed) {
hideDetailPane();
}
}
firePropertyChange("detailColumnVisible", !detailPaneVisible, detailPaneVisible);
}
}
} );
tabConfig.addEventListener(ConfigurationEvent.SET_PROPERTY,
new org.apache.commons.configuration2.event.EventListener<ConfigurationEvent>(){
@Override
public void onEvent(ConfigurationEvent evt) {
if( evt.getPropertyName().equals( "logpanel.logTreePanelVisible" ) ){
boolean newValue = (Boolean) evt.getPropertyValue();
if (newValue) {
showLogTreePanel();
} else {
hideLogTreePanel();
}
firePropertyChange("logTreePanelVisible", !newValue, newValue);
}
}
} );
m_configuration.addEventListener(ConfigurationEvent.SET_PROPERTY,
new org.apache.commons.configuration2.event.EventListener<ConfigurationEvent>(){
@Override
public void onEvent(ConfigurationEvent evt) {
if( evt.getPropertyName().equals( "logpanel.toolTips" ) ){
boolean toolTips = (Boolean) evt.getPropertyValue();
renderer.setToolTipsVisible(toolTips);
searchRenderer.setToolTipsVisible(toolTips);
searchToggleToolTips.setSelected(toolTips);
mainToggleToolTips.setSelected(toolTips);
}
}
} );
preferenceModel.addPropertyChangeListener("visibleColumns",
new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
//remove all columns and re-add visible
TableColumnModel columnModel = table.getColumnModel();
while (columnModel.getColumnCount() > 0) {
columnModel.removeColumn(columnModel.getColumn(0));
}
for (Object o1 : preferenceModel.getVisibleColumnOrder()) {
TableColumn c = (TableColumn) o1;
if (c.getHeaderValue().toString().equalsIgnoreCase(ChainsawConstants.LOG4J_MARKER_COL_NAME_LOWERCASE)) {
c.setCellEditor(markerCellEditor);
}
columnModel.addColumn(c);
}
TableColumnModel searchColumnModel = searchTable.getColumnModel();
while (searchColumnModel.getColumnCount() > 0) {
searchColumnModel.removeColumn(searchColumnModel.getColumn(0));
}
for (Object o : preferenceModel.getVisibleColumnOrder()) {
TableColumn c = (TableColumn) o;
searchColumnModel.addColumn(c);
}
}
});
PropertyChangeListener datePrefsChangeListener =
new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
LogPanelPreferenceModel model = (LogPanelPreferenceModel) evt.getSource();
isoButton.setSelected(model.isUseISO8601Format());
simpleTimeButton.setSelected(!model.isUseISO8601Format() && !model.isCustomDateFormat());
if (model.getTimeZone() != null) {
renderer.setTimeZone(model.getTimeZone());
searchRenderer.setTimeZone(model.getTimeZone());
}
if (model.isUseISO8601Format()) {
renderer.setDateFormatter(new SimpleDateFormat(Constants.ISO8601_PATTERN));
searchRenderer.setDateFormatter(new SimpleDateFormat(Constants.ISO8601_PATTERN));
} else {
try {
renderer.setDateFormatter(new SimpleDateFormat(model.getDateFormatPattern()));
} catch (IllegalArgumentException iae) {
model.setDefaultDatePatternFormat();
renderer.setDateFormatter(new SimpleDateFormat(Constants.ISO8601_PATTERN));
}
try {
searchRenderer.setDateFormatter(new SimpleDateFormat(model.getDateFormatPattern()));
} catch (IllegalArgumentException iae) {
model.setDefaultDatePatternFormat();
searchRenderer.setDateFormatter(new SimpleDateFormat(Constants.ISO8601_PATTERN));
}
}
table.tableChanged(new TableModelEvent(tableModel));
searchTable.tableChanged(new TableModelEvent(searchModel));
}
};
preferenceModel.addPropertyChangeListener("dateFormatPattern", datePrefsChangeListener);
preferenceModel.addPropertyChangeListener("dateFormatTimeZone", datePrefsChangeListener);
m_configuration.addEventListener(ConfigurationEvent.SET_PROPERTY,
evt -> {
if( evt.getPropertyName().equals( "logpanel.clearTableExpression" ) ){
LogPanelPreferenceModel model = (LogPanelPreferenceModel) evt.getSource();
String expression = model.getClearTableExpression();
try {
clearTableExpressionRule = ExpressionRule.getRule(expression);
logger.info("clearTableExpressionRule set to: " + expression);
} catch (Exception e) {
logger.info("clearTableExpressionRule invalid - ignoring: " + expression);
clearTableExpressionRule = null;
}
}
});
m_configuration.addEventListener(ConfigurationEvent.SET_PROPERTY,
new org.apache.commons.configuration2.event.EventListener<ConfigurationEvent>(){
@Override
public void onEvent(ConfigurationEvent evt) {
if( evt.getPropertyName().equals( "logpanel.loggerPrecision" ) ){
LogPanelPreferenceModel model = (LogPanelPreferenceModel) evt.getSource();
renderer.setLoggerPrecision(model.getLoggerPrecision());
table.tableChanged(new TableModelEvent(tableModel));
searchRenderer.setLoggerPrecision(model.getLoggerPrecision());
searchTable.tableChanged(new TableModelEvent(searchModel));
}
}
});
tabConfig.addEventListener(ConfigurationEvent.SET_PROPERTY,
evt -> {
if( evt.getPropertyName().equals("logpanel.logTreePanelVisible") ){
boolean value = (Boolean) evt.getPropertyValue();
menuItemLoggerTree.setSelected(value);
}
});
tabConfig.addEventListener(ConfigurationEvent.SET_PROPERTY,
evt -> {
if( evt.getPropertyName().equals("logpanel.detailColumnVisible") ){
boolean value = (Boolean) evt.getPropertyValue();
menuItemToggleDetails.setSelected(value);
}
});
// applicationPreferenceModel.addPropertyChangeListener("searchColor", new PropertyChangeListener() {
// public void propertyChange(PropertyChangeEvent evt) {
// if (table != null) {
// table.repaint();
// }
// if (searchTable != null) {
// searchTable.repaint();
// }
// }
// });
//
// applicationPreferenceModel.addPropertyChangeListener("alternatingColor", new PropertyChangeListener() {
// public void propertyChange(PropertyChangeEvent evt) {
// if (table != null) {
// table.repaint();
// }
// if (searchTable != null) {
// searchTable.repaint();
// }
// }
// });
/*
*End of preferenceModel listeners
*/
tableModel = new ChainsawCyclicBufferTableModel(cyclicBufferSize, colorizer, "main");
table = new JSortTable(tableModel);
markerCellEditor = new MarkerCellEditor();
table.setName("main");
table.setColumnSelectionAllowed(false);
table.setRowSelectionAllowed(true);
searchModel = new ChainsawCyclicBufferTableModel(cyclicBufferSize, colorizer, "search");
searchTable = new JSortTable(searchModel);
searchTable.setName("search");
searchTable.setColumnSelectionAllowed(false);
searchTable.setRowSelectionAllowed(true);
//we've mapped f2, shift f2 and ctrl-f2 to marker-related actions, unmap them from the table
table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke("F2"), "none");
table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_F2, InputEvent.SHIFT_MASK), "none");
table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_F2, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()), "none");
table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_F2, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask() | InputEvent.SHIFT_MASK), "none");
//we're also mapping ctrl-a to scroll-to-top, unmap from the table
table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_A, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()), "none");
searchTable.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke("F2"), "none");
searchTable.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_F2, InputEvent.SHIFT_MASK), "none");
searchTable.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_F2, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()), "none");
searchTable.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_F2, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask() | InputEvent.SHIFT_MASK), "none");
//we're also mapping ctrl-a to scroll-to-top, unmap from the table
searchTable.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_A, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()), "none");
//add a listener to update the 'refine focus'
tableModel.addNewKeyListener(e -> columnNameKeywordMap.put(e.getKey(), "PROP." + e.getKey()));
/*
* Set the Display rule to use the mediator, the model will add itself as
* a property change listener and update itself when the rule changes.
*/
tableModel.setRuleMediator(tableRuleMediator);
searchModel.setRuleMediator(searchRuleMediator);
tableModel.addEventCountListener(
(currentCount, totalCount) -> {
if (LogPanel.this.isVisible()) {
statusBar.setSelectedLine(
table.getSelectedRow() + 1, currentCount, totalCount, getIdentifier());
}
});
tableModel.addEventCountListener(
new EventCountListener() {
final NumberFormat formatter = NumberFormat.getPercentInstance();
boolean warning75 = false;
boolean warning100 = false;
public void eventCountChanged(int currentCount, int totalCount) {
if (preferenceModel.isCyclic()) {
double percent =
((double) totalCount) / tableModel.getMaxSize();
String msg;
boolean wasWarning = warning75 || warning100;
if ((percent > 0.75) && (percent < 1.0) && !warning75) {
msg =
"Warning :: " + formatter.format(percent) + " of the '"
+ getIdentifier() + "' buffer has been used";
warning75 = true;
} else if ((percent >= 1.0) && !warning100) {
msg =
"Warning :: " + formatter.format(percent) + " of the '"
+ getIdentifier()
+ "' buffer has been used. Older events are being discarded.";
warning100 = true;
} else {
//clear msg
msg = "";
warning75 = false;
warning100 = false;
}
if (msg != null && wasWarning) {
statusBar.setMessage(msg);
}
}
}
});
/*
* Logger tree panel
*
*/
LogPanelLoggerTreeModel logTreeModel = new LogPanelLoggerTreeModel();
logTreePanel = new LoggerNameTreePanel(logTreeModel, tabConfig, this, colorizer, filterModel);
logTreePanel.getLoggerVisibilityRule().addPropertyChangeListener(evt -> {
if (evt.getPropertyName().equals("searchExpression")) {
findCombo.setSelectedItem(evt.getNewValue().toString());
findNext();
}
});
logTreePanel.addComponentListener(new ComponentListener() {
@Override
public void componentResized(ComponentEvent ce) {
Dimension dim = ce.getComponent().getSize();
tabConfig.setProperty("logpanel.treeDividerLocation", dim.width);
}
@Override
public void componentMoved(ComponentEvent ce) {}
@Override
public void componentShown(ComponentEvent ce) {}
@Override
public void componentHidden(ComponentEvent ce) {}
});
tableModel.addLoggerNameListener(logTreeModel);
tableModel.addLoggerNameListener(logTreePanel);
/**
* Set the LoggerRule to be the LoggerTreePanel, as this visual component
* is a rule itself, and the RuleMediator will automatically listen when
* it's rule state changes.
*/
tableRuleMediator.setLoggerRule(logTreePanel.getLoggerVisibilityRule());
searchRuleMediator.setLoggerRule(logTreePanel.getLoggerVisibilityRule());
colorizer.setLoggerRule(logTreePanel.getLoggerColorRule());
/*
* Color rule frame and panel
*/
colorFrame.setTitle("'" + identifier + "' color settings");
colorFrame.setIconImage(
((ImageIcon) ChainsawIcons.ICON_PREFERENCES).getImage());
allColorizers.put(identifier, colorizer);
colorPanel = new ColorPanel(m_globalColorizer, filterModel, allColorizers, this);
colorFrame.getContentPane().add(colorPanel);
Action closeColorPanelAction = new AbstractAction() {
public void actionPerformed(ActionEvent e) {
colorPanel.hidePanel();
}
};
colorFrame.getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(escape, "ESCAPE");
colorFrame.getRootPane().
getActionMap().put("ESCAPE", closeColorPanelAction);
colorPanel.setCloseActionListener(
e -> colorFrame.setVisible(false));
colorizer.addPropertyChangeListener(
"colorrule",
new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
for (Object o : tableModel.getAllEvents()) {
LoggingEventWrapper loggingEventWrapper = (LoggingEventWrapper) o;
loggingEventWrapper.updateColorRuleColors(colorizer.getBackgroundColor(loggingEventWrapper.getLoggingEvent()), colorizer.getForegroundColor(loggingEventWrapper.getLoggingEvent()));
}
// no need to update searchmodel events since tablemodel and searchmodel share all events, and color rules aren't different between the two
// if that changes, un-do the color syncing in loggingeventwrapper & re-enable this code
//
// for (Iterator iter = searchModel.getAllEvents().iterator();iter.hasNext();) {
// LoggingEventWrapper loggingEventWrapper = (LoggingEventWrapper)iter.next();
// loggingEventWrapper.updateColorRuleColors(colorizer.getBackgroundColor(loggingEventWrapper.getLoggingEvent()), colorizer.getForegroundColor(loggingEventWrapper.getLoggingEvent()));
// }
colorizedEventAndSearchMatchThumbnail.configureColors();
lowerPanel.revalidate();
lowerPanel.repaint();
searchTable.revalidate();
searchTable.repaint();
}
});
/*
* Table definition. Actual construction is above (next to tablemodel)
*/
table.setRowHeight(ChainsawConstants.DEFAULT_ROW_HEIGHT);
table.setRowMargin(0);
table.getColumnModel().setColumnMargin(0);
table.setShowGrid(false);
table.getColumnModel().addColumnModelListener(new ChainsawTableColumnModelListener(table));
table.setAutoCreateColumnsFromModel(false);
table.addMouseMotionListener(new TableColumnDetailMouseListener(table, tableModel));
table.addMouseListener(new TableMarkerListener(table, tableModel, searchModel));
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
searchTable.setRowHeight(ChainsawConstants.DEFAULT_ROW_HEIGHT);
searchTable.setRowMargin(0);
searchTable.getColumnModel().setColumnMargin(0);
searchTable.setShowGrid(false);
searchTable.getColumnModel().addColumnModelListener(new ChainsawTableColumnModelListener(searchTable));
searchTable.setAutoCreateColumnsFromModel(false);
searchTable.addMouseMotionListener(new TableColumnDetailMouseListener(searchTable, searchModel));
searchTable.addMouseListener(new TableMarkerListener(searchTable, searchModel, tableModel));
searchTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
//set valueisadjusting if holding down a key - don't process setdetail events
table.addKeyListener(
new KeyListener() {
public void keyTyped(KeyEvent e) {
}
public void keyPressed(KeyEvent e) {
synchronized (detail) {
table.getSelectionModel().setValueIsAdjusting(true);
detail.notify();
}
}
public void keyReleased(KeyEvent e) {
synchronized (detail) {
table.getSelectionModel().setValueIsAdjusting(false);
detail.notify();
}
}
});
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
searchTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
table.getSelectionModel().addListSelectionListener(evt -> {
if (((evt.getFirstIndex() == evt.getLastIndex())
&& (evt.getFirstIndex() > 0) && previousLastIndex != -1) || (evt.getValueIsAdjusting())) {
return;
}
boolean lastIndexOnLastRow = (evt.getLastIndex() == (table.getRowCount() - 1));
boolean lastIndexSame = (previousLastIndex == evt.getLastIndex());
/*
* when scroll-to-bottom is active, here is what events look like:
* rowcount-1: 227, last: 227, previous last: 191..first: 191
*
* when the user has unselected the bottom row, here is what the events look like:
* rowcount-1: 227, last: 227, previous last: 227..first: 222
*
* note: previouslast is set after it is evaluated in the bypass scroll check
*/
//System.out.println("rowcount: " + (table.getRowCount() - 1) + ", last: " + evt.getLastIndex() +", previous last: " + previousLastIndex + "..first: " + evt.getFirstIndex() + ", isadjusting: " + evt.getValueIsAdjusting());
boolean disableScrollToBottom = (lastIndexOnLastRow && lastIndexSame && previousLastIndex != evt.getFirstIndex());
if (disableScrollToBottom && isScrollToBottom() && table.getRowCount() > 0) {
preferenceModel.setScrollToBottom(false);
}
previousLastIndex = evt.getLastIndex();
}
);
table.getSelectionModel().addListSelectionListener(
new ListSelectionListener() {
public void valueChanged(ListSelectionEvent evt) {
if (((evt.getFirstIndex() == evt.getLastIndex())
&& (evt.getFirstIndex() > 0) && previousLastIndex != -1) || (evt.getValueIsAdjusting())) {
return;
}
final ListSelectionModel lsm = (ListSelectionModel) evt.getSource();
if (lsm.isSelectionEmpty()) {
if (isVisible()) {
statusBar.setNothingSelected();
}
if (detail.getDocument().getDefaultRootElement() != null) {
detailPaneUpdater.setSelectedRow(-1);
}
} else {
if (table.getSelectedRow() > -1) {
int selectedRow = table.getSelectedRow();
if (isVisible()) {
updateStatusBar();
}
try {
if (tableModel.getRowCount() >= selectedRow) {
detailPaneUpdater.setSelectedRow(table.getSelectedRow());
} else {
detailPaneUpdater.setSelectedRow(-1);
}
} catch (Exception e) {
e.printStackTrace();
detailPaneUpdater.setSelectedRow(-1);
}
}
}
}
});
renderer = new TableColorizingRenderer(colorizer, applicationPreferenceModel, tableModel, preferenceModel, true);
renderer.setToolTipsVisible(preferenceModel.isToolTips());
table.setDefaultRenderer(Object.class, renderer);
searchRenderer = new TableColorizingRenderer(colorizer, applicationPreferenceModel, searchModel, preferenceModel, false);
searchRenderer.setToolTipsVisible(preferenceModel.isToolTips());
searchTable.setDefaultRenderer(Object.class, searchRenderer);
/*
* Throwable popup
*/
table.addMouseListener(new ThrowableDisplayMouseAdapter(table, tableModel));
searchTable.addMouseListener(new ThrowableDisplayMouseAdapter(searchTable, searchModel));
//select a row in the main table when a row in the search table is selected
searchTable.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
LoggingEventWrapper loggingEventWrapper = searchModel.getRow(searchTable.getSelectedRow());
if (loggingEventWrapper != null) {
int id = Integer.parseInt(loggingEventWrapper.getLoggingEvent().getProperty("log4jid"));
//preserve the table's viewble column
setSelectedEvent(id);
}
}
});
/*
* We listen for new Key's coming in so we can get them automatically
* added as columns
*/
tableModel.addNewKeyListener(
e -> SwingHelper.invokeOnEDT(() -> {
// don't add the column if we already know about it, this could be if we've seen it before and saved the column preferences
//this may throw an illegalargexception - ignore it because we need to add only if not already added
//if the column is already added, don't add again
try {
if (table.getColumn(e.getKey()) != null) {
return;
}
//no need to check search table - we use the same columns
} catch (IllegalArgumentException iae) {
}
TableColumn col = new TableColumn(e.getNewModelIndex());
col.setHeaderValue(e.getKey());
if (preferenceModel.addColumn(col)) {
if (preferenceModel.isColumnVisible(col) || !applicationPreferenceModel.isDefaultColumnsSet() || applicationPreferenceModel.isDefaultColumnsSet() &&
applicationPreferenceModel.getDefaultColumnNames().contains(col.getHeaderValue())) {
table.addColumn(col);
searchTable.addColumn(col);
preferenceModel.setColumnVisible(e.getKey().toString(), true);
}
}
}));
//if the table is refiltered, try to reselect the last selected row
//refilter with a newValue of TRUE means refiltering is about to begin
//refilter with a newValue of FALSE means refiltering is complete
//assuming notification is called on the EDT so we can in the current EDT call update the scroll & selection
tableModel.addPropertyChangeListener("refilter", new PropertyChangeListener() {
private LoggingEventWrapper currentEvent;
public void propertyChange(PropertyChangeEvent evt) {
//if new value is true, filtering is about to begin
//if new value is false, filtering is complete
if (evt.getNewValue().equals(Boolean.TRUE)) {
int currentRow = table.getSelectedRow();
if (currentRow > -1) {
currentEvent = tableModel.getRow(currentRow);
}
} else {
if (currentEvent != null) {
table.scrollToRow(tableModel.getRowIndex(currentEvent));
}
}
}
});
table.getTableHeader().addMouseListener(
new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
checkEvent(e);
}
public void mousePressed(MouseEvent e) {
checkEvent(e);
}
public void mouseReleased(MouseEvent e) {
checkEvent(e);
}
private void checkEvent(MouseEvent e) {
if (e.isPopupTrigger()) {
TableColumnModel colModel = table.getColumnModel();
int index = colModel.getColumnIndexAtX(e.getX());
int modelIndex = colModel.getColumn(index).getModelIndex();
if ((modelIndex + 1) == ChainsawColumns.INDEX_TIMESTAMP_COL_NAME) {
dateFormatChangePopup.show(e.getComponent(), e.getX(), e.getY());
}
}
}
});
/*
* Upper panel definition
*/
JPanel upperPanel = new JPanel();
upperPanel.setLayout(new BoxLayout(upperPanel, BoxLayout.X_AXIS));
upperPanel.setBorder(BorderFactory.createEmptyBorder(2, 5, 2, 0));
final JLabel filterLabel = new JLabel("Refine focus on: ");
filterLabel.setFont(filterLabel.getFont().deriveFont(Font.BOLD));
upperPanel.add(filterLabel);
upperPanel.add(Box.createHorizontalStrut(3));
upperPanel.add(filterCombo);
upperPanel.add(Box.createHorizontalStrut(3));
final JTextField filterText = (JTextField) filterCombo.getEditor().getEditorComponent();
final JTextField findText = (JTextField) findCombo.getEditor().getEditorComponent();
//Adding a button to clear filter expressions which are currently remembered by Chainsaw...
final JButton removeFilterButton = new JButton(" Remove ");
removeFilterButton.setToolTipText("Click here to remove the selected expression from the list");
removeFilterButton.addActionListener(
new AbstractAction() {
public void actionPerformed(ActionEvent e) {
Object selectedItem = filterCombo.getSelectedItem();
if (e.getSource() == removeFilterButton && selectedItem != null && !selectedItem.toString().trim().equals("")) {
//don't just remove the entry from the store, clear the field
int index = filterCombo.getSelectedIndex();
filterText.setText(null);
filterCombo.setSelectedIndex(-1);
filterCombo.removeItemAt(index);
if (!(findCombo.getSelectedItem() != null && findCombo.getSelectedItem().equals(selectedItem))) {
//now remove the entry from the other model
((AutoFilterComboBox.AutoFilterComboBoxModel) findCombo.getModel()).removeElement(selectedItem);
}
}
}
}
);
upperPanel.add(removeFilterButton);
//add some space between refine focus and search sections of the panel
upperPanel.add(Box.createHorizontalStrut(25));
final JLabel findLabel = new JLabel("Find: ");
findLabel.setFont(filterLabel.getFont().deriveFont(Font.BOLD));
upperPanel.add(findLabel);
upperPanel.add(Box.createHorizontalStrut(3));
upperPanel.add(findCombo);
upperPanel.add(Box.createHorizontalStrut(3));
Action findNextAction = getFindNextAction();
Action findPreviousAction = getFindPreviousAction();
//add up & down search
JButton findNextButton = new SmallButton(findNextAction);
findNextButton.setText("");
findNextButton.getActionMap().put(
findNextAction.getValue(Action.NAME), findNextAction);
findNextButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
(KeyStroke) findNextAction.getValue(Action.ACCELERATOR_KEY),
findNextAction.getValue(Action.NAME));
JButton findPreviousButton = new SmallButton(findPreviousAction);
findPreviousButton.setText("");
findPreviousButton.getActionMap().put(
findPreviousAction.getValue(Action.NAME), findPreviousAction);
findPreviousButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
(KeyStroke) findPreviousAction.getValue(Action.ACCELERATOR_KEY),
findPreviousAction.getValue(Action.NAME));
upperPanel.add(findNextButton);
upperPanel.add(findPreviousButton);
upperPanel.add(Box.createHorizontalStrut(3));
//Adding a button to clear filter expressions which are currently remembered by Chainsaw...
final JButton removeFindButton = new JButton(" Remove ");
removeFindButton.setToolTipText("Click here to remove the selected expression from the list");
removeFindButton.addActionListener(
new AbstractAction() {
public void actionPerformed(ActionEvent e) {
Object selectedItem = findCombo.getSelectedItem();
if (e.getSource() == removeFindButton && selectedItem != null && !selectedItem.toString().trim().equals("")) {
//don't just remove the entry from the store, clear the field
int index = findCombo.getSelectedIndex();
findText.setText(null);
findCombo.setSelectedIndex(-1);
findCombo.removeItemAt(index);
if (!(filterCombo.getSelectedItem() != null && filterCombo.getSelectedItem().equals(selectedItem))) {
//now remove the entry from the other model if it wasn't selected
((AutoFilterComboBox.AutoFilterComboBoxModel) filterCombo.getModel()).removeElement(selectedItem);
}
}
}
}
);
upperPanel.add(removeFindButton);
//define search and refine focus selection and clear actions
Action findFocusAction = new AbstractAction() {
public void actionPerformed(ActionEvent actionEvent) {
findCombo.requestFocus();
}
};
Action filterFocusAction = new AbstractAction() {
public void actionPerformed(ActionEvent actionEvent) {
filterCombo.requestFocus();
}
};
Action findClearAction = new AbstractAction() {
public void actionPerformed(ActionEvent actionEvent) {
findCombo.setSelectedIndex(-1);
findNext();
}
};
Action filterClearAction = new AbstractAction() {
public void actionPerformed(ActionEvent actionEvent) {
setRefineFocusText("");
filterCombo.refilter();
}
};
//now add them to the action and input maps for the logpanel
KeyStroke ksFindFocus =
KeyStroke.getKeyStroke(KeyEvent.VK_F, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask());
KeyStroke ksFilterFocus =
KeyStroke.getKeyStroke(KeyEvent.VK_R, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask());
KeyStroke ksFindClear =
KeyStroke.getKeyStroke(KeyEvent.VK_F, InputEvent.SHIFT_MASK | Toolkit.getDefaultToolkit().getMenuShortcutKeyMask());
KeyStroke ksFilterClear =
KeyStroke.getKeyStroke(KeyEvent.VK_R, InputEvent.SHIFT_MASK | Toolkit.getDefaultToolkit().getMenuShortcutKeyMask());
getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(ksFindFocus, "FindFocus");
getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(ksFilterFocus, "FilterFocus");
getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(ksFindClear, "FindClear");
getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(ksFilterClear, "FilterClear");
getActionMap().put("FindFocus", findFocusAction);
getActionMap().put("FilterFocus", filterFocusAction);
getActionMap().put("FindClear", findClearAction);
getActionMap().put("FilterClear", filterClearAction);
/*
* Detail pane definition
*/
detail = new JEditorPane(ChainsawConstants.DETAIL_CONTENT_TYPE, "");
detail.setEditable(false);
detailPaneUpdater = new DetailPaneUpdater();
//if the panel gets focus, update the detail pane
addFocusListener(new FocusListener() {
public void focusGained(FocusEvent e) {
detailPaneUpdater.updateDetailPane();
}
public void focusLost(FocusEvent e) {
}
});
findMarkerRule = ExpressionRule.getRule("prop." + ChainsawConstants.LOG4J_MARKER_COL_NAME_LOWERCASE + " exists");
tableModel.addTableModelListener(e -> {
int currentRow = table.getSelectedRow();
if (e.getFirstRow() <= currentRow && e.getLastRow() >= currentRow) {
//current row has changed - update
detailPaneUpdater.setAndUpdateSelectedRow(table.getSelectedRow());
}
});
addPropertyChangeListener("detailPaneConversionPattern", detailPaneUpdater);
addPropertyChangeListener("detailPaneDatetimeFormat", detailPaneUpdater);
searchPane = new JScrollPane(searchTable);
searchPane.getVerticalScrollBar().setUnitIncrement(ChainsawConstants.DEFAULT_ROW_HEIGHT * 2);
searchPane.setPreferredSize(new Dimension(900, 50));
//default detail panel to contain detail panel - if searchResultsVisible is true, when a search if triggered, update detail pane to contain search results
detailPane = new JScrollPane(detail);
detailPane.setPreferredSize(new Dimension(900, 50));
detailPanel.add(detailPane, BorderLayout.CENTER);
JPanel eventsAndStatusPanel = new JPanel(new BorderLayout());
eventsPane = new JScrollPane(table);
eventsPane.getVerticalScrollBar().setUnitIncrement(ChainsawConstants.DEFAULT_ROW_HEIGHT * 2);
eventsAndStatusPanel.add(eventsPane, BorderLayout.CENTER);
Integer scrollBarWidth = (Integer) UIManager.get("ScrollBar.width");
JPanel rightPanel = new JPanel();
rightPanel.setLayout(new BoxLayout(rightPanel, BoxLayout.Y_AXIS));
JPanel rightThumbNailPanel = new JPanel();
rightThumbNailPanel.setLayout(new BoxLayout(rightThumbNailPanel, BoxLayout.Y_AXIS));
rightThumbNailPanel.add(Box.createVerticalStrut(scrollBarWidth));
colorizedEventAndSearchMatchThumbnail = new ColorizedEventAndSearchMatchThumbnail();
rightThumbNailPanel.add(colorizedEventAndSearchMatchThumbnail);
rightThumbNailPanel.add(Box.createVerticalStrut(scrollBarWidth));
rightPanel.add(rightThumbNailPanel);
//set thumbnail width to be a bit narrower than scrollbar width
if (scrollBarWidth != null) {
rightThumbNailPanel.setPreferredSize(new Dimension(scrollBarWidth - 4, -1));
}
eventsAndStatusPanel.add(rightPanel, BorderLayout.EAST);
JPanel leftPanel = new JPanel();
leftPanel.setLayout(new BoxLayout(leftPanel, BoxLayout.Y_AXIS));
JPanel leftThumbNailPanel = new JPanel();
leftThumbNailPanel.setLayout(new BoxLayout(leftThumbNailPanel, BoxLayout.Y_AXIS));
leftThumbNailPanel.add(Box.createVerticalStrut(scrollBarWidth));
eventTimeDeltaMatchThumbnail = new EventTimeDeltaMatchThumbnail();
leftThumbNailPanel.add(eventTimeDeltaMatchThumbnail);
leftThumbNailPanel.add(Box.createVerticalStrut(scrollBarWidth));
leftPanel.add(leftThumbNailPanel);
//set thumbnail width to be a bit narrower than scrollbar width
if (scrollBarWidth != null) {
leftThumbNailPanel.setPreferredSize(new Dimension(scrollBarWidth - 4, -1));
}
eventsAndStatusPanel.add(leftPanel, BorderLayout.WEST);
final JPanel statusLabelPanel = new JPanel();
statusLabelPanel.setLayout(new BorderLayout());
statusLabelPanel.add(upperPanel, BorderLayout.CENTER);
eventsAndStatusPanel.add(statusLabelPanel, BorderLayout.NORTH);
/*
* Detail panel layout editor
*/
detailToolbar = new JToolBar(SwingConstants.HORIZONTAL);
detailToolbar.setFloatable(false);
final LayoutEditorPane layoutEditorPane = new LayoutEditorPane();
final JDialog layoutEditorDialog =
new JDialog((JFrame) null, "Pattern Editor");
layoutEditorDialog.getContentPane().add(layoutEditorPane);
layoutEditorDialog.setSize(640, 480);
layoutEditorPane.addCancelActionListener(
e -> layoutEditorDialog.setVisible(false));
layoutEditorPane.addOkActionListener(
e -> {
setDetailPaneConversionPattern(
layoutEditorPane.getConversionPattern());
setDetailPaneDatetimeFormat(layoutEditorPane.getDatetimeFormatter());
layoutEditorDialog.setVisible(false);
});
Action copyToRefineFocusAction = new AbstractAction("Set 'refine focus' field") {
public void actionPerformed(ActionEvent e) {
String selectedText = detail.getSelectedText();
if (selectedText == null || selectedText.equals("")) {
//no-op empty searches
return;
}
filterText.setText("msg ~= '" + selectedText + "'");
}
};
Action copyToSearchAction = new AbstractAction("Find next") {
public void actionPerformed(ActionEvent e) {
String selectedText = detail.getSelectedText();
if (selectedText == null || selectedText.equals("")) {
//no-op empty searches
return;
}
findCombo.setSelectedItem("msg ~= '" + selectedText + "'");
findNext();
}
};
Action editDetailAction =
new AbstractAction(
"Edit...", new ImageIcon(ChainsawIcons.ICON_EDIT_RECEIVER)) {
public void actionPerformed(ActionEvent e) {
layoutEditorPane.setConversionPattern(
getDetailPaneConversionPattern());
layoutEditorPane.setDatetimeFormatter(getDetailPaneDatetimeFormat());
Dimension size = Toolkit.getDefaultToolkit().getScreenSize();
Point p =
new Point(
((int) ((size.getWidth() / 2)
- (layoutEditorDialog.getSize().getWidth() / 2))),
((int) ((size.getHeight() / 2)
- (layoutEditorDialog.getSize().getHeight() / 2))));
layoutEditorDialog.setLocation(p);
layoutEditorDialog.setVisible(true);
}
};
editDetailAction.putValue(
Action.SHORT_DESCRIPTION,
"opens a Dialog window to Edit the Pattern Layout text");
final SmallButton editDetailButton = new SmallButton(editDetailAction);
editDetailButton.setText(null);
detailToolbar.add(Box.createHorizontalGlue());
detailToolbar.add(editDetailButton);
detailToolbar.addSeparator();
detailToolbar.add(Box.createHorizontalStrut(5));
Action closeDetailAction =
new AbstractAction(null, LineIconFactory.createCloseIcon()) {
public void actionPerformed(ActionEvent arg0) {
tabConfig.setProperty("logpanel.detailColumnVisible", false);
}
};
closeDetailAction.putValue(
Action.SHORT_DESCRIPTION, "Hides the Detail Panel");
SmallButton closeDetailButton = new SmallButton(closeDetailAction);
detailToolbar.add(closeDetailButton);
detailPanel.add(detailToolbar, BorderLayout.NORTH);
lowerPanel = new JSplitPane(JSplitPane.VERTICAL_SPLIT, eventsAndStatusPanel, detailPanel);
dividerSize = lowerPanel.getDividerSize();
lowerPanel.setDividerLocation(-1);
lowerPanel.setResizeWeight(1.0);
lowerPanel.setBorder(null);
lowerPanel.setContinuousLayout(true);
JPopupMenu editDetailPopupMenu = new JPopupMenu();
editDetailPopupMenu.add(copyToRefineFocusAction);
editDetailPopupMenu.add(copyToSearchAction);
editDetailPopupMenu.addSeparator();
editDetailPopupMenu.add(editDetailAction);
editDetailPopupMenu.addSeparator();
final ButtonGroup layoutGroup = new ButtonGroup();
JRadioButtonMenuItem defaultLayoutRadio =
new JRadioButtonMenuItem(
new AbstractAction("Set to Default Layout") {
public void actionPerformed(ActionEvent e) {
setDetailPaneConversionPattern(
DefaultLayoutFactory.getDefaultPatternLayout());
}
});
JRadioButtonMenuItem fullLayoutRadio =
new JRadioButtonMenuItem(
new AbstractAction("Set to Full Layout") {
public void actionPerformed(ActionEvent e) {
setDetailPaneConversionPattern(
DefaultLayoutFactory.getFullPatternLayout());
}
});
editDetailPopupMenu.add(defaultLayoutRadio);
editDetailPopupMenu.add(fullLayoutRadio);
layoutGroup.add(defaultLayoutRadio);
layoutGroup.add(fullLayoutRadio);
defaultLayoutRadio.setSelected(true);
JRadioButtonMenuItem tccLayoutRadio =
new JRadioButtonMenuItem(
new AbstractAction("Set to TCCLayout") {
public void actionPerformed(ActionEvent e) {
// setDetailPaneConversionPattern(
// PatternLayout.TTCC_CONVERSION_PATTERN);
}
});
editDetailPopupMenu.add(tccLayoutRadio);
layoutGroup.add(tccLayoutRadio);
PopupListener editDetailPopupListener =
new PopupListener(editDetailPopupMenu);
detail.addMouseListener(editDetailPopupListener);
/*
* Logger tree splitpane definition
*/
nameTreeAndMainPanelSplit = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, logTreePanel, lowerPanel);
nameTreeAndMainPanelSplit.setDividerLocation(-1);
add(nameTreeAndMainPanelSplit, BorderLayout.CENTER);
if (isLogTreeVisible()) {
showLogTreePanel();
} else {
hideLogTreePanel();
}
/*
* Other menu items
*/
class BestFit extends JMenuItem {
public BestFit() {
super("Best fit column");
addActionListener(
evt -> {
if (currentPoint != null) {
int column = currentTable.columnAtPoint(currentPoint);
int maxWidth = getMaxColumnWidth(column);
currentTable.getColumnModel().getColumn(column).setPreferredWidth(
maxWidth);
}
});
}
}
class ColorPanel extends JMenuItem {
public ColorPanel() {
super("Color settings...");
setIcon(ChainsawIcons.ICON_PREFERENCES);
addActionListener(
evt -> showColorPreferences());
}
}
class LogPanelPreferences extends JMenuItem {
public LogPanelPreferences() {
super("Tab Preferences...");
setIcon(ChainsawIcons.ICON_PREFERENCES);
addActionListener(
evt -> showPreferences());
}
}
class FocusOn extends JMenuItem {
public FocusOn() {
super("Set 'refine focus' field to value under pointer");
addActionListener(
evt -> {
if (currentPoint != null) {
String operator = "==";
int column = currentTable.columnAtPoint(currentPoint);
int row = currentTable.rowAtPoint(currentPoint);
String colName = currentTable.getColumnName(column).toUpperCase();
String value = getValueOf(row, column);
if (columnNameKeywordMap.containsKey(colName)) {
filterText.setText(
columnNameKeywordMap.get(colName).toString() + " " + operator
+ " '" + value + "'");
}
}
});
}
}
class DefineAddCustomFilter extends JMenuItem {
public DefineAddCustomFilter() {
super("Add value under pointer to 'refine focus' field");
addActionListener(
evt -> {
if (currentPoint != null) {
String operator = "==";
int column = currentTable.columnAtPoint(currentPoint);
int row = currentTable.rowAtPoint(currentPoint);
String value = getValueOf(row, column);
String colName = currentTable.getColumnName(column).toUpperCase();
if (columnNameKeywordMap.containsKey(colName)) {
filterText.setText(
filterText.getText() + " && "
+ columnNameKeywordMap.get(colName).toString() + " "
+ operator + " '" + value + "'");
}
}
});
}
}
class DefineAddCustomFind extends JMenuItem {
public DefineAddCustomFind() {
super("Add value under pointer to 'find' field");
addActionListener(
evt -> {
if (currentPoint != null) {
String operator = "==";
int column = currentTable.columnAtPoint(currentPoint);
int row = currentTable.rowAtPoint(currentPoint);
String value = getValueOf(row, column);
String colName = currentTable.getColumnName(column).toUpperCase();
if (columnNameKeywordMap.containsKey(colName)) {
findCombo.setSelectedItem(
findText.getText() + " && "
+ columnNameKeywordMap.get(colName).toString() + " "
+ operator + " '" + value + "'");
findNext();
}
}
});
}
}
class BuildColorRule extends JMenuItem {
public BuildColorRule() {
super("Define color rule for value under pointer");
addActionListener(
evt -> {
if (currentPoint != null) {
String operator = "==";
int column = currentTable.columnAtPoint(currentPoint);
int row = currentTable.rowAtPoint(currentPoint);
String colName = currentTable.getColumnName(column).toUpperCase();
String value = getValueOf(row, column);
if (columnNameKeywordMap.containsKey(colName)) {
Color c = JColorChooser.showDialog(getRootPane(), "Choose a color", Color.red);
if (c != null) {
String expression = columnNameKeywordMap.get(colName).toString() + " " + operator + " '" + value + "'";
colorizer.addRule(new ColorRule(expression,
ExpressionRule.getRule(expression), c, ChainsawConstants.COLOR_DEFAULT_FOREGROUND));
}
}
}
});
}
}
final JPopupMenu mainPopup = new JPopupMenu();
final JPopupMenu searchPopup = new JPopupMenu();
class ClearFocus extends AbstractAction {
public ClearFocus() {
super("Clear 'refine focus' field");
}
public void actionPerformed(ActionEvent e) {
filterText.setText(null);
tableRuleMediator.setFilterRule(null);
searchRuleMediator.setFilterRule(null);
}
}
class CopySelection extends AbstractAction {
public CopySelection() {
super("Copy selection to clipboard");
}
public void actionPerformed(ActionEvent e) {
if (currentTable == null) {
return;
}
int start = currentTable.getSelectionModel().getMinSelectionIndex();
int end = currentTable.getSelectionModel().getMaxSelectionIndex();
StringBuilder result = new StringBuilder();
for (int row = start; row < end + 1; row++) {
for (int column = 0; column < currentTable.getColumnCount(); column++) {
result.append(getValueOf(row, column));
if (column != (currentTable.getColumnCount() - 1)) {
result.append(" - ");
}
}
result.append(System.getProperty("line.separator"));
}
StringSelection selection = new StringSelection(result.toString());
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
clipboard.setContents(selection, null);
}
}
class CopyField extends AbstractAction {
public CopyField() {
super("Copy value under pointer to clipboard");
}
public void actionPerformed(ActionEvent e) {
if (currentPoint != null && currentTable != null) {
int column = currentTable.columnAtPoint(currentPoint);
int row = currentTable.rowAtPoint(currentPoint);
String value = getValueOf(row, column);
StringSelection selection = new StringSelection(value);
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
clipboard.setContents(selection, null);
}
}
}
final JMenuItem menuItemToggleDock = new JMenuItem("Undock/dock");
dockingAction =
new AbstractAction("Undock") {
public void actionPerformed(ActionEvent evt) {
if (isDocked()) {
undock();
} else {
dock();
}
}
};
dockingAction.putValue(
Action.SMALL_ICON, new ImageIcon(ChainsawIcons.UNDOCK));
menuItemToggleDock.setAction(dockingAction);
/*
* Popup definition
*/
mainPopup.add(new FocusOn());
searchPopup.add(new FocusOn());
mainPopup.add(new DefineAddCustomFilter());
searchPopup.add(new DefineAddCustomFilter());
mainPopup.add(new ClearFocus());
searchPopup.add(new ClearFocus());
mainPopup.add(new JSeparator());
searchPopup.add(new JSeparator());
class Search extends JMenuItem {
public Search() {
super("Find value under pointer");
addActionListener(
evt -> {
if (currentPoint != null) {
String operator = "==";
int column = currentTable.columnAtPoint(currentPoint);
int row = currentTable.rowAtPoint(currentPoint);
String colName = currentTable.getColumnName(column).toUpperCase();
String value = getValueOf(row, column);
if (columnNameKeywordMap.containsKey(colName)) {
findCombo.setSelectedItem(
columnNameKeywordMap.get(colName).toString() + " " + operator
+ " '" + value + "'");
findNext();
}
}
});
}
}
class ClearSearch extends AbstractAction {
public ClearSearch() {
super("Clear find field");
}
public void actionPerformed(ActionEvent e) {
findCombo.setSelectedItem(null);
updateFindRule(null);
}
}
mainPopup.add(new Search());
searchPopup.add(new Search());
mainPopup.add(new DefineAddCustomFind());
searchPopup.add(new DefineAddCustomFind());
mainPopup.add(new ClearSearch());
searchPopup.add(new ClearSearch());
mainPopup.add(new JSeparator());
searchPopup.add(new JSeparator());
class DisplayNormalTimes extends JMenuItem {
public DisplayNormalTimes() {
super("Hide relative times");
addActionListener(
e -> {
if (currentPoint != null) {
((TableColorizingRenderer) currentTable.getDefaultRenderer(Object.class)).setUseNormalTimes();
((ChainsawCyclicBufferTableModel) currentTable.getModel()).reFilter();
setEnabled(true);
}
});
}
}
class DisplayRelativeTimesToRowUnderCursor extends JMenuItem {
public DisplayRelativeTimesToRowUnderCursor() {
super("Show times relative to this event");
addActionListener(
e -> {
if (currentPoint != null) {
int row = currentTable.rowAtPoint(currentPoint);
ChainsawCyclicBufferTableModel cyclicBufferTableModel = (ChainsawCyclicBufferTableModel) currentTable.getModel();
LoggingEventWrapper loggingEventWrapper = cyclicBufferTableModel.getRow(row);
if (loggingEventWrapper != null) {
((TableColorizingRenderer) currentTable.getDefaultRenderer(Object.class)).setUseRelativeTimes(loggingEventWrapper.getLoggingEvent().m_timestamp.atZone(ZoneId.systemDefault()));
cyclicBufferTableModel.reFilter();
}
setEnabled(true);
}
});
}
}
class DisplayRelativeTimesToPreviousRow extends JMenuItem {
public DisplayRelativeTimesToPreviousRow() {
super("Show times relative to previous rows");
addActionListener(
e -> {
if (currentPoint != null) {
((TableColorizingRenderer) currentTable.getDefaultRenderer(Object.class)).setUseRelativeTimesToPreviousRow();
((ChainsawCyclicBufferTableModel) currentTable.getModel()).reFilter();
setEnabled(true);
}
});
}
}
mainPopup.add(new DisplayRelativeTimesToRowUnderCursor());
searchPopup.add(new DisplayRelativeTimesToRowUnderCursor());
mainPopup.add(new DisplayRelativeTimesToPreviousRow());
searchPopup.add(new DisplayRelativeTimesToPreviousRow());
mainPopup.add(new DisplayNormalTimes());
searchPopup.add(new DisplayNormalTimes());
mainPopup.add(new JSeparator());
searchPopup.add(new JSeparator());
mainPopup.add(new BuildColorRule());
searchPopup.add(new BuildColorRule());
mainPopup.add(new JSeparator());
searchPopup.add(new JSeparator());
mainPopup.add(new CopyField());
mainPopup.add(new CopySelection());
searchPopup.add(new CopyField());
searchPopup.add(new CopySelection());
mainPopup.add(new JSeparator());
searchPopup.add(new JSeparator());
mainPopup.add(menuItemToggleDetails);
mainPopup.add(menuItemLoggerTree);
mainToggleToolTips = new ToggleToolTips();
searchToggleToolTips = new ToggleToolTips();
mainPopup.add(mainToggleToolTips);
searchPopup.add(searchToggleToolTips);
mainPopup.add(new JSeparator());
mainPopup.add(menuItemToggleDock);
mainPopup.add(new BestFit());
searchPopup.add(new BestFit());
mainPopup.add(new JSeparator());
mainPopup.add(new ColorPanel());
searchPopup.add(new ColorPanel());
mainPopup.add(new LogPanelPreferences());
searchPopup.add(new LogPanelPreferences());
final PopupListener mainTablePopupListener = new PopupListener(mainPopup);
eventsPane.addMouseListener(mainTablePopupListener);
table.addMouseListener(mainTablePopupListener);
table.addMouseListener(new MouseListener() {
public void mouseClicked(MouseEvent mouseEvent) {
checkMultiSelect(mouseEvent);
}
public void mousePressed(MouseEvent mouseEvent) {
checkMultiSelect(mouseEvent);
}
public void mouseReleased(MouseEvent mouseEvent) {
checkMultiSelect(mouseEvent);
}
public void mouseEntered(MouseEvent mouseEvent) {
checkMultiSelect(mouseEvent);
}
public void mouseExited(MouseEvent mouseEvent) {
checkMultiSelect(mouseEvent);
}
private void checkMultiSelect(MouseEvent mouseEvent) {
if (mouseEvent.isAltDown()) {
table.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
} else {
table.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
}
}
});
searchTable.addMouseListener(new MouseListener() {
public void mouseClicked(MouseEvent mouseEvent) {
checkMultiSelect(mouseEvent);
}
public void mousePressed(MouseEvent mouseEvent) {
checkMultiSelect(mouseEvent);
}
public void mouseReleased(MouseEvent mouseEvent) {
checkMultiSelect(mouseEvent);
}
public void mouseEntered(MouseEvent mouseEvent) {
checkMultiSelect(mouseEvent);
}
public void mouseExited(MouseEvent mouseEvent) {
checkMultiSelect(mouseEvent);
}
private void checkMultiSelect(MouseEvent mouseEvent) {
if (mouseEvent.isAltDown()) {
searchTable.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
} else {
searchTable.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
}
}
});
final PopupListener searchTablePopupListener = new PopupListener(searchPopup);
searchPane.addMouseListener(searchTablePopupListener);
searchTable.addMouseListener(searchTablePopupListener);
loadSettings();
}