2 if ( typeof define ===
"function" && define.amd ) {
3 define( [
'JSRootCore',
'd3'], factory );
4 }
else if (typeof exports ===
'object' && typeof module !==
'undefined') {
5 var jsroot = require(
"./JSRootCore.js");
6 factory(jsroot, require(
"d3"));
7 if (jsroot.nodejs) jsroot.Painter.readStyleFromURL(
"?interactive=0&tooltip=0&nomenu&noprogress¬ouch&toolbar=0&webgl=0");
9 if (typeof JSROOT ==
'undefined')
10 throw new Error(
'JSROOT is not defined',
'JSRootPainter.js');
11 if (typeof d3 !=
'object')
12 throw new Error(
'd3 is not defined',
'JSRootPainter.js');
13 if (typeof JSROOT.Painter ==
'object')
14 throw new Error(
'JSROOT.Painter already defined',
'JSRootPainter.js');
17 } (
function(JSROOT, d3) {
21 JSROOT.sources.push(
"2d");
24 if ( typeof define ===
"function" && define.amd )
25 JSROOT.loadScript(
'$$$style/JSRootPainter.css');
27 if (!JSROOT._test_d3_) {
28 if ((typeof d3 ==
'object') && d3.version && (d3.version[0]===
"5")) {
29 if (d3.version !==
'5.7.0')
30 console.log(
'Reuse existing d3.js ' + d3.version +
", expected 5.7.0");
32 }
else if ((typeof d3 ==
'object') && d3.version && (d3.version[0]===
"4")) {
33 if (d3.version !==
'4.4.4')
34 console.warn(
'Try to use older d3.js ' + d3.version +
", expected 5.7.0");
36 }
else if ((typeof d3 ==
'object') && d3.version && (d3.version[0]===
"3")) {
37 console.error(
"Very old d3.js " + d3.version +
" found, please UPGRADE");
38 d3.timeFormat = d3.time.format;
39 d3.scaleTime = d3.time.scale;
40 d3.scaleLog = d3.scale.log;
41 d3.scaleLinear = d3.scale.linear;
44 console.error(
'Fail to identify d3.js version ' + (d3 ? d3.version :
"???"));
49 JSROOT.DrawFuncs = { lst:[], cache:{} };
62 JSROOT.addDrawFunc =
function(_name, _func, _opt) {
63 if ((arguments.length == 1) && (typeof arguments[0] ==
'object')) {
64 JSROOT.DrawFuncs.lst.push(arguments[0]);
67 var handle = { name:_name, func:_func, opt:_opt };
68 JSROOT.DrawFuncs.lst.push(handle);
74 JSROOT.ToolbarIcons = {
75 camera: { path:
'M 152.00,304.00c0.00,57.438, 46.562,104.00, 104.00,104.00s 104.00-46.562, 104.00-104.00s-46.562-104.00-104.00-104.00S 152.00,246.562, 152.00,304.00z M 480.00,128.00L 368.00,128.00 c-8.00-32.00-16.00-64.00-48.00-64.00L 192.00,64.00 c-32.00,0.00-40.00,32.00-48.00,64.00L 32.00,128.00 c-17.60,0.00-32.00,14.40-32.00,32.00l0.00,288.00 c0.00,17.60, 14.40,32.00, 32.00,32.00l 448.00,0.00 c 17.60,0.00, 32.00-14.40, 32.00-32.00L 512.00,160.00 C 512.00,142.40, 497.60,128.00, 480.00,128.00z M 256.00,446.00c-78.425,0.00-142.00-63.574-142.00-142.00c0.00-78.425, 63.575-142.00, 142.00-142.00c 78.426,0.00, 142.00,63.575, 142.00,142.00 C 398.00,382.426, 334.427,446.00, 256.00,446.00z M 480.00,224.00l-64.00,0.00 l0.00-32.00 l 64.00,0.00 L 480.00,224.00 z' },
76 disk: { path:
'M384,0H128H32C14.336,0,0,14.336,0,32v448c0,17.656,14.336,32,32,32h448c17.656,0,32-14.344,32-32V96L416,0H384z M352,160 V32h32v128c0,17.664-14.344,32-32,32H160c-17.664,0-32-14.336-32-32V32h128v128H352z M96,288c0-17.656,14.336-32,32-32h256 c17.656,0,32,14.344,32,32v192H96V288z' },
77 question: { path:
'M256,512c141.375,0,256-114.625,256-256S397.375,0,256,0S0,114.625,0,256S114.625,512,256,512z M256,64 c63.719,0,128,36.484,128,118.016c0,47.453-23.531,84.516-69.891,110.016C300.672,299.422,288,314.047,288,320 c0,17.656-14.344,32-32,32c-17.664,0-32-14.344-32-32c0-40.609,37.25-71.938,59.266-84.031 C315.625,218.109,320,198.656,320,182.016C320,135.008,279.906,128,256,128c-30.812,0-64,20.227-64,64.672 c0,17.664-14.336,32-32,32s-32-14.336-32-32C128,109.086,193.953,64,256,64z M256,449.406c-18.211,0-32.961-14.75-32.961-32.969 c0-18.188,14.75-32.953,32.961-32.953c18.219,0,32.969,14.766,32.969,32.953C288.969,434.656,274.219,449.406,256,449.406z' },
78 undo: { path:
'M450.159,48.042c8.791,9.032,16.983,18.898,24.59,29.604c7.594,10.706,14.146,22.207,19.668,34.489 c5.509,12.296,9.82,25.269,12.92,38.938c3.113,13.669,4.663,27.834,4.663,42.499c0,14.256-1.511,28.863-4.532,43.822 c-3.009,14.952-7.997,30.217-14.953,45.795c-6.955,15.577-16.202,31.52-27.755,47.826s-25.88,32.9-42.942,49.807 c-5.51,5.444-11.787,11.67-18.834,18.651c-7.033,6.98-14.496,14.366-22.39,22.168c-7.88,7.802-15.955,15.825-24.187,24.069 c-8.258,8.231-16.333,16.203-24.252,23.888c-18.3,18.13-37.354,37.016-57.191,56.65l-56.84-57.445 c19.596-19.472,38.54-38.279,56.84-56.41c7.75-7.685,15.772-15.604,24.108-23.757s16.438-16.163,24.33-24.057 c7.894-7.893,15.356-15.33,22.402-22.312c7.034-6.98,13.312-13.193,18.821-18.651c22.351-22.402,39.165-44.648,50.471-66.738 c11.279-22.09,16.932-43.567,16.932-64.446c0-15.785-3.217-31.005-9.638-45.671c-6.422-14.665-16.229-28.504-29.437-41.529 c-3.282-3.282-7.358-6.395-12.217-9.325c-4.871-2.938-10.381-5.503-16.516-7.697c-6.121-2.201-12.815-3.992-20.058-5.373 c-7.242-1.374-14.9-2.064-23.002-2.064c-8.218,0-16.802,0.834-25.788,2.507c-8.961,1.674-18.053,4.429-27.222,8.271 c-9.189,3.842-18.456,8.869-27.808,15.089c-9.358,6.219-18.521,13.819-27.502,22.793l-59.92,60.271l93.797,94.058H0V40.91 l93.27,91.597l60.181-60.532c13.376-15.018,27.222-27.248,41.536-36.697c14.308-9.443,28.608-16.776,42.89-21.992 c14.288-5.223,28.505-8.74,42.623-10.557C294.645,0.905,308.189,0,321.162,0c13.429,0,26.389,1.185,38.84,3.562 c12.478,2.377,24.2,5.718,35.192,10.029c11.006,4.311,21.126,9.404,30.374,15.265C434.79,34.724,442.995,41.119,450.159,48.042z' },
79 arrow_right : { path:
'M30.796,226.318h377.533L294.938,339.682c-11.899,11.906-11.899,31.184,0,43.084c11.887,11.899,31.19,11.893,43.077,0 l165.393-165.386c5.725-5.712,8.924-13.453,8.924-21.539c0-8.092-3.213-15.84-8.924-21.551L338.016,8.925 C332.065,2.975,324.278,0,316.478,0c-7.802,0-15.603,2.968-21.539,8.918c-11.899,11.906-11.899,31.184,0,43.084l113.391,113.384 H30.796c-16.822,0-30.463,13.645-30.463,30.463C0.333,212.674,13.974,226.318,30.796,226.318z' },
80 arrow_up : { path:
'M295.505,629.446V135.957l148.193,148.206c15.555,15.559,40.753,15.559,56.308,0c15.555-15.538,15.546-40.767,0-56.304 L283.83,11.662C276.372,4.204,266.236,0,255.68,0c-10.568,0-20.705,4.204-28.172,11.662L11.333,227.859 c-7.777,7.777-11.666,17.965-11.666,28.158c0,10.192,3.88,20.385,11.657,28.158c15.563,15.555,40.762,15.555,56.317,0 l148.201-148.219v493.489c0,21.993,17.837,39.82,39.82,39.82C277.669,669.267,295.505,651.439,295.505,629.446z' },
81 arrow_diag : { path:
'M279.875,511.994c-1.292,0-2.607-0.102-3.924-0.312c-10.944-1.771-19.333-10.676-20.457-21.71L233.97,278.348 L22.345,256.823c-11.029-1.119-19.928-9.51-21.698-20.461c-1.776-10.944,4.031-21.716,14.145-26.262L477.792,2.149 c9.282-4.163,20.167-2.165,27.355,5.024c7.201,7.189,9.199,18.086,5.024,27.356L302.22,497.527 C298.224,506.426,289.397,511.994,279.875,511.994z M118.277,217.332l140.534,14.294c11.567,1.178,20.718,10.335,21.878,21.896 l14.294,140.519l144.09-320.792L118.277,217.332z' },
82 auto_zoom: { path:
'M505.441,242.47l-78.303-78.291c-9.18-9.177-24.048-9.171-33.216,0c-9.169,9.172-9.169,24.045,0.006,33.217l38.193,38.188 H280.088V80.194l38.188,38.199c4.587,4.584,10.596,6.881,16.605,6.881c6.003,0,12.018-2.297,16.605-6.875 c9.174-9.172,9.174-24.039,0.011-33.217L273.219,6.881C268.803,2.471,262.834,0,256.596,0c-6.229,0-12.202,2.471-16.605,6.881 l-78.296,78.302c-9.178,9.172-9.178,24.045,0,33.217c9.177,9.171,24.051,9.171,33.21,0l38.205-38.205v155.4H80.521l38.2-38.188 c9.177-9.171,9.177-24.039,0.005-33.216c-9.171-9.172-24.039-9.178-33.216,0L7.208,242.464c-4.404,4.403-6.881,10.381-6.881,16.611 c0,6.227,2.477,12.207,6.881,16.61l78.302,78.291c4.587,4.581,10.599,6.875,16.605,6.875c6.006,0,12.023-2.294,16.61-6.881 c9.172-9.174,9.172-24.036-0.005-33.211l-38.205-38.199h152.593v152.063l-38.199-38.211c-9.171-9.18-24.039-9.18-33.216-0.022 c-9.178,9.18-9.178,24.059-0.006,33.222l78.284,78.302c4.41,4.404,10.382,6.881,16.611,6.881c6.233,0,12.208-2.477,16.611-6.881 l78.302-78.296c9.181-9.18,9.181-24.048,0-33.205c-9.174-9.174-24.054-9.174-33.21,0l-38.199,38.188v-152.04h152.051l-38.205,38.199 c-9.18,9.175-9.18,24.037-0.005,33.211c4.587,4.587,10.596,6.881,16.604,6.881c6.01,0,12.024-2.294,16.605-6.875l78.303-78.285 c4.403-4.403,6.887-10.378,6.887-16.611C512.328,252.851,509.845,246.873,505.441,242.47z' },
84 path :
'M28.782,56.902H483.88c15.707,0,28.451-12.74,28.451-28.451C512.331,12.741,499.599,0,483.885,0H28.782 C13.074,0,0.331,12.741,0.331,28.451C0.331,44.162,13.074,56.902,28.782,56.902z' +
85 'M483.885,136.845H28.782c-15.708,0-28.451,12.741-28.451,28.451c0,15.711,12.744,28.451,28.451,28.451H483.88 c15.707,0,28.451-12.74,28.451-28.451C512.331,149.586,499.599,136.845,483.885,136.845z' +
86 'M483.885,273.275H28.782c-15.708,0-28.451,12.731-28.451,28.452c0,15.707,12.744,28.451,28.451,28.451H483.88 c15.707,0,28.451-12.744,28.451-28.451C512.337,286.007,499.599,273.275,483.885,273.275z' +
87 'M256.065,409.704H30.492c-15.708,0-28.451,12.731-28.451,28.451c0,15.707,12.744,28.451,28.451,28.451h225.585 c15.707,0,28.451-12.744,28.451-28.451C284.516,422.436,271.785,409.704,256.065,409.704z'
89 circle: { path:
"M256,256 m-150,0 a150,150 0 1,0 300,0 a150,150 0 1,0 -300,0" },
90 three_circles: { path:
"M256,85 m-70,0 a70,70 0 1,0 140,0 a70,70 0 1,0 -140,0 M256,255 m-70,0 a70,70 0 1,0 140,0 a70,70 0 1,0 -140,0 M256,425 m-70,0 a70,70 0 1,0 140,0 a70,70 0 1,0 -140,0 " },
91 diamand: { path:
"M256,0L384,256L256,511L128,256z" },
92 rect: { path:
"M80,80h352v352h-352z" },
93 cross: { path:
"M80,40l176,176l176,-176l40,40l-176,176l176,176l-40,40l-176,-176l-176,176l-40,-40l176,-176l-176,-176z" },
94 vrgoggles: { size:
"245.82 141.73", path:
'M175.56,111.37c-22.52,0-40.77-18.84-40.77-42.07S153,27.24,175.56,27.24s40.77,18.84,40.77,42.07S198.08,111.37,175.56,111.37ZM26.84,69.31c0-23.23,18.25-42.07,40.77-42.07s40.77,18.84,40.77,42.07-18.26,42.07-40.77,42.07S26.84,92.54,26.84,69.31ZM27.27,0C11.54,0,0,12.34,0,28.58V110.9c0,16.24,11.54,30.83,27.27,30.83H99.57c2.17,0,4.19-1.83,5.4-3.7L116.47,118a8,8,0,0,1,12.52-.18l11.51,20.34c1.2,1.86,3.22,3.61,5.39,3.61h72.29c15.74,0,27.63-14.6,27.63-30.83V28.58C245.82,12.34,233.93,0,218.19,0H27.27Z'},
95 CreateSVG :
function(group,btn,size,title) {
96 var svg = group.append(
"svg:svg")
97 .attr(
"class",
"svg_toolbar_btn")
98 .attr(
"width",size+
"px")
99 .attr(
"height",size+
"px")
100 .attr(
"viewBox",
"0 0 512 512")
101 .style(
"overflow",
"hidden");
105 for (var n=0;n<btn.recs.length;++n) {
106 JSROOT.extend(rec, btn.recs[n]);
107 svg.append(
'rect').attr(
"x", rec.x).attr(
"y", rec.y)
108 .attr(
"width", rec.w).attr(
"height", rec.h)
109 .attr(
"fill", rec.f);
112 svg.append(
'svg:path').attr(
'd',btn.path);
116 svg.append(
"svg:rect").attr(
"x",0).attr(
"y",0).attr(
"width",512).attr(
"height",512)
117 .style(
'opacity',0).style(
'fill',
"none").style(
"pointer-events",
"visibleFill")
118 .append(
"svg:title").text(title);
130 function DrawOptions(opt) {
131 this.opt = opt && (typeof opt==
"string") ? opt.toUpperCase().trim() :
"";
136 DrawOptions.prototype.empty =
function() {
137 return this.opt.length === 0;
141 DrawOptions.prototype.remain =
function() {
146 DrawOptions.prototype.check =
function(name,postpart) {
147 var pos = this.opt.indexOf(name);
148 if (pos < 0)
return false;
149 this.opt = this.opt.substr(0, pos) + this.opt.substr(pos + name.length);
151 if (!postpart)
return true;
154 while ((pos2 < this.opt.length) && (
this.opt[pos2] !==
' ') && (
this.opt[pos2] !==
',') && (
this.opt[pos2] !==
';')) pos2++;
156 this.part = this.opt.substr(pos, pos2-pos);
157 this.opt = this.opt.substr(0, pos) + this.opt.substr(pos2);
163 DrawOptions.prototype.partAsInt =
function(offset, dflt) {
164 var val = this.part.replace(/^\D+/g,
'');
165 val = val ? parseInt(val,10) : Number.NaN;
166 return isNaN(val) ? (dflt || 0) : val + (offset || 0);
170 DrawOptions.prototype.partAsFloat =
function(offset, dflt) {
171 var val = this.part.replace(/^\D+/g,
'');
172 val = val ? parseFloat(val) : Number.NaN;
173 return isNaN(val) ? (dflt || 0) : val + (offset || 0);
187 root_line_styles: [
"",
"",
"3,3",
"1,2",
188 "3,4,1,4",
"5,3,1,3",
"5,3,1,3,1,3,1,3",
"5,5",
189 "5,3,1,3,1,3",
"20,5",
"20,10,1,10",
"1,3"],
190 root_markers: [ 0, 100, 8, 7, 0,
191 9, 100, 100, 100, 100,
192 100, 100, 100, 100, 100,
193 100, 100, 100, 100, 100,
194 100, 103, 105, 104, 0,
197 root_fonts: [
'Arial',
'iTimes New Roman',
198 'bTimes New Roman',
'biTimes New Roman',
'Arial',
199 'oArial',
'bArial',
'boArial',
'Courier New',
200 'oCourier New',
'bCourier New',
'boCourier New',
201 'Symbol',
'Times New Roman',
'Wingdings',
'iSymbol',
'Verdana'],
203 root_fonts_aver_width: [ 0.537, 0.510,
205 0.54, 0.556, 0.56, 0.6,
207 0.587, 0.514, 0.896, 0.587, 0.55 ],
214 '#varepsilon':
'\u03B5',
224 '#omicron':
'\u03BF',
230 '#upsilon':
'\u03C5',
231 '#varomega':
'\u03D6',
240 '#Epsilon':
'\u0395',
245 '#vartheta':
'\u03D1',
250 '#Omicron':
'\u039F',
256 '#Upsilon':
'\u03A5',
257 '#varsigma':
'\u03C2',
262 '#varUpsilon':
'\u03D2',
263 '#epsilon':
'\u03B5',
275 '#diamond':
'\u2666',
278 '#leftrightarrow':
'\u2194',
279 '#leftarrow':
'\u2190',
280 '#uparrow':
'\u2191',
281 '#rightarrow':
'\u2192',
282 '#downarrow':
'\u2193',
285 '#doublequote':
'\u2033',
289 '#partial':
'\u2202',
298 '#downleftarrow':
'\u21B5',
300 '#Jgothic':
'\u2111',
301 '#Rgothic':
'\u211C',
308 '#supseteq':
'\u2287',
310 '#notsubset':
'\u2284',
311 '#subseteq':
'\u2286',
319 '#ocopyright':
'\xA9',
320 '#trademark':
'\u2122',
327 '#Leftrightarrow':
'\u21D4',
328 '#Leftarrow':
'\u21D0',
329 '#Uparrow':
'\u21D1',
330 '#Rightarrow':
'\u21D2',
331 '#Downarrow':
'\u21D3',
334 '#copyright':
'\xA9',
339 '#arcbottom':
'\u239D',
341 '#bottombar':
'\u230A',
362 '#parallel':
'\u2225',
372 '#club':
"\\clubsuit",
373 '#spade':
"\\spadesuit",
374 '#heart':
"\\heartsuit",
375 '#diamond':
"\\diamondsuit",
395 '#aa':
"\\mathring{a}",
396 '#AA':
"\\mathring{A}",
411 '#varomega':
"\\varpi",
421 '#downleftarrow':
"?",
422 '#splitline':
"\\genfrac{}{}{0pt}{}",
427 '#right}':
"\\rbrace",
428 '#left\\[':
"\\lbrack",
429 '#right\\]':
"\\rbrack",
430 '#\\[\\]{':
"\\lbrack",
440 JSROOT.Painter = Painter;
442 Painter.convertSymbol =
function(charactere) {
444 return Painter.symbols_map[charactere];
447 Painter.createMenu =
function(painter, maincallback) {
449 document.body.style.cursor =
'wait';
450 JSROOT.AssertPrerequisites(
'hierarchy;jq2d;',
function() {
451 document.body.style.cursor =
'auto';
452 Painter.createMenu(painter, maincallback);
456 Painter.closeMenu =
function(menuname) {
457 var x = document.getElementById(menuname ||
'root_ctx_menu');
458 if (x) { x.parentNode.removeChild(x);
return true; }
462 Painter.readStyleFromURL =
function(url) {
463 var optimize = JSROOT.GetUrlOption(
"optimize", url);
464 if (optimize==
"") JSROOT.gStyle.OptimizeDraw = 2;
else
465 if (optimize!==null) {
466 JSROOT.gStyle.OptimizeDraw = parseInt(optimize);
467 if (isNaN(JSROOT.gStyle.OptimizeDraw)) JSROOT.gStyle.OptimizeDraw = 2;
470 var inter = JSROOT.GetUrlOption(
"interactive", url);
471 if (inter ===
"nomenu") JSROOT.gStyle.ContextMenu =
false;
472 else if (inter !== null) {
473 if (!inter || (inter==
"1")) inter =
"111111";
else
474 if (inter==
"0") inter =
"000000";
475 if (inter.length === 6) {
476 if (inter[0] ==
"0") JSROOT.gStyle.ToolBar =
false;
else
477 if (inter[0] ==
"1") JSROOT.gStyle.ToolBar =
'popup';
else
478 if (inter[0] ==
"2") JSROOT.gStyle.ToolBar =
true;
479 inter = inter.substr(1);
481 if (inter.length==5) {
482 JSROOT.gStyle.Tooltip = parseInt(inter[0]);
483 JSROOT.gStyle.ContextMenu = (inter[1] !=
'0');
484 JSROOT.gStyle.Zooming = (inter[2] !=
'0');
485 JSROOT.gStyle.MoveResize = (inter[3] !=
'0');
486 JSROOT.gStyle.DragAndDrop = (inter[4] !=
'0');
490 var tt = JSROOT.GetUrlOption(
"tooltip", url);
491 if (tt !== null) JSROOT.gStyle.Tooltip = parseInt(tt);
493 var mathjax = JSROOT.GetUrlOption(
"mathjax", url),
494 latex = JSROOT.GetUrlOption(
"latex", url);
496 if ((mathjax!==null) && (mathjax!=
"0") && (latex===null)) latex =
"math";
497 if (latex!==null) JSROOT.gStyle.Latex = latex;
499 if (JSROOT.GetUrlOption(
"nomenu", url)!==null) JSROOT.gStyle.ContextMenu =
false;
500 if (JSROOT.GetUrlOption(
"noprogress", url)!==null) JSROOT.gStyle.ProgressBox =
false;
501 if (JSROOT.GetUrlOption(
"notouch", url)!==null) JSROOT.touches =
false;
502 if (JSROOT.GetUrlOption(
"adjframe", url)!==null) JSROOT.gStyle.CanAdjustFrame =
true;
504 var optstat = JSROOT.GetUrlOption(
"optstat", url);
505 if (optstat!==null) JSROOT.gStyle.fOptStat = parseInt(optstat);
506 var optfit = JSROOT.GetUrlOption(
"optfit", url);
507 if (optfit!==null) JSROOT.gStyle.fOptFit = parseInt(optfit);
508 JSROOT.gStyle.fStatFormat = JSROOT.GetUrlOption(
"statfmt", url, JSROOT.gStyle.fStatFormat);
509 JSROOT.gStyle.fFitFormat = JSROOT.GetUrlOption(
"fitfmt", url, JSROOT.gStyle.fFitFormat);
511 var toolbar = JSROOT.GetUrlOption(
"toolbar", url);
512 if (toolbar !== null) {
514 if (toolbar.indexOf(
'popup')>=0) val =
'popup';
515 if (toolbar.indexOf(
'left')>=0) { JSROOT.gStyle.ToolBarSide =
'left'; val =
'popup'; }
516 if (toolbar.indexOf(
'right')>=0) { JSROOT.gStyle.ToolBarSide =
'right'; val =
'popup'; }
517 if (toolbar.indexOf(
'vert')>=0) { JSROOT.gStyle.ToolBarVert =
true; val =
'popup'; }
518 if (toolbar.indexOf(
'show')>=0) val =
true;
519 JSROOT.gStyle.ToolBar = val || ((toolbar.indexOf(
"0")<0) && (toolbar.indexOf(
"false")<0) && (toolbar.indexOf(
"off")<0));
522 var palette = JSROOT.GetUrlOption(
"palette", url);
523 if (palette!==null) {
524 palette = parseInt(palette);
525 if (!isNaN(palette) && (palette>0) && (palette<113)) JSROOT.gStyle.Palette = palette;
528 var embed3d = JSROOT.GetUrlOption(
"embed3d", url);
529 if (embed3d !== null) JSROOT.gStyle.Embed3DinSVG = parseInt(embed3d);
531 var webgl = JSROOT.GetUrlOption(
"webgl", url);
532 if ((webgl ===
"0") || (webgl ===
"false")) JSROOT.gStyle.NoWebGL =
true;
else
533 if (webgl ===
"ie") JSROOT.gStyle.NoWebGL = !JSROOT.browser.isIE;
535 var geosegm = JSROOT.GetUrlOption(
"geosegm", url);
536 if (geosegm!==null) JSROOT.gStyle.GeoGradPerSegm = Math.max(2, parseInt(geosegm));
537 var geocomp = JSROOT.GetUrlOption(
"geocomp", url);
538 if (geocomp!==null) JSROOT.gStyle.GeoCompressComp = (geocomp!==
'0') && (geocomp!==
'false');
542 Painter.createRootColors =
function() {
543 var colorMap = [
'white',
'black',
'red',
'green',
'blue',
'yellow',
'magenta',
'cyan',
'rgb(89,212,84)',
'rgb(89,84,217)',
'white'];
544 colorMap[110] =
'white';
547 {col:11,str:
'c1b7ad4d4d4d6666668080809a9a9ab3b3b3cdcdcde6e6e6f3f3f3cdc8accdc8acc3c0a9bbb6a4b3a697b8a49cae9a8d9c8f83886657b1cfc885c3a48aa9a1839f8daebdc87b8f9a768a926983976e7b857d9ad280809caca6c0d4cf88dfbb88bd9f83c89a7dc08378cf5f61ac8f94a6787b946971d45a549300ff7b00ff6300ff4b00ff3300ff1b00ff0300ff0014ff002cff0044ff005cff0074ff008cff00a4ff00bcff00d4ff00ecff00fffd00ffe500ffcd00ffb500ff9d00ff8500ff6d00ff5500ff3d00ff2600ff0e0aff0022ff003aff0052ff006aff0082ff009aff00b1ff00c9ff00e1ff00f9ff00ffef00ffd700ffbf00ffa700ff8f00ff7700ff6000ff4800ff3000ff1800ff0000'},
548 {col:201,str:
'5c5c5c7b7b7bb8b8b8d7d7d78a0f0fb81414ec4848f176760f8a0f14b81448ec4876f1760f0f8a1414b84848ec7676f18a8a0fb8b814ecec48f1f1768a0f8ab814b8ec48ecf176f10f8a8a14b8b848ecec76f1f1'},
549 {col:390,str:
'ffffcdffff9acdcd9affff66cdcd669a9a66ffff33cdcd339a9a33666633ffff00cdcd009a9a00666600333300'},
550 {col:406,str:
'cdffcd9aff9a9acd9a66ff6666cd66669a6633ff3333cd33339a3333663300ff0000cd00009a00006600003300'},
551 {col:422,str:
'cdffff9affff9acdcd66ffff66cdcd669a9a33ffff33cdcd339a9a33666600ffff00cdcd009a9a006666003333'},
552 {col:590,str:
'cdcdff9a9aff9a9acd6666ff6666cd66669a3333ff3333cd33339a3333660000ff0000cd00009a000066000033'},
553 {col:606,str:
'ffcdffff9affcd9acdff66ffcd66cd9a669aff33ffcd33cd9a339a663366ff00ffcd00cd9a009a660066330033'},
554 {col:622,str:
'ffcdcdff9a9acd9a9aff6666cd66669a6666ff3333cd33339a3333663333ff0000cd00009a0000660000330000'},
555 {col:791,str:
'ffcd9acd9a669a66339a6600cd9a33ffcd66ff9a00ffcd33cd9a00ffcd00ff9a33cd66006633009a3300cd6633ff9a66ff6600ff6633cd3300ff33009aff3366cd00336600339a0066cd339aff6666ff0066ff3333cd0033ff00cdff9a9acd66669a33669a009acd33cdff669aff00cdff339acd00cdff009affcd66cd9a339a66009a6633cd9a66ffcd00ff6633ffcd00cd9a00ffcd33ff9a00cd66006633009a3333cd6666ff9a00ff9a33ff6600cd3300ff339acdff669acd33669a00339a3366cd669aff0066ff3366ff0033cd0033ff339aff0066cd00336600669a339acd66cdff009aff33cdff009acd00cdffcd9aff9a66cd66339a66009a9a33cdcd66ff9a00ffcd33ff9a00cdcd00ff9a33ff6600cd33006633009a6633cd9a66ff6600ff6633ff3300cd3300ffff339acd00666600339a0033cd3366ff669aff0066ff3366cd0033ff0033ff9acdcd669a9a33669a0066cd339aff66cdff009acd009aff33cdff009a'},
556 {col:920,str:
'cdcdcd9a9a9a666666333333'}];
558 for (var indx = 0; indx < moreCol.length; ++indx) {
559 var entry = moreCol[indx];
560 for (var n=0; n<entry.str.length; n+=6) {
561 var num = parseInt(entry.col) + parseInt(n/6);
562 colorMap[num] =
'rgb(' + parseInt(
"0x" +entry.str.slice(n,n+2)) +
"," + parseInt(
"0x" + entry.str.slice(n+2,n+4)) +
"," + parseInt(
"0x" + entry.str.slice(n+4,n+6)) +
")";
566 Painter.root_colors = colorMap;
569 Painter.MakeColorRGB =
function(col) {
570 if ((col==null) || (col._typename !=
'TColor'))
return null;
571 var rgb = Math.round(col.fRed*255) +
"," + Math.round(col.fGreen*255) +
"," + Math.round(col.fBlue*255);
572 if ((col.fAlpha === undefined) || (col.fAlpha == 1.))
573 rgb =
"rgb(" + rgb +
")";
575 rgb =
"rgba(" + rgb +
"," + col.fAlpha.toFixed(3) +
")";
578 case 'rgb(255,255,255)': rgb =
'white';
break;
579 case 'rgb(0,0,0)': rgb =
'black';
break;
580 case 'rgb(255,0,0)': rgb =
'red';
break;
581 case 'rgb(0,255,0)': rgb =
'green';
break;
582 case 'rgb(0,0,255)': rgb =
'blue';
break;
583 case 'rgb(255,255,0)': rgb =
'yellow';
break;
584 case 'rgb(255,0,255)': rgb =
'magenta';
break;
585 case 'rgb(0,255,255)': rgb =
'cyan';
break;
591 Painter.extendRootColors =
function(jsarr, objarr) {
594 for (var n=0;n<this.root_colors.length;++n)
595 jsarr[n] = this.root_colors[n];
598 if (!objarr)
return jsarr;
600 var rgb_array = objarr;
601 if (objarr._typename && objarr.arr) {
603 for (var n = 0; n < objarr.arr.length; ++n) {
604 var col = objarr.arr[n];
605 if (!col || (col._typename !=
'TColor'))
continue;
607 if ((col.fNumber>=0) && (col.fNumber<=10000))
608 rgb_array[col.fNumber] = Painter.MakeColorRGB(col);
613 for (var n = 0; n < rgb_array.length; ++n)
614 if (rgb_array[n] && (jsarr[n] != rgb_array[n]))
615 jsarr[n] = rgb_array[n];
624 Painter.adoptRootColors =
function(objarr) {
625 this.extendRootColors(this.root_colors, objarr);
637 function ColorPalette(arr) {
642 ColorPalette.prototype.calcColorIndex =
function(i,len) {
643 var theColor = Math.floor((i+0.99)*this.palette.length/(len-1));
644 if (theColor > this.palette.length-1) theColor = this.palette.length-1;
649 ColorPalette.prototype.getColor =
function(indx) {
650 return this.palette[indx];
654 ColorPalette.prototype.getLength =
function() {
655 return this.palette.length;
659 ColorPalette.prototype.calcColor =
function(i,len) {
660 var indx = this.calcColorIndex(i,len);
661 return this.getColor(indx);
672 function TAttMarkerHandler(args) {
673 this.x0 = this.y0 = 0;
674 this.color =
'black';
683 this.changed =
false;
685 this.func = this.Apply.bind(
this);
689 this.changed =
false;
700 TAttMarkerHandler.prototype.SetArgs =
function(args) {
701 if ((typeof args ==
'object') && (typeof args.fMarkerStyle ==
'number')) args = { attr: args };
704 if (args.color === undefined) args.color = Painter.root_colors[args.attr.fMarkerColor];
705 if (!args.style || (args.style<0)) args.style = args.attr.fMarkerStyle;
706 if (!args.size) args.size = args.attr.fMarkerSize;
709 this.Change(args.color, args.style, args.size);
714 TAttMarkerHandler.prototype.reset_pos =
function() {
715 this.lastx = this.lasty = null;
726 TAttMarkerHandler.prototype.create =
function(x,y) {
728 return "M" + (x+this.x0).toFixed(this.ndig)+
"," + (y+this.y0).toFixed(this.ndig) + this.marker;
731 var xx = Math.round(x), yy = Math.round(y), m1 =
"M"+xx+
","+yy+
"h1",
732 m2 = (this.lastx===null) ? m1 : (
"m"+(xx-this.lastx)+
","+(yy-this.lasty)+
"h1");
733 this.lastx = xx+1; this.lasty = yy;
734 return (m2.length < m1.length) ? m2 : m1;
738 TAttMarkerHandler.prototype.GetFullSize =
function() {
739 return this.scale*this.size;
743 TAttMarkerHandler.prototype.MarkerLength =
function() {
744 return this.marker ? this.marker.length : 10;
753 TAttMarkerHandler.prototype.Change =
function(color, style, size) {
756 if (color!==undefined) this.color = color;
757 if ((style!==undefined) && (style>=0)) this.style = style;
758 if (size!==undefined) this.size = size;
else size = this.size;
760 this.x0 = this.y0 = 0;
762 if ((this.style === 1) || (this.style === 777)) {
766 this.optimized =
true;
771 this.optimized =
false;
773 var marker_kind = Painter.root_markers[this.style];
774 if (marker_kind === undefined) marker_kind = 100;
775 var shape = marker_kind % 100;
777 this.fill = (marker_kind>=100);
780 case 1: this.size = 1; this.scale = 1;
break;
781 case 6: this.size = 2; this.scale = 1;
break;
782 case 7: this.size = 3; this.scale = 1;
break;
783 default: this.size = size; this.scale = 8;
786 size = this.GetFullSize();
788 this.ndig = (size>7) ? 0 : ((size>2) ? 1 : 2);
789 if (shape == 6) this.ndig++;
790 var half = (size/2).toFixed(this.ndig), full = size.toFixed(this.ndig);
794 this.x0 = -parseFloat(half);
795 full = (parseFloat(half)*2).toFixed(this.ndig);
796 this.marker =
"a"+half+
","+half+
",0,1,0,"+full+
",0a"+half+
","+half+
",0,1,0,-"+full+
",0z";
799 var d = (size/3).toFixed(this.ndig);
800 this.x0 = this.y0 = size/6;
801 this.marker =
"h"+d+
"v-"+d+
"h-"+d+
"v-"+d+
"h-"+d+
"v"+d+
"h-"+d+
"v"+d+
"h"+d+
"v"+d+
"h"+d+
"z";
805 this.marker =
"l"+half+
",-"+half+
"l"+half+
","+half+
"l-"+half+
","+half +
"z";
808 this.x0 = this.y0 = -size/2;
809 this.marker =
"v"+full+
"h"+full+
"v-"+full+
"z";
813 this.marker =
"l-"+half+
",-"+full+
"h"+full+
"z";
817 this.marker =
"l-"+half+
","+full+
"h"+full+
"z";
821 this.marker =
"l" + (size/3).toFixed(this.ndig) +
"," + full +
822 "l-" + (5/6*size).toFixed(this.ndig) +
",-" + (5/8*size).toFixed(this.ndig) +
824 "l-" + (5/6*size).toFixed(this.ndig) +
"," + (5/8*size).toFixed(this.ndig) +
"z";
827 this.x0 = this.y0 = -size/2;
828 this.marker =
"l"+full+
","+full +
829 "m0,-"+full+
"l-"+full+
","+full+
830 "m0,-"+half+
"h"+full+
"m-"+half+
",-"+half+
"v"+full;
834 this.marker =
"v"+full+
"m-"+half+
",-"+half+
"h"+full;
837 this.x0 = this.y0 = -size/2;
838 this.marker =
"l"+full+
","+full +
"m0,-"+full+
"l-"+full+
","+full;
842 this.marker =
"l"+half+
",-"+half+
"l"+half+
","+half+
"l-"+half+
","+half+
"z";
849 TAttMarkerHandler.prototype.getStrokeColor =
function() {
850 return this.stroke ? this.color :
"none";
853 TAttMarkerHandler.prototype.getFillColor =
function() {
854 return this.fill ? this.color :
"none";
858 TAttMarkerHandler.prototype.Apply =
function(selection) {
859 selection.style(
'stroke', this.stroke ? this.color :
"none");
860 selection.style(
'fill', this.fill ? this.color :
"none");
865 TAttMarkerHandler.prototype.verifyDirectChange =
function(painter) {
866 this.Change(this.color, parseInt(this.style), parseFloat(this.size));
876 TAttMarkerHandler.prototype.CreateSample =
function(svg, width, height) {
880 .attr(
"d", this.create(width/2, height/2))
892 function TAttLineHandler(args) {
893 this.func = this.Apply.bind(
this);
895 if (args._typename && (args.fLineStyle!==undefined)) args = { attr: args };
909 TAttLineHandler.prototype.SetArgs =
function(args) {
911 args.color = args.color0 || Painter.root_colors[args.attr.fLineColor];
912 if (args.width===undefined) args.width = args.attr.fLineWidth;
913 args.style = args.attr.fLineStyle;
914 }
else if (typeof args.color ==
'string') {
915 if ((args.color !==
'none') && !args.width) args.width = 1;
916 }
else if (typeof args.color ==
'number') {
917 args.color = Painter.root_colors[args.color];
920 if (args.width===undefined)
921 args.width = (args.color && args.color!=
'none') ? 1 : 0;
923 this.color = (args.width===0) ?
'none' : args.color;
924 this.width = args.width;
925 this.style = args.style;
928 this.excl_side = this.excl_width = 0;
929 if (Math.abs(
this.width) > 99) {
931 this.excl_side = (this.width < 0) ? -1 : 1;
932 this.excl_width = Math.floor(this.width / 100) * 5;
933 this.width = Math.abs(this.width % 100);
938 if (!this.color && (this.width > 0))
939 this.color =
'lightgrey';
947 TAttLineHandler.prototype.ChangeExcl =
function(side,width) {
948 if (width !== undefined) this.excl_width = width;
949 if (side !== undefined) {
950 this.excl_side = side;
951 if ((this.excl_width===0) && (this.excl_side!==0)) this.excl_width = 20;
960 TAttLineHandler.prototype.empty =
function() {
961 return this.color ==
'none';
970 TAttLineHandler.prototype.Apply =
function(selection) {
973 selection.style(
'stroke', null)
974 .style(
'stroke-width', null)
975 .style(
'stroke-dasharray', null);
977 selection.style(
'stroke', this.color)
978 .style(
'stroke-width', this.width)
979 .style(
'stroke-dasharray', Painter.root_line_styles[
this.style] || null);
987 TAttLineHandler.prototype.Change =
function(color, width, style) {
988 if (color !== undefined) this.color = color;
989 if (width !== undefined) this.width = width;
990 if (style !== undefined) this.style = style;
999 TAttLineHandler.prototype.CreateSample =
function(svg, width, height) {
1001 .attr(
"d",
"M0," + height/2+
"h"+width)
1016 function TAttFillHandler(args) {
1017 this.color =
"none";
1021 this.kind = args.kind || 2;
1022 this.changed =
false;
1023 this.func = this.Apply.bind(
this);
1025 this.changed =
false;
1029 TAttFillHandler.prototype.SetArgs =
function(args) {
1030 if (args.attr && (typeof args.attr ==
'object')) {
1031 if ((args.pattern===undefined) && (args.attr.fFillStyle!==undefined)) args.pattern = args.attr.fFillStyle;
1032 if ((args.color===undefined) && (args.attr.fFillColor!==undefined)) args.color = args.attr.fFillColor;
1034 this.Change(args.color, args.pattern, args.svg, args.color_as_svg);
1038 TAttFillHandler.prototype.Apply =
function(selection) {
1041 selection.style(
'fill', this.fillcolor());
1043 if (
'opacity' in
this)
1044 selection.style(
'opacity', this.opacity);
1046 if (
'antialias' in
this)
1047 selection.style(
'antialias', this.antialias);
1051 TAttFillHandler.prototype.fillcolor =
function() {
1052 return this.pattern_url || this.color;
1060 TAttFillHandler.prototype.fillcoloralt =
function(altern) {
1061 return this.color && (this.color!=
"none") ? this.color : altern;
1065 TAttFillHandler.prototype.empty =
function() {
1066 var fill = this.fillcolor();
1067 return !fill || (fill ==
'none');
1072 TAttFillHandler.prototype.SetSolidColor =
function(col) {
1073 delete this.pattern_url;
1075 this.pattern = 1001;
1080 TAttFillHandler.prototype.isSolid =
function(solid_color) {
1081 if (this.pattern !== 1001)
return false;
1082 return !solid_color || solid_color==this.color;
1087 TAttFillHandler.prototype.verifyDirectChange =
function(painter) {
1088 if (typeof this.pattern ==
'string') this.pattern = parseInt(this.pattern);
1089 if (isNaN(this.pattern)) this.pattern = 0;
1091 this.Change(this.color, this.pattern, painter ? painter.svg_canvas() : null,
true);
1101 TAttFillHandler.prototype.Change =
function(color, pattern, svg, color_as_svg) {
1102 delete this.pattern_url;
1103 this.changed =
true;
1105 if ((color !== undefined) && !isNaN(color) && !color_as_svg)
1106 this.colorindx = parseInt(color);
1108 if ((pattern !== undefined) && !isNaN(pattern)) {
1109 this.pattern = parseInt(pattern);
1110 delete this.opacity;
1111 delete this.antialias;
1114 if ((this.pattern == 1000) && (this.colorindx === 0)) {
1115 this.pattern_url =
'white';
1119 if (this.pattern == 1000) this.pattern = 1001;
1121 if (this.pattern < 1001) {
1122 this.pattern_url =
'none';
1126 if (this.isSolid() && (this.colorindx===0) && (this.kind===1) && !color_as_svg) {
1127 this.pattern_url =
'none';
1131 var indx = this.colorindx;
1135 indx = 10000 + JSROOT.id_counter++;
1137 this.color = JSROOT.Painter.root_colors[indx];
1140 if (typeof this.color !=
'string') this.color =
"none";
1142 if (this.isSolid())
return true;
1144 if ((this.pattern >= 4000) && (this.pattern <= 4100)) {
1146 this.opacity = (this.pattern - 4000)/100;
1150 if (!svg || svg.empty() || (this.pattern < 3000))
return false;
1152 var
id =
"pat_" + this.pattern +
"_" + indx,
1153 defs = svg.select(
'.canvas_defs');
1156 defs = svg.insert(
"svg:defs",
":first-child").attr(
"class",
"canvas_defs");
1158 this.pattern_url =
"url(#" +
id +
")";
1159 this.antialias =
false;
1161 if (!defs.select(
"."+
id).empty()) {
1162 if (color_as_svg) console.log(
'find id in def',
id);
1166 var lines =
"", lfill = null, fills =
"", fills2 =
"", w = 2, h = 2;
1168 switch (this.pattern) {
1169 case 3001: w = h = 2; fills =
"M0,0h1v1h-1zM1,1h1v1h-1z";
break;
1170 case 3002: w = 4; h = 2; fills =
"M1,0h1v1h-1zM3,1h1v1h-1z";
break;
1171 case 3003: w = h = 4; fills =
"M2,1h1v1h-1zM0,3h1v1h-1z";
break;
1172 case 3004: w = h = 8; lines =
"M8,0L0,8";
break;
1173 case 3005: w = h = 8; lines =
"M0,0L8,8";
break;
1174 case 3006: w = h = 4; lines =
"M1,0v4";
break;
1175 case 3007: w = h = 4; lines =
"M0,1h4";
break;
1178 fills =
"M0,3v-3h3ZM7,0h3v3ZM0,7v3h3ZM7,10h3v-3ZM5,2l3,3l-3,3l-3,-3Z";
1179 lines =
"M0,3l5,5M3,10l5,-5M10,7l-5,-5M7,0l-5,5";
1181 case 3009: w = 12; h = 12; lines =
"M0,0A6,6,0,0,0,12,0M6,6A6,6,0,0,0,12,12M6,6A6,6,0,0,1,0,12"; lfill =
"none";
break;
1182 case 3010: w = h = 10; lines =
"M0,2h10M0,7h10M2,0v2M7,2v5M2,7v3";
break;
1183 case 3011: w = 9; h = 18; lines =
"M5,0v8M2,1l6,6M8,1l-6,6M9,9v8M6,10l3,3l-3,3M0,9v8M3,10l-3,3l3,3"; lfill =
"none";
break;
1184 case 3012: w = 10; h = 20; lines =
"M5,1A4,4,0,0,0,5,9A4,4,0,0,0,5,1M0,11A4,4,0,0,1,0,19M10,11A4,4,0,0,0,10,19"; lfill =
"none";
break;
1185 case 3013: w = h = 7; lines =
"M0,0L7,7M7,0L0,7"; lfill =
"none";
break;
1186 case 3014: w = h = 16; lines =
"M0,0h16v16h-16v-16M0,12h16M12,0v16M4,0v8M4,4h8M0,8h8M8,4v8"; lfill =
"none";
break;
1187 case 3015: w = 6; h = 12; lines =
"M2,1A2,2,0,0,0,2,5A2,2,0,0,0,2,1M0,7A2,2,0,0,1,0,11M6,7A2,2,0,0,0,6,11"; lfill =
"none";
break;
1188 case 3016: w = 12; h = 7; lines =
"M0,1A3,2,0,0,1,3,3A3,2,0,0,0,9,3A3,2,0,0,1,12,1"; lfill =
"none";
break;
1189 case 3017: w = h = 4; lines =
"M3,1l-2,2";
break;
1190 case 3018: w = h = 4; lines =
"M1,1l2,2";
break;
1193 lines =
"M1,6A5,5,0,0,0,11,6A5,5,0,0,0,1,6h-1h1A5,5,0,0,1,6,11v1v-1" +
1194 "A5,5,0,0,1,11,6h1h-1A5,5,0,0,1,6,1v-1v1A5,5,0,0,1,1,6";
1197 case 3020: w = 7; h = 12; lines =
"M1,0A2,3,0,0,0,3,3A2,3,0,0,1,3,9A2,3,0,0,0,1,12"; lfill =
"none";
break;
1198 case 3021: w = h = 8; lines =
"M8,2h-2v4h-4v2M2,0v2h-2"; lfill =
"none";
break;
1199 case 3022: w = h = 8; lines =
"M0,2h2v4h4v2M6,0v2h2"; lfill =
"none";
break;
1200 case 3023: w = h = 8; fills =
"M4,0h4v4zM8,4v4h-4z"; fills2 =
"M4,0L0,4L4,8L8,4Z";
break;
1201 case 3024: w = h = 16; fills =
"M0,8v8h2v-8zM8,0v8h2v-8M4,14v2h12v-2z"; fills2 =
"M0,2h8v6h4v-6h4v12h-12v-6h-4z";
break;
1202 case 3025: w = h = 18; fills =
"M5,13v-8h8ZM18,0v18h-18l5,-5h8v-8Z";
break;
1204 if ((this.pattern>3025) && (this.pattern<3100)) {
1206 w = 4; h = 2; fills =
"M1,0h1v1h-1zM3,1h1v1h-1z";
break;
1209 var code = this.pattern % 1000,
1210 k = code % 10, j = ((code - k) % 100) / 10, i = (code - j*10 - k)/100;
1217 function produce(dy,swap) {
1218 var pos = [], step = sz, y1 = 0, y2, max = h;
1221 if (Math.abs(dy)<3) step = Math.round(sz/12*9);
1222 if (dy==0) { step = Math.round(sz/12*8); y1 = step/2; }
1223 else if (dy>0) max -= step;
else y1 = step;
1228 var x2 = Math.round(y1/(y1-y2)*w);
1229 pos.push(0,y1,x2,0);
1230 pos.push(w,h-y1,w-x2,h);
1231 }
else if (y2 > h) {
1232 var x2 = Math.round((h-y1)/(y2-y1)*w);
1233 pos.push(0,y1,x2,h);
1234 pos.push(w,h-y1,w-x2,0);
1236 pos.push(0,y1,w,y2);
1240 for (var k=0;k<pos.length;k+=4)
1241 if (swap) lines +=
"M"+pos[k+1]+
","+pos[k]+
"L"+pos[k+3]+
","+pos[k+2];
1242 else lines +=
"M"+pos[k]+
","+pos[k+1]+
"L"+pos[k+2]+
","+pos[k+3];
1246 case 0: produce(0);
break;
1247 case 1: produce(1);
break;
1248 case 2: produce(2);
break;
1249 case 3: produce(3);
break;
1250 case 4: produce(6);
break;
1251 case 6: produce(3,
true);
break;
1252 case 7: produce(2,
true);
break;
1253 case 8: produce(1,
true);
break;
1254 case 9: produce(0,
true);
break;
1258 case 0:
if (j) produce(0);
break;
1259 case 1: produce(-1);
break;
1260 case 2: produce(-2);
break;
1261 case 3: produce(-3);
break;
1262 case 4: produce(-6);
break;
1263 case 6: produce(-3,
true);
break;
1264 case 7: produce(-2,
true);
break;
1265 case 8: produce(-1,
true);
break;
1266 case 9:
if (j!=9) produce(0,
true);
break;
1272 if (!fills && !lines)
return false;
1274 var patt = defs.append(
'svg:pattern').attr(
"id",
id).attr(
"class",
id).attr(
"patternUnits",
"userSpaceOnUse")
1275 .attr(
"width", w).attr(
"height", h);
1278 var col = d3.rgb(this.color);
1279 col.r = Math.round((col.r+255)/2); col.g = Math.round((col.g+255)/2); col.b = Math.round((col.b+255)/2);
1280 patt.append(
"svg:path").attr(
"d", fills2).style(
"fill", col);
1282 if (fills) patt.append(
"svg:path").attr(
"d", fills).style(
"fill", this.color);
1283 if (lines) patt.append(
"svg:path").attr(
"d", lines).style(
'stroke', this.color).style(
"stroke-width", 1).style(
"fill", lfill);
1290 TAttFillHandler.prototype.CreateSample =
function(sample_svg, width, height) {
1293 var sample =
new TAttFillHandler({ svg: sample_svg, pattern: this.pattern, color: this.color, color_as_svg:
true });
1295 sample_svg.append(
"path")
1296 .attr(
"d",
"M0,0h" + width+
"v"+height+
"h-" + width +
"z")
1302 Painter.getFontDetails =
function(fontIndex, size) {
1304 var res = { name:
"Arial", size: Math.round(size || 11), weight: null, style: null },
1305 indx = Math.floor(fontIndex / 10),
1306 fontName = Painter.root_fonts[indx] ||
"";
1308 while (fontName.length > 0) {
1309 if (fontName[0]===
'b') res.weight =
"bold";
else
1310 if (fontName[0]===
'i') res.style =
"italic";
else
1311 if (fontName[0]===
'o') res.style =
"oblique";
else break;
1312 fontName = fontName.substr(1);
1315 if (fontName ==
'Symbol')
1316 res.weight = res.style = null;
1318 res.name = fontName;
1319 res.aver_width = Painter.root_fonts_aver_width[indx] || 0.55;
1321 res.setFont =
function(selection, arg) {
1322 selection.attr(
"font-family", this.name);
1323 if (arg !=
'without-size')
1324 selection.attr(
"font-size", this.size)
1325 .attr(
"xml:space",
"preserve");
1327 selection.attr(
"font-weight", this.weight);
1329 selection.attr(
"font-style", this.style);
1332 res.func = res.setFont.bind(res);
1337 Painter.chooseTimeFormat =
function(awidth, ticks) {
1338 if (awidth < .5)
return ticks ?
"%S.%L" :
"%H:%M:%S.%L";
1339 if (awidth < 30)
return ticks ?
"%Mm%S" :
"%H:%M:%S";
1340 awidth /= 60;
if (awidth < 30)
return ticks ?
"%Hh%M" :
"%d/%m %H:%M";
1341 awidth /= 60;
if (awidth < 12)
return ticks ?
"%d-%Hh" :
"%d/%m/%y %Hh";
1342 awidth /= 24;
if (awidth < 15.218425)
return ticks ?
"%d/%m" :
"%d/%m/%y";
1343 awidth /= 30.43685;
if (awidth < 6)
return "%d/%m/%y";
1344 awidth /= 12;
if (awidth < 2)
return ticks ?
"%m/%y" :
"%d/%m/%y";
1349 Painter.getTimeFormat =
function(axis) {
1350 var idF = axis.fTimeFormat.indexOf(
'%F');
1351 return (idF >= 0) ? axis.fTimeFormat.substr(0, idF) : axis.fTimeFormat;
1355 Painter.getTimeOffset =
function(axis) {
1356 var dflt_time_offset = 788918400000;
1357 if (!axis)
return dflt_time_offset;
1358 var idF = axis.fTimeFormat.indexOf(
'%F');
1359 if (idF < 0)
return JSROOT.gStyle.fTimeOffset*1000;
1360 var sof = axis.fTimeFormat.substr(idF + 2);
1362 if (sof.indexOf(
'1995-01-01 00:00:00s0')==0)
return dflt_time_offset;
1364 if ((sof ==
"0") || (sof ==
""))
return 0;
1367 function next(separ, min, max) {
1368 var pos = sof.indexOf(separ);
1369 if (pos < 0) { pos =
"";
return min; }
1370 var val = parseInt(sof.substr(0,pos));
1371 sof = sof.substr(pos+1);
1372 if (isNaN(val) || (val<min) || (val>max)) { pos =
"";
return min; }
1376 var year = next(
"-", 1970, 2300),
1377 month = next(
"-", 1, 12) - 1,
1378 day = next(
" ", 1, 31),
1379 hour = next(
":", 0, 23),
1380 min = next(
":", 0, 59),
1381 sec = next(
"s", 0, 59),
1382 msec = next(
" ", 0, 999);
1384 var dt =
new Date(Date.UTC(year, month, day, hour, min, sec, msec));
1386 var offset = dt.getTime();
1389 sof = sof.toUpperCase();
1391 if (sof.indexOf(
'GMT')==0) {
1392 offset += dt.getTimezoneOffset()*60000;
1393 sof = sof.substr(4).trim();
1394 if (sof.length > 3) {
1395 var p = 0, sign = 1000;
1396 if (sof[0]==
'-') { p = 1; sign = -1000; }
1397 offset -= sign * (parseInt(sof.substr(p,2))*3600 + parseInt(sof.substr(p+2,2))*60);
1404 Painter.translateLaTeX =
function(str) {
1405 while ((str.length>2) && (str[0]==
'{') && (str[str.length-1]==
'}'))
1406 str = str.substr(1,str.length-2);
1408 if (!Painter.symbolsRegexCache) {
1410 Painter.symbolsRegexCache =
new RegExp(
'(' + Object.keys(Painter.symbols_map).join(
'|').replace(/\{/g,
'\{').replace(/\\}/g,
'\\}') +
')',
'g');
1413 str = str.replace(Painter.symbolsRegexCache, Painter.convertSymbol);
1415 str = str.replace(/\{\}/g,
"");
1420 Painter.approxTextWidth =
function(font, label) {
1423 return label.length * font.size * font.aver_width;
1426 Painter.isAnyLatex =
function(str) {
1427 return (str.indexOf(
"#")>=0) || (str.indexOf(
"\\")>=0) || (str.indexOf(
"{")>=0);
1431 Painter.translateMath =
function(str, kind, color, painter) {
1434 for (var x in Painter.math_symbols_map)
1435 str = str.replace(
new RegExp(x,
'g'), Painter.math_symbols_map[x]);
1437 for (var x in Painter.symbols_map)
1439 str = str.replace(
new RegExp(x,
'g'),
"\\" + x.substr(1));
1442 var clean =
"", first =
true;
1444 var p = str.indexOf(
"#color[");
1445 if ((p<0) && first) { clean = str;
break; }
1448 var norm = (p<0) ? str : str.substr(0, p);
1453 str = str.substr(p+7);
1454 p = str.indexOf(
"]{");
1456 var colindx = parseInt(str.substr(0,p));
1457 if (isNaN(colindx))
break;
1458 var col = painter.get_color(colindx), cnt = 1;
1459 str = str.substr(p+2);
1461 while (cnt && (++p<str.length)) {
1462 if (str[p]==
'{') cnt++;
else if (str[p]==
'}') cnt--;
1466 var part = str.substr(0,p);
1467 str = str.substr(p+1);
1469 clean +=
"\\color{" + col +
'}{' + part +
"}";
1474 str = str.replace(/\\\^/g,
"\\hat");
1477 if (typeof color !=
'string')
return "\\(" + str +
"\\)";
1484 return "\\(\\color{" + color +
'}{' + str +
"}\\)";
1494 Painter.BuildSvgPath =
function(kind, bins, height, ndig) {
1496 var smooth = kind.indexOf(
"bezier") >= 0;
1498 if (ndig===undefined) ndig = smooth ? 2 : 0;
1499 if (height===undefined) height = 0;
1501 function jsroot_d3_svg_lineSlope(p0, p1) {
1502 return (p1.gry - p0.gry) / (p1.grx - p0.grx);
1504 function jsroot_d3_svg_lineFiniteDifferences(points) {
1505 var i = 0, j = points.length - 1, m = [], p0 = points[0], p1 = points[1], d = m[0] = jsroot_d3_svg_lineSlope(p0, p1);
1507 m[i] = (d + (d = jsroot_d3_svg_lineSlope(p0 = p1, p1 = points[i + 1]))) / 2;
1512 function jsroot_d3_svg_lineMonotoneTangents(points) {
1513 var d, a, b, s, m = jsroot_d3_svg_lineFiniteDifferences(points), i = -1, j = points.length - 1;
1515 d = jsroot_d3_svg_lineSlope(points[i], points[i + 1]);
1516 if (Math.abs(d) < 1e-6) {
1517 m[i] = m[i + 1] = 0;
1523 s = d * 3 / Math.sqrt(s);
1531 s = (points[Math.min(j, i + 1)].grx - points[Math.max(0, i - 1)].grx) / (6 * (1 + m[i] * m[i]));
1532 points[i].dgrx = s || 0;
1533 points[i].dgry = m[i]*s || 0;
1537 var res = { path:
"", close:
"" }, bin = bins[0], prev, maxy = Math.max(bin.gry, height+5),
1538 currx = Math.round(bin.grx), curry = Math.round(bin.gry), dx, dy, npnts = bins.length;
1540 function conv(val) {
1541 var vvv = Math.round(val);
1542 if ((ndig==0) || (vvv===val))
return vvv.toString();
1543 var str = val.toFixed(ndig);
1544 while ((str[str.length-1] ==
'0') && (str.lastIndexOf(
".") < str.length-1))
1545 str = str.substr(0,str.length-1);
1546 if (str[str.length-1] ==
'.')
1547 str = str.substr(0,str.length-1);
1548 if (str ==
"-0") str =
"0";
1552 res.path = ((kind[0] ==
"L") ?
"L" :
"M") + conv(bin.grx) +
"," + conv(bin.gry);
1555 if (smooth || kind.indexOf(
'calc')>=0)
1556 jsroot_d3_svg_lineMonotoneTangents(bins);
1560 res.path +=
"c" + conv(bin.dgrx) +
"," + conv(bin.dgry) +
",";
1561 for(var n=1; n<npnts; ++n) {
1564 if (n > 1) res.path +=
"s";
1565 res.path += conv(bin.grx-bin.dgrx-prev.grx) +
"," + conv(bin.gry-bin.dgry-prev.gry) +
"," + conv(bin.grx-prev.grx) +
"," + conv(bin.gry-prev.gry);
1566 maxy = Math.max(maxy, prev.gry);
1568 }
else if (npnts < 10000) {
1570 for(var n=1; n<npnts; ++n) {
1572 dx = Math.round(bin.grx) - currx;
1573 dy = Math.round(bin.gry) - curry;
1574 if (dx && dy) res.path +=
"l"+dx+
","+dy;
1575 else if (!dx && dy) res.path +=
"v"+dy;
1576 else if (dx && !dy) res.path +=
"h"+dx;
1577 currx += dx; curry += dy;
1578 maxy = Math.max(maxy, curry);
1582 var lastx, lasty, cminy = curry, cmaxy = curry, prevy = curry;
1583 for(var n=1; n<npnts; ++n) {
1585 lastx = Math.round(bin.grx);
1586 lasty = Math.round(bin.gry);
1587 maxy = Math.max(maxy, lasty);
1591 cminy = Math.min(cminy, lasty);
1592 cmaxy = Math.max(cmaxy, lasty);
1597 if (cminy !== cmaxy) {
1598 if (cminy != curry) res.path +=
"v" + (cminy-curry);
1599 res.path +=
"v" + (cmaxy-cminy);
1600 if (cmaxy != prevy) res.path +=
"v" + (prevy-cmaxy);
1604 if (dy) res.path +=
"l"+dx+
","+dy;
1605 else res.path +=
"h"+dx;
1606 currx = lastx; curry = lasty;
1607 prevy = cminy = cmaxy = lasty;
1610 if (cminy != cmaxy) {
1611 if (cminy != curry) res.path +=
"v"+(cminy-curry);
1612 res.path +=
"v"+(cmaxy-cminy);
1613 if (cmaxy != prevy) res.path +=
"v"+(prevy-cmaxy);
1620 res.close =
"L"+conv(bin.grx)+
","+conv(maxy) +
1621 "h"+conv(bins[0].grx-bin.grx) +
"Z";
1628 function LongPollSocket(addr, _raw, _args) {
1635 this.nextrequest(
"",
"connect");
1638 LongPollSocket.prototype.nextrequest =
function(data, kind) {
1639 var url = this.path, reqmode =
"buf", post = null;
1640 if (kind ===
"connect") {
1641 url += this.raw ?
"?raw_connect" :
"?txt_connect";
1642 if (this.args) url +=
"&" + this.args;
1643 console.log(
'longpoll connect ' + url +
' raw = ' + this.raw);
1644 this.connid =
"connect";
1645 }
else if (kind ===
"close") {
1646 if ((this.connid===null) || (this.connid===
"close"))
return;
1647 url+=
"?connection="+this.connid +
"&close";
1648 this.connid =
"close";
1650 }
else if ((this.connid===null) || (typeof this.connid!==
'number')) {
1651 return console.error(
"No connection");
1653 url+=
"?connection="+this.connid;
1654 if (kind===
"dummy") url+=
"&dummy";
1660 url +=
"&post=" + btoa(data);
1668 var req = JSROOT.NewHttpRequest(url, reqmode,
function(res) {
1671 if (this.handle.req ===
this)
1672 this.handle.req = null;
1675 return this.handle.processreq(null);
1677 if (this.handle.raw) {
1683 var str =
"", i = 0, u8Arr =
new Uint8Array(res), offset = u8Arr.length;
1685 console.error(
'longpoll got short message in raw mode ' + offset);
1686 return this.handle.processreq(null);
1689 while(i<4) str += String.fromCharCode(u8Arr[i++]);
1690 if (str !=
"txt:") {
1692 while ((i<offset) && (String.fromCharCode(u8Arr[i]) !=
':')) str += String.fromCharCode(u8Arr[i++]);
1694 offset = i + parseInt(str.trim());
1698 while (i<offset) str += String.fromCharCode(u8Arr[i++]);
1701 if (str ==
"<<nope>>") str =
"";
1702 this.handle.processreq(str);
1704 if (offset < u8Arr.length)
1705 this.handle.processreq(res, offset);
1706 }
else if (this.getResponseHeader(
"Content-Type") ==
"application/x-binary") {
1708 var extra_hdr = this.getResponseHeader(
"LongpollHeader");
1709 if (extra_hdr) this.handle.processreq(extra_hdr);
1710 this.handle.processreq(res, 0);
1713 if (res && typeof res !==
"string") {
1714 var str =
"", u8Arr =
new Uint8Array(res);
1715 for (var i = 0; i < u8Arr.length; ++i)
1716 str += String.fromCharCode(u8Arr[i]);
1719 if (res ==
"<<nope>>") res =
"";
1720 this.handle.processreq(res);
1725 if (kind===
"dummy") this.req = req;
1729 LongPollSocket.prototype.processreq =
function(res, _offset) {
1731 if (typeof this.onerror ===
'function') this.onerror(
"receive data with connid " + (this.connid ||
"---"));
1737 if (this.connid===
"connect") {
1740 if (typeof this.onerror ===
'function') this.onerror(
"connection rejected");
1744 this.connid = parseInt(res);
1745 console.log(
'Get new longpoll connection with id ' + this.connid);
1746 if (typeof this.onopen ==
'function') this.onopen();
1747 }
else if (this.connid===
"close") {
1748 if (typeof this.onclose ==
'function') this.onclose();
1751 if ((typeof this.onmessage===
'function') && res)
1752 this.onmessage({ data: res, offset: _offset });
1755 if (!this.req) this.nextrequest(
"",
"dummy");
1758 LongPollSocket.prototype.send =
function(str) {
1759 this.nextrequest(str);
1762 LongPollSocket.prototype.close =
function() {
1763 this.nextrequest(
"",
"close");
1768 function FileDumpSocket(receiver) {
1769 this.receiver = receiver;
1772 JSROOT.NewHttpRequest(
"protocol.json",
"text", this.get_protocol.bind(
this)).send();
1775 FileDumpSocket.prototype.get_protocol =
function(res) {
1777 this.protocol = JSON.parse(res);
1778 if (typeof this.onopen ==
'function') this.onopen();
1779 this.next_operation();
1782 FileDumpSocket.prototype.send =
function(str) {
1783 if (this.protocol[this.cnt] ==
"send") {
1785 setTimeout(this.next_operation.bind(
this),10);
1789 FileDumpSocket.prototype.close =
function() {
1792 FileDumpSocket.prototype.next_operation =
function() {
1794 if (this.wait_for_file)
return;
1795 var fname = this.protocol[this.cnt];
1797 if (fname ==
"send")
return;
1799 this.wait_for_file =
true;
1800 JSROOT.NewHttpRequest(fname, (fname.indexOf(
".bin") > 0 ?
"buf" :
"text"), this.get_file.bind(
this, fname)).send();
1804 FileDumpSocket.prototype.get_file =
function(fname, res) {
1806 this.wait_for_file =
false;
1808 if (this.receiver.ProvideData)
1809 this.receiver.ProvideData(res, 0);
1810 setTimeout(this.next_operation.bind(
this),10);
1823 function WebWindowHandle(socket_kind) {
1824 this.kind = socket_kind;
1833 WebWindowHandle.prototype.GetUserArgs =
function(field) {
1834 if (field && (typeof field ==
'string')) {
1835 return (this.user_args && (typeof this.user_args ==
'object')) ? this.user_args[field] : undefined;
1838 return this.user_args;
1847 WebWindowHandle.prototype.SetReceiver =
function(obj) {
1848 this.receiver = obj;
1852 WebWindowHandle.prototype.Cleanup =
function() {
1853 delete this.receiver;
1859 WebWindowHandle.prototype.InvokeReceiver =
function(method, arg, arg2) {
1860 if (this.receiver && (typeof this.receiver[method] ==
'function'))
1861 this.receiver[method](
this, arg, arg2);
1866 WebWindowHandle.prototype.ProvideData =
function(_msg, _len) {
1867 if (!this.msgqueue || !this.msgqueue.length)
1868 return this.InvokeReceiver(
"OnWebsocketMsg", _msg, _len);
1869 this.msgqueue.push({ ready:
true, msg: _msg, len: _len});
1874 WebWindowHandle.prototype.ReserveQueueItem =
function() {
1875 if (!this.msgqueue) this.msgqueue = [];
1876 var item = { ready:
false, msg: null, len: 0 };
1877 this.msgqueue.push(item);
1883 WebWindowHandle.prototype.DoneItem =
function(item, _msg, _len) {
1887 if (this._loop_msgqueue)
return;
1888 this._loop_msgqueue =
true;
1889 while ((this.msgqueue.length > 0) && this.msgqueue[0].ready) {
1890 var front = this.msgqueue.shift();
1891 this.InvokeReceiver(
"OnWebsocketMsg", front.msg, front.len);
1893 if (this.msgqueue.length == 0)
1894 delete this.msgqueue;
1895 delete this._loop_msgqueue;
1899 WebWindowHandle.prototype.Close =
function(force) {
1901 clearTimeout(this.timerid);
1902 delete this.timerid;
1905 if (this._websocket && (this.state > 0)) {
1906 this.state = force ? -1 : 0;
1907 this._websocket.onclose = null;
1908 this._websocket.close();
1909 delete this._websocket;
1914 WebWindowHandle.prototype.CanSend =
function(numsend) {
1915 return (this.cansend >= (numsend || 1));
1919 WebWindowHandle.prototype.Send =
function(msg, chid) {
1920 if (!this._websocket || (this.state<=0))
return false;
1922 if (isNaN(chid) || (chid===undefined)) chid = 1;
1924 if (this.cansend <= 0) console.error(
'should be queued before sending cansend: ' + this.cansend);
1926 var prefix = this.ackn +
":" + this.cansend +
":" + chid +
":";
1930 this._websocket.send(prefix + msg);
1931 if (this.kind ===
"websocket") {
1932 if (this.timerid) clearTimeout(this.timerid);
1933 this.timerid = setTimeout(this.KeepAlive.bind(
this), 10000);
1941 WebWindowHandle.prototype.KeepAlive =
function() {
1942 delete this.timerid;
1943 this.Send(
"KEEPALIVE", 0);
1949 WebWindowHandle.prototype.CreateRelative =
function(relative) {
1950 if (!relative || !this.kind || !this.href)
return null;
1952 var handle =
new WebWindowHandle(this.kind);
1953 console.log(
'Try to connect ', this.href + relative);
1954 handle.Connect(this.href + relative);
1959 WebWindowHandle.prototype.Connect =
function(href) {
1963 var pthis =
this, ntry = 0, args = (this.key ? (
"key=" + this.key) :
"");
1965 function retry_open(first_time) {
1967 if (pthis.state != 0)
return;
1969 if (!first_time) console.log(
"try connect window again" + (
new Date()).getTime());
1971 if (pthis._websocket) pthis._websocket.close();
1972 delete pthis._websocket;
1976 href = window.location.href;
1977 if (href && href.indexOf(
"#")>0) href = href.substr(0, href.indexOf(
"#"));
1978 if (href && href.lastIndexOf(
"/")>0) href = href.substr(0, href.lastIndexOf(
"/")+1);
1983 if (first_time) console.log(
'Opening web socket at ' + href);
1985 if (ntry>2) JSROOT.progress(
"Trying to connect " + href);
1989 if (pthis.kind ==
"file") {
1990 path +=
"root.filedump";
1991 conn =
new FileDumpSocket(pthis);
1992 console.log(
'configure protocol log ' + path);
1993 }
else if ((pthis.kind ===
'websocket') && first_time) {
1994 path = path.replace(
"http://",
"ws://").replace(
"https://",
"wss://") +
"root.websocket";
1995 if (args) path +=
"?" + args;
1996 console.log(
'configure websocket ' + path);
1997 conn =
new WebSocket(path);
1999 path +=
"root.longpoll";
2000 console.log(
'configure longpoll ' + path);
2001 conn =
new LongPollSocket(path, (pthis.kind ===
'rawlongpoll'), args);
2006 pthis._websocket = conn;
2008 conn.onopen =
function() {
2009 if (ntry > 2) JSROOT.progress();
2012 var key = pthis.key ||
"";
2014 pthis.Send(
"READY=" + key, 0);
2015 pthis.InvokeReceiver(
'OnWebsocketOpened');
2018 conn.onmessage =
function(e) {
2021 if (pthis.next_binary) {
2022 delete pthis.next_binary;
2024 if (msg instanceof Blob) {
2027 var reader =
new FileReader, qitem = pthis.ReserveQueueItem();
2028 reader.onload =
function(event) {
2030 pthis.DoneItem(qitem, event.target.result, 0);
2032 reader.readAsArrayBuffer(msg, e.offset || 0);
2036 pthis.ProvideData(msg, e.offset || 0);
2042 if (typeof msg !=
'string')
return console.log(
"unsupported message kind: " + (typeof msg));
2044 var i1 = msg.indexOf(
":"),
2045 credit = parseInt(msg.substr(0,i1)),
2046 i2 = msg.indexOf(
":", i1+1),
2047 cansend = parseInt(msg.substr(i1+1,i2-i1)),
2048 i3 = msg.indexOf(
":", i2+1),
2049 chid = parseInt(msg.substr(i2+1,i3-i2));
2054 pthis.cansend += credit;
2056 msg = msg.substr(i3+1);
2059 console.log(
'GET chid=0 message', msg);
2060 if (msg ==
"CLOSE") {
2062 pthis.InvokeReceiver(
'OnWebsocketClosed');
2064 }
else if (msg ==
"$$binary$$") {
2065 pthis.next_binary =
true;
2066 }
else if (msg ==
"$$nullbinary$$") {
2067 pthis.ProvideData(
new ArrayBuffer(0), 0);
2069 pthis.ProvideData(msg);
2073 pthis.Send(
'READY', 0);
2076 conn.onclose =
function() {
2077 delete pthis._websocket;
2078 if (pthis.state > 0) {
2079 console.log(
'websocket closed');
2081 pthis.InvokeReceiver(
'OnWebsocketClosed');
2085 conn.onerror =
function (err) {
2086 console.log(
"websocket error " + err);
2087 if (pthis.state > 0) {
2088 pthis.InvokeReceiver(
'OnWebsocketError', err);
2094 if (!JSROOT.BatchMode)
2095 setTimeout(retry_open, 3000);
2115 JSROOT.ConnectWebWindow =
function(arg) {
2116 if (typeof arg ==
'function') arg = { callback: arg };
else
2117 if (!arg || (typeof arg !=
'object')) arg = {};
2120 if (arg.openui5src) JSROOT.openui5src = arg.openui5src;
2121 if (arg.openui5libs) JSROOT.openui5libs = arg.openui5libs;
2122 return JSROOT.AssertPrerequisites(arg.prereq,
function() {
2123 delete arg.prereq; JSROOT.ConnectWebWindow(arg);
2124 }, arg.prereq_logdiv);
2128 if ((JSROOT.GetUrlOption(
"batch_mode")!==null) && JSROOT.GetUrlOption(
"key") && (JSROOT.browser.isChromeHeadless || JSROOT.browser.isChrome))
2129 JSROOT.loadScript(
"root_batch_holder.js?key=" + JSROOT.GetUrlOption(
"key"));
2132 arg.platform = JSROOT.GetUrlOption(
"platform");
2134 if (arg.platform ==
"qt5") JSROOT.browser.qt5 =
true;
else
2135 if (arg.platform ==
"cef3") JSROOT.browser.cef3 =
true;
2137 if (arg.batch === undefined)
2138 arg.batch = (JSROOT.GetUrlOption(
"batch_mode")!==null);
2140 if (arg.batch) JSROOT.BatchMode =
true;
2142 if (!arg.socket_kind)
2143 arg.socket_kind = JSROOT.GetUrlOption(
"ws");
2145 if (!arg.socket_kind) {
2146 if (JSROOT.browser.qt5) arg.socket_kind =
"rawlongpoll";
else
2147 if (JSROOT.browser.cef3) arg.socket_kind =
"longpoll";
else arg.socket_kind =
"websocket";
2153 var handle =
new WebWindowHandle(arg.socket_kind);
2154 handle.user_args = arg.user_args;
2157 window.onbeforeunload = handle.Close.bind(handle,
true);
2158 if (JSROOT.browser.qt5) window.onqt5unload = window.onbeforeunload;
2161 if (arg.first_recv) {
2163 OnWebsocketOpened:
function(handle) {
2166 OnWebsocketMsg:
function(handle, msg) {
2168 if (msg.indexOf(arg.first_recv)!=0)
2169 return handle.Close();
2170 arg.first_msg = msg.substr(arg.first_recv.length);
2172 if (!arg.prereq2) JSROOT.CallBack(arg.callback, handle, arg);
2175 OnWebsocketClosed:
function(handle) {
2177 JSROOT.CloseCurrentWindow();
2182 handle.key = JSROOT.GetUrlOption(
"key");
2185 return JSROOT.CallBack(arg.callback, handle, arg);
2188 handle.SetReceiver(arg.receiver);
2192 JSROOT.AssertPrerequisites(arg.prereq2,
function() {
2194 if (!arg.first_recv || arg.first_msg) JSROOT.CallBack(arg.callback, handle, arg);
2196 }
else if (!arg.first_recv) {
2197 JSROOT.CallBack(arg.callback, handle, arg);
2209 function TBasePainter() {
2222 TBasePainter.prototype.AccessTopPainter =
function(on) {
2223 var main = this.select_main().node(),
2224 chld = main ? main.firstChild : null;
2225 if (!chld)
return null;
2226 if (on===
true) chld.painter =
this;
else
2227 if (on===
false)
delete chld.painter;
2228 return chld.painter;
2232 TBasePainter.prototype.Cleanup =
function(keep_origin) {
2234 var origin = this.select_main(
'origin');
2235 if (!origin.empty() && !keep_origin) origin.html(
"");
2236 if (this._changed_layout)
2237 this.set_layout_kind(
'simple');
2238 this.AccessTopPainter(
false);
2240 delete this._selected_main;
2242 if (this._hpainter && typeof this._hpainter.ClearPainter ===
'function') this._hpainter.ClearPainter(
this);
2244 delete this._changed_layout;
2245 delete this._hitemname;
2246 delete this._hdrawopt;
2247 delete this._hpainter;
2253 TBasePainter.prototype.DrawingReady =
function(res_painter) {
2254 this._ready_called_ =
true;
2255 if (this._ready_callback_ !== undefined) {
2256 var callbacks = this._ready_callback_;
2257 if (!this._return_res_painter) res_painter =
this;
2259 delete this._return_res_painter;
2260 delete this._ready_callback_;
2262 while (callbacks.length)
2263 JSROOT.CallBack(callbacks.shift(), res_painter);
2271 TBasePainter.prototype.WhenReady =
function(callback) {
2272 if (typeof callback !==
'function')
return;
2273 if (
'_ready_called_' in
this)
return JSROOT.CallBack(callback,
this);
2274 if (this._ready_callback_ === undefined) this._ready_callback_ = [];
2275 this._ready_callback_.push(callback);
2281 TBasePainter.prototype.ResetReady =
function() {
2282 delete this._ready_called_;
2283 delete this._ready_callback_;
2288 TBasePainter.prototype.GetObject =
function() {
2296 TBasePainter.prototype.MatchObjectType =
function(
typename) {
2303 TBasePainter.prototype.UpdateObject =
function(obj) {
2309 TBasePainter.prototype.RedrawPad =
function(resize) {
2315 TBasePainter.prototype.RedrawObject =
function(obj) {
2316 if (!this.UpdateObject(obj))
return false;
2317 var current = document.body.style.cursor;
2318 document.body.style.cursor =
'wait';
2320 document.body.style.cursor = current;
2328 TBasePainter.prototype.CheckResize =
function(arg) {
2335 TBasePainter.prototype.select_main =
function(is_direct) {
2337 if (!this.divid)
return d3.select(null);
2339 var res = this._selected_main;
2341 if (typeof this.divid ==
"string") {
2342 var
id = this.divid;
2343 if (
id[0]!=
'#')
id =
"#" + id;
2344 res = d3.select(
id);
2345 if (!res.empty()) this.divid = res.node();
2347 res = d3.select(this.divid);
2349 this._selected_main = res;
2352 if (!res || res.empty() || (is_direct===
'origin'))
return res;
2354 var use_enlarge = res.property(
'use_enlarge'),
2355 layout = res.property(
'layout') ||
'simple',
2356 layout_selector = (layout==
'simple') ?
"" : res.property(
'layout_selector');
2358 if (layout_selector) res = res.select(layout_selector);
2361 if (!is_direct && !res.empty() && use_enlarge) res = d3.select(
"#jsroot_enlarge_div");
2369 TBasePainter.prototype.get_main_id =
function() {
2370 var elem = this.select_main();
2371 if (elem.empty())
return "";
2372 var
id = elem.attr(
"id");
2374 id =
"jsroot_element_" + JSROOT.id_counter++;
2375 elem.attr(
"id",
id);
2383 TBasePainter.prototype.get_layout_kind =
function() {
2384 var origin = this.select_main(
'origin'),
2385 layout = origin.empty() ?
"" : origin.property(
'layout');
2387 return layout ||
'simple';
2393 TBasePainter.prototype.set_layout_kind =
function(kind, main_selector) {
2395 var origin = this.select_main(
'origin');
2396 if (!origin.empty()) {
2397 if (!kind) kind =
'simple';
2398 origin.property(
'layout', kind);
2399 origin.property(
'layout_selector', (kind!=
'simple') && main_selector ? main_selector : null);
2400 this._changed_layout = (kind !==
'simple');
2411 TBasePainter.prototype.check_main_resize =
function(check_level, new_size, height_factor) {
2413 var enlarge = this.enlarge_main(
'state'),
2414 main_origin = this.select_main(
'origin'),
2415 main = this.select_main(),
2418 if (enlarge !==
'on') {
2419 if (new_size && new_size.width && new_size.height)
2420 main_origin.style(
'width',new_size.width+
"px")
2421 .style(
'height',new_size.height+
"px");
2424 var rect_origin = this.get_visible_rect(main_origin,
true),
2425 can_resize = main_origin.attr(
'can_resize'),
2428 if (can_resize ==
"height")
2429 if (height_factor && Math.abs(rect_origin.width*height_factor - rect_origin.height) > 0.1*rect_origin.width) do_resize =
true;
2431 if (((rect_origin.height <= lmt) || (rect_origin.width <= lmt)) &&
2432 can_resize && can_resize !==
'false') do_resize =
true;
2434 if (do_resize && (enlarge !==
'on')) {
2437 if (rect_origin.width > lmt) {
2438 height_factor = height_factor || 0.66;
2439 main_origin.style(
'height', Math.round(rect_origin.width * height_factor)+
'px');
2440 }
else if (can_resize !==
'height') {
2441 main_origin.style(
'width',
'200px').style(
'height',
'100px');
2445 var rect = this.get_visible_rect(main),
2446 old_h = main.property(
'draw_height'), old_w = main.property(
'draw_width');
2448 rect.changed =
false;
2450 if (old_h && old_w && (old_h>0) && (old_w>0)) {
2451 if ((old_h !== rect.height) || (old_w !== rect.width))
2452 if ((check_level>1) || (rect.width/old_w<0.66) || (rect.width/old_w>1.5) ||
2453 (rect.height/old_h<0.66) && (rect.height/old_h>1.5)) rect.changed =
true;
2455 rect.changed =
true;
2475 TBasePainter.prototype.enlarge_main =
function(action, skip_warning) {
2477 var main = this.select_main(
true),
2478 origin = this.select_main(
'origin');
2480 if (main.empty() || !JSROOT.gStyle.CanEnlarge || (origin.property(
'can_enlarge')===
false))
return false;
2482 if (action===undefined)
return true;
2484 if (action===
'verify')
return true;
2486 var state = origin.property(
'use_enlarge') ?
"on" :
"off";
2488 if (action ===
'state')
return state;
2490 if (action ===
'toggle') action = (state===
"off");
2492 var enlarge = d3.select(
"#jsroot_enlarge_div");
2494 if ((action ===
true) && (state!==
"on")) {
2495 if (!enlarge.empty())
return false;
2497 enlarge = d3.select(document.body)
2499 .attr(
"id",
"jsroot_enlarge_div");
2501 var rect1 = this.get_visible_rect(main),
2502 rect2 = this.get_visible_rect(enlarge);
2505 if ((rect2.width <= rect1.width) || (rect2.height <= rect1.height))
2506 if (rect2.width*rect2.height < rect1.width*rect1.height) {
2508 console.log(
'Enlarged area ' + rect2.width+
"x"+rect2.height +
' smaller then original drawing ' + rect1.width+
"x"+rect1.height);
2513 while (main.node().childNodes.length > 0)
2514 enlarge.node().appendChild(main.node().firstChild);
2516 origin.property(
'use_enlarge',
true);
2520 if ((action ===
false) && (state!==
"off")) {
2522 while (enlarge.node() && enlarge.node().childNodes.length > 0)
2523 main.node().appendChild(enlarge.node().firstChild);
2526 origin.property(
'use_enlarge',
false);
2535 TBasePainter.prototype.GetStyleValue =
function(elem, name) {
2536 if (!elem || elem.empty())
return 0;
2537 var value = elem.style(name);
2538 if (!value || (typeof value !==
'string'))
return 0;
2539 value = parseFloat(value.replace(
"px",
""));
2540 return isNaN(value) ? 0 : Math.round(value);
2545 TBasePainter.prototype.get_visible_rect =
function(elem, fullsize) {
2548 return { width : parseInt(elem.attr(
"width")), height: parseInt(elem.attr(
"height")) };
2550 var rect = elem.node().getBoundingClientRect(),
2551 res = { width: Math.round(rect.width), height: Math.round(rect.height) };
2555 res.width -= this.GetStyleValue(elem,
'padding-left') + this.GetStyleValue(elem,
'padding-right');
2556 res.height -= this.GetStyleValue(elem,
'padding-top') - this.GetStyleValue(elem,
'padding-bottom');
2569 TBasePainter.prototype.SetDivId =
function(divid) {
2570 if (divid !== undefined) {
2572 delete this._selected_main;
2575 this.AccessTopPainter(
true);
2583 TBasePainter.prototype.SetItemName =
function(name, opt, hpainter) {
2584 if (typeof name ===
'string') this._hitemname = name;
2585 else delete this._hitemname;
2587 if (typeof opt ===
'string') this._hdrawopt = opt;
2589 this._hpainter = hpainter;
2594 TBasePainter.prototype.GetItemName =
function() {
2595 return (
'_hitemname' in
this) ? this._hitemname : null;
2600 TBasePainter.prototype.GetItemDrawOpt =
function() {
2601 return (
'_hdrawopt' in
this) ? this._hdrawopt :
"";
2612 TBasePainter.prototype.CanZoomIn =
function(axis,left,right) {
2625 function TObjectPainter(obj, opt) {
2626 TBasePainter.call(
this);
2630 if (typeof opt ==
"string") this.options = { original: opt };
2631 this.AssignObject(obj);
2634 TObjectPainter.prototype = Object.create(TBasePainter.prototype);
2636 TObjectPainter.prototype.AssignObject =
function(obj) {
2637 this.draw_object = ((obj!==undefined) && (typeof obj ==
'object')) ? obj : null;
2644 TObjectPainter.prototype.Cleanup =
function() {
2648 var keep_origin =
true;
2650 if (this.is_main_painter()) {
2651 var pp = this.pad_painter();
2652 if (!pp || pp.normal_canvas ===
false) keep_origin =
false;
2658 this.draw_object = null;
2662 delete this.fillatt;
2663 delete this.lineatt;
2664 delete this.markeratt;
2666 delete this.root_colors;
2667 delete this.options;
2668 delete this.options_store;
2672 delete this.csstype;
2674 TBasePainter.prototype.Cleanup.call(
this, keep_origin);
2678 TObjectPainter.prototype.GetObject =
function() {
2679 return this.draw_object;
2683 TObjectPainter.prototype.GetClassName =
function() {
2684 var res = this.draw_object ? this.draw_object._typename :
"";
2693 TObjectPainter.prototype.MatchObjectType =
function(arg) {
2694 if (!arg || !this.draw_object)
return false;
2695 if (typeof arg ===
'string')
return (this.draw_object._typename === arg);
2696 if (arg._typename)
return (this.draw_object._typename === arg._typename);
2697 return this.draw_object._typename.match(arg);
2704 TObjectPainter.prototype.SetItemName =
function(name, opt, hpainter) {
2705 TBasePainter.prototype.SetItemName.call(
this, name, opt, hpainter);
2706 if (this.no_default_title || (name==
""))
return;
2707 var can = this.svg_canvas();
2708 if (!can.empty()) can.select(
"title").text(name);
2709 else this.select_main().attr(
"title", name);
2714 TObjectPainter.prototype.OptionsStore =
function(original) {
2715 if (!this.options)
return;
2716 if (!original) original =
"";
2717 var pp = original.indexOf(
";;");
2718 if (pp>=0) original = original.substr(0,pp);
2719 this.options.original = original;
2720 this.options_store = JSROOT.extend({}, this.options);
2727 TObjectPainter.prototype.OptionesChanged =
function() {
2728 if (!this.options)
return false;
2729 if (!this.options_store)
return true;
2731 for (var k in this.options)
2732 if (this.options[k] !== this.options_store[k])
return true;
2740 TObjectPainter.prototype.OptionsAsString =
function() {
2741 if (!this.options)
return "";
2743 if (!this.OptionesChanged())
2744 return this.options.original ||
"";
2746 if (typeof this.options.asString ==
"function")
2747 return this.options.asString();
2749 return this.options.original ||
"";
2757 TObjectPainter.prototype.UpdateObject =
function(obj) {
2758 if (!this.MatchObjectType(obj))
return false;
2759 JSROOT.extend(this.GetObject(), obj);
2768 TObjectPainter.prototype.GetTipName =
function(append) {
2769 var res = this.GetItemName(), obj = this.GetObject();
2770 if (!res) res = obj && obj.fName ? obj.fName :
"";
2771 if (res.lenght > 20) res = res.substr(0,17) +
"...";
2772 if (res && append) res += append;
2778 TObjectPainter.prototype.pad_painter =
function(pad_name) {
2779 var elem = this.svg_pad(typeof pad_name ==
"string" ? pad_name : undefined);
2780 return elem.empty() ? null : elem.property(
'pad_painter');
2785 TObjectPainter.prototype.canv_painter =
function() {
2786 var elem = this.svg_canvas();
2787 return elem.empty() ? null : elem.property(
'pad_painter');
2792 TObjectPainter.prototype.get_color =
function(indx) {
2793 var jsarr = this.root_colors;
2796 var pp = this.canv_painter();
2797 jsarr = this.root_colors = (pp && pp.root_colors) ? pp.root_colors : JSROOT.Painter.root_colors;
2805 TObjectPainter.prototype.add_color =
function(color) {
2806 var jsarr = this.root_colors;
2808 var pp = this.canv_painter();
2809 jsarr = this.root_colors = (pp && pp.root_colors) ? pp.root_colors : JSROOT.Painter.root_colors;
2811 var indx = jsarr.indexOf(color);
2812 if (indx >= 0)
return indx;
2814 return jsarr.length-1;
2819 TObjectPainter.prototype.IsTooltipAllowed =
function() {
2820 var src = this.canv_painter() ||
this;
2821 return src.tooltip_allowed ?
true :
false;
2826 TObjectPainter.prototype.SetTooltipAllowed =
function(on) {
2827 var src = this.canv_painter() ||
this;
2828 src.tooltip_allowed = (on ==
"toggle") ? !src.tooltip_allowed : on;
2833 TObjectPainter.prototype.get_palette =
function(force, palettedid) {
2835 var pp = this.pad_painter();
2836 if (!pp)
return null;
2837 if (pp.custom_palette)
return pp.custom_palette;
2840 var cp = this.canv_painter();
2841 if (!cp)
return null;
2842 if (cp.custom_palette && !palettedid)
return cp.custom_palette;
2844 if (force && JSROOT.Painter.GetColorPalette)
2845 cp.custom_palette = JSROOT.Painter.GetColorPalette(palettedid);
2847 return cp.custom_palette;
2853 TObjectPainter.prototype.AttributeChange =
function(class_name, member_name, new_value) {
2862 TObjectPainter.prototype.CheckResize =
function(arg) {
2863 var pad_painter = this.canv_painter();
2864 if (!pad_painter)
return false;
2867 pad_painter.CheckCanvasResize(arg);
2873 TObjectPainter.prototype.RemoveDrawG =
function() {
2875 this.draw_g.remove();
2883 TObjectPainter.prototype.RecreateDrawG =
function(usepad, layer) {
2885 console.warn(
"Obsolete RecreateDrawG is used, will be removed soon. Change to CreateG");
2886 return this.CreateG(usepad ? undefined : layer);
2895 TObjectPainter.prototype.CreateG =
function(frame_layer) {
2899 this.draw_g.selectAll(
'*').remove();
2900 }
else if (frame_layer) {
2901 var frame = this.svg_frame();
2902 if (frame.empty())
return frame;
2903 if (typeof frame_layer !=
'string') frame_layer =
"main_layer";
2904 var layer = frame.select(
"." + frame_layer);
2905 if (layer.empty()) layer = frame.select(
".main_layer");
2906 this.draw_g = layer.append(
"svg:g");
2908 var layer = this.svg_layer(
"primitives_layer");
2909 this.draw_g = layer.append(
"svg:g");
2912 var up = [], chlds = layer.node().childNodes;
2913 for (var n=0;n<chlds.length;++n)
2914 if (d3.select(chlds[n]).classed(
"most_upper_primitives")) up.push(chlds[n]);
2916 up.forEach(
function(top) { d3.select(top).raise(); });
2920 if (this.draw_object) {
2921 this.draw_g.attr(
'objname', encodeURI(this.draw_object.fName ||
"name"));
2922 this.draw_g.attr(
'objtype', encodeURI(this.draw_object._typename ||
"type"));
2925 this.draw_g.property(
'in_frame', !!frame_layer);
2932 TObjectPainter.prototype.svg_canvas =
function() {
2933 return this.select_main().select(
".root_canvas");
2938 TObjectPainter.prototype.svg_pad =
function(pad_name) {
2939 if (pad_name === undefined) pad_name = this.pad_name;
2941 var c = this.svg_canvas();
2942 if (!pad_name || c.empty())
return c;
2944 var cp = c.property(
'pad_painter');
2945 if (cp && cp.pads_cache && cp.pads_cache[pad_name])
2946 return d3.select(cp.pads_cache[pad_name]);
2948 c = c.select(
".primitives_layer .__root_pad_" + pad_name);
2950 if (!cp.pads_cache) cp.pads_cache = {};
2951 cp.pads_cache[pad_name] = c.node();
2958 TObjectPainter.prototype.svg_layer =
function(name, pad_name) {
2959 var svg = this.svg_pad(pad_name);
2960 if (svg.empty())
return svg;
2962 if (name.indexOf(
"prim#")==0) {
2963 svg = svg.select(
".primitives_layer");
2964 name = name.substr(5);
2967 var node = svg.node().firstChild;
2968 while (node!==null) {
2969 var elem = d3.select(node);
2970 if (elem.classed(name))
return elem;
2971 node = node.nextSibling;
2974 return d3.select(null);
2980 TObjectPainter.prototype.CurrentPadName =
function(new_name) {
2981 var svg = this.svg_canvas();
2982 if (svg.empty())
return "";
2983 var curr = svg.property(
'current_pad');
2984 if (new_name !== undefined) svg.property(
'current_pad', new_name);
2990 TObjectPainter.prototype.root_pad =
function() {
2991 var pad_painter = this.pad_painter();
2992 return pad_painter ? pad_painter.pad : null;
3004 TObjectPainter.prototype.AxisToSvg =
function(axis, value, ndc, noround) {
3005 var use_frame = this.draw_g && this.draw_g.property(
'in_frame'),
3006 main = use_frame ? this.frame_painter() : null;
3008 if (use_frame && main && main[
"gr"+axis]) {
3009 value = (axis==
"y") ? main.gry(value) + (use_frame ? 0 : main.frame_y())
3010 : main.grx(value) + (use_frame ? 0 : main.frame_x());
3011 }
else if (use_frame) {
3014 var pad = ndc ? null : this.root_pad();
3018 value = (value>0) ? JSROOT.log10(value) : pad.fUymin;
3019 value = (value - pad.fY1) / (pad.fY2 - pad.fY1);
3022 value = (value>0) ? JSROOT.log10(value) : pad.fUxmin;
3023 value = (value - pad.fX1) / (pad.fX2 - pad.fX1);
3026 value = (axis==
"y") ? (1-value)*this.pad_height() : value*this.pad_width();
3029 return noround ? value : Math.round(value);
3041 TObjectPainter.prototype.SvgToAxis =
function(axis, coord, ndc) {
3042 var use_frame = this.draw_g && this.draw_g.property(
'in_frame'),
3043 main = use_frame ? this.frame_painter() : null;
3045 if (use_frame) main = this.frame_painter();
3047 if (use_frame && main) {
3048 return (axis==
"y") ? main.RevertY(coord - (use_frame ? 0 : main.frame_y()))
3049 : main.RevertX(coord - (use_frame ? 0 : main.frame_x()));
3050 }
else if (use_frame) {
3054 var value = (axis==
"y") ? (1 - coord / this.pad_height()) : coord / this.pad_width();
3055 var pad = ndc ? null : this.root_pad();
3059 value = pad.fY1 + value * (pad.fY2 - pad.fY1);
3060 if (pad.fLogy) value = Math.pow(10, value);
3062 value = pad.fX1 + value * (pad.fX2 - pad.fX1);
3063 if (pad.fLogx) value = Math.pow(10, value);
3076 TObjectPainter.prototype.AxisToSvgFunc =
function(isndc) {
3077 var func = {isndc: isndc}, use_frame = this.draw_g && this.draw_g.property(
'in_frame');
3078 if (use_frame) func.main = this.frame_painter();
3079 if (func.main && !isndc && func.main.grx && func.main.gry) {
3080 func.offx = func.main.frame_x();
3081 func.offy = func.main.frame_y();
3082 func.x =
function(x) {
return Math.round(this.main.grx(x) + this.offx); }
3083 func.y =
function(y) {
return Math.round(this.main.gry(y) + this.offy); }
3085 if (!isndc) func.pad = this.root_pad();
3086 func.padh = this.pad_height();
3087 func.padw = this.pad_width();
3088 func.x =
function(value) {
3091 value = (value>0) ? JSROOT.log10(value) : this.pad.fUxmin;
3092 value = (value - this.pad.fX1) / (this.pad.fX2 -
this.pad.fX1);
3094 return Math.round(value*this.padw);
3096 func.y =
function(value) {
3099 value = (value>0) ? JSROOT.log10(value) : this.pad.fUymin;
3100 value = (value - this.pad.fY1) / (this.pad.fY2 -
this.pad.fY1);
3102 return Math.round((1-value)*this.padh);
3112 TObjectPainter.prototype.svg_frame =
function(pad_name) {
3113 return this.svg_layer(
"primitives_layer", pad_name).select(
".root_frame");
3121 TObjectPainter.prototype.pad_width =
function(pad_name) {
3122 var res = this.svg_pad(pad_name);
3123 res = res.empty() ? 0 : res.property(
"draw_width");
3124 return isNaN(res) ? 0 : res;
3132 TObjectPainter.prototype.pad_height =
function(pad_name) {
3133 var res = this.svg_pad(pad_name);
3134 res = res.empty() ? 0 : res.property(
"draw_height");
3135 return isNaN(res) ? 0 : res;
3140 TObjectPainter.prototype.frame_painter =
function() {
3141 var pp = this.pad_painter();
3142 return pp ? pp.frame_painter_ref : null;
3147 TObjectPainter.prototype.frame_property =
function(name) {
3148 var pp = this.frame_painter();
3149 return pp && pp[name] ? pp[name] : 0;
3153 TObjectPainter.prototype.frame_x =
function() {
3154 return this.frame_property(
"_frame_x");
3158 TObjectPainter.prototype.frame_y =
function() {
3159 return this.frame_property(
"_frame_y");
3163 TObjectPainter.prototype.frame_width =
function() {
3164 return this.frame_property(
"_frame_width");
3168 TObjectPainter.prototype.frame_height =
function() {
3169 return this.frame_property(
"_frame_height");
3182 TObjectPainter.prototype.embed_3d =
function() {
3183 if (JSROOT.BatchMode)
return 4;
3184 if (JSROOT.gStyle.Embed3DinSVG < 2)
return JSROOT.gStyle.Embed3DinSVG;
3185 if (JSROOT.browser.isFirefox )
3186 return JSROOT.gStyle.Embed3DinSVG;
3195 TObjectPainter.prototype.access_3d_kind =
function(new_value) {
3196 var svg = this.svg_pad(this.this_pad_name);
3197 if (svg.empty())
return -1;
3200 var kind = svg.property(
'can3d');
3201 if (new_value !== undefined) svg.property(
'can3d', new_value);
3202 return ((kind===null) || (kind===undefined)) ? -1 : kind;
3210 TObjectPainter.prototype.size_for_3d =
function(can3d) {
3212 if (can3d === undefined) can3d = this.embed_3d();
3214 var pad = this.svg_pad(this.this_pad_name),
3215 clname =
"draw3d_" + (this.this_pad_name || this.pad_name ||
'canvas');
3220 var rect = this.get_visible_rect(this.select_main());
3222 if ((rect.height<10) && (rect.width>10)) {
3223 rect.height = Math.round(0.66*rect.width);
3224 this.select_main().style(
'height', rect.height +
"px");
3226 rect.x = 0; rect.y = 0; rect.clname = clname; rect.can3d = -1;
3230 var elem = pad, fp = this.frame_painter();
3231 if (can3d === 0) elem = this.svg_canvas();
3233 var size = { x: 0, y: 0, width: 100, height: 100, clname: clname, can3d: can3d };
3235 if (fp && !fp.mode3d) {
3236 elem = this.svg_frame();
3237 size.x = elem.property(
"draw_x");
3238 size.y = elem.property(
"draw_y");
3241 size.width = elem.property(
"draw_width");
3242 size.height = elem.property(
"draw_height");
3244 if ((!fp || fp.mode3d) && (can3d > 0)) {
3245 size.x = Math.round(size.x + size.width*JSROOT.gStyle.fPadLeftMargin);
3246 size.y = Math.round(size.y + size.height*JSROOT.gStyle.fPadTopMargin);
3247 size.width = Math.round(size.width*(1 - JSROOT.gStyle.fPadLeftMargin - JSROOT.gStyle.fPadRightMargin));
3248 size.height = Math.round(size.height*(1- JSROOT.gStyle.fPadTopMargin - JSROOT.gStyle.fPadBottomMargin));
3251 var pw = this.pad_width(this.this_pad_name), x2 = pw - size.x - size.width,
3252 ph = this.pad_height(this.this_pad_name), y2 = ph - size.y - size.height;
3254 if ((x2 >= 0) && (y2 >= 0)) {
3256 size.x = Math.round(size.x * 0.3);
3257 size.y = Math.round(size.y * 0.9);
3258 size.width = pw - size.x - Math.round(x2*0.3);
3259 size.height = ph - size.y - Math.round(y2*0.5);
3263 this.CalcAbsolutePosition(this.svg_pad(this.this_pad_name), size);
3271 TObjectPainter.prototype.clear_3d_canvas =
function() {
3272 var can3d = this.access_3d_kind(null);
3275 var main = this.select_main().node();
3276 if (main && main.firstChild && main.firstChild.$jsroot) {
3277 delete main.firstChild.painter;
3278 main.removeChild(main.firstChild);
3283 var size = this.size_for_3d(can3d);
3285 if (size.can3d === 0) {
3286 d3.select(this.svg_canvas().node().nextSibling).remove();
3287 this.svg_canvas().style(
'display', null);
3289 if (this.svg_pad(this.this_pad_name).empty())
return;
3291 this.apply_3d_size(size).remove();
3293 this.svg_frame().style(
'display', null);
3300 TObjectPainter.prototype.add_3d_canvas =
function(size, canv) {
3302 if (!canv || (size.can3d < -1))
return;
3304 if (size.can3d === -1) {
3307 var main = this.select_main().node();
3308 if (main !== null) {
3309 main.appendChild(canv);
3310 canv.painter =
this;
3311 canv.$jsroot =
true;
3317 this.access_3d_kind(size.can3d);
3319 if (size.can3d === 0) {
3320 this.svg_canvas().style(
'display',
'none');
3322 this.svg_canvas().node().parentNode.appendChild(canv);
3324 if (this.svg_pad(this.this_pad_name).empty())
return;
3327 this.svg_frame().style(
'display',
'none');
3329 var elem = this.apply_3d_size(size);
3331 elem.attr(
'title',
'').node().appendChild(canv);
3337 TObjectPainter.prototype.apply_3d_size =
function(size, onlyget) {
3339 if (size.can3d < 0)
return d3.select(null);
3343 if (size.can3d > 1) {
3345 elem = this.svg_layer(size.clname);
3348 if (onlyget)
return elem;
3350 var svg = this.svg_pad();
3352 if ((size.can3d === 3) || (size.can3d === 4)) {
3356 elem = svg.insert(
"g",
".primitives_layer").attr(
"class", size.clname);
3358 elem.attr(
"transform",
"translate(" + size.x +
"," + size.y +
")");
3363 elem = svg.insert(
"foreignObject",
".primitives_layer").attr(
"class", size.clname);
3365 elem.attr(
'x', size.x)
3367 .attr(
'width', size.width)
3368 .attr(
'height', size.height)
3369 .attr(
'viewBox',
"0 0 " + size.width +
" " + size.height)
3370 .attr(
'preserveAspectRatio',
'xMidYMid');
3374 var prnt = this.svg_canvas().node().parentNode;
3376 elem = d3.select(prnt).select(
"." + size.clname);
3377 if (onlyget)
return elem;
3380 this.svg_canvas().property(
'redraw_by_resize',
true);
3383 elem = d3.select(prnt).append(
'div').attr(
"class", size.clname +
" jsroot_noselect");
3389 var pos0 = prnt.getBoundingClientRect();
3392 if (prnt === document) { prnt = null;
break; }
3394 if (getComputedStyle(prnt).position !==
'static')
break;
3398 prnt = prnt.parentNode;
3401 var pos1 = prnt ? prnt.getBoundingClientRect() : { top: 0, left: 0 };
3403 var offx = Math.round(pos0.left - pos1.left),
3404 offy = Math.round(pos0.top - pos1.top);
3406 elem.style(
'position',
'absolute').style(
'left',(size.x+offx)+
'px').style(
'top',(size.y+offy)+
'px').style(
'width',size.width+
'px').style(
'height',size.height+
'px');
3417 TObjectPainter.prototype.main_painter =
function(not_store, pad_name) {
3418 var res = this.main;
3420 var svg_p = this.svg_pad(pad_name);
3421 if (svg_p.empty()) {
3422 res = this.AccessTopPainter();
3424 res = svg_p.property(
'mainpainter');
3426 if (!res) res = null;
3427 if (!not_store) this.main = res;
3433 TObjectPainter.prototype.is_main_painter =
function() {
3434 return this === this.main_painter();
3455 TObjectPainter.prototype.SetDivId =
function(divid, is_main, pad_name) {
3457 if (divid !== undefined) {
3459 delete this._selected_main;
3462 if (!is_main || isNaN(is_main)) is_main = 0;
3465 if ((is_main >= 0) && this.select_main(
true).empty()) {
3466 if (typeof divid ==
'string') console.error(
'element with id ' + divid +
' not exists');
3467 else console.error(
'specified HTML element can not be selected with d3.select()');
3471 this.create_canvas =
false;
3474 var svg_c = this.svg_canvas();
3476 if (svg_c.empty() && (is_main > 0) && (is_main!==5)) {
3477 JSROOT.Painter.drawCanvas(divid, null, ((is_main == 2) || (is_main == 4)) ?
"noframe" :
"");
3478 svg_c = this.svg_canvas();
3479 this.create_canvas =
true;
3482 if (svg_c.empty()) {
3483 if ((is_main < 0) || (is_main===5) || this.iscan)
return;
3484 this.AccessTopPainter(
true);
3489 this.pad_name = pad_name;
3490 if (this.pad_name === undefined)
3491 this.pad_name = this.CurrentPadName();
3493 if (is_main < 0)
return;
3496 if (this.svg_frame().select(
".main_layer").empty() && ((is_main == 1) || (is_main == 3) || (is_main == 4))) {
3497 if (typeof JSROOT.Painter.drawFrame ==
'function')
3498 JSROOT.Painter.drawFrame(divid, null, (is_main == 4) ?
"3d" :
"");
3499 if ((is_main != 4) && this.svg_frame().empty())
return alert(
"Fail to draw dummy TFrame");
3502 var svg_p = this.svg_pad();
3503 if (svg_p.empty())
return;
3505 var pp = svg_p.property(
'pad_painter');
3506 if (pp && (pp !==
this))
3507 pp.painters.push(
this);
3509 if (((is_main === 1) || (is_main === 4) || (is_main === 5)) && !svg_p.property(
'mainpainter'))
3511 svg_p.property(
'mainpainter',
this);
3516 TObjectPainter.prototype.CalcAbsolutePosition =
function(sel, pos) {
3517 while (!sel.empty() && !sel.classed(
'root_canvas')) {
3518 var cl = sel.attr(
"class");
3519 if (cl && ((cl.indexOf(
"root_frame")>=0) || (cl.indexOf(
"__root_pad_")>=0))) {
3520 pos.x += sel.property(
"draw_x") || 0;
3521 pos.y += sel.property(
"draw_y") || 0;
3523 sel = d3.select(sel.node().parentNode);
3536 TObjectPainter.prototype.createAttMarker =
function(args) {
3537 if (!args || (typeof args !==
'object')) args = { std:
true };
else
3538 if (args.fMarkerColor!==undefined && args.fMarkerStyle!==undefined && args.fMarkerSize!==undefined) args = { attr: args, std:
false };
3540 if (args.std === undefined) args.std =
true;
3542 var handler = args.std ? this.markeratt : null;
3544 if (!handler) handler =
new TAttMarkerHandler(args);
3545 else if (!handler.changed || args.force) handler.SetArgs(args);
3547 if (args.std) this.markeratt = handler;
3561 TObjectPainter.prototype.createAttLine =
function(args) {
3562 if (!args || (typeof args !==
'object')) args = { std:
true };
else
3563 if (args.fLineColor!==undefined && args.fLineStyle!==undefined && args.fLineWidth!==undefined) args = { attr: args, std:
false };
3565 if (args.std === undefined) args.std =
true;
3567 var handler = args.std ? this.lineatt : null;
3569 if (!handler) handler =
new TAttLineHandler(args);
3570 else if (!handler.changed || args.force) handler.SetArgs(args);
3572 if (args.std) this.lineatt = handler;
3594 TObjectPainter.prototype.createAttFill =
function(args) {
3595 if (!args || (typeof args !==
'object')) args = { std:
true };
else
3596 if (args._typename && args.fFillColor!==undefined && args.fFillStyle!==undefined) args = { attr: args, std:
false };
3598 if (args.std === undefined) args.std =
true;
3600 var handler = args.std ? this.fillatt : null;
3602 if (!args.svg) args.svg = this.svg_canvas();
3604 if (!handler) handler =
new TAttFillHandler(args);
3605 else if (!handler.changed || args.force) handler.SetArgs(args);
3607 if (args.std) this.fillatt = handler;
3616 TObjectPainter.prototype.ForEachPainter =
function(userfunc, kind) {
3620 var painter = this.AccessTopPainter();
3622 if (kind !==
"pads") userfunc(painter);
3627 var pp = this.pad_painter();
3628 if (pp) pp.ForEachPainterInPad(userfunc, kind);
3634 TObjectPainter.prototype.InteractiveRedraw =
function(arg, info, subelem) {
3638 }
else if (arg ==
"axes") {
3639 var main = this.main_painter(
true, this.this_pad_name);
3640 if (main && (typeof main.DrawAxes ==
'function'))
3644 }
else if (arg !==
false) {
3649 var pp = this.pad_painter();
3650 if (pp && (typeof pp.InteractiveObjectRedraw ==
'function'))
3651 pp.InteractiveObjectRedraw(
this);
3654 var canp = this.canv_painter();
3655 if (canp && (typeof canp.ProcessChanges ==
'function'))
3656 canp.ProcessChanges(info,
this, subelem);
3660 TObjectPainter.prototype.RedrawPad =
function() {
3661 var pad_painter = this.pad_painter();
3662 if (pad_painter) pad_painter.Redraw();
3667 TObjectPainter.prototype.SwitchTooltip =
function(on) {
3668 var fp = this.frame_painter();
3669 if (fp) fp.ProcessTooltipEvent(null, on);
3671 if (this.control && (typeof this.control.SwitchTooltip ==
'function'))
3672 this.control.SwitchTooltip(on);
3676 TObjectPainter.prototype.AddMove =
function() {
3678 if (!JSROOT.gStyle.MoveResize || JSROOT.BatchMode ||
3679 !
this.draw_g ||
this.draw_g.property(
"assigned_move"))
return;
3681 function detectRightButton(event) {
3682 if (
'buttons' in event)
return event.buttons === 2;
3683 else if (
'which' in event)
return event.which === 3;
3684 else if (
'button' in event)
return event.button === 2;
3688 var prefix =
"", drag_move, not_changed =
true;
3689 if (JSROOT._test_d3_ === 3) {
3691 drag_move = d3.behavior.drag().origin(Object);
3693 drag_move = d3.drag().subject(Object);
3697 .on(prefix+
"start",
function() {
3698 if (detectRightButton(d3.event.sourceEvent))
return;
3699 d3.event.sourceEvent.preventDefault();
3700 d3.event.sourceEvent.stopPropagation();
3701 var pos = d3.mouse(this.draw_g.node());
3704 this.moveStart(pos[0], pos[1]);
3705 }.bind(
this)).on(
"drag",
function() {
3706 d3.event.sourceEvent.preventDefault();
3707 d3.event.sourceEvent.stopPropagation();
3708 not_changed =
false;
3710 this.moveDrag(d3.event.dx, d3.event.dy);
3711 }.bind(
this)).on(prefix+
"end",
function() {
3712 d3.event.sourceEvent.preventDefault();
3713 d3.event.sourceEvent.stopPropagation();
3715 this.moveEnd(not_changed);
3716 var cp = this.canv_painter();
3717 if (cp) cp.SelectObjectPainter(
this);
3721 .style(
"cursor",
"move")
3722 .property(
"assigned_move",
true)
3728 TObjectPainter.prototype.AddDrag =
function(callback) {
3729 if (!JSROOT.gStyle.MoveResize || JSROOT.BatchMode)
return;
3731 var pthis =
this, drag_rect = null, pp = this.pad_painter();
3732 if (pp && pp._fast_drawing)
return;
3734 function detectRightButton(event) {
3735 if (
'buttons' in event)
return event.buttons === 2;
3736 else if (
'which' in event)
return event.which === 3;
3737 else if (
'button' in event)
return event.button === 2;
3741 function rect_width() {
return Number(pthis.draw_g.attr(
"width")); }
3742 function rect_height() {
return Number(pthis.draw_g.attr(
"height")); }
3744 function MakeResizeElements(group, width, height, handler) {
3745 function make(cursor,d) {
3746 var clname =
"js_" + cursor.replace(
'-',
'_'),
3747 elem = group.select(
'.'+clname);
3748 if (elem.empty()) elem = group.append(
'path').classed(clname,
true);
3749 elem.style(
'opacity', 0).style(
'cursor', cursor).attr(
'd',d);
3750 if (handler) elem.call(handler);
3753 make(
"nw-resize",
"M2,2h15v-5h-20v20h5Z");
3754 make(
"ne-resize",
"M" + (width-2) +
",2h-15v-5h20v20h-5 Z");
3755 make(
"sw-resize",
"M2," + (height-2) +
"h15v5h-20v-20h5Z");
3756 make(
"se-resize",
"M" + (width-2) +
"," + (height-2) +
"h-15v5h20v-20h-5Z");
3758 make(
"w-resize",
"M-3,18h5v" + Math.max(0, height - 2*18) +
"h-5Z");
3759 make(
"e-resize",
"M" + (width+3) +
",18h-5v" + Math.max(0, height - 2*18) +
"h5Z");
3760 make(
"n-resize",
"M18,-3v5h" + Math.max(0, width - 2*18) +
"v-5Z");
3761 make(
"s-resize",
"M18," + (height+3) +
"v-5h" + Math.max(0, width - 2*18) +
"v5Z");
3764 function complete_drag() {
3765 drag_rect.style(
"cursor",
"auto");
3767 if (!pthis.draw_g) {
3773 var oldx = Number(pthis.draw_g.attr(
"x")),
3774 oldy = Number(pthis.draw_g.attr(
"y")),
3775 newx = Number(drag_rect.attr(
"x")),
3776 newy = Number(drag_rect.attr(
"y")),
3777 newwidth = Number(drag_rect.attr(
"width")),
3778 newheight = Number(drag_rect.attr(
"height"));
3780 if (callback.minwidth && newwidth < callback.minwidth) newwidth = callback.minwidth;
3781 if (callback.minheight && newheight < callback.minheight) newheight = callback.minheight;
3783 var change_size = (newwidth !== rect_width()) || (newheight !== rect_height()),
3784 change_pos = (newx !== oldx) || (newy !== oldy);
3786 pthis.draw_g.attr(
'x', newx).attr(
'y', newy)
3787 .attr(
"transform",
"translate(" + newx +
"," + newy +
")")
3788 .attr(
'width', newwidth).attr(
'height', newheight);
3793 pthis.SwitchTooltip(
true);
3795 MakeResizeElements(pthis.draw_g, newwidth, newheight);
3797 if (change_size || change_pos) {
3798 if (change_size && (
'resize' in callback)) callback.resize(newwidth, newheight);
3799 if (change_pos && (
'move' in callback)) callback.move(newx, newy, newx - oldxx, newy-oldy);
3801 if (change_size || change_pos) {
3802 if (
'obj' in callback) {
3803 callback.obj.fX1NDC = newx / pthis.pad_width();
3804 callback.obj.fX2NDC = (newx + newwidth) / pthis.pad_width();
3805 callback.obj.fY1NDC = 1 - (newy + newheight) / pthis.pad_height();
3806 callback.obj.fY2NDC = 1 - newy / pthis.pad_height();
3807 callback.obj.modified_NDC =
true;
3809 if (
'redraw' in callback) callback.redraw();
3813 return change_size || change_pos;
3816 var prefix =
"", drag_move, drag_resize;
3817 if (JSROOT._test_d3_ === 3) {
3819 drag_move = d3.behavior.drag().origin(Object);
3820 drag_resize = d3.behavior.drag().origin(Object);
3822 drag_move = d3.drag().subject(Object);
3823 drag_resize = d3.drag().subject(Object);
3827 .on(prefix+
"start",
function() {
3828 if (detectRightButton(d3.event.sourceEvent))
return;
3830 JSROOT.Painter.closeMenu();
3832 pthis.SwitchTooltip(
false);
3834 d3.event.sourceEvent.preventDefault();
3835 d3.event.sourceEvent.stopPropagation();
3838 acc_x1: Number(pthis.draw_g.attr(
"x")),
3839 acc_y1: Number(pthis.draw_g.attr(
"y")),
3840 pad_w: pthis.pad_width() - rect_width(),
3841 pad_h: pthis.pad_height() - rect_height(),
3845 drag_rect = d3.select(pthis.draw_g.node().parentNode).append(
"rect")
3846 .classed(
"zoom",
true)
3847 .attr(
"x", handle.acc_x1)
3848 .attr(
"y", handle.acc_y1)
3849 .attr(
"width", rect_width())
3850 .attr(
"height", rect_height())
3851 .style(
"cursor",
"move")
3852 .style(
"pointer-events",
"none")
3853 .property(
'drag_handle', handle);
3856 }).on(
"drag",
function() {
3857 if (!drag_rect)
return;
3859 d3.event.sourceEvent.preventDefault();
3860 d3.event.sourceEvent.stopPropagation();
3862 var handle = drag_rect.property(
'drag_handle');
3864 handle.acc_x1 += d3.event.dx;
3865 handle.acc_y1 += d3.event.dy;
3867 drag_rect.attr(
"x", Math.min( Math.max(handle.acc_x1, 0), handle.pad_w))
3868 .attr(
"y", Math.min( Math.max(handle.acc_y1, 0), handle.pad_h));
3870 }).on(prefix+
"end",
function() {
3871 if (!drag_rect)
return;
3873 d3.event.sourceEvent.preventDefault();
3875 var handle = drag_rect.property(
'drag_handle');
3877 if (complete_drag() ===
false) {
3878 var spent = (
new Date()).getTime() - handle.drag_tm.getTime();
3879 if (callback.ctxmenu && (spent > 600)) {
3880 var rrr = resize_se.node().getBoundingClientRect();
3881 pthis.ShowContextMenu(
'main', { clientX: rrr.left, clientY: rrr.top } );
3882 }
else if (callback.canselect && (spent <= 600)) {
3883 pthis.canv_painter().SelectObjectPainter(pthis);
3889 .on(prefix+
"start",
function() {
3890 if (detectRightButton(d3.event.sourceEvent))
return;
3892 d3.event.sourceEvent.stopPropagation();
3893 d3.event.sourceEvent.preventDefault();
3895 pthis.SwitchTooltip(
false);
3898 acc_x1: Number(pthis.draw_g.attr(
"x")),
3899 acc_y1: Number(pthis.draw_g.attr(
"y")),
3900 pad_w: pthis.pad_width(),
3901 pad_h: pthis.pad_height()
3904 handle.acc_x2 = handle.acc_x1 + rect_width();
3905 handle.acc_y2 = handle.acc_y1 + rect_height();
3907 drag_rect = d3.select(pthis.draw_g.node().parentNode)
3909 .classed(
"zoom",
true)
3910 .style(
"cursor", d3.select(
this).style(
"cursor"))
3911 .attr(
"x", handle.acc_x1)
3912 .attr(
"y", handle.acc_y1)
3913 .attr(
"width", handle.acc_x2 - handle.acc_x1)
3914 .attr(
"height", handle.acc_y2 - handle.acc_y1)
3915 .property(
'drag_handle', handle);
3917 }).on(
"drag",
function() {
3918 if (!drag_rect)
return;
3920 d3.event.sourceEvent.preventDefault();
3921 d3.event.sourceEvent.stopPropagation();
3923 var handle = drag_rect.property(
'drag_handle'),
3924 dx = d3.event.dx, dy = d3.event.dy, elem = d3.select(
this);
3926 if (elem.classed(
'js_nw_resize')) { handle.acc_x1 += dx; handle.acc_y1 += dy; }
3927 else if (elem.classed(
'js_ne_resize')) { handle.acc_x2 += dx; handle.acc_y1 += dy; }
3928 else if (elem.classed(
'js_sw_resize')) { handle.acc_x1 += dx; handle.acc_y2 += dy; }
3929 else if (elem.classed(
'js_se_resize')) { handle.acc_x2 += dx; handle.acc_y2 += dy; }
3930 else if (elem.classed(
'js_w_resize')) { handle.acc_x1 += dx; }
3931 else if (elem.classed(
'js_n_resize')) { handle.acc_y1 += dy; }
3932 else if (elem.classed(
'js_e_resize')) { handle.acc_x2 += dx; }
3933 else if (elem.classed(
'js_s_resize')) { handle.acc_y2 += dy; }
3935 var x1 = Math.max(0, handle.acc_x1), x2 = Math.min(handle.acc_x2, handle.pad_w),
3936 y1 = Math.max(0, handle.acc_y1), y2 = Math.min(handle.acc_y2, handle.pad_h);
3938 drag_rect.attr(
"x", x1).attr(
"y", y1).attr(
"width", Math.max(0, x2-x1)).attr(
"height", Math.max(0, y2-y1));
3940 }).on(prefix+
"end",
function() {
3941 if (!drag_rect)
return;
3943 d3.event.sourceEvent.preventDefault();
3948 if (!callback.only_resize)
3949 this.draw_g.style(
"cursor",
"move").call(drag_move);
3951 MakeResizeElements(this.draw_g, rect_width(), rect_height(), drag_resize);
3956 TObjectPainter.prototype.startTouchMenu =
function(kind) {
3959 var arr = d3.touches(this.svg_frame().node());
3960 if (arr.length != 1)
return;
3962 if (!kind || (kind==
"")) kind =
"main";
3963 var fld =
"touch_" + kind;
3965 d3.event.preventDefault();
3966 d3.event.stopPropagation();
3968 this[fld] = { dt:
new Date(), pos: arr[0] };
3970 this.svg_frame().on(
"touchcancel", this.endTouchMenu.bind(
this, kind))
3971 .on(
"touchend", this.endTouchMenu.bind(
this, kind));
3976 TObjectPainter.prototype.endTouchMenu =
function(kind) {
3977 var fld =
"touch_" + kind;
3979 if (! (fld in
this))
return;
3981 d3.event.preventDefault();
3982 d3.event.stopPropagation();
3984 var diff =
new Date().getTime() -
this[fld].dt.getTime();
3986 this.svg_frame().on(
"touchcancel", null)
3987 .on(
"touchend", null);
3990 var rect = this.svg_frame().node().getBoundingClientRect();
3991 this.ShowContextMenu(kind, { clientX: rect.left +
this[fld].pos[0],
3992 clientY: rect.top +
this[fld].pos[1] } );
4000 TObjectPainter.prototype.AddColorMenuEntry =
function(menu, name, value, set_func, fill_kind) {
4001 if (value === undefined)
return;
4002 menu.add(
"sub:"+name,
function() {
4004 var useid = (typeof value !==
'string');
4005 var col = prompt(
"Enter color " + (useid ?
"(only id number)" :
"(name or id)"), value);
4006 if (col == null)
return;
4007 var
id = parseInt(col);
4008 if (!isNaN(
id) && (JSROOT.Painter.root_colors[
id] !== undefined)) {
4009 col = JSROOT.Painter.root_colors[id];
4013 set_func.bind(
this)(useid ?
id : col);
4015 var useid = (typeof value !==
'string');
4016 for (var n=-1;n<11;++n) {
4017 if ((n<0) && useid)
continue;
4018 if ((n==10) && (fill_kind!==1))
continue;
4019 var col = (n<0) ?
'none' : JSROOT.Painter.root_colors[n];
4020 if ((n==0) && (fill_kind==1)) col =
'none';
4021 var svg =
"<svg width='100' height='18' style='margin:0px;background-color:" + col +
"'><text x='4' y='12' style='font-size:12px' fill='" + (n==1 ?
"white" :
"black") +
"'>"+col+
"</text></svg>";
4022 menu.addchk((value == (useid ? n : col)), svg, (useid ? n : col), set_func);
4024 menu.add(
"endsub:");
4029 TObjectPainter.prototype.AddSizeMenuEntry =
function(menu, name, min, max, step, value, set_func) {
4030 if (value === undefined)
return;
4032 menu.add(
"sub:"+name,
function() {
4034 var entry = value.toFixed(4);
4035 if (step>=0.1) entry = value.toFixed(2);
4036 if (step>=1) entry = value.toFixed(0);
4037 var val = prompt(
"Enter value of " + name, entry);
4038 if (val==null)
return;
4039 var val = parseFloat(val);
4040 if (!isNaN(val)) set_func.bind(
this)((step>=1) ? Math.round(val) : val);
4042 for (var val=min;val<=max;val+=step) {
4043 var entry = val.toFixed(2);
4044 if (step>=0.1) entry = val.toFixed(1);
4045 if (step>=1) entry = val.toFixed(0);
4046 menu.addchk((Math.abs(value - val) < step/2), entry, val, set_func);
4048 menu.add(
"endsub:");
4053 TObjectPainter.prototype.ExecuteMenuCommand =
function(method) {
4055 if (method.fName ==
"Inspect") {
4057 this.ShowInspector();
4061 var canvp = this.canv_painter();
4062 if (!canvp)
return false;
4074 TObjectPainter.prototype.WebCanvasExec =
function(exec, snapid) {
4075 if (!exec || (typeof exec !=
'string'))
return;
4077 if (!snapid) snapid = this.snapid;
4078 if (!snapid || (typeof snapid !=
'string'))
return;
4080 var canp = this.canv_painter();
4081 if (canp && !canp._readonly && canp._websocket)
4082 canp.SendWebsocket(
"OBJEXEC:" + snapid +
":" + exec);
4087 TObjectPainter.prototype.FillObjectExecMenu =
function(menu, kind, call_back) {
4089 var canvp = this.canv_painter();
4091 if (!this.snapid || !canvp || canvp._readonly || !canvp._websocket || canvp._getmenu_callback)
4092 return JSROOT.CallBack(call_back);
4094 function DoExecMenu(arg) {
4095 var execp = this.exec_painter ||
this,
4096 cp = execp.canv_painter(),
4097 item = execp.args_menu_items[parseInt(arg)];
4099 if (!item || !item.fName)
return;
4102 if (item.fExec ==
"Show:Editor") {
4103 if (cp && (typeof cp.ActivateGed ==
'function'))
4104 cp.ActivateGed(execp);
4108 if (cp && (typeof cp.executeObjectMethod ==
'function'))
4109 if (cp.executeObjectMethod(execp, item, execp.args_menu_id))
return;
4111 if (execp.ExecuteMenuCommand(item))
return;
4113 if (execp.args_menu_id)
4114 execp.WebCanvasExec(item.fExec, execp.args_menu_id);
4117 function DoFillMenu(_menu, _reqid, _call_back, reply) {
4120 if (!canvp._getmenu_callback)
return;
4121 delete canvp._getmenu_callback;
4123 if (reply && (_reqid !== reply.fId))
4124 console.error(
'missmatch between request ' + _reqid +
' and reply ' + reply.fId +
' identifiers');
4126 var items = reply ? reply.fItems : null;
4128 if (items && items.length) {
4129 _menu.add(
"separator");
4131 this.args_menu_items = items;
4132 this.args_menu_id = reply.fId;
4136 for (var n=0;n<items.length;++n) {
4137 var item = items[n];
4139 if (item.fClassName && lastclname && (lastclname!=item.fClassName)) {
4140 _menu.add(
"endsub:");
4143 if (lastclname != item.fClassName) {
4144 lastclname = item.fClassName;
4145 _menu.add(
"sub:" + lastclname);
4148 if ((item.fChecked === undefined) || (item.fChecked < 0))
4149 _menu.add(item.fName, n, DoExecMenu);
4151 _menu.addchk(item.fChecked, item.fName, n, DoExecMenu);
4154 if (lastclname) _menu.add(
"endsub:");
4157 JSROOT.CallBack(_call_back);
4160 var reqid = this.snapid;
4161 if (kind) reqid +=
"#" + kind;
4165 menu.painter.exec_painter = (menu.painter !==
this) ?
this : undefined;
4167 canvp._getmenu_callback = DoFillMenu.bind(
this, menu, reqid, call_back);
4169 canvp.SendWebsocket(
'GETMENU:' + reqid);
4171 setTimeout(canvp._getmenu_callback, 2000);
4176 TObjectPainter.prototype.DeleteAtt =
function() {
4177 delete this.lineatt;
4178 delete this.fillatt;
4179 delete this.markeratt;
4186 TObjectPainter.prototype.GetColorExec =
function(col, method) {
4187 var
id = -1, arr = JSROOT.Painter.root_colors;
4188 if (typeof col ==
"string") {
4189 if (!col || (col ==
"none"))
id = 0;
else
4190 for (var k=1;k<arr.length;++k)
4191 if (arr[k] == col) {
id = k;
break; }
4192 if ((
id < 0) && (col.indexOf(
"rgb")==0))
id = 9999;
4193 }
else if (!isNaN(col) && arr[col]) {
4198 if (
id < 0)
return "";
4202 var c = d3.color(col);
4203 id =
"TColor::GetColor(" + c.r +
"," + c.g +
"," + c.b +
")";
4206 return "exec:" + method +
"(" +
id +
")";
4211 TObjectPainter.prototype.FillAttContextMenu =
function(menu, preffix) {
4216 if (!preffix) preffix =
"";
4218 if (this.lineatt && this.lineatt.used) {
4219 menu.add(
"sub:"+preffix+
"Line att");
4220 this.AddSizeMenuEntry(menu,
"width", 1, 10, 1, this.lineatt.width,
4221 function(arg) {
this.lineatt.Change(undefined, parseInt(arg)); this.InteractiveRedraw(
true,
"exec:SetLineWidth(" + arg +
")"); }.bind(
this));
4222 this.AddColorMenuEntry(menu,
"color", this.lineatt.color,
4223 function(arg) {
this.lineatt.Change(arg); this.InteractiveRedraw(
true, this.GetColorExec(arg,
"SetLineColor")); }.bind(
this));
4224 menu.add(
"sub:style",
function() {
4225 var
id = prompt(
"Enter line style id (1-solid)", 1);
4226 if (
id == null)
return;
4228 if (isNaN(
id) || !JSROOT.Painter.root_line_styles[
id])
return;
4229 this.lineatt.Change(undefined, undefined,
id);
4230 this.InteractiveRedraw(
true,
"exec:SetLineStyle(" +
id +
")");
4232 for (var n=1;n<11;++n) {
4234 var dash = JSROOT.Painter.root_line_styles[n];
4236 var svg =
"<svg width='100' height='18'><text x='1' y='12' style='font-size:12px'>" + n +
"</text><line x1='30' y1='8' x2='100' y2='8' stroke='black' stroke-width='3' stroke-dasharray='" + dash +
"'></line></svg>";
4238 menu.addchk((this.lineatt.style==n), svg, n,
function(arg) {
this.lineatt.Change(undefined, undefined, parseInt(arg)); this.InteractiveRedraw(
true,
"exec:SetLineStyle(" + arg +
")"); }.bind(
this));
4240 menu.add(
"endsub:");
4241 menu.add(
"endsub:");
4243 if ((
'excl_side' in this.lineatt) && (this.lineatt.excl_side!==0)) {
4244 menu.add(
"sub:Exclusion");
4245 menu.add(
"sub:side");
4246 for (var side=-1;side<=1;++side)
4247 menu.addchk((
this.lineatt.excl_side==side), side, side,
function(arg) {
4248 this.lineatt.ChangeExcl(parseInt(arg));
4249 this.InteractiveRedraw();
4251 menu.add(
"endsub:");
4253 this.AddSizeMenuEntry(menu,
"width", 10, 100, 10, this.lineatt.excl_width,
4254 function(arg) {
this.lineatt.ChangeExcl(undefined, parseInt(arg)); this.InteractiveRedraw(); }.bind(
this));
4256 menu.add(
"endsub:");
4260 if (this.fillatt && this.fillatt.used) {
4261 menu.add(
"sub:"+preffix+
"Fill att");
4262 this.AddColorMenuEntry(menu,
"color", this.fillatt.colorindx,
4263 function(arg) {
this.fillatt.Change(parseInt(arg), undefined, this.svg_canvas()); this.InteractiveRedraw(
true, this.GetColorExec(parseInt(arg),
"SetFillColor")); }.bind(
this), this.fillatt.kind);
4264 menu.add(
"sub:style",
function() {
4265 var
id = prompt(
"Enter fill style id (1001-solid, 3000..3010)", this.fillatt.pattern);
4266 if (
id == null)
return;
4268 if (isNaN(
id))
return;
4269 this.fillatt.Change(undefined,
id, this.svg_canvas());
4270 this.InteractiveRedraw(
true,
"exec:SetFillStyle(" +
id +
")");
4273 var supported = [1, 1001, 3001, 3002, 3003, 3004, 3005, 3006, 3007, 3010, 3021, 3022];
4275 for (var n=0; n<supported.length; ++n) {
4277 var sample = this.createAttFill({ std:
false, pattern: supported[n], color: this.fillatt.colorindx || 1 }),
4278 svg =
"<svg width='100' height='18'><text x='1' y='12' style='font-size:12px'>" + supported[n].toString() +
"</text><rect x='40' y='0' width='60' height='18' stroke='none' fill='" + sample.fillcolor() +
"'></rect></svg>";
4280 menu.addchk(this.fillatt.pattern == supported[n], svg, supported[n],
function(arg) {
4281 this.fillatt.Change(undefined, parseInt(arg), this.svg_canvas());
4282 this.InteractiveRedraw(
true,
"exec:SetFillStyle(" + arg +
")");
4285 menu.add(
"endsub:");
4286 menu.add(
"endsub:");
4289 if (this.markeratt && this.markeratt.used) {
4290 menu.add(
"sub:"+preffix+
"Marker att");
4291 this.AddColorMenuEntry(menu,
"color", this.markeratt.color,
4292 function(arg) {
this.markeratt.Change(arg); this.InteractiveRedraw(
true, this.GetColorExec(arg,
"SetMarkerColor")); }.bind(
this));
4293 this.AddSizeMenuEntry(menu,
"size", 0.5, 6, 0.5, this.markeratt.size,
4294 function(arg) {
this.markeratt.Change(undefined, undefined, parseFloat(arg)); this.InteractiveRedraw(
true,
"exec:SetMarkerSize(" + parseInt(arg) +
")"); }.bind(
this));
4296 menu.add(
"sub:style");
4297 var supported = [1,2,3,4,5,6,7,8,21,22,23,24,25,26,27,28,29,30,31,32,33,34];
4299 for (var n=0; n<supported.length; ++n) {
4301 var clone =
new TAttMarkerHandler({ style: supported[n], color: this.markeratt.color, size: 1.7 }),
4302 svg =
"<svg width='60' height='18'><text x='1' y='12' style='font-size:12px'>" + supported[n].toString() +
"</text><path stroke='black' fill='" + (clone.fill ?
"black" :
"none") +
"' d='" + clone.create(40,8) +
"'></path></svg>";
4304 menu.addchk(this.markeratt.style == supported[n], svg, supported[n],
4305 function(arg) {
this.markeratt.Change(undefined, parseInt(arg)); this.InteractiveRedraw(
true,
"exec:SetMarkerStyle(" + arg +
")"); }.bind(
this));
4307 menu.add(
"endsub:");
4308 menu.add(
"endsub:");
4314 TObjectPainter.prototype.TextAttContextMenu =
function(menu, prefix) {
4317 var obj = this.GetObject();
4318 if (!obj || !(
'fTextColor' in obj))
return;
4320 menu.add(
"sub:" + (prefix ? prefix :
"Text"));
4321 this.AddColorMenuEntry(menu,
"color", obj.fTextColor,
4322 function(arg) {
this.GetObject().fTextColor = parseInt(arg); this.InteractiveRedraw(
true, this.GetColorExec(parseInt(arg),
"SetTextColor")); }.bind(
this));
4324 var align = [11, 12, 13, 21, 22, 23, 31, 32, 33],
4325 hnames = [
'left',
'centered' ,
'right'],
4326 vnames = [
'bottom',
'centered',
'top'];
4328 menu.add(
"sub:align");
4329 for (var n=0; n<align.length; ++n) {
4330 menu.addchk(align[n] == obj.fTextAlign,
4333 function(arg) {
this.GetObject().fTextAlign = parseInt(arg); this.InteractiveRedraw(
true,
"exec:SetTextAlign("+arg+
")"); }.bind(
this));
4335 menu.add(
"endsub:");
4337 menu.add(
"sub:font");
4338 for (var n=1; n<16; ++n) {
4339 menu.addchk(n == Math.floor(obj.fTextFont/10), n, n,
4340 function(arg) { this.GetObject().fTextFont = parseInt(arg)*10+2; this.InteractiveRedraw(
true,
"exec:SetTextFont("+this.GetObject().fTextFont+
")"); }.bind(
this));
4342 menu.add(
"endsub:");
4344 menu.add(
"endsub:");
4348 TObjectPainter.prototype.ShowInspector =
function(obj) {
4349 var main = this.select_main(),
4350 rect = this.get_visible_rect(main),
4351 w = Math.round(rect.width*0.05) +
"px",
4352 h = Math.round(rect.height*0.05) +
"px",
4353 id =
"root_inspector_" + JSROOT.id_counter++,
4354 cont = main.append(
"div")
4356 .attr(
"class",
"jsroot_inspector")
4357 .style(
'position',
'absolute')
4363 if (!obj || (typeof obj !==
'object') || !obj._typename)
4364 obj = this.GetObject();
4366 JSROOT.draw(
id, obj,
'inspect');
4371 TObjectPainter.prototype.FillContextMenu =
function(menu) {
4372 var title = this.GetTipName();
4373 if (this.GetObject() && (
'_typename' in this.GetObject()))
4374 title = this.GetObject()._typename +
"::" + title;
4376 menu.add(
"header:"+ title);
4378 this.FillAttContextMenu(menu);
4380 if (menu.size() > 0)
4381 menu.add(
'Inspect',
this.ShowInspector);
4383 return menu.size() > 0;
4388 TObjectPainter.prototype.GetShowStatusFunc =
function() {
4392 var pp = this.canv_painter(), res = JSROOT.Painter.ShowStatus;
4394 if (pp && (typeof pp.ShowCanvasStatus ===
'function')) res = pp.ShowCanvasStatus.bind(pp);
4396 if (res && (this.enlarge_main(
'state')===
'on')) res = null;
4403 TObjectPainter.prototype.ShowObjectStatus =
function() {
4406 var obj = this.GetObject(),
4407 status_func = this.GetShowStatusFunc();
4409 if (obj && status_func) status_func(this.GetItemName() || obj.fName, obj.fTitle || obj._typename, obj._typename);
4416 TObjectPainter.prototype.FindInPrimitives =
function(objname) {
4418 var painter = this.pad_painter();
4419 if (!painter || !painter.pad)
return null;
4421 if (painter.pad.fPrimitives)
4422 for (var n=0;n<painter.pad.fPrimitives.arr.length;++n) {
4423 var prim = painter.pad.fPrimitives.arr[n];
4424 if ((
'fName' in prim) && (prim.fName === objname))
return prim;
4434 TObjectPainter.prototype.FindPainterFor =
function(selobj,selname,seltype) {
4436 var painter = this.pad_painter();
4437 var painters = painter ? painter.painters : null;
4438 if (!painters)
return null;
4440 for (var n = 0; n < painters.length; ++n) {
4441 var pobj = painters[n].GetObject();
4442 if (!pobj)
continue;
4444 if (selobj && (pobj === selobj))
return painters[n];
4445 if (!selname && !seltype)
continue;
4446 if (selname && (pobj.fName !== selname))
continue;
4447 if (seltype && (pobj._typename !== seltype))
continue;
4455 TObjectPainter.prototype.DeleteThis =
function() {
4456 var pp = this.pad_painter();
4458 var k = pp.painters.indexOf(
this);
4459 if (k>=0) pp.painters.splice(k,1);
4472 TObjectPainter.prototype.ConfigureUserTooltipCallback =
function(call_back, user_timeout) {
4474 if (!call_back || (typeof call_back !==
'function')) {
4475 delete this.UserTooltipCallback;
4476 delete this.UserTooltipTimeout;
4480 if (user_timeout===undefined) user_timeout = 500;
4482 this.UserTooltipCallback = call_back;
4483 this.UserTooltipTimeout = user_timeout;
4493 TObjectPainter.prototype.ConfigureUserClickHandler =
function(handler) {
4494 var fp = this.frame_painter();
4495 if (fp && typeof fp.ConfigureUserClickHandler ==
'function')
4496 fp.ConfigureUserClickHandler(handler);
4506 TObjectPainter.prototype.ConfigureUserDblclickHandler =
function(handler) {
4507 var fp = this.frame_painter();
4508 if (fp && typeof fp.ConfigureUserDblclickHandler ==
'function')
4509 fp.ConfigureUserDblclickHandler(handler);
4515 TObjectPainter.prototype.IsUserTooltipCallback =
function() {
4516 return typeof this.UserTooltipCallback ==
'function';
4522 TObjectPainter.prototype.ProvideUserTooltip =
function(data) {
4524 if (!this.IsUserTooltipCallback())
return;
4526 if (this.UserTooltipTimeout <= 0)
4527 return this.UserTooltipCallback(data);
4529 if (typeof this.UserTooltipTHandle !=
'undefined') {
4530 clearTimeout(this.UserTooltipTHandle);
4531 delete this.UserTooltipTHandle;
4535 return this.UserTooltipCallback(data);
4537 this.UserTooltipTHandle = setTimeout(
function(d) {
4539 delete this.UserTooltipTHandle;
4540 this.UserTooltipCallback(d);
4541 }.bind(
this, data), this.UserTooltipTimeout);
4551 TObjectPainter.prototype.Redraw =
function() {
4558 TObjectPainter.prototype.StartTextDrawing =
function(font_face, font_size, draw_g, max_font_size) {
4561 if (!draw_g) draw_g = this.draw_g;
4563 var font = (font_size===
'font') ? font_face : JSROOT.Painter.getFontDetails(font_face, font_size);
4565 var pp = this.pad_painter();
4567 draw_g.call(font.func);
4569 draw_g.property(
'draw_text_completed',
false)
4570 .property(
'text_font', font)
4571 .property(
'mathjax_use',
false)
4572 .property(
'text_factor', 0.)
4573 .property(
'max_text_width', 0)
4574 .property(
'max_font_size', max_font_size)
4575 .property(
"_fast_drawing", pp && pp._fast_drawing);
4577 if (draw_g.property(
"_fast_drawing"))
4578 draw_g.property(
"_font_too_small", (max_font_size && (max_font_size<5)) || (font.size < 4));
4583 TObjectPainter.prototype.TextScaleFactor =
function(value, draw_g) {
4584 if (!draw_g) draw_g = this.draw_g;
4585 if (value && (value > draw_g.property(
'text_factor'))) draw_g.property(
'text_factor', value);
4592 TObjectPainter.prototype.GetBoundarySizes =
function(elem) {
4593 if (elem===null) { console.warn(
'empty node in GetBoundarySizes');
return { width:0, height:0 }; }
4594 var box = elem.getBoundingClientRect();
4595 if (parseFloat(box.width) > 0) box = elem.getBBox();
4596 var res = { width : parseInt(box.width), height : parseInt(box.height) };
4597 if (
'left' in box) { res.x = parseInt(box.left); res.y = parseInt(box.right); }
else
4598 if (
'x' in box) { res.x = parseInt(box.x); res.y = parseInt(box.y); }
4606 TObjectPainter.prototype.FinishTextDrawing =
function(draw_g, call_ready) {
4607 if (!draw_g) draw_g = this.draw_g;
4609 if (draw_g.property(
'draw_text_completed')) {
4610 JSROOT.CallBack(call_ready);
4611 return draw_g.property(
'max_text_width');
4614 if (call_ready) draw_g.node().text_callback = call_ready;
4618 if (draw_g.property(
'mathjax_use')) {
4621 svgs = draw_g.selectAll(
".math_svg");
4623 svgs.each(
function() {
4624 var fo_g = d3.select(
this);
4625 if (fo_g.node().parentNode !== draw_g.node())
return;
4626 if (fo_g.select(
"svg").empty()) missing++;
4630 if (missing)
return;
4647 f = draw_g.property(
'text_factor'),
4648 font = draw_g.property(
'text_font'),
4649 max_sz = draw_g.property(
'max_font_size'),
4650 font_size = font.size;
4652 if ((f > 0) && ((f < 0.9) || (f > 1)))
4653 font.size = Math.floor(font.size/f);
4655 if (max_sz && (font.size > max_sz))
4658 if (font.size != font_size) {
4659 draw_g.call(font.func);
4660 font_size = font.size;
4665 svgs.each(
function() {
4666 var fo_g = d3.select(
this);
4667 if (fo_g.node().parentNode !== draw_g.node())
return;
4669 var vvv = fo_g.select(
"svg");
4671 console.log(
'MathJax SVG ouptut error');
4675 function transform(value) {
4676 if (!value || (typeof value !==
"string"))
return null;
4677 if (value.indexOf(
"ex")!==value.length-2)
return null;
4678 value = parseFloat(value.substr(0, value.length-2));
4679 return isNaN(value) ? null : value*font_size*0.5;
4682 var width = transform(vvv.attr(
"width")),
4683 height = transform(vvv.attr(
"height")),
4684 valign = vvv.attr(
"style");
4686 if (valign && valign.indexOf(
"vertical-align:")==0 && valign.indexOf(
"ex;")==valign.length-3) {
4687 valign = transform(valign.substr(16, valign.length-17));
4692 width = (!width || (width<=0.5)) ? 1 : Math.round(width);
4693 height = (!height || (height<=0.5)) ? 1 : Math.round(height);
4695 vvv.attr(
"width", width).attr(
'height', height).attr(
"style",null);
4697 if (!JSROOT.nodejs) {
4698 var box = painter.GetBoundarySizes(fo_g.node());
4699 width = 1.05*box.width; height = 1.05*box.height;
4702 var arg = fo_g.property(
"_arg");
4704 arg.valign = valign;
4707 svg_factor = Math.max(svg_factor, width / arg.width, height / arg.height);
4711 svgs.each(
function() {
4712 var fo_g = d3.select(
this);
4714 if (fo_g.node().parentNode !== draw_g.node())
return;
4716 var arg = fo_g.property(
"_arg"),
4717 m = fo_g.select(
"svg"),
4718 mw = parseInt(m.attr(
"width")),
4719 mh = parseInt(m.attr(
"height"));
4721 if (!isNaN(mh) && !isNaN(mw)) {
4722 if (svg_factor > 0.) {
4725 m.attr(
"width", Math.round(mw)).attr(
"height", Math.round(mh));
4728 var box = painter.GetBoundarySizes(fo_g.node());
4729 mw = box.width || mw || 100;
4730 mh = box.height || mh || 10;
4733 if ((svg_factor > 0.) && arg.valign) arg.valign = arg.valign/svg_factor;
4735 if (arg.valign===null) arg.valign = (font_size - mh)/2;
4737 var sign = { x:1, y:1 }, nx =
"x", ny =
"y";
4738 if (arg.rotate == 180) { sign.x = sign.y = -1; }
else
4739 if ((arg.rotate == 270) || (arg.rotate == 90)) {
4740 sign.x = (arg.rotate == 270) ? -1 : 1;
4745 if (arg.align[0] ==
'middle') arg[nx] += sign.x*(arg.width - mw)/2;
else
4746 if (arg.align[0] ==
'end') arg[nx] += sign.x*(arg.width - mw);
4748 if (arg.align[1] ==
'middle') arg[ny] += sign.y*(arg.height - mh)/2;
else
4749 if (arg.align[1] ==
'bottom') arg[ny] += sign.y*(arg.height - mh);
else
4750 if (arg.align[1] ==
'bottom-base') arg[ny] += sign.y*(arg.height - mh - arg.valign);
4752 var trans =
"translate("+arg.x+
","+arg.y+
")";
4753 if (arg.rotate) trans +=
" rotate("+arg.rotate+
")";
4755 fo_g.attr(
'transform', trans).attr(
'visibility', null).property(
'_arg',null);
4759 draw_g.selectAll(
'.hidden_text').attr(
'visibility', null).attr(
'class', null).each(
function() {
4761 var txt = d3.select(
this),
4762 arg = txt.property(
"_arg");
4764 txt.property(
"_arg", null);
4768 if (JSROOT.nodejs) {
4769 if (arg.scale && (f>0)) { arg.box.width = arg.box.width/f; arg.box.height = arg.box.height/f; }
4770 }
else if (!arg.plain && !arg.fast) {
4772 arg.box = painter.GetBoundarySizes(txt.node());
4779 if (arg.align[0]==
"middle") arg.x += arg.width/2;
else
4780 if (arg.align[0]==
"end") arg.x += arg.width;
4783 arg.dx = arg.dy = 0;
4786 txt.attr(
"text-anchor", arg.align[0]);
4788 txt.attr(
"text-anchor",
"start");
4789 arg.dx = ((arg.align[0]==
"middle") ? -0.5 : ((arg.align[0]==
"end") ? -1 : 0)) * arg.box.width;
4793 if (arg.align[1].indexOf(
'bottom')===0) arg.y += arg.height;
else
4794 if (arg.align[1] ==
'middle') arg.y += arg.height/2;
4798 if (arg.align[1] ==
'top') txt.attr(
"dy",
".8em");
else
4799 if (arg.align[1] ==
'middle') {
4800 if (JSROOT.browser.isIE || JSROOT.nodejs) txt.attr(
"dy",
".4em");
else txt.attr(
"dominant-baseline",
"middle");
4803 arg.dy = ((arg.align[1] ==
'top') ? (arg.top_shift || 1) : (arg.align[1] ==
'middle') ? (arg.mid_shift || 0.5) : 0) * arg.box.height;
4808 if (!arg.rotate) { arg.x += arg.dx; arg.y += arg.dy; arg.dx = arg.dy = 0; }
4811 var trans = (arg.x || arg.y) ?
"translate("+Math.round(arg.x)+
","+Math.round(arg.y)+
")" :
"";
4812 if (arg.rotate) trans +=
" rotate("+Math.round(arg.rotate)+
")";
4813 if (arg.dx || arg.dy) trans +=
" translate("+Math.round(arg.dx)+
","+Math.round(arg.dy)+
")";
4814 if (trans) txt.attr(
"transform", trans);
4816 if (JSROOT.browser.isWebKit && draw_g.node().insertAdjacentHTML && arg.large_latex) {
4820 var html = txt.node().outerHTML;
4822 draw_g.node().insertAdjacentHTML(
'beforeend', html );
4826 if (!call_ready) call_ready = draw_g.node().text_callback;
4827 draw_g.node().text_callback = null;
4829 draw_g.property(
'draw_text_completed',
true);
4832 JSROOT.CallBack(call_ready);
4834 return draw_g.property(
'max_text_width');
4842 TObjectPainter.prototype.produceLatex =
function(node, label, arg, curr) {
4846 curr = { lvl: 0, x: 0, y: 0, dx: 0, dy: -0.1, fsize: arg.font_size, parent: null };
4847 arg.mainnode = node.node();
4850 function extend_pos(pos, value) {
4852 var dx1, dx2, dy1, dy2;
4854 if (typeof value ==
'string') {
4855 if (!pos.rect) pos.rect = { x: pos.x, y: pos.y, height: 0, width: 0 };
4857 pos.x += value.length * arg.font.aver_width * pos.fsize;
4859 dy1 = -(pos.y-pos.fsize*1.1);
4860 dy2 = pos.y + pos.fsize*0.1;
4862 if (!pos.rect) pos.rect = JSROOT.extend({}, value);
4864 dx2 = value.x+value.width;
4866 dy2 = value.y+value.height;
4869 var rect = pos.rect;
4872 dx2 -= (rect.x+rect.width);
4874 dy2 -= (rect.y+rect.height);
4876 if (dx1>0) { rect.x -= dx1; rect.width += dx1; }
4877 if (dx2>0) rect.width += dx2;
4878 if (dy1>0) { rect.y -= dy1; rect.height += dy1; }
4879 if (dy2>0) rect.height+=dy2;
4881 if (pos.parent)
return extend_pos(pos.parent, rect)
4884 arg.text_rect = rect;
4886 var h = rect.height, mid = rect.y + rect.height/2;
4889 arg.mid_shift = -mid/h || 0.001;
4890 arg.top_shift = -rect.y/h || 0.001;
4894 function makeem(value) {
4895 if (Math.abs(value)<1e-2)
return null;
4896 if (value==Math.round(value))
return Math.round(value) +
"em";
4897 var res = value.toFixed(2);
4898 if (res.indexOf(
"0.")==0) res = res.substr(1);
else
4899 if (res.indexOf(
"-0.")==0) res =
"-." + res.substr(3);
4900 if (res[res.length-1]==
'0') res = res.substr(0, res.length-1);
4904 function get_boundary(painter, element, approx_rect) {
4908 if (JSROOT.nodejs || !element || element.empty())
4909 return approx_rect || { height: 0, width: 0 };
4911 var important = [], prnt = element.node();
4915 while (prnt && (prnt!=arg.mainnode)) {
4916 important.push(prnt);
4917 prnt = prnt.parentNode;
4920 element.selectAll(
'tspan').each(
function() { important.push(
this) });
4922 var tspans = d3.select(arg.mainnode).selectAll(
'tspan');
4925 if (tspans.size()>3) arg.large_latex =
true;
4927 tspans.each(
function() { if (important.indexOf(
this)<0) d3.select(
this).attr(
'display',
'none'); });
4928 var box = painter.GetBoundarySizes(arg.mainnode);
4930 tspans.each(
function() {
if (important.indexOf(
this)<0) d3.select(
this).attr(
'display', null); });
4938 { name:
"kern[", arg:
'float' },
4939 { name:
"lower[", arg:
'float' },
4940 { name:
"scale[", arg:
'float' },
4941 { name:
"#color[", arg:
'int' },
4942 { name:
"#font[", arg:
'int' },
4945 { name:
"#bar{", accent:
"\u02C9" },
4946 { name:
"#hat{", accent:
"\u02C6" },
4947 { name:
"#check{", accent:
"\u02C7" },
4948 { name:
"#acute{", accent:
"\u02CA" },
4949 { name:
"#grave{", accent:
"\u02CB" },
4950 { name:
"#dot{", accent:
"\u02D9" },
4951 { name:
"#ddot{", accent:
"\u02BA" },
4952 { name:
"#tilde{", accent:
"\u02DC" },
4953 { name:
"#slash{", accent:
"\u2215" },
4954 { name:
"#vec{", accent:
"\u02ED" },
4956 { name:
"#splitline{" },
4957 { name:
"#sqrt[", arg:
'int' },
4959 { name:
"#sum", special:
'\u2211', w: 0.8, h: 0.9 },
4960 { name:
"#int", special:
'\u222B', w: 0.3, h: 1.0 },
4961 { name:
"#left[", right:
"#right]", braces:
"[]" },
4962 { name:
"#left(", right:
"#right)", braces:
"()" },
4963 { name:
"#left{", right:
"#right}", braces:
"{}" },
4964 { name:
"#left|", right:
"#right|", braces:
"||" },
4965 { name:
"#[]{", braces:
"[]" },
4966 { name:
"#(){", braces:
"()" },
4967 { name:
"#{}{", braces:
"{}" },
4968 { name:
"#||{", braces:
"||" }
4971 var isany =
false, best, found, foundarg, pos, n, subnode, subnode1, subpos = null, prevsubpos = null;
4975 best = label.length; found = null; foundarg = null;
4977 for(n=0;n<features.length;++n) {
4978 pos = label.indexOf(features[n].name);
4979 if ((pos>=0) && (pos<best)) { best = pos; found = features[n]; }
4982 if (!found && !isany) {
4983 var s = JSROOT.Painter.translateLaTeX(label);
4984 if (!curr.lvl && (s==label))
return 0;
4985 extend_pos(curr, s);
4987 if (curr.accent && (s.length==1)) {
4988 var elem = node.append(
'svg:tspan').text(s),
4989 rect = get_boundary(
this, elem, { width : 10000 }),
4990 w = Math.min(rect.width/curr.fsize, 0.5);
4992 node.append(
'svg:tspan').attr(
'dx', makeem(curr.dx-w)).attr(
'dy', makeem(curr.dy-0.2)).text(curr.accent);
4994 curr.dx = Math.max(0.2, w-0.2);
4995 curr.accent =
false;
5003 var s = JSROOT.Painter.translateLaTeX(label.substr(0,best));
5005 extend_pos(curr, s);
5006 node.append(
'svg:tspan')
5007 .attr(
'dx', makeem(curr.dx))
5008 .attr(
'dy', makeem(curr.dy))
5010 curr.dx = curr.dy = 0;
5013 delete curr.special;
5014 delete curr.next_super_dy;
5017 if (!found)
return true;
5020 label = label.substr(best + found.name.length);
5022 subnode1 = subnode = node.append(
'svg:tspan');
5024 prevsubpos = subpos;
5026 subpos = { lvl: curr.lvl+1, x: curr.x, y: curr.y, fsize: curr.fsize, dx:0, dy: 0, parent: curr };
5031 pos = label.indexOf(
"]{");
5032 if (pos < 0) { console.log(
'missing argument for ', found.name);
return false; }
5033 foundarg = label.substr(0,pos);
5034 if (found.arg ==
'int') {
5035 foundarg = parseInt(foundarg);
5036 if (isNaN(foundarg)) { console.log(
'wrong int argument', label.substr(0,pos));
return false; }
5037 }
else if (found.arg ==
'float') {
5038 foundarg = parseFloat(foundarg);
5039 if (isNaN(foundarg)) { console.log(
'wrong float argument', label.substr(0,pos));
return false; }
5041 label = label.substr(pos + 2);
5044 var nextdy = curr.dy, nextdx = curr.dx, trav = null,
5045 scale = 1, left_brace =
"{", right_brace =
"}";
5047 curr.dy = curr.dx = 0;
5049 if (found.special) {
5050 subnode.attr(
'dx', makeem(nextdx)).attr(
'dy', makeem(nextdy)).text(found.special);
5051 nextdx = nextdy = 0;
5052 curr.special = found;
5054 var rect = get_boundary(
this, subnode);
5055 if (rect.width && rect.height) {
5056 found.w = rect.width/curr.fsize;
5057 found.h = rect.height/curr.fsize-0.1;
5064 subpos.left_cont = subnode.append(
'svg:tspan');
5065 subpos.left = subpos.left_cont.append(
'svg:tspan').text(found.braces[0]);
5066 subnode1 = subnode.append(
'svg:tspan');
5067 subpos.left_rect = { y: curr.y - curr.fsize*1.1, height: curr.fsize*1.2, x: curr.x, width: curr.fsize*0.6 };
5068 extend_pos(curr, subpos.left_rect);
5069 subpos.braces = found;
5071 left_brace = found.name;
5072 right_brace = found.right;
5074 }
else if (found.accent) {
5075 subpos.accent = found.accent;
5077 switch(found.name) {
5079 if (this.get_color(foundarg))
5080 subnode.attr(
'fill', this.get_color(foundarg));
5086 curr.dy -= foundarg;
5093 JSROOT.Painter.getFontDetails(foundarg).setFont(subnode,
'without-size');
5098 while (trav = trav.parent)
5099 if (trav.italic!==undefined) {
5100 curr.italic = !trav.italic;
5103 subnode.attr(
'font-style', curr.italic ?
'italic' :
'normal');
5108 while (trav = trav.parent)
5109 if (trav.bold!==undefined) {
5110 curr.bold = !trav.bold;
5113 subnode.attr(
'font-weight', curr.bold ?
'bold' :
'normal');
5117 subpos.script =
'sub';
5120 curr.dx = curr.special.w;
5125 nextdx += 0.1*scale;
5126 nextdy += 0.4*scale;
5127 subpos.y += 0.4*subpos.fsize;
5128 curr.dy = -0.4*scale;
5130 if (prevsubpos && (prevsubpos.script ===
'super')) {
5131 var rect = get_boundary(
this, prevsubpos.node, prevsubpos.rect);
5132 subpos.width_limit = rect.width;
5133 nextdx -= (rect.width/subpos.fsize+0.1)*scale;
5139 subpos.script =
'super';
5142 curr.dx = curr.special.w;
5143 curr.dy = curr.special.h;
5148 curr.dy = 0.6*scale;
5149 if (curr.next_super_dy) curr.dy -= curr.next_super_dy;
5151 nextdx += 0.1*scale;
5154 subpos.y -= 0.4*subpos.fsize;
5156 if (prevsubpos && (prevsubpos.script ===
'sub')) {
5157 var rect = get_boundary(
this, prevsubpos.node, prevsubpos.rect);
5158 subpos.width_limit = rect.width;
5159 nextdx -= (rect.width/subpos.fsize+0.1)*scale;
5165 subpos.first = subnode;
5166 subpos.two_lines =
true;
5167 subpos.need_middle = (found.name ==
"#frac{");
5168 subpos.x0 = subpos.x;
5175 subpos.square_root = subnode.append(
'svg:tspan');
5176 subpos.square_root.append(
'svg:tspan').text((foundarg==3) ?
'\u221B' : ((foundarg==4) ?
'\u221C' :
'\u221A'));
5177 subnode1 = subnode.append(
'svg:tspan');
5178 subpos.sqrt_rect = { y: curr.y - curr.fsize*1.1, height: curr.fsize*1.2, x: 0, width: curr.fsize*0.7 };
5179 extend_pos(curr, subpos.sqrt_rect);
5185 subnode.attr(
'font-size', Math.round(scale*100)+
'%');
5186 subpos.fsize *= scale;
5187 nextdx = nextdx/scale;
5188 nextdy = nextdy/scale;
5191 if (curr.special && !subpos.script)
delete curr.special;
5192 delete curr.next_super_dy;
5194 subpos.node = subnode;
5201 subpos.x += nextdx*subpos.fsize;
5202 subpos.y += nextdy*subpos.fsize;
5204 subnode.attr(
'dx', makeem(nextdx)).attr(
'dy', makeem(nextdy));
5205 nextdx = nextdy = 0;
5209 while ((n!=0) && (++pos < label.length)) {
5210 if (label.indexOf(left_brace, pos) === pos) n++;
else
5211 if (label.indexOf(right_brace, pos) === pos) n--;
5215 console.log(
'mismatch with open ' + left_brace +
' and close ' + right_brace +
' braces in Latex', label);
5219 var sublabel = label.substr(0,pos);
5223 if (!this.produceLatex(subnode1, sublabel, arg, subpos))
return false;
5229 curr.dx += subpos.dx*subpos.fsize/curr.fsize;
5230 curr.dy += subpos.dy*subpos.fsize/curr.fsize;
5232 label = label.substr(pos+right_brace.length);
5234 if (subpos.width_limit) {
5238 var rect = get_boundary(
this, subnode1, subpos.rect);
5239 if (rect.width < subpos.width_limit)
5240 curr.dx += (subpos.width_limit-rect.width)/curr.fsize;
5241 delete subpos.width_limit;
5246 var rect = get_boundary(
this, subnode1, subpos.rect);
5247 curr.dx -= rect.width/curr.fsize;
5250 if (subpos.square_root) {
5253 var len = 2, scale = 1, sqrt_dy = 0, yscale = 1,
5254 bs = get_boundary(
this, subpos.square_root, subpos.sqrt_rect),
5255 be = get_boundary(
this, subnode1, subpos.rect);
5258 if ((be.height > bs.height) && (bs.height > 0)) {
5259 yscale = be.height/bs.height*1.2;
5260 sqrt_dy = ((be.y+be.height) - (bs.y+bs.height))/curr.fsize/yscale;
5261 subpos.square_root.style(
'font-size', Math.round(100*yscale)+
'%').attr(
'dy', makeem(sqrt_dy));
5265 len = be.width / subpos.fsize / yscale;
5267 var a =
"", nn = Math.round(Math.max(len*3,2));
5268 while (nn--) a +=
'\u203E';
5270 subpos.square_root.append(
'svg:tspan').attr(
"dy", makeem(-0.25)).text(a);
5272 subpos.square_root.append(
'svg:tspan').attr(
"dy", makeem(0.25-sqrt_dy)).attr(
"dx", makeem(-a.length/3-0.2)).text(
'\u2009');
5277 if (subpos.braces) {
5280 var bs = get_boundary(
this, subpos.left_cont, subpos.left_rect),
5281 be = get_boundary(
this, subnode1, subpos.rect),
5282 yscale = 1, brace_dy = 0;
5286 if (1.2*bs.height < be.height) {
5288 yscale = be.height/bs.height;
5291 subpos.left.style(
'font-size', Math.round(100*yscale)+
'%').attr(
'dy', makeem(brace_dy));
5293 subpos.left_cont.append(
'svg:tspan').attr(
"dx",makeem(-0.2))
5294 .attr(
"dy", makeem(-brace_dy*yscale)).text(
'\u2009');
5295 curr.next_super_dy = -0.3*yscale;
5298 subpos.left_rect.y = curr.y;
5299 subpos.left_rect.height *= yscale;
5301 extend_pos(curr, subpos.left_rect);
5303 var right_cont = subnode.append(
'svg:tspan')
5304 .attr(
"dx", makeem(curr.dx))
5305 .attr(
"dy", makeem(curr.dy));
5307 curr.dx = curr.dy = 0;
5309 if (yscale!=1) right_cont.append(
'svg:tspan').attr(
"dx",makeem(-0.2)).text(
'\u2009');
5311 var right = right_cont.append(
'svg:tspan').text(subpos.braces.braces[1]);
5314 right.style(
'font-size', Math.round(100*yscale)+
'%').attr(
'dy', makeem(brace_dy));
5315 curr.dy = -brace_dy*yscale;
5321 if (subpos.first && subpos.second) {
5324 var rect1 = get_boundary(
this, subpos.first, subpos.rect1),
5325 rect2 = get_boundary(
this, subpos.second, subpos.rect),
5326 l1 = rect1.width / subpos.fsize,
5327 l2 = rect2.width / subpos.fsize,
5328 l3 = Math.max(l2, l1);
5330 if (subpos.need_middle) {
5332 l3 = Math.round(Math.max(l3,1)+0.3);
5334 while (a.length < l3) a +=
'\u2014';
5335 node.append(
'svg:tspan')
5336 .attr(
"dx", makeem(-0.5*(l3+l2)))
5337 .attr(
"dy", makeem(curr.dy-0.2))
5343 if (l2<l1) curr.dx += 0.5*(l1-l2);
5346 if (subpos.need_middle || arg.align[0]==
'middle') {
5347 subpos.first.attr(
"dx", makeem(0.5*(l3-l1)));
5348 subpos.second.attr(
"dx", makeem(-0.5*(l2+l1)));
5349 }
else if (arg.align[0]==
'end') {
5350 if (l1<l2) subpos.first.attr(
"dx", makeem(l2-l1));
5351 subpos.second.attr(
"dx", makeem(-l2));
5353 subpos.second.attr(
"dx", makeem(-l1));
5356 delete subpos.first;
5357 delete subpos.second;
5360 if (!subpos.two_lines)
break;
5362 if (label[0] !=
'{') {
5363 console.log(
'missing { for second line', label);
5367 label = label.substr(1);
5369 subnode = subnode1 = node.append(
'svg:tspan');
5371 subpos.two_lines =
false;
5372 subpos.rect1 = subpos.rect;
5374 subpos.x = subpos.x0;
5375 subpos.second = subnode;
5377 nextdy = curr.dy + 1.6;
5379 subpos.dx = subpos.dy = 0;
5403 TObjectPainter.prototype.DrawText =
function(arg) {
5405 var label = arg.text ||
"",
5406 align = [
'start',
'middle'];
5408 if (typeof arg.align ==
'string') {
5409 align = arg.align.split(
";");
5410 if (align.length==1) align.push(
'middle');
5411 }
else if (typeof arg.align ==
'number') {
5412 if ((arg.align / 10) >= 3) align[0] =
'end';
else
5413 if ((arg.align / 10) >= 2) align[0] =
'middle';
5414 if ((arg.align % 10) == 0) align[1] =
'bottom';
else
5415 if ((arg.align % 10) == 1) align[1] =
'bottom-base';
else
5416 if ((arg.align % 10) == 3) align[1] =
'top';
5419 arg.draw_g = arg.draw_g || this.draw_g;
5420 if (arg.latex===undefined) arg.latex = 1;
5424 arg.scale = arg.width && arg.height && !arg.font_size;
5425 arg.width = arg.width || 0;
5426 arg.height = arg.height || 0;
5428 if (arg.draw_g.property(
"_fast_drawing")) {
5431 if (arg.height < 4)
return 0;
5432 }
else if (arg.font_size) {
5434 if (arg.font_size < 4)
return 0;
5435 }
else if (arg.draw_g.property(
"_font_too_small")) {
5441 if (JSROOT.gStyle.MathJax !== undefined) {
5442 switch (JSROOT.gStyle.MathJax) {
5443 case 0: JSROOT.gStyle.Latex = 2;
break;
5444 case 2: JSROOT.gStyle.Latex = 4;
break;
5445 default: JSROOT.gStyle.Latex = 3;
5447 delete JSROOT.gStyle.MathJax;
5450 if (typeof JSROOT.gStyle.Latex ==
'string') {
5451 switch (JSROOT.gStyle.Latex) {
5452 case "off": JSROOT.gStyle.Latex = 0;
break;
5453 case "symbols": JSROOT.gStyle.Latex = 1;
break;
5456 case "math": JSROOT.gStyle.Latex = 3;
break;
5457 case "AlwaysMathJax":
5459 case "alwaysmathjax": JSROOT.gStyle.Latex = 4;
break;
5461 var code = parseInt(JSROOT.gStyle.Latex);
5462 JSROOT.gStyle.Latex = (!isNaN(code) && (code>=0) && (code<=4)) ? code : 2;
5466 var font = arg.draw_g.property(
'text_font'),
5467 use_mathjax = (arg.latex == 2);
5469 if (arg.latex === 1)
5470 use_mathjax = (JSROOT.gStyle.Latex > 3) || ((JSROOT.gStyle.Latex == 3) && JSROOT.Painter.isAnyLatex(label));
5475 if (!use_mathjax || arg.nomathjax) {
5477 var txt = arg.draw_g.append(
"svg:text");
5479 if (arg.color) txt.attr(
"fill", arg.color);
5481 if (arg.font_size) txt.attr(
"font-size", arg.font_size);
5482 else arg.font_size = font.size;
5486 arg.plain = !arg.latex || (JSROOT.gStyle.Latex < 2) || (this.produceLatex(txt, label, arg) === 0);
5489 if (arg.latex && (JSROOT.gStyle.Latex == 1)) label = Painter.translateLaTeX(label);
5494 arg.box = !JSROOT.nodejs && !JSROOT.gStyle.ApproxTextSize && !arg.fast ? this.GetBoundarySizes(txt.node()) :
5495 (arg.text_rect || { height: arg.font_size*1.2, width: JSROOT.Painter.approxTextWidth(font, label) });
5497 txt.attr(
'class',
'hidden_text')
5498 .attr(
'visibility',
'hidden')
5499 .property(
"_arg", arg);
5501 if (arg.box.width > arg.draw_g.property(
'max_text_width')) arg.draw_g.property(
'max_text_width', arg.box.width);
5502 if (arg.scale) this.TextScaleFactor(1.05*arg.box.width/arg.width, arg.draw_g);
5503 if (arg.scale) this.TextScaleFactor(1.*arg.box.height/arg.height, arg.draw_g);
5505 return arg.box.width;
5508 var mtext = JSROOT.Painter.translateMath(label, arg.latex, arg.color,
this),
5509 fo_g = arg.draw_g.append(
"svg:g")
5510 .attr(
'class',
'math_svg')
5511 .attr(
'visibility',
'hidden')
5512 .property(
'_arg', arg);
5514 arg.draw_g.property(
'mathjax_use',
true);
5516 if (JSROOT.nodejs) {
5519 if (!JSROOT.nodejs_mathjax) {
5520 JSROOT.nodejs_mathjax = require(
"mathjax-node");
5521 JSROOT.nodejs_mathjax.config({
5522 TeX: { extensions: [
"color.js"] },
5523 SVG: { mtextFontInherit:
true, minScaleAdjust: 100, matchFontHeight:
true, useFontCache:
false }
5525 JSROOT.nodejs_mathjax.start();
5528 if ((mtext.indexOf(
"\\(")==0) && (mtext.lastIndexOf(
"\\)")==mtext.length-2))
5529 mtext = mtext.substr(2,mtext.length-4);
5531 JSROOT.nodejs_mathjax.typeset({
5532 jsroot_painter:
this,
5533 jsroot_drawg: arg.draw_g,
5537 useFontCache:
false,
5538 useGlobalCache:
false,
5541 },
function (data, opt) {
5543 opt.jsroot_fog.html(data.svg);
5545 console.log(
'MathJax error', opt.math);
5546 opt.jsroot_fog.html(
"<svg></svg>");
5548 opt.jsroot_painter.FinishTextDrawing(opt.jsroot_drawg);
5554 var element = document.createElement(
"p");
5556 d3.select(element).style(
'visibility',
"hidden").style(
'overflow',
"hidden").style(
'position',
"absolute")
5557 .style(
"font-size",font.size+
'px').style(
"font-family",font.name)
5558 .html(
'<mtext>' + mtext +
'</mtext>');
5559 document.body.appendChild(element);
5561 fo_g.property(
'_element', element);
5565 JSROOT.AssertPrerequisites(
'mathjax',
function() {
5567 MathJax.Hub.Typeset(element, [
"FinishMathjax", painter, arg.draw_g, fo_g]);
5569 MathJax.Hub.Queue([
"FinishMathjax", painter, arg.draw_g, fo_g]);
5580 TObjectPainter.prototype.FinishMathjax =
function(draw_g, fo_g, id) {
5582 if (fo_g.node().parentNode !== draw_g.node())
return;
5584 var entry = fo_g.property(
'_element');
5587 var vvv = d3.select(entry).select(
"svg");
5591 var merr = d3.select(entry).select(
"merror");
5593 if (merr.empty())
return;
5595 console.warn(
'MathJax error', merr.text());
5597 var arg = fo_g.property(
'_arg');
5599 if (arg && arg.latex!=2) {
5600 arg.nomathjax =
true;
5604 fo_g.append(
"svg").attr(
'width', Math.min(20, merr.text().length + 5) +
'ex')
5605 .attr(
'height',
'3ex')
5606 .style(
'vertical-align',
'0ex')
5608 .style(
'font-size',
'12px')
5609 .style(
'fill',
'red')
5612 .text(
"Err: " + merr.text());
5615 fo_g.append(
function() {
return vvv.node(); });
5618 fo_g.property(
'_element', null);
5619 document.body.removeChild(entry);
5621 this.FinishTextDrawing(draw_g);
5633 Painter.SelectActivePad =
function(args) {
5635 if (this.$active_pp && (typeof this.$active_pp.SetActive ==
'function'))
5636 this.$active_pp.SetActive(
false);
5638 this.$active_pp = args.pp;
5640 if (this.$active_pp && (typeof this.$active_pp.SetActive ==
'function'))
5641 this.$active_pp.SetActive(
true);
5642 }
else if (this.$active_pp === args.pp) {
5643 delete this.$active_pp;
5651 Painter.GetActivePad =
function() {
5652 return this.$active_pp;
5657 function TooltipHandler(obj) {
5658 JSROOT.TObjectPainter.call(
this, obj);
5659 this.tooltip_enabled =
true;
5662 TooltipHandler.prototype = Object.create(TObjectPainter.prototype);
5664 TooltipHandler.prototype.hints_layer =
function() {
5668 var pp = this.canv_painter();
5669 return pp ? pp.svg_layer(
"info_layer") : d3.select(null);
5672 TooltipHandler.prototype.IsTooltipShown =
function() {
5674 if (!this.tooltip_enabled || !this.IsTooltipAllowed())
return false;
5675 var hintsg = this.hints_layer().select(
".objects_hints");
5676 return hintsg.empty() ?
false : hintsg.property(
"hints_pad") == this.pad_name;
5679 TooltipHandler.prototype.ProcessTooltipEvent =
function(pnt, enabled) {
5682 if (enabled !== undefined) this.tooltip_enabled = enabled;
5684 if (pnt && pnt.handler) {
5686 var rect = this.draw_g ? this.draw_g.select(
".main_layer") : null;
5687 if (!rect || rect.empty()) {
5689 }
else if (pnt.touch) {
5690 var pos = d3.touches(rect.node());
5691 pnt = (pos && pos.length == 1) ? { touch:
true, x: pos[0][0], y: pos[0][1] } : null;
5693 var pos = d3.mouse(rect.node());
5694 pnt = { touch:
false, x: pos[0], y: pos[1] };
5698 var hints = [], nhints = 0, maxlen = 0, lastcolor1 = 0, usecolor1 =
false,
5699 textheight = 11, hmargin = 3, wmargin = 3, hstep = 1.2,
5700 frame_rect = this.GetFrameRect(),
5701 pad_width = this.pad_width(),
5702 pp = this.pad_painter(),
5703 font = JSROOT.Painter.getFontDetails(160, textheight),
5704 status_func = this.GetShowStatusFunc(),
5705 disable_tootlips = !this.IsTooltipAllowed() || !this.tooltip_enabled;
5707 if ((pnt === undefined) || (disable_tootlips && !status_func)) pnt = null;
5708 if (pnt && disable_tootlips) pnt.disabled =
true;
5709 if (pnt) pnt.painters =
true;
5712 if (pp) hints = pp.GetTooltips(pnt);
5714 if (pnt && pnt.touch) textheight = 15;
5716 for (var n = 0; n < hints.length; ++n) {
5717 var hint = hints[n];
5718 if (!hint)
continue;
5720 if (hint.painter && (hint.user_info!==undefined))
5721 if (hint.painter.ProvideUserTooltip(hint.user_info)) {};
5723 if (!hint.lines || (hint.lines.length===0)) {
5724 hints[n] = null;
continue;
5728 for (var k=0;k<n;++k) {
5729 var hprev = hints[k], diff =
false;
5730 if (!hprev || (hprev.lines.length !== hint.lines.length))
continue;
5731 for (var l=0;l<hint.lines.length && !diff;++l)
5732 if (hprev.lines[l] !== hint.lines[l]) diff =
true;
5733 if (!diff) { hints[n] = null;
break; }
5735 if (!hints[n])
continue;
5739 for (var l=0;l<hint.lines.length;++l)
5740 maxlen = Math.max(maxlen, hint.lines[l].length);
5742 hint.height = Math.round(hint.lines.length*textheight*hstep + 2*hmargin - textheight*(hstep-1));
5744 if ((hint.color1!==undefined) && (hint.color1!==
'none')) {
5745 if ((lastcolor1!==0) && (lastcolor1 !== hint.color1)) usecolor1 =
true;
5746 lastcolor1 = hint.color1;
5750 var layer = this.hints_layer(),
5751 hintsg = layer.select(
".objects_hints");
5754 var title =
"", name =
"", info =
"",
5755 hint = null, best_dist2 = 1e10, best_hint = null,
5756 coordinates = pnt ? Math.round(pnt.x)+
","+Math.round(pnt.y) :
"";
5758 for (var k=0; k < (hints ? hints.length : 0); ++k) {
5759 if (!hints[k])
continue;
5760 if (!hint) hint = hints[k];
5761 if (hints[k].exact && (!hint || !hint.exact)) { hint = hints[k];
break; }
5763 if (!pnt || (hints[k].x===undefined) || (hints[k].y===undefined))
continue;
5765 var dist2 = (pnt.x-hints[k].x)*(pnt.x-hints[k].x) + (pnt.y-hints[k].y)*(pnt.y-hints[k].y);
5766 if (dist2<best_dist2) { best_dist2 = dist2; best_hint = hints[k]; }
5769 if ((!hint || !hint.exact) && (best_dist2 < 400)) hint = best_hint;
5772 name = (hint.lines && hint.lines.length>1) ? hint.lines[0] : hint.name;
5773 title = hint.title ||
"";
5775 if (!info && hint.lines) info = hint.lines.slice(1).join(
' ');
5778 status_func(name, title, info, coordinates);
5782 if (!pnt || disable_tootlips || (hints.length===0) || (maxlen===0) || (nhints > 15)) {
5791 hintsg = layer.append(
"svg:g")
5792 .attr(
"class",
"objects_hints")
5793 .style(
"pointer-events",
"none");
5795 var frame_shift = { x: 0, y: 0 }, trans = frame_rect.transform ||
"";
5797 pp.CalcAbsolutePosition(this.svg_pad(), frame_shift);
5798 trans =
"translate(" + frame_shift.x +
"," + frame_shift.y +
") " + trans;
5802 hintsg.attr(
"transform", trans)
5803 .property(
"last_point", pnt)
5804 .property(
"hints_pad", this.pad_name);
5806 var viewmode = hintsg.property(
'viewmode') ||
"",
5807 actualw = 0, posx = pnt.x + frame_rect.hint_delta_x;
5812 var bleft = 0.5, bright = 0.5;
5814 if (viewmode==
"left") bright = 0.7;
else
5815 if (viewmode==
"right") bleft = 0.3;
5817 if (posx <= bleft*frame_rect.width) {
5820 }
else if (posx >= bright*frame_rect.width) {
5822 posx = frame_rect.width - 60;
5824 posx = hintsg.property(
'startx');
5827 viewmode =
"single";
5831 if (viewmode !== hintsg.property(
'viewmode')) {
5832 hintsg.property(
'viewmode', viewmode);
5833 hintsg.selectAll(
"*").remove();
5838 gapminx = -1111, gapmaxx = -1111,
5839 minhinty = -frame_shift.y,
5840 maxhinty = this.pad_height(
"") - frame_rect.y - frame_shift.y;
5842 function FindPosInGap(y) {
5843 for (var n=0;(n<hints.length) && (y < maxhinty); ++n) {
5844 var hint = hints[n];
5845 if (!hint)
continue;
5846 if ((hint.y>=y-5) && (hint.y <= y+hint.height+5)) {
5854 for (var n=0; n < hints.length; ++n) {
5855 var hint = hints[n],
5856 group = hintsg.select(
".painter_hint_"+n);
5862 var was_empty = group.empty(), dx = 0, dy = 0;
5865 group = hintsg.append(
"svg:svg")
5866 .attr(
"class",
"painter_hint_"+n)
5868 .style(
'overflow',
'hidden')
5869 .style(
"pointer-events",
"none");
5871 if (viewmode ==
"single") {
5872 curry = pnt.touch ? (pnt.y - hint.height - 5) : Math.min(pnt.y + 15, maxhinty - hint.height - 3) + frame_rect.hint_delta_y;
5874 gapy = FindPosInGap(gapy);
5875 if ((gapminx === -1111) && (gapmaxx === -1111)) gapminx = gapmaxx = hint.x;
5876 gapminx = Math.min(gapminx, hint.x);
5877 gapmaxx = Math.min(gapmaxx, hint.x);
5880 group.attr(
"x", posx)
5882 .property(
"curry", curry)
5883 .property(
"gapy", gapy);
5885 curry += hint.height + 5;
5886 gapy += hint.height + 5;
5889 group.selectAll(
"*").remove();
5891 group.attr(
"width", 60)
5892 .attr(
"height", hint.height);
5894 var r = group.append(
"rect")
5898 .attr(
"height", hint.height)
5899 .attr(
"fill",
"lightgrey")
5900 .style(
"pointer-events",
"none");
5903 var col = usecolor1 ? hint.color1 : hint.color2;
5904 if ((col !== undefined) && (col!==
'none'))
5905 r.attr(
"stroke", col).attr(
"stroke-width", hint.exact ? 3 : 1);
5908 for (var l=0; l < (hint.lines ? hint.lines.length : 0); l++)
5909 if (hint.lines[l]!==null) {
5910 var txt = group.append(
"svg:text")
5911 .attr(
"text-anchor",
"start")
5913 .attr(
"y", hmargin + l*textheight*hstep)
5915 .attr(
"fill",
"black")
5916 .style(
"pointer-events",
"none")
5918 .text(hint.lines[l]);
5920 var box = this.GetBoundarySizes(txt.node());
5922 actualw = Math.max(actualw, box.width);
5925 function translateFn() {
5928 return function(d, i, a) {
5929 return function(t) {
5930 return t < 0.8 ?
"0" : (t-0.8)*5;
5936 if (JSROOT.gStyle.TooltipAnimation > 0)
5937 group.transition().duration(JSROOT.gStyle.TooltipAnimation).attrTween(
"opacity", translateFn());
5939 group.attr(
'opacity',1);
5942 actualw += 2*wmargin;
5944 var svgs = hintsg.selectAll(
"svg");
5946 if ((viewmode ==
"right") && (posx + actualw > frame_rect.width - 20)) {
5947 posx = frame_rect.width - actualw - 20;
5948 svgs.attr(
"x", posx);
5951 if ((viewmode ==
"single") && (posx + actualw > pad_width - frame_rect.x) && (posx > actualw+20)) {
5952 posx -= (actualw + 20);
5953 svgs.attr(
"x", posx);
5957 if ((viewmode !==
"single") && (gapy < maxhinty) && (gapy !== curry)) {
5958 if ((gapminx <= posx+actualw+5) && (gapmaxx >= posx-5))
5959 svgs.attr(
"y",
function() {
return d3.select(
this).property(
'gapy'); });
5960 }
else if ((viewmode !==
'single') && (curry > maxhinty)) {
5961 var shift = Math.max((maxhinty - curry - 10), minhinty);
5963 svgs.attr(
"y",
function() {
return d3.select(
this).property(
'curry') + shift; });
5967 svgs.attr(
"width",actualw)
5968 .select(
'rect').attr(
"width", actualw);
5970 hintsg.property(
'startx', posx);
5973 JSROOT.TCanvasStatusBits = {
5974 kShowEventStatus : JSROOT.BIT(15),
5975 kAutoExec : JSROOT.BIT(16),
5976 kMenuBar : JSROOT.BIT(17),
5977 kShowToolBar : JSROOT.BIT(18),
5978 kShowEditor : JSROOT.BIT(19),
5979 kMoveOpaque : JSROOT.BIT(20),
5980 kResizeOpaque : JSROOT.BIT(21),
5981 kIsGrayscale : JSROOT.BIT(22),
5982 kShowToolTips : JSROOT.BIT(23)
5985 JSROOT.EAxisBits = {
5986 kTickPlus : JSROOT.BIT(9),
5987 kTickMinus : JSROOT.BIT(10),
5988 kAxisRange : JSROOT.BIT(11),
5989 kCenterTitle : JSROOT.BIT(12),
5990 kCenterLabels : JSROOT.BIT(14),
5991 kRotateTitle : JSROOT.BIT(15),
5992 kPalette : JSROOT.BIT(16),
5993 kNoExponent : JSROOT.BIT(17),
5994 kLabelsHori : JSROOT.BIT(18),
5995 kLabelsVert : JSROOT.BIT(19),
5996 kLabelsDown : JSROOT.BIT(20),
5997 kLabelsUp : JSROOT.BIT(21),
5998 kIsInteger : JSROOT.BIT(22),
5999 kMoreLogLabels : JSROOT.BIT(23),
6000 kDecimals : JSROOT.BIT(11)
6006 Painter.drawRawText =
function(divid, txt, opt) {
6008 var painter =
new TBasePainter();
6010 painter.SetDivId(divid);
6012 painter.RedrawObject =
function(obj) {
6018 painter.Draw =
function() {
6019 var txt = (this.txt._typename && (this.txt._typename ==
"TObjString")) ? this.txt.fString : this.txt.value;
6020 if (typeof txt !=
'string') txt =
"<undefined>";
6022 var mathjax = this.txt.mathjax || (JSROOT.gStyle.Latex == 4);
6024 if (!mathjax && !(
'as_is' in this.txt)) {
6025 var arr = txt.split(
"\n"); txt =
"";
6026 for (var i = 0; i < arr.length; ++i)
6027 txt +=
"<pre style='margin:0'>" + arr[i] +
"</pre>";
6030 var frame = this.select_main(),
6031 main = frame.select(
"div");
6033 main = frame.append(
"div").style(
'max-width',
'100%').style(
'max-height',
'100%').style(
'overflow',
'auto');
6037 this.SetDivId(this.divid);
6040 JSROOT.AssertPrerequisites(
'mathjax',
function() {
6041 MathJax.Hub.Typeset(frame.node());
6046 return painter.DrawingReady();
6058 JSROOT.RegisterForResize =
function(handle, delay) {
6060 if (!handle)
return;
6062 var myInterval = null, myDelay = delay ? delay : 300;
6064 if (myDelay < 20) myDelay = 20;
6066 function ResizeTimer() {
6069 document.body.style.cursor =
'wait';
6070 if (typeof handle ==
'function') handle();
else
6071 if ((typeof handle ==
'object') && (typeof handle.CheckResize ==
'function')) handle.CheckResize();
else
6072 if (typeof handle ==
'string') {
6073 var node = d3.select(
'#'+handle);
6074 if (!node.empty()) {
6075 var mdi = node.property(
'mdi');
6077 mdi.CheckMDIResize();
6079 JSROOT.resize(node.node());
6083 document.body.style.cursor =
'auto';
6086 function ProcessResize() {
6087 if (myInterval !== null) clearTimeout(myInterval);
6088 myInterval = setTimeout(ResizeTimer, myDelay);
6091 window.addEventListener(
'resize', ProcessResize);
6094 JSROOT.addDrawFunc({ name:
"TCanvas", icon:
"img_canvas", prereq:
"v6", func:
"JSROOT.Painter.drawCanvas", opt:
";grid;gridx;gridy;tick;tickx;ticky;log;logx;logy;logz", expand_item:
"fPrimitives" });
6095 JSROOT.addDrawFunc({ name:
"TPad", icon:
"img_canvas", prereq:
"v6", func:
"JSROOT.Painter.drawPad", opt:
";grid;gridx;gridy;tick;tickx;ticky;log;logx;logy;logz", expand_item:
"fPrimitives" });
6096 JSROOT.addDrawFunc({ name:
"TSlider", icon:
"img_canvas", prereq:
"v6", func:
"JSROOT.Painter.drawPad" });
6097 JSROOT.addDrawFunc({ name:
"TFrame", icon:
"img_frame", prereq:
"v6", func:
"JSROOT.Painter.drawFrame" });
6098 JSROOT.addDrawFunc({ name:
"TPave", icon:
"img_pavetext", prereq:
"v6;hist", func:
"JSROOT.Painter.drawPave" });
6099 JSROOT.addDrawFunc({ name:
"TPaveText", icon:
"img_pavetext", prereq:
"v6;hist", func:
"JSROOT.Painter.drawPave" });
6100 JSROOT.addDrawFunc({ name:
"TPavesText", icon:
"img_pavetext", prereq:
"v6;hist", func:
"JSROOT.Painter.drawPave" });
6101 JSROOT.addDrawFunc({ name:
"TPaveStats", icon:
"img_pavetext", prereq:
"v6;hist", func:
"JSROOT.Painter.drawPave" });
6102 JSROOT.addDrawFunc({ name:
"TPaveLabel", icon:
"img_pavelabel", prereq:
"v6;hist", func:
"JSROOT.Painter.drawPave" });
6103 JSROOT.addDrawFunc({ name:
"TDiamond", icon:
"img_pavelabel", prereq:
"v6;hist", func:
"JSROOT.Painter.drawPave" });
6104 JSROOT.addDrawFunc({ name:
"TLatex", icon:
"img_text", prereq:
"more2d", func:
"JSROOT.Painter.drawText", direct:
true });
6105 JSROOT.addDrawFunc({ name:
"TMathText", icon:
"img_text", prereq:
"more2d", func:
"JSROOT.Painter.drawText", direct:
true });
6106 JSROOT.addDrawFunc({ name:
"TText", icon:
"img_text", prereq:
"more2d", func:
"JSROOT.Painter.drawText", direct:
true });
6107 JSROOT.addDrawFunc({ name: /^TH1/, icon:
"img_histo1d", prereq:
"v6;hist", func:
"JSROOT.Painter.drawHistogram1D", opt:
";hist;P;P0;E;E1;E2;E3;E4;E1X0;L;LF2;B;B1;A;TEXT;LEGO;same", ctrl:
"l" });
6108 JSROOT.addDrawFunc({ name:
"TProfile", icon:
"img_profile", prereq:
"v6;hist", func:
"JSROOT.Painter.drawHistogram1D", opt:
";E0;E1;E2;p;AH;hist"});
6109 JSROOT.addDrawFunc({ name:
"TH2Poly", icon:
"img_histo2d", prereq:
"v6;hist", func:
"JSROOT.Painter.drawHistogram2D", opt:
";COL;COL0;COLZ;LCOL;LCOL0;LCOLZ;LEGO;TEXT;same", expand_item:
"fBins", theonly:
true });
6110 JSROOT.addDrawFunc({ name:
"TProfile2Poly", sameas:
"TH2Poly" });
6111 JSROOT.addDrawFunc({ name:
"TH2PolyBin", icon:
"img_histo2d", draw_field:
"fPoly" });
6112 JSROOT.addDrawFunc({ name: /^TH2/, icon:
"img_histo2d", prereq:
"v6;hist", func:
"JSROOT.Painter.drawHistogram2D", opt:
";COL;COLZ;COL0;COL1;COL0Z;COL1Z;COLA;BOX;BOX1;PROJ;PROJX1;PROJX2;PROJX3;PROJY1;PROJY2;PROJY3;SCAT;TEXT;TEXTE;TEXTE0;CONT;CONT1;CONT2;CONT3;CONT4;ARR;SURF;SURF1;SURF2;SURF4;SURF6;E;A;LEGO;LEGO0;LEGO1;LEGO2;LEGO3;LEGO4;same", ctrl:
"colz" });
6113 JSROOT.addDrawFunc({ name:
"TProfile2D", sameas:
"TH2" });
6114 JSROOT.addDrawFunc({ name: /^TH3/, icon:
'img_histo3d', prereq:
"v6;hist3d", func:
"JSROOT.Painter.drawHistogram3D", opt:
";SCAT;BOX;BOX2;BOX3;GLBOX1;GLBOX2;GLCOL" });
6115 JSROOT.addDrawFunc({ name:
"THStack", icon:
"img_histo1d", prereq:
"v6;hist", func:
"JSROOT.Painter.drawHStack", expand_item:
"fHists", opt:
"NOSTACK;HIST;E;PFC;PLC" });
6116 JSROOT.addDrawFunc({ name:
"TPolyMarker3D", icon:
'img_histo3d', prereq:
"v6;hist3d", func:
"JSROOT.Painter.drawPolyMarker3D" });
6117 JSROOT.addDrawFunc({ name:
"TPolyLine3D", icon:
'img_graph', prereq:
"3d", func:
"JSROOT.Painter.drawPolyLine3D", direct:
true });
6118 JSROOT.addDrawFunc({ name:
"TGraphStruct" });
6119 JSROOT.addDrawFunc({ name:
"TGraphNode" });
6120 JSROOT.addDrawFunc({ name:
"TGraphEdge" });
6121 JSROOT.addDrawFunc({ name:
"TGraphTime", icon:
"img_graph", prereq:
"more2d", func:
"JSROOT.Painter.drawGraphTime", opt:
"once;repeat;first", theonly:
true });
6122 JSROOT.addDrawFunc({ name:
"TGraph2D", icon:
"img_graph", prereq:
"v6;hist3d", func:
"JSROOT.Painter.drawGraph2D", opt:
";P;PCOL", theonly:
true });
6123 JSROOT.addDrawFunc({ name:
"TGraph2DErrors", icon:
"img_graph", prereq:
"v6;hist3d", func:
"JSROOT.Painter.drawGraph2D", opt:
";P;PCOL;ERR", theonly:
true });
6124 JSROOT.addDrawFunc({ name:
"TGraphPolargram", icon:
"img_graph", prereq:
"more2d", func:
"JSROOT.Painter.drawGraphPolargram", theonly:
true });
6125 JSROOT.addDrawFunc({ name:
"TGraphPolar", icon:
"img_graph", prereq:
"more2d", func:
"JSROOT.Painter.drawGraphPolar", opt:
";F;L;P;PE", theonly:
true });
6126 JSROOT.addDrawFunc({ name: /^TGraph/, icon:
"img_graph", prereq:
"more2d", func:
"JSROOT.Painter.drawGraph", opt:
";L;P" });
6127 JSROOT.addDrawFunc({ name:
"TEfficiency", icon:
"img_graph", prereq:
"more2d", func:
"JSROOT.Painter.drawEfficiency", opt:
";AP" });
6128 JSROOT.addDrawFunc({ name:
"TCutG", sameas:
"TGraph" });
6129 JSROOT.addDrawFunc({ name: /^RooHist/, sameas:
"TGraph" });
6130 JSROOT.addDrawFunc({ name: /^RooCurve/, sameas:
"TGraph" });
6131 JSROOT.addDrawFunc({ name:
"RooPlot", icon:
"img_canvas", prereq:
"more2d", func:
"JSROOT.Painter.drawRooPlot" });
6132 JSROOT.addDrawFunc({ name:
"TMultiGraph", icon:
"img_mgraph", prereq:
"more2d", func:
"JSROOT.Painter.drawMultiGraph", expand_item:
"fGraphs" });
6133 JSROOT.addDrawFunc({ name:
"TStreamerInfoList", icon:
'img_question', prereq:
"hierarchy", func:
"JSROOT.Painter.drawStreamerInfo" });
6134 JSROOT.addDrawFunc({ name:
"TPaletteAxis", icon:
"img_colz", prereq:
"v6;hist", func:
"JSROOT.Painter.drawPave" });
6135 JSROOT.addDrawFunc({ name:
"TWebPainting", icon:
"img_graph", prereq:
"more2d", func:
"JSROOT.Painter.drawWebPainting" });
6136 JSROOT.addDrawFunc({ name:
"TCanvasWebSnapshot", icon:
"img_canvas", prereq:
"v6", func:
"JSROOT.Painter.drawPadSnapshot" });
6137 JSROOT.addDrawFunc({ name:
"TPadWebSnapshot", sameas:
"TCanvasWebSnapshot" });
6138 JSROOT.addDrawFunc({ name:
"kind:Text", icon:
"img_text", func: JSROOT.Painter.drawRawText });
6139 JSROOT.addDrawFunc({ name:
"TObjString", icon:
"img_text", func: JSROOT.Painter.drawRawText });
6140 JSROOT.addDrawFunc({ name:
"TF1", icon:
"img_tf1", prereq:
"math;more2d", func:
"JSROOT.Painter.drawFunction" });
6141 JSROOT.addDrawFunc({ name:
"TF2", icon:
"img_tf2", prereq:
"math;hist", func:
"JSROOT.Painter.drawTF2" });
6142 JSROOT.addDrawFunc({ name:
"TSpline3", icon:
"img_tf1", prereq:
"more2d", func:
"JSROOT.Painter.drawSpline" });
6143 JSROOT.addDrawFunc({ name:
"TSpline5", icon:
"img_tf1", prereq:
"more2d", func:
"JSROOT.Painter.drawSpline" });
6144 JSROOT.addDrawFunc({ name:
"TEllipse", icon:
'img_graph', prereq:
"more2d", func:
"JSROOT.Painter.drawEllipse", direct:
true });
6145 JSROOT.addDrawFunc({ name:
"TArc", sameas:
'TEllipse' });
6146 JSROOT.addDrawFunc({ name:
"TCrown", sameas:
'TEllipse' });
6147 JSROOT.addDrawFunc({ name:
"TPie", icon:
'img_graph', prereq:
"more2d", func:
"JSROOT.Painter.drawPie", direct:
true });
6148 JSROOT.addDrawFunc({ name:
"TLine", icon:
'img_graph', prereq:
"more2d", func:
"JSROOT.Painter.drawLine", direct:
true });
6149 JSROOT.addDrawFunc({ name:
"TArrow", icon:
'img_graph', prereq:
"more2d", func:
"JSROOT.Painter.drawArrow", direct:
true });
6150 JSROOT.addDrawFunc({ name:
"TPolyLine", icon:
'img_graph', prereq:
"more2d", func:
"JSROOT.Painter.drawPolyLine", direct:
true });
6151 JSROOT.addDrawFunc({ name:
"TCurlyLine", sameas:
'TPolyLine' });
6152 JSROOT.addDrawFunc({ name:
"TCurlyArc", sameas:
'TPolyLine' });
6153 JSROOT.addDrawFunc({ name:
"TGaxis", icon:
"img_graph", prereq:
"v6", func:
"JSROOT.Painter.drawGaxis" });
6154 JSROOT.addDrawFunc({ name:
"TLegend", icon:
"img_pavelabel", prereq:
"v6;hist", func:
"JSROOT.Painter.drawPave" });
6155 JSROOT.addDrawFunc({ name:
"TBox", icon:
'img_graph', prereq:
"more2d", func:
"JSROOT.Painter.drawBox", direct:
true });
6156 JSROOT.addDrawFunc({ name:
"TWbox", icon:
'img_graph', prereq:
"more2d", func:
"JSROOT.Painter.drawBox", direct:
true });
6157 JSROOT.addDrawFunc({ name:
"TSliderBox", icon:
'img_graph', prereq:
"more2d", func:
"JSROOT.Painter.drawBox", direct:
true });
6158 JSROOT.addDrawFunc({ name:
"TAxis3D", prereq:
"v6;hist3d", func:
"JSROOT.Painter.drawAxis3D" });
6159 JSROOT.addDrawFunc({ name:
"TMarker", icon:
'img_graph', prereq:
"more2d", func:
"JSROOT.Painter.drawMarker", direct:
true });
6160 JSROOT.addDrawFunc({ name:
"TPolyMarker", icon:
'img_graph', prereq:
"more2d", func:
"JSROOT.Painter.drawPolyMarker", direct:
true });
6161 JSROOT.addDrawFunc({ name:
"TASImage", icon:
'img_mgraph', prereq:
"more2d", func:
"JSROOT.Painter.drawASImage" });
6162 JSROOT.addDrawFunc({ name:
"TJSImage", icon:
'img_mgraph', prereq:
"more2d", func:
"JSROOT.Painter.drawJSImage", opt:
";scale;center" });
6163 JSROOT.addDrawFunc({ name:
"TGeoVolume", icon:
'img_histo3d', prereq:
"geom", func:
"JSROOT.Painter.drawGeoObject", expand:
"JSROOT.GEO.expandObject", opt:
";more;all;count;projx;projz;wire;dflt", ctrl:
"dflt" });
6164 JSROOT.addDrawFunc({ name:
"TEveGeoShapeExtract", icon:
'img_histo3d', prereq:
"geom", func:
"JSROOT.Painter.drawGeoObject", expand:
"JSROOT.GEO.expandObject", opt:
";more;all;count;projx;projz;wire;dflt", ctrl:
"dflt" });
6165 JSROOT.addDrawFunc({ name:
"ROOT::Experimental::TEveGeoShapeExtract", icon:
'img_histo3d', prereq:
"geom", func:
"JSROOT.Painter.drawGeoObject", expand:
"JSROOT.GEO.expandObject", opt:
";more;all;count;projx;projz;wire;dflt", ctrl:
"dflt" });
6166 JSROOT.addDrawFunc({ name:
"TGeoOverlap", icon:
'img_histo3d', prereq:
"geom", expand:
"JSROOT.GEO.expandObject", func:
"JSROOT.Painter.drawGeoObject", opt:
";more;all;count;projx;projz;wire;dflt", dflt:
"dflt", ctrl:
"expand" });
6167 JSROOT.addDrawFunc({ name:
"TGeoManager", icon:
'img_histo3d', prereq:
"geom", expand:
"JSROOT.GEO.expandObject", func:
"JSROOT.Painter.drawGeoObject", opt:
";more;all;count;projx;projz;wire;tracks;dflt", dflt:
"expand", ctrl:
"dflt" });
6168 JSROOT.addDrawFunc({ name: /^TGeo/, icon:
'img_histo3d', prereq:
"geom", func:
"JSROOT.Painter.drawGeoObject", opt:
";more;all;axis;compa;count;projx;projz;wire;dflt", ctrl:
"dflt" });
6170 JSROOT.addDrawFunc({ name:
"kind:Command", icon:
"img_execute", execute:
true });
6171 JSROOT.addDrawFunc({ name:
"TFolder", icon:
"img_folder", icon2:
"img_folderopen", noinspect:
true, prereq:
"hierarchy", expand:
"JSROOT.Painter.FolderHierarchy" });
6172 JSROOT.addDrawFunc({ name:
"TTask", icon:
"img_task", prereq:
"hierarchy", expand:
"JSROOT.Painter.TaskHierarchy", for_derived:
true });
6173 JSROOT.addDrawFunc({ name:
"TTree", icon:
"img_tree", prereq:
"tree;more2d", expand:
'JSROOT.Painter.TreeHierarchy', func:
'JSROOT.Painter.drawTree', dflt:
"expand", opt:
"player;testio", shift:
"inspect" });
6174 JSROOT.addDrawFunc({ name:
"TNtuple", icon:
"img_tree", prereq:
"tree;more2d", expand:
'JSROOT.Painter.TreeHierarchy', func:
'JSROOT.Painter.drawTree', dflt:
"expand", opt:
"player;testio", shift:
"inspect" });
6175 JSROOT.addDrawFunc({ name:
"TNtupleD", icon:
"img_tree", prereq:
"tree;more2d", expand:
'JSROOT.Painter.TreeHierarchy', func:
'JSROOT.Painter.drawTree', dflt:
"expand", opt:
"player;testio", shift:
"inspect" });
6176 JSROOT.addDrawFunc({ name:
"TBranchFunc", icon:
"img_leaf_method", prereq:
"tree;more2d", func:
'JSROOT.Painter.drawTree', opt:
";dump", noinspect:
true });
6177 JSROOT.addDrawFunc({ name: /^TBranch/, icon:
"img_branch", prereq:
"tree;more2d", func:
'JSROOT.Painter.drawTree', dflt:
"expand", opt:
";dump", ctrl:
"dump", shift:
"inspect", ignore_online:
true });
6178 JSROOT.addDrawFunc({ name: /^TLeaf/, icon:
"img_leaf", prereq:
"tree;more2d", noexpand:
true, func:
'JSROOT.Painter.drawTree', opt:
";dump", ctrl:
"dump", ignore_online:
true });
6179 JSROOT.addDrawFunc({ name:
"TList", icon:
"img_list", prereq:
"hierarchy", func:
"JSROOT.Painter.drawList", expand:
"JSROOT.Painter.ListHierarchy", dflt:
"expand" });
6180 JSROOT.addDrawFunc({ name:
"THashList", sameas:
"TList" });
6181 JSROOT.addDrawFunc({ name:
"TObjArray", sameas:
"TList" });
6182 JSROOT.addDrawFunc({ name:
"TClonesArray", sameas:
"TList" });
6183 JSROOT.addDrawFunc({ name:
"TMap", sameas:
"TList" });
6184 JSROOT.addDrawFunc({ name:
"TColor", icon:
"img_color" });
6185 JSROOT.addDrawFunc({ name:
"TFile", icon:
"img_file", noinspect:
true });
6186 JSROOT.addDrawFunc({ name:
"TMemFile", icon:
"img_file", noinspect:
true });
6187 JSROOT.addDrawFunc({ name:
"TStyle", icon:
"img_question", noexpand:
true });
6188 JSROOT.addDrawFunc({ name:
"Session", icon:
"img_globe" });
6189 JSROOT.addDrawFunc({ name:
"kind:TopFolder", icon:
"img_base" });
6190 JSROOT.addDrawFunc({ name:
"kind:Folder", icon:
"img_folder", icon2:
"img_folderopen", noinspect:
true });
6192 JSROOT.addDrawFunc({ name:
"ROOT::Experimental::TCanvas", icon:
"img_canvas", prereq:
"v7", func:
"JSROOT.v7.drawCanvas", opt:
"", expand_item:
"fPrimitives" });
6195 JSROOT.getDrawHandle =
function(kind, selector) {
6202 if (typeof kind !=
'string')
return null;
6203 if (selector ===
"") selector = null;
6207 if ((selector === null) && (kind in JSROOT.DrawFuncs.cache))
6208 return JSROOT.DrawFuncs.cache[kind];
6210 var search = (kind.indexOf(
"ROOT.")==0) ? kind.substr(5) :
"kind:"+kind, counter = 0;
6211 for (var i=0; i < JSROOT.DrawFuncs.lst.length; ++i) {
6212 var h = JSROOT.DrawFuncs.lst[i];
6213 if (typeof h.name ==
"string") {
6214 if (h.name != search)
continue;
6216 if (!search.match(h.name))
continue;
6219 if (h.sameas !== undefined)
6220 return JSROOT.getDrawHandle(
"ROOT."+h.sameas, selector);
6222 if ((selector === null) || (selector === undefined)) {
6224 if (!(kind in JSROOT.DrawFuncs.cache)) JSROOT.DrawFuncs.cache[kind] = h;
6226 }
else if (typeof selector ==
'string') {
6227 if (!first) first = h;
6230 if (selector ==
"::expand") {
6231 if ((
'expand' in h) || (
'expand_item' in h))
return h;
6234 var opts = h.opt.split(
';');
6235 for (var j=0; j < opts.length; ++j) opts[j] = opts[j].toLowerCase();
6236 if (opts.indexOf(selector.toLowerCase())>=0)
return h;
6238 }
else if (selector === counter) {
6250 JSROOT.addStreamerInfos =
function(lst) {
6253 function CheckBaseClasses(si, lvl) {
6254 if (si.fElements == null)
return null;
6255 if (lvl>10)
return null;
6257 for (var j=0; j<si.fElements.arr.length; ++j) {
6259 var element = si.fElements.arr[j];
6260 if (element.fTypeName !==
'BASE')
continue;
6262 var handle = JSROOT.getDrawHandle(
"ROOT." + element.fName);
6263 if (handle && !handle.for_derived) handle = null;
6266 if (handle === null)
6267 for (var k=0;k<lst.arr.length; ++k)
6268 if (lst.arr[k].fName === element.fName) {
6269 handle = CheckBaseClasses(lst.arr[k], lvl+1);
6273 if (handle && handle.for_derived)
return handle;
6278 for (var n=0;n<lst.arr.length;++n) {
6279 var si = lst.arr[n];
6280 if (JSROOT.getDrawHandle(
"ROOT." + si.fName) !== null)
continue;
6282 var handle = CheckBaseClasses(si, 0);
6284 if (!handle)
continue;
6286 var newhandle = JSROOT.extend({}, handle);
6288 newhandle.name = si.fName;
6289 JSROOT.DrawFuncs.lst.push(newhandle);
6296 JSROOT.getDrawSettings =
function(kind, selector) {
6297 var res = { opts: null, inspect:
false, expand:
false, draw:
false, handle: null };
6298 if (typeof kind !=
'string')
return res;
6299 var allopts = null, isany =
false, noinspect =
false, canexpand =
false;
6300 if (typeof selector !==
'string') selector =
"";
6302 for (var cnt=0;cnt<1000;++cnt) {
6303 var h = JSROOT.getDrawHandle(kind, cnt);
6305 if (!res.handle) res.handle = h;
6306 if (h.noinspect) noinspect =
true;
6307 if (h.expand || h.expand_item || h.can_expand) canexpand =
true;
6308 if (!(
'func' in h))
break;
6310 if (! (
'opt' in h))
continue;
6311 var opts = h.opt.split(
';');
6312 for (var i = 0; i < opts.length; ++i) {
6313 opts[i] = opts[i].toLowerCase();
6314 if ((selector.indexOf(
'nosame')>=0) && (opts[i].indexOf(
'same')==0))
continue;
6316 if (res.opts===null) res.opts = [];
6317 if (res.opts.indexOf(opts[i])<0) res.opts.push(opts[i]);
6319 if (h.theonly)
break;
6322 if (selector.indexOf(
'noinspect')>=0) noinspect =
true;
6324 if (isany && (res.opts===null)) res.opts = [
""];
6327 if (!isany && (kind.indexOf(
"ROOT.")==0) && !noinspect) res.opts = [];
6329 if (!noinspect && res.opts)
6330 res.opts.push(
"inspect");
6332 res.inspect = !noinspect;
6333 res.expand = canexpand;
6334 res.draw = res.opts && (res.opts.length>0);
6341 JSROOT.getDrawOptions =
function(kind, selector) {
6342 return JSROOT.getDrawSettings(kind).opts;
6347 JSROOT.canDraw =
function(classname) {
6348 return JSROOT.getDrawSettings(
"ROOT." + classname).opts !== null;
6371 JSROOT.draw =
function(divid, obj, opt, drawcallback) {
6373 var isdirectdraw =
true;
6375 function completeDraw(painter) {
6376 var callbackfunc = null, ishandle =
false;
6377 if (typeof drawcallback ==
'function') callbackfunc = drawcallback;
else
6378 if (drawcallback && (typeof drawcallback ==
'object') && (typeof drawcallback.func==
'function')) {
6379 callbackfunc = drawcallback.func;
6383 if (ishandle && isdirectdraw) {
6385 if (!painter || painter._ready_called_) { drawcallback.completed =
true;
return painter; }
6388 if (painter && drawcallback && (typeof painter.WhenReady ==
'function'))
6389 painter.WhenReady(callbackfunc);
6391 JSROOT.CallBack(callbackfunc, painter);
6395 if ((obj === null) || (typeof obj !==
'object'))
return completeDraw(null);
6397 if (opt ==
'inspect') {
6398 var func = JSROOT.findFunction(
"JSROOT.Painter.drawInspector");
6399 if (func)
return completeDraw(func(divid, obj));
6400 JSROOT.AssertPrerequisites(
"hierarchy",
function() {
6401 completeDraw(JSROOT.Painter.drawInspector(divid, obj));
6406 var handle = null, painter = null;
6407 if (
'_typename' in obj) handle = JSROOT.getDrawHandle(
"ROOT." + obj._typename, opt);
6408 else if (
'_kind' in obj) handle = JSROOT.getDrawHandle(obj._kind, opt);
6410 if (!handle)
return completeDraw(null);
6412 if (handle.draw_field && obj[handle.draw_field])
6413 return JSROOT.draw(divid, obj[handle.draw_field], opt, drawcallback);
6416 if (opt && (opt.indexOf(
"same")>=0)) {
6417 var main_painter = JSROOT.GetMainPainter(divid);
6418 if (main_painter && (typeof main_painter.PerformDrop ===
'function'))
6419 return main_painter.PerformDrop(obj,
"", null, opt, completeDraw);
6422 return completeDraw(null);
6425 function performDraw() {
6426 if (handle.direct) {
6427 painter =
new TObjectPainter(obj, opt);
6428 painter.csstype = handle.csstype;
6429 painter.SetDivId(divid, 2);
6430 painter.Redraw = handle.func;
6432 painter.DrawingReady();
6434 painter = handle.func(divid, obj, opt);
6436 if (painter && !painter.options) painter.options = { original: opt ||
"" };
6439 return completeDraw(painter);
6442 if (typeof handle.func ==
'function')
return performDraw();
6444 var funcname =
"", prereq =
"";
6445 if (typeof handle.func ==
'object') {
6446 if (
'func' in handle.func) funcname = handle.func.func;
6447 if (
'script' in handle.func) prereq =
"user:" + handle.func.script;
6449 if (typeof handle.func ==
'string') {
6450 funcname = handle.func;
6451 if ((
'prereq' in handle) && (typeof handle.prereq ==
'string')) prereq = handle.prereq;
6452 if ((
'script' in handle) && (typeof handle.script ==
'string')) prereq +=
";user:" + handle.script;
6455 if (funcname.length === 0)
return completeDraw(null);
6458 var func = JSROOT.findFunction(funcname);
6461 return performDraw();
6464 if (prereq.length === 0)
return completeDraw(null);
6466 isdirectdraw =
false;
6468 JSROOT.AssertPrerequisites(prereq,
function() {
6469 var func = JSROOT.findFunction(funcname);
6471 alert(
'Fail to find function ' + funcname +
' after loading ' + prereq);
6472 return completeDraw(null);
6493 JSROOT.redraw =
function(divid, obj, opt, callback) {
6494 if (!obj)
return JSROOT.CallBack(callback, null);
6495 var dummy =
new TObjectPainter();
6496 dummy.SetDivId(divid, -1);
6497 var can_painter = dummy.canv_painter();
6500 if (obj._typename) handle = JSROOT.getDrawHandle(
"ROOT." + obj._typename);
6501 if (handle && handle.draw_field && obj[handle.draw_field])
6502 obj = obj[handle.draw_field];
6505 if (obj._typename ===
"TCanvas") {
6506 can_painter.RedrawObject(obj);
6507 JSROOT.CallBack(callback, can_painter);
6511 for (var i = 0; i < can_painter.painters.length; ++i) {
6512 var painter = can_painter.painters[i];
6513 if (painter.MatchObjectType(obj._typename))
6514 if (painter.UpdateObject(obj, opt)) {
6515 can_painter.RedrawPad();
6516 JSROOT.CallBack(callback, painter);
6523 JSROOT.console(
"Cannot find painter to update object of type " + obj._typename);
6525 JSROOT.cleanup(divid);
6527 return JSROOT.draw(divid, obj, opt, callback);
6537 JSROOT.StoreJSON =
function(divid) {
6538 var p =
new TObjectPainter;
6539 p.SetDivId(divid,-1);
6541 var canp = p.canv_painter();
6542 return canp ? canp.ProduceJSON() :
"";
6558 JSROOT.MakeSVG =
function(args, callback) {
6560 if (!args) args = {};
6562 if (!args.object)
return JSROOT.CallBack(callback, null);
6564 if (!args.width) args.width = 1200;
6565 if (!args.height) args.height = 800;
6567 function build(main) {
6569 main.attr(
"width", args.width).attr(
"height", args.height);
6571 main.style(
"width", args.width+
"px").style(
"height", args.height+
"px");
6573 JSROOT.svg_workaround = undefined;
6575 JSROOT.draw(main.node(), args.object, args.option ||
"",
function(painter) {
6577 var has_workarounds = JSROOT.Painter.ProcessSVGWorkarounds && JSROOT.svg_workaround;
6579 main.select(
'svg').attr(
"xmlns",
"http://www.w3.org/2000/svg")
6580 .attr(
"xmlns:xlink",
"http://www.w3.org/1999/xlink")
6581 .attr(
"width", args.width)
6582 .attr(
"height", args.height)
6583 .attr(
"style", null).attr(
"class", null).attr(
"x", null).attr(
"y", null);
6585 var svg = main.html();
6588 svg = svg.replace(/xlink_href_nodejs=/g,
"xlink:href=");
6590 if (has_workarounds)
6591 svg = JSROOT.Painter.ProcessSVGWorkarounds(svg);
6593 svg = svg.replace(/url\(\"\;\#(\w+)\"\;\)/g,
"url(#$1)")
6594 .replace(/
class=\
"\w*\"/g,"") // remove all classes
6595 .replace(/<g transform=\"translate\(\d+\,\d+\)\"><\/g>/g,"") // remove all empty groups with transform
6596 .replace(/<g><\/g>/g,""); // remove all empty groups
6598 if (svg.indexOf("xlink:href
")<0)
6599 svg = svg.replace(/ xmlns:xlink=\"http:\/\/www.w3.org\/1999\/xlink\"/g,"");
6603 JSROOT.CallBack(callback, svg);
6607 if (!JSROOT.nodejs) {
6608 build(d3.select(window.document).append("div
").style("visible
", "hidden
"));
6609 } else if (JSROOT.nodejs_document) {
6610 build(JSROOT.nodejs_window.d3.select('body').append('div'));
6612 // use eval while old minifier is not able to parse newest Node.js syntax
6613 eval('const { JSDOM } = require("jsdom
"); JSROOT.nodejs_window = (new JSDOM("<!DOCTYPE html>hello
")).window;');
6614 JSROOT.nodejs_document = JSROOT.nodejs_window.document; // used with three.js
6615 JSROOT.nodejs_window.d3 = d3.select(JSROOT.nodejs_document); //get d3 into the dom
6616 build(JSROOT.nodejs_window.d3.select('body').append('div'));
6634 JSROOT.resize = function(divid, arg) {
6635 if (arg === true) arg = { force: true }; else
6636 if (typeof arg !== 'object') arg = null;
6637 var dummy = new TObjectPainter(), done = false;
6638 dummy.SetDivId(divid, -1);
6639 dummy.ForEachPainter(function(painter) {
6640 if (!done && typeof painter.CheckResize == 'function')
6641 done = painter.CheckResize(arg);
6650 JSROOT.CheckElementResize = JSROOT.resize;
6654 JSROOT.GetMainPainter = function(divid) {
6655 var dummy = new JSROOT.TObjectPainter();
6656 dummy.SetDivId(divid, -1);
6657 return dummy.main_painter(true);
6665 JSROOT.cleanup = function(divid) {
6666 var dummy = new TObjectPainter(), lst = [];
6667 dummy.SetDivId(divid, -1);
6668 dummy.ForEachPainter(function(painter) {
6669 if (lst.indexOf(painter) < 0) lst.push(painter);
6671 for (var n=0;n<lst.length;++n) lst[n].Cleanup();
6672 dummy.select_main().html("");
6683 JSROOT.progress = function(msg, tmout) {
6684 if (JSROOT.BatchMode || (typeof document === 'undefined')) return;
6685 var id = "jsroot_progressbox
",
6686 box = d3.select("#
"+id);
6688 if (!JSROOT.gStyle.ProgressBox) return box.remove();
6690 if ((arguments.length == 0) || !msg) {
6691 if ((tmout !== -1) || (!box.empty() && box.property("with_timeout
"))) box.remove();
6696 box = d3.select(document.body)
6702 box.property("with_timeout
", false);
6704 if (typeof msg === "string") {
6705 box.select("p
").html(msg);
6708 box.node().appendChild(msg);
6711 if (!isNaN(tmout) && (tmout>0)) {
6712 box.property("with_timeout
", true);
6713 setTimeout(JSROOT.progress.bind(JSROOT,'',-1), tmout);
6722 JSROOT.CloseCurrentWindow = function() {
6723 if (!window) return;
6725 window.open('','_self').close();
6728 Painter.createRootColors();
6730 JSROOT.LongPollSocket = LongPollSocket;
6731 JSROOT.WebWindowHandle = WebWindowHandle;
6732 JSROOT.DrawOptions = DrawOptions;
6733 JSROOT.ColorPalette = ColorPalette;
6734 JSROOT.TAttLineHandler = TAttLineHandler;
6735 JSROOT.TAttFillHandler = TAttFillHandler;
6736 JSROOT.TAttMarkerHandler = TAttMarkerHandler;
6737 JSROOT.TBasePainter = TBasePainter;
6738 JSROOT.TObjectPainter = TObjectPainter;
6739 JSROOT.TooltipHandler = TooltipHandler;