From 112083a22f0b9e94a8a01623b85b99146a009629 Mon Sep 17 00:00:00 2001 From: denny Date: Fri, 25 Mar 2016 14:26:08 -0400 Subject: [PATCH] wip #34 - finished updating all channel configuration editors and completed preliminary functional testing. --- src/alias/AliasController.java | 3 +- src/alias/MultipleAliasEditor.java | 2 +- .../channel/AbstractChannelEditor.java | 41 --- .../channel/ChannelConfigurationEditor.java | 44 --- src/controller/channel/ChannelController.java | 10 +- src/controller/channel/ChannelEditor.java | 119 ++++---- .../channel/NameConfigurationEditor.java | 5 +- src/gui/control/JFrequencyControl.java | 2 +- src/gui/editor/Editor.java | 51 +++- src/gui/editor/EmptyValidatingEditor.java | 2 +- .../decode/AuxDecodeConfigurationEditor.java | 5 + .../decode/DecodeConfigurationEditor.java | 25 +- src/module/decode/DecodeEditor.java | 127 -------- src/module/decode/DecoderFactory.java | 19 +- src/module/decode/am/AMDecoderEditor.java | 30 +- .../decode/config/DecodeConfiguration.java | 9 +- .../decode/ltrnet/LTRNetDecoderEditor.java | 71 +++-- .../ltrstandard/LTRStandardDecoderEditor.java | 177 +++++++++++ .../decode/ltrstandard/LTRStandardEditor.java | 71 ----- .../decode/mpt1327/MPT1327ConfigEditor.java | 219 ------------- .../decode/mpt1327/MPT1327DecoderEditor.java | 287 ++++++++++++++++++ src/module/decode/nbfm/NBFMDecoderEditor.java | 161 ++++++++++ src/module/decode/nbfm/NBFMEditor.java | 35 --- src/module/decode/p25/P25DecodeEditor.java | 147 --------- src/module/decode/p25/P25DecoderEditor.java | 226 ++++++++++++++ .../passport/PassportDecoderEditor.java | 159 ++++++++++ .../decode/passport/PassportEditor.java | 31 -- src/record/RecordEditor.java | 59 ---- src/source/SourceConfigurationEditor.java | 33 +- src/source/mixer/MixerSourceEditor.java | 32 +- src/source/tuner/TunerSourceEditor.java | 15 +- src/spectrum/OverlayPanel.java | 57 ++-- 32 files changed, 1328 insertions(+), 946 deletions(-) delete mode 100644 src/controller/channel/AbstractChannelEditor.java delete mode 100644 src/controller/channel/ChannelConfigurationEditor.java delete mode 100644 src/module/decode/DecodeEditor.java create mode 100644 src/module/decode/ltrstandard/LTRStandardDecoderEditor.java delete mode 100644 src/module/decode/ltrstandard/LTRStandardEditor.java delete mode 100644 src/module/decode/mpt1327/MPT1327ConfigEditor.java create mode 100644 src/module/decode/mpt1327/MPT1327DecoderEditor.java create mode 100644 src/module/decode/nbfm/NBFMDecoderEditor.java delete mode 100644 src/module/decode/nbfm/NBFMEditor.java delete mode 100644 src/module/decode/p25/P25DecodeEditor.java create mode 100644 src/module/decode/p25/P25DecoderEditor.java create mode 100644 src/module/decode/passport/PassportDecoderEditor.java delete mode 100644 src/module/decode/passport/PassportEditor.java delete mode 100644 src/record/RecordEditor.java diff --git a/src/alias/AliasController.java b/src/alias/AliasController.java index 5b8984a8..e6c86812 100644 --- a/src/alias/AliasController.java +++ b/src/alias/AliasController.java @@ -4,11 +4,11 @@ import gui.editor.Editor; 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.Arrays; import java.util.List; import javax.swing.ImageIcon; @@ -148,6 +148,7 @@ public class AliasController extends JPanel ((Editor)component).setItem( null ); mSplitPane.remove( component ); + editor.setPreferredSize( new Dimension( 100, 100 ) ); mSplitPane.add( editor ); mSplitPane.validate(); diff --git a/src/alias/MultipleAliasEditor.java b/src/alias/MultipleAliasEditor.java index 0bf1f871..ae4eeeec 100644 --- a/src/alias/MultipleAliasEditor.java +++ b/src/alias/MultipleAliasEditor.java @@ -183,7 +183,7 @@ public class MultipleAliasEditor extends Editor> mPrioritySlider.setMajorTickSpacing( 20 ); mPrioritySlider.setMinorTickSpacing( 5 ); mPrioritySlider.setPaintTicks( true ); - mPrioritySlider.setLabelTable( mPrioritySlider.createStandardLabels( 20, 20 ) ); + mPrioritySlider.setLabelTable( mPrioritySlider.createStandardLabels( 25, 25 ) ); mPrioritySlider.setPaintLabels( true ); mPrioritySlider.addChangeListener( new ChangeListener() { diff --git a/src/controller/channel/AbstractChannelEditor.java b/src/controller/channel/AbstractChannelEditor.java deleted file mode 100644 index 2ef02f60..00000000 --- a/src/controller/channel/AbstractChannelEditor.java +++ /dev/null @@ -1,41 +0,0 @@ -/******************************************************************************* - * SDR Trunk - * Copyright (C) 2014 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 controller.channel; - - -public abstract class AbstractChannelEditor extends ChannelConfigurationEditor -{ - private static final long serialVersionUID = 1L; - - protected Channel mChannel; - - public AbstractChannelEditor( Channel channel ) - { - super(); - mChannel = channel; - } - - public Channel getChannel() - { - return mChannel; - } - - public abstract void save(); - - public abstract void reset(); -} diff --git a/src/controller/channel/ChannelConfigurationEditor.java b/src/controller/channel/ChannelConfigurationEditor.java deleted file mode 100644 index 7b3e1427..00000000 --- a/src/controller/channel/ChannelConfigurationEditor.java +++ /dev/null @@ -1,44 +0,0 @@ -/******************************************************************************* - - * SDR Trunk - * Copyright (C) 2014-2016 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 controller.channel; - -import javax.swing.JPanel; - -public abstract class ChannelConfigurationEditor extends JPanel -{ - private static final long serialVersionUID = 1L; - - /** - * Sets or resets the configuration editor components - */ - public abstract void setConfiguration( Channel channel ); - - /** - * Saves the contents of the editor components to the configuration - */ - public abstract void save(); - - /** - * Validates the contents of the editor components prior to saving the - * content to the configuration. - * - * @throws ConfigurationValidationException if the content is invalid - */ - public abstract void validateConfiguration() throws ConfigurationValidationException; -} diff --git a/src/controller/channel/ChannelController.java b/src/controller/channel/ChannelController.java index 99e764aa..17a9f8e2 100644 --- a/src/controller/channel/ChannelController.java +++ b/src/controller/channel/ChannelController.java @@ -85,17 +85,17 @@ public class ChannelController extends JPanel new MigLayout( "insets 0 0 0 0", "[grow,fill][grow,fill][grow,fill]", "[]") ); mNewChannelButton.addActionListener( this ); - mNewChannelButton.setToolTipText( "Adds a new default channel" ); + mNewChannelButton.setToolTipText( "Create a new channel configuration" ); buttonsPanel.add( mNewChannelButton ); mCopyChannelButton.addActionListener( this ); mCopyChannelButton.setEnabled( false ); - mCopyChannelButton.setToolTipText( "Creates a copy of the currently selected channel and adds it" ); + mCopyChannelButton.setToolTipText( "Create a copy of the currently selected channel configuration" ); buttonsPanel.add( mCopyChannelButton ); mDeleteChannelButton.addActionListener( this ); mDeleteChannelButton.setEnabled( false ); - mDeleteChannelButton.setToolTipText( "Deletes the currently selected channel" ); + mDeleteChannelButton.setToolTipText( "Delete the currently selected channel configuration" ); buttonsPanel.add( mDeleteChannelButton ); JPanel listAndButtonsPanel = new JPanel(); @@ -115,10 +115,10 @@ public class ChannelController extends JPanel //Attempt to get a 60:40 vertical sizing preference JScrollPane listScroller = new JScrollPane( listAndButtonsPanel ); - listScroller.setPreferredSize( new Dimension( 800, 60 ) ); + listScroller.setPreferredSize( new Dimension( 800, 58 ) ); JScrollPane editorScroller = new JScrollPane( mEditor ); - editorScroller.setPreferredSize( new Dimension( 800, 40 ) ); + editorScroller.setPreferredSize( new Dimension( 800, 42 ) ); splitPane.add( listScroller ); splitPane.add( editorScroller ); diff --git a/src/controller/channel/ChannelEditor.java b/src/controller/channel/ChannelEditor.java index 5c569db3..42509675 100644 --- a/src/controller/channel/ChannelEditor.java +++ b/src/controller/channel/ChannelEditor.java @@ -81,51 +81,6 @@ public class ChannelEditor extends Editor implements ActionListener, Ch init(); } - /** - * Sets the channel configuration in each of the channel editor components - * Note: this method must be invoked on the swing event dispatch thread - */ - public void setItem( final Channel channel ) - { - //Check if the current channel configuration has changed - if( hasItem() && - ( mNameConfigurationEditor.isModified() ) ) - { - int option = JOptionPane.showConfirmDialog( ChannelEditor.this, - "This channel configuration has changed. Do you want to save these changes?", - "Save Changes?", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE ); - - if( option == JOptionPane.YES_OPTION ) - { - save(); - } - - setModified( false ); - } - - mNameConfigurationEditor.setItem( channel ); - mSourceConfigurationEditor.setItem( channel ); - mDecodeConfigurationEditor.setItem( channel ); - mAuxDecodeConfigurationEditor.setItem( channel ); - mEventLogConfigurationEditor.setItem( channel ); - mRecordConfigurationEditor.setItem( channel ); - - if( channel != null ) - { - mChannelName.setText( "Channel: " + channel.getName() ); - mEnableButton.setText( channel.getEnabled() ? "Disable" : "Enable" ); - mEnableButton.setEnabled( true ); - mEnableButton.setBackground( channel.getEnabled() ? Color.GREEN : getBackground() ); - } - else - { - mChannelName.setText( "Channel: " ); - mEnableButton.setText( "Enable" ); - mEnableButton.setEnabled( false ); - mEnableButton.setBackground( getBackground() ); - } - } - private void init() { setLayout( new MigLayout( "fill,wrap 3", "[grow,fill][grow,fill][grow,fill]", "[grow,fill][]" ) ); @@ -135,38 +90,48 @@ public class ChannelEditor extends Editor implements ActionListener, Ch tabs.setForeground( Color.BLACK ); tabs.setTabTrailingComponent( mChannelName ); + + mNameConfigurationEditor.setSaveRequestListener( this ); tabs.addTab( "Name/Alias", mNameConfigurationEditor ); mSourceConfigurationEditor = new SourceConfigurationEditor( mSourceManager ); + mSourceConfigurationEditor.setSaveRequestListener( this ); tabs.addTab( "Source", mSourceConfigurationEditor ); mDecodeConfigurationEditor = new DecodeConfigurationEditor( mChannelMapModel ); + mDecodeConfigurationEditor.setSaveRequestListener( this ); tabs.addTab( "Decoder", mDecodeConfigurationEditor ); mAuxDecodeConfigurationEditor = new AuxDecodeConfigurationEditor(); + mAuxDecodeConfigurationEditor.setSaveRequestListener( this ); tabs.addTab( "Aux Decoders", mAuxDecodeConfigurationEditor ); mEventLogConfigurationEditor = new EventLogConfigurationEditor(); + mEventLogConfigurationEditor.setSaveRequestListener( this ); tabs.addTab( "Logging", mEventLogConfigurationEditor ); mRecordConfigurationEditor = new RecordConfigurationEditor(); + mRecordConfigurationEditor.setSaveRequestListener( this ); tabs.addTab( "Recording", mRecordConfigurationEditor ); add( tabs, "span" ); mEnableButton.addActionListener( this ); mEnableButton.setEnabled( false ); + mEnableButton.setToolTipText( "Start the currently selected channel running/decoding" ); add( mEnableButton ); JButton btnSave = new JButton( "Save" ); + btnSave.setToolTipText( "Save changes to the currently selected channel" ); btnSave.addActionListener( ChannelEditor.this ); add( btnSave ); JButton btnReset = new JButton( "Reset" ); + btnReset.setToolTipText( "Reload the currently selected channel" ); btnReset.addActionListener( ChannelEditor.this ); add( btnReset ); } - + @Override public void channelChanged( ChannelEvent event ) { @@ -229,10 +194,48 @@ public class ChannelEditor extends Editor implements ActionListener, Ch } } + /** + * Sets the channel configuration in each of the channel editor components + * Note: this method must be invoked on the swing event dispatch thread + */ + public void setItem( final Channel channel ) + { + super.setItem( channel ); + + mNameConfigurationEditor.setItem( channel ); + mSourceConfigurationEditor.setItem( channel ); + mDecodeConfigurationEditor.setItem( channel ); + mAuxDecodeConfigurationEditor.setItem( channel ); + mEventLogConfigurationEditor.setItem( channel ); + mRecordConfigurationEditor.setItem( channel ); + + if( channel != null ) + { + mChannelName.setText( "Channel: " + channel.getName() ); + mEnableButton.setText( channel.getEnabled() ? "Disable" : "Enable" ); + mEnableButton.setEnabled( true ); + mEnableButton.setBackground( channel.getEnabled() ? Color.GREEN : getBackground() ); + } + else + { + mChannelName.setText( "Channel: " ); + mEnableButton.setText( "Enable" ); + mEnableButton.setEnabled( false ); + mEnableButton.setBackground( getBackground() ); + } + } + public void save() { if( hasItem() ) { + mNameConfigurationEditor.save(); + mSourceConfigurationEditor.save(); + mDecodeConfigurationEditor.save(); + mAuxDecodeConfigurationEditor.save(); + mEventLogConfigurationEditor.save(); + mRecordConfigurationEditor.save(); + try { mDecodeConfigurationEditor.validate( mSourceConfigurationEditor ); @@ -240,33 +243,17 @@ public class ChannelEditor extends Editor implements ActionListener, Ch } catch( EditorValidationException e ) { - JOptionPane.showMessageDialog( ChannelEditor.this, e.getReason(), - "Configuration Error", JOptionPane.ERROR_MESSAGE ); - e.getEditor().requestFocus(); + JOptionPane.showMessageDialog( e.getEditor(), e.getReason(), + "Configuration Error", JOptionPane.ERROR_MESSAGE ); + return; } - boolean changed = mNameConfigurationEditor.isModified() || - mSourceConfigurationEditor.isModified() || - mDecodeConfigurationEditor.isModified() || - mAuxDecodeConfigurationEditor.isModified() || - mEventLogConfigurationEditor.isModified() || - mRecordConfigurationEditor.isModified(); - - mNameConfigurationEditor.save(); - mSourceConfigurationEditor.save(); - mDecodeConfigurationEditor.save(); - mAuxDecodeConfigurationEditor.save(); - mEventLogConfigurationEditor.save(); - mRecordConfigurationEditor.save(); - if( changed ) - { - mChannelModel.broadcast( new ChannelEvent( getItem(), + mChannelModel.broadcast( new ChannelEvent( getItem(), Event.NOTIFICATION_CONFIGURATION_CHANGE ) ); - } } setModified( false ); diff --git a/src/controller/channel/NameConfigurationEditor.java b/src/controller/channel/NameConfigurationEditor.java index dcb6cd00..e0525bdf 100644 --- a/src/controller/channel/NameConfigurationEditor.java +++ b/src/controller/channel/NameConfigurationEditor.java @@ -262,5 +262,8 @@ public class NameConfigurationEditor extends Editor implements Document } @Override - public void removeUpdate( DocumentEvent e ) {} + public void removeUpdate( DocumentEvent e ) + { + setModified( true ); + } } diff --git a/src/gui/control/JFrequencyControl.java b/src/gui/control/JFrequencyControl.java index 8e3b9802..d343e47e 100644 --- a/src/gui/control/JFrequencyControl.java +++ b/src/gui/control/JFrequencyControl.java @@ -78,7 +78,7 @@ public class JFrequencyControl extends JPanel implements IFrequencyChangeProcess private void init() { - setLayout( new MigLayout( "", "[]0[]", "" ) ); + setLayout( new MigLayout( "insets 0 0 0 0", "[]0[]", "" ) ); Font font = new Font( Font.MONOSPACED, Font.BOLD, 30 ); diff --git a/src/gui/editor/Editor.java b/src/gui/editor/Editor.java index 061080c0..01f76db1 100644 --- a/src/gui/editor/Editor.java +++ b/src/gui/editor/Editor.java @@ -6,10 +6,19 @@ import javax.swing.JPanel; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import alias.id.AliasIdentifierEditor; - /** * Generic editor with change detection, save and reset functions. + * + * This editor supports hierarchical nesting of sub-component editors where changes are detected + * at the lowest editor in the tree and percolated up to the top-level editor for managing the + * configuration set as a whole. + * + * To configure this editor as a collective, register each parent editor as a saveRequestListener + * on each child editor. If no save request listener is registered, the editor will simply invoke + * save when a change is detected and the user opts to save the contents. + * + * The top-level editor can override the saveRequest() method to perform custom save operations + * and validation. */ public abstract class Editor extends JPanel { @@ -19,19 +28,51 @@ public abstract class Editor extends JPanel protected T mItem; protected boolean mModified = false; + protected Editor mSaveRequestListener; public Editor() { } + + /** + * Requests to save the contents of this editor. + * + * If a save request listener is registered, the listener is notified that a save is requested, + * otherwise the save is request is processed by the instance. + * + * This allows for a save event to be percolated up the hierarchical set of editors so that + * a top-level editor can invoke custom operations such as configuration validation. + */ + protected void saveRequest() + { + if( mSaveRequestListener != null ) + { + mSaveRequestListener.saveRequest(); + } + else + { + save(); + } + } + + /** + * Registers the editor to be notified when this editor contents have been saved. + */ + public void setSaveRequestListener( Editor listener ) + { + mSaveRequestListener = listener; + } + /** - * Sets the object to be edited + * Sets the object to be edited. If the contents from the previous object have changed, this + * prompts the user to save these changes. A saveRequest() is issued and either this editor + * or the parent editor will respond to the save request and invoke the save() method. */ public void setItem( T item ) { if( isModified() ) { - mLog.debug( "Editor that is modified: " + getClass() ); int option = JOptionPane.showConfirmDialog( Editor.this, "This item has changed. Do you want to save these changes?", @@ -41,7 +82,7 @@ public abstract class Editor extends JPanel if( option == JOptionPane.YES_OPTION ) { - save(); + saveRequest(); } setModified( false ); diff --git a/src/gui/editor/EmptyValidatingEditor.java b/src/gui/editor/EmptyValidatingEditor.java index 1c37c92c..cdcd438c 100644 --- a/src/gui/editor/EmptyValidatingEditor.java +++ b/src/gui/editor/EmptyValidatingEditor.java @@ -10,7 +10,7 @@ public class EmptyValidatingEditor extends ValidatingEditor public EmptyValidatingEditor( String descriptor ) { - setLayout( new MigLayout( "insets 0 0 0 0", "[center]", "[grow]" ) ); + setLayout( new MigLayout( "insets 0 0 0 0", "", "" ) ); add( new JLabel( "Please select " + descriptor ), "wrap" ); } diff --git a/src/module/decode/AuxDecodeConfigurationEditor.java b/src/module/decode/AuxDecodeConfigurationEditor.java index c217eea4..0e40834a 100644 --- a/src/module/decode/AuxDecodeConfigurationEditor.java +++ b/src/module/decode/AuxDecodeConfigurationEditor.java @@ -42,6 +42,11 @@ public class AuxDecodeConfigurationEditor extends Editor init(); } + public AuxDecodeConfiguration getConfiguration() + { + return hasItem() ? getItem().getAuxDecodeConfiguration() : null; + } + private void init() { setLayout( new MigLayout( "fill,wrap 4", "", "[][grow]" ) ); diff --git a/src/module/decode/DecodeConfigurationEditor.java b/src/module/decode/DecodeConfigurationEditor.java index 450a1288..a4d0fee0 100644 --- a/src/module/decode/DecodeConfigurationEditor.java +++ b/src/module/decode/DecodeConfigurationEditor.java @@ -27,7 +27,6 @@ import java.awt.event.ActionListener; import javax.swing.DefaultComboBoxModel; import javax.swing.JComboBox; -import javax.swing.JLabel; import net.miginfocom.swing.MigLayout; @@ -39,21 +38,21 @@ import controller.channel.map.ChannelMapModel; public class DecodeConfigurationEditor extends ValidatingEditor { - private final static Logger mLog = LoggerFactory.getLogger( DecodeConfigurationEditor.class ); - private static final long serialVersionUID = 1L; private JComboBox mComboDecoders; - private ValidatingEditor mCurrentEditor = new EmptyValidatingEditor<>(); + private ValidatingEditor mCurrentEditor = new EmptyValidatingEditor<>( "a decoder" ); + private ChannelMapModel mChannelMapModel; public DecodeConfigurationEditor( final ChannelMapModel channelMapModel ) { + mChannelMapModel = channelMapModel; init(); } private void init() { - setLayout( new MigLayout( "fill,wrap 3", "[right][left][grow,fill]", "[][grow]" ) ); + setLayout( new MigLayout( "wrap 2", "[][grow,fill]", "[align top][grow,fill]" ) ); mComboDecoders = new JComboBox(); mComboDecoders.setEnabled( false ); @@ -72,11 +71,11 @@ public class DecodeConfigurationEditor extends ValidatingEditor public void actionPerformed( ActionEvent e ) { DecoderType selected = mComboDecoders.getItemAt( mComboDecoders.getSelectedIndex() ); - setEditor( DecoderFactory.getEditor( selected ) ); + ValidatingEditor editor = DecoderFactory.getEditor( selected, mChannelMapModel ); + setEditor( editor ); } }); - add( new JLabel( "Decoder:" ) ); add( mComboDecoders ); add( mCurrentEditor ); } @@ -85,9 +84,18 @@ public class DecodeConfigurationEditor extends ValidatingEditor { if( mCurrentEditor != editor ) { + //Set channel to null in current editor to force a save prompt as required + if( mCurrentEditor.isModified() ) + { + mCurrentEditor.setItem( null ); + } + remove( mCurrentEditor ); + mCurrentEditor = editor; + mCurrentEditor.setSaveRequestListener( this ); mCurrentEditor.setItem( getItem() ); + add( mCurrentEditor ); revalidate(); @@ -98,7 +106,7 @@ public class DecodeConfigurationEditor extends ValidatingEditor @Override public void save() { - if( hasItem() && mCurrentEditor != null ) + if( hasItem() ) { mCurrentEditor.save(); } @@ -114,6 +122,7 @@ public class DecodeConfigurationEditor extends ValidatingEditor if( hasItem() ) { mComboDecoders.setEnabled( true ); + mComboDecoders.setSelectedItem( channel.getDecodeConfiguration().getDecoderType() ); mCurrentEditor.setItem( channel ); } else diff --git a/src/module/decode/DecodeEditor.java b/src/module/decode/DecodeEditor.java deleted file mode 100644 index cddc6082..00000000 --- a/src/module/decode/DecodeEditor.java +++ /dev/null @@ -1,127 +0,0 @@ -/******************************************************************************* - * SDR Trunk - * Copyright (C) 2014 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 module.decode; - -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - -import javax.swing.JCheckBox; -import javax.swing.JLabel; -import javax.swing.JSpinner; -import javax.swing.SpinnerModel; -import javax.swing.SpinnerNumberModel; -import javax.swing.SwingConstants; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; - -import module.decode.config.DecodeConfiguration; -import net.miginfocom.swing.MigLayout; -import controller.channel.Channel; -import controller.channel.ChannelConfigurationEditor; -import controller.channel.ConfigurationValidationException; - -public class DecodeEditor extends ChannelConfigurationEditor -{ - private static final long serialVersionUID = 1L; - - protected DecodeConfiguration mConfig; - - protected JCheckBox mAFC; - protected JSpinner mAFCMaximumCorrection; - - public DecodeEditor( DecodeConfiguration config ) - { - setLayout( new MigLayout( "fill,wrap 2", "[right,grow][grow]", "[][][][][grow]" ) ); - - mConfig = config; - - if( config.supportsAFC() ) - { - mAFC = new JCheckBox( "Automatic Frequency Control" ); - mAFC.setSelected( mConfig.isAFCEnabled() ); - mAFC.addActionListener( new ActionListener() - { - @Override - public void actionPerformed( ActionEvent arg0 ) - { - mConfig.setAFC( mAFC.isSelected() ); - } - } ); - - mAFC.setToolTipText( "AFC automatically adjusts the center " - + "frequency of the channel to correct/compensate for " - + "inaccuracies and frequency drift in the tuner" ); - - add( mAFC, "span" ); - - int initial = mConfig.getAFCMaximumCorrection(); - - SpinnerModel model = new SpinnerNumberModel( initial, 0, 15000, 1 ); - - mAFCMaximumCorrection = new JSpinner( model ); - - JSpinner.NumberEditor editor = - (JSpinner.NumberEditor)mAFCMaximumCorrection.getEditor(); - editor.getTextField().setHorizontalAlignment( SwingConstants.CENTER ); - - mAFCMaximumCorrection.setToolTipText( "Sets the maximum frequency " - + "correction value in hertz, 0 - 15kHz" ); - - mAFCMaximumCorrection.addChangeListener( new ChangeListener() - { - @Override - public void stateChanged( ChangeEvent e ) - { - int value = ((SpinnerNumberModel)mAFCMaximumCorrection - .getModel()).getNumber().intValue(); - - mConfig.setAFCMaximumCorrection( value ); - - save(); - } - } ); - - add( new JLabel( "Correction Limit Hz:" ) ); - add( mAFCMaximumCorrection, "wrap" ); - } - } - - public DecodeConfiguration getConfig() - { - return mConfig; - } - - @Override - public void save() - { - } - - @Override - public void setConfiguration( Channel channel ) - { - // TODO Auto-generated method stub - - } - - @Override - public void validateConfiguration() throws ConfigurationValidationException - { - // TODO Auto-generated method stub - - } -} diff --git a/src/module/decode/DecoderFactory.java b/src/module/decode/DecoderFactory.java index d4caedc9..bdaf7e0d 100644 --- a/src/module/decode/DecoderFactory.java +++ b/src/module/decode/DecoderFactory.java @@ -48,6 +48,7 @@ import module.decode.ltrstandard.DecodeConfigLTRStandard; import module.decode.ltrstandard.LTRStandardDecoder; import module.decode.ltrstandard.LTRStandardDecoderPanel; import module.decode.ltrstandard.LTRStandardDecoderState; +import module.decode.ltrstandard.LTRStandardDecoderEditor; import module.decode.ltrstandard.LTRStandardMessageFilter; import module.decode.mdc1200.MDCDecoder; import module.decode.mdc1200.MDCDecoderPanel; @@ -56,14 +57,17 @@ import module.decode.mdc1200.MDCMessageFilter; import module.decode.mpt1327.DecodeConfigMPT1327; import module.decode.mpt1327.MPT1327Decoder; import module.decode.mpt1327.MPT1327Decoder.Sync; +import module.decode.mpt1327.MPT1327DecoderEditor; import module.decode.mpt1327.MPT1327DecoderPanel; import module.decode.mpt1327.MPT1327DecoderState; import module.decode.mpt1327.MPT1327MessageFilter; import module.decode.nbfm.DecodeConfigNBFM; import module.decode.nbfm.NBFMDecoder; import module.decode.nbfm.NBFMDecoderPanel; +import module.decode.nbfm.NBFMDecoderEditor; import module.decode.p25.DecodeConfigP25Phase1; import module.decode.p25.P25Decoder.Modulation; +import module.decode.p25.P25DecoderEditor; import module.decode.p25.P25DecoderPanel; import module.decode.p25.P25DecoderState; import module.decode.p25.P25_C4FMDecoder; @@ -74,6 +78,7 @@ import module.decode.passport.DecodeConfigPassport; import module.decode.passport.PassportDecoder; import module.decode.passport.PassportDecoderPanel; import module.decode.passport.PassportDecoderState; +import module.decode.passport.PassportDecoderEditor; import module.decode.passport.PassportMessageFilter; import module.decode.state.AlwaysUnsquelchedDecoderState; import module.decode.state.DecoderPanel; @@ -464,7 +469,7 @@ public class DecoderFactory } } - public static ValidatingEditor getEditor( DecoderType type ) + public static ValidatingEditor getEditor( DecoderType type, ChannelMapModel model ) { switch( type ) { @@ -473,20 +478,20 @@ public class DecoderFactory case LTR_NET: return new LTRNetDecoderEditor(); case LTR_STANDARD: - break; + return new LTRStandardDecoderEditor(); case MPT1327: - break; + return new MPT1327DecoderEditor( model ); case NBFM: - break; + return new NBFMDecoderEditor(); case P25_PHASE1: - break; + return new P25DecoderEditor(); case PASSPORT: - break; + return new PassportDecoderEditor(); default: break; } - return new EmptyValidatingEditor(); + return new EmptyValidatingEditor( "a decoder" ); } /** diff --git a/src/module/decode/am/AMDecoderEditor.java b/src/module/decode/am/AMDecoderEditor.java index 53d1d41c..697f7ebe 100644 --- a/src/module/decode/am/AMDecoderEditor.java +++ b/src/module/decode/am/AMDecoderEditor.java @@ -1,6 +1,6 @@ /******************************************************************************* * SDR Trunk - * Copyright (C) 2014 Dennis Sheirer + * Copyright (C) 2014-2016 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 @@ -20,6 +20,10 @@ package module.decode.am; import gui.editor.Editor; import gui.editor.EditorValidationException; import gui.editor.ValidatingEditor; + +import javax.swing.JLabel; + +import net.miginfocom.swing.MigLayout; import controller.channel.Channel; public class AMDecoderEditor extends ValidatingEditor @@ -28,6 +32,8 @@ public class AMDecoderEditor extends ValidatingEditor public AMDecoderEditor() { + setLayout( new MigLayout( "insets 0 0 0 0", "", "" ) ); + add( new JLabel( "AM Decoder" ) ); } @Override @@ -35,6 +41,28 @@ public class AMDecoderEditor extends ValidatingEditor { } + @Override + public void setItem( Channel item ) + { + super.setItem( item ); + + if( hasItem() ) + { + if( getItem().getDecodeConfiguration() instanceof DecodeConfigAM ) + { + setModified( false ); + } + else + { + setModified( true ); + } + } + else + { + setModified( false ); + } + } + @Override public void save() { diff --git a/src/module/decode/config/DecodeConfiguration.java b/src/module/decode/config/DecodeConfiguration.java index 95070a08..8390d608 100644 --- a/src/module/decode/config/DecodeConfiguration.java +++ b/src/module/decode/config/DecodeConfiguration.java @@ -17,7 +17,7 @@ ******************************************************************************/ package module.decode.config; -import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlSeeAlso; @@ -48,10 +48,12 @@ public abstract class DecodeConfiguration extends Configuration public static final int TRAFFIC_CHANNEL_LIMIT_DEFAULT = 3; public static final int TRAFFIC_CHANNEL_LIMIT_MINIMUM = 0; public static final int TRAFFIC_CHANNEL_LIMIT_MAXIMUM = 30; + + public static final int DEFAULT_AFC_MAX_CORRECTION = 1000; private DecoderType mDecoderType = DecoderType.NBFM; private boolean mAFCEnabled = true; - private int mAFCMaxCorrection = 3000; + private int mAFCMaxCorrection = DEFAULT_AFC_MAX_CORRECTION; public DecodeConfiguration() { @@ -68,7 +70,7 @@ public abstract class DecodeConfiguration extends Configuration return mDecoderType; } - @XmlElement( name = "afc" ) + @XmlAttribute( name = "afc" ) public boolean getAFC() { return mAFCEnabled; @@ -84,6 +86,7 @@ public abstract class DecodeConfiguration extends Configuration mAFCEnabled = enabled; } + @XmlAttribute( name = "AFCMaximumCorrection" ) public int getAFCMaximumCorrection() { return mAFCMaxCorrection; diff --git a/src/module/decode/ltrnet/LTRNetDecoderEditor.java b/src/module/decode/ltrnet/LTRNetDecoderEditor.java index fafdba63..1913412d 100644 --- a/src/module/decode/ltrnet/LTRNetDecoderEditor.java +++ b/src/module/decode/ltrnet/LTRNetDecoderEditor.java @@ -28,9 +28,7 @@ import javax.swing.DefaultComboBoxModel; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JLabel; -import javax.swing.JSpinner; -import javax.swing.SpinnerNumberModel; -import javax.swing.SwingConstants; +import javax.swing.JSlider; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; @@ -43,8 +41,8 @@ public class LTRNetDecoderEditor extends ValidatingEditor { private static final long serialVersionUID = 1L; - protected JCheckBox mAFC; - protected JSpinner mAFCMaximumCorrection; + private JCheckBox mAFC; + private JSlider mAFCMaximumCorrection; private JComboBox mComboDirection; public LTRNetDecoderEditor() @@ -54,10 +52,9 @@ public class LTRNetDecoderEditor extends ValidatingEditor private void init() { - setLayout( new MigLayout( "fill,wrap 5", "[left][right][grow,fill][right][grow,fill]", - "[][grow]" ) ); + setLayout( new MigLayout( "insets 0 0 0 0,wrap 4", "[right][grow,fill][right][grow,fill]", "" ) ); - mAFC = new JCheckBox( "AFC" ); + mAFC = new JCheckBox( "AFC: 3000 Hz" ); mAFC.setEnabled( false ); mAFC.setToolTipText( "AFC automatically adjusts the center frequency of the channel to " + "correct/compensate for inaccuracies and frequency drift in the tuner" ); @@ -67,26 +64,36 @@ public class LTRNetDecoderEditor extends ValidatingEditor public void actionPerformed( ActionEvent arg0 ) { setModified( true ); + + if( mAFC.isSelected() && !mAFCMaximumCorrection.isEnabled() ) + { + mAFCMaximumCorrection.setEnabled( true ); + } + else if( !mAFC.isSelected() && mAFCMaximumCorrection.isEnabled() ) + { + mAFCMaximumCorrection.setEnabled( false ); + } } } ); add( mAFC ); - mAFCMaximumCorrection = new JSpinner( new SpinnerNumberModel( 3000, 0, 15000, 1 ) ); + mAFCMaximumCorrection = new JSlider( 0, 7000, 3000 ); mAFCMaximumCorrection.setEnabled( false ); - JSpinner.NumberEditor editor = (JSpinner.NumberEditor)mAFCMaximumCorrection.getEditor(); - editor.getTextField().setHorizontalAlignment( SwingConstants.CENTER ); - mAFCMaximumCorrection.setToolTipText( "Sets the maximum frequency correction value in hertz, 0 - 15kHz" ); - mAFCMaximumCorrection.addChangeListener( new ChangeListener() - { + mAFCMaximumCorrection.setToolTipText( "Maximum AFC frequency correction (0 - 15kHz)" ); + mAFCMaximumCorrection.setMajorTickSpacing( 2000 ); + mAFCMaximumCorrection.setMinorTickSpacing( 1000 ); + mAFCMaximumCorrection.setPaintTicks( true ); + + mAFCMaximumCorrection.addChangeListener( new ChangeListener() + { @Override - public void stateChanged( ChangeEvent e ) - { + public void stateChanged( ChangeEvent e ) + { + mAFC.setText( "AFC: " + mAFCMaximumCorrection.getValue() + " Hz" ); setModified( true ); - } - } ); - - add( new JLabel( "Correction Limit Hz:" ) ); + } + } ); add( mAFCMaximumCorrection ); mComboDirection = new JComboBox(); @@ -109,6 +116,7 @@ public class LTRNetDecoderEditor extends ValidatingEditor @Override public void validate( Editor editor ) throws EditorValidationException { + //No validation } @@ -120,7 +128,6 @@ public class LTRNetDecoderEditor extends ValidatingEditor if( hasItem() ) { mAFC.setEnabled( true ); - mAFCMaximumCorrection.setEnabled( true ); mComboDirection.setEnabled( true ); DecodeConfiguration config = getItem().getDecodeConfiguration(); @@ -131,13 +138,25 @@ public class LTRNetDecoderEditor extends ValidatingEditor mComboDirection.setSelectedItem( ltr.getMessageDirection() ); mAFC.setSelected( ltr.isAFCEnabled() ); mAFCMaximumCorrection.setValue( ltr.getAFCMaximumCorrection() ); + mAFCMaximumCorrection.setEnabled( ltr.isAFCEnabled() ); + + setModified( false ); + } + else + { + mComboDirection.setSelectedItem( MessageDirection.OSW ); + mAFC.setSelected( false ); + mAFCMaximumCorrection.setValue( DecodeConfiguration.DEFAULT_AFC_MAX_CORRECTION ); + mAFCMaximumCorrection.setEnabled( false ); + + setModified( true ); } } else { mAFC.setEnabled( false ); - mAFCMaximumCorrection.setEnabled( false ); mComboDirection.setEnabled( false ); + setModified( false ); } } @@ -147,12 +166,12 @@ public class LTRNetDecoderEditor extends ValidatingEditor if( hasItem() && isModified() ) { DecodeConfigLTRNet ltr = new DecodeConfigLTRNet(); + ltr.setAFC( mAFC.isSelected() ); - - int value = ((SpinnerNumberModel)mAFCMaximumCorrection.getModel()).getNumber().intValue(); - ltr.setAFCMaximumCorrection( value ); - + ltr.setAFCMaximumCorrection( mAFCMaximumCorrection.getValue() ); ltr.setMessageDirection( (MessageDirection)mComboDirection.getSelectedItem() ); + + getItem().setDecodeConfiguration( ltr ); } setModified( false ); diff --git a/src/module/decode/ltrstandard/LTRStandardDecoderEditor.java b/src/module/decode/ltrstandard/LTRStandardDecoderEditor.java new file mode 100644 index 00000000..f75d38c5 --- /dev/null +++ b/src/module/decode/ltrstandard/LTRStandardDecoderEditor.java @@ -0,0 +1,177 @@ +/******************************************************************************* + * SDR Trunk + * Copyright (C) 2014-2016 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 module.decode.ltrstandard; + +import gui.editor.Editor; +import gui.editor.EditorValidationException; +import gui.editor.ValidatingEditor; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.DefaultComboBoxModel; +import javax.swing.JCheckBox; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JSlider; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +import message.MessageDirection; +import module.decode.config.DecodeConfiguration; +import module.decode.ltrnet.DecodeConfigLTRNet; +import net.miginfocom.swing.MigLayout; +import controller.channel.Channel; + +public class LTRStandardDecoderEditor extends ValidatingEditor +{ + private static final long serialVersionUID = 1L; + + private JCheckBox mAFC; + private JSlider mAFCMaximumCorrection; + private JComboBox mComboDirection; + + public LTRStandardDecoderEditor() + { + init(); + } + + private void init() + { + setLayout( new MigLayout( "insets 0 0 0 0,wrap 4", "[right][grow,fill][right][grow,fill]", "" ) ); + + mAFC = new JCheckBox( "AFC: 3000 Hz" ); + mAFC.setEnabled( false ); + mAFC.setToolTipText( "AFC automatically adjusts the center frequency of the channel to " + + "correct/compensate for inaccuracies and frequency drift in the tuner" ); + mAFC.addActionListener( new ActionListener() + { + @Override + public void actionPerformed( ActionEvent arg0 ) + { + setModified( true ); + + if( mAFC.isSelected() && !mAFCMaximumCorrection.isEnabled() ) + { + mAFCMaximumCorrection.setEnabled( true ); + } + else if( !mAFC.isSelected() && mAFCMaximumCorrection.isEnabled() ) + { + mAFCMaximumCorrection.setEnabled( false ); + } + } + } ); + + add( mAFC ); + + mAFCMaximumCorrection = new JSlider( 0, 7000, 3000 ); + mAFCMaximumCorrection.setEnabled( false ); + mAFCMaximumCorrection.setToolTipText( "Maximum AFC frequency correction (0 - 15kHz)" ); + mAFCMaximumCorrection.setMajorTickSpacing( 2000 ); + mAFCMaximumCorrection.setMinorTickSpacing( 1000 ); + mAFCMaximumCorrection.setPaintTicks( true ); + + mAFCMaximumCorrection.addChangeListener( new ChangeListener() + { + @Override + public void stateChanged( ChangeEvent e ) + { + mAFC.setText( "AFC: " + mAFCMaximumCorrection.getValue() + " Hz" ); + setModified( true ); + } + } ); + add( mAFCMaximumCorrection ); + + mComboDirection = new JComboBox(); + mComboDirection.setModel( new DefaultComboBoxModel( MessageDirection.values() ) ); + mComboDirection.setSelectedItem( MessageDirection.OSW ); + mComboDirection.setEnabled( false ); + mComboDirection.addActionListener( new ActionListener() + { + @Override + public void actionPerformed( ActionEvent e ) + { + setModified( true ); + } + } ); + + add( new JLabel( "Format:" ) ); + add( mComboDirection ); + } + + @Override + public void validate( Editor editor ) throws EditorValidationException + { + } + + @Override + public void setItem( Channel item ) + { + super.setItem( item ); + + if( hasItem() ) + { + mAFC.setEnabled( true ); + mComboDirection.setEnabled( true ); + + DecodeConfiguration config = getItem().getDecodeConfiguration(); + + if( config instanceof DecodeConfigLTRStandard ) + { + DecodeConfigLTRStandard ltr = (DecodeConfigLTRStandard)config; + mComboDirection.setSelectedItem( ltr.getMessageDirection() ); + mAFC.setSelected( ltr.isAFCEnabled() ); + mAFCMaximumCorrection.setValue( ltr.getAFCMaximumCorrection() ); + mAFCMaximumCorrection.setEnabled( ltr.isAFCEnabled() ); + setModified( false ); + } + else + { + mComboDirection.setSelectedItem( MessageDirection.OSW ); + mAFC.setSelected( false ); + mAFCMaximumCorrection.setValue( DecodeConfiguration.DEFAULT_AFC_MAX_CORRECTION ); + mAFCMaximumCorrection.setEnabled( false ); + + setModified( true ); + } + } + else + { + mAFC.setEnabled( false ); + mComboDirection.setEnabled( false ); + setModified( false ); + } + } + + @Override + public void save() + { + if( hasItem() && isModified() ) + { + DecodeConfigLTRStandard ltr = new DecodeConfigLTRStandard(); + + ltr.setAFC( mAFC.isSelected() ); + ltr.setAFCMaximumCorrection( mAFCMaximumCorrection.getValue() ); + ltr.setMessageDirection( (MessageDirection)mComboDirection.getSelectedItem() ); + + getItem().setDecodeConfiguration( ltr ); + } + + setModified( false ); + } +} diff --git a/src/module/decode/ltrstandard/LTRStandardEditor.java b/src/module/decode/ltrstandard/LTRStandardEditor.java deleted file mode 100644 index 35f0e107..00000000 --- a/src/module/decode/ltrstandard/LTRStandardEditor.java +++ /dev/null @@ -1,71 +0,0 @@ -/******************************************************************************* - * SDR Trunk - * Copyright (C) 2014 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 module.decode.ltrstandard; - -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - -import javax.swing.DefaultComboBoxModel; -import javax.swing.JComboBox; -import javax.swing.JLabel; - -import message.MessageDirection; -import module.decode.DecodeEditor; -import module.decode.config.DecodeConfiguration; - -public class LTRStandardEditor extends DecodeEditor -{ - private static final long serialVersionUID = 1L; - - private JComboBox mComboDirection; - - public LTRStandardEditor( DecodeConfiguration config ) - { - super( config ); - - initGUI(); - } - - private void initGUI() - { - mComboDirection = new JComboBox(); - - mComboDirection.setModel( - new DefaultComboBoxModel( MessageDirection.values() ) ); - - mComboDirection.setSelectedItem( ((DecodeConfigLTRStandard)mConfig).getMessageDirection() ); - - mComboDirection.addActionListener( new ActionListener() - { - @Override - public void actionPerformed( ActionEvent e ) - { - MessageDirection selected = mComboDirection - .getItemAt( mComboDirection.getSelectedIndex() ); - - if( selected != null ) - { - ((DecodeConfigLTRStandard)mConfig).setMessageDirection( selected ); - } - } - } ); - - add( new JLabel( "Format:" ) ); - add( mComboDirection, "wrap" ); - } -} diff --git a/src/module/decode/mpt1327/MPT1327ConfigEditor.java b/src/module/decode/mpt1327/MPT1327ConfigEditor.java deleted file mode 100644 index 586a605d..00000000 --- a/src/module/decode/mpt1327/MPT1327ConfigEditor.java +++ /dev/null @@ -1,219 +0,0 @@ -/******************************************************************************* - * SDR Trunk - * Copyright (C) 2014 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 module.decode.mpt1327; - -import java.awt.EventQueue; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.List; - -import javax.swing.DefaultComboBoxModel; -import javax.swing.JButton; -import javax.swing.JComboBox; -import javax.swing.JLabel; -import javax.swing.JSlider; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; - -import module.decode.DecodeEditor; -import module.decode.config.DecodeConfiguration; -import module.decode.mpt1327.MPT1327Decoder.Sync; -import controller.channel.map.ChannelMap; -import controller.channel.map.ChannelMapManagerFrame; -import controller.channel.map.ChannelMapModel; - -public class MPT1327ConfigEditor extends DecodeEditor -{ - private static final long serialVersionUID = 1L; - - private JComboBox mComboChannelMaps; - private JComboBox mComboSync; - private JLabel mCallTimeoutLabel; - private JSlider mCallTimeout; - private JLabel mTrafficChannelPoolSizeLabel; - private JSlider mTrafficChannelPoolSize; - private ChannelMapModel mChannelMapModel; - - public MPT1327ConfigEditor( DecodeConfiguration config, - ChannelMapModel channelMapModel ) - { - super( config ); - - mChannelMapModel = channelMapModel; - - initGUI(); - } - - private DecodeConfigMPT1327 getMPTConfig() - { - return (DecodeConfigMPT1327)mConfig; - } - - private void initGUI() - { - /** - * ComboBox: Alias Lists - */ - List maps = mChannelMapModel.getChannelMaps(); - ChannelMap[] mapArray = maps.toArray( new ChannelMap[ maps.size() ] ); - - mComboChannelMaps = new JComboBox(); - mComboChannelMaps.setModel( - new DefaultComboBoxModel( mapArray ) ); - - add( new JLabel( "Channel Map:" ) ); - add( mComboChannelMaps, "wrap" ); - - JButton channelMapManager = new JButton( "Channel Map Manager ..." ); - channelMapManager.addActionListener( new ActionListener() - { - @Override - public void actionPerformed( ActionEvent e ) - { - final ChannelMapManagerFrame manager = - new ChannelMapManagerFrame( mChannelMapModel ); - - EventQueue.invokeLater( new Runnable() - { - @Override - public void run() - { - manager.setVisible( true ); - } - } ); - } - } ); - add( channelMapManager, "wrap" ); - - mComboSync = new JComboBox(); - mComboSync.setModel( new DefaultComboBoxModel( Sync.values() ) ); - - add( new JLabel( "Sync:" ) ); - add( mComboSync, "wrap" ); - - mCallTimeout = new JSlider( JSlider.HORIZONTAL, - DecodeConfiguration.CALL_TIMEOUT_MINIMUM, - DecodeConfiguration.CALL_TIMEOUT_MAXIMUM, - DecodeConfiguration.DEFAULT_CALL_TIMEOUT_SECONDS ); - - mCallTimeout.setMajorTickSpacing( 90 ); - mCallTimeout.setMinorTickSpacing( 10 ); - mCallTimeout.setPaintTicks( true ); - - mCallTimeout.setLabelTable( mCallTimeout.createStandardLabels( 100, 100 ) ); - mCallTimeout.setPaintLabels( true ); - - mCallTimeoutLabel = new JLabel( "Call Timeout: " + mCallTimeout.getValue() + " " ); - - mCallTimeout.addChangeListener( new ChangeListener() - { - @Override - public void stateChanged( ChangeEvent e ) - { - mCallTimeoutLabel.setText( "Call Timeout: " + mCallTimeout.getValue() ); - } - } ); - - add( mCallTimeoutLabel ); - add( mCallTimeout, "wrap,grow" ); - - mTrafficChannelPoolSize = new JSlider( JSlider.HORIZONTAL, - DecodeConfiguration.TRAFFIC_CHANNEL_LIMIT_MINIMUM, - DecodeConfiguration.TRAFFIC_CHANNEL_LIMIT_MAXIMUM, - DecodeConfiguration.TRAFFIC_CHANNEL_LIMIT_DEFAULT ); - - mTrafficChannelPoolSize.setMajorTickSpacing( 10 ); - mTrafficChannelPoolSize.setMinorTickSpacing( 1 ); - mTrafficChannelPoolSize.setPaintTicks( true ); - - mTrafficChannelPoolSize.setLabelTable( mTrafficChannelPoolSize.createStandardLabels( 10, 10 ) ); - mTrafficChannelPoolSize.setPaintLabels( true ); - - mTrafficChannelPoolSizeLabel = new JLabel( "Traffic Channel Pool: " + mTrafficChannelPoolSize.getValue() + " " ); - - mTrafficChannelPoolSize.addChangeListener( new ChangeListener() - { - @Override - public void stateChanged( ChangeEvent e ) - { - mTrafficChannelPoolSizeLabel.setText( "Traffic Channel Pool: " + mTrafficChannelPoolSize.getValue() ); - } - } ); - - add( mTrafficChannelPoolSizeLabel ); - add( mTrafficChannelPoolSize, "wrap,grow" ); - -// reset(); - } - - @Override - public void save() - { - DecodeConfigMPT1327 config = getMPTConfig(); - - ChannelMap selected = (ChannelMap)mComboChannelMaps.getSelectedItem(); - - if( selected != null ) - { - config.setChannelMapName( selected.getName() ); - } - - Sync selectedSync = (Sync)mComboSync.getSelectedItem(); - - if( selectedSync != null ) - { - config.setSync( selectedSync ); - } - - config.setCallTimeout( mCallTimeout.getValue() ); - - config.setTrafficChannelPoolSize( mTrafficChannelPoolSize.getValue() ); - } - -// @Override -// public void reset() -// { -// DecodeConfigMPT1327 config = (DecodeConfigMPT1327)mConfig; -// -// String name = config.getChannelMapName(); -// -// ChannelMap selected = null; -// -// if( name != null ) -// { -// for( ChannelMap map: mPlaylistManager.getPlayist().getChannelMapList() -// .getChannelMap() ) -// { -// if( map.getName().equalsIgnoreCase( name ) ) -// { -// selected = map; -// } -// } -// } -// -// mComboChannelMaps.setSelectedItem( selected ); -// mComboChannelMaps.requestFocus(); -// mComboChannelMaps.requestFocusInWindow(); -// -// mComboSync.setSelectedItem( config.getSync() ); -// -// mCallTimeout.setValue( config.getCallTimeout() ); -// -// mTrafficChannelPoolSize.setValue( config.getTrafficChannelPoolSize() ); -// } -} diff --git a/src/module/decode/mpt1327/MPT1327DecoderEditor.java b/src/module/decode/mpt1327/MPT1327DecoderEditor.java new file mode 100644 index 00000000..fd2bc636 --- /dev/null +++ b/src/module/decode/mpt1327/MPT1327DecoderEditor.java @@ -0,0 +1,287 @@ +/******************************************************************************* + * SDR Trunk + * Copyright (C) 2014-2016 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 module.decode.mpt1327; + +import gui.editor.Editor; +import gui.editor.EditorValidationException; +import gui.editor.ValidatingEditor; + +import java.awt.EventQueue; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.List; + +import javax.swing.DefaultComboBoxModel; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JSlider; +import javax.swing.SpinnerNumberModel; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +import module.decode.config.DecodeConfiguration; +import module.decode.ltrnet.DecodeConfigLTRNet; +import net.miginfocom.swing.MigLayout; +import controller.channel.Channel; +import controller.channel.map.ChannelMap; +import controller.channel.map.ChannelMapManagerFrame; +import controller.channel.map.ChannelMapModel; + +public class MPT1327DecoderEditor extends ValidatingEditor +{ + private static final long serialVersionUID = 1L; + + private JCheckBox mAFC; + private JSlider mAFCMaximumCorrection; + private JComboBox mComboChannelMaps; + private JLabel mCallTimeoutLabel; + private JSlider mCallTimeout; + private JLabel mTrafficChannelPoolSizeLabel; + private JSlider mTrafficChannelPoolSize; + private ChannelMapModel mChannelMapModel; + + public MPT1327DecoderEditor( ChannelMapModel channelMapModel ) + { + mChannelMapModel = channelMapModel; + + init(); + } + + private void init() + { + setLayout( new MigLayout( "insets 0 0 0 0,wrap 4", "[right][grow,fill][right][grow,fill]", "" ) ); + + mAFC = new JCheckBox( "AFC: 3000 Hz" ); + mAFC.setEnabled( false ); + mAFC.setToolTipText( "AFC automatically adjusts the center frequency of the channel to " + + "correct/compensate for inaccuracies and frequency drift in the tuner" ); + mAFC.addActionListener( new ActionListener() + { + @Override + public void actionPerformed( ActionEvent arg0 ) + { + setModified( true ); + + if( mAFC.isSelected() && !mAFCMaximumCorrection.isEnabled() ) + { + mAFCMaximumCorrection.setEnabled( true ); + } + else if( !mAFC.isSelected() && mAFCMaximumCorrection.isEnabled() ) + { + mAFCMaximumCorrection.setEnabled( false ); + } + } + } ); + + add( mAFC ); + + mAFCMaximumCorrection = new JSlider( 0, 7000, 3000 ); + mAFCMaximumCorrection.setEnabled( false ); + mAFCMaximumCorrection.setToolTipText( "Maximum AFC frequency correction (0 - 15kHz)" ); + mAFCMaximumCorrection.setMajorTickSpacing( 2000 ); + mAFCMaximumCorrection.setMinorTickSpacing( 1000 ); + mAFCMaximumCorrection.setPaintTicks( true ); + + mAFCMaximumCorrection.addChangeListener( new ChangeListener() + { + @Override + public void stateChanged( ChangeEvent e ) + { + mAFC.setText( "AFC: " + mAFCMaximumCorrection.getValue() + " Hz" ); + setModified( true ); + } + } ); + add( mAFCMaximumCorrection ); + + JButton channelMaps = new JButton( "Channel Maps" ); + channelMaps.addActionListener( new ActionListener() + { + @Override + public void actionPerformed( ActionEvent e ) + { + final ChannelMapManagerFrame manager = + new ChannelMapManagerFrame( mChannelMapModel ); + + EventQueue.invokeLater( new Runnable() + { + @Override + public void run() + { + manager.setVisible( true ); + } + } ); + } + } ); + add( channelMaps, "span 2" ); + + List maps = mChannelMapModel.getChannelMaps(); + ChannelMap[] mapArray = maps.toArray( new ChannelMap[ maps.size() ] ); + + mComboChannelMaps = new JComboBox(); + mComboChannelMaps.setModel( new DefaultComboBoxModel( mapArray ) ); + mComboChannelMaps.setEnabled( false ); + add( new JLabel( "Channel Map:" ) ); + add( mComboChannelMaps, "span 3,grow" ); + + mTrafficChannelPoolSize = new JSlider( JSlider.HORIZONTAL, DecodeConfiguration.TRAFFIC_CHANNEL_LIMIT_MINIMUM, + DecodeConfiguration.TRAFFIC_CHANNEL_LIMIT_MAXIMUM, DecodeConfiguration.TRAFFIC_CHANNEL_LIMIT_DEFAULT ); + mTrafficChannelPoolSize.setEnabled( false ); + mTrafficChannelPoolSize.setMajorTickSpacing( 10 ); + mTrafficChannelPoolSize.setMinorTickSpacing( 5 ); + mTrafficChannelPoolSize.setPaintTicks( true ); + mTrafficChannelPoolSizeLabel = new JLabel( "Traffic Pool: " + + mTrafficChannelPoolSize.getValue() + " " ); + + mTrafficChannelPoolSize.addChangeListener( new ChangeListener() + { + @Override + public void stateChanged( ChangeEvent e ) + { + mTrafficChannelPoolSizeLabel.setText( "Traffic Pool: " + + mTrafficChannelPoolSize.getValue() ); + } + } ); + + add( mTrafficChannelPoolSizeLabel ); + add( mTrafficChannelPoolSize ); + + mCallTimeout = new JSlider( JSlider.HORIZONTAL, DecodeConfiguration.CALL_TIMEOUT_MINIMUM, + DecodeConfiguration.CALL_TIMEOUT_MAXIMUM, DecodeConfiguration.DEFAULT_CALL_TIMEOUT_SECONDS ); + mCallTimeout.setEnabled( false ); + mCallTimeout.setMajorTickSpacing( 100 ); + mCallTimeout.setMinorTickSpacing( 50 ); + mCallTimeout.setPaintTicks( true ); + + mCallTimeoutLabel = new JLabel( "Timeout: " + mCallTimeout.getValue() + " " ); + + mCallTimeout.addChangeListener( new ChangeListener() + { + @Override + public void stateChanged( ChangeEvent e ) + { + mCallTimeoutLabel.setText( "Timeout: " + mCallTimeout.getValue() ); + } + } ); + + add( mCallTimeoutLabel ); + add( mCallTimeout ); + } + + @Override + public void save() + { + if( hasItem() && isModified() ) + { + DecodeConfigMPT1327 mpt = new DecodeConfigMPT1327(); + mpt.setAFC( mAFC.isSelected() ); + mpt.setAFCMaximumCorrection( mAFCMaximumCorrection.getValue() ); + mpt.setTrafficChannelPoolSize( mTrafficChannelPoolSize.getValue() ); + mpt.setCallTimeout( mCallTimeout.getValue() ); + + if( mComboChannelMaps.getSelectedItem() != null ) + { + ChannelMap map = (ChannelMap)mComboChannelMaps.getSelectedItem(); + + mpt.setChannelMapName( map.getName() ); + } + + getItem().setDecodeConfiguration( mpt ); + } + + setModified( false ); + } + + @Override + public void validate( Editor editor ) throws EditorValidationException + { + //No validation required + } + + private void setControlsEnabled( boolean enabled ) + { + if( mAFC.isEnabled() != enabled ) + { + mAFC.setEnabled( enabled ); + } + + if( mComboChannelMaps.isEnabled() != enabled ) + { + mComboChannelMaps.setEnabled( enabled ); + } + + if( mTrafficChannelPoolSize.isEnabled() != enabled ) + { + mTrafficChannelPoolSize.setEnabled( enabled ); + } + + if( mCallTimeout.isEnabled() != enabled ) + { + mCallTimeout.setEnabled( enabled ); + } + } + + @Override + public void setItem( Channel item ) + { + super.setItem( item ); + + if( hasItem() ) + { + setControlsEnabled( true ); + + DecodeConfiguration config = getItem().getDecodeConfiguration(); + + if( config instanceof DecodeConfigMPT1327 ) + { + DecodeConfigMPT1327 mpt = (DecodeConfigMPT1327)config; + mAFC.setSelected( mpt.isAFCEnabled() ); + mAFCMaximumCorrection.setValue( mpt.getAFCMaximumCorrection() ); + mAFCMaximumCorrection.setEnabled( mpt.isAFCEnabled() ); + + ChannelMap map = mChannelMapModel.getChannelMap( mpt.getChannelMapName() ); + + if( map != null ) + { + mComboChannelMaps.setSelectedItem( map ); + } + + mTrafficChannelPoolSize.setValue( mpt.getTrafficChannelPoolSize() ); + mCallTimeout.setValue( mpt.getCallTimeout() ); + + setModified( false ); + } + else + { + mAFC.setSelected( false ); + mAFCMaximumCorrection.setValue( DecodeConfiguration.DEFAULT_AFC_MAX_CORRECTION ); + mAFCMaximumCorrection.setEnabled( false ); + mTrafficChannelPoolSize.setValue( DecodeConfiguration.TRAFFIC_CHANNEL_LIMIT_DEFAULT ); + mCallTimeout.setValue( DecodeConfiguration.DEFAULT_CALL_TIMEOUT_SECONDS ); + + setModified( true ); + } + } + else + { + setControlsEnabled( false ); + setModified( false ); + } + } +} diff --git a/src/module/decode/nbfm/NBFMDecoderEditor.java b/src/module/decode/nbfm/NBFMDecoderEditor.java new file mode 100644 index 00000000..9d6d025c --- /dev/null +++ b/src/module/decode/nbfm/NBFMDecoderEditor.java @@ -0,0 +1,161 @@ +/******************************************************************************* + * SDR Trunk + * Copyright (C) 2014-2016 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 module.decode.nbfm; + +import gui.editor.Editor; +import gui.editor.EditorValidationException; +import gui.editor.ValidatingEditor; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.JCheckBox; +import javax.swing.JSlider; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +import module.decode.config.DecodeConfiguration; +import net.miginfocom.swing.MigLayout; +import controller.channel.Channel; + +public class NBFMDecoderEditor extends ValidatingEditor +{ + private static final long serialVersionUID = 1L; + + private JCheckBox mAFC; + private JSlider mAFCMaximumCorrection; + + public NBFMDecoderEditor() + { + init(); + } + + private void init() + { + setLayout( new MigLayout( "insets 0 0 0 0,wrap 2", "[right][grow,fill]", "" ) ); + + mAFC = new JCheckBox( "AFC: 3000 Hz" ); + mAFC.setEnabled( false ); + mAFC.setToolTipText( "AFC automatically adjusts the center frequency of the channel to " + + "correct/compensate for inaccuracies and frequency drift in the tuner" ); + mAFC.addActionListener( new ActionListener() + { + @Override + public void actionPerformed( ActionEvent arg0 ) + { + setModified( true ); + + if( mAFC.isSelected() && !mAFCMaximumCorrection.isEnabled() ) + { + mAFCMaximumCorrection.setEnabled( true ); + } + else if( !mAFC.isSelected() && mAFCMaximumCorrection.isEnabled() ) + { + mAFCMaximumCorrection.setEnabled( false ); + } + } + } ); + + add( mAFC ); + + mAFCMaximumCorrection = new JSlider( 0, 7000, 3000 ); + mAFCMaximumCorrection.setEnabled( false ); + mAFCMaximumCorrection.setToolTipText( "Maximum AFC frequency correction (0 - 15kHz)" ); + mAFCMaximumCorrection.setMajorTickSpacing( 2000 ); + mAFCMaximumCorrection.setMinorTickSpacing( 1000 ); + mAFCMaximumCorrection.setPaintTicks( true ); + + mAFCMaximumCorrection.addChangeListener( new ChangeListener() + { + @Override + public void stateChanged( ChangeEvent e ) + { + mAFC.setText( "AFC: " + mAFCMaximumCorrection.getValue() + " Hz" ); + setModified( true ); + } + } ); + add( mAFCMaximumCorrection ); + } + + @Override + public void validate( Editor editor ) throws EditorValidationException + { + //No validation + } + + @Override + public void save() + { + if( hasItem() && isModified() ) + { + DecodeConfigNBFM nbfm = new DecodeConfigNBFM(); + + nbfm.setAFC( mAFC.isSelected() ); + nbfm.setAFCMaximumCorrection( mAFCMaximumCorrection.getValue() ); + + getItem().setDecodeConfiguration( nbfm ); + } + + setModified( false ); + } + + private void setControlsEnabled( boolean enabled ) + { + if( mAFC.isEnabled() != enabled ) + { + mAFC.setEnabled( enabled ); + } + } + + @Override + public void setItem( Channel item ) + { + super.setItem( item ); + + if( hasItem() ) + { + setControlsEnabled( true ); + + DecodeConfiguration config = getItem().getDecodeConfiguration(); + + if( config instanceof DecodeConfigNBFM ) + { + DecodeConfigNBFM nbfm = (DecodeConfigNBFM)config; + + mAFC.setSelected( nbfm.isAFCEnabled() ); + mAFCMaximumCorrection.setValue( nbfm.getAFCMaximumCorrection() ); + mAFCMaximumCorrection.setEnabled( nbfm.isAFCEnabled() ); + + setModified( false ); + } + else + { + mAFC.setSelected( false ); + mAFCMaximumCorrection.setValue( DecodeConfiguration.DEFAULT_AFC_MAX_CORRECTION ); + mAFCMaximumCorrection.setEnabled( false ); + + setModified( true ); + } + } + else + { + setControlsEnabled( false ); + setModified( false ); + } + } +} diff --git a/src/module/decode/nbfm/NBFMEditor.java b/src/module/decode/nbfm/NBFMEditor.java deleted file mode 100644 index d80e099a..00000000 --- a/src/module/decode/nbfm/NBFMEditor.java +++ /dev/null @@ -1,35 +0,0 @@ -/******************************************************************************* - * SDR Trunk - * Copyright (C) 2014 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 module.decode.nbfm; - -import javax.swing.JCheckBox; - -import module.decode.DecodeEditor; -import module.decode.config.DecodeConfiguration; - -public class NBFMEditor extends DecodeEditor -{ - private static final long serialVersionUID = 1L; - - private JCheckBox mAFC; - - public NBFMEditor( DecodeConfiguration config ) - { - super( config ); - } -} diff --git a/src/module/decode/p25/P25DecodeEditor.java b/src/module/decode/p25/P25DecodeEditor.java deleted file mode 100644 index e381cc28..00000000 --- a/src/module/decode/p25/P25DecodeEditor.java +++ /dev/null @@ -1,147 +0,0 @@ -/******************************************************************************* - * SDR Trunk - * Copyright (C) 2014 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 module.decode.p25; - -import javax.swing.DefaultComboBoxModel; -import javax.swing.JCheckBox; -import javax.swing.JComboBox; -import javax.swing.JLabel; -import javax.swing.JSlider; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; - -import module.decode.DecodeEditor; -import module.decode.config.DecodeConfiguration; -import module.decode.p25.P25Decoder.Modulation; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import source.SourceConfigurationEditor; -import source.tuner.TunerSourceEditor; -import controller.channel.ChannelConfigurationEditor; -import controller.channel.ConfigurationValidationException; - -public class P25DecodeEditor extends DecodeEditor -{ - private final static Logger mLog = LoggerFactory.getLogger( P25DecodeEditor.class ); - - private static final long serialVersionUID = 1L; - - private JComboBox mComboModulation; - private JCheckBox mIgnoreDataCalls; - private JLabel mTrafficChannelPoolSizeLabel; - private JSlider mTrafficChannelPoolSize; - - public P25DecodeEditor( DecodeConfiguration config ) - { - super( config ); - - initGUI(); - } - - private void initGUI() - { - final DecodeConfigP25Phase1 config = (DecodeConfigP25Phase1)mConfig; - - mComboModulation = new JComboBox(); - - mComboModulation.setModel( new DefaultComboBoxModel( - P25_LSMDecoder.Modulation.values() ) ); - - mComboModulation.setSelectedItem( config.getModulation() ); - - add( new JLabel( "Modulation:" ) ); - add( mComboModulation, "wrap" ); - - mTrafficChannelPoolSize = new JSlider( JSlider.HORIZONTAL, - DecodeConfiguration.TRAFFIC_CHANNEL_LIMIT_MINIMUM, - DecodeConfiguration.TRAFFIC_CHANNEL_LIMIT_MAXIMUM, - config.getTrafficChannelPoolSize() ); - - mTrafficChannelPoolSize.setMajorTickSpacing( 10 ); - mTrafficChannelPoolSize.setMinorTickSpacing( 1 ); - mTrafficChannelPoolSize.setPaintTicks( true ); - - mTrafficChannelPoolSize.setLabelTable( mTrafficChannelPoolSize.createStandardLabels( 10, 10 ) ); - mTrafficChannelPoolSize.setPaintLabels( true ); - - mTrafficChannelPoolSizeLabel = new JLabel( "Traffic Channel Pool: " + mTrafficChannelPoolSize.getValue() + " " ); - - mTrafficChannelPoolSize.addChangeListener( new ChangeListener() - { - @Override - public void stateChanged( ChangeEvent e ) - { - mTrafficChannelPoolSizeLabel.setText( "Traffic Channel Pool: " + mTrafficChannelPoolSize.getValue() ); - } - } ); - - add( mTrafficChannelPoolSizeLabel ); - add( mTrafficChannelPoolSize, "wrap,grow" ); - - mIgnoreDataCalls = new JCheckBox(); - mIgnoreDataCalls.setSelected( config.getIgnoreDataCalls() ); - - add( new JLabel( "Ignore Data Calls" ) ); - add( mIgnoreDataCalls, "wrap,grow" ); - -// reset(); - } - -// /** -// * Enforce source=tuner for CQPSK modulation -// */ -// @Override -// public void validate( ChannelConfigurationEditor editor ) throws ConfigurationValidationException -// { -// if( editor instanceof SourceEditor && -// ((DecodeConfigP25Phase1)mConfig).getModulation() == Modulation.CQPSK ) -// { -// if( !( editor instanceof TunerEditor ) ) -// { -// throw new ConfigurationValidationException( -// "

LSM Simulcast

" -// + "

P25 LSM Simulcast decoder can only be used with " -// + "a tuner source. Please change the Source to use a tuner" -// + " or change the P25 Decoder to C4FM modulation" ); -// -// } -// } -// } - - @Override - public void save() - { - DecodeConfigP25Phase1 config = (DecodeConfigP25Phase1)mConfig; - - config.setModulation( (Modulation)mComboModulation.getSelectedItem() ); - config.setIgnoreDataCalls( mIgnoreDataCalls.isSelected() ); - config.setTrafficChannelPoolSize( mTrafficChannelPoolSize.getValue() ); - } - -// @Override -// public void reset() -// { -// DecodeConfigP25Phase1 config = (DecodeConfigP25Phase1)mConfig; -// -// mComboModulation.setSelectedItem( config.getModulation() ); -// mIgnoreDataCalls.setSelected( config.getIgnoreDataCalls() ); -// mTrafficChannelPoolSize.setValue( config.getTrafficChannelPoolSize() ); -// } -} diff --git a/src/module/decode/p25/P25DecoderEditor.java b/src/module/decode/p25/P25DecoderEditor.java new file mode 100644 index 00000000..e647e407 --- /dev/null +++ b/src/module/decode/p25/P25DecoderEditor.java @@ -0,0 +1,226 @@ +/******************************************************************************* + * SDR Trunk + * Copyright (C) 2014-2016 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 module.decode.p25; + +import gui.editor.Editor; +import gui.editor.EditorValidationException; +import gui.editor.ValidatingEditor; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.DefaultComboBoxModel; +import javax.swing.JCheckBox; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JSlider; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +import module.decode.AuxDecodeConfigurationEditor; +import module.decode.config.AuxDecodeConfiguration; +import module.decode.config.DecodeConfiguration; +import module.decode.p25.P25Decoder.Modulation; +import net.miginfocom.swing.MigLayout; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import source.SourceConfigurationEditor; +import source.config.SourceConfigTuner; +import source.config.SourceConfiguration; +import controller.channel.Channel; + +public class P25DecoderEditor extends ValidatingEditor +{ + private final static Logger mLog = LoggerFactory.getLogger( P25DecoderEditor.class ); + + private static final long serialVersionUID = 1L; + + private JComboBox mComboModulation; + private JCheckBox mIgnoreDataCalls; + private JLabel mTrafficChannelPoolSizeLabel; + private JSlider mTrafficChannelPoolSize; + + public P25DecoderEditor() + { + init(); + } + + private void init() + { + setLayout( new MigLayout( "insets 0 0 0 0,wrap 3", "[right][grow,fill][]", "" ) ); + + mComboModulation = new JComboBox(); + mComboModulation.setModel( new DefaultComboBoxModel( + P25_LSMDecoder.Modulation.values() ) ); + mComboModulation.setEnabled( false ); + mComboModulation.addActionListener( new ActionListener() + { + @Override + public void actionPerformed( ActionEvent e ) + { + setModified( true ); + } + } ); + + add( new JLabel( "Modulation:" ) ); + add( mComboModulation ); + + mIgnoreDataCalls = new JCheckBox( "Ignore Data Calls" ); + mIgnoreDataCalls.setEnabled( false ); + mIgnoreDataCalls.addActionListener( new ActionListener() + { + @Override + public void actionPerformed( ActionEvent e ) + { + setModified( true ); + } + } ); + + add( mIgnoreDataCalls ); + + mTrafficChannelPoolSize = new JSlider( JSlider.HORIZONTAL, DecodeConfiguration.TRAFFIC_CHANNEL_LIMIT_MINIMUM, + DecodeConfiguration.TRAFFIC_CHANNEL_LIMIT_MAXIMUM, DecodeConfiguration.TRAFFIC_CHANNEL_LIMIT_DEFAULT ); + mTrafficChannelPoolSize.setEnabled( false ); + mTrafficChannelPoolSize.setMajorTickSpacing( 10 ); + mTrafficChannelPoolSize.setMinorTickSpacing( 5 ); + mTrafficChannelPoolSize.setPaintTicks( true ); + mTrafficChannelPoolSize.addChangeListener( new ChangeListener() + { + @Override + public void stateChanged( ChangeEvent e ) + { + mTrafficChannelPoolSizeLabel.setText( "Traffic Pool: " + mTrafficChannelPoolSize.getValue() ); + setModified( true ); + } + } ); + + mTrafficChannelPoolSizeLabel = new JLabel( "Traffic Pool: " + mTrafficChannelPoolSize.getValue() + " " ); + + add( mTrafficChannelPoolSizeLabel ); + add( mTrafficChannelPoolSize ); + } + + @Override + public void save() + { + if( hasItem() && isModified() ) + { + DecodeConfigP25Phase1 p25 = new DecodeConfigP25Phase1(); + + p25.setModulation( (Modulation)mComboModulation.getSelectedItem() ); + p25.setIgnoreDataCalls( mIgnoreDataCalls.isSelected() ); + p25.setTrafficChannelPoolSize( mTrafficChannelPoolSize.getValue() ); + + getItem().setDecodeConfiguration( p25 ); + } + + setModified( false ); + } + + @Override + public void validate( Editor editor ) throws EditorValidationException + { + mLog.debug( "Validating editor:" + editor.getClass() ); + /** + * Enforce CQPSK modulation uses a Tuner Source for I/Q sample data + */ + if( editor instanceof SourceConfigurationEditor && + ((Modulation)mComboModulation.getSelectedItem()) == Modulation.CQPSK ) + { + SourceConfiguration config = ((SourceConfigurationEditor)editor).getSourceConfiguration(); + + if( config != null && !( config instanceof SourceConfigTuner ) ) + { + throw new EditorValidationException( editor, + "

LSM Simulcast

" + + "

P25 LSM Simulcast decoder can only be used with " + + "a tuner source. Please change the Source to use a tuner" + + " or change the P25 Decoder to C4FM modulation

" ); + } + } + + if( editor instanceof AuxDecodeConfigurationEditor ) + { + AuxDecodeConfiguration config = ((AuxDecodeConfigurationEditor)editor).getConfiguration(); + + if( config != null && !config.getAuxDecoders().isEmpty() ) + { + throw new EditorValidationException( editor, + "

Auxilary Decoders

" + + "

The auxiliary decoders work with analog audio and are not " + + "compatible with the P25 Decoder. Please uncheck any auxiliary " + + "decoders that you have selected for this channel

" ); + } + } + } + + private void setControlsEnabled( boolean enabled ) + { + if( mComboModulation.isEnabled() != enabled ) + { + mComboModulation.setEnabled( enabled ); + } + + if( mTrafficChannelPoolSize.isEnabled() != enabled ) + { + mTrafficChannelPoolSize.setEnabled( enabled ); + } + + if( mIgnoreDataCalls.isEnabled() != enabled ) + { + mIgnoreDataCalls.setEnabled( enabled ); + } + } + + @Override + public void setItem( Channel item ) + { + super.setItem( item ); + + if( hasItem() ) + { + setControlsEnabled( true ); + + DecodeConfiguration config = getItem().getDecodeConfiguration(); + + if( config instanceof DecodeConfigP25Phase1 ) + { + DecodeConfigP25Phase1 p25 = (DecodeConfigP25Phase1)config; + + mComboModulation.setSelectedItem( p25.getModulation() ); + mIgnoreDataCalls.setSelected( p25.getIgnoreDataCalls() ); + mTrafficChannelPoolSize.setValue( p25.getTrafficChannelPoolSize() ); + setModified( false ); + } + else + { + mComboModulation.setSelectedItem( Modulation.C4FM ); + mIgnoreDataCalls.setSelected( false ); + mTrafficChannelPoolSize.setValue( DecodeConfiguration.TRAFFIC_CHANNEL_LIMIT_DEFAULT ); + setModified( true ); + } + } + else + { + setControlsEnabled( false ); + setModified( false ); + } + } +} diff --git a/src/module/decode/passport/PassportDecoderEditor.java b/src/module/decode/passport/PassportDecoderEditor.java new file mode 100644 index 00000000..e40dd11a --- /dev/null +++ b/src/module/decode/passport/PassportDecoderEditor.java @@ -0,0 +1,159 @@ +/******************************************************************************* + * SDR Trunk + * Copyright (C) 2014-2016 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 module.decode.passport; + +import gui.editor.Editor; +import gui.editor.EditorValidationException; +import gui.editor.ValidatingEditor; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.JCheckBox; +import javax.swing.JSlider; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +import module.decode.config.DecodeConfiguration; +import net.miginfocom.swing.MigLayout; +import controller.channel.Channel; + +public class PassportDecoderEditor extends ValidatingEditor +{ + private static final long serialVersionUID = 1L; + + private JCheckBox mAFC; + private JSlider mAFCMaximumCorrection; + + public PassportDecoderEditor() + { + init(); + } + + private void init() + { + setLayout( new MigLayout( "insets 0 0 0 0,wrap 2", "[right][grow,fill]", "" ) ); + + mAFC = new JCheckBox( "AFC: 3000 Hz" ); + mAFC.setEnabled( false ); + mAFC.setToolTipText( "AFC automatically adjusts the center frequency of the channel to " + + "correct/compensate for inaccuracies and frequency drift in the tuner" ); + mAFC.addActionListener( new ActionListener() + { + @Override + public void actionPerformed( ActionEvent arg0 ) + { + setModified( true ); + + if( mAFC.isSelected() && !mAFCMaximumCorrection.isEnabled() ) + { + mAFCMaximumCorrection.setEnabled( true ); + } + else if( !mAFC.isSelected() && mAFCMaximumCorrection.isEnabled() ) + { + mAFCMaximumCorrection.setEnabled( false ); + } + } + } ); + + add( mAFC ); + + mAFCMaximumCorrection = new JSlider( 0, 7000, 3000 ); + mAFCMaximumCorrection.setEnabled( false ); + mAFCMaximumCorrection.setToolTipText( "Maximum AFC frequency correction (0 - 15kHz)" ); + mAFCMaximumCorrection.setMajorTickSpacing( 2000 ); + mAFCMaximumCorrection.setMinorTickSpacing( 1000 ); + mAFCMaximumCorrection.setPaintTicks( true ); + + mAFCMaximumCorrection.addChangeListener( new ChangeListener() + { + @Override + public void stateChanged( ChangeEvent e ) + { + mAFC.setText( "AFC: " + mAFCMaximumCorrection.getValue() + " Hz" ); + setModified( true ); + } + } ); + add( mAFCMaximumCorrection ); + } + + @Override + public void validate( Editor editor ) throws EditorValidationException + { + //No validation + } + + @Override + public void save() + { + if( hasItem() && isModified() ) + { + DecodeConfigPassport passport = new DecodeConfigPassport(); + + passport.setAFC( mAFC.isSelected() ); + passport.setAFCMaximumCorrection( mAFCMaximumCorrection.getValue() ); + + getItem().setDecodeConfiguration( passport ); + } + + setModified( false ); + } + + private void setControlsEnabled( boolean enabled ) + { + if( mAFC.isEnabled() != enabled ) + { + mAFC.setEnabled( enabled ); + } + } + + @Override + public void setItem( Channel item ) + { + super.setItem( item ); + + if( hasItem() ) + { + setControlsEnabled( true ); + + DecodeConfiguration config = getItem().getDecodeConfiguration(); + + if( config instanceof DecodeConfigPassport ) + { + DecodeConfigPassport passport = (DecodeConfigPassport)config; + + mAFC.setSelected( passport.isAFCEnabled() ); + mAFCMaximumCorrection.setValue( passport.getAFCMaximumCorrection() ); + mAFCMaximumCorrection.setEnabled( passport.isAFCEnabled() ); + setModified( false ); + } + else + { + mAFC.setSelected( false ); + mAFCMaximumCorrection.setValue( DecodeConfiguration.DEFAULT_AFC_MAX_CORRECTION ); + mAFCMaximumCorrection.setEnabled( false ); + setModified( true ); + } + } + else + { + setControlsEnabled( false ); + setModified( false ); + } + } +} diff --git a/src/module/decode/passport/PassportEditor.java b/src/module/decode/passport/PassportEditor.java deleted file mode 100644 index 4b39e15d..00000000 --- a/src/module/decode/passport/PassportEditor.java +++ /dev/null @@ -1,31 +0,0 @@ -/******************************************************************************* - * SDR Trunk - * Copyright (C) 2014 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 module.decode.passport; - -import module.decode.DecodeEditor; -import module.decode.config.DecodeConfiguration; - -public class PassportEditor extends DecodeEditor -{ - private static final long serialVersionUID = 1L; - - public PassportEditor( DecodeConfiguration config ) - { - super( config ); - } -} diff --git a/src/record/RecordEditor.java b/src/record/RecordEditor.java deleted file mode 100644 index 9913bf9e..00000000 --- a/src/record/RecordEditor.java +++ /dev/null @@ -1,59 +0,0 @@ -/******************************************************************************* - * SDR Trunk - * Copyright (C) 2014 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 record; - -import record.config.RecordConfiguration; -import controller.channel.Channel; -import controller.channel.ChannelConfigurationEditor; -import controller.channel.ConfigurationValidationException; - -public class RecordEditor extends ChannelConfigurationEditor -{ - private static final long serialVersionUID = 1L; - - protected RecordConfiguration mConfig; - - public RecordEditor( RecordConfiguration config ) - { - mConfig = config; - } - - public RecordConfiguration getConfig() - { - return mConfig; - } - - @Override - public void save() - { - } - - @Override - public void setConfiguration( Channel channel ) - { - // TODO Auto-generated method stub - - } - - @Override - public void validateConfiguration() throws ConfigurationValidationException - { - // TODO Auto-generated method stub - - } -} diff --git a/src/source/SourceConfigurationEditor.java b/src/source/SourceConfigurationEditor.java index e5df0ae9..2c16c299 100644 --- a/src/source/SourceConfigurationEditor.java +++ b/src/source/SourceConfigurationEditor.java @@ -25,9 +25,9 @@ import java.awt.event.ActionListener; import javax.swing.DefaultComboBoxModel; import javax.swing.JComboBox; -import javax.swing.JLabel; import net.miginfocom.swing.MigLayout; +import source.config.SourceConfiguration; import source.mixer.MixerSourceEditor; import source.tuner.TunerSourceEditor; import controller.channel.Channel; @@ -44,13 +44,22 @@ public class SourceConfigurationEditor extends Editor public SourceConfigurationEditor( SourceManager sourceManager ) { mMixerSourceEditor = new MixerSourceEditor( sourceManager ); + mMixerSourceEditor.setSaveRequestListener( this ); + mTunerSourceEditor = new TunerSourceEditor(); + mTunerSourceEditor.setSaveRequestListener( this ); + init(); } + + public SourceConfiguration getSourceConfiguration() + { + return hasItem() ? getItem().getSourceConfiguration() : null; + } private void init() { - setLayout( new MigLayout( "fill,wrap 3", "[right][left][grow,fill]", "[][grow]" ) ); + setLayout( new MigLayout( "wrap 2", "[][grow,fill]", "[align top][grow]" ) ); mComboSources = new JComboBox(); mComboSources.setModel( new DefaultComboBoxModel( SourceType.getTypes() ) ); @@ -76,7 +85,6 @@ public class SourceConfigurationEditor extends Editor } }); - add( new JLabel( "Source:" ) ); add( mComboSources ); mCurrentEditor = mTunerSourceEditor; @@ -87,10 +95,16 @@ public class SourceConfigurationEditor extends Editor { if( mCurrentEditor != editor ) { + //Set channel to null to force a save prompt as required + mCurrentEditor.setItem( null ); + remove( mCurrentEditor ); mCurrentEditor = editor; + mCurrentEditor.setSaveRequestListener( this ); add( mCurrentEditor ); + mCurrentEditor.setItem( getItem() ); + revalidate(); } } @@ -98,18 +112,12 @@ public class SourceConfigurationEditor extends Editor @Override public void save() { - if( hasItem() && mCurrentEditor.isModified() ) + if( hasItem() ) { mCurrentEditor.save(); } } - @Override - public boolean isModified() - { - return super.isModified() || mCurrentEditor.isModified(); - } - /** * Sets the channel configuration. Note: this method must be invoked from * the swing event dispatch thread. @@ -121,8 +129,9 @@ public class SourceConfigurationEditor extends Editor if( hasItem() ) { - mMixerSourceEditor.setItem( channel ); - mTunerSourceEditor.setItem( channel ); + mComboSources.setSelectedItem( getItem().getSourceConfiguration().getSourceType() ); + repaint(); + mCurrentEditor.setItem( channel ); } } } diff --git a/src/source/mixer/MixerSourceEditor.java b/src/source/mixer/MixerSourceEditor.java index fdae5537..11ad5516 100644 --- a/src/source/mixer/MixerSourceEditor.java +++ b/src/source/mixer/MixerSourceEditor.java @@ -50,7 +50,7 @@ public class MixerSourceEditor extends Editor private void init() { - setLayout( new MigLayout( "fill,wrap 4", "[right][grow,fill][right][grow,fill]", "[][grow]" ) ); + setLayout( new MigLayout( "insets 0 0 0 0,wrap 4", "[right][grow,fill][right][grow,fill]", "" ) ); mComboMixers = new JComboBox(); InputMixerConfiguration[] inputMixers = mSourceManager.getMixerManager().getInputMixers(); @@ -68,6 +68,8 @@ public class MixerSourceEditor extends Editor mComboChannels.setModel( new DefaultComboBoxModel( channels.toArray( new MixerChannel[ channels.size() ] ) ) ); + repaint(); + setModified( true ); } } ); @@ -76,6 +78,17 @@ public class MixerSourceEditor extends Editor add( mComboMixers ); mComboChannels = new JComboBox(); + + InputMixerConfiguration selected = (InputMixerConfiguration)mComboMixers.getSelectedItem(); + + if( selected != null ) + { + EnumSet channels = selected.getChannels(); + + mComboChannels.setModel( new DefaultComboBoxModel( + channels.toArray( new MixerChannel[ channels.size() ] ) ) ); + } + mComboChannels.setEnabled( false ); mComboChannels.addActionListener( new ActionListener() { @@ -114,24 +127,33 @@ public class MixerSourceEditor extends Editor for( MixerChannel channel: inputMixer.getChannels() ) { - if( channel.getLabel().equalsIgnoreCase( mixer.getChannel().getLabel() ) ) + if( channel.getLabel() != null && mixer.getChannel() != null ) { - mComboChannels.setSelectedItem( channel ); + if( channel.getLabel().equalsIgnoreCase( mixer.getChannel().getLabel() ) ) + { + mComboChannels.setSelectedItem( channel ); + } } } continue; } } + + setModified( false ); + } + else + { + setModified( true ); } } else { mComboMixers.setEnabled( false ); mComboChannels.setEnabled( false ); + + setModified( false ); } - - setModified( false ); } public void save() diff --git a/src/source/tuner/TunerSourceEditor.java b/src/source/tuner/TunerSourceEditor.java index 1bc26ee6..4973e6b7 100644 --- a/src/source/tuner/TunerSourceEditor.java +++ b/src/source/tuner/TunerSourceEditor.java @@ -38,7 +38,7 @@ public class TunerSourceEditor extends Editor private void init() { - setLayout( new MigLayout( "fill", "[left]", "[][grow]" ) ); + setLayout( new MigLayout( "insets 0 0 0 0", "[left]", "" ) ); mFrequencyControl = new JFrequencyControl(); mFrequencyControl.setEnabled( false ); mFrequencyControl.addListener( new IFrequencyChangeProcessor() @@ -73,18 +73,23 @@ public class TunerSourceEditor extends Editor { SourceConfiguration config = getItem().getSourceConfiguration(); + mFrequencyControl.setEnabled( true ); + if( config instanceof SourceConfigTuner ) { mFrequencyControl.setFrequency( ((SourceConfigTuner)config).getFrequency(), false ); + setModified( false ); + } + else + { + mFrequencyControl.setFrequency( 101000000, false ); + setModified( true ); } - - mFrequencyControl.setEnabled( true ); } else { mFrequencyControl.setEnabled( false ); + setModified( false ); } - - setModified( false ); } } diff --git a/src/spectrum/OverlayPanel.java b/src/spectrum/OverlayPanel.java index 7e1aadf1..ded12c2a 100644 --- a/src/spectrum/OverlayPanel.java +++ b/src/spectrum/OverlayPanel.java @@ -100,8 +100,7 @@ public class OverlayPanel extends JPanel // private List mChannels = new ArrayList(); // //Currently visible/displayable channels - private CopyOnWriteArrayList mVisibleChannels = - new CopyOnWriteArrayList(); + private CopyOnWriteArrayList mVisibleChannels = new CopyOnWriteArrayList(); private ChannelDisplay mChannelDisplay = ChannelDisplay.ALL; //Defines the offset at the bottom of the spectral display to account for @@ -597,29 +596,24 @@ public class OverlayPanel extends JPanel width ); //Draw the decoder label - drawLabel( graphics, - channel.getDecodeConfiguration().getDecoderType() - .getShortDisplayString(), - this.getFont(), - xAxis, - yAxis, - width ); - } - - long frequency = tunerChannel.getFrequency(); - - double frequencyAxis = getAxisFromFrequency( frequency ); - - drawChannelCenterLine( graphics, frequencyAxis ); - - /* Draw Automatic Frequency Control line */ - int correction = channel.getChannelFrequencyCorrection(); - - if( correction != 0 ) - { - long error = frequency + correction; + drawLabel( graphics, channel.getDecodeConfiguration().getDecoderType().getShortDisplayString(), + this.getFont(), xAxis, yAxis, width ); + + long frequency = tunerChannel.getFrequency(); - drawAFC( graphics, frequencyAxis, getAxisFromFrequency( error ) ); + double frequencyAxis = getAxisFromFrequency( frequency ); + + drawChannelCenterLine( graphics, frequencyAxis ); + + /* Draw Automatic Frequency Control line */ + int correction = channel.getChannelFrequencyCorrection(); + + if( correction != 0 ) + { + long error = frequency + correction; + + drawAFC( graphics, frequencyAxis, getAxisFromFrequency( error ) ); + } } } } @@ -725,6 +719,21 @@ public class OverlayPanel extends JPanel mVisibleChannels.remove( channel ); } break; + case NOTIFICATION_CONFIGURATION_CHANGE: + if( mVisibleChannels.contains( channel ) && + !channel.isWithin( getMinFrequency(), getMaxFrequency() ) ) + { + mVisibleChannels.remove( channel ); + } + + if( !mVisibleChannels.contains( channel ) && + channel.isWithin( getMinFrequency(), getMaxFrequency() ) ) + { + mVisibleChannels.add( channel ); + } + break; + default: + break; } repaint();