views:

297

answers:

2

We have a ViewerFilter for a TableViewer that is a little slow, so to try to give the impression of awesomeness, we wanted to have the viewer wait 500 milliseconds before refreshing the window (otherwise, it was blocking after every key stroke).

Not having any clue what I was doing, I tried creating a class that would check if System.currentTimeMillis() was greater then the time of the last key stroke + 500 from a different thread. This just caused an Invalid thread access exception to be thrown, so I'm lost.

Edit: I was able to use TableViewer.getTable().getDisplay().asyncExec() to sidestep the invalid thread problem, but I don't like my solution, and would love to hear other suggestions.

A: 

Just wrap your code in display.syncExec, something like this:

Display.getDefault().asyncExec(new Runnable() {
 public void run() {
      // check refresh time
      // refresh.
 }
});

You may want to look in to asyncExec too, if syncExec does not meet your needs.

Suraj Chandran
+1  A: 

You might want to try to turn off redraw while updating the viewer.

Viewer.getControl().setRedraw(false);
// update
Viewer.getControl().setRedraw(true);

It can sometimes give a better user experience. You can also schedule a ui-job that you cancel when the user hits a new key or modifies the text. E.g.

class RefreshJob extends WorkbenchJob
{
        public RefreshJob()
        {
            super("Refresh Job");   
            setSystem(true); // set to false to show progress to user
        }

        public IStatus runInUIThread(IProgressMonitor monitor)
        {
            monitor.beginTask("Refreshing", ProgressMonitor.UNKNOWN);
            m_viewer.refresh();
            monitor.done(); 
            return Status.OK_STATUS;
        };
}

and then reschedule the refresh in a separate job.

private RefreshJob              m_refreshJob = new RefreshJob();   
private Text                    m_filterText;
void hookModifyListener()
{
    m_filterText.addModifyListener(new ModifyListener()
    {
        public void modifyText(ModifyEvent e)
        {
            m_refreshJob.cancel();
            m_refreshJob.schedule(500);
        }
    });
}

If the user hits the Enter key you can schedule a refresh job without the delay,

Kire Haglin
Thanks! I ended up actually using both of these concepts, and they're working great.To solve future problems: `monitor.beginTask("Refreshing", ProgressMonitor.UNKNOWN);` should be `IProgressMonitor.UNKNOWN`
mwalling