package nbtool.util; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedList; import nbtool.util.Events.EventListener; //public class Boss implements Executor { public class Center { /* * EventListener framework. * */ private static final HashMap<Class<? extends EventListener>, ArrayList<EventListener>> guiListeners = new HashMap<Class<? extends EventListener>, ArrayList<EventListener>>(); private static final HashMap<Class<? extends EventListener>, ArrayList<EventListener>> centerListeners = new HashMap<Class<? extends EventListener>, ArrayList<EventListener>>(); /* * eventClass determines what list the listener is added to, and should match <I> * */ public static <I extends EventListener> void listen(Class<I> eventClass, I listener, boolean guiThread) { assert(eventClass.isInstance(listener)); HashMap<Class<? extends EventListener>, ArrayList<EventListener>> relevant = guiThread ? guiListeners : centerListeners; synchronized(relevant) { if (relevant.containsKey(eventClass)) { relevant.get(eventClass).add(listener); } else { ArrayList<EventListener> listeners = new ArrayList<EventListener>(); listeners.add(listener); relevant.put(eventClass, listeners); } } } /* * Event running framework. */ private static Thread center_thread = null; public static void startCenter() { if (center_thread == null) { center_thread = new Thread(new CenterRunnable()); center_thread.setName("nbtool-Center"); center_thread.setDaemon(true); Debug.info( "Starting Center thread..."); center_thread.start(); } else { Debug.error( "Could not start Center, center_thread != null."); } } private static class CenterRunnable implements Runnable { @Override public void run() { Debug.info( "Center thread active."); try { while(true) { // System.out.println("Center loop..."); ToolEvent head = null; Class<? extends EventListener> eventClass = null; LinkedList<ToolEvent> similar = null; synchronized(events) { if (events.size() == 0) { events.wait(); } assert(events.size() > 0); head = events.pop(); eventClass = head.listenerClass(); if (head.canCombine() && eventClass != null) { similar = new LinkedList<ToolEvent>(); for (ToolEvent e : events) { //if (e.listenerClass().equals(eventClass)) if (eventClass.equals(e.listenerClass())) similar.add(e); } for (ToolEvent s : similar) { events.remove(s); } } } Debug.event( "Center choosing event %s", head.getClass().getName()); assert(head != null); if (similar != null && head.canCombine()) { Debug.event( "Center combining event %s, %d instances", head.getClass().getName(), similar.size()); head.combine(similar); } ArrayList<EventListener> glist = null; ArrayList<EventListener> clist = null; if (eventClass != null) { glist = guiListeners.get(eventClass); clist = centerListeners.get(eventClass); if (glist == null) glist = new ArrayList<EventListener>(); if (clist == null) clist = new ArrayList<EventListener>(); Debug.event( "Center executing event %s with %d cListeners, %d guiListeners.", head.getClass().getName(), clist.size(), glist.size()); } else { Debug.event( "Center executing event %s with null event class.", head.getClass().getName()); } head.execute(glist, clist); //Wow, that sounds macabre. } } catch (InterruptedException e) { e.printStackTrace(); System.exit(1); } } } private static final LinkedList<ToolEvent> events = new LinkedList<ToolEvent>(); public static void addEvent(ToolEvent e) { synchronized(events) { events.add(e); events.notify(); } } public static boolean isCenterThread() { if (center_thread == null) return false; return Thread.currentThread() == center_thread; } public static abstract class ToolEvent { protected abstract boolean canCombine(); protected abstract void combine(LinkedList<ToolEvent> others); protected abstract Class<? extends EventListener> listenerClass(); protected abstract void execute(ArrayList<EventListener> guiList, ArrayList<EventListener> centerList); } public static abstract class EventRunnable extends ToolEvent { @Override protected final boolean canCombine() { return false; } @Override protected final void combine(LinkedList<ToolEvent> others) { assert(false); } @Override protected Class<? extends EventListener> listenerClass() { return null; } @Override protected void execute(ArrayList<EventListener> guiList, ArrayList<EventListener> centerList) { run(); } protected abstract void run(); } /* * tool shutdown handling */ public static interface NBToolShutdownListener { //Guaranteed to be called before user settings are saved, *if* user settings are saved. public void nbtoolShutdownCallback(); } private static final LinkedList<NBToolShutdownListener> shutdownListeners = new LinkedList<>(); public static void listen(NBToolShutdownListener li) { synchronized(shutdownListeners) { shutdownListeners.add(li); } } static { Debug.plain("Center adding preference shutdown hook."); Runtime.getRuntime().addShutdownHook(new Thread(new Runnable(){ @Override public void run() { Debug.dbreak(" <tool saving preferences>"); for (NBToolShutdownListener l : shutdownListeners) { Debug.print("\tinforming %s", l.toString()); l.nbtoolShutdownCallback(); } try { UserSettings.savePreferences(); } catch (IOException e) { e.printStackTrace(); } Debug.print("Center hook done."); } })); } }