/******************************************************************************* * 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); } } }); } } }