Suporte Simultâneo do Workbench

Observamos que a estrutura da UI de JFace fornece suporte básico para mostrar o progresso da tarefa em um diálogo (consulte Operações de longa execução para obter detalhes). Em Infra-estrutura de coincidência, revisamos o suporte do tempo execução da plataforma para coincidência e operações de longa execução. Agora observaremos como a UI da plataforma aprimora essa infra-estrutura no pacote de org.eclipse.ui.progress. Esse pacote fornece a UI para mostrar o progresso da tarefa no workbench e define suporte adicional para as tarefas que são executadas no encadeamento da UI.

Primeiro, vamos examinar os diferentes tipos de operações de segundo plano que podem estar em execução e como elas são mostradas na UI do workbench:


Fornecido um ambiente onde várias coisas podem estar em execução ao mesmo tempo, um usuário precisa do seguinte:

Serviço de progresso

O serviço de progresso do workbench (IProgressService) é a interface principal do suporte de progresso do workbench. Pode ser obtido a partir do workbench e, em seguida, utilizado para mostrar progresso para as operações de segundo plano e as operações que são executadas no encadeamento da UI. A finalidade principal dessa classe é fornecer um ponto de compras para execução das operações, removendo a necessidade de desenvolvedores de plug-in para decidir qual mecanismo deve ser utilizado para mostrar progresso em uma determinada situação. Outra vantagem é que o diálogo de progresso mostrado com esses métodos fornece um bom suporte para indicar quando uma operação está bloqueada por outra e fornece o controle do usuário para resolver o conflito. Onde possível, as operações de longa execução devem ser executadas utilizando IProgressService#busyCursorWhile:

   IProgressService progressService = PlatformUI.getWorkbench().getProgressService();
   progressService.busyCursorWhile(new IRunnableWithProgress(){
         public void run(IProgressMonitor monitor) {
         //do non-UI work
      }
   });

Este método inicialmente colocará um cursor ocupado e o substituirá por um diálogo de progresso se a operação durar mais tempo que um limite de tempo especificado. A vantagem desse método sobre o uso de um diálogo de progresso é que, se a operação for de execução curta, o diálogo de progresso não será mostrado. Se a operação precisar atualizar a UI, você sempre poderá utilizar Display.asyncExec ou Display.syncExec para executar o código que modifica a UI.

Se uma operação precisar ser executada na sua totalidade no encadeamento da UI, IProgressService#runInUI deverá ser utilizado. Esse método exibirá um diálogo de progresso se a operação for bloqueada e fornecer controle ao usuário.

   progressService.runInUI(
      PlatformUI.getWorkbench().getProgressService(),
      new IRunnableWithProgress() {
         public void run(IProgressMonitor monitor) {
            //do UI work
         }
      },
      Platform.getWorkspace().getRoot());

O terceiro parâmetro pode ser nulo ou uma regra de planejamento para a operação. Neste exemplo, estamos especificando a raiz do espaço de trabalho que, essencialmente, bloqueará o espaço de trabalho enquanto essa operação da UI é executada.

Também é possível registrar um ícone para uma família de tarefas com o serviço de progresso, para que a visualização do progresso possa mostrar o ícone próximo à tarefa em execução. Aqui está um exemplo que mostra como a auto-construção está associada a seu ícone:

   IProgressService service = PlatformUI.getWorkbench().getProgressService();
   ImageDescriptor newImage = IDEInternalWorkbenchImages.getImageDescriptor(
      IDEInternalWorkbenchImages.IMG_ETOOL_BUILD_EXEC);
   service.registerIconForFamily(newImage, ResourcesPlugin.FAMILY_MANUAL_BUILD);
   service.registerIconForFamily(newImage, ResourcesPlugin.FAMILY_AUTO_BUILD);

Mostrando que uma Peça está Ocupada

IWorkbenchSiteProgressService inclui API para tarefas de planejamento que alteram a aparência de uma parte do workbench enquanto a tarefa está em execução. Se o plug-in estiver executando operações em segundo plano que afetam o estado de uma parte, você poderá planejar a tarefa por meio da parte e o usuário obterá feedback de que a parte está ocupada. A seguir encontra-se um exemplo:

   IWorkbenchSiteProgressService siteService =
      (IWorkbenchSiteProgressService)view.getSite().getAdapter(IWorkbenchSiteProgressService.class);
   siteService.schedule(job, 0 /* now */, true /* use the half-busy cursor in the part */);

Propriedades de Progresso para Tarefas

O workbench define propriedades relacionadas ao progresso para tarefas em IProgressConstants . Elas podem ser utilizadas para controlar como uma tarefa é mostrada na visualização de progresso. Isso pode ser utilizado para dizer à visualização de progresso para manter IProgressConstants#KEEP_PROPERTY) sua tarefa na visualização depois de ter sido concluída ou manter uma (IProgressConstants#KEEPONE_PROPERTY) tarefa de cada vez na visualização. Também é possível associar uma ação (IProgressConstants#ACTION_PROPERTY) a uma tarefa. Quando uma tarefa tem uma ação associada, a visualização de progresso mostra um hyperlink para que um usuário possa executar a ação. Também é possível descobrir se uma tarefa do usuário está sendo mostrada atualmente em um diálogo de progresso IProgressConstants#PROPERTY_IN_DIALOG). Uma sugestão é fornecida na parte inferior direita da linha de status quando uma ação está disponível. O exemplo a seguir utiliza essas propriedades:

   Job job = new Job("Do Work") {
      public IStatus run(IProgressMonitor monitor) {
         // executar algum trabalho.
         // Manter o trabalho concluído na visualização de progresso apenas se não estiver executando no diálogo de progresso
         Boolean inDialog = (Boolean)getProperty(IProgressConstants.PROPERTY_IN_DIALOG);
         if(!inDialog.booleanValue())
            setProperty(IProgressConstants.KEEP_PROPERTY, Boolean.TRUE);
      }
   };
   job.setProperty(IProgressConstants.ICON_PROPERTY, Plugin.getImageDescriptor(WORK_IMAGE));
   IAction gotoAction = new Action("Results") {
   public void run() {
         // show the results
      }
   };
   job.setProperty(IProgressConstants.ACTION_PROPERTY, gotoAction);
   job.setUser(true);
   job.schedule();

Tarefas do Workbench

Onde possível, as operações de longa execução devem ser executadas fora do encadeamento da UI. No entanto, isso não pode ser sempre evitado quando a finalidade da operação é atualizar a UI. Problemas de encadeamento SWT explica como isso pode ser feito utilizando SWT Exibir. O workbench define uma tarefa especial, UIJob, cujo método de execução é executado dentro de um asyncExec de SWT. As subclasses de UIJob devem implementar o método runInUIThread em vez do método de execução.

WorkbenchJob estende UIJob para que a tarefa possa ser somente planejada ou executada quando o workbench está em execução. Como sempre, você deve evitar trabalho excessivo no encadeamento UI porque a UI não será atualizado para a duração da Tarefa da UI.