/******************************************************************************* * Copyright (c) 2013 Dirk Fauth and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Dirk Fauth <dirk.fauth@gmail.com> - initial API and implementation *******************************************************************************/ package org.eclipse.nebula.widgets.nattable.hover; import org.eclipse.nebula.widgets.nattable.hover.command.ClearHoverStylingCommandHandler; import org.eclipse.nebula.widgets.nattable.hover.command.HoverStylingCommandHandler; import org.eclipse.nebula.widgets.nattable.hover.config.BodyHoverStylingBindings; import org.eclipse.nebula.widgets.nattable.layer.AbstractIndexLayerTransform; import org.eclipse.nebula.widgets.nattable.layer.IUniqueIndexLayer; import org.eclipse.nebula.widgets.nattable.layer.event.CellVisualUpdateEvent; import org.eclipse.nebula.widgets.nattable.style.DisplayMode; import org.eclipse.swt.graphics.Point; /** * This layer simply adds the possibility to render cells differently if the * mouse cursor is moved over them. This is also called "hover styling". * <p> * It knows over which cell the mouse cursor is currently set as it is informed * about that via IMouseActions that react on mouse move events. * <p> * The place where this layer is added to the layer stack has impact on the * result. If you for example add the SelectionLayer on top of the HoverLayer, * selected cells will not change their style while moving the mouse cursor over * them. Adding the HoverLayer on top of the SelectionLayer will also change the * style of the selected cells. * <p> * Note: If the HoverLayer should be added to the row or column header region, * the corresponding configurations need to be set instead of the default * configuration. This is because the row and column headers by default have * mouse move listeners registered that collide with the mouse move listener for * managing hover behaviour. * * @author Dirk Fauth * */ public class HoverLayer extends AbstractIndexLayerTransform { /** * The position of the cell over which the mouse cursor is currently * located. */ private Point currentHoveredCellPosition; /** * Create a new HoverLayer that uses the default configuration. * * @param underlyingLayer * The layer on which the HoverLayer should be positioned. */ public HoverLayer(IUniqueIndexLayer underlyingLayer) { this(underlyingLayer, true); } /** * @param underlyingLayer * The layer on which the HoverLayer should be positioned. * @param useDefaultConfiguration * <code>true</code> if the default configuration should be used, * <code>false</code> if a different configuration will be set * after creation time. */ public HoverLayer(IUniqueIndexLayer underlyingLayer, boolean useDefaultConfiguration) { super(underlyingLayer); if (useDefaultConfiguration) addConfiguration(new BodyHoverStylingBindings(this)); registerCommandHandler(new HoverStylingCommandHandler(this)); registerCommandHandler(new ClearHoverStylingCommandHandler(this)); } @Override public String getDisplayModeByPosition(int columnPosition, int rowPosition) { if (isCellPositionHovered(columnPosition, rowPosition)) { return DisplayMode.HOVER; } else { return super.getDisplayModeByPosition(columnPosition, rowPosition); } } /** * Check if this HoverLayer knows the current hovered cell and if that cell * is located at the given position coordinates. * * @param cellPosition * The position of the cell that should be checked. * @return <code>true</code> if the mouse cursor is currently located over * the cell at the given position, <code>false</code> if not. */ public boolean isCellPositionHovered(Point cellPosition) { return isCellPositionHovered(cellPosition.x, cellPosition.y); } /** * Check if this HoverLayer knows the current hovered cell and if that cell * is located at the given position coordinates. * * @param columnPosition * The column position of the cell that should be checked. * @param rowPosition * The row position of the cell that should be checked. * @return <code>true</code> if the mouse cursor is currently located over * the cell at the given position, <code>false</code> if not. */ public boolean isCellPositionHovered(int columnPosition, int rowPosition) { return (this.currentHoveredCellPosition != null && this.currentHoveredCellPosition.x == columnPosition && this.currentHoveredCellPosition.y == rowPosition); } /** * @return The position of the cell that is currently hovered. */ public Point getCurrentHoveredCellPosition() { return this.currentHoveredCellPosition; } /** * Set the information about the cell position that is currently hovered and * fire an event to update a possible previous hovered cell to remove the * hover styling and an event to update the newly hovered cell to apply the * hover styling. * * @param columnPosition * The column position of the cell that is currently hovered. * @param rowPosition * The row position of the cell that is currently hovered. */ public void setCurrentHoveredCellPosition(int columnPosition, int rowPosition) { setCurrentHoveredCellPosition(new Point(columnPosition, rowPosition)); } /** * Set the information about the cell position that is currently hovered and * fire an event to update a possible previous hovered cell to remove the * hover styling and an event to update the newly hovered cell to apply the * hover styling. * * @param cellPosition * The position of the cell that is currently hovered. */ public void setCurrentHoveredCellPosition(Point cellPosition) { if (!isCellPositionHovered(cellPosition)) { Point oldHover = this.currentHoveredCellPosition; this.currentHoveredCellPosition = cellPosition; if (oldHover != null) { fireLayerEvent(new CellVisualUpdateEvent(this, oldHover.x, oldHover.y)); } fireLayerEvent(new CellVisualUpdateEvent(this, this.currentHoveredCellPosition.x, this.currentHoveredCellPosition.y)); } } /** * Removes the local stored information about the cell position that is * currently hovered and fires an event to update the cell so the hover * styling is removed. */ public void clearCurrentHoveredCellPosition() { if (this.currentHoveredCellPosition != null) { Point oldHover = this.currentHoveredCellPosition; this.currentHoveredCellPosition = null; fireLayerEvent(new CellVisualUpdateEvent(this, oldHover.x, oldHover.y)); } } }