TreeTableView disable any cell in parent row - javafx-8

How can I disable any cell editable in parent row in treetableview? Please look the pictures and check the sample code. Shortly I want to disable row editable if row is expandable (root row or sub root row)
this picture is correct
but this is not correct
**Example code **
import javafx.application.Application;
import javafx.beans.property.ReadOnlyStringWrapper;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ObservableValue;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeTableCell;
import javafx.scene.control.TreeTableColumn;
import javafx.scene.control.TreeTableView;
import javafx.scene.control.cell.TreeItemPropertyValueFactory;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
import javafx.util.Callback;
public class TreeTableExample extends Application {
public static void main(String[] args) {
Application.launch(args);
}
#Override
#SuppressWarnings("unchecked")
public void start(Stage stage) {
HBox root = new HBox(createTable());
Scene scene = new Scene(root);
stage.setScene(scene);
stage.setTitle("Using a TreeTableView");
stage.show();
}
public TreeTableView createTable() {
TreeTableView<Person> treeTable = new TreeTableView<>();
treeTable.setEditable(true);
Callback<TreeTableColumn<Person, String>,
TreeTableCell<Person, String>> cellFactory
= (TreeTableColumn<Person, String> p) -> new EditingCell();
TreeTableColumn<Person, String> firstName = new TreeTableColumn<>("First Name");
firstName.setCellValueFactory(new TreeItemPropertyValueFactory<>("firstName"));
firstName.setCellFactory(cellFactory);
firstName.setOnEditCommit((TreeTableColumn.CellEditEvent<Person, String> event) -> {
if(event.getNewValue()!=null)
event.getRowValue().getValue().setFirstName(event.getNewValue());
});
TreeTableColumn<Person, String> lastName = new TreeTableColumn<>("Last Name");
lastName.setCellValueFactory(new TreeItemPropertyValueFactory<>("lastName"));
lastName.setCellFactory(cellFactory);
lastName.setOnEditCommit((TreeTableColumn.CellEditEvent<Person, String> event) -> {
if(event.getNewValue()!=null)
event.getRowValue().getValue().setLastName(event.getNewValue());
});
treeTable.getColumns().addAll(firstName, lastName);
TreeItem<Person> root = new TreeItem<>();
for (int i = 0; i < 5; i++) {
root.getChildren().add(new TreeItem<>(new Person()));
}
treeTable.setRoot(root);
return treeTable;
}
public class Person {
private SimpleStringProperty firstName;
private SimpleStringProperty lastName;
public Person(){
firstName = new SimpleStringProperty(this, "firstName");
lastName = new SimpleStringProperty(this, "lastName");
};
public String getFirstName() {
return firstName.get();
}
public void setFirstName(String fName) {
firstName.set(fName);
}
public String getLastName() {
return lastName.get();
}
public void setLastName(String fName) {
lastName.set(fName);
}
}
class EditingCell extends TreeTableCell<Person, String> {
private TextField textField;
public EditingCell() {
}
#Override
public void startEdit() {
if (!isEmpty()) {
super.startEdit();
createTextField();
setText(null);
setGraphic(textField);
textField.selectAll();
}
}
#Override
public void cancelEdit() {
super.cancelEdit();
setText((String) getItem());
setGraphic(null);
}
#Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
setGraphic(null);
} else if (isEditing()) {
if(!getTreeTableView().getTreeItem(getIndex()).isLeaf())
setEditable(false);
if (textField != null) {
textField.setText(getString());
}
setText(null);
setGraphic(textField);
} else {
setText(getString());
setGraphic(null);
}
}
private void createTextField() {
textField = new TextField(getString());
textField.setMinWidth(this.getWidth() - this.getGraphicTextGap() * 2);
textField.focusedProperty().addListener(
(ObservableValue<? extends Boolean> arg0,
Boolean arg1, Boolean arg2) -> {
if (!arg2) {
commitEdit(textField.getText());
}
});
}
private String getString() {
return getItem() == null ? "" : getItem();
}
}
}
just run it and double click on the root item
make-individual-cell-editable-in-javafx-tableview I checked the solution works for tableview but for treetaleview does not work.

It seems that TreeTableCell does not properly check its editable property before deciding whether or not to call startEdit(). I think that's a bug. You can work around it by checking that yourself in your startEdit() method:
#Override
public void startEdit() {
if (isEditable() && !isEmpty()) {
super.startEdit();
createTextField();
setText(null);
setGraphic(textField);
textField.selectAll();
}
}
and now in your updateItem() method, you can check the current tree item from the row, and update editable as required:
#Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
TreeItem<Person> treeItem = getTreeTableRow().getTreeItem();
setEditable(treeItem != null && treeItem.isLeaf());
if (empty) {
setText(null);
setGraphic(null);
} else if (isEditing()) {
if(!getTreeTableView().getTreeItem(getIndex()).isLeaf())
setEditable(false);
if (textField != null) {
textField.setText(getString());
}
setText(null);
setGraphic(textField);
} else {
setText(getString());
setGraphic(null);
}
}

Actually I disagree with the reasoning in the other answer: there is nothing wrong with core TreeTableCell (it does check for its editability before actually starting an edit) - instead the logic in the custom cell implementation is broken. Particularly, the part of updateItem that sets the editable property:
} else if (isEditing()) {
if(!getTreeTableView().getTreeItem(getIndex()).isLeaf())
setEditable(false);
Besides being incomplete in not resetting the editable back to true anywhere (remember: cells are re-used), we allow super to first start editing and only after it started, it's disabled.
This logic error is fixed (in the other answer, copied here for convenience) by unconditionally setting the editability in updateItem:
super.updateItem(item, empty);
TreeItem<Person> treeItem = getTreeTableRow().getTreeItem();
setEditable(treeItem != null && treeItem.isLeaf());
The other usage error (as already noted) was not fully checking cell state before actually configuring the editor. The suggested fix - check cell's editable - isn't quite complete because table/column editability might be disabled as well. To take that into account, I would tend to let super do its job and only configure the editor if editability actually changed, like
super.startEdit();
// super changed state into editing
if (isEditing()) {
// create and install the textField
}

Related

Javafx Combobox update issue when updating the observable values

I have create a ComboBox in JavaFx as in the following image
Then i have selected a particular value which shows up in the button cell as shown in the figure.
Then i updated its value so if there is a change in the value i can observe it. But it is not displaying the changed value but an object value.
When i again select from the dropdown view the selected value becomes correct.
The code for the Combobox is
ComboBox<AspectRatio> aspectRatio = new ComboBox<>();
aspectRatio.setCellFactory(new AspectRatioCellFactory());
aspectRatio.setButtonCell(new AspectRatioCell());
Cell Factory
class AspectRatioCellFactory implements Callback<ListView<AspectRatio>, ListCell<AspectRatio>> {
#Override
public ListCell<AspectRatio> call(ListView<AspectRatio> param) {
return new AspectRatioCell();
}
}
class AspectRatioCell extends ListCell<AspectRatio> {
public AspectRatioCell() {
super();
}
#Override
protected void updateItem(AspectRatio item, boolean empty) {
super.updateItem(item, empty);
if (item == null || empty) {
setText(null);
setGraphic(null);
} else {
setText(item.getAspectRatio());
setGraphic(null);
}
}
}
Updating class
private class RefreshButtonListener implements ButtonListener {
#Override
public void onClick() {
theModel.setObservableAspectRatios(theModel.getAllAspectRatio());
theView.clearCombo();
}
}

JavaFX TreeTable select children when parent is selected and remove selection from parent

I have a TreeTable which has maximum depth of 2, e.g.
fooType
-foo
-foo
If I select fooType I want the program to select automatically all child-items AND deselect the parent item. But when I try this, I always get an IndexOutOfBoundsException.
myTreeTable.getSelectionModel().selectedItemProperty().addListener((obs, ov, nv) -> {
if (nv.getValue() instanceof fooType) {
myTreeTable.getSelectionModel().clearSelection(myTreeTable.getSelectionModel().getSelectedIndex());
if (!nv.isExpanded()) {
nv.setExpanded(true);
}
ObservableList<TreeItem<IfooTreeItem>> children = nv.getChildren();
for (TreeItem<IfooTreeItem> item : children) {
annotationsTreeTable.getSelectionModel().select(item);
}
}
});
Multi selection mode is enabled.
Any help appreciated.
In JavaFX, you are not allowed to change an ObservableList while an existing change to that list is being processed. (Whether or not this is a sensible rule is open to debate, nevertheless, it is a rule.)
The selection model keeps ObservableLists of both the selected indices and the selected items. Part of the processing of changes in those lists is to call listeners on the selected item and selected index. Consequently, you can't change the selection from a listener on the selection itself.
The "proper" way to do this would be to provide your own implementation of the selection model. This is a bit of a pain, as there are a lot of methods to implement, and their use is not well documented. Here is an example, though this is intended as a starting point and is not intended to be production quality:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
import javafx.application.Application;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.MultipleSelectionModel;
import javafx.scene.control.SelectionMode;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class TreeSelectionExample extends Application {
#Override
public void start(Stage primaryStage) {
TreeView<String> tree = new TreeView<>();
TreeItem<String> root = new TreeItem<>();
tree.setRoot(root);
tree.setShowRoot(false);
root.getChildren().add(new TreeItem<>("Item 1"));
root.getChildren().add(new TreeItem<>("Item 2"));
root.getChildren().forEach(item ->
Stream.of("A", "B").map(s -> new TreeItem<String>(item.getValue()+s))
.forEach(item.getChildren()::add));
MultipleSelectionModel<TreeItem<String>> defaultSelectionModel = tree.getSelectionModel() ;
defaultSelectionModel.setSelectionMode(SelectionMode.MULTIPLE);
tree.setSelectionModel(new MultipleSelectionModel<TreeItem<String>>() {
{
setSelectionMode(SelectionMode.MULTIPLE);
}
#Override
public ObservableList<Integer> getSelectedIndices() {
return defaultSelectionModel.getSelectedIndices();
}
#Override
public ObservableList<TreeItem<String>> getSelectedItems() {
return defaultSelectionModel.getSelectedItems();
}
#Override
public void selectRange(int start, int end) {
System.out.println("selectRange("+start+", "+end+")");
List<TreeItem<String>> items = new ArrayList<>();
for (int i = start; i < end; i++) {
items.add(tree.getTreeItem(i));
}
for (int i = start ; i > end; i--) {
items.add(tree.getTreeItem(i));
}
items.forEach(this::select);
}
#Override
public void selectIndices(int index, int... indices) {
System.out.println("select("+index+", "+Arrays.toString(indices)+")");
TreeItem<String> item = tree.getTreeItem(index);
if (item.isLeaf()) {
defaultSelectionModel.select(item);;
} else {
List<TreeItem<String>> leaves = new ArrayList<>();
findLeavesAndExpand(item, leaves);
for (TreeItem<String> leaf : leaves) {
defaultSelectionModel.select(leaf);
}
}
for (int i : indices) {
item = tree.getTreeItem(i);
if (item.isLeaf()) {
defaultSelectionModel.select(item);;
} else {
List<TreeItem<String>> leaves = new ArrayList<>();
findLeavesAndExpand(item, leaves);
for (TreeItem<String> leaf : leaves) {
defaultSelectionModel.select(leaf);
}
}
}
}
#Override
public void selectAll() {
System.out.println("selectAll()");
List<TreeItem<String>> leaves = new ArrayList<>();
findLeavesAndExpand(tree.getRoot(), leaves);
for (TreeItem<String> leaf : leaves) {
defaultSelectionModel.select(leaf);
}
}
#Override
public void selectFirst() {
System.out.println("selectFirst()");
TreeItem<String> firstLeaf ;
for (firstLeaf = tree.getRoot(); ! firstLeaf.isLeaf(); firstLeaf = firstLeaf.getChildren().get(0)) ;
defaultSelectionModel.select(firstLeaf);
}
#Override
public void selectLast() {
System.out.println("selectLast()");
TreeItem<String> lastLeaf ;
for (lastLeaf = tree.getRoot(); ! lastLeaf.isLeaf();
lastLeaf = lastLeaf.getChildren().get(lastLeaf.getChildren().size()-1)) ;
defaultSelectionModel.select(lastLeaf);
}
#Override
public void clearAndSelect(int index) {
TreeItem<String> item = tree.getTreeItem(index);
defaultSelectionModel.clearSelection();
if (item.isLeaf()) {
defaultSelectionModel.select(item);
} else {
List<TreeItem<String>> leaves = new ArrayList<>();
findLeavesAndExpand(item, leaves);
for (TreeItem<String> leaf : leaves) {
defaultSelectionModel.select(leaf);
}
}
}
#Override
public void select(int index) {
System.out.println("select("+index+")");
select(tree.getTreeItem(index));
}
#Override
public void select(TreeItem<String> item) {
System.out.println("select("+item.getValue()+")");
if (item.isLeaf()) {
defaultSelectionModel.select(item);
} else {
List<TreeItem<String>> leaves = new ArrayList<>();
findLeavesAndExpand(item, leaves);
for (TreeItem<String> leaf : leaves) {
defaultSelectionModel.select(leaf);
}
}
}
#Override
public void clearSelection(int index) {
defaultSelectionModel.clearSelection(index);
}
#Override
public void clearSelection() {
defaultSelectionModel.clearSelection();
}
#Override
public boolean isSelected(int index) {
return defaultSelectionModel.isSelected(index);
}
#Override
public boolean isEmpty() {
return defaultSelectionModel.isEmpty();
}
#Override
public void selectPrevious() {
// TODO Auto-generated method stub
// not sure on implementation needed here
}
#Override
public void selectNext() {
System.out.println("selectNext()");
// TODO Auto-generated method stub
// not sure on implementation needed here
}
private void findLeavesAndExpand(TreeItem<String> node, List<TreeItem<String>> leaves) {
if (node.isLeaf()) {
leaves.add(node);
} else {
node.setExpanded(true);
for (TreeItem<String> child : node.getChildren()) {
findLeavesAndExpand(child, leaves);
}
}
}
});
primaryStage.setScene(new Scene(new BorderPane(tree), 400, 400));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}

GWT CellTable and ListBoxes complex identifiers

I'm following Goolge's example on how to add ListBoxes/SelectionCells to a CellTable, but I can't figure how to change the behaviour so the matching is done not with the string value displayed.
The items I display #SelectionCell are not unique (i.e there can be 2 elements with the same name), so I need to use other fields associated with the object to know which one was selected
for (IrrigationProgramDTO program: programOptions)
categoryNames.add(program.getName());
SelectionCell categoryCell = new SelectionCell(categoryNames);
Column<IrrigationGapDTO, String> categoryColumn = new Column<IrrigationGapDTO, String> (categoryCell) {
#Override
public String getValue(IrrigationGapDTO object) {
if (object.getProgramSelected()!=null)
return object.getProgramSelected().getName();
else
return "";
}
};
categoryColumn.setFieldUpdater(new FieldUpdater<IrrigationGapDTO, String>() {
public void update(int index, IrrigationGapDTO object, String value) {
for (IrrigationProgramDTO program: programOptions) {
//not valid as there could be more than 1 program with the same name
if (program.getName().equals(value)) {
object.setProgramSelected(program);
break;
}
}
}
Here is my new implementation of solution #3 (note that you must add a FieldUpdater to the column for it to work):
import java.util.Arrays;
import java.util.List;
import com.google.gwt.cell.client.AbstractEditableCell;
import com.google.gwt.cell.client.Cell;
import com.google.gwt.cell.client.ValueUpdater;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.BrowserEvents;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.dom.client.SelectElement;
import com.google.gwt.safehtml.client.SafeHtmlTemplates;
import com.google.gwt.safehtml.client.SafeHtmlTemplates.Template;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
/**
* A {#link Cell} used to render a drop-down list.
*
* #author Gaspard van Koningsveld
*/
public class ItemSelectionCell<C> extends AbstractEditableCell<C, C> {
interface Template extends SafeHtmlTemplates {
#Template("<select tabindex=\"-1\" style=\"width:100%\">")
SafeHtml beginSelect();
#Template("<option value=\"{0}\">{1}</option>")
SafeHtml deselected(int hash, String option);
#Template("<option value=\"{0}\" selected=\"selected\">{1}</option>")
SafeHtml selected(int hash, String option);
#Template("</select>")
SafeHtml endSelect();
}
private static Template template;
private List<C> items;
public ItemSelectionCell(C itemsArray[]) {
this(Arrays.asList(itemsArray));
}
public ItemSelectionCell(List<C> items) {
super(BrowserEvents.CHANGE);
if (template == null) {
template = GWT.create(Template.class);
}
this.items = items;
}
#Override
public void onBrowserEvent(Context context, Element parent, C value, NativeEvent event, ValueUpdater<C> valueUpdater) {
super.onBrowserEvent(context, parent, value, event, valueUpdater);
if (BrowserEvents.CHANGE.equals(event.getType())) {
SelectElement select = parent.getFirstChild().cast();
int newIndex = select.getSelectedIndex();
valueUpdater.update(items.get(newIndex));
}
}
#Override
public void render(Context context, C value, SafeHtmlBuilder sb) {
sb.append(template.beginSelect());
for (int i = 0; i < items.size(); i++) {
C item = items.get(i);
if (item.equals(value)) {
sb.append(template.selected(i, getItemDisplayString(item)));
} else {
sb.append(template.deselected(i, getItemDisplayString(item)));
}
}
sb.append(template.endSelect());
}
public String getItemDisplayString(C item) {
return item.toString();
}
public List<C> getItems() {
return items;
}
public void setItems(List<C> items) {
this.items = items;
}
#Override
public boolean isEditing(Context context, Element parent, C value) {
return false;
}
}
3 possible solutions:
1. Dirty workaround:
Instead of getName() return getName() + some unique identifier:
public String getValue(IrrigationGapDTO object) {
if (object.getProgramSelected()!=null)
return object.getProgramSelected().getName()+"_"+object.getUniqueIdentiufier();
else
return "";
}
then in the FieldUpdater you can split on the "_" character and deal with duplicates
2. Use a unique id instead of getName():
Just generate/assign a unique id to your programms and use it instead of name.
3. Use IrrigationProgramDTO type instead of String:
Instead of String you can use IrrigationProgramDTO class in the Column definition. However you probably have to use a user-defined SelectionCell which takes IrrigationProgramDTO type instead of String as Data-type.
Column<IrrigationGapDTO, IrrigationProgramDTO> categoryColumn = new Column<IrrigationGapDTO, IrrigationProgramDTO> (categoryCell) {
#Override
public IrrigationProgramDTO (IrrigationGapDTO object) {
if (object.getProgramSelected()!=null)
return object.getProgramSelected();
else
return null;
}
};
categoryColumn.setFieldUpdater(new FieldUpdater<IrrigationGapDTO, IrrigationProgramDTO>() {
public void update(int index, IrrigationGapDTO object, IrrigationProgramDTO value) {
object.setProgramSelected(program);
}
}
Here is my implementation of Solution #3 of #Ümit:
public static abstract class EditSelectColumn<E, S> {
Map<String, S> selectionMap = new HashMap<String, S>();
EditColumn<E> column;
protected final String relationshipFieldName;
public EditSelectColumn(String relationshipFieldName) {
this.relationshipFieldName = relationshipFieldName;
for (S option : getOptions()) {
assert getOptionString(option) != null : "Option string cannot be null, please check your database";
selectionMap.put(getOptionString(option), option);
}
SelectionCell cell = new SelectionCell(new ArrayList<String>(selectionMap.keySet()));
column = new EditColumn<E>(cell) {
#Override
public String getValue(E object) {
if (getOption(object) == null)
return "";
return getOptionString(getOption(object));
}
#Override
public void setValue(E object, String value) {
setOption(object, selectionMap.get(value));
}
};
}
public EditColumn<E> getColumn() {
return column;
}
public abstract List<S> getOptions();
public abstract String getOptionString(S option);
public abstract S getOption(E object);
public abstract void setOption(E object, S value);
}

How to disable copy/paste from/to EditText

In my application, there is a registration screen, where i do not want the user to be able to copy/paste text into the EditText field. I have set an onLongClickListener on each EditText so that the context menu showing copy/paste/inputmethod and other options does not show up. So the user won't be able to copy/ paste into the Edit fields.
OnLongClickListener mOnLongClickListener = new OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
// prevent context menu from being popped up, so that user
// cannot copy/paste from/into any EditText fields.
return true;
}
};
But the problem arises if the user has enabled a third-party keyboard other than the Android default, which may have a button to copy/paste or which may show the same context menu. So how do i disable copy/paste in that scenario ?
Please let me know if there are other ways to copy/paste as well. (and possibly how to disable them)
Any help would be appreciated.
Best method is to use:
etUsername.setLongClickable(false);
If you are using API level 11 or above then you can stop copy,paste,cut and custom context menus from appearing by.
edittext.setCustomSelectionActionModeCallback(new ActionMode.Callback() {
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
public void onDestroyActionMode(ActionMode mode) {
}
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
return false;
}
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
return false;
}
});
Returning false from onCreateActionMode(ActionMode, Menu) will prevent the action mode from being started(Select All, Cut, Copy and Paste actions).
You can do this by disabling the long press of the EditText
To implement it, just add the following line in the xml -
android:longClickable="false"
I am able to disable copy-and-paste functionality with the following:
textField.setCustomSelectionActionModeCallback(new ActionMode.Callback() {
public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
return false;
}
public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) {
return false;
}
public boolean onActionItemClicked(ActionMode actionMode, MenuItem item) {
return false;
}
public void onDestroyActionMode(ActionMode actionMode) {
}
});
textField.setLongClickable(false);
textField.setTextIsSelectable(false);
Hope it works for you ;-)
Kotlin solution:
fun TextView.disableCopyPaste() {
isLongClickable = false
setTextIsSelectable(false)
customSelectionActionModeCallback = object : ActionMode.Callback {
override fun onCreateActionMode(mode: ActionMode?, menu: Menu): Boolean {
return false
}
override fun onPrepareActionMode(mode: ActionMode?, menu: Menu): Boolean {
return false
}
override fun onActionItemClicked(mode: ActionMode?, item: MenuItem): Boolean {
return false
}
override fun onDestroyActionMode(mode: ActionMode?) {}
}
}
Then you can simply call this method on your TextView:
override fun onCreate() {
priceEditText.disableCopyPaste()
}
here is a best way to disable cut copy paste of editText work in all version
if (android.os.Build.VERSION.SDK_INT < 11) {
editText.setOnCreateContextMenuListener(new OnCreateContextMenuListener() {
#Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
// TODO Auto-generated method stub
menu.clear();
}
});
} else {
editText.setCustomSelectionActionModeCallback(new ActionMode.Callback() {
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
// TODO Auto-generated method stub
return false;
}
public void onDestroyActionMode(ActionMode mode) {
// TODO Auto-generated method stub
}
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
// TODO Auto-generated method stub
return false;
}
public boolean onActionItemClicked(ActionMode mode,
MenuItem item) {
// TODO Auto-generated method stub
return false;
}
});
}
In addition to the setCustomSelectionActionModeCallback, and disabled long-click solutions, it's necessary to prevent the PASTE/REPLACE menus from appearing when the text selection handle is clicked, as per the image below:
The solution lies in preventing PASTE/REPLACE menu from appearing in the show() method of the (non-documented) android.widget.Editor class. Before the menu appears, a check is done to if (!canPaste && !canSuggest) return;. The two methods that are used as the basis to set these variables are both in the EditText class:
isSuggestionsEnabled() is public, and may thus be overridden.
canPaste() is not, and thus must be hidden by introducing a function of the same name in the derived class.
A more complete answer is available here.
If you don't wan't to disable long click because you need to perform some functionality on long click than returning true is a better option to do so.
Your edittext long click will be like this.
edittext.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
// Do Something or Don't
return true;
}
});
As per documentation
Returning "True" will indicate that long click have been handled so no need to perform default operations.
I tested this on API level 16, 22 and 25. Its working fine for me. Hope this will help.
Here is a hack to disable "paste" popup. You have to override EditText method:
#Override
public int getSelectionStart() {
for (StackTraceElement element : Thread.currentThread().getStackTrace()) {
if (element.getMethodName().equals("canPaste")) {
return -1;
}
}
return super.getSelectionStart();
}
Similar can be done for the other actions.
I've tested this solution and this works
mSubdomainEditText.setLongClickable(false);
mSubdomainEditText.setCustomSelectionActionModeCallback(new ActionMode.Callback() {
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
public void onDestroyActionMode(ActionMode mode) {
}
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
return false;
}
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
return false;
}
});
i added Extension Function in Kotlin language :
fun EditText.disableTextSelection() {
this.setCustomSelectionActionModeCallback(object : android.view.ActionMode.Callback {
override fun onActionItemClicked(mode: android.view.ActionMode?, item: MenuItem?): Boolean {
return false
}
override fun onCreateActionMode(mode: android.view.ActionMode?, menu: Menu?): Boolean {
return false
}
override fun onPrepareActionMode(mode: android.view.ActionMode?, menu: Menu?): Boolean {
return false
}
override fun onDestroyActionMode(mode: android.view.ActionMode?) {
}
})
}
you can use it like this :
edit_text.disableTextSelection()
also added below line in your xml :
android:longClickable="false"
android:textIsSelectable="false"
https://github.com/neopixl/PixlUI provides an EditText with a method
myEditText.disableCopyAndPaste().
And it's works on the old API
If you want to disable ActionMode for copy/pasting, you need to override 2 callbacks. This works for both TextView and EditText (or TextInputEditText)
import android.view.ActionMode
fun TextView.disableCopyPaste() {
isLongClickable = false
setTextIsSelectable(false)
customSelectionActionModeCallback = object : ActionMode.Callback {
override fun onCreateActionMode(mode: ActionMode?, menu: Menu) = false
override fun onPrepareActionMode(mode: ActionMode?, menu: Menu) = false
override fun onActionItemClicked(mode: ActionMode?, item: MenuItem) = false
override fun onDestroyActionMode(mode: ActionMode?) {}
}
//disable action mode when edittext gain focus at first
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
customInsertionActionModeCallback = object : ActionMode.Callback {
override fun onCreateActionMode(mode: ActionMode?, menu: Menu) = false
override fun onPrepareActionMode(mode: ActionMode?, menu: Menu) = false
override fun onActionItemClicked(mode: ActionMode?, item: MenuItem) = false
override fun onDestroyActionMode(mode: ActionMode?) {}
}
}
}
This extension is based off above #Alexandr solution and worked fine for me.
#Zain Ali, your answer works on API 11. I just wanted to suggest a way to do in on API 10 as well. Since I had to maintain my project API on that version, I was constantly playing with the functions available in 2.3.3 and got a possibility to do it. I have share the snippet below. I tested the code and it was working for me. I did this snippet on an urgency. Feel free to improve the code if there are any changes that can be done..
// A custom TouchListener is being implemented which will clear out the focus
// and gain the focus for the EditText, in few milliseconds so the selection
// will be cleared and hence the copy paste option wil not pop up.
// the respective EditText should be set with this listener
// tmpEditText.setOnTouchListener(new MyTouchListener(tmpEditText, tmpImm));
public class MyTouchListener implements View.OnTouchListener {
long click = 0;
EditText mEtView;
InputMethodManager imm;
public MyTouchListener(EditText etView, InputMethodManager im) {
mEtView = etView;
imm = im;
}
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
long curr = System.currentTimeMillis();
if (click !=0 && ( curr - click) < 30) {
mEtView.setSelected(false);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
mEtView.setSelected(true);
mEtView.requestFocusFromTouch();
imm.showSoftInput(mEtView, InputMethodManager.RESULT_SHOWN);
}
},25);
return true;
}
else {
if (click == 0)
click = curr;
else
click = 0;
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
mEtView.requestFocusFromTouch();
mEtView.requestFocusFromTouch();
imm.showSoftInput(mEtView, InputMethodManager.RESULT_SHOWN);
}
},25);
return true;
}
} else if (event.getAction() == MotionEvent.ACTION_MOVE) {
mEtView.setSelected(false);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
mEtView.setSelected(true);
mEtView.requestFocusFromTouch();
mEtView.requestFocusFromTouch();
imm.showSoftInput(mEtView, InputMethodManager.RESULT_SHOWN);
}
},25);
return true;
}
return false;
}
For smartphone with clipboard, is possible prevent like this.
editText.setFilters(new InputFilter[]{new InputFilter() {
#Override
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
if (source.length() > 1) {
return "";
} return null;
}
}});
Read the Clipboard, check against the input and the time the input is "typed". If the Clipboard has the same text and it is too fast, delete the pasted input.
the solution is very simple
public class MainActivity extends AppCompatActivity {
EditText et_0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et_0 = findViewById(R.id.et_0);
et_0.setCustomSelectionActionModeCallback(new ActionMode.Callback() {
#Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
//to keep the text selection capability available ( selection cursor)
return true;
}
#Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
//to prevent the menu from appearing
menu.clear();
return false;
}
#Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
return false;
}
#Override
public void onDestroyActionMode(ActionMode mode) {
}
});
}
}
--------> preview <---------
Try Following custome class for prevant copy and paste in Edittext
public class SegoeUiEditText extends AppCompatEditText {
private final Context context;
#Override
public boolean isSuggestionsEnabled() {
return false;
}
public SegoeUiEditText(Context context) {
super(context);
this.context = context;
init();
}
public SegoeUiEditText(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
init();
}
public SegoeUiEditText(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this.context = context;
init();
}
private void setFonts(Context context) {
this.setTypeface(Typeface.createFromAsset(context.getAssets(), "Fonts/Helvetica-Normal.ttf"));
}
private void init() {
setTextIsSelectable(false);
this.setCustomSelectionActionModeCallback(new ActionModeCallbackInterceptor());
this.setLongClickable(false);
}
#Override
public int getSelectionStart() {
for (StackTraceElement element : Thread.currentThread().getStackTrace()) {
if (element.getMethodName().equals("canPaste")) {
return -1;
}
}
return super.getSelectionStart();
}
/**
* Prevents the action bar (top horizontal bar with cut, copy, paste, etc.) from appearing
* by intercepting the callback that would cause it to be created, and returning false.
*/
private class ActionModeCallbackInterceptor implements ActionMode.Callback, android.view.ActionMode.Callback {
private final String TAG = SegoeUiEditText.class.getSimpleName();
public boolean onCreateActionMode(ActionMode mode, Menu menu) { return false; }
public boolean onPrepareActionMode(ActionMode mode, Menu menu) { return false; }
public boolean onActionItemClicked(ActionMode mode, MenuItem item) { return false; }
public void onDestroyActionMode(ActionMode mode) {}
#Override
public boolean onCreateActionMode(android.view.ActionMode mode, Menu menu) {
return false;
}
#Override
public boolean onPrepareActionMode(android.view.ActionMode mode, Menu menu) {
menu.clear();
return false;
}
#Override
public boolean onActionItemClicked(android.view.ActionMode mode, MenuItem item) {
return false;
}
#Override
public void onDestroyActionMode(android.view.ActionMode mode) {
}
}
}
The solutions above do not take into account pasting with hardware keyboards (Ctrl+v). The easiest solution is to set a TextWatcher on your EditText, and filter characters you want or don't want in the afterTextChanged method. This works for all situations, i.e. typed characters, pastes, auto suggestions and auto corrections.
Rather than completely disabling all actions on the EditText, you may want to prevent only certain actions (like cut/copy, but not paste):
/**
* Prevent copy/cut of the (presumably sensitive) contents of this TextView.
*/
fun TextView.disableCopyCut() {
setCustomSelectionActionModeCallback(
object : Callback {
override fun onActionItemClicked(mode: ActionMode?, item: MenuItem?) = false
override fun onCreateActionMode(mode: ActionMode?, menu: Menu?): Boolean {
menu?.apply {
removeItem(android.R.id.copy)
removeItem(android.R.id.cut)
}
return true
}
override fun onPrepareActionMode(mode: ActionMode?, menu: Menu?) = false
override fun onDestroyActionMode(mode: ActionMode?) {
// no-op
}
}
)
}
Actions that can be selectively removed:
removeItem(android.R.id.copy)
removeItem(android.R.id.cut)
removeItem(android.R.id.paste)
removeItem(android.R.id.shareText) // Share
removeItem(android.R.id.textAssist) // Open with Chrome
its very late but may it help someone .
add these lines in your edittext xml
android:longClickable="false"
android:textIsSelectable="false"
android:importantForAutofill="no"
I found that when you create an input filter to avoid entry of unwanted characters, pasting such characters into the edit text is having no effect. So this sort of solves my problem as well.
Solution that worked for me was to create custom Edittext and override following method:
public class MyEditText extends EditText {
private int mPreviousCursorPosition;
#Override
protected void onSelectionChanged(int selStart, int selEnd) {
CharSequence text = getText();
if (text != null) {
if (selStart != selEnd) {
setSelection(mPreviousCursorPosition, mPreviousCursorPosition);
return;
}
}
mPreviousCursorPosition = selStart;
super.onSelectionChanged(selStart, selEnd);
}
}
Try to use.
myEditext.setCursorVisible(false);
myEditext.setCustomSelectionActionModeCallback(new ActionMode.Callback() {
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
// TODO Auto-generated method stub
return false;
}
public void onDestroyActionMode(ActionMode mode) {
// TODO Auto-generated method stub
}
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
// TODO Auto-generated method stub
return false;
}
public boolean onActionItemClicked(ActionMode mode,
MenuItem item) {
// TODO Auto-generated method stub
return false;
}
});
Who is looking for a solution in Kotlin use the below class as a custom widget and use it in the xml.
class SecureEditText : TextInputEditText {
/** This is a replacement method for the base TextView class' method of the same name. This method
* is used in hidden class android.widget.Editor to determine whether the PASTE/REPLACE popup
* appears when triggered from the text insertion handle. Returning false forces this window
* to never appear.
* #return false
*/
override fun isSuggestionsEnabled(): Boolean {
return false
}
override fun getSelectionStart(): Int {
for (element in Thread.currentThread().stackTrace) {
if (element.methodName == "canPaste") {
return -1
}
}
return super.getSelectionStart()
}
public override fun onSelectionChanged(start: Int, end: Int) {
val text = text
if (text != null) {
if (start != text.length || end != text.length) {
setSelection(text.length, text.length)
return
}
}
super.onSelectionChanged(start, end)
}
companion object {
private val EDITTEXT_ATTRIBUTE_COPY_AND_PASTE = "isCopyPasteDisabled"
private val PACKAGE_NAME = "http://schemas.android.com/apk/res-auto"
}
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
disableCopyAndPaste(context, attrs)
}
/**
* Disable Copy and Paste functionality on EditText
*
* #param context Context object
* #param attrs AttributeSet Object
*/
private fun disableCopyAndPaste(context: Context, attrs: AttributeSet) {
val isDisableCopyAndPaste = attrs.getAttributeBooleanValue(
PACKAGE_NAME,
EDITTEXT_ATTRIBUTE_COPY_AND_PASTE, true
)
if (isDisableCopyAndPaste && !isInEditMode()) {
val inputMethodManager =
context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
this.setLongClickable(false)
this.setOnTouchListener(BlockContextMenuTouchListener(inputMethodManager))
}
}
/**
* Perform Focus Enabling Task to the widget with the help of handler object
* with some delay
* #param inputMethodManager is used to show the key board
*/
private fun performHandlerAction(inputMethodManager: InputMethodManager) {
val postDelayedIntervalTime: Long = 25
Handler().postDelayed(Runnable {
this#SecureEditText.setSelected(true)
this#SecureEditText.requestFocusFromTouch()
inputMethodManager.showSoftInput(
this#SecureEditText,
InputMethodManager.RESULT_SHOWN
)
}, postDelayedIntervalTime)
}
/**
* Class to Block Context Menu on double Tap
* A custom TouchListener is being implemented which will clear out the focus
* and gain the focus for the EditText, in few milliseconds so the selection
* will be cleared and hence the copy paste option wil not pop up.
* the respective EditText should be set with this listener
*
* #param inputMethodManager is used to show the key board
*/
private inner class BlockContextMenuTouchListener internal constructor(private val inputMethodManager: InputMethodManager) :
View.OnTouchListener {
private var lastTapTime: Long = 0
val TIME_INTERVAL_BETWEEN_DOUBLE_TAP = 30
override fun onTouch(v: View, event: MotionEvent): Boolean {
if (event.getAction() === MotionEvent.ACTION_DOWN) {
val currentTapTime = System.currentTimeMillis()
if (lastTapTime != 0L && currentTapTime - lastTapTime < TIME_INTERVAL_BETWEEN_DOUBLE_TAP) {
this#SecureEditText.setSelected(false)
performHandlerAction(inputMethodManager)
return true
} else {
if (lastTapTime == 0L) {
lastTapTime = currentTapTime
} else {
lastTapTime = 0
}
performHandlerAction(inputMethodManager)
return true
}
} else if (event.getAction() === MotionEvent.ACTION_MOVE) {
this#SecureEditText.setSelected(false)
performHandlerAction(inputMethodManager)
}
return false
}
}
}
A widely compatible solution (from Android 1.5 onwards) is
#Override
public boolean onTextContextMenuItem(int id) {
switch (id){
case android.R.id.cut:
onTextCut();
return false;
case android.R.id.paste:
onTextPaste();
return false;
case android.R.id.copy:
onTextCopy();
return false;
}
return true;
}
After spending a lot of time, removing the paste option in ContextMenu of EditText I have followed the below code in Java.
NoMenuEditText.Java
import android.content.Context;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import androidx.appcompat.widget.AppCompatEditText;
/**
* custom edit text
*/
public class NoMenuEditText extends AppCompatEditText {
private static final String EDITTEXT_ATTRIBUTE_COPY_AND_PASTE = "isCopyPasteDisabled";
private static final String PACKAGE_NAME = "http://schemas.android.com/apk/res-auto";
public NoMenuEditText(Context context) {
super(context);
}
public NoMenuEditText(Context context, AttributeSet attrs) {
super(context, attrs);
EnableDisableCopyAndPaste(context, attrs);
}
/**
* Enable/Disable Copy and Paste functionality on EditText
*
* #param context Context object
* #param attrs AttributeSet Object
*/
private void EnableDisableCopyAndPaste(Context context, AttributeSet attrs) {
boolean isDisableCopyAndPaste = attrs.getAttributeBooleanValue(PACKAGE_NAME,
EDITTEXT_ATTRIBUTE_COPY_AND_PASTE, false);
if (isDisableCopyAndPaste && !isInEditMode()) {
InputMethodManager inputMethodManager = (InputMethodManager)
context.getSystemService(Context.INPUT_METHOD_SERVICE);
this.setLongClickable(false);
this.setOnTouchListener(new BlockContextMenuTouchListener
(inputMethodManager));
}
}
/**
* Perform Focus Enabling Task to the widget with the help of handler object
* with some delay
*/
private void performHandlerAction(final InputMethodManager inputMethodManager) {
int postDelayedIntervalTime = 25;
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
NoMenuEditText.this.setSelected(true);
NoMenuEditText.this.requestFocusFromTouch();
inputMethodManager.showSoftInput(NoMenuEditText.this,
InputMethodManager.RESULT_SHOWN);
}
}, postDelayedIntervalTime);
}
/**
* Class to Block Context Menu on double Tap
* A custom TouchListener is being implemented which will clear out the focus
* and gain the focus for the EditText, in few milliseconds so the selection
* will be cleared and hence the copy paste option wil not pop up.
* the respective EditText should be set with this listener
*/
private class BlockContextMenuTouchListener implements View.OnTouchListener {
private static final int TIME_INTERVAL_BETWEEN_DOUBLE_TAP = 30;
private InputMethodManager inputMethodManager;
private long lastTapTime = 0;
BlockContextMenuTouchListener(InputMethodManager inputMethodManager) {
this.inputMethodManager = inputMethodManager;
}
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
long currentTapTime = System.currentTimeMillis();
if (lastTapTime != 0 && (currentTapTime - lastTapTime)
< TIME_INTERVAL_BETWEEN_DOUBLE_TAP) {
NoMenuEditText.this.setSelected(false);
performHandlerAction(inputMethodManager);
return true;
} else {
if (lastTapTime == 0) {
lastTapTime = currentTapTime;
} else {
lastTapTime = 0;
}
performHandlerAction(inputMethodManager);
return true;
}
} else if (event.getAction() == MotionEvent.ACTION_MOVE) {
NoMenuEditText.this.setSelected(false);
performHandlerAction(inputMethodManager);
}
return false;
}
}
#Override
protected void onSelectionChanged(int selStart, int selEnd) {
CharSequence text = getText();
if (text != null) {
if (selStart != text.length() || selEnd != text.length()) {
setSelection(text.length(), text.length());
return;
}
}
super.onSelectionChanged(selStart, selEnd);
}
#Override
public boolean isSuggestionsEnabled() {
return false;
}
#Override
public int getSelectionStart() {
for (StackTraceElement element : Thread.currentThread().getStackTrace()) {
if (element.getMethodName().equals("canPaste")) {
return -1;
}
}
return super.getSelectionStart();
}
}
MainActivity
import androidx.appcompat.app.AppCompatActivity;
import android.content.ClipboardManager;
import android.content.Context;
import android.os.Bundle;
import android.view.ActionMode;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
public class MainActivity extends AppCompatActivity {
NoMenuEditText edt_username;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
edt_username = (NoMenuEditText) findViewById(R.id.edt_username);
edt_username.setLongClickable(false);
edt_username.setTextIsSelectable(false);
edt_username.setCustomSelectionActionModeCallback(new ActionMode.Callback() {
#Override
public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
return false;
}
#Override
public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) {
return false;
}
#Override
public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) {
return false;
}
#Override
public void onDestroyActionMode(ActionMode actionMode) {
}
});
}
}
drawable- zeropx.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<size
android:width="0dp"
android:height="0dp"/>
</shape>
attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="NoMenuEditText">
<attr name="isCopyPasteDisabled" format="boolean" />
</declare-styleable>
</resources>
At Last, I finally Removed the paste option from the Context Menu of EditText
Thank you StackOverflow posts and http://androidinformative.com/disabling-context-menu/
editText.apply {
setOnTouchListener { v, event ->
if (event.action == KeyEvent.ACTION_DOWN) {
requestFocus()
setSelection(text.toString().length)
showKeyboard()
return#setOnTouchListener true
}
}
}
fun View.showKeyboard() {
val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.showSoftInput(this, 0)
}
Actually in my case i had to set the callback for both selection and insertion and only then i got the copy/paste pop-up to not appear anymore.
Something like this :
private void disableCopyPaste() {
input.setLongClickable(false);
input.setTextIsSelectable(false);
final ActionMode.Callback disableCopyPasteCallback = new ActionMode.Callback() {
#Override
public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
return false;
}
#Override
public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) {
return false;
}
#Override
public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) {
return false;
}
#Override
public void onDestroyActionMode(ActionMode actionMode) {
}
};
input.setCustomSelectionActionModeCallback(disableCopyPasteCallback);
input.setCustomInsertionActionModeCallback(disableCopyPasteCallback);
}
Similar to GnrlKnowledge, you can clear the Clipboard
http://developer.android.com/reference/android/text/ClipboardManager.html
If you want, preserve the text in the Clipboard, and on onDestroy, you can set it again.

GWT CEll Browser Real Time Update

has someone been able to correctly to update a cell browser at runtime, i.e. when u remove a node or add a node, the change is reflected immediately in the CEll Browser, because I am using a List and when i am making a change it is not being updated on the spot
You can use ListDataProvider setList(...) method for dynamic updates. Here is an example how I update cell browser via RPC:
private void loadAllData(final ListDataProvider<Data> dataProvider) {
dBservice.getAllData(new AsyncCallback<List<Data>>() {
public void onSuccess(List<Data> result) {
dataProvider.setList(result);
}
public void onFailure(Throwable caught) {
caught.printStackTrace();
}
});
}
to refresh a cellBrowser you have to close all the child on the root node.
anyway something like this
for (int i = 0; i < cellBrowser.getRootTreeNode().getChildCount(); i++) {
cellBrowser.getRootTreeNode().setChildOpen(i, false);
}
the AsyncDataProvider calls refreshes data
private final class Model implements TreeViewModel{
private List<ZonaProxy> zonaList = null;
private List<CategoriaProxy> categoriaList = null;
public void setCategoriaList(List<CategoriaProxy> categoriaList) {
this.categoriaList = categoriaList;
}
public void setListZona(List<ZonaProxy> zonaList) {
this.zonaList = zonaList;
}
#SuppressWarnings({ "unchecked", "rawtypes" })
public <T> NodeInfo<?> getNodeInfo(T value) {
CategoryDataProvider dataProvider1 = new CategoryDataProvider();
return new DefaultNodeInfo(dataProvider1, new CategoriaCell());
}
/**
* Check if the specified value represents a leaf node. Leaf nodes cannot be
* opened.
*/
public boolean isLeaf(Object value) {
if (value instanceof CategoriaProxy){
if (((CategoriaProxy) value).getLivello() == 3) {
return true;
}
}
return false;
}
}
private class CategoryDataProvider extends AsyncDataProvider<CategoriaProxy>
{
#Override
protected void onRangeChanged(HasData<CategoriaProxy> display)
{
requests.categoriaRequest().findAllCategorias(0, 8).with().fire(new Receiver<List<CategoriaProxy>>() {
#Override
public void onSuccess(List<CategoriaProxy> values) {
updateRowCount(values.size(), true);
updateRowData(0, values);
}
});
}
}
it Works.
Apparently it is not enough to change the data provider and refresh it.
You need also to force the affected cell to close and reopen it, as in this example
public void updateCellBrowser(String id) {
TreeNode node = getNode(cellBrowser.getRootTreeNode(),id);
if(node != null && ! node.isDestroyed()) {
TreeNode parent = node.getParent();
int index = node.getIndex();
parent.setChildOpen(index, false,true);
parent.setChildOpen(index, true, true);
}
}
In my particular example the cell ids are pathnames hence the following
implementation of getNode().
private TreeNode getNode(TreeNode node, String id) {
for(int i=0; i < node.getChildCount(); i++)
if(node.isChildOpen(i)) {
Object value = node.getChildValue(i);
if(value instanceof String) {
String nodeId = ((String) value);
if(id.equals(nodeId))
return node.setChildOpen(i, true);
if(id.startsWith(nodeId))
getNode(node.setChildOpen(i, true),id);
}
}
return null;
}