UNPKG

11.7 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 messaging_1 = require("@phosphor/messaging");
25var layout_1 = require("./layout");
26var widget_1 = require("./widget");
27/**
28 * A concrete layout implementation suitable for many use cases.
29 *
30 * #### Notes
31 * This class is suitable as a base class for implementing a variety of
32 * layouts, but can also be used directly with standard CSS to layout a
33 * collection of widgets.
34 */
35var PanelLayout = /** @class */ (function (_super) {
36 __extends(PanelLayout, _super);
37 function PanelLayout() {
38 var _this = _super !== null && _super.apply(this, arguments) || this;
39 _this._widgets = [];
40 return _this;
41 }
42 /**
43 * Dispose of the resources held by the layout.
44 *
45 * #### Notes
46 * This will clear and dispose all widgets in the layout.
47 *
48 * All reimplementations should call the superclass method.
49 *
50 * This method is called automatically when the parent is disposed.
51 */
52 PanelLayout.prototype.dispose = function () {
53 while (this._widgets.length > 0) {
54 this._widgets.pop().dispose();
55 }
56 _super.prototype.dispose.call(this);
57 };
58 Object.defineProperty(PanelLayout.prototype, "widgets", {
59 /**
60 * A read-only array of the widgets in the layout.
61 */
62 get: function () {
63 return this._widgets;
64 },
65 enumerable: true,
66 configurable: true
67 });
68 /**
69 * Create an iterator over the widgets in the layout.
70 *
71 * @returns A new iterator over the widgets in the layout.
72 */
73 PanelLayout.prototype.iter = function () {
74 return algorithm_1.iter(this._widgets);
75 };
76 /**
77 * Add a widget to the end of the layout.
78 *
79 * @param widget - The widget to add to the layout.
80 *
81 * #### Notes
82 * If the widget is already contained in the layout, it will be moved.
83 */
84 PanelLayout.prototype.addWidget = function (widget) {
85 this.insertWidget(this._widgets.length, widget);
86 };
87 /**
88 * Insert a widget into the layout at the specified index.
89 *
90 * @param index - The index at which to insert the widget.
91 *
92 * @param widget - The widget to insert into the layout.
93 *
94 * #### Notes
95 * The index will be clamped to the bounds of the widgets.
96 *
97 * If the widget is already added to the layout, it will be moved.
98 *
99 * #### Undefined Behavior
100 * An `index` which is non-integral.
101 */
102 PanelLayout.prototype.insertWidget = function (index, widget) {
103 // Remove the widget from its current parent. This is a no-op
104 // if the widget's parent is already the layout parent widget.
105 widget.parent = this.parent;
106 // Look up the current index of the widget.
107 var i = this._widgets.indexOf(widget);
108 // Clamp the insert index to the array bounds.
109 var j = Math.max(0, Math.min(index, this._widgets.length));
110 // If the widget is not in the array, insert it.
111 if (i === -1) {
112 // Insert the widget into the array.
113 algorithm_1.ArrayExt.insert(this._widgets, j, widget);
114 // If the layout is parented, attach the widget to the DOM.
115 if (this.parent) {
116 this.attachWidget(j, widget);
117 }
118 // There is nothing more to do.
119 return;
120 }
121 // Otherwise, the widget exists in the array and should be moved.
122 // Adjust the index if the location is at the end of the array.
123 if (j === this._widgets.length) {
124 j--;
125 }
126 // Bail if there is no effective move.
127 if (i === j) {
128 return;
129 }
130 // Move the widget to the new location.
131 algorithm_1.ArrayExt.move(this._widgets, i, j);
132 // If the layout is parented, move the widget in the DOM.
133 if (this.parent) {
134 this.moveWidget(i, j, widget);
135 }
136 };
137 /**
138 * Remove a widget from the layout.
139 *
140 * @param widget - The widget to remove from the layout.
141 *
142 * #### Notes
143 * A widget is automatically removed from the layout when its `parent`
144 * is set to `null`. This method should only be invoked directly when
145 * removing a widget from a layout which has yet to be installed on a
146 * parent widget.
147 *
148 * This method does *not* modify the widget's `parent`.
149 */
150 PanelLayout.prototype.removeWidget = function (widget) {
151 this.removeWidgetAt(this._widgets.indexOf(widget));
152 };
153 /**
154 * Remove the widget at a given index from the layout.
155 *
156 * @param index - The index of the widget to remove.
157 *
158 * #### Notes
159 * A widget is automatically removed from the layout when its `parent`
160 * is set to `null`. This method should only be invoked directly when
161 * removing a widget from a layout which has yet to be installed on a
162 * parent widget.
163 *
164 * This method does *not* modify the widget's `parent`.
165 *
166 * #### Undefined Behavior
167 * An `index` which is non-integral.
168 */
169 PanelLayout.prototype.removeWidgetAt = function (index) {
170 // Remove the widget from the array.
171 var widget = algorithm_1.ArrayExt.removeAt(this._widgets, index);
172 // If the layout is parented, detach the widget from the DOM.
173 if (widget && this.parent) {
174 this.detachWidget(index, widget);
175 }
176 };
177 /**
178 * Perform layout initialization which requires the parent widget.
179 */
180 PanelLayout.prototype.init = function () {
181 var _this = this;
182 _super.prototype.init.call(this);
183 algorithm_1.each(this, function (widget, index) {
184 _this.attachWidget(index, widget);
185 });
186 };
187 /**
188 * Attach a widget to the parent's DOM node.
189 *
190 * @param index - The current index of the widget in the layout.
191 *
192 * @param widget - The widget to attach to the parent.
193 *
194 * #### Notes
195 * This method is called automatically by the panel layout at the
196 * appropriate time. It should not be called directly by user code.
197 *
198 * The default implementation adds the widgets's node to the parent's
199 * node at the proper location, and sends the appropriate attach
200 * messages to the widget if the parent is attached to the DOM.
201 *
202 * Subclasses may reimplement this method to control how the widget's
203 * node is added to the parent's node.
204 */
205 PanelLayout.prototype.attachWidget = function (index, widget) {
206 // Look up the next sibling reference node.
207 var ref = this.parent.node.children[index];
208 // Send a `'before-attach'` message if the parent is attached.
209 if (this.parent.isAttached) {
210 messaging_1.MessageLoop.sendMessage(widget, widget_1.Widget.Msg.BeforeAttach);
211 }
212 // Insert the widget's node before the sibling.
213 this.parent.node.insertBefore(widget.node, ref);
214 // Send an `'after-attach'` message if the parent is attached.
215 if (this.parent.isAttached) {
216 messaging_1.MessageLoop.sendMessage(widget, widget_1.Widget.Msg.AfterAttach);
217 }
218 };
219 /**
220 * Move a widget in the parent's DOM node.
221 *
222 * @param fromIndex - The previous index of the widget in the layout.
223 *
224 * @param toIndex - The current index of the widget in the layout.
225 *
226 * @param widget - The widget to move in the parent.
227 *
228 * #### Notes
229 * This method is called automatically by the panel layout at the
230 * appropriate time. It should not be called directly by user code.
231 *
232 * The default implementation moves the widget's node to the proper
233 * location in the parent's node and sends the appropriate attach and
234 * detach messages to the widget if the parent is attached to the DOM.
235 *
236 * Subclasses may reimplement this method to control how the widget's
237 * node is moved in the parent's node.
238 */
239 PanelLayout.prototype.moveWidget = function (fromIndex, toIndex, widget) {
240 // Send a `'before-detach'` message if the parent is attached.
241 if (this.parent.isAttached) {
242 messaging_1.MessageLoop.sendMessage(widget, widget_1.Widget.Msg.BeforeDetach);
243 }
244 // Remove the widget's node from the parent.
245 this.parent.node.removeChild(widget.node);
246 // Send an `'after-detach'` and message if the parent is attached.
247 if (this.parent.isAttached) {
248 messaging_1.MessageLoop.sendMessage(widget, widget_1.Widget.Msg.AfterDetach);
249 }
250 // Look up the next sibling reference node.
251 var ref = this.parent.node.children[toIndex];
252 // Send a `'before-attach'` message if the parent is attached.
253 if (this.parent.isAttached) {
254 messaging_1.MessageLoop.sendMessage(widget, widget_1.Widget.Msg.BeforeAttach);
255 }
256 // Insert the widget's node before the sibling.
257 this.parent.node.insertBefore(widget.node, ref);
258 // Send an `'after-attach'` message if the parent is attached.
259 if (this.parent.isAttached) {
260 messaging_1.MessageLoop.sendMessage(widget, widget_1.Widget.Msg.AfterAttach);
261 }
262 };
263 /**
264 * Detach a widget from the parent's DOM node.
265 *
266 * @param index - The previous index of the widget in the layout.
267 *
268 * @param widget - The widget to detach from the parent.
269 *
270 * #### Notes
271 * This method is called automatically by the panel layout at the
272 * appropriate time. It should not be called directly by user code.
273 *
274 * The default implementation removes the widget's node from the
275 * parent's node, and sends the appropriate detach messages to the
276 * widget if the parent is attached to the DOM.
277 *
278 * Subclasses may reimplement this method to control how the widget's
279 * node is removed from the parent's node.
280 */
281 PanelLayout.prototype.detachWidget = function (index, widget) {
282 // Send a `'before-detach'` message if the parent is attached.
283 if (this.parent.isAttached) {
284 messaging_1.MessageLoop.sendMessage(widget, widget_1.Widget.Msg.BeforeDetach);
285 }
286 // Remove the widget's node from the parent.
287 this.parent.node.removeChild(widget.node);
288 // Send an `'after-detach'` message if the parent is attached.
289 if (this.parent.isAttached) {
290 messaging_1.MessageLoop.sendMessage(widget, widget_1.Widget.Msg.AfterDetach);
291 }
292 };
293 return PanelLayout;
294}(layout_1.Layout));
295exports.PanelLayout = PanelLayout;