views:

549

answers:

2

I'm working on learning GWT (total newb) and have a question regarding the Visualiztion API provided by Google. This page: http://code.google.com/p/gwt-google-apis/wiki/VisualizationGettingStarted

Describes getting started with a pie chart (which is what I need). However I'm trying to do this in a composite UI using UiBinder. To that end I don't know how to handle the callback correctly that is shown:

public class SimpleViz implements EntryPoint {
  public void onModuleLoad() {
    // Create a callback to be called when the visualization API
    // has been loaded.
    Runnable onLoadCallback = new Runnable() {
      public void run() {
        Panel panel = RootPanel.get();

        // Create a pie chart visualization.
        PieChart pie = new PieChart(createTable(), createOptions());

        pie.addSelectHandler(createSelectHandler(pie));
        panel.add(pie);
      }
    };

    // Load the visualization api, passing the onLoadCallback to be called
    // when loading is done.
    VisualizationUtils.loadVisualizationApi(onLoadCallback, PieChart.PACKAGE);
  }

My First assumption is this would go in the UiBinder constructor, correct? Yet this assumes that I want to place the element in the RootLayoutPanel, and I don't. I can't see an elegant and obvious way of placing it in the binder. I submit that even this guess may be wrong. Any ideas from the experts?

EDIT: I should make clear my attempt:

    public GraphPanel() {
        initWidget(uiBinder.createAndBindUi(this));

        Runnable onLoadCallback = new Runnable() {  
            public void run() {
              //LayoutPanel panel = RootPanel.

              // Create a pie chart visualization.
              PieChart pie = new PieChart(createPieTable(), createPieOptions());
              pie.addSelectHandler(createSelectHandler(pie));
              mySelf.getElement().appendChild(pie.getElement());   // .add(pie);
            }
          };

          // Load the visualization api, passing the onLoadCallback to be called
          // when loading is done.
          VisualizationUtils.loadVisualizationApi(onLoadCallback, PieChart.PACKAGE);
    }

When run I get the following in the Composites DIV:

<div class="gwt-viz-container"></div>

But I see no graph using the code from the above page.

EDIT 2: This link may provide additional information. However, the solution suggested is not optimal since the app then needs to know more about the widget (and if the widget is even there). http://vaadin.com/forum/-/message_boards/message/97850

EDIT 3: It shouldn't matter, but just in case, I'm running FF on Linux. Some articles I've read have implied that this is a problem.

EDIT 4: Adding:

pie.draw(createPieTable(), createPieOptions());

after the append child gets the graph to display. This implies that the ordering of the example is wrong. If so what is the optimum?

+1  A: 

Either way you suggest would work. If the Visualization API is used by a bunch of different widgets on the page, then it might be simpler to put the loadVisualizationApi call in the EntryPoint class - an example of this is below.

You can write the Composite like so:

public MyPieChartContainer extends Composite {
  interface MyUiBinder extends UiBinder<Widget, MyPieChartContainer>;
  private static MyUiBinder uiBinder = GWT.create(MyUiBinder.class);

  @UiField Panel panel;

  public MyPieChartContainer() {
    initWidget(uiBinder.createAndBindUi(this));

    PieChart pie = new PieChart(createTable(), createOptions());
    pie.addSelectHandler(createSelectHandler(pie));
    panel.add(pie);
  }
}

And then do this in the EntryPoint:

public class SimpleViz implements EntryPoint {
  public void onModuleLoad() {
    // Create a callback to be called when the visualization API
    // has been loaded.
    Runnable onLoadCallback = new Runnable() {
      public void run() {
        Panel panel = RootPanel.get();
        MyPieChartContainer myPieChartContainer = new MyPieChartContainer();    
        panel.add(myPieChartContainer);
      }
    };

    // Load the visualization api, passing the onLoadCallback to be called
    // when loading is done.
    VisualizationUtils.loadVisualizationApi(onLoadCallback, PieChart.PACKAGE);
  }
aem
Wouldn't this imply a single chart if I do this in EntryPoint?
nick
I don't see why doing the initialization in EntryPoint implies a single chart - just imagine this implementation of the run method: public void run() { Panel panel = RootPanel.get(); MyPieChartContainer myPieChartContainer1 = new MyPieChartContainer(); panel.add(myPieChartContainer1); MyPieChartContainer myPieChartContainer2 = new MyPieChartContainer(); panel.add(myPieChartContainer2); }
aem
+1  A: 

It is also important to know that although the GWT JRE Emulation library supports the Runnable interface, it can't really be used for parallel processing in a separate thread, as the code is compiled into JavaScript which in turn runs single-threaded in the browser. Same goes for the synchronized keyword.

I also would recommend doing all preparation logic in the Widget/Composite's constructor but any actual drawing in the onLoad callback, which you need to override. This callback is called when the widget is loaded in the browser document, it is only then that you can perform any page/layout interaction, like enabling/disabling controls or requesting focus.

Jeroen
Voting you both up but giving the check here as I think this was key for my problem. Thanks for the help both of you.
nick