Add BarChart widget and snippet

Create a basic BarChart based on nv's discreteBarChart.
Add a snippet and include it in ChartSnippetPage.

Change-Id: Ie925151c8ae8e68913eee41b7c2bdb1caf22b464
diff --git a/bundles/org.eclipse.rap.addons.chart/js/chart/nv/nv-bar.js b/bundles/org.eclipse.rap.addons.chart/js/chart/nv/nv-bar.js
new file mode 100644
index 0000000..3268982
--- /dev/null
+++ b/bundles/org.eclipse.rap.addons.chart/js/chart/nv/nv-bar.js
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (c) 2016 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:
+ *    Ralf Sternberg - initial API and implementation
+ ******************************************************************************/
+
+rwt.chart.register( "nv-bar", function( widget ) {
+  var chart = nv.models.discreteBarChart()
+    .x( function( d ) { return d.label; } )
+    .y( function( d ) { return d.value; } )
+    .showValues( true );
+  chart.discretebar.dispatch.on( "elementClick.rap", function( item ) {
+    widget.notifySelection( item.index );
+  });
+  return chart;
+});
diff --git a/bundles/org.eclipse.rap.addons.chart/src/org/eclipse/rap/addons/chart/basic/BarChart.java b/bundles/org.eclipse.rap.addons.chart/src/org/eclipse/rap/addons/chart/basic/BarChart.java
new file mode 100644
index 0000000..291db0e
--- /dev/null
+++ b/bundles/org.eclipse.rap.addons.chart/src/org/eclipse/rap/addons/chart/basic/BarChart.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2016 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:
+ *    Ralf Sternberg - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.rap.addons.chart.basic;
+
+import org.eclipse.rap.addons.chart.NvChart;
+import org.eclipse.swt.widgets.Composite;
+
+
+public class BarChart extends NvChart {
+
+  private boolean showValues = true;
+
+  public BarChart( Composite parent, int style ) {
+    super( parent, style, "nv-bar" );
+    requireJs( registerResource( "chart/nv/nv-bar.js" ) );
+  }
+
+  public void setShowValues( boolean show ) {
+    checkWidget();
+    if( show != showValues ) {
+      showValues = show;
+      setOption( "showValues", show );
+    }
+  }
+
+  public boolean getShowValues() {
+    checkWidget();
+    return showValues;
+  }
+
+}
diff --git a/examples/org.eclipse.rap.addons.chart.demo/src/org/eclipse/rap/addons/chart/nv/demo/BarChartSnippet.java b/examples/org.eclipse.rap.addons.chart.demo/src/org/eclipse/rap/addons/chart/nv/demo/BarChartSnippet.java
new file mode 100644
index 0000000..62544b0
--- /dev/null
+++ b/examples/org.eclipse.rap.addons.chart.demo/src/org/eclipse/rap/addons/chart/nv/demo/BarChartSnippet.java
@@ -0,0 +1,86 @@
+/*******************************************************************************
+ * Copyright (c) 2016 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:
+ *    Ralf Sternberg - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.rap.addons.chart.nv.demo;
+
+import org.eclipse.rap.addons.chart.basic.BarChart;
+import org.eclipse.rap.json.JsonArray;
+import org.eclipse.rap.json.JsonObject;
+import org.eclipse.rap.rwt.application.AbstractEntryPoint;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+
+
+public class BarChartSnippet extends AbstractEntryPoint {
+
+  private BarChart barChart;
+
+  @Override
+  public void createContents( Composite parent ) {
+    parent.setLayout( new GridLayout() );
+    createBarChart( parent );
+    createUpdateButton( parent );
+    update();
+  }
+
+  private void createBarChart( Composite parent ) {
+    barChart = new BarChart( parent, SWT.NONE );
+    barChart.setLayoutData( new GridData( SWT.FILL, SWT.FILL, true, true ) );
+    barChart.setShowValues( true );
+    barChart.addListener( SWT.Selection, new Listener() {
+      @Override
+      public void handleEvent( Event event ) {
+        System.out.println( "Selected bar item #" + event.index );
+      }
+    } );
+  }
+
+  private void createUpdateButton( Composite parent ) {
+    Button button = new Button( parent, SWT.PUSH );
+    button.setText( "Change data" );
+    button.addListener( SWT.Selection, new Listener() {
+      @Override
+      public void handleEvent( Event event ) {
+        update();
+      }
+    } );
+  }
+
+  private void update() {
+    barChart.setChartData( createData() );
+  }
+
+  private static JsonArray createData() {
+    return new JsonArray()
+      .add( new JsonObject().add( "key", "foo" ).add( "values", createRandomValues() ) );
+  }
+
+  private static JsonArray createRandomValues() {
+    return new JsonArray()
+      .add( createItem( "Item 1", "#ff0000", Math.random() * 100 ) )
+      .add( createItem( "Item 2", "#00ff00", Math.random() * 100 ) )
+      .add( createItem( "Item 3", "#0000ff", Math.random() * 100 ) )
+      .add( createItem( "Item 4", "#ffff00", Math.random() * 100 ) )
+      .add( createItem( "Item 5", "#00ffff", Math.random() * 100 ) );
+  }
+
+  private static JsonObject createItem( String text, String color, double value ) {
+    return new JsonObject()
+      .add( "label", text )
+      .add( "color", color )
+      .add( "value", value );
+  }
+
+}
diff --git a/examples/org.eclipse.rap.addons.chart.demo/src/org/eclipse/rap/addons/chart/nv/demo/ChartSnippetPage.java b/examples/org.eclipse.rap.addons.chart.demo/src/org/eclipse/rap/addons/chart/nv/demo/ChartSnippetPage.java
index f8d3d13..76ebc92 100644
--- a/examples/org.eclipse.rap.addons.chart.demo/src/org/eclipse/rap/addons/chart/nv/demo/ChartSnippetPage.java
+++ b/examples/org.eclipse.rap.addons.chart.demo/src/org/eclipse/rap/addons/chart/nv/demo/ChartSnippetPage.java
@@ -22,11 +22,20 @@
 
   @Override
   public void createContents( Composite parent ) {
-    parent.setLayout( new GridLayout() );
+    parent.setLayout( new GridLayout( 2, true ) );
+    createBarChart( parent );
     createPieChart( parent );
     createLineChart( parent );
   }
 
+  private static void createBarChart( Composite parent ) {
+    Composite composite = new Composite( parent, SWT.NONE );
+    composite.setLayoutData( new GridData( SWT.FILL, SWT.FILL, true, true ) );
+    composite.setBackground( new Color( parent.getDisplay(), 250, 250, 250 ) );
+    composite.setBackgroundMode( SWT.INHERIT_DEFAULT );
+    new BarChartSnippet().createContents( composite );
+  }
+
   private static void createPieChart( Composite parent ) {
     Composite composite = new Composite( parent, SWT.NONE );
     composite.setLayoutData( new GridData( SWT.FILL, SWT.FILL, true, true ) );
@@ -37,7 +46,7 @@
 
   private static void createLineChart( Composite parent ) {
     Composite composite = new Composite( parent, SWT.NONE );
-    composite.setLayoutData( new GridData( SWT.FILL, SWT.FILL, true, true ) );
+    composite.setLayoutData( new GridData( SWT.FILL, SWT.FILL, true, true, 2, 1 ) );
     composite.setBackground( new Color( parent.getDisplay(), 250, 250, 250 ) );
     composite.setBackgroundMode( SWT.INHERIT_DEFAULT );
     new LineChartSnippet().createContents( composite );
diff --git a/tests/org.eclipse.rap.addons.chart.test/src/org/eclipse/rap/addons/chart/basic/BarChart_Test.java b/tests/org.eclipse.rap.addons.chart.test/src/org/eclipse/rap/addons/chart/basic/BarChart_Test.java
new file mode 100644
index 0000000..069ad1e
--- /dev/null
+++ b/tests/org.eclipse.rap.addons.chart.test/src/org/eclipse/rap/addons/chart/basic/BarChart_Test.java
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * Copyright (c) 2016 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:
+ *    Ralf Sternberg - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.rap.addons.chart.basic;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+
+import org.eclipse.rap.json.JsonObject;
+import org.eclipse.rap.rwt.internal.remote.ConnectionImpl;
+import org.eclipse.rap.rwt.remote.Connection;
+import org.eclipse.rap.rwt.remote.RemoteObject;
+import org.eclipse.rap.rwt.testfixture.TestContext;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+
+@SuppressWarnings( "restriction" )
+public class BarChart_Test {
+
+  private Display display;
+  private Shell shell;
+  private RemoteObject remoteObject;
+  private Connection connection;
+  private BarChart chart;
+
+  @Rule
+  public TestContext context = new TestContext();
+
+  @Before
+  public void setUp() {
+    display = new Display();
+    shell = new Shell( display );
+    remoteObject = mock( RemoteObject.class );
+    connection = fakeConnection( remoteObject );
+    chart = new BarChart( shell, SWT.NONE );
+  }
+
+  @Test
+  public void testCreate_createsRemoteObject() {
+    verify( connection ).createRemoteObject( eq( "rwt.chart.Chart" ) );
+  }
+
+  @Test
+  public void testCreate_setsRenderer() {
+    verify( remoteObject ).set( "renderer", "nv-bar" );
+  }
+
+  @Test
+  public void testGetShowValues_defaultsToTrue() {
+    assertTrue( chart.getShowValues() );
+  }
+
+  @Test
+  public void testSetShowValues_changesValue() {
+    chart.setShowValues( false );
+
+    assertFalse( chart.getShowValues() );
+  }
+
+  @Test
+  public void testSetShowValues_isRendered() {
+    reset( remoteObject );
+
+    chart.setShowValues( false );
+
+    verify( remoteObject ).call( "setOptions", new JsonObject().add( "showValues", false ) );
+  }
+
+  private Connection fakeConnection( RemoteObject remoteObject ) {
+    ConnectionImpl connection = mock( ConnectionImpl.class );
+    when( connection.createRemoteObject( anyString() ) ).thenReturn( remoteObject );
+    when( connection.createServiceObject( anyString() ) ).thenReturn( mock( RemoteObject.class ) );
+    context.replaceConnection( connection );
+    return connection;
+  }
+
+}