All Downloads are FREE. Search and download functionalities are using the official Maven repository.

editor.util.BackgroundOperation Maven / Gradle / Ivy

There is a newer version: 1.18.1
Show newest version
package editor.util;

import javax.swing.*;
import java.awt.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class BackgroundOperation
{
  private static BackgroundOperation g_instance;
  private ExecutorService _jobRunner;


  public static BackgroundOperation instance()
  {
    if( g_instance == null )
    {
      g_instance = new BackgroundOperation();
    }
    return g_instance;
  }

  private BackgroundOperation()
  {
  }

  /**
   * Sets the mouse cursor to the wait cursor, blocks input, and queues the runnable
   * up in the ExecutorService.
   */
  public void doBackgroundWaitOp( final Runnable run )
  {
    doBackgroundOp( run, true );
  }

  /**
   * Runs a job in a background thread, using the ExecutorService, and optionally
   * sets the cursor to the wait cursor and blocks input.
   */
  public void doBackgroundOp( final Runnable run, final boolean showWaitCursor )
  {
    final Component[] key = new Component[1];
    ExecutorService jobRunner = getJobRunner();
    if( jobRunner != null )
    {
      jobRunner.submit( () -> performBackgroundOp( run, key, showWaitCursor ) );
    }
    else
    {
      run.run();
    }
  }

  void performBackgroundOp( Runnable run, final Component[] key, boolean showWaitCursor )
  {
    if( showWaitCursor )
    {
      SwingUtilities.invokeLater( () -> key[0] = EditorUtilities.showWaitCursor( true ) );
    }

    try
    {
      run.run();
    }
    finally
    {
      if( showWaitCursor )
      {
        SwingUtilities.invokeLater( () -> EditorUtilities.showWaitCursor( false, key[0] ) );
      }
    }
  }

  /**
   * Returns the instance of the job dispatcher, used for scheduling time-consuming
   * operations (element state updates) on a separate thread.
   */
  private ExecutorService getJobRunner()
  {
    if( _jobRunner == null )
    {
      _jobRunner = Executors.newSingleThreadExecutor();
    }
    return _jobRunner;
  }


  /**
   * Pumps through all current events in the background operation queue.  Note that this is *NOT* a settle.
   * Any operations added after this method is invoked will not be executed.
   */
  public void waitOnBackgroundOp()
  {
    ExecutorService jobRunner = getJobRunner();
    if( jobRunner != null )
    {
      final Object wait = new Object();
      synchronized( wait ) //## wtf?
      {
        BackgroundOperation.instance().doBackgroundOp( () -> {
          synchronized( wait )
          {
            wait.notifyAll();
          }
        }, false );

        try
        {
          wait.wait();
        }
        catch( InterruptedException e )
        {
          //ignore
        }
      }
    }
  }

  public void waitOnBackgroundOp( long timeout )
  {
    Thread waiter = new Thread( this::waitOnBackgroundOp, "Background Operation Waiter" );
    waiter.start();
    try
    {
      waiter.join( timeout );
    }
    catch( InterruptedException ex )
    {
      //ignore
    }
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy