wtorek, 22 marca 2011

Breadcrumbs composite with SWT (Eclipse Forms)

Breadcrumbs panel is very popular navigation widget. Especially useful when comes to navigation in big hierarchical models where one need a way to quickly move to the parent elements.


At the picture you can see breadcrumbs in action.

Implementation details


Two providers needs to be delivered to BreadcrumbsPanel instance: IBreadcrumbsItemProvider and IBreadcrumbsLinkActionProvider.

public interface IBreadcrumbsItemProvider{
  public List<IBreadcrumbsItem> getBreadcrumbs();
 }

 public interface IBreadcrumbsLinkActionProvider{
  public void run(IBreadcrumbsItem item);
 }

 public interface IBreadcrumbsItem {
  public abstract Object getObject();
  public abstract String getLabel();
 }

Instances of both providers needs to be delivered to BreadcrumbsPanel constructor.

public BreadcrumbsPanel(
             FormToolkit toolkit, // only when composite is used with Eclipse Forms
             Composite parent, 
             IBreadcrumbsItemProvider itemProvider, 
             final IBreadcrumbsLinkActionProvider actionProvider) {
  super(parent, SWT.NONE);
  this.toolkit = toolkit;
  this.itemProvider = itemProvider;
  this.actionProvider = actionProvider;
  
  this.setLayout(new RowLayout());
  updateLinks();
 }

UpdateLinks method is particularly important piece of code here. It is responsible for generating actual list of hyperlinks. This method make use of both providers. For each element returned by item provider creates a hyperlink control which on click will performed an action delivered with action provider.

private void updateLinks() {
  
  for (Control c :this.getChildren()){
   if (c instanceof Hyperlink || c instanceof Label){
    c.dispose();
   }
  }
  
  links = new ArrayList<Hyperlink>();
  
  final List<IBreadcrumbsItem> items = itemProvider.getBreadcrumbs();
  
  for (int i = 0;i < items.size(); i++) { 
   String label = items.get(i).getLabel();
   if (1+i < items.size()){
    Hyperlink link = toolkit.createHyperlink(this, label, SWT.None);
    link.setHref(items.get(i));
    
    toolkit.createLabel(this, "/");
    
    link.addHyperlinkListener(new HyperlinkAdapter(){
     @Override
     public void linkActivated(HyperlinkEvent e) {
      if (e.getHref() instanceof IBreadcrumbsItem){
       actionProvider.run((IBreadcrumbsItem)e.getHref());
      }
     }
    });
    links.add(link);
   } else {
    toolkit.createLabel(this, label);
   }
  }
 }

Note that in case of pure SWT you may use raw Link and Label controls.