Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GroupPanel type woes #2

Open
Sciss opened this issue Mar 26, 2013 · 2 comments
Open

GroupPanel type woes #2

Sciss opened this issue Mar 26, 2013 · 2 comments

Comments

@Sciss
Copy link
Contributor

Sciss commented Mar 26, 2013

I am regularly running into trouble trying to figure out how to massage my components to fit into the GroupPanel's groups. I have come up with all sorts of crazy type conversions, and once again I forgot how I managed. It would be great to have an example that shows how to accomplish the IMO standard case of creating a group from a collection of widgets:

val labels  = (1 to 10).map(i => new Label(i.toString))
val fields  = (1 to 10).map(i => new TextField(10))

new GroupPanel {
  theHorizontalLayout is Sequential(
    Parallel(labels: _*), Parallel(fields: _*)  // type mismatch: required: Seq[this.InParallel]
  )
  theVerticalLayout is Sequential(              // type mismatch: required: Seq[this.InSequential]
    (labels zip fields).map { case (lb, f) =>
      Parallel(Baseline)(lb, f)
    }: _*
  )
}

This drives me nuts. InParallel and InSequential are private types, so the straight forward : InParallel doesn't work.

Am I blind not to see the solution?

@asflierl
Copy link

Hi,
I am a bit swamped in work right now so can't fully check this out before next week...

Off the top of my head, here's an idea for the first case:

theHorizontalLayout is Sequential(
  Parallel((labels map add):_*), Parallel((fields map add):_*)
)

It might be possible to add your own implicit like

implicit def addAll[A <: G](comps: Seq[Component]): Seq[InGroup[A]] = comps map add

to enable your original code to work as is.

The (badly named, sorry) add method is what (implicitly) converts a component to an element inside a specific group. This usually happens by the time you specify a component "by hand" inside a Parallel(...) or Sequential(...), so triggering that conversion explicitly might help. You might have to give a specific subtype of GroupLayout#Group as type parameter to add.

By the way, note that InParallel and InSequential are nothing more than type aliases for InGroup[GroupLayout#ParallelGroup] and InGroup[GroupLayout#SequentialGroup] resp. and the InGroup type should be accessible.
Softening the access restriction on those two type aliases from private[grouppanel] to protected shouldn't hurt, although it might not help at all in your case (since the conversion must be triggered somehow).

Also note that the underlying group layout is fully exposed through the layout field - for better or worse, so you can always fall back to Java-style as a last resort.

@Sciss
Copy link
Contributor Author

Sciss commented Mar 27, 2013

Parallel((labels map add):_*) is not enough for the type checker, because it fails to infer the type parameter of add. So in the end I had something like

Parallel(labels.map(lb => add[GroupLayout#ParallelGroup](lb)): _*)

and

(labels zip fields).map { case (lb, f) =>    
  Parallel(Baseline)(lb, f): InGroup[GroupLayout#SequentialGroup]
}): _*

So I was wondering if not the best solution is to define the apply method on Parallel and Sequential along the lines of

def apply[A <% InParallel](elems: A*): Group

I haven't played this through, but perhaps it's an easy solution.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants