I'm trying to add drag-n-drop to cell widgets. More specifically, I want to drag and drop ClickableTextCell
s, but they don't have the specific methods and not even .addDomHandler
, so I can't just create something like .addDomHandler(new DragStartHandler() { ... }
Can someone give some help on how to DnD cells, preferably with pure GWT?
I do not know how to implement a DnD with GWT, but I know how to implement a CnC (Clic 'n Clic), which might interest you. DnD are cool, fun and beautiful, but I think that some times they are not very convenient. For instance if you have a big screen requiring a scroll, and if you want to DnD an item from the top to the bottom, it is not so convenient to have to hold the mouse... But this just a personnal feeling...
Anyway, I would recommand you to use a ListDataProvider along with simple events, in order to move your items: the first clic selects the source item, and the second clic selects the destination. Once the source and the destination are known, you can move your item.
It works well for me... and if you add some styles to highlight source and destination, it is very nice.
Example:
This is the main class:
import java.util.ArrayList;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.cellview.client.CellList;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.FocusPanel;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.view.client.ListDataProvider;
import com.google.gwt.view.client.SelectionChangeEvent;
import com.google.gwt.view.client.SingleSelectionModel;
public class Clic_Clic {
private static final Integer LEFT = 0;
private static final Integer CENTER = 1;
private static final Integer RIGHT = 2;
private ClicClicSelectionModel<Item> selectionModel = new ClicClicSelectionModel<Item>();
ListDataProvider<Item> leftLDP = new ListDataProvider<Item>();
ListDataProvider<Item> centerLDP = new ListDataProvider<Item>();
ListDataProvider<Item> rightLDP = new ListDataProvider<Item>();
FocusPanel left = new FocusPanel(), center = new FocusPanel(), right = new FocusPanel();
Item selected = null;
public Clic_Clic() {
// --- Builds the GUI
DialogBox clic_clic = buildGUI();
clic_clic.center();
clic_clic.show();
// --- Initializes data
configureSelectionManagement();
initCellLists();
configureAddAndRemove();
// --- Fills the left LDP
leftLDP.getList().add(new Item("Fraternité", LEFT));
leftLDP.refresh();
// --- Fills the center LDP
centerLDP.getList().add(new Item("Egalité", LEFT));
centerLDP.refresh();
// --- Fills the right LDP
rightLDP.getList().add(new Item("Liberté", RIGHT));
rightLDP.refresh();
}
private DialogBox buildGUI() {
DialogBox db = new DialogBox();
db.setText("A simple example for Clic 'n Clic");
db.setSize("300px", "200px");
db.setGlassEnabled(true);
db.setModal(true);
FlowPanel fp = buildContent();
db.add(fp);
return db;
}
private FlowPanel buildContent() {
Grid g = new Grid(1, 3);
g.setSize("300px", "200px");
g.setWidget(0, 0, left);
left.setSize("100px", "100px");
left.getElement().getStyle().setBackgroundColor("blue");
g.setWidget(0, 1, center);
center.setSize("100px", "100px");
g.setWidget(0, 2, right);
right.setSize("100px", "100px");
right.getElement().getStyle().setBackgroundColor("red");
FlowPanel fp = new FlowPanel();
fp.setSize("300px", "200px");
fp.add(new Label("Do you know the correct order ?"));
fp.add(g);
return fp;
}
private void initCellLists() {
// --- Associates the left panel with the leftLDP ListDataProvider
CellList<Item> cellListLeft = new CellList<Item>(new MyCell());
cellListLeft.setSelectionModel(selectionModel);
left.add(cellListLeft);
leftLDP = new ListDataProvider<Item>(new ArrayList<Item>());
leftLDP.addDataDisplay(cellListLeft);
// --- Associates the center panel with the centerLDP ListDataProvider
CellList<Item> cellListCenter = new CellList<Item>(new MyCell());
cellListCenter.setSelectionModel(selectionModel);
center.add(cellListCenter);
centerLDP = new ListDataProvider<Item>(new ArrayList<Item>());
centerLDP.addDataDisplay(cellListCenter);
// --- Associates the right panel with the rightLDP ListDataProvider
CellList<Item> cellListRight = new CellList<Item>(new MyCell());
cellListRight.setSelectionModel(selectionModel);
right.add(cellListRight);
rightLDP = new ListDataProvider<Item>(new ArrayList<Item>());
rightLDP.addDataDisplay(cellListRight);
}
private void configureAddAndRemove() {
// --- If the user clic on the left
left.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
if (selected != null) {
// --- If the selected item comes from the right
if (selected.getContainerIndex() == RIGHT) {
rightLDP.getList().remove(selected);
rightLDP.refresh();
selected.setContainerIndex(LEFT);
leftLDP.getList().add(selected);
leftLDP.refresh();
selected = null;
}
// --- If the selected item comes from the center
if (selected.getContainerIndex() == CENTER) {
centerLDP.getList().remove(selected);
centerLDP.refresh();
selected.setContainerIndex(LEFT);
leftLDP.getList().add(selected);
leftLDP.refresh();
selected = null;
}
}
}
});
// --- If the user clic on the center
center.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
if (selected != null) {
// --- If the selected item comes from the right
if (selected.getContainerIndex() == RIGHT) {
rightLDP.getList().remove(selected);
rightLDP.refresh();
selected.setContainerIndex(CENTER);
centerLDP.getList().add(selected);
centerLDP.refresh();
selected = null;
}
// --- If the selected item comes from the left
if (selected.getContainerIndex() == LEFT) {
leftLDP.getList().remove(selected);
leftLDP.refresh();
selected.setContainerIndex(CENTER);
centerLDP.getList().add(selected);
centerLDP.refresh();
selected = null;
}
}
}
});
// --- If the user clic on the right
right.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
// --- If the selected item comes from the left
if (selected.getContainerIndex() == LEFT) {
leftLDP.getList().remove(selected);
leftLDP.refresh();
selected.setContainerIndex(RIGHT);
rightLDP.getList().add(selected);
rightLDP.refresh();
selected = null;
}
// --- If the selected item comes from the center
if (selected.getContainerIndex() == CENTER) {
centerLDP.getList().remove(selected);
centerLDP.refresh();
selected.setContainerIndex(RIGHT);
rightLDP.getList().add(selected);
rightLDP.refresh();
selected = null;
}
}
});
}
@SuppressWarnings("hiding")
class ClicClicSelectionModel<Item> extends SingleSelectionModel<Item> {
@Override
public void setSelected(Item object, boolean selected) {
if (getSelectedObject() != null && getSelectedObject().equals(object)) {
super.setSelected(object, !selected);
} else {
super.setSelected(object, selected);
}
};
}
private void configureSelectionManagement() {
selectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
@Override
public void onSelectionChange(SelectionChangeEvent event) {
Item selected = selectionModel.getSelectedObject();
updateSelected(selected);
}
});
}
private void updateSelected(Item item) {
// --- If no item has been selected, update the selected item
if (selected == null) {
selected = item;
}
}
}
You also need this one:
public class Item {
private String label;
private Integer containerIndex;
public Item(String l, Integer id) {
this.label = l;
this.containerIndex = id;
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
public Integer getContainerIndex() {
return containerIndex;
}
public void setContainerIndex(Integer containerIndex) {
this.containerIndex = containerIndex;
}
}
And finally, this one:
import com.google.gwt.cell.client.AbstractCell;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.safehtml.shared.SafeHtmlUtils;
public class MyCell extends AbstractCell<Item> {
@Override
public void render(com.google.gwt.cell.client.Cell.Context context, Item value, SafeHtmlBuilder sb) {
if (value != null) {
// --- If the value comes from the user, we escape it to avoid XSS
// attacks.
SafeHtml safeValue = SafeHtmlUtils.fromString(value.getLabel());
sb.append(safeValue);
}
}
}
Here you go. Next time I'll try to make a fun example :)
Hope it helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With