On Wed, Aug 5, 2009 at 8:32 AM, Sami Jaber <[email protected]> wrote:
>
> We considered doing something like this originally, and I think it's the
>> right approach for Swing/SWT. However, when you have to implement these
>> layouts in (...) impossible to change a panel's layout after it's
>> constructed, because it forces you to reconstruct the entire DOM.
>>
>
> I understand, It could be interesting to have a look at how GXT guys have
> solved this pb, I guess they have this separation between
> XXLayout/ContentPanel
>
As I understand it, GXT uses the same structural model for all containers,
and all their layouts are built with explicit Java code to manage the
positions and sizes of their children. Unless I'm missing something, this
explicitly precludes a particular layout implementation using a different
DOM structure (i.e., other than <div>(<child/>)*</div>). It's a different,
but perfectly valid, set of tradeoffs. For GWT proper, I think it's better
that we stick with a model that allows us to model arbitrary DOM structures,
even if it's at the expense of a degree of generality.
LayoutData has always been there, but it was just package-protected. The doc
>> states explicitly that it may only be used by the panel that owns the
>> widget, and it really does help avoid lots of extra maps, which can get
>> pretty expensive. The userData on Layer should probably have been called
>> userObject (like in TreeItem), and I should have made it invariant rather
>> than having a setter (the next patch will include this change). I admit it's
>> a bit odd, but the "user data" pattern (to the extent one can call it a
>> pattern) can really make things a lot easier in this case. It's also worth
>> pointing out that most users won't really be exposed to Layer.userObject,
>> since they'll mostly be using panels and widgets.
>>
>
> Ok I understand.
>
>>
>> I'm not a huge fan of attach() and detach() either, now that I think of it
>> (actually, I *really* wish I could get rid of them, but this appears to be
>> impossible because of requirements imposed by the IE6 implementation). What
>> about calling them something like onElement[De A]ttached()? Would that make
>> it a bit clearer?
>>
>
> That would definitively be better names
>
>
Done, in the next patch (onAttached, onDetached).
Actually, if you're using a LayoutPanel (or similar widget, more are on
>> their way, such as DockLayoutPanel, StackLayoutPanel, and the like), you
>> shouldn't ever have to use the Layout class directly. The above code could
>> simply be:
>>
>> Does that make sense? I would prefer to modify add() to return the Layer
>> directly, but it's inherited from HasWidgets (unfortunately, it was a bad
>> idea to have add() there in the first place, but it's too late to fix now).
>>
>
> Yes, that's right. That said, I would have probably chosen a name like
> "LayerConstraints" instead of "Layer" because of the specific nature of the
> data passed to attachChild
>
It really came down to a tradeoff between correctness and brevity. You end
up with the name of this class all over your layout code, which can get to
be a bit much if it's really long. I was also inspired (at least a little
bit) by the Core Animation concept of a "layer".
explicitly). The RootLayoutPanel is meant to solve this problem in a pretty
>> simple way -- please let me know if it's not sufficient for some reason I'm
>> not seeing.
>>
>
> That's it. I have replaced RootPanel by RootLayoutPanel and things are
> better. I still have the problem to find an equivalent of
> RootPanel.get("slotId").
> As it is designed, that seems difficult. Does it mean that embedding
> LayoutPanel in an existing DOM will be forbidden by design ? I don't see how
> you could infer the existing raw HTML to add all the layout data stuff
>
I've been banging my head on this problem for a while. The issue is this:
RootLayoutPanel *could* provide the option of attaching itself to an
arbitrary <div> in the page, but it would then lose the ability to notify
its children of onLayout() -- because there's no way to know when an
arbitrary element on the page changes size.
You *could* implement something like this by hand, as long as you were
willing to either (a) explicitly size the root element so that it's size
doesn't change arbitrarily, or (b) accept that the RequiresLayout contract
will be broken. Like so:
class MyRoot extends LayoutPanel {
private static MyRoot singleton;
public static MyRoot get(String id) {
if (singleton == null) {
singleton = new MyRoot();
RootPanel.get(id).add(singleton);
}
return singleton;
}
private MyRoot() {
}
@Override
protected void onLoad() {
getLayout().onAttached();
getLayout().fillParent();
}
}
Note that this class can't "provide layout", because it has no way of
following that contract. You could do so correctly as long as you found a
way to fix the element's size and inform your children whenever you change
it.
Also, I can't quite follow all the logic here, but do remember that you have
>> to explicitly call layout() on these LayoutPanel (and RootLayoutPanel)
>> instances once all the children are added and their layers' constraints set.
>> Once I get the patch updated to take this (and other) feedback into account,
>> I'll have a deeper look at the code to provide a simple example that I
>> believe captures what it's trying to do.
>>
> Ok great
>
>
>> I realize it's probably not immediately obvious quite how all these
>> classes fit together, so please let me know if you have any ideas on how I
>> can make it clearer. Once it's all done, we'll be updating the samples,
>> which should help, but I'm open to other ideas as well.
>>
>
> With those explanations, things are clearer. That said, I still have a
> problem with my previous sample. I have updated it to reflect the changes
> you made in LayoutPanelExample and I want to be sure I didn't make any
> mistake. Here is a small snippet
>
> //HorizontalPanel hp = new HorizontalPanel();
> LayoutPanel hp = new LayoutPanel();
> Widget childOne = hp, childTwo = getTabPanel();
> FlexTable ft = getTable() ;
> hp.add(ft);
> hp.layout();
> childOne.setStyleName("red");
> childTwo.setStyleName("yellow");
> LayoutPanel p = new LayoutPanel();
> p.add(childOne);
> p.add(childTwo);
> Layer layerOne = p.getLayer(childOne), layerTwo = p.getLayer(childTwo);
> layerOne.setBottomHeight(0, Unit.PCT, 50, Unit.PCT);
> layerTwo.setTopHeight(0, Unit.PCT, 50, Unit.PCT);
> p.layout();
> RootLayoutPanel rp = RootLayoutPanel.get();
> rp.add(p);rp.layout();
>
> When I use a LayoutPanel ("hp" reference), the FlexTable would shrink as
> expected in terms of height and width (don't behave consistently across all
> browsers). When I use an HorizontalPanel, the childs components won't grow
> to fill all the parent space. This use case will be very common in the
> future as many users will try to compose legacy panels with the new Layout
> widgets.
> Do you see a simple way to apply the layout to the newly added FlexTable if
> its parent is not a LayoutPanel ?
>
AFAICT, what's happening here is that the layout works "properly" in the
sense that the tables inside the various LayoutPanels are in fact laid out
as requested. The problem is that children nested *inside* table cells don't
take up the entire cell in standards mode, even if their width/height are
set to 100%. This is one of the biggest mistakes (IMNSHO) in the CSS
standard, but there's little to be done about that now.
I believe Tab/DeckPanel are going to have to be among the widgets for which
we build layout-aware implementations. This would eliminate this problem by
eliminating the <table>. I'm going to be reviewing and checking in
implementations of the widgets described in the layout design doc over the
next week or so. Any help you could provide by reviewing their APIs and
behaviors would be greatly appreciated.
--~--~---------~--~----~------------~-------~--~----~
http://groups.google.com/group/Google-Web-Toolkit-Contributors
-~----------~----~----~----~------~----~------~--~---