blob: 74d0811783d148025ed6f0a4b47881dbb3820b30 [file] [log] [blame]
/******************************************************************************
* Copyright (c) 2012, 2014 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.gridkit;
import static org.eclipse.rap.rwt.internal.lifecycle.WidgetLCAUtil.getStyles;
import static org.eclipse.rap.rwt.internal.lifecycle.WidgetLCAUtil.preserveListener;
import static org.eclipse.rap.rwt.internal.lifecycle.WidgetLCAUtil.preserveProperty;
import static org.eclipse.rap.rwt.internal.lifecycle.WidgetLCAUtil.renderListener;
import static org.eclipse.rap.rwt.internal.lifecycle.WidgetLCAUtil.renderProperty;
import static org.eclipse.rap.rwt.internal.lifecycle.WidgetUtil.getId;
import static org.eclipse.rap.rwt.internal.protocol.JsonUtil.createJsonArray;
import static org.eclipse.rap.rwt.internal.protocol.RemoteObjectFactory.createRemoteObject;
import static org.eclipse.rap.rwt.internal.protocol.RemoteObjectFactory.getRemoteObject;
import static org.eclipse.swt.internal.events.EventLCAUtil.isListening;
import static org.eclipse.swt.internal.widgets.MarkupUtil.isMarkupEnabledFor;
import java.io.IOException;
import org.eclipse.nebula.widgets.grid.Grid;
import org.eclipse.nebula.widgets.grid.GridColumn;
import org.eclipse.nebula.widgets.grid.GridItem;
import org.eclipse.nebula.widgets.grid.internal.IGridAdapter;
import org.eclipse.rap.json.JsonArray;
import org.eclipse.rap.rwt.internal.lifecycle.AbstractWidgetLCA;
import org.eclipse.rap.rwt.internal.lifecycle.ControlLCAUtil;
import org.eclipse.rap.rwt.internal.lifecycle.WidgetLCAUtil;
import org.eclipse.rap.rwt.remote.RemoteObject;
import org.eclipse.swt.SWT;
import org.eclipse.swt.internal.widgets.CellToolTipUtil;
import org.eclipse.swt.internal.widgets.ICellToolTipAdapter;
import org.eclipse.swt.internal.widgets.ScrollBarLCAUtil;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.ScrollBar;
import org.eclipse.swt.widgets.Widget;
@SuppressWarnings("restriction")
public class GridLCA extends AbstractWidgetLCA {
private static final String TYPE = "rwt.widgets.Grid";
private static final String[] ALLOWED_STYLES = new String[] {
"SINGLE",
"MULTI",
"FULL_SELECTION",
"VIRTUAL",
"NO_FOCUS",
"BORDER"
};
private static final String PROP_ITEM_COUNT = "itemCount";
private static final String PROP_ITEM_HEIGHT = "itemHeight";
private static final String PROP_ITEM_METRICS = "itemMetrics";
private static final String PROP_COLUMN_COUNT = "columnCount";
private static final String PROP_COLUMN_ORDER = "columnOrder";
private static final String PROP_TREE_COLUMN = "treeColumn";
private static final String PROP_HEADER_HEIGHT = "headerHeight";
private static final String PROP_HEADER_VISIBLE = "headerVisible";
private static final String PROP_FOOTER_HEIGHT = "footerHeight";
private static final String PROP_FOOTER_VISIBLE = "footerVisible";
private static final String PROP_LINES_VISIBLE = "linesVisible";
private static final String PROP_TOP_ITEM_INDEX = "topItemIndex";
private static final String PROP_FOCUS_ITEM = "focusItem";
private static final String PROP_SCROLL_LEFT = "scrollLeft";
private static final String PROP_SELECTION = "selection";
private static final String PROP_AUTO_HEIGHT = "autoHeight";
// TODO: [if] Sync sortDirection and sortColumn in GridColumnLCA when multiple sort columns are
// possible on the client
private static final String PROP_SORT_DIRECTION = "sortDirection";
private static final String PROP_SORT_COLUMN = "sortColumn";
private static final String PROP_SELECTION_LISTENER = "Selection";
private static final String PROP_DEFAULT_SELECTION_LISTENER = "DefaultSelection";
private static final String PROP_SETDATA_LISTENER = "SetData";
private static final String PROP_EXPAND_LISTENER = "Expand";
private static final String PROP_COLLAPSE_LISTENER = "Collapse";
// TODO: [if] Sync toolTipText in GridItemLCA when it's possible on the client
private static final String PROP_ENABLE_CELL_TOOLTIP = "enableCellToolTip";
private static final String PROP_CELL_TOOLTIP_TEXT = "cellToolTipText";
private static final String PROP_MARKUP_ENABLED = "markupEnabled";
private static final int ZERO = 0 ;
private static final String[] DEFAULT_SELECTION = new String[ 0 ];
private static final String[] DEFAULT_COLUMN_ORDER = new String[ 0 ];
private static final String DEFAULT_SORT_DIRECTION = "none";
@Override
public void renderInitialization( Widget widget ) throws IOException {
Grid grid = ( Grid )widget;
RemoteObject remoteObject = createRemoteObject( grid, TYPE );
remoteObject.setHandler( new GridOperationHandler( grid ) );
remoteObject.set( "parent", getId( grid.getParent() ) );
remoteObject.set( "style", createJsonArray( getStyles( grid, ALLOWED_STYLES ) ) );
remoteObject.set( "appearance", "tree" );
IGridAdapter adapter = getGridAdapter( grid );
remoteObject.set( "indentionWidth", adapter.getIndentationWidth() );
remoteObject.set( PROP_MARKUP_ENABLED, isMarkupEnabledFor( grid ) );
ScrollBarLCAUtil.renderInitialization( grid );
}
@Override
public void readData( Widget widget ) {
super.readData( widget );
ScrollBarLCAUtil.processSelectionEvent( ( Grid )widget );
}
@Override
public void preserveValues( Widget widget ) {
Grid grid = ( Grid )widget;
ControlLCAUtil.preserveValues( ( Control )widget );
WidgetLCAUtil.preserveCustomVariant( grid );
preserveProperty( grid, PROP_ITEM_COUNT, grid.getRootItemCount() );
preserveProperty( grid, PROP_ITEM_HEIGHT, grid.getItemHeight() );
preserveProperty( grid, PROP_ITEM_METRICS, getItemMetrics( grid ) );
preserveProperty( grid, PROP_COLUMN_COUNT, grid.getColumnCount() );
preserveProperty( grid, PROP_COLUMN_ORDER, getColumnOrder( grid ) );
preserveProperty( grid, PROP_TREE_COLUMN, getTreeColumn( grid ) );
preserveProperty( grid, PROP_HEADER_HEIGHT, grid.getHeaderHeight() );
preserveProperty( grid, PROP_HEADER_VISIBLE, grid.getHeaderVisible() );
preserveProperty( grid, PROP_FOOTER_HEIGHT, grid.getFooterHeight() );
preserveProperty( grid, PROP_FOOTER_VISIBLE, grid.getFooterVisible() );
preserveProperty( grid, PROP_LINES_VISIBLE, grid.getLinesVisible() );
preserveProperty( grid, PROP_TOP_ITEM_INDEX, getTopItemIndex( grid ) );
preserveProperty( grid, PROP_FOCUS_ITEM, grid.getFocusItem() );
preserveProperty( grid, PROP_SCROLL_LEFT, getScrollLeft( grid ) );
preserveProperty( grid, PROP_SELECTION, getSelection( grid ) );
preserveProperty( grid, PROP_AUTO_HEIGHT, grid.isAutoHeight() );
preserveProperty( grid, PROP_SORT_DIRECTION, getSortDirection( grid ) );
preserveProperty( grid, PROP_SORT_COLUMN, getSortColumn( grid ) );
preserveListener( grid, PROP_SELECTION_LISTENER, isListening( grid, SWT.Selection ) );
preserveListener( grid,
PROP_DEFAULT_SELECTION_LISTENER,
isListening( grid, SWT.DefaultSelection ) );
preserveListener( grid, PROP_SETDATA_LISTENER, listensToSetData( grid ) );
preserveListener( grid, PROP_EXPAND_LISTENER, hasExpandListener( grid ) );
preserveListener( grid, PROP_COLLAPSE_LISTENER, hasCollapseListener( grid ) );
preserveProperty( grid, PROP_ENABLE_CELL_TOOLTIP, CellToolTipUtil.isEnabledFor( grid ) );
preserveProperty( grid, PROP_CELL_TOOLTIP_TEXT, null );
ScrollBarLCAUtil.preserveValues( grid );
}
@Override
public void renderChanges( Widget widget ) throws IOException {
Grid grid = ( Grid )widget;
ControlLCAUtil.renderChanges( grid );
WidgetLCAUtil.renderCustomVariant( grid );
renderProperty( grid, PROP_ITEM_COUNT, grid.getRootItemCount(), ZERO );
renderProperty( grid, PROP_ITEM_HEIGHT, grid.getItemHeight(), ZERO );
renderItemMetrics( grid );
renderProperty( grid, PROP_COLUMN_COUNT, grid.getColumnCount(), ZERO );
renderProperty( grid, PROP_COLUMN_ORDER, getColumnOrder( grid ), DEFAULT_COLUMN_ORDER );
renderProperty( grid, PROP_TREE_COLUMN, getTreeColumn( grid ), ZERO );
renderProperty( grid, PROP_HEADER_HEIGHT, grid.getHeaderHeight(), ZERO );
renderProperty( grid, PROP_HEADER_VISIBLE, grid.getHeaderVisible(), false );
renderProperty( grid, PROP_FOOTER_HEIGHT, grid.getFooterHeight(), ZERO );
renderProperty( grid, PROP_FOOTER_VISIBLE, grid.getFooterVisible(), false );
renderProperty( grid, PROP_LINES_VISIBLE, grid.getLinesVisible(), false );
renderProperty( grid, PROP_TOP_ITEM_INDEX, getTopItemIndex( grid ), ZERO );
renderProperty( grid, PROP_FOCUS_ITEM, grid.getFocusItem(), null );
renderProperty( grid, PROP_SCROLL_LEFT, getScrollLeft( grid ), ZERO );
renderProperty( grid, PROP_SELECTION, getSelection( grid ), DEFAULT_SELECTION );
renderProperty( grid, PROP_AUTO_HEIGHT, grid.isAutoHeight(), false );
renderProperty( grid, PROP_SORT_DIRECTION, getSortDirection( grid ), DEFAULT_SORT_DIRECTION );
renderProperty( grid, PROP_SORT_COLUMN, getSortColumn( grid ), null );
renderListener( grid, PROP_SELECTION_LISTENER, isListening( grid, SWT.Selection ), false );
renderListener( grid,
PROP_DEFAULT_SELECTION_LISTENER,
isListening( grid, SWT.DefaultSelection ),
false );
renderListener( grid, PROP_SETDATA_LISTENER, listensToSetData( grid ), false );
renderListener( grid, PROP_EXPAND_LISTENER, hasExpandListener( grid ), false );
renderListener( grid, PROP_COLLAPSE_LISTENER, hasCollapseListener( grid ), false );
renderProperty( grid, PROP_ENABLE_CELL_TOOLTIP, CellToolTipUtil.isEnabledFor( grid ), false );
renderProperty( grid, PROP_CELL_TOOLTIP_TEXT, getAndResetCellToolTipText( grid ), null );
ScrollBarLCAUtil.renderChanges( grid );
}
@Override
public void doRedrawFake( Control control ) {
getGridAdapter( ( Grid )control ).doRedraw();
}
//////////////////
// Helping methods
private static String getAndResetCellToolTipText( Grid grid ) {
ICellToolTipAdapter adapter = CellToolTipUtil.getAdapter( grid );
String toolTipText = adapter.getCellToolTipText();
adapter.setCellToolTipText( null );
return toolTipText;
}
private static boolean listensToSetData( Grid grid ) {
return ( grid.getStyle() & SWT.VIRTUAL ) != 0;
}
private static int getTreeColumn( Grid grid ) {
int[] order = grid.getColumnOrder();
return order.length > 0 ? order[ 0 ] : 0;
}
private static int getTopItemIndex( Grid grid ) {
int result = 0;
ScrollBar verticalBar = grid.getVerticalBar();
if( verticalBar != null ) {
result = verticalBar.getSelection();
}
return result;
}
private static int getScrollLeft( Grid grid ) {
int result = 0;
ScrollBar horizontalBar = grid.getHorizontalBar();
if( horizontalBar != null ) {
result = horizontalBar.getSelection();
}
return result;
}
private static String[] getSelection( Grid grid ) {
GridItem[] selection = grid.getSelection();
String[] result = new String[ selection.length ];
for( int i = 0; i < result.length; i++ ) {
result[ i ] = getId( selection[ i ] );
}
return result;
}
private static String getSortDirection( Grid grid ) {
String result = "none";
for( int i = 0; i < grid.getColumnCount() && result.equals( "none" ); i++ ) {
int sort = grid.getColumn( i ).getSort();
if( sort == SWT.UP ) {
result = "up";
} else if( sort == SWT.DOWN ) {
result = "down";
}
}
return result;
}
private static GridColumn getSortColumn( Grid grid ) {
GridColumn result = null;
for( int i = 0; i < grid.getColumnCount() && result == null; i++ ) {
GridColumn column = grid.getColumn( i );
if( column.getSort() != SWT.NONE ) {
result = column;
}
}
return result;
}
private static String[] getColumnOrder( Grid grid ) {
int[] order = grid.getColumnOrder();
String[] result = new String[ order.length ];
for( int i = 0; i < result.length; i++ ) {
result[ i ] = getId( grid.getColumn( order[ i ] ) );
}
return result;
}
@SuppressWarnings( "unused" )
private static boolean hasExpandListener( Grid grid ) {
// Always render listen for Expand and Collapse, currently required for scrollbar
// visibility update and setData events.
return true;
}
@SuppressWarnings( "unused" )
private static boolean hasCollapseListener( Grid grid ) {
// Always render listen for Expand and Collapse, currently required for scrollbar
// visibility update and setData events.
return true;
}
///////////////
// Item Metrics
private static void renderItemMetrics( Grid grid ) {
ItemMetrics[] itemMetrics = getItemMetrics( grid );
if( WidgetLCAUtil.hasChanged( grid, PROP_ITEM_METRICS, itemMetrics ) ) {
JsonArray metrics = new JsonArray();
for( int i = 0; i < itemMetrics.length; i++ ) {
metrics.add( new JsonArray().add( i )
.add( itemMetrics[ i ].left )
.add( itemMetrics[ i ].width )
.add( itemMetrics[ i ].imageLeft )
.add( itemMetrics[ i ].imageWidth )
.add( itemMetrics[ i ].textLeft )
.add( itemMetrics[ i ].textWidth )
.add( itemMetrics[ i ].checkLeft )
.add( itemMetrics[ i ].checkWidth ) );
}
getRemoteObject( grid ).set( PROP_ITEM_METRICS, metrics );
}
}
static ItemMetrics[] getItemMetrics( Grid grid ) {
int columnCount = grid.getColumnCount();
ItemMetrics[] result = new ItemMetrics[ columnCount ];
IGridAdapter adapter = getGridAdapter( grid );
for( int i = 0; i < columnCount; i++ ) {
result[ i ] = new ItemMetrics();
result[ i ].left = adapter.getCellLeft( i );
result[ i ].width = adapter.getCellWidth( i );
result[ i ].checkLeft = result[ i ].left + adapter.getCheckBoxOffset( i );
result[ i ].checkWidth = adapter.getCheckBoxWidth( i );
result[ i ].imageLeft = result[ i ].left + adapter.getImageOffset( i );
result[ i ].imageWidth = adapter.getImageWidth( i );
result[ i ].textLeft = result[ i ].left + adapter.getTextOffset( i );
result[ i ].textWidth = adapter.getTextWidth( i );
}
return result;
}
private static IGridAdapter getGridAdapter( Grid grid ) {
return grid.getAdapter( IGridAdapter.class );
}
////////////////
// Inner classes
static final class ItemMetrics {
int left;
int width;
int checkLeft;
int checkWidth;
int imageLeft;
int imageWidth;
int textLeft;
int textWidth;
@Override
public boolean equals( Object obj ) {
boolean result;
if( obj == this ) {
result = true;
} else if( obj instanceof ItemMetrics ) {
ItemMetrics other = ( ItemMetrics )obj;
result = other.left == left
&& other.width == width
&& other.checkLeft == checkLeft
&& other.checkWidth == checkWidth
&& other.imageLeft == imageLeft
&& other.imageWidth == imageWidth
&& other.textLeft == textLeft
&& other.textWidth == textWidth;
} else {
result = false;
}
return result;
}
@Override
public int hashCode() {
String msg = "ItemMetrics#hashCode() not implemented";
throw new UnsupportedOperationException( msg );
}
}
}