blob: 25f3c9a054446ced039816456bd20a84221b27d4 [file] [log] [blame]
/*
* Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @constructor
* @extends {WebInspector.View}
* @param {WebInspector.NamedFlow} flow
*/
WebInspector.CSSNamedFlowView = function(flow)
{
WebInspector.View.call(this);
this.element.addStyleClass("css-named-flow");
this.element.addStyleClass("outline-disclosure");
this._treeOutline = new TreeOutline(this.element.createChild("ol"), true);
this._contentTreeItem = new TreeElement(WebInspector.UIString("content"), null, true);
this._treeOutline.appendChild(this._contentTreeItem);
this._regionsTreeItem = new TreeElement(WebInspector.UIString("region chain"), null, true);
this._regionsTreeItem.expand();
this._treeOutline.appendChild(this._regionsTreeItem);
this._flow = flow;
var content = flow.content;
for (var i = 0; i < content.length; ++i)
this._insertContentNode(content[i]);
var regions = flow.regions;
for (var i = 0; i < regions.length; ++i)
this._insertRegion(regions[i]);
}
WebInspector.CSSNamedFlowView.OversetTypeMessageMap = {
empty: "empty",
fit: "fit",
overset: "overset"
}
WebInspector.CSSNamedFlowView.prototype = {
/**
* @param {WebInspector.DOMNode=} rootDOMNode
* @return {?WebInspector.ElementsTreeOutline}
*/
_createFlowTreeOutline: function(rootDOMNode)
{
if (!rootDOMNode)
return null;
var treeOutline = new WebInspector.ElementsTreeOutline(false, false);
treeOutline.element.addStyleClass("named-flow-element");
treeOutline.setVisible(true);
treeOutline.rootDOMNode = rootDOMNode;
treeOutline.wireToDomAgent();
WebInspector.domAgent.removeEventListener(WebInspector.DOMAgent.Events.DocumentUpdated, treeOutline._elementsTreeUpdater._documentUpdated, treeOutline._elementsTreeUpdater);
return treeOutline;
},
/**
* @param {DOMAgent.NodeId} contentNodeId
* @param {number=} index
*/
_insertContentNode: function(contentNodeId, index)
{
var treeOutline = this._createFlowTreeOutline(WebInspector.domAgent.nodeForId(contentNodeId));
var treeItem = new TreeElement(treeOutline.element, treeOutline);
if (index === undefined) {
this._contentTreeItem.appendChild(treeItem);
return;
}
this._contentTreeItem.insertChild(treeItem, index);
},
/**
* @param {CSSAgent.Region} region
* @param {number=} index
*/
_insertRegion: function(region, index)
{
var treeOutline = this._createFlowTreeOutline(WebInspector.domAgent.nodeForId(region.nodeId));
treeOutline.element.addStyleClass("region-" + region.regionOverset);
var treeItem = new TreeElement(treeOutline.element, treeOutline);
var oversetText = WebInspector.UIString(WebInspector.CSSNamedFlowView.OversetTypeMessageMap[region.regionOverset]);
treeItem.tooltip = WebInspector.UIString("Region is %s.", oversetText);
if (index === undefined) {
this._regionsTreeItem.appendChild(treeItem);
return;
}
this._regionsTreeItem.insertChild(treeItem, index);
},
get flow()
{
return this._flow;
},
set flow(newFlow)
{
this._update(newFlow);
},
/**
* @param {TreeElement} regionTreeItem
* @param {string} newRegionOverset
* @param {string} oldRegionOverset
*/
_updateRegionOverset: function(regionTreeItem, newRegionOverset, oldRegionOverset)
{
var element = regionTreeItem.representedObject.element;
element.removeStyleClass("region-" + oldRegionOverset);
element.addStyleClass("region-" + newRegionOverset);
var oversetText = WebInspector.UIString(WebInspector.CSSNamedFlowView.OversetTypeMessageMap[newRegionOverset]);
regionTreeItem.tooltip = WebInspector.UIString("Region is %s." , oversetText);
},
/**
* @param {Array.<DOMAgent.NodeId>} oldContent
* @param {Array.<DOMAgent.NodeId>} newContent
*/
_mergeContentNodes: function(oldContent, newContent)
{
var nodeIdSet = {};
for (var i = 0; i < newContent.length; ++i)
nodeIdSet[newContent[i]] = true;
var oldContentIndex = 0;
var newContentIndex = 0;
var contentTreeChildIndex = 0;
while(oldContentIndex < oldContent.length || newContentIndex < newContent.length) {
if (oldContentIndex === oldContent.length) {
this._insertContentNode(newContent[newContentIndex]);
++newContentIndex;
continue;
}
if (newContentIndex === newContent.length) {
this._contentTreeItem.removeChildAtIndex(contentTreeChildIndex);
++oldContentIndex;
continue;
}
if (oldContent[oldContentIndex] === newContent[newContentIndex]) {
++oldContentIndex;
++newContentIndex;
++contentTreeChildIndex;
continue;
}
if (nodeIdSet[oldContent[oldContentIndex]]) {
this._insertContentNode(newContent[newContentIndex], contentTreeChildIndex);
++newContentIndex;
++contentTreeChildIndex;
continue;
}
this._contentTreeItem.removeChildAtIndex(contentTreeChildIndex);
++oldContentIndex;
}
},
/**
* @param {Array.<CSSAgent.Region>} oldRegions
* @param {Array.<CSSAgent.Region>} newRegions
*/
_mergeRegions: function(oldRegions, newRegions)
{
var nodeIdSet = {};
for (var i = 0; i < newRegions.length; ++i)
nodeIdSet[newRegions[i].nodeId] = true;
var oldRegionsIndex = 0;
var newRegionsIndex = 0;
var regionsTreeChildIndex = 0;
while(oldRegionsIndex < oldRegions.length || newRegionsIndex < newRegions.length) {
if (oldRegionsIndex === oldRegions.length) {
this._insertRegion(newRegions[newRegionsIndex]);
++newRegionsIndex;
continue;
}
if (newRegionsIndex === newRegions.length) {
this._regionsTreeItem.removeChildAtIndex(regionsTreeChildIndex);
++oldRegionsIndex;
continue;
}
if (oldRegions[oldRegionsIndex].nodeId === newRegions[newRegionsIndex].nodeId) {
if (oldRegions[oldRegionsIndex].regionOverset !== newRegions[newRegionsIndex].regionOverset)
this._updateRegionOverset(this._regionsTreeItem.children[regionsTreeChildIndex], newRegions[newRegionsIndex].regionOverset, oldRegions[oldRegionsIndex].regionOverset);
++oldRegionsIndex;
++newRegionsIndex;
++regionsTreeChildIndex;
continue;
}
if (nodeIdSet[oldRegions[oldRegionsIndex].nodeId]) {
this._insertRegion(newRegions[newRegionsIndex], regionsTreeChildIndex);
++newRegionsIndex;
++regionsTreeChildIndex;
continue;
}
this._regionsTreeItem.removeChildAtIndex(regionsTreeChildIndex);
++oldRegionsIndex;
}
},
/**
* @param {WebInspector.NamedFlow} newFlow
*/
_update: function(newFlow)
{
this._mergeContentNodes(this._flow.content, newFlow.content);
this._mergeRegions(this._flow.regions, newFlow.regions);
this._flow = newFlow;
},
__proto__: WebInspector.View.prototype
}