Skip to content

Commit

Permalink
Merge pull request #1652 from bryan-m-hughes/timob-7945
Browse files Browse the repository at this point in the history
Timob 7945 Layout performance update.
  • Loading branch information
cb1kenobi committed Mar 14, 2012
2 parents 5d5921c + c51eef4 commit a64933a
Show file tree
Hide file tree
Showing 13 changed files with 325 additions and 267 deletions.
180 changes: 120 additions & 60 deletions mobileweb/titanium/Ti/UI.js
Expand Up @@ -6,7 +6,8 @@ define(
isIOS = /(iPhone|iPad)/.test(navigator.userAgent),
modules = "2DMatrix,ActivityIndicator,AlertDialog,Animation,Button,EmailDialog,ImageView,Label,OptionDialog,Picker,PickerColumn,PickerRow,ProgressBar,ScrollableView,ScrollView,Slider,Switch,Tab,TabGroup,TableView,TableViewRow,TableViewSection,TextArea,TextField,View,WebView,Window",
creators = {},
setStyle = style.set;
setStyle = style.set,
undef;

body.addEventListener('touchmove', function(e) {
e.preventDefault();
Expand Down Expand Up @@ -72,6 +73,8 @@ define(

_layoutSemaphore: 0,

_nodesToLayout: [],

_startLayout: function() {
this._layoutSemaphore++;
},
Expand All @@ -83,64 +86,128 @@ define(
}
},

_triggerLayout: function(force) {
if (force) {
clearTimeout(this._layoutTimer);
this._layoutMarkedNodes(this._container);
this._layoutInProgress = false;
} else {
if (!this._layoutInProgress) {
this._layoutInProgress = true;
this._layoutTimer = setTimeout(lang.hitch(this, function(){
this._layoutMarkedNodes(this._container);
this._layoutInProgress = false;
this._layoutTimer = null;
}), 25);
}
}
},
_elementLayoutCount: 0,

_layoutCount: 0,

_layoutMarkedNodes: function(node) {
if (node._markedForLayout) {
var parent = node._parent,
isParentWidthSize = parent && parent.width === Ti.UI.SIZE,
isParentHeightSize = parent && parent.height === Ti.UI.SIZE;
node._layout && node._layout._doLayout(node, node._measuredWidth, node._measuredHeight, !!isParentWidthSize, !!isParentHeightSize);
} else {
for (var i in node.children) {
this._layoutMarkedNodes(node.children[i]);
_triggerLayout: function(node, force) {
var self = this;
if (~self._nodesToLayout.indexOf(node)) {
return;
}
self._nodesToLayout.push(node);
function startLayout() {

self._elementLayoutCount = 0;
self._layoutCount++;
var startTime = (new Date()).getTime(),
nodes = self._nodesToLayout,
layoutNode,
node,
parent,
previousParent,
children,
child,
recursionStack,
rootNodesToLayout = [],
layoutRootNode = false;

// Determine which nodes need to be re-layed out
for (var i in nodes) {
layoutNode = nodes[i];

// Mark all of the children for update that need to be updated
recursionStack = [layoutNode];
while (recursionStack.length > 0) {
node = recursionStack.pop();
node._markedForLayout = true;
children = node.children;
for (var j in children) {
child = children[j];
if (node.layout !== "composite" || child._isDependentOnParent || !child._hasBeenLayedOut) {
recursionStack.push(child);
}
}
}

// Go up and mark any other nodes that need to be marked
parent = layoutNode;
while(1) {
if (!parent._parent) {
layoutRootNode = true;
break;
} else if(!parent._parent._hasSizeDimensions()) {
!parent._parent._markedForLayout && rootNodesToLayout.push(parent._parent);
break;
}

previousParent = parent;
parent = parent._parent;
recursionStack = [parent];
while (recursionStack.length > 0) {
node = recursionStack.pop();
children = node.children;
for (var j in children) {
child = children[j];
if (child !== previousParent && (node.layout !== "composite" || child._isDependentOnParent)) {
child._markedForLayout = true;
recursionStack.push(child);
}
}
}
}
}
// Run the post-layout animation, if needed
if (node._doAnimationAfterLayout) {
node._doAnimationAfterLayout = false;
node._doAnimation();

// Layout all nodes that need it
if (layoutRootNode) {
var container = self._container;
container._doLayout({
origin: {
x: 0,
y: 0
},
isParentSize: {
width: false,
height: false
},
boundingSize: {
width: window.innerWidth,
height: window.innerHeight
},
alignment: {
horizontal: "center",
vertical: "center"
},
positionElement: true,
layoutChildren: true
});
}
for (var i in rootNodesToLayout) {
node = rootNodesToLayout[i];
node._layout._doLayout(node, node._measuredWidth, node._measuredHeight, node.width === Ti.UI.SIZE, node.height === Ti.UI.SIZE);
}

console.debug("Layout " + self._layoutCount + ": " + self._elementLayoutCount +
" elements laid out in " + ((new Date().getTime() - startTime)) + "ms");

self._layoutInProgress = false;
self._layoutTimer = null;
self._nodesToLayout = [];
}
if (force) {
clearTimeout(self._layoutTimer);
self._layoutInProgress = true;
startLayout();
} else if (self._nodesToLayout.length === 1) {
self._layoutInProgress = true;
self._layoutTimer = setTimeout(function(){ startLayout(); }, 25);
}
},

_recalculateLayout: function() {
var width = this._container.width = window.innerWidth,
height = this._container.height = window.innerHeight;
this._container._doLayout({
origin: {
x: 0,
y: 0
},
isParentSize: {
width: false,
height: false
},
boundingSize: {
width: width,
height: height
},
alignment: {
horizontal: "center",
vertical: "center"
},
positionElement: true,
layoutChildren: true
});
var container = this._container;
container.width = window.innerWidth;
container.height = window.innerHeight;
},

properties: {
Expand All @@ -154,14 +221,7 @@ define(
return setStyle(body, "backgroundImage", value ? style.url(value) : "");
}
},
currentTab: {
get: function() {
return (this.currentWindow || {}).activeTab;
},
set: function(value) {
return (this.currentWindow || {}).activeTab = value;
}
}
currentTab: undef
},

convertUnits: function(convertFromValue, convertToUnits) {
Expand Down
2 changes: 1 addition & 1 deletion mobileweb/titanium/Ti/UI/ActivityIndicator.js
Expand Up @@ -109,7 +109,7 @@ define(["Ti/_/declare", "Ti/_/UI/FontWidget", "Ti/_/dom", "Ti/_/style", "Ti/Loca
}
setStyle(this._indicatorMessage,"paddingLeft", dom.unitize(this._messagePadding));
this._indicatorMessage.innerHTML = innerHTML;
this._hasSizeDimensions() && this._triggerParentLayout();
this._hasSizeDimensions() && this._triggerLayout();
return value;
}
},
Expand Down
2 changes: 1 addition & 1 deletion mobileweb/titanium/Ti/UI/Button.js
Expand Up @@ -166,7 +166,7 @@ define(["Ti/_/declare", "Ti/_/UI/FontWidget", "Ti/_/dom", "Ti/_/css", "Ti/_/styl
title: {
set: function(value) {
this._buttonTitle.innerHTML = value;
this._hasSizeDimensions() && this._triggerParentLayout();
this._hasSizeDimensions() && this._triggerLayout();
return value;
}
},
Expand Down
4 changes: 2 additions & 2 deletions mobileweb/titanium/Ti/UI/Label.js
Expand Up @@ -83,7 +83,7 @@ define(["Ti/_/declare", "Ti/_/UI/FontWidget", "Ti/_/dom", "Ti/_/css", "Ti/_/styl
html: {
set: function(value) {
this.textContainerDiv.innerHTML = value;
this._hasSizeDimensions() && this._triggerParentLayout();
this._hasSizeDimensions() && this._triggerLayout();
return value;
}
},
Expand Down Expand Up @@ -129,7 +129,7 @@ define(["Ti/_/declare", "Ti/_/UI/FontWidget", "Ti/_/dom", "Ti/_/css", "Ti/_/styl
value.match("<br/>$") && (value += "&nbsp;");

this.textContainerDiv.innerHTML = value;
this._hasSizeDimensions() && this._triggerParentLayout();
this._hasSizeDimensions() && this._triggerLayout();
return value;
}
},
Expand Down
8 changes: 4 additions & 4 deletions mobileweb/titanium/Ti/UI/PickerColumn.js
Expand Up @@ -205,7 +205,7 @@ define(["Ti/_/declare", "Ti/_/UI/FontWidget", "Ti/_/dom", "Ti/UI", "Ti/_/style",
}
if (this._widestRowWidth !== widestRowWidth) {
this._widestRowWidth = widestRowWidth;
this._triggerParentLayout();
this._triggerLayout();
}
}
},
Expand All @@ -225,7 +225,7 @@ define(["Ti/_/declare", "Ti/_/UI/FontWidget", "Ti/_/dom", "Ti/UI", "Ti/_/style",
_setTallestRowHeight: function(height) {
if (this._tallestRowHeight !== height) {
this._tallestRowHeight = height;
this._triggerParentLayout();
this._triggerLayout();
}
},

Expand Down Expand Up @@ -276,7 +276,7 @@ define(["Ti/_/declare", "Ti/_/UI/FontWidget", "Ti/_/dom", "Ti/UI", "Ti/_/style",
this.font = undef;
this.color = undef;
this._titleContainer.innerHTML = "";
this._hasSizeDimensions() && this._triggerParentLayout();
this._hasSizeDimensions() && this._triggerLayout();
} else {
var rowIndex = this._rows.indexOf(value);
if (rowIndex === -1) {
Expand All @@ -285,7 +285,7 @@ define(["Ti/_/declare", "Ti/_/UI/FontWidget", "Ti/_/dom", "Ti/UI", "Ti/_/style",
this.font = value.font;
this.color = lang.val(value.color, "");
this._titleContainer.innerHTML = value.title;
this._hasSizeDimensions() && this._triggerParentLayout();
this._hasSizeDimensions() && this._triggerLayout();
}
return value;
},
Expand Down
6 changes: 3 additions & 3 deletions mobileweb/titanium/Ti/UI/Switch.js
Expand Up @@ -186,7 +186,7 @@ define(["Ti/_/declare", "Ti/_/UI/FontWidget", "Ti/_/dom", "Ti/_/css", "Ti/_/styl
set: function(value) {
if (!this.value) {
this._switchTitle.innerHTML = value;
this._hasSizeDimensions() && this._triggerParentLayout();
this._hasSizeDimensions() && this._triggerLayout();
}
return value;
},
Expand All @@ -197,7 +197,7 @@ define(["Ti/_/declare", "Ti/_/UI/FontWidget", "Ti/_/dom", "Ti/_/css", "Ti/_/styl
set: function(value) {
if (this.value) {
this._switchTitle.innerHTML = value;
this._hasSizeDimensions() && this._triggerParentLayout();
this._hasSizeDimensions() && this._triggerLayout();
}
return value;
},
Expand All @@ -211,7 +211,7 @@ define(["Ti/_/declare", "Ti/_/UI/FontWidget", "Ti/_/dom", "Ti/_/css", "Ti/_/styl
});
value = !!value;
this._switchTitle.innerHTML = value ? this.titleOn : this.titleOff;
this._hasSizeDimensions() && this._triggerParentLayout();
this._hasSizeDimensions() && this._triggerLayout();
return value;
},
post: function() {
Expand Down
1 change: 1 addition & 0 deletions mobileweb/titanium/Ti/UI/TabGroup.js
Expand Up @@ -109,6 +109,7 @@ define(["Ti/_/declare", "Ti/_/css", "Ti/_/UI/SuperView", "Ti/UI/View", "Ti/UI",

tab.active = true;
this._activeTab = tab;
UI.currentTab = tab;
tab["window"] && this._tabContentContainer.add(tab["window"]);
this._state = {
index: tabs.indexOf(tab),
Expand Down
3 changes: 2 additions & 1 deletion mobileweb/titanium/Ti/UI/View.js
Expand Up @@ -19,7 +19,8 @@ define(["Ti/_/declare", "Ti/_/dom", "Ti/_/UI/Element", "Ti/_/lang", "Ti/_/string
view._setParent(this);
this.children.push(view);
this.containerNode.appendChild(view.domNode);
this._triggerLayout();
view._hasBeenLaidOut = false;
this._triggerLayout(this._isAttachedToActiveWin());
},

_setParent: function(view) {
Expand Down
4 changes: 3 additions & 1 deletion mobileweb/titanium/Ti/_/Layouts/Base.js
Expand Up @@ -9,7 +9,9 @@ define(["Ti/_/css", "Ti/_/declare", "Ti/_/style", "Ti/_/dom"], function(css, dec

destroy: function() {
css.remove(this.element.domNode, css.clean(this.declaredClass));
}
},

_computedSize: {width: 0, height: 0}

});

Expand Down
47 changes: 25 additions & 22 deletions mobileweb/titanium/Ti/_/Layouts/Composite.js
Expand Up @@ -3,31 +3,34 @@ define(["Ti/_/Layouts/Base", "Ti/_/declare"], function(Base, declare) {
return declare("Ti._.Layouts.Composite", Base, {

_doLayout: function(element, width, height, isWidthSize, isHeightSize) {
var computedSize = this._computedSize = {width: 0, height: 0};
for(var i in element.children) {
var computedSize = this._computedSize = {width: 0, height: 0},
children = element.children;
for(var i = 0; i < children.length; i++) {

// Layout the child
var child = element.children[i];
child._doLayout({
origin: {
x: 0,
y: 0
},
isParentSize: {
width: isWidthSize,
height: isHeightSize
},
boundingSize: {
width: width,
height: height
},
alignment: {
horizontal: this._defaultHorizontalAlignment,
vertical: this._defaultVerticalAlignment
},
positionElement: true,
layoutChildren: true
});
if (child._markedForLayout) {
child._doLayout({
origin: {
x: 0,
y: 0
},
isParentSize: {
width: isWidthSize,
height: isHeightSize
},
boundingSize: {
width: width,
height: height
},
alignment: {
horizontal: this._defaultHorizontalAlignment,
vertical: this._defaultVerticalAlignment
},
positionElement: true,
layoutChildren: true
});
}

// Update the size of the component
var rightMostEdge = child._measuredWidth + child._measuredLeft + child._measuredBorderSize.left + child._measuredBorderSize.right + child._measuredRightPadding;
Expand Down

0 comments on commit a64933a

Please sign in to comment.