/*******************************************************************************
* Copyright (c) 2013, 2015 EclipseSource 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:
* EclipseSource - initial API and implementation
******************************************************************************/
package org.eclipse.nebula.widgets.grid.internal.gridcolumnkit;
import static org.eclipse.rap.rwt.internal.protocol.ClientMessageConst.EVENT_DEFAULT_SELECTION;
import static org.eclipse.rap.rwt.internal.protocol.ClientMessageConst.EVENT_SELECTION;
import java.util.Arrays;
import org.eclipse.nebula.widgets.grid.Grid;
import org.eclipse.nebula.widgets.grid.GridColumn;
import org.eclipse.nebula.widgets.grid.internal.IGridAdapter;
import org.eclipse.rap.json.JsonObject;
import org.eclipse.rap.rwt.internal.lifecycle.ProcessActionRunner;
import org.eclipse.rap.rwt.internal.lifecycle.RemoteAdapter;
import org.eclipse.rap.rwt.internal.lifecycle.WidgetUtil;
import org.eclipse.rap.rwt.internal.protocol.WidgetOperationHandler;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Event;
@SuppressWarnings( "restriction" )
public class GridColumnOperationHandler extends WidgetOperationHandler<GridColumn> {
private static final String METHOD_MOVE = "move";
private static final String METHOD_RESIZE = "resize";
private static final String PROP_LEFT = "left";
private static final String PROP_WIDTH = "width";
public GridColumnOperationHandler( GridColumn column ) {
super( column );
}
@Override
public void handleCall( GridColumn column, String method, JsonObject properties ) {
if( METHOD_MOVE.equals( method ) ) {
handleCallMove( column, properties );
} else if( METHOD_RESIZE.equals( method ) ) {
handleCallResize( column, properties );
}
}
@Override
public void handleNotify( GridColumn column, String eventName, JsonObject properties ) {
if( EVENT_SELECTION.equals( eventName ) ) {
handleNotifySelection( column, properties );
} else if( EVENT_DEFAULT_SELECTION.equals( eventName ) ) {
handleNotifyDefaultSelection( column, properties );
} else {
super.handleNotify( column, eventName, properties );
}
}
/*
* PROTOCOL CALL move
*
* @param left (int) the left position of the column
*/
public void handleCallMove( final GridColumn column, JsonObject properties ) {
final int newLeft = properties.get( PROP_LEFT ).asInt();
ProcessActionRunner.add( new Runnable() {
@Override
public void run() {
moveColumn( column, newLeft );
}
} );
}
/*
* PROTOCOL CALL resize
*
* @param width (int) the width of the column
*/
public void handleCallResize( final GridColumn column, JsonObject properties ) {
final int width = properties.get( PROP_WIDTH ).asInt();
ProcessActionRunner.add( new Runnable() {
@Override
public void run() {
column.setWidth( width );
}
} );
}
/*
* PROTOCOL NOTIFY Selection
*
* @param altKey (boolean) true if the ALT key was pressed
* @param ctrlKey (boolean) true if the CTRL key was pressed
* @param shiftKey (boolean) true if the SHIFT key was pressed
*/
public void handleNotifySelection( GridColumn column, JsonObject properties ) {
Event event = createSelectionEvent( SWT.Selection, properties );
column.notifyListeners( SWT.Selection, event );
}
/*
* PROTOCOL NOTIFY DefaultSelection
*
* @param altKey (boolean) true if the ALT key was pressed
* @param ctrlKey (boolean) true if the CTRL key was pressed
* @param shiftKey (boolean) true if the SHIFT key was pressed
*/
public void handleNotifyDefaultSelection( GridColumn column, JsonObject properties ) {
Event event = createSelectionEvent( SWT.DefaultSelection, properties );
column.notifyListeners( SWT.DefaultSelection, event );
}
static void moveColumn( GridColumn column, int newLeft ) {
Grid grid = column.getParent();
int index = grid.indexOf( column );
int targetColumn = findMoveTarget( grid, newLeft );
int[] columnOrder = grid.getColumnOrder();
int orderIndex = arrayIndexOf( columnOrder, index );
columnOrder = arrayRemove( columnOrder, orderIndex );
if( orderIndex < targetColumn ) {
targetColumn--;
}
columnOrder = arrayInsert( columnOrder, targetColumn, index );
if( Arrays.equals( columnOrder, grid.getColumnOrder() ) ) {
GridColumn[] columns = grid.getColumns();
for( int i = 0; i < columns.length; i++ ) {
RemoteAdapter adapter = WidgetUtil.getAdapter( columns[ i ] );
adapter.preserve( PROP_LEFT, null );
}
} else {
try {
grid.setColumnOrder( columnOrder );
} catch( IllegalArgumentException exception ) {
// move the column in/out of a group is invalid
} finally {
RemoteAdapter adapter = WidgetUtil.getAdapter( column );
adapter.preserve( PROP_LEFT, null );
}
}
}
private static int findMoveTarget( Grid grid, int newLeft ) {
int result = -1;
GridColumn[] columns = grid.getColumns();
int[] columnOrder = grid.getColumnOrder();
if( newLeft < 0 ) {
result = 0;
} else {
for( int i = 0; result == -1 && i < columns.length; i++ ) {
GridColumn column = columns[ columnOrder[ i ] ];
int left = getLeft( column );
int width = getWidth( column );
if( newLeft >= left && newLeft <= left + width ) {
result = i;
if( newLeft >= left + width / 2 && result < columns.length ) {
result++;
}
}
}
}
if( result == -1 ) {
result = columns.length;
}
return result;
}
private static int getLeft( GridColumn column ) {
return getGridAdapter( column ).getCellLeft( getIndex( column ) );
}
private static int getWidth( GridColumn column ) {
return getGridAdapter( column ).getCellWidth( getIndex( column ) );
}
private static int getIndex( GridColumn column ) {
return column.getParent().indexOf( column );
}
private static IGridAdapter getGridAdapter( GridColumn column ) {
return column.getParent().getAdapter( IGridAdapter.class );
}
private static int arrayIndexOf( int[] array, int value ) {
int result = -1;
for( int i = 0; result == -1 && i < array.length; i++ ) {
if( array[ i ] == value ) {
result = i;
}
}
return result;
}
private static int[] arrayRemove( int[] array, int index ) {
int length = array.length;
int[] result = new int[ length - 1 ];
System.arraycopy( array, 0, result, 0, index );
if( index < length - 1 ) {
System.arraycopy( array, index + 1, result, index, length - index - 1 );
}
return result;
}
private static int[] arrayInsert( int[] array, int index, int value ) {
int length = array.length;
int[] result = new int[ length + 1 ];
System.arraycopy( array, 0, result, 0, length );
System.arraycopy( result, index, result, index + 1, length - index );
result[ index ] = value;
return result;
}
}