RSS

Search Engine

Saturday, October 23, 2010

Using the selection and part service

Eclipse e4 provides several services which can be used in your RCP application. For example the selection service (ESelectionService). A client can get the selection service via @Inject ESelectionService and the set the selection. The consumer simple defines a method with a named parameter (IServiceConstants.ACTIVE_SELECTION) and a type. The e4 framework will make sure that selections are only injected if they have the fitting type.

EPartService allows to find and perform actions on parts of the model. We will use this service to find the todo details view and hide it if in the tree a category has been selected.

We will now create a JFace tree on the TodoOverview part which will display the Todos. Add "org.eclipse.jface" to the dependencies in "sawan.modi.e4.todo".

We will display the Todo in a Eclipse JFace Tree. Create the following content provider.

  
package sawan.modi.e4.todo.provider;

import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.Viewer;

import sawan.modi.e4.todo.model.ITodoModel;

public class TodoContentProvider implements ITreeContentProvider {

private ITodoModel model;

@Override
public void dispose() {
}

@Override
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
this.model = (ITodoModel) newInput;
}

@Override
public Object[] getElements(Object inputElement) {
return model.getTodos().toArray();
}

@Override
public Object[] getChildren(Object parentElement) {
return null;
}

@Override
public Object getParent(Object element) {
return null;
}

@Override
public boolean hasChildren(Object element) {
return false;
}

}

Change the TodoOvervier.java to the following. This class will aquire the selection service and set it once the user selects a value in the tree. It also will use the EPartService to hide and show the details view based on the selection.

  
package sawan.modi.e4.todo.parts;

import javax.annotation.PostConstruct;
import javax.inject.Inject;

import org.eclipse.e4.core.services.log.Logger;
import org.eclipse.e4.ui.di.Focus;
import org.eclipse.e4.ui.model.application.ui.basic.MPart;
import org.eclipse.e4.ui.workbench.modeling.EPartService;
import org.eclipse.e4.ui.workbench.modeling.EPartService.PartState;
import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;

import sawan.modi.e4.todo.model.Category;
import sawan.modi.e4.todo.model.ITodoModel;
import sawan.modi.e4.todo.model.Todo;
import sawan.modi.e4.todo.provider.TodoContentProvider;

public class TodoOverview {

@Inject
ESelectionService selectionService;
@Inject
private Logger logger;
@Inject
private ITodoModel model;
@Inject
private EPartService service;


// PostConstruct ensures that the dependency injection has been finished
// this this method is called

private final Composite parent;
private TreeViewer viewer;
private MPart findPart;

// e4 will inject the composite "parent" into the view
@Inject
public TodoOverview(Composite parent) {
this.parent = parent;
}

@PostConstruct
public void buildUi() {
findPart = service.findPart("sawan.modi.e4.tododetails");


logger.info("Start building UI");

final GridLayout layout = new GridLayout(2, false);
parent.setLayout(layout);

createLable("Number of Categories:");
createText(String.valueOf(model.getCategories().size()));

viewer = new TreeViewer(parent);
viewer.setLabelProvider(new ColumnLabelProvider() {
@Override
public String getText(Object element) {
if (element instanceof Category) {
Category category = (Category) element;
return category.getName();
}
return ((Todo) element).getSummary();
}
});

viewer.setContentProvider(new TodoContentProvider());
viewer.setInput(model);
viewer.setAutoExpandLevel(2);
GridData gridData = new GridData();
gridData.verticalAlignment = GridData.FILL;
gridData.horizontalSpan = 2;
gridData.grabExcessHorizontalSpace = true;
gridData.grabExcessVerticalSpace = true;
gridData.horizontalAlignment = GridData.FILL;

viewer.getControl().setLayoutData(gridData);
viewer.addSelectionChangedListener(new ISelectionChangedListener() {
@Override
public void selectionChanged(SelectionChangedEvent event) {

IStructuredSelection selection = (IStructuredSelection) viewer
.getSelection();
Object firstElement = selection.getFirstElement();
if (firstElement instanceof Category) {
service.hidePart(findPart);
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=328178
// findPart.setToBeRendered(false);
} else {
// findPart.setVisible(true);
// findPart.setToBeRendered(true);
service.showPart(findPart, PartState.VISIBLE);
}
selectionService.setSelection(selection.getFirstElement());
}
});


}

// Standard SWT Stuff
private void createLable(String text) {
Label label = new Label(parent, SWT.NONE);
label.setText(text);
GridData gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
gridData.horizontalIndent = 20;
label.setLayoutData(gridData);
}

// Standard SWT Stuff
private void createText(String text) {
GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
Text textField = new Text(parent, SWT.NONE);
textField.setText(text);
textField.setLayoutData(gridData);
}

@Focus
public void havingFocus() {
System.out.println("TodoOveriew has now the focus.");
}

}

Change the TodoDetails.java to the following. This class defines the method setTodo which gets as a named parameter the current selection, if this selection is of type Todo.

  
package sawan.modi.e4.todo.parts;

import java.util.HashMap;
import java.util.Map;

import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.inject.Named;

import org.eclipse.e4.core.di.annotations.Optional;
import org.eclipse.e4.core.services.events.IEventBroker;
import org.eclipse.e4.ui.di.Focus;
import org.eclipse.e4.ui.services.IServiceConstants;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.osgi.service.event.EventHandler;

import sawan.modi.e4.todo.model.Todo;

public class TodoDetails {
private final Composite parent;
private Todo todo;
private Text summary;
private Text description;

// e4 will inject the composite "parent" into the view
@Inject
public TodoDetails(Composite parent) {
this.parent = parent;
}

@PostConstruct
public void buildUi(){
final GridLayout layout = new GridLayout(2, false);
parent.setLayout(layout);

createLable("Summary:");
GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
summary = new Text(parent, SWT.NONE);
summary.setTextLimit(100);
summary.setLayoutData(gridData);

createLable("Description:");
gridData = new GridData(GridData.FILL_HORIZONTAL);
description = new Text(parent, SWT.NONE);
description.setSize(30, 400);
description.setLayoutData(gridData);
}

// Standard SWT Stuff
private void createLable(String text) {
Label label = new Label(parent, SWT.NONE);
label.setText(text);
GridData gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
gridData.horizontalIndent = 20;
label.setLayoutData(gridData);
}

@Inject
public void setTodo(
@Optional @Named(IServiceConstants.ACTIVE_SELECTION) Todo todo) {
if (todo != null) {
this.todo = todo;
summary.setText(todo.getSummary());
description.setText(todo.getDescription());
}
}

@Focus
public void havingFocus() {
System.out.println("TodoDetails has now the focus.");
}

}

If you now select a Todo in the tree, this will be propagated via the selection service to the TodoDetails view. If you select a category then the detail view will be hidden.

0 comments:

Post a Comment