| 
									
										
										
										
											2011-07-06 15:48:52 +00:00
										 |  |  | /************************************************************************** | 
					
						
							|  |  |  | ** | 
					
						
							|  |  |  | ** This file is part of Qt Creator | 
					
						
							|  |  |  | ** | 
					
						
							|  |  |  | ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). | 
					
						
							|  |  |  | ** | 
					
						
							| 
									
										
										
										
											2011-11-02 15:59:12 +01:00
										 |  |  | ** Contact: Nokia Corporation (qt-info@nokia.com) | 
					
						
							| 
									
										
										
										
											2011-07-06 15:48:52 +00:00
										 |  |  | ** | 
					
						
							|  |  |  | ** | 
					
						
							|  |  |  | ** GNU Lesser General Public License Usage | 
					
						
							|  |  |  | ** | 
					
						
							|  |  |  | ** This file may be used under the terms of the GNU Lesser General Public | 
					
						
							|  |  |  | ** License version 2.1 as published by the Free Software Foundation and | 
					
						
							|  |  |  | ** appearing in the file LICENSE.LGPL included in the packaging of this file. | 
					
						
							|  |  |  | ** Please review the following information to ensure the GNU Lesser General | 
					
						
							|  |  |  | ** Public License version 2.1 requirements will be met: | 
					
						
							|  |  |  | ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 | 
					
						
							|  |  |  | ** | 
					
						
							|  |  |  | ** In addition, as a special exception, Nokia gives you certain additional | 
					
						
							|  |  |  | ** rights. These rights are described in the Nokia Qt LGPL Exception | 
					
						
							|  |  |  | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. | 
					
						
							|  |  |  | ** | 
					
						
							|  |  |  | ** Other Usage | 
					
						
							|  |  |  | ** | 
					
						
							|  |  |  | ** Alternatively, this file may be used in accordance with the terms and | 
					
						
							|  |  |  | ** conditions contained in a signed written agreement between you and Nokia. | 
					
						
							|  |  |  | ** | 
					
						
							|  |  |  | ** If you have questions regarding the use of this file, please contact | 
					
						
							| 
									
										
										
										
											2011-11-02 15:59:12 +01:00
										 |  |  | ** Nokia at qt-info@nokia.com. | 
					
						
							| 
									
										
										
										
											2011-07-06 15:48:52 +00:00
										 |  |  | ** | 
					
						
							|  |  |  | **************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-11 16:49:17 +01:00
										 |  |  | import QtQuick 1.0 | 
					
						
							|  |  |  | import "private" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* | 
					
						
							|  |  |  | * | 
					
						
							|  |  |  | * SplitterRow | 
					
						
							|  |  |  | * | 
					
						
							|  |  |  | * SplitterRow is a component that provides a way to layout items horisontally with | 
					
						
							|  |  |  | * a draggable splitter added in-between each item. | 
					
						
							|  |  |  | * | 
					
						
							|  |  |  | * Add items to the SplitterRow by inserting them as child items. The splitter handle | 
					
						
							|  |  |  | * is outsourced as a delegate (handleBackground). For this delegate to work properly, | 
					
						
							|  |  |  | * it will need to contain a mouse area that communicates with the SplitterRow by binding | 
					
						
							|  |  |  | * 'onMouseXChanged: handleDragged(handleIndex)', and 'drag.target: dragTarget'. | 
					
						
							|  |  |  | * | 
					
						
							|  |  |  | * The SplitterRow contains the followin API: | 
					
						
							|  |  |  | * | 
					
						
							|  |  |  | * Component handleBackground - delegate that will be instanciated between each | 
					
						
							|  |  |  | *   child item. Inside the delegate, the following properties are available: | 
					
						
							|  |  |  | *   int handleIndex - specifies the index of the splitter handle. The handle | 
					
						
							|  |  |  | *       between the first and the second item will get index 0, the next handle index 1 etc. | 
					
						
							|  |  |  | *   Item handleDragTarget - convenience property that tells which drag target any | 
					
						
							|  |  |  | *       inner mouse areas that controls the handle should bind to. | 
					
						
							|  |  |  | *   function handleDragged(handleIndex) - function that should be called whenever | 
					
						
							|  |  |  | *       the handle is dragged to a new position | 
					
						
							|  |  |  | * | 
					
						
							|  |  |  | * The following properties can optionally be added for each direct child item of SplitterRow: | 
					
						
							|  |  |  | * | 
					
						
							|  |  |  | * real minimumWidth - if present, ensures that the item cannot be resized below the | 
					
						
							|  |  |  | *   given value. A value of -1 will disable it. | 
					
						
							|  |  |  | * real maximumWidth - if present, ensures that the item cannot be resized above the | 
					
						
							|  |  |  | *   given value. A value of -1 will disable it. | 
					
						
							|  |  |  | * real percentageWidth - if present, should be a value between 0-100. This value specifies | 
					
						
							|  |  |  | *   a percentage of the width of the SplitterRow width. If the width of the SplitterRow | 
					
						
							|  |  |  | *   change, the width of the item will change as well. 'percentageWidth' have precedence | 
					
						
							|  |  |  | *   over 'width', which means that SplitterRow will ignore any assignments done to 'width'. | 
					
						
							|  |  |  | *   A value of -1 disables it. | 
					
						
							|  |  |  | * bool expanding - if present, the item will consume all extra space in the SplitterRow, down to | 
					
						
							|  |  |  | *   minimumWidth. This means that that 'width', 'percentageWidth' and 'maximumWidth' will be ignored. | 
					
						
							|  |  |  | *   There will always be one (and only one) item in the SplitterRow that has this behaviour, and by | 
					
						
							|  |  |  | *   default, it will be the last child item of the SplitterRow. Also note that which item that gets | 
					
						
							|  |  |  | *   resized upon dragging a handle depends on whether the expanding item is located towards the left | 
					
						
							|  |  |  | *   or the right of the handle. | 
					
						
							|  |  |  | * | 
					
						
							|  |  |  | * Example: | 
					
						
							|  |  |  | * | 
					
						
							|  |  |  | * To create a SplitterRow with three items, and let | 
					
						
							|  |  |  | * the center item be the one that should be expanding, one | 
					
						
							|  |  |  | * could do the following: | 
					
						
							|  |  |  | * | 
					
						
							|  |  |  | *    SplitterRow { | 
					
						
							|  |  |  | *        anchors.fill: parent | 
					
						
							|  |  |  | * | 
					
						
							|  |  |  | *        handleBackground: Rectangle { | 
					
						
							|  |  |  | *            width: 1 | 
					
						
							|  |  |  | *            color: "black" | 
					
						
							|  |  |  | * | 
					
						
							|  |  |  | *            MouseArea { | 
					
						
							|  |  |  | *                anchors.fill: parent | 
					
						
							|  |  |  | *                anchors.leftMargin: -2 | 
					
						
							|  |  |  | *                anchors.rightMargin: -2 | 
					
						
							|  |  |  | *                drag.axis: Qt.YAxis | 
					
						
							|  |  |  | *                drag.target: handleDragTarget | 
					
						
							|  |  |  | *                onMouseXChanged: handleDragged(handleIndex) | 
					
						
							|  |  |  | *            } | 
					
						
							|  |  |  | *        } | 
					
						
							|  |  |  | * | 
					
						
							|  |  |  | *        Rectangle { | 
					
						
							|  |  |  | *            color: "gray" | 
					
						
							|  |  |  | *            width: 200 | 
					
						
							|  |  |  | *        } | 
					
						
							|  |  |  | *        Rectangle { | 
					
						
							|  |  |  | *            property real minimumWidth: 50 | 
					
						
							|  |  |  | *            property real maximumWidth: 400 | 
					
						
							|  |  |  | *            property bool expanding: true | 
					
						
							|  |  |  | *            color: "darkgray" | 
					
						
							|  |  |  | *        } | 
					
						
							|  |  |  | *        Rectangle { | 
					
						
							|  |  |  | *            color: "gray" | 
					
						
							|  |  |  | *            width: 200 | 
					
						
							|  |  |  | *        } | 
					
						
							|  |  |  | *    } | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Item { | 
					
						
							|  |  |  |     id: root | 
					
						
							|  |  |  |     default property alias items: splitterItems.children | 
					
						
							|  |  |  |     property alias handles: splitterHandles.children | 
					
						
							|  |  |  |     property Component handleBackground: Rectangle { width:3; color: "black" } | 
					
						
							|  |  |  |     clip: true | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Component.onCompleted: d.init(); | 
					
						
							|  |  |  |     onWidthChanged: d.updateLayout(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QtObject { | 
					
						
							|  |  |  |         id: d | 
					
						
							|  |  |  |         property int expandingIndex: items.length-1 | 
					
						
							|  |  |  |         property bool updateOptimizationBlock: true | 
					
						
							|  |  |  |         property bool bindingRecursionGuard: false | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         function init() | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             for (var i=0; i<items.length-1; ++i) { | 
					
						
							|  |  |  |                 // Anchor each item to fill out all space vertically:
 | 
					
						
							|  |  |  |                 var item = items[i]; | 
					
						
							|  |  |  |                 item.anchors.top = splitterItems.top | 
					
						
							|  |  |  |                 item.anchors.bottom = splitterItems.bottom | 
					
						
							|  |  |  |                 // Listen for changes to width and expanding:
 | 
					
						
							|  |  |  |                 propertyChangeListener.createObject(item); | 
					
						
							|  |  |  |                 // Create a handle for the item:
 | 
					
						
							|  |  |  |                 var handle = handleBackgroundLoader.createObject(splitterHandles, {"handleIndex":i}); | 
					
						
							|  |  |  |                 handle.anchors.top = splitterHandles.top | 
					
						
							|  |  |  |                 handle.anchors.bottom = splitterHandles.bottom | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             item = items[i] | 
					
						
							|  |  |  |             if (item) { | 
					
						
							|  |  |  |                 // Do the same for the last item as well, since
 | 
					
						
							|  |  |  |                 // the for-loop skipped the last item:
 | 
					
						
							|  |  |  |                 items[i].anchors.top = splitterItems.top | 
					
						
							|  |  |  |                 items[i].anchors.bottom = splitterItems.bottom | 
					
						
							|  |  |  |                 propertyChangeListener.createObject(items[i]); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             d.updateOptimizationBlock = false | 
					
						
							|  |  |  |             d.updateLayout() | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         function accumulatedWidth(firstIndex, lastIndex, includeExpandingMinimum) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             // Go through items and handles, and
 | 
					
						
							|  |  |  |             // calculate their acummulated width.
 | 
					
						
							|  |  |  |             var w = 0 | 
					
						
							|  |  |  |             for (var i=firstIndex; i<lastIndex; ++i) { | 
					
						
							|  |  |  |                 var item = items[i] | 
					
						
							|  |  |  |                 if (i !== d.expandingIndex) | 
					
						
							|  |  |  |                     w += item.width; | 
					
						
							|  |  |  |                 else if (includeExpandingMinimum && item.minimumWidth != undefined && item.minimumWidth != -1) | 
					
						
							|  |  |  |                     w += item.minimumWidth | 
					
						
							|  |  |  |                 if (handles[i] && (i !== d.expandingIndex || includeExpandingMinimum === false)) | 
					
						
							|  |  |  |                     w += handles[i].width | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             return w | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         function updateLayout() | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             if (items.length === 0) | 
					
						
							|  |  |  |                 return; | 
					
						
							|  |  |  |             if (d.updateOptimizationBlock === true) | 
					
						
							|  |  |  |                 return | 
					
						
							|  |  |  |             d.updateOptimizationBlock = true | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // This function will reposition both handles and
 | 
					
						
							|  |  |  |             // items according to the _width of the each item_
 | 
					
						
							|  |  |  |             var item, prevItem | 
					
						
							|  |  |  |             var handle, prevHandle | 
					
						
							|  |  |  |             var newValue | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // Ensure all items within min/max:
 | 
					
						
							|  |  |  |             for (var i=0; i<items.length; ++i) { | 
					
						
							|  |  |  |                 if (i !== d.expandingIndex) { | 
					
						
							|  |  |  |                     item = items[i]; | 
					
						
							|  |  |  |                     // If the item is using percentage width, convert
 | 
					
						
							|  |  |  |                     // that number to real width now:
 | 
					
						
							|  |  |  |                     if (item.percentageWidth != undefined && item.percentageWidth !== -1) { | 
					
						
							|  |  |  |                         newValue = item.percentageWidth * (root.width / 100) | 
					
						
							|  |  |  |                         if (newValue !== item.width) | 
					
						
							|  |  |  |                             item.width = newValue | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                     // Ensure item width is not more than maximumWidth:
 | 
					
						
							|  |  |  |                     if (item.maximumWidth != undefined && item.maximumWidth != -1) { | 
					
						
							|  |  |  |                         newValue = Math.min(item.width, item.maximumWidth) | 
					
						
							|  |  |  |                         if (newValue !== item.width) | 
					
						
							|  |  |  |                             item.width = newValue | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                     // Ensure item width is not more less minimumWidth:
 | 
					
						
							|  |  |  |                     if (item.minimumWidth != undefined && item.minimumWidth != -1) { | 
					
						
							|  |  |  |                         newValue = Math.max(item.width, item.minimumWidth) | 
					
						
							|  |  |  |                         if (newValue !== item.width) | 
					
						
							|  |  |  |                             item.width = newValue | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // Special case: set width of expanding item to available space:
 | 
					
						
							|  |  |  |             newValue = root.width - d.accumulatedWidth(0, items.length, false); | 
					
						
							|  |  |  |             var expandingItem = items[d.expandingIndex] | 
					
						
							|  |  |  |             if (expandingItem.minimumWidth != undefined && expandingItem.minimumWidth != -1) | 
					
						
							|  |  |  |                 newValue = Math.max(newValue, expandingItem.minimumWidth) | 
					
						
							|  |  |  |             if (expandingItem.width !== newValue) | 
					
						
							|  |  |  |                 expandingItem.width = newValue | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // Then, position items and handles according to their width:
 | 
					
						
							|  |  |  |             for (i=0; i<items.length; ++i) { | 
					
						
							|  |  |  |                 item = items[i]; | 
					
						
							|  |  |  |                 handle = handles[i] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 // Position item to the right of the previus handle:
 | 
					
						
							|  |  |  |                 if (prevHandle) { | 
					
						
							|  |  |  |                     newValue = prevHandle.x + prevHandle.width | 
					
						
							|  |  |  |                     if (newValue !== item.x) | 
					
						
							|  |  |  |                         item.x = newValue | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 // Position handle to the right of item:
 | 
					
						
							|  |  |  |                 if (handle) { | 
					
						
							|  |  |  |                     newValue = item.x + Math.max(0, item.width) | 
					
						
							|  |  |  |                     if (newValue !== handle.x) | 
					
						
							|  |  |  |                         handle.x = newValue | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 prevItem = item | 
					
						
							|  |  |  |                 prevHandle = handle | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             d.updateOptimizationBlock = false | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Component { | 
					
						
							|  |  |  |         id: handleBackgroundLoader | 
					
						
							|  |  |  |         Loader { | 
					
						
							|  |  |  |             id: loader | 
					
						
							|  |  |  |             property int handleIndex: 0 | 
					
						
							|  |  |  |             property Item handleDragTarget: loader | 
					
						
							|  |  |  |             sourceComponent: handleBackground | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             function handleDragged(handleIndex) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 // Moving the handle means resizing an item. Which one,
 | 
					
						
							|  |  |  |                 // left or right, depends on where the expanding item is.
 | 
					
						
							|  |  |  |                 // 'updateLayout' will override in case new width violates max/min.
 | 
					
						
							|  |  |  |                 // And 'updateLayout will be triggered when an item changes width.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 var leftHandle, leftItem, handle, rightItem, rightHandle | 
					
						
							|  |  |  |                 var leftEdge, rightEdge, newWidth | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 handle = handles[handleIndex] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if (d.expandingIndex > handleIndex) { | 
					
						
							|  |  |  |                     // Resize item to the left.
 | 
					
						
							|  |  |  |                     // Ensure that the handle is not crossing other handles:
 | 
					
						
							|  |  |  |                     leftHandle = handles[handleIndex-1] | 
					
						
							|  |  |  |                     leftItem = items[handleIndex] | 
					
						
							|  |  |  |                     leftEdge = leftHandle ? (leftHandle.x + leftHandle.width) : 0 | 
					
						
							|  |  |  |                     handle.x = Math.max(leftEdge, handle.x) | 
					
						
							|  |  |  |                     newWidth = handle.x - leftEdge | 
					
						
							|  |  |  |                     if (root.width != 0 && leftItem.percentageWidth != undefined && leftItem.percentageWidth !== -1) | 
					
						
							|  |  |  |                         leftItem.percentageWidth = newWidth * (100 / root.width) | 
					
						
							|  |  |  |                     // The next line will trigger 'updateLayout' inside 'propertyChangeListener':
 | 
					
						
							|  |  |  |                     leftItem.width = newWidth | 
					
						
							|  |  |  |                 } else { | 
					
						
							|  |  |  |                     // Resize item to the right:
 | 
					
						
							|  |  |  |                     // Since the first item in the splitter always will have x=0, we need
 | 
					
						
							|  |  |  |                     // to ensure that the user cannot drag the handle more left than what
 | 
					
						
							|  |  |  |                     // we got space for:
 | 
					
						
							|  |  |  |                     var min = d.accumulatedWidth(0, handleIndex+1, true) | 
					
						
							|  |  |  |                     // Ensure that the handle is not crossing other handles:
 | 
					
						
							|  |  |  |                     rightItem = items[handleIndex+1] | 
					
						
							|  |  |  |                     rightHandle = handles[handleIndex+1] | 
					
						
							|  |  |  |                     rightEdge = (rightHandle ? rightHandle.x : root.width) | 
					
						
							|  |  |  |                     handle.x = Math.max(min, Math.max(Math.min((rightEdge - handle.width), handle.x))) | 
					
						
							|  |  |  |                     newWidth = rightEdge - (handle.x + handle.width) | 
					
						
							|  |  |  |                     if (root.width != 0 && rightItem.percentageWidth != undefined && rightItem.percentageWidth !== -1) | 
					
						
							|  |  |  |                         rightItem.percentageWidth = newWidth * (100 / root.width) | 
					
						
							|  |  |  |                     // The next line will trigger 'updateLayout' inside 'propertyChangeListener':
 | 
					
						
							|  |  |  |                     rightItem.width = newWidth | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Item { | 
					
						
							|  |  |  |         id: splitterItems | 
					
						
							|  |  |  |         anchors.fill: parent | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     Item { | 
					
						
							|  |  |  |         id: splitterHandles | 
					
						
							|  |  |  |         anchors.fill: parent | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Component { | 
					
						
							|  |  |  |         // This dummy item becomes a child of all
 | 
					
						
							|  |  |  |         // items it the splitter, just to provide a way
 | 
					
						
							|  |  |  |         // to listed for changes to their width, expanding etc.
 | 
					
						
							|  |  |  |         id: propertyChangeListener | 
					
						
							|  |  |  |         Item { | 
					
						
							|  |  |  |             id: target | 
					
						
							|  |  |  |             width: parent.width | 
					
						
							|  |  |  |             property bool expanding: (parent.expanding != undefined) ? parent.expanding : false | 
					
						
							|  |  |  |             property real percentageWidth: (parent.percentageWidth != undefined) ? parent.percentageWidth : -1 | 
					
						
							|  |  |  |             property real minimumWidth: (parent.minimumWidth != undefined) ? parent.minimumWidth : -1 | 
					
						
							|  |  |  |             property real maximumWidth: (parent.maximumWidth != undefined) ? parent.maximumWidth : -1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             onPercentageWidthChanged: d.updateLayout(); | 
					
						
							|  |  |  |             onMinimumWidthChanged: d.updateLayout(); | 
					
						
							|  |  |  |             onMaximumWidthChanged: d.updateLayout(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             onExpandingChanged: { | 
					
						
							|  |  |  |                 // Find out which item that has the expanding flag:
 | 
					
						
							|  |  |  |                 for (var i=0; i<items.length; ++i) { | 
					
						
							|  |  |  |                     var item = items[i] | 
					
						
							|  |  |  |                     if (item.expanding && item.expanding === true) { | 
					
						
							|  |  |  |                         d.expandingIndex = i | 
					
						
							|  |  |  |                         d.updateLayout(); | 
					
						
							|  |  |  |                         return | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 d.expandingIndex = i-1 | 
					
						
							|  |  |  |                 updateLayout(); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             onWidthChanged: { | 
					
						
							|  |  |  |                 // We need to update the layout:
 | 
					
						
							|  |  |  |                 if (d.bindingRecursionGuard === true) | 
					
						
							|  |  |  |                     return | 
					
						
							|  |  |  |                 d.bindingRecursionGuard = true | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 // Break binding:
 | 
					
						
							|  |  |  |                 width = 0 | 
					
						
							|  |  |  |                 d.updateLayout() | 
					
						
							|  |  |  |                 // Restablish binding:
 | 
					
						
							|  |  |  |                 width = function() { return parent.width; } | 
					
						
							|  |  |  |                  | 
					
						
							|  |  |  |                 d.bindingRecursionGuard = false | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } |