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 }