PDA

View Full Version : Drag and drop not working after scrolling grid



DamionS
9 Nov 2011, 10:09 AM
We seem to be having an issue with drag and drop. We have a grid with 100 rows in it and we need to drag rows to another grid. The screen shows 13 rows at a time. If we drag and drop a row from the first 13 rows then all works fine. However the moment you scroll down the grid the drag and drop starts to fail.

To make it more clear if you start off with rows 1 to 13 visible all is fine. If you drag the 3rd row now visible, the 3rd of the store is dropped into the target grid. However if you scroll so that rows 14 to 26 are now visible and drag row 17 to the target, the row that is actually dropped is row 3.

Has anybody seen this issue before and if so how do I fix it?

Colin Alworth
9 Nov 2011, 5:05 PM
The use case sounds like the demo at http://www.sencha.com/examples/explorer.html#gridtogrid but I am unable to reproduce the issue there. Can you offer specific instructions on how to reproduce this with the above link, or what modifications can be made to the sample code to have the issue occur?

DamionS
10 Nov 2011, 3:01 AM
Our example is a little more complex, hope this explains my app.

We have a channel which is a list of tracks and a track search window (which is a list of tracks). Both the channel and the search contain a class called trackObjGridBuiilder which builds and returns a Grid<TrackObj>. The application allows the dragging of tracks into the channel or the changing of the order of tracks in the channel via drag and drop. Search grid is only ever the source whilst channel grid can be the source or the target. In the drag enter event I check the component and if the source is the same as the target then the operation is set to move whilst if they are different the operation is set to copy.

The main difference is the fact that the grids are in different classes and that the operation changes depending on what the source is..

Colin Alworth
10 Nov 2011, 6:20 AM
The use case sounds involved, but not too complex - none of the things you describe seem that they should change the behavior of DnD enough that an issue like this could occur. Instead, it sounds like you have some code that is asking which row is selected by which item was clicked, and deciding on that item by the position of the last mousedown. That code is probably failing to take into account the position of the scrolling.

Add logging statements into your dnd stuff you have so far - perhaps that will show that early in the drag, the item is correct, then something else is selecting the wrong item.

Beyond that, without seeing code (or going ahead and trying to build your application myself...) there isn't a lot I can say.

DamionS
10 Nov 2011, 8:16 AM
I have added some logging to display the row index in the mouse over event

grid.addListener(Events.OnMouseOver, new Listener<GridEvent<TrackObj>>() {

@Override
public void handleEvent(GridEvent<TrackObj> be) {
TrackObj t = be.getModel();
System.out.println("t="+t);
int track = be.getRowIndex();
System.out.println("row="+ track);
if (t != null) {


}
}
};

and even though the mouse is over row 23 (which is in position 1 of the grid) the rowindex is 0. So I would say my issue lies deeper that DND.

Colin Alworth
10 Nov 2011, 8:53 AM
I'm not sure why you are listening to that event, and expecting non-zero value for the GridEvent - OnMouseOver isn't listed in the Grid javadocs as an event that is issued. Zero is probably the value for _every_ OnMouseOver GridEvent fired, since that is the default value for the event.

Grid.createComponentEvent makes _all_ events fired from the Grid a GridEvent, but, doesn't set all the values for every event.

Take a look at the class's javadoc to see what properties are set for what events - try Grid's Events.RowClick or RowMouseDown events to see that the row number is set correctly (see http://dev.sencha.com/deploy/gxtdocs/com/extjs/gxt/ui/client/widget/grid/Grid.html). Also try to get the DragStart event from the GridDragSource object, and check which model you are getting.

DamionS
10 Nov 2011, 9:01 AM
I was listening to that event because it had already been added to the grid for another purpose. Maybe I did not explain myself clearly.

I will try the RowMouseDown etc, but don't see the point as the onMouseOver proves the is an issue. No Zero is not the value for every row. Zero is the value for the first and 1 for the second, 2 for the third and so on until 12 for the thirteenth. As I said before the grid can only display 13 rows, I now scroll down and the row index is reset ie.e when display 14 to 27 14 is row zero, 15 is row 1 etc.

As I said I will have a look at the events you have suggested but I think the fact that the row count is already wrong is the source of my error.

DamionS
10 Nov 2011, 9:11 AM
I can confirm the same behaviour for rowclick and rowmousedown i.e row index is fine until row 13 scrolling down causes the rowindex to be reset. Hence the fact that when you drag and drop row 17 the row dropped is actually row 3

DamionS
11 Nov 2011, 3:38 AM
Hi Colin

I agree with your point that without seeing my code that there is not a lot you can say. So maybe this will help a little.

I am now convinced that the issue lies in the fact that the 2 grids have a view that is a LiveGridView. I have taken the http://www.sencha.com/examples/#livegrid example and added to my application , also adding the following code:

grid.addListener(Events.RowClick, new Listener<GridEvent<TrackObj>>() {


@Override
public void handleEvent(GridEvent<TrackObj> be) {
int track = be.getRowIndex();
System.out.println("click row="+ track);
}
});

When the grid is a normal GridView the row index shows correctly even when scrolling down. However when a live view is attached the row index is correct until you scroll down the grid and then the index is always based on the rows shown not the full list.

There is a strong possibility that the issue I have on DND is not related to this but I find it very suspicious that the behaviour found on drop is the same as the row index.



The use case sounds involved, but not too complex - none of the things you describe seem that they should change the behavior of DnD enough that an issue like this could occur. Instead, it sounds like you have some code that is asking which row is selected by which item was clicked, and deciding on that item by the position of the last mousedown. That code is probably failing to take into account the position of the scrolling.

Add logging statements into your dnd stuff you have so far - perhaps that will show that early in the drag, the item is correct, then something else is selecting the wrong item.

Beyond that, without seeing code (or going ahead and trying to build your application myself...) there isn't a lot I can say.

Colin Alworth
11 Nov 2011, 5:33 AM
The live grid view may well be the extra detail that I needed - I suspect that it doesn't track numbers correctly, as the scrollbar is used as a way to see where in the data you are and to load more, not to actually move the viewport. Notice that it isn't possible to scroll partly through an item, only to the top of the next item.

Let me look into this, and see what I can tell you - I don't believe live grid was ever intended to work with dnd, especially if selecting more than one item at once, as you could select something, scroll, then select again, and get an item which has been paged out of the store.

Colin Alworth
11 Nov 2011, 9:25 AM
Just built an example that seems to work just fine, using the live grid off of the samples page, plus a bit of dnd code. If there are other major differences between this code and the use case you have, perhaps you can point them out?

You will note that the row number in events is offset by the scroll position, as mentioned in the previous message. Note too that this is the correct index within the store at that time, due to how the live grid pages items in and out automatically. However, you should be able to correct that to get the actual index in the entire collection using the offset in the store's loader, updated when ever the grid scrolls.


public class LiveDndSample extends LayoutContainer implements EntryPoint {

public void onModuleLoad() {
RootPanel.get().add(this);
}


@Override
protected void onRender(Element parent, int index) {
super.onRender(parent, index);


FlowLayout layout = new FlowLayout(10);
setLayout(layout);


String url = "http://www.extjs.com/forum/topics-browse-remote.php";
ScriptTagProxy<PagingLoadResult<ModelData>> proxy = new ScriptTagProxy<PagingLoadResult<ModelData>>(url);


ModelType type = new ModelType();
type.setRoot("topics");
type.setTotalName("totalCount");
type.addField("title");
type.addField("forumtitle");
type.addField("forumid");
type.addField("author");
type.addField("replycount");
type.addField("lastposter");
type.addField("excerpt");
type.addField("replycount");
type.addField("threadid");


DataField datefield = new DataField("lastpost");
datefield.setType(Date.class);
datefield.setFormat("timestamp");
type.addField(datefield);


JsonPagingLoadResultReader<PagingLoadResult<ModelData>> reader = new JsonPagingLoadResultReader<PagingLoadResult<ModelData>>(
type);


final PagingLoader<PagingLoadResult<ModelData>> loader = new BasePagingLoader<PagingLoadResult<ModelData>>(proxy,
reader);


loader.addListener(Loader.BeforeLoad, new Listener<LoadEvent>() {
public void handleEvent(LoadEvent be) {
BasePagingLoadConfig m = be.<BasePagingLoadConfig> getConfig();
m.set("start", m.get("offset"));
m.set("ext", "js");
m.set("lightWeight", true);
m.set("sort", (m.get("sortField") == null) ? "" : m.get("sortField"));
m.set("dir",
(m.get("sortDir") == null || (m.get("sortDir") != null && m.<SortDir> get("sortDir").equals(SortDir.NONE)))
? "" : m.get("sortDir"));


}
});
loader.setSortDir(SortDir.DESC);
loader.setSortField("lastpost");


loader.setRemoteSort(true);


ListStore<ModelData> store = new ListStore<ModelData>(loader);


List<ColumnConfig> columns = new ArrayList<ColumnConfig>();


ColumnConfig title = new ColumnConfig("title", "Topic", 100);
title.setRenderer(new GridCellRenderer<ModelData>() {


public Object render(ModelData model, String property, ColumnData config, int rowIndex, int colIndex,
ListStore<ModelData> store, Grid<ModelData> grid) {
return "<b><a style=\"color: #385F95; text-decoration: none;\" href=\"http://extjs.com/forum/showthread.php?t="
+ model.get("threadid")
+ "\" target=\"_blank\">"
+ model.get("title")
+ "</a></b><br /><a style=\"color: #385F95; text-decoration: none;\" href=\"http://extjs.com/forum/forumdisplay.php?f="
+ model.get("forumid") + "\" target=\"_blank\">" + model.get("forumtitle") + " Forum</a>";
}


});
columns.add(title);
columns.add(new ColumnConfig("replycount", "Replies", 50));


ColumnConfig last = new ColumnConfig("lastpost", "Last Post", 200);
last.setRenderer(new GridCellRenderer<ModelData>() {


public Object render(ModelData model, String property, ColumnData config, int rowIndex, int colIndex,
ListStore<ModelData> store, Grid<ModelData> grid) {
return model.get("lastpost") + "<br/>by " + model.get("lastposter");
}


});
columns.add(last);


ColumnModel cm = new ColumnModel(columns);


final Grid<ModelData> grid = new Grid<ModelData>(store, cm);
grid.setBorders(true);
grid.setAutoExpandColumn("title");
grid.setLoadMask(true);
grid.setStripeRows(true);


LiveGridView liveView = new LiveGridView();
liveView.setEmptyText("No rows available on the server.");
liveView.setRowHeight(32);
grid.setView(liveView);


ContentPanel panel = new ContentPanel();
panel.setFrame(true);
panel.setCollapsible(true);
panel.setAnimCollapse(false);
panel.setHeading("LiveGrid Grid");
panel.setLayout(new FitLayout());
panel.add(grid);
panel.setSize(600, 350);
grid.getAriaSupport().setLabelledBy(panel.getHeader().getId() + "-label");


ToolBar toolBar = new ToolBar();
toolBar.add(new FillToolItem());


LiveToolItem item = new LiveToolItem();
item.bindGrid(grid);


toolBar.add(item);
panel.setBottomComponent(toolBar);


add(panel);


new GridDragSource(grid);






ContentPanel cp = new ContentPanel(new FitLayout());
cp.setSize(600, 300);
// List<ColumnConfig> cols = new ArrayList<ColumnConfig>();


Grid<ModelData> dropGrid = new Grid<ModelData>(new ListStore<ModelData>(), new ColumnModel(columns));
new GridDropTarget(dropGrid);


cp.add(dropGrid);
add(cp);
}
}

DamionS
15 Nov 2011, 8:51 AM
Thanks for your help

I have realised that the grid was originally implemented with a live view as it would require paging. My spec has changed and the paging is no longer required.

I have therefore changed the live view and PagingLoadResult to a grid view and ListLoadResult. Everything now works properly.

Thanks for you time.

Damion