001    package nl.cwi.sen1.tide.tool.proclist;
002    
003    import java.awt.BorderLayout;
004    import java.awt.Color;
005    import java.awt.Component;
006    import java.awt.Container;
007    import java.awt.Dimension;
008    import java.awt.EventQueue;
009    import java.awt.event.MouseAdapter;
010    import java.awt.event.MouseEvent;
011    import java.awt.event.MouseListener;
012    import java.util.HashMap;
013    import java.util.Iterator;
014    import java.util.Map;
015    
016    import javax.swing.Box;
017    import javax.swing.BoxLayout;
018    import javax.swing.JComponent;
019    import javax.swing.JLabel;
020    import javax.swing.JPanel;
021    import javax.swing.JPopupMenu;
022    import javax.swing.border.EmptyBorder;
023    
024    import nl.cwi.sen1.tide.tool.AdapterAction;
025    import nl.cwi.sen1.tide.tool.ProcessAction;
026    import nl.cwi.sen1.tide.tool.ToolManager;
027    import nl.cwi.sen1.tide.tool.support.DebugAdapter;
028    import nl.cwi.sen1.tide.tool.support.DebugAdapterListener;
029    import nl.cwi.sen1.tide.tool.support.DebugProcess;
030    import nl.cwi.sen1.tide.tool.support.DebugTool;
031    import nl.cwi.sen1.tide.tool.support.DebugToolListener;
032    import nl.cwi.sen1.tide.tool.support.Info;
033    import nl.cwi.sen1.tide.tool.support.ProcessStatus;
034    
035    public class ProcessList
036      extends JPanel
037      implements DebugToolListener
038    {
039      private Info info;
040      private Container adapterPanel;
041      private Map<DebugAdapter, JComponent> adapters;
042      private ToolManager toolManager;
043    
044      //{{{ public ProcessList(ToolManager manager)
045    
046      public ProcessList(ToolManager manager)
047      {
048        info = new Info("ProcessList");
049        setBackground(new Color(0xFF, 0xFF, 0xFF));
050        setLayout(new BorderLayout());
051    
052        adapterPanel = new JPanel();
053        adapterPanel.setLayout(new BoxLayout(adapterPanel, BoxLayout.Y_AXIS));
054        add("North", adapterPanel);
055    
056        adapters = new HashMap<DebugAdapter, JComponent>();
057        setPreferredSize(new Dimension(170, 300));
058    
059        this.toolManager = manager;
060      }
061    
062      //}}}
063    
064      //{{{ public void adapterConnected(DebugTool tool, DebugAdapter adapter)
065    
066      public void adapterConnected(DebugTool tool, DebugAdapter adapter)
067      {
068        JComponent panel = new AdapterPanel(adapter, toolManager);
069        adapters.put(adapter, panel);
070    
071        adapterPanel.add(panel);
072        validate();
073        repaint();
074      }
075    
076      //}}}
077      //{{{ public void adapterDisconnected(DebugTool tool, DebugAdapter adapter)
078    
079      public void adapterDisconnected(DebugTool tool, DebugAdapter adapter)
080      {
081        info.info("adapterDisconnected: " + adapter);
082        final JComponent panel = adapters.get(adapter);
083        adapters.remove(adapter);
084    
085        // remove/validate/repaint must be called from the system
086        // event queue thread, because otherwise we encounter deadlocks
087        // as the 'ToolBus' thread and the 'UI' thread both want to
088        // modify the component tree at the same time
089        Runnable runnable = new Runnable()
090        {
091          public void run()
092          {
093            adapterPanel.remove(panel);
094            validate();
095            repaint();
096          }
097        };
098        EventQueue.invokeLater(runnable);
099      }
100    
101      //}}}
102    }
103    
104    class AdapterPanel
105      extends JPanel
106      implements DebugAdapterListener
107    {
108      private Info info;
109      private DebugAdapter adapter;
110      private Container processPanel;
111      private Map<DebugProcess, Component> processes;
112    
113      private ToolManager toolManager;
114      private JPopupMenu adapterMenu;
115    
116      //{{{ public AdapterPanel(DebugAdapter adapter, ToolManager manager)
117    
118      public AdapterPanel(DebugAdapter adap, ToolManager manager)
119      {
120        setBackground(Color.white);
121    
122        info    = new Info("AdapterPanel");
123        adapter = adap;
124        toolManager = manager;
125    
126        adapter.addDebugAdapterListener(this);
127    
128        setLayout(new BorderLayout());
129    
130        //{{{ Handle adapter popup menu
131    
132        adapterMenu = new JPopupMenu("Adapter Tools");
133        Iterator<AdapterAction> iter = manager.adapterActionIterator();
134        while (iter.hasNext()) {
135          adapterMenu.add(iter.next());
136        }
137    
138        //}}}
139        JLabel label = new JLabel(adapter.getName())
140        {
141          public void processMouseEvent(MouseEvent event)
142          {
143            if (event.isPopupTrigger()) {
144              toolManager.setCurrentAdapter(adapter);
145              adapterMenu.show(this, event.getX(), event.getY());
146            } else {
147              super.processMouseEvent(event);
148            }
149          }
150        };
151        label.addMouseListener(new MouseAdapter(){});
152    
153        label.setBorder(new EmptyBorder(2,0,2,0));
154        add("North", label);
155    
156        processPanel = Box.createVerticalBox();
157        add("Center", processPanel);
158        add("South",  Box.createVerticalStrut(3));
159    
160        processes = new HashMap<DebugProcess, Component>();
161    
162        //{{{ Handle selection of adapters
163    
164        MouseListener selectionListener = new MouseAdapter()
165          {
166            public void mouseClicked(MouseEvent event)
167            {
168              toolManager.setCurrentAdapter(adapter);
169            }
170          };
171        addMouseListener(selectionListener);
172    
173        //}}}
174      }
175    
176      //}}}
177      //{{{ public void processCreated(DebugAdapter adapter, DebugProcess process)
178    
179      public void processCreated(DebugAdapter adapter, DebugProcess process)
180      {
181        info.info("processCreated: " + process.getName());
182    
183        Container panel = new ProcessPanel(toolManager, process, this);
184    
185        processPanel.add(panel);
186        getParent().getParent().validate();
187        getParent().getParent().repaint();
188    
189        processes.put(process, panel);
190      }
191    
192      //}}}
193      //{{{ public void processDestroyed(DebugAdapter adapter, DebugProcess process)
194    
195      public void processDestroyed(DebugAdapter adapter, DebugProcess process)
196      {
197        Component panel = processes.get(process);
198        processes.remove(process);
199        processPanel.remove(panel);
200      }
201    
202      //}}}
203      //{{{ public void select()
204    
205      public void select()
206      {
207        toolManager.setCurrentAdapter(adapter);
208      }
209    
210      //}}}
211    }
212    
213    class ProcessPanel
214      extends JPanel
215    {
216      private ToolManager  toolManager;
217      private DebugProcess process;
218      private AdapterPanel adapterPanel;
219      private JPopupMenu   processMenu;
220    
221      //{{{ public ProcessPanel(manager, process, adapterPanel)
222    
223      public ProcessPanel(ToolManager manager, DebugProcess proc,
224                          AdapterPanel adapPanel)
225      {
226        this.toolManager  = manager;
227        this.process      = proc;
228        this.adapterPanel = adapPanel;
229    
230        //{{{ Handle process popup menu
231    
232        processMenu = new JPopupMenu("Process Tools");
233        Iterator<ProcessAction> iter = manager.processActionIterator();
234        while (iter.hasNext()) {
235          processMenu.add(iter.next());
236        }
237    
238        // Enable mouse events by adding a dummy listener
239        addMouseListener(new MouseAdapter(){});
240    
241        //}}}
242    
243        setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
244        setBackground(null);
245        add(new JLabel("  " + process.getPid() + " - " + process.getName()));
246        add(Box.createHorizontalGlue());
247        ProcessStatus status = new ProcessStatus(process);
248        status.setBackground(Color.red);
249        add(status);
250        add(Box.createHorizontalStrut(3));
251    
252        //{{{ Handle selection of adapters
253    
254        MouseListener selectionListener =
255          new MouseAdapter()
256          {
257            public void mouseClicked(MouseEvent event)
258            {
259              adapterPanel.select();
260              toolManager.setCurrentProcess(process);
261            }
262          };
263        addMouseListener(selectionListener);
264    
265        //}}}
266      }
267    
268      //}}}
269    
270      //{{{ public void processMouseEvent(MouseEvent event)
271    
272      public void processMouseEvent(MouseEvent event)
273      {
274        if (event.isPopupTrigger()) {
275          adapterPanel.select();
276          toolManager.setCurrentProcess(process);
277          processMenu.show(this, event.getX(), event.getY());
278        } else {
279          super.processMouseEvent(event);
280        }
281      }
282    
283      //}}}
284    }