+ /**
+ * Mod count for delaying post selection changed events.
+ */
+ int postSelectionModCount = 0;
+
+ /**
+ * Last tree selection modification time for implementing a quiet
+ * time for selection changes.
+ */
+ long lastSelectionModTime = System.currentTimeMillis() - 10000;
+
+ /**
+ * Current target time for the selection to be set. Calculated
+ * according to the set quiet time and last selection modification
+ * time.
+ */
+ long selectionSetTargetTime = 0;
+
+ /**
+ * <code>true</code> if delayed selection runnable is current scheduled or
+ * running.
+ */
+ boolean delayedSelectionScheduled = false;
+
+ Runnable SELECTION_DELAY = new Runnable() {
+ @Override
+ public void run() {
+ if (tree.isDisposed())
+ return;
+ long now = System.currentTimeMillis();
+ long waitTimeLeft = selectionSetTargetTime - now;
+ if (waitTimeLeft > 0) {
+ // Not enough quiet time, reschedule.
+ delayedSelectionScheduled = true;
+ tree.getDisplay().timerExec((int) waitTimeLeft, this);
+ } else {
+ // Time to perform selection, stop rescheduling.
+ delayedSelectionScheduled = false;
+ resetSelection();
+ }
+ }
+ };
+
+ private void widgetSelectionChanged(boolean forceSelectionChange) {
+ long modTime = System.currentTimeMillis();
+ long delta = modTime - lastSelectionModTime;
+ lastSelectionModTime = modTime;
+ if (!forceSelectionChange && delta < SELECTION_CHANGE_QUIET_TIME) {
+ long msToWait = SELECTION_CHANGE_QUIET_TIME - delta;
+ selectionSetTargetTime = modTime + msToWait;
+ if (!delayedSelectionScheduled) {
+ delayedSelectionScheduled = true;
+ tree.getDisplay().timerExec((int) msToWait, SELECTION_DELAY);
+ }
+ // Make sure that post selection change events do not fire.
+ ++postSelectionModCount;
+ return;
+ }
+
+ // Immediate selection reconstruction.
+ resetSelection();
+ }
+