package esmska.gui;
import esmska.Context;
import esmska.data.Config;
import esmska.data.CountryPrefix;
import esmska.data.event.ValuedEvent;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.beans.PropertyChangeEvent;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.AbstractListModel;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.JToggleButton;
import javax.swing.LayoutStyle.ComponentPlacement;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import esmska.data.Icons;
import esmska.data.Gateways;
import esmska.data.Queue;
import esmska.data.SMS;
import esmska.data.Gateway;
import esmska.data.event.AbstractListDataListener;
import esmska.data.event.ActionEventSupport;
import esmska.data.event.ValuedEventSupport;
import esmska.utils.L10N;
import esmska.data.event.ValuedListener;
import esmska.utils.MiscUtils;
import esmska.utils.RuntimeUtils;
import java.awt.BorderLayout;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeListener;
import java.net.URL;
import java.util.ArrayList;
import java.util.ResourceBundle;
import java.util.logging.Logger;
import javax.swing.JDialog;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.ListCellRenderer;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.WordUtils;
import org.openide.awt.Mnemonics;
import org.pushingpixels.substance.api.ColorSchemeAssociationKind;
import org.pushingpixels.substance.api.ComponentState;
import org.pushingpixels.substance.api.SubstanceColorScheme;
import org.pushingpixels.substance.api.SubstanceLookAndFeel;
import org.pushingpixels.substance.api.painter.border.SubstanceBorderPainter;
import org.pushingpixels.substance.api.painter.highlight.SubstanceHighlightPainter;
import org.pushingpixels.substance.api.renderers.SubstanceDefaultListCellRenderer;
import org.pushingpixels.substance.api.skin.SkinChangeListener;
/** SMS queue panel
*
* @author ripper
*/
public class QueuePanel extends javax.swing.JPanel {
public static enum Events {
/** A message wants to be edited. Event value: sms to be edited. */
SMS_EDIT_REQUESTED;
}
private static final Logger logger = Logger.getLogger(QueuePanel.class.getName());
private static final String RES = "/esmska/resources/";
private static final ResourceBundle l10n = L10N.l10nBundle;
private static final Queue queue = Queue.getInstance();
private static final Config config = Config.getInstance();
private static final Gateways gateways = Gateways.getInstance();
private Action deleteSMSAction = new DeleteSMSAction();
private Action editSMSAction = new EditSMSAction();
private Action smsUpAction = new SMSUpAction();
private Action smsDownAction = new SMSDownAction();
private QueueListModel queueListModel = new QueueListModel();
//sms which have been requested to be edited
private QueuePopupMenu popup = new QueuePopupMenu();
private QueueMouseListener mouseListener;
//regularly update sms delay indicators
private Timer timer = new Timer(500, new DelayListener());
// <editor-fold defaultstate="collapsed" desc="ValuedEvent support">
private ValuedEventSupport<Events, SMS> valuedSupport = new ValuedEventSupport<Events, SMS>(this);
public void addValuedListener(ValuedListener<Events, SMS> valuedListener) {
valuedSupport.addValuedListener(valuedListener);
}
public void removeValuedListener(ValuedListener<Events, SMS> valuedListener) {
valuedSupport.removeValuedListener(valuedListener);
}
// </editor-fold>
// <editor-fold defaultstate="collapsed" desc="ActionEvent support">
private ActionEventSupport actionSupport = new ActionEventSupport(this);
public void addActionListener(ActionListener actionListener) {
actionSupport.addActionListener(actionListener);
}
public void removeActionListener(ActionListener actionListener) {
actionSupport.removeActionListener(actionListener);
}
// </editor-fold>
/** Creates new form QueuePanel */
public QueuePanel() {
initComponents();
//add mouse listeners to the queue list
mouseListener = new QueueMouseListener(queueList, popup);
queueList.addMouseListener(mouseListener);
//when model is changed update actions
queueListModel.addListDataListener(new AbstractListDataListener() {
@Override
public void onUpdate(ListDataEvent e) {
queueListValueChanged(null);
}
});
//set visibility of advanced controls
showAdvancedControls(config.isShowAdvancedControls());
config.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if ("showAdvancedControls".equals(evt.getPropertyName())) {
showAdvancedControls((Boolean)evt.getNewValue());
}
}
});
// update pausedLabel on queue changes
queue.addValuedListener(new ValuedListener<Queue.Events, SMS>() {
@Override
public void eventOccured(ValuedEvent<Queue.Events, SMS> e) {
switch (e.getEvent()) {
case QUEUE_PAUSED:
pausedLabel.setVisible(true);
break;
case QUEUE_RESUMED:
pausedLabel.setVisible(false);
break;
}
if (MiscUtils.needsResize(QueuePanel.this, MiscUtils.Direction.HEIGHT)) {
actionSupport.fireActionPerformed(ActionEventSupport.ACTION_NEED_RESIZE, null);
}
QueuePanel.this.revalidate(); //fixes problem with cropped PauseButton
}
});
//listen for changes in gateways and repaint queue if necessary
gateways.addValuedListener(new ValuedListener<Gateways.Events, Gateway>() {
@Override
public void eventOccured(ValuedEvent<Gateways.Events, Gateway> e) {
switch(e.getEvent()) {
case ADDED_GATEWAY:
case ADDED_GATEWAYS:
case CLEARED_GATEWAYS:
case REMOVED_GATEWAY:
case REMOVED_GATEWAYS:
queueList.repaint();
}
}
});
}
/** Show or hide advanced controls (buttons, etc) */
private void showAdvancedControls(boolean show) {
smsUpButton.setVisible(show);
smsDownButton.setVisible(show);
popup.showAdvancedControls(show);
}
/** This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
jPanel1 = new JPanel();
jScrollPane2 = new JScrollPane();
queueList = new JList();
pausedLabel = new InfoLabel();
jPanel2 = new JPanel();
jPanel3 = new JPanel();
editButton = new JButton();
deleteButton = new JButton();
jPanel4 = new JPanel();
pauseButton = new JToggleButton();
jPanel5 = new JPanel();
smsUpButton = new JButton();
smsDownButton = new JButton();
setBorder(BorderFactory.createTitledBorder(l10n.getString("QueuePanel.border.title"))); // NOI18N
addFocusListener(new FocusAdapter() {
public void focusGained(FocusEvent evt) {
formFocusGained(evt);
}
});
jPanel1.setBorder(null);
queueList.setModel(queueListModel);
queueList.setCellRenderer(new SMSQueueListRenderer(queueList));
queueList.setVisibleRowCount(1);
queueList.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent evt) {
queueListValueChanged(evt);
}
});
queueList.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent evt) {
queueListKeyPressed(evt);
}
});
jScrollPane2.setViewportView(queueList);
Mnemonics.setLocalizedText(pausedLabel, l10n.getString("QueuePanel.pausedLabel.text"));
pausedLabel.setVisible(queue.isPaused());
GroupLayout jPanel1Layout = new GroupLayout(jPanel1);
jPanel1.setLayout(jPanel1Layout);
jPanel1Layout.setHorizontalGroup(
jPanel1Layout.createParallelGroup(Alignment.LEADING)
.addComponent(jScrollPane2, Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, 195, Short.MAX_VALUE)
.addComponent(pausedLabel, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
);
jPanel1Layout.setVerticalGroup(
jPanel1Layout.createParallelGroup(Alignment.LEADING)
.addGroup(Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
.addComponent(jScrollPane2, GroupLayout.DEFAULT_SIZE, 25, Short.MAX_VALUE)
.addPreferredGap(ComponentPlacement.RELATED)
.addComponent(pausedLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
);
jPanel2.setBorder(null);
jPanel2.setLayout(new BorderLayout());
jPanel3.setBorder(null);
editButton.setAction(editSMSAction);
editButton.putClientProperty(SubstanceLookAndFeel.FLAT_PROPERTY, Boolean.TRUE);
editButton.setText("");
deleteButton.setAction(deleteSMSAction);
deleteButton.putClientProperty(SubstanceLookAndFeel.FLAT_PROPERTY, Boolean.TRUE);
deleteButton.setText("");
GroupLayout jPanel3Layout = new GroupLayout(jPanel3);
jPanel3.setLayout(jPanel3Layout);
jPanel3Layout.setHorizontalGroup(
jPanel3Layout.createParallelGroup(Alignment.LEADING)
.addGroup(jPanel3Layout.createSequentialGroup()
.addComponent(editButton, GroupLayout.DEFAULT_SIZE, 28, Short.MAX_VALUE)
.addPreferredGap(ComponentPlacement.RELATED)
.addComponent(deleteButton, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
jPanel3Layout.setVerticalGroup(
jPanel3Layout.createParallelGroup(Alignment.LEADING)
.addComponent(editButton)
.addComponent(deleteButton)
);
jPanel2.add(jPanel3, BorderLayout.PAGE_START);
jPanel4.setBorder(null);
pauseButton.setAction(Actions.getQueuePauseAction(false));
pauseButton.putClientProperty(SubstanceLookAndFeel.FLAT_PROPERTY, Boolean.TRUE);
GroupLayout jPanel4Layout = new GroupLayout(jPanel4);
jPanel4.setLayout(jPanel4Layout);
jPanel4Layout.setHorizontalGroup(
jPanel4Layout.createParallelGroup(Alignment.LEADING)
.addComponent(pauseButton, GroupLayout.DEFAULT_SIZE, 62, Short.MAX_VALUE)
);
jPanel4Layout.setVerticalGroup(
jPanel4Layout.createParallelGroup(Alignment.LEADING)
.addComponent(pauseButton)
);
jPanel2.add(jPanel4, BorderLayout.PAGE_END);
smsUpButton.setAction(smsUpAction);
smsUpButton.putClientProperty(SubstanceLookAndFeel.FLAT_PROPERTY, Boolean.TRUE);
smsUpButton.setText("");
smsDownButton.setAction(smsDownAction);
smsDownButton.putClientProperty(SubstanceLookAndFeel.FLAT_PROPERTY, Boolean.TRUE);
smsDownButton.setText("");
GroupLayout jPanel5Layout = new GroupLayout(jPanel5);
jPanel5.setLayout(jPanel5Layout);
jPanel5Layout.setHorizontalGroup(
jPanel5Layout.createParallelGroup(Alignment.LEADING)
.addComponent(smsUpButton)
.addComponent(smsDownButton)
);
jPanel5Layout.setVerticalGroup(
jPanel5Layout.createParallelGroup(Alignment.LEADING)
.addGroup(jPanel5Layout.createSequentialGroup()
.addComponent(smsUpButton)
.addPreferredGap(ComponentPlacement.RELATED)
.addComponent(smsDownButton))
);
GroupLayout layout = new GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(Alignment.LEADING)
.addGroup(Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap()
.addComponent(jPanel5, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addPreferredGap(ComponentPlacement.RELATED)
.addComponent(jPanel1, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addPreferredGap(ComponentPlacement.RELATED)
.addComponent(jPanel2, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(Alignment.LEADING)
.addGroup(Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(Alignment.TRAILING)
.addComponent(jPanel1, Alignment.LEADING, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jPanel5, Alignment.LEADING, GroupLayout.DEFAULT_SIZE, 55, Short.MAX_VALUE)
.addComponent(jPanel2, Alignment.LEADING, GroupLayout.DEFAULT_SIZE, 55, Short.MAX_VALUE))
.addContainerGap())
);
}// </editor-fold>//GEN-END:initComponents
private void queueListValueChanged(ListSelectionEvent evt) {//GEN-FIRST:event_queueListValueChanged
if (evt != null && evt.getValueIsAdjusting()) {
return;
}
if (queueList.getMaxSelectionIndex() >= queueListModel.getSize()) {
//selection model has not yet been updated
return;
}
//update form components
int size = queueList.getSelectedIndices().length;
SMS sms = (SMS) queueList.getSelectedValue();
Object[] smses = queueList.getSelectedValues();
editSMSAction.setEnabled(size == 1 && sms.getStatus() != SMS.Status.SENDING);
deleteSMSAction.setEnabled(size > 0);
for (Object s : smses) {
if (((SMS)s).getStatus() == SMS.Status.SENDING) {
deleteSMSAction.setEnabled(false);
}
}
if (sms != null && size == 1) {
List<SMS> list = queue.getAll(sms.getGateway());
int index = list.indexOf(sms);
smsUpAction.setEnabled(index != 0);
smsDownAction.setEnabled(index < list.size() - 1);
} else {
smsUpAction.setEnabled(false);
smsDownAction.setEnabled(false);
}
}//GEN-LAST:event_queueListValueChanged
private void formFocusGained(FocusEvent evt) {//GEN-FIRST:event_formFocusGained
pauseButton.requestFocusInWindow();
}//GEN-LAST:event_formFocusGained
private void queueListKeyPressed(KeyEvent evt) {//GEN-FIRST:event_queueListKeyPressed
//delete sms on delete
if (evt.getKeyCode() == KeyEvent.VK_DELETE) {
deleteButton.doClick(0);
return;
}
}//GEN-LAST:event_queueListKeyPressed
/** Erase sms from queue list */
private class DeleteSMSAction extends AbstractAction {
private final String deleteOption = l10n.getString("Delete");
private final String cancelOption = l10n.getString("Cancel");
private final Object[] options = RuntimeUtils.sortDialogOptions(
cancelOption, deleteOption);
private final String message = l10n.getString("QueuePanel.confirmDelete");
public DeleteSMSAction() {
super(l10n.getString("Delete_messages"), Icons.get("delete-16.png"));
this.putValue(SHORT_DESCRIPTION,l10n.getString("Delete_selected_messages"));
this.putValue(LARGE_ICON_KEY, Icons.get("delete-22.png"));
this.setEnabled(false);
}
@Override
public void actionPerformed(ActionEvent e) {
Object[] toRemove = queueList.getSelectedValues();
//confirm
JOptionPane pane = new JOptionPane(message, JOptionPane.WARNING_MESSAGE,
JOptionPane.DEFAULT_OPTION, null, options, deleteOption);
JDialog dialog = pane.createDialog(Context.mainFrame, null);
dialog.setResizable(true);
RuntimeUtils.setDocumentModalDialog(dialog);
dialog.pack();
dialog.setVisible(true);
//delete
if (deleteOption.equals(pane.getValue())) {
for (Object o : toRemove) {
SMS sms = (SMS) o;
queue.remove(sms.getId());
}
}
//transfer focus
if (queueListModel.getSize() > 0) {
queueList.requestFocusInWindow();
} else {
pauseButton.requestFocusInWindow();
}
}
}
/** Edit sms from queue */
private class EditSMSAction extends AbstractAction {
public EditSMSAction() {
super(l10n.getString("Edit_message"), Icons.get("edit-16.png"));
this.putValue(SHORT_DESCRIPTION,l10n.getString("Edit_selected_message"));
this.putValue(LARGE_ICON_KEY, Icons.get("edit-22.png"));
this.setEnabled(false);
}
@Override
public void actionPerformed(ActionEvent e) {
SMS sms = (SMS) queueList.getSelectedValue();
if (sms == null) {
return;
}
//fire event
logger.fine("SMS requested for editing: " + sms);
valuedSupport.fireEventOccured(Events.SMS_EDIT_REQUESTED, sms);
}
}
/** move sms up in sms queue */
private class SMSUpAction extends AbstractAction {
public SMSUpAction() {
super(l10n.getString("Move_up"), Icons.get("up-16.png"));
this.putValue(SHORT_DESCRIPTION,l10n.getString("QueuePanel.Move_sms_up_in_the_queue"));
this.putValue(LARGE_ICON_KEY, Icons.get("up-22.png"));
this.setEnabled(false);
}
@Override
public void actionPerformed(ActionEvent e) {
SMS sms = (SMS) queueList.getSelectedValue();
if (sms == null) {
return;
}
queue.movePosition(sms, -1);
int index = queueListModel.indexOf(sms);
queueList.setSelectedIndex(index);
queueList.ensureIndexIsVisible(index);
}
}
/** move sms down in sms queue */
private class SMSDownAction extends AbstractAction {
public SMSDownAction() {
super(l10n.getString("Move_down"), Icons.get("down-16.png"));
this.putValue(SHORT_DESCRIPTION,l10n.getString("QueuePanel.Move_sms_down_in_the_queue"));
this.putValue(LARGE_ICON_KEY, Icons.get("down-22.png"));
this.setEnabled(false);
}
@Override
public void actionPerformed(ActionEvent e) {
SMS sms = (SMS) queueList.getSelectedValue();
if (sms == null) {
return;
}
queue.movePosition(sms, 1);
int index = queueListModel.indexOf(sms);
queueList.setSelectedIndex(index);
queueList.ensureIndexIsVisible(index);
}
}
/** Model for SMSQueueList */
private class QueueListModel extends AbstractListModel {
private int oldSize = getSize();
public QueueListModel() {
//listen for changes in contacts and fire events accordingly
queue.addValuedListener(new ValuedListener<Queue.Events, SMS>() {
@Override
public void eventOccured(ValuedEvent<Queue.Events, SMS> e) {
switch (e.getEvent()) {
case SMS_ADDED:
case SENDING_SMS:
case SMS_SENDING_FAILED:
case SMS_POSITION_CHANGED:
fireContentsChanged(QueueListModel.this, 0, getSize());
break;
case SMS_REMOVED:
case QUEUE_CLEARED:
fireIntervalRemoved(QueueListModel.this, 0, oldSize);
break;
}
oldSize = getSize();
timer.start(); //start counting down delays
}
});
}
@Override
public SMS getElementAt(int index) {
return queue.getAll().get(index);
}
@Override
public int getSize() {
return queue.size();
}
public int indexOf(SMS element) {
return queue.getAll().indexOf(element);
}
public void fireContentsChanged(int index0, int index1) {
super.fireContentsChanged(this, index0, index1);
}
}
/** Renderer for items in queue list */
private class SMSQueueListRenderer extends SubstanceDefaultListCellRenderer {
private final ListCellRenderer lafRenderer = new JList().getCellRenderer();
private final JLabel delayLabel = new JLabel("", SwingConstants.TRAILING);
private final ImageIcon sendIcon = Icons.get("send-16.png");
private final URL messageIconURI = getClass().getResource(RES + "message-32.png");
private final boolean isSubstance = ThemeManager.isSubstanceCurrentLaF();
private boolean selected = false; //whether current item is selected
private final JList jlist; //list to render
private SubstanceColorScheme scheme; //current Substance color scheme for this list
private SubstanceColorScheme borderScheme; //current Substance border color scheme for this list
private SubstanceHighlightPainter highlPainter; //current Substance highlight painter for this list
private SubstanceBorderPainter borderPainter; //current Substance border painter for this list
private final JPanel panel = new JPanel(new BorderLayout()) { //panel to wrap multiple labels
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
//Substance is not painting highlights on JPanels, therefore we must
//handle this painting on our own
if (isSubstance && selected) {
highlPainter.paintHighlight((Graphics2D) g, this, getWidth(),
getHeight(), scheme);
//do some black magic to get component contour - one pixel is
//substracted from right and bottom, bcz it was cut off otherwise
Rectangle contour = new Rectangle(0, 0, getWidth() - 1, getHeight() - 1);
borderPainter.paintBorder((Graphics2D) g, this, getWidth(),
getHeight(), contour, contour, borderScheme);
}
}
};
public SMSQueueListRenderer(JList list) {
this.jlist = list;
panel.add(delayLabel, BorderLayout.LINE_END);
updateSubstanceSkinValues();
SubstanceLookAndFeel.registerSkinChangeListener(new SkinChangeListener() {
@Override
public void skinChanged() {
updateSubstanceSkinValues();
}
});
}
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
Component c = lafRenderer.getListCellRendererComponent(list, value, index,
isSelected, false); //looks better without cell focus
selected = isSelected;
JLabel label = (JLabel) c;
SMS sms = (SMS)value;
//set text
label.setText(StringUtils.defaultIfEmpty(sms.getName(),
CountryPrefix.stripCountryPrefix(sms.getNumber(), true)));
//problematic sms colored
if ((sms.isProblematic()) && !isSelected) {
label.setBackground(Color.RED);
}
//set colors on other components
delayLabel.setForeground(label.getForeground());
delayLabel.setBackground(label.getBackground());
panel.setBackground(label.getBackground());
//add gateway logo
Gateway gateway = gateways.get(sms.getGateway());
label.setIcon(gateway != null ? gateway.getIcon() : Icons.GATEWAY_BLANK);
//set tooltip
String text = WordUtils.wrap(sms.getText(), 50, null, true);
text = MiscUtils.escapeHtml(text);
text = text.replaceAll("\n", "<br>");
String tooltip = "<html><table><tr><td><img src=\"" + messageIconURI +
"\"></td><td valign=top><b>" + label.getText() + "</b><br>" +
(StringUtils.isEmpty(sms.getName())?"":CountryPrefix.stripCountryPrefix(sms.getNumber(), true)+", ") +
sms.getGateway() + "<br><br>" + text +
"</td></tr></table></html>";
panel.setToolTipText(tooltip);
//set delay label
if (queue.getAllWithStatus(SMS.Status.SENDING).contains(sms)) {
delayLabel.setIcon(sendIcon);
delayLabel.setText(null);
} else {
delayLabel.setIcon(null);
long delay = queue.getSMSDelay(sms);
delayLabel.setText(Gateways.convertDelayToHumanString(delay, true));
}
//add to panel
panel.add(label, BorderLayout.CENTER);
return panel;
}
/** on substance skin update reinitialize some properties */
private void updateSubstanceSkinValues() {
if (!isSubstance) {
return;
}
scheme = SubstanceLookAndFeel.getCurrentSkin(jlist).getColorScheme(jlist,
ColorSchemeAssociationKind.HIGHLIGHT, ComponentState.SELECTED);
borderScheme = SubstanceLookAndFeel.getCurrentSkin(jlist).getColorScheme(jlist,
ColorSchemeAssociationKind.HIGHLIGHT_BORDER, ComponentState.SELECTED);
highlPainter = SubstanceLookAndFeel.getCurrentSkin(jlist).getHighlightPainter();
borderPainter = (SubstanceBorderPainter) ObjectUtils.defaultIfNull(
SubstanceLookAndFeel.getCurrentSkin(jlist).getHighlightBorderPainter(),
SubstanceLookAndFeel.getCurrentSkin(jlist).getBorderPainter());
}
}
/** Regularly update the information about current message delays */
private class DelayListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
boolean timerNeeded = false;
for (int i = 0; i < queueListModel.getSize(); i++) {
SMS sms = queueListModel.getElementAt(i);
long delay = queue.getSMSDelay(sms);
if (delay > 0) {
timerNeeded = true;
queueListModel.fireContentsChanged(i, i);
}
}
if (!timerNeeded) {
//when everything is on 0, no need for timer to run, let's stop it
timer.stop();
}
}
}
/** Popup menu in the queue list */
private class QueuePopupMenu extends JPopupMenu {
private ArrayList<JMenuItem> advancedItems = new ArrayList<JMenuItem>();
public QueuePopupMenu() {
JMenuItem menuItem = null;
//edit sms action
menuItem = new JMenuItem(editSMSAction);
this.add(menuItem);
//delete sms action
menuItem = new JMenuItem(deleteSMSAction);
this.add(menuItem);
//move sms up action
menuItem = new JMenuItem(smsUpAction);
this.add(menuItem);
advancedItems.add(menuItem);
//move sms down action
menuItem = new JMenuItem(smsDownAction);
this.add(menuItem);
advancedItems.add(menuItem);
this.addSeparator();
//queue pause action
menuItem = new JMenuItem(Actions.getQueuePauseAction(true));
this.add(menuItem);
}
public void showAdvancedControls(boolean show) {
for (JMenuItem item : advancedItems) {
item.setVisible(show);
}
}
}
/** Mouse listener on the queue list */
private class QueueMouseListener extends ListPopupMouseListener {
public QueueMouseListener(JList list, JPopupMenu popup) {
super(list, popup);
}
@Override
public void mouseClicked(MouseEvent e) {
//transfer on left button doubleclick
if (SwingUtilities.isLeftMouseButton(e) && e.getClickCount() > 1) {
editButton.doClick();
}
}
}
// Variables declaration - do not modify//GEN-BEGIN:variables
private JButton deleteButton;
private JButton editButton;
private JPanel jPanel1;
private JPanel jPanel2;
private JPanel jPanel3;
private JPanel jPanel4;
private JPanel jPanel5;
private JScrollPane jScrollPane2;
private JToggleButton pauseButton;
private InfoLabel pausedLabel;
private JList queueList;
private JButton smsDownButton;
private JButton smsUpButton;
// End of variables declaration//GEN-END:variables
}