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;
021    
022    import java.awt.BorderLayout;
023    import java.awt.CardLayout;
024    import java.awt.Color;
025    import java.awt.Component;
026    import java.awt.Font;
027    import java.awt.Frame;
028    import java.awt.Toolkit;
029    import java.awt.event.ActionEvent;
030    import java.awt.event.ActionListener;
031    import java.io.File;
032    import java.util.LinkedList;
033    
034    import javax.swing.AbstractAction;
035    import javax.swing.BorderFactory;
036    import javax.swing.JButton;
037    import javax.swing.JEditorPane;
038    import javax.swing.JFrame;
039    import javax.swing.JLabel;
040    import javax.swing.JMenuBar;
041    import javax.swing.JOptionPane;
042    import javax.swing.JPanel;
043    import javax.swing.JScrollPane;
044    import javax.swing.JSplitPane;
045    import javax.swing.JTabbedPane;
046    import javax.swing.Timer;
047    
048    import org.dom4j.Element;
049    import org.mactor.brokers.MessageBrokerManager;
050    import org.mactor.framework.MactorException;
051    import org.mactor.framework.spec.ProjectContext;
052    import org.mactor.ui.gui.project.ProjectControlListener;
053    import org.mactor.ui.gui.project.ProjectExplorerPanel;
054    import org.mactor.ui.gui.project.ProjectNodeType;
055    import org.mactor.ui.gui.project.ProjectTreeNode;
056    import org.mactor.ui.gui.project.editors.NodeEditor;
057    import org.mactor.ui.gui.project.editors.NodeEditorConfig;
058    import org.mactor.ui.gui.project.editors.NodeEditorConfigManager;
059    import org.mactor.ui.gui.testrunner.ChannelRuntimePanel;
060    import org.mactor.ui.gui.testrunner.MockBatteryPanel;
061    import org.mactor.ui.gui.testrunner.SingelTestPanel;
062    import org.mactor.ui.gui.testrunner.TestRunPanel;
063    
064    public class MActorGui {
065            JFrame f;
066            TipPanel tipPanel = new TipPanel();
067            NodeEditor editor;
068            JSplitPane projectPane;
069            JEditorPane introPane;
070            JPanel mainPane = new JPanel(new CardLayout());
071            JTabbedPane tabbedPane = new JTabbedPane();
072            JPanel editorContainer = new JPanel(new BorderLayout());
073            JPanel editorPanel = new JPanel(new BorderLayout());
074            TabPanel editorTab = new TabPanel(editorPanel, false);
075            EventLogPanel eventLog = new EventLogPanel();
076            JButton dummyButton = new JButton("");
077            ProjectExplorerPanel pc;
078            JButton reloadButton = new JButton(new AsyncAction("Reload the Project to Activate the Message Broker Modification", false, new AsyncAction.AsyncRunnable() {
079                    public void run() throws MactorException {
080                            pc.getProjectController().reloadProject();
081                    };
082            }));
083            Timer reloadTimer = new Timer(700, new ActionListener() {
084                    public void actionPerformed(ActionEvent e) {
085                            if (reloadButton.getBackground().equals(Color.RED))
086                                    reloadButton.setBackground(dummyButton.getBackground());
087                            else
088                                    reloadButton.setBackground(Color.RED);
089                    }
090            });
091            private void showEditorForNode(ProjectTreeNode newNode, ProjectTreeNode oldNode) {
092                    if (editor != null) {
093                            editor.applyChanges();
094                    }
095                    if (tabbedPane.getTabCount() > 0)
096                            tabbedPane.setSelectedIndex(0);
097                    try {
098                            if (newNode != null && oldNode != newNode) {
099                                    editorTab.setHeader(getPath(newNode));
100                                    NodeEditorConfig editorConfig = NodeEditorConfigManager.getInstance().getNodeEditorConfig(newNode.getNodeType());
101                                    if (oldNode != null && editor != null && editor.isDirty())
102                                            oldNode.save();
103                                    editorContainer.removeAll();
104                                    if (editorConfig != null) {
105                                            tipPanel.onTip(1, editorConfig.getTip());
106                                            editor = editorConfig.createEditor();
107                                            editor.setTipListener(tipPanel);
108                                            editor.setData(newNode);
109                                            editorContainer.add((Component) editor, BorderLayout.WEST);
110                                    } else {
111                                            tipPanel.onTip(1, null);
112                                            editor = null;
113                                    }
114                            }
115                            editorTab.revalidate();
116                            editorTab.repaint();
117                    } catch (MactorException me) {
118                            GuiUtil.showGuiError(f, me);
119                    }
120            }
121            private String getPath(ProjectTreeNode node) {
122                    LinkedList<String> names = new LinkedList<String>();
123                    while (node != null && node.getParentNode() != null) {
124                            names.addFirst(node.getCaption());
125                            node = node.getParentNode();
126                    }
127                    StringBuffer sb = new StringBuffer();
128                    for (String n : names) {
129                            if (sb.length() > 0)
130                                    sb.append(" > ");
131                            sb.append(n);
132                    }
133                    return sb.toString();
134            }
135            ProjectControlListener projectControlListener = new ProjectControlListener() {
136                    public void onProjectLoaded() {
137                            CardLayout cl = (CardLayout) (mainPane.getLayout());
138                            cl.show(mainPane, "PROJECT");
139                            tabbedPane.removeAll();
140                            tabbedPane.addTab("Edit", new JScrollPane(editorTab));
141                            f.setTitle("MActor (" + VersionUtil.getVersion() + ") - " + ProjectContext.getGlobalInstance().getProjectName());
142                            tabbedPane.revalidate();
143                            tabbedPane.repaint();
144                            try {
145                                    if (MessageBrokerManager.isActive())
146                                            MessageBrokerManager.getInstance().terminate();
147                            } catch (MactorException me) {
148                                    me.printStackTrace();
149                            }
150                            reloadButton.setVisible(false);
151                            reloadTimer.stop();
152                    };
153                    public void onProjectTreeSelectionChanged(ProjectTreeNode selectedNode, ProjectTreeNode previousSelectedNode) {
154                            showEditorForNode(selectedNode, previousSelectedNode);
155                    };
156                    public void onRequestGuiAction(ProjectTreeNode node, String action) {
157                            if ("run".equals(action) && node != null)
158                                    openInNewTab(node);
159                            if ("open".equals(action) && node != null)
160                                    openInNewTab(node);
161                            return;
162                    }
163                    public void onProjectDirty() {
164                            if (MessageBrokerManager.isActive()) {
165                                    reloadButton.setVisible(true);
166                                    reloadTimer.start();
167                            }
168                    }
169            };
170            public void openInNewTab(ProjectTreeNode node) {
171                    try {
172                            if (node != null) {
173                                    if (ProjectNodeType.MBC_CHANNEL.equals(node.getNodeType())) {
174                                            TabPanel tc = new TabPanel(new ChannelRuntimePanel(node.getName(), Boolean.parseBoolean(((Element) node.getModelObject()).attributeValue("requires_response"))), true);
175                                            tc.setHeader(getPath(node));
176                                            tabbedPane.addTab("Channel - " + node.getCaption(), tc);
177                                            tabbedPane.setSelectedIndex(tabbedPane.getTabCount() - 1);
178                                    } else if (ProjectNodeType.T_TEST.equals(node.getNodeType())) {
179                                            TabPanel tc = new TabPanel(new SingelTestPanel(node), true);
180                                            tc.setHeader(getPath(node));
181                                            tabbedPane.addTab("Test - " + node.getCaption(), tc);
182                                            tabbedPane.setSelectedIndex(tabbedPane.getTabCount() - 1);
183                                    } else if (ProjectNodeType.TM_MOCK_BATTERY.equals(node.getNodeType())) {
184                                            TabPanel tc = new TabPanel(new MockBatteryPanel(node), true);
185                                            tc.setHeader(getPath(node));
186                                            tabbedPane.addTab("Mock Battery - " + node.getCaption(), tc);
187                                            tabbedPane.setSelectedIndex(tabbedPane.getTabCount() - 1);
188                                    } else if (ProjectNodeType.TR_TEST_RUN.equals(node.getNodeType())) {
189                                            TabPanel tc = new TabPanel(new TestRunPanel(node), true);
190                                            tc.setHeader(getPath(node));
191                                            tabbedPane.addTab("Test Run - " + node.getCaption(), tc);
192                                            tabbedPane.setSelectedIndex(tabbedPane.getTabCount() - 1);
193                                    }
194                            }
195                    } catch (MactorException me) {
196                            GuiUtil.showGuiError(f, me);
197                    }
198            }
199            private class TabPanel extends JPanel {
200                    JLabel headerLabel = new JLabel("");
201                    JButton closeButton = new JButton(new AbstractAction("X") {
202                            public void actionPerformed(ActionEvent e) {
203                                    tabbedPane.remove(tabbedPane.indexOfComponent(TabPanel.this));
204                                    if (containedComponent instanceof Stoppable)
205                                            ((Stoppable) containedComponent).stop();
206                            }
207                    });
208                    Component containedComponent;
209                    public TabPanel(Component containedComponent, boolean closeable) {
210                            super(new BorderLayout());
211                            this.containedComponent = containedComponent;
212                            headerLabel.setBackground(getBackground().darker().darker().darker());
213                            headerLabel.setForeground(getBackground().brighter().brighter());
214                            headerLabel.setOpaque(true);
215                            headerLabel.setFont(headerLabel.getFont().deriveFont(Font.BOLD, 12));
216                            headerLabel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
217                            JPanel headerPanel = new JPanel(new BorderLayout());
218                            setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
219                            if (closeable)
220                                    headerPanel.add(closeButton, BorderLayout.EAST);
221                            headerPanel.add(headerLabel, BorderLayout.CENTER);
222                            add(headerPanel, BorderLayout.NORTH);
223                            add(containedComponent, BorderLayout.CENTER);
224                    }
225                    public void setHeader(String header) {
226                            headerLabel.setText(header);
227                            headerLabel.setVisible(header != null && header.trim().length() > 0);
228                    }
229            }
230            MActorGui(File projectDir) throws Exception {
231                    reloadButton.setVisible(false);
232                    f = new JFrame("MActor (" + VersionUtil.getVersion() + ")");
233                    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
234                    JMenuBar bar = new JMenuBar();
235                    pc = new ProjectExplorerPanel(projectControlListener);
236                    bar.add(pc.getMenuBuilder().buildMenu("Project"));
237                    bar.add(pc.getMenuBuilder().buildMenu("Help"));
238                    bar.add(reloadButton);
239                    f.setJMenuBar(bar);
240                    editorPanel.add(tipPanel, BorderLayout.CENTER);
241                    editorPanel.add(editorContainer, BorderLayout.NORTH);
242                    projectPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, pc, tabbedPane);
243                    projectPane.setDividerLocation(250);
244                    introPane = new JEditorPane(Thread.currentThread().getContextClassLoader().getResource("frontpage.html"));
245                    introPane.addHyperlinkListener(BrowserUtil.createLinkListener());
246                    introPane.setEditable(false);
247                    mainPane.add(new JScrollPane(introPane), "INTRO");
248                    mainPane.add(projectPane, "PROJECT");
249                    JSplitPane allPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, mainPane, eventLog);
250                    allPane.setDividerLocation((int) Toolkit.getDefaultToolkit().getScreenSize().getHeight() - 250);
251                    f.getContentPane().add(allPane, BorderLayout.CENTER);
252                    if (projectDir != null)
253                            pc.getProjectController().openProject(projectDir);
254                    f.setSize(1024, 800);
255                    f.setExtendedState(Frame.MAXIMIZED_BOTH);
256                    f.setVisible(true);
257            }
258            public static void main(String[] args) throws Exception {
259                    File projectDir = null;
260                    if (args != null && args.length > 0) {
261                            projectDir = new File(args[0]);
262                            if (!projectDir.exists()) {
263                                    JOptionPane.showMessageDialog(null, "Project directory '" + projectDir.getAbsolutePath() + "' does not exist", "Project not found", JOptionPane.ERROR_MESSAGE);
264                                    System.exit(1);
265                            } else if (projectDir.isFile()) {
266                                    projectDir = projectDir.getParentFile();
267                            }
268                    }
269                    Splash s = new Splash();
270                    new MActorGui(projectDir);
271                    s.dispose();
272            }
273    }