/******************************************************************************* * sdrtrunk * Copyright (C) 2014-2017 Dennis Sheirer * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/> * ******************************************************************************/ package channel.metadata; import alias.Alias; import channel.state.State; import controller.channel.Channel; import controller.channel.ChannelProcessingManager; import controller.channel.ChannelUtils; import icon.IconManager; import module.ProcessingChain; import net.miginfocom.swing.MigLayout; import org.apache.commons.lang3.Validate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import properties.SystemProperties; import sample.Broadcaster; import sample.Listener; import javax.swing.*; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import javax.swing.table.DefaultTableCellRenderer; import java.awt.*; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; public class ChannelMetadataPanel extends JPanel implements ListSelectionListener { private final static Logger mLog = LoggerFactory.getLogger(ChannelMetadataPanel.class); private static final String PROPERTY_PREFIX_BACKGROUND = "channel.metadata.panel.state.color."; private static final String PROPERTY_PREFIX_FOREGROUND = "channel.metadata.panel.text.color."; private ChannelProcessingManager mChannelProcessingManager; private IconManager mIconManager; private JTable mTable; private Broadcaster<ProcessingChain> mSelectedProcessingChainBroadcaster = new Broadcaster<>(); /** * Table view for currently decoding channel metadata */ public ChannelMetadataPanel(ChannelProcessingManager channelProcessingManager, IconManager iconManager) { mIconManager = iconManager; mChannelProcessingManager = channelProcessingManager; init(); } /** * Initializes the panel */ private void init() { setLayout( new MigLayout( "insets 0 0 0 0", "[grow,fill]", "[grow,fill]") ); mTable = new JTable(mChannelProcessingManager.getChannelMetadataModel()); DefaultTableCellRenderer renderer = (DefaultTableCellRenderer)mTable.getDefaultRenderer(String.class); renderer.setHorizontalAlignment(SwingConstants.CENTER); mTable.getSelectionModel().addListSelectionListener(this); mTable.addMouseListener(new MouseSupport()); mTable.getColumnModel().getColumn(ChannelMetadataModel.COLUMN_STATE) .setCellRenderer(new ColoredStateCellRenderer()); mTable.getColumnModel().getColumn(ChannelMetadataModel.COLUMN_PRIMARY_TO) .setCellRenderer(new AliasedValueCellRenderer(Attribute.PRIMARY_ADDRESS_TO)); mTable.getColumnModel().getColumn(ChannelMetadataModel.COLUMN_PRIMARY_FROM) .setCellRenderer(new AliasedValueCellRenderer(Attribute.PRIMARY_ADDRESS_FROM)); mTable.getColumnModel().getColumn(ChannelMetadataModel.COLUMN_SECONDARY_TO) .setCellRenderer(new AliasedValueCellRenderer(Attribute.SECONDARY_ADDRESS_TO)); mTable.getColumnModel().getColumn(ChannelMetadataModel.COLUMN_SECONDARY_FROM) .setCellRenderer(new AliasedValueCellRenderer(Attribute.SECONDARY_ADDRESS_FROM)); JScrollPane scrollPane = new JScrollPane(mTable, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); add(scrollPane); // new TableColumnWidthMonitor(mTable, PROPERTY_PREFIX, new int[] {15,15,15,15,25,25,25,25,15,40}); } @Override public void valueChanged(ListSelectionEvent e) { if(!mTable.getSelectionModel().getValueIsAdjusting()) { ProcessingChain processingChain = null; int selectedViewRow = mTable.getSelectedRow(); if(selectedViewRow >= 0) { int selectedModelRow = mTable.convertRowIndexToModel(selectedViewRow); Metadata selectedMetadata = mChannelProcessingManager.getChannelMetadataModel() .getMetadata(selectedModelRow); if(selectedMetadata != null) { Channel selectedChannel = mChannelProcessingManager.getChannelMetadataModel() .getChannelFromMetadata(selectedMetadata); processingChain = mChannelProcessingManager.getProcessingChain(selectedChannel); } } mSelectedProcessingChainBroadcaster.broadcast(processingChain); } } /** * Adds the listener to receive the processing chain associated with the metadata selected in the * metadata table. */ public void addProcessingChainSelectionListener(Listener<ProcessingChain> listener) { mSelectedProcessingChainBroadcaster.addListener(listener); } public class AliasedValueCellRenderer extends DefaultTableCellRenderer { private Attribute mAttribute; public AliasedValueCellRenderer(Attribute attribute) { Validate.isTrue(attribute != null); mAttribute = attribute; setHorizontalAlignment(JLabel.CENTER); } @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { JLabel label = (JLabel)super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); Metadata metadata = (Metadata)value; String value1 = metadata.getValue(mAttribute); Alias alias = metadata.getAlias(mAttribute); label.setText(alias != null ? alias.getName() : value1); label.setIcon(alias != null ? mIconManager.getIcon(alias.getIconName(), IconManager.DEFAULT_ICON_SIZE) : null); label.setForeground(alias != null ? alias.getDisplayColor() : table.getForeground()); return label; } } public class ColoredStateCellRenderer extends DefaultTableCellRenderer { public ColoredStateCellRenderer() { setHorizontalAlignment(SwingConstants.CENTER); } @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { JLabel label = (JLabel)super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); Color background = table.getBackground(); Color foreground = table.getForeground(); if(value instanceof State) { State state = (State)value; label.setText(state.getDisplayValue()); switch(state) { case CALL: background = SystemProperties.getInstance().get(PROPERTY_PREFIX_BACKGROUND + "call", Color.BLUE); foreground = SystemProperties.getInstance().get(PROPERTY_PREFIX_FOREGROUND + "call", Color.YELLOW); break; case CONTROL: background = SystemProperties.getInstance().get(PROPERTY_PREFIX_BACKGROUND + "control", Color.ORANGE); foreground = SystemProperties.getInstance().get(PROPERTY_PREFIX_FOREGROUND + "control", Color.BLUE); break; case DATA: background = SystemProperties.getInstance().get(PROPERTY_PREFIX_BACKGROUND + "data", Color.GREEN); foreground = SystemProperties.getInstance().get(PROPERTY_PREFIX_FOREGROUND + "data", Color.BLUE); break; case ENCRYPTED: background = SystemProperties.getInstance().get(PROPERTY_PREFIX_BACKGROUND + "encrypted", Color.MAGENTA); foreground = SystemProperties.getInstance().get(PROPERTY_PREFIX_FOREGROUND + "encrypted", Color.WHITE); break; case FADE: background = SystemProperties.getInstance().get(PROPERTY_PREFIX_BACKGROUND + "fade", Color.LIGHT_GRAY.BLUE); foreground = SystemProperties.getInstance().get(PROPERTY_PREFIX_FOREGROUND + "fade", Color.YELLOW); break; case IDLE: background = SystemProperties.getInstance().get(PROPERTY_PREFIX_BACKGROUND + "idle", Color.WHITE); foreground = SystemProperties.getInstance().get(PROPERTY_PREFIX_FOREGROUND + "idle", Color.BLUE); break; case OVERFLOW: background = SystemProperties.getInstance().get(PROPERTY_PREFIX_BACKGROUND + "overflow", Color.RED); foreground = SystemProperties.getInstance().get(PROPERTY_PREFIX_FOREGROUND + "overflow", Color.YELLOW); break; case RESET: background = SystemProperties.getInstance().get(PROPERTY_PREFIX_BACKGROUND + "reset", Color.PINK); foreground = SystemProperties.getInstance().get(PROPERTY_PREFIX_FOREGROUND + "reset", Color.YELLOW); break; case TEARDOWN: background = SystemProperties.getInstance().get(PROPERTY_PREFIX_BACKGROUND + "teardown", Color.DARK_GRAY); foreground = SystemProperties.getInstance().get(PROPERTY_PREFIX_FOREGROUND + "teardown", Color.WHITE); break; } } else { setText(""); } setBackground(background); setForeground(foreground); return label; } } public class MouseSupport extends MouseAdapter { @Override public void mouseClicked(MouseEvent e) { if(e.getButton() == MouseEvent.BUTTON3) //Right click for context { JPopupMenu popupMenu = new JPopupMenu(); boolean populated = false; int viewRowIndex = mTable.rowAtPoint(e.getPoint()); if(viewRowIndex >= 0) { int modelRowIndex = mTable.convertRowIndexToModel(viewRowIndex); if(modelRowIndex >= 0) { Metadata metadata = mChannelProcessingManager.getChannelMetadataModel().getMetadata(modelRowIndex); if(metadata != null) { Channel channel = mChannelProcessingManager.getChannelMetadataModel() .getChannelFromMetadata(metadata); if(channel != null) { popupMenu.add(ChannelUtils.getContextMenu(mChannelProcessingManager.getChannelModel(), mChannelProcessingManager, channel, mTable)); populated = true; } } } } if(!populated) { popupMenu.add(new JMenuItem("No Actions Available")); } popupMenu.show(mTable, e.getX(), e.getY()); } } } }