@@ -70,6 +70,18 @@ define(function (require, exports, module) {
7070 /** @type {string|null } The panel ID of the currently visible (active) tab */
7171 let _activeId = null ;
7272
73+ /** @type {boolean } Whether the bottom panel is currently maximized */
74+ let _isMaximized = false ;
75+
76+ /** @type {number|null } The panel height before maximize, for restore */
77+ let _preMaximizeHeight = null ;
78+
79+ /** @type {jQueryObject } The editor holder element, passed from WorkspaceManager */
80+ let _$editorHolder = null ;
81+
82+ /** @type {function } recomputeLayout callback from WorkspaceManager */
83+ let _recomputeLayout = null ;
84+
7385 // --- Tab helper functions ---
7486
7587 /**
@@ -324,6 +336,7 @@ define(function (require, exports, module) {
324336 // No more tabs - hide the container
325337 _activeId = null ;
326338 if ( _$container ) {
339+ restoreIfMaximized ( ) ;
327340 Resizer . hide ( _$container [ 0 ] ) ;
328341 }
329342 }
@@ -389,11 +402,15 @@ define(function (require, exports, module) {
389402 * @param {jQueryObject } $container The bottom panel container element.
390403 * @param {jQueryObject } $tabBar The tab bar element inside the container.
391404 * @param {jQueryObject } $tabsOverflow The scrollable area holding tab elements.
405+ * @param {jQueryObject } $editorHolder The editor holder element (for maximize height calculation).
406+ * @param {function } recomputeLayoutFn Callback to trigger workspace layout recomputation.
392407 */
393- function init ( $container , $tabBar , $tabsOverflow ) {
408+ function init ( $container , $tabBar , $tabsOverflow , $editorHolder , recomputeLayoutFn ) {
394409 _$container = $container ;
395410 _$tabBar = $tabBar ;
396411 _$tabsOverflow = $tabsOverflow ;
412+ _$editorHolder = $editorHolder ;
413+ _recomputeLayout = recomputeLayoutFn ;
397414
398415 // Tab bar click handlers
399416 _$tabBar . on ( "click" , ".bottom-panel-tab-close-btn" , function ( e ) {
@@ -421,9 +438,129 @@ define(function (require, exports, module) {
421438 _$tabBar . on ( "click" , ".bottom-panel-hide-btn" , function ( e ) {
422439 e . stopPropagation ( ) ;
423440 if ( _$container . is ( ":visible" ) ) {
441+ restoreIfMaximized ( ) ;
424442 Resizer . hide ( _$container [ 0 ] ) ;
425443 }
426444 } ) ;
445+
446+ // Maximize/restore toggle button
447+ _$tabBar . on ( "click" , ".bottom-panel-maximize-btn" , function ( e ) {
448+ e . stopPropagation ( ) ;
449+ _toggleMaximize ( ) ;
450+ } ) ;
451+
452+ // Double-click on tab bar toggles maximize (exclude action buttons)
453+ _$tabBar . on ( "dblclick" , function ( e ) {
454+ if ( $ ( e . target ) . closest ( ".bottom-panel-tab-close-btn, .bottom-panel-hide-btn, .bottom-panel-maximize-btn" ) . length ) {
455+ return ;
456+ }
457+ _toggleMaximize ( ) ;
458+ } ) ;
459+ }
460+
461+ /**
462+ * Toggle maximize/restore of the bottom panel.
463+ * @private
464+ */
465+ function _toggleMaximize ( ) {
466+ if ( ! _$container || ! _$container . is ( ":visible" ) ) {
467+ return ;
468+ }
469+ if ( _isMaximized ) {
470+ _restorePanel ( ) ;
471+ } else {
472+ _maximizePanel ( ) ;
473+ }
474+ }
475+
476+ /**
477+ * Maximize the bottom panel to fill all available vertical space.
478+ * @private
479+ */
480+ function _maximizePanel ( ) {
481+ _preMaximizeHeight = _$container . height ( ) ;
482+ let maxHeight = _$editorHolder . height ( ) + _$container . height ( ) ;
483+ _$container . height ( maxHeight ) ;
484+ _isMaximized = true ;
485+ _updateMaximizeButton ( ) ;
486+ if ( _recomputeLayout ) {
487+ _recomputeLayout ( ) ;
488+ }
489+ }
490+
491+ /**
492+ * Restore the bottom panel to its pre-maximize height.
493+ * @private
494+ */
495+ function _restorePanel ( ) {
496+ if ( _preMaximizeHeight !== null ) {
497+ _$container . height ( _preMaximizeHeight ) ;
498+ }
499+ _isMaximized = false ;
500+ _preMaximizeHeight = null ;
501+ _updateMaximizeButton ( ) ;
502+ if ( _recomputeLayout ) {
503+ _recomputeLayout ( ) ;
504+ }
505+ }
506+
507+ /**
508+ * Update the maximize button icon and tooltip based on current state.
509+ * @private
510+ */
511+ function _updateMaximizeButton ( ) {
512+ if ( ! _$tabBar ) {
513+ return ;
514+ }
515+ let $btn = _$tabBar . find ( ".bottom-panel-maximize-btn" ) ;
516+ let $icon = $btn . find ( "i" ) ;
517+ if ( _isMaximized ) {
518+ $icon . removeClass ( "fa-up-right-and-down-left-from-center" )
519+ . addClass ( "fa-down-left-and-up-right-to-center" ) ;
520+ $btn . attr ( "title" , Strings . BOTTOM_PANEL_RESTORE ) ;
521+ } else {
522+ $icon . removeClass ( "fa-down-left-and-up-right-to-center" )
523+ . addClass ( "fa-up-right-and-down-left-from-center" ) ;
524+ $btn . attr ( "title" , Strings . BOTTOM_PANEL_MAXIMIZE ) ;
525+ }
526+ }
527+
528+ /**
529+ * Exit maximize state without resizing (for external callers like drag-resize).
530+ * Clears internal maximize state and resets the button icon.
531+ */
532+ function exitMaximizeOnResize ( ) {
533+ if ( ! _isMaximized ) {
534+ return ;
535+ }
536+ _isMaximized = false ;
537+ _preMaximizeHeight = null ;
538+ _updateMaximizeButton ( ) ;
539+ }
540+
541+ /**
542+ * Restore the container's CSS height to the pre-maximize value and clear maximize state.
543+ * Must be called BEFORE Resizer.hide() so the Resizer reads the correct height.
544+ * If not maximized, this is a no-op.
545+ */
546+ function restoreIfMaximized ( ) {
547+ if ( ! _isMaximized ) {
548+ return ;
549+ }
550+ if ( _preMaximizeHeight !== null ) {
551+ _$container . height ( _preMaximizeHeight ) ;
552+ }
553+ _isMaximized = false ;
554+ _preMaximizeHeight = null ;
555+ _updateMaximizeButton ( ) ;
556+ }
557+
558+ /**
559+ * Returns true if the bottom panel is currently maximized.
560+ * @return {boolean }
561+ */
562+ function isMaximized ( ) {
563+ return _isMaximized ;
427564 }
428565
429566 /**
@@ -459,6 +596,7 @@ define(function (require, exports, module) {
459596 _activeId = null ;
460597
461598 if ( _$container && _$container . is ( ":visible" ) ) {
599+ restoreIfMaximized ( ) ;
462600 Resizer . hide ( _$container [ 0 ] ) ;
463601 }
464602
@@ -480,6 +618,9 @@ define(function (require, exports, module) {
480618 exports . init = init ;
481619 exports . getOpenBottomPanelIDs = getOpenBottomPanelIDs ;
482620 exports . hideAllOpenPanels = hideAllOpenPanels ;
621+ exports . exitMaximizeOnResize = exitMaximizeOnResize ;
622+ exports . restoreIfMaximized = restoreIfMaximized ;
623+ exports . isMaximized = isMaximized ;
483624 //events
484625 exports . EVENT_PANEL_HIDDEN = EVENT_PANEL_HIDDEN ;
485626 exports . EVENT_PANEL_SHOWN = EVENT_PANEL_SHOWN ;
0 commit comments