开发者

GWT: Select a TreeItem with right click

I'm capturing a right click event to show a context menu. What I haven't been able to figure out, is how to make the right click actually select the TreeItem, prior to showing of context menu.

All help is appreciated.

 private Tree tree = new Tree() {
  @Override
  public void onBrowserEvent(Event event) {   
    if (event.getTypeInt() == Event.ONCONTEXTMENU) {
     DOM.eventPreventDefault(event开发者_C百科);          
     showContextMenu(event);
    }   
   super.onBrowserEvent(event);
  }

  @Override
  protected void setElement(Element elem) {
   super.setElement(elem);
   sinkEvents(Event.ONCONTEXTMENU);
  }

 };


ONMOUSEDOWN event gets fired before ONCONTEXTMENU. Have you tried to listen for onMouseDown events, and set the selected item? Something along these lines:

@Override
public void onBrowserEvent(Event event) {   
switch (DOM.eventGetType(event)) {
    case Event.ONMOUSEDOWN:
        if (DOM.eventGetButton(event) == Event.BUTTON_RIGHT) {
            TreeItem selectedItem = findSelectedItem(event);
            if (selectedItem != null) {
                selectedItem.setSelected(true);
            }
        } else {
            super.onBrowserEvent(event);
        }
        break;
    case Event.ONCONTEXTMENU:
        showContextMenu(event);
        break;
    default:
        super.onBrowserEvent(event);
        break;
    }

and findSelectedItem traverses the tree looking for the selected item:

TreeItem findSelectedItem(Event e) {
    return findSelectedItemRecursive(event.getClientX(), event.getClientY());
}

TreeItem findSelectedTreeItemRecursive(TreeItem root, int x, int y) {
    if (null == root) {
        int count = getItemCount();
        for (int i = 0; i < count; i++) {
            TreeItem selected = findSelectedTreeItemRecursive(getItem(i), x, y);
            if (selected != null) {
               return selected;
            }
        }
        return null;
    }
    int count = item.getChildCount();
    for (int i = 0; i < count; i++) {
        TreeItem selected = findSelectedTreeItem(item.getChild(i), x, y);
        if (selected != null) {
            return selected;
        }
    }

    if (x >= item.getAbsoluteLeft()
        && x <= item.getAbsoluteLeft() + item.getOffsetWidth()
        && y >= item.getAbsoluteTop()
        && y <= item.getAbsoluteTop() + item.getOffsetHeight()) {
        return item;
    }
    return null;
}


You can use dedicated overloaded TreeItem :

public class MyTreeItem extends TreeItem implements ContextMenuHandler {


    public SBTreeItem(SBItemTree tree, String name) {
        super();
        Label w = new Label(name);
        w.addDomHandler(this, ContextMenuEvent.getType());
        setWidget(w);
    }

            public void onContextMenu(ContextMenuEvent event) {
        Window.alert(getSBItem().getName());
        event.getNativeEvent().stopPropagation();

    }

   }


I'd just like to add a couple of links leading to issues about this:

http://code.google.com/p/google-web-toolkit/issues/detail?id=4529&q=right%20click%20selection http://code.google.com/p/google-web-toolkit/issues/detail?id=4604&q=right%20click%20selection


I know this is an old question, but hopefully here's an answer that will save time for the masses hitting this page from a Google search. IMO, the best way is to use Google's own internal tree searching code -- it's a solution that scales very well with the number of elements in the tree. I am using GWT 2.5.1.

private void initTree() {
    tree = new Tree() {

        @Override
        public void onBrowserEvent(Event event) {
            /*
             * If the event is a context menu event, we want the tree item
             * to also be selected.
             * 
             * This logic must occur before the call to the superclass
             * method so the selection is updated before the context menu
             * logic executes. This is useful when we want to make items in
             * the context menu invisible/disabled based on the selection.
             */
            if (DOM.eventGetType(event) == Event.ONCONTEXTMENU) {
                if (getItemCount() > 0) {
                    // In my use case there is only 1 top-level tree item
                    TreeItem root = getItem(0);

                    // Taken from com.google.gwt.user.client.ui.Tree.elementClicked(Element):
                    ArrayList<Element> chain = new ArrayList<Element>();
                    collectElementChain(chain, getElement(), DOM.eventGetTarget(event));

                    TreeItem selection = findItemByChain(chain, 0, root);

                    /*
                     * For some reason SelectionEvent will only fire if
                     * selection is non-null; I am firing the selection
                     * event manually because I want to know when there has
                     * been a deselection of an item in the tree.
                     */
                    if (selection != null) {
                        this.setSelectedItem(selection);
                    } else {
                        SelectionEvent.fire(this, null);
                    }
                }
            }

            super.onBrowserEvent(event);
        }

    };

    tree.setAnimationEnabled(true);
}


//// BEGIN code copied from com.google.gwt.user.client.ui.Tree:

/**
 * Collects parents going up the element tree, terminated at the tree root.
 */
private void collectElementChain(ArrayList<Element> chain, Element hRoot,
        Element hElem) {
    if ((hElem == null) || (hElem == hRoot)) {
        return;
    }

    collectElementChain(chain, hRoot, DOM.getParent(hElem));
    chain.add(hElem);
}

private TreeItem findItemByChain(ArrayList<Element> chain, int idx,
        TreeItem root) {
    if (idx == chain.size()) {
        return root;
    }

    Element hCurElem = chain.get(idx);
    for (int i = 0, n = root.getChildCount(); i < n; ++i) {
        TreeItem child = root.getChild(i);
        if (child.getElement() == hCurElem) {
            TreeItem retItem = findItemByChain(chain, idx + 1,
                    root.getChild(i));
            if (retItem == null) {
                return child;
            }
            return retItem;
        }
    }

    return findItemByChain(chain, idx + 1, root);
}

//// END
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜