Sunday, April 28, 2013

CellTable created in onModuleLoad() doesn't draw until mouse moves over the browser window

package com.redbottledesign.continuum.timer.client.json;

import java.util.Date;

import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.i18n.shared.DateTimeFormat;

public class TimeEntry
extends JavaScriptObject
{
private static final DateTimeFormat DRUPAL_DATE_FORMAT = DateTimeFormat.getFormat("y-M-d H:m:s z");

public static final native JsArray<TimeEntry> fromJavascriptObject(JavaScriptObject object)
/*-{
return object;
}-*/;

public static final native JsArray<TimeEntry> fromJsonArray(String json)
/*-{
return eval(json);
}-*/;

public static final native TimeEntry fromJson(String json)
/*-{
return eval('(' + json + ')');
}-*/;

protected TimeEntry()
{
}

/* JSNI methods. */
public final native int getId()
/*-{
return parseInt(this.nid);
}-*/;

public final native int getRevision()
/*-{
return parseInt(this.vid);
}-*/;

public final native int getUserId()
/*-{
return parseInt(this.uid);
}-*/;

public final native String getTitle()
/*-{
return this.title;
}-*/;

public final Date getStartTime()
{
return parseDrupalDate(this.getStartTimeRaw());
}

public final Date getStopTime()
{
return parseDrupalDate(this.getStopTimeRaw());
}

protected static Date parseDrupalDate(String drupalDate)
{
Date result = null;

if ((drupalDate != null) && !drupalDate.isEmpty())
result = DRUPAL_DATE_FORMAT.parse(drupalDate + " UTC");

return result;
}

protected final native String getStartTimeRaw()
/*-{
var language = @com.redbottledesign.continuum.timer.shared.DrupalConstants::LANGUAGE_NONE;

return this.field_time_entry_date[language][0].value;
}-*/;

protected final native String getStopTimeRaw()
/*-{
var language = @com.redbottledesign.continuum.timer.shared.DrupalConstants::LANGUAGE_NONE;

return this.field_time_entry_date[language][0].value2;
}-*/;
}
package com.redbottledesign.continuum.timer.client;

import java.util.Comparator;
import java.util.List;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.user.cellview.client.CellTable;
import com.google.gwt.user.cellview.client.Column;
import com.google.gwt.user.cellview.client.ColumnSortEvent.ListHandler;
import com.google.gwt.user.cellview.client.TextColumn;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.view.client.ListDataProvider;
import com.redbottledesign.continuum.timer.client.json.TimeEntry;

public class Timer
implements EntryPoint
{
private static final String JSON_URL = "http://continuum.localhost:8082/timer/1.0/entry.jsonp?parameters[type]=time_entry&fields=title,nid,vid,uid,field_time_entry_date";

private Label errorMsgLabel;
private FlowPanel mainPanel;
private CellTable<TimeEntry> timeEntryTable;

@Override
public void onModuleLoad()
{
this.setupComponents();

this.getJson(0, JSON_URL);
}

protected void setupComponents()
{
this.errorMsgLabel = new Label();

this.errorMsgLabel.setStyleName("errorMessage");
this.errorMsgLabel.setVisible(false);

this.mainPanel = new FlowPanel();

mainPanel.add(errorMsgLabel);

// Associate the Main panel with the HTML host page.
RootPanel.get("time-entry-list").add(mainPanel);
}

protected void setupTable(JsArray<TimeEntry> timeEntries)
{
Column<TimeEntry,String> titleColumn,
startTimeColumn,
stopTimeColumn;
ListDataProvider<TimeEntry> dataProvider;
List<TimeEntry> entryList;
ListHandler<TimeEntry> titleSortHandler,
startTimeSortHandler,
stopTimeSortHandler;

if (this.timeEntryTable != null)
this.mainPanel.remove(this.timeEntryTable);

this.timeEntryTable = new CellTable<TimeEntry>();

titleColumn = new TextColumn<TimeEntry>()
{
@Override
public String getValue(TimeEntry entry)
{
return entry.getTitle();
}
};

startTimeColumn = new TextColumn<TimeEntry>()
{
@Override
public String getValue(TimeEntry entry)
{
return entry.getStartTime().toString();
}
};

stopTimeColumn = new TextColumn<TimeEntry>()
{
@Override
public String getValue(TimeEntry entry)
{
return entry.getStopTime().toString();
}
};

titleColumn.setSortable(true);
startTimeColumn.setSortable(true);
stopTimeColumn.setSortable(true);

this.timeEntryTable.addColumn(titleColumn, "Title");
this.timeEntryTable.addColumn(startTimeColumn, "Start time");
this.timeEntryTable.addColumn(stopTimeColumn, "Stop time");

dataProvider = new ListDataProvider<TimeEntry>();

dataProvider.addDataDisplay(this.timeEntryTable);

entryList = dataProvider.getList();

for (int entryIndex = 0; entryIndex < timeEntries.length(); ++entryIndex)
{
entryList.add(timeEntries.get(entryIndex));
}

titleSortHandler = new ListHandler<TimeEntry>(entryList);
startTimeSortHandler = new ListHandler<TimeEntry>(entryList);
stopTimeSortHandler = new ListHandler<TimeEntry>(entryList);

titleSortHandler.setComparator(
titleColumn,
new Comparator<TimeEntry>()
{
@Override
public int compare(TimeEntry first, TimeEntry second)
{
if (first == second)
return 0;

else if (first != null)
return (second != null) ? first.getTitle().compareTo(second.getTitle()) : 1;

else
return -1;
}
});

startTimeSortHandler.setComparator(
startTimeColumn,
new Comparator<TimeEntry>()
{
@Override
public int compare(TimeEntry first, TimeEntry second)
{
if (first == second)
return 0;

else if (first != null)
return (second != null) ? first.getStartTime().compareTo(second.getStartTime()) : 1;

else
return -1;
}
});

stopTimeSortHandler.setComparator(
stopTimeColumn,
new Comparator<TimeEntry>()
{
@Override
public int compare(TimeEntry first, TimeEntry second)
{
if (first == second)
return 0;

else if (first != null)
return (second != null) ? first.getStopTime().compareTo(second.getStopTime()) : 1;

else
return -1;
}
});

this.timeEntryTable.addColumnSortHandler(titleSortHandler);
this.timeEntryTable.addColumnSortHandler(startTimeSortHandler);
this.timeEntryTable.addColumnSortHandler(stopTimeSortHandler);

this.timeEntryTable.getColumnSortList().push(titleColumn);

this.mainPanel.add(this.timeEntryTable);

// FIXME: Why is this necessary?
com.google.gwt.user.client.Timer timer = new com.google.gwt.user.client.Timer()
{
@Override
public void run()
{
Timer.this.timeEntryTable.redraw();
}
};

timer.schedule(100);
}

/**
* Make call to remote server.
*/
protected native void getJson(int requestId, String url) /*-{
var callbackId = "callback" + requestId;
var callbackParam = "&callback=" + callbackId;
var script = document.createElement("script");
var handler = this;

script.setAttribute("src", url + callbackParam);
script.setAttribute("type", "text/javascript");

window[callbackId] = function(jsonObj) {
handler.@com.redbottledesign.continuum.timer.client.Timer::handleJsonResponse(Lcom/google/gwt/core/client/JavaScriptObject;)(jsonObj);
window[callbackId + "done"] = true;
}

setTimeout(function() {
if (!window[callbackId + "done"]) {
handler.@com.redbottledesign.continuum.timer.client.Timer::handleJsonResponse(Lcom/google/gwt/core/client/JavaScriptObject;)(null);
}

document.body.removeChild(script);

delete window[callbackId];
delete window[callbackId + "done"];
}, 5000);

document.body.appendChild(script);
}-*/;

/**
* Handle the response to the request from a remote server.
*/
public void handleJsonResponse(JavaScriptObject result) {
if (result == null)
displayError("Couldn't retrieve JSON");

else
Timer.this.setupTable(TimeEntry.fromJavascriptObject(result));

}

/**
* If can't get JSON, display error message.
* @param error
*/
protected void displayError(String error) {
errorMsgLabel.setText("Error: " + error);
errorMsgLabel.setVisible(true);
}
}Hey all,

I'm working with some code that was modeled after the StockWatch sample for JSONP. A key difference between that code and mine is that the JSON data is loaded immediately on module load rather than on a button click.

I'm finding that my CellTable doesn't render completely until I move the mouse over the page. A workaround is to schedule a timer for 100 milliseconds after the table is added to the page that just calls redraw() on the table, but this seems like a hack.

Anyone know why the table demonstrates this behavior?

The code is attached.

--
You received this message because you are subscribed to the Google Groups "Google Web Toolkit" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-web-toolkit+unsubscribe@googlegroups.com.
To post to this group, send email to google-web-toolkit@googlegroups.com.
Visit this group at http://groups.google.com/group/google-web-toolkit?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

No comments:

Post a Comment