GWT FlexTable - 拖动选择如何?

时间:2010-02-10 08:05:37

标签: gwt

我试图在flextable的列中选择多个单元格来获得适当的方法。

到目前为止,我只是设法用点击效果很好,但拖动选择会好得多。我一直在阅读文档和搜索,但我找到的所有东西都是基于弃用的代码。我使用GWT 2.0。

我知道我需要一些在拖动选择鼠标手势发生时运行的事件处理程序,并且该处理程序需要知道选择开始的单元格索引,当然还有选择结束的单元格索引。

任何建议||代码将非常感激。

1 个答案:

答案 0 :(得分:1)

这需要改进,但它应该给你基本的想法。首先,您需要创建一个侦听MouseEvents的CustomTable。你可以通过扩展复合来包装一个focuspanel和一个flextable来实现这个目的:

public class CustomTable extends Composite implements MouseDownHandler, MouseMoveHandler, MouseUpHandler{

List<CellWidget> widgets = new ArrayList<CellWidget>();
FlexTable table = new FlexTable();
FocusPanel focusPanel = new FocusPanel();
boolean selecting= false;
Point selectStart,selectEnd;    

public CustomTable(){
    focusPanel.setWidget(table);
    focusPanel.addMouseDownHandler(this);
    focusPanel.addMouseMoveHandler(this);
    focusPanel.addMouseUpHandler(this);

    initWidget(focusPanel);
}

public void setWidget(int row, int column, CellWidget widget){
    widgets.add(widget);
    table.setWidget(row, column, widget);
}

@Override
public void onMouseUp(MouseUpEvent event) {
    event.preventDefault();
    if (selecting){
        selecting=false;
        DOM.releaseCapture(this.getElement());
        selectEnd = new Point(event.getClientX(),event.getClientY());

        for (CellWidget widget : widgets){
            if (widget.isIn(selectStart,selectEnd))
                widget.say();               
        }
        selectStart = selectEnd = null;         
    }       
}

@Override
public void onMouseMove(MouseMoveEvent event) {
    event.preventDefault();
    if (selecting){
        //do some fancy layout
    }       
}

@Override
public void onMouseDown(MouseDownEvent event) {
    event.preventDefault();
    selecting = true;
    DOM.setCapture(this.getElement());  
    selectStart = new Point(event.getClientX(),event.getClientY());
}   
}

接下来,您定义一个CellWidget,它基本上封装了您要添加到单元格的内容。当添加到DOM时,CellWidget会稍后计算并存储其位置,以确定它是否在所选区域中:

public class CellWidget extends Composite{

Widget content;
Point topLeft,topRight,bottomLeft,bottomRight;

public CellWidget(Widget w){
    this.content = w;
    initWidget(w);
}

@Override
protected void onLoad() {
    topLeft = new Point(getAbsoluteLeft(),getAbsoluteTop());
    topRight = new Point(getAbsoluteLeft()+getOffsetWidth(),getAbsoluteTop());
    bottomLeft = new Point(getAbsoluteLeft(),getAbsoluteTop()+getOffsetHeight());
    bottomRight = new Point(getAbsoluteLeft()+getOffsetWidth(),getAbsoluteTop()+getOffsetHeight());
}

public void say(){
    Window.alert(content + " is selected!");
}

public boolean isIn(Point start, Point end){
    if (topLeft.isBetween(start, end) || topRight.isBetween(start, end)
            || bottomLeft.isBetween(start, end) || bottomRight.isBetween(start, end))
        return true;
    else
        return false;           
}
}

简化实施以简化操作:

public class Point {

int x,y;

public Point(int x,int y){
    this.x=x;
    this.y=y;
}   
public int getX() {
    return x;
}
public int getY() {
    return y;
}
@Override
public String toString() {
    return x+","+y;
}
public boolean isBetween(Point p1,Point p2){
    if (p1.getX() < x && p2.getX() > x && p1.getY() < y && p2.getY() > y)
        return true;
    return false;
}
}

最后在您的EntryPoint模块中,您可以通过以下方式进行整理:

public void onModuleLoad() {
    RootPanel rootPanel = RootPanel.get();
    CustomTable table = new CustomTable();
    table.setWidget(0, 0, new CellWidget(new Label("hello 0,0")));
    table.setWidget(0, 1, new CellWidget(new Label("hello 0,1")));
    table.setWidget(1, 0, new CellWidget(new Label("hello 1,0")));
    table.setWidget(1, 1, new CellWidget(new Label("hello 1,1")));
    rootPanel.add(table);
}

我知道确定小部件是否属于所选区域的实际逻辑是不完整的,需要改进,但我认为这个解决方案足够清晰,可以提供基本的想法。干杯