mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-12 08:37:25 -05:00
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:
@@ -52,7 +52,7 @@ public class ConfigurationTreePanel extends JPanel
|
||||
mSystemTree.getSelectionModel().setSelectionMode(
|
||||
TreeSelectionModel.SINGLE_TREE_SELECTION );
|
||||
mSystemTree.setShowsRootHandles( true );
|
||||
mSystemTree.addMouseListener( new Handler() );
|
||||
mSystemTree.addMouseListener( new MouseHandler() );
|
||||
mSystemTree.setCellRenderer( new ControllerTreeCellRenderer() );
|
||||
|
||||
//Give the model a reference to the tree, so that it can force newly
|
||||
@@ -68,9 +68,9 @@ public class ConfigurationTreePanel extends JPanel
|
||||
mSystemTree.addTreeSelectionListener( listener );
|
||||
}
|
||||
|
||||
public class Handler implements MouseListener
|
||||
public class MouseHandler implements MouseListener
|
||||
{
|
||||
public Handler()
|
||||
public MouseHandler()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Dimension;
|
||||
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTable;
|
||||
@@ -131,7 +132,7 @@ public class ControllerPanel extends JPanel
|
||||
|
||||
MapPanel mapPanel = new MapPanel( mResourceManager );
|
||||
mTabbedPane.addTab( "Map", mapPanel );
|
||||
|
||||
|
||||
|
||||
/* Channel state list */
|
||||
mChannelStateList = new ChannelStateList( mResourceManager.getSettingsManager() );
|
||||
|
||||
@@ -18,8 +18,10 @@
|
||||
package controller.activity;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JFrame;
|
||||
@@ -63,7 +65,13 @@ public class ActivitySummaryFrame extends JFrame
|
||||
} );
|
||||
|
||||
add( close );
|
||||
|
||||
setVisible( true );
|
||||
|
||||
EventQueue.invokeLater( new Runnable()
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
setVisible( true );
|
||||
}
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import javax.swing.table.AbstractTableModel;
|
||||
|
||||
import message.Message;
|
||||
import sample.Listener;
|
||||
import filter.FilterSet;
|
||||
|
||||
public class MessageActivityModel extends AbstractTableModel
|
||||
implements Listener<Message>
|
||||
@@ -51,10 +52,41 @@ public class MessageActivityModel extends AbstractTableModel
|
||||
|
||||
private boolean mNewMessagesFirst = true;
|
||||
|
||||
private FilterSet mMessageFilter;
|
||||
|
||||
public MessageActivityModel( FilterSet messageFilter )
|
||||
{
|
||||
mMessageFilter = messageFilter;
|
||||
}
|
||||
|
||||
public MessageActivityModel()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all messages from history
|
||||
*/
|
||||
public void clear()
|
||||
{
|
||||
EventQueue.invokeLater( new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
int messageCount = mMessages.size();
|
||||
|
||||
mMessages.clear();
|
||||
|
||||
fireTableRowsDeleted( 0, messageCount - 1 );
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public FilterSet getMessageFilter()
|
||||
{
|
||||
return mMessageFilter;
|
||||
}
|
||||
|
||||
public void dispose()
|
||||
{
|
||||
mMessages.clear();
|
||||
@@ -90,18 +122,21 @@ public class MessageActivityModel extends AbstractTableModel
|
||||
|
||||
public void receive( final Message message )
|
||||
{
|
||||
EventQueue.invokeLater( new Runnable()
|
||||
if( mMessageFilter.passes( message ) )
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
mMessages.addFirst( message );
|
||||
EventQueue.invokeLater( new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
mMessages.addFirst( message );
|
||||
|
||||
MessageActivityModel.this.fireTableRowsInserted( 0, 0 );
|
||||
MessageActivityModel.this.fireTableRowsInserted( 0, 0 );
|
||||
|
||||
prune();
|
||||
}
|
||||
} );
|
||||
prune();
|
||||
}
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
private void prune()
|
||||
|
||||
@@ -17,11 +17,37 @@
|
||||
******************************************************************************/
|
||||
package controller.activity;
|
||||
|
||||
import filter.FilterEditorPanel;
|
||||
import filter.FilterSet;
|
||||
import gui.SDRTrunk;
|
||||
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseListener;
|
||||
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JSlider;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
|
||||
import message.Message;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.jidesoft.swing.JideButton;
|
||||
import com.jidesoft.swing.JideSplitButton;
|
||||
|
||||
import controller.channel.Channel;
|
||||
import controller.channel.ChannelEvent;
|
||||
import controller.channel.ChannelEvent.Event;
|
||||
@@ -30,23 +56,33 @@ import controller.channel.ChannelEventListener;
|
||||
public class MessageActivityPanel extends JPanel implements ChannelEventListener
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final static Logger mLog = LoggerFactory.getLogger( SDRTrunk.class );
|
||||
|
||||
private static MessageActivityModel EMPTY_MODEL = new MessageActivityModel();
|
||||
|
||||
private JTable mMessageTable;
|
||||
|
||||
private JScrollPane mEmptyScrollPane;
|
||||
private Channel mDisplayedChannel;
|
||||
|
||||
private MessageManagementPanel mManagementPanel = new MessageManagementPanel();
|
||||
|
||||
public MessageActivityPanel()
|
||||
{
|
||||
setLayout( new MigLayout("insets 0 0 0 0 ", "[grow,fill]", "[grow,fill]") );
|
||||
setLayout( new MigLayout("insets 0 0 0 0", "[][grow,fill]", "[]0[grow,fill]") );
|
||||
|
||||
mEmptyScrollPane =
|
||||
new JScrollPane( new JTable( new MessageActivityModel() ) );
|
||||
add( mManagementPanel, "span,growx" );
|
||||
|
||||
mMessageTable = new JTable( EMPTY_MODEL );
|
||||
|
||||
add( mEmptyScrollPane );
|
||||
add( new JScrollPane( mMessageTable ), "span,grow" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelChanged( ChannelEvent event )
|
||||
{
|
||||
boolean changed = false;
|
||||
|
||||
if( event.getEvent() == Event.CHANGE_SELECTED &&
|
||||
event.getChannel().isSelected() )
|
||||
{
|
||||
@@ -54,18 +90,21 @@ public class MessageActivityPanel extends JPanel implements ChannelEventListener
|
||||
( mDisplayedChannel != null &&
|
||||
mDisplayedChannel != event.getChannel() ) )
|
||||
{
|
||||
removeAll();
|
||||
|
||||
JScrollPane scroll =
|
||||
new JScrollPane( event.getChannel().getProcessingChain()
|
||||
.getChannelState().getMessageActivityTable() );
|
||||
|
||||
add( scroll );
|
||||
|
||||
mDisplayedChannel = event.getChannel();
|
||||
|
||||
mMessageTable.setModel( event.getChannel().getProcessingChain()
|
||||
.getChannelState().getMessageActivityModel() );
|
||||
|
||||
if( mDisplayedChannel != null )
|
||||
{
|
||||
mManagementPanel.enable();
|
||||
}
|
||||
else
|
||||
{
|
||||
mManagementPanel.disable();
|
||||
}
|
||||
|
||||
revalidate();
|
||||
repaint();
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
else if( event.getEvent() == Event.PROCESSING_STOPPED ||
|
||||
@@ -75,12 +114,203 @@ public class MessageActivityPanel extends JPanel implements ChannelEventListener
|
||||
mDisplayedChannel == event.getChannel() )
|
||||
{
|
||||
mDisplayedChannel = null;
|
||||
removeAll();
|
||||
add( mEmptyScrollPane );
|
||||
|
||||
revalidate();
|
||||
repaint();
|
||||
mMessageTable.setModel( EMPTY_MODEL );
|
||||
|
||||
mManagementPanel.disable();
|
||||
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if( changed )
|
||||
{
|
||||
revalidate();
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
|
||||
public class MessageManagementPanel extends JPanel
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private MessageHistoryButton mHistoryButton = new MessageHistoryButton();
|
||||
private MessageFilterButton mFilterButton = new MessageFilterButton();
|
||||
|
||||
public MessageManagementPanel()
|
||||
{
|
||||
setLayout( new MigLayout("insets 2 2 5 5", "[]5[left,grow]", "") );
|
||||
|
||||
disable();
|
||||
|
||||
add( mFilterButton );
|
||||
add( mHistoryButton );
|
||||
}
|
||||
|
||||
public void enable()
|
||||
{
|
||||
mHistoryButton.setEnabled( true );
|
||||
mFilterButton.setEnabled( true );
|
||||
}
|
||||
|
||||
public void disable()
|
||||
{
|
||||
mHistoryButton.setEnabled( false );
|
||||
mFilterButton.setEnabled( false );
|
||||
}
|
||||
}
|
||||
|
||||
public class MessageHistoryButton extends JideSplitButton
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public MessageHistoryButton()
|
||||
{
|
||||
super( "Clear" );
|
||||
|
||||
JPanel historyPanel = new JPanel();
|
||||
|
||||
historyPanel.add( new JLabel( "Message History:" ) );
|
||||
|
||||
final JSlider slider = new JSlider();
|
||||
slider.setMinimum( 0 );
|
||||
slider.setMaximum( 2000 );
|
||||
slider.setMajorTickSpacing( 500 );
|
||||
slider.setPaintTicks( true );
|
||||
slider.setPaintLabels( true );
|
||||
|
||||
slider.addMouseListener( new MouseListener()
|
||||
{
|
||||
@Override
|
||||
public void mouseClicked( MouseEvent arg0 )
|
||||
{
|
||||
if( SwingUtilities.isLeftMouseButton( arg0 ) &&
|
||||
arg0.getClickCount() == 2 )
|
||||
{
|
||||
slider.setValue( 500 ); //default
|
||||
}
|
||||
}
|
||||
|
||||
public void mouseEntered( MouseEvent arg0 ) {}
|
||||
public void mouseExited( MouseEvent arg0 ) {}
|
||||
public void mousePressed( MouseEvent arg0 ) {}
|
||||
public void mouseReleased( MouseEvent arg0 ) {}
|
||||
} );
|
||||
|
||||
if( mDisplayedChannel != null )
|
||||
{
|
||||
slider.setValue( mDisplayedChannel.getProcessingChain()
|
||||
.getChannelState().getMessageActivityModel()
|
||||
.getMaxMessageCount() );
|
||||
}
|
||||
else
|
||||
{
|
||||
slider.setValue( 500 );
|
||||
}
|
||||
|
||||
slider.addChangeListener( new ChangeListener()
|
||||
{
|
||||
@Override
|
||||
public void stateChanged( ChangeEvent arg0 )
|
||||
{
|
||||
if( mDisplayedChannel != null )
|
||||
{
|
||||
mDisplayedChannel.getProcessingChain().getChannelState()
|
||||
.getMessageActivityModel()
|
||||
.setMaxMessageCount( slider.getValue() );
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
historyPanel.add( slider );
|
||||
|
||||
add( historyPanel );
|
||||
|
||||
/* Clear messages */
|
||||
addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
if( mDisplayedChannel != null )
|
||||
{
|
||||
mDisplayedChannel.getProcessingChain().getChannelState()
|
||||
.getMessageActivityModel().clear();
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
public class MessageFilterButton extends JideButton
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public MessageFilterButton()
|
||||
{
|
||||
super( "Filter" );
|
||||
|
||||
addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent arg0 )
|
||||
{
|
||||
if( mDisplayedChannel == null )
|
||||
{
|
||||
JOptionPane.showMessageDialog( MessageFilterButton.this,
|
||||
"Please enable and select a decoding channel to "
|
||||
+ "adjust the channel's message display filter" );
|
||||
}
|
||||
else
|
||||
{
|
||||
final JFrame editor = new JFrame();
|
||||
|
||||
editor.setTitle( "Message Filter Editor" );
|
||||
editor.setSize( 600, 400 );
|
||||
editor.setLocationRelativeTo( MessageFilterButton.this );
|
||||
editor.setDefaultCloseOperation( JFrame.DISPOSE_ON_CLOSE );
|
||||
editor.setLayout( new MigLayout( "", "[grow,fill]",
|
||||
"[grow,fill][][]" ) );
|
||||
|
||||
@SuppressWarnings( "unchecked" )
|
||||
FilterSet<Message> filter =
|
||||
mDisplayedChannel
|
||||
.getProcessingChain().getChannelState()
|
||||
.getMessageActivityModel().getMessageFilter();
|
||||
|
||||
FilterEditorPanel<Message> panel =
|
||||
new FilterEditorPanel<Message>( filter );
|
||||
|
||||
JScrollPane scroller = new JScrollPane( panel );
|
||||
scroller.setViewportView( panel );
|
||||
|
||||
editor.add( scroller, "wrap" );
|
||||
|
||||
editor.add( new JLabel( "Right-click to select/deselect "
|
||||
+ "all nodes" ), "wrap" );
|
||||
|
||||
JButton close = new JButton( "Close" );
|
||||
close.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
editor.dispose();
|
||||
}
|
||||
} );
|
||||
|
||||
editor.add( close );
|
||||
|
||||
EventQueue.invokeLater( new Runnable()
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
editor.setVisible( true );
|
||||
}
|
||||
} );
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import java.util.concurrent.TimeUnit;
|
||||
import javax.swing.JTable;
|
||||
|
||||
import message.Message;
|
||||
import message.MessageFilterFactory;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -45,6 +46,7 @@ import controller.activity.CallEventModel;
|
||||
import controller.activity.MessageActivityModel;
|
||||
import controller.channel.Channel.ChannelType;
|
||||
import controller.channel.ProcessingChain;
|
||||
import filter.FilterSet;
|
||||
|
||||
/**
|
||||
* ChannelState provides a state machine for tracking a voice or data call
|
||||
@@ -108,8 +110,7 @@ public abstract class ChannelState implements Listener<Message>
|
||||
|
||||
protected JTable mCallEventTable;
|
||||
|
||||
protected MessageActivityModel mMessageActivityModel =
|
||||
new MessageActivityModel();
|
||||
protected MessageActivityModel mMessageActivityModel;
|
||||
protected JTable mMessageActivityTable;
|
||||
|
||||
protected ProcessingChain mProcessingChain;
|
||||
@@ -130,6 +131,12 @@ public abstract class ChannelState implements Listener<Message>
|
||||
SystemProperties props = SystemProperties.getInstance();
|
||||
mCallFadeTimeout = props.get( "call.fade.timeout", 2000 );
|
||||
mCallResetTimeout = props.get( "call.reset.timeout", 4000 );
|
||||
|
||||
/* Get a message filter for the primary decoder and aux decoders */
|
||||
FilterSet messageFilter = MessageFilterFactory
|
||||
.getMessageFilter( mProcessingChain.getChannel() );
|
||||
|
||||
mMessageActivityModel = new MessageActivityModel( messageFilter );
|
||||
}
|
||||
|
||||
public void setCurrentCallEvent( CallEvent callEvent )
|
||||
@@ -240,20 +247,11 @@ public abstract class ChannelState implements Listener<Message>
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the message activity model wrapped in a JTable. Although this
|
||||
* may seem to violate separation between model and view, it simplifies
|
||||
* retaining the JTable state for each channel by keeping a local reference
|
||||
* to reuse
|
||||
* Returns the message activity model.
|
||||
*/
|
||||
public JTable getMessageActivityTable()
|
||||
public MessageActivityModel getMessageActivityModel()
|
||||
{
|
||||
if( mMessageActivityTable == null )
|
||||
{
|
||||
mMessageActivityTable = new JTable( mMessageActivityModel );
|
||||
mMessageActivityTable.setAutoResizeMode( JTable.AUTO_RESIZE_LAST_COLUMN );
|
||||
}
|
||||
|
||||
return mMessageActivityTable;
|
||||
return mMessageActivityModel;
|
||||
}
|
||||
|
||||
public void addAuxChannelState( AuxChannelState state )
|
||||
|
||||
@@ -67,7 +67,7 @@ public enum DecoderType
|
||||
DecoderType.LTR_STANDARD,
|
||||
DecoderType.MPT1327,
|
||||
DecoderType.NBFM,
|
||||
DecoderType.P25_PHASE1,
|
||||
// DecoderType.P25_PHASE1,
|
||||
DecoderType.PASSPORT );
|
||||
}
|
||||
|
||||
|
||||
56
src/decode/fleetsync2/FleetsyncMessageFilter.java
Normal file
56
src/decode/fleetsync2/FleetsyncMessageFilter.java
Normal file
@@ -0,0 +1,56 @@
|
||||
package decode.fleetsync2;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import message.Message;
|
||||
import filter.Filter;
|
||||
import filter.FilterElement;
|
||||
|
||||
public class FleetsyncMessageFilter extends Filter<Message>
|
||||
{
|
||||
private HashMap<FleetsyncMessageType, FilterElement<FleetsyncMessageType>> mElements =
|
||||
new HashMap<FleetsyncMessageType, FilterElement<FleetsyncMessageType>>();
|
||||
|
||||
public FleetsyncMessageFilter()
|
||||
{
|
||||
super( "Fleetsync Message Filter" );
|
||||
|
||||
for( FleetsyncMessageType type: FleetsyncMessageType.values() )
|
||||
{
|
||||
if( type != FleetsyncMessageType.UNKNOWN )
|
||||
{
|
||||
mElements.put( type, new FilterElement<FleetsyncMessageType>( type ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean passes( Message message )
|
||||
{
|
||||
if( mEnabled && canProcess( message ) )
|
||||
{
|
||||
FleetsyncMessage fleet = (FleetsyncMessage)message;
|
||||
|
||||
if( mElements.containsKey( fleet.getMessageType() ) )
|
||||
{
|
||||
return mElements.get( fleet.getMessageType() ).isEnabled();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canProcess( Message message )
|
||||
{
|
||||
return message instanceof FleetsyncMessage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FilterElement<?>> getFilterElements()
|
||||
{
|
||||
return new ArrayList<FilterElement<?>>( mElements.values() );
|
||||
}
|
||||
}
|
||||
35
src/decode/lj1200/LJ1200MessageFilter.java
Normal file
35
src/decode/lj1200/LJ1200MessageFilter.java
Normal file
@@ -0,0 +1,35 @@
|
||||
package decode.lj1200;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import message.Message;
|
||||
import filter.Filter;
|
||||
import filter.FilterElement;
|
||||
|
||||
public class LJ1200MessageFilter extends Filter<Message>
|
||||
{
|
||||
|
||||
public LJ1200MessageFilter()
|
||||
{
|
||||
super( "LJ-1200 Message Filter" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean passes( Message message )
|
||||
{
|
||||
return mEnabled && canProcess( message );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canProcess( Message message )
|
||||
{
|
||||
return message instanceof LJ1200Message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FilterElement<?>> getFilterElements()
|
||||
{
|
||||
return Collections.EMPTY_LIST;
|
||||
}
|
||||
}
|
||||
80
src/decode/ltrnet/LTRNetMessageFilter.java
Normal file
80
src/decode/ltrnet/LTRNetMessageFilter.java
Normal file
@@ -0,0 +1,80 @@
|
||||
package decode.ltrnet;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import message.Message;
|
||||
import message.MessageType;
|
||||
import filter.Filter;
|
||||
import filter.FilterElement;
|
||||
|
||||
public class LTRNetMessageFilter extends Filter<Message>
|
||||
{
|
||||
private HashMap<MessageType, FilterElement<MessageType>> mElements =
|
||||
new HashMap<MessageType, FilterElement<MessageType>>();
|
||||
|
||||
public LTRNetMessageFilter()
|
||||
{
|
||||
super( "LTR-Net Message Filter" );
|
||||
|
||||
mElements.put( MessageType.CA_STRT,
|
||||
new FilterElement<MessageType>( MessageType.CA_STRT ) );
|
||||
mElements.put( MessageType.CA_ENDD,
|
||||
new FilterElement<MessageType>( MessageType.CA_ENDD ) );
|
||||
mElements.put( MessageType.SY_IDLE,
|
||||
new FilterElement<MessageType>( MessageType.SY_IDLE ) );
|
||||
mElements.put( MessageType.ID_UNIQ,
|
||||
new FilterElement<MessageType>( MessageType.ID_UNIQ ) );
|
||||
mElements.put( MessageType.ID_ESNH,
|
||||
new FilterElement<MessageType>( MessageType.ID_ESNH ) );
|
||||
mElements.put( MessageType.ID_ESNL,
|
||||
new FilterElement<MessageType>( MessageType.ID_ESNL ) );
|
||||
mElements.put( MessageType.RQ_ACCE,
|
||||
new FilterElement<MessageType>( MessageType.RQ_ACCE ) );
|
||||
mElements.put( MessageType.ID_SITE,
|
||||
new FilterElement<MessageType>( MessageType.ID_SITE ) );
|
||||
mElements.put( MessageType.FQ_RXHI,
|
||||
new FilterElement<MessageType>( MessageType.FQ_RXHI ) );
|
||||
mElements.put( MessageType.FQ_RXLO,
|
||||
new FilterElement<MessageType>( MessageType.FQ_RXLO ) );
|
||||
mElements.put( MessageType.FQ_TXHI,
|
||||
new FilterElement<MessageType>( MessageType.FQ_TXHI ) );
|
||||
mElements.put( MessageType.FQ_TXLO,
|
||||
new FilterElement<MessageType>( MessageType.FQ_TXLO ) );
|
||||
mElements.put( MessageType.ID_NBOR,
|
||||
new FilterElement<MessageType>( MessageType.ID_NBOR ) );
|
||||
mElements.put( MessageType.MA_CHNH,
|
||||
new FilterElement<MessageType>( MessageType.MA_CHNH ) );
|
||||
mElements.put( MessageType.MA_CHNL,
|
||||
new FilterElement<MessageType>( MessageType.MA_CHNL ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean passes( Message message )
|
||||
{
|
||||
if( mEnabled && canProcess( message ) )
|
||||
{
|
||||
LTRNetMessage ltr = (LTRNetMessage)message;
|
||||
|
||||
if( mElements.containsKey( ltr.getMessageType() ) )
|
||||
{
|
||||
return mElements.get( ltr.getMessageType() ).isEnabled();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canProcess( Message message )
|
||||
{
|
||||
return message instanceof LTRNetMessage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FilterElement<?>> getFilterElements()
|
||||
{
|
||||
return new ArrayList<FilterElement<?>>( mElements.values() );
|
||||
}
|
||||
}
|
||||
56
src/decode/ltrstandard/LTRStandardMessageFilter.java
Normal file
56
src/decode/ltrstandard/LTRStandardMessageFilter.java
Normal file
@@ -0,0 +1,56 @@
|
||||
package decode.ltrstandard;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import message.Message;
|
||||
import message.MessageType;
|
||||
import filter.Filter;
|
||||
import filter.FilterElement;
|
||||
|
||||
public class LTRStandardMessageFilter extends Filter<Message>
|
||||
{
|
||||
private HashMap<MessageType, FilterElement<MessageType>> mElements =
|
||||
new HashMap<MessageType, FilterElement<MessageType>>();
|
||||
|
||||
public LTRStandardMessageFilter()
|
||||
{
|
||||
super( "LTR Message Filter" );
|
||||
|
||||
mElements.put( MessageType.CA_STRT,
|
||||
new FilterElement<MessageType>( MessageType.CA_STRT ) );
|
||||
mElements.put( MessageType.CA_ENDD,
|
||||
new FilterElement<MessageType>( MessageType.CA_ENDD ) );
|
||||
mElements.put( MessageType.SY_IDLE,
|
||||
new FilterElement<MessageType>( MessageType.SY_IDLE ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean passes( Message message )
|
||||
{
|
||||
if( mEnabled && canProcess( message ) )
|
||||
{
|
||||
LTRStandardMessage ltr = (LTRStandardMessage)message;
|
||||
|
||||
if( mElements.containsKey( ltr.getMessageType() ) )
|
||||
{
|
||||
return mElements.get( ltr.getMessageType() ).isEnabled();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canProcess( Message message )
|
||||
{
|
||||
return message instanceof LTRStandardMessage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FilterElement<?>> getFilterElements()
|
||||
{
|
||||
return new ArrayList<FilterElement<?>>( mElements.values() );
|
||||
}
|
||||
}
|
||||
56
src/decode/mdc1200/MDCMessageFilter.java
Normal file
56
src/decode/mdc1200/MDCMessageFilter.java
Normal file
@@ -0,0 +1,56 @@
|
||||
package decode.mdc1200;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import message.Message;
|
||||
import filter.Filter;
|
||||
import filter.FilterElement;
|
||||
|
||||
public class MDCMessageFilter extends Filter<Message>
|
||||
{
|
||||
private HashMap<MDCMessageType, FilterElement<MDCMessageType>> mElements =
|
||||
new HashMap<MDCMessageType, FilterElement<MDCMessageType>>();
|
||||
|
||||
public MDCMessageFilter()
|
||||
{
|
||||
super( "MDC-1200 Message Filter" );
|
||||
|
||||
for( MDCMessageType type: MDCMessageType.values() )
|
||||
{
|
||||
if( type != MDCMessageType.UNKNOWN )
|
||||
{
|
||||
mElements.put( type, new FilterElement<MDCMessageType>( type ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean passes( Message message )
|
||||
{
|
||||
if( mEnabled && canProcess( message ) )
|
||||
{
|
||||
MDCMessage mdc = (MDCMessage)message;
|
||||
|
||||
if( mElements.containsKey( mdc.getMessageType() ) )
|
||||
{
|
||||
return mElements.get( mdc.getMessageType() ).isEnabled();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canProcess( Message message )
|
||||
{
|
||||
return message instanceof MDCMessage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FilterElement<?>> getFilterElements()
|
||||
{
|
||||
return new ArrayList<FilterElement<?>>( mElements.values() );
|
||||
}
|
||||
}
|
||||
@@ -1930,6 +1930,11 @@ public class MPT1327Message extends Message
|
||||
{
|
||||
return mDescription;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return getDescription();
|
||||
}
|
||||
|
||||
public static MPTMessageType fromNumber( int number )
|
||||
{
|
||||
|
||||
62
src/decode/mpt1327/MPT1327MessageFilter.java
Normal file
62
src/decode/mpt1327/MPT1327MessageFilter.java
Normal file
@@ -0,0 +1,62 @@
|
||||
package decode.mpt1327;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import message.Message;
|
||||
import decode.mpt1327.MPT1327Message.MPTMessageType;
|
||||
import filter.Filter;
|
||||
import filter.FilterElement;
|
||||
|
||||
public class MPT1327MessageFilter extends Filter<Message>
|
||||
{
|
||||
private HashMap<MPTMessageType,FilterElement<MPTMessageType>> mFilterElements =
|
||||
new HashMap<MPTMessageType,FilterElement<MPTMessageType>>();
|
||||
|
||||
public MPT1327MessageFilter()
|
||||
{
|
||||
super( "MPT1327 Message Type Filter" );
|
||||
|
||||
for( MPTMessageType type: MPT1327Message.MPTMessageType.values() )
|
||||
{
|
||||
if( type != MPTMessageType.UNKN )
|
||||
{
|
||||
mFilterElements.put( type,
|
||||
new FilterElement<MPTMessageType>( type ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean passes( Message message )
|
||||
{
|
||||
if( mEnabled && canProcess( message ) )
|
||||
{
|
||||
MPT1327Message mpt = (MPT1327Message)message;
|
||||
|
||||
FilterElement<MPTMessageType> element =
|
||||
mFilterElements.get( mpt.getMessageType() );
|
||||
|
||||
if( element != null )
|
||||
{
|
||||
return element.isEnabled();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canProcess( Message message )
|
||||
{
|
||||
return message instanceof MPT1327Message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FilterElement<?>> getFilterElements()
|
||||
{
|
||||
return new ArrayList<FilterElement<?>>( mFilterElements.values() );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package decode.p25;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
|
||||
import message.Message;
|
||||
@@ -8,12 +7,9 @@ import message.Message;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import bits.BitSetBuffer;
|
||||
import sample.Broadcaster;
|
||||
import sample.Listener;
|
||||
import alias.AliasList;
|
||||
import decode.mpt1327.MPT1327Message;
|
||||
import decode.p25.message.tsbk.TSBKMessage;
|
||||
import decode.p25.message.tsbk.osp.control.IdentifierUpdate;
|
||||
import decode.p25.message.tsbk.osp.control.IdentifierUpdateReceiver;
|
||||
|
||||
|
||||
23
src/decode/p25/message/filter/P25MessageFilterSet.java
Normal file
23
src/decode/p25/message/filter/P25MessageFilterSet.java
Normal file
@@ -0,0 +1,23 @@
|
||||
package decode.p25.message.filter;
|
||||
|
||||
import message.Message;
|
||||
import decode.p25.message.P25Message;
|
||||
import filter.FilterSet;
|
||||
|
||||
public class P25MessageFilterSet extends FilterSet<Message>
|
||||
{
|
||||
public P25MessageFilterSet()
|
||||
{
|
||||
super( "P25 Message Filter" );
|
||||
|
||||
addFilter( new PDUMessageFilter() );
|
||||
addFilter( new TDUMessageFilter() );
|
||||
addFilter( new TSBKMessageFilter() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canProcess( Message message )
|
||||
{
|
||||
return message instanceof P25Message;
|
||||
}
|
||||
}
|
||||
54
src/decode/p25/message/filter/PDUMessageFilter.java
Normal file
54
src/decode/p25/message/filter/PDUMessageFilter.java
Normal file
@@ -0,0 +1,54 @@
|
||||
package decode.p25.message.filter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import message.Message;
|
||||
import decode.p25.message.pdu.PDUMessage;
|
||||
import decode.p25.reference.Opcode;
|
||||
import filter.Filter;
|
||||
import filter.FilterElement;
|
||||
|
||||
public class PDUMessageFilter extends Filter<Message>
|
||||
{
|
||||
private HashMap<Opcode,FilterElement<Opcode>> mOpcodeFilterElements =
|
||||
new HashMap<Opcode,FilterElement<Opcode>>();
|
||||
|
||||
public PDUMessageFilter()
|
||||
{
|
||||
super( "PDU - Packet Data Unit" );
|
||||
|
||||
for( Opcode opcode: Opcode.values() )
|
||||
{
|
||||
mOpcodeFilterElements.put( opcode, new FilterElement<Opcode>( opcode ) );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean passes( Message message )
|
||||
{
|
||||
if( mEnabled && message instanceof PDUMessage )
|
||||
{
|
||||
PDUMessage pdu = (PDUMessage)message;
|
||||
|
||||
Opcode opcode = pdu.getOpcode();
|
||||
|
||||
return mOpcodeFilterElements.get( opcode ).isEnabled();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canProcess( Message message )
|
||||
{
|
||||
return message instanceof PDUMessage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FilterElement<?>> getFilterElements()
|
||||
{
|
||||
return new ArrayList<FilterElement<?>>( mOpcodeFilterElements.values() );
|
||||
}
|
||||
}
|
||||
35
src/decode/p25/message/filter/TDUMessageFilter.java
Normal file
35
src/decode/p25/message/filter/TDUMessageFilter.java
Normal file
@@ -0,0 +1,35 @@
|
||||
package decode.p25.message.filter;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import message.Message;
|
||||
import decode.p25.message.tdu.TDUMessage;
|
||||
import filter.Filter;
|
||||
import filter.FilterElement;
|
||||
|
||||
public class TDUMessageFilter extends Filter<Message>
|
||||
{
|
||||
public TDUMessageFilter()
|
||||
{
|
||||
super( "TDU Terminator Data Unit" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean passes( Message message )
|
||||
{
|
||||
return mEnabled && canProcess( message );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canProcess( Message message )
|
||||
{
|
||||
return message instanceof TDUMessage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FilterElement<?>> getFilterElements()
|
||||
{
|
||||
return Collections.EMPTY_LIST;
|
||||
}
|
||||
}
|
||||
54
src/decode/p25/message/filter/TSBKMessageFilter.java
Normal file
54
src/decode/p25/message/filter/TSBKMessageFilter.java
Normal file
@@ -0,0 +1,54 @@
|
||||
package decode.p25.message.filter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import message.Message;
|
||||
import decode.p25.message.tsbk.TSBKMessage;
|
||||
import decode.p25.reference.Opcode;
|
||||
import filter.Filter;
|
||||
import filter.FilterElement;
|
||||
|
||||
public class TSBKMessageFilter extends Filter<Message>
|
||||
{
|
||||
private HashMap<Opcode,FilterElement<Opcode>> mFilterElements =
|
||||
new HashMap<Opcode,FilterElement<Opcode>>();
|
||||
|
||||
public TSBKMessageFilter()
|
||||
{
|
||||
super( "TSBK Trunking Signalling Block" );
|
||||
|
||||
for( Opcode opcode: Opcode.values() )
|
||||
{
|
||||
mFilterElements.put( opcode, new FilterElement<Opcode>( opcode ) );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean passes( Message message )
|
||||
{
|
||||
if( mEnabled && canProcess( message ) )
|
||||
{
|
||||
TSBKMessage tsbk = (TSBKMessage)message;
|
||||
|
||||
Opcode opcode = tsbk.getOpcode();
|
||||
|
||||
return mFilterElements.get( opcode ).isEnabled();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canProcess( Message message )
|
||||
{
|
||||
return message instanceof TSBKMessage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FilterElement<?>> getFilterElements()
|
||||
{
|
||||
return new ArrayList<FilterElement<?>>( mFilterElements.values() );
|
||||
}
|
||||
}
|
||||
68
src/decode/passport/PassportMessageFilter.java
Normal file
68
src/decode/passport/PassportMessageFilter.java
Normal file
@@ -0,0 +1,68 @@
|
||||
package decode.passport;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import message.Message;
|
||||
import message.MessageType;
|
||||
import filter.Filter;
|
||||
import filter.FilterElement;
|
||||
|
||||
public class PassportMessageFilter extends Filter<Message>
|
||||
{
|
||||
private HashMap<MessageType, FilterElement<MessageType>> mElements =
|
||||
new HashMap<MessageType, FilterElement<MessageType>>();
|
||||
|
||||
public PassportMessageFilter()
|
||||
{
|
||||
super( "Passport Message Filter" );
|
||||
|
||||
mElements.put( MessageType.CA_STRT,
|
||||
new FilterElement<MessageType>( MessageType.CA_STRT ) );
|
||||
mElements.put( MessageType.CA_ENDD,
|
||||
new FilterElement<MessageType>( MessageType.CA_ENDD ) );
|
||||
mElements.put( MessageType.SY_IDLE,
|
||||
new FilterElement<MessageType>( MessageType.SY_IDLE ) );
|
||||
mElements.put( MessageType.ID_TGAS,
|
||||
new FilterElement<MessageType>( MessageType.ID_TGAS ) );
|
||||
mElements.put( MessageType.ID_ESNH,
|
||||
new FilterElement<MessageType>( MessageType.ID_ESNH ) );
|
||||
mElements.put( MessageType.CA_PAGE,
|
||||
new FilterElement<MessageType>( MessageType.CA_PAGE ) );
|
||||
mElements.put( MessageType.ID_RDIO,
|
||||
new FilterElement<MessageType>( MessageType.ID_RDIO ) );
|
||||
mElements.put( MessageType.DA_STRT,
|
||||
new FilterElement<MessageType>( MessageType.DA_STRT ) );
|
||||
mElements.put( MessageType.RA_REGI,
|
||||
new FilterElement<MessageType>( MessageType.RA_REGI ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean passes( Message message )
|
||||
{
|
||||
if( mEnabled && canProcess( message ) )
|
||||
{
|
||||
PassportMessage passport = (PassportMessage)message;
|
||||
|
||||
if( mElements.containsKey( passport.getMessageType() ) )
|
||||
{
|
||||
return mElements.get( passport.getMessageType() ).isEnabled();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canProcess( Message message )
|
||||
{
|
||||
return message instanceof PassportMessage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FilterElement<?>> getFilterElements()
|
||||
{
|
||||
return new ArrayList<FilterElement<?>>( mElements.values() );
|
||||
}
|
||||
}
|
||||
35
src/filter/AllPassFilter.java
Normal file
35
src/filter/AllPassFilter.java
Normal 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
55
src/filter/Filter.java
Normal 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;
|
||||
}
|
||||
}
|
||||
400
src/filter/FilterEditorPanel.java
Normal file
400
src/filter/FilterEditorPanel.java
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
49
src/filter/FilterElement.java
Normal file
49
src/filter/FilterElement.java
Normal 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
97
src/filter/FilterSet.java
Normal 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
36
src/filter/IFilter.java
Normal 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();
|
||||
}
|
||||
111
src/message/MessageFilterFactory.java
Normal file
111
src/message/MessageFilterFactory.java
Normal file
@@ -0,0 +1,111 @@
|
||||
package message;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import controller.channel.Channel;
|
||||
import decode.DecoderType;
|
||||
import decode.config.AuxDecodeConfiguration;
|
||||
import decode.fleetsync2.FleetsyncMessageFilter;
|
||||
import decode.lj1200.LJ1200MessageFilter;
|
||||
import decode.ltrnet.LTRNetMessageFilter;
|
||||
import decode.ltrstandard.LTRStandardMessageFilter;
|
||||
import decode.mdc1200.MDCMessageFilter;
|
||||
import decode.mpt1327.MPT1327MessageFilter;
|
||||
import decode.p25.message.filter.P25MessageFilterSet;
|
||||
import decode.passport.PassportMessageFilter;
|
||||
import filter.AllPassFilter;
|
||||
import filter.FilterSet;
|
||||
import filter.IFilter;
|
||||
|
||||
/**
|
||||
* Constructs message filters for each of the decoder types
|
||||
*/
|
||||
public class MessageFilterFactory
|
||||
{
|
||||
/**
|
||||
* Assembles a filter set containing filters for the primary channel
|
||||
* decoder and each of the auxiliary decoders
|
||||
*/
|
||||
public static FilterSet<Message> getMessageFilter( Channel channel )
|
||||
{
|
||||
FilterSet<Message> filterSet = new FilterSet<Message>(
|
||||
"Message Filter: " + channel.getChannelDisplayName() );
|
||||
|
||||
filterSet.addFilters( getMessageFilters(
|
||||
channel.getDecodeConfiguration().getDecoderType() ) );
|
||||
|
||||
AuxDecodeConfiguration auxConfig = channel.getAuxDecodeConfiguration();
|
||||
|
||||
for( DecoderType decoderType: auxConfig.getAuxDecoders() )
|
||||
{
|
||||
filterSet.addFilters( getMessageFilters( decoderType ) );
|
||||
}
|
||||
|
||||
/* If we don't have any filters, add an ALL-PASS filter */
|
||||
if( filterSet.getFilters().isEmpty() )
|
||||
{
|
||||
filterSet.addFilter( new AllPassFilter<Message>() );
|
||||
}
|
||||
|
||||
return filterSet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a set of IMessageFilter objects (FilterSets or Filters) that
|
||||
* can process all of the messages produced by the specified decoder type.
|
||||
*/
|
||||
public static List<IFilter<Message>> getMessageFilters( DecoderType decoder )
|
||||
{
|
||||
ArrayList<IFilter<Message>> filters = new ArrayList<IFilter<Message>>();
|
||||
|
||||
switch( decoder )
|
||||
{
|
||||
case ACARS:
|
||||
break;
|
||||
case AIS:
|
||||
break;
|
||||
case AM:
|
||||
break;
|
||||
case APRS:
|
||||
break;
|
||||
case DMR:
|
||||
break;
|
||||
case FLEETSYNC2:
|
||||
filters.add( new FleetsyncMessageFilter() );
|
||||
break;
|
||||
case LJ_1200:
|
||||
filters.add( new LJ1200MessageFilter() );
|
||||
break;
|
||||
case LTR_NET:
|
||||
filters.add( new LTRNetMessageFilter() );
|
||||
break;
|
||||
case LTR_STANDARD:
|
||||
filters.add( new LTRStandardMessageFilter() );
|
||||
break;
|
||||
case MDC1200:
|
||||
filters.add( new MDCMessageFilter() );
|
||||
break;
|
||||
case MOTOROLA_TYPE_2:
|
||||
break;
|
||||
case MPT1327:
|
||||
filters.add( new MPT1327MessageFilter() );
|
||||
break;
|
||||
case NBFM:
|
||||
break;
|
||||
case NXDN:
|
||||
break;
|
||||
case P25_PHASE1:
|
||||
case P25_PHASE2:
|
||||
filters.add( new P25MessageFilterSet() );
|
||||
break;
|
||||
case PASSPORT:
|
||||
filters.add( new PassportMessageFilter() );
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return filters;
|
||||
}
|
||||
}
|
||||
@@ -71,4 +71,9 @@ public enum MessageType
|
||||
{
|
||||
return mDisplayText;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return getDisplayText();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user