package chatty.gui.components;
import chatty.gui.MainGui;
import chatty.util.DateTime;
import chatty.util.StringUtil;
import chatty.util.api.pubsub.ModeratorActionData;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.BorderFactory;
import javax.swing.JDialog;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultCaret;
import javax.swing.text.Document;
import javax.swing.text.Element;
/**
*
* @author tduva
*/
public class ModerationLog extends JDialog {
private static final int MAX_NUMBER_LINES = 1000;
private final JTextArea log;
private final JScrollPane scroll;
private final Map<String, List<String>> cache = new HashMap<>();
private String currentChannel;
public ModerationLog(MainGui owner) {
super(owner);
log = createLogArea();
setTitle("Moderator Actions");
scroll = new JScrollPane(log);
scroll.setPreferredSize(new Dimension(300, 200));
add(scroll, BorderLayout.CENTER);
pack();
}
private static JTextArea createLogArea() {
// Caret to prevent scrolling
DefaultCaret caret = new DefaultCaret();
caret.setUpdatePolicy(DefaultCaret.NEVER_UPDATE);
JTextArea text = new JTextArea();
text.setLineWrap(true);
text.setWrapStyleWord(true);
text.setEditable(false);
text.setCaret(caret);
text.setBorder(BorderFactory.createEmptyBorder(1, 2, 3, 2));
return text;
}
public void setChannel(String channel) {
if (channel != null && !channel.equals(currentChannel)) {
currentChannel = channel;
setTitle("Moderation Actions ("+channel+")");
List<String> cached = cache.get(channel);
if (cached != null) {
StringBuilder b = new StringBuilder();
String linebreak = "";
for (String line : cached) {
b.append(linebreak);
b.append(line);
linebreak = "\n";
}
log.setText(b.toString());
scrollDown();
} else {
log.setText(null);
}
}
}
public void add(ModeratorActionData data) {
if (data.stream == null) {
return;
}
String channel = data.stream;
String line = String.format("[%s] <%s> /%s %s",
DateTime.currentTime(),
data.created_by,
data.moderation_action,
StringUtil.join(data.args," "));
if (channel.equals(currentChannel)) {
printLine(log, line);
}
if (!cache.containsKey(channel)) {
cache.put(channel, new ArrayList<String>());
}
cache.get(channel).add(line);
}
private void printLine(JTextArea text, String line) {
try {
Document doc = text.getDocument();
String linebreak = doc.getLength() > 0 ? "\n" : "";
doc.insertString(doc.getLength(), linebreak+line, null);
JScrollBar bar = scroll.getVerticalScrollBar();
boolean scrollDown = bar.getValue() > bar.getMaximum() - bar.getVisibleAmount() - 4;
if (scrollDown) {
scrollDown();
}
clearSomeChat(doc);
} catch (BadLocationException e) {
e.printStackTrace();
}
}
private void scrollDown() {
scroll.validate();
scroll.getVerticalScrollBar().setValue(scroll.getVerticalScrollBar().getMaximum());
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
scroll.getVerticalScrollBar().setValue(scroll.getVerticalScrollBar().getMaximum());
}
});
}
/**
* Removes some lines from the given Document so it won't exceed the maximum
* number of lines.
*
* @param doc
*/
public void clearSomeChat(Document doc) {
int count = doc.getDefaultRootElement().getElementCount();
if (count > MAX_NUMBER_LINES) {
removeFirstLines(doc, 10);
}
}
/**
* Removes the given number of lines from the given Document.
*
* @param doc
* @param amount
*/
private void removeFirstLines(Document doc, int amount) {
if (amount < 1) {
amount = 1;
}
Element firstToRemove = doc.getDefaultRootElement().getElement(0);
Element lastToRemove = doc.getDefaultRootElement().getElement(amount - 1);
int startOffset = firstToRemove.getStartOffset();
int endOffset = lastToRemove.getEndOffset();
try {
doc.remove(startOffset,endOffset);
} catch (BadLocationException ex) {
ex.printStackTrace();
}
}
public void showDialog() {
setVisible(true);
}
}