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:
Tarefas iniciadas pelo usuário são aquelas que o usuário acionou. O workbench mostrará automaticamente as tarefas do usuário em um diálogo do progresso com um botão para permitir que o usuário execute a operação no segundo plano e continue trabalhando. Uma preferência global é utilizada para indicar se as tarefas do usuário sempre serão executadas em segundo plano. Tarefas de usuário são indicadas como tal na API da Tarefa, utilizando o (Job#setUser). Exemplos de tarefas do usuário incluem construção, registro de saída do projeto, sincronização com o repositório, exportação de um plug-in e procura.
Tarefas acionadas automaticamente têm um significado para os usuários, mas não são iniciadas pelo usuário. Essas tarefas são mostradas na visualização do progresso e na linha de status, mas um diálogo de progresso modal não é mostrado quando elas são executadas. Os exemplos incluem a autoconstrução e a sincronização planejada.
As operações do sistema não são acionadas pelo usuário e podem ser consideradas como um detalhe de implementação da plataforma. Essas tarefas são criadas configurando o sinalizador do sistema, utilizando (Job#setSystem). Os exemplos das tarefas do sistema incluem tarefas que lentamente ocupam widgets ou computam decorações e anotações para visualizações.
Fornecido um ambiente onde várias coisas podem estar em execução ao mesmo tempo,
um usuário precisa do seguinte:
Indicação do tempo desde o início da operação.
As tarefas do usuário são mostradas para o usuário em um diálogo de progresso fornecendo
feedback imediato, enquanto que as tarefas acionadas automaticamente são mostradas na linha de
status e na visualização de progresso. Tarefas que afetam uma parte devem ser
planejadas ou registradas com a parte
para que o workbench possa fornecer sugestões ao usuário de que
algo está em execução e afeta a parte.
Indicação de que uma operação foi encerrada.
O usuário pode facilmente saber quando as tarefas do usuário terminam porque o diálogo de progresso é fechado. Para tarefas que não são do usuário, há dois mecanismos de feedback disponíveis. Se a tarefa estiver planejada ou
registrada com uma parte, a sugestão do progresso mostrará quando
ela é concluída. Se uma tarefa retorna um erro, um indicador de erro aparecerá na parte inferior direita da linha de status, mostrando uma sugestão que um erro ocorreu.
Indicação de novos resultados interessantes ou de novas informações, sem tirar o foco, utilizando um diálogo.
Uma tarefa do usuário pode mostrar diretamente os resultados para o usuário quando a operação é
concluída. Para tarefas que não são do usuário, é recomendável utilizar algo diferente de um diálogo para mostrar resultados, para que o usuário não seja interrompido. Por exemplo, uma visualização pode ser aberta quando a tarefa iniciar e os resultados serem mostrados nessa visualização sem interromper o fluxo de trabalho do usuário. Além disso, propriedades da tarefa podem ser incluídas na tarefa para indicar que ela deve ser mantida na visualização de progresso e fornecer uma ação que mostrará os resultados. Nesse caso, uma indicação de aviso aparecerá no canto inferior direito
da linha de status quando uma tarefa permanecer na visualização de progresso e
tiver resultados para mostrar ao usuário.
Um sentimento geral de estar no controle do que está em execução, com a habilidade de monitorar e cancelar as operações de segundo plano.
As tarefas do usuário fornecem o melhor controle para o usuário, pois são facilmente
canceladas e fornecem uma forte indicação de bloqueio ou de operações simultâneas
em execução por meio da guia Detalhes do diálogo de progresso. Observe que o diálogo de progresso aprimorado que fornece a área Detalhes é mostrado apenas quando plug-ins
utilizam IProgressService#busyCursorWhile
ou IProgressService#runInUI.
Além disso, a visualização de progresso fornece acesso às tarefas que estão em execução.
Relatórios consistentes sobre o progresso por todos os plug-ins instalados.
A vantagem de utilizar a API do serviço de progresso é que os usuários obtêm uma experiência de progresso consistente.
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);
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 */);
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();
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.