@hpcc-js/phosphor 3.7.1 → 3.8.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hpcc-js/phosphor",
3
- "version": "3.7.1",
3
+ "version": "3.8.0",
4
4
  "description": "hpcc-js - Viz Phosphor",
5
5
  "type": "module",
6
6
  "main": "./dist/index.umd.cjs",
@@ -39,10 +39,10 @@
39
39
  "update-major": "npx --yes npm-check-updates -u"
40
40
  },
41
41
  "dependencies": {
42
- "@hpcc-js/common": "^3.8.1"
42
+ "@hpcc-js/common": "^3.8.2"
43
43
  },
44
44
  "devDependencies": {
45
- "@hpcc-js/esbuild-plugins": "^1.9.1",
45
+ "@hpcc-js/esbuild-plugins": "^1.9.2",
46
46
  "@lumino/algorithm": "2.0.4",
47
47
  "@lumino/commands": "2.3.3",
48
48
  "@lumino/messaging": "2.0.4",
@@ -59,5 +59,5 @@
59
59
  "url": "https://github.com/hpcc-systems/Visualization/issues"
60
60
  },
61
61
  "homepage": "https://github.com/hpcc-systems/Visualization",
62
- "gitHead": "0cfcae9b4ccbd0b3c9f21381f4581bf121392585"
62
+ "gitHead": "9d31241482c78decca86e3bf624244ce5b40f3d6"
63
63
  }
@@ -0,0 +1,87 @@
1
+ import { HTMLWidget, Widget, Utility } from "@hpcc-js/common";
2
+ import { Widget as PWidget, IMessageHandler, IMessageHook, Message, MessageLoop } from "./phosphor-shim.ts";
3
+ import { Msg, WidgetAdapter, WidgetAdapterArray } from "./WidgetAdapter.ts";
4
+
5
+ export namespace BasePanel {
6
+ export interface IAddWidgetOptions {
7
+ /** Minimum size in pixels */
8
+ minSize?: number;
9
+ /** Preferred/default size in pixels — used as initial size hint */
10
+ defaultSize?: number;
11
+ /** Inner padding in pixels (default 8) */
12
+ padding?: number;
13
+
14
+ /** Reference widget for split/tab positioning */
15
+ refWidget?: Widget;
16
+ }
17
+ }
18
+
19
+ export abstract class BasePanel extends HTMLWidget implements IMessageHandler, IMessageHook {
20
+
21
+ protected abstract _content: WidgetAdapterArray;
22
+
23
+ constructor() {
24
+ super();
25
+ this._tag = "div";
26
+ MessageLoop.installMessageHook(this, this);
27
+ }
28
+
29
+ getWidget(wa: PWidget): Widget | undefined {
30
+ if (wa instanceof WidgetAdapter) {
31
+ return wa.widget;
32
+ }
33
+ }
34
+
35
+ getWidgetAdapter(widget: Widget): WidgetAdapter | null {
36
+ let retVal = null;
37
+ this._content.some(wa => {
38
+ if (wa.widget === widget) {
39
+ retVal = wa;
40
+ return true;
41
+ }
42
+ return false;
43
+ });
44
+ return retVal;
45
+ }
46
+
47
+ protected _prevActive: Widget;
48
+ active(): Widget {
49
+ return this._prevActive;
50
+ }
51
+
52
+ // Phosphor Messaging ---
53
+ protected _lazyLayoutChanged = Utility.debounce(async () => {
54
+ this.layoutChanged();
55
+ }, 1000);
56
+
57
+ processMessage(msg: Message): void {
58
+ switch (msg.type) {
59
+ case Msg.WAActivateRequest.type:
60
+ const wa = (msg as Msg.WAActivateRequest).wa;
61
+ const widget = wa.widget;
62
+ if (this._prevActive !== widget) {
63
+ this._prevActive = widget;
64
+ this.childActivation(widget, wa);
65
+ }
66
+ break;
67
+ case Msg.WALayoutChanged.type:
68
+ this._lazyLayoutChanged();
69
+ break;
70
+ }
71
+ }
72
+
73
+ messageHook(handler: IMessageHandler, msg: Message): boolean {
74
+ if (handler === this) {
75
+ this.processMessage(msg);
76
+ }
77
+ return true;
78
+ }
79
+
80
+ // Events ---
81
+ childActivation(w: Widget, wa: WidgetAdapter) {
82
+ }
83
+
84
+ layoutChanged() {
85
+ }
86
+
87
+ }
package/src/DockPanel.ts CHANGED
@@ -1,43 +1,144 @@
1
- import { HTMLWidget, Widget, Utility, select as d3Select } from "@hpcc-js/common";
2
- import { DockPanel as PhosphorDockPanel, IMessageHandler, IMessageHook, Message, MessageLoop, Widget as PWidget } from "./phosphor-shim.ts";
1
+ import { Widget, select as d3Select } from "@hpcc-js/common";
2
+ import { BasePanel } from "./BasePanel.ts";
3
+ import { DockLayout, DockPanel as PhosphorDockPanel, MessageLoop, Widget as PWidget } from "./phosphor-shim.ts";
4
+ import { IClosable, WidgetAdapter } from "./WidgetAdapter.ts";
3
5
  import { PDockPanel } from "./PDockPanel.ts";
4
- import { IClosable, Msg, WidgetAdapter } from "./WidgetAdapter.ts";
5
6
 
6
7
  import "../src/DockPanel.css";
7
8
 
8
- export class DockPanel extends HTMLWidget implements IMessageHandler, IMessageHook {
9
+ export namespace DockPanel {
10
+ export interface IAddWidgetOptions extends BasePanel.IAddWidgetOptions {
11
+ /** Tab title */
12
+ title?: string;
13
+ /** Insertion mode relative to refWidget */
14
+ location?: PhosphorDockPanel.InsertMode;
15
+ /** Whether the tab can be closed */
16
+ closable?: boolean | IClosable;
17
+ }
18
+ }
19
+
20
+ export class DockPanel extends BasePanel {
9
21
  private _dock = new PDockPanel({ mode: "multiple-document" });
22
+ protected _content = this._dock.content();
10
23
 
11
24
  constructor() {
12
25
  super();
13
- this._tag = "div";
14
26
  this._dock.id = "p" + this.id();
15
- MessageLoop.installMessageHook(this, this);
16
27
  }
17
28
 
18
- protected getWidgetAdapter(widget: Widget): WidgetAdapter | null {
19
- let retVal = null;
20
- this._dock.content().some(wa => {
21
- if (wa.widget === widget) {
22
- retVal = wa;
23
- return true;
24
- }
25
- return false;
26
- });
27
- return retVal;
28
- }
29
+ private _pendingDefaults: Map<WidgetAdapter, { defaultSize?: number }> = new Map();
30
+ addWidget(widget: Widget, options: DockPanel.IAddWidgetOptions): this;
31
+ /** @deprecated Use options object form instead */
32
+ addWidget(widget: Widget, title: string, location?: PhosphorDockPanel.InsertMode, refWidget?: Widget, closable?: boolean | IClosable, padding?: number): this;
33
+ addWidget(widget: Widget, titleOrOptions: string | DockPanel.IAddWidgetOptions, location: PhosphorDockPanel.InsertMode = "split-right", refWidget?: Widget, closable?: boolean | IClosable, padding: number = 8) {
34
+ const opts: DockPanel.IAddWidgetOptions = typeof titleOrOptions === "string"
35
+ ? { title: titleOrOptions, location, refWidget, closable, padding }
36
+ : titleOrOptions;
29
37
 
30
- addWidget(widget: Widget, title: string, location: PhosphorDockPanel.InsertMode = "split-right", refWidget?: Widget, closable?: boolean | IClosable, padding: number = 8) {
31
- const addMode: PhosphorDockPanel.IAddOptions = { mode: location, ref: this.getWidgetAdapter(refWidget) };
32
- const wa = new WidgetAdapter(this, widget, {}, closable);
38
+ const {
39
+ title = "",
40
+ location: loc = "split-right",
41
+ refWidget: ref,
42
+ closable: canClose,
43
+ padding: pad = 8,
44
+ minSize,
45
+ defaultSize
46
+ } = opts;
47
+
48
+ const addMode: PhosphorDockPanel.IAddOptions = { mode: loc, ref: this.getWidgetAdapter(ref) };
49
+ const wa = new WidgetAdapter(this, widget, {}, canClose);
33
50
  wa.title.label = title;
34
- wa.padding = padding;
51
+ wa.padding = pad;
52
+
53
+ if (minSize != null) {
54
+ const style = wa.node.style;
55
+ if (loc === "split-left" || loc === "split-right") {
56
+ style.minWidth = `${minSize}px`;
57
+ } else {
58
+ style.minHeight = `${minSize}px`;
59
+ }
60
+ }
61
+
35
62
  this._dock.addWidget(wa, addMode);
36
63
  this._dock.appendContent(wa);
37
64
  this._dock.tabsMovable = true;
65
+
66
+ if (defaultSize != null) {
67
+ this._pendingDefaults.set(wa, { defaultSize });
68
+ }
69
+
38
70
  return this;
39
71
  }
40
72
 
73
+ private _applyPendingDefaults() {
74
+ if (this._pendingDefaults.size === 0) return;
75
+
76
+ const config = this._dock.saveLayout() as DockLayout.ILayoutConfig;
77
+ if (!config.main) {
78
+ this._pendingDefaults.clear();
79
+ return;
80
+ }
81
+
82
+ // Build a lookup: widgetId → { defaultSize }
83
+ const lookup = new Map<string, { defaultSize?: number }>();
84
+ for (const [wa, defaults] of this._pendingDefaults) {
85
+ lookup.set(wa.widget.id(), defaults);
86
+ }
87
+ this._pendingDefaults.clear();
88
+
89
+ const containerWidth = this.width();
90
+ const containerHeight = this.height();
91
+
92
+ const applySizes = (area: DockLayout.AreaConfig, availWidth: number, availHeight: number): void => {
93
+ if (!area || area.type !== "split-area") return;
94
+
95
+ const isHorizontal = area.orientation === "horizontal";
96
+ const totalSpace = isHorizontal ? availWidth : availHeight;
97
+ const n = area.children.length;
98
+
99
+ // Collect requested pixel sizes per child
100
+ let usedSpace = 0;
101
+ let flexCount = 0;
102
+ const pixelSizes: (number | null)[] = area.children.map((child, i) => {
103
+ if (child.type === "tab-area") {
104
+ for (const w of (child as any).widgets) {
105
+ const defaults = lookup.get(w?.__id);
106
+ if (defaults) {
107
+ const size = defaults.defaultSize;
108
+ if (size != null) {
109
+ usedSpace += size;
110
+ return size;
111
+ }
112
+ }
113
+ }
114
+ }
115
+ flexCount++;
116
+ return null;
117
+ });
118
+
119
+ // Only apply if at least one child has a default
120
+ if (flexCount < n) {
121
+ const remainingSpace = Math.max(0, totalSpace - usedSpace);
122
+ const flexSize = flexCount > 0 ? remainingSpace / flexCount : 0;
123
+ area.sizes = pixelSizes.map(px => px != null ? px : flexSize);
124
+ }
125
+
126
+ // Recurse into nested split areas with their allocated portion
127
+ for (let i = 0; i < area.children.length; i++) {
128
+ const child = area.children[i];
129
+ if (child.type === "split-area") {
130
+ const ratio = area.sizes[i] / (area.sizes.reduce((a, b) => a + b, 0) || 1);
131
+ const childW = isHorizontal ? availWidth * ratio : availWidth;
132
+ const childH = isHorizontal ? availHeight : availHeight * ratio;
133
+ applySizes(child, childW, childH);
134
+ }
135
+ }
136
+ };
137
+
138
+ applySizes(config.main, containerWidth, containerHeight);
139
+ this._dock.restoreLayout(config as any);
140
+ }
141
+
41
142
  removeWidget(widget: Widget) {
42
143
  const wa = this.getWidgetAdapter(widget);
43
144
  if (wa) {
@@ -74,25 +175,16 @@ export class DockPanel extends HTMLWidget implements IMessageHandler, IMessageHo
74
175
  return this;
75
176
  }
76
177
 
77
- private _pPlaceholder;
78
178
  enter(domNode, element) {
79
179
  super.enter(domNode, element);
80
- this._pPlaceholder = element.append("div");
81
- PWidget.attach(this._dock, this._pPlaceholder.node());
180
+ PWidget.attach(this._dock, domNode);
82
181
  }
83
182
 
84
183
  _prevHideSingleTabs;
85
184
  update(domNode, element) {
86
185
  super.update(domNode, element);
87
-
88
- this._pPlaceholder
89
- .style("width", this.width() + "px")
90
- .style("height", this.height() + "px")
91
- .style("overflow", "hidden")
92
- ;
93
-
94
186
  element.select(".lm-Widget")
95
- .style("width", this._pPlaceholder.node().clientWidth + "px")
187
+ .style("width", this.width() + "px")
96
188
  .style("height", this.height() + "px")
97
189
  ;
98
190
 
@@ -100,8 +192,21 @@ export class DockPanel extends HTMLWidget implements IMessageHandler, IMessageHo
100
192
  }
101
193
 
102
194
  exit(domNode, element) {
195
+ if (this._dock.isAttached) {
196
+ if (this._dock.node.isConnected) {
197
+ // Proper Lumino detach — propagates AfterDetach to all children
198
+ // (TabBars etc.), clearing their isAttached flags before disposal.
199
+ PWidget.detach(this._dock);
200
+ } else {
201
+ // The DOM node has already been removed from the document by the
202
+ // parent framework (e.g. React unmount). We cannot call the
203
+ // static Widget.detach() because it guards against !isConnected,
204
+ // so manually broadcast AfterDetach so that Lumino's isAttached
205
+ // bookkeeping is consistent before we dispose child widgets.
206
+ MessageLoop.sendMessage(this._dock, PWidget.Msg.AfterDetach);
207
+ }
208
+ }
103
209
  [...this.widgets()].forEach(w => this.removeWidget(w));
104
- PWidget.detach(this._dock);
105
210
  super.exit(domNode, element);
106
211
  }
107
212
 
@@ -112,6 +217,7 @@ export class DockPanel extends HTMLWidget implements IMessageHandler, IMessageHo
112
217
  this.layoutObj(null);
113
218
  }
114
219
  return super.render((w) => {
220
+ this._applyPendingDefaults();
115
221
  this._dock.content().watchRendered(this, callback);
116
222
  this._dock.update();
117
223
  setTimeout(() => {
@@ -137,39 +243,6 @@ export class DockPanel extends HTMLWidget implements IMessageHandler, IMessageHo
137
243
  this._dock.fit();
138
244
  }
139
245
 
140
- // Phosphor Messaging ---
141
- messageHook(handler: IMessageHandler, msg: Message): boolean {
142
- if (handler === this) {
143
- this.processMessage(msg);
144
- }
145
- return true;
146
- }
147
-
148
- private _lazyLayoutChanged = Utility.debounce(async () => {
149
- this.layoutChanged();
150
- }, 1000);
151
-
152
- _prevActive: Widget;
153
- processMessage(msg: Message): void {
154
- switch (msg.type) {
155
- case Msg.WAActivateRequest.type:
156
- const wa = (msg as Msg.WAActivateRequest).wa;
157
- const widget = wa.widget;
158
- if (this._prevActive !== widget) {
159
- this._prevActive = widget;
160
- this.childActivation(widget, wa);
161
- }
162
- break;
163
- case Msg.WALayoutChanged.type:
164
- this._lazyLayoutChanged();
165
- break;
166
- }
167
- }
168
-
169
- active(): Widget {
170
- return this._prevActive;
171
- }
172
-
173
246
  // Events ---
174
247
  childActivation(w: Widget, wa: WidgetAdapter) {
175
248
  }
package/src/SplitPanel.ts CHANGED
@@ -1,36 +1,61 @@
1
1
  import { HTMLWidget, SVGWidget, Widget } from "@hpcc-js/common";
2
- import { Message, SplitPanel as PSplitPanel, Widget as PWidget } from "./phosphor-shim.ts";
3
- import { Msg, WidgetAdapter, WidgetAdapterArray } from "./WidgetAdapter.ts";
2
+ import { BasePanel } from "./BasePanel.ts";
3
+ import { SplitPanel as PSplitPanel, Widget as PWidget } from "./phosphor-shim.ts";
4
+ import { WidgetAdapter, WidgetAdapterArray } from "./WidgetAdapter.ts";
4
5
 
5
6
  import "../src/DockPanel.css";
6
7
 
7
- export class SplitPanel extends HTMLWidget {
8
+ export namespace SplitPanel {
9
+
10
+ export interface IAddWidgetOptions extends BasePanel.IAddWidgetOptions {
11
+ /** Maximum size in pixels */
12
+ maxSize?: number;
13
+ }
14
+ }
15
+
16
+ export class SplitPanel extends BasePanel {
8
17
  private _split: PSplitPanel;
9
- private content = WidgetAdapterArray.create();
18
+ protected _content = WidgetAdapterArray.create();
10
19
 
11
- constructor(orientation: "horizontal" | "vertical" = "vertical") {
20
+ constructor(readonly _orientation: "horizontal" | "vertical" = "vertical") {
12
21
  super();
13
- this._split = new PSplitPanel({ orientation });
14
- this._tag = "div";
22
+ this._split = new PSplitPanel({ orientation: _orientation });
15
23
  this._split.id = "p" + this.id();
16
24
  }
17
25
 
18
- protected getWidgetAdapter(widget: Widget): WidgetAdapter | null {
19
- let retVal = null;
20
- this.content.some(wa => {
21
- if (wa.widget === widget) {
22
- retVal = wa;
23
- return true;
26
+ private _pendingDefaults: Map<number, { defaultSize?: number }> = new Map();
27
+ addWidget(widget: SVGWidget | HTMLWidget, options?: SplitPanel.IAddWidgetOptions): this {
28
+ const opts = options || {};
29
+ const wa = new WidgetAdapter(this, widget);
30
+ wa.padding = opts.padding ?? 0;
31
+
32
+ if (opts.minSize != null || opts.maxSize != null) {
33
+ const style = wa.node.style;
34
+ if (opts.minSize != null) {
35
+ if (this._orientation === "horizontal") {
36
+ style.minWidth = `${opts.minSize}px`;
37
+ } else {
38
+ style.minHeight = `${opts.minSize}px`;
39
+ }
24
40
  }
25
- return false;
26
- });
27
- return retVal;
28
- }
41
+ if (opts.maxSize != null) {
42
+ if (this._orientation === "horizontal") {
43
+ style.maxWidth = `${opts.maxSize}px`;
44
+ } else {
45
+ style.maxHeight = `${opts.maxSize}px`;
46
+ }
47
+ }
48
+ }
29
49
 
30
- addWidget(widget: SVGWidget | HTMLWidget) {
31
- const wa = new WidgetAdapter(this, widget);
32
50
  this._split.addWidget(wa);
33
- this.content.push(wa);
51
+ this._content.push(wa);
52
+
53
+ if (opts.defaultSize != null) {
54
+ this._pendingDefaults.set(this._content.length - 1, {
55
+ defaultSize: opts.defaultSize
56
+ });
57
+ }
58
+
34
59
  return this;
35
60
  }
36
61
 
@@ -62,26 +87,51 @@ export class SplitPanel extends HTMLWidget {
62
87
 
63
88
  render(callback?: (w: Widget) => void): this {
64
89
  return super.render(w => {
65
- this.content.watchRendered(this, callback);
90
+ this._applyPendingDefaults();
91
+ this._content.watchRendered(this, callback);
66
92
  this._split.update();
67
93
  });
68
94
  }
69
95
 
70
- private _prevActive: Widget;
71
- processMessage(msg: Message): void {
72
- switch (msg.type) {
73
- case "wa-activate-request":
74
- const widget = (msg as Msg.WAActivateRequest).wa.widget;
75
- if (this._prevActive !== widget) {
76
- this._prevActive = widget;
77
- this.childActivation(widget);
96
+ private _applyPendingDefaults() {
97
+ if (this._pendingDefaults.size === 0) return;
98
+
99
+ const isHorizontal = this._orientation === "horizontal";
100
+ const totalSpace = isHorizontal ? this.width() : this.height();
101
+ const n = this._content.length;
102
+
103
+ let usedSpace = 0;
104
+ let flexCount = 0;
105
+ const pixelSizes: (number | null)[] = [];
106
+
107
+ for (let i = 0; i < n; i++) {
108
+ const defaults = this._pendingDefaults.get(i);
109
+ if (defaults) {
110
+ const size = defaults.defaultSize;
111
+ if (size != null) {
112
+ pixelSizes.push(size);
113
+ usedSpace += size;
114
+ continue;
78
115
  }
79
- break;
116
+ }
117
+ pixelSizes.push(null);
118
+ flexCount++;
80
119
  }
120
+
121
+ this._pendingDefaults.clear();
122
+
123
+ const remainingSpace = Math.max(0, totalSpace - usedSpace);
124
+ const flexSize = flexCount > 0 ? remainingSpace / flexCount : 0;
125
+ const sizes = pixelSizes.map(px => px != null ? px : flexSize);
126
+ this._split.setRelativeSizes(sizes);
81
127
  }
82
128
 
83
- // Events ---
84
- childActivation(w: Widget) {
129
+ // Events ---
130
+ childActivation(w: Widget, wa: WidgetAdapter) {
131
+ }
132
+
133
+ layoutChanged() {
85
134
  }
86
135
  }
87
136
  SplitPanel.prototype._class += " phosphor_SplitPanel";
137
+
package/src/TabPanel.ts CHANGED
@@ -1,55 +1,63 @@
1
1
  import { HTMLWidget, SVGWidget, Widget } from "@hpcc-js/common";
2
- import { IMessageHandler, Message, TabPanel as PTabPanel, Widget as PWidget } from "./phosphor-shim.ts";
3
- import { Msg, WidgetAdapter, WidgetAdapterArray, WidgetAdapterExt } from "./WidgetAdapter.ts";
2
+ import { BasePanel } from "./BasePanel.ts";
3
+ import { TabPanel as PTabPanel, Widget as PWidget } from "./phosphor-shim.ts";
4
+ import { WidgetAdapter, WidgetAdapterArray, WidgetAdapterExt } from "./WidgetAdapter.ts";
4
5
 
5
6
  import "../src/DockPanel.css";
6
7
 
7
- export class TabPanel extends HTMLWidget {
8
+ export namespace TabPanel {
9
+
10
+ export interface IAddWidgetOptions {
11
+ /** Inner padding in pixels (default 8) */
12
+ padding?: number;
13
+ /** Tab title */
14
+ title?: string;
15
+ /** Widget adapter extensions (overflow settings) */
16
+ ext?: WidgetAdapterExt;
17
+ }
18
+ }
19
+
20
+ export class TabPanel extends BasePanel {
8
21
  private _tab = new PTabPanel({ tabPlacement: "top" });
9
- protected content = WidgetAdapterArray.create();
22
+ protected _content = WidgetAdapterArray.create();
10
23
 
11
24
  constructor() {
12
25
  super();
13
- this._tag = "div";
14
26
  this._tab.id = "p" + this.id();
15
27
  }
16
28
 
17
- protected getWidget(wa: PWidget): Widget | undefined {
18
- if (wa instanceof WidgetAdapter) {
19
- return wa.widget;
20
- }
21
- }
29
+ addWidget(widget: SVGWidget | HTMLWidget, options: TabPanel.IAddWidgetOptions): this;
30
+ /** @deprecated Use options object form instead */
31
+ addWidget(widget: SVGWidget | HTMLWidget, title: string, ext?: WidgetAdapterExt): this;
32
+ addWidget(widget: SVGWidget | HTMLWidget, titleOrOptions: string | TabPanel.IAddWidgetOptions, ext: WidgetAdapterExt = {}) {
33
+ const opts: TabPanel.IAddWidgetOptions = typeof titleOrOptions === "string"
34
+ ? { title: titleOrOptions, ext }
35
+ : titleOrOptions;
22
36
 
23
- protected getWidgetAdapter(widget: Widget): WidgetAdapter | null {
24
- let retVal = null;
25
- this.content.some(wa => {
26
- if (wa.widget === widget) {
27
- retVal = wa;
28
- return true;
29
- }
30
- return false;
31
- });
32
- return retVal;
33
- }
37
+ const {
38
+ title = "",
39
+ ext: widgetExt = {},
40
+ padding = 8
41
+ } = opts;
34
42
 
35
- addWidget(widget: SVGWidget | HTMLWidget, title: string, ext: WidgetAdapterExt = {}) {
36
43
  if (!this._prevActive) {
37
44
  this._prevActive = widget;
38
45
  }
39
- const wa = new WidgetAdapter(this, widget, undefined, undefined, ext);
46
+ const wa = new WidgetAdapter(this, widget, undefined, undefined, widgetExt);
40
47
  wa.title.label = title;
41
- wa.padding = 8;
48
+ wa.padding = padding;
49
+
42
50
  this._tab.addWidget(wa);
43
- this.content.push(wa);
51
+ this._content.push(wa);
44
52
  return this;
45
53
  }
46
54
 
47
55
  removeWidget(widget: SVGWidget | HTMLWidget) {
48
56
  const wa = this.getWidgetAdapter(widget);
49
57
  if (wa) {
50
- const found = this.content.indexOf(wa);
58
+ const found = this._content.indexOf(wa);
51
59
  if (found >= 0) {
52
- this.content.splice(found, 1);
60
+ this._content.splice(found, 1);
53
61
  }
54
62
  widget.target(null);
55
63
  wa.dispose();
@@ -77,35 +85,11 @@ export class TabPanel extends HTMLWidget {
77
85
 
78
86
  render(callback?: (w: Widget) => void): this {
79
87
  return super.render(w => {
80
- this.content.watchRendered(this, callback);
88
+ this._content.watchRendered(this, callback);
81
89
  this._tab.update();
82
90
  });
83
91
  }
84
92
 
85
- // Phosphor Messaging ---
86
- messageHook(handler: IMessageHandler, msg: Message): boolean {
87
- if (handler === this) {
88
- this.processMessage(msg);
89
- }
90
- return true;
91
- }
92
-
93
- private _prevActive: Widget;
94
- processMessage(msg: Message): void {
95
- switch (msg.type) {
96
- case "wa-activate-request":
97
- const widget = (msg as Msg.WAActivateRequest).wa.widget;
98
- if (this._prevActive !== widget) {
99
- this._prevActive = widget;
100
- this.childActivation(widget);
101
- }
102
- break;
103
- }
104
- }
105
-
106
- childActivation(w: Widget) {
107
- }
108
-
109
93
  active(): Widget;
110
94
  active(_: Widget);
111
95
  active(_?: Widget): Widget | this {
@@ -113,5 +97,12 @@ export class TabPanel extends HTMLWidget {
113
97
  this._tab.currentWidget = this.getWidgetAdapter(_);
114
98
  return this;
115
99
  }
100
+
101
+ // Events ---
102
+ childActivation(w: Widget, wa: WidgetAdapter) {
103
+ }
104
+
105
+ layoutChanged() {
106
+ }
116
107
  }
117
108
  TabPanel.prototype._class += " phosphor_TabPanel";
@@ -13,5 +13,6 @@
13
13
  }
14
14
 
15
15
  .phosphor_WidgetAdapter.lm-SplitPanel-child {
16
- border: none;
16
+ border-top: none;
17
+ box-shadow: 0px -1px 0px rgba(0, 0, 0, 0.2), 1px 1px 2px rgba(0, 0, 0, 0.2);
17
18
  }