/** * Copyright (c) 2010-2011 United States Government as represented by the Administrator for The National Aeronautics and Space Administration. All Rights Reserved. */ package net.certware.measurement.spm.view; import net.certware.core.ICertWareConstants; import net.certware.core.ui.log.CertWareLog; import net.certware.measurement.smm.DimensionalMeasure; import net.certware.measurement.smm.DimensionalMeasurement; import net.certware.measurement.smm.Measurement; import net.certware.measurement.spm.AdaptabilityRatioMeasure; import net.certware.measurement.spm.AdaptabilityTrend; import net.certware.measurement.spm.BaselineCaseSizeMeasure; import net.certware.measurement.spm.BrokenCaseSizeMeasure; import net.certware.measurement.spm.CriticalDefectChangeOrderCount; import net.certware.measurement.spm.DevelopmentEffortMeasure; import net.certware.measurement.spm.FixedCaseSizeMeasure; import net.certware.measurement.spm.ImprovementChangeOrderCount; import net.certware.measurement.spm.MaintainabilityMeasure; import net.certware.measurement.spm.MaturityRatioMeasure; import net.certware.measurement.spm.MaturityTrend; import net.certware.measurement.spm.ModularityMeasure; import net.certware.measurement.spm.ModularityTrend; import net.certware.measurement.spm.NewFeatureChangeOrderCount; import net.certware.measurement.spm.NormalDefectChangeOrderCount; import net.certware.measurement.spm.ProjectCommit; import net.certware.measurement.spm.ProjectModel; import net.certware.measurement.spm.RepairEffortMeasure; import net.certware.measurement.spm.ReworkBacklogMeasure; import net.certware.measurement.spm.ReworkRatioMeasure; import net.certware.measurement.spm.ReworkStabilityMeasure; import net.certware.measurement.spm.ScrapRatioMeasure; import net.certware.measurement.spm.TotalCaseSizeMeasure; import net.certware.measurement.spm.UsageTimeMeasure; import net.certware.measurement.spm.impl.ProjectCommitImpl; import net.certware.measurement.spm.impl.ProjectModelImpl; import net.certware.measurement.spm.util.SpmResourceImpl; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResourceChangeEvent; import org.eclipse.core.resources.IResourceChangeListener; import org.eclipse.core.resources.IResourceDelta; import org.eclipse.core.resources.IResourceDeltaVisitor; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.emf.common.util.TreeIterator; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.resource.ResourceSet; import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; import org.eclipse.jface.action.Action; import org.eclipse.jface.dialogs.IMessageProvider; import org.eclipse.jface.resource.FontRegistry; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.TreeSelection; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Tree; import org.eclipse.ui.ISelectionListener; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.forms.DetailsPart; import org.eclipse.ui.forms.IDetailsPage; import org.eclipse.ui.forms.IFormPart; import org.eclipse.ui.forms.IManagedForm; import org.eclipse.ui.forms.ManagedForm; import org.eclipse.ui.forms.MasterDetailsBlock; import org.eclipse.ui.forms.SectionPart; import org.eclipse.ui.forms.widgets.FormToolkit; import org.eclipse.ui.forms.widgets.Hyperlink; import org.eclipse.ui.forms.widgets.ScrolledForm; import org.eclipse.ui.forms.widgets.Section; import org.eclipse.ui.forms.widgets.TableWrapData; import org.eclipse.ui.forms.widgets.TableWrapLayout; import org.eclipse.ui.part.ViewPart; /** * SPM details viewer. * High-level details-only layout on a view, latest commit in project model. * Selecting an SPM file in the workbench refreshes the view. * @author mrb * @since 1.1 */ public class SpmViewMasterDetails extends ViewPart implements ISelectionListener, ICertWareConstants, IResourceChangeListener { /** form toolkit */ FormToolkit toolkit; /** scrolled form on the part */ ScrolledForm form; /** selected SPM file */ IFile selectedFile = null; /** selected file opener */ Hyperlink fileLink = null; /** selected results model */ ProjectModel projectModel; /** default section style */ int sectionStyle = Section.DESCRIPTION | Section.TITLE_BAR | Section.TWISTIE | Section.EXPANDED; /** bold font from resources */ Font boldFont; /** tree viewer for master part */ TreeViewer viewer; /** * Creates the view part, applying a scrolled form and master-details blocks. * @param parent workbench parent composite */ @Override public void createPartControl(Composite parent) { toolkit = new FormToolkit(parent.getDisplay()); // scrolled form on which to place the block Composite composite = new Composite(parent, SWT.BORDER); composite.setLayout(new FillLayout()); form = toolkit.createScrolledForm(composite); form.setImage( Activator.getDefault().getImageRegistry().get( Activator.FORM_IMAGE )); form.setText("Software Project Management Metrics"); form.setMessage(null, IMessageProvider.NONE); form.setToolTipText("Select an SPM file in the workbench"); toolkit.decorateFormHeading(form.getForm()); // retrieve the bold font FontRegistry fontRegistry = new FontRegistry(parent.getDisplay()); boldFont = fontRegistry.getBold(JFaceResources.DEFAULT_FONT); // master-details setup IManagedForm managedForm = new ManagedForm(toolkit, form); ScrolledPropertiesBlock block = new ScrolledPropertiesBlock(); block.createContent(managedForm); // workbench selection listener getSite().getWorkbenchWindow().getSelectionService().addSelectionListener(this); // resource change listener ResourcesPlugin.getWorkspace().addResourceChangeListener(this, IResourceChangeEvent.POST_CHANGE | IResourceChangeEvent.PRE_CLOSE | IResourceChangeEvent.PRE_DELETE ); form.layout(true); form.reflow(true); } /** * Refresh the part. * Tries to use a safe thread on default display. */ protected void refreshPart() { // update the input to the tree viewer in the master part new Thread(new Runnable() { public void run() { // try { Thread.sleep(1000); } catch (Exception e) { } Display.getDefault().asyncExec(new Runnable() { public void run() { viewer.setInput(projectModel); if ( projectModel != null ) { // update master side fields, if any // unused at this point as there are no product model element fields to display } form.reflow(true); } }); } }).start(); } /** * Sets the focus to the form. */ @Override public void setFocus() { form.setFocus(); } /** * Disposes the toolkit. * Removes the listeners for the workbench and resources. * Calls super class dispose. */ @Override public void dispose() { toolkit.dispose(); getSite().getWorkbenchWindow().getSelectionService().removeSelectionListener(this); ResourcesPlugin.getWorkspace().removeResourceChangeListener(this); super.dispose(); } /** * Refreshes the model object given the selected file. * Loads using the resource set contents. * Does not refresh the display. */ protected void refreshModelFromFile() { if ( selectedFile == null ) return; try { // load the XML file through the EMF resource set implementation ResourceSet resourceSet = new ResourceSetImpl(); Resource resource = resourceSet.getResource( URI.createPlatformResourceURI(selectedFile.getFullPath().toString(), true), true); ProjectModel documentRoot = (ProjectModel)resource.getContents().get(0); if ( documentRoot != null ) { projectModel = documentRoot; } } catch( Exception exception ) { CertWareLog.logError(String.format("%s %s", "Document root null loading" + selectedFile.getName()), exception); } } /** * Sets the selected file. * For use by other actions. * If the selected file changes, calls {@link refreshModelFromFile} and {@link refreshPart}. * @param sf selected file */ public void setSelectedFile(IFile sf) { if ( sf != null ) { if ( sf != selectedFile ) { selectedFile = sf; refreshModelFromFile(); refreshPart(); } } } /** * Captures the selected file name if it matches our interest. * @param part workbench part * @param selection structured selection expecting {@code IFile} or an {@code EObject} with {@code ProjectModel} container */ @Override public void selectionChanged(IWorkbenchPart part, ISelection selection) { // skip the selection change if it came from this part if ( part != SpmViewMasterDetails.this ) { if ( selection instanceof IStructuredSelection ) { IStructuredSelection iss = (IStructuredSelection)selection; Object object = iss.getFirstElement(); // save the selection if it's an SPM file if ( object instanceof IFile ) { IFile f = (IFile)object; // skip if already loaded if ( f == selectedFile ) return; if ( f.getFileExtension().equalsIgnoreCase( ICertWareConstants.SPM_EXTENSION )) { setSelectedFile((IFile)f); } return; } // save the resource if it's an editor object if ( object instanceof EObject ) { EObject eo = (EObject)object; if ( eo != null ) { if ( eo instanceof ProjectModel ) { projectModel = (ProjectModel)eo; selectedFile = null; refreshPart(); return; } EObject container = eo.eContainer(); if ( container instanceof ProjectModel ) { projectModel = (ProjectModel)container; selectedFile = null; refreshPart(); return; } if ( container instanceof SpmResourceImpl ) { // might do something with contents later return; } } } } } } /** * Responds to resource change events. * Checks for removed and change events. Refreshes part if necessary. */ @Override public void resourceChanged(IResourceChangeEvent event) { try { event.getDelta().accept(new IResourceDeltaVisitor() { public boolean visit(IResourceDelta delta) throws CoreException { if ( delta.getKind() == IResourceDelta.REMOVED ) { // selected results file if ( selectedFile != null ) if ( delta.getResource() instanceof IFile && selectedFile.equals(delta.getResource()) ) { selectedFile = null; refreshPart(); } } // removed else if ( delta.getKind() == IResourceDelta.CHANGED ) { if ( selectedFile != null ) if ( delta.getResource() instanceof IFile && selectedFile.equals(delta.getResource()) ) { refreshPart(); } } // changed return true; } }); } catch( CoreException ce ) { CertWareLog.logWarning("Refreshing SPM file" + ce.getMessage()); } } /** * Master details block, scrolled in the parent container. * Registers two details pages, one for artifact identifiers, one for change orders. */ public class ScrolledPropertiesBlock extends MasterDetailsBlock { /** * Create the master part. * Creates the section with a tree container and viewer. * Uses the EMF providers for tree content. * @param managedForm managed form scroll parent * @param parent container */ protected void createMasterPart(final IManagedForm managedForm, Composite parent) { FormToolkit toolkit = managedForm.getToolkit(); // section has a table wrap layout for the form Section treeSection = toolkit.createSection(parent, Section.TITLE_BAR); treeSection.setText("Project Commits"); toolkit.createCompositeSeparator(treeSection); TableWrapLayout wrapLayout = new TableWrapLayout(); wrapLayout.numColumns = 1; treeSection.setLayout(wrapLayout); // section client has a grid layout for its tree container Composite sectionClient = toolkit.createComposite(treeSection); sectionClient.setLayout(new GridLayout(1, false)); treeSection.setClient(sectionClient); // tree on the client Tree tree = toolkit.createTree(sectionClient, SWT.NULL); GridData gd2 = new GridData(GridData.FILL,GridData.FILL,true,true); // works to fill master container gd2.heightHint = 100; gd2.widthHint = 200; tree.setLayoutData(gd2); toolkit.paintBordersFor(sectionClient); treeSection.setClient(sectionClient); final SectionPart spart = new SectionPart(treeSection); managedForm.addPart(spart); // tree viewer //SpmItemProviderAdapterFactory factory = new SpmItemProviderAdapterFactory(); viewer = new TreeViewer(tree); viewer.setContentProvider(new ContentProvider()); viewer.setLabelProvider(new LabelProvider()); viewer.setInput(projectModel); viewer.expandAll(); viewer.addSelectionChangedListener(new ISelectionChangedListener() { public void selectionChanged(SelectionChangedEvent event) { managedForm.fireSelectionChanged(spart, event.getSelection()); } }); } /** * Creates the typical horizontal and vertical layout actions for the tool bar. * @param managedForm form for toolbar */ protected void createToolBarActions(IManagedForm managedForm) { final ScrolledForm form = managedForm.getForm(); // layout horizontal Action haction = new Action("hor", Action.AS_RADIO_BUTTON) { public void run() { sashForm.setOrientation(SWT.HORIZONTAL); form.reflow(true); } }; haction.setChecked(true); haction.setToolTipText("Horizontal orientation"); haction.setImageDescriptor(Activator.getDefault() .getImageRegistry() .getDescriptor(Activator.HORIZONTAL_IMAGE)); // layout vertical Action vaction = new Action("ver", Action.AS_RADIO_BUTTON) { public void run() { sashForm.setOrientation(SWT.VERTICAL); form.reflow(true); } }; vaction.setChecked(false); vaction.setToolTipText("Vertical orientation"); vaction.setImageDescriptor(Activator.getDefault() .getImageRegistry() .getDescriptor(Activator.VERTICAL_IMAGE)); // add buttons to the tool bar form.getToolBarManager().add(haction); form.getToolBarManager().add(vaction); } /** * Registers detail pages by class. * Registers a page for {@code ProjectModelImpl} and {@code ProjectCommitImpl}. */ protected void registerPages(DetailsPart detailsPart) { detailsPart.registerPage(ProjectModelImpl.class, new ProjectModelDetailsPage()); detailsPart.registerPage(ProjectCommitImpl.class, new ProjectCommitDetailsPage()); } } /** * Details page for a commit record. */ public class ProjectCommitDetailsPage implements IDetailsPage { /** whether the page content is stale */ boolean stale = true; /** commit metrics client on the section */ Composite metricsClient; /** commit metrics section */ Composite statisticsClient; /** selected commit object from the master side */ ProjectCommit projectCommit; /** toolkit for creating form content */ FormToolkit myToolkit; /** scrap ratio label */ Label scrapRatio; /** maturity ratio label */ Label maturityRatio; /** maturity trend label */ Label maturityTrend; /** maintainability label */ Label maintainability; /** rework stability label */ Label reworkStability; /** rework ratio label */ Label reworkRatio; /** rework backlog label */ Label reworkBacklog; /** modularity label */ Label modularity; /** adaptability ratio label */ Label adaptabilityRatio; /** adaptability trend label */ Label adaptabilityTrend; /** modularity trend label */ Label modularityTrend; /** critical change orders count label */ Label criticalCount; /** normal change orders count label */ Label normalCount; /** improvement change orders count label */ Label improvementCount; /** new feature change orders count label */ Label newCount; /** broken case size label */ Label brokenSize; /** fixed case size label */ Label fixedSize; /** total case size label */ Label totalSize; /** baselined case size label */ Label baselineSize; /** usage time label */ Label usageTime; /** repair effort label */ Label repairEffort; /** development effort label */ Label developmentEffort; @Override public void initialize(IManagedForm form) { myToolkit = form.getToolkit(); } @Override public void dispose() { } @Override public boolean isDirty() { return false; } @Override public void commit(boolean onSave) { } @Override public boolean setFormInput(Object input) { if ( input instanceof ProjectCommit ) { projectCommit = (ProjectCommit)input; refresh(); return true; } return false; } @Override public void setFocus() { } @Override public boolean isStale() { return stale; } /** * Returns the value from the first attribute of the observation. * @param measure dimensional measure, ratio or trend * @param index measurement index, usually zero * @return value formatted, or none string */ public String getValue(DimensionalMeasure measure, int index) { if ( measure.getMeasurement() != null && measure.getMeasurement().size() > 0 ) { Measurement measurement = measure.getMeasurement().get(index); // direct measurement if ( measurement instanceof DimensionalMeasurement ) { DimensionalMeasurement dm = (DimensionalMeasurement)measurement; String unit = measure.getUnit(); if ( unit == null ) { return String.format("%7.2f",dm.getValue()); } else { return String.format("%7.2f %s",dm.getValue(),unit); } } // other measurement types, such as ranking, not used in this model } return "<none>"; } @Override public void refresh() { // visit the model, collect statistics // these are all direct measurement measures, so the tree data content expects only these types // we are only using the first measurement (index 0) in every case TreeIterator<EObject> ti = projectCommit.eAllContents(); while( ti.hasNext() ) { EObject eo = (EObject)ti.next(); // individual statistics if ( eo instanceof CriticalDefectChangeOrderCount ) { criticalCount.setText( getValue((CriticalDefectChangeOrderCount)eo,0)); continue; } if ( eo instanceof NormalDefectChangeOrderCount ) { normalCount.setText( getValue((NormalDefectChangeOrderCount)eo,0)); continue; } if ( eo instanceof ImprovementChangeOrderCount ) { improvementCount.setText( getValue((ImprovementChangeOrderCount)eo,0)); continue; } if ( eo instanceof NewFeatureChangeOrderCount ) { newCount.setText( getValue((NewFeatureChangeOrderCount)eo,0)); continue; } if ( eo instanceof BrokenCaseSizeMeasure ) { brokenSize.setText( getValue((BrokenCaseSizeMeasure)eo,0)); } if ( eo instanceof FixedCaseSizeMeasure ) { fixedSize.setText( getValue((FixedCaseSizeMeasure)eo,0)); } if ( eo instanceof TotalCaseSizeMeasure ) { totalSize.setText( getValue((TotalCaseSizeMeasure)eo,0)); } if ( eo instanceof BaselineCaseSizeMeasure ) { baselineSize.setText( getValue((BaselineCaseSizeMeasure)eo,0)); } if ( eo instanceof UsageTimeMeasure ) { usageTime.setText( getValue((UsageTimeMeasure)eo,0)); } if ( eo instanceof DevelopmentEffortMeasure ) { developmentEffort.setText( getValue((DevelopmentEffortMeasure)eo,0)); } if ( eo instanceof RepairEffortMeasure ) { repairEffort.setText( getValue((RepairEffortMeasure)eo,0)); } // computed metrics if ( eo instanceof ScrapRatioMeasure ) { scrapRatio.setText( getValue((ScrapRatioMeasure)eo,0) ); continue; } if ( eo instanceof MaturityRatioMeasure ) { maturityRatio.setText( getValue((MaturityRatioMeasure)eo,0) ); continue; } if ( eo instanceof MaturityTrend ) { maturityTrend.setText( getValue((MaturityTrend)eo,0) ); continue; } if ( eo instanceof MaintainabilityMeasure ) { maintainability.setText( getValue((MaintainabilityMeasure)eo,0) ); continue; } if ( eo instanceof ReworkStabilityMeasure ) { reworkStability.setText( getValue((ReworkStabilityMeasure)eo,0) ); continue; } if ( eo instanceof ReworkRatioMeasure ) { reworkRatio.setText( getValue((ReworkRatioMeasure)eo,0) ); continue; } if ( eo instanceof ReworkBacklogMeasure ) { reworkBacklog.setText( getValue((ReworkBacklogMeasure)eo,0) ); continue; } if ( eo instanceof ModularityMeasure ) { modularity.setText( getValue((ModularityMeasure)eo,0) ); continue; } if ( eo instanceof AdaptabilityRatioMeasure) { adaptabilityRatio.setText( getValue((AdaptabilityRatioMeasure)eo,0) ); continue; } if ( eo instanceof AdaptabilityTrend) { adaptabilityTrend.setText( getValue((AdaptabilityTrend)eo,0) ); continue; } if ( eo instanceof ModularityTrend) { modularityTrend.setText( getValue((ModularityTrend)eo,0) ); continue; } } stale = false; metricsClient.getParent().layout(true); statisticsClient.getParent().layout(true); } @Override public void selectionChanged(IFormPart part, ISelection selection) { if ( selection instanceof TreeSelection ) { TreeSelection ts = (TreeSelection)selection; Object first = ts.getFirstElement(); if ( first instanceof ProjectCommit ) { projectCommit = (ProjectCommit)first; stale = true; setFormInput(projectCommit); } } } /** * Creates two sections on the form, one for computed metrics and one for the raw statistics * used to compute those metrics. * @param parent parent for the sections */ @Override public void createContents(Composite parent) { TableWrapLayout layout = new TableWrapLayout(); layout.topMargin = 0; layout.leftMargin = 5; layout.rightMargin = 5; layout.bottomMargin = 5; layout.numColumns = 1; parent.setLayout(layout); // computed metrics section Section metricsSection = myToolkit.createSection(parent, Section.TITLE_BAR | Section.EXPANDED | Section.TWISTIE ); metricsSection.setText("Commit Metrics"); metricsSection.setLayoutData(new TableWrapData(TableWrapData.FILL_GRAB, TableWrapData.TOP)); // toolkit.createCompositeSeparator(metricsSection); metricsClient = myToolkit.createComposite(metricsSection); TableWrapLayout dcl = new TableWrapLayout(); dcl.numColumns = 3; metricsClient.setLayout( dcl ); // each creation creates three cells for its row scrapRatio = createLabel(metricsClient, "Scrap Ratio",Activator.NODE_SCRAP_RATIO); maturityRatio = createLabel(metricsClient, "Maturity Ratio",Activator.NODE_MATURITY); maturityTrend = createLabel(metricsClient, "Maturity Trend",Activator.NODE_MATURITY_TREND); maintainability = createLabel(metricsClient, "Maintainability",Activator.NODE_MAINTAINABILITY); reworkRatio = createLabel(metricsClient, "Rework Ratio",Activator.NODE_REWORK_RATIO); reworkStability = createLabel(metricsClient, "Rework Stability",Activator.NODE_REWORK_STABILITY); reworkBacklog = createLabel(metricsClient, "Rework Backlog",Activator.NODE_REWORK_BACKLOG); modularity = createLabel(metricsClient, "Modularity",Activator.NODE_MODULARITY); modularityTrend = createLabel(metricsClient, "Modularity Trend",Activator.NODE_MODULARITY_TREND); adaptabilityRatio = createLabel(metricsClient, "Adaptability Ratio",Activator.NODE_ADAPTABILITY); adaptabilityTrend = createLabel(metricsClient, "Adaptability Trend",Activator.NODE_ADAPTABILITY_TREND); metricsSection.setClient(metricsClient); // raw statistics section Section statisticsSection = myToolkit.createSection(parent, Section.TITLE_BAR | Section.TWISTIE ); statisticsSection.setText("Raw Statistics"); statisticsSection.setLayoutData(new TableWrapData(TableWrapData.FILL_GRAB, TableWrapData.TOP)); // toolkit.createCompositeSeparator(statisticsSection); statisticsClient = myToolkit.createComposite(statisticsSection); dcl = new TableWrapLayout(); dcl.numColumns = 3; statisticsClient.setLayout( dcl ); // each creation creates three cells for its row criticalCount = createLabel(statisticsClient, "Critical Defect Change Orders",Activator.NODE_CRITICAL_CHANGE_ORDERS); normalCount = createLabel(statisticsClient, "Normal Defect Change Orders",Activator.NODE_NORMAL_CHANGE_ORDERS); improvementCount = createLabel(statisticsClient, "Improvement Change Orders",Activator.NODE_IMPROVEMENT_CHANGE_ORDERS); newCount = createLabel(statisticsClient, "New Feature Change Orders",Activator.NODE_NEW_CHANGE_ORDERS); totalSize = createLabel(statisticsClient, "Total Case Size",Activator.NODE_TOTAL_SIZE); brokenSize = createLabel(statisticsClient, "Broken Case Size",Activator.NODE_BROKEN_SIZE); fixedSize = createLabel(statisticsClient, "Fixed Case Size",Activator.NODE_FIXED_SIZE); baselineSize = createLabel(statisticsClient, "Baselined Case Size",Activator.NODE_BASELINED_LINES); usageTime = createLabel(statisticsClient,"Usage Time",Activator.NODE_USAGE_TIME); repairEffort = createLabel(statisticsClient,"Repair Effort",Activator.NODE_REPAIR_EFFORT); developmentEffort = createLabel(statisticsClient,"Development Effort",Activator.NODE_DEVELOPMENT_EFFORT); statisticsSection.setClient(statisticsClient); stale = false; } /** * Creates the image, text, and value cells for the table layout. * Used for convenience to produce three labels on a row for image, description, and value cells. * @param client details client * @param name row name * @param imageId row image id key from plug-in image registry * @return value label with its text set to empty string */ protected Label createLabel(Composite client, String name, String imageId) { Label image = myToolkit.createLabel(client, ""); image.setImage(Activator.getDefault().getImageRegistry().get(imageId)); image.setLayoutData(new TableWrapData(TableWrapData.CENTER, TableWrapData.TOP)); Label label = myToolkit.createLabel(client, name); label.setLayoutData(new TableWrapData(TableWrapData.LEFT, TableWrapData.TOP)); Label value = myToolkit.createLabel(client, ""); value.setLayoutData(new TableWrapData(TableWrapData.RIGHT, TableWrapData.TOP)); return value; } } /** * Project model details page. */ public class ProjectModelDetailsPage implements IDetailsPage { Composite client; boolean stale = true; ProjectModel inputModel; FormToolkit myToolkit; Label commitCount; @Override public void initialize(IManagedForm form) { myToolkit = form.getToolkit(); } @Override public void dispose() { } @Override public boolean isDirty() { return false; } @Override public void commit(boolean onSave) { } @Override public boolean setFormInput(Object input) { if ( input instanceof ProjectModel ) { inputModel = (ProjectModel)input; refresh(); return true; } return false; } @Override public void setFocus() { } @Override public boolean isStale() { return stale; } @Override public void refresh() { if ( inputModel.getCommits() != null ) { commitCount.setText(String.format("%d commits",inputModel.getCommits().size())); } else { commitCount.setText("none"); } stale = false; client.getParent().layout(true); } @Override public void selectionChanged(IFormPart part, ISelection selection) { if ( selection instanceof TreeSelection ) { TreeSelection ts = (TreeSelection)selection; inputModel = (ProjectModel)ts.getFirstElement(); stale = true; setFormInput(inputModel); } } @Override public void createContents(Composite parent) { TableWrapLayout layout = new TableWrapLayout(); layout.topMargin = 0; layout.leftMargin = 5; layout.rightMargin = 5; layout.bottomMargin = 5; layout.numColumns = 3; parent.setLayout(layout); Section section = myToolkit.createSection(parent, Section.TWISTIE | Section.EXPANDED | Section.TITLE_BAR ); section.setText("Project Model"); section.setLayoutData(new TableWrapData(TableWrapData.FILL_GRAB, TableWrapData.TOP)); // toolkit.createCompositeSeparator(section); client = myToolkit.createComposite(section); TableWrapLayout dcl = new TableWrapLayout(); dcl.numColumns = 3; client.setLayout( dcl ); // creates three cells for the row commitCount = createLabel(client,"Project commits",Activator.COMMIT_IMAGE); section.setClient(client); stale = false; } /** * Creates the image, text, and value cells for the table layout. * @param client details client * @param name row name * @param imageId row image id key from plug-in image registry * @return value label with its text set to empty string */ protected Label createLabel(Composite client, String name, String imageId) { Label image = myToolkit.createLabel(client, ""); image.setImage(Activator.getDefault().getImageRegistry().get(imageId)); image.setLayoutData(new TableWrapData(TableWrapData.CENTER, TableWrapData.TOP)); Label label = myToolkit.createLabel(client, name); label.setLayoutData(new TableWrapData(TableWrapData.LEFT, TableWrapData.TOP)); Label value = myToolkit.createLabel(client, ""); value.setLayoutData(new TableWrapData(TableWrapData.RIGHT, TableWrapData.TOP)); return value; } } }