Layout with nested SplitLayoutPanel

224 views
Skip to first unread message

Magnus

unread,
Dec 6, 2013, 12:31:17 AM12/6/13
to google-we...@googlegroups.com
Hi,

I would like a panel with split bars like this:

+--------------------+--------------------+
|                    |                    |
|      west          |       east         |
|                    |                    |
+--------------------+--------------------+
|                                         |
|                center                   |
|                                         |
+--------------------+--------------------+

I believe that this is not possible with a single SplitLayoutPanel, but it requires two nested SplitLayoutPanels, correct?

I have realized it in UIBinder like shown below. An outer SplitPanel divides the space into an upper and a lower area, and an inner SplitPanel devides the upper area into a left and right side.
Can this be done in a better way, e. g. with only one SplitLayoutPanel?

Now the main question:

Both split bars should be initially positioned at the middle, so that the splitted areas are of same size. I tried to do this with size="50" and unit="PCT", but this does not work.

What can I do else?

Thank you
Magnus


 <g:SplitLayoutPanel width="100%" height="100%">

  <g:north size='150' unit='EM'>
   <g:SplitLayoutPanel width="100%" height="100%">

    <g:west size='150' unit='EM'>
     <g:FlowPanel>
      <g:Label text="west" />
     </g:FlowPanel>

    </g:west>

    <g:center>
     <g:FlowPanel>
      <g:Label text="center" />
     </g:FlowPanel>
    </g:center>

   </g:SplitLayoutPanel>
  </g:north>

  <g:center>

   <g:FlowPanel>
    <g:Label text="center" />
   </g:FlowPanel>

  </g:center>

 </g:SplitLayoutPanel>

</ui:UiBinder> 

Patrick Tucker

unread,
Dec 6, 2013, 8:20:01 AM12/6/13
to google-we...@googlegroups.com
SplitLayoutPanel does not do percentages so you will have to calculate the center in pixels.

Magnus

unread,
Dec 6, 2013, 11:46:02 AM12/6/13
to google-we...@googlegroups.com
Hi,

this means, I cannot do it in a declarative way?

So whenever the form is displayed, compute the pixel values and set them manually?

But I remember that when fetching the sizes of a panel on creation / within the constructor the size values often are 0.
How can I compute them?

How would you realize the middle position within the SplitPanel?

Magnus

Patrick Tucker

unread,
Dec 7, 2013, 10:29:09 AM12/7/13
to google-we...@googlegroups.com
If its parent is already attached, you can just ask it how wide it is.

Patrick Tucker

unread,
Dec 7, 2013, 10:31:39 AM12/7/13
to google-we...@googlegroups.com
Pleasr provide some code. You just have to make sure the parent and its parents are added before you ask.

Magnus

unread,
Dec 8, 2013, 11:54:18 AM12/8/13
to google-we...@googlegroups.com
Hi Patrick,

I cannot resize the panel yet, because even if I do not change any sizes, it is not displayed correctly.

If I create the panel based on the UIBinder code below and add it to the center of a surrounding DockLayoutPanel, the bottom part "main" is not visible. When inspecting it with Chrome, I can see that its height is 0. Setting the height to "100%" does not help. But setting it manually to a pixel valuie will make it visible.

Note that I am not talking about the splitter's positions. I simply cannot display the nested SplitPanel correctly.

Magnus





<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
 xmlns:g="urn:import:com.google.gwt.user.client.ui">
 <ui:style>
  
 </ui:style>

 <g:SplitLayoutPanel>

  <g:north size='150' unit='EM'>
   <g:SplitLayoutPanel>

    <g:west size='150' unit='EM'>
     <g:FlowPanel>
      <g:Label text="west" />
     </g:FlowPanel>

    </g:west>

    <g:center>
     <g:FlowPanel>
      <g:Label text="center" />
     </g:FlowPanel>
    </g:center>

   </g:SplitLayoutPanel>
  </g:north>

  <g:center>

   <g:FlowPanel>
    <g:Label text="main" />

Patrick Tucker

unread,
Dec 8, 2013, 1:17:07 PM12/8/13
to google-we...@googlegroups.com
Can you provide code for the java side?

Also, I'm pretty sure SplitLayoutPanel only works in pixels.

Message has been deleted

Magnus

unread,
Dec 12, 2013, 6:09:54 PM12/12/13
to google-we...@googlegroups.com
Hi,

as happened so often: While preparing a minimal code example I found the problem myself: My SplitLayoutPanel was not inserted into the surrounding DockLayoutPanel directly. There was a ScrollPanel between, so that the south part of my SplitLayoutPanel was sized to 0. I don't know why, but going without ScrollPanel solved the problem.

Now the repositioning of the Splitters: I tried to do it within constructor of the containing panel, but - as expected - the size of the containing panel is 0 at this time. So I moved the repositioning into a deferred method, which should be called after the constructor has finished. But even then, the size of the containing panel is 0.

Below is the code.
What can I do?

Thanks
Magnus 

---


public class PortalPanel extends Composite
{

 private static PortalPanelUiBinder uiBinder = GWT
   .create (PortalPanelUiBinder.class);

 interface PortalPanelUiBinder extends UiBinder<Widget, PortalPanel>
 {
 }

 public PortalPanel()
 {
  initWidget (uiBinder.createAndBindUi (this));
  resetSplittersLater ();
 }

 private void resetSplittersLater ()
 {
  Scheduler.get().scheduleDeferred
  (
    new ScheduledCommand()
    {
     @Override
     public void execute()
     {
      resetSplitters ();
     }
    }
  );
 }

 public void resetSplitters ()
 {
  int ys = this.getOffsetHeight ();
  Window.alert ("h:" + ys); // -> 0
 }
 
}

Patrick Tucker

unread,
Dec 12, 2013, 9:50:33 PM12/12/13
to google-we...@googlegroups.com
That is what I was going to recommend but I haven't had time to sit down and look at all the code you provided. Glad you were able to figure it out though.

Instead of resizing in your constructor, try overriding onAttach and call the resize function in there. Make sure you call super.onAttach() before resize. Depending on how the parent classes are setup you may have to schedule the resize.

Hope that helps!

Magnus

unread,
Dec 13, 2013, 11:59:01 AM12/13/13
to google-we...@googlegroups.com
Hi Patrick,

thanks, but it didn't help.

I call the resize method from within onAttach, but the value is still 0 (see below).

Magnus


 
 public void resetSplitters ()
 {
  int ys = this.getOffsetHeight ();
  Window.alert ("h:" + ys);
 }
 

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

Thad Humphries

unread,
Dec 13, 2013, 2:15:27 PM12/13/13
to google-we...@googlegroups.com
Just a hunch--I've not tried this--maybe you should instead override onLoad().

From the Javadocs:

onAttach: "It is strongly recommended that you override onLoad() or doAttachChildren() instead of this method to avoid inconsistencies between logical and physical attachment states."

onLoad: "This method is called immediately after a widget becomes attached to the browser's document."

I've had to deal a lot with sizing issues, like trying to size an AbsolutePanel or CustomScrollPanel a tab not yet selected or brought front. Nothing gets a size until the DOM realizes it. Though I have instantiated and attached widget in my code, the DOM may not have done it's thing yet. Getting it right can be frustrating (I'm not above using the occasional state variable to be sure the timing works).

Magnus

unread,
Dec 13, 2013, 6:38:57 PM12/13/13
to google-we...@googlegroups.com
Hi Thad,


I have also tried to override onLoad, but getIOffsetHeight returns 0...

Magnus

Magnus

unread,
Dec 14, 2013, 12:33:02 PM12/14/13
to google-we...@googlegroups.com
 public void resetSplitters ()
 {
  int ys = this.getOffsetHeight ();
  Window.alert ("h:" + ys); // -> 0
 }
 
 @Override
 protected void onLoad()
 {
  super.onLoad ();
  resetSplitters ();
 }
 

Magnus

unread,
Dec 15, 2013, 2:11:15 AM12/15/13
to google-we...@googlegroups.com
Hi,

I found that implementing RequiresResize and overriding onResize produces a non zero width/height. So this could be a solution for the right place to reposition the splitters.

But there is no method to actually reposition the splitters. I found that this has been addressed in several discussions, but there is no solution.

How can you reposition the splitters?

Thanks
Magnus

Patrick Tucker

unread,
Dec 15, 2013, 2:00:35 PM12/15/13
to google-we...@googlegroups.com
To move the splitter, you have to change the size of its associated widget.

Magnus

unread,
Dec 16, 2013, 11:49:50 AM12/16/13
to google-we...@googlegroups.com
Hi Patrick,

nothing happens. What am I doing wrong?

Magnus

-----

public class PortalPanel extends Composite implements RequiresResize
{
 private static PortalPanelUiBinder uiBinder = GWT.create (PortalPanelUiBinder.class);
 
 @UiField SplitLayoutPanel slp_Outer;
 @UiField SplitLayoutPanel slp_North;

 interface PortalPanelUiBinder extends UiBinder<Widget, PortalPanel>
 {
 }

 public PortalPanel()
 {
  initWidget (uiBinder.createAndBindUi (this));
 }

 public void resetSplitters ()
 {
  int pys = this.getOffsetHeight ();
  int ys = pys / 2;
  
  // Window.alert ("ys: " + ys); // it's a  non zero height when called from within onResize
  slp_North.setHeight (ys + "px");
 }
 
 @Override
 public void onResize()
 {
  resetSplitters ();
 }
}

-----

<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
 xmlns:g="urn:import:com.google.gwt.user.client.ui">
 <ui:style>
  
 </ui:style>

 <g:SplitLayoutPanel ui:field="slp_Outer">

  <g:north size='150' unit='PX'>
 
    <g:SplitLayoutPanel ui:field="slp_North">

    <g:west size='150' unit='PX'>

Juan Pablo Gardella

unread,
Dec 16, 2013, 12:27:41 PM12/16/13
to google-we...@googlegroups.com
Try add a docklayoutPanel outside.


2013/12/16 Magnus <alpine...@gmail.com>

--
You received this message because you are subscribed to the Google Groups "Google Web Toolkit" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-web-tool...@googlegroups.com.
To post to this group, send email to google-we...@googlegroups.com.
Visit this group at http://groups.google.com/group/google-web-toolkit.
For more options, visit https://groups.google.com/groups/opt_out.

Patrick Tucker

unread,
Dec 16, 2013, 2:10:26 PM12/16/13
to google-we...@googlegroups.com
I'm pretty sure your problem is above PortalPanel.  I will try to put all of the pieces together tonight.

Patrick Tucker

unread,
Dec 17, 2013, 9:15:52 PM12/17/13
to google-we...@googlegroups.com
I took your PortalPanel class above and added it to the page using RootLayoutPanel.get().add(Widget)

This is what it took to get your widgets sizing properly:
 public void resetSplitters () {
// parent height
int ph = this.getParent().getOffsetHeight();
// parent width
int pw = this.getParent().getOffsetWidth();
  
slp_Outer.setWidgetSize(slp_North, ph/2);
slp_North.setWidgetSize(fp_West, pw/2);
 }

I was able to call this from both onAttach and onResize.

Hope this helps!

Magnus

unread,
Dec 18, 2013, 6:47:20 AM12/18/13
to google-we...@googlegroups.com
Hi Patrick,

thank you very much! This works!

I did several things differently:
I used this.getOffsetWidth/Height instead of this.getParent().getOffsetWidth/Height
And I also used setHeigth instead of setWidgetSize

So for now I have a working solution.

One thing is noticeable: The widget, the size is changed, is always larger than half of the parent size.
Especially the north panel is larger than the south part. When inspecting it has a height of 255px, while the south/center part has a height of 175px, the parent height was divided by 2. This could result from the splitters size, but in this case, the difference is much more (80px).
I just wonder if I should correct this by a constant value.

Thanks
Magnus

Patrick Tucker

unread,
Dec 18, 2013, 6:37:32 PM12/18/13
to google-we...@googlegroups.com
I didn't look that close at it but maybe you should use the parent element's client width and height instead?

Patrick Tucker

unread,
Dec 18, 2013, 8:22:46 PM12/18/13
to google-we...@googlegroups.com
Also, you might want to put the resize in a timer or deferred command when called from onResize().
Reply all
Reply to author
Forward
0 new messages