|
Lines 1-5
Link Here
|
| 1 |
package org.eclipse.equinox.internal.p2.ui.dialogs; |
1 |
package org.eclipse.equinox.internal.p2.ui.dialogs; |
| 2 |
|
2 |
|
|
|
3 |
import java.util.ArrayList; |
| 4 |
import java.util.Iterator; |
| 3 |
import org.eclipse.core.runtime.*; |
5 |
import org.eclipse.core.runtime.*; |
| 4 |
import org.eclipse.core.runtime.jobs.*; |
6 |
import org.eclipse.core.runtime.jobs.*; |
| 5 |
import org.eclipse.equinox.internal.p2.ui.ProvUIMessages; |
7 |
import org.eclipse.equinox.internal.p2.ui.ProvUIMessages; |
|
Lines 13-20
Link Here
|
| 13 |
import org.eclipse.jface.dialogs.ControlEnableState; |
15 |
import org.eclipse.jface.dialogs.ControlEnableState; |
| 14 |
import org.eclipse.jface.dialogs.PopupDialog; |
16 |
import org.eclipse.jface.dialogs.PopupDialog; |
| 15 |
import org.eclipse.jface.resource.JFaceResources; |
17 |
import org.eclipse.jface.resource.JFaceResources; |
| 16 |
import org.eclipse.jface.viewers.TreeViewer; |
18 |
import org.eclipse.jface.viewers.*; |
| 17 |
import org.eclipse.jface.viewers.Viewer; |
|
|
| 18 |
import org.eclipse.swt.SWT; |
19 |
import org.eclipse.swt.SWT; |
| 19 |
import org.eclipse.swt.events.*; |
20 |
import org.eclipse.swt.events.*; |
| 20 |
import org.eclipse.swt.graphics.Point; |
21 |
import org.eclipse.swt.graphics.Point; |
|
Lines 51-56
Link Here
|
| 51 |
WorkbenchJob filterJob; |
52 |
WorkbenchJob filterJob; |
| 52 |
ControlEnableState enableState; |
53 |
ControlEnableState enableState; |
| 53 |
Object viewerInput; |
54 |
Object viewerInput; |
|
|
55 |
ArrayList checkState = new ArrayList(); |
| 54 |
|
56 |
|
| 55 |
class InputSchedulingRule implements ISchedulingRule { |
57 |
class InputSchedulingRule implements ISchedulingRule { |
| 56 |
Object input; |
58 |
Object input; |
|
Lines 108-115
Link Here
|
| 108 |
} |
110 |
} |
| 109 |
|
111 |
|
| 110 |
protected TreeViewer doCreateTreeViewer(Composite composite, int style) { |
112 |
protected TreeViewer doCreateTreeViewer(Composite composite, int style) { |
| 111 |
if (useCheckBoxTree) |
113 |
if (useCheckBoxTree) { |
| 112 |
return new ContainerCheckedTreeViewer(composite, style); |
114 |
final ContainerCheckedTreeViewer v = new ContainerCheckedTreeViewer(composite, style); |
|
|
115 |
v.addCheckStateListener(new ICheckStateListener() { |
| 116 |
public void checkStateChanged(CheckStateChangedEvent event) { |
| 117 |
// We use an additive check state cache so we need to remove |
| 118 |
// previously checked items if the user unchecked them. |
| 119 |
if (!event.getChecked() && checkState != null) { |
| 120 |
Iterator iter = checkState.iterator(); |
| 121 |
ArrayList toRemove = new ArrayList(1); |
| 122 |
while (iter.hasNext()) { |
| 123 |
Object element = iter.next(); |
| 124 |
if (v.getComparer().equals(element, event.getElement())) { |
| 125 |
toRemove.add(element); |
| 126 |
// Do not break out of the loop. We may have duplicate equal |
| 127 |
// elements in the cache. Since the cache is additive, we want |
| 128 |
// to be sure we've gotten everything. |
| 129 |
} |
| 130 |
} |
| 131 |
checkState.removeAll(toRemove); |
| 132 |
} |
| 133 |
|
| 134 |
} |
| 135 |
}); |
| 136 |
return v; |
| 137 |
} |
| 113 |
return super.doCreateTreeViewer(composite, style); |
138 |
return super.doCreateTreeViewer(composite, style); |
| 114 |
} |
139 |
} |
| 115 |
|
140 |
|
|
Lines 172-177
Link Here
|
| 172 |
// Store the input because it's not reset in the viewer until |
197 |
// Store the input because it's not reset in the viewer until |
| 173 |
// after this listener is run. |
198 |
// after this listener is run. |
| 174 |
viewerInput = newInput; |
199 |
viewerInput = newInput; |
|
|
200 |
|
| 201 |
// Reset the state for remembering check marks |
| 202 |
checkState = new ArrayList(); |
| 175 |
// Cancel the load and filter jobs and null out the scheduling rule |
203 |
// Cancel the load and filter jobs and null out the scheduling rule |
| 176 |
// so that a new one will be created on the new input when needed. |
204 |
// so that a new one will be created on the new input when needed. |
| 177 |
filterRule = null; |
205 |
filterRule = null; |
|
Lines 195-201
Link Here
|
| 195 |
* @see org.eclipse.ui.dialogs.FilteredTree#doCreateRefreshJob() |
223 |
* @see org.eclipse.ui.dialogs.FilteredTree#doCreateRefreshJob() |
| 196 |
*/ |
224 |
*/ |
| 197 |
protected WorkbenchJob doCreateRefreshJob() { |
225 |
protected WorkbenchJob doCreateRefreshJob() { |
| 198 |
filterJob = super.doCreateRefreshJob(); |
226 |
// See bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=229735 |
|
|
227 |
// Ideally we would not have to copy the filtering job, but this |
| 228 |
// gives us the most precise control over how and when to preserve |
| 229 |
// the check mark state. We have modified the superclass job so |
| 230 |
// that everything is expanded rather than recursively expanding |
| 231 |
// the tree and checking for the stop time. This simplifies the |
| 232 |
// restoration of the correct checkmarks. |
| 233 |
filterJob = new WorkbenchJob("Refresh Filter") {//$NON-NLS-1$ |
| 234 |
public IStatus runInUIThread(IProgressMonitor monitor) { |
| 235 |
if (treeViewer.getControl().isDisposed()) { |
| 236 |
return Status.CANCEL_STATUS; |
| 237 |
} |
| 238 |
|
| 239 |
String text = getFilterString(); |
| 240 |
if (text == null) { |
| 241 |
return Status.OK_STATUS; |
| 242 |
} |
| 243 |
|
| 244 |
if (monitor.isCanceled()) |
| 245 |
return Status.CANCEL_STATUS; |
| 246 |
boolean initial = initialText != null && initialText.equals(text); |
| 247 |
if (initial) { |
| 248 |
patternFilter.setPattern(null); |
| 249 |
} else if (text != null) { |
| 250 |
patternFilter.setPattern(text); |
| 251 |
} |
| 252 |
|
| 253 |
Control redrawFalseControl = treeComposite != null ? treeComposite : treeViewer.getControl(); |
| 254 |
try { |
| 255 |
// don't want the user to see updates that will be made to |
| 256 |
// the tree |
| 257 |
// we are setting redraw(false) on the composite to avoid |
| 258 |
// dancing scrollbar |
| 259 |
redrawFalseControl.setRedraw(false); |
| 260 |
treeViewer.getTree().setCursor(display.getSystemCursor(SWT.CURSOR_WAIT)); |
| 261 |
rememberLeafCheckState(); |
| 262 |
treeViewer.refresh(true); |
| 263 |
// The superclass did a recursive expand so it could be more responsive to subsequent |
| 264 |
// typing. We are expanding all so that we know everything is realized when we go to |
| 265 |
// restore the check state afterward. |
| 266 |
treeViewer.expandAll(); |
| 267 |
if (text.length() > 0 && !initial) { |
| 268 |
// enabled toolbar - there is text to clear |
| 269 |
// and the list is currently being filtered |
| 270 |
updateToolbar(true); |
| 271 |
} else { |
| 272 |
// disabled toolbar - there is no text to clear |
| 273 |
// and the list is currently not filtered |
| 274 |
updateToolbar(false); |
| 275 |
} |
| 276 |
} finally { |
| 277 |
// done updating the tree - set redraw back to true |
| 278 |
TreeItem[] items = getViewer().getTree().getItems(); |
| 279 |
if (items.length > 0 && getViewer().getTree().getSelectionCount() == 0) { |
| 280 |
treeViewer.getTree().setTopItem(items[0]); |
| 281 |
} |
| 282 |
restoreLeafCheckState(); |
| 283 |
redrawFalseControl.setRedraw(true); |
| 284 |
treeViewer.getTree().setCursor(null); |
| 285 |
} |
| 286 |
return Status.OK_STATUS; |
| 287 |
} |
| 288 |
}; |
| 289 |
|
| 199 |
filterJob.addJobChangeListener(new JobChangeAdapter() { |
290 |
filterJob.addJobChangeListener(new JobChangeAdapter() { |
| 200 |
public void aboutToRun(final IJobChangeEvent event) { |
291 |
public void aboutToRun(final IJobChangeEvent event) { |
| 201 |
final boolean[] shouldLoad = new boolean[1]; |
292 |
final boolean[] shouldLoad = new boolean[1]; |
|
Lines 247-252
Link Here
|
| 247 |
} |
338 |
} |
| 248 |
if (filterText != null && !filterText.isDisposed()) { |
339 |
if (filterText != null && !filterText.isDisposed()) { |
| 249 |
filterText.setCursor(display.getSystemCursor(SWT.CURSOR_WAIT)); |
340 |
filterText.setCursor(display.getSystemCursor(SWT.CURSOR_WAIT)); |
|
|
341 |
getViewer().getTree().setCursor(display.getSystemCursor(SWT.CURSOR_WAIT)); |
| 250 |
savedFilterText = filterText.getText(); |
342 |
savedFilterText = filterText.getText(); |
| 251 |
filterText.setText(WAIT_STRING); |
343 |
filterText.setText(WAIT_STRING); |
| 252 |
} |
344 |
} |
|
Lines 257-262
Link Here
|
| 257 |
if (filterText != null && !filterText.isDisposed() && !filterText.isEnabled()) { |
349 |
if (filterText != null && !filterText.isDisposed() && !filterText.isEnabled()) { |
| 258 |
filterText.setText(filterTextToRestore); |
350 |
filterText.setText(filterTextToRestore); |
| 259 |
filterText.setCursor(null); |
351 |
filterText.setCursor(null); |
|
|
352 |
getViewer().getTree().setCursor(null); |
| 260 |
filterText.setFocus(); |
353 |
filterText.setFocus(); |
| 261 |
filterText.setSelection(filterTextToRestore.length(), filterTextToRestore.length()); |
354 |
filterText.setSelection(filterTextToRestore.length(), filterTextToRestore.length()); |
| 262 |
} |
355 |
} |
|
Lines 297-302
Link Here
|
| 297 |
contentProvider.setSynchronous(true); |
390 |
contentProvider.setSynchronous(true); |
| 298 |
display.asyncExec(new Runnable() { |
391 |
display.asyncExec(new Runnable() { |
| 299 |
public void run() { |
392 |
public void run() { |
|
|
393 |
// We have just loaded all content. Trigger a viewer expand. |
| 394 |
// This really only need be done before filtering, but it can |
| 395 |
// be slow the very first time, so we may as well do it while |
| 396 |
// the user is already waiting rather than after they expect |
| 397 |
// things to be responsive. |
| 398 |
if (getViewer() != null && !getViewer().getTree().isDisposed()) { |
| 399 |
getViewer().expandAll(); |
| 400 |
} |
| 300 |
restoreAfterLoading(savedFilterText); |
401 |
restoreAfterLoading(savedFilterText); |
| 301 |
} |
402 |
} |
| 302 |
}); |
403 |
}); |
|
Lines 339-342
Link Here
|
| 339 |
return; |
440 |
return; |
| 340 |
super.textChanged(); |
441 |
super.textChanged(); |
| 341 |
} |
442 |
} |
|
|
443 |
|
| 444 |
void rememberLeafCheckState() { |
| 445 |
if (!useCheckBoxTree) |
| 446 |
return; |
| 447 |
ContainerCheckedTreeViewer v = (ContainerCheckedTreeViewer) getViewer(); |
| 448 |
Object[] checked = v.getCheckedElements(); |
| 449 |
if (checkState == null) |
| 450 |
checkState = new ArrayList(checked.length); |
| 451 |
for (int i = 0; i < checked.length; i++) |
| 452 |
if (!v.getGrayed(checked[i])) |
| 453 |
checkState.add(checked[i]); |
| 454 |
} |
| 455 |
|
| 456 |
void restoreLeafCheckState() { |
| 457 |
if (!useCheckBoxTree) |
| 458 |
return; |
| 459 |
ContainerCheckedTreeViewer v = (ContainerCheckedTreeViewer) getViewer(); |
| 460 |
if (v == null || v.getTree().isDisposed()) |
| 461 |
return; |
| 462 |
if (checkState == null) |
| 463 |
return; |
| 464 |
|
| 465 |
v.setCheckedElements(new Object[0]); |
| 466 |
v.setGrayedElements(new Object[0]); |
| 467 |
// Now we are only going to set the check state of the leaf nodes |
| 468 |
// and rely on our container checked code to update the parents properly. |
| 469 |
Iterator iter = checkState.iterator(); |
| 470 |
Object element = null; |
| 471 |
while (iter.hasNext()) { |
| 472 |
element = iter.next(); |
| 473 |
if (!v.isExpandable(element)) { |
| 474 |
// setChecked does an internal expand |
| 475 |
v.setChecked(element, true); |
| 476 |
} |
| 477 |
} |
| 478 |
// We are only firing one event, knowing that this is enough for our listeners. |
| 479 |
if (element != null) |
| 480 |
v.fireCheckStateChanged(element, true); |
| 481 |
} |
| 342 |
} |
482 |
} |