|
15 | 15 | import org.eclipse.jdt.annotation.Nullable; |
16 | 16 | import org.eclipse.jface.action.IStatusLineManager; |
17 | 17 | import org.eclipse.jface.viewers.IStructuredSelection; |
| 18 | +import org.eclipse.swt.SWT; |
18 | 19 | import org.eclipse.swt.SWTException; |
| 20 | +import org.eclipse.swt.events.ModifyEvent; |
| 21 | +import org.eclipse.swt.events.ModifyListener; |
19 | 22 | import org.eclipse.swt.graphics.Point; |
20 | 23 | import org.eclipse.swt.graphics.Rectangle; |
21 | 24 | import org.eclipse.swt.widgets.Display; |
| 25 | +import org.eclipse.swt.widgets.Event; |
22 | 26 | import org.eclipse.swt.widgets.Shell; |
23 | 27 | import org.eclipse.ui.IEditorReference; |
24 | 28 | import org.eclipse.ui.IViewPart; |
@@ -57,6 +61,45 @@ public static void center(final Shell shell) { |
57 | 61 | shell.setLocation(new Point(x, y)); |
58 | 62 | } |
59 | 63 |
|
| 64 | + public static ModifyListener debounce(final int delayMS, final ModifyListener listener) { |
| 65 | + final int delay = Math.max(0, delayMS); |
| 66 | + return new ModifyListener() { |
| 67 | + private static final Runnable NOOP = () -> { /* empty lambda to avoid null checks */ }; |
| 68 | + private Runnable fireModifyText = NOOP; |
| 69 | + |
| 70 | + @Override |
| 71 | + public void modifyText(final ModifyEvent ev) { |
| 72 | + final var display = ev.display; |
| 73 | + final var widget = ev.widget; |
| 74 | + |
| 75 | + // Cancel the previously scheduled task, if any |
| 76 | + if (fireModifyText != NOOP) { |
| 77 | + display.timerExec(-1, fireModifyText); |
| 78 | + } |
| 79 | + |
| 80 | + fireModifyText = () -> { |
| 81 | + if (widget.isDisposed()) |
| 82 | + return; |
| 83 | + try { |
| 84 | + // create a fresh event so downstream code doesn't see a stale one |
| 85 | + final var newEv = new Event(); |
| 86 | + newEv.type = SWT.Modify; |
| 87 | + newEv.widget = widget; |
| 88 | + newEv.display = display; |
| 89 | + newEv.time = (int) (System.currentTimeMillis() & 0x7fff_ffff); |
| 90 | + listener.modifyText(new ModifyEvent(newEv)); |
| 91 | + } finally { |
| 92 | + // drop references quickly |
| 93 | + fireModifyText = NOOP; |
| 94 | + } |
| 95 | + }; |
| 96 | + |
| 97 | + // schedule after debounce delay |
| 98 | + display.timerExec(delay, fireModifyText); |
| 99 | + } |
| 100 | + }; |
| 101 | + } |
| 102 | + |
60 | 103 | @SuppressWarnings("unchecked") |
61 | 104 | public static @Nullable <T extends IViewPart> T findView(final String viewId) { |
62 | 105 | try { |
|
0 commit comments