package me.escapeNT.pail;
import com.google.api.translate.Language;
import com.google.api.translate.Translate;
import java.awt.Color;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.BufferedReader;
import java.io.StringReader;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.ImageIcon;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollBar;
import javax.swing.LookAndFeel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UIManager.LookAndFeelInfo;
import me.escapeNT.pail.GUIComponents.AboutView;
import me.escapeNT.pail.GUIComponents.MainWindow;
import me.escapeNT.pail.GUIComponents.SettingsPanel;
import me.escapeNT.pail.Util.ScrollableTextArea;
import me.escapeNT.pail.config.General;
import me.escapeNT.pail.Util.ServerReadyListener;
import me.escapeNT.pail.Util.Util;
import me.escapeNT.pail.Util.Waypoint;
import me.escapeNT.pail.config.PanelConfig;
import me.escapeNT.pail.config.WaypointConfig;
import me.escapeNT.pail.scheduler.Scheduler;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.entity.Player;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin;
/**
* Independent, comprehensive, and extensible GUI for Bukkit.
* @author escapeNT
*/
public final class Pail extends JavaPlugin {
public final Image PAIL_ICON = Toolkit.getDefaultToolkit().createImage(getClass().getResource("GUIComponents/images/pailicon.png"));
public static String PLUGIN_NAME;
public static String PLUGIN_THREAD;
public static String PLUGIN_VERSION;
public static final ServerReadyListener handler = new ServerReadyListener();
private final WindowCloseListener windowListener = new WindowCloseListener();
private MainWindow main;
public Pail() {
Util.setPlugin(this);
Bukkit.getServer().getLogger().addHandler(handler);
for (Handler h : Bukkit.getServer().getLogger().getHandlers()) {
if (h instanceof PailLogHandler) { // Don't add another handler
return;
}
}
PailLogHandler mainHandler = new PailLogHandler();
mainHandler.setLevel(Level.ALL);
Bukkit.getServer().getLogger().addHandler(mainHandler);
}
public void onEnable() {
// Setup variables
PLUGIN_NAME = getDescription().getName();
PLUGIN_THREAD = getDescription().getWebsite();
PLUGIN_VERSION = getDescription().getVersion();
Translate.setHttpReferrer(PLUGIN_THREAD);
if (main == null) {
main = new MainWindow();
}
General.load();
Scheduler.loadTasks();
try {
if(System.getProperty("os.name").contains("Mac")) {
Class application = Class.forName("com.apple.eawt.Application");
Object app = application.getMethod("getApplication", (Class<?>[]) null).invoke(null, (Object[]) null);
app.getClass().getMethod("setDockIconImage", Image.class).invoke(app, PAIL_ICON);
Object al = Proxy.newProxyInstance(Class.forName("com.apple.eawt.AboutHandler").getClassLoader(),
new Class[] { Class.forName("com.apple.eawt.AboutHandler") },
new AboutListener());
app.getClass().getMethod("setAboutHandler", Class.forName("com.apple.eawt.AboutHandler")).invoke(app, al);
System.setProperty("com.apple.mrj.application.apple.menu.about.name", "Pail");
System.setProperty("apple.laf.useScreenMenuBar", "true");
}
} catch(Throwable e) {}
setupLookAndFeels();
Thread t = new Thread(new InitMain(), "Pail");
t.start();
PluginManager pm = this.getServer().getPluginManager();
pm.registerEvents(new PailPlayerListener(), this);
pm.registerEvents(new PailServerListener(), this);
}
public void onDisable() {
if(getMainWindow() != null) {
getMainWindow().getTabPane().removeAll();
getMainWindow().dispose();
}
WaypointConfig.save();
PanelConfig.save();
Scheduler.saveTasks();
for(LookAndFeelInfo laf : UIManager.getInstalledLookAndFeels()) {
if(laf.getName().equals(((SettingsPanel)this.getInterfaceComponent("Settings")).getThemes().getSelectedItem())) {
General.setLookAndFeel(laf.getClassName());
}
}
General.save();
getLogger().info(PLUGIN_NAME + " " + PLUGIN_VERSION + " Disabled");
}
public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args) {
if(cmd.getName().equalsIgnoreCase("Pail") && args.length == 0 && sender instanceof ConsoleCommandSender) {
getMainWindow().setVisible(true);
getMainWindow().requestFocus();
}
return true;
}
private void setupLookAndFeels() {
HashMap<String, Boolean> installQueue = new HashMap<String, Boolean>();
installQueue.put("com.jtattoo.plaf.acryl.AcrylLookAndFeel", Boolean.TRUE);
installQueue.put("com.jtattoo.plaf.hifi.HiFiLookAndFeel", Boolean.TRUE);
installQueue.put("com.jtattoo.plaf.graphite.GraphiteLookAndFeel", Boolean.TRUE);
installQueue.put("com.jtattoo.plaf.aluminium.AluminiumLookAndFeel", Boolean.TRUE);
installQueue.put("com.jtattoo.plaf.aero.AeroLookAndFeel", Boolean.TRUE);
installQueue.put("com.jtattoo.plaf.fast.FastLookAndFeel", Boolean.TRUE);
for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if (installQueue.keySet().contains(info.getClassName())) {
installQueue.put(info.getClassName(), Boolean.FALSE);
}
}
for (String n : installQueue.keySet()) {
if (installQueue.get(n)) {
try {
UIManager.installLookAndFeel(((LookAndFeel) Class.forName(n).newInstance()).getName(), n);
} catch (Exception ex) {
Logger.getLogger(Pail.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
try {
LookAndFeel laf = (LookAndFeel) Class.forName(General.getLookAndFeel()).newInstance();
UIManager.setLookAndFeel(laf);
UIManager.getLookAndFeelDefaults().put("ClassLoader", getClass().getClassLoader());
} catch (Exception ex) {
Logger.getLogger(Pail.class.getName()).log(Level.SEVERE, null, ex);
}
}
/**
* Saves the current plugin state to file.
*/
public void saveState() {
if(main.isVisible()) {
new PailPersistance().save(getMainWindow().getLocationOnScreen(),
Util.getServerControls().getServerConsolePanel().getConsoleOutput().getText());
}
}
/**
* Attempts to load a previous state from file (if it exists).
*/
protected void loadState() {
if(!PailPersistance.file.exists()) {
return;
}
getLogger().info("Retrieving state...");
final PailPersistance prev = new PailPersistance().load();
getMainWindow().setLocation(prev.getWindowLocation());
final ScrollableTextArea output = Util.getServerControls().getServerConsolePanel().getConsoleOutput();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
BufferedReader reader = new BufferedReader(new StringReader(prev.getConsoleText()));
String str;
try {
while((str = reader.readLine()) != null) {
try {
if(str.length() > 0) {
String[] s = str.split(" ");
output.append(Color.GRAY, true, s[0]);
output.append(Color.GRAY, true, " " + s[1]);
Color color = Color.BLACK;
Level lv = Level.parse(s[2].substring(1, s[2].length() - 1));
if(lv == Level.INFO) {
color = Color.BLUE;
} else if(lv == Level.WARNING) {
color = Color.ORANGE;
} else if(lv == Level.SEVERE) {
color = Color.RED;
} else if(lv == Level.CONFIG) {
color = Color.GREEN;
}
output.append(color, " [" + lv.toString() + "] ");
if(UIManager.getLookAndFeel().getName().equals("HiFi")) {
color = Color.WHITE;
} else {
color = Color.BLACK;
}
StringBuilder sb = new StringBuilder();
for(int i = 3; i < s.length; i++) {
if((s[i].startsWith("[") && s[i].contains("]"))
|| (s[i].startsWith("<") && s[i].contains(">"))) {
output.append(color, sb.toString());
sb = new StringBuilder();
output.append(color, true, s[i] + " ");
} else {
sb.append(s[i]);
sb.append(" ");
}
}
output.append(color, sb.toString() + "\n");
}
} catch(IllegalArgumentException ex) {
output.append(Color.BLACK, str);
} catch (IndexOutOfBoundsException e) {
output.append(Color.BLACK, str);
}
}
} catch (Exception e) {
getLogger().severe(e.toString());
}
JScrollBar vertical = Util.getServerControls().getServerConsolePanel().getConsoleOutput().getScrollerPanel().getVerticalScrollBar();
vertical.setValue(vertical.getMaximum());
}
});
}
/**
* Returns the main window of this instance.
* @return the main
*/
public MainWindow getMainWindow() {
return main;
}
private class WindowCloseListener implements WindowListener {
public void windowClosing(WindowEvent e) {
int confirm = JOptionPane.showConfirmDialog(getMainWindow(), Util.translate("Are you sure you want to close the Pail window?"),
Util.translate("Confirm Close"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE);
if(confirm == JOptionPane.OK_OPTION) {
getMainWindow().setVisible(false);
}
}
public void windowOpened(WindowEvent e) {}
public void windowClosed(WindowEvent e) {}
public void windowIconified(WindowEvent e) {}
public void windowDeiconified(WindowEvent e) {}
public void windowActivated(WindowEvent e) {}
public void windowDeactivated(WindowEvent e) {}
}
public class InitMain implements Runnable {
public void run() {
Util.setServerControls(getMainWindow().getServerControls());
for(Player p : getServer().getOnlinePlayers()) {
Util.getServerControls().addPlayer(p.getName());
}
loadState();
}
}
private class AboutListener implements InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
new AboutView().setVisible(true);
return null;
}
}
// Public API ------------------------------------------------------------
/**
* Loads the provided JPanel into the user interface under the given title.
* If the title is null, it will be converted to the empty String.
* @param panel The JPanel to load.
* @param title The title of this panel.
* @throws NullPointerException if the specified JPanel is null.
* @throws IllegalArgumentException if the title is already taken.
*/
public void loadInterfaceComponent(String title, JPanel panel) {
if(panel == null) {
throw new NullPointerException("Attempt to pass null panel to be loaded.");
}
else if(Util.getInterfaceComponents().containsKey(title)) {
throw new IllegalArgumentException("That title is taken!");
}
else {
if(title == null) {
title = "";
}
Util.getInterfaceComponents().put(title, panel);
}
}
/**
* Gets the interface component by the specified title, or null if it isn't loaded.
* @param title The title of the component.
* @return The component loaded with the specified title, or null if it doesn't exist.
*/
public JPanel getInterfaceComponent(String title) {
if(Util.getInterfaceComponents().containsKey(title)) {
return Util.getInterfaceComponents().get(title);
}
else {
return null;
}
}
/**
* Sets the activated (visible) status of the specified tab. Note: this will
* refresh the tab layout to reflect changes immediately.
* @param title The title of the panel.
* @param activated True if the tab will be visible.
*/
public void setActivated(String title, boolean activated) {
if(!PanelConfig.getPanelsActivated().containsKey(title)) {
throw new IllegalArgumentException("Panel doen't exist.");
}
PanelConfig.getPanelsActivated().put(title, activated);
PanelConfig.save();
getMainWindow().loadPanels();
}
/**
* Gets the waypoint with the specified name, or null if it doesn't exist.
* @param name The name of the waypoint.
* @return
*/
public Waypoint getWaypoint(String name) {
for(Waypoint w : WaypointConfig.getWaypoints()) {
if(w.getName().equals(name)) {
return w;
}
}
return null;
}
/**
* Add the provided Waypoint to the list.
* @param waypoint The Waypoint to add.
*/
public void addWaypoint(Waypoint waypoint) {
WaypointConfig.getWaypoints().add(waypoint);
WaypointConfig.save();
}
/**
* Removes the waypoint with the given name from the list.
* @param name The name of the Waypoint to remove.
* @return True if a waypoint was indeed removed.
*/
public boolean removeWaypoint(String name) {
for(Waypoint w : WaypointConfig.getWaypoints()) {
if(w.getName().equals(name)) {
WaypointConfig.getWaypoints().remove(w);
WaypointConfig.save();
return true;
}
}
return false;
}
/**
* Gets the currently selected language.
* @return The Language selected.
*/
public Language getLanguage() {
return General.getLang();
}
/**
* Translates the given text to the currently selected language.
* @param text The text to translate.
* @return the translated text, or the original text if English is the
* currently selected language.
*/
public String translate(String text) {
return Util.translate(text);
}
/**
* Gets the 25x25 pixel image icon for the provided Material.
* @param material The material to get the icon for.
* @return The 25x25px ImageIcon of the provided material.
* @throws IllegalArgumentException if the Material is AIR.
*/
public ImageIcon getIcon(Material material) {
if(material == Material.AIR) {
throw new IllegalArgumentException("There is no image for air silly.");
}
return new ImageIcon(getClass().getResource("GUIComponents/images/" + material.toString() + ".png"));
}
public WindowListener getWindowListener() {
return windowListener;
}
}