// -*- mode: java; c-basic-offset: 2; -*- // Copyright 2009-2011 Google, All Rights reserved // Copyright 2011-2012 MIT, All rights reserved // Released under the Apache License, Version 2.0 // http://www.apache.org/licenses/LICENSE-2.0 package com.google.appinventor.components.runtime; import com.google.appinventor.components.annotations.SimpleObject; import com.google.appinventor.components.common.ComponentConstants; import android.content.Context; import android.view.ViewGroup; /** * Linear layout for placing components horizontally or vertically. * */ @SimpleObject public final class LinearLayout implements Layout { private final android.widget.LinearLayout layoutManager; /** * Creates a new linear layout. * * @param context view context * @param orientation one of * {@link ComponentConstants#LAYOUT_ORIENTATION_HORIZONTAL}. * {@link ComponentConstants#LAYOUT_ORIENTATION_VERTICAL} */ LinearLayout(Context context, int orientation) { this(context, orientation, null, null); } /** * Creates a new linear layout with a preferred empty width/height. * * @param context view context * @param orientation one of * {@link ComponentConstants#LAYOUT_ORIENTATION_HORIZONTAL}. * {@link ComponentConstants#LAYOUT_ORIENTATION_VERTICAL} * @param preferredEmptyWidth the preferred width of an empty layout * @param preferredEmptyHeight the preferred height of an empty layout */ LinearLayout(Context context, int orientation, final Integer preferredEmptyWidth, final Integer preferredEmptyHeight) { if (preferredEmptyWidth == null && preferredEmptyHeight != null || preferredEmptyWidth != null && preferredEmptyHeight == null) { throw new IllegalArgumentException("LinearLayout - preferredEmptyWidth and " + "preferredEmptyHeight must be either both null or both not null"); } // Create an Android LinearLayout, but override onMeasure so that we can use our preferred // empty width/height. layoutManager = new android.widget.LinearLayout(context) { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // If there was no preferred empty width/height specified (see constructors above), just // call super. (This is the case for the Form component.) if (preferredEmptyWidth == null || preferredEmptyHeight == null) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); return; } // If the layout has any children, just call super. if (getChildCount() != 0) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); return; } setMeasuredDimension(getSize(widthMeasureSpec, preferredEmptyWidth), getSize(heightMeasureSpec, preferredEmptyHeight)); } private int getSize(int measureSpec, int preferredSize) { int result; int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); if (specMode == MeasureSpec.EXACTLY) { // We were told how big to be result = specSize; } else { // Use the preferred size. result = preferredSize; if (specMode == MeasureSpec.AT_MOST) { // Respect AT_MOST value if that was what is called for by measureSpec result = Math.min(result, specSize); } } return result; } }; layoutManager.setOrientation( orientation == ComponentConstants.LAYOUT_ORIENTATION_HORIZONTAL ? android.widget.LinearLayout.HORIZONTAL : android.widget.LinearLayout.VERTICAL); } // Layout implementation public ViewGroup getLayoutManager() { return layoutManager; } public void add(AndroidViewComponent component) { layoutManager.addView(component.getView(), new android.widget.LinearLayout.LayoutParams( ViewGroup.LayoutParams.WRAP_CONTENT, // width ViewGroup.LayoutParams.WRAP_CONTENT, // height 0f)); // weight } public void setHorizontalGravity(int gravity) { layoutManager.setHorizontalGravity(gravity); } public void setVerticalGravity(int gravity) { layoutManager.setVerticalGravity(gravity); } public void setBaselineAligned(boolean baselineAligned) { layoutManager.setBaselineAligned(baselineAligned); } }