package org.andork.redux.ui; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Container; import java.awt.event.HierarchyEvent; import java.awt.event.HierarchyListener; import org.andork.redux.Action; import org.andork.redux.Dispatcher; import org.andork.redux.Store; import org.andork.swing.FromEDT; public abstract class Connector<S> extends Container implements Dispatcher { private static final long serialVersionUID = 3101848419113180498L; private Store<S> store; private Runnable unsubscribe; public Connector(Component comp) { setLayout(new BorderLayout()); if (comp != null) { add(comp, BorderLayout.CENTER); } addHierarchyListener(new HierarchyListener() { @Override public void hierarchyChanged(HierarchyEvent e) { if ((e.getChangeFlags() & HierarchyEvent.PARENT_CHANGED) != 0) { onParentChanged(); } } }); } @Override public Object dispatch(Action action) { return FromEDT.fromEDT(() -> { if (store != null) { return store.dispatch(action); } throw new IllegalStateException("not connected to a store"); }); } protected void onParentChanged() { Store<S> newStore = Provider.<S> getStore(this); if (newStore != store) { if (unsubscribe != null) { unsubscribe.run(); unsubscribe = null; } store = newStore; if (store != null) { unsubscribe = store.subscribe(() -> { update(store.getState()); }); update(store.getState()); } } } public abstract void update(S state); }