/*******************************************************************************
* Copyright (c) 2014 EclipseSource and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* EclipseSource - initial API and implementation
******************************************************************************/
package com.eclipsesource.tabris.passepartout.internal;
import static com.eclipsesource.tabris.passepartout.internal.Clauses.whenNull;
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.List;
import com.eclipsesource.tabris.passepartout.Bounds;
import com.eclipsesource.tabris.passepartout.FluidGridConfiguration;
import com.eclipsesource.tabris.passepartout.Instruction;
import com.eclipsesource.tabris.passepartout.UIEnvironment;
import com.eclipsesource.tabris.passepartout.internal.instruction.ColumnsInstruction;
import com.eclipsesource.tabris.passepartout.internal.instruction.ExcludeInstruction;
import com.eclipsesource.tabris.passepartout.internal.instruction.HeightInstruction;
import com.eclipsesource.tabris.passepartout.internal.instruction.MarginInstruction;
public class Layouter {
private final UIEnvironment environment;
private final FluidGridConfiguration configuration;
private final Stacker stacker;
public Layouter( UIEnvironment environment, FluidGridConfiguration configuration ) {
whenNull( environment ).throwIllegalArgument( "UIEnvironment must not be null" );
whenNull( configuration ).throwIllegalArgument( "FluidGridConfiguration must not be null" );
this.environment = environment;
this.configuration = configuration;
this.stacker = new Stacker( this.environment.getParentBounds() );
}
public Bounds computeBounds( Bounds preferedBounds, List<Instruction> instructions ) {
if( isExcluded( instructions ) ) {
return new Bounds( 0, 0, 0, 0 );
}
return calculateBounds( preferedBounds, instructions );
}
private boolean isExcluded( List<Instruction> instructions ) {
for( Instruction instruction : instructions ) {
if( instruction instanceof ExcludeInstruction ) {
return true;
}
}
return false;
}
private Bounds calculateBounds( Bounds preferedBounds, List<Instruction> instructions ) {
int width = computeWidth( instructions );
int height = computeHeight( preferedBounds, instructions );
Bounds bounds = stacker.stack( width, height );
return applyMargins( bounds, instructions );
}
private int computeHeight( Bounds preferedBounds, List<Instruction> instructions ) {
int height = preferedBounds.getHeight();
for( Instruction instruction : instructions ) {
if( instruction instanceof HeightInstruction ) {
height = ( ( HeightInstruction )instruction ).computeHeight( environment.getParentBounds(),
environment.getParentFontSize() );
}
}
return height;
}
private int computeWidth( List<Instruction> instructions ) {
int occupiedColumns = 1;
for( Instruction instruction : instructions ) {
if( instruction instanceof ColumnsInstruction ) {
occupiedColumns = ( ( ColumnsInstruction )instruction ).getColumns();
}
}
BigDecimal width = BigDecimal.valueOf( environment.getParentBounds().getWidth() )
.divide( BigDecimal.valueOf( getColumns() ), MathContext.DECIMAL32 )
.multiply( BigDecimal.valueOf( occupiedColumns ) )
.setScale( 0, RoundingMode.HALF_UP );
return width.intValue();
}
public int getColumns() {
int columns = 4;
if( environment.getParentBounds().getWidth() >= configuration.getSixteenColumnWidth() ) {
columns = 16;
} else if( environment.getParentBounds().getWidth() >= configuration.getEightColumnWidth() ) {
columns = 8;
}
return columns;
}
private Bounds applyMargins( Bounds bounds, List<Instruction> instructions ) {
Bounds result = bounds;
for( Instruction instruction : instructions ) {
if( instruction instanceof MarginInstruction ) {
result = ( ( MarginInstruction )instruction ).computeBounds( result, environment.getParentFontSize() );
}
}
return result;
}
}