This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

View | Details | Raw Unified | Return to bug 165005
Collapse All | Expand All

(-)a/api.progress/apichanges.xml (+24 lines)
Lines 106-111 Link Here
106
106
107
  <changes>
107
  <changes>
108
    <change id="spi">
108
    <change id="spi">
109
        <api name="modal_run_methods"/>
110
        <summary>SPI added</summary>
111
        <version major="1" minor="10"/>
112
        <date day="1" month="2" year="2010"/>
113
        <author login="tboudreau"/>
114
        <compatibility addition="yes"/>
115
        <description>
116
            <p>
117
                Added methods to ProgressUtils for invoking a runnable or
118
                similar with
119
                a modal dialog blocking the UI and showing progress:
120
                <ul>
121
                    <li><code>public static void showProgressDialogAndRun(Runnable operation, String displayName)</code></li>
122
                    <li><code>public static <T> T showProgressDialogAndRun(final ProgressRunnable<T> operation, final String displayName, boolean includeDetailLabel)</code></li>
123
                    <li><code>public static void showProgressDialogAndRun(Runnable operation, ProgressHandle progress, boolean includeDetailLabel</code></li>
124
                </ul>
125
                Added interface ProgressRunnable for performing background
126
                work, and an SPI class ProgressRunOffEdtProvider which is
127
                implemented by the Progress UI module.
128
            </p>
129
        </description>
130
        <issue number="165005"/>
131
    </change>
132
    <change id="spi">
109
        <api name="progress_api"/>
133
        <api name="progress_api"/>
110
        <summary>SPI added</summary>
134
        <summary>SPI added</summary>
111
        <version major="1" minor="18"/>
135
        <version major="1" minor="18"/>
(-)a/api.progress/manifest.mf (-1 / +1 lines)
Lines 3-7 Link Here
3
OpenIDE-Module-Localizing-Bundle: org/netbeans/progress/module/resources/Bundle.properties
3
OpenIDE-Module-Localizing-Bundle: org/netbeans/progress/module/resources/Bundle.properties
4
OpenIDE-Module-Recommends: org.netbeans.modules.progress.spi.ProgressUIWorkerProvider, org.netbeans.modules.progress.spi.RunOffEDTProvider
4
OpenIDE-Module-Recommends: org.netbeans.modules.progress.spi.ProgressUIWorkerProvider, org.netbeans.modules.progress.spi.RunOffEDTProvider
5
AutoUpdate-Essential-Module: true
5
AutoUpdate-Essential-Module: true
6
OpenIDE-Module-Specification-Version: 1.18
6
OpenIDE-Module-Specification-Version: 1.19
7
7
(-)a/api.progress/src/org/netbeans/api/progress/ProgressHandle.java (+6 lines)
Lines 197-202 Link Here
197
        LOG.fine(newDisplayName);
197
        LOG.fine(newDisplayName);
198
        internal.requestDisplayNameChange(newDisplayName);
198
        internal.requestDisplayNameChange(newDisplayName);
199
    }
199
    }
200
201
    String getDisplayName() {
202
        synchronized (internal) {
203
            return internal.getDisplayName();
204
        }
205
    }
200
    
206
    
201
    /**
207
    /**
202
     * have the component in custom location, don't include in the status bar.
208
     * have the component in custom location, don't include in the status bar.
(-)a/api.progress/src/org/netbeans/api/progress/ProgressRunnable.java (+56 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2010 Sun Microsystems, Inc.
38
 */
39
40
package org.netbeans.api.progress;
41
42
/**
43
 * Callable used by ProgressUtils.showProgressDialogAndRun to do background
44
 * work while a modal progress dialog is shown blocking all application windows.
45
 *
46
 * @author Tim Boudreau
47
 */
48
public interface ProgressRunnable<T> {
49
    /**
50
     * Perform the background work
51
     * @param handle A progress handle to post background work progress from.
52
     * The handle, when passed in, has had start() and setToIndeterminate() called.
53
     * @return The result of the background computation
54
     */
55
    public T run(ProgressHandle handle);
56
}
(-)a/api.progress/src/org/netbeans/api/progress/ProgressUtils.java (+96 lines)
Lines 40-46 Link Here
40
package org.netbeans.api.progress;
40
package org.netbeans.api.progress;
41
41
42
import java.util.concurrent.atomic.AtomicBoolean;
42
import java.util.concurrent.atomic.AtomicBoolean;
43
import java.util.concurrent.atomic.AtomicReference;
43
import javax.swing.SwingUtilities;
44
import javax.swing.SwingUtilities;
45
import org.netbeans.modules.progress.spi.ProgressRunOffEdtProvider;
44
import org.netbeans.modules.progress.spi.RunOffEDTProvider;
46
import org.netbeans.modules.progress.spi.RunOffEDTProvider;
45
import org.openide.util.Lookup;
47
import org.openide.util.Lookup;
46
import org.openide.util.RequestProcessor;
48
import org.openide.util.RequestProcessor;
Lines 100-105 Link Here
100
        PROVIDER.runOffEventDispatchThread(operation, operationDescr, cancelOperation, waitForCanceled, waitCursorAfter, dialogAfter);
102
        PROVIDER.runOffEventDispatchThread(operation, operationDescr, cancelOperation, waitForCanceled, waitCursorAfter, dialogAfter);
101
    }
103
    }
102
104
105
    /**
106
     * Show a modal progress dialog that blocks the main window, while running
107
     * the passed runnable on a background thread.
108
     * <p/>
109
     * This method is thread-safe, and will block until the operation has
110
     * completed, regardless of what thread calls this method.
111
     * <p/>
112
     * Unless you are being passed the runnable or progress handle from foreign
113
     * code (such as in WizardDescriptor.progressInstantiatingIterator), it
114
     * is usually simpler to use the version of this method that takes a
115
     * <code>ProgressCallable</code>.
116
     *
117
     * @param operation A runnable to run in the background
118
     * @param progress A progress handle to create a progress bar for
119
     * @param includeDetailLabel True if the caller will use
120
     * ProgressHandle.progress (String, int), false if not.  If true, the
121
     * created dialog will include a label that shows progress details.
122
     */
123
    public static void showProgressDialogAndRun(Runnable operation, ProgressHandle progress, boolean includeDetailLabel) {
124
        if (PROVIDER instanceof ProgressRunOffEdtProvider) {
125
            ProgressRunOffEdtProvider p = (ProgressRunOffEdtProvider) PROVIDER;
126
            p.showProgressDialogAndRun(operation, progress, includeDetailLabel);
127
        } else {
128
            PROVIDER.runOffEventDispatchThread(operation, progress.getDisplayName(), new AtomicBoolean(false), false, 0, 0);
129
        }
130
    }
131
132
    /**
133
     * Show a modal progress dialog that blocks the main window, while running
134
     * the passed runnable on a background thread.
135
     * <p/>
136
     * This method is thread-safe, and will block until the operation has
137
     * completed, regardless of what thread calls this method.
138
     *
139
     * @param <T> The result type - use Void if no return type needed
140
     * @param operation A runnable-like object which performs work in the
141
     * background, and is passed a ProgressHandle to update progress
142
     * @param displayName The display name for this operation
143
     * @param includeDetailLabel If true, include a lable to show progress
144
     * details (needed only if you plan to call ProgressHandle.setProgress(String, int)
145
     * @return The result of the operation.
146
     */
147
    public static <T> T showProgressDialogAndRun(final ProgressRunnable<T> operation, final String displayName, boolean includeDetailLabel) {
148
        if (PROVIDER instanceof ProgressRunOffEdtProvider) {
149
            ProgressRunOffEdtProvider p = (ProgressRunOffEdtProvider) PROVIDER;
150
            return p.showProgressDialogAndRun(operation, displayName, includeDetailLabel);
151
        } else {
152
            final AtomicReference<T> ref = new AtomicReference<T>();
153
            PROVIDER.runOffEventDispatchThread(new Runnable() {
154
                @Override
155
                public void run() {
156
                    ProgressHandle handle = ProgressHandleFactory.createHandle(displayName);
157
                    handle.start();
158
                    handle.switchToIndeterminate();
159
                    try {
160
                        ref.set(operation.run(handle));
161
                    } finally {
162
                        handle.finish();
163
                    }
164
                }
165
            }, displayName, new AtomicBoolean(false), true, 0, 0);
166
            return ref.get();
167
        }
168
    }
169
170
    /**
171
     * Show a modal progress dialog that blocks the main window, while running
172
     * the passed runnable on a background thread with an indeterminate-state
173
     * progress bar.
174
     * <p/>
175
     * This method is thread-safe, and will block until the operation has
176
     * completed, regardless of what thread calls this method.
177
     * .
178
     * @param operation A runnable to run
179
     * @param displayName The display name of the operation, to show in the dialog
180
     */
181
    public static void showProgressDialogAndRun(Runnable operation, String displayName) {
182
        showProgressDialogAndRun(new RunnableWrapper(operation), displayName, false);
183
    }
184
185
186
    private static final class RunnableWrapper implements ProgressRunnable<Void> {
187
        private final Runnable toRun;
188
        RunnableWrapper(Runnable toRun) {
189
            this.toRun = toRun;
190
        }
191
192
        @Override
193
        public Void run(ProgressHandle handle) {
194
            toRun.run();
195
            return null;
196
        }
197
    }
198
103
    private static class Trivial implements RunOffEDTProvider {
199
    private static class Trivial implements RunOffEDTProvider {
104
        private static final RequestProcessor WORKER = new RequestProcessor(ProgressUtils.class.getName());
200
        private static final RequestProcessor WORKER = new RequestProcessor(ProgressUtils.class.getName());
105
201
(-)a/api.progress/src/org/netbeans/modules/progress/spi/ProgressRunOffEdtProvider.java (+79 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2010 Sun Microsystems, Inc.
38
 */
39
40
package org.netbeans.modules.progress.spi;
41
42
import org.netbeans.api.progress.ProgressRunnable;
43
import org.netbeans.api.progress.ProgressHandle;
44
45
/**
46
 * Extension to RunOffEDTProvider which allows for a modal dialog to
47
 * be shown which contains a progress bar.
48
 *
49
 * @author Tim Boudreau
50
 */
51
public interface ProgressRunOffEdtProvider extends RunOffEDTProvider{
52
    /**
53
     * Show a modal progress dialog that blocks the main window while running
54
     * a background process.  This call should block until the work is
55
     * completed.
56
     *
57
     * @param operation A runnable that needs to be run with the UI blocked
58
     * @param handle A progress handle that will be updated to reflect
59
     * the progress of the operation
60
     * @param showDetails If true, a label should be provided in the progress
61
     * dialog to show detailed progress messages
62
     */
63
    void showProgressDialogAndRun(Runnable operation, ProgressHandle handle, boolean showDetails);
64
    /**
65
     * Show a modal progress dialog that blocks the main window while running
66
     * a background process.  This call should block until the work is
67
     * completed.
68
     *
69
     * @param <T> The type of the return value
70
     * @param toRun A ProgressCallable which will be passed a progress handle
71
     * on a background thread, can do its work and (optionally) return a value
72
     * @param displayName The display name of the work being done
73
     * @param includeDetailLabel Show the detail levels.  Set to true if the
74
     * caller will use ProgressHandle.progress (String, int) to provide
75
     * detailed progress messages
76
     * @return The result of the call to ProgressRunnable.call()
77
     */
78
    <T> T showProgressDialogAndRun(ProgressRunnable<T> toRun, String displayName, boolean includeDetailLabel);
79
}
(-)a/progress.ui/manifest.mf (-1 / +1 lines)
Lines 4-8 Link Here
4
OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/progress/ui/Bundle.properties
4
OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/progress/ui/Bundle.properties
5
OpenIDE-Module-Provides: org.netbeans.modules.progress.spi.ProgressUIWorkerProvider, org.netbeans.modules.progress.spi.RunOffEDTProvider
5
OpenIDE-Module-Provides: org.netbeans.modules.progress.spi.ProgressUIWorkerProvider, org.netbeans.modules.progress.spi.RunOffEDTProvider
6
AutoUpdate-Essential-Module: true
6
AutoUpdate-Essential-Module: true
7
OpenIDE-Module-Specification-Version: 1.8
7
OpenIDE-Module-Specification-Version: 1.9
8
8
(-)a/progress.ui/nbproject/project.xml (-1 / +5 lines)
Lines 11-17 Link Here
11
                    <compile-dependency/>
11
                    <compile-dependency/>
12
                    <run-dependency>
12
                    <run-dependency>
13
                        <release-version>1</release-version>
13
                        <release-version>1</release-version>
14
                        <specification-version>1.18</specification-version>
14
                        <specification-version>1.19</specification-version>
15
                    </run-dependency>
15
                    </run-dependency>
16
                </dependency>
16
                </dependency>
17
                <dependency>
17
                <dependency>
Lines 54-59 Link Here
54
                        <code-name-base>org.netbeans.libs.junit4</code-name-base>
54
                        <code-name-base>org.netbeans.libs.junit4</code-name-base>
55
                        <compile-dependency/>
55
                        <compile-dependency/>
56
                    </test-dependency>
56
                    </test-dependency>
57
                    <test-dependency>
58
                        <code-name-base>org.netbeans.modules.nbjunit</code-name-base>
59
                        <compile-dependency/>
60
                    </test-dependency>
57
                </test-type>
61
                </test-type>
58
            </test-dependencies>
62
            </test-dependencies>
59
            <public-packages/>
63
            <public-packages/>
(-)a/progress.ui/src/org/netbeans/modules/progress/ui/RunOffEDTImpl.java (-2 / +262 lines)
Lines 38-48 Link Here
38
 */
38
 */
39
package org.netbeans.modules.progress.ui;
39
package org.netbeans.modules.progress.ui;
40
40
41
import java.awt.BorderLayout;
42
import java.awt.Color;
41
import java.awt.Component;
43
import java.awt.Component;
42
import java.awt.Cursor;
44
import java.awt.Cursor;
43
import java.awt.Dialog;
45
import java.awt.Dialog;
46
import java.awt.Dimension;
47
import java.awt.EventQueue;
48
import java.awt.Font;
49
import java.awt.Frame;
50
import java.awt.Graphics;
51
import java.awt.Graphics2D;
52
import java.awt.GridLayout;
53
import java.awt.RenderingHints;
54
import java.awt.Toolkit;
44
import java.awt.event.ActionEvent;
55
import java.awt.event.ActionEvent;
45
import java.awt.event.ActionListener;
56
import java.awt.event.ActionListener;
57
import java.awt.event.WindowAdapter;
58
import java.awt.event.WindowEvent;
46
import java.util.Map;
59
import java.util.Map;
47
import java.util.WeakHashMap;
60
import java.util.WeakHashMap;
48
import java.util.concurrent.CountDownLatch;
61
import java.util.concurrent.CountDownLatch;
Lines 51-74 Link Here
51
import java.util.concurrent.atomic.AtomicReference;
64
import java.util.concurrent.atomic.AtomicReference;
52
import java.util.logging.Level;
65
import java.util.logging.Level;
53
import java.util.logging.Logger;
66
import java.util.logging.Logger;
67
import javax.swing.BorderFactory;
68
import javax.swing.JComponent;
69
import javax.swing.JDialog;
54
import javax.swing.JFrame;
70
import javax.swing.JFrame;
71
import javax.swing.JLabel;
72
import javax.swing.JPanel;
55
import javax.swing.SwingUtilities;
73
import javax.swing.SwingUtilities;
74
import javax.swing.WindowConstants;
75
import org.netbeans.api.progress.ProgressRunnable;
76
import org.netbeans.api.progress.ProgressHandle;
77
import org.netbeans.api.progress.ProgressHandleFactory;
56
import org.netbeans.api.progress.ProgressUtils;
78
import org.netbeans.api.progress.ProgressUtils;
57
import org.netbeans.modules.progress.spi.RunOffEDTProvider;
79
import org.netbeans.modules.progress.spi.RunOffEDTProvider;
80
import org.netbeans.modules.progress.spi.ProgressRunOffEdtProvider;
58
import org.openide.DialogDescriptor;
81
import org.openide.DialogDescriptor;
59
import org.openide.DialogDisplayer;
82
import org.openide.DialogDisplayer;
60
import org.openide.NotifyDescriptor;
83
import org.openide.NotifyDescriptor;
84
import org.openide.util.Exceptions;
61
import org.openide.util.NbBundle;
85
import org.openide.util.NbBundle;
62
import org.openide.util.Parameters;
86
import org.openide.util.Parameters;
63
import org.openide.util.RequestProcessor;
87
import org.openide.util.RequestProcessor;
88
import org.openide.util.Utilities;
64
import org.openide.windows.WindowManager;
89
import org.openide.windows.WindowManager;
65
90
66
/**
91
/**
67
 * Default RunOffEDTProvider implementation for ProgressUtils.runOffEventDispatchThread() methods
92
 * Default RunOffEDTProvider implementation for ProgressUtils.runOffEventDispatchThread() methods
68
 * @author Jan Lahoda, Tomas Holy
93
 * @author Jan Lahoda, Tomas Holy, Tim Boudreau
69
 */
94
 */
70
@org.openide.util.lookup.ServiceProvider(service = org.netbeans.modules.progress.spi.RunOffEDTProvider.class, position = 100)
95
@org.openide.util.lookup.ServiceProvider(service = org.netbeans.modules.progress.spi.RunOffEDTProvider.class, position = 100)
71
public class RunOffEDTImpl implements RunOffEDTProvider {
96
public class RunOffEDTImpl implements RunOffEDTProvider, ProgressRunOffEdtProvider {
72
97
73
    private static final RequestProcessor WORKER = new RequestProcessor(ProgressUtils.class.getName());
98
    private static final RequestProcessor WORKER = new RequestProcessor(ProgressUtils.class.getName());
74
    private static final Map<Class<? extends Runnable>, Integer> OPERATIONS = new WeakHashMap<Class<? extends Runnable>, Integer>();
99
    private static final Map<Class<? extends Runnable>, Integer> OPERATIONS = new WeakHashMap<Class<? extends Runnable>, Integer>();
Lines 190-193 Link Here
190
            glassPane.setCursor(original);
215
            glassPane.setCursor(original);
191
        }
216
        }
192
    }
217
    }
218
219
    @Override
220
    public void showProgressDialogAndRun(Runnable operation, ProgressHandle handle, boolean includeDetailLabel) {
221
       AbstractWindowRunner wr = new RunnableWindowRunner(operation, handle, includeDetailLabel);
222
       wr.start();
223
       if (!EventQueue.isDispatchThread()) {
224
            try {
225
                wr.await();
226
            } catch (InterruptedException ex) {
227
                Exceptions.printStackTrace(ex);
228
            }
229
       }
230
    }
231
232
    @Override
233
    public <T> T showProgressDialogAndRun(ProgressRunnable<T> toRun, String displayName, boolean includeDetailLabel) {
234
        AbstractWindowRunner<T> wr = new ProgressBackgroundRunner<T>(toRun, displayName, includeDetailLabel);
235
        wr.start();
236
        if (!EventQueue.isDispatchThread()) {
237
             try {
238
                 wr.await();
239
             } catch (InterruptedException ex) {
240
                 Exceptions.printStackTrace(ex);
241
             }
242
        }
243
        return wr.getResult();
244
    }
245
246
    private static abstract class AbstractWindowRunner<T> extends WindowAdapter implements Runnable {
247
        private volatile JDialog dlg;
248
        private final boolean includeDetail;
249
        protected final ProgressHandle handle;
250
        private final CountDownLatch latch = new CountDownLatch(1);
251
        private volatile T operationResult;
252
253
        AbstractWindowRunner(ProgressHandle handle, boolean includeDetail) {
254
            this.includeDetail = includeDetail;
255
            this.handle = handle;
256
        }
257
258
        @Override
259
        public final void windowOpened(WindowEvent e) {
260
            dlg = (JDialog) e.getSource();
261
            RequestProcessor.getDefault().post(this);
262
            grayOutMainWindow();
263
        }
264
265
        @Override
266
        public final void windowClosed(WindowEvent e) {
267
            ungrayMainWindow();
268
            latch.countDown();
269
        }
270
271
        final void await() throws InterruptedException {
272
            latch.await();
273
        }
274
275
        final void start() {
276
            if (EventQueue.isDispatchThread()) {
277
                createModalProgressDialog(handle, includeDetail);
278
            } else {
279
                CountDownLatch dlgLatch = new CountDownLatch(1);
280
                DialogCreator dc = new DialogCreator(dlgLatch);
281
                EventQueue.invokeLater (dc);
282
                try {
283
                    dlgLatch.await();
284
                } catch (InterruptedException ex) {
285
                    throw new IllegalStateException(ex);
286
                }
287
            }
288
        }
289
290
        protected abstract T runBackground();
291
292
        T getResult() {
293
            return operationResult;
294
        }
295
296
        @Override
297
        public void run() {
298
            if (!EventQueue.isDispatchThread()) {
299
                try {
300
                    operationResult = runBackground();
301
                } finally {
302
                    EventQueue.invokeLater(this);
303
                }
304
            } else {
305
                dlg.setVisible(false);
306
                dlg.dispose();
307
            }
308
        }
309
310
        private final class DialogCreator implements Runnable {
311
            private final CountDownLatch latch;
312
            DialogCreator (CountDownLatch latch) {
313
                this.latch = latch;
314
            }
315
316
            @Override
317
            public void run() {
318
                createModalProgressDialog(handle, includeDetail);
319
                latch.countDown();
320
            }
321
        }
322
323
        private JDialog createModalProgressDialog(ProgressHandle handle, boolean includeDetail) {
324
            assert EventQueue.isDispatchThread();
325
            int edgeGap = Utilities.isMac() ? 12 : 8;
326
            int compGap = Utilities.isMac() ? 9 : 5;
327
            JPanel panel = new JPanel(new GridLayout(includeDetail ? 3 : 2, 1, compGap, compGap));
328
            JLabel mainLabel = ProgressHandleFactory.createMainLabelComponent(handle);
329
            Font f = mainLabel.getFont();
330
            if (f != null) {
331
                mainLabel.setFont (f.deriveFont(Font.BOLD));
332
            }
333
            panel.add(mainLabel);
334
335
            JComponent progressBar = ProgressHandleFactory.createProgressComponent(handle);
336
            progressBar.setMinimumSize(new Dimension (400, 32));
337
            panel.add(progressBar);
338
339
            if (includeDetail) {
340
                JLabel details = ProgressHandleFactory.createDetailLabelComponent(handle);
341
                details.setMinimumSize(new Dimension(300, 16));
342
                panel.add(details);
343
            }
344
            panel.setBorder (BorderFactory.createCompoundBorder(
345
                    BorderFactory.createRaisedBevelBorder(),
346
                    BorderFactory.createEmptyBorder(edgeGap, edgeGap, edgeGap, edgeGap)));
347
            panel.setMinimumSize(new Dimension(400, 100));
348
            Frame mainWindow = WindowManager.getDefault().getMainWindow();
349
            JDialog result = new JDialog(mainWindow, true);
350
            result.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
351
            result.setUndecorated(true);
352
            result.setSize(400, 100);
353
            result.getContentPane().setLayout(new BorderLayout());
354
            result.getContentPane().add(panel, BorderLayout.CENTER);
355
            result.pack();
356
            int reqWidth = result.getWidth();
357
            result.setSize(Math.max (reqWidth,
358
                    mainWindow instanceof JFrame ?
359
                        ((JFrame) mainWindow).getContentPane().getWidth() / 3 :
360
                        mainWindow.getWidth()), result.getHeight());
361
            result.setLocationRelativeTo(WindowManager.getDefault().getMainWindow());
362
            result.addWindowListener(this);
363
            result.setVisible(true);
364
            return result;
365
        }
366
367
        private Component oldGlassPane;
368
        private void grayOutMainWindow() {
369
            assert EventQueue.isDispatchThread();
370
            Frame f = WindowManager.getDefault().getMainWindow();
371
            if (f instanceof JFrame) {
372
                Map<?,?> hintsMap = (Map)(Toolkit.getDefaultToolkit().getDesktopProperty("awt.font.desktophints")); //NOI18N
373
                //Avoid translucent painting on, for example, remote X terminal
374
                if (hintsMap == null || !RenderingHints.VALUE_TEXT_ANTIALIAS_OFF.equals(hintsMap.get(RenderingHints.KEY_TEXT_ANTIALIASING))) {
375
                    JFrame jf = (JFrame) f;
376
                    TranslucentMask mask = new TranslucentMask();
377
                    oldGlassPane = jf.getGlassPane();
378
                    jf.setGlassPane(mask);
379
                    mask.setVisible(true);
380
                    mask.setBounds (0, 0, jf.getContentPane().getWidth(), jf.getContentPane().getHeight());
381
                    mask.invalidate();
382
                    mask.revalidate();
383
                    mask.repaint();
384
                    jf.getRootPane().paintImmediately(0, 0, jf.getRootPane().getWidth(), jf.getRootPane().getHeight());
385
                }
386
            }
387
        }
388
389
        private void ungrayMainWindow() {
390
            if (oldGlassPane != null) {
391
                JFrame jf = (JFrame) WindowManager.getDefault().getMainWindow();
392
                jf.setGlassPane(oldGlassPane);
393
                jf.invalidate();
394
                jf.repaint();
395
            }
396
        }
397
    }
398
399
    static final class TranslucentMask extends JComponent { //pkg private for tests
400
        TranslucentMask() {
401
            setVisible(false); //so we will trigger a property change
402
        }
403
404
        @Override
405
        public boolean isOpaque() {
406
            return false;
407
        }
408
409
        @Override
410
        public void paint (Graphics g) {
411
            Graphics2D g2d = (Graphics2D) g;
412
            Color translu = new Color (180, 180, 180, 148);
413
            g2d.setColor(translu);
414
            g2d.fillRect (0, 0, getWidth(), getHeight());
415
        }
416
    }
417
418
    private static final class ProgressBackgroundRunner<T> extends AbstractWindowRunner<T> {
419
        private final ProgressRunnable<T> toRun;
420
        public ProgressBackgroundRunner(ProgressRunnable<T> toRun, String displayName, boolean includeDetail) {
421
            super (ProgressHandleFactory.createHandle(displayName), includeDetail);
422
            this.toRun = toRun;
423
        }
424
425
        @Override
426
        protected T runBackground() {
427
            handle.start();
428
            handle.switchToIndeterminate();
429
            T result;
430
            try {
431
                result = toRun.run(handle);
432
            } finally {
433
                handle.finish();
434
            }
435
            return result;
436
        }
437
    }
438
439
    private static final class RunnableWindowRunner extends AbstractWindowRunner<Void> {
440
        private Runnable toRun;
441
        public RunnableWindowRunner(Runnable toRun, ProgressHandle progress, boolean includeDetail) {
442
            super (progress, includeDetail);
443
            this.toRun = toRun;
444
        }
445
446
        @Override
447
        protected Void runBackground() {
448
            toRun.run();
449
            return null;
450
        }
451
    }
452
193
}
453
}
(-)a/progress.ui/test/unit/src/org/netbeans/modules/progress/ui/RunOffEDTImplTest.java (+310 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2010 Sun Microsystems, Inc.
38
 */
39
40
package org.netbeans.modules.progress.ui;
41
42
import java.awt.EventQueue;
43
import java.awt.Frame;
44
import java.awt.Image;
45
import java.awt.RenderingHints;
46
import java.awt.Toolkit;
47
import java.beans.PropertyChangeListener;
48
import java.util.Map;
49
import java.util.Set;
50
import javax.swing.Action;
51
import javax.swing.JFrame;
52
import org.netbeans.api.progress.ProgressHandle;
53
import org.openide.nodes.Node;
54
import org.openide.util.Exceptions;
55
import org.openide.windows.Mode;
56
import org.openide.windows.TopComponent;
57
import org.openide.windows.TopComponentGroup;
58
import org.openide.windows.WindowManager;
59
import org.junit.After;
60
import static org.junit.Assert.*;
61
import org.junit.AfterClass;
62
import org.junit.Before;
63
import org.junit.BeforeClass;
64
import org.junit.Test;
65
import org.netbeans.api.progress.ProgressRunnable;
66
import org.netbeans.api.progress.ProgressUtils;
67
import org.netbeans.junit.MockServices;
68
import org.openide.windows.Workspace;
69
70
/**
71
 *
72
 * @author Tim Boudreau
73
 */
74
public class RunOffEDTImplTest {
75
76
    public RunOffEDTImplTest() {
77
    }
78
79
    @BeforeClass
80
    public static void setUpClass() throws Exception {
81
    }
82
83
    @AfterClass
84
    public static void tearDownClass() throws Exception {
85
    }
86
87
    @Before
88
    public void setUp() {
89
        MockServices.setServices(WM.class, RunOffEDTImpl.class);
90
    }
91
92
    @After
93
    public void tearDown() {
94
    }
95
96
    private static boolean canTestGlassPane() {
97
        Map<?,?> hintsMap = (Map)(Toolkit.getDefaultToolkit().getDesktopProperty("awt.font.desktophints")); //NOI18N
98
        //Avoid translucent painting on, for example, remote X terminal
99
        return hintsMap == null || !RenderingHints.VALUE_TEXT_ANTIALIAS_OFF.equals(hintsMap.get(RenderingHints.KEY_TEXT_ANTIALIASING));
100
    }
101
102
    @Test
103
    public void testShowProgressDialogAndRun_3args_1_EQ() throws Exception {
104
        EventQueue.invokeAndWait(new Runnable() {
105
106
            @Override
107
            public void run() {
108
                testShowProgressDialogAndRun_3args_1();
109
            }
110
        });
111
    }
112
113
    @Test
114
    public void testShowProgressDialogAndRun_3args_2_EQ() throws Exception {
115
        EventQueue.invokeAndWait(new Runnable() {
116
117
            @Override
118
            public void run() {
119
                testShowProgressDialogAndRun_3args_2();
120
            }
121
        });
122
    }
123
124
    @Test
125
    public void testShowProgressDialogAndRun_3args_1() {
126
        assertEquals ("Done", ProgressUtils.showProgressDialogAndRun(new CB(), "Doing Stuff", true));
127
    }
128
129
    @Test
130
    public void testShowProgressDialogAndRun_3args_2() {
131
        final JFrame jf = (JFrame) WindowManager.getDefault().getMainWindow();
132
        class R implements Runnable {
133
            boolean hasRun;
134
            public void run() {
135
                try {
136
                    Thread.sleep(200);
137
                } catch (InterruptedException ex) {
138
                    Exceptions.printStackTrace(ex);
139
                }
140
                if (canTestGlassPane()) {
141
                    assertTrue (jf.getGlassPane() instanceof RunOffEDTImpl.TranslucentMask);
142
                }
143
                hasRun = true;
144
            }
145
        };
146
        R r = new R();
147
        ProgressUtils.showProgressDialogAndRun(r, "Something");
148
        assertTrue (r.hasRun);
149
    }
150
151
    private class CB implements ProgressRunnable<String> {
152
153
        @Override
154
        public String run(ProgressHandle handle) {
155
            handle.switchToDeterminate(5);
156
            for (int i= 0; i < 5; i++) {
157
                try {
158
                    Thread.sleep(200);
159
                } catch (InterruptedException ex) {
160
                    Exceptions.printStackTrace(ex);
161
                }
162
                handle.progress("Job " + i, i);
163
            }
164
            return "Done";
165
        }
166
167
    }
168
169
    public static final class WM extends WindowManager {
170
        private final JFrame jf = new JFrame ("Main Window");
171
        public WM() {
172
            jf.setVisible(true);
173
        }
174
175
        @Override
176
        public Mode findMode(String name) {
177
            throw new UnsupportedOperationException("Not supported yet.");
178
        }
179
180
        @Override
181
        public Mode findMode(TopComponent tc) {
182
            throw new UnsupportedOperationException("Not supported yet.");
183
        }
184
185
        @Override
186
        public Set<? extends Mode> getModes() {
187
            throw new UnsupportedOperationException("Not supported yet.");
188
        }
189
190
        @Override
191
        public Frame getMainWindow() {
192
            return jf;
193
        }
194
195
        @Override
196
        public void updateUI() {
197
            throw new UnsupportedOperationException("Not supported yet.");
198
        }
199
200
        @Override
201
        protected Component createTopComponentManager(TopComponent c) {
202
            throw new UnsupportedOperationException("Not supported yet.");
203
        }
204
205
        @Override
206
        public Workspace createWorkspace(String name, String displayName) {
207
            throw new UnsupportedOperationException("Not supported yet.");
208
        }
209
210
        @Override
211
        public Workspace findWorkspace(String name) {
212
            throw new UnsupportedOperationException("Not supported yet.");
213
        }
214
215
        @Override
216
        public Workspace[] getWorkspaces() {
217
            throw new UnsupportedOperationException("Not supported yet.");
218
        }
219
220
        @Override
221
        public void setWorkspaces(Workspace[] workspaces) {
222
            throw new UnsupportedOperationException("Not supported yet.");
223
        }
224
225
        @Override
226
        public Workspace getCurrentWorkspace() {
227
            throw new UnsupportedOperationException("Not supported yet.");
228
        }
229
230
        @Override
231
        public TopComponentGroup findTopComponentGroup(String name) {
232
            throw new UnsupportedOperationException("Not supported yet.");
233
        }
234
235
        @Override
236
        public void addPropertyChangeListener(PropertyChangeListener l) {
237
            throw new UnsupportedOperationException("Not supported yet.");
238
        }
239
240
        @Override
241
        public void removePropertyChangeListener(PropertyChangeListener l) {
242
            throw new UnsupportedOperationException("Not supported yet.");
243
        }
244
245
        @Override
246
        protected void topComponentOpen(TopComponent tc) {
247
            throw new UnsupportedOperationException("Not supported yet.");
248
        }
249
250
        @Override
251
        protected void topComponentClose(TopComponent tc) {
252
            throw new UnsupportedOperationException("Not supported yet.");
253
        }
254
255
        @Override
256
        protected void topComponentRequestActive(TopComponent tc) {
257
            throw new UnsupportedOperationException("Not supported yet.");
258
        }
259
260
        @Override
261
        protected void topComponentRequestVisible(TopComponent tc) {
262
            throw new UnsupportedOperationException("Not supported yet.");
263
        }
264
265
        @Override
266
        protected void topComponentDisplayNameChanged(TopComponent tc, String displayName) {
267
            throw new UnsupportedOperationException("Not supported yet.");
268
        }
269
270
        @Override
271
        protected void topComponentHtmlDisplayNameChanged(TopComponent tc, String htmlDisplayName) {
272
            throw new UnsupportedOperationException("Not supported yet.");
273
        }
274
275
        @Override
276
        protected void topComponentToolTipChanged(TopComponent tc, String toolTip) {
277
            throw new UnsupportedOperationException("Not supported yet.");
278
        }
279
280
        @Override
281
        protected void topComponentIconChanged(TopComponent tc, Image icon) {
282
            throw new UnsupportedOperationException("Not supported yet.");
283
        }
284
285
        @Override
286
        protected void topComponentActivatedNodesChanged(TopComponent tc, Node[] activatedNodes) {
287
            throw new UnsupportedOperationException("Not supported yet.");
288
        }
289
290
        @Override
291
        protected boolean topComponentIsOpened(TopComponent tc) {
292
            throw new UnsupportedOperationException("Not supported yet.");
293
        }
294
295
        @Override
296
        protected Action[] topComponentDefaultActions(TopComponent tc) {
297
            throw new UnsupportedOperationException("Not supported yet.");
298
        }
299
300
        @Override
301
        protected String topComponentID(TopComponent tc, String preferredID) {
302
            throw new UnsupportedOperationException("Not supported yet.");
303
        }
304
305
        @Override
306
        public TopComponent findTopComponent(String tcID) {
307
            throw new UnsupportedOperationException("Not supported yet.");
308
        }
309
    }
310
}

Return to bug 165005