2017-01-09 20:37:57 +01:00
|
|
|
package net.ME1312.SubServers.Console;
|
|
|
|
|
|
|
|
import net.ME1312.SubServers.Bungee.Host.SubLogFilter;
|
2017-01-11 04:23:29 +01:00
|
|
|
import net.ME1312.SubServers.Bungee.Host.SubLogger;
|
2017-01-09 20:37:57 +01:00
|
|
|
import net.ME1312.SubServers.Bungee.Host.SubServer;
|
2017-01-21 17:49:37 +01:00
|
|
|
import net.md_5.bungee.api.ProxyServer;
|
2017-01-09 20:37:57 +01:00
|
|
|
|
|
|
|
import javax.swing.*;
|
2017-01-12 21:58:31 +01:00
|
|
|
import javax.swing.border.Border;
|
2017-01-11 04:23:29 +01:00
|
|
|
import javax.swing.text.*;
|
2017-01-09 20:37:57 +01:00
|
|
|
import java.awt.*;
|
|
|
|
import java.awt.event.*;
|
|
|
|
import java.text.SimpleDateFormat;
|
2017-01-11 04:23:29 +01:00
|
|
|
import java.util.*;
|
|
|
|
import java.util.List;
|
2017-01-09 20:37:57 +01:00
|
|
|
import java.util.logging.Level;
|
2017-01-21 17:49:37 +01:00
|
|
|
import java.util.regex.Matcher;
|
|
|
|
import java.util.regex.Pattern;
|
2017-01-09 20:37:57 +01:00
|
|
|
|
2017-01-11 04:23:29 +01:00
|
|
|
public class ConsoleWindow implements SubLogFilter {
|
2017-01-11 23:07:03 +01:00
|
|
|
private ConsolePlugin plugin;
|
2017-01-11 04:23:29 +01:00
|
|
|
private JFrame window;
|
|
|
|
private JPanel panel;
|
2017-01-09 20:37:57 +01:00
|
|
|
private JTextField input;
|
2017-01-11 23:07:03 +01:00
|
|
|
private boolean ifocus = false;
|
2017-01-09 20:37:57 +01:00
|
|
|
private TextFieldPopup popup;
|
|
|
|
private JTextArea log;
|
2017-01-11 04:23:29 +01:00
|
|
|
private JScrollPane vScroll;
|
|
|
|
private JScrollBar hScroll;
|
|
|
|
private List<Integer> eScroll = new ArrayList<Integer>();
|
|
|
|
private JPanel find;
|
|
|
|
private JTextField findT;
|
|
|
|
private JButton findN;
|
|
|
|
private JButton findP;
|
|
|
|
private JButton findD;
|
|
|
|
private int findO = 0;
|
|
|
|
private int findI = 0;
|
2017-01-11 23:07:03 +01:00
|
|
|
private boolean open = false;
|
2017-01-11 04:23:29 +01:00
|
|
|
private SubLogger logger;
|
|
|
|
private KeyEventDispatcher keys = event -> {
|
|
|
|
if (window.isVisible() && window.isFocused()) {
|
2017-01-12 21:58:31 +01:00
|
|
|
if (event.getID() == KeyEvent.KEY_PRESSED) switch (event.getKeyCode()) {
|
2017-01-11 23:07:03 +01:00
|
|
|
case KeyEvent.VK_UP:
|
|
|
|
if (ifocus)
|
2017-01-11 04:23:29 +01:00
|
|
|
popup.prev(input);
|
|
|
|
break;
|
2017-01-11 23:07:03 +01:00
|
|
|
case KeyEvent.VK_DOWN:
|
|
|
|
if (ifocus)
|
2017-01-11 04:23:29 +01:00
|
|
|
popup.next(input);
|
2017-01-11 23:07:03 +01:00
|
|
|
break;
|
|
|
|
case KeyEvent.VK_ESCAPE:
|
|
|
|
if (find.isVisible()) {
|
|
|
|
find.setVisible(false);
|
|
|
|
findI = 0;
|
|
|
|
findO = 0;
|
2017-01-11 04:23:29 +01:00
|
|
|
}
|
|
|
|
break;
|
2017-01-11 23:07:03 +01:00
|
|
|
case KeyEvent.VK_ENTER:
|
|
|
|
if (find.isVisible() && !ifocus)
|
|
|
|
find(true);
|
|
|
|
break;
|
2017-01-11 04:23:29 +01:00
|
|
|
}
|
2017-01-11 23:07:03 +01:00
|
|
|
|
2017-01-11 04:23:29 +01:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
};
|
2017-01-09 20:37:57 +01:00
|
|
|
|
2017-01-11 23:07:03 +01:00
|
|
|
public ConsoleWindow(ConsolePlugin plugin, SubLogger logger) {
|
|
|
|
this.plugin = plugin;
|
2017-01-11 04:23:29 +01:00
|
|
|
this.logger = logger;
|
2017-01-12 21:58:31 +01:00
|
|
|
|
|
|
|
window = new JFrame();
|
|
|
|
|
|
|
|
JMenuBar jMenu = new JMenuBar();
|
|
|
|
JMenu menu = new JMenu("View");
|
|
|
|
JMenuItem item = new JMenuItem("Scroll to Top");
|
|
|
|
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_UP, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), true));
|
|
|
|
item.addActionListener(event -> vScroll.getVerticalScrollBar().setValue(0));
|
|
|
|
menu.add(item);
|
|
|
|
item = new JMenuItem("Scroll to Bottom");
|
|
|
|
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), true));
|
|
|
|
item.addActionListener(event -> vScroll.getVerticalScrollBar().setValue(vScroll.getVerticalScrollBar().getMaximum() - vScroll.getVerticalScrollBar().getVisibleAmount()));
|
|
|
|
menu.add(item);
|
|
|
|
item = new JMenuItem("Find");
|
|
|
|
item.setAccelerator(KeyStroke.getKeyStroke('F', Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), true));
|
|
|
|
item.addActionListener(event -> {
|
|
|
|
if (find.isVisible()) {
|
|
|
|
find.setVisible(false);
|
|
|
|
findI = 0;
|
|
|
|
findO = 0;
|
|
|
|
} else {
|
|
|
|
find.setVisible(true);
|
|
|
|
findT.selectAll();
|
|
|
|
findT.requestFocusInWindow();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
menu.add(item);
|
|
|
|
menu.addSeparator();
|
|
|
|
item = new JMenuItem("Reset Text Size");
|
|
|
|
item.addActionListener(event -> {
|
|
|
|
log.setFont(new Font(log.getFont().getName(), log.getFont().getStyle(), 12));
|
|
|
|
SwingUtilities.invokeLater(this::hScroll);
|
|
|
|
});
|
|
|
|
menu.add(item);
|
|
|
|
item = new JMenuItem("Bigger Text");
|
|
|
|
item.setAccelerator(KeyStroke.getKeyStroke('=', Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), true));
|
|
|
|
item.addActionListener(event -> {
|
|
|
|
log.setFont(new Font(log.getFont().getName(), log.getFont().getStyle(), log.getFont().getSize() + 2));
|
|
|
|
SwingUtilities.invokeLater(this::hScroll);
|
|
|
|
});
|
|
|
|
menu.add(item);
|
|
|
|
item = new JMenuItem("Smaller Text");
|
|
|
|
item.setAccelerator(KeyStroke.getKeyStroke('-', Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), true));
|
|
|
|
item.addActionListener(event -> {
|
|
|
|
log.setFont(new Font(log.getFont().getName(), log.getFont().getStyle(), log.getFont().getSize() - 2));
|
|
|
|
SwingUtilities.invokeLater(this::hScroll);
|
|
|
|
});
|
|
|
|
menu.add(item);
|
|
|
|
menu.addSeparator();
|
|
|
|
item = new JMenuItem("Clear Screen");
|
|
|
|
item.setAccelerator(KeyStroke.getKeyStroke('L', Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), true));
|
|
|
|
item.addActionListener(event -> clear());
|
|
|
|
menu.add(item);
|
|
|
|
item = new JMenuItem("Reload Log");
|
|
|
|
item.setAccelerator(KeyStroke.getKeyStroke('R', Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), true));
|
|
|
|
item.addActionListener(event -> {
|
2017-01-11 04:23:29 +01:00
|
|
|
log.setText("\n");
|
2017-01-21 17:49:37 +01:00
|
|
|
loadContent();
|
2017-01-12 21:58:31 +01:00
|
|
|
});
|
|
|
|
menu.add(item);
|
|
|
|
jMenu.add(menu);
|
|
|
|
window.setJMenuBar(jMenu);
|
|
|
|
window.setContentPane(panel);
|
|
|
|
window.pack();
|
|
|
|
window.setTitle(logger.getName() + " \u2014 SubServers 2");
|
|
|
|
window.setSize(1024, 576);
|
|
|
|
Dimension dimension = Toolkit.getDefaultToolkit().getScreenSize();
|
|
|
|
int x = (int) ((dimension.getWidth() - window.getWidth()) / 2);
|
|
|
|
int y = (int) ((dimension.getHeight() - window.getHeight()) / 2);
|
|
|
|
window.setLocation(x, y);
|
|
|
|
window.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
|
|
|
|
window.addWindowListener(new WindowAdapter() {
|
|
|
|
@Override
|
|
|
|
public void windowClosing(WindowEvent e) {
|
|
|
|
close();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
window.addComponentListener(new ComponentAdapter() {
|
|
|
|
public void componentResized(ComponentEvent e) {
|
|
|
|
SwingUtilities.invokeLater(ConsoleWindow.this::hScroll);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
vScroll.setBorder(BorderFactory.createEmptyBorder());
|
|
|
|
new SmartScroller(vScroll, SmartScroller.VERTICAL, SmartScroller.END);
|
|
|
|
log.setBorder(BorderFactory.createLineBorder(new Color(40, 44, 45)));
|
|
|
|
new TextFieldPopup(log, false);
|
|
|
|
((AbstractDocument) log.getDocument()).setDocumentFilter(new DocumentFilter() {
|
|
|
|
@Override
|
|
|
|
public void insertString(FilterBypass fb, int offset, String string, AttributeSet attr) throws BadLocationException {
|
|
|
|
super.insertString(fb, offset, string, attr);
|
|
|
|
hScroll();
|
|
|
|
}
|
2017-01-11 04:23:29 +01:00
|
|
|
|
2017-01-12 21:58:31 +01:00
|
|
|
@Override
|
|
|
|
public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException {
|
|
|
|
super.replace(fb, offset, length, text, attrs);
|
|
|
|
hScroll();
|
|
|
|
}
|
2017-01-11 04:23:29 +01:00
|
|
|
|
2017-01-12 21:58:31 +01:00
|
|
|
@Override
|
|
|
|
public void remove(FilterBypass fb, int offset, int length) throws BadLocationException {
|
|
|
|
super.remove(fb, offset, length);
|
|
|
|
hScroll();
|
|
|
|
}
|
|
|
|
});
|
2017-01-11 04:23:29 +01:00
|
|
|
|
|
|
|
|
2017-01-12 21:58:31 +01:00
|
|
|
popup = new TextFieldPopup(input, true);
|
|
|
|
input.setBorder(BorderFactory.createLineBorder(new Color(40, 44, 45), 4));
|
|
|
|
input.addActionListener((ActionEvent event) -> {
|
|
|
|
if (logger.getHandler() instanceof SubServer && input.getText().length() > 0 && !input.getText().equals(">")) {
|
|
|
|
if (((SubServer) logger.getHandler()).command((input.getText().startsWith(">")) ? input.getText().substring(1) : input.getText())) {
|
|
|
|
popup.commands.add((input.getText().startsWith(">")) ? input.getText().substring(1) : input.getText());
|
|
|
|
popup.current = 0;
|
|
|
|
popup.last = true;
|
|
|
|
input.setText("");
|
2017-01-11 04:23:29 +01:00
|
|
|
}
|
2017-01-12 21:58:31 +01:00
|
|
|
}
|
|
|
|
});
|
|
|
|
((AbstractDocument) input.getDocument()).setDocumentFilter(new DocumentFilter() {
|
|
|
|
@Override
|
|
|
|
public void insertString(FilterBypass fb, int offset, String string, AttributeSet attr) throws BadLocationException {
|
|
|
|
if (offset < 1) {
|
|
|
|
return;
|
2017-01-11 04:23:29 +01:00
|
|
|
}
|
2017-01-12 21:58:31 +01:00
|
|
|
super.insertString(fb, offset, string, attr);
|
|
|
|
}
|
2017-01-11 04:23:29 +01:00
|
|
|
|
2017-01-12 21:58:31 +01:00
|
|
|
@Override
|
|
|
|
public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException {
|
|
|
|
if (offset < 1) {
|
|
|
|
length = Math.max(0, length - 1);
|
|
|
|
offset = 1;
|
2017-01-11 04:23:29 +01:00
|
|
|
}
|
2017-01-12 21:58:31 +01:00
|
|
|
super.replace(fb, offset, length, text, attrs);
|
|
|
|
}
|
2017-01-11 04:23:29 +01:00
|
|
|
|
2017-01-12 21:58:31 +01:00
|
|
|
@Override
|
|
|
|
public void remove(FilterBypass fb, int offset, int length) throws BadLocationException {
|
|
|
|
if (offset < 1) {
|
|
|
|
length = Math.max(0, length + offset - 1);
|
|
|
|
offset = 1;
|
2017-01-11 23:07:03 +01:00
|
|
|
}
|
2017-01-12 21:58:31 +01:00
|
|
|
if (length > 0) {
|
|
|
|
super.remove(fb, offset, length);
|
2017-01-11 23:07:03 +01:00
|
|
|
}
|
2017-01-12 21:58:31 +01:00
|
|
|
}
|
|
|
|
});
|
|
|
|
input.addFocusListener(new FocusListener() {
|
|
|
|
@Override
|
|
|
|
public void focusGained(FocusEvent e) {
|
|
|
|
ifocus = true;
|
|
|
|
}
|
2017-01-11 04:23:29 +01:00
|
|
|
|
2017-01-12 21:58:31 +01:00
|
|
|
@Override
|
|
|
|
public void focusLost(FocusEvent e) {
|
|
|
|
ifocus = false;
|
|
|
|
}
|
|
|
|
});
|
2017-01-11 04:23:29 +01:00
|
|
|
|
2017-01-12 21:58:31 +01:00
|
|
|
vScroll.getHorizontalScrollBar().addAdjustmentListener(event -> {
|
|
|
|
if (!eScroll.contains(event.getValue())) {
|
|
|
|
eScroll.add(event.getValue());
|
|
|
|
hScroll.setValue(event.getValue());
|
|
|
|
} else {
|
|
|
|
eScroll.remove((Object) event.getValue());
|
|
|
|
}
|
|
|
|
});
|
|
|
|
hScroll.addAdjustmentListener(event -> {
|
|
|
|
if (!eScroll.contains(event.getValue())) {
|
|
|
|
eScroll.add(event.getValue());
|
|
|
|
vScroll.getHorizontalScrollBar().setValue(event.getValue());
|
|
|
|
} else {
|
|
|
|
eScroll.remove((Object) event.getValue());
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
new TextFieldPopup(findT, false);
|
|
|
|
findT.setBorder(BorderFactory.createLineBorder(new Color(40, 44, 45), 4));
|
|
|
|
((AbstractDocument) findT.getDocument()).setDocumentFilter(new DocumentFilter() {
|
|
|
|
@Override
|
|
|
|
public void insertString(FilterBypass fb, int offset, String string, AttributeSet attr) throws BadLocationException {
|
|
|
|
super.insertString(fb, offset, string, attr);
|
2017-01-11 04:23:29 +01:00
|
|
|
findI = 0;
|
|
|
|
findO = 0;
|
2017-01-12 21:58:31 +01:00
|
|
|
}
|
2017-01-09 20:37:57 +01:00
|
|
|
|
2017-01-12 21:58:31 +01:00
|
|
|
@Override
|
|
|
|
public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException {
|
|
|
|
super.replace(fb, offset, length, text, attrs);
|
|
|
|
findI = 0;
|
|
|
|
findO = 0;
|
2017-01-09 20:37:57 +01:00
|
|
|
}
|
2017-01-11 04:23:29 +01:00
|
|
|
|
2017-01-12 21:58:31 +01:00
|
|
|
@Override
|
|
|
|
public void remove(FilterBypass fb, int offset, int length) throws BadLocationException {
|
|
|
|
super.remove(fb, offset, length);
|
|
|
|
findI = 0;
|
|
|
|
findO = 0;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
findP.addChangeListener(e -> {
|
|
|
|
if (findP.getModel().isPressed()) findP.setBackground(new Color(40, 44, 45));
|
|
|
|
else findP.setBackground(new Color(69, 73, 74));
|
|
|
|
});
|
|
|
|
findP.setBorder(new ButtonBorder(40, 44, 45, 4));
|
|
|
|
findP.addActionListener(event -> find(false));
|
|
|
|
findN.addChangeListener(e -> {
|
|
|
|
if (findN.getModel().isPressed()) findN.setBackground(new Color(40, 44, 45));
|
|
|
|
else findN.setBackground(new Color(69, 73, 74));
|
|
|
|
});
|
|
|
|
findN.setBorder(new ButtonBorder(40, 44, 45, 4));
|
|
|
|
findN.addActionListener(event -> find(true));
|
|
|
|
findD.addChangeListener(e -> {
|
|
|
|
if (findD.getModel().isPressed()) findD.setBackground(new Color(40, 44, 45));
|
|
|
|
else findD.setBackground(new Color(69, 73, 74));
|
2017-01-09 20:37:57 +01:00
|
|
|
});
|
2017-01-12 21:58:31 +01:00
|
|
|
findD.setBorder(new ButtonBorder(40, 44, 45, 4));
|
|
|
|
findD.addActionListener(event -> {
|
|
|
|
find.setVisible(false);
|
|
|
|
findI = 0;
|
|
|
|
findO = 0;
|
|
|
|
});
|
|
|
|
|
|
|
|
|
2017-01-21 17:49:37 +01:00
|
|
|
if (logger.getHandler() instanceof SubServer) {
|
|
|
|
for (SubServer.LoggedCommand command : ((SubServer) logger.getHandler()).getCommandHistory()) popup.commands.add(command.getCommand());
|
|
|
|
} else {
|
2017-01-12 21:58:31 +01:00
|
|
|
input.setVisible(false);
|
|
|
|
hScroll.setVisible(false);
|
|
|
|
vScroll.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
|
|
|
|
}
|
|
|
|
|
|
|
|
logger.registerFilter(this);
|
2017-01-21 17:49:37 +01:00
|
|
|
log.setText("\n");
|
|
|
|
loadContent();
|
2017-01-12 21:58:31 +01:00
|
|
|
KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(keys);
|
|
|
|
if (logger.isLogging() && !open) open();
|
2017-01-11 04:23:29 +01:00
|
|
|
}
|
|
|
|
private void hScroll() {
|
|
|
|
hScroll.setMaximum(vScroll.getHorizontalScrollBar().getMaximum());
|
|
|
|
hScroll.setMinimum(vScroll.getHorizontalScrollBar().getMinimum());
|
|
|
|
hScroll.setVisibleAmount(vScroll.getHorizontalScrollBar().getVisibleAmount());
|
2017-01-09 20:37:57 +01:00
|
|
|
}
|
|
|
|
|
2017-01-21 17:49:37 +01:00
|
|
|
private void loadContent() {
|
|
|
|
LinkedList<Object> list = new LinkedList<Object>();
|
|
|
|
list.addAll(logger.getMessageHistory());
|
|
|
|
if (logger.getHandler() instanceof SubServer) list.addAll(((SubServer) logger.getHandler()).getCommandHistory());
|
|
|
|
list.sort((A, B) -> {
|
|
|
|
Date a = null, b = null;
|
|
|
|
|
|
|
|
if (A instanceof SubLogger.LogMessage) a = ((SubLogger.LogMessage) A).getDate();
|
|
|
|
if (A instanceof SubServer.LoggedCommand) a = ((SubServer.LoggedCommand) A).getDate();
|
|
|
|
|
|
|
|
if (B instanceof SubLogger.LogMessage) b = ((SubLogger.LogMessage) B).getDate();
|
|
|
|
if (B instanceof SubServer.LoggedCommand) b = ((SubServer.LoggedCommand) B).getDate();
|
|
|
|
|
|
|
|
return (a == null || b == null)?0:a.compareTo(b);
|
|
|
|
});
|
|
|
|
for (Object obj : list) {
|
|
|
|
if (obj instanceof SubLogger.LogMessage) log(((SubLogger.LogMessage) obj).getDate(), ((SubLogger.LogMessage) obj).getLevel(), ((SubLogger.LogMessage) obj).getMessage());
|
|
|
|
if (obj instanceof SubServer.LoggedCommand) log(((SubServer.LoggedCommand) obj).getDate(), '<' + ((((SubServer.LoggedCommand) obj).getSender() == null)?"CONSOLE":((ProxyServer.getInstance().getPlayer(((SubServer.LoggedCommand) obj).getSender()) == null)?((SubServer.LoggedCommand) obj).getSender().toString():ProxyServer.getInstance().getPlayer(((SubServer.LoggedCommand) obj).getSender()).getName())) + "> /" + ((SubServer.LoggedCommand) obj).getCommand());
|
|
|
|
}
|
|
|
|
SwingUtilities.invokeLater(this::hScroll);
|
|
|
|
}
|
|
|
|
|
2017-01-11 23:07:03 +01:00
|
|
|
public SubLogger getLogger() {
|
|
|
|
return logger;
|
2017-01-11 04:23:29 +01:00
|
|
|
}
|
|
|
|
|
2017-01-11 23:07:03 +01:00
|
|
|
public void log(Date date, String message) {
|
|
|
|
log.append(' ' + new SimpleDateFormat("hh:mm:ss").format(date) + ' ' + message + " \n");
|
2017-01-11 04:23:29 +01:00
|
|
|
}
|
|
|
|
public void log(String message) {
|
2017-01-11 23:07:03 +01:00
|
|
|
log(Calendar.getInstance().getTime(), message);
|
|
|
|
}
|
|
|
|
public void log(Date date, Level level, String message) {
|
|
|
|
log(date, "[" + level.getLocalizedName() + "] " + message);
|
2017-01-11 04:23:29 +01:00
|
|
|
}
|
2017-01-09 20:37:57 +01:00
|
|
|
@Override
|
|
|
|
public boolean log(Level level, String message) {
|
2017-01-11 23:07:03 +01:00
|
|
|
log(Calendar.getInstance().getTime(), level, message);
|
2017-01-09 21:15:43 +01:00
|
|
|
return !open;
|
2017-01-09 20:37:57 +01:00
|
|
|
}
|
|
|
|
|
2017-01-11 23:07:03 +01:00
|
|
|
public void clear() {
|
|
|
|
log.setText("\n");
|
|
|
|
SwingUtilities.invokeLater(this::hScroll);
|
|
|
|
}
|
|
|
|
|
2017-01-11 04:23:29 +01:00
|
|
|
@Override
|
|
|
|
public void start() {
|
|
|
|
open();
|
|
|
|
}
|
2017-01-09 20:37:57 +01:00
|
|
|
public void open() {
|
2017-01-12 21:58:31 +01:00
|
|
|
SwingUtilities.invokeLater(() -> {
|
2017-01-11 04:23:29 +01:00
|
|
|
if (!open) {
|
|
|
|
window.setVisible(true);
|
|
|
|
this.open = true;
|
|
|
|
}
|
|
|
|
window.toFront();
|
|
|
|
});
|
2017-01-09 20:37:57 +01:00
|
|
|
}
|
|
|
|
|
2017-01-11 23:07:03 +01:00
|
|
|
public boolean isOpen() {
|
|
|
|
return open;
|
2017-01-11 04:23:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void stop() {
|
|
|
|
close();
|
2017-01-21 17:49:37 +01:00
|
|
|
clear();
|
2017-01-11 04:23:29 +01:00
|
|
|
}
|
2017-01-09 20:37:57 +01:00
|
|
|
public void close() {
|
2017-01-12 21:58:31 +01:00
|
|
|
SwingUtilities.invokeLater(() -> {
|
2017-01-11 04:23:29 +01:00
|
|
|
if (open) {
|
|
|
|
this.open = false;
|
|
|
|
if (find.isVisible()) {
|
|
|
|
find.setVisible(false);
|
|
|
|
findI = 0;
|
|
|
|
findO = 0;
|
|
|
|
}
|
|
|
|
window.setVisible(false);
|
2017-01-11 23:07:03 +01:00
|
|
|
plugin.onClose(this);
|
2017-01-11 04:23:29 +01:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
public void destroy() {
|
|
|
|
close();
|
|
|
|
logger.unregisterFilter(this);
|
|
|
|
KeyboardFocusManager.getCurrentKeyboardFocusManager().removeKeyEventDispatcher(keys);
|
2017-01-09 20:37:57 +01:00
|
|
|
}
|
|
|
|
|
2017-01-11 23:07:03 +01:00
|
|
|
private void find(boolean direction) {
|
|
|
|
if (!direction) findI -= findO + 1;
|
|
|
|
String find = findT.getText().toLowerCase();
|
|
|
|
log.requestFocusInWindow();
|
|
|
|
|
|
|
|
if (find.length() > 0) {
|
|
|
|
Document document = log.getDocument();
|
|
|
|
int findLength = find.length();
|
|
|
|
try {
|
|
|
|
boolean found = false;
|
|
|
|
|
|
|
|
if (findI + findLength >= document.getLength()) findI = 1;
|
|
|
|
|
|
|
|
while (findLength <= document.getLength()) {
|
|
|
|
String match = document.getText(findI, findLength).toLowerCase();
|
|
|
|
if (match.equals(find)) {
|
|
|
|
found = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (direction) findI++;
|
|
|
|
else findI--;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (found) {
|
|
|
|
Rectangle viewRect = log.modelToView(findI);
|
|
|
|
log.scrollRectToVisible(viewRect);
|
|
|
|
|
|
|
|
log.setCaretPosition(findI + findLength);
|
|
|
|
log.moveCaretPosition(findI);
|
|
|
|
|
|
|
|
findI += findLength;
|
|
|
|
findO = findLength;
|
|
|
|
}
|
|
|
|
|
|
|
|
} catch (BadLocationException e) {
|
|
|
|
findI = log.getText().length() - 1;
|
|
|
|
JOptionPane.showMessageDialog(window,
|
2017-01-12 21:58:31 +01:00
|
|
|
((findO > 0)?"There are no more results\nSearch again to start from the " + ((direction)?"top":"bottom"):"Couldn't find \"" + findT.getText() + "\""),
|
2017-01-11 23:07:03 +01:00
|
|
|
"Find",
|
|
|
|
JOptionPane.WARNING_MESSAGE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-09 20:37:57 +01:00
|
|
|
private class TextFieldPopup extends JPanel {
|
|
|
|
protected LinkedList<String> commands = new LinkedList<String>();
|
|
|
|
protected int current = 0;
|
|
|
|
protected boolean last = true;
|
|
|
|
|
2017-01-11 04:23:29 +01:00
|
|
|
public TextFieldPopup(JTextComponent field, boolean command) {
|
2017-01-09 20:37:57 +01:00
|
|
|
JPopupMenu menu = new JPopupMenu();
|
|
|
|
|
2017-01-09 21:15:43 +01:00
|
|
|
if (field.isEditable()) {
|
2017-01-11 04:23:29 +01:00
|
|
|
if (command) {
|
|
|
|
Action backward = new TextAction("Previous Command") {
|
|
|
|
public void actionPerformed(ActionEvent e) {
|
|
|
|
prev(getFocusedComponent());
|
2017-01-09 20:37:57 +01:00
|
|
|
}
|
2017-01-11 04:23:29 +01:00
|
|
|
};
|
|
|
|
menu.add(backward);
|
|
|
|
|
|
|
|
Action forward = new TextAction("Next Command") {
|
|
|
|
public void actionPerformed(ActionEvent e) {
|
|
|
|
next(getFocusedComponent());
|
2017-01-09 21:15:43 +01:00
|
|
|
}
|
2017-01-11 04:23:29 +01:00
|
|
|
};
|
|
|
|
menu.add(forward);
|
|
|
|
menu.addSeparator();
|
|
|
|
}
|
2017-01-09 20:37:57 +01:00
|
|
|
|
|
|
|
Action cut = new DefaultEditorKit.CutAction();
|
|
|
|
cut.putValue(Action.NAME, "Cut");
|
|
|
|
cut.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke('X', Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), true));
|
|
|
|
menu.add(cut);
|
|
|
|
}
|
|
|
|
|
|
|
|
Action copy = new DefaultEditorKit.CopyAction();
|
|
|
|
copy.putValue(Action.NAME, "Copy");
|
|
|
|
copy.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke('C', Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), true));
|
|
|
|
menu.add(copy);
|
|
|
|
|
2017-01-09 21:15:43 +01:00
|
|
|
if (field.isEditable()) {
|
2017-01-09 20:37:57 +01:00
|
|
|
Action paste = new DefaultEditorKit.PasteAction();
|
|
|
|
paste.putValue(Action.NAME, "Paste");
|
|
|
|
paste.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke('V', Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), true));
|
|
|
|
menu.add(paste);
|
|
|
|
}
|
|
|
|
|
2017-01-12 21:58:31 +01:00
|
|
|
Action find = new TextAction("Find Selection") {
|
|
|
|
public void actionPerformed(ActionEvent e) {
|
|
|
|
JTextComponent field = getFocusedComponent();
|
|
|
|
if (field.getSelectedText() != null && field.getSelectedText().length() > 0) {
|
|
|
|
findT.setText(field.getSelectedText());
|
|
|
|
findI = 0;
|
|
|
|
findO = 0;
|
|
|
|
ConsoleWindow.this.find.setVisible(true);
|
|
|
|
find(true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
find.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke('F', Toolkit.getDefaultToolkit().getMenuShortcutKeyMask() + KeyEvent.SHIFT_MASK, true));
|
|
|
|
menu.add(find);
|
|
|
|
|
2017-01-09 20:37:57 +01:00
|
|
|
Action selectAll = new TextAction("Select All") {
|
|
|
|
public void actionPerformed(ActionEvent e) {
|
|
|
|
JTextComponent field = getFocusedComponent();
|
|
|
|
field.selectAll();
|
|
|
|
field.requestFocusInWindow();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
selectAll.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke('A', Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), true));
|
|
|
|
menu.add(selectAll);
|
|
|
|
|
|
|
|
field.setComponentPopupMenu(menu);
|
|
|
|
}
|
2017-01-11 04:23:29 +01:00
|
|
|
|
|
|
|
public void next(JTextComponent field) {
|
|
|
|
if (field.isEditable()) {
|
|
|
|
LinkedList<String> list = new LinkedList<String>(commands);
|
|
|
|
Collections.reverse(list);
|
|
|
|
if (current > 0) {
|
|
|
|
if (last && current != 1) current--;
|
|
|
|
last = false;
|
|
|
|
field.setText(list.get(--current));
|
|
|
|
} else field.setText("");
|
|
|
|
field.setCaretPosition(field.getText().length());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void prev(JTextComponent field) {
|
|
|
|
if (field.isEditable()) {
|
|
|
|
LinkedList<String> list = new LinkedList<String>(commands);
|
|
|
|
Collections.reverse(list);
|
|
|
|
if (list.size() > current) {
|
|
|
|
if (!last) current++;
|
|
|
|
last = true;
|
|
|
|
field.setText(list.get(current++));
|
|
|
|
field.setCaretPosition(field.getText().length());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-01-09 20:37:57 +01:00
|
|
|
}
|
|
|
|
private class SmartScroller implements AdjustmentListener {
|
|
|
|
public final static int HORIZONTAL = 0;
|
|
|
|
public final static int VERTICAL = 1;
|
|
|
|
|
|
|
|
public final static int START = 0;
|
|
|
|
public final static int END = 1;
|
|
|
|
|
|
|
|
private int viewportPosition;
|
|
|
|
|
|
|
|
private JScrollBar scrollBar;
|
|
|
|
private boolean adjustScrollBar = true;
|
|
|
|
|
|
|
|
private int previousValue = -1;
|
|
|
|
private int previousMaximum = -1;
|
|
|
|
|
|
|
|
public SmartScroller(JScrollPane scrollPane)
|
|
|
|
{
|
|
|
|
this(scrollPane, VERTICAL, END);
|
|
|
|
}
|
|
|
|
|
|
|
|
public SmartScroller(JScrollPane scrollPane, int viewportPosition)
|
|
|
|
{
|
|
|
|
this(scrollPane, VERTICAL, viewportPosition);
|
|
|
|
}
|
|
|
|
|
|
|
|
public SmartScroller(JScrollPane scrollPane, int scrollDirection, int viewportPosition)
|
|
|
|
{
|
|
|
|
if (scrollDirection != HORIZONTAL
|
|
|
|
&& scrollDirection != VERTICAL)
|
2017-01-11 04:23:29 +01:00
|
|
|
throw new IllegalArgumentException("invalid vScroll direction specified");
|
2017-01-09 20:37:57 +01:00
|
|
|
|
|
|
|
if (viewportPosition != START
|
|
|
|
&& viewportPosition != END)
|
|
|
|
throw new IllegalArgumentException("invalid viewport position specified");
|
|
|
|
|
|
|
|
this.viewportPosition = viewportPosition;
|
|
|
|
|
|
|
|
if (scrollDirection == HORIZONTAL)
|
|
|
|
scrollBar = scrollPane.getHorizontalScrollBar();
|
|
|
|
else
|
|
|
|
scrollBar = scrollPane.getVerticalScrollBar();
|
|
|
|
|
|
|
|
scrollBar.addAdjustmentListener( this );
|
|
|
|
|
|
|
|
// Turn off automatic scrolling for text components
|
|
|
|
|
|
|
|
Component view = scrollPane.getViewport().getView();
|
|
|
|
|
|
|
|
if (view instanceof JTextComponent)
|
|
|
|
{
|
|
|
|
JTextComponent textComponent = (JTextComponent)view;
|
|
|
|
DefaultCaret caret = (DefaultCaret)textComponent.getCaret();
|
|
|
|
caret.setUpdatePolicy(DefaultCaret.NEVER_UPDATE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void adjustmentValueChanged(final AdjustmentEvent e)
|
|
|
|
{
|
|
|
|
SwingUtilities.invokeLater(new Runnable()
|
|
|
|
{
|
|
|
|
public void run()
|
|
|
|
{
|
|
|
|
checkScrollBar(e);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Analyze every adjustment event to determine when the viewport
|
|
|
|
* needs to be repositioned.
|
|
|
|
*/
|
|
|
|
private void checkScrollBar(AdjustmentEvent e)
|
|
|
|
{
|
2017-01-11 04:23:29 +01:00
|
|
|
// The vScroll bar listModel contains information needed to determine
|
2017-01-09 20:37:57 +01:00
|
|
|
// whether the viewport should be repositioned or not.
|
|
|
|
|
|
|
|
JScrollBar scrollBar = (JScrollBar)e.getSource();
|
|
|
|
BoundedRangeModel listModel = scrollBar.getModel();
|
|
|
|
int value = listModel.getValue();
|
|
|
|
int extent = listModel.getExtent();
|
|
|
|
int maximum = listModel.getMaximum();
|
|
|
|
|
|
|
|
boolean valueChanged = previousValue != value;
|
|
|
|
boolean maximumChanged = previousMaximum != maximum;
|
|
|
|
|
|
|
|
// Check if the user has manually repositioned the scrollbar
|
|
|
|
|
|
|
|
if (valueChanged && !maximumChanged)
|
|
|
|
{
|
|
|
|
if (viewportPosition == START)
|
|
|
|
adjustScrollBar = value != 0;
|
|
|
|
else
|
|
|
|
adjustScrollBar = value + extent >= maximum;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Reset the "value" so we can reposition the viewport and
|
2017-01-11 04:23:29 +01:00
|
|
|
// distinguish between a user vScroll and a program vScroll.
|
|
|
|
// (ie. valueChanged will be false on a program vScroll)
|
2017-01-09 20:37:57 +01:00
|
|
|
|
|
|
|
if (adjustScrollBar && viewportPosition == END)
|
|
|
|
{
|
|
|
|
// Scroll the viewport to the end.
|
|
|
|
scrollBar.removeAdjustmentListener( this );
|
|
|
|
value = maximum - extent;
|
|
|
|
scrollBar.setValue( value );
|
|
|
|
scrollBar.addAdjustmentListener( this );
|
|
|
|
}
|
|
|
|
|
|
|
|
if (adjustScrollBar && viewportPosition == START)
|
|
|
|
{
|
|
|
|
// Keep the viewport at the same relative viewportPosition
|
|
|
|
scrollBar.removeAdjustmentListener( this );
|
|
|
|
value = value + maximum - previousMaximum;
|
|
|
|
scrollBar.setValue( value );
|
|
|
|
scrollBar.addAdjustmentListener( this );
|
|
|
|
}
|
|
|
|
|
|
|
|
previousValue = value;
|
|
|
|
previousMaximum = maximum;
|
|
|
|
}
|
|
|
|
}
|
2017-01-12 21:58:31 +01:00
|
|
|
private class ButtonBorder implements Border {
|
|
|
|
private int radius;
|
|
|
|
private Color color;
|
|
|
|
|
|
|
|
public ButtonBorder(int red, int green, int blue, int radius) {
|
|
|
|
this.color = new Color(red, green, blue);
|
|
|
|
this.radius = radius;
|
|
|
|
}
|
|
|
|
|
|
|
|
public Insets getBorderInsets(Component c) {
|
|
|
|
return new Insets(this.radius+1, this.radius+1, this.radius+2, this.radius);
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean isBorderOpaque() {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
|
|
|
|
g.setColor(color);
|
|
|
|
g.drawRoundRect(x, y, width-1, height-1, radius, radius);
|
|
|
|
}
|
|
|
|
}
|
2017-01-09 20:37:57 +01:00
|
|
|
}
|