How do I call setParent without inheriting from Panel or Composite?

135 views
Skip to first unread message

Diego

unread,
Aug 14, 2008, 6:59:12 PM8/14/08
to Google Web Toolkit
I have extended Widget to create my own widget consisting in two lists
and some buttons to move items back and forth.

The lists extends Panel, and each item has an ClickListener that fires
when the user clicks on them. The listener updates the internal state
of the list to reflect selected items and such.

To do the layout I opted to create the HTML elements using DOM
manipulation directly instead of composing with Table or SimplePanel.
The code is like this (called from the constructor and minimalized for
clarity):

setElement(DOM.createDiv());
Element table = DOM.createTable();
Element tdLeft = DOM.createTD();
DOM.appendChild(tdLeft, getLeftList().getElement());
Element tr = DOM.createTR();
DOM.appendChild(tr, tdLeft);
DOM.appendChild(table, tr);
DOM.appendChild(getElement(), table);

The problem I encountered is how to make the list call the onAttach()
of its children. Calling setParent() would do the trick, but it's
package local.

I know I could inherit from panel, but implementing HasWidgets in my
widget doesn't make sense, as it has no widgets the user can access,
add or remove. On the other hand, as I am building my own HTML layout
using DOM, I don't have a widget to call setWidget() if I chose to
extend Composite.

Am I wrong to extend widget directly? What is the rationale behind the
scope of setParent()?

walden

unread,
Aug 15, 2008, 8:17:07 AM8/15/08
to Google Web Toolkit
I think you want to extend Composite; did you notice the initWidget()
call there?

Diego

unread,
Aug 15, 2008, 6:15:25 PM8/15/08
to Google Web Toolkit
Yes, I did. Composite.setWidget() calls Composite.initWidget()
internally. Anyway, I need a single widget for that and in my scenario
I don't have one. Composite is nice when you have a panel that
contains many widgets and you don't want to extend Panel itself.

Having setParent() as package local and onAttach() as protected makes
extending GWT cumbersome when you want to do anything more complicated
than a simple widget.

Ian Bambury

unread,
Aug 15, 2008, 8:08:39 PM8/15/08
to Google-We...@googlegroups.com
Not sure you need to get that complicated, do you?
 
Extend composite, stick a HorizontalPanel in it with initWidget.
 
Put your list/buttonholder/list in the HorizontalPanel .
 
Put your buttons in the buttonholder (VerticalPanel?).
 
Job done.
 
Or am I missing something which requires all the faffing about with the DOM object and divs and s**t?
 
Ian

2008/8/15 Diego <dpr...@gmail.com>

Stuff the environment - Print this email
_______________________________________

Diego

unread,
Aug 15, 2008, 11:48:55 PM8/15/08
to Google Web Toolkit
The example was simplified for clarity. In this particular case it
could be done as you describe, but that's not the point. When you need
to build something using the DOM and you want to reuse some of your
code in the form of inner widgets, you break the "attachment chain"
and the deeper widgets cease to receive events.

Restricting widgets that have widgets to Panels and Composites, seems
overkill. It's not apparent from the toolkit code that the restriction
is necessary, so I would like to know the rational behind it. If it's
something like "it just come out that way", I might file a request for
enhancement, but if there is a compelling reason behind it, I will
shut up and use Panel/Composite :).

walden

unread,
Aug 16, 2008, 8:26:41 AM8/16/08
to Google Web Toolkit
Diego,

I think the exact experience that you had *is* the rationale behind
the approach taken by GWT for complex widgets. You need not worry
about that plumbing, or event bubbling, or memory leaks, if you leave
the bulk of direct DOM manipulation to the toolkit.

Walden

Ian Bambury

unread,
Aug 16, 2008, 8:49:34 AM8/16/08
to Google-We...@googlegroups.com
Any widget that has widgets *is* a composite (small 'c') by definition.
 
How about an example of "When you need to build something using the DOM" then, instead of the one you used? If it doesn't demonstrate your situation adequately, then you are not necessarily going to get a relevant response, and if that happens, you are wasting your time and that of anyone who takes the trouble to read and/or try to help.
 
Ian

Diego

unread,
Aug 16, 2008, 9:02:46 PM8/16/08
to Google Web Toolkit
> Any widget that has widgets *is* a composite (small 'c') by definition.

I think Composite (big 'C') *is not* a composite (small 'c'), it's
just an ill-named wrapper, as it only has *one* widget and forces me
to have a public interface I don't want to have.

> How about an example of "When you need to build something using the DOM"
> then, instead of the one you used? If it doesn't demonstrate your situation
> adequately, then you are not necessarily going to get a relevant response,
> and if that happens, you are wasting your time and that of anyone who takes
> the trouble to read and/or try to help.

If you take one minute to read the gwt page, it states you can make
you own widgets "From Scratch in Java code". You want an example? Go
look into com.google.gwt.user.client.ui.Tree, specially its
doAttachChildren method. How can I do that exact same thing with my
widgets, that obviously aren't inside the com.google.gwt.user.client
package?

I appreciate you taking your time answering me, but I think I have
been polite enough not to deserve the "your example is crap, don't
waste our time" remark. I reduced the example because it shows the
problem and it doesn't make you read and try to understand a thousand-
line widget, specially since I don't know how to properly indent code
here.

Regards,

D.

Ian Bambury

unread,
Aug 16, 2008, 10:23:36 PM8/16/08
to Google-We...@googlegroups.com
2008/8/17 Diego dpr...@gmail.com
I think I have been polite enough not to deserve the "your example is crap, don't waste our time" remark.

That is your interpretation, and those are your words, not mine.
 
I used the conditional twice on purpose, specifically so that my remarks were hypothetical, and the final statement is true only if you accept both premises to be true.
 
I apologise for the offence you took from my attempt to help.
 
It won't happen again.
 
Ian

Diego

unread,
Aug 16, 2008, 11:43:35 PM8/16/08
to Google Web Toolkit
> I apologise for the offence you took from my attempt to help.
No need for that. I might have overreacted as English is not my first
language and I didn't get the subtlety of the conditionals.

Going back to my question, how might I code something like Tree? If
you go to the documentation for Widget it states that if you implement
HasWidgets, you should override doAttachChildren/doDetachChildren and
call onAttach/onDettach for each child widget, but that is not
possible as it violates Java's access rules. Tree gets away with it,
as does Panel and Composite, as they are in the same package as
Widget.



gregor

unread,
Aug 17, 2008, 7:53:15 AM8/17/08
to Google Web Toolkit
Diego,

Tree can override doAttachChildren/doDetachChildren because it extends
Widget, and so can you. A sub-class can always override a protected
method declared in its super class no matter what package it's in. I
have written a couple of my own widgets that extend Widget like this
where the implementation is pure DOM manipulation. Mine don't
themselves have child widgets as such (it's all DOM elements) but if
you wanted to write a custom widget like this that also had child
Widgets (as opposed to just nested DOM elements) then you can
implements the HasWidgets interface (like Tree does to accommodate
child TreeItems) and there is no restriction on you doing that.

In other words you don't just implement HasWidgets but also extend
Widget (which is abstract) and you are away, or to put it another way
you can write something in exactly the same way as Tree is written
(i.e. it is not written around a specific Panel or Composite). I don't
think it was clear from your previous posts that you didn't know that
so Ian and Walden probably thought you were asking something strange
and wondered what the reason was.

regards
gregor

Diego

unread,
Aug 17, 2008, 8:41:40 AM8/17/08
to Google Web Toolkit
> Tree can override doAttachChildren/doDetachChildren because it extends
> Widget, and so can you.

I can override it, but I cannot call onAttach/onDettach, as Tree does,
for my child widgets as that method is protected. Tree is able to call
doAttach as it's in the same package as Widget.

You might want to take a look at the section 6.6.7 here:
http://java.sun.com/docs/books/jls/second_edition/html/names.doc.html

When you have a widget that extends Widget and implements HasWidgets,
a safe bet is that the widgets you want to have are just Widget
objects (meaning you take any widget and all you know about them is
that they are Widget subclasses). Since your code is not involved in
the implementation of Widget, you cannot access the onAttach/onDetach
instance methods of the child widgets.

A quick example showing the access limitation:

package test;
import com.google.gwt.user.client.ui.Widget;

public class MyWidget extends Widget {
private Widget child;

@Override
protected void doAttachChildren() {
super.doAttachChildren();
child.onAttach(); // <- Compiler error: onAttach() has protected
access in com.google.gwt.user.client.ui.Widget
}

}

As you can see here, onAttach cannot be called from outside
com.google.gwt.user.client.ui package.

Regards,
D.



gregor

unread,
Aug 17, 2008, 11:35:42 AM8/17/08
to Google Web Toolkit
Well, yes, but I would assume if you wanted to do something like Tree
+ TreeItem then you would put both classes in the same package so it
would be something like:

package test;
import com.google.gwt.user.client.ui.Widget;

public class SubWidget extends Widget {
@Override
protected void onAttach() {
super.onAttach();
}
}

package test;
import com.google.gwt.user.client.ui.Widget;

public class MyWidget extends Widget {
private SubWidget child;

@Override
protected void doAttachChildren() {
super.doAttachChildren();
child.onAttach();
}
}

I appreciate you couldn't do that with a standard widget as is, but
there is nothing to stop you extending any that you need and
overriding onAtach() in the same way.

regards
gregor

Diego

unread,
Aug 17, 2008, 2:13:37 PM8/17/08
to Google Web Toolkit
> Well, yes, but I would assume if you wanted to do something like Tree
> + TreeItem then you would put both classes in the same package
If you look at Tree.doAttachChildren(), it doesn't call onAttach() on
TreeItem but on the widgets contained in them. Tree.iterator() returns
the keyset of a Map<Widget, TreeItem>. TreeItem is not even a Widget,
it's a UIObject (Widget parent class).

> I appreciate you couldn't do that with a standard widget as is, but
> there is nothing to stop you extending any that you need and
> overriding onAtach() in the same way.
Imagine you are building a Grid or something like that. You don't
control which widgets the end-user puts in your container, so you need
to code for Widget, without inheritance involved. Tree is an excellent
example actually, as you can put whatever you like in a node.
Reply all
Reply to author
Forward
0 new messages