UNPKG

10.5 kBJavaScriptView Raw
1"use strict";
2var __extends = (this && this.__extends) || (function () {
3 var extendStatics = function (d, b) {
4 extendStatics = Object.setPrototypeOf ||
5 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
6 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
7 return extendStatics(d, b);
8 }
9 return function (d, b) {
10 extendStatics(d, b);
11 function __() { this.constructor = d; }
12 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
13 };
14})();
15Object.defineProperty(exports, "__esModule", { value: true });
16/*-----------------------------------------------------------------------------
17| Copyright (c) 2014-2017, PhosphorJS Contributors
18|
19| Distributed under the terms of the BSD 3-Clause License.
20|
21| The full license is in the file LICENSE, distributed with this software.
22|----------------------------------------------------------------------------*/
23var algorithm_1 = require("@phosphor/algorithm");
24var domutils_1 = require("@phosphor/domutils");
25var messaging_1 = require("@phosphor/messaging");
26var layout_1 = require("./layout");
27var panellayout_1 = require("./panellayout");
28var widget_1 = require("./widget");
29/**
30 * A layout where visible widgets are stacked atop one another.
31 *
32 * #### Notes
33 * The Z-order of the visible widgets follows their layout order.
34 */
35var StackedLayout = /** @class */ (function (_super) {
36 __extends(StackedLayout, _super);
37 function StackedLayout() {
38 var _this = _super !== null && _super.apply(this, arguments) || this;
39 _this._dirty = false;
40 _this._items = [];
41 _this._box = null;
42 return _this;
43 }
44 /**
45 * Dispose of the resources held by the layout.
46 */
47 StackedLayout.prototype.dispose = function () {
48 // Dispose of the layout items.
49 algorithm_1.each(this._items, function (item) { item.dispose(); });
50 // Clear the layout state.
51 this._box = null;
52 this._items.length = 0;
53 // Dispose of the rest of the layout.
54 _super.prototype.dispose.call(this);
55 };
56 /**
57 * Attach a widget to the parent's DOM node.
58 *
59 * @param index - The current index of the widget in the layout.
60 *
61 * @param widget - The widget to attach to the parent.
62 *
63 * #### Notes
64 * This is a reimplementation of the superclass method.
65 */
66 StackedLayout.prototype.attachWidget = function (index, widget) {
67 // Create and add a new layout item for the widget.
68 algorithm_1.ArrayExt.insert(this._items, index, new layout_1.LayoutItem(widget));
69 // Send a `'before-attach'` message if the parent is attached.
70 if (this.parent.isAttached) {
71 messaging_1.MessageLoop.sendMessage(widget, widget_1.Widget.Msg.BeforeAttach);
72 }
73 // Add the widget's node to the parent.
74 this.parent.node.appendChild(widget.node);
75 // Send an `'after-attach'` message if the parent is attached.
76 if (this.parent.isAttached) {
77 messaging_1.MessageLoop.sendMessage(widget, widget_1.Widget.Msg.AfterAttach);
78 }
79 // Post a fit request for the parent widget.
80 this.parent.fit();
81 };
82 /**
83 * Move a widget in the parent's DOM node.
84 *
85 * @param fromIndex - The previous index of the widget in the layout.
86 *
87 * @param toIndex - The current index of the widget in the layout.
88 *
89 * @param widget - The widget to move in the parent.
90 *
91 * #### Notes
92 * This is a reimplementation of the superclass method.
93 */
94 StackedLayout.prototype.moveWidget = function (fromIndex, toIndex, widget) {
95 // Move the layout item for the widget.
96 algorithm_1.ArrayExt.move(this._items, fromIndex, toIndex);
97 // Post an update request for the parent widget.
98 this.parent.update();
99 };
100 /**
101 * Detach a widget from the parent's DOM node.
102 *
103 * @param index - The previous index of the widget in the layout.
104 *
105 * @param widget - The widget to detach from the parent.
106 *
107 * #### Notes
108 * This is a reimplementation of the superclass method.
109 */
110 StackedLayout.prototype.detachWidget = function (index, widget) {
111 // Remove the layout item for the widget.
112 var item = algorithm_1.ArrayExt.removeAt(this._items, index);
113 // Send a `'before-detach'` message if the parent is attached.
114 if (this.parent.isAttached) {
115 messaging_1.MessageLoop.sendMessage(widget, widget_1.Widget.Msg.BeforeDetach);
116 }
117 // Remove the widget's node from the parent.
118 this.parent.node.removeChild(widget.node);
119 // Send an `'after-detach'` message if the parent is attached.
120 if (this.parent.isAttached) {
121 messaging_1.MessageLoop.sendMessage(widget, widget_1.Widget.Msg.AfterDetach);
122 }
123 // Reset the z-index for the widget.
124 item.widget.node.style.zIndex = '';
125 // Dispose of the layout item.
126 item.dispose();
127 // Post a fit request for the parent widget.
128 this.parent.fit();
129 };
130 /**
131 * A message handler invoked on a `'before-show'` message.
132 */
133 StackedLayout.prototype.onBeforeShow = function (msg) {
134 _super.prototype.onBeforeShow.call(this, msg);
135 this.parent.update();
136 };
137 /**
138 * A message handler invoked on a `'before-attach'` message.
139 */
140 StackedLayout.prototype.onBeforeAttach = function (msg) {
141 _super.prototype.onBeforeAttach.call(this, msg);
142 this.parent.fit();
143 };
144 /**
145 * A message handler invoked on a `'child-shown'` message.
146 */
147 StackedLayout.prototype.onChildShown = function (msg) {
148 this.parent.fit();
149 };
150 /**
151 * A message handler invoked on a `'child-hidden'` message.
152 */
153 StackedLayout.prototype.onChildHidden = function (msg) {
154 this.parent.fit();
155 };
156 /**
157 * A message handler invoked on a `'resize'` message.
158 */
159 StackedLayout.prototype.onResize = function (msg) {
160 if (this.parent.isVisible) {
161 this._update(msg.width, msg.height);
162 }
163 };
164 /**
165 * A message handler invoked on an `'update-request'` message.
166 */
167 StackedLayout.prototype.onUpdateRequest = function (msg) {
168 if (this.parent.isVisible) {
169 this._update(-1, -1);
170 }
171 };
172 /**
173 * A message handler invoked on a `'fit-request'` message.
174 */
175 StackedLayout.prototype.onFitRequest = function (msg) {
176 if (this.parent.isAttached) {
177 this._fit();
178 }
179 };
180 /**
181 * Fit the layout to the total size required by the widgets.
182 */
183 StackedLayout.prototype._fit = function () {
184 // Set up the computed minimum size.
185 var minW = 0;
186 var minH = 0;
187 // Update the computed minimum size.
188 for (var i = 0, n = this._items.length; i < n; ++i) {
189 // Fetch the item.
190 var item = this._items[i];
191 // Ignore hidden items.
192 if (item.isHidden) {
193 continue;
194 }
195 // Update the size limits for the item.
196 item.fit();
197 // Update the computed minimum size.
198 minW = Math.max(minW, item.minWidth);
199 minH = Math.max(minH, item.minHeight);
200 }
201 // Update the box sizing and add it to the computed min size.
202 var box = this._box = domutils_1.ElementExt.boxSizing(this.parent.node);
203 minW += box.horizontalSum;
204 minH += box.verticalSum;
205 // Update the parent's min size constraints.
206 var style = this.parent.node.style;
207 style.minWidth = minW + "px";
208 style.minHeight = minH + "px";
209 // Set the dirty flag to ensure only a single update occurs.
210 this._dirty = true;
211 // Notify the ancestor that it should fit immediately. This may
212 // cause a resize of the parent, fulfilling the required update.
213 if (this.parent.parent) {
214 messaging_1.MessageLoop.sendMessage(this.parent.parent, widget_1.Widget.Msg.FitRequest);
215 }
216 // If the dirty flag is still set, the parent was not resized.
217 // Trigger the required update on the parent widget immediately.
218 if (this._dirty) {
219 messaging_1.MessageLoop.sendMessage(this.parent, widget_1.Widget.Msg.UpdateRequest);
220 }
221 };
222 /**
223 * Update the layout position and size of the widgets.
224 *
225 * The parent offset dimensions should be `-1` if unknown.
226 */
227 StackedLayout.prototype._update = function (offsetWidth, offsetHeight) {
228 // Clear the dirty flag to indicate the update occurred.
229 this._dirty = false;
230 // Compute the visible item count.
231 var nVisible = 0;
232 for (var i = 0, n = this._items.length; i < n; ++i) {
233 nVisible += +!this._items[i].isHidden;
234 }
235 // Bail early if there are no visible items to layout.
236 if (nVisible === 0) {
237 return;
238 }
239 // Measure the parent if the offset dimensions are unknown.
240 if (offsetWidth < 0) {
241 offsetWidth = this.parent.node.offsetWidth;
242 }
243 if (offsetHeight < 0) {
244 offsetHeight = this.parent.node.offsetHeight;
245 }
246 // Ensure the parent box sizing data is computed.
247 if (!this._box) {
248 this._box = domutils_1.ElementExt.boxSizing(this.parent.node);
249 }
250 // Compute the actual layout bounds adjusted for border and padding.
251 var top = this._box.paddingTop;
252 var left = this._box.paddingLeft;
253 var width = offsetWidth - this._box.horizontalSum;
254 var height = offsetHeight - this._box.verticalSum;
255 // Update the widget stacking order and layout geometry.
256 for (var i = 0, n = this._items.length; i < n; ++i) {
257 // Fetch the item.
258 var item = this._items[i];
259 // Ignore hidden items.
260 if (item.isHidden) {
261 continue;
262 }
263 // Set the z-index for the widget.
264 item.widget.node.style.zIndex = "" + i;
265 // Update the item geometry.
266 item.update(left, top, width, height);
267 }
268 };
269 return StackedLayout;
270}(panellayout_1.PanelLayout));
271exports.StackedLayout = StackedLayout;