1 11 package org.eclipse.team.internal.ui.mapping; 12 13 import java.util.*; 14 15 import org.eclipse.compare.structuremergeviewer.ICompareInput; 16 import org.eclipse.core.resources.*; 17 import org.eclipse.core.runtime.CoreException; 18 import org.eclipse.core.runtime.IProgressMonitor; 19 import org.eclipse.core.runtime.jobs.Job; 20 import org.eclipse.swt.widgets.Display; 21 import org.eclipse.team.core.TeamException; 22 import org.eclipse.team.internal.core.BackgroundEventHandler; 23 import org.eclipse.team.internal.core.BackgroundEventHandler.Event; 24 import org.eclipse.team.internal.ui.Policy; 25 import org.eclipse.team.internal.ui.TeamUIMessages; 26 27 40 public abstract class CompareInputChangeNotifier implements 41 IResourceChangeListener { 42 43 private Map inputs = new HashMap(); 44 private InputChangeEventHandler eventHandler; 45 46 private class CompareInputConnecton { 47 private ICompareInput input; 48 private int connections; 49 public CompareInputConnecton(ICompareInput input) { 50 this.input = input; 51 } 52 public void increment() { 53 connections++; 54 } 55 public void decrement() { 56 if (connections > 0) 57 connections--; 58 59 } 60 public boolean isDisconnected() { 61 return connections == 0; 62 } 63 public ICompareInput getInput() { 64 return input; 65 } 66 } 67 68 private static final int COMPARE_INPUT_CHANGE = 1; 69 70 private static class InputChangeEvent extends Event { 71 private final ICompareInput[] inputs; 72 public InputChangeEvent(ICompareInput[] inputs) { 73 super(COMPARE_INPUT_CHANGE); 74 this.inputs = inputs; 75 76 } 77 public ICompareInput[] getChangedInputs() { 78 return inputs; 79 } 80 } 81 82 private class InputChangeEventHandler extends BackgroundEventHandler { 83 84 private final Set changedInputs = new HashSet(); 85 private final List pendingRunnables = new ArrayList(); 86 87 protected InputChangeEventHandler() { 88 super(TeamUIMessages.CompareInputChangeNotifier_0, TeamUIMessages.CompareInputChangeNotifier_1); 89 } 90 91 protected boolean doDispatchEvents(IProgressMonitor monitor) 92 throws TeamException { 93 ICompareInput[] toDispatch; 94 RunnableEvent[] events; 95 synchronized (pendingRunnables) { 96 synchronized (changedInputs) { 97 if (changedInputs.isEmpty() && pendingRunnables.isEmpty()) 98 return false; 99 toDispatch = (ICompareInput[]) changedInputs.toArray(new ICompareInput[changedInputs.size()]); 100 events = (RunnableEvent[]) pendingRunnables.toArray(new RunnableEvent[pendingRunnables.size()]); 101 changedInputs.clear(); 102 pendingRunnables.clear(); 103 } 104 } 105 dispatchChanges(toDispatch, monitor); 106 for (int i = 0; i < events.length; i++) { 107 RunnableEvent event = events[i]; 108 executeRunnableNow(event, monitor); 109 } 110 return true; 111 } 112 113 protected void processEvent(Event event, IProgressMonitor monitor) 114 throws CoreException { 115 int type = event.getType(); 116 switch (type) { 117 case BackgroundEventHandler.RUNNABLE_EVENT : 118 RunnableEvent runnableEvent = ((RunnableEvent)event); 119 if (runnableEvent.isPreemtive()) 120 executeRunnableNow(event, monitor); 121 else 122 executeRunnableDuringDispatch(event); 123 break; 124 case COMPARE_INPUT_CHANGE : 125 if (event instanceof InputChangeEvent) { 126 InputChangeEvent changeEvent = (InputChangeEvent) event; 127 ICompareInput[] inputs = changeEvent.getChangedInputs(); 128 synchronized (changedInputs) { 129 for (int i = 0; i < inputs.length; i++) { 130 ICompareInput input = inputs[i]; 131 changedInputs.add(input); 132 } 133 } 134 } 135 break; 136 } 137 } 138 139 private void executeRunnableDuringDispatch(Event event) { 140 synchronized (pendingRunnables) { 141 pendingRunnables.add(event); 142 } 143 } 144 145 private void executeRunnableNow(Event event, IProgressMonitor monitor) { 146 try { 147 dispatchEvents(Policy.subMonitorFor(monitor, 1)); 149 } catch (TeamException e) { 150 handleException(e); 151 } 152 try { 153 ((RunnableEvent)event).run(Policy.subMonitorFor(monitor, 1)); 154 } catch (CoreException e) { 155 handleException(e); 156 } 157 } 158 159 protected synchronized void queueEvent(Event event) { 160 super.queueEvent(event, false); 161 } 162 163 protected long getShortDispatchDelay() { 164 return 250; 166 } 167 168 protected boolean belongsTo(Object family) { 169 return CompareInputChangeNotifier.this.belongsTo(family); 170 } 171 } 172 173 176 public CompareInputChangeNotifier() { 177 super(); 178 } 179 180 187 public void initialize() { 188 ResourcesPlugin.getWorkspace().addResourceChangeListener(this, IResourceChangeEvent.POST_CHANGE); 189 eventHandler = new InputChangeEventHandler(); 190 } 191 192 197 public void dispose() { 198 ResourcesPlugin.getWorkspace().removeResourceChangeListener(this); 199 eventHandler.shutdown(); 200 } 201 202 209 public void connect(ICompareInput input) { 210 CompareInputConnecton con = (CompareInputConnecton)inputs.get(input); 211 if (con == null) { 212 con = new CompareInputConnecton(input); 213 inputs.put(input, con); 214 } 215 con.increment(); 216 } 217 218 223 public void disconnect(ICompareInput input) { 224 CompareInputConnecton con = (CompareInputConnecton)inputs.get(input); 225 if (con != null) { 226 con.decrement(); 227 if (con.isDisconnected()) { 228 inputs.remove(input); 229 } 230 } 231 } 232 233 237 protected ICompareInput[] getConnectedInputs() { 238 return (ICompareInput[])inputs.keySet().toArray(new ICompareInput[inputs.size()]); 239 } 240 241 245 protected void inputsChanged(ICompareInput[] inputs) { 246 InputChangeEvent event = new InputChangeEvent(inputs); 247 eventHandler.queueEvent(event); 248 } 249 250 255 protected void dispatchChanges(final ICompareInput[] inputs, IProgressMonitor monitor) { 256 prepareInputs(inputs, monitor); 257 Display.getDefault().syncExec(new Runnable () { 258 public void run() { 259 fireChanges(inputs); 260 } 261 }); 262 } 263 264 270 protected void prepareInputs(ICompareInput[] inputs, IProgressMonitor monitor) { 271 monitor.beginTask(null, inputs.length * 100); 272 for (int i = 0; i < inputs.length; i++) { 273 ICompareInput input = inputs[i]; 274 prepareInput(input, Policy.subMonitorFor(monitor, 100)); 275 } 276 monitor.done(); 277 } 278 279 287 protected void prepareInput(ICompareInput input, IProgressMonitor monitor) { 288 } 290 291 298 protected void fireChanges(ICompareInput[] inputs) { 299 for (int i = 0; i < inputs.length; i++) { 300 ICompareInput input = inputs[i]; 301 fireChange(input); 302 } 303 } 304 305 309 protected void runInBackground(IWorkspaceRunnable runnable) { 310 eventHandler.queueEvent(new BackgroundEventHandler.RunnableEvent(runnable, false)); 311 } 312 313 316 public void resourceChanged(IResourceChangeEvent event) { 317 List changedInputs = new ArrayList(); 318 ICompareInput[] inputs = getConnectedInputs(); 319 for (int i = 0; i < inputs.length; i++) { 320 ICompareInput input = inputs[i]; 321 IResource[] resources = getResources(input); 322 for (int j = 0; j < resources.length; j++) { 323 IResource resource = resources[j]; 324 if (resource != null) { 325 IResourceDelta delta = event.getDelta().findMember(resource.getFullPath()); 326 if (delta != null) { 327 if ((delta.getKind() & (IResourceDelta.ADDED | IResourceDelta.REMOVED)) > 0 328 || (delta.getKind() & (IResourceDelta.CHANGED)) > 0 329 && (delta.getFlags() & (IResourceDelta.CONTENT | IResourceDelta.REPLACED)) > 0) { 330 changedInputs.add(input); 331 break; 332 } 333 } 334 } 335 } 336 } 337 if (!changedInputs.isEmpty()) 338 handleInputChanges((ICompareInput[]) changedInputs.toArray(new ICompareInput[changedInputs.size()]), true); 339 } 340 341 348 protected abstract IResource[] getResources(ICompareInput input); 349 350 354 protected void handleInputChanges(ICompareInput[] inputs, boolean force) { 355 ICompareInput[] realChanges; 356 if (force) { 357 realChanges = inputs; 358 } else { 359 List result = new ArrayList(); 360 for (int i = 0; i < inputs.length; i++) { 361 ICompareInput input = inputs[i]; 362 if (isChanged(input)) { 363 result.add(input); 364 } 365 } 366 realChanges = (ICompareInput[]) result.toArray(new ICompareInput[result.size()]); 367 } 368 if (realChanges.length > 0) 369 inputsChanged(realChanges); 370 } 371 372 378 protected boolean isChanged(ICompareInput input) { 379 if (input instanceof AbstractCompareInput) { 380 AbstractCompareInput ci = (AbstractCompareInput) input; 381 return ci.needsUpdate(); 382 } 383 return false; 384 } 385 386 392 protected void fireChange(ICompareInput input) { 393 if (input instanceof AbstractCompareInput) { 394 AbstractCompareInput ci = (AbstractCompareInput) input; 395 ci.update(); 396 } 397 } 398 399 406 protected boolean belongsTo(Object family) { 407 return false; 408 } 409 410 } 411 | Popular Tags |