Wat is het nut van het gebruiken van een viewer, nu gebleken is dat de UI-bijdragen van de workbench, bijvoorbeeld views, editors, wizards en dialoogvensters direct kunnen worden geïmplementeerd met SWT-widgets?
Met viewers kunt u widgets maken terwijl u uw modelobjecten kunt blijven gebruiken. Als u een SWT-widget direct gebruikt, moet u de objecten converteren naar de tekenreeksen en afbeeldingen die door SWT worden verwacht. Viewers gedragen zich als adapters met SWT-widgets, waarbij de algemene code voor het afhandelen van widgetevents wordt gebruikt die u anders zelf zou moeten implementeren.
Eerder werd een viewer besproken in de viewbijdrage van de Readme-tool in de ReadmeSectionsView.
public void createPartControl(Composite parent) { viewer = new ListViewer(parent); ... }
Opmerking: Viewers kunnen worden gebruikt om de implementatie te leveren voor zowel workbenchviews als -editors. De term viewer impliceert niet dat deze alleen nuttig is voor het implementeren van views. De TextViewer wordt bijvoorbeeld gebruikt voor de implementatie in veel van de workbench- en plugineditors.
JFace levert viewers voor de meeste niet-triviale widgets in SWT. Viewers worden vooral gebruikt voor lijst-, boom-, tabel- en tekstwidgets.
Elke viewer heeft een bijbehorende SWT-widget. Deze widget kan impliciet worden gemaakt door het bovenliggende item Samengesteld te leveren in een viewerconstructor of expliciet door de widget eerst te maken en vervolgens te leveren aan de viewer in de constructor.
Lijsten, bomen en tabellen delen vele gemeenschappelijke voorzieningen vanuit het gezichtspunt van de gebruiker, bijvoorbeeld het vullen met objecten, selectie, sorteren en filteren.
Deze viewers bewaren een lijst met domeinobjecten (worden elementen genoemd) en geven deze weer in de bijbehorende SWT-widget. Een lijstviewer kan een tekstlabel ophalen uit elk element van de lijst. De viewer verkrijgt het label van een ILabelProvider die kan worden ingesteld op de viewer. Lijstviewers kunnen toewijzen van de widget-callbackmethoden naar de wereld van de elementen die bekend is voor de viewerclients.
De clients die normale SWT-widgets gebruiken, moeten functioneren op het SWT-niveau, waar de items tekenreeksen zijn en events vaak in verband staan met een index binnen de tekenreeksenlijst. De viewers leveren semantiek op een hoger niveau. De clients krijgen een melding bij selecties van en wijzigingen aan de lijst met de elementen die de clients aan de viewer hebben geleverd. De viewer verwerkt al het geestdodende werk voor het terug toewijzen van indexen aan de elementen, het aanpassen voor een gefilterde view van de objecten en het opnieuw sorteren wanneer dit nodig is.
Het filteren en sorteren wordt afgehandeld door het aanwijzen van een viewersorteerder (ViewerSorter) en/of een viewerfilter (ViewerFilter) voor de viewer. (Behalve voor de lijstviewers, kunnen deze worden opgegeven voor de boom- en tabelviewers.) De client hoeft alleen een klasse te leveren die de objecten in de lijst vergelijkt of filtert. De viewer verwerkt de details van het vullen van de lijst volgens de opgegeven volgorde en filter en van het onderhouden van de volgorde en filter wanneer de elementen worden toegevoegd en verwijderd.
Viewers zijn niet bedoeld voor uitbreiding door clients. Om een viewer aan te passen, kunt u deze configureren met uw eigen content- en labelproviders.
Een ListViewer wijst elementen in een lijst toe aan een SWT-Lijst-besturing.
Een TreeViewer geeft hiërarchisch objecten weer in een SWT- Boomstructuur-widget. Deze verwerkt de details voor het uitbreiden en samenvouwen van de items. Er zijn verschillende soorten boomstructuurviewers voor verschillende SWT-boombesturingsfuncties (eenvoudige boomstructuur, tabellenboomstructuur, selectievakjesboomstructuur).
Een TableViewer lijkt erg op een lijstviewer, maar voegt het vermogen toe verschillende kolommen met informatie over elk element in de tabel te kunnen bekijken. Tabelviewers breiden de functie van de SWT-tabelwidget aanzienlijk uit door het introduceren van het concept van celbewerking. Speciale cel-editors kunnen worden gebruikt om het mogelijk te maken voor de gebruiker een tabelcel te bewerken met behulp van een keuzelijst met invoerveld, een dialoogvenster of een tekstwidget. De tabelviewer handelt het maken en plaatsen van deze widgets af wanneer deze vereist zijn voor bewerking door de gebruiker. Dit wordt uitgevoerd door gebruik te maken van de CellEditor-klassen, bijvoorbeeld TextCellEditor en CheckboxCellEditor. Als een virtuele tabel die alleen wordt gevuld wanneer deze wordt bekeken, verwerkt de tabelviewer alleen een aangewezen aantal resultaten, onafhankelijk van wat er in werkelijkheid is gemaakt. De database vraagt "slechts" JIT aan en vraagt alleen een vooraf vastgesteld aantal tegelijk op.
Tekstwidgets hebben veel gemeenschappelijke semantiek, bijvoorbeeld het gedragspatroon bij dubbelklikken, ongedaan maken, inkleuren en navigeren via index of regels. Een TextViewer is een adapter voor een SWT-StyledText- widget.Tekstviewers leveren een documentmodel aan de client en beheren de conversie van het document naar de gestileerde tekstinformatie die wordt geleverd door de tekstwidget.
Tekstviewers worden meer gedetailleerd behandeld in Workbencheditors.
Om een viewer te kunnen begrijpen, is het belangrijk dat u bekend raakt met de relatie tussen het invoerelement van de viewer, de content, de selectie en de informatie die uiteindelijk wordt weergegeven in de widget die wordt gemanipuleerd.
Een invoerelement is het hoofdobject dat door de viewer wordt weergegeven (of bewerkt). Voor wat betreft de viewer, kan een invoerelement elk willekeurig object zijn. Door de viewer wordt niet aangenomen dat een bepaalde interface is geïmplementeerd door het invoerelement. (Later wordt bij de bespreking van de contentproviders duidelijk waarom)
Een viewer moet een wijziging van een invoerelement kunnen afhandelen. Als een nieuw invoerelement in een viewer wordt geplaatst, moet deze zijn widget opnieuw vullen in overeenstemming met het nieuwe element en zichzelf loskoppelen van het vorige invoerelement. De semantiek voor registreren als listener op een invoerelement en vullen van de widget op basis van het element, zijn voor ieder type viewer verschillend.
Een contentviewer is een viewer waarvoor een protocol is gedefinieerd voor het verkrijgen van gegevens uit het invoerelement. De contentviewers gebruiken twee gespecialiseerde helperklassen, IContentProvider en ILabelProvider, om hun widgets te vullen en informatie weer te geven over het invoerelement.
IContentProvider levert een basislevenscyclusprotocol voor het koppelen van een contentprovider aan een invoerelement en het afhandelen van een wijziging van het invoerelement. De meer gespecialiseerde contentproviders worden voor verschillende typen viewers geïmplementeerd. De meest algemene contentprovider is IStructuredContentProvider, die een lijst met objecten kan leveren met een bepaald invoerelement. Deze wordt gebruikt in viewers met verschillende lijsttypen, bijvoorbeeld lijsten, tabellen of boomstructuren. In het algemeen is voor de contentprovider bekend hoe een toewijzing wordt aangebracht van het invoerelement naar de verwachte viewercontent.
ILabelProvider gaat nog een stap verder. Wanneer de content van een viewer bekend is (afgeleid van het invoerelement en de contentprovider), kan deze de specifieke UI-elementen leveren, bijvoorbeeld namen en pictogrammen, die vereist zijn voor het weergeven van de content in de viewer. Labelproviders kunnen helpen bij het besparen van pictogramresources, omdat deze ervoor kunnen zorgen dat voor alle zelfde typen in een viewer hetzelfde instance van het pictogram wordt gebruikt.
Opmerking: Instances van bepaalde content- en labelproviders zijn niet bedoeld om gemeenschappelijk te worden gebruikt door verschillende viewers. Zelfs als al uw viewers hetzelfde type content- of labelprovider gebruiken, moet elke viewer worden geïnitialiseerd met een eigen instance van de providerklasse. Het providerlevenscyclusprotocol is ontworpen voor een één-op-één-relatie tussen de provider en de viewer.
De invoerelementen, contentproviders en labelproviders maken het mogelijk voor de viewers om de meeste implementatiedetails voor het vullen van widgets te verbergen. De clients van een viewer hoeven alleen te zorgen voor het vullen van een viewer met het juiste type invoer en contentprovider. Voor de labelprovider moet bekend zijn hoe de UI-informatie wordt afgeleid van de viewercontent.
Met een labelprovider kan meer dan alleen tekst en een afbeelding worden afgebeeld. JFace levert verschillende klassen en interfaces voor de ondersteuning van extra functionaliteit. De volgende klassen worden ondersteund door de TableViewer, AbstractTreeViewer en TableTreeViewer.
Het is mogelijk de kleur van items in een view te wijzigen via de labelprovider van de view of via een decoratieprogramma. Het is in het algemeen beter om de ondersteuning voor kleur en lettertype te gebruiken in labelproviders, omdat de decoratieprogramma's invloed hebben op iedere view die een bepaald type bevat. Als u een kleur- of lettertypedecoratieprogramma gebruikt, is het belangrijk dat u bekijkt of de waarden hiervan kunnen worden ingesteld op de pagina met Voorkeuren voor Kleuren en lettertypen.
De flexibiliteit die wordt geleverd door viewers, contentproviders en labelproviders kan worden duidelijk gemaakt aan de hand van de manier waarop de workbench deze gebruikt.
De WorkbenchContentProvider is een gestructureerde contentprovider die de content van een invoerelement verkrijgt door de onderliggende items op te vragen. Het concept van adapters wordt opnieuw gebruikt om de generieke functie te implementeren. Wanneer wordt gevraagd naar de lijst met elementen van het invoerelement, verkrijgt de WorkbenchContentProvider een IWorkbenchAdapter voor het invoerelement. Als een IWorkbenchAdapter geregistreerd is voor het invoerelement, kan er door de contentprovider worden verondersteld dat de gegevens van de onderliggende items van het element kunnen worden opgevraagd. WorkbenchContentProvider voert ook het werk uit dat nodig is om de viewer up-to-date te houden wanneer het werkgebied wordt gewijzigd.
De WorkbenchLabelProvider is een labelprovider die een IWorkbenchAdapter van een object ophaalt zodat de tekst en afbeelding kunnen worden gevonden. Het concept van een labelprovider is bijzonder handig voor workbenchobjecten, omdat hiermee een enkele labelprovider afbeeldingen in cache kan plaatsen die veel worden gebruikt in een viewer. Wanneer bijvoorbeeld de WorkbenchLabelProvider een afbeelding verkrijgt om te gebruiken voor een IProject, kan deze afbeelding in cache worden geplaatst en worden gebruikt voor alle IProject-objecten die in de viewer worden afgebeeld.
Door een gemeenschappelijke adapter IWorkbenchAdapter te definiëren en deze te registreren voor veel van de platformtypen, kunnen deze typen correct worden weergegeven in veel van de algemene viewers en de workbenchviews waarin deze zich bevinden.