diff --git a/src/main/java/io/github/dsheirer/alias/AliasController.java b/src/main/java/io/github/dsheirer/alias/AliasController.java index 89851f6e..4b321d91 100644 --- a/src/main/java/io/github/dsheirer/alias/AliasController.java +++ b/src/main/java/io/github/dsheirer/alias/AliasController.java @@ -24,6 +24,8 @@ 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; @@ -48,17 +50,18 @@ 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"; @@ -69,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(); @@ -86,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); @@ -96,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); @@ -109,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"); @@ -128,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); diff --git a/src/main/java/io/github/dsheirer/audio/broadcast/BroadcastPanel.java b/src/main/java/io/github/dsheirer/audio/broadcast/BroadcastPanel.java index 74eeb3cc..e1b8a9f1 100644 --- a/src/main/java/io/github/dsheirer/audio/broadcast/BroadcastPanel.java +++ b/src/main/java/io/github/dsheirer/audio/broadcast/BroadcastPanel.java @@ -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 - * - ******************************************************************************/ + * ***************************************************************************** + */ 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); diff --git a/src/main/java/io/github/dsheirer/audio/broadcast/BroadcastStatusPanel.java b/src/main/java/io/github/dsheirer/audio/broadcast/BroadcastStatusPanel.java index 38ce234e..429a3ded 100644 --- a/src/main/java/io/github/dsheirer/audio/broadcast/BroadcastStatusPanel.java +++ b/src/main/java/io/github/dsheirer/audio/broadcast/BroadcastStatusPanel.java @@ -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 - * - ******************************************************************************/ + * ***************************************************************************** + */ 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); diff --git a/src/main/java/io/github/dsheirer/channel/metadata/ChannelMetadataPanel.java b/src/main/java/io/github/dsheirer/channel/metadata/ChannelMetadataPanel.java index 5c64d920..30da5070 100644 --- a/src/main/java/io/github/dsheirer/channel/metadata/ChannelMetadataPanel.java +++ b/src/main/java/io/github/dsheirer/channel/metadata/ChannelMetadataPanel.java @@ -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 mSelectedProcessingChainBroadcaster = new Broadcaster<>(); private Map mBackgroundColors = new HashMap<>(); private Map 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); diff --git a/src/main/java/io/github/dsheirer/channel/metadata/ChannelMetadataViewer.java b/src/main/java/io/github/dsheirer/channel/metadata/NowPlayingPanel.java similarity index 83% rename from src/main/java/io/github/dsheirer/channel/metadata/ChannelMetadataViewer.java rename to src/main/java/io/github/dsheirer/channel/metadata/NowPlayingPanel.java index b7b3c65c..4a434643 100644 --- a/src/main/java/io/github/dsheirer/channel/metadata/ChannelMetadataViewer.java +++ b/src/main/java/io/github/dsheirer/channel/metadata/NowPlayingPanel.java @@ -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 - * - ******************************************************************************/ + * ***************************************************************************** + */ 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); diff --git a/src/main/java/io/github/dsheirer/controller/ControllerPanel.java b/src/main/java/io/github/dsheirer/controller/ControllerPanel.java index 64f0eb32..3d8fb5f3 100644 --- a/src/main/java/io/github/dsheirer/controller/ControllerPanel.java +++ b/src/main/java/io/github/dsheirer/controller/ControllerPanel.java @@ -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 - * - ******************************************************************************/ + * ***************************************************************************** + */ 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); diff --git a/src/main/java/io/github/dsheirer/controller/channel/ChannelController.java b/src/main/java/io/github/dsheirer/controller/channel/ChannelController.java index 9963ea7f..c99dc77a 100644 --- a/src/main/java/io/github/dsheirer/controller/channel/ChannelController.java +++ b/src/main/java/io/github/dsheirer/controller/channel/ChannelController.java @@ -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 - * - ******************************************************************************/ + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + * ***************************************************************************** + */ 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); diff --git a/src/main/java/io/github/dsheirer/gui/SDRTrunk.java b/src/main/java/io/github/dsheirer/gui/SDRTrunk.java index 35e8bbdc..fcf63d8f 100644 --- a/src/main/java/io/github/dsheirer/gui/SDRTrunk.java +++ b/src/main/java/io/github/dsheirer/gui/SDRTrunk.java @@ -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 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 */ 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 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 { 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); } diff --git a/src/main/java/io/github/dsheirer/module/decode/event/DecodeEventPanel.java b/src/main/java/io/github/dsheirer/module/decode/event/DecodeEventPanel.java index 22326b8b..dab408e0 100644 --- a/src/main/java/io/github/dsheirer/module/decode/event/DecodeEventPanel.java +++ b/src/main/java/io/github/dsheirer/module/decode/event/DecodeEventPanel.java @@ -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 { - 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 { + + //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 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 diff --git a/src/main/java/io/github/dsheirer/module/decode/event/MessageActivityPanel.java b/src/main/java/io/github/dsheirer/module/decode/event/MessageActivityPanel.java index 42c89762..d25323e5 100644 --- a/src/main/java/io/github/dsheirer/module/decode/event/MessageActivityPanel.java +++ b/src/main/java/io/github/dsheirer/module/decode/event/MessageActivityPanel.java @@ -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 - * - ******************************************************************************/ + * ***************************************************************************** + */ 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 { 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 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 return mTunerPreference; } + + /** + * Swing window location/size user preferences + */ + public SwingPreference getSwingPreference() + { + return mSwingPreference; + } + /** * Loads the managed preferences */ diff --git a/src/main/java/io/github/dsheirer/preference/swing/JTableColumnWidthMonitor.java b/src/main/java/io/github/dsheirer/preference/swing/JTableColumnWidthMonitor.java new file mode 100644 index 00000000..7eeb37d4 --- /dev/null +++ b/src/main/java/io/github/dsheirer/preference/swing/JTableColumnWidthMonitor.java @@ -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 + * ***************************************************************************** + */ + +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); + } + } +} diff --git a/src/main/java/io/github/dsheirer/preference/swing/SwingPreference.java b/src/main/java/io/github/dsheirer/preference/swing/SwingPreference.java new file mode 100644 index 00000000..4aaf9842 --- /dev/null +++ b/src/main/java/io/github/dsheirer/preference/swing/SwingPreference.java @@ -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 + * ***************************************************************************** + */ + +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; + } +} diff --git a/src/main/java/io/github/dsheirer/source/tuner/TunerViewPanel.java b/src/main/java/io/github/dsheirer/source/tuner/TunerViewPanel.java index 217b62c0..35950965 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/TunerViewPanel.java +++ b/src/main/java/io/github/dsheirer/source/tuner/TunerViewPanel.java @@ -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 - ******************************************************************************/ + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + * ***************************************************************************** + */ 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 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));