Menu

CustomizingViews

Tom Swain

Customizing Views


This article will discuss customizing the model view.

The EMF Book covers editing ListViewers and TableViewers. A ListViewer displays items in its focused ViewerPane as a list, while a TableViewer can display the contents of a list of items in a grid-like view.

ListViewer Customization


To be added.

TableViewer Customization


A TableViewer can be used to show the contents of model objects in a tabular view. The following is a description of how to set up a table viewer that will show model objects of the same feature within the model editor's viewer pane.

Terminology

  • EMFProject is the name of the EMF project
  • Foo is the name of the root model object containing a list of Bar objects.
  • Bar is the name of the set of objects to be displayed in the table viewer.

Changes to .genmodel File

Set the TableProviders property to true in the Edit section the root object in the EMF .genmodel file.

Changes to Editor Code

Create a TableViewer member variable within the editor class

public class EMFProjectEditor
  extends MultiPageEditorPart
  implements 
    IEditingDomainProvider, 
    ISelectionProvider, 
    IMenuListener, 
    IViewerProvider, 
    IGotoMarker 
{
  ...

  /**

  * This is the Bar table viewer
  * @generated NOT
  */
  protected TableViewer barViewer;

  ...

In createPages(), create a new self-contained block of code (using the {} delimiters). Then, make the following changes (be sure to change the method's java annotation to @generated NOT in order to keep EMF from overwriting any changes to the method). Much of this code can be copied from EMF default table viewer code in createPages().

/**

 * @generated NOT
 */
public void createPages()
{

  ...

  {
    ViewerPane viewerPane =
      new ViewerPane(getSite().getPage(), RealEditor.this) {
      @Override
      public Viewer createViewer(Composite composite) {
    return new TableViewer(composite);
      }
      @Override
      public void requestActivation() {
        super.requestActivation();
        setCurrentViewerPane(this);
      }
    };
    viewerPane.createControl(getContainer());

    /** This is the barViewer that we created **/
    barViewer = (TableViewer)viewerPane.getViewer();

    Table table = barViewer.getTable();
    TableLayout layout = new TableLayout();
    table.setLayout(layout);
    table.setHeaderVisible(true);
    table.setLinesVisible(true);

    /** Here we add in the columns that will hold bar's properties **/

    TableColumn column = new TableColumn(table, SWT.NONE);   // This is the column for the label
    layout.addColumnData(new ColumnWeightData(3, 100, true));
    column.setText("Bar Label");
    column.setResizable(true);

    column = new TableColumn(table, SWT.NONE);   // This is column for the first property
    layout.addColumnData(new ColumnWeightData(2, 100, true));
    column.setText("First Property");
    column.setResizable(true);

    column = new TableColumn(table, SWT.NONE);    // This is the column for the second property
    layout.addColumnData(new ColumnWeightData(2, 100, true));
    descriptionColumn.setText("Second Property");
    descriptionColumn.setResizable(true);

    ...  /* and so on */

    /* This will need to be changed for cell editing */     
    barViewer.setColumnProperties(new String [] {"a", "b", "c", "d"});

    /*

     * Here we need to subclass AdapterFactoryContentProvider. 
     * getElements() will need to only return instances of ``Bar'', assuming that ``Foo''
     * is the root object containing instances of ``Bar'' in the model
     * notifyChanged() will need to only pass on changes ``bar'' feature.  Also,
     * the viewer will be notified after every change (see ch 19, pg 586 in EMF book)
     */
    barViewer.setContentProvider(
      new AdapterFactoryContentProvider(adapterFactory)
      {
        public Object [] getElements(Object object)
        {
          return ((Foo)object).getInterfaces().toArray();
        }
        public void notifyChanged(Notification notification)
        {
          super.notifyChanged(new ViewerNotification(notification));
        }
    });

    barViewer.setLabelProvider(new AdapterFactoryLabelProvider(adapterFactory));

    /*

     * This code ensures that the input to the table is always an instance of Foo 
     * so the call to getElements() is successful.
     */
    Resource resource =
      (Resource)editingDomain.getResourceSet().getResources().get(0);
    Object rootObject = resource.getContents().get(0);
    if (rootObject instanceof Foo) {
      barViewer.setInput(rootObject);
    }
    /*****************************************************************************/

    createContextMenuFor(barViewer);
    int pageIndex = addPage(viewerPane.getControl());

    /** Change the argument in getString to whatever is appropriate **/
    setPageText(pageIndex, getString("_UI_Bar_feature"));
  }

  ...

Finally, we need to make some changes to handleContentOutlineSelection() to prevent the table viewer's input from being changed by the current selection (EMF book, pg 586). Actual changes to the code are delimited by comment blocks.

public void handleOutlineContentSelection(ISelection selection)
{

  ...

    if (currentViewerPane.getViewer() == selectionViewer ||
        /* Add change here */
        currentViewerPane.getViewer() == barViewer
        /**/)
       {
         ArrayList selectionList = new ArrayList();
         selectionList.add(selectedElement);
         while (selectedElements.hasNext())
         {
           selectionList.add(selectedElements.next());
         }

         // Set the selection to the widget.
         //

         /*

          * Here we will be replacing the following code:
          * selectionViewer.setSelection(
          *   new StructuredSelection(selectionList));
          */
         currentViewerPane.getViewer().setSelection(
           new StructuredSelection(selectionList));
         /**/
       }

     ...
    }

Changes to Item Provider

First, make sure that the item provider implements ITableItemLabelProvider like so:

/**

 * This is the item provider adapter for a Bar object.
 * <!-- begin-user-doc -->
 * @implements ITableItemLabelProvider
 * <!-- end-user-doc -->
 * @generated
 */
public class BarItemProvider
  extends ItemProviderAdapter
  implements
    IEditingDomainItemProvider
    IStructuredItemContentProvider
    ITreeItemContentProvider
    IItemLabelProvider
    IItemPropertySource    
    ITableItemLabelProvider
{

  ...

Now, implement getColumnText() and getColumnImage() as specified in ITableItemLabelProvider.

  /**

   * @generated NOT
   */
  public String getColumnImage(Object object, int columnIndex)
  {
    switch(columnIndex) {
    case 0:  // First column: object label
      return getText(object);
    case 1:  // Second column
      ...
    case 2:  // Third column
      ...
    ...
    default:
      return ""
    }
  }
  /**
   * @generated NOT
   */
  public String getColumnImage(Object object, int columnIndex)
  {
    return getImage(object); // EMF book has different code, but this is simpler 
  }

Changes to Item Provider Adapter Factory

Add support for ITableItemLabelProvider in the item provider adapter factory for model's item providers. Be sure to change the method annotation to @generated NOT

  /**

   * This creates an instance.
   * <!-- begin-user-doc -->
   * <!-- end-user-doc -->
   * @generated NOT
   */
   public EMFProjectItemProviderAdapterFactory()
   {
     supportedTypes.add(IStructuredItemContentProvider.class);
     ...
     /* Add support for ITableItemLabelProvider here */
     supportedTypes.add(ITableItemLabelProvider.class);
   }

EMF Reference



Related

Wiki: Home

MongoDB Logo MongoDB