Ondersteuning voor gemeenschappelijk gebruik van de workbench

In een eerder onderwerp is al uitgelegd dat het JFace-gebruikersinterfaceframework de voortgang van taken in een dialoogvenster kan afbeelden. (Raadpleeg Langdurige bewerkingen voor meer informatie.) In Gemeenschappelijke infrastructuur is de runtime-ondersteuning van het platform voor gemeenschappelijk gebruik en langdurige bewerkingen aan bod gekomen. In dit onderwerp komt u te weten hoe deze infrastructuur door de platformgebruikersinterface uitgebreid wordt met het pakket org.eclipse.ui.progress. Dit pakket levert de gebruikersinterface voor het afbeelden van de voortgang van taken in de workbench en definieert aanvullende ondersteuning voor taken die in de gebruikersinterface-thread worden uitgevoerd.

Eerst komen de verschillende soorten achtergrondbewerkingen aan bod en wordt uitgelegd hoe deze kunnen worden uitgevoerd en worden afgebeeld in de gebruikersinterface van de workbench:


In een omgeving waar meerdere processen gelijktijdig kunnen worden uitgevoerd, is het volgende van belang voor de gebruiker:

Voortgangsservice

De voortgangsservice van de workbench (IProgressService) is de primaire interface voor voortgangsondersteuning door de workbench. U kunt de service ophalen uit de workbench en vervolgens gebruiken om de voortgang af te beelden van zowel achtergrondbewerkingen als bewerkingen die in de gebruikersinterface-thread worden uitgevoerd. Deze klasse fungeert voornamelijk als centraal punt voor uitgevoerde bewerkingen, zodat ontwikkelaars van plugins niet steeds hoeven na te denken over een manier voor het afbeelden van voortgang. Bovendien kan het voortgangsdialoogvenster worden ingezet om conflicten tussen bewerkingen aan te duiden, zodat de gebruiker zelf kan bepalen hoe het probleem moet worden opgelost. Waar mogelijk moeten langdurige bewerkingen worden uitgevoerd met IProgressService#busyCursorWhile:

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

Met deze methode wordt de cursor aanvankelijk gewijzigd in "bezet" en verschijnt een voortgangsdialoogvenster als de uitvoering van de taak langer duurt dan een bepaalde tijddrempelwarde. Het voordeel van deze methode is dat het voortgangsdialoogvenster niet wordt afgebeeld voor kortstondige bewerkingen. Als de bewerking de gebruikersinterface moet bijwerken, kunt u altijd gebruik maken van Display.asyncExec of Display.syncExec voor het uitvoeren van de code waarmee de gebruikersinterface wordt gewijzigd.

Moet een bewerking volledig in de gebruikersinterface-thread worden uitgevoerd, dan moet u IProgressService#runInUI gebruiken. Met deze methode wordt ook een dialoogvenster afgebeeld als de bewerking wordt geblokkeerd en kan de gebruiker actie ondernemen.

   progressService.runInUI(
      PlatformUI.getWorkbench().getProgressService(),
      new IRunnableWithProgress() {
         public void run(IProgressMonitor monitor) {
            // gebruikersinterface-instructies
         }
      },
      Platform.getWorkspace().getRoot());

De derde parameter mag null blijven of moet anders een planregel voor de bewerking zijn. In dit voorbeeld wordt de directory van het werkgebied opgegeven, waardoor het werkgebied niet reageert tijdens het uitvoeren van de gebruikersinterfacebewerking.

U kunt ook een pictogram van de taakcategorie registreren met de voortgangsservice, zodat het pictogram wordt afgebeeld naast de uitgevoerde taak in de voortgangsview. In het onderstaande voorbeeld ziet u hoe de taakcategorie voor automatisch bouwen aan een pictogram wordt gekoppeld:

   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);

Aanduiden dat een onderdeel bezet is

IWorkbenchSiteProgressService bevat API voor het plannen van taken waarmee de presentatie van workbenchonderdelen wordt gewijzigd tijdens de taakuitvoering. Als met uw plugin bewerkingen op de achtergrond worden uitgevoerd die van invloed zijn op de status van een onderdeel, kunt u de taak plannen via het onderdeel. De gebruiker wordt dan geïnformeerd wanneer het onderdeel bezet is. Hier volgt een voorbeeld:

   IWorkbenchSiteProgressService siteService =
      (IWorkbenchSiteProgressService)view.getSite().getAdapter(IWorkbenchSiteProgressService.class);
   siteService.schedule(job, 0 /* nu */, true /* cursor met pijl en zandloper */);

Voortgangseigenschappen van taken

In de workbench worden voortgangseigenschappen voor taken gedefinieerd in IProgressConstants. Deze eigenschappen komen van pas bij het instellen van de presentatie van een taak in de voortgangsview. U kunt in de eigenschappen aangeven dat de taak niet uit de view moet worden gewist nadat deze is voltooid (IProgressConstants#KEEP_PROPERTY) of dat slechts één view per keer mag worden afgebeeld in de view (IProgressConstants#KEEPONE_PROPERTY). U kunt ook een actie aan een taak koppelen (IProgressConstants#ACTION_PROPERTY). Wanneer een actie aan een taak is gekoppeld, wordt in de voortgangsview een hyperlink afgebeeld waarmee de gebruiker de actie kan uitvoeren. U kunt ook achterhalen of een gebruikerstaak wordt afgebeeld in een voortgangsdialoogvenster (IProgressConstants#PROPERTY_IN_DIALOG). Wanneer er een actie beschikbaar is, wordt rechtsonder op de statusbalk een aanduiding afgebeeld. In het volgende voorbeeld worden deze eigenschappen gebruikt:

   Job job = new Job("Instructies uitvoeren") {
         public IStatus run(IProgressMonitor monitor) {
         // Enkele instructies uitvoeren.
         // Houd de voltooide taak alleen in de voortgangsview als het voortgangsdialoogvenster niet wordt afgebeeld.
         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("Resultaten") {
      public void run() {
         // De resultaten afbeelden.
      }
   };
   job.setProperty(IProgressConstants.ACTION_PROPERTY, gotoAction);
   job.setUser(true);
   job.schedule();

Workbenchtaken

Waar mogelijk moeten langdurige bewerkingen buiten de gebruikersinterface-thread om worden uitgevoerd. Wanneer de gebruikersinterface moet worden bijgewerkt, is dit echter niet te voorkomen. In Problemen met threads kunt u zien hoe u dit in zijn werk gaat met SWT Display. Door de workbench wordt een speciale taak gedefinieerd, UIJob, waarvan de methoden worden uitgevoerd in een SWT asyncExec. Voor subklassen van UIJob moet de methode runInUIThread worden geïmplementeerd in plaats van de methode run.

WorkbenchJob is een uitbreiding van UIJob, zodat de taak alleen kan worden gepland of uitgevoerd wanneer de workbench actief is. U moet altijd voorkomen dat de gebruikersinterface-thread zwaar wordt belast, omdat de gebruikersinterface niet wordt vernieuwd tijdens de uitvoering van de gebruikersinterfacetaak.