-
Notifications
You must be signed in to change notification settings - Fork 0
Container Sides
There are five sides in the ContainerSide
enumeration class, which are:
-
ContainerSide.FILL
- Adds a panel to the same container -
ContainerSide.LEFT
- Adds a panel to the left subcontainer of the current container -
ContainerSide.RIGHT
- Adds a panel to the right subcontainer of the current container -
ContainerSide.TOP
- Adds a panel to the top subcontainer of the current container -
ContainerSide.BOTTOM
- Adds a panel to the bottom subcontainer of the current container
If there is no subcontainer, then a new subcontainer is created; this process occurs with two possible conditions:
This happens when there are no panels attached to the container; recall that no IContainer instance can have both subcontainers and panels (without undefined behavior occurring). Suppose a container A
is empty, and a container needs to be added to the RIGHT
side; the tree view and the physical rendering is shown below:
┌───────────────────┐
│ │
A │ │
| │ A │
* │ │
│ │
└───────────────────┘
Then, a new container is created and added as a subcontainer to A (first as a weak link, and then committed; the intermediate step is left out, but it is worth noting). For the DefaultContainer
implementation, another container is created, which is complementary to the current side (LEFT
in this case):
┌─────────┬─────────┐
A │ │ │
/ \ │ │ │
B C │ C │ B │
| | │ │ │
* * │ │ │
└─────────┴─────────┘
That's pretty much it. Calling A.getSide(PanelContainerSide.RIGHT)
returns B
, and calling A.getSide(PanelContainerSide.LEFT)
returns C
.
Since no IContainer can have both panels and subcontainers at the same time without undefined behavior occurring, the default behavior which occurs when a container needs to be added to a non-empty container, is to create a new container which is complementary to the container that is being created as a soft link, merge all the container's contents into this container, add the other container as a soft link, and commit right after.
Suppose a container
A
has 2 panels,b
andc
, and a new containerB
has to be added to theRIGHT
side:
┌───────────────────┐
│ │
A │ │
| │ A │
[b,c] │ │
╞═══╤═══╤═══════════╡
│ b │ c │ │
└───┴───┴───────────┘
Before adding B
to the RIGHT
side, a new container C is created as a soft link, and the contents are merged into it:
┌───────────────────┐
│ │
A │ │
: \ │ C │
C B │ │
| │ │
[b,c] ╞═══╤═══╤═══════════╡
│ b │ c │ │
└───┴───┴───────────┘
Which finally results in the following layout:
┌─────────┬─────────┐
│ │ │
A │ │ │
/ \ │ │ │
C B │ C │ B │
| │ │ │
[b,c] ╞═══╤═══╤═╡ │
│ b │ c │ │ │
└───┴───┴─┴─────────┘
Because of the merging that occurs, a few points should be noted:
- No priority is given to any side.
- Because no priority is given to any side, the order in which containers are added matters.
- Serializing containers becomes a little trickier because the exact order in which panels are added affects the final layout.
- Non-complementary (aka anti-complementary) sides always result in new containers being created, and the existing contents merged down into the complementary container for the new side.
For an example of #1, #2, and #4, consider the following case:
A container
A
has to have two containers,B
andC
, added toLEFT
andTOP
respectively. What is the final layout of the container?
- Add container
B
to theLEFT
side. A new containerZ
is created for theRIGHT
side, and ifA
had any contents, they would have been merged intoZ
. So far, so good:
┌─────────┬─────────┐
A │ │ │
/ \ │ │ │
B Z │ B │ Z │
| | │ │ │
* * │ │ │
└─────────┴─────────┘
- Add container
C
toA
. Here, though, the current "side" ofA
isLEFT
.C
is being added to theTOP
side, butTOP
is anti-complementary toLEFT
; as a result,A
's entire subtree will be merged into a new container,Y
, andC
will be added to theTOP
side:
┌───────────────────┐
A │ │
/ \ │ C │
C Y │ │
| / \ ├─────────┬─────────┤
* B Z │ │ │
| | │ B │ Z │
* * │ │ │
└─────────┴─────────┘
On the other hand, if C
were added first and then B
, i.e. TOP
followed by LEFT
, then the following steps would occur instead:
- Add container
C
to theTOP
side. A new containerZ
is created for theBOTTOM
side, and ifA
had any contents, they would have been merged intoZ
:
┌───────────────────┐
│ │
A │ C │
/ \ │ │
C Z ├───────────────────┤
| | │ │
* * │ Z │
│ │
└───────────────────┘
- Add container
B
toA
. Here, though, the current "side" ofA
isTOP
.B
is being added to theLEFT
side, butLEFT
is anti-complementary toTOP
; as a result,A
's entire subtree will be merged into a new container,Y
, andB
will be added to theLEFT
side:
┌─────────┬─────────┐
A │ │ │
/ \ │ │ C │
B Y │ │ │
| / \ │ B ├─────────┤
* C Z │ │ │
| | │ │ Z │
* * │ │ │
└─────────┴─────────┘
Remember: Don't mix up the order!
- No priority over sides - because of only two sides, or none at all - means that there's no situation like the following occurring here (in this example, there are four sides in a container; which side should be longer?
A
is blocking offB
, which is blocking offC
;D
is blocked off on both sides byA
andC
)
┌───┬─────────────────┐
│ │ B │
│ ├─────────────┬───┤
│ │ │ │
│ │ │ │
│ │ │ │
│ A │ │ C │
│ │ │ │
│ │ │ │
│ ├─────────────┤ │
│ │ D │ │
└───┴─────────────┴───┘
- Works seamlessly with parked containers (no merging means that parked containers won't be removed from their
stage
s)
- Order of insertion matters
- Serialization is more tricky because the order of insertion has to be kept track of as well, requiring a linear instead of an associative data structure
- Really unbalanced trees can be produced in extreme cases:
Assume containers
[B, C, D, E, F, G, H ...]
are to be added toA
in alternatingTOP
-LEFT
sides (where + indicates a container is on theTOP
side and * indicates a container is on theLEFT
side):
A:
A+ ┌──────────────────────────────┬───────────────────────────────┐
/ \ │ │ │
H+ T* │ │ │
| / \ │ │ │
* G* U+ │ │ C │
| / \ │ │ │
* F+ V* │ │ │
| / \ │ │ │
* E* W+ │ H ├───────────────┬───────────────┤
| / \ │ │ │ │
* D+ X* │ │ │ E │
| / \ │ │ │ │
* C* Y+ │ │ D ├───────┬───────┤
| / \ │ │ │ │ G │
* B+ Z │ │ │ F ├───┬───┤
| | │ │ │ │ H │...│
* * └──────────────────────────────┴───────────────┴───────┴───┴───┘
(Extra truncated due to size constraints.)
The newer version contains breaking changes over the older versions, which used the PanelContainerSide
class to refer to the same concept (instead of ContainerSide
), and an int
datatype instead of a String
. This has knock-on effects regarding resolvers - namely, newer versions allow for multiple side codes to be scanned in a single function call, something that is not possible in older versions.