PDA

View Full Version : DND for roerdering rows on a grouping grid



Nico33
16 Jan 2010, 1:16 AM
Hi all,
I'm trying to reorder the rows of a grouping grid, but only in the same group.
First, I'm trying to know what is dropped and where. So i'm adding a listener on the dragDrop event.
I can get the dragged elements with :



target.addDNDListener(new DNDListener()
{
public void dragDrop(DNDEvent e)
{
if (e.getData() instanceof List<?>)
{
List<Stock> list = (List<Stock>) e.getData();
}
}
}


But I'm unable to know where it is dropped. If I use :



Element dst = e.getTarget();
int row = grid.getView().findRowIndex(dst);


row is always equal to -1 and of course

grid.getStore().getAt(row)
is never good

When I'll be able to know what is dropped and where, I will change the values of the objects, reorder the store and refresh the view.
This is my complete code (based on the GroupingGridExample) :



public class GroupingGridExample extends LayoutContainer {
@Override
protected void onRender(Element parent, int index) {
super.onRender(parent, index);
setLayout(new FlowLayout(10));
GroupingStore<Stock> store = new GroupingStore<Stock>();
store.add(TestData.getCompanies());
store.groupBy("industry");
ColumnConfig company = new ColumnConfig("name", "Company", 60);
ColumnConfig price = new ColumnConfig("open", "Price", 20);
ColumnConfig change = new ColumnConfig("change", "Change", 20);
ColumnConfig industry = new ColumnConfig("industry", "Industry", 20);
ColumnConfig last = new ColumnConfig("date", "Last Updated", 20);
last.setDateTimeFormat(DateTimeFormat.getFormat("MM/dd/y"));
List<ColumnConfig> config = new ArrayList<ColumnConfig>();
config.add(company);
config.add(price);
config.add(change);
config.add(industry);
config.add(last);
final ColumnModel cm = new ColumnModel(config);
GroupingView view = new GroupingView();
view.setShowGroupedColumn(false);
view.setForceFit(true);
view.setGroupRenderer(new GridGroupRenderer() {
public String render(GroupColumnData data) {
String f = cm.getColumnById(data.field).getHeader();
String l = data.models.size() == 1 ? "Item" : "Items";
return f + ": " + data.group + " (" + data.models.size() + " " + l + ")";
}
});
final Grid<Stock> grid = new Grid<Stock>(store, cm);
grid.setView(view);
grid.setBorders(true);
ContentPanel panel = new ContentPanel();
panel.setHeading("Grouping Example");
panel.setCollapsible(true);
panel.setFrame(true);
panel.setSize(700, 450);
panel.setLayout(new FitLayout());
panel.add(grid);
add(panel);

new GridDragSource(grid);
GridDropTarget target = new GridDropTarget(grid);
target.setAllowSelfAsSource(true);
target.setFeedback(Feedback.INSERT);
target.addDNDListener(new DNDListener()
{
public void dragDrop(DNDEvent e)
{
if (e.getData() instanceof List<?>)
{
List<Stock> list = (List<Stock>) e.getData();
/*for (Stock s : list)
MessageBox.alert("", s.getName(), null);*/

Element dst = e.getTarget();
int row = grid.getView().findRowIndex(dst);
MessageBox.alert("", String.valueOf(row), null);
}
}
});
}
}


Maybe there's a better (and simpler) solution.

Thanks in advance for any help.
Best regards

Nico33
18 Jan 2010, 9:04 AM
No idea ?

Nico33
21 Jan 2010, 1:38 AM
maybe i'm not going in the right way, Is there a better solution ?

Nico33
22 Jan 2010, 6:01 AM
I'm sorry to up again ... But i'm stuck :((

Arno.Nyhm
22 Jan 2010, 8:38 AM
I'm sorry to up again ... But i'm stuck :((

i looked into your code.

i get some data visible on Drag Move and on Drag End. I dont know if it the data you need.

but maybe this helps you:


the key thing is this code:


GridDropTarget target = new GridDropTarget(grid) {

@Override
protected void onDragMove(DNDEvent e) {
super.onDragMove(e);
int findRowIndex = grid.getView().findRowIndex(e.getDragEvent().getTarget());

Stock at = (Stock) grid.getStore().getAt(findRowIndex);

Info.display("GridDropTarget:onDragMove", "" + findRowIndex + ": " + ((at != null) ? (at.getName() + " " + at.getIndustry()) : " n/a"));
}
};
target.setAllowSelfAsSource(true);
target.setFeedback(Feedback.INSERT);
GridDragSource gridDragSource = new GridDragSource(grid) {

@Override
protected void onDragDrop(DNDEvent e) {
super.onDragDrop(e);
int findRowIndex = grid.getView().findRowIndex(e.getDragEvent().getTarget());
Stock at = (Stock) grid.getStore().getAt(findRowIndex);
Info.display("GridDragSource", "" + findRowIndex + ": " + ((at != null) ? (at.getName() + " " + at.getIndustry()) : " n/a"));
}
};
18373

the full code:


package com.mycompany.myapplication.client.forumsnippets;

import com.extjs.gxt.ui.client.dnd.DND.Feedback;
import com.extjs.gxt.ui.client.dnd.GridDragSource;
import com.extjs.gxt.ui.client.dnd.GridDropTarget;
import com.extjs.gxt.ui.client.event.DNDEvent;
import com.extjs.gxt.ui.client.store.GroupingStore;
import com.extjs.gxt.ui.client.widget.ContentPanel;
import com.extjs.gxt.ui.client.widget.Info;
import com.extjs.gxt.ui.client.widget.LayoutContainer;
import com.extjs.gxt.ui.client.widget.Window;
import com.extjs.gxt.ui.client.widget.grid.ColumnConfig;
import com.extjs.gxt.ui.client.widget.grid.ColumnModel;
import com.extjs.gxt.ui.client.widget.grid.Grid;
import com.extjs.gxt.ui.client.widget.grid.GridGroupRenderer;
import com.extjs.gxt.ui.client.widget.grid.GroupColumnData;
import com.extjs.gxt.ui.client.widget.grid.GroupingView;
import com.extjs.gxt.ui.client.widget.layout.FitLayout;
import com.extjs.gxt.ui.client.widget.layout.FlowLayout;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.user.client.Element;
import com.mycompany.myapplication.client.forumsnippets.resources.TestData;
import com.mycompany.myapplication.client.forumsnippets.resources.model.Stock;
import java.util.ArrayList;
import java.util.List;

/**
*
* @author Arno.Nyhm
*/
public class ForumThread429942DragDropGroupingGrid implements EntryPoint {

public void onModuleLoad() {
Window window = new Window();
window.setSize(800, 500);
window.add(new GroupingGridExample());
window.show();
}

public class GroupingGridExample extends LayoutContainer {

@Override
protected void onRender(Element parent, int index) {
super.onRender(parent, index);
setLayout(new FlowLayout(10));
GroupingStore<Stock> store = new GroupingStore<Stock>();
store.add(TestData.getCompanies());
store.groupBy("industry");
ColumnConfig company = new ColumnConfig("name", "Company", 60);
ColumnConfig price = new ColumnConfig("open", "Price", 20);
ColumnConfig change = new ColumnConfig("change", "Change", 20);
ColumnConfig industry = new ColumnConfig("industry", "Industry", 20);
ColumnConfig last = new ColumnConfig("date", "Last Updated", 20);
last.setDateTimeFormat(DateTimeFormat.getFormat("MM/dd/y"));
List<ColumnConfig> config = new ArrayList<ColumnConfig>();
config.add(company);
config.add(price);
config.add(change);
config.add(industry);
config.add(last);
final ColumnModel cm = new ColumnModel(config);
GroupingView view = new GroupingView();
view.setShowGroupedColumn(false);
view.setForceFit(true);
view.setGroupRenderer(new GridGroupRenderer() {

public String render(GroupColumnData data) {
String f = cm.getColumnById(data.field).getHeader();
String l = data.models.size() == 1 ? "Item" : "Items";
return f + ": " + data.group + " (" + data.models.size() + " " + l + ")";
}
});
final Grid<Stock> grid = new Grid<Stock>(store, cm);
grid.setView(view);
grid.setBorders(true);
ContentPanel panel = new ContentPanel();
panel.setHeading("Grouping Example");
panel.setCollapsible(true);
panel.setFrame(true);
panel.setSize(700, 450);
panel.setLayout(new FitLayout());
panel.add(grid);
add(panel);

GridDropTarget target = new GridDropTarget(grid) {

@Override
protected void onDragMove(DNDEvent e) {
super.onDragMove(e);
int findRowIndex = grid.getView().findRowIndex(e.getDragEvent().getTarget());

Stock at = (Stock) grid.getStore().getAt(findRowIndex);

Info.display("GridDropTarget:onDragMove", "" + findRowIndex + ": " + ((at != null) ? (at.getName() + " " + at.getIndustry()) : " n/a"));
}
};
target.setAllowSelfAsSource(true);
target.setFeedback(Feedback.INSERT);
GridDragSource gridDragSource = new GridDragSource(grid) {

@Override
protected void onDragDrop(DNDEvent e) {
super.onDragDrop(e);
int findRowIndex = grid.getView().findRowIndex(e.getDragEvent().getTarget());
Stock at = (Stock) grid.getStore().getAt(findRowIndex);
Info.display("GridDragSource", "" + findRowIndex + ": " + ((at != null) ? (at.getName() + " " + at.getIndustry()) : " n/a"));
}
};
}
}
}

Nico33
26 Jan 2010, 9:04 AM
Thanks for your answer Arno.

I'm still trying to adapt your example. But that's 3 day I can't achieve anything.
I'm surprised that there's nothing that allow reordering rows in the grouping grid.

I've even tryed with an "order" value in the rows, and sort on this value, but ... nothing.

Do you have an idea ? Or maybe another working example ?

that would be very appreciated.

Thanks in advance.

Arno.Nyhm
26 Jan 2010, 10:28 AM
if you sort on a column it should be reordered. maybe there is some other missing point. you have a current state of your code where you try to ordering it.

Nico33
26 Jan 2010, 2:09 PM
Thanks Arno for your help, I fell less lonely :D

this is my code, it seems to work most of the time, but it seems to don't work everytime ...


package com.test.client;

import java.util.ArrayList;
import java.util.List;

import com.extjs.gxt.ui.client.data.BaseModel;
import com.extjs.gxt.ui.client.data.ModelData;
import com.extjs.gxt.ui.client.dnd.GridDragSource;
import com.extjs.gxt.ui.client.dnd.GridDropTarget;
import com.extjs.gxt.ui.client.dnd.DND.Feedback;
import com.extjs.gxt.ui.client.event.DNDEvent;
import com.extjs.gxt.ui.client.store.GroupingStore;
import com.extjs.gxt.ui.client.store.ListStore;
import com.extjs.gxt.ui.client.widget.ContentPanel;
import com.extjs.gxt.ui.client.widget.LayoutContainer;
import com.extjs.gxt.ui.client.widget.Window;
import com.extjs.gxt.ui.client.widget.grid.ColumnConfig;
import com.extjs.gxt.ui.client.widget.grid.ColumnModel;
import com.extjs.gxt.ui.client.widget.grid.Grid;
import com.extjs.gxt.ui.client.widget.grid.GroupingView;
import com.extjs.gxt.ui.client.widget.layout.FitLayout;
import com.extjs.gxt.ui.client.widget.layout.FlowLayout;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.Element;

final class MyValue extends BaseModel
{
private static final long serialVersionUID = -3209667217029014368L;

public MyValue(String group, String name, int order)
{
set("group", group);
set("name", name);
set("order", order);
}

public static List<MyValue> getValues()
{
List<MyValue> list = new ArrayList<MyValue>();
list.add(new MyValue("group 1", "Name 1", 1));
list.add(new MyValue("group 1", "Name 2", 2));
list.add(new MyValue("group 1", "Name 3", 3));
list.add(new MyValue("group 1", "Name 4", 4));

list.add(new MyValue("group 2", "Other name 2", 2));
list.add(new MyValue("group 2", "Other name 3", 3));
list.add(new MyValue("group 2", "Other name 1", 1));
return list;
}
}

/**
*
* @author Arno.Nyhm
*/
public class ForumThread429942DragDropGroupingGrid implements EntryPoint
{
public void onModuleLoad()
{
Window window = new Window();
window.setSize(800, 500);
window.add(new GroupingGridExample());
window.show();
}

public class GroupingGridExample extends LayoutContainer
{
int rowIndex = -1;
@Override
protected void onRender(Element parent, int index)
{
super.onRender(parent, index);
setLayout(new FlowLayout(10));
GroupingStore<MyValue> store = new GroupingStore<MyValue>();
store.add(MyValue.getValues());
store.groupBy("group");
store.setSortField("order");
ColumnConfig group = new ColumnConfig("group", "group", 150);
ColumnConfig name = new ColumnConfig("name", "Name", 150);
ColumnConfig order = new ColumnConfig("order", "Order", 140);
List<ColumnConfig> config = new ArrayList<ColumnConfig>();
config.add(group);
config.add(name);
config.add(order);
final ColumnModel cm = new ColumnModel(config);
GroupingView view = new GroupingView();
view.setShowGroupedColumn(false);
view.setForceFit(true);

final Grid<MyValue> grid = new Grid<MyValue>(store, cm);
grid.setView(view);
grid.setBorders(true);
ContentPanel panel = new ContentPanel();
panel.setHeading("Grouping Example");
panel.setCollapsible(true);
panel.setFrame(true);
panel.setSize(700, 450);
panel.setLayout(new FitLayout());
panel.add(grid);
add(panel);

GridDropTarget target = new GridDropTarget(grid)
{
@Override
protected void onDragMove(DNDEvent e)
{
super.onDragMove(e);
rowIndex = grid.getView().findRowIndex(e.getDragEvent().getTarget());
}

@SuppressWarnings("unchecked")
@Override
protected void onDragDrop(DNDEvent e)
{
if (rowIndex == -1)
{
super.onDragDrop(e);
return;
}

ListStore<ModelData> store = grid.getStore();
if (e.getData() instanceof List<?>)
{
MyValue from = ((List<MyValue>) e.getData()).get(0);
MyValue at = (MyValue) grid.getStore().getAt(rowIndex);

int orderSource = from.get("order");
int orderDestination = at.get("order");
from.set("order", orderDestination);

super.onDragDrop(e);

for (int i = 0 ; i < store.getCount() ; i++)
{
MyValue current = (MyValue)store.getAt(i);
int currentOrder = current.get("order");
String group = current.get("group");
if (current != from && group.equals(from.get("group")))
{
if (orderSource > orderDestination)
{
if (currentOrder >= orderDestination && currentOrder <= orderSource)
current.set("order", currentOrder + 1);
}
else
{
if (currentOrder <= orderDestination && currentOrder >= orderSource)
current.set("order", currentOrder - 1);
}
}
}

grid.getView().refresh(false);
}
else
super.onDragDrop(e);
}
};
target.setAllowSelfAsSource(true);
target.setFeedback(Feedback.BOTH);
new GridDragSource(grid)
{
@Override
protected void onDragDrop(DNDEvent e)
{
super.onDragDrop(e);
rowIndex = grid.getView().findRowIndex(e.getDragEvent().getTarget());
}
};
}
}
}

I've changed for Feedback.BOTH too.
Do you see anything wrong ?

Thanks for your answers

Nico33
29 Jan 2010, 5:49 AM
Hi, this is my full example that looks to work.
But I find it very complex.

First I need to have an "order" property on my ModelData.
Second, I need to define this as a sort.
While dragmoving, I need to check if the target is an other group.
When droping, I need to reorder the store.

Can this be optimized ? Done with magic that I don't know ?


final class MyValue extends BaseModel
{
private static final long serialVersionUID = -3209667217029014368L;

public MyValue(String group, String name, int order)
{
set("group", group);
set("name", name);
set("order", order);
}

public static List<MyValue> getValues()
{
List<MyValue> list = new ArrayList<MyValue>();
list.add(new MyValue("group 1", "Name 1", 1));
list.add(new MyValue("group 1", "Name 2", 2));
list.add(new MyValue("group 1", "Name 3", 3));
list.add(new MyValue("group 1", "Name 4", 4));

list.add(new MyValue("group 2", "Other name 2", 2));
list.add(new MyValue("group 2", "Other name 3", 3));
list.add(new MyValue("group 2", "Other name 1", 1));
return list;
}
}

/**
*
* @author Arno.Nyhm
*/
public class ForumThread429942DragDropGroupingGrid implements EntryPoint
{
public void onModuleLoad()
{
Window window = new Window();
window.setSize(800, 500);
window.add(new GroupingGridExample());
window.show();
}

public class GroupingGridExample extends LayoutContainer
{
int rowIndex = -1;
@Override
protected void onRender(Element parent, int index)
{
super.onRender(parent, index);
setLayout(new FlowLayout(10));
GroupingStore<MyValue> store = new GroupingStore<MyValue>();
store.add(MyValue.getValues());
store.groupBy("group");
store.setSortField("order");
ColumnConfig group = new ColumnConfig("group", "group", 150);
ColumnConfig name = new ColumnConfig("name", "Name", 150);
//ColumnConfig order = new ColumnConfig("order", "Order", 140);
List<ColumnConfig> config = new ArrayList<ColumnConfig>();
config.add(group);
config.add(name);
//config.add(order);
final ColumnModel cm = new ColumnModel(config);
GroupingView view = new GroupingView();
view.setShowGroupedColumn(false);
view.setForceFit(true);

final Grid<MyValue> grid = new Grid<MyValue>(store, cm);
grid.setView(view);
grid.setBorders(true);
ContentPanel panel = new ContentPanel();
panel.setHeading("Grouping Example");
panel.setCollapsible(true);
panel.setFrame(true);
panel.setSize(700, 450);
panel.setLayout(new FitLayout());
panel.add(grid);
add(panel);

GridDropTarget target = new GridDropTarget(grid)
{
@Override
protected void onDragMove(DNDEvent e)
{
super.onDragMove(e);
rowIndex = grid.getView().findRowIndex(e.getDragEvent().getTarget());
if (rowIndex == -1)
{
e.setCancelled(true);
e.getStatus().setStatus(false);
}
else
{
MyValue at = (MyValue) grid.getStore().getAt(rowIndex);
MyValue from = (MyValue) grid.getSelectionModel().getSelectedItem();
if (!at.get("group").equals(from.get("group")))
{
e.setCancelled(true);
e.getStatus().setStatus(false);
}
}
}

@SuppressWarnings("unchecked")
@Override
protected void onDragDrop(DNDEvent e)
{
if (rowIndex == -1)
{
super.onDragDrop(e);
return;
}

ListStore<ModelData> store = grid.getStore();
if (e.getData() instanceof List<?>)
{
MyValue from = ((List<MyValue>) e.getData()).get(0);
MyValue at = (MyValue) grid.getStore().getAt(rowIndex);

int orderSource = from.get("order");
int orderDestination = at.get("order");
from.set("order", orderDestination);

super.onDragDrop(e);

for (int i = 0 ; i < store.getCount() ; i++)
{
MyValue current = (MyValue)store.getAt(i);
int currentOrder = current.get("order");
String group = current.get("group");
if (current != from && group.equals(from.get("group")))
{
if (orderSource > orderDestination)
{
if (currentOrder >= orderDestination && currentOrder <= orderSource)
current.set("order", currentOrder + 1);
}
else
{
if (currentOrder <= orderDestination && currentOrder >= orderSource)
current.set("order", currentOrder - 1);
}
}
}

store.sort("order", SortDir.ASC);
}
else
super.onDragDrop(e);
}
};
target.setAllowSelfAsSource(true);
target.setFeedback(Feedback.INSERT);
new GridDragSource(grid)
{
@Override
protected void onDragDrop(DNDEvent e)
{
super.onDragDrop(e);
rowIndex = grid.getView().findRowIndex(e.getDragEvent().getTarget());
}
};
}
}
} I have to use the gridselectionmodel.getselecteditem too ...

I don't dare to think what will append if I sort on another column ...:-?

Arno.Nyhm
29 Jan 2010, 10:42 AM
i played yesterday also your example and find out that including that sort was needed. i replay your new example but i get in the hosted mode an NPE error :-(

BUT: i have digged in a littel and created a GroupingGridDropTarget which encapsulate all :-)
you can see it here:

GroupingGridDropTarget
http://www.extjs.com/forum/showthread.php?t=90903

Nico33
31 Jan 2010, 1:12 AM
What do you mean with NPE error ?

Thanks for your sample, I see with your code that I have many things to learn ;)

Arno.Nyhm
1 Feb 2010, 6:53 AM
NPE = NullPointerException

the only point i have done was to digg into the java source of GridDropTarget and GridDragSource to look whats going on there and how i can reuse it for my needs.