package demo.view;

import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JToolBar;
import javax.swing.SwingUtilities;

import y.layout.CopiedLayoutGraph;
import y.layout.GraphLayout;
import y.layout.organic.OrganicLayouter;
import y.view.LayoutMorpher;

/**
 * Demo that shows how a layout algorithm can be invoked in a separate thread to 
 * run in the background.
 */
public class ThreadedLayoutDemo extends ViewActionDemo {
  public ThreadedLayoutDemo() {}

  public JToolBar createToolBar() {
    JToolBar bar = super.createToolBar();
    bar.add(new ThreadedLayoutAction());
    return bar;
  }
  
  class ThreadedLayoutAction extends AbstractAction {
    boolean layoutMorphingEnabled = true;

    public ThreadedLayoutAction() {
      super("Threaded Layout");
    }

    public void actionPerformed(ActionEvent ev) {
      final OrganicLayouter layouter = new OrganicLayouter();
      // Copy graph in AWT thread.
      final CopiedLayoutGraph cGraph = new CopiedLayoutGraph(view.getGraph2D());

      // Calculate a layout on the copy of the original graph within a separate 
      // thread.
      final Thread thread = new Thread() {
        public void run() {
          layouter.doLayout(cGraph);

          // Assign the calculated layout to the original graph within the AWT 
          // thread.
          SwingUtilities.invokeLater(new Runnable() {
            public void run() {
              if (layoutMorphingEnabled) {
                // Perform an animated morphing on layout result.
                GraphLayout gl = cGraph.getLayoutForOriginalGraph();
                new LayoutMorpher(view, gl).execute();
              }
              else {
                // Assign the layout directly without morphing and display the 
                // result.
                cGraph.commitLayoutToOriginalGraph();
                view.fitContent();
                view.updateView();
              }
            }
          });
        }
      };
      // Assign minimum priority to the layout thread so that the GUI remains 
      // responsive.
      thread.setPriority(Thread.MIN_PRIORITY);
      // Start the layout thread.
      thread.start();
    }
  }

  public static void main(String[] args) {
    ThreadedLayoutDemo demo = new ThreadedLayoutDemo();
    demo.start(demo.getClass().getName());
  }
}
