I'll answer using the numbers of your questions:
Correct
Correct. The top trait is
UIElement
which defines an abstract memberdef peer: java.awt.Component
. Then you haveContainer
which merely adds abstract memberdef contents: Seq[Component]
to be able to read the child components.Container.Wrapper
is a concrete implementation ofContainer
which assumes (abstractly) the Java peer is ajavax.swing.JComponent
. Note that in Java's own hierarchy,javax.swing.JComponent
is a sub-type ofjava.awt.Component
, so there is no conflict. Sub-types can refine the types of their members ("covariance").SequentialContainer
refinesContainer
by saying thatcontents
is a mutable buffer (instead of the read-only sequence). Consequently, its implementationSequentialContainer.Wrapper
mixes inContainer.Wrapper
but replaces thecontents
by a standard Scala buffer. At no point has a concretepeer
been given, yet. For convenience,Component
does implement that member, but then as you have seen, the final classPopupMenu
overrides thepeer
. Because of the way the type system works, all the participating traits can accesspeer
, but onlyPopupMenu
"knows" that the type has been refined to bejavax.swing.JPopupMenu
. For exampleSequentialContainer.Wrapper
only knows there is ajavax.swing.JComponent
, and so it can use this part of the API of the peer.The
Publisher
trait is introduced byUIElement
, so you will find it in all types deriving fromUIElement
. There is nothing wrong with having the same trait appear multiple times in the hierarchy. In the final class, there is only one instance ofPublisher
, there do not exist multiple "versions" of it. Even ifPublisher
had not been defined at the root, but independently in for exampleComponent
andSequentialContainer.Wrapper
, you would only get one instance in the final class.This is an easy one. In Scala you can only extend one class, but mix in any number of traits.
Component
is a class while all other things else are traits. It'sclass A extends <trait-or-class> with <trait> with <trait> ...
.
To sum up, all GUI elements inherit from trait UIElement
which is backed up by a java.awt.Component
. Elements which have child elements use trait Container
, and all the normal panel type elements which allow you to add and remove elements in a specific order use SequentialContainer
. (Not all panels have a sequential order, for example BorderPanel
does not). These are abstract interfaces, to get all the necessary implementations, you have the .Wrapper
types. Finally to get a useable class, you have Component
which extends UIElement
and requires that the peer is javax.swing.JComponent
, so it can implement all the standard functionality.
When you implement a new wrapper, you usually use Component
and refine the peer
type so that you can access the specific functionality of that peer (e.g. the show
method of JPopupMenu
).