PDA

View Full Version : Use of setData() method



obender
5 Jun 2008, 12:21 PM
I've noticed that many containers and other controls use setData() method.
Can anyone clarify this?
Why for example the sample code uses it this way:


ContentPanel panel = new ContentPanel();
...
BorderLayoutData data = new BorderLayoutData(LayoutRegion.WEST, 150, 100, 250);
panel.setData(data);

gslender
5 Jun 2008, 1:21 PM
cheat instead of calling setLayout which does the same thing

obender
5 Jun 2008, 1:40 PM
thanks, good to know I thought I need to change my old code.

flow
5 Jun 2008, 11:02 PM
Didn't the method setData(Object) already cause some confusion previously? AFAIK (and gslender wrote something along the line) it's only used to set the LayoutData. Shouldn't it then be removed from Component and replaced by a more "speaking" method?
Or can it be used in other fashions, too?

gslender
5 Jun 2008, 11:36 PM
Sorry, sorry, sorry - I wrong...

setData is setting the layout data, not the layout.

add(widget, layoutdata) of a container eventually calls


public boolean insert(Widget widget, int index, Object layoutData) {
Component component = wrapWidget(widget);
boolean added = super.insert(component, index);
if (added && layoutData != null) {
component.setData(layoutData); // <<<<<<<< see here
}
return added;
}

which when laying-out, the data is used to determine hints...

meessa sorry

flow
5 Jun 2008, 11:41 PM
Thou shall be forgiven ;)
But I still don't get it completely, why the method setData is used instead of Widget#setLayoutData. I guess this is related to the fact, that "hints" might be LayoutData, but also something magical else.

Grandiosa
6 Jun 2008, 3:03 AM
Issue was raised earlier, reply from Darrel here (http://mygwt.net/forum/viewtopic.php?t=1187&highlight=setdata)...

I don't quite understand why the setData method isn't called setLayoutData instead

obender
6 Jun 2008, 5:28 AM
How about the following code:


public class AccordionLayoutPage extends ContentPanel implements EntryPoint {
public AccordionLayoutPage() {
setData("layout", new FlowLayout(10));
...
}
}

Why!?
Why not just:


...
public AccordionLayoutPage() {
setLayout(new FlowLayout(10));
...
}

Grandiosa
6 Jun 2008, 7:40 AM
The setData statment doesn't set the layout of the AccordianLayoutPage, but your suggestion would.

So what is the purpose of the setData statement in this particular example?
I believe it's just a way to let the example pages like AccordianLayoutPage to know themselves what layout their parent container must use for them.

The setData call stores a layout object as a generic data element on the AccordianLayoutPage component. In the explorer sample this is then picked up later to set the layout of AccordianLayoutPage's parent container, i.e. the TabItem which contains it. If you look in the constructor for the Page class you'll see:


TabItem demo = new TabItem();

Layout l = (Layout) content.getData("layout");
if (l != null) {
demo.setLayout(l);
}
Note, the Page class is the bottom-aligned TabPanel in explorer (the one containing the Demo and Source tabs). Using this technique the TabItems in the Page class does not need to know how to layout all the example pages, it simply checks if its example content has a "layout" data element, and will use that as a layout if its present.
Among all the examples it's only the Layout examples that uses this mechanism. The other examples just rely on the default layout of their parent container, thus a FlowLayout

obender
6 Jun 2008, 8:25 AM
ok, thanks, as long as the old way works it is quite fine.

zaccret
11 Jun 2008, 10:15 PM
The data attribute seems to be used for generic stuff, not only for layoutdata. For example, in tree items, it contains the model associated with the item.

Grandiosa
11 Jun 2008, 11:41 PM
Yes, as I did mention that in my previous post..


The setData call stores a layout object as a generic data element Components have two ways to host "data" elements. From GXT Component class source:



private Object data;
private HashMap dataMap;
While the method Component.setData(String,Object) can be used to store any data on your component, the setData(Object) should only be used to specify layout data for a component.

Each of GXT's layout's will pick up this data in their onLayout() method, for example in RowLayout class, you can find:

RowData data = (RowData) c.getData();


This implies that the single data item on Component only should be used for layout data, or else the statement above will throw a runtime cast exception.

That's why I thought it would be better to rename the setData(Object) and getData(Object) methods accordingly.

zaccret
17 Jun 2008, 10:31 PM
So what you suggest is refactoring :

public Object getData()
public void setData(Object)to

public LayoutData getLayoutData()
public void setLayoutData(LayoutData)and then list/table/tree binders should use instead getData("model") and setData("model", object) for getting models ?

Grandiosa
18 Jun 2008, 1:06 AM
Yes, that is what I meant.


and then list/table/tree binders should use instead getData("model") and setData("model", object) for getting models ?
I wasn't aware of that the binders use the setData/getData methods until you wrote this :-)
I don't really care what GXT is doing internally, I just found their usage confusing in the example code. I prefer to use more intuitive convenience method Container.add(Widget, LayoutData) to set the layout data.

cheers!

zaccret
18 Jun 2008, 1:47 AM
Agree.

Darell, I think that the explorer and mail demos should use Container.add(Widget, Object) instead of Component.setData(layoutData).

Actually, it would be nice to have a LayoutData interface/class and refactor Container.add(Widget, Object) to Container.add(Widget, LayoutData) but if the interface is just a marker (empty interface), maybe it is not really pertinent.

At first, an end user like me (us) doesn't see what is the purpose of the setData(Object) method, so it should be either not public or refactored to setLayoutData(Object/LayoutData) (and of course do the same for getData).

sdc
25 Jun 2008, 1:32 AM
Darell, I think at least it would be nice to specify in the javadoc that the getData/setData are essentially for internal purposes, I think that we (end users) should not use these methods, I guess we always have a more elegant alternative.

darrellmeyer
25 Jun 2008, 6:44 AM
I have made the following changes:

1. LayoutData in a abstract base class for all layout data.
2. LayoutContainer add / insert take LayoutData not Object.
3. Added setLayoutData / getLayoutData to Component.
4. Added setModel / getModel to Component.
5. Component setData now asserts that object is not a LayoutData or ModelData instance.
6. Updated all library and sample code to use new API.

How does that work for everyone?

sdc
25 Jun 2008, 8:25 AM
Wow, you made a lot of job =D> Let's answer.


I have made the following changes:

1. LayoutData in a abstract base class for all layout data.
2. LayoutContainer add / insert take LayoutData not Object.

I think this is nice and will enhance the use of layouts.


3. Added setLayoutData / getLayoutData to Component.
4. Added setModel / getModel to Component.I don't really know about the public model getter/setter, in my app I always avoid to get the model from a Component, I think it is better to directly work with models in Store and StoreBinder. The same for layout getter/setter, I think it is better to use LayoutContainer.add(widget,layoutdata). However, the method signatures are explicit, so that's OK for me.


5. Component setData now asserts that object is not a LayoutData or ModelData instance.I think you should completely REMOVE the data Object property, it has no more use now and it is really a source of confusion.
If you still want to keep the property, as long as the setter method is public, you cannot ASSERT that the user will not give LayoutData or ModelData param, IMHO you should rather throw IllegalArgumentException.


6. Updated all library and sample code to use new API.Great job, Darell, and thanks again ;)

darrellmeyer
25 Jun 2008, 9:32 AM
Ok, you raised some good points and I have made a few more changes. I have always been a little unhappy with the data and layout data methods, so I decided to make these changes now before 1.0 goes out the door.


I don't really know about the public model getter/setter, in my app I always avoid to get the model from a Component, I think it is better to directly work with models in Store and StoreBinder. The same for layout getter/setter, I think it is better to use LayoutContainer.add(widget,layoutdata). However, the method signatures are explicit, so that's OK for me.setLayoutData and getLayoutData are protected, which means layout data can now only be specified when adding to the container. This makes more sense, as the layout data is used with the layout of the container and not the widget itself.

setModel is now protected and only used internally. I left getModel public as sometimes it is useful to get the model from a component. Although, I agree with your comments and this is done ideally through the store and binder.


I think you should completely REMOVE the data Object property, it has no more use now and it is really a source of confusion.
If you still want to keep the property, as long as the setter method is public, you cannot ASSERT that the user will not give LayoutData or ModelData param, IMHO you should rather throw IllegalArgumentException.setData(Object) / getData() are deprectated and will be removed at a later time. I changed the asserts to IllegalArgumentException.

The changes are in SVN.

sdc
25 Jun 2008, 10:10 PM
Ok, you raised some good points and I have made a few more changes. I have always been a little unhappy with the data and layout data methods, so I decided to make these changes now before 1.0 goes out the door.I'm glad to see that we agree about the data methods. Let me also say that it was not criticism, I just give you my concerns as an end user and I hope it helps you to enhance the API.


setLayoutData and getLayoutData are protected, which means layout data can now only be specified when adding to the container. This makes more sense, as the layout data is used with the layout of the container and not the widget itself.

setModel is now protected and only used internally. I left getModel public as sometimes it is useful to get the model from a component. Although, I agree with your comments and this is done ideally through the store and binder.
setData(Object) / getData() are deprectated and will be removed at a later time. I changed the asserts to IllegalArgumentException.

The changes are in SVN.100% agree. GREAT JOB, THANKS =D>

darrellmeyer
25 Jun 2008, 10:32 PM
I'm glad to see that we agree about the data methods. Let me also say that it was not criticism, I just give you my concerns as an end user and I hope it helps you to enhance the API.No worries, I appreciate any feedback. If the feedback makes sense, which it did in this case, I am happy to update things to make the API clearer and easier to use. There will be a bunch of new code in 1.1, so keep the comments coming :).

Grandiosa
26 Jun 2008, 3:43 AM
Nice "cleanup" !

flow
27 Jun 2008, 12:41 AM
Mh, thinking about the setModel and its modifier. I guess it's more in the streamline of the whole architecture, to use a Store and a StoreBinder to set the model of a component. But in my case (and I guess there could be some more guys out there, who want to be free in their design) I want to create a TableItem directly and thus set the model. (btw. the static method WidgetHelper.setModel(Component, ModelData) does something like this, eh?)

Another thing is the deprecation of the Component#setData. Now there is a setData(String, Object). Will this method be remove, too, or what might be use cases of it?

darrellmeyer
27 Jun 2008, 6:24 AM
Another thing is the deprecation of the Component#setData. Now there is a setData(String, Object). Will this method be remove, too, or what might be use cases of it?
Looking back, the API should not have been changed since we are at a release candidate. The only changes going forward will be bug fixes. The setData(String, Object) method will not be removed. You should use this method to set any "user defined" data on any component. With the latest changes, GXT does not use setData, so you are free to use any keys for your data.

flow
27 Jun 2008, 7:26 AM
Thanks for the info!!