Sorting in NatTables - nattable

I have got implemented filtering in nattables. How to add sorting? do I have to create new columnHeaderLayer? Here is my code:
1 class BodyLayerStack
class BodyLayerStack extends AbstractLayerTransform {
private final FilterList<TableLine> filterList;
private final SelectionLayer selectionLayer;
private final DataLayer bodyDataLayer;
private final IRowDataProvider<TableLine> bodyDataProvider;
private final SortedList<TableLine> sortedList;
public DataLayer getBodyDataLayer() {
return bodyDataLayer;
}
public SelectionLayer getSelectionLayer() {
return selectionLayer;
}
public IRowDataProvider<TableLine> getBodyDataProvider() {
return bodyDataProvider;
}
getting values from tables:
public BodyLayerStack(List<TableLine> values, IColumnAccessor<TableLine> columnAccessor, Integer[] columnIndicesForRowHeaders) {
EventList<TableLine> eventList = GlazedLists.eventList(values);
TransformedList<TableLine, TableLine> rowObjectsGlazedList = GlazedLists.threadSafeList(eventList);
creating filter and sorted list:
this.filterList = new FilterList<>(rowObjectsGlazedList);
this.sortedList = new SortedList<>(filterList, null);
this.bodyDataProvider = new ListDataProvider<TableLine>(this.sortedList, columnAccessor);
bodyDataLayer = new DataLayer(this.bodyDataProvider);
ColumnOverrideLabelAccumulator bodyLabelAccumulator = new ColumnOverrideLabelAccumulator(bodyDataLayer);
bodyDataLayer.setConfigLabelAccumulator(bodyLabelAccumulator);
if( columnIndicesForRowHeaders != null ) {
for ( int i = 0; i < columnIndicesForRowHeaders.length; i++ ) {
bodyLabelAccumulator.registerColumnOverrides(
columnIndicesForRowHeaders[i],
RowHeaderLabel);
}
}
event layer:
GlazedListsEventLayer<TableLine> glazedListsEventLayer =
new GlazedListsEventLayer<>(bodyDataLayer, this.filterList);
this.selectionLayer = new SelectionLayer(glazedListsEventLayer, false);
selectionLayer.setSelectionModel(new RowSelectionModel<TableLine>(selectionLayer, this.bodyDataProvider, new IRowIdAccessor<TableLine>()
{
#Override
public Serializable getRowId(TableLine line)
{
return line.getId();
}
}));
adding configuration to selection layer
selectionLayer.addConfiguration(new DefaultSelectionLayerConfiguration()
{
#Override
protected void addSelectionUIBindings()
{
addConfiguration(new SelectionBindings());
}
#SuppressWarnings("rawtypes")
#Override
protected void addMoveSelectionConfig()
{
addConfiguration(new RowOnlySelectionConfiguration());
}
});
viewport layer + return
ViewportLayer viewportLayer = new ViewportLayer(selectionLayer);
setUnderlyingLayer(viewportLayer);
}
public FilterList<TableLine> getFilterList() {
return this.filterList;
}
}

If you want to add sorting by click on column header cells, you have to add the SortHeaderLayer to your column header layer stack.
Please check the NatTable examples, like for example the SortableFilterableColumnGroupExample

Related

assertion failed: Unknown column layout data

When I create combo box in particular only one 3rd column using table viewer in Eclipse SWT.
I think I've done everything ok until now, however when I compile the code then i get error:
Code:
public void createPartControl(Composite parent) {
Composite tableComposite = new Composite(parent, SWT.NONE);
tableColumnLayout = new TableColumnLayout();
tableComposite.setLayout(tableColumnLayout);
tableComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true,
true));
tableViewer = new TableViewer(tableComposite, SWT.MULTI | SWT.H_SCROLL
| SWT.V_SCROLL);
tableViewer.setContentProvider(ArrayContentProvider.getInstance());
// TODO viewer.setLabelProvider(new ViewLabelProvider());
table = tableViewer.getTable();
// Table table = tableViewer.getTable();
table.setHeaderVisible(true);
table.setLinesVisible(true);
String[] titles = { "Threat Name", "Category Name", "Status",
"Priority", "Description", "Justification" };
int[] bounds = { 100, 100, 100, 100 };
TableViewerColumn col = createTableViewerColumn(titles[2], bounds[2], 2);
col.setLabelProvider(new ColumnLabelProvider() {
#Override
public String getText(Object element) {
Dummy p = (Dummy) element;
return p.getValue();
}
});
col.setEditingSupport(new FirstValueEditingSupport(tableViewer));
}
private SelectionAdapter getSelectionAdapter(final TableColumn column,
final int index) {
SelectionAdapter selectionAdapter = new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
tableViewer.refresh();
}
};
return selectionAdapter;
}
private static class Dummy {
public String value;
public Dummy(String value) {
this.value = value;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
public static class FirstValueEditingSupport extends EditingSupport {
private final TableViewer viewer;
private final CellEditor editor;
private final String[] possibleValues = { "Mitigated",
"Not Applicable", "Not Started", "Needs Investigation" };
public FirstValueEditingSupport(TableViewer viewer) {
super(viewer);
this.viewer = viewer;
this.editor = new ComboBoxCellEditor(viewer.getTable(),
possibleValues);
}
#Override
protected CellEditor getCellEditor(Object element) {
return editor;
}
#Override
protected boolean canEdit(Object element) {
return true;
}
#Override
protected Object getValue(Object element) {
Dummy dummy = (Dummy) element;
int index = 0;
for (int i = 0; i < possibleValues.length; i++) {
if (Objects.equals(possibleValues[i], dummy.getValue())) {
index = i;
break;
}
}
return index;
}
#Override
protected void setValue(Object element, Object value) {
Dummy dummy = (Dummy) element;
int index = (Integer) value;
dummy.setValue(possibleValues[index]);
viewer.update(element, null);
}
}
private void fillRows(String shortdesc, String categ, String descp) {
System.out.println("fillRows call from above method.");
TableColumn status_Name_Col = tableViewer.getTable().getColumn(2);
System.out.println("**************** status_Name_Col ************ "
+ status_Name_Col);
tableViewer
.addSelectionChangedListener(new ISelectionChangedListener() {
#Override
public void selectionChanged(
SelectionChangedEvent selectionChangedEvent) {
StructuredSelection selection = (StructuredSelection) selectionChangedEvent
.getSelection();
System.out.println(((Dummy) selection.getFirstElement())
.getValue());
}
});
List<Dummy> elements = new ArrayList<>();
for (int i = 0; i < Connection.Number_Of_Connection; i++) {
elements.add(new Dummy("First option"));
}
tableViewer.setInput(elements);
tableColumnLayout.setColumnData(status_Name_Col, new ColumnWeightData(
1, true));
tableViewerColumn.setEditingSupport(new FirstValueEditingSupport(
tableViewer));
}
Questions:
how to display combo box in particular only one column?
You must not do the TableViewer setInput call until you have set up everything on the table. All the content providers, label providers, column layouts, editing support, .... must be set before setInput is called.
You must also call setColumnData for every column you create.

How to re-render a specific node in gwt cell tree

I am implementing a directory structure like Windows Explorer. I want to re-render a specific node of tree after any folder operations is done such as add folder, remove folder... etc
private ListDataProvider<Object> dataProvider= new ListDataProvider<Object>();
private Object current;//store object of currentNode;
private Map<Object, ListDataProvider<Object>> keyprovider =
new HashMap<Object,ListDataProvider<Object>>();
private CellTree tree;
// keeps a map for storing dataproviders in each hierarchy ,
public void setListToCurrentNode(List<Object> newList){
//adding this newlist to current data provider not reflecting to display
keyprovider.get(currentObject).setList(newList);
}
public void onModuleLoad(){
treeSelectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
public void onSelectionChange(SelectionChangeEvent event) {
//setting current object as selected node
current = treeSelectionModel.getSelectedObject();
}
});
}
Data providers force to re-render corresponding DOM. Code below demonstrates how it works.
This example generates 2-leveled tree, where you can refresh (re-generate) leaf nodes by pressing Enter key on selected root node.
I tried to keep code as simple as possible, all needed stuff contained right here.
public class TestEntryPoint implements EntryPoint {
private static final Logger LOG = Logger.getLogger(TestEntryPoint.class.getName());
class Item {
String name;
boolean leaf;
public Item(String name, boolean leaf) {
this.name = name;
this.leaf = leaf;
}
#Override
public String toString() {
return "Item {name=" + name + ", leaf=" + leaf + "}";
}
}
class ItemCell extends AbstractCell<Item> {
public ItemCell() {
super("keydown");
}
#Override
public void render(Context context, Item value, SafeHtmlBuilder sb) {
if (value != null) sb.appendEscaped(value.name);
}
#Override
protected void onEnterKeyDown(
Context context, Element parent, Item value, NativeEvent event, ValueUpdater<Item> valueUpdater) {
LOG.info("ItemCell.onEnterKeyDown: value=" + value);
if (value == null || value.leaf) return;
ListDataProvider<Item> leafDataProvider = leafDataProviders.get(value.name);
if (leafDataProvider == null) return;
// -->> Here we generate new childs of selected root node
leafDataProvider.setList(generateLeafs());
}
}
class ItemTreeViewModel implements TreeViewModel {
#Override
public <T> NodeInfo<?> getNodeInfo(T value) {
return new DefaultNodeInfo<Item>(
value == null ? rootDataProvider : leafDataProviders.get(((Item) value).name),
new ItemCell());
}
#Override
public boolean isLeaf(Object value) {
return (value instanceof Item) && ((Item) value).leaf;
}
}
private int id = 0;
private CellTree cellTree;
private ListDataProvider<Item> rootDataProvider;
private Map<String, ListDataProvider<Item>> leafDataProviders = new HashMap<String, ListDataProvider<Item>>();
private List<Item> generateLeafs() {
List<Item> leafList = new ArrayList<Item>(5);
for (int j = 0; j < 5; ++j)
leafList.add(new Item("Leaf Item " + (++id), true));
return leafList;
}
public void onModuleLoad() {
List<Item> rootList = new ArrayList<Item>(10);
for (int i = 0; i < 10; ++i) {
Item rootItem = new Item("Root Item " + (++id), false);
rootList.add(rootItem);
leafDataProviders.put(rootItem.name, new ListDataProvider<Item>(generateLeafs()));
}
rootDataProvider = new ListDataProvider<Item>(rootList);
cellTree = new CellTree(new ItemTreeViewModel(), null);
cellTree.setAnimationEnabled(true);
RootLayoutPanel.get().add(cellTree);
}
}
Solved by Changing Listdataprovider into AsyncDataProvider ,Implementation is below
private final class DataProvider extends AsyncDataProvider<Object> {
private Object value;
private List Objs;
DataProvider(Object value) {
this.value = value;
}
public void update(List objs) {//Call update when you wanted to refresh tree
this.objs=objs;
for (HasData<Object> disp : getDataDisplays()) {
this.onRangeChanged(disp);
break;
}
}
#Override
protected void onRangeChanged(final HasData<Object> display) {
updateRowData(0, objs);
updateRowCount(objs.size(), true);
}

CheckboxCell, MultiSelectionModel unwantonly reset DataGrid's data

Using GWT 2.4...
I am building upon a complex Composite dual view/edit mode implementation that is backed GWT's DataGrid and MultiSelectionModel. My goal is for a user to be able to click a checkbox in each row that they'd like to post updates for.
Here's a screenshot from a semi-functional interface:
Note the selected (highlighted) rows.
Now the problem is that when I type something in any of the cells (e.g., the first row's $ cell under the $/Mw 1 composite cell header), then click that row's checkbox (or any other row's checkbox for that matter) to select or de-select, the value gets reset to the original value when the screen's data was first requested. Not desired behavior by any stretch!
Let's take a look at my custom implementation for the grid. (Excuse the length).
public abstract class ToggleableGrid<T extends Identifiable<?>> extends Composite {
private static final int CHKBOX_COLUMN_WIDTH = App.INSTANCE.checkboxColumnWidth();
private static final DisplayMode DEFAULT_MODE = DisplayMode.VIEW;
private ProvidesKey<T> keyProvider;
private DataGrid<T> grid;
private MultiSelectionModel<T> selectionModel;
private ListDataProvider<T> dataProvider;
private int tabIndex = 0;
public ToggleableGrid() {
final DataGridConfiguration config = new DefaultDataGridConfiguration();
initGrid(config);
}
public ToggleableGrid(DataGridConfiguration config) {
initGrid(config);
}
private void initGrid(DataGridConfiguration config) {
keyProvider = new ProvidesKey<T>() {
#Override
public Object getKey(T item) {
return item == null ? null : item.getId();
}
};
grid = new DataGrid<T>(config.getPageSize(), config.getResources(), keyProvider);
// Set the message to display when the table is empty.
grid.setEmptyTableWidget(new Label(UiMessages.INSTANCE.no_results()));
initWidget(grid);
setVisible(true);
}
public void setInput(List<T> content) {
setInput(content, DEFAULT_MODE);
}
public void setInput(List<T> content, DisplayMode mode) {
resetTableColumns();
if (isInEditMode(mode)) {
// Add a selection model so we can select cells
selectionModel = new MultiSelectionModel<T>(keyProvider);
grid.setSelectionModel(selectionModel, DefaultSelectionEventManager.<T> createCheckboxManager(0));
addRowSelector();
}
dataProvider = new ListDataProvider<T>(content);
final ListHandler<T> sortHandler = new ListHandler<T>(dataProvider.getList());
grid.addColumnSortHandler(sortHandler);
initializeStructure(constructMetadata(), sortHandler, mode);
dataProvider.addDataDisplay(grid);
}
// see https://stackoverflow.com/questions/3772480/remove-all-columns-from-a-celltable
// concrete classes are forced to maintain a handle on all columns added
private void resetTableColumns() {
for (final Column<T, ?> column: allColumns()) {
grid.removeColumn(column);
}
allColumns().clear();
}
protected boolean isInEditMode(DisplayMode currentDisplayMode) {
boolean result = false;
if (currentDisplayMode.equals(DisplayMode.EDIT)) {
result = true;
}
return result;
}
protected abstract Set<Column<T, ?>> allColumns();
protected abstract TableMetadata constructMetadata();
protected abstract void initializeStructure(TableMetadata metadata, ListHandler<T> sortHandler, DisplayMode mode);
protected void setColumnHorizontalAlignment(Column<T, ?> column, HorizontalAlignmentConstant alignment) {
column.setHorizontalAlignment(alignment);
}
// TODO figure out how to add a checkbox to column header that provides select/de-select all capability
// see https://stackoverflow.com/questions/6174689/gwt-celltable-programmatically-select-checkboxcell
protected void addRowSelector() {
final Column<T, Boolean> rowSelectColumn = new Column<T, Boolean>(new CheckboxCell(true, false)) {
#Override
public Boolean getValue(T value) {
Boolean result;
// check for null value and return null;
if(value == null || value.getId() == null) {
result = null;
} else { // get value from the selection model
result = selectionModel.isSelected(value);
}
return result;
}
};
addColumn(rowSelectColumn, UiMessages.INSTANCE.select());
setColumnWidth(rowSelectColumn, CHKBOX_COLUMN_WIDTH, Unit.PX);
setColumnHorizontalAlignment(rowSelectColumn, HasHorizontalAlignment.ALIGN_CENTER);
}
protected void setColumnWidth(Column<T, ?> column, int width, Unit unit) {
grid.setColumnWidth(column, width, unit);
}
protected void addColumn(Column<T, ?> column, String columnHeaderName) {
addColumn(column, columnHeaderName, HasHorizontalAlignment.ALIGN_RIGHT);
}
protected void addColumn(Column<T, ?> column, String columnHeaderName, HorizontalAlignmentConstant alignment) {
final SafeHtmlBuilder sb = new SafeHtmlBuilder();
final String divStart = "<div align=\""+ alignment.getTextAlignString() + "\" class=\"" +UiResources.INSTANCE.style().word_wrap() + "\">";
sb.appendHtmlConstant(divStart).appendEscaped(columnHeaderName).appendHtmlConstant("</div>");
final SafeHtml header = sb.toSafeHtml();
grid.addColumn(column, header);
allColumns().add(column);
}
protected CompositeCell<T> generateCompositeCell(final List<HasCell<T, ?>> hasCells) {
final CompositeCell<T> compositeCell = new CompositeCell<T>(hasCells) {
#Override
public void render(Context context, T value, SafeHtmlBuilder sb) {
sb.appendHtmlConstant("<table><tbody><tr>");
super.render(context, value, sb);
sb.appendHtmlConstant("</tr></tbody></table>");
}
#Override
protected Element getContainerElement(Element parent) {
// Return the first TR element in the table.
return parent.getFirstChildElement().getFirstChildElement().getFirstChildElement();
}
#Override
protected <X> void render(Context context, T value,
SafeHtmlBuilder sb, HasCell<T, X> hasCell) {
final Cell<X> cell = hasCell.getCell();
sb.appendHtmlConstant("<td>");
cell.render(context, hasCell.getValue(value), sb);
sb.appendHtmlConstant("</td>");
}
};
return compositeCell;
}
// FIXME not working quite the way we'd expect, index incremented within column for each row, not each row by column
protected int nextTabIndex() {
tabIndex++;
return tabIndex;
}
protected AbstractCellTable<T> getGrid() {
return grid;
}
/**
* Gets the selected (row(s) of) data from grid (used in edit mode)
* #return the selected data (as per selection model)
*/
public List<T> getSelectedData() {
final List<T> data = new ArrayList<T>();
data.addAll(selectionModel.getSelectedSet());
return data;
}
/**
* Gets all (row(s) of) data in grid (used in edit mode)
* #return all data as list
*/
public List<T> getAllData() {
return dataProvider.getList();
}
/**
* Clears the currently selected (row(s) of) data (used in edit mode)
*/
public void clearSelectedData() {
selectionModel.clear();
grid.redraw();
}
}
So, the interesting methods to stare at above (I think) are setInput, generateCompositeCell and addRowSelector.
We initialize the grid with List data and set a display mode in setInput. It's here as well that the selection model is initialized. It uses GWT's DefaultSelectionEventManager createCheckboxManager().
I've been trying to grok the event model, but it eludes me. I've visited the following sources online, but have come up short on avenues to solving this problem.
-- https://groups.google.com/forum/?fromgroups#!topic/google-web-toolkit/k5sfURxDaVg
AbstractInputCell's getConsumedEventsImpl adds focus, blur and keydown, so this (I believe) is not a track I need to explore
-- GWT CellTable programmatically select CheckBoxCell
The various ways you can instantiate a CheckBoxCell got me curious, and I've tried many constructor argument permutations, but the one I settled on (true, false) is (I believe) the right one
Agreeing here and now (before being reprimanded) that there's perhaps some unnecessary complexity in my implementation, but I am looking for guidance nonetheless. Thanks!
Update
If it helps here's an impl of the aforementioned ToggleableGrid. If anything it gives you more detail on what goes into each CompositeCell. For details on AbstractValidatableColumn and ValidatableInputCell, see: In search of a GWT validation example... where art thou?.
public class EnergyOfferGrid extends ToggleableGrid<EnergyOfferDTO> {
public EnergyOfferGrid() {
super();
}
public EnergyOfferGrid(DataGridConfiguration config) {
super(config);
}
private static final int MAX_NUMBER_OF_MW_PRICE_POINTS = App.INSTANCE.maxNoOfMwPricePoints();
private Set<Column<EnergyOfferDTO, ?>> columns = new HashSet<Column<EnergyOfferDTO, ?>>();
#Override
protected Set<Column<EnergyOfferDTO, ?>> allColumns() {
return columns;
}
#Override
protected TableMetadata constructMetadata() {
final TableMetadata metadata = new TableMetadata();
// TODO Consider a predefined set of ReferenceData to be held in a common package
// Use Slope
metadata.addColumnMetadata(UiMessages.INSTANCE.use_slope(), new String[] {UiMessages.INSTANCE.yes(), UiMessages.INSTANCE.no()}, new String[] {"true", "false"});
return metadata;
}
#Override
protected void initializeStructure(TableMetadata metadata, ListHandler<EnergyOfferDTO> sortHandler, DisplayMode currentDisplayMode) {
addHourColumn(sortHandler);
addUseSlopeColumn(metadata, sortHandler, currentDisplayMode);
for (int i = 0; i < MAX_NUMBER_OF_MW_PRICE_POINTS; i++) { // zero-based indexing
addPriceMwColumn(i, currentDisplayMode);
}
}
protected void addHourColumn(ListHandler<EnergyOfferDTO> sortHandler) {
final Column<EnergyOfferDTO, String> hourColumn = new Column<EnergyOfferDTO, String>(new TextCell()) {
#Override
public String getValue(EnergyOfferDTO energyOffer) {
String result = "";
if (energyOffer.getId() != null) {
final String isoDateTime = energyOffer.getId().getOperatingHour();
if (isoDateTime != null && !isoDateTime.isEmpty()) {
final Date dateTime = CSTimeUtil.isoToDate(isoDateTime);
if (dateTime != null) {
result = CSTimeUtil.dateToHour(dateTime);
}
}
}
return result;
}
};
hourColumn.setSortable(true);
sortHandler.setComparator(hourColumn, new Comparator<EnergyOfferDTO>() {
#Override
public int compare(EnergyOfferDTO eo1, EnergyOfferDTO eo2) {
final String date1 = eo1.getId() != null ? eo1.getId().getOperatingHour() : "";
final String date2 = eo2.getId() != null ? eo2.getId().getOperatingHour() : "";
return date1.compareTo(date2);
}
});
// We know that the data is sorted by hour by default.
getGrid(). getColumnSortList().push(hourColumn);
addColumn(hourColumn, UiMessages.INSTANCE.hour());
setColumnWidth(hourColumn, 45, Unit.PX);
setColumnHorizontalAlignment(hourColumn, HasHorizontalAlignment.ALIGN_RIGHT);
}
protected void addUseSlopeColumn(TableMetadata metadata, ListHandler<EnergyOfferDTO> sortHandler, DisplayMode currentDisplayMode) {
final ReferenceData refData = metadata.allColumnMetadata().get(UiMessages.INSTANCE.use_slope());
Column<EnergyOfferDTO, String> useSlopeColumn;
Cell<String> cell;
if (isInEditMode(currentDisplayMode)) {
cell = new ReferenceDataBackedSelectionCell(refData);
} else {
cell = new TextCell();
}
useSlopeColumn = new Column<EnergyOfferDTO, String>(cell) {
#Override
public String getValue(EnergyOfferDTO energyOffer) {
return refData.getDisplayValueForSubmitValue(Boolean.toString(energyOffer.isSlopeUsed()));
}
};
useSlopeColumn.setSortable(true);
sortHandler.setComparator(useSlopeColumn, new Comparator<EnergyOfferDTO>() {
#Override
public int compare(EnergyOfferDTO eo1, EnergyOfferDTO eo2) {
final String slopeUsed1 = String.valueOf(eo1.isSlopeUsed());
final String slopeUsed2 = String.valueOf(eo1.isSlopeUsed());
return slopeUsed1.compareTo(slopeUsed2);
}
});
addColumn(useSlopeColumn, UiMessages.INSTANCE.use_slope());
setColumnWidth(useSlopeColumn, 75, Unit.PX);
setColumnHorizontalAlignment(useSlopeColumn, HasHorizontalAlignment.ALIGN_RIGHT);
}
protected void addPriceMwColumn(final int colIndex, DisplayMode currentDisplayMode) {
// Construct a composite cell for energy offers that includes a pair of text inputs
final List<HasCell<EnergyOfferDTO, ?>> columns = new ArrayList<
HasCell<EnergyOfferDTO, ?>>();
// this DTO is passed along so that price and mw values for new entries are kept together
final OfferPriceMwPair newOfferPriceMwPair = new OfferPriceMwPair();
// Price
final Column<EnergyOfferDTO, String> priceColumn = generatePriceColumn(colIndex, newOfferPriceMwPair, currentDisplayMode);
columns.add(priceColumn);
// MW
final Column<EnergyOfferDTO, String> mwColumn = generateMwColumn(colIndex, newOfferPriceMwPair, currentDisplayMode);
columns.add(mwColumn);
// Composite
final CompositeCell<EnergyOfferDTO> priceMwColumnInnards = generateCompositeCell(columns);
final IdentityColumn<EnergyOfferDTO> priceMwColumn = new IdentityColumn<EnergyOfferDTO>(priceMwColumnInnards);
final StringBuilder colHeader = new StringBuilder();
colHeader.append(UiMessages.INSTANCE.price_mw_header()).append(" ").append(String.valueOf(colIndex + 1));
addColumn(priceMwColumn, colHeader.toString());
setColumnWidth(priceMwColumn, 7, Unit.EM);
setColumnHorizontalAlignment(priceMwColumn, HasHorizontalAlignment.ALIGN_RIGHT);
}
protected Column<EnergyOfferDTO, String> generatePriceColumn(final int colIndex, final OfferPriceMwPair newOfferPriceMwPair, DisplayMode currentDisplayMode) {
Column<EnergyOfferDTO, String> priceColumn;
if (isInEditMode(currentDisplayMode)) {
priceColumn = new BigDecimalValidatableColumn<EnergyOfferDTO, OfferPriceMwPair>(nextTabIndex(), getGrid()) {
#Override
public String getValue(EnergyOfferDTO energyOffer) {
return obtainPriceValue(colIndex, energyOffer, false);
}
#Override
public void doUpdate(int index, EnergyOfferDTO energyOffer, String value) {
if (value != null && !value.isEmpty()) {
// number format exceptions should be caught and handled by event bus's handle method
final double valueAsDouble = NumberFormat.getDecimalFormat().parse(value);
final BigDecimal price = BigDecimal.valueOf(valueAsDouble);
final List<OfferPriceMwPair> offerPriceCurve = energyOffer.getCurve();
final OfferPriceMwPair offerPriceMwPair = offerPriceCurve.get(colIndex);
if (offerPriceMwPair == null) { // we have a new price value
newOfferPriceMwPair.setPrice(price);
offerPriceCurve.add(newOfferPriceMwPair);
} else {
offerPriceMwPair.setPrice(price);
}
}
}
#Override
protected String getPropertyName() {
return "price";
}
#Override
protected Class<OfferPriceMwPair> getPropertyOwner() {
return OfferPriceMwPair.class;
}
};
} else {
priceColumn = new Column<EnergyOfferDTO, String>(new TextCell()) {
#Override
public String getValue(EnergyOfferDTO energyOffer) {
final String result = obtainPriceValue(colIndex, energyOffer, true);
return result;
}
};
}
return priceColumn;
}
private String obtainPriceValue(final int colIndex, EnergyOfferDTO energyOffer, boolean withCurrency) {
String result = "";
if (energyOffer != null) {
final List<OfferPriceMwPair> offerPriceCurve = energyOffer.getCurve();
final int numberOfPairs = offerPriceCurve.size();
if (colIndex < numberOfPairs) {
final OfferPriceMwPair offerPriceMwPair = offerPriceCurve.get(colIndex);
if (offerPriceMwPair != null) {
final BigDecimal price = offerPriceMwPair.getPrice();
if (price != null) {
final double value = price.doubleValue();
if (withCurrency) {
result = NumberFormat.getCurrencyFormat().format(value);
} else {
result = NumberFormat.getDecimalFormat().format(value);
}
}
}
}
}
return result;
}
protected Column<EnergyOfferDTO, String> generateMwColumn(final int colIndex, final OfferPriceMwPair newOfferPriceMwPair, DisplayMode currentDisplayMode) {
Column<EnergyOfferDTO, String> mwColumn;
if (isInEditMode(currentDisplayMode)) {
mwColumn = new BigDecimalValidatableColumn<EnergyOfferDTO, PriceMwPair>(nextTabIndex(), getGrid()) {
#Override
public String getValue(EnergyOfferDTO energyOffer) {
return obtainMwValue(colIndex, energyOffer);
}
#Override
public void doUpdate(int index, EnergyOfferDTO energyOffer, String value) {
if (value != null && !value.isEmpty()) {
// number format exceptions should be caught and handled by event bus's handle method
final double valueAsDouble = NumberFormat.getDecimalFormat().parse(value);
final BigDecimal mw = BigDecimal.valueOf(valueAsDouble);
final List<OfferPriceMwPair> offerPriceCurve = energyOffer.getCurve();
final OfferPriceMwPair offerPriceMwPair = offerPriceCurve.get(colIndex);
if (offerPriceMwPair == null) { // we have a new price value
newOfferPriceMwPair.setMw(mw);
offerPriceCurve.add(newOfferPriceMwPair);
} else {
offerPriceMwPair.setMw(mw);
}
}
}
#Override
protected String getPropertyName() {
return "mw";
}
#Override
protected Class<PriceMwPair> getPropertyOwner() {
return PriceMwPair.class;
}
};
} else {
mwColumn = new Column<EnergyOfferDTO, String>(new TextCell()) {
#Override
public String getValue(EnergyOfferDTO energyOffer) {
final String result = obtainMwValue(colIndex, energyOffer);
return result;
}
};
}
return mwColumn;
}
private String obtainMwValue(final int colIndex, EnergyOfferDTO energyOffer) {
String result = "";
if (energyOffer != null) {
final List<OfferPriceMwPair> offerPriceCurve = energyOffer.getCurve();
final int numberOfPairs = offerPriceCurve.size();
if (colIndex < numberOfPairs) {
final PriceMwPair offerPriceMwPair = offerPriceCurve.get(colIndex);
if (offerPriceMwPair != null) {
final BigDecimal mw = offerPriceMwPair.getMw();
if (mw != null) {
result = NumberFormat.getDecimalFormat().format(mw);
}
}
}
}
return result;
}
}
All that custom work w.r.t. WrapperCell and CompositeValidatableColumn was unnecessary.
It turns out that there's a way you should not construct CompositeCells. See http://code.google.com/p/google-web-toolkit/issues/detail?id=5714. My CompositeCells were not receiving events. So, I changed the way I construct them in ToggleableGrid.
protected CompositeCell<T> generateCompositeCell(final List<HasCell<T, String>> hasCells) {
final CompositeCell<T> compositeCell = new CompositeCell<T>(hasCells) {
// to not run afoul of http://code.google.com/p/google-web-toolkit/issues/detail?id=5714
#Override
public void render(Context context, T value, SafeHtmlBuilder sb) {
sb.appendHtmlConstant("<div style=\"display: inline\">");
super.render(context, value, sb);
sb.appendHtmlConstant("</div>");
}
#Override
protected Element getContainerElement(Element parent) {
// Return the first element in the DIV.
return parent.getFirstChildElement();
}
};
return compositeCell;
}
After that change and incorporating my other validation-oriented classes: ValidatableFieldUpdater, AbstractValidatableColumn (and derivatives), ValidatableInputField and ConversionResult, life couldn't be more grand!

Drag and drop for tableviewer in SWT

I need to Drag tableViewer cell value to another tableViewer cell in swt.
I need to remove that value where i dragged and add those value where i dropped in tableViewer i'm able to drag and drop but not able to drop where i want too and not able to remove and add value when i drag and drop in tableviewer. Here is the i have:Thank in advance for help.
public void DragandDrop(){
Transfer[] types = new Transfer[] { TextTransfer.getInstance() };
DragSource source = new DragSource(table_2, DND.DROP_MOVE | DND.DROP_COPY);
source.setTransfer(types);
source.addDragListener(new DragSourceAdapter() {
public void dragSetData(DragSourceEvent event) {
DragSource ds = (DragSource) event.widget;
Table table = (Table) ds.getControl();
TableItem[] selection = table.getSelection();
StringBuffer buff = new StringBuffer();
for (int i = 0, n = selection.length; i < n; i++) {
buff.append(selection[i].getText());
}
event.data = buff.toString();
}
});
DropTarget target = new DropTarget(table_3, DND.DROP_MOVE | DND.DROP_COPY );
target.setTransfer(types);
target.addDropListener(new DropTargetAdapter() {
public void dragEnter(DropTargetEvent event) {
if (event.detail != DND.DROP_DEFAULT) {
event.detail = (event.operations & DND.DROP_COPY) != 0 ? DND.DROP_COPY : DND.DROP_NONE;
}
for (int i = 0, n = event.dataTypes.length; i < n; i++) {
if (TextTransfer.getInstance().isSupportedType(event.dataTypes[i])) {
event.currentDataType = event.dataTypes[i];
}
}
}
public void dragOver(DropTargetEvent event) {
event.feedback = DND.FEEDBACK_SELECT | DND.FEEDBACK_SCROLL;
}
public void drop(DropTargetEvent event) {
if (TextTransfer.getInstance().isSupportedType(event.currentDataType)) {
DropTarget target = (DropTarget) event.widget;
Table table = (Table) target.getControl();
String data = (String) event.data;
TableItem item = new TableItem(table, SWT.NONE);
item.setText(new String[] { data });
// table.redraw();
}
}
});
}
to remove the selected value you can use follows
public void drop(DropTargetEvent event) {
if (TextTransfer.getInstance().isSupportedType(event.currentDataType)) {
DropTarget target = (DropTarget) event.widget;
Table table = (Table) target.getControl();
String data = (String) event.data;
TableItem item = new TableItem(table, SWT.NONE);
item.setText(new String[] { data });
//remove the tableitem you drag
table.remove(table.getSelectionIndex());
}
I was looking for Drag and Drop on TableViewer and found the solutions. Hope everyone understand easily. My case, I created two new Listener class inheritance from DragSourceListener & DropTargetListener. Because I want to use TableViewer functions. You need three things to do.
First save index of source item from void dragStart(DragSourceEvent event),
Seconds set data into event.data and
Then Last found target index from void drop(DropTargetEvent event).
public class TestClass extends TableViewer {
private int sourceIndex;
priavte class DragListener implements DragSourceListener {
private TableViewer viewer;
public ItemDragListener(TableViewer viewer) {
this.viewer = viewer;
}
public void dragStart(DragSourceEvent event) {
sourceIndex = viewer.getTable().getSelectionIndex();
}
public void dragSetData(DragSourceEvent event) {
// save data
ISelection select = viewer.getSelection();
if (select instanceof IStructuredSelection) {
Object item = (Object) ((IStructuredSelection)select).getFirstElement();
// save item to event.data
event.data = .........
}
:
}
private class ItemDropListener implements DropTargetListener {
TableViewer viewer;
public ItemDropListener(TableViewer viewer) {
this.viewer = viewer;
}
public void drop(DropTargetEvent event) {
if (TextTransfer.getInstance().isSupportedType(event.currentDataType)) {
TableItem item = (TableItem)event.item;
int targetIndex= -1;
if (item != null) {
Table table = item.getParent();
targetIndex= table.indexOf(item);
}
String data = (String) event.data;
// add an item
if (targetIndex >= 0)
viewer.insert((Object)data, targetIndex);
else
viewer.add((Object)data);
// remove an item
viewer.getTable().remove(sourceIndex); // Careful, it can be changed after add an item
}
}
public void init() {
Transfer[] transfers = new Transfer[] { TextTransfer.getInstance() };
this.addDragSupport(DND.DROP_COPY | DND.DROP_MOVE, transfers, new ItemDragListener(this));
this.addDropSupport(DND.DROP_COPY | DND.DROP_MOVE, transfers, new ItemDropListener(this));
}
}

Problem with GWT connector in a straight ended connection

I am trying to make a straight ended connection between widgets.But when I am doing so, the orientation of my connector is coming wrong.Its always coming parallel to the required one.Also , it is independent of the connecting widgets i.e when I move my widget, my connector does not move.Snippet of my code is given as :
Link to snapshot of the problem: http://goo.gl/JUEmJ
public class DragNDropPage {
SyncCurrentUser cu = SyncCurrentUser.getUser();
private AbsolutePanel area = new AbsolutePanel();
HorizontalPanel toolsPanel = new HorizontalPanel();
AbsolutePanel canvas = new AbsolutePanel();
DragController toolboxDragController;
Label startLabel = new Label("START");
Label stopLabel = new Label("STOP");
Label activityLabel = new Label("ACTIVITY");
Label processLabel = new Label("PROCESS");
Button stopDrag = new Button("Done Dragging");
Button saveButton = new Button("Save");
PickupDragController dragController = new PickupDragController(area, true);
AbsolutePositionDropController dropController = new AbsolutePositionDropController(area);
private List<Widget> selected = new ArrayList<Widget>();
private List<Widget> onCanvas = new ArrayList<Widget>();
private List<Connection> connections = new ArrayList<Connection>();
private CActivity[] aItems;
private CProcess[] pItems;
MyHandler handler = new MyHandler();
int mouseX,mouseY;
String style;
public DragNDropPage() {
toolboxDragController = new ToolboxDragController(dropController, dragController);
RootPanel.get("rightbar").add(area);
area.setSize("575px", "461px");
area.add(toolsPanel);
toolsPanel.setSize("575px", "37px");
toolsPanel.add(startLabel);
startLabel.setSize("76px", "37px");
toolboxDragController.makeDraggable(startLabel);
toolsPanel.add(stopLabel);
stopLabel.setSize("66px", "37px");
toolboxDragController.makeDraggable(stopLabel);
toolsPanel.add(activityLabel);
activityLabel.setSize("82px", "36px");
toolboxDragController.makeDraggable(activityLabel);
toolsPanel.add(processLabel);
processLabel.setSize("85px", "36px");
toolboxDragController.makeDraggable(processLabel);
stopDrag.addClickHandler(handler);
toolsPanel.add(stopDrag);
stopDrag.setWidth("114px");
saveButton.addClickHandler(handler);
toolsPanel.add(saveButton);
area.add(canvas, 0, 36);
canvas.setSize("575px", "425px");
Event.addNativePreviewHandler(new Event.NativePreviewHandler() {
#Override
public void onPreviewNativeEvent(NativePreviewEvent event) {
//46 is the key code for Delete Button
if(event.getNativeEvent().getKeyCode() == 46 && !selected.isEmpty()) {
for (Iterator<Widget> i = selected.listIterator(); i.hasNext();) {
Widget w = (Widget) i.next();
UIObjectConnector.unwrap(w);
i.remove();
w.removeFromParent();
onCanvas.remove(i);
}
}
}
});
aItems = cu.currentUser.getcActivity();
pItems = cu.currentUser.getcProcess();
}
private class ToolboxDragController extends PickupDragController {
public ToolboxDragController(final DropController dropController, final DragController nodesDragController) {
super(area ,false);
setBehaviorDragProxy(true);
registerDropController(dropController);
addDragHandler(new DragHandlerAdapter(){
public void onPreviewDragEnd(DragEndEvent event) throws VetoDragException {
Widget node = (Widget) event.getSource();
int left = event.getContext().desiredDraggableX;
int top = event.getContext().desiredDraggableY;
AbsolutePanel panel = (AbsolutePanel) dropController.getDropTarget();
createConnector((Label) node, panel, left, top);
throw new VetoDragException();
}
});
}
}
protected UIObjectConnector createConnector(Label proxy, AbsolutePanel panel, int left, int top) {
Widget w;
String str = proxy.getText();
if(str.equals("START") || str.equals("STOP")){
w = new Label(proxy.getText()){
public void onBrowserEvent(Event event) {
if( DOM.eventGetType(event) == 4
&& DOM.eventGetCtrlKey(event)){
select(this);
}
super.onBrowserEvent(event);
}
};
w.getElement().setClassName("dnd-start-stop");
}
else{
w = new ListBox(){
public void onBrowserEvent(Event event) {
if( DOM.eventGetType(event) == 4
&& DOM.eventGetCtrlKey(event)){
select(this);
}
super.onBrowserEvent(event);
}
};
if(str.equals("ACTIVITY")){
getAItems((ListBox)w);
//w.getElement().addClassName("dnd-activity");
}
else if(str.equals("PROCESS")){
getPItems((ListBox)w);
//w.getElement().addClassName("dnd-process");
}
}
onCanvas.add(w);
left -= panel.getAbsoluteLeft();
top -= panel.getAbsoluteTop();
//panel.add(w,10,10);
panel.add(w, left, top);
dragController.makeDraggable(w);
return UIObjectConnector.wrap(w);
}
private void getAItems(ListBox w) {
for(int i=0;i<aItems.length;i++)
w.addItem(aItems[i].getActivityName());
}
private void getPItems(ListBox w) {
/*for(int i=0;i<pItems.length;i++)
w.addItem(pItems[i].getProcessName());*/
w.addItem("Process1");
}
protected void select(Widget w){
if(selected.isEmpty()) {
selected.add(w);
w.getElement().addClassName("color-green");
} else if(selected.contains(w)){
selected.remove(w);
w.getElement().removeClassName("color-green");
} else if(selected.size() == 1) {
Widget w2 = (Widget) selected.get(0);
connect(UIObjectConnector.getWrapper(w2), UIObjectConnector.getWrapper(w));
selected.clear();
}
}
protected void connect(Connector a, Connector b) {
//System.out.println(a.getLeft());
//System.out.println(b.getLeft());
add(new StraightTwoEndedConnection(a,b));
}
private void add(StraightTwoEndedConnection c) {
canvas.add(c);
connections.add(c);
c.update();
}
protected void remove(Connection c) {
connections.remove(c);
}
class MyHandler implements ClickHandler{
#Override
public void onClick(ClickEvent event) {
Button name = (Button) event.getSource();
if(name.equals(stopDrag)){
if(name.getText().equals("Done Dragging")){
for(Iterator<Widget> i = onCanvas.listIterator();i.hasNext();){
Widget w = (Widget) i.next();
dragController.makeNotDraggable(w);
}
name.setText("Continue");
}
else {
for(Iterator<Widget> i = onCanvas.listIterator();i.hasNext();){
Widget w = (Widget) i.next();
dragController.makeDraggable(w);
}
name.setText("Done Dragging");
}
}
else{
}
}
}
}
I know this is quite old, but I was having similar issues with the gwt-connector library.
The connectors will not appear in the correct placement if you are using standards mode. Use quirks mode instead.
Additionally, you need to manually perform a connector.update() while your dnd components are being dragged (in your drag listener) for the connection to move with the endpoint while you are dragging.