package chatty.gui.components;
import chatty.gui.LinkListener;
import chatty.gui.UrlOpener;
import chatty.gui.components.menus.ContextMenuListener;
import chatty.util.DateTime;
import static chatty.util.DateTime.H;
import static chatty.util.DateTime.S;
import chatty.util.api.CommunitiesManager.Community;
import chatty.util.api.StreamInfo;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.*;
/**
*
* @author tduva
*/
public class ChannelInfoDialog extends JDialog implements ViewerHistoryListener {
private static final String STATUS_LABEL_TEXT = "Status:";
private static final String STATUS_LABEL_TEXT_HISTORY = "Status (History):";
private final JLabel statusLabel = new JLabel("Status:");
private final ExtendedTextPane title = new ExtendedTextPane();
private final JLabel onlineSince = new JLabel();
private boolean showWithPicnic;
private final JLabel gameLabel = new JLabel("Playing:");
private final JTextField game = new JTextField();
private final LinkLabel communityLabel;
private final JLabel historyLabel = new JLabel("Viewers:");
private final ViewerHistory history = new ViewerHistory();
private StreamInfo currentStreamInfo;
private String statusText = "";
private String gameText = "";
/**
* The time the stream of the current StreamInfo started. This is -1 if the
* stream is offline or the StreamInfo is invalid, or no time was received.
*/
private long timeStarted = -1;
public ChannelInfoDialog(Frame owner) {
super(owner);
setTitle("Channel Info");
setLayout(new GridBagLayout());
GridBagConstraints gbc;
// Status
gbc = makeGbc(0,0,1,1);
gbc.anchor = GridBagConstraints.WEST;
add(statusLabel,gbc);
gbc = makeGbc(1,0,1,1);
gbc.anchor = GridBagConstraints.EAST;
onlineSince.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
showWithPicnic = !showWithPicnic;
updateOnlineTime();
}
});
add(onlineSince, gbc);
title.setEditable(false);
title.setLinkListener(new MyLinkListener());
JScrollPane scroll = new JScrollPane(title);
scroll.setPreferredSize(new Dimension(300,70));
scroll.setMinimumSize(new Dimension(1,45));
gbc = makeGbc(0,1,2,1);
gbc.weighty = 0;
gbc.fill = GridBagConstraints.HORIZONTAL;
add(scroll,gbc);
// Game
gbc = makeGbc(0,2,1,1);
gbc.anchor = GridBagConstraints.WEST;
add(gameLabel,gbc);
game.setEditable(false);
gbc = makeGbc(0,3,2,1);
gbc.fill = GridBagConstraints.HORIZONTAL;
add(game,gbc);
gbc = makeGbc(1, 2, 1, 1);
gbc.anchor = GridBagConstraints.EAST;
communityLabel = new LinkLabel("", new LinkLabelListener() {
@Override
public void linkClicked(String type, String ref) {
String url = "https://www.twitch.tv/communities/"+ref;
UrlOpener.openUrlPrompt(ChannelInfoDialog.this, url);
}
});
communityLabel.setMargin(game.getMargin());
add(communityLabel, gbc);
// Graph
gbc = makeGbc(0,4,1,1);
gbc.insets = new Insets(3,5,3,3);
gbc.anchor = GridBagConstraints.WEST;
add(historyLabel,gbc);
history.setListener(this);
history.setForegroundColor(gameLabel.getForeground());
history.setBackgroundColor(gameLabel.getBackground());
history.setPreferredSize(new Dimension(300,150));
history.setMinimumSize(new Dimension(1,20));
gbc = makeGbc(0,5,2,1);
gbc.fill = GridBagConstraints.BOTH;
gbc.insets = new Insets(4,4,4,4);
gbc.weightx = 1;
gbc.weighty = 1;
add(history,gbc);
Timer timer = new Timer(30000, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
updateOnlineTime();
}
});
timer.setRepeats(true);
timer.start();
pack();
setMinimumSize(new Dimension(200,0));
}
/**
* Sets a new StreamInfo object.
*
* @param streamInfo
*/
public void set(StreamInfo streamInfo) {
String name = streamInfo.getDisplayName();
if (!streamInfo.hasRegularDisplayName()) {
name += " ("+streamInfo.getCapitalizedName()+")";
}
this.setTitle("Channel: "+name+(streamInfo.getFollowed() ? " (followed)" : ""));
String communityText = "";
if (streamInfo.isValid() && streamInfo.getOnline()) {
statusText = streamInfo.getTitle();
gameText = streamInfo.getGame();
if (gameText.isEmpty()) {
gameText = "No game";
}
timeStarted = streamInfo.getTimeStarted();
onlineSince.setText(null);
onlineSince.setToolTipText("Stream started: "+DateTime.formatFullDatetime(timeStarted));
Community community = streamInfo.getCommunity();
if (community != null) {
communityText = String.format("[community:%s %s]",
community.getName(),
community.getName());
}
}
else if (streamInfo.isValid()) {
statusText = "Stream offline";
gameText = "";
timeStarted = -1;
onlineSince.setText("Offline");
if (streamInfo.getLastOnlineTime() != -1) {
String lastBroadcastTime = formatTime(streamInfo.getTimeStarted(), streamInfo.getLastOnlineTime());
if (streamInfo.getTimeStarted() != streamInfo.getTimeStartedWithPicnic()) {
String withPicnic = formatTime(streamInfo.getTimeStartedWithPicnic(), streamInfo.getLastOnlineTime());
onlineSince.setToolTipText("Last broadcast length (probably approx.): " + lastBroadcastTime+" (With PICNIC: "+withPicnic+")");
} else {
onlineSince.setToolTipText("Last broadcast length (probably approx.): " + lastBroadcastTime);
}
} else {
onlineSince.setToolTipText(null);
}
}
else {
statusText = "[No Stream Information]";
gameText = "";
timeStarted = -1;
onlineSince.setText(null);
onlineSince.setToolTipText(null);
}
title.setText(statusText);
game.setText(gameText);
communityLabel.setText(communityText);
history.setHistory(streamInfo.getStream(), streamInfo.getHistory());
currentStreamInfo = streamInfo;
updateOnlineTime();
}
/**
* Updates the dialog if the given StreamInfo object is the one already
* set, or does nothing otherwise.
*
* @param streamInfo
*/
public void update(StreamInfo streamInfo) {
if (streamInfo == currentStreamInfo) {
set(streamInfo);
}
}
private void updateOnlineTime() {
if (timeStarted != -1) {
long withPicnic = currentStreamInfo.getTimeStartedWithPicnic();
if (withPicnic != timeStarted) {
onlineSince.setText("Online: " + formatTime(timeStarted) + " (" + formatTime(withPicnic)+")");
onlineSince.setToolTipText("Stream started: "+DateTime.formatFullDatetime(timeStarted)
+" (With PICNIC: "
+DateTime.formatFullDatetime(withPicnic)+")");
} else {
onlineSince.setText("Online: " + formatTime(timeStarted));
}
}
}
private static String formatTime(long time) {
return formatDuration(System.currentTimeMillis() - time);
}
private static String formatTime(long time, long time2) {
return formatDuration(time2 - time);
}
private static String formatDuration(long time) {
return DateTime.duration(time, H, 2, S);
}
private GridBagConstraints makeGbc(int x, int y, int w, int h) {
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = x;
gbc.gridy = y;
gbc.gridwidth = w;
gbc.gridheight = h;
gbc.insets = new Insets(3,3,3,3);
return gbc;
}
@Override
public void itemSelected(int viewers, String historyTitle, String historyGame) {
title.setText(historyTitle);
game.setText(historyGame);
statusLabel.setText(STATUS_LABEL_TEXT_HISTORY);
}
@Override
public void noItemSelected() {
this.title.setText(statusText);
this.game.setText(gameText);
statusLabel.setText(STATUS_LABEL_TEXT);
}
public void setHistoryRange(int minutes) {
history.setRange(minutes*60*1000);
}
public void addContextMenuListener(ContextMenuListener listener) {
history.addContextMenuListener(listener);
title.setContextMenuListener(listener);
}
private class MyLinkListener implements LinkListener {
@Override
public void linkClicked(String url) {
UrlOpener.openUrlPrompt(ChannelInfoDialog.this, url);
}
}
}