001    /******************************************************************************
002     * Copyright (C) MActor Developers. All rights reserved.                        *
003     * ---------------------------------------------------------------------------*
004     * This file is part of MActor.                                               *
005     *                                                                            *
006     * MActor is free software; you can redistribute it and/or modify             *
007     * it under the terms of the GNU General Public License as published by       *
008     * the Free Software Foundation; either version 2 of the License, or          *
009     * (at your option) any later version.                                        *
010     *                                                                            *
011     * MActor is distributed in the hope that it will be useful,                  *
012     * but WITHOUT ANY WARRANTY; without even the implied warranty of             *
013     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
014     * GNU General Public License for more details.                               *
015     *                                                                            *
016     * You should have received a copy of the GNU General Public License          *
017     * along with MActor; if not, write to the Free Software                      *
018     * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA *
019     ******************************************************************************/
020    package org.mactor.ui.gui.testrunner;
021    
022    import java.awt.BorderLayout;
023    import java.awt.Color;
024    import java.awt.Component;
025    import java.awt.Font;
026    import java.awt.event.ActionEvent;
027    import java.awt.event.ActionListener;
028    import java.util.HashSet;
029    
030    import javax.swing.Icon;
031    import javax.swing.JLabel;
032    import javax.swing.JPanel;
033    import javax.swing.JScrollPane;
034    import javax.swing.JTextArea;
035    import javax.swing.JTree;
036    import javax.swing.Timer;
037    import javax.swing.event.TreeModelListener;
038    import javax.swing.tree.DefaultTreeCellRenderer;
039    import javax.swing.tree.TreeModel;
040    import javax.swing.tree.TreePath;
041    
042    import org.mactor.framework.MactorException;
043    import org.mactor.framework.TestEvent;
044    import org.mactor.ui.gui.GuiUtil;
045    import org.mactor.ui.gui.project.ProjectNodeType;
046    import org.mactor.ui.gui.project.ProjectTreeNode;
047    
048    public class RunningTestTreePanel extends JPanel {
049            JTree tree = new JTree();
050            JTextArea messageText = new JTextArea(10, 50);
051            Timer timer = new Timer(400, new ActionListener() {
052                    public void actionPerformed(ActionEvent e) {
053                            if (runningColor.equals(runningColor1))
054                                    runningColor = runningColor2;
055                            else
056                                    runningColor = runningColor1;
057                            tree.validate();
058                            tree.repaint();
059                    }
060            });
061            public RunningTestTreePanel(ProjectTreeNode node) throws MactorException {
062                    super(new BorderLayout());
063                    tree.setModel(new ProjectModel(node));
064                    tree.setCellRenderer(new ProjectTreeCellRenderer());
065                    expandAll(tree, true);
066                    JScrollPane sp = new JScrollPane(tree);
067                    // sp.setPreferredSize(new Dimension(300, 300));
068                    add(sp, BorderLayout.CENTER);
069                    messageText.setEditable(false);
070                    messageText.setFont(messageText.getFont().deriveFont(Font.ITALIC));
071                    add(messageText, BorderLayout.SOUTH);
072            }
073            public void expandAll(JTree tree, boolean expand) {
074                    ProjectTreeNode root = (ProjectTreeNode) tree.getModel().getRoot();
075                    // Traverse tree from root
076                    expandAll(tree, new TreePath(root), expand);
077            }
078            private void expandAll(JTree tree, TreePath parent, boolean expand) {
079                    // Traverse children
080                    ProjectTreeNode node = (ProjectTreeNode) parent.getLastPathComponent();
081                    if (node.getChildCount() >= 0) {
082                            for (ProjectTreeNode n : node.getChildNodes()) {
083                                    TreePath path = parent.pathByAddingChild(n);
084                                    expandAll(tree, path, expand);
085                            }
086                    }
087                    if (expand) {
088                            tree.expandPath(parent);
089                    } else {
090                            tree.collapsePath(parent);
091                    }
092            }
093            public static class RunningTestModel {
094                    String last = null;
095                    boolean complete = false;
096                    boolean success;
097                    HashSet<String> executed = new HashSet<String>();
098                    String message;
099                    boolean running = false;
100                    public void reset() {
101                            last = null;
102                            complete = false;
103                            executed.clear();
104                    }
105                    public void addEvent(TestEvent event) {
106                            if (event.isStartEventType()) {
107                                    String name = event.getNode().getName();
108                                    executed.add(name);
109                                    last = name;
110                                    running = true;
111                            } else if (event.isTestCompleteEvent()) {
112                                    success = event.isSuccessful();
113                                    complete = true;
114                                    running = false;
115                            }
116                            if (event.getCause() != null)
117                                    message = event.getCause().getMessage();
118                            else
119                                    message = event.getOutputText();
120                    }
121                    public boolean hasBeenExecuted(String nodeName) {
122                            return executed.contains(nodeName);
123                    }
124                    public boolean isComplete() {
125                            return complete;
126                    }
127                    public String getLast() {
128                            return last;
129                    }
130                    public String getMessage() {
131                            return message;
132                    }
133                    public boolean isRunning() {
134                            return running;
135                    }
136                    public boolean isSuccess() {
137                            return success;
138                    }
139            }
140            RunningTestModel rtModel = new RunningTestModel();
141            public void setModel(RunningTestModel rtModel) {
142                    if (rtModel == null)
143                            throw new RuntimeException("RunningTestModel can not be null!");
144                    this.rtModel = rtModel;
145                    if (rtModel.isRunning() && !timer.isRunning())
146                            timer.start();
147                    else if (rtModel.isComplete() && timer.isRunning())
148                            timer.stop();
149                    messageText.setText(rtModel.getMessage());
150                    tree.validate();
151                    tree.repaint();
152            }
153            public class ProjectModel implements TreeModel {
154                    ProjectTreeNode root;// = new
155                    public ProjectModel(ProjectTreeNode root) throws MactorException {
156                            this.root = root;
157                    }
158                    public Object getChild(Object node, int index) {
159                            return ((ProjectTreeNode) node).getChildNode(index);
160                    }
161                    public int getChildCount(Object node) {
162                            return ((ProjectTreeNode) node).getChildCount();
163                    }
164                    public int getIndexOfChild(Object node, Object child) {
165                            return ((ProjectTreeNode) node).getIndexOfChild((ProjectTreeNode) child);
166                    }
167                    public ProjectTreeNode getRoot() {
168                            return root;
169                    }
170                    public boolean isLeaf(Object node) {
171                            return ((ProjectTreeNode) node).getChildCount() == 0;
172                    }
173                    public void valueForPathChanged(TreePath path, Object newValue) {
174                    }
175                    public void addTreeModelListener(TreeModelListener l) {
176                    }
177                    public void removeTreeModelListener(TreeModelListener l) {
178                    }
179            }
180            JLabel ref = new JLabel();
181            Font runningFont = ref.getFont().deriveFont(Font.ITALIC);
182            Font normalFont = ref.getFont();
183            Font doneFont = ref.getFont();
184            Color runningColor1 = Color.WHITE;
185            Color runningColor2 = ref.getForeground();
186            Color runningColor = runningColor1;
187            Color doneColor = Color.GREEN;
188            Color failedColor = Color.RED.darker();
189            Color notDoneColor = ref.getForeground().brighter().brighter().brighter().brighter();
190            class ProjectTreeCellRenderer extends DefaultTreeCellRenderer {
191                    private final Icon INCOMING_ICON = GuiUtil.loadIcon("/incoming_16.PNG");
192                    private final Icon SUBSCR_ICON = GuiUtil.loadIcon("/subscribe_16.PNG");
193                    private final Icon CONDITION_ICON = GuiUtil.loadIcon("/condition_16.PNG");
194                    private final Icon LOOP_ICON = GuiUtil.loadIcon("/loop_16.PNG");
195                    private final Icon ACTION_ICON = GuiUtil.loadIcon("/action_16.PNG");
196                    private final Icon VALUE_EXTRACT_ICON = GuiUtil.loadIcon("/value_extract_16.PNG");
197                    private final Icon OUTGOING_ICON = GuiUtil.loadIcon("/outgoing_16.PNG");
198                    private final Icon OUTGOING_RESP_ICON = GuiUtil.loadIcon("/outgoing_resp_16.PNG");
199                    public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean focus) {
200                            Component com = super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, focus);
201                            ProjectTreeNode node = (ProjectTreeNode) value;
202                            if (node != null) {
203                                    if (ProjectNodeType.T_MESSAGE_PUBLISH.equals(node.getNodeType()))
204                                            setIcon(OUTGOING_ICON);
205                                    else if (ProjectNodeType.T_MESSAGE_RECEIVE.equals(node.getNodeType()))
206                                            setIcon(INCOMING_ICON);
207                                    else if (ProjectNodeType.T_MESSAGE_RESPOND.equals(node.getNodeType()))
208                                            setIcon(OUTGOING_RESP_ICON);
209                                    else if (ProjectNodeType.T_MESSAGE_SUBSCRIBE.equals(node.getNodeType()))
210                                            setIcon(SUBSCR_ICON);
211                                    else if (ProjectNodeType.T_CONDITION.equals(node.getNodeType()))
212                                            setIcon(CONDITION_ICON);
213                                    else if (ProjectNodeType.T_LOOP.equals(node.getNodeType()))
214                                            setIcon(LOOP_ICON);
215                                    else if (ProjectNodeType.T_ACTION.equals(node.getNodeType()))
216                                            setIcon(ACTION_ICON);
217                                    else if (ProjectNodeType.T_VALUE.equals(node.getNodeType()))
218                                            setIcon(VALUE_EXTRACT_ICON);
219                                    if (rtModel.isComplete() && node.getName().equals(rtModel.getLast())) {
220                                            if (rtModel.isSuccess()) {
221                                                    setFont(doneFont);
222                                                    setForeground(doneColor);
223                                            } else {
224                                                    setFont(doneFont);
225                                                    setForeground(failedColor);
226                                            }
227                                    } else if (node.getName().equals(rtModel.getLast())) {
228                                            setFont(runningFont);
229                                            setForeground(runningColor);
230                                    } else if (rtModel.hasBeenExecuted(node.getName())) {
231                                            setFont(doneFont);
232                                            setForeground(doneColor);
233                                    } else {
234                                            setFont(normalFont);
235                                            setForeground(notDoneColor);
236                                    }
237                            }
238                            return com;
239                    }
240            }
241    }