/*******************************************************************************
* Copyright (c) 2012, 2015 Original authors and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Original authors and others - initial API and implementation
******************************************************************************/
package org.eclipse.nebula.widgets.nattable.examples.examples._103_Events;
import java.beans.PropertyChangeListener;
import java.io.Serializable;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import org.eclipse.nebula.widgets.nattable.NatTable;
import org.eclipse.nebula.widgets.nattable.blink.BlinkConfigAttributes;
import org.eclipse.nebula.widgets.nattable.blink.BlinkLayer;
import org.eclipse.nebula.widgets.nattable.blink.BlinkingCellResolver;
import org.eclipse.nebula.widgets.nattable.blink.IBlinkingCellResolver;
import org.eclipse.nebula.widgets.nattable.config.CellConfigAttributes;
import org.eclipse.nebula.widgets.nattable.config.ConfigRegistry;
import org.eclipse.nebula.widgets.nattable.config.DefaultNatTableStyleConfiguration;
import org.eclipse.nebula.widgets.nattable.data.IColumnPropertyAccessor;
import org.eclipse.nebula.widgets.nattable.data.IRowIdAccessor;
import org.eclipse.nebula.widgets.nattable.data.ListDataProvider;
import org.eclipse.nebula.widgets.nattable.data.ReflectiveColumnPropertyAccessor;
import org.eclipse.nebula.widgets.nattable.dataset.fixture.data.BlinkingRowDataFixture;
import org.eclipse.nebula.widgets.nattable.dataset.fixture.data.RowDataListFixture;
import org.eclipse.nebula.widgets.nattable.examples.AbstractNatExample;
import org.eclipse.nebula.widgets.nattable.examples.runner.StandaloneNatExampleRunner;
import org.eclipse.nebula.widgets.nattable.extension.glazedlists.GlazedListsEventLayer;
import org.eclipse.nebula.widgets.nattable.grid.data.DefaultColumnHeaderDataProvider;
import org.eclipse.nebula.widgets.nattable.grid.data.DefaultCornerDataProvider;
import org.eclipse.nebula.widgets.nattable.grid.data.DefaultRowHeaderDataProvider;
import org.eclipse.nebula.widgets.nattable.grid.layer.DefaultColumnHeaderDataLayer;
import org.eclipse.nebula.widgets.nattable.grid.layer.DefaultGridLayer;
import org.eclipse.nebula.widgets.nattable.grid.layer.DefaultRowHeaderDataLayer;
import org.eclipse.nebula.widgets.nattable.grid.layer.GridLayer;
import org.eclipse.nebula.widgets.nattable.layer.DataLayer;
import org.eclipse.nebula.widgets.nattable.style.CellStyleAttributes;
import org.eclipse.nebula.widgets.nattable.style.DisplayMode;
import org.eclipse.nebula.widgets.nattable.style.Style;
import org.eclipse.nebula.widgets.nattable.util.GUIHelper;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import ca.odell.glazedlists.EventList;
import ca.odell.glazedlists.GlazedLists;
import ca.odell.glazedlists.ObservableElementList;
public class BlinkingGridExample extends AbstractNatExample {
public static void main(String[] args) {
StandaloneNatExampleRunner.run(800, 400, new BlinkingGridExample());
}
private static final String BLINK_UP_CONFIG_LABEL = "blinkUpConfigLabel";
private static final String BLINK_DOWN_CONFIG_LABEL = "blinkDownConfigLabel";
private ListDataProvider<BlinkingRowDataFixture> bodyDataProvider;
private ScheduledExecutorService scheduledThreadPool;
@Override
public Control createExampleControl(Composite parent) {
final String[] propertyNames = RowDataListFixture.getPropertyNames();
final Map<String, String> propertyToLabelMap = RowDataListFixture.getPropertyToLabelMap();
ConfigRegistry configRegistry = new ConfigRegistry();
// Body
LinkedList<BlinkingRowDataFixture> rowData = new LinkedList<>();
EventList<BlinkingRowDataFixture> eventList = GlazedLists.eventList(rowData);
ObservableElementList<BlinkingRowDataFixture> observableElementList =
new ObservableElementList<>(
eventList,
GlazedLists.beanConnector(BlinkingRowDataFixture.class));
IColumnPropertyAccessor<BlinkingRowDataFixture> columnPropertyAccessor =
new ReflectiveColumnPropertyAccessor<>(propertyNames);
this.bodyDataProvider =
new ListDataProvider<>(observableElementList, columnPropertyAccessor);
final DataLayer bodyLayer = new DataLayer(this.bodyDataProvider);
GlazedListsEventLayer<BlinkingRowDataFixture> glazedListsEventLayer =
new GlazedListsEventLayer<>(bodyLayer, observableElementList);
BlinkLayer<BlinkingRowDataFixture> blinkingLayer =
new BlinkLayer<>(
glazedListsEventLayer,
this.bodyDataProvider,
new IRowIdAccessor<BlinkingRowDataFixture>() {
@Override
public Serializable getRowId(BlinkingRowDataFixture rowObject) {
return rowObject.getSecurity_description();
}
},
columnPropertyAccessor,
configRegistry);
registerBlinkingConfigCells(configRegistry);
insertRowData(glazedListsEventLayer, this.bodyDataProvider);
// Column header
final DefaultColumnHeaderDataProvider defaultColumnHeaderDataProvider =
new DefaultColumnHeaderDataProvider(propertyNames, propertyToLabelMap);
// Row header
final DefaultRowHeaderDataProvider rowHeaderDataProvider =
new DefaultRowHeaderDataProvider(this.bodyDataProvider);
// Corner
final DefaultCornerDataProvider cornerDataProvider =
new DefaultCornerDataProvider(defaultColumnHeaderDataProvider, rowHeaderDataProvider);
// Grid
GridLayer gridLayer = new DefaultGridLayer(
blinkingLayer,
new DefaultColumnHeaderDataLayer(defaultColumnHeaderDataProvider),
new DefaultRowHeaderDataLayer(rowHeaderDataProvider),
new DataLayer(cornerDataProvider));
NatTable natTable = new NatTable(parent, gridLayer, false);
natTable.setConfigRegistry(configRegistry);
natTable.addConfiguration(new DefaultNatTableStyleConfiguration());
natTable.configure();
return natTable;
}
/**
* Start threads to fire data updates (at intervals)
*/
@Override
public void onStart() {
Display.getDefault().asyncExec(new Runnable() {
@Override
public void run() {
BlinkingGridExample.this.scheduledThreadPool = Executors.newScheduledThreadPool(1);
// Fire updates to indexes 1,3,5
BlinkingGridExample.this.scheduledThreadPool.scheduleAtFixedRate(
new DataPumper(BlinkingGridExample.this.bodyDataProvider, 1, 3, 5),
500L,
5000L,
TimeUnit.MILLISECONDS);
// while they are still blinking update index 1
BlinkingGridExample.this.scheduledThreadPool.scheduleAtFixedRate(
new DataPumper(BlinkingGridExample.this.bodyDataProvider, 1),
750L,
5000L,
TimeUnit.MILLISECONDS);
// While the above are still blinking update indexes 2,8
BlinkingGridExample.this.scheduledThreadPool.scheduleAtFixedRate(
new DataPumper(BlinkingGridExample.this.bodyDataProvider, 2, 8),
1000L,
5000L,
TimeUnit.MILLISECONDS);
}
});
}
@Override
public void onStop() {
this.scheduledThreadPool.shutdown();
}
private void registerBlinkingConfigCells(ConfigRegistry configRegistry) {
configRegistry.registerConfigAttribute(
BlinkConfigAttributes.BLINK_RESOLVER,
getBlinkResolver(),
DisplayMode.NORMAL);
// Bg color styles to be used for blinking cells
Style cellStyle = new Style();
cellStyle.setAttributeValue(
CellStyleAttributes.BACKGROUND_COLOR,
GUIHelper.COLOR_GREEN);
configRegistry.registerConfigAttribute(
CellConfigAttributes.CELL_STYLE,
cellStyle,
DisplayMode.NORMAL,
BLINK_UP_CONFIG_LABEL);
cellStyle = new Style();
cellStyle.setAttributeValue(
CellStyleAttributes.BACKGROUND_COLOR,
GUIHelper.COLOR_RED);
configRegistry.registerConfigAttribute(
CellConfigAttributes.CELL_STYLE,
cellStyle,
DisplayMode.NORMAL,
BLINK_DOWN_CONFIG_LABEL);
}
/**
* The blinking resolver decides how the cell should blink i.e what styles
* should be applied depending on the update. This one returns a green color
* label when the value goee up, a red one otherwise.
*/
private IBlinkingCellResolver getBlinkResolver() {
return new BlinkingCellResolver() {
private String[] configLabels = new String[1];
@Override
public String[] resolve(Object oldValue, Object newValue) {
double old = ((Double) oldValue).doubleValue();
double latest = ((Double) newValue).doubleValue();
this.configLabels[0] = (latest > old ? BLINK_UP_CONFIG_LABEL : BLINK_DOWN_CONFIG_LABEL);
return this.configLabels;
};
};
}
private void insertRowData(
PropertyChangeListener changeListener,
ListDataProvider<BlinkingRowDataFixture> dataProvider) {
List<BlinkingRowDataFixture> listFixture = BlinkingRowDataFixture.getList(changeListener);
for (BlinkingRowDataFixture rowObject : listFixture) {
dataProvider.getList().add(rowObject);
}
}
final Random random = new Random();
/**
* Util class to fire periodic updates
*/
class DataPumper implements Runnable {
ListDataProvider<BlinkingRowDataFixture> dataProvider;
private final int[] rowIndexes;
DataPumper(ListDataProvider<BlinkingRowDataFixture> dataProvider, final int... rowIndexes) {
this.dataProvider = dataProvider;
this.rowIndexes = rowIndexes;
}
@Override
public void run() {
Display.getDefault().asyncExec(new Runnable() {
@Override
public void run() {
for (int i = 0; i < DataPumper.this.rowIndexes.length; i++) {
double nextPrice = BlinkingGridExample.this.random.nextInt(1000);
BlinkingRowDataFixture rowObject =
DataPumper.this.dataProvider.getRowObject(DataPumper.this.rowIndexes[i]);
rowObject.setAsk_price(nextPrice);
}
}
});
}
}
}