Dear Isomorphic Team, I'm having trouble with the TileGrid-Component. My UI heavily relies on thsis component, so this is quite urgent and I hope, you can shed some light on a few things, see below.
I've provide a test case for you. I'm working with the latest production build (5.0p) on GWT 2.6, testing on Chrome in Super Dev Mode.
1. RecordContextClick on tiles throws an error
- Related to http://forums.smartclient.com/showthread.php?t=31328&highlight=TileGrid
- An error will be logged to the DevConsole on every RecordContextClick
- On record context click, the respective tile will be selected and the selectionChangedHandler will fire. I have a use case where I want to show a context menu for a tile without the selectionChangedHandler to fire. Unfortunately it is not possible to cancel the recordContextClick-Event without suppressing the context menu at all. How can I accomplish this?
2. Tile Hover Components
- Related to http://forums.smartclient.com/showthread.php?t=30898
- Hover Components work for the TileGrid itself.
- Tile Hover Components will not work when configured setTileProperties-API
- Hover Components do work, when implemented by a child component of SimpleTile, e.g. a DynamicForm
3. Tile Recycling
- UseCase: I'd like to be able to define a tileContructor using the setTileContructor-API and use the updateTile-API to keep my CustomTiles up to date.
- The new createTile-API and updateTile-API are not usable i.e. these two functions exist in the Java-API but NOT in the JavaScript-Modules (see TileGrid.js). Hence, overriding these methods is useless because they will never be called, right? So, what is meant by "If defined, this method will be called when a new tile is required." (from JavaDoc)? Should I use JSNI to define these methods on each TileGrid instance? I guess not. Could you please explain!
- Tile recycling will only work reliably for the internally rendered DetailViewer that is showing tile record data. Have a look at TileGrid #2 in the TestCase.
Here is the TestCase.
It took me some hours to research these questions and elaborate on feasible workarounds, however I'm quite stuck at the moment. I really appreciate your suggestions.
I've provide a test case for you. I'm working with the latest production build (5.0p) on GWT 2.6, testing on Chrome in Super Dev Mode.
1. RecordContextClick on tiles throws an error
- Related to http://forums.smartclient.com/showthread.php?t=31328&highlight=TileGrid
- An error will be logged to the DevConsole on every RecordContextClick
- On record context click, the respective tile will be selected and the selectionChangedHandler will fire. I have a use case where I want to show a context menu for a tile without the selectionChangedHandler to fire. Unfortunately it is not possible to cancel the recordContextClick-Event without suppressing the context menu at all. How can I accomplish this?
Code:
18:31:01.584:MDN3:WARN:Log:Call to Super for method: handleRightMouseDown failed on: [SimpleTile ID:isc_HelloWorld_1_0_tile_3]: couldn't find a superclass implementation of : SimpleTile.handleRightMouseDown [a][c]SimpleTile.invokeSuper(clazz=>null, methodName=>"handleRightMouseDown", a=>undef, b=>undef, c=>undef, d=>undef, e=>undef, f=>undef, g=>undef, h=>undef, i=>undef, j=>undef, lastArg=>undef) @ Class.js:1556:47
[a][c]SimpleTile.Super(methodName=>"handleRightMouseDown", args=>[object Arguments], nativeArguments=>undef) @ Class.js:1404:21
[a]SimpleTile.handleRightMouseDown() @ TileGrid.js:1054:25
[c]EventHandler.bubbleEvent(target=>[SimpleTile ID:isc_HelloWorld_1_0_tile_3], eventType=>"rightMouseDown", eventInfo=>null, targetIsMasked=>false) @ EventHandler.js:5123:44
EventHandler.doHandleMouseDown(DOMevent=>[object MouseEvent], syntheticEvent=>undef) @ EventHandler.js:1810:28
EventHandler.observation() @ Class.js:2476:68
[c]EventHandler.handleMouseDown(DOMevent=>[object MouseEvent], syntheticEvent=>undef) @ EventHandler.js:1643:26
[c]EventHandler.dispatch(handler=>[c]EventHandler.handleMouseDown(), event=>[object MouseEvent]) @ EventHandler.js:6544:34
HTMLDocument.eval(event=>[object MouseEvent]) @ [no file]:3:127
- Related to http://forums.smartclient.com/showthread.php?t=30898
- Hover Components work for the TileGrid itself.
- Tile Hover Components will not work when configured setTileProperties-API
- Hover Components do work, when implemented by a child component of SimpleTile, e.g. a DynamicForm
3. Tile Recycling
- UseCase: I'd like to be able to define a tileContructor using the setTileContructor-API and use the updateTile-API to keep my CustomTiles up to date.
- The new createTile-API and updateTile-API are not usable i.e. these two functions exist in the Java-API but NOT in the JavaScript-Modules (see TileGrid.js). Hence, overriding these methods is useless because they will never be called, right? So, what is meant by "If defined, this method will be called when a new tile is required." (from JavaDoc)? Should I use JSNI to define these methods on each TileGrid instance? I guess not. Could you please explain!
- Tile recycling will only work reliably for the internally rendered DetailViewer that is showing tile record data. Have a look at TileGrid #2 in the TestCase.
Here is the TestCase.
Code:
public class HelloWorld implements EntryPoint {
public static class CustomTileForm extends DynamicForm {
public CustomTileForm() {
super();
setBorder("1px solid black");
setHeight(HEIGHT);
setWidth(WIDTH);
setNumCols(1);
setColWidths("*");
setCanHover(true);
setHoverMoveWithMouse(true);
setShowHoverComponents(true);
FormItem idField = new StaticTextItem(TestRecord.ID);
idField.setShowTitle(false);
FormItem nameField = new StaticTextItem(TestRecord.NAME);
nameField.setShowTitle(false);
setFields(idField, nameField);
}
@Override
public Canvas getHoverComponent() {
return createDefaultHoverComponent("TileForm");
}
}
static class CustomTileGrid extends TileGrid {
public CustomTileGrid() {
super();
setDataSource(new DS());
setBackgroundColor("lightGray");
setBorder("1px solid black");
setWidth(300);
setHeight(300);
setTileHeight(HelloWorld.HEIGHT);
setTileWidth(HelloWorld.WIDTH);
setAutoFetchData(true);
addRecordContextClickHandler(new RecordContextClickHandler() {
private Menu createContextMenu() {
return new Menu();
}
@Override
public void onRecordContextClick(RecordContextClickEvent event) {
setContextMenu(createContextMenu());
}
});
}
}
public static class CustomTileWrapper extends SimpleTile {
private CustomTileForm editor;
public CustomTileWrapper() {
super();
setCanHover(true);
setShowHoverComponents(true);
addDrawHandler(new DrawHandler() {
@Override
public void onDraw(DrawEvent event) {
addChild(getOrCreateEditor());
updateContents(getTileRecord());
}
});
}
@Override
public Canvas getHoverComponent() {
return createDefaultHoverComponent("TileWrapper");
}
public CustomTileForm getOrCreateEditor() {
if (editor == null) {
editor = new CustomTileForm();
}
return editor;
}
public Record getTileRecord() {
return getAttributeAsRecord("record");
}
public void updateContents(Record record) {
getOrCreateEditor().editRecord(record);
}
}
static class DS extends DataSource {
public DS() {
setClientOnly(true);
DataSourceTextField id = new DataSourceTextField(TestRecord.ID);
id.setPrimaryKey(true);
DataSourceTextField name = new DataSourceTextField(TestRecord.NAME);
setFields(id, name);
int recCount = 1000;
Record[] data = new Record[recCount];
for (int i = 0; i < recCount; i++) {
data[i] = new TestRecord(String.valueOf(i), "Name_" + String.valueOf(i));
}
setCacheData(data);
}
}
public static class TestRecord extends Record {
public static final String ID = "id";
public static final String NAME = "name";
public TestRecord(String id, String name) {
setAttribute(ID, id);
setAttribute(NAME, name);
}
}
public interface TileMetaFactory extends BeanFactory.MetaFactory {
BeanFactory<CustomTileWrapper> getCustomTileWrapper();
}
static int HEIGHT = 120;
static int WIDTH = 120;
public static Canvas createDefaultHoverComponent(String contents) {
Canvas canvas = new Canvas();
canvas.setContents("Hover Generated by " + contents);
return canvas;
}
@Override
public void onModuleLoad() {
HLayout testLayout = new HLayout(10);
//use default approach with TileProperties-Config
final TileGrid tg1 = new CustomTileGrid() {
@Override
public Canvas getHoverComponent() {
return createDefaultHoverComponent("TileGrid#1");
}
};
tg1.setCanHover(true);
tg1.setShowHoverComponents(true);
Canvas c = new Canvas() {
@Override
public Canvas getHoverComponent() {
//WILL NOT WORK
return createDefaultHoverComponent("Plain Old SimpleTile");
}
};
c.setCanHover(true);
c.setShowHoverComponents(true);
tg1.setTileProperties(c);
//use factory-based approach
GWT.create(TileMetaFactory.class);
final TileGrid tg2 = new CustomTileGrid() {
@Override
public Canvas getHoverComponent() {
return createDefaultHoverComponent("TileGrid#2");
}
//WILL NEVER BE CALLED, BECAUSE NEITHER updateTile(..) NOR createTile(..) are defined on the TileGrid Instance.
//However, HOW SHOULD THESE METHODS BE DEFINED?
@Override
public void updateTile(Record record, Integer tileIndex, Canvas reclaimedTile) {
CustomTileWrapper wrapper = (CustomTileWrapper) reclaimedTile;
wrapper.updateContents(record);
}
};
tg2.setCanHover(true);
tg2.setShowHoverComponents(true);
tg2.setTileConstructor(CustomTileWrapper.class.getName());
testLayout.addMember(tg1);
testLayout.addMember(tg2);
testLayout.draw();
}
}
It took me some hours to research these questions and elaborate on feasible workarounds, however I'm quite stuck at the moment. I really appreciate your suggestions.