/*
* Copyright (C) 2006 The Android Open Source Project
*
* 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 android.widget;
import com.intel.mpt.annotation.MayloonStubAnnotation;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Region;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
/**
* FrameLayout is designed to block out an area on the screen to display a
* single item. You can add multiple children to a FrameLayout, but all children
* are pegged to the top left of the screen. Children are drawn in a stack, with
* the most recently added child on top. The size of the frame layout is the
* size of its largest child (plus padding), visible or not (if the
* FrameLayout's parent permits). Views that are GONE are used for sizing only
* if {@link #setMeasureAllChildren(boolean)
* setConsiderGoneChildrenWhenMeasuring()} is set to true.
*
* @attr ref android.R.styleable#FrameLayout_foreground
* @attr ref android.R.styleable#FrameLayout_foregroundGravity
* @attr ref android.R.styleable#FrameLayout_measureAllChildren
*/
public class FrameLayout extends ViewGroup {
boolean mMeasureAllChildren = false;
private Drawable mForeground = null;
private int mForegroundPaddingLeft = 0;
private int mForegroundPaddingTop = 0;
private int mForegroundPaddingRight = 0;
private int mForegroundPaddingBottom = 0;
/** {@hide} */
protected boolean mForegroundInPadding = true;
boolean mForegroundBoundsChanged = false;
public FrameLayout(Context context) {
super(context);
}
public FrameLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public FrameLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
TypedArray a = context.obtainStyledAttributes(attrs,
com.android.internal.R.styleable.FrameLayout, defStyle, 0);
// final Drawable d = null;//TODO
// a.getDrawable(com.android.internal.R.styleable.FrameLayout_foreground);
// if (d != null) {
// setForeground(d);
// }
if (a.getBoolean(
com.android.internal.R.styleable.FrameLayout_measureAllChildren,
false)) {
setMeasureAllChildren(true);
}
mForegroundInPadding = a
.getBoolean(
com.android.internal.R.styleable.FrameLayout_foregroundInsidePadding,
true);
a.recycle();
}
/**
* Describes how the foreground is positioned. Defaults to FILL.
*
* @param foregroundGravity
* See {@link android.view.Gravity}
*
* @attr ref android.R.styleable#FrameLayout_foregroundGravity
*/
// public void setForegroundGravity(int foregroundGravity) {
// if (mForegroundGravity != foregroundGravity) {
// if ((foregroundGravity & Gravity.HORIZONTAL_GRAVITY_MASK) == 0) {
// foregroundGravity |= Gravity.LEFT;
// }
//
// if ((foregroundGravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
// foregroundGravity |= Gravity.TOP;
// }
//
// mForegroundGravity = foregroundGravity;
//
// if (mForegroundGravity == Gravity.FILL && mForeground != null) {
// Rect padding = new Rect();
// if (mForeground.getPadding(padding)) {
// mForegroundPaddingLeft = padding.left;
// mForegroundPaddingTop = padding.top;
// mForegroundPaddingRight = padding.right;
// mForegroundPaddingBottom = padding.bottom;
// }
// } else {
// mForegroundPaddingLeft = 0;
// mForegroundPaddingTop = 0;
// mForegroundPaddingRight = 0;
// mForegroundPaddingBottom = 0;
// }
//
// requestLayout();
// }
// }
/**
* {@inheritDoc}
*/
public boolean verifyDrawable(Drawable who) {
return super.verifyDrawable(who) || (who == mForeground);
}
/**
* {@inheritDoc}
*/
public void drawableStateChanged() {
super.drawableStateChanged();
if (mForeground != null && mForeground.isStateful()) {
mForeground.setState(getDrawableState());
}
}
/**
* Returns a set of layout parameters with a width of
* {@link android.view.ViewGroup.LayoutParams#MATCH_PARENT}, and a height of
* {@link android.view.ViewGroup.LayoutParams#MATCH_PARENT}.
*/
protected LayoutParams generateDefaultLayoutParams() {
return new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT);
}
/**
* Supply a Drawable that is to be rendered on top of all of the child views
* in the frame layout. Any padding in the Drawable will be taken into
* account by ensuring that the children are inset to be placed inside of
* the padding area.
*
* @param drawable
* The Drawable to be drawn on top of the children.
*
* @attr ref android.R.styleable#FrameLayout_foreground
*/
public void setForeground(Drawable drawable) {
// TODO
}
/**
* Returns the drawable used as the foreground of this FrameLayout. The
* foreground drawable, if non-null, is always drawn on top of the children.
*
* @return A Drawable or null if no foreground was set.
*/
public Drawable getForeground() {
return mForeground;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final int count = getChildCount();
int maxHeight = 0;
int maxWidth = 0;
// Find rightmost and bottommost child
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
if (child.getVisibility() != GONE) {
measureChildWithMargins(child, widthMeasureSpec, 0,
heightMeasureSpec, 0);
maxWidth = Math.max(maxWidth, child.getMeasuredWidth());
maxHeight = Math.max(maxHeight, child.getMeasuredHeight());
}
}
// Account for padding too
maxWidth += mPaddingLeft + mPaddingRight + mForegroundPaddingLeft
+ mForegroundPaddingRight;
maxHeight += mPaddingTop + mPaddingBottom + mForegroundPaddingTop
+ mForegroundPaddingBottom;
// Check against our minimum height and width
maxHeight = Math.max(maxHeight, getSuggestedMinimumHeight());
maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth());
setMeasuredDimension(resolveSize(maxWidth, widthMeasureSpec),
resolveSize(maxHeight, heightMeasureSpec));
}
@Override
protected void onLayout(boolean changed, int left, int top, int right,
int bottom) {
final int count = getChildCount();
final int parentLeft = mPaddingLeft + mForegroundPaddingLeft;
final int parentRight = right - left - mPaddingRight
- mForegroundPaddingRight;
final int parentTop = mPaddingTop + mForegroundPaddingTop;
final int parentBottom = bottom - top - mPaddingBottom
- mForegroundPaddingBottom;
mForegroundBoundsChanged = true;
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
if (child.getVisibility() != GONE) {
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
/**
@j2sNative
if (isNaN(lp.leftMargin))
lp.leftMargin = 0;
if (isNaN(lp.rightMargin))
lp.rightMargin = 0;
if (isNaN(lp.topMargin))
lp.topMargin = 0;
if (isNaN(lp.bottomMargin))
lp.bottomMargin = 0;
*/
{
}
final int width = child.getMeasuredWidth();
final int height = child.getMeasuredHeight();
int childLeft = parentLeft;
int childTop = parentTop;
final int gravity = lp.gravity;
if (gravity != -1) {
final int horizontalGravity = gravity
& Gravity.HORIZONTAL_GRAVITY_MASK;
final int verticalGravity = gravity
& Gravity.VERTICAL_GRAVITY_MASK;
switch (horizontalGravity) {
case Gravity.LEFT:
childLeft = parentLeft + lp.leftMargin;
break;
case Gravity.CENTER_HORIZONTAL:
childLeft = parentLeft
+ (parentRight - parentLeft - width) / 2
+ lp.leftMargin - lp.rightMargin;
break;
case Gravity.RIGHT:
childLeft = parentRight - width - lp.rightMargin;
break;
default:
childLeft = parentLeft + lp.leftMargin;
}
switch (verticalGravity) {
case Gravity.TOP:
childTop = parentTop + lp.topMargin;
break;
case Gravity.CENTER_VERTICAL:
childTop = parentTop
+ (parentBottom - parentTop - height) / 2
+ lp.topMargin - lp.bottomMargin;
break;
case Gravity.BOTTOM:
childTop = parentBottom - height - lp.bottomMargin;
break;
default:
childTop = parentTop + lp.topMargin;
}
}
child.layout(childLeft, childTop, childLeft + width, childTop
+ height);
}
}
}
/**
* {@inheritDoc}
*/
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mForegroundBoundsChanged = true;
}
/**
* Determines whether to measure all children or just those in the VISIBLE
* or INVISIBLE state when measuring. Defaults to false.
*
* @param measureAll
* true to consider children marked GONE, false otherwise.
* Default value is false.
*
* @attr ref android.R.styleable#FrameLayout_measureAllChildren
*/
public void setMeasureAllChildren(boolean measureAll) {
mMeasureAllChildren = measureAll;
}
/**
* Determines whether to measure all children or just those in the VISIBLE
* or INVISIBLE state when measuring.
*/
public boolean getConsiderGoneChildrenWhenMeasuring() {
return mMeasureAllChildren;
}
/**
* {@inheritDoc}
*/
@Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
return new FrameLayout.LayoutParams(getContext(), attrs);
}
/**
* {@inheritDoc}
*/
@Override
protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
return p instanceof LayoutParams;
}
@Override
protected ViewGroup.LayoutParams generateLayoutParams(
ViewGroup.LayoutParams p) {
return new LayoutParams(p);
}
/**
* Per-child layout information for layouts that support margins. See
* {@link com.intel.jsdroid.sample.R.styleable#FrameLayout_Layout
* FrameLayout Layout Attributes} for a list of all child view attributes
* that this class supports.
*/
public static class LayoutParams extends MarginLayoutParams {
/**
* The gravity to apply with the View to which these layout parameters
* are associated.
*
* @see android.view.Gravity
*/
public int gravity = -1;
/**
* {@inheritDoc}
*/
public LayoutParams(Context c, AttributeSet attrs) {
super(c, attrs);
TypedArray a = c.obtainStyledAttributes(attrs,
com.android.internal.R.styleable.FrameLayout_Layout);
gravity = a
.getInt(com.android.internal.R.styleable.FrameLayout_Layout_layout_gravity,
-1);
a.recycle();
}
/**
* {@inheritDoc}
*/
public LayoutParams(int width, int height) {
super(width, height);
}
/**
* Creates a new set of layout parameters with the specified width,
* height and weight.
*
* @param width
* the width, either {@link #MATCH_PARENT},
* {@link #WRAP_CONTENT} or a fixed size in pixels
* @param height
* the height, either {@link #MATCH_PARENT},
* {@link #WRAP_CONTENT} or a fixed size in pixels
* @param gravity
* the gravity
*
* @see android.view.Gravity
*/
public LayoutParams(int width, int height, int gravity) {
super(width, height);
this.gravity = gravity;
}
/**
* {@inheritDoc}
*/
public LayoutParams(ViewGroup.LayoutParams source) {
super(source);
}
/**
* {@inheritDoc}
*/
public LayoutParams(ViewGroup.MarginLayoutParams source) {
super(source);
}
}
@Override
public void childDrawableStateChanged(View child) {
// TODO Auto-generated method stub
}
@Override
public View focusSearch(View v, int direction) {
// TODO Auto-generated method stub
return null;
}
@Override
public void addView(View view, android.view.ViewGroup.LayoutParams params) {
addView(view, params, true);
}
/**
* @j2sNative
* console.log("Missing method: gatherTransparentRegion");
*/
@MayloonStubAnnotation()
public boolean gatherTransparentRegion(Region region) {
System.out.println("Stub" + " Function : gatherTransparentRegion");
return true;
}
/**
* @j2sNative
* console.log("Missing method: setForegroundGravity");
*/
@MayloonStubAnnotation()
public void setForegroundGravity(int foregroundGravity) {
System.out.println("Stub" + " Function : setForegroundGravity");
return;
}
}