Synchronize scrollbars visibility and selection event on a widget of
it's own
diff --git a/bundles/org.eclipse.rap.nebula.widgets.grid/src/org/eclipse/nebula/widgets/grid/internal/gridkit/GridLCA.java b/bundles/org.eclipse.rap.nebula.widgets.grid/src/org/eclipse/nebula/widgets/grid/internal/gridkit/GridLCA.java
index 7cdb793..11dd5d1 100644
--- a/bundles/org.eclipse.rap.nebula.widgets.grid/src/org/eclipse/nebula/widgets/grid/internal/gridkit/GridLCA.java
+++ b/bundles/org.eclipse.rap.nebula.widgets.grid/src/org/eclipse/nebula/widgets/grid/internal/gridkit/GridLCA.java
@@ -38,10 +38,10 @@
 import org.eclipse.rap.rwt.lifecycle.WidgetLCAUtil;
 import org.eclipse.rap.rwt.lifecycle.WidgetUtil;
 import org.eclipse.swt.SWT;
-import org.eclipse.swt.internal.events.EventLCAUtil;
 import org.eclipse.swt.internal.widgets.CellToolTipUtil;
 import org.eclipse.swt.internal.widgets.ICellToolTipAdapter;
 import org.eclipse.swt.internal.widgets.ICellToolTipProvider;
+import org.eclipse.swt.internal.widgets.ScrollBarLCAUtil;
 import org.eclipse.swt.widgets.Control;
 import org.eclipse.swt.widgets.Event;
 import org.eclipse.swt.widgets.ScrollBar;
@@ -79,10 +79,9 @@
   // 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_SCROLLBARS_VISIBLE = "scrollBarsVisible";
-  private static final String PROP_SCROLLBARS_SELECTION_LISTENER = "scrollBarsSelection";
   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
@@ -93,7 +92,6 @@
   private static final int ZERO = 0 ;
   private static final String[] DEFAULT_SELECTION = new String[ 0 ];
   private static final String DEFAULT_SORT_DIRECTION = "none";
-  private static final boolean[] DEFAULT_SCROLLBARS_VISIBLE = new boolean[] { false, false };
 
   @Override
   public void renderInitialization( Widget widget ) throws IOException {
@@ -106,6 +104,7 @@
     IGridAdapter adapter = getGridAdapter( grid );
     clientObject.set( "indentionWidth", adapter.getIndentationWidth() );
     clientObject.set( PROP_MARKUP_ENABLED, isMarkupEnabled( grid ) );
+    ScrollBarLCAUtil.renderInitialization( grid );
   }
 
   public void readData( Widget widget ) {
@@ -122,7 +121,7 @@
     ControlLCAUtil.processKeyEvents( grid );
     ControlLCAUtil.processMenuDetect( grid );
     WidgetLCAUtil.processHelp( grid );
-    EventLCAUtil.processScrollBarSelection( grid );
+    ScrollBarLCAUtil.processSelectionEvent( grid );
   }
 
   @Override
@@ -146,18 +145,16 @@
     preserveProperty( grid, PROP_SELECTION, getSelection( grid ) );
     preserveProperty( grid, PROP_SORT_DIRECTION, getSortDirection( grid ) );
     preserveProperty( grid, PROP_SORT_COLUMN, getSortColumn( grid ) );
-    preserveProperty( grid, PROP_SCROLLBARS_VISIBLE, getScrollBarsVisible( grid ) );
-    preserveListener( grid,
-                      PROP_SCROLLBARS_SELECTION_LISTENER,
-                      EventLCAUtil.hasScrollBarsSelectionListener( grid ) );
     preserveListener( grid, PROP_SELECTION_LISTENER, grid.isListening( SWT.Selection ) );
     preserveListener( grid,
                       PROP_DEFAULT_SELECTION_LISTENER,
                       grid.isListening( 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
@@ -181,23 +178,17 @@
     renderProperty( grid, PROP_SELECTION, getSelection( grid ), DEFAULT_SELECTION );
     renderProperty( grid, PROP_SORT_DIRECTION, getSortDirection( grid ), DEFAULT_SORT_DIRECTION );
     renderProperty( grid, PROP_SORT_COLUMN, getSortColumn( grid ), null );
-    renderProperty( grid,
-                    PROP_SCROLLBARS_VISIBLE,
-                    getScrollBarsVisible( grid ),
-                    DEFAULT_SCROLLBARS_VISIBLE );
-    renderListener( grid,
-                    PROP_SCROLLBARS_SELECTION_LISTENER,
-                    EventLCAUtil.hasScrollBarsSelectionListener( grid ),
-                    false );
     renderListener( grid, PROP_SELECTION_LISTENER, grid.isListening( SWT.Selection ), false );
     renderListener( grid,
                     PROP_DEFAULT_SELECTION_LISTENER,
                     grid.isListening( 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, getCellToolTipText( grid ), null );
+    ScrollBarLCAUtil.renderChanges( grid );
   }
 
   @Override
@@ -275,6 +266,10 @@
   //////////////////
   // Helping methods
 
+  private boolean listensToSetData( Grid grid ) {
+    return ( grid.getStyle() & SWT.VIRTUAL ) != 0;
+  }
+
   private static boolean isMarkupEnabled( Grid grid ) {
     return Boolean.TRUE.equals( grid.getData( RWT.MARKUP_ENABLED ) );
   }
@@ -335,20 +330,6 @@
     return result;
   }
 
-  private static boolean[] getScrollBarsVisible( Grid grid ) {
-    boolean horizontalBarVisible = false;
-    ScrollBar horizontalBar = grid.getHorizontalBar();
-    if( horizontalBar != null ) {
-      horizontalBarVisible = horizontalBar.getVisible();
-    }
-    boolean verticalBarVisible = false;
-    ScrollBar verticalBar = grid.getVerticalBar();
-    if( verticalBar != null ) {
-      verticalBarVisible = verticalBar.getVisible();
-    }
-    return new boolean[] { horizontalBarVisible, verticalBarVisible };
-  }
-
   private static GridItem getItem( Grid grid, String itemId ) {
     return ( GridItem )WidgetUtil.find( grid, itemId );
   }
diff --git a/tests/org.eclipse.rap.nebula.widgets.grid.test/.settings/GridAllTests.launch b/tests/org.eclipse.rap.nebula.widgets.grid.test/.settings/GridAllTests.launch
index c0e249e..70b23e3 100644
--- a/tests/org.eclipse.rap.nebula.widgets.grid.test/.settings/GridAllTests.launch
+++ b/tests/org.eclipse.rap.nebula.widgets.grid.test/.settings/GridAllTests.launch
@@ -6,6 +6,9 @@
 <listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">

 <listEntry value="4"/>

 </listAttribute>

+<mapAttribute key="org.eclipse.debug.core.preferred_launchers">

+<mapEntry key="[run]" value="org.eclipse.jdt.junit.launchconfig"/>

+</mapAttribute>

 <listAttribute key="org.eclipse.debug.ui.favoriteGroups">

 <listEntry value="com.mountainminds.eclemma.ui.launchGroup.coverage"/>

 <listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>

diff --git a/tests/org.eclipse.rap.nebula.widgets.grid.test/src/org/eclipse/nebula/widgets/grid/internal/griditemkit/GridItemLCA_Test.java b/tests/org.eclipse.rap.nebula.widgets.grid.test/src/org/eclipse/nebula/widgets/grid/internal/griditemkit/GridItemLCA_Test.java
index df1ec76..dd47fc8 100644
--- a/tests/org.eclipse.rap.nebula.widgets.grid.test/src/org/eclipse/nebula/widgets/grid/internal/griditemkit/GridItemLCA_Test.java
+++ b/tests/org.eclipse.rap.nebula.widgets.grid.test/src/org/eclipse/nebula/widgets/grid/internal/griditemkit/GridItemLCA_Test.java
@@ -650,7 +650,7 @@
     assertFalse( item.isExpanded() );
   }
 
-  public void testRenderScrollbarsVisibleAfterExpanded() throws JSONException {
+  public void testRenderScrollbarsVisibleAfterExpanded() {
     grid.setSize( 200, 200 );
     createGridColumns( grid, 3, SWT.NONE );
     GridItem[] items = createGridItems( grid, 5, 10 );
@@ -660,8 +660,7 @@
     Fixture.executeLifeCycleFromServerThread();
 
     Message message = Fixture.getProtocolMessage();
-    JSONArray actual = ( JSONArray )message.findSetProperty( grid, "scrollBarsVisible" );
-    assertTrue( jsonEquals( "[ false, true ]", actual ) );
+    assertNotNull( message.findSetOperation( grid.getVerticalBar(), "visibility" ) );
   }
 
   private static void fakeTreeEvent( GridItem item, String eventName ) {
diff --git a/tests/org.eclipse.rap.nebula.widgets.grid.test/src/org/eclipse/nebula/widgets/grid/internal/gridkit/GridLCA_Test.java b/tests/org.eclipse.rap.nebula.widgets.grid.test/src/org/eclipse/nebula/widgets/grid/internal/gridkit/GridLCA_Test.java
index d862e15..fb0bc54 100644
--- a/tests/org.eclipse.rap.nebula.widgets.grid.test/src/org/eclipse/nebula/widgets/grid/internal/gridkit/GridLCA_Test.java
+++ b/tests/org.eclipse.rap.nebula.widgets.grid.test/src/org/eclipse/nebula/widgets/grid/internal/gridkit/GridLCA_Test.java
@@ -45,6 +45,7 @@
 import org.eclipse.swt.widgets.Display;
 import org.eclipse.swt.widgets.Event;
 import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.ScrollBar;
 import org.eclipse.swt.widgets.Shell;
 import org.json.JSONArray;
 import org.json.JSONException;
@@ -99,13 +100,14 @@
   public void testRenderCreateWithVirtualMulti() throws IOException {
     grid = new Grid( shell, SWT.VIRTUAL | SWT.MULTI );
 
-    lca.renderInitialization( grid );
+    lca.render( grid );
 
     Message message = Fixture.getProtocolMessage();
     CreateOperation operation = message.findCreateOperation( grid );
     List<Object> styles = Arrays.asList( operation.getStyles() );
     assertTrue( styles.contains( "VIRTUAL" ) );
     assertTrue( styles.contains( "MULTI" ) );
+    assertEquals( Boolean.TRUE, message.findListenProperty( grid, "SetData" ) );
   }
 
   public void testRenderDispose() throws IOException {
@@ -149,8 +151,7 @@
     lca.render( grid );
 
     Message message = Fixture.getProtocolMessage();
-    CreateOperation operation = message.findCreateOperation( grid );
-    assertTrue( operation.getPropertyNames().contains( "itemHeight" ) );
+    assertNotNull( message.findSetOperation( grid, "itemHeight" ) );
   }
 
   public void testRenderItemHeight() throws IOException {
@@ -177,8 +178,7 @@
     lca.render( grid );
 
     Message message = Fixture.getProtocolMessage();
-    CreateOperation operation = message.findCreateOperation( grid );
-    assertTrue( operation.getPropertyNames().contains( "itemMetrics" ) );
+    assertNotNull( message.findSetOperation( grid, "itemMetrics" ) );
   }
 
   public void testRenderItemMetrics() throws IOException, JSONException {
@@ -408,7 +408,7 @@
     lca.render( grid );
 
     Message message = Fixture.getProtocolMessage();
-    assertEquals( Boolean.TRUE, message.findCreateProperty( grid, "linesVisible" ) );
+    assertEquals( Boolean.TRUE, message.findSetProperty( grid, "linesVisible" ) );
   }
 
   public void testRenderLinesVisible() throws IOException {
@@ -636,11 +636,11 @@
     lca.render( grid );
 
     Message message = Fixture.getProtocolMessage();
-    CreateOperation operation = message.findCreateOperation( grid );
-    assertTrue( operation.getPropertyNames().indexOf( "scrollBarsVisible" ) == -1 );
+    assertNull( message.findSetOperation( grid.getHorizontalBar(), "visibility" ) );
+    assertNull( message.findSetOperation( grid.getVerticalBar(), "visibility" ) );
   }
 
-  public void testRenderScrollBarsVisible_Horizontal() throws IOException, JSONException {
+  public void testRenderScrollBarsVisible_Horizontal() throws IOException {
     grid.setSize( 200, 200 );
     GridColumn[] columns = createGridColumns( grid, 3, SWT.NONE );
 
@@ -649,11 +649,11 @@
     lca.renderChanges( grid );
 
     Message message = Fixture.getProtocolMessage();
-    JSONArray actual = ( JSONArray )message.findSetProperty( grid, "scrollBarsVisible" );
-    assertTrue( jsonEquals( "[ true, false ]", actual ) );
+    assertEquals( Boolean.TRUE, message.findSetProperty( grid.getHorizontalBar(), "visibility" ) );
+    assertNull( message.findSetOperation( grid.getVerticalBar(), "visibility" ) );
   }
 
-  public void testRenderScrollBarsVisible_Vertical() throws IOException, JSONException {
+  public void testRenderScrollBarsVisible_Vertical() throws IOException {
     grid.setSize( 200, 200 );
     createGridColumns( grid, 3, SWT.NONE );
 
@@ -662,8 +662,8 @@
     lca.renderChanges( grid );
 
     Message message = Fixture.getProtocolMessage();
-    JSONArray actual = ( JSONArray )message.findSetProperty( grid, "scrollBarsVisible" );
-    assertTrue( jsonEquals( "[ false, true ]", actual ) );
+    assertNull( message.findSetOperation( grid.getHorizontalBar(), "visibility" ) );
+    assertEquals( Boolean.TRUE, message.findSetProperty( grid.getVerticalBar(), "visibility" ) );
   }
 
   public void testRenderScrollBarsVisibleUnchanged() throws IOException {
@@ -671,6 +671,8 @@
     GridColumn[] columns = createGridColumns( grid, 3, SWT.NONE );
     Fixture.markInitialized( display );
     Fixture.markInitialized( grid );
+    Fixture.markInitialized( grid.getHorizontalBar() );
+    Fixture.markInitialized( grid.getVerticalBar() );
 
     columns[ 0 ].setWidth( 150 );
     createGridItems( grid, 20, 0 );
@@ -679,85 +681,98 @@
     lca.renderChanges( grid );
 
     Message message = Fixture.getProtocolMessage();
-    assertNull( message.findSetOperation( grid, "scrollBarsVisible" ) );
+    assertNull( message.findSetOperation( grid.getHorizontalBar(), "visibility" ) );
+    assertNull( message.findSetOperation( grid.getVerticalBar(), "visibility" ) );
   }
 
   public void testRenderAddScrollBarsSelectionListener_Horizontal() throws Exception {
+    ScrollBar hScroll = grid.getHorizontalBar();
     Fixture.markInitialized( display );
     Fixture.markInitialized( grid );
+    Fixture.markInitialized( hScroll );
     Fixture.preserveWidgets();
 
-    grid.getHorizontalBar().addSelectionListener( new SelectionAdapter() { } );
+    hScroll.addSelectionListener( new SelectionAdapter() { } );
     lca.renderChanges( grid );
 
     Message message = Fixture.getProtocolMessage();
-    assertEquals( Boolean.TRUE, message.findListenProperty( grid, "scrollBarsSelection" ) );
+    assertEquals( Boolean.TRUE, message.findListenProperty( hScroll, "Selection" ) );
   }
 
   public void testRenderRemoveScrollBarsSelectionListener_Horizontal() throws Exception {
+    ScrollBar hScroll = grid.getHorizontalBar();
     SelectionListener listener = new SelectionAdapter() { };
-    grid.getHorizontalBar().addSelectionListener( listener );
+    hScroll.addSelectionListener( listener );
     Fixture.markInitialized( display );
     Fixture.markInitialized( grid );
+    Fixture.markInitialized( hScroll );
     Fixture.preserveWidgets();
 
-    grid.getHorizontalBar().removeSelectionListener( listener );
+    hScroll.removeSelectionListener( listener );
     lca.renderChanges( grid );
 
     Message message = Fixture.getProtocolMessage();
-    assertEquals( Boolean.FALSE, message.findListenProperty( grid, "scrollBarsSelection" ) );
+    assertEquals( Boolean.FALSE, message.findListenProperty( hScroll, "Selection" ) );
   }
 
   public void testRenderScrollBarsSelectionListenerUnchanged_Horizontal() throws Exception {
+    ScrollBar hScroll = grid.getHorizontalBar();
     Fixture.markInitialized( display );
     Fixture.markInitialized( grid );
+    Fixture.markInitialized( hScroll );
     Fixture.preserveWidgets();
 
-    grid.getHorizontalBar().addSelectionListener( new SelectionAdapter() { } );
+    hScroll.addSelectionListener( new SelectionAdapter() { } );
     Fixture.preserveWidgets();
     lca.renderChanges( grid );
 
     Message message = Fixture.getProtocolMessage();
-    assertNull( message.findListenOperation( grid, "scrollBarsSelection" ) );
+    assertNull( message.findListenOperation( hScroll, "Selection" ) );
   }
 
   public void testRenderAddScrollBarsSelectionListener_Vertical() throws Exception {
+    ScrollBar vScroll = grid.getVerticalBar();
     Fixture.markInitialized( display );
     Fixture.markInitialized( grid );
+    Fixture.markInitialized( vScroll );
     Fixture.preserveWidgets();
 
-    grid.getVerticalBar().addSelectionListener( new SelectionAdapter() { } );
+    vScroll.addSelectionListener( new SelectionAdapter() { } );
     lca.renderChanges( grid );
 
     Message message = Fixture.getProtocolMessage();
-    assertEquals( Boolean.TRUE, message.findListenProperty( grid, "scrollBarsSelection" ) );
+    assertEquals( Boolean.TRUE, message.findListenProperty( vScroll, "Selection" ) );
   }
 
   public void testRenderRemoveScrollBarsSelectionListener_Vertical() throws Exception {
+    ScrollBar vScroll = grid.getVerticalBar();
     SelectionListener listener = new SelectionAdapter() { };
-    grid.getVerticalBar().addSelectionListener( listener );
+    vScroll.addSelectionListener( listener );
     Fixture.markInitialized( display );
     Fixture.markInitialized( grid );
+    Fixture.markInitialized( vScroll );
     Fixture.preserveWidgets();
 
-    grid.getVerticalBar().removeSelectionListener( listener );
+    vScroll.removeSelectionListener( listener );
     lca.renderChanges( grid );
 
     Message message = Fixture.getProtocolMessage();
-    assertEquals( Boolean.FALSE, message.findListenProperty( grid, "scrollBarsSelection" ) );
+    assertEquals( Boolean.FALSE, message.findListenProperty( vScroll, "Selection" ) );
   }
 
   public void testRenderScrollBarsSelectionListenerUnchanged_Vertical() throws Exception {
+    ScrollBar vScroll = grid.getVerticalBar();
     Fixture.markInitialized( display );
     Fixture.markInitialized( grid );
+    Fixture.markInitialized( vScroll );
     Fixture.preserveWidgets();
 
-    grid.getVerticalBar().addSelectionListener( new SelectionAdapter() { } );
+    vScroll.addSelectionListener( new SelectionAdapter() { } );
     Fixture.preserveWidgets();
     lca.renderChanges( grid );
 
     Message message = Fixture.getProtocolMessage();
-    assertNull( message.findListenOperation( grid, "scrollBarsSelection" ) );
+    assertNull( message.findListenOperation( vScroll, "Selection" ) );
   }
 
   public void testRenderAddSelectionListener() throws Exception {
@@ -1097,6 +1112,29 @@
     assertEquals( Boolean.TRUE, message.findListenProperty( grid, "Collapse" ) );
   }
 
+  public void testDontRenderSetDataListenerTwice() throws Exception {
+    grid = new Grid( shell, SWT.VIRTUAL | SWT.MULTI );
+    Fixture.markInitialized( display );
+    Fixture.markInitialized( grid );
+    Fixture.preserveWidgets();
+
+    lca.renderChanges( grid );
+
+    Message message = Fixture.getProtocolMessage();
+    assertNull( message.findListenOperation( grid, "SetData" ) );
+  }
+
+  public void testDontRenderSetDataWithoutVirtual() throws Exception {
+    Fixture.markInitialized( display );
+    Fixture.markInitialized( grid );
+    Fixture.preserveWidgets();
+
+    lca.renderChanges( grid );
+
+    Message message = Fixture.getProtocolMessage();
+    assertNull( message.findListenOperation( grid, "SetData" ) );
+  }
+
   //////////////////
   // Helping methods