Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TIMOB-7836: Allow fill behavior for horiztonal and veritcal layouts #1659

Merged
merged 6 commits into from
Mar 15, 2012
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ private int calculateAbsoluteRight(View child)
int contentWidth = getContentProperty(TiC.PROPERTY_CONTENT_WIDTH);
if (contentWidth == AUTO) {
int childMeasuredWidth = child.getMeasuredWidth();
if (!p.autoWidth && p.optionWidth != null) {
if (!p.sizeOrFillWidthEnabled && p.optionWidth != null) {
childMeasuredWidth = getDimensionValue(p.optionWidth, parentWidth);
}
if (p.optionLeft != null) {
Expand All @@ -137,7 +137,7 @@ private int calculateAbsoluteBottom(View child)

if (contentHeight == AUTO) {
int childMeasuredHeight = child.getMeasuredHeight();
if (!p.autoHeight && p.optionHeight != null) {
if (!p.sizeOrFillHeightEnabled && p.optionHeight != null) {
childMeasuredHeight = getDimensionValue(p.optionHeight, parentHeight);
}
if (p.optionTop != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -411,14 +411,14 @@ private View layoutHeaderOrFooter(TiViewProxy viewProxy)

int width = AbsListView.LayoutParams.WRAP_CONTENT;
int height = AbsListView.LayoutParams.WRAP_CONTENT;
if (params.autoHeight) {
if (params.sizeOrFillHeightEnabled) {
if (params.autoFillsHeight) {
height = AbsListView.LayoutParams.FILL_PARENT;
}
} else if (params.optionHeight != null) {
height = params.optionHeight.getAsPixels(listView);
}
if (params.autoWidth) {
if (params.sizeOrFillWidthEnabled) {
if (params.autoFillsWidth) {
width = AbsListView.LayoutParams.FILL_PARENT;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,9 +175,9 @@ public static boolean fillLayout(HashMap<String, Object> hashMap, LayoutParams l
Object width = null;
Object height = null;

// Set auto width/height to false to trigger undefined behavior
layoutParams.autoWidth = false;
layoutParams.autoHeight = false;
// Don't use fill or size by default (this is to trigger undefined behavior)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is "undefined" behavior? You should add a definition or a link if its already documented somewhere.

layoutParams.sizeOrFillWidthEnabled = false;
layoutParams.sizeOrFillHeightEnabled = false;

if (hashMap.containsKey(TiC.PROPERTY_SIZE)) {
HashMap<String, Object> size = (HashMap<String, Object>) hashMap.get(TiC.PROPERTY_SIZE);
Expand Down Expand Up @@ -217,26 +217,26 @@ public static boolean fillLayout(HashMap<String, Object> hashMap, LayoutParams l

if (width == null) {
layoutParams.optionWidth = null;
layoutParams.autoWidth = false;
layoutParams.sizeOrFillWidthEnabled = false;

} else if (width.equals(TiC.SIZE_AUTO)) {
layoutParams.optionWidth = null;
layoutParams.autoWidth = true;
layoutParams.sizeOrFillWidthEnabled = true;

} else if (width.equals(TiC.LAYOUT_FILL)) {
// fill
layoutParams.optionWidth = null;
layoutParams.autoWidth = true;
layoutParams.sizeOrFillWidthEnabled = true;
layoutParams.autoFillsWidth = true;

} else if (width.equals(TiC.LAYOUT_SIZE)) {
// size
layoutParams.optionWidth = null;
layoutParams.autoWidth = true;
layoutParams.sizeOrFillWidthEnabled = true;
layoutParams.autoFillsWidth = false;
} else {
layoutParams.optionWidth = toTiDimension(width, TiDimension.TYPE_WIDTH);
layoutParams.autoWidth = false;
layoutParams.sizeOrFillWidthEnabled = false;
}
dirty = true;
}
Expand All @@ -248,26 +248,26 @@ public static boolean fillLayout(HashMap<String, Object> hashMap, LayoutParams l

if (height == null) {
layoutParams.optionHeight = null;
layoutParams.autoHeight = false;
layoutParams.sizeOrFillHeightEnabled = false;

} else if (height.equals(TiC.SIZE_AUTO)) {
layoutParams.optionHeight = null;
layoutParams.autoHeight = true;
layoutParams.sizeOrFillHeightEnabled = true;

} else if (height.equals(TiC.LAYOUT_FILL)) {
// fill
layoutParams.optionHeight = null;
layoutParams.autoHeight = true;
layoutParams.sizeOrFillHeightEnabled = true;
layoutParams.autoFillsHeight = true;

} else if (height.equals(TiC.LAYOUT_SIZE)) {
// size
layoutParams.optionHeight = null;
layoutParams.autoHeight = true;
layoutParams.sizeOrFillHeightEnabled = true;
layoutParams.autoFillsHeight = false;
} else {
layoutParams.optionHeight = toTiDimension(height, TiDimension.TYPE_HEIGHT);
layoutParams.autoHeight = false;
layoutParams.sizeOrFillHeightEnabled = false;
}
dirty = true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,15 +190,17 @@ protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
@Override
protected LayoutParams generateDefaultLayoutParams()
{
// Default is fill view
// Default behavior is size since optionWidth/optionHeight is null, and autoFillsWidth/autoFillsHeight is false.
// Some classes such as ViewProxy will set autoFillsWidth/autoFillsHeight to true in order to trigger the fill
// behavior by default.
LayoutParams params = new LayoutParams();
params.optionLeft = null;
params.optionRight = null;
params.optionTop = null;
params.optionBottom = null;
params.optionZIndex = NOT_SET;
params.autoHeight = true;
params.autoWidth = true;
params.sizeOrFillHeightEnabled = true;
params.sizeOrFillWidthEnabled = true;

return params;
}
Expand Down Expand Up @@ -308,6 +310,7 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
protected void constrainChild(View child, int width, int wMode, int height, int hMode)
{
LayoutParams p = (LayoutParams) child.getLayoutParams();
// If autoFillsWidth is false, and optionWidth is null, then we use size behavior.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Definition of size behavior would be nice here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added description for size in the autoFillHeight moduleAPI description.

int childDimension = LayoutParams.WRAP_CONTENT;
if (p.optionWidth != null) {
if (p.optionWidth.isUnitPercent() && width > 0) {
Expand All @@ -316,14 +319,15 @@ protected void constrainChild(View child, int width, int wMode, int height, int
childDimension = p.optionWidth.getAsPixels(this);
}
} else {
if (p.autoFillsWidth && !isHorizontalArrangement()) {
if (p.autoFillsWidth) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not see code where width is undefined and can not be calculated from pins (follow auto behavior) or auto where the default auto behavior if fill. Are these flags set up somewhere else?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did some code clean up to make the logic more clear. I renamed two methods to calculateHeightFromPins() and calculateWidthFromPins() inside onLayout() which takes care of the calculation. We essentially do the calculation for fill/size in constrainChild() and then we determine if we want to use those calculations in calculateHeightFromPins(). If we can't calculate from the pins, then we use the default size/fill behavior (passed in as measuredHeight).

childDimension = LayoutParams.FILL_PARENT;
}
}

int widthPadding = getViewWidthPadding(child, width);
int widthSpec = ViewGroup.getChildMeasureSpec(MeasureSpec.makeMeasureSpec(width, wMode), widthPadding,
childDimension);
// If autoFillsHeight is false, and optionHeight is null, then we use size behavior.
childDimension = LayoutParams.WRAP_CONTENT;
if (p.optionHeight != null) {
if (p.optionHeight.isUnitPercent() && height > 0) {
Expand All @@ -332,7 +336,7 @@ protected void constrainChild(View child, int width, int wMode, int height, int
childDimension = p.optionHeight.getAsPixels(this);
}
} else {
if (p.autoFillsHeight && !isVerticalArrangement()) {
if (p.autoFillsHeight) {
childDimension = LayoutParams.FILL_PARENT;
}
}
Expand All @@ -347,11 +351,14 @@ protected void constrainChild(View child, int width, int wMode, int height, int
// int childHeight = child.getMeasuredHeight();
}

private int getUndefinedWidth(LayoutParams params, int parentLeft, int parentRight, int parentWidth)
// Try to calculate width from pins, if we couldn't calculate from pins or we don't need to, then return the measured
// width
private int calculateWidthFromPins(LayoutParams params, int parentLeft, int parentRight, int parentWidth,
int measuredWidth)
{
int width = -1;
int width = measuredWidth;

if (params.optionWidth != null || params.autoWidth) {
if (params.optionWidth != null || params.sizeOrFillWidthEnabled) {
return width;
}

Expand All @@ -371,12 +378,15 @@ private int getUndefinedWidth(LayoutParams params, int parentLeft, int parentRig
return width;
}

private int getUndefinedHeight(LayoutParams params, int parentTop, int parentBottom, int parentHeight)
// Try to calculate height from pins, if we couldn't calculate from pins or we don't need to, then return the measured
// height
private int calculateHeightFromPins(LayoutParams params, int parentTop, int parentBottom, int parentHeight,
int measuredHeight)
{
int height = -1;
int height = measuredHeight;

// Return if we don't need undefined behavior
if (params.optionHeight != null || params.autoHeight) {
if (params.optionHeight != null || params.sizeOrFillHeightEnabled) {
return height;
}

Expand Down Expand Up @@ -451,18 +461,11 @@ protected void onLayout(boolean changed, int l, int t, int r, int b)
(TiCompositeLayout.LayoutParams) child.getLayoutParams();
if (child.getVisibility() != View.GONE) {
// Dimension is required from Measure. Positioning is determined here.

// Try using undefined behavior first
int childMeasuredHeight = getUndefinedHeight(params, top, bottom, getHeight());
int childMeasuredWidth = getUndefinedWidth(params, left, right, getWidth());

if (childMeasuredWidth == -1) {
childMeasuredWidth = child.getMeasuredWidth();
}

if (childMeasuredHeight == -1) {
childMeasuredHeight = child.getMeasuredHeight();
}
// Try to calculate width/height from pins, and default to measured width/height. We have to do this in
// onLayout since we can't get the correct top, bottom, left, and right values inside constrainChild().
int childMeasuredHeight = calculateHeightFromPins(params, top, bottom, getHeight(), child.getMeasuredHeight());
int childMeasuredWidth = calculateWidthFromPins(params, left, right, getWidth(), child.getMeasuredWidth());

if (isHorizontalArrangement()) {
if (i == 0) {
Expand Down Expand Up @@ -610,17 +613,18 @@ public static class LayoutParams extends ViewGroup.LayoutParams {
public TiDimension optionHeight = null;
public Ti2DMatrix optionTransform = null;

public boolean autoHeight = true;
public boolean autoWidth = true;
// This are flags to determine whether we are using fill or size behavior
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Definition or link of fill behavior.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fill behavior is already documented in the moduleAPI description for autoFillHeight. I made it more clear that we are describing the fill behavior.

public boolean sizeOrFillHeightEnabled = true;
public boolean sizeOrFillWidthEnabled = true;

/**
* If this is true, and {@link #autoWidth} is true, then the current view will fill available parent width.
* If this is true, and {@link #sizeOrFillWidthEnabled} is true, then the current view will fill available parent width.
* @module.api
*/
public boolean autoFillsWidth = false;

/**
* If this is true, and {@link #autoHeight} is true, then the current view will fill available parent height.
* If this is true, and {@link #sizeOrFillHeightEnabled} is true, then the current view will fill available parent height.
* @module.api
*/
public boolean autoFillsHeight = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -381,10 +381,10 @@ public void propertyChanged(String key, Object oldValue, Object newValue, KrollP
if (newValue != null) {
if (!newValue.equals(TiC.SIZE_AUTO)) {
layoutParams.optionHeight = TiConvert.toTiDimension(TiConvert.toString(newValue), TiDimension.TYPE_HEIGHT);
layoutParams.autoHeight = false;
layoutParams.sizeOrFillHeightEnabled = false;
} else {
layoutParams.optionHeight = null;
layoutParams.autoHeight = true;
layoutParams.sizeOrFillHeightEnabled = true;
}
} else {
layoutParams.optionHeight = null;
Expand All @@ -394,10 +394,10 @@ public void propertyChanged(String key, Object oldValue, Object newValue, KrollP
if (newValue != null) {
if (!newValue.equals(TiC.SIZE_AUTO)) {
layoutParams.optionWidth = TiConvert.toTiDimension(TiConvert.toString(newValue), TiDimension.TYPE_WIDTH);
layoutParams.autoWidth = false;
layoutParams.sizeOrFillWidthEnabled = false;
} else {
layoutParams.optionWidth = null;
layoutParams.autoWidth = true;
layoutParams.sizeOrFillWidthEnabled = true;
}
} else {
layoutParams.optionWidth = null;
Expand Down
20 changes: 20 additions & 0 deletions drillbit/tests/ui.layout/ui.layout.js
Original file line number Diff line number Diff line change
Expand Up @@ -631,6 +631,26 @@ describe("Ti.UI Layout tests", {
win.add(view1);
win.open();
}),
fillInVerticalLayout: asyncTest(function() {
var win = Ti.UI.createWindow({
});
var parent = Ti.UI.createView({
height: 50,
width: 40,
layout: 'vertical',
});
var child = Ti.UI.createView({
});
parent.add(child);
win.add(parent);
win.addEventListener("open", this.async(function(e) {
valueOf(parent.size.width).shouldBe(40);
valueOf(parent.size.height).shouldBe(50);
valueOf(child.size.width).shouldBe(40);
valueOf(child.size.height).shouldBe(50);
}));
win.open();
}),
fourPins: asyncTest(function() {
var win = Ti.UI.createWindow({
width: 100, height: 100
Expand Down