Thanks for your reply. I'm glad Container meets your basic
requirements. I'm planning on introducing Container at work and see
how well it fits in. Maybe it isn't worth the trouble.
(I think of one particular class that extends Panel but makes all four
HasWidgets methods throw UnsupportedOperationExceptions. All child
widgets are managed internally and aren't exposed.)
I addressed your concerns below.
On Aug 22, 4:51 pm, "Joel Webber" <
j...@google.com> wrote:
> Your Container class doesn't seem unreasonable at all to me. As you say, it
> seems like a middle-ground between Widget and Panel, but it still enforces
> consistency between a widget's parent and its attached state, which is good.
> I do have a few concerns about it:
> - A Container would be opaque to child enumeration, which might be a problem
> for things like drag & drop (though you could arguably consider this a
> feature, if that's what you're trying to achieve).
I haven't tried any D&D implementations yet but I would think that
they should treat any Widget atomically. In fact, they have to if
they're not inside the GWT's UI package. And even then no
implementation can know about all child widgets because
HasWidgets.iterator() might not return all widgets, i.e., if you have
some sort of caption that is a Label or an HTML widget. This widget
does not belong to the collection of widgets that are added by
HasWidgets.add().
What I cannot answer is how to make a Container act as a drop target
or any of its children, or how to make the children be draggable
outside the container. That's very implementation specific. I'll take
a look at the gwt-dnd project. But adding and removing other widgets
directly to a Container should not be possible. (See below.) That's
what Panels are for.
> - The Container subclass would need to call Widget.removeFromParent() (just
> like most Panels) to avoid getting the widget hierarchy in an inconsistent
> state (e.g. if you tried to add a Composite's widget to the Container,
> removeFromParent() would correctly fail).
Container subclasses create and dispose of their child widgets. No
need for removeFromParent(). Besides, removeFromParent() will throw an
IllegalStateException, as you implied below. Containers usually don't
implement HasWidgets. That's the whole point. If you expose a child
widget, like I did in my example (getNameBox), then other classes
cannot rip it out by calling removeFromParent(). That wasn't planned
but it's a nice side effect.
On the other hand, Container could provide a "protected"
remove(Widget) method (which could be made "public" by Panel) and
Widget.removeFromParent() could be changed to check the parent against
HasWidgets and Container.
Container:
protected boolean remove(Widget child) {
throw new UnsupportedOperationException();
}
Panel (extends Container):
public abstract boolean remove(Widget child);
Widget:
public void removeFromParent() {
if (parent instanceof Container) {
((Container) parent).remove(this);
} else if (parent instanceof HasWidgets) {
((HasWidgets) parent).remove(this);
} else if (parent != null) {
throw new IllegalStateException(
"This widget's parent does not implement HasWidgets");
}
}
Now people can override Container.remove() to allow safe "extraction"
of child widgets.
Container now has a protected remove() method:
http://docs.google.com/View?docId=dgf5d73j_17c99djxgc
> - It introduces a new situation where a Widget cannot be removed from its
> parent. Currently this can only happen for Widgets passed to
> Composite.initWidget() (see Widget.removeFromParent()). Not the end of the
> world, but it could be potentially confusing when you try to add a
> container's child to another panel.
Well, child widgets should not be removable because no one is supposed
to know about them.
There's only Container! ;)
Have a nice weekend!
Folke