#813 FWT layout question

tcolar Thu 12 Nov 2009

I can't figure out how to do the following simple layout.

The simple version:

  • I got a Pane of a specific size (say 800*600).
  • I want to divide into 2 "columns" of equal size (50% each)
  • I want to center a component (let's say a Button) in each of those columns.

I've tried it a bunch of different ways but I can't seem to get it to work right: Latest try:

Window
    {
      title = "Catalog tool"
      size = Size(800, 600)
      content = EdgePane
      {
        left = EdgePane{it.center = Button{text = "button1"}}
        right = EdgePane{it.center = Button{text = "button2"}}
      }
    }.open

I think the issue is that my "inner" EdgePane(s) containing the buttons are not "filling" the parent EdgePage ... that's the main thing i can't figure ... how to tell a component to "fill" it's parent(as in HTML with width=100% height=100%)

I've also tried using a GridPane but could not quite get it to work either.

qualidafial Thu 12 Nov 2009

Did you try GridPane.uniformCols = true?

qualidafial Thu 12 Nov 2009

The other option is to subclass fwt::Pane and override onLayout to do the layout yourself--this doesn't sound like a complicated layout.

tcolar Thu 12 Nov 2009

That wasn't it, but it got me in the right direction: gridPane.halignPane = Halign.center & gridPane.halignCells = Halign.center do the trick

tcolar Fri 13 Nov 2009

Nevermind, I still can't do this. I guess I might have to create my own component ....

Maybe I need a Grid that supports expandCol & uniformCols both at the same time.

KevinKelley Fri 13 Nov 2009

How about

numCols = 2
halignCells = Halign.fill
uniformCols = true

?

Side note, the FWT demo (examples/fwt/demo.fan) is a handy way to tinker with layouts, using the Serialization tab to instantiate a pane. But, I just found that Halign (and Valign) apparently aren't serializable, so testing the above didn't work.

At some point it'd probably be good to go through the codebase, mark everything serializable that could possibly make sense.

tcolar Fri 13 Nov 2009

No can't find anyway to make it happen

I think it would work if halignPane=fill was supported. I looked into the GridPane implementation and it doesn't do a "fill" (just ignores it).

Anyway I'm a it under the weather so i'll come back to it later. I think i could just add support for that, or maybe just create my own simple BoxLayout.

andy Fri 13 Nov 2009

Aside from using a SashPane I'm pretty sure there is no way to do this right now. This is a common enough type of thing that we should fix tho. Ideally by enhancing an existing widget, like toggling off dividers in SashPane, or enhancing GridPane to be more flexible (prob the latter).

qualidafial Fri 13 Nov 2009

Seems like GridPane should support more than one expanding column/row, e.g.

Int[] expandCols := [,]
Int[] expandRows := [,]

andy Fri 13 Nov 2009

Yeah, I was thinking of a weights property like we use for SashPane, though we need to capture prefSize in there, so not entirely sure what that looks like.

qualidafial Fri 13 Nov 2009

More than that, for really effective layout you want to have prefSize and minSize which would allow grids to compute sizes using the W3C recommendation for table column sizing. We do this in the PaperClips printing library to great effect.

For those not familiar with the algorithm, the basic idea is that when you have less horizontal space than you need, you take the the difference between the preferred width (i.e. text lays out with no line breaks) and the minimum width (the width of the largest individual word in the text) for each column in the grid. Columns are shrunk proportionate to the difference between the preferred and minimum width. The net effect is that columns are balanced such that vertical space is minimized.

tcolar Fri 13 Nov 2009

Cool , good to know. In the mean time I made own basic Hbox and Vbox.

It would be nice to improve GridBox.

@qualidafial: Multiple expending columns might be tricky to implement ... at least in the browser.

Talking about browser ... I feel like GridBox Halign and Valign are kinda Html/CSS like and am wondering why those properties would not be valid for most widgets not just box cells.

Maybe it would be nice to have a "sizing/positioning" widget which would have similar properties to a CSS Div (ie: positioning: relative, absolute and so on and sizing), that way this could be added within any other widget and used to defined positioning/sizing of it's content (like say "fill" and/or "top right").

Maybe those props makes sense to be part of widget itself even.

Sometimes I wonder why no Software Layout API's(AFAIK) do it the way CSS does(even if not perfect), nowadays most people understand that, and other layouts, such as the ones used in Swing, need to be learned separately and have pretty large learning curves.

Sorry, getting sidetracked here :)

DanielFath Fri 13 Nov 2009

Did anyone used MIG layout for Java? I found it to be incredibly versatile and easy to understand and would love to see it as a feature in Fan(tom).

Still if all else fails I could import it and use it anyway I guess.

andy Fri 13 Nov 2009

MiG was brought up before (by Mikael himself) #420

DanielFath Fri 13 Nov 2009

So, I assume it was rejected or there wasn't enough interest?

brian Fri 13 Nov 2009

Andy and I have had a bunch of ideas about enhancing GridPane, or doing things more in a CSS fashion. Now that we are fully supporting FWT in the browser, I'm thinking a CSS like approach makes more sense.

The MiG layout might be another good alternative. We had some discussions, but no one actually ever took up the torch to do the port :-)

mikaelgrev Sat 14 Nov 2009

Hi guys!

Funny, I just stumbled in here to see this.

MiGLayout is made to be portable. There's just a very small portion that is toolkit dependent (three adaptor classes). There is currently at least a Swing, SWT and JavaFX port. The JavaFX port was made by Dean Iversson and he had no problems porting it.

I will support any porting with timely help, but I cannot do the port myself due to time constraints.

I've had very little bad feedback, so I don't think there's much risk of adding MigLayout. The fact that it is GUI agnostic should help as well. As is the advantage that developers can use the same layout engine in all languages.

Some comments are here in the RFE: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6530906 It is currently the #3 most wanted think in Java.

I just need to learn Fan. I think the only reason I haven't is that I'm an IDE junkie. I need coloring, refactoring and auto error checking in IntelliJ IDEA. Fan is the most interesting language I've seen to date. Keep it up guys!

Cheers, Mikael

brian Sat 14 Nov 2009

But, I just found that Halign (and Valign) apparently aren't serializable, so testing the above didn't work.

Kevin, I investigated this because if enums are not serializable that would definitely be a serious problem. But everything appears to be working okay to me:

fansh> Sys.out.writeObj(gfx::Halign.left)
gfx::Halign("left")
fansh> "gfx::Halign(\"left\")".in.readObj
left

If you think there is a problem here, please let me know.

KevinKelley Sat 14 Nov 2009

I didn't try to understand what was happening... saw an error trace and jumped to a conclusion.

I used the Serialization tab of demo.fwt, and modified the serialize code in the left-hand pane to look like this:

fwt::GridPane
{
  halignCells = gfx::Halign.fill
  fwt::Button { text="one" },
  fwt::Button { text="two" },
}

and instead of two buttons, it pops up this error trace:

sys::Err: Type missing 'make' or 'defVal' slots: gfx::Halign
  more...

Oh. Sorry, my bad. I should have used:

halignCells = gfx::Halign("fill")

since it needs the "serialized" syntax, not the Fan syntax. So no problem, just my mistake.

tcolar Fri 1 Oct 2010

Just wondering if any progress/planning made here, every time i start playing with FWT I run into this :)

andy Fri 1 Oct 2010

If you were referring to your initial post - you can knock something out yourself pretty easily:

class FooPane : Pane
{
  override Size prefSize(Hints hints := Hints.defVal)
  {
    // if needed, otherwise just dummy
    Size(10,10)
  }

  override Void onLayout()
  {
    x  := 0
    w  := size.w / children.size
    children.each |kid|
    {
      kid.bounds = Rect(x, 0, w, size.h)
      x += w
    }
  } 
}

Login or Signup to reply.