Vi har set, hvordan JFace UI-strukturen giver grundlæggende understøttelse til visning af opgavestatus i en dialogboks (der er flere oplysninger i Langvarige
funktioner). I Samtidighedsinfrastruktur gennemgik vi platformens runtime-understøttelse
af samtidighed og langvarige funktioner.
Vi skal nu se på, hvordan platformsbrugergrænsefladen forbedrer infrastrukturen
i pakken org.eclipse.ui.progress. Pakken leverer den brugergrænseflade, der
viser jobstatus på arbejdsbænken, og definerer yderligere understøttelse af job, der udføres i
brugergrænsefladeprogramdelen.
Lad os først se på de forskellige typer baggrundsfunktioner, der kan være i gang, og hvordan de vises på arbejdsbænkens brugergrænseflade:
Brugerinitierede job er dem, som brugeren har udløst. Arbejdsbænken viser automatisk brugerjobbene i en modal statusdialogboks med en knap, som brugeren kan trykke på for at udføre funktionen i baggrunden og fortsætte arbejdet. Der bruges en global indstilling til at angive, om brugerjobbene altid skal udføres i baggrunden. Brugerjob er karakteriseret som sådanne i Job-API'et med (Job#setUser). Eksempler på brugerjob omfatter bygning, udtjekning af et projekt, synkronisering med opbevaringsstedet, eksport af en plugin og søgning.
Automatisk udløste job har en betydning for brugere, men initieres ikke af brugeren. Disse job vises i statusoversigten og på statuslinjen, men en modal statusdialogboks vises ikke, mens jobbene udføres. Eksemplerne omfatter autobygning og planlagt synkronisering.
Systemfunktioner udløses ikke af brugeren og kan betragtes som en platformsimplementeringsdetalje. Disse job oprettes ved at angive systemflaget med (Job#setSystem). Eksempler på systemjob omfatter job, som langsomt udfylder widgets eller beregner dekorationer og annotationer for oversigter.
I et miljø, hvor der kan ske flere ting på samme tid, har en bruger brug for følgende:
Angivelse af, at en langvarig funktion er startet.
Brugerjob vises for brugeren i en statusdialog, som giver tilbagemelding med det samme,
hvorimod automatisk udløste job vises på statuslinjen og i statusoversigten.
Job, der påvirker en del, skal være
planlagte eller registrerede med delen, så arbejdsbænken kan give
brugeren tip om, at der er noget i gang, som påvirker delen.
Angivelse af, at en funktion er afsluttet.
Brugeren ved, hvornår et brugerjob afsluttes, fordi statusdialogboksen lukkes.
Der er forskellige svarmekanismer for ikke-brugerjob.
Hvis jobbet er planlagt eller registreret
med en del, vises delens statustip, når det er færdigt.
Hvis et job returnerer en fejl, vises en fejlindikator nederst til højre på statuslinjen med
et tip om, at der er opstået en fejl.
Indikation af interessante nye resultater eller nye oplysninger, som ikke stjæler fokus ved at bruge en dialogboks.
Et brugerjob kan vise resultatet direkte for brugeren, når funktionen er udført.
Hvad angår ikke-brugerjob anbefales det at bruge en anden måde end en dialogboks til at vise
resultater, så brugeren ikke bliver forstyrret. Der kan f.eks. åbnes en oversigt, når
jobbet starter, og resultaterne kan blive vist i denne oversigt uden at afbryde
brugerens arbejdsgang. Derudover kan der føjes jobegenskaber til jobbet for at
angive, at det skal beholdes i statusvinduet, og at det stiller en funktion til
rådighed, som viser resultatet.
I dette tilfælde vises en advarselsindikator nederst til højre på statuslinjen, når et
job forbliver i statusvinduet og har resultater, som brugeren skal se.
En generel fornemmelse af at kunne styre det, der er i gang, med mulighed for at overvåge og annullere baggrundsfunktioner.
Brugerjob giver den bedste kontrol for brugeren, fordi de er lette at annullere og giver en god
indikation af blokerende eller samtidigt kørende funktioner via skillebladet
Oplysninger i statusdialogboksen. Bemærk, at den forbedrede
statusdialogboks, der indeholder området Oplysninger, kun vises, hvis plugins bruger
IProgressService#busyCursorWhile
eller IProgressService#runInUI.
Derudover giver statusoversigten adgang til igangværende job.
Konsistent rapportering om status fra alle installerede plugins.
Fordelen ved at bruge statusservice-API'et er, at brugerne får en ensartet fremvisning af status.
Arbejdsbænkens statusservice (IProgressService) er den primære grænseflade til arbejdsbænkens statusstøtte. Den kan hentes fra arbejdsbænken og derefter bruges til at vise status for baggrundsfunktioner og funktioner, som udføres i brugergrænsefladens programdel. Hovedformålet med klassen er at tilvejebringe et enkelt sted til udførelse af funktioner, som fjerner behovet for, at plugin-udviklere skal beslutte, hvilken mekanisme der skal bruges til at vise status i en given situation. En anden fordel er, at den statusdialogboks, som vises med disse metoder, giver god understøttelse til at angive, hvornår en funktion er blokeret af en anden, og giver brugeren mulighed for at løse konflikten. Hvor det er muligt, bør langvarige funktioner udføres med IProgressService#busyCursorWhile:
IProgressService progressService = PlatformUI.getWorkbench().getProgressService(); progressService.busyCursorWhile(new IRunnableWithProgress(){ public void run(IProgressMonitor monitor) { //do non-UI work } });
Metoden sætter som udgangspunkt en markør for optaget og erstatter den med en statusdialogboks, hvis funktionen tager længere tid end den angivne tidsgrænse. Fordelen med denne metode i modsætning til at bruge en statusdialogboks er, at statusdialogboksen ikke bliver vist, hvis funktionen er kortvarig. Du kan altid bruge Display.asyncExec eller Display.syncExec til at udføre den kode, der ændrer brugergrænsefladen, hvis din funktion skal opdatere brugergrænsefladen.
Hvis en funktion skal udføres i sin helhed i brugergrænsefladens programdel, skal du bruge IProgressService#runInUI. Denne metode viser også en statusdialogboks, hvis funktionen er blokeret og overgiver kontrollen til brugeren.
progressService.runInUI( PlatformUI.getWorkbench().getProgressService(), new IRunnableWithProgress() { public void run(IProgressMonitor monitor) { //do UI work } }, Platform.getWorkspace().getRoot());
Den tredje parameter kan være NULL eller en planlægningsrute for funktionen. I dette eksempel angiver vi den rod for arbejdsområdet, der som udgangspunkt låser arbejdsområdet, men dens brugergrænsefladefunktion er i gang.
Du kan også registrere en ikon for en jobserie med statusservicen, så statusoversigten kan vise ikonen ved siden af det igangværende job. Det følgende er et eksempel på, hvordan jobserien til autobygning er knyttet til dens ikon: ½
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 indeholder API til planlægning af job, der ændrer udseendet af en arbejdsbænksdel, mens jobbet er i gang. Hvis din plugin udfører baggrundsfunktioner, som påvirker tilstanden af en del, kan du planlægge jobbet via delen, og brugeren får tilbagemelding om, at delen er optaget. Her er et eksempel:
IWorkbenchSiteProgressService siteService = (IWorkbenchSiteProgressService)view.getSite().getAdapter(IWorkbenchSiteProgressService.class); siteService.schedule(job, 0 /* now */, true /* use the half-busy cursor in the part */);
Arbejdsbænken definerer statusrelaterede egenskaber for job i IProgressConstants. De kan bruges til at styre, hvordan et job vises i statusoversigten. De kan også bruges til at fortælle statusoversigten, at jobbet skal forblive i oversigten (IProgressConstants#KEEP_PROPERTY), når det er afsluttet, eller der kun skal være ét job i oversigten ad gangen (IProgressConstants#KEEPONE_PROPERTY). Du kan også knytte en funktion (IProgressConstants#ACTION_PROPERTY) til et job. Når et job har en tilknyttet funktion, viser statusoversigten et hyperlink, så brugeren kan udføre funktionen. Du kan også finde ud af, om der i øjeblikket vises et brugerjob i en statusdialogboks (IProgressConstants#PROPERTY_IN_DIALOG). Der vises et tip nederst til højre på statuslinjen, når en funktion er tilgængelig. Følgende eksempel bruger egenskaberne:
Job job = new Job("Do Work") { public IStatus run(IProgressMonitor monitor) { // do some work. // Keep the finished job in the progress view only if it is not running in the progress dialog 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();
Hvor det er muligt, bør langvarige funktioner udføres uden for brugergrænsefladens programdel. Det kan imidlertid ikke altid undgås, hvis funktionen har til formål at opdatere brugergrænsefladen. Afsnittet Bemærkninger om programdele forklarer, hvordan det gøres ved hjælp af Display i SWT. Arbejdsbænken definerer et specialjob, UIJob, hvis run-metode udføres inde i en SWT asyncExec. Underklasser af UIJob skal implementere metoden runInUIThread i stedet for run-metoden.
WorkbenchJob udvider UIJob, så jobbet kun kan planlægges eller udføres, når arbejdsbænken er i gang. Du bør som altid undgå for meget arbejde i brugergrænsefladens programdel, fordi brugergrænsefladen ikke opfriskes, mens brugergrænsefladejobbet er i gang.