/** * Colloid project * * Combat log analyzer. * * copyright: (c) 2013 by Darek <netmik12 [AT] gmail [DOT] com> * license: BSD, see LICENSE for more details */ package colloid; import java.awt.GraphicsEnvironment; import java.awt.event.MouseWheelEvent; import java.awt.event.MouseWheelListener; import java.awt.event.WindowListener; import java.net.URL; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.Iterator; import java.util.ResourceBundle; import javax.swing.JFrame; import javax.swing.SwingUtilities; import colloid.App.AppResource; import colloid.http.Peer; import colloid.http.User; import colloid.http.User.UnloggedUserError; import colloid.model.control.DamageFightTree; import colloid.model.control.HealFightTree; import colloid.model.event.Actor; import colloid.model.event.Combat; import colloid.model.event.CombatEvent; import colloid.model.event.Fight; import colloid.model.event.Util; import javafx.application.Platform; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.embed.swing.JFXPanel; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.fxml.FXML; import javafx.fxml.Initializable; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.ListView; import javafx.scene.control.TreeItem; import javafx.scene.control.TreeView; import javafx.scene.layout.AnchorPane; import javafx.stage.WindowEvent; import javafx.scene.input.MouseEvent; import javafx.scene.input.DragEvent; public class PopupTextLogController extends AnchorPane implements Initializable { final RecountApp recountApp = RecountApp.getInstance(); static AppResource resource; ArrayList<Actor> historyLog = new ArrayList<Actor>(); Fight lastFight; JFrame frame; @FXML ListView<String> popupTextLog; @FXML Button moveMe; @FXML Button close; @FXML Button resize; @FXML TreeView<String> treeView; @FXML TreeView<String> combatTreeView; @FXML TreeView<String> settingsTreeView; @FXML TreeView<String> combatDamageTreeView; @FXML TreeView<String> combatHealTreeView; TreeItem<ArrayList<Actor>> rootItem = new TreeItem<ArrayList<Actor>>(); @Override public void initialize(URL url, ResourceBundle bundleResource) { settingsTreeView.setRoot(new TreeItem<String>("Info")); settingsTreeView.getRoot().setExpanded(true); initSettingsTab(settingsTreeView.getRoot().getChildren()); resource = (AppResource) bundleResource; recountApp.onUpdate(new Combat.EventHandler<CombatEvent>() { private ArrayList<Fight> fights; @Override public void handle(CombatEvent event) { popupTextLog.getItems().add(0, event.getLogdata()); fights = recountApp.getFightList(); updateCombatTree(fights); updateDamageTree(fights); updateHealTree(fights); if (!fights.isEmpty()) { lastFight = fights.get(0); } initSettingsTab(settingsTreeView.getRoot().getChildren()); if (Peer.getInstance().isRunning()) { Peer.getInstance().send(event.getLogdata()); } } }); resource.getApp().getStage().setOnCloseRequest(new EventHandler<WindowEvent>() { @Override public void handle(WindowEvent event) { if (frame != null) { frame.dispose(); } resource.getApp().getStage().setOpacity(1f); resource.getApp().showMain(); } }); moveMe.setOnMouseDragged(new EventHandler<MouseEvent>() { @Override public void handle(MouseEvent event) { if (frame == null) { return; } java.awt.Point location = frame.getLocationOnScreen(); location.setLocation(event.getScreenX(), event.getScreenY()); frame.setLocation(location); } }); popupTextLog.setOnDragExited(new EventHandler<DragEvent>(){ @Override public void handle(DragEvent e) { System.out.println(e); } }); resize.setOnMouseDragged(new EventHandler<MouseEvent>() { @Override public void handle(MouseEvent event) { if (frame == null) { return; } java.awt.Dimension size = frame.getSize(); java.awt.Point location = frame.getLocationOnScreen(); double width = event.getScreenX() - location.getX(); double height = event.getScreenY() - location.getY(); if (width > 5 && height > 5) { size.setSize(width, height); } frame.setSize(size); } }); if (!GraphicsEnvironment.isHeadless()) { //resource.getApp().getStage().setOpacity(0.0f); showSwing(); } } private void initAndShowGUI() { frame = new JFrame("Colloid Combat Log"); final JFXPanel fxPanel = new JFXPanel(); frame.add(fxPanel); frame.setAlwaysOnTop(true); frame.setSize(new java.awt.Dimension(312, 265)); frame.setLocation(new java.awt.Point(1280, 550)); frame.setUndecorated(true); frame.setOpacity(0.8f); frame.setVisible(true); frame.addMouseWheelListener(new MouseWheelListener() { @Override public void mouseWheelMoved(MouseWheelEvent e) { } }); frame.addWindowListener(new WindowListener() { @Override public void windowOpened(java.awt.event.WindowEvent e) { } @Override public void windowIconified(java.awt.event.WindowEvent e) { } @Override public void windowDeiconified(java.awt.event.WindowEvent e) { } @Override public void windowDeactivated(java.awt.event.WindowEvent e) { } @Override public void windowClosing(java.awt.event.WindowEvent e) { frame.dispose(); } @Override public void windowClosed(java.awt.event.WindowEvent e) { Platform.runLater(new Runnable() { @Override public void run() { resource.getApp().showMain(); resource.getApp().getStage().setOpacity(1f); } }); } @Override public void windowActivated(java.awt.event.WindowEvent e) { } }); Platform.runLater(new Runnable() { @Override public void run() { initFX(fxPanel); } }); } public void close() { Platform.runLater(new Runnable() { @Override public void run() { resource.getApp().getStage().close(); } }); } private static void initFX(JFXPanel fxPanel) { if (resource.getObject("scene") != null) { fxPanel.setScene((Scene) resource.getObject("scene")); } else { fxPanel.setScene(resource.getApp().getStage().getScene()); } } public void showSwing() { if (SwingUtilities.isEventDispatchThread()) { initAndShowGUI(); } else { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { showSwing(); } }); } } public void closeAction(ActionEvent event) { Platform.runLater(new Runnable() { @Override public void run() { showFxMain(); } }); } private void showFxMain() { if (frame != null) { frame.dispose(); } } private void runRecountApp() throws InvalidCombatlogPath { String combatLogPath = resource.getApp().getProps().getProperty("combatLogPath"); if (combatLogPath == null) { throw new InvalidCombatlogPath(); } if (!recountApp.isRunning()) { recountApp.run(); } } private TreeItem<String> rootTreeView(ArrayList<Fight> fights) { TreeItem<String> root = new TreeItem<String>("Combat Fights"); root.setExpanded(true); Iterator<Fight> iter = fights.iterator(); int i = 0; while (iter.hasNext()) { TreeItem<String> item = createFightTree(iter.next()); if (i == 0) { item.setExpanded(true); } root.getChildren().add(item); i++; } return root; } private TreeItem<String> createFightTree(Fight fight) { TreeItem<String> item = new TreeItem<String>(fight.info()); ArrayList<Actor> fightActors = new ArrayList<Actor>(fight.getActors()); Collections.sort(fightActors, fight.new ActorDamageDoneComparator()); Iterator<Actor> iterActor = fightActors.iterator(); while(iterActor.hasNext()) { Actor actor = iterActor.next(); String dps = ""; String hps = ""; Date endTime = fight.getFinish(); if (endTime == null) { endTime = new Date(); } long duration = endTime.getTime() - fight.getStart().getTime(); if (duration > 100) { dps = Util.valuePerSecond(actor.getDamageDone(fight), duration); hps = Util.valuePerSecond(actor.getHealDone(fight), duration); item.getChildren().add(new TreeItem<String>(actor.info(fight, dps, hps))); } } return item; } private void updateCombatTree(ArrayList<Fight> fights) { if (fights.isEmpty()) { return; } if (combatTreeView.getRoot() == null) { combatTreeView.setRoot(rootTreeView(fights)); return; } ObservableList<TreeItem<String>> children = combatTreeView.getRoot().getChildren(); Fight fight = fights.get(0); children.get(0).setExpanded(false); if (fight.equals(lastFight)) { children.set(0, createFightTree(fight)); } else { children.add(0, createFightTree(fight)); } //lastFight = fight; children.get(0).setExpanded(true); } private void updateDamageTree(ArrayList<Fight> fights) { if (fights.isEmpty()) { return; } if (combatDamageTreeView.getRoot() == null) { combatDamageTreeView.setRoot(rootTreeView(fights)); return; } ObservableList<TreeItem<String>> children = combatDamageTreeView.getRoot().getChildren(); Fight fight = fights.get(0); children.get(0).setExpanded(false); DamageFightTree treeItem = new DamageFightTree(fight); if (fight.equals(lastFight)) { children.set(0, treeItem.getItem()); } else { children.add(0, treeItem.getItem()); } //lastFight = fight; children.get(0).setExpanded(true); } private void updateHealTree(ArrayList<Fight> fights) { if (fights.isEmpty()) { return; } if (combatHealTreeView.getRoot() == null) { combatHealTreeView.setRoot(rootTreeView(fights)); return; } ObservableList<TreeItem<String>> children = combatHealTreeView.getRoot().getChildren(); Fight fight = fights.get(0); children.get(0).setExpanded(false); HealFightTree treeItem = new HealFightTree(fight); if (fight.equals(lastFight)) { children.set(0, treeItem.getItem()); } else { children.add(0, treeItem.getItem()); } children.get(0).setExpanded(true); } private void initSettingsTab(ObservableList<TreeItem<String>> children) { if (children.size() < 6) { for (int i =0; i < 6; i++) { children.add(new TreeItem<String>("")); } } children.set(0, new TreeItem<String>(recountApp.sysInfo.allocatedMemInfo())); children.set(1, new TreeItem<String>(recountApp.sysInfo.maxMemInfo())); children.set(2, new TreeItem<String>(recountApp.sysInfo.freeMemInfo())); children.set(3, new TreeItem<String>(recountApp.sysInfo.totalMemInfo())); children.set(4, new TreeItem<String>(recountApp.sysInfo.osInfo())); try { children.set(5, new TreeItem<String>(String.format("Peer owner: @me=: %s", User.getInstance().me().getName()))); } catch (UnloggedUserError e) { if (!Peer.getInstance().isRunning()) { children.set(5, new TreeItem<String>(String.format("Peer is disabled."))); } } } }