wip: finished alias, alias ID and alias action editing framework.

This commit is contained in:
denny
2016-03-04 09:33:46 -05:00
parent 2c3dbe1b22
commit 00d2b43c2a
68 changed files with 1472 additions and 647 deletions

View File

@@ -19,6 +19,7 @@ package alias.action;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.bind.annotation.XmlTransient;
import message.Message;
import alias.Alias;
@@ -37,6 +38,9 @@ public abstract class AliasAction
public AliasAction()
{
}
@XmlTransient
public abstract AliasActionType getType();
/**
* Task to execute when an alias action is defined. The message argument is

View File

@@ -0,0 +1,349 @@
/*******************************************************************************
* 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 <http://www.gnu.org/licenses/>
******************************************************************************/
package alias.action;
import gui.editor.Editor;
import gui.editor.EmptyEditor;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JList;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.ListModel;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import net.miginfocom.swing.MigLayout;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import alias.Alias;
import alias.AliasEvent;
import alias.AliasEvent.Event;
import alias.AliasFactory;
import alias.AliasModel;
public class AliasActionEditor extends Editor<Alias>
{
private static final long serialVersionUID = 1L;
private final static Logger mLog = LoggerFactory.getLogger( AliasActionEditor.class );
private static ListModel<AliasAction> EMPTY_MODEL = new DefaultListModel<>();
private JList<AliasAction> mAliasActionList = new JList<>( EMPTY_MODEL );
private JButton mNewActionButton;
private JButton mCloneActionButton;
private JButton mDeleteActionButton;
private EditorContainer mEditorContainer = new EditorContainer();
private AliasModel mAliasModel;
public AliasActionEditor( AliasModel model )
{
mAliasModel = model;
init();
}
private void init()
{
setLayout( new MigLayout( "fill,wrap 3",
"[grow,fill][grow,fill][grow,fill]", "[][grow,fill][]" ) );
mAliasActionList.setVisibleRowCount( 6 );
mAliasActionList.setSelectionMode( ListSelectionModel.SINGLE_SELECTION );
mAliasActionList.setLayoutOrientation( JList.VERTICAL );
mAliasActionList.addListSelectionListener( new ListSelectionListener()
{
@Override
public void valueChanged( ListSelectionEvent event )
{
if( !event.getValueIsAdjusting() )
{
JList<?> list = (JList<?>)event.getSource();
Object selectedItem = list.getSelectedValue();
if( selectedItem != null && selectedItem instanceof AliasAction )
{
AliasAction selected = (AliasAction)selectedItem;
mEditorContainer.setAliasAction( selected );
mCloneActionButton.setEnabled( true );
mDeleteActionButton.setEnabled( true );
}
else
{
mCloneActionButton.setEnabled( false );
mDeleteActionButton.setEnabled( false );
}
}
}
} );
JScrollPane scroller = new JScrollPane( mAliasActionList );
add( scroller, "span,grow" );
add( mEditorContainer, "span,grow" );
mNewActionButton = new JButton( "New ..." );
mNewActionButton.setToolTipText( "Create a new Alias Action" );
mNewActionButton.addMouseListener( new MouseAdapter()
{
@Override
public void mouseClicked( MouseEvent e )
{
JPopupMenu menu = new JPopupMenu();
menu.add( new AddAliasActionItem( AliasActionType.BEEP ) );
menu.add( new AddAliasActionItem( AliasActionType.CLIP ) );
menu.add( new AddAliasActionItem( AliasActionType.SCRIPT ) );
menu.show( e.getComponent(), e.getX(), e.getY() );
}
} );
add( mNewActionButton );
mCloneActionButton = new JButton( "Clone" );
mCloneActionButton.setToolTipText( "Create a copy of the currently selected action" );
mCloneActionButton.setEnabled( false );
mCloneActionButton.addActionListener( new ActionListener()
{
@Override
public void actionPerformed( ActionEvent e )
{
AliasAction selected = mAliasActionList.getSelectedValue();
if( selected != null )
{
AliasAction clone = AliasFactory.copyOf( selected );
if( clone != null )
{
addAliasActionToList( clone );
}
}
}
} );
add( mCloneActionButton );
mDeleteActionButton = new JButton( "Delete" );
mDeleteActionButton.setToolTipText( "Delete the currently selected action" );
mDeleteActionButton.setEnabled( false );
mDeleteActionButton.addActionListener( new ActionListener()
{
@Override
public void actionPerformed( ActionEvent e )
{
final AliasAction selected = mAliasActionList.getSelectedValue();
if( selected != null )
{
int choice = JOptionPane.showConfirmDialog( mDeleteActionButton,
"Do you want to delete [" + selected.toString() + "]",
"Are you sure?", JOptionPane.YES_NO_OPTION );
if( choice == JOptionPane.YES_OPTION && hasItem() )
{
Alias alias = getItem();
alias.removeAliasAction( selected );
mAliasModel.broadcast( new AliasEvent( alias, Event.CHANGE ) );
setItem( alias );
}
}
}
} );
add( mDeleteActionButton, "wrap" );
}
@Override
public void setItem( Alias alias )
{
super.setItem( alias );
if( alias == null || alias.getAction().isEmpty() )
{
mAliasActionList.setModel( EMPTY_MODEL );
}
else
{
DefaultListModel<AliasAction> model = new DefaultListModel<>();
List<AliasAction> actions = alias.getAction();
Collections.sort( actions, new Comparator<AliasAction>()
{
@Override
public int compare( AliasAction o1, AliasAction o2 )
{
return o1.toString().compareTo( o2.toString() );
}
} );
for( AliasAction action: actions )
{
model.addElement( action );
}
mAliasActionList.setModel( model );
}
mEditorContainer.setAliasAction( null );
}
@Override
public void save()
{
if( mEditorContainer.isModified() )
{
mEditorContainer.save();
if( hasItem() )
{
mAliasModel.broadcast( new AliasEvent( getItem(), Event.CHANGE ) );
}
}
}
public class EditorContainer extends JPanel
{
private static final long serialVersionUID = 1L;
private Editor<AliasAction> mEditor = new EmptyEditor<>();
public EditorContainer()
{
setLayout( new MigLayout( "","[grow,fill]", "[grow,fill]" ) );
add( mEditor );
}
public boolean isModified()
{
if( mEditor != null )
{
return mEditor.isModified();
}
return false;
}
public void save()
{
if( mEditor != null )
{
mEditor.save();
}
}
public void setAliasAction( AliasAction aliasAction )
{
if( mEditor != null )
{
if( mEditor.isModified() )
{
int option = JOptionPane.showConfirmDialog(
EditorContainer.this,
"Action settings have changed. Do you want to save these changes?",
"Save Changes?",
JOptionPane.YES_NO_OPTION,
JOptionPane.QUESTION_MESSAGE );
if( option == JOptionPane.YES_OPTION )
{
mEditor.save();
}
}
}
removeAll();
//This will always give us an editor
mEditor = AliasFactory.getEditor( aliasAction );
add( mEditor );
revalidate();
}
}
private void addAliasActionToList( final AliasAction action )
{
if( action != null && hasItem() )
{
final Alias alias = getItem();
alias.addAliasAction( action );
EventQueue.invokeLater( new Runnable()
{
@Override
public void run()
{
setItem( alias );
mAliasActionList.setSelectedValue( action, true );
}
} );
}
}
public class AddAliasActionItem extends JMenuItem
{
private static final long serialVersionUID = 1L;
private AliasActionType mAliasActionType;
public AddAliasActionItem( AliasActionType type )
{
super( type.toString() );
mAliasActionType = type;
addActionListener( new ActionListener()
{
@Override
public void actionPerformed( ActionEvent e )
{
final AliasAction action =
AliasFactory.getAliasAction( mAliasActionType );
addAliasActionToList( action );
}
} );
}
}
}

View File

@@ -0,0 +1,32 @@
/*******************************************************************************
* 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 <http://www.gnu.org/licenses/>
******************************************************************************/
package alias.action;
import alias.AliasEvent;
/**
* Interface for receiving alias events. Each listener will receive
* notification of all alias events.
*/
public interface AliasActionListener
{
/**
* Notifies the listener that an alias event has occurred
*/
public void aliasChanged( AliasEvent event );
}

View File

@@ -0,0 +1,37 @@
/*******************************************************************************
* 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 <http://www.gnu.org/licenses/>
******************************************************************************/
package alias.action;
public enum AliasActionType
{
BEEP( "Beep" ),
CLIP( "Play Clip" ),
SCRIPT( "Run Script" );
private String mLabel;
private AliasActionType( String label )
{
mLabel = label;
}
public String toString()
{
return mLabel;
}
}

View File

@@ -2,13 +2,27 @@ package alias.action.beep;
import message.Message;
import alias.Alias;
import alias.action.AliasActionType;
import alias.action.RecurringAction;
public class BeepAction extends RecurringAction
{
@Override
public AliasActionType getType()
{
return AliasActionType.BEEP;
}
@Override
public void performAction( Alias alias, Message message )
{
System.out.println( "\007" );
}
@Override
public String toString()
{
return "Beep";
}
}

View File

@@ -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
@@ -17,59 +17,77 @@
******************************************************************************/
package alias.action.beep;
import gui.editor.DocumentListenerEditor;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JOptionPane;
import javax.swing.JSlider;
import javax.swing.JSpinner;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SpinnerModel;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import net.miginfocom.swing.MigLayout;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import alias.action.AliasAction;
import alias.action.RecurringAction.Interval;
import alias.id.priority.Priority;
public class BeepActionEditor extends JPanel implements ActionListener
public class BeepActionEditor extends DocumentListenerEditor<AliasAction>
{
private static final long serialVersionUID = 1L;
private final static Logger mLog =
LoggerFactory.getLogger( BeepActionEditor.class );
private BeepActionNode mBeepActionNode;
private JTextField mTextSiteID;
private JComboBox<Interval> mComboInterval;
private JSpinner mSpinnerPeriod;
private static final String HELP_TEXT =
"<html><h3>Beep Action</h3>"
+ "This action will sound a beep according to the interval<br>"
+ "that you select:<br><br>"
+ "<b>Once:</b> Beep the first time the alias is active and<br>"
+ "never again<br><br>"
+ "<b>Once, Reset After Delay:</b> Beep once and suppress<br>"
+ "subsequent beeps for the specified period in seconds.<br>"
+ "After the reset period, beep again when the alias is active.<br><br>"
+ "<b>Until Dismissed:</b> Beep every period seconds until you<br>"
+ "click OK on the dialog that appears. Alerting is suppressed<br>"
+ "for 15 seconds after you click OK.<br>"
+ "</html>";
public BeepActionEditor( BeepActionNode beepActionNode )
private JComboBox<Interval> mComboInterval;
private JSlider mPeriodSlider;
private JLabel mPeriodSliderLabel;
public BeepActionEditor( AliasAction aliasAction )
{
mBeepActionNode = beepActionNode;
initGUI();
init();
setItem( aliasAction );
}
private void initGUI()
public BeepAction getBeepAction()
{
setLayout( new MigLayout( "fill,wrap 2", "[right][left]", "[][][][][][grow]" ) );
add( new JLabel( "Action: Beep" ), "span,align center" );
if( getItem() instanceof BeepAction )
{
return (BeepAction)getItem();
}
add( new JLabel( "Interval:" ) );
return null;
}
private void init()
{
setLayout( new MigLayout( "fill,wrap 2", "[right][left]", "[][][]" ) );
add( new JLabel( "Beep Interval:" ) );
mComboInterval = new JComboBox<Interval>( Interval.values() );
mComboInterval.setSelectedItem( mBeepActionNode.getBeepAction().getInterval() );
mComboInterval.setToolTipText( HELP_TEXT );
mComboInterval.addActionListener( new ActionListener()
{
@Override
@@ -81,71 +99,97 @@ public class BeepActionEditor extends JPanel implements ActionListener
if( selected != null )
{
/* Enable/disable period spinner based on selection */
mSpinnerPeriod.setEnabled( selected != Interval.ONCE );
boolean enabled = selected != Interval.ONCE;
mBeepActionNode.getBeepAction().setInterval( selected );
mPeriodSlider.setEnabled( enabled );
mPeriodSliderLabel.setEnabled( enabled );
}
setModified( true );
}
});
add( mComboInterval, "wrap" );
final SpinnerModel model = new SpinnerNumberModel(
mBeepActionNode.getBeepAction().getPeriod(), 1, 30, 1 );
final SpinnerModel model = new SpinnerNumberModel( 1, 1, 30, 1 );
model.addChangeListener( new ChangeListener()
{
@Override
public void stateChanged( ChangeEvent e )
{
mBeepActionNode.getBeepAction().setPeriod( (int)model.getValue() );
setModified( true );
}
} );
mSpinnerPeriod = new JSpinner( model );
if( mBeepActionNode.getBeepAction().getInterval() == Interval.ONCE )
mPeriodSlider = new JSlider( JSlider.HORIZONTAL, 1, 60, 1 );
mPeriodSlider.setMajorTickSpacing( 10 );
mPeriodSlider.setMinorTickSpacing( 2 );
mPeriodSlider.setPaintTicks( true );
mPeriodSlider.setLabelTable( mPeriodSlider.createStandardLabels( 10, 10 ) );
mPeriodSlider.setPaintLabels( true );
mPeriodSlider.addChangeListener( new ChangeListener()
{
mSpinnerPeriod.setEnabled( false );
@Override
public void stateChanged( ChangeEvent e )
{
mPeriodSliderLabel.setText( "Period: " + mPeriodSlider.getValue() );
setModified( true );
}
} );
mPeriodSlider.setToolTipText( HELP_TEXT );
mPeriodSliderLabel = new JLabel( "Period: " + mPeriodSlider.getValue() + " " );
add( mPeriodSliderLabel );
add( mPeriodSlider, "wrap,grow" );
JLabel example = new JLabel( "Help ..." );
example.setForeground( Color.BLUE.brighter() );
example.setCursor( new Cursor( Cursor.HAND_CURSOR ) );
example.addMouseListener( new MouseAdapter()
{
@Override
public void mouseClicked( MouseEvent e )
{
JOptionPane.showMessageDialog( BeepActionEditor.this,
HELP_TEXT, "Help", JOptionPane.INFORMATION_MESSAGE );
}
} );
add( example );
}
@Override
public void setItem( AliasAction item )
{
super.setItem( item );
if( hasItem() )
{
BeepAction beep = getBeepAction();
Interval interval = beep.getInterval();
mComboInterval.setSelectedItem( interval );
boolean enabled = interval != Interval.ONCE;
mPeriodSliderLabel.setEnabled( enabled );
mPeriodSlider.setEnabled( enabled );
mPeriodSlider.setValue( beep.getPeriod() );
}
add( new JLabel( "Period:" ) );
add( mSpinnerPeriod, "wrap" );
StringBuilder sb = new StringBuilder();
sb.append( "This action will sound a beep according to the interval that you select.\n\n" );
sb.append( "Once - Beep the first time the alias is active and never again.\n\n" );
sb.append( "Once, Reset After Delay - Beep once and suppress subsequent beeps for the specified period in seconds. After the reset period, it will beep again when the alias is active.\n\n" );
sb.append( "Until Dismissed - Beep every period seconds until you click OK on the dialog that appears. Alerting is suppressed for 15 seconds after you click OK." );
JTextArea description = new JTextArea( sb.toString() );
description.setLineWrap( true );
description.setBackground( getBackground() );
add( description, "growx,span" );
JButton btnSave = new JButton( "Save" );
btnSave.addActionListener( BeepActionEditor.this );
add( btnSave, "growx,push" );
JButton btnReset = new JButton( "Reset" );
btnReset.addActionListener( BeepActionEditor.this );
add( btnReset, "growx,push" );
setModified( false );
}
@Override
public void actionPerformed( ActionEvent e )
{
String command = e.getActionCommand();
if( command.contentEquals( "Save" ) )
public void save()
{
if( hasItem() && isModified() )
{
mBeepActionNode.save();
mBeepActionNode.show();
BeepAction beep = getBeepAction();
beep.setInterval( (Interval)mComboInterval.getSelectedItem() );
beep.setPeriod( mPeriodSlider.getValue() );
}
mBeepActionNode.refresh();
}
setModified( false );
}
}

View File

@@ -41,7 +41,7 @@ public class BeepActionNode extends AliasActionNode
@Override
public JPanel getEditor()
{
return new BeepActionEditor( this );
return null;
}
public BeepAction getBeepAction()

View File

@@ -13,6 +13,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import alias.Alias;
import alias.action.AliasActionType;
import alias.action.RecurringAction;
public class ClipAction extends RecurringAction
@@ -28,9 +29,14 @@ public class ClipAction extends RecurringAction
{
}
@Override
public AliasActionType getType()
{
return AliasActionType.CLIP;
}
public String getPath()
{
return mFilePath;
}
@@ -87,4 +93,18 @@ public class ClipAction extends RecurringAction
throw e;
}
}
@Override
public String toString()
{
if( mFilePath == null )
{
return "Play Clip";
}
else
{
return "Play Clip: " + mFilePath;
}
}
}

View File

@@ -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
@@ -17,9 +17,15 @@
******************************************************************************/
package alias.action.clip;
import gui.editor.DocumentListenerEditor;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import javax.swing.JButton;
@@ -27,9 +33,7 @@ import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.JTextArea;
import javax.swing.JSlider;
import javax.swing.JTextField;
import javax.swing.SpinnerModel;
import javax.swing.SpinnerNumberModel;
@@ -37,43 +41,59 @@ import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import net.miginfocom.swing.MigLayout;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import alias.action.AliasAction;
import alias.action.RecurringAction.Interval;
import alias.action.script.ScriptActionEditor;
public class ClipActionEditor extends JPanel implements ActionListener
public class ClipActionEditor extends DocumentListenerEditor<AliasAction>
{
private static final long serialVersionUID = 1L;
private final static Logger mLog =
LoggerFactory.getLogger( ClipActionEditor.class );
private ClipActionNode mClipActionNode;
private static final String PLEASE_SELECT_A_FILE = "Please select a file";
private static final String HELP_TEXT =
"<html><h3>Clip Action</h3>"
+ "This action will play an audio clip according to the interval<br>"
+ "that you select:<br><br>"
+ "<b>Once:</b> play the first time the alias is active and<br>"
+ "never again<br><br>"
+ "<b>Once, Reset After Delay:</b> play once and suppress<br>"
+ "subsequent runs for the specified period in seconds.<br>"
+ "After the reset period, play again when the alias is active.<br><br>"
+ "<b>Until Dismissed:</b> play every period seconds until you<br>"
+ "click OK on the dialog that appears. Alerting is suppressed<br>"
+ "for 15 seconds after you click OK.<br>"
+ "</html>";
private JComboBox<Interval> mComboInterval;
private JSpinner mSpinnerPeriod;
private JSlider mPeriodSlider;
private JLabel mPeriodSliderLabel;
private JTextField mTextFilePath;
public ClipActionEditor( ClipActionNode clipActionNode )
public ClipActionEditor( AliasAction aliasAction )
{
mClipActionNode = clipActionNode;
initGUI();
init();
setItem( aliasAction );
}
private void initGUI()
public ClipAction getClipAction()
{
setLayout( new MigLayout( "fill,wrap 2", "[right][left]", "[][][][][][grow]" ) );
add( new JLabel( "Action: Audio Clip" ), "span,align center" );
if( getItem() instanceof ClipAction )
{
return (ClipAction)getItem();
}
add( new JLabel( "Interval:" ) );
return null;
}
private void init()
{
setLayout( new MigLayout( "fill,wrap 2", "[right][left]", "[][][][][]" ) );
add( new JLabel( "Play Interval:" ) );
mComboInterval = new JComboBox<Interval>( Interval.values() );
mComboInterval.setSelectedItem( mClipActionNode.getClipAction().getInterval() );
mComboInterval.setToolTipText( HELP_TEXT );
mComboInterval.addActionListener( new ActionListener()
{
@Override
@@ -84,37 +104,51 @@ public class ClipActionEditor extends JPanel implements ActionListener
if( selected != null )
{
/* Enable/disable period spinner based on selection */
mSpinnerPeriod.setEnabled( selected != Interval.ONCE );
/* Enable/disable period slider based on selection */
boolean enabled = selected != Interval.ONCE;
mClipActionNode.getClipAction().setInterval( selected );
mPeriodSlider.setEnabled( enabled );
mPeriodSliderLabel.setEnabled( enabled );
}
setModified( true );
}
});
add( mComboInterval, "wrap" );
add( mComboInterval );
final SpinnerModel model = new SpinnerNumberModel(
mClipActionNode.getClipAction().getPeriod(), 1, 30, 1 );
final SpinnerModel model = new SpinnerNumberModel( 1, 1, 30, 1 );
model.addChangeListener( new ChangeListener()
{
@Override
public void stateChanged( ChangeEvent e )
{
mClipActionNode.getClipAction().setPeriod( (int)model.getValue() );
setModified( true );
}
} );
mSpinnerPeriod = new JSpinner( model );
if( mClipActionNode.getClipAction().getInterval() == Interval.ONCE )
mPeriodSlider = new JSlider( JSlider.HORIZONTAL, 1, 60, 1 );
mPeriodSlider.setMajorTickSpacing( 10 );
mPeriodSlider.setMinorTickSpacing( 2 );
mPeriodSlider.setPaintTicks( true );
mPeriodSlider.setLabelTable( mPeriodSlider.createStandardLabels( 10, 10 ) );
mPeriodSlider.setPaintLabels( true );
mPeriodSlider.addChangeListener( new ChangeListener()
{
mSpinnerPeriod.setEnabled( false );
}
@Override
public void stateChanged( ChangeEvent e )
{
mPeriodSliderLabel.setText( "Period: " + mPeriodSlider.getValue() );
setModified( true );
}
} );
mPeriodSlider.setToolTipText( HELP_TEXT );
add( new JLabel( "Period:" ) );
add( mSpinnerPeriod, "wrap" );
mPeriodSliderLabel = new JLabel( "Period: " + mPeriodSlider.getValue() + " " );
add( mPeriodSliderLabel );
add( mPeriodSlider, "wrap,grow" );
mTextFilePath = new JTextField( PLEASE_SELECT_A_FILE );
add( mTextFilePath, "growx,span" );
JButton fileButton = new JButton( "File" );
@@ -131,88 +165,134 @@ public class ClipActionEditor extends JPanel implements ActionListener
{
File file = chooser.getSelectedFile();
mClipActionNode.getClipAction().setPath( file.getAbsolutePath() );
mTextFilePath.setText( file.getAbsolutePath() );
setModified( true );
}
}
} );
add( fileButton );
add( fileButton, "grow" );
JButton testButton = new JButton( "Test" );
testButton.addActionListener( new ActionListener()
testButton.addActionListener( new ActionListener()
{
@Override
public void actionPerformed( ActionEvent actionEvent )
public void actionPerformed( ActionEvent e )
{
String path = mClipActionNode.getClipAction().getPath();
if( path == null || path.trim().isEmpty() )
if( hasItem() )
{
JOptionPane.showMessageDialog( ClipActionEditor.this,
"Please select an audio file", "Please select file",
JOptionPane.ERROR_MESSAGE );
}
EventQueue.invokeLater( new Runnable()
{
@Override
public void run()
String path = mTextFilePath.getText();
if( path == null || path.trim().isEmpty() )
{
try
{
mClipActionNode.getClipAction().play();
}
catch( Exception e )
{
JOptionPane.showMessageDialog( ClipActionEditor.this,
"Couldn't play audio clip [" + e.getMessage() + "]",
"Error", JOptionPane.ERROR_MESSAGE );
}
JOptionPane.showMessageDialog( ClipActionEditor.this,
"Please select an audio file", PLEASE_SELECT_A_FILE,
JOptionPane.ERROR_MESSAGE );
}
} );
else
{
if( isModified() )
{
int option = JOptionPane.showConfirmDialog(
ClipActionEditor.this,
"Settings have changed. Do you want to save these changes?",
"Save Changes?",
JOptionPane.YES_NO_OPTION,
JOptionPane.QUESTION_MESSAGE );
if( option == JOptionPane.YES_OPTION )
{
save();
}
}
new Thread( new Runnable()
{
@Override
public void run()
{
try
{
getClipAction().play();
}
catch( Exception e1 )
{
JOptionPane.showMessageDialog( ClipActionEditor.this,
"Couldn't play audio clip [" + e1.getMessage() + "]",
"Error", JOptionPane.ERROR_MESSAGE );
}
}
}).start();
}
}
}
} );
add( testButton, "wrap" );
mTextFilePath = new JTextField( mClipActionNode.getClipAction().getPath() );
add( mTextFilePath, "growx,span" );
StringBuilder sb = new StringBuilder();
add( testButton, "grow,wrap" );
sb.append( "This action will play the audio clip according to the interval that you select.\n\n" );
sb.append( "Once - Play the first time the alias is active and never again.\n\n" );
sb.append( "Once, Reset After Delay - Play once and suppress subsequent plays for the specified period in seconds. After the reset period, it will play again when the alias is active.\n\n" );
sb.append( "Until Dismissed - Play audio clip every period seconds until you click OK on the dialog that appears. Alerting is suppressed for 15 seconds after you click OK." );
JLabel example = new JLabel( "Help ..." );
example.setForeground( Color.BLUE.brighter() );
example.setCursor( new Cursor( Cursor.HAND_CURSOR ) );
example.addMouseListener( new MouseAdapter()
{
@Override
public void mouseClicked( MouseEvent e )
{
JOptionPane.showMessageDialog( ClipActionEditor.this,
HELP_TEXT, "Help", JOptionPane.INFORMATION_MESSAGE );
}
} );
add( example );
}
@Override
public void setItem( AliasAction item )
{
super.setItem( item );
JTextArea description = new JTextArea( sb.toString() );
description.setLineWrap( true );
description.setBackground( getBackground() );
add( description, "growx,span" );
JButton btnSave = new JButton( "Save" );
btnSave.addActionListener( ClipActionEditor.this );
add( btnSave, "growx,push" );
if( hasItem() )
{
ClipAction clip = getClipAction();
JButton btnReset = new JButton( "Reset" );
btnReset.addActionListener( ClipActionEditor.this );
add( btnReset, "growx,push" );
Interval interval = clip.getInterval();
mComboInterval.setSelectedItem( interval );
boolean enabled = interval != Interval.ONCE;
mPeriodSliderLabel.setEnabled( enabled );
mPeriodSlider.setEnabled( enabled );
mPeriodSlider.setValue( clip.getPeriod() );
String filepath = clip.getPath();
if( filepath != null && !filepath.isEmpty() )
{
mTextFilePath.setText( filepath );
}
else
{
mTextFilePath.setText( PLEASE_SELECT_A_FILE );
}
}
setModified( false );
}
@Override
public void actionPerformed( ActionEvent e )
{
String command = e.getActionCommand();
if( command.contentEquals( "Save" ) )
public void save()
{
if( hasItem() && isModified() )
{
mClipActionNode.save();
mClipActionNode.show();
ClipAction script = getClipAction();
script.setInterval( (Interval)mComboInterval.getSelectedItem() );
script.setPeriod( mPeriodSlider.getValue() );
script.setPath( mTextFilePath.getText() );
}
mClipActionNode.refresh();
}
setModified( false );
}
}

View File

@@ -41,7 +41,7 @@ public class ClipActionNode extends AliasActionNode
@Override
public JPanel getEditor()
{
return new ClipActionEditor( this );
return null;
}
public ClipAction getClipAction()

View File

@@ -9,6 +9,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import alias.Alias;
import alias.action.AliasActionType;
import alias.action.RecurringAction;
public class ScriptAction extends RecurringAction
@@ -21,6 +22,12 @@ public class ScriptAction extends RecurringAction
{
}
@Override
public AliasActionType getType()
{
return AliasActionType.SCRIPT;
}
public String getScript()
{
return mScript;
@@ -75,4 +82,17 @@ public class ScriptAction extends RecurringAction
}
}
}
@Override
public String toString()
{
if( mScript == null )
{
return "Run Script";
}
else
{
return "Run Script: " + mScript;
}
}
}

View File

@@ -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
@@ -17,9 +17,16 @@
******************************************************************************/
package alias.action.script;
import gui.editor.DocumentListenerEditor;
import gui.editor.Editor;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import javax.swing.JButton;
@@ -27,9 +34,7 @@ import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.JTextArea;
import javax.swing.JSlider;
import javax.swing.JTextField;
import javax.swing.SpinnerModel;
import javax.swing.SpinnerNumberModel;
@@ -37,43 +42,59 @@ import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import net.miginfocom.swing.MigLayout;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import alias.action.AliasAction;
import alias.action.RecurringAction.Interval;
import alias.action.clip.ClipActionEditor;
public class ScriptActionEditor extends JPanel implements ActionListener
public class ScriptActionEditor extends DocumentListenerEditor<AliasAction>
{
private static final long serialVersionUID = 1L;
private final static Logger mLog =
LoggerFactory.getLogger( ScriptActionEditor.class );
private ScriptActionNode mScriptActionNode;
private static final String PLEASE_SELECT_A_FILE = "Please select a file";
private static final String HELP_TEXT =
"<html><h3>Script Action</h3>"
+ "This action will run a script according to the interval<br>"
+ "that you select:<br><br>"
+ "<b>Once:</b> run the first time the alias is active and<br>"
+ "never again<br><br>"
+ "<b>Once, Reset After Delay:</b> run once and suppress<br>"
+ "subsequent runs for the specified period in seconds.<br>"
+ "After the reset period, run again when the alias is active.<br><br>"
+ "<b>Until Dismissed:</b> run every period seconds until you<br>"
+ "click OK on the dialog that appears. Alerting is suppressed<br>"
+ "for 15 seconds after you click OK.<br>"
+ "</html>";
private JComboBox<Interval> mComboInterval;
private JSpinner mSpinnerPeriod;
private JSlider mPeriodSlider;
private JLabel mPeriodSliderLabel;
private JTextField mTextFilePath;
public ScriptActionEditor( ScriptActionNode clipActionNode )
public ScriptActionEditor( AliasAction aliasAction )
{
mScriptActionNode = clipActionNode;
initGUI();
init();
setItem( aliasAction );
}
private void initGUI()
public ScriptAction getScriptAction()
{
setLayout( new MigLayout( "fill,wrap 2", "[right][left]", "[][][][][][grow]" ) );
add( new JLabel( "Action: Script" ), "span,align center" );
if( getItem() instanceof ScriptAction )
{
return (ScriptAction)getItem();
}
add( new JLabel( "Interval:" ) );
return null;
}
private void init()
{
setLayout( new MigLayout( "fill,wrap 2", "[right][left]", "[][][][][]" ) );
add( new JLabel( "Run Interval:" ) );
mComboInterval = new JComboBox<Interval>( Interval.values() );
mComboInterval.setSelectedItem( mScriptActionNode.getScriptAction().getInterval() );
mComboInterval.setToolTipText( HELP_TEXT );
mComboInterval.addActionListener( new ActionListener()
{
@Override
@@ -84,37 +105,51 @@ public class ScriptActionEditor extends JPanel implements ActionListener
if( selected != null )
{
/* Enable/disable period spinner based on selection */
mSpinnerPeriod.setEnabled( selected != Interval.ONCE );
/* Enable/disable period slider based on selection */
boolean enabled = selected != Interval.ONCE;
mScriptActionNode.getScriptAction().setInterval( selected );
mPeriodSlider.setEnabled( enabled );
mPeriodSliderLabel.setEnabled( enabled );
}
setModified( true );
}
});
add( mComboInterval, "wrap" );
add( mComboInterval );
final SpinnerModel model = new SpinnerNumberModel(
mScriptActionNode.getScriptAction().getPeriod(), 1, 30, 1 );
final SpinnerModel model = new SpinnerNumberModel( 1, 1, 30, 1 );
model.addChangeListener( new ChangeListener()
{
@Override
public void stateChanged( ChangeEvent e )
{
mScriptActionNode.getScriptAction().setPeriod( (int)model.getValue() );
setModified( true );
}
} );
mSpinnerPeriod = new JSpinner( model );
if( mScriptActionNode.getScriptAction().getInterval() == Interval.ONCE )
mPeriodSlider = new JSlider( JSlider.HORIZONTAL, 1, 60, 1 );
mPeriodSlider.setMajorTickSpacing( 10 );
mPeriodSlider.setMinorTickSpacing( 2 );
mPeriodSlider.setPaintTicks( true );
mPeriodSlider.setLabelTable( mPeriodSlider.createStandardLabels( 10, 10 ) );
mPeriodSlider.setPaintLabels( true );
mPeriodSlider.addChangeListener( new ChangeListener()
{
mSpinnerPeriod.setEnabled( false );
}
@Override
public void stateChanged( ChangeEvent e )
{
mPeriodSliderLabel.setText( "Period: " + mPeriodSlider.getValue() );
setModified( true );
}
} );
mPeriodSlider.setToolTipText( HELP_TEXT );
add( new JLabel( "Period:" ) );
add( mSpinnerPeriod, "wrap" );
mPeriodSliderLabel = new JLabel( "Period: " + mPeriodSlider.getValue() + " " );
add( mPeriodSliderLabel );
add( mPeriodSlider, "wrap,grow" );
mTextFilePath = new JTextField( PLEASE_SELECT_A_FILE );
add( mTextFilePath, "growx,span" );
JButton fileButton = new JButton( "File" );
@@ -131,13 +166,14 @@ public class ScriptActionEditor extends JPanel implements ActionListener
{
File file = chooser.getSelectedFile();
mScriptActionNode.getScriptAction().setScript( file.getAbsolutePath() );
mTextFilePath.setText( file.getAbsolutePath() );
setModified( true );
}
}
} );
add( fileButton );
add( fileButton, "grow" );
JButton testButton = new JButton( "Test" );
testButton.addActionListener( new ActionListener()
@@ -145,74 +181,115 @@ public class ScriptActionEditor extends JPanel implements ActionListener
@Override
public void actionPerformed( ActionEvent actionEvent )
{
String script = mScriptActionNode.getScriptAction().getScript();
String script = mTextFilePath.getText();
if( script == null || script.trim().isEmpty() )
{
JOptionPane.showMessageDialog( ScriptActionEditor.this,
"Please select a script file", "Please select file",
"Please select a script file", PLEASE_SELECT_A_FILE,
JOptionPane.ERROR_MESSAGE );
}
EventQueue.invokeLater( new Runnable()
else
{
@Override
public void run()
if( isModified() )
{
try
int option = JOptionPane.showConfirmDialog(
ScriptActionEditor.this,
"Settings have changed. Do you want to save these changes?",
"Save Changes?",
JOptionPane.YES_NO_OPTION,
JOptionPane.QUESTION_MESSAGE );
if( option == JOptionPane.YES_OPTION )
{
mScriptActionNode.getScriptAction().play();
}
catch( Exception e )
{
JOptionPane.showMessageDialog( ScriptActionEditor.this,
"Couldn't run script [" + e.getMessage() + "]",
"Error", JOptionPane.ERROR_MESSAGE );
save();
}
}
} );
new Thread( new Runnable()
{
@Override
public void run()
{
try
{
getScriptAction().play();
}
catch( Exception e1 )
{
JOptionPane.showMessageDialog( ScriptActionEditor.this,
e1.getMessage(), "Error", JOptionPane.ERROR_MESSAGE );
}
}
}).start();
}
}
} );
add( testButton, "wrap" );
add( testButton, "grow,wrap" );
mTextFilePath = new JTextField( mScriptActionNode.getScriptAction().getScript() );
add( mTextFilePath, "growx,span" );
JLabel example = new JLabel( "Help ..." );
example.setForeground( Color.BLUE.brighter() );
example.setCursor( new Cursor( Cursor.HAND_CURSOR ) );
example.addMouseListener( new MouseAdapter()
{
@Override
public void mouseClicked( MouseEvent e )
{
JOptionPane.showMessageDialog( ScriptActionEditor.this,
HELP_TEXT, "Help", JOptionPane.INFORMATION_MESSAGE );
}
} );
add( example );
}
@Override
public void setItem( AliasAction item )
{
super.setItem( item );
if( hasItem() )
{
ScriptAction script = getScriptAction();
StringBuilder sb = new StringBuilder();
sb.append( "This action will run the script according to the interval that you select.\n\n" );
sb.append( "Once - Run script the first time the alias is active and never again.\n\n" );
sb.append( "Once, Reset After Delay - Run once and suppress subsequent runs for the specified period in seconds. After the reset period, it will play again when the alias is active.\n\n" );
sb.append( "Until Dismissed - Run script every period seconds until you click OK on the dialog that appears. Alerting is suppressed for 15 seconds after you click OK." );
JTextArea description = new JTextArea( sb.toString() );
description.setLineWrap( true );
description.setBackground( getBackground() );
add( description, "growx,span" );
JButton btnSave = new JButton( "Save" );
btnSave.addActionListener( ScriptActionEditor.this );
add( btnSave, "growx,push" );
Interval interval = script.getInterval();
mComboInterval.setSelectedItem( interval );
JButton btnReset = new JButton( "Reset" );
btnReset.addActionListener( ScriptActionEditor.this );
add( btnReset, "growx,push" );
boolean enabled = interval != Interval.ONCE;
mPeriodSliderLabel.setEnabled( enabled );
mPeriodSlider.setEnabled( enabled );
mPeriodSlider.setValue( script.getPeriod() );
String filepath = script.getScript();
if( filepath != null && !filepath.isEmpty() )
{
mTextFilePath.setText( filepath );
}
else
{
mTextFilePath.setText( PLEASE_SELECT_A_FILE );
}
}
setModified( false );
}
@Override
public void actionPerformed( ActionEvent e )
{
String command = e.getActionCommand();
if( command.contentEquals( "Save" ) )
public void save()
{
if( hasItem() && isModified() )
{
mScriptActionNode.save();
mScriptActionNode.show();
ScriptAction script = getScriptAction();
script.setInterval( (Interval)mComboInterval.getSelectedItem() );
script.setPeriod( mPeriodSlider.getValue() );
script.setScript( mTextFilePath.getText() );
}
mScriptActionNode.refresh();
}
setModified( false );
}
}

View File

@@ -41,7 +41,7 @@ public class ScriptActionNode extends AliasActionNode
@Override
public JPanel getEditor()
{
return new ScriptActionEditor( this );
return null;
}
public ScriptAction getScriptAction()