fi.jasoft.dragdroplayouts.DDGridLayout.java Source code

Java tutorial

Introduction

Here is the source code for fi.jasoft.dragdroplayouts.DDGridLayout.java

Source

/*
 * Copyright 2015 John Ahlroos
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */
package fi.jasoft.dragdroplayouts;

import java.util.Map;

import com.vaadin.event.Transferable;
import com.vaadin.event.dd.DropHandler;
import com.vaadin.event.dd.DropTarget;
import com.vaadin.event.dd.TargetDetails;
import com.vaadin.event.dd.TargetDetailsImpl;
import com.vaadin.server.PaintException;
import com.vaadin.server.PaintTarget;
import com.vaadin.shared.MouseEventDetails;
import com.vaadin.shared.ui.dd.HorizontalDropLocation;
import com.vaadin.shared.ui.dd.VerticalDropLocation;
import com.vaadin.ui.Component;
import com.vaadin.ui.GridLayout;
import com.vaadin.ui.LegacyComponent;

import fi.jasoft.dragdroplayouts.client.ui.Constants;
import fi.jasoft.dragdroplayouts.client.ui.LayoutDragMode;
import fi.jasoft.dragdroplayouts.client.ui.gridlayout.DDGridLayoutState;
import fi.jasoft.dragdroplayouts.events.LayoutBoundTransferable;
import fi.jasoft.dragdroplayouts.interfaces.DragFilter;
import fi.jasoft.dragdroplayouts.interfaces.DragFilterSupport;
import fi.jasoft.dragdroplayouts.interfaces.DragImageProvider;
import fi.jasoft.dragdroplayouts.interfaces.DragImageReferenceSupport;
import fi.jasoft.dragdroplayouts.interfaces.LayoutDragSource;
import fi.jasoft.dragdroplayouts.interfaces.ShimSupport;

/**
 * Grid layout with drag and drop support
 * 
 * @author John Ahlroos / www.jasoft.fi
 * @since 0.4.0
 */
@SuppressWarnings("serial")
public class DDGridLayout extends GridLayout implements LayoutDragSource, DropTarget, ShimSupport, LegacyComponent,
        DragFilterSupport, DragImageReferenceSupport {

    private DropHandler dropHandler;

    // A filter for dragging components.
    private DragFilter dragFilter = DragFilter.ALL;

    private DragImageProvider dragImageProvider;

    /**
     * Target details for a drop event
     */
    public class GridLayoutTargetDetails extends TargetDetailsImpl {

        private Component over;

        private int row = -1;

        private int column = -1;

        protected GridLayoutTargetDetails(Map<String, Object> rawDropData) {
            super(rawDropData, DDGridLayout.this);

            if (getData(Constants.DROP_DETAIL_ROW) != null) {
                row = Integer.valueOf(getData(Constants.DROP_DETAIL_ROW).toString());
            } else {
                row = -1;
            }

            if (getData(Constants.DROP_DETAIL_COLUMN) != null) {
                column = Integer.valueOf(getData(Constants.DROP_DETAIL_COLUMN).toString());
            } else {
                column = -1;
            }

            if (row != -1 && column != -1) {
                over = getComponent(column, row);
            }

            if (over == null) {
                over = DDGridLayout.this;
            }
        }

        /**
         * Returns the component over which the dragged component was dropped.
         * Returns NULL if no component was under the dragged component
         * 
         * @return
         */
        public Component getOverComponent() {
            return over;
        }

        /**
         * Over which row was the component dropped
         * 
         * @return The index of the row over which the component was dropped
         */
        public int getOverRow() {
            return row;
        }

        /**
         * Over which column was the component dropped
         * 
         * @return The index of the column over which the component was dropped
         */
        public int getOverColumn() {
            return column;
        }

        /**
         * Returns the horizontal location within the cell the component was
         * dropped
         * 
         * @return
         */
        public HorizontalDropLocation getHorizontalDropLocation() {
            return HorizontalDropLocation
                    .valueOf(getData(Constants.DROP_DETAIL_HORIZONTAL_DROP_LOCATION).toString());
        }

        /**
         * Returns the vertical location within the cell the component was
         * dropped
         * 
         * @return
         */
        public VerticalDropLocation getVerticalDropLocation() {
            return VerticalDropLocation.valueOf(getData(Constants.DROP_DETAIL_VERTICAL_DROP_LOCATION).toString());
        }

        /**
         * Was the dropped component dropped in an empty cell
         * 
         * @return
         */
        public boolean overEmptyCell() {
            return Boolean.valueOf(getData(Constants.DROP_DETAIL_EMPTY_CELL).toString());
        }

        /**
         * Some details about the mouse event
         * 
         * @return details about the actual event that caused the event details.
         *         Practically mouse move or mouse up.
         */
        public MouseEventDetails getMouseEvent() {
            return MouseEventDetails.deSerialize(getData(Constants.DROP_DETAIL_MOUSE_EVENT).toString());
        }
    }

    /**
     * Contains the transferable details when dragging from a GridLayout.
     */
    public class GridLayoutTransferable extends LayoutBoundTransferable {

        /**
         * Constructor
         * 
         * @param sourceComponent
         *            The source layout from where the component was dragged
         * @param rawVariables
         *            The drag details
         */
        public GridLayoutTransferable(Component sourceComponent, Map<String, Object> rawVariables) {
            super(sourceComponent, rawVariables);
        }

        /**
         * The row from where the component was dragged
         * 
         * @return The row index
         */
        public int getSourceRow() {
            return Integer.valueOf(getData(Constants.DROP_DETAIL_ROW).toString());
        }

        /**
         * The column from where the component was dragged
         * 
         * @return The column index
         */
        public int getSourceColumn() {
            return Integer.valueOf(getData(Constants.DROP_DETAIL_COLUMN).toString());
        }
    }

    /**
     * Constructor for grid of given size (number of cells). Note that grid's
     * final size depends on the items that are added into the grid. Grid grows
     * if you add components outside the grid's area.
     * 
     * @param columns
     *            Number of columns in the grid.
     * @param rows
     *            Number of rows in the grid.
     */
    public DDGridLayout(int columns, int rows) {
        super(columns, rows);
    }

    /**
     * Constructor for grid of given size (number of cells). Note that grid's
     * final size depends on the items that are added into the grid. Grid grows
     * if you add components outside the grid's area.
     * 
     * @param columns
     *            Number of columns in the grid.
     * @param rows
     *            Number of rows in the grid.
     * @param children
     *            Child components
     */
    public DDGridLayout(int columns, int rows, Component... children) {
        super(columns, rows, children);
    }

    /**
     * Constructs an empty grid layout that is extended as needed.
     */
    public DDGridLayout() {
        super();
    }

    @Override
    public void paintContent(PaintTarget target) throws PaintException {
        if (dropHandler != null && isEnabled()) {
            dropHandler.getAcceptCriterion().paint(target);
        }
    }

    @Override
    public void changeVariables(Object source, Map<String, Object> variables) {
        // To be compatible with Designer drag & drop
    }

    /**
     * {@inheritDoc}
     */
    public DropHandler getDropHandler() {
        return dropHandler;
    }

    /**
     * {@inheritDoc}
     */
    public void setDropHandler(DropHandler dropHandler) {
        DDUtil.verifyHandlerType(this, dropHandler);
        if (dropHandler != this.dropHandler) {
            this.dropHandler = dropHandler;
            markAsDirty();
        }
    }

    /**
     * {@inheritDoc}
     */
    public LayoutDragMode getDragMode() {
        return getState().ddState.dragMode;
    }

    /**
     * {@inheritDoc}
     */
    public void setDragMode(LayoutDragMode mode) {
        getState().ddState.dragMode = mode;
    }

    /**
     * {@inheritDoc}
     */
    public TargetDetails translateDropTargetDetails(Map<String, Object> clientVariables) {
        return new GridLayoutTargetDetails(clientVariables);
    }

    /**
     * {@inheritDoc}
     */
    public Transferable getTransferable(Map<String, Object> rawVariables) {
        return new GridLayoutTransferable(this, rawVariables);
    }

    /**
     * Sets the ratio which determines how a cell is divided into drop zones.
     * The ratio is measured from the left and right borders. For example,
     * setting the ratio to 0.3 will divide the drop zone in three equal parts
     * (left,middle,right). Setting the ratio to 0.5 will disable dropping in
     * the middle and setting it to 0 will disable dropping at the sides.
     * 
     * @param ratio
     *            A ratio between 0 and 0.5. Default is 0.2
     */
    public void setComponentHorizontalDropRatio(float ratio) {
        if (ratio != getState().cellLeftRightDropRatio) {
            if (ratio >= 0 && ratio <= 0.5) {
                getState().cellLeftRightDropRatio = ratio;
            } else {
                throw new IllegalArgumentException("Ratio must be between 0 and 0.5");
            }
        }
    }

    /**
     * Sets the ratio which determines how a cell is divided into drop zones.
     * The ratio is measured from the top and bottom borders. For example,
     * setting the ratio to 0.3 will divide the drop zone in three equal parts
     * (top,center,bottom). Setting the ratio to 0.5 will disable dropping in
     * the center and setting it to 0 will disable dropping at the sides.
     * 
     * @param ratio
     *            A ratio between 0 and 0.5. Default is 0.2
     */
    public void setComponentVerticalDropRatio(float ratio) {
        if (ratio != getState().cellTopBottomDropRatio) {
            if (ratio >= 0 && ratio <= 0.5) {
                getState().cellTopBottomDropRatio = ratio;
            } else {
                throw new IllegalArgumentException("Ratio must be between 0 and 0.5");
            }
        }
    }

    /**
     * {@inheritDoc}
     */
    public void setShim(boolean shim) {
        getState().ddState.iframeShims = shim;
    }

    /**
     * {@inheritDoc}
     */
    public boolean isShimmed() {
        return getState().ddState.iframeShims;
    }

    /**
     * {@inheritDoc}
     */
    public DragFilter getDragFilter() {
        return dragFilter;
    }

    /**
     * {@inheritDoc}
     */
    public void setDragFilter(DragFilter dragFilter) {
        this.dragFilter = dragFilter;
    }

    @Override
    public DDGridLayoutState getState() {
        return (DDGridLayoutState) super.getState();
    }

    @Override
    public void beforeClientResponse(boolean initial) {
        super.beforeClientResponse(initial);
        DDUtil.onBeforeClientResponse(this, getState());
    }

    @Override
    public void setDragImageProvider(DragImageProvider provider) {
        this.dragImageProvider = provider;
        markAsDirty();
    }

    @Override
    public DragImageProvider getDragImageProvider() {
        return this.dragImageProvider;
    }

}