mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-11 08:07:24 -05:00
Compare commits
10 Commits
v0.4.0-alp
...
v0.4.0-alp
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
712eb07f4b | ||
|
|
d5c3ecc7df | ||
|
|
c4bf089667 | ||
|
|
378b03e06e | ||
|
|
34235382fb | ||
|
|
c05aff0768 | ||
|
|
f0c3e0fd1a | ||
|
|
d601cbda0e | ||
|
|
2653dc6b38 | ||
|
|
48cbbfc656 |
@@ -31,7 +31,7 @@ plugins {
|
||||
id 'java'
|
||||
id 'idea'
|
||||
id 'org.openjfx.javafxplugin' version '0.0.6'
|
||||
id 'org.beryx.runtime' version '1.1.1'
|
||||
id 'org.beryx.runtime' version '1.1.2'
|
||||
}
|
||||
|
||||
repositories {
|
||||
@@ -39,7 +39,7 @@ repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
version = '0.4.0-alpha.7'
|
||||
version = '0.4.0-alpha.8'
|
||||
sourceCompatibility = '11'
|
||||
|
||||
sourceSets {
|
||||
|
||||
@@ -1,34 +1,67 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2019 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 io.github.dsheirer.alias;
|
||||
|
||||
import com.jidesoft.swing.JideSplitPane;
|
||||
import io.github.dsheirer.audio.broadcast.BroadcastModel;
|
||||
import io.github.dsheirer.gui.editor.Editor;
|
||||
import io.github.dsheirer.icon.IconManager;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.preference.swing.JTableColumnWidthMonitor;
|
||||
import net.coderazzi.filters.gui.AutoChoices;
|
||||
import net.coderazzi.filters.gui.TableFilterHeader;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.ListSelectionModel;
|
||||
import javax.swing.event.ListSelectionEvent;
|
||||
import javax.swing.event.ListSelectionListener;
|
||||
import javax.swing.table.DefaultTableCellRenderer;
|
||||
import java.awt.*;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class AliasController extends JPanel
|
||||
implements ActionListener, ListSelectionListener
|
||||
public class AliasController extends JPanel implements ActionListener, ListSelectionListener
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static final String TABLE_PREFERENCE_KEY = "alias.controller";
|
||||
private AliasModel mAliasModel;
|
||||
private JTable mAliasTable;
|
||||
private TableFilterHeader mTableFilterHeader;
|
||||
private AliasEditor mAliasEditor;
|
||||
private MultipleAliasEditor mMultipleAliasEditor;
|
||||
private JideSplitPane mSplitPane;
|
||||
private UserPreferences mUserPreferences;
|
||||
|
||||
private static final String NEW_ALIAS = "New";
|
||||
private static final String COPY_ALIAS = "Copy";
|
||||
@@ -39,15 +72,16 @@ public class AliasController extends JPanel
|
||||
private JButton mDeleteButton = new JButton(DELETE_ALIAS);
|
||||
|
||||
private IconCellRenderer mIconCellRenderer;
|
||||
private JTableColumnWidthMonitor mColumnWidthMonitor;
|
||||
|
||||
public AliasController(AliasModel aliasModel, BroadcastModel broadcastModel, IconManager iconManager)
|
||||
public AliasController(AliasModel aliasModel, BroadcastModel broadcastModel, IconManager iconManager,
|
||||
UserPreferences userPreferences)
|
||||
{
|
||||
mAliasModel = aliasModel;
|
||||
|
||||
mAliasEditor = new AliasEditor(mAliasModel, broadcastModel, iconManager);
|
||||
mMultipleAliasEditor = new MultipleAliasEditor(mAliasModel, broadcastModel, iconManager);
|
||||
|
||||
mIconCellRenderer = new IconCellRenderer(iconManager);
|
||||
mUserPreferences = userPreferences;
|
||||
|
||||
init();
|
||||
|
||||
@@ -56,9 +90,7 @@ public class AliasController extends JPanel
|
||||
|
||||
private void init()
|
||||
{
|
||||
setLayout(new MigLayout("insets 0 0 0 0",
|
||||
"[grow,fill]",
|
||||
"[grow,fill]"));
|
||||
setLayout(new MigLayout("insets 0 0 0 0", "[grow,fill]", "[grow,fill]"));
|
||||
|
||||
//System Configuration View and Editor
|
||||
mAliasTable = new JTable(mAliasModel);
|
||||
@@ -66,11 +98,11 @@ public class AliasController extends JPanel
|
||||
mAliasTable.getSelectionModel().addListSelectionListener(this);
|
||||
mAliasTable.setAutoCreateRowSorter(true);
|
||||
|
||||
mAliasTable.getColumnModel().getColumn(AliasModel.COLUMN_COLOR)
|
||||
.setCellRenderer(new ColorCellRenderer());
|
||||
mAliasTable.getColumnModel().getColumn(AliasModel.COLUMN_COLOR).setCellRenderer(new ColorCellRenderer());
|
||||
|
||||
mAliasTable.getColumnModel().getColumn(AliasModel.COLUMN_ICON)
|
||||
.setCellRenderer(mIconCellRenderer);
|
||||
mAliasTable.getColumnModel().getColumn(AliasModel.COLUMN_ICON).setCellRenderer(mIconCellRenderer);
|
||||
|
||||
mColumnWidthMonitor = new JTableColumnWidthMonitor(mUserPreferences, mAliasTable, TABLE_PREFERENCE_KEY);
|
||||
|
||||
mTableFilterHeader = new TableFilterHeader(mAliasTable, AutoChoices.ENABLED);
|
||||
mTableFilterHeader.setFilterOnUpdates(true);
|
||||
@@ -79,8 +111,8 @@ public class AliasController extends JPanel
|
||||
|
||||
JPanel buttonsPanel = new JPanel();
|
||||
|
||||
buttonsPanel.setLayout(
|
||||
new MigLayout("insets 0 0 0 0", "[grow,fill][grow,fill][grow,fill]", "[]"));
|
||||
buttonsPanel.setLayout(new MigLayout("insets 0 0 0 0",
|
||||
"[grow,fill][grow,fill][grow,fill]", "[]"));
|
||||
|
||||
mNewButton.addActionListener(this);
|
||||
mNewButton.setToolTipText("Adds a new alias");
|
||||
@@ -98,8 +130,8 @@ public class AliasController extends JPanel
|
||||
|
||||
JPanel listAndButtonsPanel = new JPanel();
|
||||
|
||||
listAndButtonsPanel.setLayout(
|
||||
new MigLayout("insets 0 0 0 0", "[grow,fill]", "[grow,fill][]"));
|
||||
listAndButtonsPanel.setLayout(new MigLayout("insets 0 0 0 0", "[grow,fill]",
|
||||
"[grow,fill][]"));
|
||||
|
||||
listAndButtonsPanel.add(tableScroller, "wrap");
|
||||
listAndButtonsPanel.add(buttonsPanel);
|
||||
@@ -212,18 +244,11 @@ public class AliasController extends JPanel
|
||||
*/
|
||||
private void addAlias(Alias alias)
|
||||
{
|
||||
//HACK: when inserting a row to the model, the JTable gets
|
||||
//notified and attempts to tell the coderazzi table filter
|
||||
//adaptive choices filter to refresh before the table filter is
|
||||
//notified of the row additions, causing an index out of bounds
|
||||
//exception. We turn off adaptive choices temporarily, add the
|
||||
//channel, and turn on adaptive choices again.
|
||||
mTableFilterHeader.setAdaptiveChoices(false);
|
||||
//Remove any column headers so that the newly added alias shows correctly.
|
||||
mTableFilterHeader.resetFilter();
|
||||
|
||||
int index = mAliasModel.addAlias(alias);
|
||||
|
||||
mTableFilterHeader.setAdaptiveChoices(true);
|
||||
|
||||
if(index >= 0)
|
||||
{
|
||||
int translatedIndex = mAliasTable.convertRowIndexToView(index);
|
||||
|
||||
@@ -505,11 +505,32 @@ public class AliasList implements Listener<AliasEvent>
|
||||
|
||||
public void add(Talkgroup talkgroup, Alias alias)
|
||||
{
|
||||
//Detect talkgroup collisions
|
||||
if(mTalkgroupAliasMap.containsKey(talkgroup.getValue()))
|
||||
{
|
||||
Alias existing = mTalkgroupAliasMap.get(talkgroup.getValue());
|
||||
|
||||
mLog.warn("Alias [" + alias.getName() + "] talkgroup [" + talkgroup.getValue() +
|
||||
"] has the same talkgroup value as alias [" + existing.getName() +
|
||||
"] - alias [" + alias.getName() + "] will be used for alias list [" + getName() + "]");
|
||||
}
|
||||
|
||||
mTalkgroupAliasMap.put(talkgroup.getValue(), alias);
|
||||
}
|
||||
|
||||
public void add(TalkgroupRange talkgroupRange, Alias alias)
|
||||
{
|
||||
//Log warning if the new talkgroup range overlaps with any existing ranges
|
||||
for(Map.Entry<TalkgroupRange,Alias> entry: mTalkgroupRangeAliasMap.entrySet())
|
||||
{
|
||||
if(talkgroupRange.overlaps(entry.getKey()))
|
||||
{
|
||||
mLog.warn("Alias [" + alias.getName() + "] with talkgroup range [" + talkgroupRange.toString() +
|
||||
"] overlaps with alias [" + entry.getValue().getName() +
|
||||
"] with talkgroup range [" + entry.getKey().toString() + "] for alias list [" + getName() + "]");
|
||||
}
|
||||
}
|
||||
|
||||
mTalkgroupRangeAliasMap.put(talkgroupRange, alias);
|
||||
}
|
||||
|
||||
|
||||
@@ -140,6 +140,21 @@ public class TalkgroupRange extends AliasID
|
||||
return getMinTalkgroup() <= talkgroupValue && talkgroupValue <= getMaxTalkgroup();
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this talkgroup range overlaps the talkgroup range argument.
|
||||
* @param talkgroupRange to check for overlap
|
||||
* @return true if the ranges overlap
|
||||
*/
|
||||
public boolean overlaps(TalkgroupRange talkgroupRange)
|
||||
{
|
||||
return contains(talkgroupRange.getMinTalkgroup()) ||
|
||||
contains(talkgroupRange.getMaxTalkgroup()) ||
|
||||
(getMinTalkgroup() < talkgroupRange.getMinTalkgroup() &&
|
||||
talkgroupRange.getMaxTalkgroup() < getMaxTalkgroup()) ||
|
||||
(talkgroupRange.getMinTalkgroup() < getMinTalkgroup() &&
|
||||
getMaxTalkgroup() < talkgroupRange.getMaxTalkgroup());
|
||||
}
|
||||
|
||||
@JacksonXmlProperty(isAttribute = true, localName = "type", namespace = "http://www.w3.org/2001/XMLSchema-instance")
|
||||
@Override
|
||||
public AliasIDType getType()
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/*******************************************************************************
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2016 Dennis Sheirer
|
||||
* Copyright (C) 2014-2019 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
|
||||
@@ -14,8 +15,8 @@
|
||||
*
|
||||
* 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 io.github.dsheirer.audio.broadcast;
|
||||
|
||||
import com.jidesoft.swing.JideSplitPane;
|
||||
@@ -23,6 +24,7 @@ import io.github.dsheirer.alias.AliasModel;
|
||||
import io.github.dsheirer.gui.editor.Editor;
|
||||
import io.github.dsheirer.gui.editor.EmptyEditor;
|
||||
import io.github.dsheirer.icon.IconManager;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -51,6 +53,7 @@ public class BroadcastPanel extends JPanel implements ActionListener, ListSelect
|
||||
private BroadcastModel mBroadcastModel;
|
||||
private AliasModel mAliasModel;
|
||||
private IconManager mIconManager;
|
||||
private UserPreferences mUserPreferences;
|
||||
|
||||
private BroadcastStatusPanel mBroadcastStatusPanel;
|
||||
private JideSplitPane mSplitPane;
|
||||
@@ -60,12 +63,14 @@ public class BroadcastPanel extends JPanel implements ActionListener, ListSelect
|
||||
private JButton mCopyButton = new JButton(COPY_BROADCAST_CONFIGURATION);
|
||||
private JButton mDeleteButton = new JButton(DELETE_BROADCAST_CONFIGURATION);
|
||||
|
||||
public BroadcastPanel(BroadcastModel broadcastModel, AliasModel aliasModel, IconManager iconManager)
|
||||
public BroadcastPanel(BroadcastModel broadcastModel, AliasModel aliasModel, IconManager iconManager,
|
||||
UserPreferences userPreferences)
|
||||
{
|
||||
mBroadcastModel = broadcastModel;
|
||||
mAliasModel = aliasModel;
|
||||
mIconManager = iconManager;
|
||||
mEditor = mEmptyEditor;
|
||||
mUserPreferences = userPreferences;
|
||||
|
||||
init();
|
||||
}
|
||||
@@ -74,7 +79,8 @@ public class BroadcastPanel extends JPanel implements ActionListener, ListSelect
|
||||
{
|
||||
setLayout(new MigLayout("insets 0 0 0 0 ", "[grow,fill]", "[grow,fill]"));
|
||||
|
||||
mBroadcastStatusPanel = new BroadcastStatusPanel(mBroadcastModel);
|
||||
mBroadcastStatusPanel = new BroadcastStatusPanel(mBroadcastModel, mUserPreferences,
|
||||
"broadcast.panel.broadcast.status.panel");
|
||||
|
||||
mBroadcastStatusPanel.getTable().setAutoCreateRowSorter(true);
|
||||
mBroadcastStatusPanel.getTable().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/*******************************************************************************
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2017 Dennis Sheirer
|
||||
* Copyright (C) 2014-2019 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
|
||||
@@ -14,10 +15,12 @@
|
||||
*
|
||||
* 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 io.github.dsheirer.audio.broadcast;
|
||||
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.preference.swing.JTableColumnWidthMonitor;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
import javax.swing.JLabel;
|
||||
@@ -32,12 +35,17 @@ import java.awt.Component;
|
||||
public class BroadcastStatusPanel extends JPanel
|
||||
{
|
||||
private JTable mTable;
|
||||
private JTableColumnWidthMonitor mColumnWidthMonitor;
|
||||
private JScrollPane mScrollPane;
|
||||
private BroadcastModel mBroadcastModel;
|
||||
private UserPreferences mUserPreferences;
|
||||
private String mPreferenceKey;
|
||||
|
||||
public BroadcastStatusPanel(BroadcastModel broadcastModel)
|
||||
public BroadcastStatusPanel(BroadcastModel broadcastModel, UserPreferences userPreferences, String preferenceKey)
|
||||
{
|
||||
mBroadcastModel = broadcastModel;
|
||||
mUserPreferences = userPreferences;
|
||||
mPreferenceKey = preferenceKey;
|
||||
|
||||
init();
|
||||
}
|
||||
@@ -57,6 +65,7 @@ public class BroadcastStatusPanel extends JPanel
|
||||
renderer.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
|
||||
mTable.getColumnModel().getColumn(BroadcastModel.COLUMN_BROADCASTER_STATUS).setCellRenderer(new StatusCellRenderer());
|
||||
mColumnWidthMonitor = new JTableColumnWidthMonitor(mUserPreferences, mTable, mPreferenceKey);
|
||||
|
||||
mScrollPane = new JScrollPane(mTable);
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/*******************************************************************************
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2016 Dennis Sheirer
|
||||
* Copyright (C) 2014-2019 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
|
||||
@@ -14,8 +15,8 @@
|
||||
*
|
||||
* 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 io.github.dsheirer.audio.broadcast.icecast;
|
||||
|
||||
import io.github.dsheirer.alias.AliasModel;
|
||||
@@ -30,11 +31,9 @@ import org.apache.mina.core.service.IoHandlerAdapter;
|
||||
import org.apache.mina.core.session.IoSession;
|
||||
import org.apache.mina.filter.codec.ProtocolDecoderException;
|
||||
import org.apache.mina.http.HttpClientCodec;
|
||||
import org.apache.mina.http.HttpException;
|
||||
import org.apache.mina.http.HttpRequestImpl;
|
||||
import org.apache.mina.http.api.DefaultHttpResponse;
|
||||
import org.apache.mina.http.api.HttpMethod;
|
||||
import org.apache.mina.http.api.HttpStatus;
|
||||
import org.apache.mina.http.api.HttpVersion;
|
||||
import org.apache.mina.transport.socket.nio.NioSocketConnector;
|
||||
import org.slf4j.Logger;
|
||||
@@ -51,6 +50,7 @@ public class IcecastHTTPAudioBroadcaster extends IcecastAudioBroadcaster
|
||||
{
|
||||
private static final Logger mLog = LoggerFactory.getLogger(IcecastHTTPAudioBroadcaster.class);
|
||||
private static final long RECONNECT_INTERVAL_MILLISECONDS = 30000; //30 seconds
|
||||
private static final String HTTP_1_0_OK_HEX_DUMP = "48 54 54 50 2F 31 2E 30 20 32 30 30 20 4F 4B";
|
||||
|
||||
private NioSocketConnector mSocketConnector;
|
||||
private IoSession mStreamingSession = null;
|
||||
@@ -113,7 +113,7 @@ public class IcecastHTTPAudioBroadcaster extends IcecastAudioBroadcaster
|
||||
mSocketConnector.setConnectTimeoutCheckInterval(10000);
|
||||
|
||||
// mSocketConnector.getFilterChain().addLast("logger",
|
||||
// new LoggingFilter(IcecastTCPAudioBroadcaster.class));
|
||||
// new LoggingFilter(IcecastHTTPAudioBroadcaster.class));
|
||||
|
||||
mSocketConnector.getFilterChain().addLast("codec", new HttpClientCodec());
|
||||
mSocketConnector.setHandler(new IcecastHTTPIOHandler());
|
||||
@@ -266,13 +266,18 @@ public class IcecastHTTPAudioBroadcaster extends IcecastAudioBroadcaster
|
||||
{
|
||||
if(throwable instanceof ProtocolDecoderException)
|
||||
{
|
||||
Throwable cause = ((ProtocolDecoderException) throwable).getCause();
|
||||
Throwable cause = throwable.getCause();
|
||||
|
||||
if(cause instanceof HttpException &&
|
||||
((HttpException) cause).getStatusCode() == HttpStatus.CLIENT_ERROR_LENGTH_REQUIRED.code())
|
||||
/**
|
||||
* Warning: Hack. Icecast 2.4.2+ doesn't like to send HTTP headers along with their HTTP/1.0 OK
|
||||
* message which causes Apache Mina to think that it hasn't received the full HTTP response. So, we
|
||||
* intercept the out of bounds exception and then inspect the message hex dump to see if it's an
|
||||
* OK response and then play like everything is well and good.
|
||||
*/
|
||||
if(cause instanceof ArrayIndexOutOfBoundsException &&
|
||||
((ProtocolDecoderException)throwable).getHexdump().startsWith(HTTP_1_0_OK_HEX_DUMP))
|
||||
{
|
||||
//Ignore - Icecast 2.4 sometimes doesn't send any headers with their HTTP responses. Mina expects a
|
||||
//content-length for HTTP responses.
|
||||
setBroadcastState(BroadcastState.CONNECTED);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -83,8 +83,6 @@ public class AudioChannelPanel extends JPanel implements Listener<AudioEvent>, S
|
||||
private JLabel mIdentifierLabel = new JLabel("-----");
|
||||
private Identifier mIdentifier;
|
||||
private List<Alias> mAliases = Collections.EMPTY_LIST;
|
||||
|
||||
private boolean mConfigured = false;
|
||||
private AliasModel mAliasModel;
|
||||
|
||||
public AudioChannelPanel(IconManager iconManager, UserPreferences userPreferences, SettingsManager settingsManager,
|
||||
@@ -191,31 +189,71 @@ public class AudioChannelPanel extends JPanel implements Listener<AudioEvent>, S
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the from and to labels. Note: this does not happen on the swing
|
||||
* event thread. Only invoke from the swing thread.
|
||||
* Resets the from and to labels.
|
||||
*/
|
||||
private void resetLabels()
|
||||
{
|
||||
boolean updated = mIdentifier != null;
|
||||
mIdentifier = null;
|
||||
mAliases = Collections.EMPTY_LIST;
|
||||
updateLabels();
|
||||
mConfigured = false;
|
||||
|
||||
if(updated)
|
||||
{
|
||||
updateLabels();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Truncates the string to the specified length using an ellipses at the end
|
||||
* @param value to optionally truncate
|
||||
* @param length of the final formatted string
|
||||
* @return formatted string or null
|
||||
*/
|
||||
private static String truncate(String value, int length)
|
||||
private void updateIdentifiers(IdentifierCollection identifierCollection)
|
||||
{
|
||||
if(value != null && value.length() > length)
|
||||
if(identifierCollection == null || identifierCollection.isEmpty())
|
||||
{
|
||||
return value.substring(0, length - 3) + "...";
|
||||
resetLabels();
|
||||
return;
|
||||
}
|
||||
|
||||
return value;
|
||||
List<Identifier> toIds = identifierCollection.getIdentifiers(IdentifierClass.USER, Role.TO);
|
||||
|
||||
if(toIds.isEmpty())
|
||||
{
|
||||
resetLabels();
|
||||
return;
|
||||
}
|
||||
|
||||
boolean updated = false;
|
||||
|
||||
if(toIds.size() == 1)
|
||||
{
|
||||
Identifier currentIdentifier = mIdentifier;
|
||||
|
||||
if(currentIdentifier == null || currentIdentifier != toIds.get(0))
|
||||
{
|
||||
mIdentifier = toIds.get(0);
|
||||
AliasList aliasList = mAliasModel.getAliasList(identifierCollection);
|
||||
|
||||
if(aliasList != null)
|
||||
{
|
||||
mAliases = aliasList.getAliases(mIdentifier);
|
||||
}
|
||||
updated = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mLog.warn("Multiple To Identifiers in Collection: " + Joiner.on(",").join(toIds));
|
||||
mIdentifier = toIds.get(0);
|
||||
AliasList aliasList = mAliasModel.getAliasList(identifierCollection);
|
||||
|
||||
if(aliasList != null)
|
||||
{
|
||||
mAliases = aliasList.getAliases(mIdentifier);
|
||||
}
|
||||
updated = true;
|
||||
}
|
||||
|
||||
if(updated)
|
||||
{
|
||||
updateLabels();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -249,7 +287,8 @@ public class AudioChannelPanel extends JPanel implements Listener<AudioEvent>, S
|
||||
}
|
||||
|
||||
final ImageIcon icon = iconName != null ? mIconManager.getIcon(iconName, 18) : null;
|
||||
final String identifierText = truncate(identifier, 33);
|
||||
|
||||
final String identifierText = identifier;
|
||||
|
||||
EventQueue.invokeLater(new Runnable()
|
||||
{
|
||||
@@ -258,7 +297,6 @@ public class AudioChannelPanel extends JPanel implements Listener<AudioEvent>, S
|
||||
{
|
||||
mIdentifierLabel.setText(identifierText);
|
||||
mIconLabel.setIcon(icon);
|
||||
mConfigured = true;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -272,23 +310,10 @@ public class AudioChannelPanel extends JPanel implements Listener<AudioEvent>, S
|
||||
@Override
|
||||
public void receive(final IdentifierCollection identifierCollection)
|
||||
{
|
||||
if(identifierCollection != null && (identifierCollection.isUpdated() || !mConfigured))
|
||||
{
|
||||
List<Identifier> toIds = identifierCollection.getIdentifiers(IdentifierClass.USER, Role.TO);
|
||||
mIdentifier = !toIds.isEmpty() ? toIds.get(0) : null;
|
||||
AliasList aliasList = mAliasModel.getAliasList(identifierCollection);
|
||||
|
||||
if(aliasList != null)
|
||||
{
|
||||
mAliases = aliasList.getAliases(mIdentifier);
|
||||
}
|
||||
|
||||
updateLabels();
|
||||
}
|
||||
updateIdentifiers(identifierCollection);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void settingChanged(Setting setting)
|
||||
{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
* Copyright (C) 2014-2019 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
|
||||
@@ -39,7 +39,8 @@ public class AudioChannelsPanel extends JPanel
|
||||
public AudioChannelsPanel(IconManager iconManager, UserPreferences userPreferences, SettingsManager settingsManager,
|
||||
IAudioController controller, AliasModel aliasModel)
|
||||
{
|
||||
setLayout(new MigLayout("insets 0 0 0 0", "[][sg abc,grow,fill][][sg abc,grow,fill]", "[grow,fill]"));
|
||||
setLayout(new MigLayout("insets 0 0 0 0",
|
||||
"[][sizegroup abc,grow,fill][][sizegroup abc,grow,fill]", "[grow,fill]"));
|
||||
|
||||
setBackground(Color.BLACK);
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
* Copyright (C) 2014-2019 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
|
||||
@@ -54,6 +54,11 @@ public abstract class AudioOutput implements Listener<ReusableAudioPacket>, Line
|
||||
private LinkedTransferQueue<ReusableAudioPacket> mBuffer = new LinkedTransferQueue<>();
|
||||
private int mBufferStartThreshold;
|
||||
private int mBufferStopThreshold;
|
||||
private static IdentifierCollection EMPTY_IDENTIFIER_COLLECTION = new IdentifierCollection();
|
||||
static
|
||||
{
|
||||
EMPTY_IDENTIFIER_COLLECTION.setUpdated(true);
|
||||
}
|
||||
|
||||
private Listener<IdentifierCollection> mIdentifierCollectionListener;
|
||||
private Broadcaster<AudioEvent> mAudioEventBroadcaster = new Broadcaster<>();
|
||||
@@ -380,12 +385,11 @@ public abstract class AudioOutput implements Listener<ReusableAudioPacket>, Line
|
||||
*/
|
||||
private void checkStop()
|
||||
{
|
||||
if(mCanProcessAudio &&
|
||||
mOutput.isRunning() &&
|
||||
mOutput.available() >= mBufferStopThreshold)
|
||||
if(mCanProcessAudio && mOutput.isRunning() && mOutput.available() >= mBufferStopThreshold)
|
||||
{
|
||||
mOutput.drain();
|
||||
mOutput.stop();
|
||||
broadcast(EMPTY_IDENTIFIER_COLLECTION);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ import io.github.dsheirer.identifier.decoder.ChannelStateIdentifier;
|
||||
import io.github.dsheirer.module.ProcessingChain;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.preference.identifier.TalkgroupFormatPreference;
|
||||
import io.github.dsheirer.preference.swing.JTableColumnWidthMonitor;
|
||||
import io.github.dsheirer.sample.Broadcaster;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
@@ -58,6 +59,7 @@ import java.util.Map;
|
||||
|
||||
public class ChannelMetadataPanel extends JPanel implements ListSelectionListener
|
||||
{
|
||||
private static final String TABLE_PREFERENCE_KEY = "channel.metadata.panel";
|
||||
private ChannelModel mChannelModel;
|
||||
private ChannelProcessingManager mChannelProcessingManager;
|
||||
private IconManager mIconManager;
|
||||
@@ -66,6 +68,7 @@ public class ChannelMetadataPanel extends JPanel implements ListSelectionListene
|
||||
private Broadcaster<ProcessingChain> mSelectedProcessingChainBroadcaster = new Broadcaster<>();
|
||||
private Map<State,Color> mBackgroundColors = new HashMap<>();
|
||||
private Map<State,Color> mForegroundColors = new HashMap<>();
|
||||
private JTableColumnWidthMonitor mTableColumnMonitor;
|
||||
|
||||
/**
|
||||
* Table view for currently decoding channel metadata
|
||||
@@ -108,6 +111,9 @@ public class ChannelMetadataPanel extends JPanel implements ListSelectionListene
|
||||
mTable.getColumnModel().getColumn(ChannelMetadataModel.COLUMN_CONFIGURATION_FREQUENCY)
|
||||
.setCellRenderer(new FrequencyCellRenderer());
|
||||
|
||||
//Add a table column width monitor to store/restore column widths
|
||||
mTableColumnMonitor = new JTableColumnWidthMonitor(mUserPreferences, mTable, TABLE_PREFERENCE_KEY);
|
||||
|
||||
JScrollPane scrollPane = new JScrollPane(mTable, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
|
||||
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/*******************************************************************************
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2017 Dennis Sheirer
|
||||
* Copyright (C) 2014-2019 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
|
||||
@@ -14,8 +15,8 @@
|
||||
*
|
||||
* 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 io.github.dsheirer.channel.metadata;
|
||||
|
||||
import com.jidesoft.swing.JideSplitPane;
|
||||
@@ -33,10 +34,9 @@ import net.miginfocom.swing.MigLayout;
|
||||
import javax.swing.JPanel;
|
||||
import java.awt.Color;
|
||||
|
||||
public class ChannelMetadataViewer extends JPanel
|
||||
public class NowPlayingPanel extends JPanel
|
||||
{
|
||||
private ChannelMetadataPanel mChannelMetadataPanel;
|
||||
|
||||
private ChannelDetailPanel mChannelDetailPanel;
|
||||
private DecodeEventPanel mDecodeEventPanel;
|
||||
private MessageActivityPanel mMessageActivityPanel;
|
||||
@@ -45,12 +45,12 @@ public class ChannelMetadataViewer extends JPanel
|
||||
* GUI panel that combines the currently decoding channels metadata table and viewers for channel details,
|
||||
* messages, events, and spectral view.
|
||||
*/
|
||||
public ChannelMetadataViewer(ChannelModel channelModel, ChannelProcessingManager channelProcessingManager,
|
||||
IconManager iconManager, AliasModel aliasModel, UserPreferences userPreferences)
|
||||
public NowPlayingPanel(ChannelModel channelModel, ChannelProcessingManager channelProcessingManager,
|
||||
IconManager iconManager, AliasModel aliasModel, UserPreferences userPreferences)
|
||||
{
|
||||
mChannelDetailPanel = new ChannelDetailPanel(channelProcessingManager);
|
||||
mDecodeEventPanel = new DecodeEventPanel(iconManager, userPreferences, aliasModel);
|
||||
mMessageActivityPanel = new MessageActivityPanel(channelProcessingManager);
|
||||
mMessageActivityPanel = new MessageActivityPanel(userPreferences);
|
||||
mChannelMetadataPanel = new ChannelMetadataPanel(channelModel, channelProcessingManager, iconManager, userPreferences);
|
||||
|
||||
init();
|
||||
@@ -64,7 +64,6 @@ public class ChannelMetadataViewer extends JPanel
|
||||
tabbedPane.addTab("Details", mChannelDetailPanel);
|
||||
tabbedPane.addTab("Events", mDecodeEventPanel);
|
||||
tabbedPane.addTab("Messages", mMessageActivityPanel);
|
||||
// tabbedPane.addTab("Spectrum", mChannelSpectrumPanel);
|
||||
tabbedPane.setFont(this.getFont());
|
||||
tabbedPane.setForeground(Color.BLACK);
|
||||
|
||||
@@ -28,6 +28,7 @@ import io.github.dsheirer.controller.channel.Channel;
|
||||
import io.github.dsheirer.controller.channel.Channel.ChannelType;
|
||||
import io.github.dsheirer.controller.channel.ChannelEvent;
|
||||
import io.github.dsheirer.controller.channel.IChannelEventProvider;
|
||||
import io.github.dsheirer.identifier.IdentifierClass;
|
||||
import io.github.dsheirer.identifier.IdentifierUpdateListener;
|
||||
import io.github.dsheirer.identifier.IdentifierUpdateNotification;
|
||||
import io.github.dsheirer.identifier.IdentifierUpdateProvider;
|
||||
@@ -203,6 +204,7 @@ public class ChannelState extends Module implements IChannelEventProvider, IDeco
|
||||
{
|
||||
mState = State.IDLE;
|
||||
broadcast(new DecoderStateEvent(this, Event.RESET, State.IDLE));
|
||||
mIdentifierCollection.remove(IdentifierClass.USER);
|
||||
mIdentifierCollection.update(ChannelStateIdentifier.IDLE);
|
||||
mSourceOverflow = false;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/*******************************************************************************
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2017 Dennis Sheirer
|
||||
* Copyright (C) 2014-2019 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
|
||||
@@ -14,8 +15,8 @@
|
||||
*
|
||||
* 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 io.github.dsheirer.controller;
|
||||
|
||||
import com.jidesoft.swing.JideTabbedPane;
|
||||
@@ -25,7 +26,7 @@ import io.github.dsheirer.audio.broadcast.BroadcastModel;
|
||||
import io.github.dsheirer.audio.broadcast.BroadcastPanel;
|
||||
import io.github.dsheirer.audio.playback.AudioPanel;
|
||||
import io.github.dsheirer.audio.playback.AudioPlaybackManager;
|
||||
import io.github.dsheirer.channel.metadata.ChannelMetadataViewer;
|
||||
import io.github.dsheirer.channel.metadata.NowPlayingPanel;
|
||||
import io.github.dsheirer.controller.channel.ChannelController;
|
||||
import io.github.dsheirer.controller.channel.ChannelModel;
|
||||
import io.github.dsheirer.controller.channel.ChannelProcessingManager;
|
||||
@@ -41,7 +42,6 @@ import io.github.dsheirer.source.tuner.TunerViewPanel;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JTable;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
|
||||
@@ -53,27 +53,18 @@ public class ControllerPanel extends JPanel
|
||||
private AudioPanel mAudioPanel;
|
||||
private BroadcastPanel mBroadcastPanel;
|
||||
private ChannelController mChannelController;
|
||||
private ChannelMetadataViewer mChannelMetadataViewer;
|
||||
private NowPlayingPanel mNowPlayingPanel;
|
||||
private ChannelModel mChannelModel;
|
||||
private MapPanel mMapPanel;
|
||||
private TunerViewPanel mTunerManagerPanel;
|
||||
private BroadcastModel mBroadcastModel;
|
||||
|
||||
private JideTabbedPane mTabbedPane;
|
||||
protected JTable mChannelActivityTable = new JTable();
|
||||
|
||||
public ControllerPanel(AudioPlaybackManager audioPlaybackManager,
|
||||
AliasModel aliasModel,
|
||||
BroadcastModel broadcastModel,
|
||||
ChannelModel channelModel,
|
||||
ChannelMapModel channelMapModel,
|
||||
ChannelProcessingManager channelProcessingManager,
|
||||
IconManager iconManager,
|
||||
MapService mapService,
|
||||
SettingsManager settingsManager,
|
||||
SourceManager sourceManager,
|
||||
TunerModel tunerModel,
|
||||
UserPreferences userPreferences)
|
||||
public ControllerPanel(AudioPlaybackManager audioPlaybackManager, AliasModel aliasModel, BroadcastModel broadcastModel,
|
||||
ChannelModel channelModel, ChannelMapModel channelMapModel, ChannelProcessingManager channelProcessingManager,
|
||||
IconManager iconManager, MapService mapService, SettingsManager settingsManager,
|
||||
SourceManager sourceManager, TunerModel tunerModel, UserPreferences userPreferences)
|
||||
{
|
||||
mBroadcastModel = broadcastModel;
|
||||
mChannelModel = channelModel;
|
||||
@@ -81,19 +72,19 @@ public class ControllerPanel extends JPanel
|
||||
mAudioPanel = new AudioPanel(iconManager, userPreferences, settingsManager, sourceManager, audioPlaybackManager,
|
||||
aliasModel);
|
||||
|
||||
mChannelMetadataViewer = new ChannelMetadataViewer(channelModel, channelProcessingManager, iconManager,
|
||||
mNowPlayingPanel = new NowPlayingPanel(channelModel, channelProcessingManager, iconManager,
|
||||
aliasModel, userPreferences);
|
||||
|
||||
mMapPanel = new MapPanel(mapService, aliasModel, iconManager, settingsManager);
|
||||
|
||||
mBroadcastPanel = new BroadcastPanel(broadcastModel, aliasModel, iconManager);
|
||||
mBroadcastPanel = new BroadcastPanel(broadcastModel, aliasModel, iconManager, userPreferences);
|
||||
|
||||
mChannelController = new ChannelController(channelModel, channelProcessingManager, channelMapModel,
|
||||
sourceManager, aliasModel);
|
||||
sourceManager, aliasModel, userPreferences);
|
||||
|
||||
mAliasController = new AliasController(aliasModel, broadcastModel, iconManager);
|
||||
mAliasController = new AliasController(aliasModel, broadcastModel, iconManager, userPreferences);
|
||||
|
||||
mTunerManagerPanel = new TunerViewPanel(tunerModel);
|
||||
mTunerManagerPanel = new TunerViewPanel(tunerModel, userPreferences);
|
||||
|
||||
init();
|
||||
}
|
||||
@@ -108,7 +99,7 @@ public class ControllerPanel extends JPanel
|
||||
mTabbedPane = new JideTabbedPane();
|
||||
mTabbedPane.setFont(this.getFont());
|
||||
mTabbedPane.setForeground(Color.BLACK);
|
||||
mTabbedPane.addTab("Now Playing", mChannelMetadataViewer);
|
||||
mTabbedPane.addTab("Now Playing", mNowPlayingPanel);
|
||||
mTabbedPane.addTab("Aliases", mAliasController);
|
||||
mTabbedPane.addTab("Channels", mChannelController);
|
||||
mTabbedPane.addTab("Map", mMapPanel);
|
||||
|
||||
@@ -1,23 +1,29 @@
|
||||
/*******************************************************************************
|
||||
* sdr-trunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2019 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 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.
|
||||
* 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/>
|
||||
*
|
||||
******************************************************************************/
|
||||
* 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 io.github.dsheirer.controller.channel;
|
||||
|
||||
import com.jidesoft.swing.JideSplitPane;
|
||||
import io.github.dsheirer.alias.AliasModel;
|
||||
import io.github.dsheirer.controller.channel.map.ChannelMapModel;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.preference.swing.JTableColumnWidthMonitor;
|
||||
import io.github.dsheirer.source.SourceManager;
|
||||
import net.coderazzi.filters.gui.AutoChoices;
|
||||
import net.coderazzi.filters.gui.TableFilterHeader;
|
||||
@@ -43,11 +49,14 @@ public class ChannelController extends JPanel implements ActionListener, ListSel
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static final String TABLE_PREFERENCE_KEY = "channel.controller";
|
||||
private ChannelModel mChannelModel;
|
||||
private ChannelProcessingManager mChannelProcessingManager;
|
||||
private JTable mChannelTable;
|
||||
private JTableColumnWidthMonitor mColumnWidthMonitor;
|
||||
private TableFilterHeader mTableFilterHeader;
|
||||
private ChannelEditor mEditor;
|
||||
private UserPreferences mUserPreferences;
|
||||
|
||||
private static final String NEW_CHANNEL = "New";
|
||||
private static final String COPY_CHANNEL = "Copy";
|
||||
@@ -57,17 +66,16 @@ public class ChannelController extends JPanel implements ActionListener, ListSel
|
||||
private JButton mCopyChannelButton = new JButton(COPY_CHANNEL);
|
||||
private JButton mDeleteChannelButton = new JButton(DELETE_CHANNEL);
|
||||
|
||||
public ChannelController(ChannelModel channelModel,
|
||||
ChannelProcessingManager channelProcessingManager,
|
||||
ChannelMapModel channelMapModel,
|
||||
SourceManager sourceManager,
|
||||
AliasModel aliasModel)
|
||||
public ChannelController(ChannelModel channelModel, ChannelProcessingManager channelProcessingManager,
|
||||
ChannelMapModel channelMapModel, SourceManager sourceManager, AliasModel aliasModel,
|
||||
UserPreferences userPreferences)
|
||||
{
|
||||
mChannelModel = channelModel;
|
||||
mChannelProcessingManager = channelProcessingManager;
|
||||
mEditor = new ChannelEditor(channelModel, channelProcessingManager, channelMapModel, sourceManager, aliasModel);
|
||||
mChannelModel.addListener(mEditor);
|
||||
mChannelProcessingManager.addChannelEventListener(mEditor);
|
||||
mUserPreferences = userPreferences;
|
||||
|
||||
init();
|
||||
}
|
||||
@@ -82,6 +90,7 @@ public class ChannelController extends JPanel implements ActionListener, ListSel
|
||||
mChannelTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||
mChannelTable.getSelectionModel().addListSelectionListener(this);
|
||||
mChannelTable.setAutoCreateRowSorter(true);
|
||||
mColumnWidthMonitor = new JTableColumnWidthMonitor(mUserPreferences, mChannelTable, TABLE_PREFERENCE_KEY);
|
||||
|
||||
mTableFilterHeader = new TableFilterHeader(mChannelTable, AutoChoices.ENABLED);
|
||||
mTableFilterHeader.setFilterOnUpdates(true);
|
||||
|
||||
@@ -78,6 +78,7 @@ import java.awt.AWTException;
|
||||
import java.awt.Desktop;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.Point;
|
||||
import java.awt.Robot;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
@@ -97,8 +98,12 @@ public class SDRTrunk implements Listener<TunerEvent>
|
||||
private final static Logger mLog = LoggerFactory.getLogger(SDRTrunk.class);
|
||||
|
||||
private static final String PROPERTY_BROADCAST_STATUS_VISIBLE = "main.broadcast.status.visible";
|
||||
private boolean mBroadcastStatusVisible;
|
||||
private static final String BASE_WINDOW_NAME = "sdrtrunk.main.window";
|
||||
private static final String CONTROLLER_PANEL_IDENTIFIER = BASE_WINDOW_NAME + ".control.panel";
|
||||
private static final String SPECTRAL_PANEL_IDENTIFIER = BASE_WINDOW_NAME + ".spectral.panel";
|
||||
private static final String WINDOW_FRAME_IDENTIFIER = BASE_WINDOW_NAME + ".frame";
|
||||
|
||||
private boolean mBroadcastStatusVisible;
|
||||
private AudioPacketManager mAudioPacketManager;
|
||||
private IconManager mIconManager;
|
||||
private BroadcastStatusPanel mBroadcastStatusPanel;
|
||||
@@ -271,15 +276,45 @@ public class SDRTrunk implements Listener<TunerEvent>
|
||||
*/
|
||||
mTitle = SystemProperties.getInstance().getApplicationName();
|
||||
mMainGui.setTitle(mTitle);
|
||||
mMainGui.setSize(new Dimension(1280, 800));
|
||||
mMainGui.setLocationRelativeTo(null);
|
||||
|
||||
Point location = mUserPreferences.getSwingPreference().getLocation(WINDOW_FRAME_IDENTIFIER);
|
||||
if(location != null)
|
||||
{
|
||||
mMainGui.setLocation(location);
|
||||
}
|
||||
else
|
||||
{
|
||||
mMainGui.setLocationRelativeTo(null);
|
||||
}
|
||||
mMainGui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
mMainGui.addWindowListener(new ShutdownMonitor());
|
||||
|
||||
//Set preferred sizes to influence the split
|
||||
Dimension dimension = mUserPreferences.getSwingPreference().getDimension(WINDOW_FRAME_IDENTIFIER);
|
||||
|
||||
mSpectralPanel.setPreferredSize(new Dimension(1280, 300));
|
||||
mControllerPanel.setPreferredSize(new Dimension(1280, 500));
|
||||
|
||||
if(dimension != null)
|
||||
{
|
||||
Dimension spectral = mUserPreferences.getSwingPreference().getDimension(SPECTRAL_PANEL_IDENTIFIER);
|
||||
if(spectral != null)
|
||||
{
|
||||
mSpectralPanel.setSize(spectral);
|
||||
}
|
||||
|
||||
Dimension controller = mUserPreferences.getSwingPreference().getDimension(CONTROLLER_PANEL_IDENTIFIER);
|
||||
if(controller != null)
|
||||
{
|
||||
mControllerPanel.setSize(controller);
|
||||
}
|
||||
|
||||
mMainGui.setSize(dimension);
|
||||
}
|
||||
else
|
||||
{
|
||||
mMainGui.setSize(new Dimension(1280, 800));
|
||||
}
|
||||
|
||||
mSplitPane = new JideSplitPane(JideSplitPane.VERTICAL_SPLIT);
|
||||
mSplitPane.setDividerSize(5);
|
||||
mSplitPane.add(mSpectralPanel);
|
||||
@@ -424,6 +459,10 @@ public class SDRTrunk implements Listener<TunerEvent>
|
||||
private void processShutdown()
|
||||
{
|
||||
mLog.info("Application shutdown started ...");
|
||||
mUserPreferences.getSwingPreference().setLocation(WINDOW_FRAME_IDENTIFIER, mMainGui.getLocation());
|
||||
mUserPreferences.getSwingPreference().setDimension(WINDOW_FRAME_IDENTIFIER, mMainGui.getSize());
|
||||
mUserPreferences.getSwingPreference().setDimension(SPECTRAL_PANEL_IDENTIFIER, mSpectralPanel.getSize());
|
||||
mUserPreferences.getSwingPreference().setDimension(CONTROLLER_PANEL_IDENTIFIER, mControllerPanel.getSize());
|
||||
mJavaFxWindowManager.shutdown();
|
||||
mLog.info("Stopping channels ...");
|
||||
mChannelProcessingManager.shutdown();
|
||||
@@ -443,7 +482,8 @@ public class SDRTrunk implements Listener<TunerEvent>
|
||||
{
|
||||
if(mBroadcastStatusPanel == null)
|
||||
{
|
||||
mBroadcastStatusPanel = new BroadcastStatusPanel(mBroadcastModel);
|
||||
mBroadcastStatusPanel = new BroadcastStatusPanel(mBroadcastModel, mUserPreferences,
|
||||
"application.broadcast.status.panel");
|
||||
mBroadcastStatusPanel.setPreferredSize(new Dimension(880, 70));
|
||||
mBroadcastStatusPanel.getTable().setEnabled(false);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
* Copyright (C) 2014-2019 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
|
||||
@@ -84,7 +84,7 @@ public class IdentifierCollection
|
||||
return mUpdated;
|
||||
}
|
||||
|
||||
protected void setUpdated(boolean updated)
|
||||
public void setUpdated(boolean updated)
|
||||
{
|
||||
mUpdated = updated;
|
||||
}
|
||||
@@ -114,6 +114,14 @@ public class IdentifierCollection
|
||||
return Collections.unmodifiableList(mIdentifiers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this collection has no identifiers
|
||||
*/
|
||||
public boolean isEmpty()
|
||||
{
|
||||
return mIdentifiers.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of identifiers by identifier class from this collection.
|
||||
*
|
||||
|
||||
@@ -22,6 +22,8 @@ package io.github.dsheirer.identifier;
|
||||
|
||||
import io.github.dsheirer.identifier.configuration.AliasListConfigurationIdentifier;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
@@ -32,6 +34,7 @@ import java.util.Iterator;
|
||||
public class MutableIdentifierCollection extends IdentifierCollection implements IdentifierUpdateProvider,
|
||||
Listener<IdentifierUpdateNotification>
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger(MutableIdentifierCollection.class);
|
||||
private Listener<IdentifierUpdateNotification> mListener;
|
||||
|
||||
public MutableIdentifierCollection()
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
* Copyright (C) 2014-2019 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
|
||||
@@ -23,7 +23,6 @@ package io.github.dsheirer.identifier.patch;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.identifier.IdentifierClass;
|
||||
import io.github.dsheirer.identifier.Role;
|
||||
import io.github.dsheirer.identifier.talkgroup.TalkgroupIdentifier;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
@@ -32,6 +31,14 @@ import java.util.Map;
|
||||
|
||||
/**
|
||||
* Manager for (temporary) patch groups and related identifiers.
|
||||
*
|
||||
* Patch groups are primarily used on Motorola P25 systems. This manager monitors patch group additions and deletions
|
||||
* and maintains a map of the current patch groups.
|
||||
*
|
||||
* Traffic channel calls will sometimes reference a patch group by simply using the patch group identifier. This
|
||||
* manager will replace that reference with the full patch group so that the call event has the full patch group
|
||||
* including all of the patched groups, which may not have been included in the patch group reference on the
|
||||
* traffic channel.
|
||||
*/
|
||||
public class PatchGroupManager
|
||||
{
|
||||
@@ -127,7 +134,7 @@ public class PatchGroupManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the TALKGROUP or PATCH GROUP identifier and replaces the identifier with the current patch group
|
||||
* Checks the PATCH GROUP identifier and replaces the identifier with the current patch group
|
||||
* if the identifier matches a currently managed patch group.
|
||||
*
|
||||
* @param identifier for a talkgroup or a patch group.
|
||||
@@ -144,22 +151,6 @@ public class PatchGroupManager
|
||||
{
|
||||
switch(identifier.getForm())
|
||||
{
|
||||
case TALKGROUP:
|
||||
if(identifier instanceof TalkgroupIdentifier)
|
||||
{
|
||||
TalkgroupIdentifier tgi = (TalkgroupIdentifier)identifier;
|
||||
|
||||
if(tgi.isGroup())
|
||||
{
|
||||
int talkgroupId = ((TalkgroupIdentifier)identifier).getValue();
|
||||
|
||||
if(mPatchGroupMap.containsKey(talkgroupId))
|
||||
{
|
||||
return mPatchGroupMap.get(talkgroupId);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PATCH_GROUP:
|
||||
if(identifier instanceof PatchGroupIdentifier)
|
||||
{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
* Copyright (C) 2014-2019 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
|
||||
@@ -34,6 +34,7 @@ import io.github.dsheirer.identifier.Role;
|
||||
import io.github.dsheirer.module.ProcessingChain;
|
||||
import io.github.dsheirer.preference.PreferenceType;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.preference.swing.JTableColumnWidthMonitor;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import org.slf4j.Logger;
|
||||
@@ -55,10 +56,12 @@ import java.util.List;
|
||||
|
||||
public class DecodeEventPanel extends JPanel implements Listener<ProcessingChain>
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger(DecodeEventPanel.class);
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final static Logger mLog = LoggerFactory.getLogger(DecodeEventPanel.class);
|
||||
private static final String TABLE_PREFERENCE_KEY = "decode.event.panel";
|
||||
|
||||
private JTable mTable;
|
||||
private JTableColumnWidthMonitor mTableColumnWidthMonitor;
|
||||
private DecodeEventModel mEmptyDecodeEventModel;
|
||||
private JScrollPane mEmptyScroller;
|
||||
private IconManager mIconManager;
|
||||
@@ -83,6 +86,7 @@ public class DecodeEventPanel extends JPanel implements Listener<ProcessingChain
|
||||
mTable = new JTable(mEmptyDecodeEventModel);
|
||||
mTable.setAutoCreateRowSorter(true);
|
||||
mTable.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN);
|
||||
mTableColumnWidthMonitor = new JTableColumnWidthMonitor(mUserPreferences, mTable, TABLE_PREFERENCE_KEY);
|
||||
updateCellRenderers();
|
||||
|
||||
mEmptyScroller = new JScrollPane(mTable);
|
||||
@@ -127,12 +131,17 @@ public class DecodeEventPanel extends JPanel implements Listener<ProcessingChain
|
||||
public void receive(ProcessingChain processingChain)
|
||||
{
|
||||
EventQueue.invokeLater(() -> {
|
||||
|
||||
//Dispose the current column width monitor and recreate after we swap out the table model
|
||||
mTableColumnWidthMonitor.dispose();
|
||||
mTable.setModel(processingChain != null ? processingChain.getDecodeEventModel() : mEmptyDecodeEventModel);
|
||||
|
||||
if(processingChain != null)
|
||||
{
|
||||
updateCellRenderers();
|
||||
}
|
||||
|
||||
mTableColumnWidthMonitor = new JTableColumnWidthMonitor(mUserPreferences, mTable, TABLE_PREFERENCE_KEY);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -162,17 +171,6 @@ public class DecodeEventPanel extends JPanel implements Listener<ProcessingChain
|
||||
if(value instanceof IdentifierCollection)
|
||||
{
|
||||
List<Identifier> identifiers = ((IdentifierCollection)value).getIdentifiers(mRole);
|
||||
|
||||
// if(identifiers.size() > 1)
|
||||
// {
|
||||
// StringBuilder sb = new StringBuilder();
|
||||
// sb.append("Multiple Identifiers:\n");
|
||||
// for(Identifier identifier: identifiers)
|
||||
// {
|
||||
// sb.append("ID:").append(identifier.debug()).append("\n");
|
||||
// }
|
||||
// mLog.debug(sb.toString());
|
||||
// }
|
||||
label.setText(format(identifiers));
|
||||
}
|
||||
else
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/*******************************************************************************
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2017 Dennis Sheirer
|
||||
* Copyright (C) 2014-2019 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
|
||||
@@ -14,17 +15,18 @@
|
||||
*
|
||||
* 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 io.github.dsheirer.module.decode.event;
|
||||
|
||||
import com.jidesoft.swing.JideButton;
|
||||
import com.jidesoft.swing.JideSplitButton;
|
||||
import io.github.dsheirer.controller.channel.ChannelProcessingManager;
|
||||
import io.github.dsheirer.filter.FilterEditorPanel;
|
||||
import io.github.dsheirer.filter.FilterSet;
|
||||
import io.github.dsheirer.message.IMessage;
|
||||
import io.github.dsheirer.module.ProcessingChain;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.preference.swing.JTableColumnWidthMonitor;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import org.slf4j.Logger;
|
||||
@@ -49,26 +51,24 @@ import java.awt.event.MouseListener;
|
||||
public class MessageActivityPanel extends JPanel implements Listener<ProcessingChain>
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final static Logger mLog = LoggerFactory.getLogger(MessageActivityPanel.class);
|
||||
|
||||
private static final String TABLE_PREFERENCE_KEY = "message.activity.panel";
|
||||
private static MessageActivityModel EMPTY_MODEL = new MessageActivityModel();
|
||||
|
||||
private JTable mTable = new JTable(EMPTY_MODEL);
|
||||
|
||||
private JTableColumnWidthMonitor mTableColumnWidthMonitor;
|
||||
private UserPreferences mUserPreferences;
|
||||
private MessageManagementPanel mManagementPanel = new MessageManagementPanel();
|
||||
|
||||
private ChannelProcessingManager mChannelProcessingManager;
|
||||
|
||||
public MessageActivityPanel(ChannelProcessingManager channelProcessingManager)
|
||||
public MessageActivityPanel(UserPreferences userPreferences)
|
||||
{
|
||||
mChannelProcessingManager = channelProcessingManager;
|
||||
mUserPreferences = userPreferences;
|
||||
|
||||
setLayout(new MigLayout("insets 0 0 0 0", "[][grow,fill]", "[]0[grow,fill]"));
|
||||
|
||||
add(mManagementPanel, "span,growx");
|
||||
|
||||
add(new JScrollPane(mTable), "span,grow");
|
||||
mTableColumnWidthMonitor = new JTableColumnWidthMonitor(mUserPreferences, mTable, TABLE_PREFERENCE_KEY);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -79,6 +79,8 @@ public class MessageActivityPanel extends JPanel implements Listener<ProcessingC
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
//Remove the existing table column width monitor and replace after swapping the table model
|
||||
mTableColumnWidthMonitor.dispose();
|
||||
mTable.setModel(processingChain != null ? processingChain.getMessageActivityModel() : EMPTY_MODEL);
|
||||
|
||||
mTable.getColumnModel().getColumn(0).setPreferredWidth(18);
|
||||
@@ -93,6 +95,7 @@ public class MessageActivityPanel extends JPanel implements Listener<ProcessingC
|
||||
{
|
||||
mManagementPanel.disableButtons();
|
||||
}
|
||||
mTableColumnWidthMonitor = new JTableColumnWidthMonitor(mUserPreferences, mTable, TABLE_PREFERENCE_KEY);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
* Copyright (C) 2014-2019 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
|
||||
@@ -33,8 +33,6 @@ import io.github.dsheirer.module.decode.p25.message.pdu.packet.sndcp.SNDCPPacket
|
||||
import io.github.dsheirer.module.decode.p25.reference.DataUnitID;
|
||||
import io.github.dsheirer.module.decode.p25.reference.IPHeaderCompression;
|
||||
import io.github.dsheirer.module.decode.p25.reference.UDPHeaderCompression;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -44,7 +42,7 @@ import java.util.List;
|
||||
*/
|
||||
public class PacketMessage extends P25Message
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger(PacketMessage.class);
|
||||
// private final static Logger mLog = LoggerFactory.getLogger(PacketMessage.class);
|
||||
|
||||
private PDUSequence mPDUSequence;
|
||||
private BinaryMessage mPayload;
|
||||
@@ -88,7 +86,6 @@ public class PacketMessage extends P25Message
|
||||
}
|
||||
else
|
||||
{
|
||||
mLog.debug("***************** 2 byte SNDCP header with no data blocks header: " + getPDUSequence().getHeader().getMessage().toHexString());
|
||||
mSNDCPPacketHeader = new SNDCPPacketHeader(getHeader().isOutbound());
|
||||
}
|
||||
}
|
||||
@@ -162,7 +159,7 @@ public class PacketMessage extends P25Message
|
||||
{
|
||||
List<Integer> numbers = new ArrayList<>();
|
||||
|
||||
for(DataBlock dataBlock: getPDUSequence().getDataBlocks())
|
||||
for(DataBlock dataBlock : getPDUSequence().getDataBlocks())
|
||||
{
|
||||
if(dataBlock instanceof ConfirmedDataBlock)
|
||||
{
|
||||
|
||||
@@ -28,6 +28,7 @@ import io.github.dsheirer.preference.identifier.TalkgroupFormatPreference;
|
||||
import io.github.dsheirer.preference.playlist.PlaylistPreference;
|
||||
import io.github.dsheirer.preference.source.ChannelMultiFrequencyPreference;
|
||||
import io.github.dsheirer.preference.source.TunerPreference;
|
||||
import io.github.dsheirer.preference.swing.SwingPreference;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
|
||||
/**
|
||||
@@ -55,6 +56,7 @@ public class UserPreferences implements Listener<PreferenceType>
|
||||
private PlaylistPreference mPlaylistPreference;
|
||||
private TalkgroupFormatPreference mTalkgroupFormatPreference;
|
||||
private TunerPreference mTunerPreference;
|
||||
private SwingPreference mSwingPreference = new SwingPreference();
|
||||
|
||||
/**
|
||||
* Constructs a new user preferences instance
|
||||
@@ -120,6 +122,15 @@ public class UserPreferences implements Listener<PreferenceType>
|
||||
return mTunerPreference;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Swing window location/size user preferences
|
||||
*/
|
||||
public SwingPreference getSwingPreference()
|
||||
{
|
||||
return mSwingPreference;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the managed preferences
|
||||
*/
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
* Copyright (C) 2014-2019 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
|
||||
@@ -42,6 +42,7 @@ public class APCO25TalkgroupFormatter extends IntegerFormatter
|
||||
switch(format)
|
||||
{
|
||||
case DECIMAL:
|
||||
case FORMATTED:
|
||||
return toDecimal(identifier.getValue(),
|
||||
(identifier.isGroup() ? GROUP_DECIMAL_WIDTH : UNIT_DECIMAL_WIDTH));
|
||||
case HEXADECIMAL:
|
||||
|
||||
@@ -38,6 +38,7 @@ public class MDC1200TalkgroupFormatter extends IntegerFormatter
|
||||
switch(format)
|
||||
{
|
||||
case DECIMAL:
|
||||
case FORMATTED:
|
||||
return toDecimal(identifier.getValue(), DECIMAL_WIDTH);
|
||||
case HEXADECIMAL:
|
||||
return toHex(identifier.getValue(), HEXADECIMAL_WIDTH);
|
||||
|
||||
@@ -38,6 +38,7 @@ public class PassportTalkgroupFormatter extends IntegerFormatter
|
||||
switch(format)
|
||||
{
|
||||
case DECIMAL:
|
||||
case FORMATTED:
|
||||
return toDecimal(identifier.getValue(), DECIMAL_WIDTH);
|
||||
case HEXADECIMAL:
|
||||
return toHex(identifier.getValue(), HEXADECIMAL_WIDTH);
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2019 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 io.github.dsheirer.preference.swing;
|
||||
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.util.ThreadPool;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ListSelectionEvent;
|
||||
import javax.swing.event.TableColumnModelEvent;
|
||||
import javax.swing.event.TableColumnModelListener;
|
||||
import javax.swing.table.TableColumnModel;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
* Monitors a JTable column model and persists column width changes to the user preferences. Restores
|
||||
* previous column width preferred sizes on application restart.
|
||||
*/
|
||||
public class JTableColumnWidthMonitor
|
||||
{
|
||||
private static final Logger mLog = LoggerFactory.getLogger(JTableColumnWidthMonitor.class);
|
||||
private UserPreferences mUserPreferences;
|
||||
private JTable mTable;
|
||||
private String mKey;
|
||||
private ColumnResizeListener mColumnResizeListener = new ColumnResizeListener();
|
||||
private AtomicBoolean mSaveInProgress = new AtomicBoolean();
|
||||
|
||||
/**
|
||||
* Constructs a column width monitor.
|
||||
*
|
||||
* @param userPreferences to store column widths
|
||||
* @param table to monitor for column width changes
|
||||
* @param key that uniquely identifies the table to monitor
|
||||
*/
|
||||
public JTableColumnWidthMonitor(UserPreferences userPreferences, JTable table, String key)
|
||||
{
|
||||
mUserPreferences = userPreferences;
|
||||
mTable = table;
|
||||
mKey = key;
|
||||
|
||||
restoreColumnWidths();
|
||||
mTable.getColumnModel().addColumnModelListener(mColumnResizeListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares this monitor for disposal by unregistering as a listener to the table column model.
|
||||
*/
|
||||
public void dispose()
|
||||
{
|
||||
if(mTable != null && mColumnResizeListener != null)
|
||||
{
|
||||
mTable.getColumnModel().removeColumnModelListener(mColumnResizeListener);
|
||||
}
|
||||
|
||||
mTable = null;
|
||||
mUserPreferences = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the preferred column widths on the table from persisted settings
|
||||
*/
|
||||
private void restoreColumnWidths()
|
||||
{
|
||||
TableColumnModel model = mTable.getColumnModel();
|
||||
|
||||
for(int x = 0; x < model.getColumnCount(); x++)
|
||||
{
|
||||
int width = mUserPreferences.getSwingPreference().getInt(getColumnKey(x), Integer.MAX_VALUE);
|
||||
|
||||
if(width != Integer.MAX_VALUE)
|
||||
{
|
||||
model.getColumn(x).setPreferredWidth(width);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the current column widths to the user preferences
|
||||
*/
|
||||
private void storeColumnWidths()
|
||||
{
|
||||
TableColumnModel model = mTable.getColumnModel();
|
||||
|
||||
for(int x = 0; x < model.getColumnCount(); x++)
|
||||
{
|
||||
mUserPreferences.getSwingPreference().setInt(getColumnKey(x), model.getColumn(x).getWidth());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a preference key for the column number
|
||||
*/
|
||||
private String getColumnKey(int column)
|
||||
{
|
||||
return mKey + ".column." + column;
|
||||
}
|
||||
|
||||
/**
|
||||
* Table column model listener.
|
||||
*/
|
||||
class ColumnResizeListener implements TableColumnModelListener
|
||||
{
|
||||
@Override
|
||||
public void columnMarginChanged(ChangeEvent e)
|
||||
{
|
||||
if(mSaveInProgress.compareAndSet(false, true))
|
||||
{
|
||||
ThreadPool.SCHEDULED.schedule(new ColumnWidthSaveTask(), 2, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void columnAdded(TableColumnModelEvent e){}
|
||||
@Override
|
||||
public void columnRemoved(TableColumnModelEvent e){}
|
||||
@Override
|
||||
public void columnMoved(TableColumnModelEvent e){}
|
||||
@Override
|
||||
public void columnSelectionChanged(ListSelectionEvent e){}
|
||||
}
|
||||
|
||||
public class ColumnWidthSaveTask implements Runnable
|
||||
{
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
storeColumnWidths();
|
||||
mSaveInProgress.set(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2019 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 io.github.dsheirer.preference.swing;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.GraphicsDevice;
|
||||
import java.awt.GraphicsEnvironment;
|
||||
import java.awt.Point;
|
||||
import java.util.prefs.Preferences;
|
||||
|
||||
/**
|
||||
* User preference settings for Swing windows and components.
|
||||
*/
|
||||
public class SwingPreference
|
||||
{
|
||||
private static final Logger mLog = LoggerFactory.getLogger(SwingPreference.class);
|
||||
|
||||
private static final String LOCATION_X = ".x";
|
||||
private static final String LOCATION_Y = ".y";
|
||||
private static final String SIZE_HEIGHT = ".height";
|
||||
private static final String SIZE_WIDTH = ".width";
|
||||
|
||||
private Preferences mPreferences = Preferences.userNodeForPackage(SwingPreference.class);
|
||||
|
||||
public SwingPreference()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the stored swing related integer value
|
||||
* @param key for accessing the value
|
||||
* @param defaultValue to return if the value has not yet been persisted
|
||||
* @return value or default value
|
||||
*/
|
||||
public int getInt(String key, int defaultValue)
|
||||
{
|
||||
return mPreferences.getInt(key, defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the swing related integer value
|
||||
* @param key to reference the value
|
||||
*/
|
||||
public void setInt(String key, int value)
|
||||
{
|
||||
mPreferences.putInt(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the persisted window location for the specified preference key.
|
||||
* @param key identifying the window
|
||||
* @return location or null
|
||||
*/
|
||||
public Point getLocation(String key)
|
||||
{
|
||||
int x = mPreferences.getInt(key + LOCATION_X, Integer.MAX_VALUE);
|
||||
int y = mPreferences.getInt(key + LOCATION_Y, Integer.MAX_VALUE);
|
||||
|
||||
if(x != Integer.MAX_VALUE && y != Integer.MAX_VALUE)
|
||||
{
|
||||
Point location = new Point(x,y);
|
||||
|
||||
if(isValidWindowLocation(location))
|
||||
{
|
||||
return location;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the current window location
|
||||
* @param key to identify the window
|
||||
* @param location to persist
|
||||
*/
|
||||
public void setLocation(String key, Point location)
|
||||
{
|
||||
mPreferences.putInt(key + LOCATION_X, location.x);
|
||||
mPreferences.putInt(key + LOCATION_Y, location.y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the stored size/dimension of the window identified by the key argument.
|
||||
* @param key to identify the window
|
||||
* @return dimension or null
|
||||
*/
|
||||
public Dimension getDimension(String key)
|
||||
{
|
||||
int height = mPreferences.getInt(key + SIZE_HEIGHT, Integer.MAX_VALUE);
|
||||
int width = mPreferences.getInt(key + SIZE_WIDTH, Integer.MAX_VALUE);
|
||||
|
||||
if(height != Integer.MAX_VALUE && width != Integer.MAX_VALUE)
|
||||
{
|
||||
return new Dimension(width, height);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setDimension(String key, Dimension dimension)
|
||||
{
|
||||
mPreferences.putInt(key + SIZE_HEIGHT, dimension.height);
|
||||
mPreferences.putInt(key + SIZE_WIDTH, dimension.width);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests a stored window location to determine if it can be displayed on the currently available
|
||||
* graphics display devices so that we don't position a window at a previously available location
|
||||
* that is not currently available.
|
||||
*
|
||||
* @param location to test
|
||||
* @return true if the location is displayable.
|
||||
*/
|
||||
private boolean isValidWindowLocation(Point location)
|
||||
{
|
||||
for(GraphicsDevice gd:GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices())
|
||||
{
|
||||
if(gd.getDefaultConfiguration().getBounds().contains(location))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,24 +1,28 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014-2016 Dennis Sheirer
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2019 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 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.
|
||||
* 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/>
|
||||
******************************************************************************/
|
||||
* 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 io.github.dsheirer.source.tuner;
|
||||
|
||||
import com.jidesoft.swing.JideSplitPane;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.preference.swing.JTableColumnWidthMonitor;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
import io.github.dsheirer.source.tuner.TunerEvent.Event;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
@@ -49,17 +53,21 @@ public class TunerViewPanel extends JPanel
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final static Logger mLog = LoggerFactory.getLogger(TunerViewPanel.class);
|
||||
private static final String TABLE_PREFERENCE_KEY = "tuner.view.panel";
|
||||
|
||||
private TunerModel mTunerModel;
|
||||
private JTable mTunerTable;
|
||||
private JTableColumnWidthMonitor mColumnWidthMonitor;
|
||||
private TableRowSorter<TunerModel> mRowSorter;
|
||||
private JideSplitPane mSplitPane;
|
||||
private TunerEditor mTunerEditor;
|
||||
private UserPreferences mUserPreferences;
|
||||
|
||||
public TunerViewPanel(TunerModel tunerModel)
|
||||
public TunerViewPanel(TunerModel tunerModel, UserPreferences userPreferences)
|
||||
{
|
||||
mTunerModel = tunerModel;
|
||||
mTunerEditor = new TunerEditor(mTunerModel.getTunerConfigurationModel());
|
||||
mUserPreferences = userPreferences;
|
||||
|
||||
init();
|
||||
}
|
||||
@@ -149,6 +157,7 @@ public class TunerViewPanel extends JPanel
|
||||
TableCellRenderer renderer = new LinkCellRenderer();
|
||||
mTunerTable.getColumnModel().getColumn(TunerModel.SPECTRAL_DISPLAY_NEW).setCellRenderer(renderer);
|
||||
|
||||
mColumnWidthMonitor = new JTableColumnWidthMonitor(mUserPreferences, mTunerTable, TABLE_PREFERENCE_KEY);
|
||||
JScrollPane listScroller = new JScrollPane(mTunerTable);
|
||||
listScroller.setPreferredSize(new Dimension(400, 20));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user