Showing posts with label design pattern. Show all posts
Showing posts with label design pattern. Show all posts

Wednesday, August 31, 2011

Notifier Design Pattern

Say you want to develop an application which will have many viewers/pages and all these have to be refreshed with the latest data as soon as the data changes in the engine.


A very simple example is - Weather Reports. When the data changes in the engine, the weather report page has to be refreshed to show the latest data.

Let's follow the below steps:
  1. Develop your report dialog - which will show the weather information.
  2. Implement the ChangeListener in the dialog report- This will act as a listener
  3. Implement your report data class, which contains the weather information. This will act a notifier and also as a registry.
  4. Register your listener with the data class so that the viewer will get a notification if the data changes.


Here is the sample code for it:

import java.util.List;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import org.eclipse.jface.viewers.TableViewer;
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.Display;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
/**
 *
 * Weather report dialog.
 *
 */
public class WeatherDetailsDialog implements ChangeListener {
  
 private TableViewer weatherViewer;
  
 protected WeatherDetailsDialog() {  
  //your specific data passed through constructor 
 }
 protected void createReport(Composite topComposite) {
   
  Group dependantsViewerGroup = new Group(topComposite, SWT.NONE);
  dependantsViewerGroup.setLayout(new GridLayout());
  GridData gridData3 = new GridData(SWT.FILL, SWT.FILL, true, false);
  dependantsViewerGroup.setLayoutData(gridData3);
  dependantsViewerGroup.setText("Weather Report"); //$NON-NLS-1$
   
  weatherViewer = new TableViewer(
    dependantsViewerGroup, SWT.FULL_SELECTION | SWT.H_SCROLL | SWT.BORDER);
  final Table reportTable = weatherViewer.getTable();
  reportTable.setLinesVisible(false);
  reportTable.setHeaderVisible(true);
  reportTable.setLayoutData(gridData3);
  GridData gridData = new GridData(SWT.FILL, SWT.TOP, true, false);
  gridData.heightHint = 140;
  reportTable.setLayoutData(gridData);
  TableColumn cityName = new TableColumn(reportTable, SWT.LEFT);
  cityName.setText("City"); //$NON-NLS-1$
  cityName.pack();
  cityName.setWidth(100);
   
  TableColumn valueColumn = new TableColumn(reportTable, SWT.LEFT);
  valueColumn.setText("Value"); //$NON-NLS-1$
  valueColumn.pack();
  valueColumn.setWidth(100);
   
  TableColumn descriptionColumn = new TableColumn(reportTable, SWT.LEFT);
  descriptionColumn.setText("Description"); //$NON-NLS-1$
  descriptionColumn.pack();
  descriptionColumn.setWidth(120);
   
  weatherViewer.setContentProvider(new WeatherContentProvider()); 
  weatherViewer.setLabelProvider(new WeatherLabelProvider());
  //Register viewer with the weathe report data.
   
  List<IWeather> reportData = computingEngine.getReportData();
  for (IWeather data : reportData) {
   ((Weather)data).addChangeListener(this);
  }
  weatherViewer.setInput(reportData);
 }
/**
     * Invoked when the target of the listener has changed its state.
     *
     * @param e  a ChangeEvent object
     */
   
 @Override
 public void stateChanged(ChangeEvent arg0) {
  Display.getDefault().asyncExec(new Runnable() {
   @Override
   public void run() {
    weatherViewer.refresh();
   }
  });
 }
}


This will notfiy as soon the data changes.


import java.util.ArrayList;
import java.util.List;
import javax.swing.event.ChangeListener;

public class Weather {

 private List<ChangeListener> registeredListners = new ArrayList<ChangeListener>();
 private ComputingEngine ComputingData;
 private Float newValue;
 private String description;
 
 public Weather(ComputingEngine ComputingData) {
  this.ComputingData = ComputingData;
 }
  
 /**
  * Updating the status change. This will notify to all the registered listeners
  * Ex: It will notify to the viewer/UI about the weather change report
  *   */
  
 public void setValue(Float newValue) {
  this.newValue = newValue;
  notifyListeners();
 }
  
 public ComputingEngine getComputingData() {
  return ComputingData;
 }
  
 public void setDescription(String description) {
  this.description = description;
 }
  
 public String getDescription() {
  return description;
 }
  
 public Float getNewValue() {
  return newValue;
 }
 //Add your listener here
 public void addChangeListener(ChangeListener listener) {
  if (!registeredListners.contains(listener))
   registeredListners.add(listener);
 }
 //removing the listener
 public void removeChangeListener(ChangeListener listener) {
  if (registeredListners.contains(listener))
   registeredListners.remove(listener);
 }
 //This will be triggered when the state changes
 public void notifyListeners() {
  for (ChangeListener listener : registeredListners) {
   listener.stateChanged(null);
  }
 }
}