001    package nl.cwi.sen1.gui.plugin;
002    
003    import java.awt.Dimension;
004    import java.awt.event.MouseEvent;
005    import java.util.HashMap;
006    import java.util.Map;
007    
008    import javax.swing.JComponent;
009    import javax.swing.JLabel;
010    
011    import nl.cwi.sen1.configapi.types.ActionDescriptionList;
012    import nl.cwi.sen1.configapi.types.Event;
013    import nl.cwi.sen1.graph.Factory;
014    import nl.cwi.sen1.graph.types.Graph;
015    import nl.cwi.sen1.gui.CloseAbortedException;
016    import nl.cwi.sen1.gui.Studio;
017    import nl.cwi.sen1.gui.StudioImplWithPredefinedLayout;
018    import nl.cwi.sen1.gui.StudioWithPredefinedLayout;
019    import nl.cwi.sen1.gui.component.StudioComponent;
020    import nl.cwi.sen1.gui.component.StudioComponentImpl;
021    import nl.cwi.sen1.gui.plugin.data.Module;
022    import nl.cwi.sen1.gui.plugin.data.ModuleSelectionListener;
023    import nl.cwi.sen1.gui.plugin.data.ModuleTreeModel;
024    import nl.cwi.sen1.ioapi.types.File;
025    import nl.cwi.sen1.util.DefaultPopupImpl;
026    import nl.cwi.sen1.util.MouseAdapter;
027    import aterm.ATerm;
028    import aterm.ATermFactory;
029    import aterm.pure.PureFactory;
030    
031    public class Navigator extends DefaultStudioPlugin implements NavigatorTif {
032            private static final String TOOL_NAME = "navigator";
033    
034            private NavigatorBridge bridge;
035    
036            private ModuleTreeModel moduleModel;
037    
038            private Studio studio;
039    
040            private Map<String, JComponent> statusBarComponents;
041    
042            private JLabel status;
043    
044            private Factory graphFactory;
045    
046            private nl.cwi.sen1.ioapi.Factory ioFactory;
047    
048            private boolean suspendSelectionNotification;
049    
050            private StudioComponent navigatorComponent;
051    
052            private nl.cwi.sen1.configapi.Factory configFactory;
053    
054            private ModuleTree tree;
055    
056            public Navigator() {
057                    statusBarComponents = new HashMap<String, JComponent>();
058                    status = new JLabel(" ");
059                    status.setPreferredSize(new Dimension(100, 18));
060    
061                    statusBarComponents.put("Status", status);
062                    createModel();
063            }
064    
065            public void deleteModule(ATerm moduleId) {
066                    tree.saveExpansionState();
067                    moduleModel.removeModule(moduleId);
068                    tree.loadExpansionState();
069            }
070    
071            public void updateModule(ATerm moduleId, ATerm path) {
072                    Module module = moduleModel.getModule(moduleId);
073    
074                    File file = ioFactory.FileFromTerm(path);
075                    String label = file.getName();
076    
077                    if (tree != null) {
078                            tree.saveExpansionState();
079                            if (module != null) {
080                                    moduleModel.removeModule(moduleId);
081                            }
082                            module = new Module(moduleId, file, label);
083                            moduleModel.addModule(module);
084                            tree.loadExpansionState();
085                    }
086            }
087    
088            public void setModules(ATerm graphTerm) {
089                    Graph graph = graphFactory.GraphFromTerm(graphTerm);
090    
091                    setModules(graph);
092            }
093    
094            public void postPopupRequest(MouseEvent e, Module module) {
095                    ATermFactory factory = studio.getATermFactory();
096                    ATerm moduleId = module.getId();
097                    bridge.postEvent(factory.make("request-popup-event(<term>)", moduleId));
098            }
099    
100            public void showPopup(final ATerm id, final ATerm menu) {
101                    nl.cwi.sen1.configapi.Factory f = nl.cwi.sen1.configapi.Factory
102                                    .getInstance((PureFactory) id.getFactory());
103                    ActionDescriptionList list = f.ActionDescriptionListFromTerm(menu);
104                    DefaultPopupImpl popup = new DefaultPopupImpl(bridge);
105                    popup.showPopup(id, list);
106            }
107    
108            public void recAckEvent(ATerm t0) {
109            }
110    
111            public void recTerminate(ATerm t0) {
112                    fireStudioPluginClosed();
113            }
114    
115            public String getName() {
116                    return TOOL_NAME;
117            }
118    
119            private ATerm createEventId(ATerm moduleId) {
120                    return studio.getATermFactory().make(TOOL_NAME + "(<term>)", moduleId);
121            }
122    
123            public void initStudioPlugin(Studio studio) {
124                    this.studio = studio;
125                    graphFactory = Factory.getInstance((PureFactory) studio
126                                    .getATermFactory());
127                    configFactory = nl.cwi.sen1.configapi.Factory
128                                    .getInstance((PureFactory) studio.getATermFactory());
129                    ioFactory = nl.cwi.sen1.ioapi.Factory.getInstance((PureFactory) studio
130                                    .getATermFactory());
131                    bridge = new NavigatorBridge(studio.getATermFactory(), this);
132                    bridge.setLockObject(this);
133                    studio.connect(getName(), bridge);
134    
135                    addNavigatorComponent();
136            }
137    
138            private void createModel() {
139                    moduleModel = new ModuleTreeModel();
140                    moduleModel.addModuleSelectionListener(new ModuleSelectionListener() {
141                            public void moduleSelected(Module module) {
142                                    if (!suspendSelectionNotification) {
143                                            if (module != null) {
144                                                    status.setText(module.toString());
145                                                    bridge.postEvent(studio.getATermFactory().make(
146                                                                    "module-selected(<term>)", module.getId()));
147                                            }
148                                    }
149                            }
150                    });
151            }
152    
153            private void addNavigatorComponent() {
154                    tree = new ModuleTree(this, moduleModel);
155                    final ATerm id = configFactory.getPureFactory().parse(TOOL_NAME);
156                    final Event popupAction = configFactory.makeEvent_Popup();
157    
158                    tree.addMouseListener(new MouseAdapter(id, bridge, popupAction) {
159                            public void mousePressed(MouseEvent e) {
160                                    ATerm moduleId = tree.selectModule(e.getX(), e.getY());
161                                    if (moduleId != null) {
162                                            setId(createEventId(moduleId));
163                                            super.mousePressed(e);
164                                    }
165                            }
166                    });
167    
168                    navigatorComponent = new StudioComponentImpl("Modules", tree) {
169                            public void requestClose() throws CloseAbortedException {
170                                    throw new CloseAbortedException();
171                            }
172    
173                            public JComponent[] getStatusBarComponents() {
174                                    return new JComponent[] { status };
175                            }
176                    };
177                    ((StudioWithPredefinedLayout) studio).addComponent(navigatorComponent,
178                                    StudioImplWithPredefinedLayout.TOP_LEFT);
179                    // studio.addComponentMenu(navigatorComponent, new JMenu("Navigate"));
180            }
181    
182            public void selectModule(ATerm moduleId) {
183                    suspendSelectionNotification = true;
184                    moduleModel.selectModule(moduleId);
185                    suspendSelectionNotification = false;
186            }
187    
188            public void markModuleError(ATerm moduleId) {
189                    tree.saveExpansionState();
190                    moduleModel.markError(moduleId);
191                    tree.loadExpansionState();
192            }
193    
194            public void markModuleNormal(ATerm moduleId) {
195                    tree.saveExpansionState();
196                    moduleModel.markNormal(moduleId);
197                    tree.loadExpansionState();
198            }
199    }