Java tutorial
/* * Copyright 2012 Krzysztof Otrebski * * Licensed 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 pl.otros.logview.gui; import net.miginfocom.swing.MigLayout; import org.apache.commons.configuration.AbstractConfiguration; import org.apache.commons.configuration.DataConfiguration; import org.apache.commons.configuration.event.ConfigurationEvent; import org.apache.commons.configuration.event.ConfigurationListener; import org.apache.commons.configuration.event.EventSource; import org.jdesktop.swingx.JXComboBox; import org.jdesktop.swingx.JXTable; import org.jdesktop.swingx.autocomplete.AutoCompleteDecorator; import org.jdesktop.swingx.table.ColumnControlButton; import pl.otros.logview.LogData; import pl.otros.logview.LogDataCollector; import pl.otros.logview.MarkerColors; import pl.otros.logview.Note; import pl.otros.logview.accept.AcceptCondition; import pl.otros.logview.accept.FilteredAcceptCondition; import pl.otros.logview.accept.HigherIdAcceptCondition; import pl.otros.logview.accept.LevelLowerAcceptCondition; import pl.otros.logview.accept.LowerIdAcceptCondition; import pl.otros.logview.accept.PropertyAcceptCondition; import pl.otros.logview.accept.SelectedClassAcceptCondition; import pl.otros.logview.accept.SelectedEventsAcceptCondition; import pl.otros.logview.accept.SelectedThreadAcceptCondition; import pl.otros.logview.api.plugins.MenuActionProvider; import pl.otros.logview.filter.CallHierarchyLogFilter; import pl.otros.logview.filter.ClassFilter; import pl.otros.logview.filter.FilterPanel; import pl.otros.logview.filter.LogFilter; import pl.otros.logview.filter.LogFilterValueChangeListener; import pl.otros.logview.filter.LoggerNameFilter; import pl.otros.logview.filter.PropertyFilter; import pl.otros.logview.filter.ThreadFilter; import pl.otros.logview.filter.TimeFilter; import pl.otros.logview.gui.actions.AutomaticMarkUnamrkActionListener; import pl.otros.logview.gui.actions.ClearMarkingsAction; import pl.otros.logview.gui.actions.CopySelectedText; import pl.otros.logview.gui.actions.CopyStyledMessageDetailAction; import pl.otros.logview.gui.actions.FocusOnEventsAfter; import pl.otros.logview.gui.actions.FocusOnEventsBefore; import pl.otros.logview.gui.actions.FocusOnSelectedClassesAction; import pl.otros.logview.gui.actions.FocusOnSelectedLoggerNameAction; import pl.otros.logview.gui.actions.FocusOnSelectedPropertyAction; import pl.otros.logview.gui.actions.FocusOnThisThreadAction; import pl.otros.logview.gui.actions.IgnoreSelectedEventsClasses; import pl.otros.logview.gui.actions.MarkRowAction; import pl.otros.logview.gui.actions.OtrosAction; import pl.otros.logview.gui.actions.RemoveByAcceptanceCriteria; import pl.otros.logview.gui.actions.ShowCallHierarchyAction; import pl.otros.logview.gui.actions.TableResizeActionListener; import pl.otros.logview.gui.actions.UnMarkRowAction; import pl.otros.logview.gui.actions.table.MarkRowBySpaceKeyListener; import pl.otros.logview.gui.config.LogTableFormatConfigView; import pl.otros.logview.gui.markers.AutomaticMarker; import pl.otros.logview.gui.message.LocationInfo; import pl.otros.logview.gui.message.MessageColorizer; import pl.otros.logview.gui.message.MessageFormatter; import pl.otros.logview.gui.message.update.MessageDetailListener; import pl.otros.logview.gui.note.NoteEvent; import pl.otros.logview.gui.note.NoteEvent.EventType; import pl.otros.logview.gui.note.NoteObserver; import pl.otros.logview.gui.renderers.DateRenderer; import pl.otros.logview.gui.renderers.LevelRenderer; import pl.otros.logview.gui.renderers.MarkTableEditor; import pl.otros.logview.gui.renderers.MarkTableRenderer; import pl.otros.logview.gui.renderers.NoteRenderer; import pl.otros.logview.gui.renderers.NoteTableEditor; import pl.otros.logview.gui.renderers.Renderers; import pl.otros.logview.gui.renderers.TableMarkDecoratorRenderer; import pl.otros.logview.gui.renderers.TimeDeltaRenderer; import pl.otros.logview.gui.services.jumptocode.JumpToCodeService; import pl.otros.logview.gui.table.JTableWith2RowHighliting; import pl.otros.logview.gui.table.TableColumns; import pl.otros.logview.pluginable.AllPluginables; import pl.otros.logview.pluginable.PluginableElement; import pl.otros.logview.pluginable.PluginableElementEventListener; import pl.otros.logview.pluginable.PluginableElementNameComparator; import pl.otros.logview.pluginable.PluginableElementsContainer; import pl.otros.logview.pluginable.SynchronizePluginableContainerListener; import pl.otros.swing.rulerbar.OtrosJTextWithRulerScrollPane; import pl.otros.swing.rulerbar.RulerBarHelper; import pl.otros.swing.table.ColumnLayout; import pl.otros.vfs.browser.table.FileSize; import javax.swing.*; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import javax.swing.table.TableColumn; import javax.swing.table.TableRowSorter; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.TreeSet; import java.util.concurrent.Callable; import java.util.logging.Level; import java.util.logging.Logger; public class LogViewPanel extends JPanel implements LogDataCollector { private static final Logger LOGGER = Logger.getLogger(LogViewPanel.class.getName()); private final OtrosJTextWithRulerScrollPane<JTextPane> logDetailWithRulerScrollPane; private final MessageDetailListener messageDetailListener; private Font menuLabelFont; private JPanel filtersPanel; private JPanel logsTablePanel; private JPanel logsMarkersPanel; private JPanel leftPanel; private JMenu automaticMarkersMenu; private JMenu automaticUnmarkersMenu; private LogDataTableModel dataTableModel; private OtrosApplication otrosApplication; private JTextPane logDetailTextArea; private JXTable table; private TableRowSorter<LogDataTableModel> sorter; private StatusObserver statusObserver; private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); private JTabbedPane jTabbedPane; private JTextArea notes; // private JScrollPane scrollPane; private FocusOnThisThreadAction focusOnThisThreadAction; private FocusOnEventsAfter focusOnEventsAfter; private FocusOnEventsBefore focusOnEventsBefore; private FocusOnSelectedClassesAction focusOnSelectedClassesAction; private FocusOnSelectedLoggerNameAction focusOnSelectedLoggerNameAction; private IgnoreSelectedEventsClasses ignoreSelectedEventsClasses; private ShowCallHierarchyAction showCallHierarchyAction; private PluginableElementsContainer<AutomaticMarker> markersContainer; private PluginableElementsContainer<LogFilter> logFiltersContainer; private PluginableElementsContainer<MessageColorizer> messageColorizersContainer; private PluginableElementsContainer<MessageFormatter> messageFormattersContainer; private PluginableElementsContainer<MessageColorizer> selectedMessageColorizersContainer; private PluginableElementsContainer<MessageFormatter> selectedMessageFormattersContainer; private JToolBar messageDetailToolbar; private List<AcceptCondition> acceptConditionList; private PropertyFilter propertyFilter; private FilterPanel propertyFilterPanel; private Collection<LogFilter> filtersList; private DataConfiguration configuration; private LogData displayedLogData; public LogViewPanel(final LogDataTableModel dataTableModel, TableColumns[] visibleColumns, final OtrosApplication otrosApplication) { super(); this.dataTableModel = dataTableModel; this.otrosApplication = otrosApplication; this.statusObserver = otrosApplication.getStatusObserver(); configuration = otrosApplication.getConfiguration(); AllPluginables allPluginable = AllPluginables.getInstance(); markersContainer = allPluginable.getMarkersContainser(); markersContainer.addListener(new MarkersMenuReloader()); logFiltersContainer = allPluginable.getLogFiltersContainer(); messageColorizersContainer = allPluginable.getMessageColorizers(); messageFormattersContainer = allPluginable.getMessageFormatters(); selectedMessageColorizersContainer = new PluginableElementsContainer<MessageColorizer>(); selectedMessageFormattersContainer = new PluginableElementsContainer<MessageFormatter>(); for (MessageColorizer messageColorizer : messageColorizersContainer.getElements()) { selectedMessageColorizersContainer.addElement(messageColorizer); } for (MessageFormatter messageFormatter : messageFormattersContainer.getElements()) { selectedMessageFormattersContainer.addElement(messageFormatter); } messageColorizersContainer.addListener( new SynchronizePluginableContainerListener<MessageColorizer>(selectedMessageColorizersContainer)); messageFormattersContainer.addListener( new SynchronizePluginableContainerListener<MessageFormatter>(selectedMessageFormattersContainer)); menuLabelFont = new JLabel().getFont().deriveFont(Font.BOLD); filtersPanel = new JPanel(); logsTablePanel = new JPanel(); logsMarkersPanel = new JPanel(); leftPanel = new JPanel(new MigLayout()); logDetailTextArea = new JTextPane(); logDetailTextArea.setEditable(false); MouseAdapter locationInfo = new LocationClickMouseAdapter(otrosApplication, logDetailTextArea); logDetailTextArea.addMouseMotionListener(locationInfo); logDetailTextArea.addMouseListener(locationInfo); logDetailTextArea.setBorder(BorderFactory.createTitledBorder("Details")); logDetailWithRulerScrollPane = RulerBarHelper.wrapTextComponent(logDetailTextArea); table = new JTableWith2RowHighliting(dataTableModel); // Initialize default column visible before creating context menu table.setColumnControlVisible(true); final ColumnControlButton columnControlButton = new ColumnControlButton(table) { @Override public void togglePopup() { populatePopup(); super.togglePopup(); } @Override protected List<Action> getAdditionalActions() { final List<Action> additionalActions = super.getAdditionalActions(); final AbstractAction saveLayout = new AbstractAction("Save current to new column layout", Icons.DISK) { @Override public void actionPerformed(ActionEvent actionEvent) { String newLayoutName = JOptionPane.showInputDialog(table, "New Layout name"); if (newLayoutName == null) { return; } newLayoutName = newLayoutName.trim(); LOGGER.info(String.format("Saving New column layout '%s'", newLayoutName)); ArrayList<String> visibleColNames = new ArrayList<String>(); for (TableColumn tc : table.getColumns()) { Object o = tc.getIdentifier(); if (!(o instanceof TableColumns)) { LOGGER.severe("TableColumn identifier of unexpected type: " + tc.getIdentifier().getClass().getName()); LOGGER.warning("Throw up a pop-up"); return; } TableColumns tcs = (TableColumns) o; visibleColNames.add(tcs.getName()); } ColumnLayout columnLayout = new ColumnLayout(newLayoutName, visibleColNames); final List<ColumnLayout> columnLayouts = LogTableFormatConfigView .loadColumnLayouts(configuration); columnLayouts.add(columnLayout); LogTableFormatConfigView.saveColumnLayouts(columnLayouts, configuration); populatePopup(); } }; additionalActions.add(saveLayout); final List<ColumnLayout> columnLayoutNames = LogTableFormatConfigView .loadColumnLayouts(configuration); for (final ColumnLayout columnLayout : columnLayoutNames) { final String name = columnLayout.getName(); final AbstractAction applyColumnLayout = new ApplyColumnLayoutAction(name, Icons.EDIT_COLUMNS, columnLayout, table); additionalActions.add(applyColumnLayout); } return additionalActions; } }; table.setColumnControl(columnControlButton); List<TableColumn> columns = table.getColumns(true); for (int i = 0; i < columns.size(); i++) { columns.get(i).setIdentifier(TableColumns.getColumnById(i)); } for (TableColumn tableColumn : columns) { table.getColumnExt(tableColumn.getIdentifier()).setVisible(false); } for (TableColumns tableColumns : visibleColumns) { table.getColumnExt(tableColumns).setVisible(true); } table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); updateColumnsSize(); table.setAutoResizeMode(JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS); final Renderers renderers = Renderers.getInstance(otrosApplication); table.setDefaultRenderer(String.class, new TableMarkDecoratorRenderer(renderers.getStringRenderer())); table.setDefaultRenderer(Object.class, new TableMarkDecoratorRenderer(table.getDefaultRenderer(Object.class))); table.setDefaultRenderer(Integer.class, new TableMarkDecoratorRenderer(table.getDefaultRenderer(Object.class))); table.setDefaultRenderer(Level.class, new TableMarkDecoratorRenderer(renderers.getLevelRenderer())); table.setDefaultRenderer(Date.class, new TableMarkDecoratorRenderer(renderers.getDateRenderer())); final TimeDeltaRenderer timeDeltaRenderer = new TimeDeltaRenderer(); table.getSelectionModel().addListSelectionListener(new ListSelectionListener() { @Override public void valueChanged(ListSelectionEvent listSelectionEvent) { final int[] selectedRows = table.getSelectedRows(); if (selectedRows.length > 0) { final int selectedRow = selectedRows[selectedRows.length - 1]; final Date selectedDate = dataTableModel.getLogData(table.convertRowIndexToModel(selectedRow)) .getDate(); timeDeltaRenderer.setSelectedTimestamp(selectedDate); table.repaint(); } } }); table.setDefaultRenderer(TimeDelta.class, new TableMarkDecoratorRenderer(timeDeltaRenderer)); ((EventSource) configuration.getConfiguration()).addConfigurationListener(new ConfigurationListener() { @Override public void configurationChanged(ConfigurationEvent ce) { if (ce.getType() == AbstractConfiguration.EVENT_SET_PROPERTY && !ce.isBeforeUpdate()) { if (ce.getPropertyName().equals(ConfKeys.LOG_TABLE_FORMAT_DATE_FORMAT)) { table.setDefaultRenderer(Date.class, new TableMarkDecoratorRenderer(new DateRenderer( configuration.getString(ConfKeys.LOG_TABLE_FORMAT_DATE_FORMAT, "HH:mm:ss.SSS")))); updateTimeColumnSize(); } else if (ce.getPropertyName().equals(ConfKeys.LOG_TABLE_FORMAT_LEVEL_RENDERER)) { table.setDefaultRenderer(Level.class, new TableMarkDecoratorRenderer(new LevelRenderer(configuration.get( LevelRenderer.Mode.class, ConfKeys.LOG_TABLE_FORMAT_LEVEL_RENDERER, LevelRenderer.Mode.IconsOnly)))); updateLevelColumnSize(); } } } }); table.setDefaultRenderer(Boolean.class, new TableMarkDecoratorRenderer(table.getDefaultRenderer(Boolean.class))); table.setDefaultRenderer(Note.class, new TableMarkDecoratorRenderer(new NoteRenderer())); table.setDefaultRenderer(MarkerColors.class, new TableMarkDecoratorRenderer(new MarkTableRenderer())); table.setDefaultEditor(Note.class, new NoteTableEditor()); table.setDefaultEditor(MarkerColors.class, new MarkTableEditor(otrosApplication)); table.setDefaultRenderer(ClassWrapper.class, new TableMarkDecoratorRenderer(renderers.getClassWrapperRenderer())); sorter = new TableRowSorter<LogDataTableModel>(dataTableModel); for (int i = 0; i < dataTableModel.getColumnCount(); i++) { sorter.setSortable(i, false); } sorter.setSortable(TableColumns.ID.getColumn(), true); sorter.setSortable(TableColumns.TIME.getColumn(), true); table.setRowSorter(sorter); messageDetailListener = new MessageDetailListener(this, dateFormat, selectedMessageFormattersContainer, selectedMessageColorizersContainer); table.getSelectionModel().addListSelectionListener(messageDetailListener); dataTableModel.addNoteObserver(messageDetailListener); table.getSelectionModel().addListSelectionListener(new ListSelectionListener() { @Override public void valueChanged(ListSelectionEvent e) { boolean hasFocus = otrosApplication.getApplicationJFrame().isFocused(); final boolean enabled = otrosApplication.getConfiguration() .getBoolean(ConfKeys.JUMP_TO_CODE_AUTO_JUMP_ENABLED, false); if (hasFocus && enabled && !e.getValueIsAdjusting()) { try { final LogData logData = dataTableModel .getLogData(table.convertRowIndexToModel(e.getFirstIndex())); LocationInfo li = new LocationInfo(logData.getClazz(), logData.getMethod(), logData.getFile(), Integer.valueOf(logData.getLine())); final JumpToCodeService jumpToCodeService = otrosApplication.getServices() .getJumpToCodeService(); final boolean ideAvailable = jumpToCodeService.isIdeAvailable(); if (ideAvailable) { LOGGER.fine("Jumping to " + li); jumpToCodeService.jump(li); } } catch (Exception e1) { LOGGER.warning("Can't perform jump to code " + e1.getMessage()); } } } }); notes = new JTextArea(); notes.setEditable(false); NoteObserver allNotesObserver = new AllNotesTextAreaObserver(notes); dataTableModel.addNoteObserver(allNotesObserver); addFiltersGUIsToPanel(filtersPanel); logsTablePanel.setLayout(new BorderLayout()); logsTablePanel.add(new JScrollPane(table)); JPanel messageDetailsPanel = new JPanel(new BorderLayout()); messageDetailToolbar = new JToolBar("MessageDetail"); messageDetailsPanel.add(messageDetailToolbar, BorderLayout.NORTH); messageDetailsPanel.add(logDetailWithRulerScrollPane); initMessageDetailsToolbar(); jTabbedPane = new JTabbedPane(); jTabbedPane.add("Message detail", messageDetailsPanel); jTabbedPane.add("All notes", new JScrollPane(notes)); leftPanel.add(filtersPanel, "wrap, growx"); leftPanel.add(new JSeparator(SwingConstants.HORIZONTAL), "wrap,growx"); leftPanel.add(logsMarkersPanel, "wrap,growx"); JSplitPane splitPaneLogsTableAndDetails = new JSplitPane(JSplitPane.VERTICAL_SPLIT, logsTablePanel, jTabbedPane); JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, new JScrollPane(leftPanel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED), splitPaneLogsTableAndDetails); splitPane.setOneTouchExpandable(true); this.setLayout(new BorderLayout()); this.add(splitPane); splitPaneLogsTableAndDetails.setDividerLocation(0.5d); splitPaneLogsTableAndDetails.setOneTouchExpandable(true); splitPane.setDividerLocation(leftPanel.getPreferredSize().width + 10); PopupListener popupListener = new PopupListener(new Callable<JPopupMenu>() { @Override public JPopupMenu call() throws Exception { return initTableContextMenu(); } }); table.addMouseListener(popupListener); table.addKeyListener(popupListener); PopupListener popupListenerMessageDetailMenu = new PopupListener(new Callable<JPopupMenu>() { @Override public JPopupMenu call() throws Exception { return initMessageDetailPopupMenu(); } }); logDetailTextArea.addMouseListener(popupListenerMessageDetailMenu); logDetailTextArea.addKeyListener(popupListenerMessageDetailMenu); dataTableModel.notifyAllNoteObservers(new NoteEvent(EventType.CLEAR, dataTableModel, null, 0)); table.addKeyListener(new MarkRowBySpaceKeyListener(otrosApplication)); initAcceptConditions(); } private JPopupMenu initMessageDetailPopupMenu() { JPopupMenu jPopupMenu = new JPopupMenu(); jPopupMenu.add(new CopySelectedText(otrosApplication, logDetailTextArea)); jPopupMenu.add(new CopyStyledMessageDetailAction(otrosApplication, dateFormat, selectedMessageColorizersContainer, selectedMessageFormattersContainer)); return jPopupMenu; } private void initAcceptConditions() { acceptConditionList = new ArrayList<AcceptCondition>(); acceptConditionList.add(new SelectedEventsAcceptCondition(table, dataTableModel)); acceptConditionList.add(new LowerIdAcceptCondition(table, dataTableModel)); acceptConditionList.add(new HigherIdAcceptCondition(table, dataTableModel)); acceptConditionList.add(new SelectedClassAcceptCondition(table, dataTableModel)); acceptConditionList.add(new SelectedThreadAcceptCondition(table, dataTableModel)); acceptConditionList.add(new LevelLowerAcceptCondition(Level.INFO)); acceptConditionList.add(new LevelLowerAcceptCondition(Level.WARNING)); acceptConditionList.add(new LevelLowerAcceptCondition(Level.SEVERE)); acceptConditionList.add(new FilteredAcceptCondition(filtersList)); } private void updateColumnsSize() { FontMetrics fm = table.getFontMetrics(table.getFont()); updateColumnSizeIfVisible(TableColumns.ID, fm.stringWidth("0000000"), fm.stringWidth("000000000")); updateTimeColumnSize(); updateColumnSizeIfVisible(TableColumns.DELTA, 60, 100); updateLevelColumnSize(); updateColumnSizeIfVisible(TableColumns.CLASS, 100, 500); updateColumnSizeIfVisible(TableColumns.THREAD, 100, 300); updateColumnSizeIfVisible(TableColumns.METHOD, 100, 200); updateColumnSizeIfVisible(TableColumns.LINE, fm.stringWidth("0000"), fm.stringWidth("000000")); updateColumnSizeIfVisible(TableColumns.MARK, 16, 16); updateColumnSizeIfVisible(TableColumns.NOTE, 100, 1500); } private void updateTimeColumnSize() { FontMetrics fm = table.getFontMetrics(table.getFont()); int dateWidth = fm.stringWidth( new SimpleDateFormat(configuration.getString(ConfKeys.LOG_TABLE_FORMAT_DATE_FORMAT, "HH:mm:ss.SSS")) .format(new Date())); updateColumnSizeIfVisible(TableColumns.TIME, dateWidth + 1, dateWidth + 1); } private void updateLevelColumnSize() { FontMetrics fm = table.getFontMetrics(table.getFont()); int levelWidth = fm.stringWidth(Level.WARNING.getName()); switch (configuration.get(LevelRenderer.Mode.class, ConfKeys.LOG_TABLE_FORMAT_LEVEL_RENDERER, LevelRenderer.Mode.IconsOnly)) { case IconsOnly: updateColumnSizeIfVisible(TableColumns.LEVEL, 16 + 1, 16 + 1); break; case IconsAndText: updateColumnSizeIfVisible(TableColumns.LEVEL, 16 + levelWidth + 5, 16 + levelWidth + 5); break; case TextOnly: updateColumnSizeIfVisible(TableColumns.LEVEL, levelWidth + 1, levelWidth + 1); break; } } private void updateColumnSizeIfVisible(TableColumns column, int width, int maxWidth) { table.getColumns(true).get(column.getColumn()).setMaxWidth(maxWidth); table.getColumns(true).get(column.getColumn()).setPreferredWidth(width); } public JTextPane getLogDetailTextArea() { return logDetailTextArea; } public void add(LogData[] autoResizeSubsequent) { dataTableModel.add(autoResizeSubsequent); } public void add(LogData logData) { dataTableModel.add(logData); } public LogData[] getLogData() { return dataTableModel.getLogData(); } private void addFiltersGUIsToPanel(JPanel filtersPanel) { filtersPanel.setLayout(new MigLayout("", "[grow]", "")); Collection<LogFilter> loadedFilters = logFiltersContainer.getElements(); // Reload filters, every instance of filter is connected to listeners, data table etc. filtersList = new ArrayList<LogFilter>(); for (LogFilter logFilter : loadedFilters) { try { LogFilter filter = logFilter.getClass().newInstance(); filtersList.add(filter); } catch (Exception e) { LOGGER.log(Level.SEVERE, "Can't initialize filter: " + logFilter.getClass(), e); } } JLabel filtersLabel = new JLabel("Filters:"); filtersLabel.setMinimumSize(new Dimension(200, 16)); filtersLabel.setPreferredSize(new Dimension(200, 16)); filtersLabel.setIcon(Icons.FILTER); Font f = filtersLabel.getFont().deriveFont(Font.BOLD); filtersLabel.setFont(f); filtersPanel.add(filtersLabel, "wrap, growx, span"); LogFilterValueChangeListener listener = new LogFilterValueChangeListener(table, sorter, filtersList, statusObserver); for (LogFilter filter : filtersList) { filter.init(new Properties(), dataTableModel); FilterPanel filterPanel = new FilterPanel(filter, listener); filtersPanel.add(filterPanel, "wrap, growx"); if (filter instanceof ThreadFilter) { ThreadFilter threadFilter = (ThreadFilter) filter; focusOnThisThreadAction = new FocusOnThisThreadAction(threadFilter, filterPanel.getEnableCheckBox(), otrosApplication); } else if (filter instanceof TimeFilter) { focusOnEventsAfter = new FocusOnEventsAfter((TimeFilter) filter, filterPanel.getEnableCheckBox(), otrosApplication); focusOnEventsBefore = new FocusOnEventsBefore((TimeFilter) filter, filterPanel.getEnableCheckBox(), otrosApplication); } else if (filter instanceof ClassFilter) { focusOnSelectedClassesAction = new FocusOnSelectedClassesAction((ClassFilter) filter, filterPanel.getEnableCheckBox(), otrosApplication); ignoreSelectedEventsClasses = new IgnoreSelectedEventsClasses((ClassFilter) filter, filterPanel.getEnableCheckBox(), otrosApplication); } else if (filter instanceof LoggerNameFilter) { focusOnSelectedLoggerNameAction = new FocusOnSelectedLoggerNameAction((LoggerNameFilter) filter, filterPanel.getEnableCheckBox(), otrosApplication); } else if (filter instanceof CallHierarchyLogFilter) { showCallHierarchyAction = new ShowCallHierarchyAction((CallHierarchyLogFilter) filter, filterPanel.getEnableCheckBox(), otrosApplication); } else if (filter instanceof PropertyFilter) { propertyFilter = (PropertyFilter) filter; propertyFilterPanel = filterPanel; } } filtersLabel.add(logsMarkersPanel, "span, grow"); } private JPopupMenu initTableContextMenu() { JPopupMenu menu = new JPopupMenu("Menu"); JMenuItem mark = new JMenuItem("Mark selected rows"); mark.addActionListener(new MarkRowAction(otrosApplication)); JMenuItem unmark = new JMenuItem("Unmark selected rows"); unmark.addActionListener(new UnMarkRowAction(otrosApplication)); JMenuItem autoResizeMenu = new JMenu("Table auto resize mode"); autoResizeMenu.setIcon(Icons.TABLE_RESIZE); JMenuItem autoResizeSubsequent = new JMenuItem("Subsequent columns"); autoResizeSubsequent .addActionListener(new TableResizeActionListener(table, JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS)); JMenuItem autoResizeLast = new JMenuItem("Last column"); autoResizeLast.addActionListener(new TableResizeActionListener(table, JTable.AUTO_RESIZE_LAST_COLUMN)); JMenuItem autoResizeNext = new JMenuItem("Next column"); autoResizeNext.addActionListener(new TableResizeActionListener(table, JTable.AUTO_RESIZE_NEXT_COLUMN)); JMenuItem autoResizeAll = new JMenuItem("All columns"); autoResizeAll.addActionListener(new TableResizeActionListener(table, JTable.AUTO_RESIZE_ALL_COLUMNS)); JMenuItem autoResizeOff = new JMenuItem("Auto resize off"); autoResizeOff.addActionListener(new TableResizeActionListener(table, JTable.AUTO_RESIZE_OFF)); autoResizeMenu.add(autoResizeSubsequent); autoResizeMenu.add(autoResizeOff); autoResizeMenu.add(autoResizeNext); autoResizeMenu.add(autoResizeLast); autoResizeMenu.add(autoResizeAll); JMenu removeMenu = new JMenu("Remove log events"); removeMenu.setFont(menuLabelFont); removeMenu.setIcon(Icons.BIN); JLabel removeLabel = new JLabel("Remove by:"); removeLabel.setFont(menuLabelFont); removeMenu.add(removeLabel); Map<String, Set<String>> propKeyValue = getPropertiesOfSelectedLogEvents(); for (AcceptCondition acceptCondition : acceptConditionList) { removeMenu.add(new JMenuItem(new RemoveByAcceptanceCriteria(acceptCondition, otrosApplication))); } for (String propertyKey : propKeyValue.keySet()) { for (String propertyValue : propKeyValue.get(propertyKey)) { PropertyAcceptCondition propAcceptCondition = new PropertyAcceptCondition(propertyKey, propertyValue); removeMenu .add(new JMenuItem(new RemoveByAcceptanceCriteria(propAcceptCondition, otrosApplication))); } } menu.add(new JSeparator()); JLabel labelMarkingRows = new JLabel("Marking/unmarking rows"); labelMarkingRows.setFont(menuLabelFont); menu.add(labelMarkingRows); menu.add(new JSeparator()); menu.add(mark); menu.add(unmark); JMenu[] markersMenu = getAutomaticMarkersMenu(); menu.add(markersMenu[0]); menu.add(markersMenu[1]); menu.add(new ClearMarkingsAction(otrosApplication)); menu.add(new JSeparator()); JLabel labelQuickFilters = new JLabel("Quick filters"); labelQuickFilters.setFont(menuLabelFont); menu.add(labelQuickFilters); menu.add(new JSeparator()); menu.add(focusOnThisThreadAction); menu.add(focusOnEventsAfter); menu.add(focusOnEventsBefore); menu.add(focusOnSelectedClassesAction); menu.add(ignoreSelectedEventsClasses); menu.add(focusOnSelectedLoggerNameAction); menu.add(showCallHierarchyAction); for (String propertyKey : propKeyValue.keySet()) { for (String propertyValue : propKeyValue.get(propertyKey)) { menu.add(new FocusOnSelectedPropertyAction(propertyFilter, propertyFilterPanel.getEnableCheckBox(), otrosApplication, propertyKey, propertyValue)); } } menu.add(new JSeparator()); menu.add(removeMenu); menu.add(new JSeparator()); JLabel labelTableOptions = new JLabel("Table options"); labelTableOptions.setFont(menuLabelFont); menu.add(labelTableOptions); menu.add(new JSeparator()); menu.add(autoResizeMenu); menu.add(new JSeparator()); List<MenuActionProvider> menuActionProviders = otrosApplication.getLogViewPanelMenuActionProvider(); for (MenuActionProvider menuActionProvider : menuActionProviders) { try { List<OtrosAction> actions = menuActionProvider.getActions(otrosApplication, this); if (actions == null) { continue; } for (OtrosAction action : actions) { menu.add(action); } } catch (Exception e) { LOGGER.log(Level.SEVERE, "Cant get action from from provider " + menuActionProvider, e); } } return menu; } public int[] getSelectedRowsInModel() { int[] selectedRows = table.getSelectedRows(); for (int index = 0; index < selectedRows.length; index++) { selectedRows[index] = table.convertRowIndexToModel(selectedRows[index]); } return selectedRows; } private Map<String, Set<String>> getPropertiesOfSelectedLogEvents() { Map<String, Set<String>> result = new HashMap<String, Set<String>>(); int[] selectedRows = getSelectedRowsInModel(); for (int i : selectedRows) { LogData logData = dataTableModel.getLogData(i); Map<String, String> properties = logData.getProperties(); if (properties == null) { continue; } for (String s : properties.keySet()) { if (!result.containsKey(s)) { result.put(s, new TreeSet<String>()); } result.get(s).add(properties.get(s)); } } return result; } private JMenu[] getAutomaticMarkersMenu() { // AutomaticMarker[] markers = MarkersContainer.getInstance().getMarkers().toArray(new AutomaticMarker[0]); automaticMarkersMenu = new JMenu("Mark rows automatically"); automaticMarkersMenu.setIcon(Icons.AUTOMATIC_MARKERS); automaticUnmarkersMenu = new JMenu("Unmark rows automatically"); automaticUnmarkersMenu.setIcon(Icons.AUTOMATIC_UNMARKERS); updateMarkerMenu(markersContainer.getElements()); return new JMenu[] { automaticMarkersMenu, automaticUnmarkersMenu }; } private void addMarkerToMenu(JMenu menu, AutomaticMarker automaticMarker, HashMap<String, JMenu> marksGroups, boolean mode) { String[] groups = automaticMarker.getMarkerGroups(); if (groups == null || groups.length == 0) { groups = new String[] { "" }; } for (String g : groups) { JMenuItem markerMenuItem = new JMenuItem(automaticMarker.getName()); Icon icon = new ColorIcon(automaticMarker.getColors().getBackground(), automaticMarker.getColors().getForeground(), 16, 16); markerMenuItem.setIcon(icon); markerMenuItem.setToolTipText(automaticMarker.getDescription()); markerMenuItem.addActionListener( new AutomaticMarkUnamrkActionListener(dataTableModel, automaticMarker, mode, statusObserver)); if (g.length() > 0) { JMenu m = marksGroups.get(g); if (m == null) { m = new JMenu(g); marksGroups.put(g, m); menu.add(m); } m.add(markerMenuItem); } else { menu.add(markerMenuItem); } } } public void updateMarkerMenu(Collection<AutomaticMarker> markers) { HashMap<String, JMenu> marksGroups = new HashMap<String, JMenu>(); HashMap<String, JMenu> unmarksGroups = new HashMap<String, JMenu>(); automaticMarkersMenu.removeAll(); automaticUnmarkersMenu.removeAll(); for (AutomaticMarker automaticMarker : markers) { addMarkerToMenu(automaticMarkersMenu, automaticMarker, marksGroups, AutomaticMarkUnamrkActionListener.MODE_MARK); addMarkerToMenu(automaticUnmarkersMenu, automaticMarker, unmarksGroups, AutomaticMarkUnamrkActionListener.MODE_UNMARK); } GuiUtils.sortDirAndAlfabetic(automaticMarkersMenu); GuiUtils.sortDirAndAlfabetic(automaticUnmarkersMenu); } protected void initMessageDetailsToolbar() { final JButton buttonFormatters = new JButton("Message formatters", Icons.MESSAGE_FORMATTER); buttonFormatters.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { showMessageFormatterOrColorizerPopupMenu(e, "Message formatters", selectedMessageFormattersContainer, messageFormattersContainer); } }); buttonFormatters.setToolTipText("Select used message formatters"); messageDetailToolbar.add(buttonFormatters); final JButton buttonColorizers = new JButton("Message colorizers", Icons.MESSAGE_COLORIZER); buttonColorizers.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { showMessageFormatterOrColorizerPopupMenu(e, "Message colorizers", selectedMessageColorizersContainer, messageColorizersContainer); } }); buttonColorizers.setToolTipText("Select used message colorizers"); messageDetailToolbar.add(buttonColorizers); messageDetailToolbar.add(new CopyStyledMessageDetailAction(otrosApplication, dateFormat, selectedMessageColorizersContainer, selectedMessageFormattersContainer)); messageDetailToolbar.add(new JLabel("Maximum message size for format")); final DefaultComboBoxModel defaultComboBoxModel = new DefaultComboBoxModel(new String[] {}); String[] values = new String[] { "10kB", "100kB", "200kB", "300kB", "400kB", "500kB", "600kB", "700kB", "800kB", "900kB", "1MB", "2MB", "3MB", "4MB", "5MB" }; for (String value : values) { defaultComboBoxModel.addElement(value); } final JXComboBox messageMaximumSize = new JXComboBox(defaultComboBoxModel); messageMaximumSize.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { String max = (String) defaultComboBoxModel.getElementAt(messageMaximumSize.getSelectedIndex()); configuration.setProperty(ConfKeys.MESSAGE_FORMATTER_MAX_SIZE, max); messageDetailListener.setMaximumMessageSize((int) new FileSize(max).getBytes()); } }); messageMaximumSize.setEditable(false); AutoCompleteDecorator.decorate(messageMaximumSize); messageMaximumSize.setMaximumSize(new Dimension(100, 50)); messageDetailToolbar.add(messageMaximumSize); String messageMaxSize = configuration.getString(ConfKeys.MESSAGE_FORMATTER_MAX_SIZE, (String) defaultComboBoxModel.getElementAt(messageMaximumSize.getSelectedIndex())); if (defaultComboBoxModel.getIndexOf(messageMaxSize) >= 0) { messageMaximumSize.setSelectedItem(messageMaxSize); } } private void showMessageFormatterOrColorizerPopupMenu(MouseEvent e, String menuTitle, PluginableElementsContainer<? extends PluginableElement> selectedPluginableElementsContainer, PluginableElementsContainer<? extends PluginableElement> pluginableElementsContainer) { final JPopupMenu popupMenu = new JPopupMenu(menuTitle); popupMenu.add(new JLabel(menuTitle)); ArrayList<PluginableElement> elements = new ArrayList<PluginableElement>( pluginableElementsContainer.getElements()); Collections.sort(elements, new PluginableElementNameComparator()); for (final PluginableElement pluginableElement : elements) { addMessageFormatterOrColorizerToMenu(popupMenu, pluginableElement, selectedPluginableElementsContainer); } popupMenu.show(e.getComponent(), e.getX(), e.getY()); } private void addMessageFormatterOrColorizerToMenu(final JPopupMenu menu, final PluginableElement pluginable, final PluginableElementsContainer selectedPluginableContainer) { { final JCheckBoxMenuItem boxMenuItem = new JCheckBoxMenuItem(pluginable.getName(), selectedPluginableContainer.contains(pluginable)); boxMenuItem.setToolTipText(pluginable.getDescription()); menu.add(boxMenuItem); boxMenuItem.addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { if (boxMenuItem.isSelected() && !selectedPluginableContainer.contains(pluginable)) { selectedPluginableContainer.addElement(pluginable); } else if (!boxMenuItem.isSelected() && selectedPluginableContainer.contains(pluginable)) { selectedPluginableContainer.removeElement(pluginable); } } }); } } public JXTable getTable() { return table; } public LogDataTableModel getDataTableModel() { return dataTableModel; } public JPanel getLogsMarkersPanel() { return logsMarkersPanel; } @Override public int clear() { return dataTableModel.clear(); } public LogData getDisplayedLogData() { return displayedLogData; } public void setDisplayedLogData(LogData displayedLogData) { this.displayedLogData = displayedLogData; } public OtrosJTextWithRulerScrollPane<JTextPane> getLogDetailWithRulerScrollPane() { return logDetailWithRulerScrollPane; } public PluginableElementsContainer<MessageColorizer> getSelectedMessageColorizersContainer() { return selectedMessageColorizersContainer; } public PluginableElementsContainer<MessageFormatter> getSelectedMessageFormattersContainer() { return selectedMessageFormattersContainer; } public JToolBar getMessageDetailToolbar() { return messageDetailToolbar; } private class MarkersMenuReloader implements PluginableElementEventListener<AutomaticMarker> { PluginableElementsContainer<AutomaticMarker> markersContainer = AllPluginables.getInstance() .getMarkersContainser(); @Override public void elementAdded(AutomaticMarker element) { updateMarkerMenu(markersContainer.getElements()); } @Override public void elementRemoved(AutomaticMarker element) { updateMarkerMenu(markersContainer.getElements()); } @Override public void elementChanged(AutomaticMarker element) { updateMarkerMenu(markersContainer.getElements()); } } }