I have a TwinColSelect and a Textfield that I use to filter the content of the table, it works great, but the problem is that the filter filters the content of both columnos of the TwinColSelect, and I would like to know if it is possible that it only affects to the left column.
My code right now looks like this:
final TwinColSelect select = new TwinColSelect();
select.setItemCaptionPropertyId(PersistenceLoinc.CORPUS_NOMBRE);
TextField filtro = new TextField();
filtro.addTextChangeListener(new TextChangeListener() {
private static final long serialVersionUID = 1L;
SimpleStringFilter filter = null;
#Override
public void textChange(TextChangeEvent event) {
Filterable f = (Filterable) select.getContainerDataSource();
if (filter != null) {
f.removeContainerFilter(filter);
}
filter = new SimpleStringFilter(select.getItemCaptionPropertyId(), event.getText(), true, false);
f.addContainerFilter(filter);
}
});
Thanks,
Cris.
I followed the suggestion from #andreSchild in the comments section of the question, and developed the following class that works perfectly:
public class TwinColSelectStringFilter implements Container.Filter {
final SimpleStringFilter spf;
final TwinColSelect select;
final Object propertyId;
public TwinColSelectStringFilter(Object propertyId, String filterString, boolean ignoreCase, boolean onlyMatchPrefix, TwinColSelect select) {
spf = new SimpleStringFilter(propertyId, filterString, ignoreCase, onlyMatchPrefix);
this.select = select;
this.propertyId=propertyId;
}
#Override
public boolean passesFilter(Object itemId, Item item) throws UnsupportedOperationException {
if(select.getValue() != null && (select.getValue() instanceof Collection)) {
if (((Collection<Integer>) select.getValue()).contains(itemId)) {
return true;
}
}
return spf.passesFilter(itemId, item);
}
#Override
public boolean appliesToProperty(Object propertyId) {
return spf.appliesToProperty(propertyId);
}
}
Related
i'm trying to implement a lucene filter to remove a prefix from a term in a query.
It seems that sometime after multiple queries, the filter has been reused so the char buffer is dirty.
Code below is simplified, prefix is an external parameter.
public static class PrefixFilter extends TokenFilter {
private final PackedTokenAttributeImpl termAtt = (PackedTokenAttributeImpl) addAttribute(CharTermAttribute.class);
public PrefixFilter(TokenStream in) {
super(in);
}
#Override
public final boolean incrementToken() throws IOException {
if (!input.incrementToken()) {
return false;
}
String value = new String(termAtt.buffer());
value = value.trim();
value = value.toLowerCase();
value = StringUtils.removeStart(value, "prefix_");
if (value.isBlank()) {
termAtt.setEmpty();
} else {
termAtt.copyBuffer(value.toCharArray(), 0, value.length());
termAtt.setLength(value.length());
}
return true;
}
}
So after 10 or twelve queries, the value "prefix_a" became "abcde".
So i'm trying to add termBuffer offset end value in this way:
termAtt.setEmpty();
termAtt.resizeBuffer(value.length());
termAtt.copyBuffer(value.toCharArray(), 0, value.length());
termAtt.setLength(value.length());
termAtt.setOffset(0, value.length());
But i don't know if it's correct. Can anyone help me?
Thanks.
See if this helps you,
/**
* Standard number token filter.
*/
public class StandardnumberTokenFilter extends TokenFilter {
private final LinkedList<PackedTokenAttributeImpl> tokens;
private final StandardnumberService service;
private final Settings settings;
private final CharTermAttribute termAtt = addAttribute(CharTermAttribute.class);
private final PositionIncrementAttribute posIncAtt = addAttribute(PositionIncrementAttribute.class);
private State current;
protected StandardnumberTokenFilter(TokenStream input, StandardnumberService service, Settings settings) {
super(input);
this.tokens = new LinkedList<>();
this.service = service;
this.settings = settings;
}
#Override
public final boolean incrementToken() throws IOException {
if (!tokens.isEmpty()) {
if (current == null) {
throw new IllegalArgumentException("current is null");
}
PackedTokenAttributeImpl token = tokens.removeFirst();
restoreState(current);
termAtt.setEmpty().append(token);
posIncAtt.setPositionIncrement(0);
return true;
}
if (input.incrementToken()) {
detect();
if (!tokens.isEmpty()) {
current = captureState();
}
return true;
} else {
return false;
}
}
private void detect() throws CharacterCodingException {
CharSequence term = new String(termAtt.buffer(), 0, termAtt.length());
Collection<CharSequence> variants = service.lookup(settings, term);
for (CharSequence ch : variants) {
if (ch != null) {
PackedTokenAttributeImpl token = new PackedTokenAttributeImpl();
token.append(ch);
tokens.add(token);
}
}
}
#Override
public void reset() throws IOException {
super.reset();
tokens.clear();
current = null;
}
#Override
public boolean equals(Object object) {
return object instanceof StandardnumberTokenFilter &&
service.equals(((StandardnumberTokenFilter)object).service) &&
settings.equals(((StandardnumberTokenFilter)object).settings);
}
#Override
public int hashCode() {
return service.hashCode() ^ settings.hashCode();
}
}
https://github.com/jprante/elasticsearch-plugin-bundle/blob/f63690f877cc7f50360faffbac827622c9d404ef/src/main/java/org/xbib/elasticsearch/plugin/bundle/index/analysis/standardnumber/StandardnumberTokenFilter.java
I am new to Eclipse RCP/Plug-ins and SWT. I want to reorder table items via drag-and-drop.
I have a TableViewer which contains a table with my custom elements of type ITask (еach of my custom elements is wrapped in TableItem). All tutorials I found are about trees or dragging between different tables which is not what I need.
So I want to know how to reorder the table rows via drag-and-drop.
It's a bit long, but you can make this work in your code with a few changes. I did not included the imports; Eclipse can do it for you automatically.
I used Spring's BeanUtils class but you can use any lib (or write your own) that can deepcopy POJOs. I assume that your ITask has a setOrder(int) method and is Serializable (and it qualifies for a POJO)
You need to create a Transfer-type for your ITask: SimpleObjectTransfer is IBM's code, from Eclipse GEF. You can Google/GrepCode it.
public final class TaskTransfer extends SimpleObjectTransfer {
public static final TaskTransfer INSTANCE = new TaskTransfer();
private TaskTransfer() {
}
#Override
protected String getTypeNamePrefix() {
return "TASK_TRANSFER_FORMAT";
}
}
A ViewerDropAdapter:
public class MyDropAdapter<TM extends ITask> extends ViewerDropAdapter {
private final Class<TM> targetModelClass;
private List<TM> listOfModels;
protected MyDropAdapter(Viewer viewer, Class<TM> targetModelClass, List<TM> listOfModels) {
super(viewer);
this.listOfModels = listOfModels;
this.targetModelClass = targetModelClass;
}
#Override
public boolean performDrop(Object arg0) {
boolean ret = false;
TM targetModel = targetModelClass.cast(determineTarget(getCurrentEvent()));
if (targetModel != null) {
if (List.class.isAssignableFrom(arg0.getClass())) {
ret = processDropToTable(targetModel, arg0);
getViewer().refresh();
}
}
return ret;
}
public final boolean processDropToTable(TM targetModel, Object data) {
List<TM> transferredModels = (List<TM>) data;
List<TM> copyOfTransferredModels = transferredModels;
switch (getCurrentOperation()) {
case DND.DROP_COPY:
copyOfTransferredModels = deepCopyBeanList(transferredModels, new String[]{});
break;
case DND.DROP_MOVE:
// moving
break;
default:
throw new UnsupportedOperationException(getCurrentOperation() + " is not supported!");
}
adjustPosition(transferredModels, copyOfTransferredModels, targetModel);
return true;
}
private void adjustPosition(List<TM> transferredModels, List<TM> copyOfTransferredModels, TM targetModel) {
int transferredObjectPosition = listOfModels.indexOf(transferredModels.get(0));
listOfModels.removeAll(copyOfTransferredModels);
addModelsToNewLocation(copyOfTransferredModels, targetModel, listOfModels, transferredObjectPosition);
for (int i = 0; i < listOfModels.size(); i++) {
int orderPosition = i * 10 + 10;
listOfModels.get(i).setOrder(orderPosition);
}
}
protected void addModelsToNewLocation(List<TM> transferredModels, TM targetModel, List<TM> targetList, int transferredObjectPosition) {
switch (determineLocation(getCurrentEvent())) {
case LOCATION_AFTER:
case LOCATION_ON:
int i;
if (!transferredModels.contains(targetModel)) {
i = targetList.indexOf(targetModel) + 1;
} else {
i = transferredObjectPosition;
}
targetList.addAll(i, transferredModels);
break;
case LOCATION_BEFORE:
if (!transferredModels.contains(targetModel)) {
i = targetList.indexOf(targetModel);
} else {
i = transferredObjectPosition;
}
targetList.addAll(i, transferredModels);
break;
case LOCATION_NONE:
default:
break;
}
}
private List<TM> deepCopyBeanList(List<TM> transferredModels, String[] ignoreProperties) {
List<TM> targetList = new LinkedList<TM>();
for (TM element : transferredModels) {
try {
#SuppressWarnings("unchecked")
TM copy = (TM) element.getClass().newInstance();
BeanUtils.copyProperties(element, copy, ignoreProperties);
targetList.add(copy);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
return targetList;
}
#Override
public boolean validateDrop(Object arg0, int arg1, TransferData arg2) {
boolean ret = false;
for (Transfer t : new Transfer[]{TaskTransfer.INSTANCE}) {
if (t.isSupportedType(arg2)) {
ret = true;
break;
}
}
return ret;
}
}
A DragSourceListener
public class MyDragSourceListener implements DragSourceListener {
private final Viewer dragSourceViewer;
private final boolean multiObjectsEnabled;
private final Class<?> transferrableElementClass;
private Object[] draggedObjects;
public MyDragSourceListener(Viewer dragSourceViewer, boolean multiObjectsEnabled, Class<?> transferrableElementClass) {
this.dragSourceViewer = dragSourceViewer;
this.multiObjectsEnabled = multiObjectsEnabled;
this.transferrableElementClass = transferrableElementClass;
}
#Override
public void dragStart(DragSourceEvent event) {
Control source = ((DragSource) event.getSource()).getControl();
draggedObjects = null;
if (dragSourceViewer.getControl().equals(source)) {
if (multiObjectsEnabled) {
draggedObjects = ((StructuredSelection) dragSourceViewer.getSelection()).toArray();
} else {
draggedObjects = new Object[]{((StructuredSelection) dragSourceViewer.getSelection()).getFirstElement()};
}
}
event.doit = draggedObjects.length > 0 && transferredDataIsSupported();
}
private boolean transferredDataIsSupported() {
boolean ret = true;
for (Object o : draggedObjects) {
if (o == null || !transferrableElementClass.isAssignableFrom(o.getClass())) {
ret = false;
break;
}
}
return ret;
}
#Override
public void dragSetData(DragSourceEvent event) {
event.data = Arrays.asList(draggedObjects);
}
#Override
public void dragFinished(DragSourceEvent event) {
if (event.detail != DND.DROP_NONE) {
dragSourceViewer.refresh();
}
draggedObjects = null;
}
}
And place a code somewhat like this in your View:
List<ITask> tasks = new WritableList(new ArrayList<ITask>(), ITask.class);
// Let's say tableViewerTasks is your TableViewer's name
DragSource sourceTasks = new DragSource(tblTasks, DND.DROP_MOVE);
sourceTasks.setTransfer(new Transfer[]{TaskTransfer.INSTANCE});
sourceTasks.addDragListener(new MyDragSourceListener(tableViewerTasks, true, ITask.class));
DropTarget targetTasks = new DropTarget(tblTasks, DND.DROP_MOVE);
targetTasks.setTransfer(new Transfer[]{TaskTransfer.INSTANCE});
targetTasks.addDropListener(new MyDropAdapter<ITask>(tableViewerTasks, ITask.class, tasks));
I use two text fields and a button to add entries to a two column table.
If I add a new entry the table is updated right away:
private void addBtn(ActionEvent event) {
Test o = new Test();
o.setTitle(title.getText());
o.setCount(Integer.parseInt(count.getText()));
mainApp.getData().add(o);
}
In a second step I added an additional button to amend the highlighted count cell:
private void editBtn(ActionEvent event) {
Test o = getSelection();
o.setCount(Integer.parseInt(count.getText()));
mainApp.getData().set(tablePosition, o);
}
If I click the button, the cell will update the value, but it's not visible in the table. If I click the button a second time it will update the table.
To check for which row is highlighted I use the following functions:
private final ListChangeListener<Test> selector = new ListChangeListener<Test>() {
#Override
public void onChanged(ListChangeListener.Change<? extends Test> c) {
setSelection();
}
};
public Test getSelection() {
if (testTable != null) {
List<Test> table = testTable.getSelectionModel().getSelectedItems();
if (table.size() == 1) {
final Test selection = table.get(0);
return selection;
}
}
return null;
}
private void setSelection() {
final Test o = getSelection();
tablePosition = mainApp.getData().indexOf(o);
if (o != null) {
title.setText(o.getTitle());
count.setText(o.getCount().toString());
}
}
In the initialize method I add a listener to the observable list:
final ObservableList<Test> t1 = testTable.getSelectionModel().getSelectedItems();
t1.addListener(selector);
My Test class:
public class Test {
private final SimpleStringProperty title = new SimpleStringProperty();
private final SimpleIntegerProperty count = new SimpleIntegerProperty();
public void setTitle(String title) {
this.title.set(title);
}
public String getTitle() {
return title.get();
}
public void setCount(Integer count) {
this.count.set(count);
}
public Integer getCount() {
return count.get();
}
}
How can I make the Edit button to update the cell value right away?
Assuming you are using a PropertyValueFactory as the cell factory for your table columns, you need to provide property accessor methods in order that the table cell provided by the PropertyValueFactory can listen to those properties for changes.
One correct implementation of using the JavaFX Property model looks like
public class Test {
private final IntegerProperty count = new SimpleIntegerProperty(this, "count", 0);
private final StringProperty title = new SimpleStringProperty(this, "title", "");
public final int getCount() {
return count.get();
}
public final void setCount(int count) {
this.count.set(count);
}
public IntegerProperty countProperty() {
return count ;
}
public final String getTitle() {
return title.get();
}
public final void setTitle(String title) {
this.title.set(title);
}
public StringProperty titleProperty() {
return title ;
}
}
With that, the following method will then correctly update the selected row in the table:
private void editBtn(ActionEvent event) {
Test o = testTable.getSelectionModel().getSelectedItem();
if (o != null) {
o.setCount(Integer.parseInt(count.getText()));
}
}
If that doesn't fix the problem for you, I recommend you edit your question completely and provide a sscce that demonstrates the problem.
I have a datagrid in GWT, and I'm using RPC to populate it with data, I can get the data to show up just fine, and I can also select individual cells but when it comes to sorting it just doesn't work! I can occasionaly click on column headers (it happens intermittently and I'm not sure why) but when I do nothing sorts. I'm using a dataProvider, but I think I'm implementing it incorrectly, I've attached the related code, can someone give me a pointer on how to do this correctly?
first is the actual table itself
public class GuiInventory {
public final static LayoutPanel hpMain = new LayoutPanel();
static ListHandler<OpInventory> sortHandler;
/*
* Define a key provider for a Contact. We use the unique ID as the key,
* which allows to maintain selection even if the name changes.
*/
static ProvidesKey<OpInventory> keyProvider = new ProvidesKey<OpInventory>() {
#Override
public Object getKey(OpInventory item) {
// Always do a null check.
return (item == null) ? null : item.getPartID();
}
};
//the table
final static DataGrid<OpInventory> table = new DataGrid<OpInventory>(keyProvider);
final static SelectionModel<OpInventory> selectionModel = new MultiSelectionModel<OpInventory>(keyProvider);
/**
* The provider that holds the list of contacts in the database.
*/
private final static ListDataProvider<OpInventory> dataProvider = new ListDataProvider<OpInventory>();
public ListDataProvider<OpInventory> getDataProvider() {
return dataProvider;
}
/**
* Add a display to the database. The current range of interest of the display
* will be populated with data.
*
* #param display a {#Link HasData}.
*/
public void addDataDisplay(HasData<OpInventory> display) {
dataProvider.addDataDisplay(display);
}
/**
* Refresh all displays.
*/
public void refreshDisplays() {
dataProvider.refresh();
}
public static Widget init() {
hpMain.clear();
table.setWidth("100%");
table.setSelectionModel(selectionModel);
Ioma.dataservice.getPartInventory(new AsyncCallback<ArrayList<OpInventory>>() {
#Override
public void onFailure(Throwable caught) {
// TODO Auto-generated method stub
}
#Override
public void onSuccess(ArrayList<OpInventory> result) {
dataProvider.setList(result);
// Attach a column sort handler to the ListDataProvider to sort the list.
sortHandler = new ListHandler<OpInventory>(result);
table.addColumnSortHandler(sortHandler);
dataProvider.addDataDisplay(table);
if (table.getColumnCount() == 0) {
initTable();
}
}
});
//add in table
hpMain.add(table);
return hpMain;
}
public static void initTable() {
// Add a text column to show the part ID.
Column<OpInventory, Number> partIDColumn = new Column<OpInventory, Number>(new NumberCell()) {
#Override
public Integer getValue(OpInventory object) {
return object.getPartID();
}
};
table.addColumn(partIDColumn, "Part ID");
table.setColumnWidth(partIDColumn, 4, Unit.PX);
//add a sort to partID
partIDColumn.setSortable(true);
sortHandler.setComparator(partIDColumn, new Comparator<OpInventory>() {
#Override
public int compare(OpInventory o1, OpInventory o2) {
return Integer.valueOf(o1.getPartID()).compareTo(o2.getPartID());
}
});
// Add a text column to show the part Number.
Column<OpInventory, String> partNumberColumn = new Column<OpInventory, String>(new EditTextCell()) {
#Override
public String getValue(OpInventory object) {
return object.getPartNumber();
}
};
table.addColumn(partNumberColumn, "Part Number");
table.setColumnWidth(partNumberColumn, 4, Unit.PX);
//add a sort to the part Number
partNumberColumn.setSortable(true);
sortHandler.setComparator(partNumberColumn, new Comparator<OpInventory>() {
#Override
public int compare(OpInventory o1, OpInventory o2) {
return o1.getPartNumber().compareTo(o2.getPartNumber());
}
});
//add a field updater to be notified when the user enters a new Part Number
partNumberColumn.setFieldUpdater(new FieldUpdater<OpInventory, String>() {
#Override
public void update(int index, OpInventory object, String value) {
object.setPartNumber(value);
//TODO add async call to database to update part Number
table.redraw();
}
});
// Add a text column to show the name.
Column<OpInventory, String> nameColumn = new Column<OpInventory, String>(new EditTextCell()) {
#Override
public String getValue(OpInventory object) {
return object.getName();
}
};
table.addColumn(nameColumn, "Name");
table.setColumnWidth(nameColumn, 10, Unit.PX);
//add a field updater to be notified when the user enters a new part name
nameColumn.setFieldUpdater(new FieldUpdater<OpInventory, String>() {
#Override
public void update(int index, OpInventory object, String value) {
object.setName(value);
//TODO add async call to database to update part name
table.redraw();
}
});
//add a sort to the name
nameColumn.setSortable(true);
sortHandler.setComparator(nameColumn, new Comparator<OpInventory>() {
#Override
public int compare(OpInventory o1, OpInventory o2) {
return o1.getName().compareTo(o2.getName());
}
});
}
this is the Opinventory class to hold each object in the datagrid
public class OpInventory implements Comparable<OpInventory>, IsSerializable {
int partID;
String partNumber;
String name;
String desc;
String partLotNumber;
String supplier;
String reOrderNumber;
boolean isActive;
int quantity;
Double price;
/**
* The key provider that provides the unique ID of a contact.
*/
public static final ProvidesKey<OpInventory> KEY_PROVIDER = new ProvidesKey<OpInventory>() {
#Override
public Object getKey(OpInventory item) {
return item == null ? null : item.getPartID();
}
};
#Override
public int compareTo(OpInventory o) {
return (o == null || o.partNumber == null) ? -1 : -o.partNumber.compareTo(partNumber);
}
#Override
public boolean equals(Object o) {
if (o instanceof OpInventory) {
return partID == ((OpInventory) o).partID;
}
return false;
}
#Override
public int hashCode() {
return partID;
}
public OpInventory(int partID, String partNumber, String name, String desc, String partLotNumber, String supplier, String reOrderNumber, Double price, boolean isActive) {
this.partID = partID;
this.partNumber = partNumber;
this.name = name;
this.desc = desc;
this.partLotNumber = partLotNumber;
this.supplier = supplier;
this.reOrderNumber = reOrderNumber;
this.price = price;
this.isActive = isActive;
}
public OpInventory() {
}
//getters and setters here
}
Apparently my issue was with the fact that I had a keyProvider in both classes, instead of just one. I removed it from the OpInventory class and it seems to work now. this looks like a very specific issue so I expect this question will be closed soon. but I'll leave the code there for future analysis.
I have a Client/Server app and my JTables are paginated, it shows only a range of the data. Now I would like to handle the sorting but server side. How can I customize the default sorting implementation?
I found a solution that works but I'm sure that it is not the best! :)
...
final MyTableModel myModel = new MyTableModel();
final MySorter mySorter = new MySorter(myModel);
mySorter.addRowSorterListener(new RowSorterListener() {
#Override
public void sorterChanged(RowSorterEvent e) {
// server side sorting
sortDataByColumn(mySorter.getColumnToSort());
}
});
JTable table = new JTable();
table.setModel(myModel);
table.setRowSorter(mySorter);
...
class MySorter extends TableRowSorter<TableModel> {
private String columnToSort;
public MySorter(AbstractTableModel model) {
super(model);
}
#Override
public void sort() {
// do nothing! because server side sorting
}
#Override
protected void fireSortOrderChanged() {
// build a string like [+-]column_identifier.
// where + is for ASC and - for DESC ordering
final SortKey k = getSortKeys().get(0);
final String colName = getModel().getTableColumnModel()
.getColumn(k.getColumn()).getIdentifier().toString();
if (colName != null && !colName.isEmpty()) {
columnToSort = (k.getSortOrder() == SortOrder.ASCENDING ? '+' : '-') + colName;
} else {
columnToSort = null;
}
super.fireSortOrderChanged();
}
public String getColumnToSort() {
return columnToSort;
}
}