@hpcc-js/layout 2.51.1 → 2.51.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/ChartPanel.ts CHANGED
@@ -1,656 +1,656 @@
1
- import { IHighlight } from "@hpcc-js/api";
2
- import { Button, Database, IconBar, ProgressBar, Spacer, SVGWidget, Text, TitleBar, ToggleButton, Utility, Widget } from "@hpcc-js/common";
3
- import type { XYAxis } from "@hpcc-js/chart";
4
- import { Table } from "@hpcc-js/dgrid2";
5
- import { select as d3Select } from "d3-selection";
6
- import { Border2 } from "./Border2";
7
- import { Carousel } from "./Carousel";
8
- import { Legend } from "./Legend";
9
- import { Modal } from "./Modal";
10
-
11
- import "../src/ChartPanel.css";
12
-
13
- export class ChartPanel extends Border2 implements IHighlight {
14
-
15
- protected _legend = new Legend(this).enableOverflow(true);
16
- protected _progressBar = new ProgressBar();
17
- protected _autoScale = false;
18
- protected _resolutions = {
19
- tiny: { width: 100, height: 100 },
20
- small: { width: 300, height: 300 }
21
- };
22
- private _modal = new Modal();
23
- private _highlight: boolean;
24
- private _scale: number;
25
- private _orig_size: any;
26
-
27
- private _toggleInfo = new ToggleButton().faChar("fa-info-circle").tooltip(".Description")
28
- .selected(false)
29
- .on("enabled", () => {
30
- return this.description() !== "";
31
- })
32
- .on("click", () => {
33
- if (this._toggleInfo.selected()) {
34
- this._modal
35
- .title(this.title())
36
- .widget(new Text().text(this.description()))
37
- .show(true)
38
- .render()
39
- ;
40
-
41
- const origCloseFunc = this._modal._close;
42
- this._modal._close = () => {
43
- this._toggleInfo
44
- .selected(false)
45
- .render()
46
- ;
47
- this._modal._close = origCloseFunc;
48
- };
49
- }
50
- })
51
- .on("mouseMove", () => {
52
- /*
53
- this._modal.showPreview(true).render(n => {
54
- n.resize().render();
55
- });
56
- */
57
- })
58
- .on("mouseOut", () => {
59
- /*
60
- if (this._modal.showPreview()) {
61
- this._modal.show(false).showPreview(false).render();
62
- }
63
- */
64
- });
65
-
66
- private _toggleData = new ToggleButton().faChar("fa-table").tooltip("Data")
67
- .on("click", () => {
68
- this.dataVisible(this._toggleData.selected());
69
- this.render();
70
- });
71
-
72
- private _buttonDownload = new Button().faChar("fa-download").tooltip("Download")
73
- .on("click", () => {
74
- this.downloadCSV();
75
- });
76
-
77
- private _buttonDownloadImage = new Button().faChar("fa-image").tooltip("Download Image")
78
- .on("click", () => {
79
- this.downloadPNG();
80
- });
81
-
82
- private _toggleLegend = new ToggleButton().faChar("fa-list-ul").tooltip("Legend")
83
- .selected(false)
84
- .on("click", () => {
85
- const selected = this._toggleLegend.selected();
86
- if (this.legendPosition() === "bottom") {
87
- this.showBottom(selected);
88
- } else if (this.legendPosition() === "right") {
89
- this.showRight(selected);
90
- }
91
- this.legendVisible(selected);
92
- this.render();
93
- });
94
-
95
- protected _spacer = new Spacer();
96
-
97
- _titleBar = new TitleBar().buttons([this._toggleData, this._buttonDownload, this._buttonDownloadImage, this._spacer, this._toggleLegend]);
98
-
99
- protected _carousel = new Carousel();
100
- protected _table = new Table();
101
- protected _widget: Widget;
102
-
103
- protected _hideLegendToggleList = ["dgrid_Table"];
104
-
105
- constructor() {
106
- super();
107
- this._tag = "div";
108
- }
109
-
110
- fields(): Database.Field[];
111
- fields(_: Database.Field[]): this;
112
- fields(_?: Database.Field[]): this | Database.Field[] {
113
- if (!arguments.length) return super.fields();
114
- super.fields(_);
115
- this._legend.fields(_);
116
- this.refreshFields();
117
- return this;
118
- }
119
- refreshFields() {
120
- this._widget.fields(this._legend.filteredFields());
121
- this._table.fields(this._legend.filteredFields());
122
- return this;
123
- }
124
-
125
- columns(): string[];
126
- columns(_: string[], asDefault?: boolean): this;
127
- columns(_?: string[], asDefault?: boolean): string[] | this {
128
- if (!arguments.length) return super.columns();
129
- super.columns(_, asDefault);
130
- this._legend.columns(_, asDefault);
131
- this.refreshColumns();
132
- return this;
133
- }
134
- refreshColumns() {
135
- this._widget.columns(this._legend.filteredColumns());
136
- this._table.columns(this._legend.filteredColumns());
137
- return this;
138
- }
139
-
140
- data(_?) {
141
- if (!arguments.length) return super.data();
142
- super.data(_);
143
- this._legend.data(_);
144
- this.refreshData();
145
- return this;
146
- }
147
- refreshData() {
148
- this._widget.data(this._legend.filteredData());
149
- this._table.data(this._legend.filteredData());
150
- return this;
151
- }
152
-
153
- highlight(): boolean;
154
- highlight(_: boolean): this;
155
- highlight(_?: boolean): boolean | this {
156
- if (!arguments.length) return this._highlight;
157
- this._highlight = _;
158
- return this;
159
- }
160
-
161
- startProgress() {
162
- this._progressBar.start();
163
- }
164
-
165
- finishProgress() {
166
- this._progressBar.finish();
167
- }
168
-
169
- buttons(): Widget[];
170
- buttons(_: Widget[]): this;
171
- buttons(_?: Widget[]): this | Widget[] {
172
- if (!arguments.length) return this._titleBar.buttons();
173
- this._titleBar.buttons(_);
174
- return this;
175
- }
176
-
177
- downloadCSV() {
178
- const namePrefix = this.downloadTitle() ? this.downloadTitle() : this.title() ? this.title() : "data";
179
- const nameSuffix = this.downloadTimestampSuffix() ? "_" + Utility.timestamp() : "";
180
- Utility.downloadString("CSV", this._widget.export("CSV"), namePrefix + nameSuffix);
181
- return this;
182
- }
183
-
184
- downloadPNG() {
185
- const widget = this.widget();
186
- if (widget instanceof SVGWidget) {
187
- if (!this.legendVisible()) {
188
- widget.downloadPNG(this.title());
189
- } else {
190
- widget.downloadPNG(this.title(), undefined, this._legend);
191
- }
192
- }
193
- return this;
194
- }
195
-
196
- highlightColumn(column?: string): this {
197
- if (column) {
198
- const cssTag = `series-${this.cssTag(column)}`;
199
- this._centerWA.element().selectAll(".series")
200
- .each(function () {
201
- const element = d3Select(this);
202
- const highlight = element.classed(cssTag);
203
- element
204
- .classed("highlight", highlight)
205
- .classed("lowlight", !highlight)
206
- ;
207
- })
208
- ;
209
- } else {
210
- this._centerWA.element().selectAll(".series")
211
- .classed("highlight", false)
212
- .classed("lowlight", false)
213
- ;
214
- }
215
- return this;
216
- }
217
-
218
- getResponsiveMode(): "tiny" | "small" | "regular" | "none" {
219
- if (!this.enableAutoscaling()) return "none";
220
- if (!this._autoScale) return "regular";
221
- if (this.size().width <= this._resolutions.tiny.width || this.size().height <= this._resolutions.tiny.height) {
222
- return "tiny";
223
- } else if (this.size().width <= this._resolutions.small.width || this.size().height <= this._resolutions.small.height) {
224
- return "small";
225
- }
226
- return "regular";
227
- }
228
-
229
- setOrigSize() {
230
- this._orig_size = JSON.parse(JSON.stringify(this.size()));
231
- }
232
-
233
- enter(domNode, element) {
234
- super.enter(domNode, element);
235
- this._modal
236
- .target(this.target())
237
- .relativeTargetId(this.id())
238
- ;
239
-
240
- this.top(this._titleBar);
241
- this.center(this._carousel);
242
-
243
- this._legend
244
- .targetWidget(this._widget)
245
- .orientation("vertical")
246
- .title("")
247
- .visible(false)
248
- ;
249
-
250
- this._progressBar.enter(domNode, element);
251
- this.setOrigSize();
252
- }
253
-
254
- preUpdateTiny(element) {
255
- element.selectAll("div.body,div.title-text,div.icon-bar").style("display", "none");
256
- }
257
-
258
- preUpdateSmall(element) {
259
- const scale_x = this._orig_size.width / this._resolutions.small.width;
260
- const scale_y = this._orig_size.height / this._resolutions.small.height;
261
- this._scale = Math.min(scale_x, scale_y);
262
- const x_is_smaller = this._scale === scale_x;
263
- this.size({
264
- width: x_is_smaller ? this._resolutions.small.width : this._orig_size.width * (1 / this._scale),
265
- height: !x_is_smaller ? this._resolutions.small.height : this._orig_size.height * (1 / this._scale)
266
- });
267
- element.select("div.title-icon").style("position", "static");
268
- element.selectAll("lhs").style("display", "none");
269
- element.selectAll("div.body,div.title-text,div.icon-bar").style("display", "");
270
- element.selectAll("div.data-count").style("visibility", "hidden");
271
- element.style("transform", `scale(${this._scale})`);
272
- }
273
-
274
- preUpdateRegular(element) {
275
- element.selectAll("div.body,div.title-text,div.icon-bar").style("display", "");
276
- element.selectAll("div.data-count").style("visibility", "hidden");
277
- element.select("div.title-icon").style("position", "static");
278
- element.style("transform", "translate(0px,0px) scale(1)");
279
- }
280
-
281
- private _prevdataVisible;
282
- private _prevlegendVisible;
283
- private _prevLegendPosition;
284
- private _prevChartDataFamily;
285
- private _prevChart;
286
- private _prevButtons;
287
- update(domNode, element) {
288
- super.update(domNode, element);
289
- if (this._table && this.widget_exists() && this.widget().class().indexOf("chart_XYAxis") >= 0) {
290
- const chart = this.widget() as XYAxis;
291
- this._table.columns().forEach((column, idx) => {
292
- switch (idx === 0 ? chart.xAxisType() : chart.yAxisType()) {
293
- case "linear":
294
- case "log":
295
- case "pow":
296
- this._table.columnType(column, "number");
297
- break;
298
- case "time":
299
- this._table.columnType(column, "time");
300
- break;
301
- case "ordinal":
302
- default:
303
- this._table.columnType(column, "string");
304
- }
305
- this._table.columnPattern(column, idx === 0 ? chart.xAxisTypeTimePattern() : chart.yAxisTypeTimePattern());
306
- this._table.columnFormat(column, idx === 0 ? chart.xAxisTickFormat() : chart.yAxisTickFormat());
307
- });
308
- }
309
- }
310
-
311
- preUpdate(domNode, element) {
312
-
313
- super.preUpdate(domNode, element);
314
-
315
- if (this._prevLegendPosition !== this.legendPosition()) {
316
- if (this._legend.target() !== null) this._legend.target(null);
317
- if (this._prevLegendPosition !== undefined) {
318
- this.swap(this._prevLegendPosition, this.legendPosition());
319
- } else {
320
- this[this.legendPosition()](this._legend);
321
- }
322
- if (this.legendPosition() === "right") {
323
- this.rightOverflowX("hidden");
324
- this.rightOverflowY("auto");
325
- this.bottomOverflowX("visible");
326
- this.bottomOverflowY("visible");
327
- } else {
328
- this.rightOverflowX("visible");
329
- this.rightOverflowY("visible");
330
- this.bottomOverflowX("auto");
331
- this.bottomOverflowY("hidden");
332
- }
333
- this._prevLegendPosition = this.legendPosition();
334
- }
335
-
336
- if (this._prevdataVisible !== this.dataVisible()) {
337
- this._prevdataVisible = this.dataVisible();
338
- this._toggleData.selected(this._prevdataVisible);
339
- this._legend.visible(this._prevlegendVisible && !this._prevdataVisible);
340
- this._carousel.active(this._prevdataVisible ? 1 : 0);
341
- }
342
-
343
- if (this._prevlegendVisible !== this.legendVisible()) {
344
- this._prevlegendVisible = this.legendVisible();
345
- this._toggleLegend.selected(this._prevlegendVisible);
346
- this._legend.visible(this._prevlegendVisible && !this._prevdataVisible);
347
- }
348
-
349
- this._legend.orientation(this.legendPosition() === "bottom" ? "horizontal" : "vertical");
350
-
351
- this.showLeft(!this.left());
352
-
353
- switch (this.getResponsiveMode()) {
354
- case "tiny":
355
- this.preUpdateTiny(element);
356
- break;
357
- case "small":
358
- this.preUpdateSmall(element);
359
- break;
360
- case "regular":
361
- this.preUpdateRegular(element);
362
- break;
363
- }
364
-
365
- const chart = this._widget.classID() === "composite_MultiChart" ? this._widget["chart"]() : this._widget;
366
- this._legend.dataFamily(chart._dataFamily || "any");
367
-
368
- if (this._prevChartDataFamily !== this._legend.dataFamily()) {
369
- this._prevChartDataFamily = this._legend.dataFamily();
370
- switch (this._prevChartDataFamily) {
371
- case "any":
372
- this._toggleLegend.selected(false);
373
- this._legend.visible(false);
374
- break;
375
- }
376
- }
377
- element.style("box-shadow", this.highlight() ? `inset 0px 0px 0px ${this.highlightSize()}px ${this.highlightColor()}` : "none");
378
-
379
- if (this._hideLegendToggleList.indexOf(chart.classID()) !== -1) {
380
- this._spacer.visible(false);
381
- this._toggleLegend.visible(false);
382
- } else {
383
- this._spacer.visible(true);
384
- this._toggleLegend.visible(true);
385
- }
386
- if (this._prevChart !== chart) {
387
- this._prevChart = chart;
388
- const widgetIconBar = chart ? chart["_titleBar"] || chart["_iconBar"] : undefined;
389
- if (widgetIconBar && widgetIconBar instanceof IconBar) {
390
- this._prevButtons = this._prevButtons || [...this.buttons()];
391
- const buttons: Widget[] = [
392
- ...widgetIconBar.buttons(),
393
- new Spacer(),
394
- ...this._prevButtons
395
- ];
396
- widgetIconBar.buttons([]).render();
397
- this.buttons(buttons);
398
- } else if (this._prevButtons) {
399
- this.buttons(this._prevButtons);
400
- }
401
- }
402
-
403
- const hiddenButtons = [];
404
- if (!this.dataButtonVisible()) hiddenButtons.push(this._toggleData);
405
- if (!this.downloadButtonVisible()) hiddenButtons.push(this._buttonDownload);
406
- if (!this.downloadImageButtonVisible()) hiddenButtons.push(this._buttonDownloadImage);
407
- if (!this.legendButtonVisible()) hiddenButtons.push(this._toggleLegend);
408
- this._buttonDownloadImage.enabled(this.widget() instanceof SVGWidget);
409
- this._titleBar
410
- .hiddenButtons(hiddenButtons)
411
- .visible(this.titleVisible())
412
- ;
413
- this.topOverlay(this.titleOverlay() || !this.titleVisible());
414
- }
415
-
416
- postUpdate(domNode, element) {
417
- super.postUpdate(domNode, element);
418
-
419
- switch (this.getResponsiveMode()) {
420
- case "tiny":
421
- this.postUpdateTiny(element);
422
- break;
423
- case "small":
424
- this.postUpdateSmall(element);
425
- break;
426
- case "regular":
427
- this.postUpdateRegular(element);
428
- break;
429
- }
430
- }
431
-
432
- postUpdateTiny(element) {
433
- element.selectAll("div.body,div.title-text,div.icon-bar").style("display", "none");
434
- element.selectAll("div.data-count")
435
- .style("visibility", "visible")
436
- .style("font-size", (this.titleIconFontSize() / 3) + "px")
437
- .style("line-height", (this.titleIconFontSize() / 3) + "px")
438
- .style("left", this.titleIconFontSize() + "px")
439
- .text(this.data().length)
440
- ;
441
- element.style("transform", "translate(0px,0px) scale(1)");
442
- const iconDiv = element.selectAll("div.title-icon");
443
- const _node = iconDiv.node();
444
- const _container = element.node().parentElement;
445
- const containerRect = _container.getBoundingClientRect();
446
- if (_node) {
447
- const rect = iconDiv.node().getBoundingClientRect();
448
- const icon_top = containerRect.height / 2;
449
- iconDiv
450
- .style("position", "absolute")
451
- .style("left", `calc(50% - ${rect.width / 2}px)`)
452
- .style("top", `${icon_top - (rect.height / 2)}px`)
453
- ;
454
- element.selectAll("div.data-count")
455
- .style("position", "absolute")
456
- .style("left", `calc(50% + ${rect.width / 2}px)`)
457
- .style("top", `${icon_top - (rect.height / 2)}px`)
458
- ;
459
- }
460
- }
461
-
462
- postUpdateSmall(element) {
463
- element.selectAll("lhs").style("display", "none"); // TODO: a bug in Border2?
464
- element.selectAll("div.title-icon").style("position", "static");
465
- element.selectAll("div.body,div.title-text,div.icon-bar").style("display", "");
466
- element.selectAll("div.data-count").style("visibility", "hidden");
467
- const rect = element.node().getBoundingClientRect();
468
- const parentRect = element.node().parentElement.getBoundingClientRect();
469
- element.style("transform", `translate(${parentRect.x - rect.x}px, ${parentRect.y - rect.y}px) scale(${this._scale})`);
470
- }
471
-
472
- postUpdateRegular(element) {
473
- element.selectAll("div.title-icon").style("position", "static");
474
- element.selectAll("div.body,div.title-text,div.icon-bar").style("display", "");
475
- element.selectAll("div.data-count").style("visibility", "hidden");
476
- }
477
-
478
- exit(domNode, element) {
479
- this._progressBar.exit(domNode, element);
480
-
481
- this.right(null);
482
- this._legend.target(null);
483
- this.center(null);
484
- this._carousel.target(null);
485
- this.top(null);
486
- this._titleBar.target(null);
487
-
488
- this._modal.target(null);
489
-
490
- delete this._prevChart;
491
- delete this._prevButtons;
492
- delete this._prevChartDataFamily;
493
- delete this._prevPos;
494
- delete this._prevdataVisible;
495
- delete this._prevlegendVisible;
496
-
497
- super.exit(domNode, element);
498
- }
499
-
500
- // Event Handlers ---
501
- // Events ---
502
- click(row, column, selected) {
503
- // console.log("Click: " + JSON.stringify(row) + ", " + column + ", " + selected);
504
- }
505
-
506
- dblclick(row, column, selected) {
507
- // console.log("Double click: " + JSON.stringify(row) + ", " + column + ", " + selected);
508
- }
509
-
510
- vertex_click(row, col, sel, more) {
511
- if (more && more.vertex) {
512
- // console.log("Vertex click: " + more.vertex.id());
513
- }
514
- }
515
-
516
- vertex_dblclick(row, col, sel, more) {
517
- if (more && more.vertex) {
518
- // console.log("Vertex double click: " + more.vertex.id());
519
- }
520
- }
521
-
522
- edge_click(row, col, sel, more) {
523
- if (more && more.edge) {
524
- // console.log("Edge click: " + more.edge.id());
525
- }
526
- }
527
-
528
- edge_dblclick(row, col, sel, more) {
529
- if (more && more.edge) {
530
- // console.log("Edge double click: " + more.edge.id());
531
- }
532
- }
533
- }
534
- ChartPanel.prototype._class += " layout_ChartPanel";
535
-
536
- export interface ChartPanel {
537
- title(): string;
538
- title(_: string): this;
539
- titleVisible(): boolean;
540
- titleVisible(_: boolean): this;
541
- titleOverlay(): boolean;
542
- titleOverlay(_: boolean): this;
543
- title_exists(): boolean;
544
- titleFontSize(): number;
545
- titleFontSize(_: number): this;
546
- titleFontSize_exists(): boolean;
547
- titleIconFontSize(): number;
548
- titleIconFontSize(_: number): this;
549
- titleIconFontSize_exists(): boolean;
550
- dataVisible(): boolean;
551
- dataVisible(_: boolean): this;
552
- dataButtonVisible(): boolean;
553
- dataButtonVisible(_: boolean): this;
554
- downloadButtonVisible(): boolean;
555
- downloadButtonVisible(_: boolean): this;
556
- downloadImageButtonVisible(): boolean;
557
- downloadImageButtonVisible(_: boolean): this;
558
- downloadTitle(): string;
559
- downloadTitle(_: string): this;
560
- downloadTimestampSuffix(): boolean;
561
- downloadTimestampSuffix(_: boolean): this;
562
- legendVisible(): boolean;
563
- legendVisible(_: boolean): this;
564
- legendButtonVisible(): boolean;
565
- legendButtonVisible(_: boolean): this;
566
- legendPosition(): "right" | "bottom";
567
- legendPosition(_: "right" | "bottom"): this;
568
- description(): string;
569
- description(_: string): this;
570
- description_exists(): boolean;
571
- widget(): Widget;
572
- widget(_: Widget): this;
573
- widget_exists(): boolean;
574
- enableAutoscaling(): boolean;
575
- enableAutoscaling(_: boolean): this;
576
- enableAutoscaling_exists(): boolean;
577
- highlightSize(): number;
578
- highlightSize(_: number): this;
579
- highlightSize_exists(): boolean;
580
- highlightColor(): string;
581
- highlightColor(_: string): this;
582
- highlightColor_exists(): boolean;
583
- }
584
-
585
- ChartPanel.prototype.publishReset();
586
- ChartPanel.prototype.publishProxy("title", "_titleBar");
587
- ChartPanel.prototype.publish("titleVisible", true, "boolean");
588
- ChartPanel.prototype.publish("titleOverlay", false, "boolean");
589
- ChartPanel.prototype.publishProxy("titleIcon", "_titleBar");
590
- ChartPanel.prototype.publishProxy("titleIconFont", "_titleBar");
591
- ChartPanel.prototype.publishProxy("titleFont", "_titleBar");
592
- ChartPanel.prototype.publishProxy("titleIconFontSize", "_titleBar");
593
- ChartPanel.prototype.publishProxy("titleFontSize", "_titleBar");
594
- ChartPanel.prototype.publishProxy("description", "_titleBar");
595
- ChartPanel.prototype.publishProxy("descriptionFont", "_titleBar");
596
- ChartPanel.prototype.publishProxy("descriptionFontSize", "_titleBar");
597
- ChartPanel.prototype.publish("dataVisible", false, "boolean", "Show data table");
598
- ChartPanel.prototype.publish("dataButtonVisible", true, "boolean", "Show data table button");
599
- ChartPanel.prototype.publish("downloadButtonVisible", true, "boolean", "Show data download button");
600
- ChartPanel.prototype.publish("downloadImageButtonVisible", false, "boolean", "Show image download button");
601
- ChartPanel.prototype.publish("downloadTitle", "", "string", "File name when downloaded");
602
- ChartPanel.prototype.publish("downloadTimestampSuffix", true, "boolean", "Use timestamp as file name suffix");
603
- ChartPanel.prototype.publish("legendVisible", false, "boolean", "Show legend");
604
- ChartPanel.prototype.publish("legendButtonVisible", true, "boolean", "Show legend button");
605
- ChartPanel.prototype.publish("legendPosition", "right", "set", "Position of legend", ["right", "bottom"]);
606
- ChartPanel.prototype.publishProxy("legend_labelMaxWidth", "_legend", "labelMaxWidth");
607
- ChartPanel.prototype.publishProxy("legend_showSeriesTotal", "_legend", "showSeriesTotal");
608
- ChartPanel.prototype.publishProxy("legend_showLegendTotal", "_legend", "showLegendTotal");
609
- ChartPanel.prototype.publishProxy("legend_itemPadding", "_legend", "itemPadding");
610
- ChartPanel.prototype.publishProxy("legend_shapeRadius", "_legend", "shapeRadius");
611
- ChartPanel.prototype.publishProxy("legend_symbolType", "_legend", "symbolType");
612
- ChartPanel.prototype.publishProxy("legend_labelAlign", "_legend", "labelAlign");
613
- ChartPanel.prototype.publish("widget", null, "widget", "Widget", undefined, { render: false });
614
- ChartPanel.prototype.publish("enableAutoscaling", false, "boolean");
615
- ChartPanel.prototype.publish("highlightSize", 4, "number");
616
- ChartPanel.prototype.publish("highlightColor", "#e67e22", "html-color");
617
- ChartPanel.prototype.publishProxy("progress_halfLife", "_progressBar", "halfLife");
618
- ChartPanel.prototype.publishProxy("progress_decay", "_progressBar", "decay");
619
- ChartPanel.prototype.publishProxy("progress_size", "_progressBar", "size");
620
- ChartPanel.prototype.publishProxy("progress_color", "_progressBar", "color");
621
- ChartPanel.prototype.publishProxy("progress_blurBar", "_progressBar", "blurBar");
622
- ChartPanel.prototype.publishProxy("progress_blurSize", "_progressBar", "blurSize");
623
- ChartPanel.prototype.publishProxy("progress_blurColor", "_progressBar", "blurColor");
624
- ChartPanel.prototype.publishProxy("progress_blurOpacity", "_progressBar", "blurOpacity");
625
-
626
- ChartPanel.prototype.widget = function (_?) {
627
- if (!arguments.length) return this._widget;
628
- this._carousel.widgets([_, this._table]);
629
- this._widget = _;
630
- this._widget
631
- .fields(this._legend.filteredFields())
632
- .data(this._legend.filteredData())
633
- ;
634
-
635
- const context = this;
636
- const tmpAny = this._widget as any;
637
- tmpAny.click = function () {
638
- context.click.apply(context, arguments);
639
- };
640
- tmpAny.dblclick = function () {
641
- context.dblclick.apply(context, arguments);
642
- };
643
- tmpAny.vertex_click = function () {
644
- context.vertex_click.apply(context, arguments);
645
- };
646
- tmpAny.vertex_dblclick = function () {
647
- context.vertex_dblclick.apply(context, arguments);
648
- };
649
- tmpAny.edge_click = function () {
650
- context.edge_click.apply(context, arguments);
651
- };
652
- tmpAny.edge_dblclick = function () {
653
- context.edge_dblclick.apply(context, arguments);
654
- };
655
- return this;
656
- };
1
+ import { IHighlight } from "@hpcc-js/api";
2
+ import { Button, Database, IconBar, ProgressBar, Spacer, SVGWidget, Text, TitleBar, ToggleButton, Utility, Widget } from "@hpcc-js/common";
3
+ import type { XYAxis } from "@hpcc-js/chart";
4
+ import { Table } from "@hpcc-js/dgrid2";
5
+ import { select as d3Select } from "d3-selection";
6
+ import { Border2 } from "./Border2";
7
+ import { Carousel } from "./Carousel";
8
+ import { Legend } from "./Legend";
9
+ import { Modal } from "./Modal";
10
+
11
+ import "../src/ChartPanel.css";
12
+
13
+ export class ChartPanel extends Border2 implements IHighlight {
14
+
15
+ protected _legend = new Legend(this).enableOverflow(true);
16
+ protected _progressBar = new ProgressBar();
17
+ protected _autoScale = false;
18
+ protected _resolutions = {
19
+ tiny: { width: 100, height: 100 },
20
+ small: { width: 300, height: 300 }
21
+ };
22
+ private _modal = new Modal();
23
+ private _highlight: boolean;
24
+ private _scale: number;
25
+ private _orig_size: any;
26
+
27
+ private _toggleInfo = new ToggleButton().faChar("fa-info-circle").tooltip(".Description")
28
+ .selected(false)
29
+ .on("enabled", () => {
30
+ return this.description() !== "";
31
+ })
32
+ .on("click", () => {
33
+ if (this._toggleInfo.selected()) {
34
+ this._modal
35
+ .title(this.title())
36
+ .widget(new Text().text(this.description()))
37
+ .show(true)
38
+ .render()
39
+ ;
40
+
41
+ const origCloseFunc = this._modal._close;
42
+ this._modal._close = () => {
43
+ this._toggleInfo
44
+ .selected(false)
45
+ .render()
46
+ ;
47
+ this._modal._close = origCloseFunc;
48
+ };
49
+ }
50
+ })
51
+ .on("mouseMove", () => {
52
+ /*
53
+ this._modal.showPreview(true).render(n => {
54
+ n.resize().render();
55
+ });
56
+ */
57
+ })
58
+ .on("mouseOut", () => {
59
+ /*
60
+ if (this._modal.showPreview()) {
61
+ this._modal.show(false).showPreview(false).render();
62
+ }
63
+ */
64
+ });
65
+
66
+ private _toggleData = new ToggleButton().faChar("fa-table").tooltip("Data")
67
+ .on("click", () => {
68
+ this.dataVisible(this._toggleData.selected());
69
+ this.render();
70
+ });
71
+
72
+ private _buttonDownload = new Button().faChar("fa-download").tooltip("Download")
73
+ .on("click", () => {
74
+ this.downloadCSV();
75
+ });
76
+
77
+ private _buttonDownloadImage = new Button().faChar("fa-image").tooltip("Download Image")
78
+ .on("click", () => {
79
+ this.downloadPNG();
80
+ });
81
+
82
+ private _toggleLegend = new ToggleButton().faChar("fa-list-ul").tooltip("Legend")
83
+ .selected(false)
84
+ .on("click", () => {
85
+ const selected = this._toggleLegend.selected();
86
+ if (this.legendPosition() === "bottom") {
87
+ this.showBottom(selected);
88
+ } else if (this.legendPosition() === "right") {
89
+ this.showRight(selected);
90
+ }
91
+ this.legendVisible(selected);
92
+ this.render();
93
+ });
94
+
95
+ protected _spacer = new Spacer();
96
+
97
+ _titleBar = new TitleBar().buttons([this._toggleData, this._buttonDownload, this._buttonDownloadImage, this._spacer, this._toggleLegend]);
98
+
99
+ protected _carousel = new Carousel();
100
+ protected _table = new Table();
101
+ protected _widget: Widget;
102
+
103
+ protected _hideLegendToggleList = ["dgrid_Table"];
104
+
105
+ constructor() {
106
+ super();
107
+ this._tag = "div";
108
+ }
109
+
110
+ fields(): Database.Field[];
111
+ fields(_: Database.Field[]): this;
112
+ fields(_?: Database.Field[]): this | Database.Field[] {
113
+ if (!arguments.length) return super.fields();
114
+ super.fields(_);
115
+ this._legend.fields(_);
116
+ this.refreshFields();
117
+ return this;
118
+ }
119
+ refreshFields() {
120
+ this._widget.fields(this._legend.filteredFields());
121
+ this._table.fields(this._legend.filteredFields());
122
+ return this;
123
+ }
124
+
125
+ columns(): string[];
126
+ columns(_: string[], asDefault?: boolean): this;
127
+ columns(_?: string[], asDefault?: boolean): string[] | this {
128
+ if (!arguments.length) return super.columns();
129
+ super.columns(_, asDefault);
130
+ this._legend.columns(_, asDefault);
131
+ this.refreshColumns();
132
+ return this;
133
+ }
134
+ refreshColumns() {
135
+ this._widget.columns(this._legend.filteredColumns());
136
+ this._table.columns(this._legend.filteredColumns());
137
+ return this;
138
+ }
139
+
140
+ data(_?) {
141
+ if (!arguments.length) return super.data();
142
+ super.data(_);
143
+ this._legend.data(_);
144
+ this.refreshData();
145
+ return this;
146
+ }
147
+ refreshData() {
148
+ this._widget.data(this._legend.filteredData());
149
+ this._table.data(this._legend.filteredData());
150
+ return this;
151
+ }
152
+
153
+ highlight(): boolean;
154
+ highlight(_: boolean): this;
155
+ highlight(_?: boolean): boolean | this {
156
+ if (!arguments.length) return this._highlight;
157
+ this._highlight = _;
158
+ return this;
159
+ }
160
+
161
+ startProgress() {
162
+ this._progressBar.start();
163
+ }
164
+
165
+ finishProgress() {
166
+ this._progressBar.finish();
167
+ }
168
+
169
+ buttons(): Widget[];
170
+ buttons(_: Widget[]): this;
171
+ buttons(_?: Widget[]): this | Widget[] {
172
+ if (!arguments.length) return this._titleBar.buttons();
173
+ this._titleBar.buttons(_);
174
+ return this;
175
+ }
176
+
177
+ downloadCSV() {
178
+ const namePrefix = this.downloadTitle() ? this.downloadTitle() : this.title() ? this.title() : "data";
179
+ const nameSuffix = this.downloadTimestampSuffix() ? "_" + Utility.timestamp() : "";
180
+ Utility.downloadString("CSV", this._widget.export("CSV"), namePrefix + nameSuffix);
181
+ return this;
182
+ }
183
+
184
+ downloadPNG() {
185
+ const widget = this.widget();
186
+ if (widget instanceof SVGWidget) {
187
+ if (!this.legendVisible()) {
188
+ widget.downloadPNG(this.title());
189
+ } else {
190
+ widget.downloadPNG(this.title(), undefined, this._legend);
191
+ }
192
+ }
193
+ return this;
194
+ }
195
+
196
+ highlightColumn(column?: string): this {
197
+ if (column) {
198
+ const cssTag = `series-${this.cssTag(column)}`;
199
+ this._centerWA.element().selectAll(".series")
200
+ .each(function () {
201
+ const element = d3Select(this);
202
+ const highlight = element.classed(cssTag);
203
+ element
204
+ .classed("highlight", highlight)
205
+ .classed("lowlight", !highlight)
206
+ ;
207
+ })
208
+ ;
209
+ } else {
210
+ this._centerWA.element().selectAll(".series")
211
+ .classed("highlight", false)
212
+ .classed("lowlight", false)
213
+ ;
214
+ }
215
+ return this;
216
+ }
217
+
218
+ getResponsiveMode(): "tiny" | "small" | "regular" | "none" {
219
+ if (!this.enableAutoscaling()) return "none";
220
+ if (!this._autoScale) return "regular";
221
+ if (this.size().width <= this._resolutions.tiny.width || this.size().height <= this._resolutions.tiny.height) {
222
+ return "tiny";
223
+ } else if (this.size().width <= this._resolutions.small.width || this.size().height <= this._resolutions.small.height) {
224
+ return "small";
225
+ }
226
+ return "regular";
227
+ }
228
+
229
+ setOrigSize() {
230
+ this._orig_size = JSON.parse(JSON.stringify(this.size()));
231
+ }
232
+
233
+ enter(domNode, element) {
234
+ super.enter(domNode, element);
235
+ this._modal
236
+ .target(this.target())
237
+ .relativeTargetId(this.id())
238
+ ;
239
+
240
+ this.top(this._titleBar);
241
+ this.center(this._carousel);
242
+
243
+ this._legend
244
+ .targetWidget(this._widget)
245
+ .orientation("vertical")
246
+ .title("")
247
+ .visible(false)
248
+ ;
249
+
250
+ this._progressBar.enter(domNode, element);
251
+ this.setOrigSize();
252
+ }
253
+
254
+ preUpdateTiny(element) {
255
+ element.selectAll("div.body,div.title-text,div.icon-bar").style("display", "none");
256
+ }
257
+
258
+ preUpdateSmall(element) {
259
+ const scale_x = this._orig_size.width / this._resolutions.small.width;
260
+ const scale_y = this._orig_size.height / this._resolutions.small.height;
261
+ this._scale = Math.min(scale_x, scale_y);
262
+ const x_is_smaller = this._scale === scale_x;
263
+ this.size({
264
+ width: x_is_smaller ? this._resolutions.small.width : this._orig_size.width * (1 / this._scale),
265
+ height: !x_is_smaller ? this._resolutions.small.height : this._orig_size.height * (1 / this._scale)
266
+ });
267
+ element.select("div.title-icon").style("position", "static");
268
+ element.selectAll("lhs").style("display", "none");
269
+ element.selectAll("div.body,div.title-text,div.icon-bar").style("display", "");
270
+ element.selectAll("div.data-count").style("visibility", "hidden");
271
+ element.style("transform", `scale(${this._scale})`);
272
+ }
273
+
274
+ preUpdateRegular(element) {
275
+ element.selectAll("div.body,div.title-text,div.icon-bar").style("display", "");
276
+ element.selectAll("div.data-count").style("visibility", "hidden");
277
+ element.select("div.title-icon").style("position", "static");
278
+ element.style("transform", "translate(0px,0px) scale(1)");
279
+ }
280
+
281
+ private _prevdataVisible;
282
+ private _prevlegendVisible;
283
+ private _prevLegendPosition;
284
+ private _prevChartDataFamily;
285
+ private _prevChart;
286
+ private _prevButtons;
287
+ update(domNode, element) {
288
+ super.update(domNode, element);
289
+ if (this._table && this.widget_exists() && this.widget().class().indexOf("chart_XYAxis") >= 0) {
290
+ const chart = this.widget() as XYAxis;
291
+ this._table.columns().forEach((column, idx) => {
292
+ switch (idx === 0 ? chart.xAxisType() : chart.yAxisType()) {
293
+ case "linear":
294
+ case "log":
295
+ case "pow":
296
+ this._table.columnType(column, "number");
297
+ break;
298
+ case "time":
299
+ this._table.columnType(column, "time");
300
+ break;
301
+ case "ordinal":
302
+ default:
303
+ this._table.columnType(column, "string");
304
+ }
305
+ this._table.columnPattern(column, idx === 0 ? chart.xAxisTypeTimePattern() : chart.yAxisTypeTimePattern());
306
+ this._table.columnFormat(column, idx === 0 ? chart.xAxisTickFormat() : chart.yAxisTickFormat());
307
+ });
308
+ }
309
+ }
310
+
311
+ preUpdate(domNode, element) {
312
+
313
+ super.preUpdate(domNode, element);
314
+
315
+ if (this._prevLegendPosition !== this.legendPosition()) {
316
+ if (this._legend.target() !== null) this._legend.target(null);
317
+ if (this._prevLegendPosition !== undefined) {
318
+ this.swap(this._prevLegendPosition, this.legendPosition());
319
+ } else {
320
+ this[this.legendPosition()](this._legend);
321
+ }
322
+ if (this.legendPosition() === "right") {
323
+ this.rightOverflowX("hidden");
324
+ this.rightOverflowY("auto");
325
+ this.bottomOverflowX("visible");
326
+ this.bottomOverflowY("visible");
327
+ } else {
328
+ this.rightOverflowX("visible");
329
+ this.rightOverflowY("visible");
330
+ this.bottomOverflowX("auto");
331
+ this.bottomOverflowY("hidden");
332
+ }
333
+ this._prevLegendPosition = this.legendPosition();
334
+ }
335
+
336
+ if (this._prevdataVisible !== this.dataVisible()) {
337
+ this._prevdataVisible = this.dataVisible();
338
+ this._toggleData.selected(this._prevdataVisible);
339
+ this._legend.visible(this._prevlegendVisible && !this._prevdataVisible);
340
+ this._carousel.active(this._prevdataVisible ? 1 : 0);
341
+ }
342
+
343
+ if (this._prevlegendVisible !== this.legendVisible()) {
344
+ this._prevlegendVisible = this.legendVisible();
345
+ this._toggleLegend.selected(this._prevlegendVisible);
346
+ this._legend.visible(this._prevlegendVisible && !this._prevdataVisible);
347
+ }
348
+
349
+ this._legend.orientation(this.legendPosition() === "bottom" ? "horizontal" : "vertical");
350
+
351
+ this.showLeft(!this.left());
352
+
353
+ switch (this.getResponsiveMode()) {
354
+ case "tiny":
355
+ this.preUpdateTiny(element);
356
+ break;
357
+ case "small":
358
+ this.preUpdateSmall(element);
359
+ break;
360
+ case "regular":
361
+ this.preUpdateRegular(element);
362
+ break;
363
+ }
364
+
365
+ const chart = this._widget.classID() === "composite_MultiChart" ? this._widget["chart"]() : this._widget;
366
+ this._legend.dataFamily(chart._dataFamily || "any");
367
+
368
+ if (this._prevChartDataFamily !== this._legend.dataFamily()) {
369
+ this._prevChartDataFamily = this._legend.dataFamily();
370
+ switch (this._prevChartDataFamily) {
371
+ case "any":
372
+ this._toggleLegend.selected(false);
373
+ this._legend.visible(false);
374
+ break;
375
+ }
376
+ }
377
+ element.style("box-shadow", this.highlight() ? `inset 0px 0px 0px ${this.highlightSize()}px ${this.highlightColor()}` : "none");
378
+
379
+ if (this._hideLegendToggleList.indexOf(chart.classID()) !== -1) {
380
+ this._spacer.visible(false);
381
+ this._toggleLegend.visible(false);
382
+ } else {
383
+ this._spacer.visible(true);
384
+ this._toggleLegend.visible(true);
385
+ }
386
+ if (this._prevChart !== chart) {
387
+ this._prevChart = chart;
388
+ const widgetIconBar = chart ? chart["_titleBar"] || chart["_iconBar"] : undefined;
389
+ if (widgetIconBar && widgetIconBar instanceof IconBar) {
390
+ this._prevButtons = this._prevButtons || [...this.buttons()];
391
+ const buttons: Widget[] = [
392
+ ...widgetIconBar.buttons(),
393
+ new Spacer(),
394
+ ...this._prevButtons
395
+ ];
396
+ widgetIconBar.buttons([]).render();
397
+ this.buttons(buttons);
398
+ } else if (this._prevButtons) {
399
+ this.buttons(this._prevButtons);
400
+ }
401
+ }
402
+
403
+ const hiddenButtons = [];
404
+ if (!this.dataButtonVisible()) hiddenButtons.push(this._toggleData);
405
+ if (!this.downloadButtonVisible()) hiddenButtons.push(this._buttonDownload);
406
+ if (!this.downloadImageButtonVisible()) hiddenButtons.push(this._buttonDownloadImage);
407
+ if (!this.legendButtonVisible()) hiddenButtons.push(this._toggleLegend);
408
+ this._buttonDownloadImage.enabled(this.widget() instanceof SVGWidget);
409
+ this._titleBar
410
+ .hiddenButtons(hiddenButtons)
411
+ .visible(this.titleVisible())
412
+ ;
413
+ this.topOverlay(this.titleOverlay() || !this.titleVisible());
414
+ }
415
+
416
+ postUpdate(domNode, element) {
417
+ super.postUpdate(domNode, element);
418
+
419
+ switch (this.getResponsiveMode()) {
420
+ case "tiny":
421
+ this.postUpdateTiny(element);
422
+ break;
423
+ case "small":
424
+ this.postUpdateSmall(element);
425
+ break;
426
+ case "regular":
427
+ this.postUpdateRegular(element);
428
+ break;
429
+ }
430
+ }
431
+
432
+ postUpdateTiny(element) {
433
+ element.selectAll("div.body,div.title-text,div.icon-bar").style("display", "none");
434
+ element.selectAll("div.data-count")
435
+ .style("visibility", "visible")
436
+ .style("font-size", (this.titleIconFontSize() / 3) + "px")
437
+ .style("line-height", (this.titleIconFontSize() / 3) + "px")
438
+ .style("left", this.titleIconFontSize() + "px")
439
+ .text(this.data().length)
440
+ ;
441
+ element.style("transform", "translate(0px,0px) scale(1)");
442
+ const iconDiv = element.selectAll("div.title-icon");
443
+ const _node = iconDiv.node();
444
+ const _container = element.node().parentElement;
445
+ const containerRect = _container.getBoundingClientRect();
446
+ if (_node) {
447
+ const rect = iconDiv.node().getBoundingClientRect();
448
+ const icon_top = containerRect.height / 2;
449
+ iconDiv
450
+ .style("position", "absolute")
451
+ .style("left", `calc(50% - ${rect.width / 2}px)`)
452
+ .style("top", `${icon_top - (rect.height / 2)}px`)
453
+ ;
454
+ element.selectAll("div.data-count")
455
+ .style("position", "absolute")
456
+ .style("left", `calc(50% + ${rect.width / 2}px)`)
457
+ .style("top", `${icon_top - (rect.height / 2)}px`)
458
+ ;
459
+ }
460
+ }
461
+
462
+ postUpdateSmall(element) {
463
+ element.selectAll("lhs").style("display", "none"); // TODO: a bug in Border2?
464
+ element.selectAll("div.title-icon").style("position", "static");
465
+ element.selectAll("div.body,div.title-text,div.icon-bar").style("display", "");
466
+ element.selectAll("div.data-count").style("visibility", "hidden");
467
+ const rect = element.node().getBoundingClientRect();
468
+ const parentRect = element.node().parentElement.getBoundingClientRect();
469
+ element.style("transform", `translate(${parentRect.x - rect.x}px, ${parentRect.y - rect.y}px) scale(${this._scale})`);
470
+ }
471
+
472
+ postUpdateRegular(element) {
473
+ element.selectAll("div.title-icon").style("position", "static");
474
+ element.selectAll("div.body,div.title-text,div.icon-bar").style("display", "");
475
+ element.selectAll("div.data-count").style("visibility", "hidden");
476
+ }
477
+
478
+ exit(domNode, element) {
479
+ this._progressBar.exit(domNode, element);
480
+
481
+ this.right(null);
482
+ this._legend.target(null);
483
+ this.center(null);
484
+ this._carousel.target(null);
485
+ this.top(null);
486
+ this._titleBar.target(null);
487
+
488
+ this._modal.target(null);
489
+
490
+ delete this._prevChart;
491
+ delete this._prevButtons;
492
+ delete this._prevChartDataFamily;
493
+ delete this._prevPos;
494
+ delete this._prevdataVisible;
495
+ delete this._prevlegendVisible;
496
+
497
+ super.exit(domNode, element);
498
+ }
499
+
500
+ // Event Handlers ---
501
+ // Events ---
502
+ click(row, column, selected) {
503
+ // console.log("Click: " + JSON.stringify(row) + ", " + column + ", " + selected);
504
+ }
505
+
506
+ dblclick(row, column, selected) {
507
+ // console.log("Double click: " + JSON.stringify(row) + ", " + column + ", " + selected);
508
+ }
509
+
510
+ vertex_click(row, col, sel, more) {
511
+ if (more && more.vertex) {
512
+ // console.log("Vertex click: " + more.vertex.id());
513
+ }
514
+ }
515
+
516
+ vertex_dblclick(row, col, sel, more) {
517
+ if (more && more.vertex) {
518
+ // console.log("Vertex double click: " + more.vertex.id());
519
+ }
520
+ }
521
+
522
+ edge_click(row, col, sel, more) {
523
+ if (more && more.edge) {
524
+ // console.log("Edge click: " + more.edge.id());
525
+ }
526
+ }
527
+
528
+ edge_dblclick(row, col, sel, more) {
529
+ if (more && more.edge) {
530
+ // console.log("Edge double click: " + more.edge.id());
531
+ }
532
+ }
533
+ }
534
+ ChartPanel.prototype._class += " layout_ChartPanel";
535
+
536
+ export interface ChartPanel {
537
+ title(): string;
538
+ title(_: string): this;
539
+ titleVisible(): boolean;
540
+ titleVisible(_: boolean): this;
541
+ titleOverlay(): boolean;
542
+ titleOverlay(_: boolean): this;
543
+ title_exists(): boolean;
544
+ titleFontSize(): number;
545
+ titleFontSize(_: number): this;
546
+ titleFontSize_exists(): boolean;
547
+ titleIconFontSize(): number;
548
+ titleIconFontSize(_: number): this;
549
+ titleIconFontSize_exists(): boolean;
550
+ dataVisible(): boolean;
551
+ dataVisible(_: boolean): this;
552
+ dataButtonVisible(): boolean;
553
+ dataButtonVisible(_: boolean): this;
554
+ downloadButtonVisible(): boolean;
555
+ downloadButtonVisible(_: boolean): this;
556
+ downloadImageButtonVisible(): boolean;
557
+ downloadImageButtonVisible(_: boolean): this;
558
+ downloadTitle(): string;
559
+ downloadTitle(_: string): this;
560
+ downloadTimestampSuffix(): boolean;
561
+ downloadTimestampSuffix(_: boolean): this;
562
+ legendVisible(): boolean;
563
+ legendVisible(_: boolean): this;
564
+ legendButtonVisible(): boolean;
565
+ legendButtonVisible(_: boolean): this;
566
+ legendPosition(): "right" | "bottom";
567
+ legendPosition(_: "right" | "bottom"): this;
568
+ description(): string;
569
+ description(_: string): this;
570
+ description_exists(): boolean;
571
+ widget(): Widget;
572
+ widget(_: Widget): this;
573
+ widget_exists(): boolean;
574
+ enableAutoscaling(): boolean;
575
+ enableAutoscaling(_: boolean): this;
576
+ enableAutoscaling_exists(): boolean;
577
+ highlightSize(): number;
578
+ highlightSize(_: number): this;
579
+ highlightSize_exists(): boolean;
580
+ highlightColor(): string;
581
+ highlightColor(_: string): this;
582
+ highlightColor_exists(): boolean;
583
+ }
584
+
585
+ ChartPanel.prototype.publishReset();
586
+ ChartPanel.prototype.publishProxy("title", "_titleBar");
587
+ ChartPanel.prototype.publish("titleVisible", true, "boolean");
588
+ ChartPanel.prototype.publish("titleOverlay", false, "boolean");
589
+ ChartPanel.prototype.publishProxy("titleIcon", "_titleBar");
590
+ ChartPanel.prototype.publishProxy("titleIconFont", "_titleBar");
591
+ ChartPanel.prototype.publishProxy("titleFont", "_titleBar");
592
+ ChartPanel.prototype.publishProxy("titleIconFontSize", "_titleBar");
593
+ ChartPanel.prototype.publishProxy("titleFontSize", "_titleBar");
594
+ ChartPanel.prototype.publishProxy("description", "_titleBar");
595
+ ChartPanel.prototype.publishProxy("descriptionFont", "_titleBar");
596
+ ChartPanel.prototype.publishProxy("descriptionFontSize", "_titleBar");
597
+ ChartPanel.prototype.publish("dataVisible", false, "boolean", "Show data table");
598
+ ChartPanel.prototype.publish("dataButtonVisible", true, "boolean", "Show data table button");
599
+ ChartPanel.prototype.publish("downloadButtonVisible", true, "boolean", "Show data download button");
600
+ ChartPanel.prototype.publish("downloadImageButtonVisible", false, "boolean", "Show image download button");
601
+ ChartPanel.prototype.publish("downloadTitle", "", "string", "File name when downloaded");
602
+ ChartPanel.prototype.publish("downloadTimestampSuffix", true, "boolean", "Use timestamp as file name suffix");
603
+ ChartPanel.prototype.publish("legendVisible", false, "boolean", "Show legend");
604
+ ChartPanel.prototype.publish("legendButtonVisible", true, "boolean", "Show legend button");
605
+ ChartPanel.prototype.publish("legendPosition", "right", "set", "Position of legend", ["right", "bottom"]);
606
+ ChartPanel.prototype.publishProxy("legend_labelMaxWidth", "_legend", "labelMaxWidth");
607
+ ChartPanel.prototype.publishProxy("legend_showSeriesTotal", "_legend", "showSeriesTotal");
608
+ ChartPanel.prototype.publishProxy("legend_showLegendTotal", "_legend", "showLegendTotal");
609
+ ChartPanel.prototype.publishProxy("legend_itemPadding", "_legend", "itemPadding");
610
+ ChartPanel.prototype.publishProxy("legend_shapeRadius", "_legend", "shapeRadius");
611
+ ChartPanel.prototype.publishProxy("legend_symbolType", "_legend", "symbolType");
612
+ ChartPanel.prototype.publishProxy("legend_labelAlign", "_legend", "labelAlign");
613
+ ChartPanel.prototype.publish("widget", null, "widget", "Widget", undefined, { render: false });
614
+ ChartPanel.prototype.publish("enableAutoscaling", false, "boolean");
615
+ ChartPanel.prototype.publish("highlightSize", 4, "number");
616
+ ChartPanel.prototype.publish("highlightColor", "#e67e22", "html-color");
617
+ ChartPanel.prototype.publishProxy("progress_halfLife", "_progressBar", "halfLife");
618
+ ChartPanel.prototype.publishProxy("progress_decay", "_progressBar", "decay");
619
+ ChartPanel.prototype.publishProxy("progress_size", "_progressBar", "size");
620
+ ChartPanel.prototype.publishProxy("progress_color", "_progressBar", "color");
621
+ ChartPanel.prototype.publishProxy("progress_blurBar", "_progressBar", "blurBar");
622
+ ChartPanel.prototype.publishProxy("progress_blurSize", "_progressBar", "blurSize");
623
+ ChartPanel.prototype.publishProxy("progress_blurColor", "_progressBar", "blurColor");
624
+ ChartPanel.prototype.publishProxy("progress_blurOpacity", "_progressBar", "blurOpacity");
625
+
626
+ ChartPanel.prototype.widget = function (_?) {
627
+ if (!arguments.length) return this._widget;
628
+ this._carousel.widgets([_, this._table]);
629
+ this._widget = _;
630
+ this._widget
631
+ .fields(this._legend.filteredFields())
632
+ .data(this._legend.filteredData())
633
+ ;
634
+
635
+ const context = this;
636
+ const tmpAny = this._widget as any;
637
+ tmpAny.click = function () {
638
+ context.click.apply(context, arguments);
639
+ };
640
+ tmpAny.dblclick = function () {
641
+ context.dblclick.apply(context, arguments);
642
+ };
643
+ tmpAny.vertex_click = function () {
644
+ context.vertex_click.apply(context, arguments);
645
+ };
646
+ tmpAny.vertex_dblclick = function () {
647
+ context.vertex_dblclick.apply(context, arguments);
648
+ };
649
+ tmpAny.edge_click = function () {
650
+ context.edge_click.apply(context, arguments);
651
+ };
652
+ tmpAny.edge_dblclick = function () {
653
+ context.edge_dblclick.apply(context, arguments);
654
+ };
655
+ return this;
656
+ };