Vaadin Grid 鼠标中键单击

Vaadin Grid middle mouse click

我正在尝试在我的 vaadin 网格中模拟正常的浏览器行为,其中包括单击鼠标中键以在新选项卡中打开:

addItemClickListener(e -> {
            boolean newTab = e.getMouseEventDetails().getButton() == MouseEventDetails.MouseButton.MIDDLE || e.getMouseEventDetails().isCtrlKey();
            //open in window or new tab
        }); 

但是,vaadin 没有注册鼠标中键。我怎样才能让它发挥作用?

该功能已包含在 vaadin-grid(进入 Vaadin 10)中,在 Vaadin 8 中将无法使用。

对于 Vaadin 8,您可以使用某些客户端扩展来拦截事件,或者使用 ComponentRenderer 为每个组件添加 Panel(可行,但并不理想 because it degrades performance):

grid.addColumn(item->{
    Panel p = new Panel(item.getName());
    p.setStyleName(ValoTheme.PANEL_BORDERLESS);
    p.addClickListener(ev->{
        System.out.println(ev.getButtonName());             
    });
    return p;
}).setRenderer(new ComponentRenderer());

另一方面,客户端扩展允许侦听 javascript 事件(例如 MouseEvent)并触发服务器事件作为响应。创建扩展是一个相当复杂的主题(因为它使用了通常对开发人员隐藏的 API 的一部分)但是它允许直接访问呈现的 DOM,否则这是不可能的。

文档中的以下资源可以为您提供一个起点: Creating a component extension (which describes a simple extension with Java code only) and Integrating JavaScript Components and Extension(解释了如何将本机 JavaScript 代码添加到您的扩展)。

在我的具体案例中我是如何解决问题的:

服务器端:

public class MyGrid<T> extends Grid<T> {
    public MyGrid(String caption, DataProvider<T, ?> dataProvider) {
        super(caption, dataProvider);
        MiddleClickExtension.extend(this);
    }

    public static class MiddleClickExtension<T> extends AbstractGridExtension<T> {
        private MiddleClickExtension(MyGrid<T> grid) {
            super.extend(grid);
            registerRpc((rowKey, columnInternalId, details) -> grid.fireEvent(
                    new ItemClick<>(grid, grid.getColumnByInternalId(columnInternalId), grid.getDataCommunicator().getKeyMapper().get(rowKey), details)),
                    MiddleClickGridExtensionConnector.Rpc.class);
        }

        public static void extend(MyGrid<?> grid) {
            new MiddleClickExtension<>(grid);
        }

        @Override
        public void generateData(Object item, JsonObject jsonObject) {
        }

        @Override
        public void destroyData(Object item) {
        }

        @Override
        public void destroyAllData() {
        }

        @Override
        public void refreshData(Object item) {
        }
    }
}

客户端:

@Connect(MyGrid.MiddleClickExtension.class)
public class MiddleClickGridExtensionConnector extends AbstractExtensionConnector {
    @Override
    protected void extend(ServerConnector target) {
        getParent().getWidget().addDomHandler(event -> {
            if (event.getNativeButton() == NativeEvent.BUTTON_MIDDLE) {
                event.preventDefault();
                CellReference<JsonObject> cell = getParent().getWidget().getEventCell();
                getRpcProxy(Rpc.class).middleClick(cell.getRow().getString(DataCommunicatorConstants.KEY), getParent().getColumnId(cell.getColumn()),
                        MouseEventDetailsBuilder.buildMouseEventDetails(event.getNativeEvent(), event.getRelativeElement()));
            }
        }, MouseDownEvent.getType());
    }

    @Override
    public GridConnector getParent() {
        return (GridConnector) super.getParent();
    }

    public interface Rpc extends ServerRpc {
        void middleClick(String rowKey, String columnInternalId, MouseEventDetails details);
    }
}