001 // GraphLab Project: http://graphlab.sharif.edu 002 // Copyright (C) 2008 Mathematical Science Department of Sharif University of Technology 003 // Distributed under the terms of the GNU General Public License (GPL): http://www.gnu.org/licenses/ 004 package graphlab.plugins.algorithmanimator.core; 005 006 import graphlab.graph.atributeset.GraphAttrSet; 007 import graphlab.graph.graph.GraphModel; 008 import graphlab.library.algorithms.AutomatedAlgorithm; 009 import graphlab.library.event.AlgorithmStep; 010 import graphlab.library.event.Event; 011 import graphlab.library.event.EventDispatcher; 012 import graphlab.platform.core.BlackBoard; 013 import graphlab.plugins.algorithmanimator.AnimatorGUI; 014 import graphlab.plugins.algorithmanimator.core.atoms.*; 015 016 import javax.swing.*; 017 import java.awt.event.ActionEvent; 018 import java.awt.event.ActionListener; 019 import java.util.Vector; 020 021 /** 022 * Actually the class which animates the algorithms! 023 * 024 * @author Azin Azadi 025 */ 026 public class AlgorithmAnimator implements EventDispatcher, ActionListener { 027 static Vector<AtomAnimator> animators = new Vector<AtomAnimator>(); 028 BlackBoard blackboard; 029 private boolean paused = true; 030 private JFrame f; 031 /** 032 * running algorithm just one step 033 */ 034 private boolean oneStep; 035 036 public AlgorithmAnimator(BlackBoard blackboard) { 037 this.blackboard = blackboard; 038 registerAtomAnimation(new VertexSelect()); 039 registerAtomAnimation(new GraphSelect()); 040 registerAtomAnimation(new PrePostWork()); 041 registerAtomAnimation(new NewGraph()); 042 registerAtomAnimation(new DelayEventHandler()); 043 registerAtomAnimation(new ShowMessage()); 044 } 045 046 /** 047 * registers a new kind of AtomAnimator 048 * 049 * @param a 050 */ 051 static public void registerAtomAnimation(AtomAnimator a) { 052 animators.add(a); 053 } 054 055 public Event animateEvent(Event ae) { 056 for (AtomAnimator _ : animators) 057 if (_.isAnimatable(ae)) { 058 return _.animate(ae, blackboard); 059 } 060 return ae; 061 } 062 063 /** 064 * The main method, Animates an algorithm 065 * 066 * @param aa 067 */ 068 public void animateAlgorithm(final AutomatedAlgorithm aa) { 069 new Thread() { 070 public void run() { 071 GraphModel g = blackboard.getData(GraphAttrSet.name); 072 boolean b = g.isShowChangesOnView(); 073 g.setShowChangesOnView(true); 074 aa.acceptEventDispatcher(AlgorithmAnimator.this); 075 aa.doAlgorithm(); 076 g.setShowChangesOnView(b); 077 } 078 }.start(); 079 080 } 081 082 /** 083 * dispatchs events that recieved from the algorithm 084 * 085 * @param event 086 * @return 087 */ 088 public Event dispatchEvent(Event event) { 089 try { 090 091 if (event instanceof AlgorithmStep) { 092 if (!oneStep) { 093 double s = 100.0 - alggui.speedSlider.getValue(); 094 Thread.sleep((long) (10 * s)); 095 } 096 if (oneStep) { 097 paused = true; 098 } 099 } 100 } catch (InterruptedException e) { 101 System.err.println("Thread sleep has error."); 102 } 103 Event event1 = animateEvent(event); 104 105 JTextArea txt = alggui.algorithmOutputTextArea; 106 int cursorDot = txt.getCaret().getDot(); 107 int cursorMark = txt.getCaret().getMark(); 108 boolean isCursorInEnd = cursorDot == txt.getText().length(); 109 if (event1 != null && event1.getMessage() != null && event1.getMessage() != "") { 110 alggui.algorithmOutputTextArea.setText(alggui.algorithmOutputTextArea.getText() + "\n" + event1.getMessage()); 111 if (isCursorInEnd) 112 txt.getCaret().setDot(txt.getText().length()); 113 else { 114 txt.getCaret().setDot(cursorMark); 115 txt.getCaret().moveDot(cursorDot); 116 } 117 txt.getCaret().setVisible(true); 118 119 } 120 121 if (oneStep && event instanceof AlgorithmStep) { 122 alggui.playOneStepButton.setEnabled(true); 123 oneStep = false; 124 } 125 while (paused) 126 try { 127 Thread.sleep(100); 128 } catch (InterruptedException e) { 129 e.printStackTrace(); 130 } 131 132 return event1; 133 } 134 135 /** 136 * handles gui control events 137 * 138 * @param e 139 */ 140 public void actionPerformed(ActionEvent e) { 141 oneStep = false; 142 alggui.pauseButton.setEnabled(true); 143 alggui.playButton.setEnabled(true); 144 alggui.playOneStepButton.setEnabled(true); 145 146 if (e.getActionCommand().contains("Pause")) { 147 alggui.pauseButton.setEnabled(false); 148 paused = true; 149 } else if (e.getActionCommand().equals("Play")) { 150 alggui.playButton.setEnabled(false); 151 paused = false; 152 } else if (e.getActionCommand().contains("One Step")) { 153 alggui.playOneStepButton.setEnabled(false); 154 oneStep = true; 155 paused = false; 156 } else System.out.println("Sooti !"); 157 } 158 159 AnimatorGUI alggui; 160 161 /** 162 * creates the GUI control frame 163 * 164 * @param algorithmName 165 */ 166 public void createControlDialog(String algorithmName) { 167 f = new JFrame(); 168 f.setTitle("Algorithm Runner: " + algorithmName); 169 f.setAlwaysOnTop(true); 170 alggui = new AnimatorGUI(this); 171 //moves the carret to the end of text, see dispatch event 172 alggui.algorithmOutputTextArea.getCaret().setDot(alggui.algorithmOutputTextArea.getText().length()); 173 174 f.add(alggui.animatorFrame); 175 f.pack(); 176 f.setVisible(true); 177 // f = new JFrame("Controls"); 178 // f.setLayout(new GridBagLayout()); 179 // addBtn("Pause", new Dimension(75, 25)); 180 // addBtn("Play", new Dimension(75, 25)); 181 // addBtn("Play One Step", new Dimension(95, 25)); 182 // f.setSize(245,70); 183 // f.setAlwaysOnTop(true); 184 // f.setLocation(300,300); 185 // f.setVisible(true); 186 //// System.out.println("frame created"); 187 // try { 188 // Thread.sleep(1000); 189 // } catch (InterruptedException e) { 190 // System.out.println("Error"); 191 // } 192 } 193 194 // private void addBtn(String lbl, Dimension d) { 195 // JButton play = new JButton(lbl); 196 // play.setSize(d); 197 // play.addActionListener(this); 198 // f.add(play); 199 // } 200 201 }