/******************************************************************************* * Copyright (c) 2012, 2017 Original authors 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: * Original authors and others - initial API and implementation ******************************************************************************/ package org.eclipse.nebula.widgets.nattable.reorder.action; import org.eclipse.nebula.widgets.nattable.NatTable; import org.eclipse.nebula.widgets.nattable.layer.ILayer; import org.eclipse.nebula.widgets.nattable.layer.cell.ILayerCell; import org.eclipse.nebula.widgets.nattable.painter.IOverlayPainter; import org.eclipse.nebula.widgets.nattable.reorder.command.ColumnReorderEndCommand; import org.eclipse.nebula.widgets.nattable.reorder.command.ColumnReorderStartCommand; import org.eclipse.nebula.widgets.nattable.selection.command.ClearAllSelectionsCommand; import org.eclipse.nebula.widgets.nattable.ui.action.IDragMode; import org.eclipse.nebula.widgets.nattable.ui.util.CellEdgeDetectUtil; import org.eclipse.nebula.widgets.nattable.ui.util.CellEdgeEnum; import org.eclipse.nebula.widgets.nattable.ui.util.MouseEventHelper; import org.eclipse.nebula.widgets.nattable.util.GUIHelper; import org.eclipse.nebula.widgets.nattable.viewport.action.AutoScrollDragMode; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; /** * Default {@link IDragMode} invoked for 'left click + drag' on the column * header. It does the following when invoked: * <ol> * <li>Fires a column reorder command, to move columns</li> * <li>Overlays a black line indicating the new column position</li> * </ol> */ public class ColumnReorderDragMode extends AutoScrollDragMode { protected NatTable natTable; protected MouseEvent initialEvent; protected MouseEvent currentEvent; protected int dragFromGridColumnPosition; protected ColumnReorderOverlayPainter targetOverlayPainter = new ColumnReorderOverlayPainter(); public ColumnReorderDragMode() { super(true, false); } @Override public void mouseDown(NatTable natTable, MouseEvent event) { this.natTable = natTable; this.initialEvent = event; this.currentEvent = this.initialEvent; this.dragFromGridColumnPosition = getDragFromGridColumnPosition(); natTable.addOverlayPainter(this.targetOverlayPainter); natTable.doCommand(new ClearAllSelectionsCommand()); fireMoveStartCommand(natTable, this.dragFromGridColumnPosition); } @Override public void mouseMove(NatTable natTable, MouseEvent event) { super.mouseMove(natTable, event); this.currentEvent = event; natTable.redraw(); } @Override public void mouseUp(NatTable natTable, MouseEvent event) { // Cancel any active viewport drag super.mouseUp(natTable, event); natTable.removeOverlayPainter(this.targetOverlayPainter); // only trigger column reordering in case there is a real drag operation if (!MouseEventHelper.treatAsClick(this.initialEvent, this.currentEvent)) { int dragToGridColumnPosition = getDragToGridColumnPosition( getMoveDirection(event.x), natTable.getColumnPositionByX(event.x)); if (!isValidTargetColumnPosition(natTable, this.dragFromGridColumnPosition, dragToGridColumnPosition)) { dragToGridColumnPosition = -1; } fireMoveEndCommand(natTable, dragToGridColumnPosition); } natTable.redraw(); } protected int getDragFromGridColumnPosition() { return this.natTable.getColumnPositionByX(this.initialEvent.x); } protected int getDragToGridColumnPosition(CellEdgeEnum moveDirection, int gridColumnPosition) { int dragToGridColumnPosition = -1; if (moveDirection != null) { switch (moveDirection) { case LEFT: dragToGridColumnPosition = gridColumnPosition; break; case RIGHT: dragToGridColumnPosition = gridColumnPosition + 1; break; } } return dragToGridColumnPosition; } protected CellEdgeEnum getMoveDirection(int x) { ILayerCell cell = getColumnCell(x); if (cell != null) { Rectangle selectedColumnHeaderRect = cell.getBounds(); return CellEdgeDetectUtil.getHorizontalCellEdge(selectedColumnHeaderRect, new Point(x, this.initialEvent.y)); } return null; } private ILayerCell getColumnCell(int x) { int gridColumnPosition = this.natTable.getColumnPositionByX(x); int gridRowPosition = this.natTable.getRowPositionByY(this.initialEvent.y); return this.natTable.getCellByPosition(gridColumnPosition, gridRowPosition); } protected boolean isValidTargetColumnPosition(ILayer natLayer, int dragFromGridColumnPosition, int dragToGridColumnPosition) { return dragFromGridColumnPosition >= 0 && dragToGridColumnPosition >= 0; } protected void fireMoveStartCommand(NatTable natTable, int dragFromGridColumnPosition) { natTable.doCommand(new ColumnReorderStartCommand(natTable, dragFromGridColumnPosition)); } protected void fireMoveEndCommand(NatTable natTable, int dragToGridColumnPosition) { natTable.doCommand(new ColumnReorderEndCommand(natTable, dragToGridColumnPosition)); } private class ColumnReorderOverlayPainter implements IOverlayPainter { @Override public void paintOverlay(GC gc, ILayer layer) { int dragFromGridColumnPosition = getDragFromGridColumnPosition(); if (ColumnReorderDragMode.this.currentEvent.x > ColumnReorderDragMode.this.natTable.getWidth()) { return; } CellEdgeEnum moveDirection = getMoveDirection(ColumnReorderDragMode.this.currentEvent.x); int dragToGridColumnPosition = getDragToGridColumnPosition( moveDirection, ColumnReorderDragMode.this.natTable.getColumnPositionByX(ColumnReorderDragMode.this.currentEvent.x)); if (isValidTargetColumnPosition( ColumnReorderDragMode.this.natTable, dragFromGridColumnPosition, dragToGridColumnPosition)) { int dragToColumnHandleX = -1; if (moveDirection != null) { Rectangle selectedColumnHeaderRect = getColumnCell(ColumnReorderDragMode.this.currentEvent.x).getBounds(); switch (moveDirection) { case LEFT: dragToColumnHandleX = selectedColumnHeaderRect.x; break; case RIGHT: dragToColumnHandleX = selectedColumnHeaderRect.x + selectedColumnHeaderRect.width; break; } } if (dragToColumnHandleX > 0) { Color orgBgColor = gc.getBackground(); gc.setBackground(GUIHelper.COLOR_DARK_GRAY); gc.fillRectangle(dragToColumnHandleX - 1, 0, 2, layer.getHeight()); gc.setBackground(orgBgColor); } } } } }