package chatty.gui.components; import chatty.gui.components.menus.ContextMenuListener; import chatty.gui.components.menus.StreamInfosContextMenu; import chatty.util.DateTime; import chatty.util.api.StreamInfo; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Rectangle; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.ArrayList; import java.util.List; import javax.swing.JButton; import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JScrollPane; /** * List where items are added to that were removed from the LiveStreamsDialog. * This includes offline streams as well as streams that didn't receive any * data anymore and are assumed offline (e.g. if you leave a channel). * * @author tduva */ public class LiveStreamsRemovedList extends JPanel { private final JList<RemovedListItem> list; private final JButton button; private final LiveStreamListener streamListener; private final List<ContextMenuListener> contextMenuListeners; private final SortedListModel<RemovedListItem> data; public LiveStreamsRemovedList(LiveStreamListener l) { setLayout(new GridBagLayout()); streamListener = l; contextMenuListeners = new ArrayList<>(); GridBagConstraints gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.gridy = 0; gbc.weightx = 1; gbc.weighty = 0; gbc.fill = GridBagConstraints.HORIZONTAL; button = new JButton("Back to Live Streams"); add(button, gbc); gbc.gridx = 0; gbc.gridy = 1; gbc.weighty = 1; gbc.fill = GridBagConstraints.BOTH; list = new JList<>(); data = new SortedListModel<>(); list.setModel(data); list.addMouseListener(new MyMouseListener()); add(new JScrollPane(list), gbc); } public void addStreamInfo(StreamInfo info) { data.add(new RemovedListItem(info)); } public void removeStreamInfo(StreamInfo info) { data.remove(getListItem(info)); } public void addContextMenuListener(ContextMenuListener cml) { if (cml != null) { contextMenuListeners.add(cml); } } public void addBackButtonListener(ActionListener listener) { button.addActionListener(listener); } private RemovedListItem getListItem(StreamInfo info) { for (RemovedListItem item : data) { if (item.getStreamInfo() == info) { return item; } } return null; } /** * Open context menu for this user, if the event points at one. * * @param e */ private void openContextMenu(MouseEvent e) { if (e.isPopupTrigger()) { selectClicked(e, false); List<RemovedListItem> selectedItems = list.getSelectedValuesList(); List<StreamInfo> selected = new ArrayList<>(); for (RemovedListItem item : selectedItems) { selected.add(item.getStreamInfo()); } StreamInfosContextMenu m = new StreamInfosContextMenu(selected, false); for (ContextMenuListener cml : contextMenuListeners) { m.addContextMenuListener(cml); } m.show(list, e.getX(), e.getY()); } } /** * Adds selection of the clicked element, or removes selection if no * element was clicked. * * @param e * @param onlyOutside */ private void selectClicked(MouseEvent e, boolean onlyOutside) { int index = list.locationToIndex(e.getPoint()); Rectangle bounds = list.getCellBounds(index, index); if (bounds != null && bounds.contains(e.getPoint())) { if (!onlyOutside) { if (list.isSelectedIndex(index)) { list.addSelectionInterval(index, index); } else { list.setSelectedIndex(index); } } } else { list.clearSelection(); } } private class MyMouseListener extends MouseAdapter { @Override public void mousePressed(MouseEvent e) { selectClicked(e, true); openContextMenu(e); } @Override public void mouseReleased(MouseEvent e) { openContextMenu(e); } @Override public void mouseClicked(MouseEvent e) { if (e.getClickCount() == 2) { RemovedListItem item = list.getSelectedValue(); if (item != null && streamListener != null) { streamListener.liveStreamClicked(item.getStreamInfo()); } } } } private static class RemovedListItem implements Comparable<RemovedListItem> { private final StreamInfo info; private final Long time; public RemovedListItem(StreamInfo info) { this.info = info; this.time = System.currentTimeMillis(); } @Override public String toString() { return DateTime.format(time)+" "+info.getCapitalizedName() +(info.getFollowed() ? " (followed)" : ""); } public StreamInfo getStreamInfo() { return info; } public Long getTime() { return time; } @Override public int compareTo(RemovedListItem o) { if (time > o.getTime()) { return -1; } if (time == o.getTime()) { return info.getStream().compareTo(o.getStreamInfo().getStream()); } return 1; } } }