- 1 :
/**
- 2 :
* CustomSet is a tool for creating a layout of other tools.
- 3 :
*
- 4 :
* @class CustomSet
- 5 :
* @memberof Tools
- 6 :
*/
- 7 :
Ext.define('Voyant.panel.CustomSet', {
- 8 :
extend: 'Ext.panel.Panel',
- 9 :
mixins: ['Voyant.panel.Panel'],
- 10 :
alias: 'widget.customset',
- 11 :
statics: {
- 12 :
i18n: {
- 13 :
},
- 14 :
api: {
- 15 :
/**
- 16 :
* @memberof Tools.CustomSet
- 17 :
* @instance
- 18 :
* @property {String} layout A border layout string, of the format expected by <a target="_blank" href="https://docs.sencha.com/extjs/6.2.0/classic/Ext.layout.container.Border.html">Border layout</a>
- 19 :
*/
- 20 :
layout: undefined,
- 21 :
- 22 :
/**
- 23 :
* @memberof Tools.CustomSet
- 24 :
* @instance
- 25 :
* @property {String} tableLayout A table layout string, usually generated by the <a target="_blank" href="https://voyant-tools.org/builder/">Skin Builder</a>
- 26 :
*/
- 27 :
tableLayout: undefined
- 28 :
},
- 29 :
glyph: 'xf17a@FontAwesome'
- 30 :
},
- 31 :
header: false,
- 32 :
height: '100%',
- 33 :
width: '100%',
- 34 :
- 35 :
constructor: function() {
- 36 :
this.mixins['Voyant.util.Api'].constructor.apply(this, arguments); // force api load
- 37 :
this.callParent(arguments);
- 38 :
this.mixins['Voyant.panel.Panel'].constructor.apply(this, arguments);
- 39 :
},
- 40 :
- 41 :
initComponent: function() {
- 42 :
if (this.getApiParam('layout')) {
- 43 :
Ext.apply(this,{
- 44 :
layout: 'border',
- 45 :
items: []
- 46 :
})
- 47 :
} else if (this.getApiParam('tableLayout')) {
- 48 :
this.initTableLayout();
- 49 :
}
- 50 :
this.callParent()
- 51 :
},
- 52 :
- 53 :
listeners: {
- 54 :
loadedCorpus: function(src, corpus) {
- 55 :
if (this.getApiParam('layout')) { // not sure why, but we seem to need to fire event for child panels
- 56 :
this.query("panel").forEach(function(p) {
- 57 :
p.fireEvent("loadedCorpus", src, corpus);
- 58 :
})
- 59 :
}
- 60 :
},
- 61 :
boxready: function(panel) {
- 62 :
if (this.getApiParam('layout')) {
- 63 :
this.initBorderLayoutComponents();
- 64 :
} else if (this.getApiParam('tableLayout')) {
- 65 :
this.doTableSizing();
- 66 :
this.on('resize', function(panel, newwidth, newheight, oldwidth, oldheight) {
- 67 :
if (oldwidth !== undefined && oldheight !== undefined) {
- 68 :
var widthRatio = newwidth/oldwidth;
- 69 :
var heightRatio = newheight/oldheight;
- 70 :
this.doTableSizing(widthRatio, heightRatio);
- 71 :
}
- 72 :
}, this);
- 73 :
} else {
- 74 :
this.showError(this.localize('noLayoutSpecified'))
- 75 :
}
- 76 :
}
- 77 :
- 78 :
},
- 79 :
- 80 :
initBorderLayoutComponents: function() {
- 81 :
var layoutString = decodeURI(this.getApiParam('layout'))
- 82 :
.replace(/r1/g, 'region')
- 83 :
.replace(/i1/g, 'items')
- 84 :
.replace(/s1/g, 'split')
- 85 :
.replace(/c1/g, 'collapsible')
- 86 :
.replace(/c2/g, 'collapsed')
- 87 :
.replace(/w1/g, 'width')
- 88 :
.replace(/h1/g, 'height')
- 89 :
.replace(/p1/g, '%')
- 90 :
.replace(/"x1":"/g, '"xtype":"')
- 91 :
.replace(/c3/g, 'center')
- 92 :
.replace(/n1/g, 'north')
- 93 :
.replace(/e1/g, 'east')
- 94 :
.replace(/s2/g, 'south')
- 95 :
.replace(/w2/g, 'west')
- 96 :
.replace(/"xtype":"(\w+)"/g, function(match, tool) {
- 97 :
if (!Ext.ClassManager.getByAlias("widget."+tool.toLowerCase())) {
- 98 :
if (tool=="Links") {tool="CollocatesGraph";}
- 99 :
else if (tool=="CorpusGrid") {tool="Documents";}
- 100 :
else if (tool=="CorpusSummary") {tool="Summary";}
- 101 :
else if (tool=="CorpusTypeFrequenciesGrid") {tool="CorpusTerms";}
- 102 :
else if (tool=="DocumentInputAdd") {tool="CorpusTerms";}
- 103 :
else if (tool=="DocumentTypeCollocateFrequenciesGrid") {tool="CorpusTerms";}
- 104 :
else if (tool=="DocumentTypeFrequenciesGrid") {tool="DocumentTerms";}
- 105 :
else if (tool=="DocumentTypeKwicsGrid") {tool="Contexts";}
- 106 :
else if (tool=="TypeFrequenciesChart") {tool="Trends";}
- 107 :
else if (tool=="VisualCollocator") {tool="CollocatesGraph";}
- 108 :
else {tool="NoTool"}
- 109 :
}
- 110 :
return '"xtype":"'+tool.toLowerCase()+'"'+(tool=="NoTool" ? ',"html":"'+new Ext.Template(panel.localize('noSuchTool')).applyTemplate([tool])+'"' : '')
- 111 :
})
- 112 :
- 113 :
var items;
- 114 :
try {
- 115 :
items = Ext.decode(layoutString);
- 116 :
} catch (e) {
- 117 :
items = {region: 'center', html: '<div>Error constructing layout:'+e+'</div>'};
- 118 :
}
- 119 :
- 120 :
if (items == null) {
- 121 :
items = {region: 'center', html: '<div>Error: no layout information found.</div>'}
- 122 :
}
- 123 :
- 124 :
this.addBorderLayouts(items);
- 125 :
- 126 :
this.on("add", function(custom, cmp) {
- 127 :
cmp.on("boxready", function(cmp) {
- 128 :
// cmp.query("panel").forEach(function(p) {
- 129 :
// custom;
- 130 :
//// debugger
- 131 :
// })
- 132 :
})
- 133 :
})
- 134 :
this.add(items);
- 135 :
// .on("boxready", function() {
- 136 :
// debugger
- 137 :
// if (this.getCorpus()) { // we may have loaded the corpus after the layout, so refire the event
- 138 :
// this.getApplication().dispatchEvent("loadedCorpus", this.getApplication(), corpus);
- 139 :
// }
- 140 :
// })
- 141 :
- 142 :
},
- 143 :
- 144 :
addBorderLayouts: function(items) {
- 145 :
var size = Ext.getBody().getSize();
- 146 :
for (var i = 0; i < items.length; i++) {
- 147 :
var item = items[i];
- 148 :
if (Ext.isString(item.width)) {
- 149 :
item.width = Math.round(size.width * parseInt(item.width) / 100);
- 150 :
} else if (Ext.isString(item.height)) {
- 151 :
item.height = Math.round(size.height * parseInt(item.height) / 100);
- 152 :
}
- 153 :
if (item.items && item.items.length > 1) {
- 154 :
item.layout = 'border';
- 155 :
this.addBorderLayouts(item.items);
- 156 :
} else {
- 157 :
item.layout = 'fit';
- 158 :
}
- 159 :
}
- 160 :
},
- 161 :
- 162 :
initTableLayout: function() {
- 163 :
Ext.suspendLayouts();
- 164 :
var tableLayout = decodeURI(this.getApiParam('tableLayout'));
- 165 :
- 166 :
if (tableLayout && tableLayout.charAt(0)!="{" && tableLayout.charAt(0)!="[") {
- 167 :
var cells = [];
- 168 :
tableLayout.replace(/;/g,",").split(/,\s*/).forEach(function(cell) {
- 169 :
cells.push(/^"'/.test(cell) ? cell : '"'+cell+'"');
- 170 :
});
- 171 :
tableLayout = "["+cells.join(",")+"]"; // treat as simple comma-separated string
- 172 :
}
- 173 :
var layout = Ext.decode(tableLayout);
- 174 :
if (Ext.isArray(layout)) {
- 175 :
layout = {
- 176 :
cells: layout
- 177 :
};
- 178 :
}
- 179 :
if (!layout.numCols && layout.cells && Ext.isArray(layout.cells)) {
- 180 :
if (layout.cells.length < 3) {
- 181 :
layout.numCols = layout.cells.length;
- 182 :
} else if (layout.cells.length < 5) {
- 183 :
layout.numCols = Math.ceil(layout.cells.length / 2);
- 184 :
} else {
- 185 :
layout.numCols = Math.ceil(layout.cells.length / 3);
- 186 :
}
- 187 :
}
- 188 :
if (layout.numCols != null && layout.cells && Ext.isArray(layout.cells)) {
- 189 :
var items = [];
- 190 :
for (var i = 0; i < layout.cells.length; i++) {
- 191 :
var cell = layout.cells[i];
- 192 :
if (Ext.isObject(cell)) {
- 193 :
cell.cellWidth = parseFloat(cell.width) || undefined;
- 194 :
cell.cellHeight = parseFloat(cell.height) || undefined;
- 195 :
delete cell.width;
- 196 :
delete cell.height;
- 197 :
items.push(cell);
- 198 :
} else if (Ext.isArray(cell)) {
- 199 :
var colspan = 1, rowspan = 1; xtype = undefined;
- 200 :
if (cell[0] && Ext.isNumber(cell[0])) {
- 201 :
colspan = cell[0];
- 202 :
cell.shift();
- 203 :
}
- 204 :
if (cell[0] && Ext.isString(cell[0])) {
- 205 :
xtype = cell[0].toLowerCase();
- 206 :
cell.shift();
- 207 :
}
- 208 :
if (cell[0] && Ext.isNumber(cell[0])) {
- 209 :
rowspan = cell[0];
- 210 :
}
- 211 :
if (xtype) {
- 212 :
items.push({
- 213 :
colspan: colspan,
- 214 :
rowspan: rowspan,
- 215 :
xtype: xtype
- 216 :
})
- 217 :
}
- 218 :
} else if (Ext.isString(cell)) {
- 219 :
items.push({
- 220 :
xtype: cell.toLowerCase(),
- 221 :
colspan: 1,
- 222 :
rowspan: 1
- 223 :
})
- 224 :
}
- 225 :
}
- 226 :
Ext.apply(this, {
- 227 :
layout: {
- 228 :
type: 'table',
- 229 :
width: '100%',
- 230 :
height: '100%',
- 231 :
columns: layout.numCols,
- 232 :
tableAttrs: {
- 233 :
style: {
- 234 :
width: '100%',
- 235 :
height: '100%'
- 236 :
}
- 237 :
},
- 238 :
tdAttrs: {
- 239 :
style: {
- 240 :
padding: '0px',
- 241 :
verticalAlign: 'top'
- 242 :
}
- 243 :
}
- 244 :
},
- 245 :
defaults: { // place holder values to ensure that the children are rendered
- 246 :
width: 10,
- 247 :
height: 10,
- 248 :
border: true
- 249 :
},
- 250 :
items: items
- 251 :
});
- 252 :
} else {
- 253 :
this.showError("badTableLayoutDefinition")
- 254 :
}
- 255 :
- 256 :
Ext.resumeLayouts();
- 257 :
},
- 258 :
doTableSizing: function(widthRatio, heightRatio) {
- 259 :
var sizeMap = {};
- 260 :
- 261 :
var table = this.getTargetEl().down(".x-table-layout");
- 262 :
var tableSize = table.getSize(false);
- 263 :
- 264 :
var rows = table.dom.rows;
- 265 :
for (var i=0; i<rows.length; i++) {
- 266 :
var cells = rows[i].cells;
- 267 :
for (var j=0; j<cells.length; j++) {
- 268 :
var cell = cells[j];
- 269 :
var cellEl = Ext.get(cell);
- 270 :
var panelEl = cellEl.down('.x-panel');
- 271 :
var cmpId = panelEl.id;
- 272 :
- 273 :
var size;
- 274 :
if (widthRatio !== undefined && heightRatio !== undefined) {
- 275 :
size = panelEl.getSize(false);
- 276 :
size.width = size.width * widthRatio;
- 277 :
size.height = size.height * heightRatio;
- 278 :
// FIXME multiple resize calls gradually reduce size
- 279 :
} else {
- 280 :
var sizeObj = cellEl.getSize(false);
- 281 :
- 282 :
var cmp = Ext.getCmp(cmpId);
- 283 :
var widthPercent = cmp.initialConfig.cellWidth;
- 284 :
var heightPercent = cmp.initialConfig.cellHeight;
- 285 :
- 286 :
if (widthPercent !== undefined) {
- 287 :
sizeObj.width = tableSize.width * (widthPercent/100);
- 288 :
cellEl.setWidth(sizeObj.width);
- 289 :
}
- 290 :
if (heightPercent !== undefined) {
- 291 :
sizeObj.height = tableSize.height * (heightPercent/100);
- 292 :
cellEl.setHeight(sizeObj.height);
- 293 :
}
- 294 :
- 295 :
size = sizeObj;
- 296 :
}
- 297 :
- 298 :
sizeMap[cmpId] = size;
- 299 :
}
- 300 :
}
- 301 :
- 302 :
for (var id in sizeMap) {
- 303 :
var size = sizeMap[id];
- 304 :
Ext.getCmp(id).setSize(size);
- 305 :
}
- 306 :
- 307 :
this.updateLayout();
- 308 :
}
- 309 :
})