Adds message filtering, message history clear, and message history size features to the 'Messages' tab. Filter window dynamically constructs a list of filters from the primary filter and each of the auxiliary filters enabled within the currently selected/enabled processing channel.

This commit is contained in:
dennis.sheirer
2014-12-12 04:30:31 +00:00
parent 33d18b1186
commit 0d8da161e1
28 changed files with 1693 additions and 53 deletions

View File

@@ -0,0 +1,35 @@
package filter;
import java.util.Collections;
import java.util.List;
/**
* Implements a message filter that passes (true) all messages
*/
@SuppressWarnings( "rawtypes" )
public class AllPassFilter<T> extends Filter<T>
{
public AllPassFilter()
{
super( "Allow All Messages" );
}
@Override
public boolean passes( T t )
{
return true;
}
@Override
public boolean canProcess( T t )
{
return true;
}
@Override
@SuppressWarnings( "unchecked" )
public List getFilterElements()
{
return Collections.EMPTY_LIST;
}
}

55
src/filter/Filter.java Normal file
View File

@@ -0,0 +1,55 @@
package filter;
import java.util.List;
public abstract class Filter<T> implements IFilter<T>
{
protected String mName;
protected boolean mEnabled = true;
public Filter( String name )
{
mName = name;
}
/**
* Indicates if this filter is enabled or disabled
*/
public boolean isEnabled()
{
return mEnabled;
}
/**
* Enables (true) or disables (false) this filter. An enabled filter will
* evaluate messages and a disabled filter will return false on all message
* test methods.
*/
public void setEnabled( boolean enabled )
{
mEnabled = enabled;
}
/**
* List of filter elements managed by this filter
*/
public abstract List<FilterElement<?>> getFilterElements();
/**
* Name of this filter
*/
public String getName()
{
return mName;
}
public void setName( String name )
{
mName = name;
}
public String toString()
{
return mName;
}
}

View File

@@ -0,0 +1,400 @@
package filter;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Collections;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.EventObject;
import java.util.List;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.event.CellEditorListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeCellEditor;
import javax.swing.tree.TreeSelectionModel;
import net.miginfocom.swing.MigLayout;
public class FilterEditorPanel<T> extends JPanel
{
private static final long serialVersionUID = 1L;
private JTree mTree;
private DefaultTreeModel mModel;
private FilterSet<T> mFilterSet;
public FilterEditorPanel( FilterSet<T> filterSet )
{
setLayout( new MigLayout("insets 0 0 0 0", "[grow,fill]", "[grow,fill]") );
mFilterSet = filterSet;
init();
}
private void init()
{
DefaultMutableTreeNode root = new DefaultMutableTreeNode( mFilterSet );
mModel = new DefaultTreeModel( root );
addFilterSet( mFilterSet, root );
mTree = new JTree( mModel );
mTree.setShowsRootHandles( true );
mTree.addMouseListener( new MouseHandler() );
mTree.getSelectionModel().setSelectionMode(
TreeSelectionModel.SINGLE_TREE_SELECTION );
mTree.setCellRenderer( new EditorTreeCellRenderer() );
mTree.setCellEditor( new FilterTreeNodeEditor() );
mTree.setEditable( true );
add( mTree );
}
private void addFilterSet( FilterSet<T> filterSet, DefaultMutableTreeNode parent )
{
List<IFilter<T>> filters = filterSet.getFilters();
/* sort the filters in alphabetical order by name */
Collections.sort( filters, new Comparator<IFilter<?>>()
{
@Override
public int compare( IFilter<?> first, IFilter<?> second )
{
return first.getName().compareTo( second.getName() );
}
});
for( IFilter<T> filter: filters )
{
DefaultMutableTreeNode child = new DefaultMutableTreeNode( filter );
mModel.insertNodeInto( child, parent, parent.getChildCount() );
if( filter instanceof FilterSet )
{
addFilterSet( (FilterSet<T>)filter, child );
}
else if( filter instanceof Filter )
{
addFilter( (Filter<T>)filter, child );
}
}
}
private void addFilter( Filter<T> filter, DefaultMutableTreeNode parent )
{
List<FilterElement<?>> elements = filter.getFilterElements();
Collections.sort( elements );
for( FilterElement<?> element: elements )
{
DefaultMutableTreeNode child = new DefaultMutableTreeNode( element );
mModel.insertNodeInto( child, parent, parent.getChildCount() );
}
}
public class MouseHandler implements MouseListener
{
public MouseHandler()
{
}
@Override
public void mouseClicked( MouseEvent event )
{
if( SwingUtilities.isRightMouseButton( event ) )
{
int row = mTree.getRowForLocation( event.getX(),
event.getY() );
if( row != -1 )
{
mTree.setSelectionRow( row );
Object selectedNode =
mTree.getLastSelectedPathComponent();
if( selectedNode instanceof DefaultMutableTreeNode )
{
final DefaultMutableTreeNode node =
(DefaultMutableTreeNode)selectedNode;
if( node.getChildCount() > 0 )
{
JPopupMenu selectionMenu = new JPopupMenu();
JMenuItem selectAll = new JMenuItem( "Select All" );
selectAll.addActionListener( new ActionListener()
{
@Override
public void actionPerformed( ActionEvent arg0 )
{
setFilterEnabled( mModel, node, true );
}
});
selectionMenu.add( selectAll );
JMenuItem deselectAll = new JMenuItem( "Deselect All" );
deselectAll.addActionListener( new ActionListener()
{
@Override
public void actionPerformed( ActionEvent arg0 )
{
setFilterEnabled( mModel, node, false );
}
});
selectionMenu.add( deselectAll );
selectionMenu.show( mTree,
event.getX(),
event.getY() );
}
}
}
}
}
@Override
public void mousePressed( MouseEvent e ){}
@Override
public void mouseReleased( MouseEvent e ){}
@Override
public void mouseEntered( MouseEvent e ){}
@Override
public void mouseExited( MouseEvent e ){}
}
/**
* Recursively sets the enabled state on all filter node children below the
* specified parent node.
*
* @param model - model containing the tree nodes
* @param node - parent node
* @param enabled - true or false to enable or disable the filters
*/
private void setFilterEnabled( DefaultTreeModel model,
DefaultMutableTreeNode node,
boolean enabled )
{
Object obj = node.getUserObject();
if( obj instanceof FilterSet<?> )
{
((FilterSet<?>)obj).setEnabled( enabled );
}
else if( obj instanceof Filter )
{
((Filter<?>)obj).setEnabled( enabled );
}
else if( obj instanceof FilterElement )
{
((FilterElement<?>)obj).setEnabled( enabled );
}
model.nodeChanged( node );
/* Recursively set the children of this node */
Enumeration<?> children = node.children();
while( children.hasMoreElements() )
{
Object child = children.nextElement();
if( child instanceof DefaultMutableTreeNode )
{
setFilterEnabled( model, (DefaultMutableTreeNode)child, enabled );
}
}
}
public class EditorTreeCellRenderer extends DefaultTreeCellRenderer
{
private static final long serialVersionUID = 1L;
public Component getTreeCellRendererComponent( JTree tree,
Object treeNode,
boolean selected,
boolean expanded,
boolean leaf,
int row,
boolean hasFocus )
{
if( treeNode instanceof DefaultMutableTreeNode )
{
Object userObject = ((DefaultMutableTreeNode)treeNode).getUserObject();
JCheckBox checkBox = null;
if( userObject instanceof IFilter )
{
IFilter<?> filter = (IFilter<?>)userObject;
checkBox = new JCheckBox( filter.getName() );
checkBox.setSelected( filter.isEnabled() );
}
else if( userObject instanceof FilterElement )
{
FilterElement<?> element = (FilterElement<?>)userObject;
checkBox = new JCheckBox( element.getName() );
checkBox.setSelected( element.isEnabled() );
}
if( checkBox != null )
{
if( selected )
{
checkBox.setForeground( getTextSelectionColor() );
checkBox.setBackground( getBackgroundSelectionColor() );
}
else
{
checkBox.setForeground( getTextNonSelectionColor() );
checkBox.setBackground( getBackgroundNonSelectionColor() );
}
return checkBox;
}
}
return super.getTreeCellRendererComponent( tree, treeNode, selected,
expanded, leaf, row, hasFocus );
}
}
public class FilterCheckBox extends JCheckBox
{
private static final long serialVersionUID = 1L;
private IFilter<T> mFilter;
public FilterCheckBox( IFilter<T> filter )
{
super( filter.getName() );
mFilter = filter;
setSelected( mFilter.isEnabled() );
addItemListener( new ItemListener()
{
@Override
public void itemStateChanged( ItemEvent e )
{
mFilter.setEnabled( FilterCheckBox.this.isSelected() );
}
} );
}
}
public class FilterElementCheckBox extends JCheckBox
{
private static final long serialVersionUID = 1L;
private FilterElement<?> mFilter;
public FilterElementCheckBox( FilterElement<?> filter )
{
super( filter.getName() );
mFilter = filter;
setSelected( mFilter.isEnabled() );
addItemListener( new ItemListener()
{
@Override
public void itemStateChanged( ItemEvent arg0 )
{
mFilter.setEnabled( FilterElementCheckBox.this.isSelected() );
}
} );
}
}
public class FilterTreeNodeEditor implements TreeCellEditor
{
@Override
@SuppressWarnings( { "rawtypes", "unchecked" } )
public Component getTreeCellEditorComponent( JTree tree, Object node,
boolean isSelected, boolean expanded, boolean leaf, int row )
{
if( node instanceof DefaultMutableTreeNode )
{
Object userObject = ((DefaultMutableTreeNode)node).getUserObject();
if( userObject instanceof IFilter )
{
return new FilterCheckBox( (IFilter)userObject );
}
else if( userObject instanceof FilterElement )
{
return new FilterElementCheckBox( (FilterElement<?>)userObject );
}
}
return new JLabel( node.toString() );
}
@Override
public void addCellEditorListener( CellEditorListener l ) {}
@Override
public void cancelCellEditing()
{
}
@Override
public Object getCellEditorValue()
{
return null;
}
@Override
public boolean isCellEditable( EventObject anEvent )
{
return true;
}
@Override
public void removeCellEditorListener( CellEditorListener l ) {}
@Override
public boolean shouldSelectCell( EventObject anEvent )
{
return false;
}
@Override
public boolean stopCellEditing()
{
return false;
}
}
}

View File

@@ -0,0 +1,49 @@
package filter;
public class FilterElement<T> implements Comparable<FilterElement<T>>
{
private boolean mEnabled;
private T mElement;
public FilterElement( T element, boolean enabled )
{
mElement = element;
mEnabled = enabled;
}
public FilterElement( T t )
{
this( t, true );
}
public T getElement()
{
return mElement;
}
public String toString()
{
return getName();
}
public boolean isEnabled()
{
return mEnabled;
}
public void setEnabled( boolean enabled )
{
mEnabled = enabled;
}
public String getName()
{
return mElement.toString();
}
@Override
public int compareTo( FilterElement<T> other )
{
return toString().compareTo( other.toString() );
}
}

97
src/filter/FilterSet.java Normal file
View File

@@ -0,0 +1,97 @@
package filter;
import java.util.ArrayList;
import java.util.List;
public class FilterSet<T> implements IFilter<T>
{
protected List<IFilter<T>> mFilters = new ArrayList<IFilter<T>>();
protected boolean mEnabled = true;
protected String mName;
public FilterSet( String name )
{
mName = name;
}
public String getName()
{
return mName;
}
public void setName( String name )
{
mName = name;
}
public String toString()
{
return getName();
}
@Override
public boolean passes( T t )
{
if( mEnabled )
{
for( IFilter<T> filter: mFilters )
{
if( filter.canProcess( t ) )
{
return filter.passes( t );
}
}
}
return false;
}
@Override
public boolean canProcess( T t )
{
if( mEnabled )
{
for( IFilter<T> filter: mFilters )
{
if( filter.canProcess( t ) )
{
return true;
}
}
}
return false;
}
public List<IFilter<T>> getFilters()
{
return mFilters;
}
public void addFilters( List<IFilter<T>> filters )
{
mFilters.addAll( filters );
}
public void addFilter( IFilter<T> filter )
{
mFilters.add( filter );
}
public void removeFilter( IFilter<T> filter )
{
mFilters.remove( filter );
}
@Override
public boolean isEnabled()
{
return mEnabled;
}
@Override
public void setEnabled( boolean enabled )
{
mEnabled = enabled;
}
}

36
src/filter/IFilter.java Normal file
View File

@@ -0,0 +1,36 @@
package filter;
public interface IFilter<T>
{
/**
* Generic filter method.
*
* @param message - message to filter
* @return - true if the message passes the filter
*/
public boolean passes( T t );
/**
* Indicates if the filter can process (filter) the object
*
* @param message - candidate message for filtering
*
* @return - true if the filter is capable of filtering the message
*/
public boolean canProcess( T t );
/**
* Indicates if this filter is enabled to evaluate messages
*/
public boolean isEnabled();
/**
* Sets the enabled state of the filter
*/
public void setEnabled( boolean enabled );
/**
* Display name for the filter
*/
public String getName();
}