Форк Rambox
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

260 lines
9.7 KiB

Ext.define('Ext.app.bindinspector.Container', {
extend: 'Ext.container.Container',
alias: 'widget.bindinspector-container',
requires: [
'Ext.layout.container.Border',
'Ext.tab.Panel',
'Ext.app.bindinspector.ComponentDetail',
'Ext.app.bindinspector.ComponentList',
'Ext.app.bindinspector.Environment',
'Ext.app.bindinspector.Util',
'Ext.app.bindinspector.ViewModelDetail',
'Ext.app.bindinspector.noconflict.BaseModel'
],
isBindInspector: true,
referenceHolder: true,
layout: 'border',
cls: Ext.baseCSSPrefix + 'bindinspector-container',
//pickerCls: Ext.baseCSSPrefix + 'bindinspector-target-menu',
//pickerPreviewBindingsCls: Ext.baseCSSPrefix + 'bindinspector-preview-bind',
//pickerOpenBindingsCls: Ext.baseCSSPrefix + 'bindinspector-open-bind',
//pickerPreviewVMCls: Ext.baseCSSPrefix + 'bindinspector-preview-vm',
//pickerOpenVMCls: Ext.baseCSSPrefix + 'bindinspector-open-vm',
// the default view for the bindings preview tab for:
// 1) when a component hasn't been selected
// 2) when a component is clicked, but has no bindings
componentPreviewDefault: {
xtype: 'container',
cls: Ext.baseCSSPrefix + 'bindinspector-prev-default',
padding: 20,
layout: {
type: 'hbox',
align: 'middle',
pack: 'center'
},
items: [{
xtype: 'component',
flex: 1,
html: 'Select a component with bindings from the ComponentList to view the bindings details along with the component\'s inherited ViewModel'
}]
},
initComponent: function() {
var me = this;
Ext.data.schema.Schema.get('Ext_app_bindinspector').clear();
me.items = [{
xtype: 'bindinspector-componentlist',
reference: 'componentList',
region: 'west',
width: 400,
split: true,
collapsible: true,
components: me.env.rootComponents,
listeners: {
scope: me,
componentdblclick: me.onComponentDblclick,
componentselect: me.onComponentSelect
}
}, {
xtype: 'tabpanel',
region: 'center',
reference: 'tabs',
items: [{
title: 'Preview',
reference: 'preview',
layout: 'fit',
items: [me.componentPreviewDefault]
}],
listeners: {
add: function () {
this.getTabBar().setVisible(this.items.getCount() > 1);
},
remove: function () {
this.getTabBar().setVisible(this.items.getCount() > 1);
}
}
}];
me.callParent();
me.on('vmSearchClick', me.onVMSearchClick, me);
},
// When the search icon in the ViewModelDetail is clicked sort the items in the ComponentList panel to show
// 1) The viewmodels that have the root data node for the row clicked
// 2) All components with bindings that will consume the selected data point
onVMSearchClick: function (rec) {
var componentList = this.lookupReference('componentList'),
store = componentList.getStore(),
ownerVMs = rec.get('ownerVMs'),
sourceVMs = [],
bindCount = rec.get('bindCount'),
names = [],
consumerNodes = [],
query = [],
source, descriptor;
// THE INDICATING OF THE SOURCE VMS
store.suspendEvents();
componentList.clearVMSearchIndicators();
Ext.Array.forEach(ownerVMs, function (vm) {
source = store.getById(vm.view);
source.set('isSrcVM', rec);
sourceVMs.push(source);
});
store.resumeEvents();
componentList.getView().refresh();
// cache the list of source VMs for the given root data point
// used by ComponentList.clearVMSearchIndicators() to clear the selected indicators when clearing search results
componentList.indicatedVM = sourceVMs;
// THE INDICATING OF THE CONSUMER COMPONENTS
if (bindCount > 0) {
// find the descriptor path for the selected row
rec.bubble(function (node) {
var nodeName = node.get('name');
if (nodeName) {
names.push(nodeName);
}
});
// and save as a '.' separated string of node values
descriptor = names.reverse().join('.');
// iterate over the component tree and find components whose bindings match the descriptor for the selected row
componentList.getStore().getRootNode().cascadeBy(function (node) {
if (node.get('hasBindings')) {
Ext.Array.forEach(node.get('bindData'), function (binding) {
var tokenStr = [];
if (binding.tokens) {
Ext.Array.forEach(binding.tokens, function (token) {
if (Ext.isArray(token)) {
Ext.Array.forEach(token, function (t) {
tokenStr.push(t);
});
} else {
tokenStr.push(token);
}
});
}
if (tokenStr.join('.') === descriptor) {
consumerNodes.push(node);
}
});
}
});
}
// collect into an array all consuming components and source VMs for use in the componentlist filter in the next step
Ext.Array.forEach(consumerNodes.concat(sourceVMs), function (node) {
query.push(node.getId());
});
// filter to find the matching binding consumer components and source VMs
componentList.expand();
componentList.filterComponentTree(null, query);
// pull the filter styling off of any nodes that are VM sources, but not a binding match
Ext.Array.forEach(sourceVMs, function (src) {
if (!Ext.Array.contains(consumerNodes)) {
src.set('filtervisible', false);
}
});
componentList.down('#srcVMIndicator').show(); // show the indicator column used to show which VMs are source VMs
componentList.down('#queryFieldTb').hide(); // hide the normal filter toolbar
componentList.down('#vmQueryResultsTb').show(); // and show the one that indicates that it's filtered by VM search
},
// on component select review the component in the dedicated preview tab
onComponentSelect: function (tree, rec, node) {
var me = this,
id = rec.getId(),
preview = me.lookupReference('preview');
if (preview.referringID !== id) {
Ext.suspendLayouts();
preview.removeAll();
preview.add({
xtype: 'bindinspector-componentdetail',
env: me.env,
component: me.env.getCmp(id)
});
Ext.resumeLayouts(true);
preview.referringID = id;
}
preview.show();
},
// on component dblclick (or clicking the 'open in own tab button') open the component's bindings view in its own tab
onComponentDblclick: function(tree, rec, node) {
var id = rec.id,
tabId = 'bindtab-' + id,
tabs = this.lookupReference('tabs'),
tab = tabs.items.get(tabId),
component, reference;
if (!tab) {
component = this.env.getCmp(id);
reference = component.reference;
tab = tabs.add({
xtype: 'bindinspector-componentdetail',
env: this.env,
itemId: tabId,
title: reference ? '[' + reference + '] ' + id : id,
closable: true,
component: component
});
}
tabs.setActiveTab(tab);
},
// loop over the view models and build a reference that shows where each
// data point originates
buildVMDataMap: function (vm) {
var env = this.env,
currVM = vm,
dataMap = vm.dataMap,
viewModels = [],
data, isDirect;
// if the datamap has not yet been created for this view model build it
if (!dataMap) {
dataMap = vm.dataMap = {};
// collect up all ancestor view models which this view model will inherit from
while (currVM) {
viewModels.push(currVM);
currVM = env.getVM(currVM.parent);
}
// loop through and see if each data point is found on this view model or an ancestor
// and catalog all viewmodels where this data point is found (to how overlapping keys)
Ext.Array.forEach(viewModels, function (item) {
var key;
data = item.data;
if (data && Ext.isObject(data)) {
for (key in data) {
isDirect = data.hasOwnProperty(key);
if (!dataMap[key]) {
dataMap[key] = {
isDirect: isDirect
};
}
dataMap[key].ownerVMs = dataMap[key].ownerVMs || [];
if (isDirect) {
dataMap[key].ownerVMs.push(item);
}
}
}
});
}
return vm;
}
});