package nars.gui.output;
import automenta.vivisect.Video;
import automenta.vivisect.swing.dock.DockingContent;
import automenta.vivisect.swing.dock.DockingRegionRoot;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.HierarchyEvent;
import java.awt.event.HierarchyListener;
import java.util.HashMap;
import java.util.Map;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JMenuBar;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.SwingUtilities;
import nars.NAR;
import nars.entity.Task;
import nars.gui.NARControls;
/**
* TODO queue outputs in non-displayed SwingLogPanel's into ArrayDeque without involving
* any display methods
*
* @author me
*/
public class MultiOutputPanel extends JPanel implements HierarchyListener {
DockingRegionRoot dock = new DockingRegionRoot();
final long activityDecayPeriodNS = 100 * 1000 * 1000; //100ms
public Map<Object, MultiModePanel> categories = new HashMap();
private final MultiModePanel rootTaskPanel;
private final NAR nar;
private final JPanel side;
private final DefaultListModel categoriesListModel;
private final JCategoryList categoriesList;
public MultiOutputPanel(NARControls c) {
super(new BorderLayout());
JMenuBar menu = new JMenuBar();
add(menu, BorderLayout.NORTH);
JSplitPane innerPanel = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
this.nar = c.nar;
categoriesListModel = new DefaultListModel();
categoriesList = new JCategoryList(categoriesListModel);
categoriesList.setBackground(Color.BLACK);
side = new JPanel(new BorderLayout());
side.add(categoriesList, BorderLayout.CENTER);
add(innerPanel, BorderLayout.CENTER);
innerPanel.add(new JScrollPane(side), 0);
innerPanel.add(dock, 1);
innerPanel.setDividerLocation(0.25f);
rootTaskPanel = getModePanel("Root");//new MultiModePanel(nar, "Root");
showCategory("Root");
}
protected void onShowing(boolean showing) {
// if (showing) {
// nar.addOutput(this);
// }
// else {
// nar.removeOutput(this);
// }
}
//TODO use Output instance
public void output(Class channel, Object o) {
Object category;
if (o instanceof Task) {
Task t = (Task) o;
category = t.getRootTask();
} else {
category = null;
}
MultiModePanel p = getModePanel(category);
if (p!=null)
p.output(channel, o);
decayActivities();
}
public MultiModePanel getModePanel(Object category) {
if (category == null) {
return categories.get("Root");
} else {
MultiModePanel p = categories.get(category);
if (p == null) {
p = new MultiModePanel(nar, category);
JButton jc = p.newStatusButton();
jc.addActionListener(new ActionListener() {
@Override public void actionPerformed(ActionEvent e) {
showCategory(category);
}
});
categories.put(category, p);
categoriesListModel.addElement(jc);
}
return p;
}
}
public JPanel showCategory(Object category) {
String title = category.toString();
MultiModePanel p = getModePanel(category);
JMenuBar headerMenu = new JMenuBar();
headerMenu.setOpaque(false);
headerMenu.setBorder(null);
headerMenu.add(p.newMenu());
//http://stackoverflow.com/questions/4702891/toggling-text-wrap-in-a-jtextpane
JPanel ioTextWrap = new JPanel(new BorderLayout());
ioTextWrap.add(p);
JPanel x = new JPanel(new BorderLayout());
x.add(new JScrollPane(ioTextWrap), BorderLayout.CENTER);
x.validate();
DockingContent cont = new DockingContent("view" + category, title, x);
dock.addRootContent(cont);
cont.getTab().setLabel(p.getLabel());
cont.getTab().setFont(Video.fontMono(15));
cont.getTab().setMenuButton(headerMenu);
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
revalidate();
repaint();
}
});
return x;
}
public void hideCategory(JPanel p) {
dock.getDockingRoot().remove(p);
validate();
repaint();
}
@Override
public void addNotify() {
super.addNotify();
addHierarchyListener(this);
}
@Override
public void removeNotify() {
removeHierarchyListener(this);
super.removeNotify();
}
@Override
public void hierarchyChanged(HierarchyEvent e) {
if ((e.getChangeFlags() & HierarchyEvent.SHOWING_CHANGED) != 0) {
boolean showing = isShowing();
onShowing(showing);
}
}
long lastDecayed = 0;
protected void decayActivities() {
long now = System.nanoTime();
if (now - lastDecayed > activityDecayPeriodNS) {
for (MultiModePanel c : categories.values()) {
c.decayActvity();
}
lastDecayed = now;
categoriesList.repaint();
}
}
}