在GWT 2.5中拖放FlexTable

时间:2012-12-28 11:00:30

标签: gwt

我正在尝试使用本机GWT拖动事件进行简单的拖放FlexTable,以允许用户移动行。

//This works fine
galleryList.getElement().setDraggable(Element.DRAGGABLE_TRUE);
galleryList.addDragStartHandler(new DragStartHandler() {
     @Override
     public void onDragStart(DragStartEvent event) {
         event.setData("text", "Hello World");
         groupList.getElement().getStyle().setBackgroundColor("#aff");
     }
});

但是,我想: 1.给出物品掉落的可视指示器。 2.当drop事件触发时,找出我应该放弃行的位置。

galleryList.addDragOverHandler(new DragOverHandler() {
    @Override
    public void onDragOver(DragOverEvent event) {
       //TODO: How do i get the current location one would drop an item into a flextable here
    }
});

galleryList.addDragEndHandler(new DragEndHandler() {
    @Override
    public void onDragEnd(DragEndEvent event) {
       //TODO: How do i know where i am in the flextable 
    }
});

我看到这些FlexTable方法在获取单元格/行时非常有用:

public Cell getCellForEvent(ClickEvent event)
protected Element getEventTargetCell(Event event)

但问题是Drag事件没有继承Event

提前致谢

2 个答案:

答案 0 :(得分:1)

警告:我不能保证这将会解决问题。这是我最终制作的代码(并且适用于我) - 它是一个继承自FlexTable的Drag n Drop Widget。我检测到表上的任何拖动事件,然后尝试计算鼠标在FlexTable上的位置。

import com.google.gwt.dom.client.TableRowElement;
import com.google.gwt.event.dom.client.*;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.Widget;

public class DragFlexTable extends FlexTable implements DraggableWidget {

public String dragStyle = "drag-table-row";
public String dragReplaceStyle;

protected DragVerticalHandler dragFlexTableHandler;

private int currentRow;
private int[] yLocations;
private int rowBeingDragged;

DragFlexTable() {
    sinkEvents(Event.ONMOUSEOVER | Event.ONMOUSEOUT);
    getElement().setDraggable(Element.DRAGGABLE_TRUE);
    final DragUtil dragUtil = new DragUtil();

    addDragStartHandler(new DragStartHandler() {
        @Override
        public void onDragStart(DragStartEvent event) {
            dragUtil.startVerticalDrag(event, DragFlexTable.this);
        }
    });

    addDragEndHandler(new DragEndHandler() {
        @Override
        public void onDragEnd(DragEndEvent event) {
            dragUtil.endVerticalDrag(event, DragFlexTable.this);
        }
    });


    addDragOverHandler(new DragOverHandler() {

        @Override
        public void onDragOver(DragOverEvent event) {
            dragUtil.handleVerticalDragOver(event, DragFlexTable.this, 3);
        }
    });

}

@Override
public void onBrowserEvent(Event event) {
    super.onBrowserEvent(event);
    Element td = getEventTargetCell(event);

    if (td == null) return;
    Element tr = DOM.getParent(td);

    currentRow = TableRowElement.as(td.getParentElement()).getSectionRowIndex();


    switch (DOM.eventGetType(event)) {
        case Event.ONMOUSEOVER: {
            //tr.addClassName(ROW_STYLE_NAME + "-mouseover");
            tr.addClassName(dragStyle);
            break;
        }
        case Event.ONMOUSEOUT: {
            tr.removeClassName(dragStyle);
            break;
        }
    }
}

public void setDragStyle(String dragStyle) {
    this.dragStyle = dragStyle;
}

@Override
public void resetDragState() {
    yLocations = null;
}

@Override
public void setRowBeingDragged(int currentRow) {
    this.rowBeingDragged = currentRow;
}

@Override
public int getDragRow(DragDropEventBase event) {
    if (yLocations == null) {
        yLocations = new int[getRowCount()];
        for (int i = 0; i < getRowCount(); i++) {
            Widget widget = getWidget(i, 0);
            if (widget.isVisible()) {
                com.google.gwt.dom.client.Element imgTd = widget.getElement().getParentElement();
                int absoluteBottom = imgTd.getAbsoluteBottom();
                yLocations[i] = absoluteBottom;
            } else {
                yLocations[i] = -1;
            }
        }
    }

    int lastY = 0;
    for (int i = 0; i < yLocations.length; i++) {
        int absoluteBottom = yLocations[i];
        //invisible
        if (absoluteBottom != -1) {
            int absoluteTop = lastY;
            int clientY = event.getNativeEvent().getClientY();
            if (absoluteBottom > clientY && absoluteTop < clientY) {
                //com.google.gwt.dom.client.Element tr = imgTd.getParentElement();
                return i;
            }
            lastY = absoluteBottom;
        }
    }
    return currentRow;
}


@Override
public com.google.gwt.dom.client.Element getTrElement(int row) {
    return getWidget(row, 0).getElement().getParentElement().getParentElement();
}

@Override
public DragVerticalHandler getDragFlexTableHandler() {
    return dragFlexTableHandler;
}

public void setDragReplaceStyle(String dragReplaceStyle) {
    this.dragReplaceStyle = dragReplaceStyle;
}

@Override
public int getRowBeingDragged() {
    return rowBeingDragged;
}

@Override
public String getDragReplaceStyle() {
    return dragReplaceStyle;
}

public void setDragFlexTableHandler(DragVerticalHandler dragFlexTableHandler) {
    this.dragFlexTableHandler = dragFlexTableHandler;
}

}

这是它使用的util类

import com.google.gwt.event.dom.client.DragEndEvent;
import com.google.gwt.event.dom.client.DragOverEvent;
import com.google.gwt.event.dom.client.DragStartEvent;
import com.google.gwt.user.client.ui.Image;

public class DragUtil {
private int alternateIgnoreEvent = 0;
private int lastDragRow = -1;

public void startVerticalDrag(DragStartEvent event, DraggableWidget widget) {
    widget.resetDragState();
    //Required
    event.setData("text", "dragging");
    int currentRow = widget.getDragRow(event);
    widget.setRowBeingDragged(currentRow);

    if (widget.getDragFlexTableHandler()!=null) {
        Image thumbnailImg = widget.getDragFlexTableHandler().getImage(currentRow);
        if (thumbnailImg!=null) {
            event.getDataTransfer().setDragImage(thumbnailImg.getElement(), -10, -10);
        }
    }
}

public void handleVerticalDragOver(DragOverEvent event, DraggableWidget widgets, int sensitivity) {
    if (alternateIgnoreEvent++ % sensitivity != 0) {
        //many events fire, for every pixel move, which slow the browser, so ill ignore some
        return;
    }
    int dragRow = widgets.getDragRow(event);
    if (dragRow != lastDragRow) {
        com.google.gwt.dom.client.Element dragOverTr = widgets.getTrElement(dragRow);
        if (lastDragRow != -1) {
            com.google.gwt.dom.client.Element lastTr = widgets.getTrElement(lastDragRow);
            lastTr.removeClassName(widgets.getDragReplaceStyle());
        }
        lastDragRow = dragRow;
        dragOverTr.addClassName(widgets.getDragReplaceStyle());
    }
}

public void endVerticalDrag(DragEndEvent event, DraggableWidget widgets) {
    int newRowPosition = widgets.getDragRow(event);
    //cleanup last position
    if (newRowPosition != lastDragRow) {
        com.google.gwt.dom.client.Element lastTr = widgets.getTrElement(lastDragRow);
        lastTr.removeClassName(widgets.getDragReplaceStyle());
    }
    if (newRowPosition != widgets.getRowBeingDragged()) {
        com.google.gwt.dom.client.Element dragOverTr = widgets.getTrElement(newRowPosition);
        dragOverTr.removeClassName(widgets.getDragReplaceStyle());
        widgets.getDragFlexTableHandler().moveRow(widgets.getRowBeingDragged(), newRowPosition);
    }
}
}

在uibinder中我然后使用它:

   <adminDnd:DragFlexTable ui:field='itemFlexTable' styleName='{style.table}' cellSpacing='0'
                                                            cellPadding='0'
                                                            dragStyle='{style.drag-table-row-mouseover}'
                                                            dragReplaceStyle='{style.drag-replace-table-row}'
                                        />

答案 1 :(得分:1)

即使我遇到了这个问题,经过一些原型设计,这也是我最终的结果 。我创建了一个扩展flex表的类。这是代码

public class DragFlexTable extends FlexTable implements
            MouseDownHandler,MouseUpHandler,MouseMoveHandler,
            MouseOutHandler
{
    private int row,column,draggedrow,draggedcolumn;
    private Element td;
    private Widget w;
    private boolean emptycellclicked;
    DragFlexTable()
    {
        sinkEvents(Event.ONMOUSEOVER | Event.ONMOUSEOUT | Event.ONMOUSEDOWN | Event.ONMOUSEMOVE);
        this.addMouseDownHandler(this);
        this.addMouseMoveHandler(this);
        this.addMouseUpHandler(this);
        this.addMouseOutHandler(this);
    }
    @Override
    public void onBrowserEvent(Event event)
    {
        super.onBrowserEvent(event);
        td = getEventTargetCell(event);
        if (td == null)
        {
            return;
        }
        Element tr = DOM.getParent((com.google.gwt.user.client.Element) td);
        Element body = DOM.getParent((com.google.gwt.user.client.Element) tr);
        row = DOM.getChildIndex((com.google.gwt.user.client.Element) body, (com.google.gwt.user.client.Element) tr);//(body, tr);
        column = DOM.getChildIndex((com.google.gwt.user.client.Element) tr, (com.google.gwt.user.client.Element) td);
    }
    boolean mousedown;
    @Override
    public void onMouseDown(MouseDownEvent event)
    {
        if (event.getNativeButton() == NativeEvent.BUTTON_LEFT)
        {
            //to ensure empty cell is not clciked
            if (!td.hasChildNodes())
            {
                emptycellclicked = true;
            }
            event.preventDefault();
            start(event);
            mousedown = true;
        }
    }
    @Override
    public void onMouseMove(MouseMoveEvent event)
    {
        if (mousedown)
        {
            drag(event);
        }
    }
    @Override
    public void onMouseUp(MouseUpEvent event)
    {
        if (event.getNativeButton() == NativeEvent.BUTTON_LEFT)
        {
            if (!emptycellclicked)
            {
                end(event);
            }
            emptycellclicked = false;
            mousedown = false;
        }
    }
    @Override
    public void onMouseOut(MouseOutEvent event)
    {
        this.getCellFormatter().getElement(row, column).getStyle().clearBorderStyle();
        this.getCellFormatter().getElement(row, column).getStyle().clearBorderColor();
        this.getCellFormatter().getElement(row, column).getStyle().clearBorderWidth();
        w.getElement().getStyle().setOpacity(1);
        mousedown = false;
    }
    private void start(MouseDownEvent event)
    {
        w = this.getWidget(row, column);
        w.getElement().getStyle().setOpacity(0.5);
    }
    private void drag(MouseMoveEvent event)
    {
        if (draggedrow != row || draggedcolumn != column)
        {
            this.getCellFormatter().getElement(draggedrow, draggedcolumn).getStyle().clearBorderStyle();
            this.getCellFormatter().getElement(draggedrow, draggedcolumn).getStyle().clearBorderColor();
            this.getCellFormatter().getElement(draggedrow, draggedcolumn).getStyle().clearBorderWidth();
            this.draggedrow = row;
            this.draggedcolumn = column;
            this.getCellFormatter().getElement(row, column).getStyle().setBorderStyle(BorderStyle.DASHED);
            this.getCellFormatter().getElement(row, column).getStyle().setBorderColor("black");
            this.getCellFormatter().getElement(row, column).getStyle().setBorderWidth(2, Unit.PX);
        }
    }
    private void end(MouseUpEvent event)
    {
        insertDraggedWidget(row, column);
    }
    private void insertDraggedWidget(int r,int c)
    {
        this.getCellFormatter().getElement(r, c).getStyle().clearBorderStyle();
        this.getCellFormatter().getElement(r, c).getStyle().clearBorderColor();
        this.getCellFormatter().getElement(r, c).getStyle().clearBorderWidth();
        w.getElement().getStyle().setOpacity(1);
        if (this.getWidget(r, c) != null)
        {
            //pushing down the widgets already in the column 
            //          int widgetheight = (this.getWidget(r, c).getOffsetHeight() / 2) + this.getWidget(r, c).getAbsoluteTop();
            //          int rw;
            //placing the widget above the dropped widget
            for (int i = this.getRowCount() - 1; i >= r; i--)
            {
                if (this.isCellPresent(i, c))
                {
                    this.setWidget(i + 1, c, this.getWidget(i, c));
                }
            }
        }
        this.setWidget(r, c, w);
        //removes unneccesary blank rows 
        cleanupRows();
        //pushing up the column in the stack
        //      for (int i = oldrow;i<this.getRowCount()-1 ;i++)
        //      {
        //          
        //              this.setWidget(i ,oldcolumn, this.getWidget(i+1, oldcolumn));
        //          
        //      }
    }
    private void cleanupRows()
    {
        ArrayList<Integer> rowsfilled = new ArrayList<Integer>();
        for (int i = 0; i <= this.getRowCount() - 1; i++)
        {
            for (int j = 0; j <= this.getCellCount(i) - 1; j++)
            {
                if (this.getWidget(i, j) != null)
                {
                    rowsfilled.add(i);
                    break;
                }
            }
        }
        //replace the empty rows
        for (int i = 0; i < rowsfilled.size(); i++)
        {
            int currentFilledRow = rowsfilled.get(i);
            if (i != currentFilledRow)
            {
                for (int j = 0; j < this.getCellCount(currentFilledRow); j++)
                {
                    this.setWidget(i, j, this.getWidget(currentFilledRow, j));
                }
            }
        }
        for (int i = rowsfilled.size(); i < this.getRowCount(); i++)
        {
            this.removeRow(i);
        }
    }
    public HandlerRegistration addMouseUpHandler(MouseUpHandler handler)
    {
        return addDomHandler(handler, MouseUpEvent.getType());
    }
    public HandlerRegistration addMouseDownHandler(MouseDownHandler handler)
    {
        return addDomHandler(handler, MouseDownEvent.getType());
    }
    public HandlerRegistration addMouseMoveHandler(MouseMoveHandler handler)
    {
        return addDomHandler(handler, MouseMoveEvent.getType());
    }
    public HandlerRegistration addMouseOutHandler(MouseOutHandler handler)
    {
        return addDomHandler(handler, MouseOutEvent.getType());
    }
}

以上自定义窗口小部件的on模块加载

public void onModuleLoad()
    {
        Label a = new Label("asad");
        Label b = new Label("ad");
        Label c = new Label("qwad");
        Label w = new Label("zxd");
        a.setPixelSize(200, 200);
        a.getElement().getStyle().setBorderStyle(BorderStyle.SOLID);
        a.getElement().getStyle().setBorderWidth(1, Unit.PX);
        b.setPixelSize(200, 200);
        c.setPixelSize(200, 200);
        w.setPixelSize(200, 200);
        a.getElement().getStyle().setBackgroundColor("red");
        b.getElement().getStyle().setBackgroundColor("yellowgreen");
        c.getElement().getStyle().setBackgroundColor("lightblue");
        w.getElement().getStyle().setBackgroundColor("grey");
        DragFlexTable d = new DragFlexTable();
        d.setWidget(0, 0, a);
        d.setWidget(0, 1, b);
        d.setWidget(1, 0, c);
        d.setWidget(1, 1, w);
        d.setCellPadding(20);
        RootPanel.get().add(d);
    }