Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / third_party / WebKit / Source / devtools / front_end / ui / SplitWidget.js
blob592e2a1227e47dd1c39aa0fc2c032daf8c9cc28a
1 /*
2 * Copyright (C) 2012 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following disclaimer
13 * in the documentation and/or other materials provided with the
14 * distribution.
16 * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. AND ITS CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC.
20 * OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 /**
30 * @constructor
31 * @extends {WebInspector.Widget}
32 * @param {boolean} isVertical
33 * @param {boolean} secondIsSidebar
34 * @param {string=} settingName
35 * @param {number=} defaultSidebarWidth
36 * @param {number=} defaultSidebarHeight
37 * @param {boolean=} constraintsInDip
39 WebInspector.SplitWidget = function(isVertical, secondIsSidebar, settingName, defaultSidebarWidth, defaultSidebarHeight, constraintsInDip)
41 WebInspector.Widget.call(this, true);
42 this.element.classList.add("split-widget");
43 this.registerRequiredCSS("ui/splitWidget.css");
45 this.contentElement.classList.add("shadow-split-widget");
46 this._mainElement = this.contentElement.createChild("div", "shadow-split-widget-contents shadow-split-widget-main vbox");
47 this._mainElement.createChild("content").select = ".insertion-point-main";
48 this._sidebarElement = this.contentElement.createChild("div", "shadow-split-widget-contents shadow-split-widget-sidebar vbox");
49 this._sidebarElement.createChild("content").select = ".insertion-point-sidebar";
50 this._resizerElement = this.contentElement.createChild("div", "shadow-split-widget-resizer");
52 this._resizerWidget = new WebInspector.SimpleResizerWidget();
53 this._resizerWidget.setEnabled(true);
54 this._resizerWidget.addEventListener(WebInspector.ResizerWidget.Events.ResizeStart, this._onResizeStart, this);
55 this._resizerWidget.addEventListener(WebInspector.ResizerWidget.Events.ResizeUpdate, this._onResizeUpdate, this);
56 this._resizerWidget.addEventListener(WebInspector.ResizerWidget.Events.ResizeEnd, this._onResizeEnd, this);
58 this._defaultSidebarWidth = defaultSidebarWidth || 200;
59 this._defaultSidebarHeight = defaultSidebarHeight || this._defaultSidebarWidth;
60 this._constraintsInDip = !!constraintsInDip;
61 this._setting = settingName ? WebInspector.settings.createSetting(settingName, {}) : null;
63 this.setSecondIsSidebar(secondIsSidebar);
65 this._innerSetVertical(isVertical);
66 this._showMode = WebInspector.SplitWidget.ShowMode.Both;
68 // Should be called after isVertical has the right value.
69 this.installResizer(this._resizerElement);
72 /** @typedef {{showMode: string, size: number}} */
73 WebInspector.SplitWidget.SettingForOrientation;
75 WebInspector.SplitWidget.ShowMode = {
76 Both: "Both",
77 OnlyMain: "OnlyMain",
78 OnlySidebar: "OnlySidebar"
81 WebInspector.SplitWidget.Events = {
82 SidebarSizeChanged: "SidebarSizeChanged",
83 ShowModeChanged: "ShowModeChanged"
86 WebInspector.SplitWidget.MinPadding = 20;
88 WebInspector.SplitWidget.prototype = {
89 /**
90 * @return {boolean}
92 isVertical: function()
94 return this._isVertical;
97 /**
98 * @param {boolean} isVertical
100 setVertical: function(isVertical)
102 if (this._isVertical === isVertical)
103 return;
105 this._innerSetVertical(isVertical);
107 if (this.isShowing())
108 this._updateLayout();
112 * @param {boolean} isVertical
114 _innerSetVertical: function(isVertical)
116 this.contentElement.classList.toggle("vbox", !isVertical);
117 this.contentElement.classList.toggle("hbox", isVertical);
118 this._isVertical = isVertical;
120 delete this._resizerElementSize;
121 this._sidebarSizeDIP = -1;
122 this._restoreSidebarSizeFromSettings();
123 if (this._shouldSaveShowMode)
124 this._restoreAndApplyShowModeFromSettings();
125 this._updateShowHideSidebarButton();
126 // FIXME: reverse SplitWidget.isVertical meaning.
127 this._resizerWidget.setVertical(!isVertical);
128 this.invalidateConstraints();
132 * @param {boolean=} animate
134 _updateLayout: function(animate)
136 delete this._totalSizeCSS; // Lazy update.
137 delete this._totalSizeOtherDimensionCSS;
139 // Remove properties that might affect total size calculation.
140 this._mainElement.style.removeProperty("width");
141 this._mainElement.style.removeProperty("height");
142 this._sidebarElement.style.removeProperty("width");
143 this._sidebarElement.style.removeProperty("height");
145 this._innerSetSidebarSizeDIP(this._preferredSidebarSizeDIP(), !!animate);
149 * @param {!WebInspector.Widget} widget
151 setMainWidget: function(widget)
153 if (this._mainWidget)
154 this._mainWidget.detach();
155 this._mainWidget = widget;
156 if (widget) {
157 widget.element.classList.add("insertion-point-main");
158 widget.element.classList.remove("insertion-point-sidebar");
159 if (this._showMode === WebInspector.SplitWidget.ShowMode.OnlyMain || this._showMode === WebInspector.SplitWidget.ShowMode.Both)
160 widget.show(this.element);
165 * @param {!WebInspector.Widget} widget
167 setSidebarWidget: function(widget)
169 if (this._sidebarWidget)
170 this._sidebarWidget.detach();
171 this._sidebarWidget = widget;
172 if (widget) {
173 widget.element.classList.add("insertion-point-sidebar");
174 widget.element.classList.remove("insertion-point-main");
175 if (this._showMode === WebInspector.SplitWidget.ShowMode.OnlySidebar || this._showMode === WebInspector.SplitWidget.ShowMode.Both)
176 widget.show(this.element);
181 * @return {?WebInspector.Widget}
183 mainWidget: function()
185 return this._mainWidget;
189 * @return {?WebInspector.Widget}
191 sidebarWidget: function()
193 return this._sidebarWidget;
197 * @override
198 * @param {!WebInspector.Widget} widget
200 childWasDetached: function(widget)
202 if (this._detaching)
203 return;
204 if (this._mainWidget === widget)
205 delete this._mainWidget;
206 if (this._sidebarWidget === widget)
207 delete this._sidebarWidget;
211 * @return {boolean}
213 isSidebarSecond: function()
215 return this._secondIsSidebar;
218 enableShowModeSaving: function()
220 this._shouldSaveShowMode = true;
221 this._restoreAndApplyShowModeFromSettings();
225 * @return {string}
227 showMode: function()
229 return this._showMode;
233 * @param {boolean} secondIsSidebar
235 setSecondIsSidebar: function(secondIsSidebar)
237 this.contentElement.classList.toggle("shadow-split-widget-first-is-sidebar", !secondIsSidebar);
238 this._secondIsSidebar = secondIsSidebar;
242 * @return {?string}
244 sidebarSide: function()
246 if (this._showMode !== WebInspector.SplitWidget.ShowMode.Both)
247 return null;
248 return this._isVertical ?
249 (this._secondIsSidebar ? "right" : "left") :
250 (this._secondIsSidebar ? "bottom" : "top");
254 * @return {!Element}
256 resizerElement: function()
258 return this._resizerElement;
262 * @param {boolean=} animate
264 hideMain: function(animate)
266 this._showOnly(this._sidebarWidget, this._mainWidget, this._sidebarElement, this._mainElement, animate);
267 this._updateShowMode(WebInspector.SplitWidget.ShowMode.OnlySidebar);
271 * @param {boolean=} animate
273 hideSidebar: function(animate)
275 this._showOnly(this._mainWidget, this._sidebarWidget, this._mainElement, this._sidebarElement, animate);
276 this._updateShowMode(WebInspector.SplitWidget.ShowMode.OnlyMain);
280 * @param {!WebInspector.Widget} sideToShow
281 * @param {!WebInspector.Widget} sideToHide
282 * @param {!Element} shadowToShow
283 * @param {!Element} shadowToHide
284 * @param {boolean=} animate
286 _showOnly: function(sideToShow, sideToHide, shadowToShow, shadowToHide, animate)
288 this._cancelAnimation();
291 * @this {WebInspector.SplitWidget}
293 function callback()
295 if (sideToShow) {
296 // Make sure main is first in the children list.
297 if (sideToShow === this._mainWidget)
298 this._mainWidget.show(this.element, this._sidebarWidget ? this._sidebarWidget.element : null);
299 else
300 this._sidebarWidget.show(this.element);
302 if (sideToHide) {
303 this._detaching = true;
304 sideToHide.detach();
305 delete this._detaching;
308 this._resizerElement.classList.add("hidden");
309 shadowToShow.classList.remove("hidden");
310 shadowToShow.classList.add("maximized");
311 shadowToHide.classList.add("hidden");
312 shadowToHide.classList.remove("maximized");
313 this._removeAllLayoutProperties();
314 this.doResize();
317 if (animate)
318 this._animate(true, callback.bind(this));
319 else
320 callback.call(this);
322 this._sidebarSizeDIP = -1;
323 this.setResizable(false);
326 _removeAllLayoutProperties: function()
328 this._sidebarElement.style.removeProperty("flexBasis");
330 this._mainElement.style.removeProperty("width");
331 this._mainElement.style.removeProperty("height");
332 this._sidebarElement.style.removeProperty("width");
333 this._sidebarElement.style.removeProperty("height");
335 this._resizerElement.style.removeProperty("left");
336 this._resizerElement.style.removeProperty("right");
337 this._resizerElement.style.removeProperty("top");
338 this._resizerElement.style.removeProperty("bottom");
340 this._resizerElement.style.removeProperty("margin-left");
341 this._resizerElement.style.removeProperty("margin-right");
342 this._resizerElement.style.removeProperty("margin-top");
343 this._resizerElement.style.removeProperty("margin-bottom");
347 * @param {boolean=} animate
349 showBoth: function(animate)
351 if (this._showMode === WebInspector.SplitWidget.ShowMode.Both)
352 animate = false;
354 this._cancelAnimation();
355 this._mainElement.classList.remove("maximized", "hidden");
356 this._sidebarElement.classList.remove("maximized", "hidden");
357 this._resizerElement.classList.remove("hidden");
359 // Make sure main is the first in the children list.
360 if (this._sidebarWidget)
361 this._sidebarWidget.show(this.element);
362 if (this._mainWidget)
363 this._mainWidget.show(this.element, this._sidebarWidget ? this._sidebarWidget.element : null);
364 // Order widgets in DOM properly.
365 this.setSecondIsSidebar(this._secondIsSidebar);
367 this._sidebarSizeDIP = -1;
368 this.setResizable(true);
369 this._updateShowMode(WebInspector.SplitWidget.ShowMode.Both);
370 this._updateLayout(animate);
374 * @param {boolean} resizable
376 setResizable: function(resizable)
378 this._resizerWidget.setEnabled(resizable);
382 * @return {boolean}
384 isResizable: function()
386 return this._resizerWidget.isEnabled();
390 * @param {number} size
392 setSidebarSize: function(size)
394 var sizeDIP = WebInspector.zoomManager.cssToDIP(size);
395 this._savedSidebarSizeDIP = sizeDIP;
396 this._saveSetting();
397 this._innerSetSidebarSizeDIP(sizeDIP, false, true);
401 * @return {number}
403 sidebarSize: function()
405 var sizeDIP = Math.max(0, this._sidebarSizeDIP);
406 return WebInspector.zoomManager.dipToCSS(sizeDIP);
410 * Returns total size in DIP.
411 * @return {number}
413 _totalSizeDIP: function()
415 if (!this._totalSizeCSS) {
416 this._totalSizeCSS = this._isVertical ? this.contentElement.offsetWidth : this.contentElement.offsetHeight;
417 this._totalSizeOtherDimensionCSS = this._isVertical ? this.contentElement.offsetHeight : this.contentElement.offsetWidth;
419 return WebInspector.zoomManager.cssToDIP(this._totalSizeCSS);
423 * @param {string} showMode
425 _updateShowMode: function(showMode)
427 this._showMode = showMode;
428 this._saveShowModeToSettings();
429 this._updateShowHideSidebarButton();
430 this.dispatchEventToListeners(WebInspector.SplitWidget.Events.ShowModeChanged, showMode);
431 this.invalidateConstraints();
435 * @param {number} sizeDIP
436 * @param {boolean} animate
437 * @param {boolean=} userAction
439 _innerSetSidebarSizeDIP: function(sizeDIP, animate, userAction)
441 if (this._showMode !== WebInspector.SplitWidget.ShowMode.Both || !this.isShowing())
442 return;
444 sizeDIP = this._applyConstraints(sizeDIP, userAction);
445 if (this._sidebarSizeDIP === sizeDIP)
446 return;
448 if (!this._resizerElementSize)
449 this._resizerElementSize = this._isVertical ? this._resizerElement.offsetWidth : this._resizerElement.offsetHeight;
451 // Invalidate layout below.
453 this._removeAllLayoutProperties();
455 // this._totalSizeDIP is available below since we successfully applied constraints.
456 var sidebarSizeValue = WebInspector.zoomManager.dipToCSS(sizeDIP) + "px";
457 var mainSizeValue = (this._totalSizeCSS - WebInspector.zoomManager.dipToCSS(sizeDIP)) + "px";
458 this._sidebarElement.style.flexBasis = sidebarSizeValue;
460 // Make both sides relayout boundaries.
461 if (this._isVertical) {
462 this._sidebarElement.style.width = sidebarSizeValue;
463 this._mainElement.style.width = mainSizeValue;
464 this._sidebarElement.style.height = this._totalSizeOtherDimensionCSS + "px";
465 this._mainElement.style.height = this._totalSizeOtherDimensionCSS + "px";
466 } else {
467 this._sidebarElement.style.height = sidebarSizeValue;
468 this._mainElement.style.height = mainSizeValue;
469 this._sidebarElement.style.width = this._totalSizeOtherDimensionCSS + "px";
470 this._mainElement.style.width = this._totalSizeOtherDimensionCSS + "px";
473 // Position resizer.
474 if (this._isVertical) {
475 if (this._secondIsSidebar) {
476 this._resizerElement.style.right = sidebarSizeValue;
477 this._resizerElement.style.marginRight = -this._resizerElementSize / 2 + "px";
478 } else {
479 this._resizerElement.style.left = sidebarSizeValue;
480 this._resizerElement.style.marginLeft = -this._resizerElementSize / 2 + "px";
482 } else {
483 if (this._secondIsSidebar) {
484 this._resizerElement.style.bottom = sidebarSizeValue;
485 this._resizerElement.style.marginBottom = -this._resizerElementSize / 2 + "px";
486 } else {
487 this._resizerElement.style.top = sidebarSizeValue;
488 this._resizerElement.style.marginTop = -this._resizerElementSize / 2 + "px";
492 this._sidebarSizeDIP = sizeDIP;
494 // Force layout.
496 if (animate) {
497 this._animate(false);
498 } else {
499 // No need to recalculate this._sidebarSizeDIP and this._totalSizeDIP again.
500 this.doResize();
501 this.dispatchEventToListeners(WebInspector.SplitWidget.Events.SidebarSizeChanged, this.sidebarSize());
506 * @param {boolean} reverse
507 * @param {function()=} callback
509 _animate: function(reverse, callback)
511 var animationTime = 50;
512 this._animationCallback = callback;
514 var animatedMarginPropertyName;
515 if (this._isVertical)
516 animatedMarginPropertyName = this._secondIsSidebar ? "margin-right" : "margin-left";
517 else
518 animatedMarginPropertyName = this._secondIsSidebar ? "margin-bottom" : "margin-top";
520 var marginFrom = reverse ? "0" : "-" + WebInspector.zoomManager.dipToCSS(this._sidebarSizeDIP) + "px";
521 var marginTo = reverse ? "-" + WebInspector.zoomManager.dipToCSS(this._sidebarSizeDIP) + "px" : "0";
523 // This order of things is important.
524 // 1. Resize main element early and force layout.
525 this.contentElement.style.setProperty(animatedMarginPropertyName, marginFrom);
526 if (!reverse) {
527 suppressUnused(this._mainElement.offsetWidth);
528 suppressUnused(this._sidebarElement.offsetWidth);
531 // 2. Issue onresize to the sidebar element, its size won't change.
532 if (!reverse)
533 this._sidebarWidget.doResize();
535 // 3. Configure and run animation
536 this.contentElement.style.setProperty("transition", animatedMarginPropertyName + " " + animationTime + "ms linear");
538 var boundAnimationFrame;
539 var startTime;
541 * @this {WebInspector.SplitWidget}
543 function animationFrame()
545 delete this._animationFrameHandle;
547 if (!startTime) {
548 // Kick animation on first frame.
549 this.contentElement.style.setProperty(animatedMarginPropertyName, marginTo);
550 startTime = window.performance.now();
551 } else if (window.performance.now() < startTime + animationTime) {
552 // Process regular animation frame.
553 if (this._mainWidget)
554 this._mainWidget.doResize();
555 } else {
556 // Complete animation.
557 this._cancelAnimation();
558 if (this._mainWidget)
559 this._mainWidget.doResize();
560 this.dispatchEventToListeners(WebInspector.SplitWidget.Events.SidebarSizeChanged, this.sidebarSize());
561 return;
563 this._animationFrameHandle = this.contentElement.window().requestAnimationFrame(boundAnimationFrame);
565 boundAnimationFrame = animationFrame.bind(this);
566 this._animationFrameHandle = this.contentElement.window().requestAnimationFrame(boundAnimationFrame);
569 _cancelAnimation: function()
571 this.contentElement.style.removeProperty("margin-top");
572 this.contentElement.style.removeProperty("margin-right");
573 this.contentElement.style.removeProperty("margin-bottom");
574 this.contentElement.style.removeProperty("margin-left");
575 this.contentElement.style.removeProperty("transition");
577 if (this._animationFrameHandle) {
578 this.contentElement.window().cancelAnimationFrame(this._animationFrameHandle);
579 delete this._animationFrameHandle;
581 if (this._animationCallback) {
582 this._animationCallback();
583 delete this._animationCallback;
588 * @param {number} sidebarSize
589 * @param {boolean=} userAction
590 * @return {number}
592 _applyConstraints: function(sidebarSize, userAction)
594 var totalSize = this._totalSizeDIP();
595 var zoomFactor = this._constraintsInDip ? 1 : WebInspector.zoomManager.zoomFactor();
597 var constraints = this._sidebarWidget ? this._sidebarWidget.constraints() : new Constraints();
598 var minSidebarSize = this.isVertical() ? constraints.minimum.width : constraints.minimum.height;
599 if (!minSidebarSize)
600 minSidebarSize = WebInspector.SplitWidget.MinPadding;
601 minSidebarSize *= zoomFactor;
603 var preferredSidebarSize = this.isVertical() ? constraints.preferred.width : constraints.preferred.height;
604 if (!preferredSidebarSize)
605 preferredSidebarSize = WebInspector.SplitWidget.MinPadding;
606 preferredSidebarSize *= zoomFactor;
607 // Allow sidebar to be less than preferred by explicit user action.
608 if (sidebarSize < preferredSidebarSize)
609 preferredSidebarSize = Math.max(sidebarSize, minSidebarSize);
610 preferredSidebarSize += zoomFactor; // 1 css pixel for splitter border.
612 constraints = this._mainWidget ? this._mainWidget.constraints() : new Constraints();
613 var minMainSize = this.isVertical() ? constraints.minimum.width : constraints.minimum.height;
614 if (!minMainSize)
615 minMainSize = WebInspector.SplitWidget.MinPadding;
616 minMainSize *= zoomFactor;
618 var preferredMainSize = this.isVertical() ? constraints.preferred.width : constraints.preferred.height;
619 if (!preferredMainSize)
620 preferredMainSize = WebInspector.SplitWidget.MinPadding;
621 preferredMainSize *= zoomFactor;
622 var savedMainSize = this.isVertical() ? this._savedVerticalMainSize : this._savedHorizontalMainSize;
623 if (typeof savedMainSize !== "undefined")
624 preferredMainSize = Math.min(preferredMainSize, savedMainSize * zoomFactor);
625 if (userAction)
626 preferredMainSize = minMainSize;
628 // Enough space for preferred.
629 var totalPreferred = preferredMainSize + preferredSidebarSize;
630 if (totalPreferred <= totalSize)
631 return Number.constrain(sidebarSize, preferredSidebarSize, totalSize - preferredMainSize);
633 // Enough space for minimum.
634 if (minMainSize + minSidebarSize <= totalSize) {
635 var delta = totalPreferred - totalSize;
636 var sidebarDelta = delta * preferredSidebarSize / totalPreferred;
637 sidebarSize = preferredSidebarSize - sidebarDelta;
638 return Number.constrain(sidebarSize, minSidebarSize, totalSize - minMainSize);
641 // Not enough space even for minimum sizes.
642 return Math.max(0, totalSize - minMainSize);
645 wasShown: function()
647 this._forceUpdateLayout();
648 WebInspector.zoomManager.addEventListener(WebInspector.ZoomManager.Events.ZoomChanged, this._onZoomChanged, this);
651 willHide: function()
653 WebInspector.zoomManager.removeEventListener(WebInspector.ZoomManager.Events.ZoomChanged, this._onZoomChanged, this);
656 onResize: function()
658 this._updateLayout();
661 onLayout: function()
663 this._updateLayout();
667 * @override
668 * @return {!Constraints}
670 calculateConstraints: function()
672 if (this._showMode === WebInspector.SplitWidget.ShowMode.OnlyMain)
673 return this._mainWidget ? this._mainWidget.constraints() : new Constraints();
674 if (this._showMode === WebInspector.SplitWidget.ShowMode.OnlySidebar)
675 return this._sidebarWidget ? this._sidebarWidget.constraints() : new Constraints();
677 var mainConstraints = this._mainWidget ? this._mainWidget.constraints() : new Constraints();
678 var sidebarConstraints = this._sidebarWidget ? this._sidebarWidget.constraints() : new Constraints();
679 var min = WebInspector.SplitWidget.MinPadding;
680 if (this._isVertical) {
681 mainConstraints = mainConstraints.widthToMax(min).addWidth(1); // 1 for splitter
682 sidebarConstraints = sidebarConstraints.widthToMax(min);
683 return mainConstraints.addWidth(sidebarConstraints).heightToMax(sidebarConstraints);
684 } else {
685 mainConstraints = mainConstraints.heightToMax(min).addHeight(1); // 1 for splitter
686 sidebarConstraints = sidebarConstraints.heightToMax(min);
687 return mainConstraints.widthToMax(sidebarConstraints).addHeight(sidebarConstraints);
692 * @param {!WebInspector.Event} event
694 _onResizeStart: function(event)
696 this._resizeStartSizeDIP = this._sidebarSizeDIP;
700 * @param {!WebInspector.Event} event
702 _onResizeUpdate: function(event)
704 var offset = event.data.currentPosition - event.data.startPosition;
705 var offsetDIP = WebInspector.zoomManager.cssToDIP(offset);
706 var newSizeDIP = this._secondIsSidebar ? this._resizeStartSizeDIP - offsetDIP : this._resizeStartSizeDIP + offsetDIP;
707 var constrainedSizeDIP = this._applyConstraints(newSizeDIP, true);
708 this._savedSidebarSizeDIP = constrainedSizeDIP;
709 this._saveSetting();
710 this._innerSetSidebarSizeDIP(constrainedSizeDIP, false, true);
711 if (this.isVertical())
712 this._savedVerticalMainSize = this._totalSizeDIP() - this._sidebarSizeDIP;
713 else
714 this._savedHorizontalMainSize = this._totalSizeDIP() - this._sidebarSizeDIP;
718 * @param {!WebInspector.Event} event
720 _onResizeEnd: function(event)
722 delete this._resizeStartSizeDIP;
725 hideDefaultResizer: function()
727 this.uninstallResizer(this._resizerElement);
731 * @param {!Element} resizerElement
733 installResizer: function(resizerElement)
735 this._resizerWidget.addElement(resizerElement);
739 * @param {!Element} resizerElement
741 uninstallResizer: function(resizerElement)
743 this._resizerWidget.removeElement(resizerElement);
747 * @return {boolean}
749 hasCustomResizer: function()
751 var elements = this._resizerWidget.elements();
752 return elements.length > 1 || (elements.length == 1 && elements[0] !== this._resizerElement);
756 * @param {!Element} resizer
757 * @param {boolean} on
759 toggleResizer: function(resizer, on)
761 if (on)
762 this.installResizer(resizer);
763 else
764 this.uninstallResizer(resizer);
768 * @return {?WebInspector.SplitWidget.SettingForOrientation}
770 _settingForOrientation: function()
772 var state = this._setting ? this._setting.get() : {};
773 return this._isVertical ? state.vertical : state.horizontal;
777 * @return {number}
779 _preferredSidebarSizeDIP: function()
781 var size = this._savedSidebarSizeDIP;
782 if (!size) {
783 size = this._isVertical ? this._defaultSidebarWidth : this._defaultSidebarHeight;
784 // If we have default value in percents, calculate it on first use.
785 if (0 < size && size < 1)
786 size *= this._totalSizeDIP();
788 return size;
791 _restoreSidebarSizeFromSettings: function()
793 var settingForOrientation = this._settingForOrientation();
794 this._savedSidebarSizeDIP = settingForOrientation ? settingForOrientation.size : 0;
797 _restoreAndApplyShowModeFromSettings: function()
799 var orientationState = this._settingForOrientation();
800 this._savedShowMode = orientationState && orientationState.showMode ? orientationState.showMode : this._showMode;
801 this._showMode = this._savedShowMode;
803 switch (this._savedShowMode) {
804 case WebInspector.SplitWidget.ShowMode.Both:
805 this.showBoth();
806 break;
807 case WebInspector.SplitWidget.ShowMode.OnlyMain:
808 this.hideSidebar();
809 break;
810 case WebInspector.SplitWidget.ShowMode.OnlySidebar:
811 this.hideMain();
812 break;
816 _saveShowModeToSettings: function()
818 this._savedShowMode = this._showMode;
819 this._saveSetting();
822 _saveSetting: function()
824 if (!this._setting)
825 return;
826 var state = this._setting.get();
827 var orientationState = (this._isVertical ? state.vertical : state.horizontal) || {};
829 orientationState.size = this._savedSidebarSizeDIP;
830 if (this._shouldSaveShowMode)
831 orientationState.showMode = this._savedShowMode;
833 if (this._isVertical)
834 state.vertical = orientationState;
835 else
836 state.horizontal = orientationState;
837 this._setting.set(state);
840 _forceUpdateLayout: function()
842 // Force layout even if sidebar size does not change.
843 this._sidebarSizeDIP = -1;
844 this._updateLayout();
848 * @param {!WebInspector.Event} event
850 _onZoomChanged: function(event)
852 this._forceUpdateLayout();
856 * @param {string} title
857 * @param {string=} className
858 * @return {!Element}
860 displayShowHideSidebarButton: function(title, className)
862 console.assert(this.isVertical(), "Buttons for split widget with horizontal split are not supported yet.");
864 this._showHideSidebarButtonTitle = WebInspector.UIString(title);
865 this._showHideSidebarButton = this._mainElement.createChild("button", "sidebar-show-hide-button " + (className || ""));
866 this._showHideSidebarButton.addEventListener("click", buttonClicked.bind(this), false);
867 this._updateShowHideSidebarButton();
870 * @param {!Event} event
871 * @this {WebInspector.SplitWidget}
873 function buttonClicked(event)
875 if (this._showMode !== WebInspector.SplitWidget.ShowMode.Both)
876 this.showBoth(true);
877 else
878 this.hideSidebar(true);
881 return this._showHideSidebarButton;
884 _updateShowHideSidebarButton: function()
886 if (!this._showHideSidebarButton)
887 return;
888 var sidebarHidden = this._showMode === WebInspector.SplitWidget.ShowMode.OnlyMain;
889 this._showHideSidebarButton.classList.toggle("toggled-show", sidebarHidden);
890 this._showHideSidebarButton.classList.toggle("toggled-hide", !sidebarHidden);
891 this._showHideSidebarButton.classList.toggle("top-sidebar-show-hide-button", !this.isVertical() && !this.isSidebarSecond());
892 this._showHideSidebarButton.classList.toggle("right-sidebar-show-hide-button", this.isVertical() && this.isSidebarSecond());
893 this._showHideSidebarButton.classList.toggle("bottom-sidebar-show-hide-button", !this.isVertical() && this.isSidebarSecond());
894 this._showHideSidebarButton.classList.toggle("left-sidebar-show-hide-button", this.isVertical() && !this.isSidebarSecond());
895 this._showHideSidebarButton.title = sidebarHidden ? WebInspector.UIString("Show %s", this._showHideSidebarButtonTitle) : WebInspector.UIString("Hide %s", this._showHideSidebarButtonTitle);
898 __proto__: WebInspector.Widget.prototype