Bug 165005 - Simple way to show modal progress w/ background runnable
Simple way to show modal progress w/ background runnable
Status: RESOLVED FIXED
Product: platform
Classification: Unclassified
Component: Progress
6.x
All All
: P3 (vote)
: 6.x
Assigned To: _ tboudreau
issues@platform
: API, API_REVIEW_FAST
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2009-05-12 22:06 UTC by _ tboudreau
Modified: 2010-02-10 02:19 UTC (History)
4 users (show)

See Also:
Issue Type: ENHANCEMENT
:


Attachments
Patch to enhance API & implementation as described in previous comment (38.85 KB, patch)
2010-01-31 16:55 UTC, _ tboudreau
Details | Diff
Patch to Java Card modules to use this API and delete the internal equivalent (16.23 KB, patch)
2010-01-31 23:25 UTC, _ tboudreau
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description _ tboudreau 2009-05-12 22:06:00 UTC
I frequently need to block the UI and show progress while running a background task.  This involves a bunch of
complicated code that can easily be abstracted into a static method you just pass a Runnable and ProgressHandle into. 
Would be nice to see this become API either in the progress API or elsewhere:

    public static JDialog createModalProgressDialog(ProgressHandle handle, boolean includeDetail) {
        assert EventQueue.isDispatchThread();
        JPanel panel = new JPanel();
        panel.setLayout(new BorderLayout());
        panel.add(ProgressHandleFactory.createMainLabelComponent(handle), BorderLayout.SOUTH);
        panel.add(ProgressHandleFactory.createProgressComponent(handle), BorderLayout.CENTER);
        panel.setBorder(BorderFactory.createEmptyBorder(12, 12, 12, 12));
        panel.setSize(new Dimension(400, 100));
        panel.setPreferredSize(new Dimension(400, 50));
        JDialog dlg = new JDialog(WindowManager.getDefault().getMainWindow(), true);
        dlg.setSize(400, 100);
        dlg.getContentPane().setLayout(new BorderLayout());
        dlg.getContentPane().add(panel, BorderLayout.CENTER);
        if (includeDetail) {
            dlg.getContentPane().add(ProgressHandleFactory.createDetailLabelComponent(handle));
        }
        dlg.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
        dlg.setAlwaysOnTop(true);
        dlg.setLocationRelativeTo(WindowManager.getDefault().getMainWindow());
        return dlg;
    }

    public static void showProgressDialogAndRun (final ProgressHandle handle, final Runnable run, boolean includeDetail) {
        final JDialog dlg = createModalProgressDialog(handle, includeDetail);
        class WR extends WindowAdapter implements Runnable {

            public void run() {
                if (!EventQueue.isDispatchThread()) {
                    try {
                        run.run();
                    } finally {
                        EventQueue.invokeLater(this);
                    }
                } else {
                    dlg.setVisible(false);
                    dlg.dispose();
                }
            }

            @Override
            public void windowOpened(WindowEvent e) {
                RequestProcessor.getDefault().post(this);
            }
        }
        WR wr = new WR();
        dlg.addWindowListener(wr);
        dlg.setVisible(true);
    }
Comment 1 _ tboudreau 2010-01-31 16:48:46 UTC
It adds an optional interface, ProgressRunOffEdtProvider, which extends the existing RunOffEDTProvider and adds two methods:

void showProgressDialogAndRun(Runnable operation, ProgressHandle handle, boolean showDetails);
<T> T showProgressDialogAndRun(ProgressRunnable<T> toRun, String displayName, boolean includeDetailLabel);

extends the existing RunOffEDTImpl to implement it, and adds three methods to ProgressUtils:

public static void showProgressDialogAndRun(Runnable operation, ProgressHandle progress, boolean includeDetailLabel)
public static <T> T showProgressDialogAndRun(final ProgressRunnable<T> operation, final String displayName, boolean includeDetailLabel)
public static void showProgressDialogAndRun(Runnable operation, String displayName)

and an interface, ProgressRunnable, which has one method
<T> T run(ProgressHandle handle);

This will replace a number of uses of org.netbeans.modules.javacard.common.GuiUtils in various Java Card modules.  Could also be useful for a number of other operations such as saving project properties, which currently do the same thing with custom code.
Comment 2 _ tboudreau 2010-01-31 16:55:19 UTC
Created attachment 93694 [details]
Patch to enhance API & implementation as described in previous comment

Attaching patch w/ compatible API changes and tests
Comment 3 _ tboudreau 2010-01-31 16:57:12 UTC
BTW, all three added methods to ProgressUtils are thread-safe and will block until the background work has completed, no matter what thread they are called from (w/ tests to check this behavior).
Comment 4 _ tboudreau 2010-01-31 23:25:35 UTC
Created attachment 93697 [details]
Patch to Java Card modules to use this API and delete the internal equivalent
Comment 5 Jaroslav Tulach 2010-02-01 08:31:23 UTC
Y01 Be consistent when referring to EDT. Compare: "RunOffEDTProvider, ProgressRunOffEdtProvider". Possibly rename the new interface to RunOffEDTProvider.Progress

Y02 Missing @since tags on new methods

Y03 javacard modules need updated dependency on api.progress
Comment 6 David Simonek 2010-02-01 09:22:46 UTC
Just one minor comment from me - is making main window gray really needed? I mean, OS like Ubuntu uses graying as signalization that application stopped responding and users may be confused. No strong opinion on this though.
Comment 7 greggwon 2010-02-01 11:07:16 UTC
Tim, would you be willing to look at the code that I've put up in issue

https://netbeans.org/bugzilla/show_bug.cgi?id=175342

and see if you'd be willing to put all of this together into one package?  I'd really like to see a lot more formal framework for event handling happen that makes it very easy and practical to get things set up correctly to use the EDT only when it needs to be, and background threads for everything else.
Comment 8 _ tboudreau 2010-02-01 15:14:18 UTC
@Y01 & @Y02: RunOffEDTProvider.Progress would be fine.  Would prefer to rename RunOffEDTProvider to RunOffEdtProvider (capitalizing acronyms in class names makes it hard to see where the acronym ends - i.e. it is EDT not EDTP - since I broke our CVS repository for 3 days once by renaming HTMLRenderer to HtmlRenderer at Jesse's suggestion, I will never forget it)

@Dafe:  Perhaps the color should be L&F-specific, so it does not confuse users with Ubuntu's behavior?  Since we are using a non-decorated window (and I would like to keep it that way - title-bar is useless in this case), it can be a little non-obvious what is happening otherwise.  This has also become the convention in a lot of web applications that create fake modal dialogs using Javascript, so it is likely to be clear what is happening.  There is already a test to avoid using translucency if text antialiasing is off (a likely sign that it is VNC or remote X or similar).

@Gregg:  See my comments in issue #175342.  A general mechanism for this sort of thing would be nice, but seems out of scope for this issue.  Given the diminished size of the core tem, merging these two into one would likely guarantee that neither issue gets integrated for 6.9.
Comment 9 Jaroslav Tulach 2010-02-02 01:14:53 UTC
Re. Y01: Use RunOffEDTProvider.Progress then.
Comment 10 _ tboudreau 2010-02-09 00:45:27 UTC
Integrated in main/ 3a4848d4fd0
Comment 11 Quality Engineering 2010-02-10 02:19:10 UTC
Integrated into 'main-golden', will be available in build *201002100200* on http://bits.netbeans.org/dev/nightly/ (upload may still be in progress)
Changeset: http://hg.netbeans.org/main/rev/3a4848d4fd0f
User: Tim Boudreau <tboudreau@netbeans.org>
Log: #165005 - Ability to use progress API w/ blocking modal dialog showing progress


By use of this website, you agree to the NetBeans Policies and Terms of Use. © 2012, Oracle Corporation and/or its affiliates. Sponsored by Oracle logo