/*
* Copyright 2010, Maarten Billemont
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.lyndir.lanterna.view;
import com.google.common.base.Optional;
import com.googlecode.lanterna.screen.Screen;
import java.util.ArrayList;
import java.util.List;
/**
* @author lhunath, 2013-07-21
*/
public class LinearView extends View {
public enum Parameters implements LayoutParameter {
DESIRED_SPACE
}
public enum Orientation {
HORIZONTAL,
VERTICAL
}
private final List<Integer> measuredChildOffsets = new ArrayList<>();
private final Orientation orientation;
public LinearView(final Orientation orientation) {
this.orientation = orientation;
}
@Override
protected void measureChildren(final Screen screen) {
// Calculate the amount of undesired space and the amount of dynamic views to divvy that space up for.
int totalDesiredSpace = 0, amountDynamicViews = 0;
for (final View child : getChildren()) {
Optional<?> desiredSpace = child.layoutValue( Parameters.DESIRED_SPACE );
if (desiredSpace.isPresent())
totalDesiredSpace += (Integer) desiredSpace.get();
else
++amountDynamicViews;
}
int totalRemainingSpace = getContentBoxOnScreen().getSize().getHeight() - totalDesiredSpace;
// logger.dbg( "totalDesiredSpace: %s, amountDynamicViews: %s, totalRemainingSpace: %s, contentBox: %s", totalDesiredSpace,
// amountDynamicViews, totalRemainingSpace, getContentBoxOnScreen() );
// Determine the offset for each child depending on its desired or allocated space.
int offset = 0;
measuredChildOffsets.clear();
for (final View child : getChildren()) {
measuredChildOffsets.add( offset );
//logger.dbg( "offset for %s: %s", child.getClass().getSimpleName(), offset );
Optional<?> desiredSpace = child.layoutValue( Parameters.DESIRED_SPACE );
if (desiredSpace.isPresent())
offset += (Integer) desiredSpace.get();
else
offset += totalRemainingSpace / amountDynamicViews;
}
// Measure the children.
super.measureChildren( screen );
}
@Override
protected Box measuredBoxForChildInView(final View child) {
int childIndex = getChildren().indexOf( child );
int childOffset = measuredChildOffsets.get( childIndex );
int newChildIndex = childIndex + 1;
switch (orientation) {
case HORIZONTAL: {
int newChildOffset = newChildIndex < measuredChildOffsets.size()? measuredChildOffsets.get( newChildIndex )
: getContentBoxOnScreen().getSize().getWidth() + 1;
return new Box( 0, newChildOffset - 1, getContentBoxOnScreen().getSize().getHeight(), childOffset );
}
case VERTICAL:
int newChildOffset = newChildIndex < measuredChildOffsets.size()? measuredChildOffsets.get( newChildIndex )
: getContentBoxOnScreen().getSize().getHeight() + 1;
return new Box( childOffset, getContentBoxOnScreen().getSize().getWidth(), newChildOffset - 1, 0 );
}
throw new UnsupportedOperationException( "Unsupported orientation: " + orientation );
}
public Orientation getOrientation() {
return orientation;
}
}