1 19 20 package org.netbeans.modules.navigator; 21 22 import java.awt.Component ; 23 import java.awt.event.ActionEvent ; 24 import java.awt.event.ActionListener ; 25 import java.awt.event.KeyEvent ; 26 import java.beans.PropertyChangeEvent ; 27 import java.beans.PropertyChangeListener ; 28 import java.lang.ref.Reference ; 29 import java.lang.ref.WeakReference ; 30 import java.util.ArrayList ; 31 import java.util.Collection ; 32 import java.util.List ; 33 import javax.swing.AbstractAction ; 34 import javax.swing.FocusManager ; 35 import javax.swing.JComboBox ; 36 import javax.swing.JComponent ; 37 import javax.swing.KeyStroke ; 38 import javax.swing.SwingUtilities ; 39 import org.netbeans.spi.navigator.NavigatorLookupHint; 40 import org.netbeans.spi.navigator.NavigatorPanel; 41 import org.openide.filesystems.FileObject; 42 import org.openide.loaders.DataShadow; 43 import org.openide.nodes.Node; 44 import org.openide.util.Lookup; 45 import org.openide.util.LookupEvent; 46 import org.openide.util.LookupListener; 47 import org.openide.util.NbBundle; 48 import org.openide.util.RequestProcessor; 49 import org.openide.util.Task; 50 import org.openide.util.TaskListener; 51 import org.openide.util.Utilities; 52 import org.openide.util.lookup.Lookups; 53 import org.openide.windows.TopComponent; 54 import org.openide.loaders.DataObject; 55 import org.openide.windows.WindowManager; 56 57 62 public final class NavigatorController implements LookupListener, ActionListener , Lookup.Provider, PropertyChangeListener { 63 64 66 67 static final int COALESCE_TIME = 100; 68 69 70 private NavigatorTC navigatorTC; 71 72 73 private RequestProcessor.Task nodeSetterTask; 74 private final Object NODE_SETTER_LOCK = new Object (); 75 76 77 private static final Lookup.Template<Node> CUR_NODES = 78 new Lookup.Template<Node>(Node.class); 79 80 private static final Lookup.Template<NavigatorLookupHint> CUR_HINTS = 81 new Lookup.Template<NavigatorLookupHint>(NavigatorLookupHint.class); 82 83 84 private Lookup.Result<Node> curNodes; 85 86 private Lookup.Result<NavigatorLookupHint> curHints; 87 88 89 private Node curNode; 90 91 private final Lookup clientsLookup; 92 93 private final Lookup panelLookup; 94 95 96 private Reference <TopComponent> lastActivatedRef; 97 98 99 100 public NavigatorController(NavigatorTC navigatorTC) { 101 this.navigatorTC = navigatorTC; 102 clientsLookup = Lookups.proxy(this); 103 panelLookup = Lookups.proxy(new PanelLookupWrapper()); 104 } 105 106 107 public void navigatorTCOpened() { 108 curNodes = Utilities.actionsGlobalContext().lookup(CUR_NODES); 109 curNodes.addLookupListener(this); 110 curHints = Utilities.actionsGlobalContext().lookup(CUR_HINTS); 111 curHints.addLookupListener(this); 112 navigatorTC.getPanelSelector().addActionListener(this); 113 TopComponent.getRegistry().addPropertyChangeListener(this); 114 115 updateContext(); 116 } 117 118 119 public void navigatorTCClosed() { 120 curNodes.removeLookupListener(this); 121 curHints.removeLookupListener(this); 122 navigatorTC.getPanelSelector().removeActionListener(this); 123 TopComponent.getRegistry().removePropertyChangeListener(this); 124 curNodes = null; 125 curHints = null; 126 curNode = null; 127 lastActivatedRef = null; 128 navigatorTC.setPanels(null); 129 } 130 131 134 public Lookup getPanelLookup () { 135 return panelLookup; 136 } 137 138 141 public void actionPerformed (ActionEvent e) { 142 int index = navigatorTC.getPanelSelector().getSelectedIndex(); 143 if (index == -1) { 144 return; 146 } 147 NavigatorPanel newPanel = (NavigatorPanel)navigatorTC.getPanels().get(index); 148 activatePanel(newPanel); 149 } 150 151 154 public void activatePanel (NavigatorPanel panel) { 155 if (!navigatorTC.getPanels().contains(panel)) { 156 throw new IllegalArgumentException ("Panel is not available for activation: " + panel); } 158 NavigatorPanel oldPanel = navigatorTC.getSelectedPanel(); 159 if (!panel.equals(oldPanel)) { 160 if (oldPanel != null) { 161 oldPanel.panelDeactivated(); 162 } 163 panel.panelActivated(clientsLookup); 164 navigatorTC.setSelectedPanel(panel); 165 } 166 } 167 168 172 public void resultChanged(LookupEvent ev) { 173 if (!navigatorTC.equals(WindowManager.getDefault().getRegistry().getActivated())) { 174 ActNodeSetter nodeSetter = new ActNodeSetter(); 175 synchronized (NODE_SETTER_LOCK) { 176 if (nodeSetterTask != null) { 177 nodeSetterTask.cancel(); 178 } 179 nodeSetterTask = RequestProcessor.getDefault().post(nodeSetter, COALESCE_TIME); 181 nodeSetterTask.addTaskListener(nodeSetter); 182 } 183 } 184 } 185 186 187 private Node obtainFirstCurNode () { 188 Collection nodeList = curNodes.allInstances(); 189 return nodeList.isEmpty() ? null : (Node)nodeList.iterator().next(); 190 } 191 192 196 private boolean shouldUpdate () { 197 return TopComponent.getRegistry().getCurrentNodes() != null || 198 Utilities.actionsGlobalContext().lookup(NavigatorLookupHint.class) != null; 199 } 200 201 204 private void updateContext () { 205 Node node = obtainFirstCurNode(); 208 if (node == null && !shouldUpdate()) { 209 return; 210 } 211 212 curNode = node; 215 216 List <NavigatorPanel> providers = obtainProviders(node); 217 List oldProviders = navigatorTC.getPanels(); 218 219 navigatorTC.setActivatedNodes(node == null ? new Node[0] : new Node[] { node }); 222 223 updateTCTitle(providers != null && !providers.isEmpty() ? node : null); 224 225 if (oldProviders == null && providers == null) { 227 return; 228 } 229 230 NavigatorPanel selPanel = navigatorTC.getSelectedPanel(); 231 if (oldProviders != null && oldProviders.contains(selPanel) && 235 providers != null && providers.contains(selPanel)) { 236 clientsLookup.lookup(Node.class); 238 if (!oldProviders.equals(providers)) { 240 navigatorTC.getPanelSelector().removeActionListener(this); 243 navigatorTC.setPanels(providers); 244 navigatorTC.setSelectedPanel(selPanel); 245 navigatorTC.getPanelSelector().addActionListener(this); 246 } 247 return; 248 } 249 250 if (selPanel != null) { 251 selPanel.panelDeactivated(); 252 } 253 if (providers != null && providers.size() > 0) { 254 NavigatorPanel newSel = (NavigatorPanel)providers.get(0); 255 newSel.panelActivated(clientsLookup); 256 } 257 navigatorTC.getPanelSelector().removeActionListener(this); 260 navigatorTC.setPanels(providers); 261 navigatorTC.getPanelSelector().addActionListener(this); 262 } 263 264 265 private void updateTCTitle (Node node) { 266 String newTitle; 267 if (node != null) { 268 newTitle = NbBundle.getMessage( 269 NavigatorTC.class, "FMT_Navigator", node.getDisplayName() ); 271 } else { 272 newTitle = NbBundle.getMessage(NavigatorTC.class, "LBL_Navigator"); } 274 navigatorTC.setName(newTitle); 275 } 276 277 283 List <NavigatorPanel> obtainProviders (Node node) { 284 List <NavigatorPanel> result = null; 285 Collection <? extends NavigatorLookupHint> lkpHints = 287 Utilities.actionsGlobalContext().lookupAll(NavigatorLookupHint.class); 288 for (NavigatorLookupHint curHint : lkpHints) { 289 Collection <? extends NavigatorPanel> providers = ProviderRegistry.getInstance().getProviders(curHint.getContentType()); 290 if (providers != null && !providers.isEmpty()) { 291 if (result == null) { 292 result = new ArrayList <NavigatorPanel>(providers.size() * lkpHints.size()); 293 } 294 result.addAll(providers); 295 } 296 } 297 298 if (node != null) { 300 DataObject dObj = (DataObject)node.getLookup().lookup(DataObject.class); 301 while (dObj instanceof DataShadow) { 303 dObj = ((DataShadow)dObj).getOriginal(); 304 } 305 if (dObj != null) { 306 FileObject fo = dObj.getPrimaryFile(); 307 if (!fo.isVirtual()) { 309 String contentType = fo.getMIMEType(); 310 Collection <? extends NavigatorPanel> providers = ProviderRegistry.getInstance().getProviders(contentType); 311 if (providers != null && !providers.isEmpty()) { 312 if (result == null) { 313 result = new ArrayList <NavigatorPanel>(providers.size()); 314 } 315 result.addAll(providers); 316 } 317 } 318 } 319 } 320 321 return result; 322 } 323 324 329 public Lookup getLookup () { 330 if (curNode == null) { 334 return Lookup.EMPTY; 335 } 336 return curNode.getLookup(); 337 } 338 339 340 public void installActions () { 341 KeyStroke returnKey = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0, true); 343 navigatorTC.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(returnKey, "return"); navigatorTC.getActionMap().put("return", new ESCHandler()); } 347 348 349 350 352 public void propertyChange(PropertyChangeEvent evt) { 353 if (TopComponent.Registry.PROP_ACTIVATED.equals(evt.getPropertyName())) { 354 TopComponent tc = TopComponent.getRegistry().getActivated(); 355 if (tc != null && tc != navigatorTC) { 356 lastActivatedRef = new WeakReference <TopComponent>(tc); 357 } 358 } 359 } 360 361 363 private class ESCHandler extends AbstractAction { 364 public void actionPerformed (ActionEvent evt) { 365 Component focusOwner = FocusManager.getCurrentManager().getFocusOwner(); 366 if (lastActivatedRef == null || 369 focusOwner == null || 370 !SwingUtilities.isDescendingFrom(focusOwner, navigatorTC) || 371 focusOwner instanceof JComboBox ) { 372 return; 373 } 374 TopComponent prevFocusedTc = lastActivatedRef.get(); 375 if (prevFocusedTc != null) { 376 prevFocusedTc.requestActive(); 377 } 378 } 379 } 381 385 private class PanelLookupWrapper implements Lookup.Provider { 386 387 public Lookup getLookup () { 388 NavigatorPanel selPanel = navigatorTC.getSelectedPanel(); 389 if (selPanel != null) { 390 Lookup panelLkp = selPanel.getLookup(); 391 if (panelLkp != null) { 392 return panelLkp; 393 } 394 } 395 return Lookup.EMPTY; 396 } 397 398 } 400 403 private class ActNodeSetter implements Runnable , TaskListener { 404 405 public void run() { 406 if (RequestProcessor.getDefault().isRequestProcessorThread()) { 409 SwingUtilities.invokeLater(this); 410 } else { 411 if (curNodes != null) { 415 updateContext(); 416 } 417 } 418 } 419 420 public void taskFinished(Task task) { 421 synchronized (NODE_SETTER_LOCK) { 422 if (task == nodeSetterTask) { 423 nodeSetterTask = null; 424 } 425 } 426 } 427 428 } 430 431 } 432 | Popular Tags |