78
|
1 /*******************************************************************************
|
|
2 * Copyright (c) 2006, 2007 IBM Corporation and others.
|
|
3 * All rights reserved. This program and the accompanying materials
|
|
4 * are made available under the terms of the Eclipse Public License v1.0
|
|
5 * which accompanies this distribution, and is available at
|
|
6 * http://www.eclipse.org/legal/epl-v10.html
|
|
7 *
|
|
8 * Contributors:
|
|
9 * IBM Corporation - initial API and implementation
|
|
10 *******************************************************************************/
|
|
11 module org.eclipse.jface.internal.databinding.provisional.swt.WorkQueue;
|
|
12
|
|
13 import java.lang.all;
|
|
14
|
|
15 import java.util.HashSet;
|
|
16 import java.util.LinkedList;
|
|
17 import java.util.Set;
|
|
18
|
|
19 import org.eclipse.swt.SWT;
|
|
20 import org.eclipse.swt.widgets.Display;
|
|
21 import org.eclipse.swt.widgets.Event;
|
|
22 import org.eclipse.swt.widgets.Listener;
|
|
23
|
|
24 /**
|
|
25 * NON-API - Helper class to manage a queue of runnables to be posted to the UI thread in a way
|
|
26 * that they are only run once.
|
|
27 * @since 1.1
|
|
28 *
|
|
29 */
|
|
30 public class WorkQueue {
|
|
31
|
|
32 private bool updateScheduled = false;
|
|
33
|
|
34 private bool paintListenerAttached = false;
|
|
35
|
85
|
36 private LinkedList pendingWork;
|
78
|
37
|
|
38 private Display d;
|
|
39
|
85
|
40 private Set pendingWorkSet;
|
78
|
41
|
85
|
42 private Runnable updateJob;
|
|
43 class UpdateJob : Runnable {
|
78
|
44 public void run() {
|
|
45 doUpdate();
|
|
46 updateScheduled = false;
|
|
47 }
|
|
48 };
|
|
49
|
85
|
50 private Listener paintListener;
|
|
51 class PaintListener : Listener {
|
78
|
52 public void handleEvent(Event event) {
|
|
53 paintListenerAttached = false;
|
|
54 d.removeFilter(SWT.Paint, this);
|
|
55 doUpdate();
|
|
56 }
|
|
57 };
|
|
58
|
|
59 /**
|
|
60 * @param targetDisplay
|
|
61 */
|
|
62 public this(Display targetDisplay) {
|
85
|
63 pendingWork = new LinkedList();
|
|
64 pendingWorkSet = new HashSet();
|
|
65 updateJob = new UpdateJob();
|
|
66 paintListener = new PaintListener();
|
78
|
67 d = targetDisplay;
|
|
68 }
|
|
69
|
|
70 private void doUpdate() {
|
|
71 for (;;) {
|
|
72 Runnable next;
|
|
73 synchronized (pendingWork) {
|
|
74 if (pendingWork.isEmpty()) {
|
|
75 break;
|
|
76 }
|
|
77 next = cast(Runnable) pendingWork.removeFirst();
|
85
|
78 pendingWorkSet.remove(cast(Object)next);
|
78
|
79 }
|
|
80
|
|
81 next.run();
|
|
82 }
|
|
83 }
|
|
84
|
|
85 /**
|
|
86 * Schedules some work to happen in the UI thread as soon as possible. If
|
|
87 * possible, the work will happen before the next control redraws. The given
|
|
88 * runnable will only be run once. Has no effect if this runnable has
|
|
89 * already been queued for execution.
|
|
90 *
|
|
91 * @param work
|
|
92 * runnable to execute
|
|
93 */
|
|
94 public void runOnce(Runnable work) {
|
|
95 synchronized (pendingWork) {
|
85
|
96 if (pendingWorkSet.contains(cast(Object)work)) {
|
78
|
97 return;
|
|
98 }
|
|
99
|
85
|
100 pendingWorkSet.add(cast(Object)work);
|
78
|
101
|
|
102 asyncExec(work);
|
|
103 }
|
|
104 }
|
|
105
|
|
106 /**
|
|
107 * Schedules some work to happen in the UI thread as soon as possible. If
|
|
108 * possible, the work will happen before the next control redraws. Unlike
|
|
109 * runOnce, calling asyncExec twice with the same runnable will cause that
|
|
110 * runnable to run twice.
|
|
111 *
|
|
112 * @param work
|
|
113 * runnable to execute
|
|
114 */
|
|
115 public void asyncExec(Runnable work) {
|
|
116 synchronized (pendingWork) {
|
85
|
117 pendingWork.add(cast(Object)work);
|
78
|
118 if (!updateScheduled) {
|
|
119 updateScheduled = true;
|
|
120 d.asyncExec(updateJob);
|
|
121 }
|
|
122
|
|
123 // If we're in the UI thread, add an event filter to ensure
|
|
124 // the work happens ASAP
|
|
125 if (Display.getCurrent() is d) {
|
|
126 if (!paintListenerAttached) {
|
|
127 paintListenerAttached = true;
|
|
128 d.addFilter(SWT.Paint, paintListener);
|
|
129 }
|
|
130 }
|
|
131 }
|
|
132 }
|
|
133
|
|
134 /**
|
|
135 * Cancels a previously-scheduled runnable. Has no effect if the given
|
|
136 * runnable was not previously scheduled or has already executed.
|
|
137 *
|
|
138 * @param toCancel
|
|
139 * runnable to cancel
|
|
140 */
|
|
141 public void cancelExec(Runnable toCancel) {
|
|
142 synchronized (pendingWork) {
|
85
|
143 pendingWork.remove(cast(Object)toCancel);
|
|
144 pendingWorkSet.remove(cast(Object)toCancel);
|
78
|
145 }
|
|
146 }
|
|
147
|
|
148 /**
|
|
149 * Cancels all pending work.
|
|
150 */
|
|
151 public void cancelAll() {
|
|
152 synchronized (pendingWork) {
|
|
153 pendingWork.clear();
|
|
154 pendingWorkSet.clear();
|
|
155 }
|
|
156 }
|
|
157 }
|