All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.vaadin.v7.client.renderers.ClickableRenderer Maven / Gradle / Ivy

There is a newer version: 8.27.3
Show newest version
/*
 * Copyright (C) 2000-2024 Vaadin Ltd
 *
 * This program is available under Vaadin Commercial License and Service Terms.
 *
 * See  for the full
 * license.
 */
package com.vaadin.v7.client.renderers;

import com.google.gwt.dom.client.BrowserEvents;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.EventTarget;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.DomEvent;
import com.google.gwt.event.dom.client.MouseEvent;
import com.google.gwt.event.shared.EventHandler;
import com.google.gwt.event.shared.HandlerManager;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Widget;
import com.google.web.bindery.event.shared.HandlerRegistration;
import com.vaadin.client.WidgetUtil;
import com.vaadin.v7.client.widget.escalator.Cell;
import com.vaadin.v7.client.widget.escalator.RowContainer;
import com.vaadin.v7.client.widget.grid.CellReference;
import com.vaadin.v7.client.widget.grid.EventCellReference;
import com.vaadin.v7.client.widgets.Escalator;
import com.vaadin.v7.client.widgets.Grid;
import com.vaadin.v7.shared.ui.grid.GridConstants.Section;

/**
 * An abstract superclass for renderers that render clickable widgets. Click
 * handlers can be added to a renderer to listen to click events emitted by all
 * widgets rendered by the renderer.
 *
 * @param 
 *            the presentation (column) type
 * @param 
 *            the widget type
 *
 * @since 7.4
 * @author Vaadin Ltd
 */
public abstract class ClickableRenderer
        extends WidgetRenderer implements ClickHandler {

    /**
     * A handler for {@link RendererClickEvent renderer click events}.
     *
     * @param 
     *            the row type of the containing Grid
     *
     * @see ButtonRenderer#addClickHandler(RendererClickHandler)
     */
    public interface RendererClickHandler extends EventHandler {

        /**
         * Called when a rendered button is clicked.
         *
         * @param event
         *            the event representing the click
         */
        void onClick(RendererClickEvent event);
    }

    /**
     * An event fired when a widget rendered by a ClickableWidgetRenderer
     * subclass is clicked.
     *
     * @param 
     *            the row type of the containing Grid
     */
    @SuppressWarnings("rawtypes")
    public static class RendererClickEvent
            extends MouseEvent {

        @SuppressWarnings("unchecked")
        static final Type TYPE = new Type(
                BrowserEvents.CLICK, new RendererClickEvent());

        private CellReference cell;

        private R row;

        private RendererClickEvent() {
        }

        /**
         * Returns the cell of the clicked button.
         *
         * @return the cell
         */
        public CellReference getCell() {
            return cell;
        }

        /**
         * Returns the data object corresponding to the row of the clicked
         * button.
         *
         * @return the row data object
         */
        public R getRow() {
            return row;
        }

        @Override
        public Type getAssociatedType() {
            return TYPE;
        }

        @Override
        @SuppressWarnings("unchecked")
        protected void dispatch(RendererClickHandler handler) {

            EventTarget target = getNativeEvent().getEventTarget();

            if (!Element.is(target)) {
                return;
            }

            Element e = Element.as(target);
            Grid grid = (Grid) findClosestParentGrid(e);

            cell = findCell(grid, e);
            row = cell.getRow();

            handler.onClick(this);
        }

        /**
         * Returns the cell the given element belongs to.
         *
         * @param grid
         *            the grid instance that is queried
         * @param e
         *            a cell element or the descendant of one
         * @return the cell or null if the element is not a grid cell or a
         *         descendant of one
         */
        private static  CellReference findCell(Grid grid, Element e) {
            RowContainer container = getEscalator(grid).findRowContainer(e);
            if (container == null) {
                return null;
            }
            Cell cell = container.getCell(e);
            EventCellReference cellReference = new EventCellReference(
                    grid);
            // FIXME: Section is currently always body. Might be useful for the
            // future to have an actual check.
            cellReference.set(cell, Section.BODY);
            return cellReference;
        }

        private static native Escalator getEscalator(Grid grid)
        /*-{
          return [email protected]::escalator;
        }-*/;

        /**
         * Returns the Grid instance containing the given element, if any.
         * 

* Note: This method may not work reliably if the grid * in question is wrapped in a {@link Composite} unless the * element is inside another widget that is a child of the wrapped grid; * please refer to the note in * {@link WidgetUtil#findWidget(Element, Class) Util.findWidget} for * details. * * @param e * the element whose parent grid to find * @return the parent grid or null if none found. */ private static Grid findClosestParentGrid(Element e) { Widget w = WidgetUtil.findWidget(e, null); while (w != null && !(w instanceof Grid)) { w = w.getParent(); } return (Grid) w; } } private HandlerManager handlerManager; /** * {@inheritDoc} *

* Implementation note: It is the implementing method's * responsibility to add {@code this} as a click handler of the returned * widget, or a widget nested therein, in order to make click events * propagate properly to handlers registered via * {@link #addClickHandler(RendererClickHandler) addClickHandler}. */ @Override public abstract W createWidget(); /** * Adds a click handler to this button renderer. The handler is invoked * every time one of the widgets rendered by this renderer is clicked. *

* Note that the row type of the click handler must match the row type of * the containing Grid. * * @param handler * the click handler to be added */ public HandlerRegistration addClickHandler( RendererClickHandler handler) { if (handlerManager == null) { handlerManager = new HandlerManager(this); } return handlerManager.addHandler(RendererClickEvent.TYPE, handler); } @Override public void onClick(ClickEvent event) { /* * The handler manager is lazily instantiated so it's null iff * addClickHandler is never called. */ if (handlerManager != null) { DomEvent.fireNativeEvent(event.getNativeEvent(), handlerManager); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy