Skip to content
Merged
6 changes: 5 additions & 1 deletion src/command/DefaultMenus.js
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,10 @@ define(function (require, exports, module) {
* an existing selection
*/
$("#editor-holder").on("contextmenu", function (e) {
// make sure that the click was not made inside a tab bar container
// if it is, then we don't show editor context menu as tab bar has its own
if($(e.target).closest('.tab-bar-container').length) { return; }

require(["editor/EditorManager"], function (EditorManager) {
if ($(e.target).parents(".CodeMirror-gutter").length !== 0) {
return;
Expand Down Expand Up @@ -477,4 +481,4 @@ define(function (require, exports, module) {
Menus.getContextMenu(Menus.ContextMenuIds.WORKING_SET_CONTEXT_MENU).on("beforeContextMenuOpen", _setMenuItemsVisible);
Menus.getContextMenu(Menus.ContextMenuIds.PROJECT_MENU).on("beforeContextMenuOpen", _setMenuItemsVisible);
});
});
});
998 changes: 313 additions & 685 deletions src/extensionsIntegrated/TabBar/drag-drop.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/extensionsIntegrated/TabBar/html/tabbar-pane.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

</div>

<div id="overflow-button" class="overflow-button" title="Show hidden tabs">
<div id="overflow-button" class="overflow-button">
<i class="fa-solid fa-chevron-down"></i>
</div>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

</div>

<div id="overflow-button-2" class="overflow-button-2" title="Show hidden tabs">
<div id="overflow-button-2" class="overflow-button-2">
<i class="fa-solid fa-chevron-down"></i>
</div>
</div>
58 changes: 20 additions & 38 deletions src/extensionsIntegrated/TabBar/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ define(function (require, exports, module) {
$tabBar = $(TabBarHTML);
// since we need to add the tab bar before the editor which has .not-editor class
$(".pane-header").after($tabBar);
$("#overflow-button").attr("title", Strings.TABBAR_SHOW_HIDDEN_TABS);
WorkspaceManager.recomputeLayout(true);
updateTabs();
} else if ($paneHeader.length === 2) {
Expand All @@ -239,6 +240,8 @@ define(function (require, exports, module) {
// TODO: Fix bug where the tab bar gets hidden inside the editor in horizontal split
$paneHeader.eq(0).after($tabBar);
$paneHeader.eq(1).after($tabBar2);
$("#overflow-button").attr("title", Strings.TABBAR_SHOW_HIDDEN_TABS);
$("#overflow-button-2").attr("title", Strings.TABBAR_SHOW_HIDDEN_TABS);
WorkspaceManager.recomputeLayout(true);
updateTabs();
}
Expand Down Expand Up @@ -487,57 +490,36 @@ define(function (require, exports, module) {
function handleTabClick() {
// delegate event handling for both tab bars
$(document).on("click", ".phoenix-tab-bar .tab", function (event) {
// check if the clicked element is the close button
if ($(event.target).hasClass("fa-times") || $(event.target).closest(".tab-close").length) {
// Get the file path from the data-path attribute of the parent tab
const filePath = $(this).attr("data-path");

if (filePath) {
// determine the pane inside which the tab belongs
const isSecondPane = $(this).closest("#phoenix-tab-bar-2").length > 0;
const paneId = isSecondPane ? "second-pane" : "first-pane";
// Get the file path from the data-path attribute of the parent tab
const filePath = $(this).attr("data-path");
if (!filePath) { return; }

// get the file object
const fileObj = FileSystem.getFileForPath(filePath);
// close the file
CommandManager.execute(Commands.FILE_CLOSE, { file: fileObj, paneId: paneId });
// determine the pane inside which the tab belongs
const isSecondPane = $(this).closest("#phoenix-tab-bar-2").length > 0;
const paneId = isSecondPane ? "second-pane" : "first-pane";

// Prevent default behavior
event.preventDefault();
event.stopPropagation();
}
}
});
// get the file object
const fileObj = FileSystem.getFileForPath(filePath);

// delegate event handling for both tab bars
$(document).on("mousedown", ".phoenix-tab-bar .tab", function (event) {
// check if the clicked element is the close button
if ($(event.target).hasClass("fa-times") || $(event.target).closest(".tab-close").length) {
return;
}
// Get the file path from the data-path attribute
const filePath = $(this).attr("data-path");
event.preventDefault();
event.stopPropagation();

if (filePath) {
// determine the pane inside which the tab belongs
const isSecondPane = $(this).closest("#phoenix-tab-bar-2").length > 0;
const paneId = isSecondPane ? "second-pane" : "first-pane";
CommandManager.execute(Commands.FILE_CLOSE, { file: fileObj, paneId: paneId }); // close the file
} else { // open the clicked tab
const currentActivePane = MainViewManager.getActivePaneId();
const isPaneActive = paneId === currentActivePane;
const currentFile = MainViewManager.getCurrentlyViewedFile(currentActivePane);

// Check if this is a placeholder tab
// if the clicked tab is a placeholder tab, we add it to the working set
if ($(this).hasClass("placeholder")) {
// Add the file to the working set when placeholder tab is clicked
const fileObj = FileSystem.getFileForPath(filePath);
MainViewManager.addToWorkingSet(paneId, fileObj);
}

if (isPaneActive && currentFile && currentFile.fullPath === filePath) {
return;
}
// clicked tab is already active, don't do anything
if (isPaneActive && currentFile && currentFile.fullPath === filePath) { return; }
CommandManager.execute(Commands.FILE_OPEN, { fullPath: filePath, paneId: paneId });

// We dont prevent default behavior here to enable drag and drop of this tab
}
});

Expand Down Expand Up @@ -613,7 +595,7 @@ define(function (require, exports, module) {
MainViewManager.on("paneCreate paneDestroy paneLayoutChange", createTabBar);

// For active pane changes, update only the tabs
MainViewManager.on("activePaneChange", updateTabs);
MainViewManager.on("activePaneChange", debounceUpdateTabs);

// For editor changes, update only the tabs.
MainViewManager.on(MainViewManager.EVENT_CURRENT_FILE_CHANGE, debounceUpdateTabs);
Expand Down
73 changes: 44 additions & 29 deletions src/extensionsIntegrated/TabBar/overflow.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ define(function (require, exports, module) {
const EditorManager = require("editor/EditorManager");
const FileSystem = require("filesystem/FileSystem");

// holds the dropdown instance
let $dropdown = null;

/**
* This function determines which tabs are hidden in the tab bar due to overflow
Expand Down Expand Up @@ -130,15 +132,12 @@ define(function (require, exports, module) {
function showOverflowMenu(paneId, x, y) {
const hiddenTabs = _getListOfHiddenTabs(paneId);

// first, remove any existing dropdown menus to prevent duplicates
$(".dropdown-overflow-menu").remove();

// Create a map to track tabs that are being closed
// Using paths as keys for quick lookup
const closingTabPaths = {};

// create the dropdown
const dropdown = new DropdownButton.DropdownButton("", hiddenTabs, function (item, index) {
$dropdown = new DropdownButton.DropdownButton("", hiddenTabs, function (item, index) {
const iconHtml = item.$icon[0].outerHTML; // the file icon
const dirtyHtml = item.isDirty
? '<span class="tab-dirty-icon-overflow">•</span>'
Expand Down Expand Up @@ -169,15 +168,14 @@ define(function (require, exports, module) {
};
});

// add the custom classes for styling the dropdown
dropdown.dropdownExtraClasses = "dropdown-overflow-menu";
dropdown.$button.addClass("btn-overflow-tabs");
// add custom class to separate overflow dropdown from regular ones
$dropdown.dropdownExtraClasses = "dropdown-overflow-menu";

// appending to document body. we'll position this with absolute positioning
$("body").append(dropdown.$button);
$("body").append($dropdown.$button);

// position the dropdown where the user clicked
dropdown.$button.css({
$dropdown.$button.css({
position: "absolute",
left: x + "px",
top: y + "px",
Expand All @@ -203,10 +201,10 @@ define(function (require, exports, module) {
e.preventDefault();
});

dropdown.showDropdown();
$dropdown.showDropdown();

// handle the option selection
dropdown.on("select", function (e, item, index) {
$dropdown.on("select", function (e, item, index) {
// check if this tab was marked for closing
if (closingTabPaths[item.path]) {
// this tab is being closed, so handle the close operation
Expand Down Expand Up @@ -240,15 +238,9 @@ define(function (require, exports, module) {
}
});

// clean up when the dropdown is closed
dropdown.$button.on("dropdown-closed", function () {
$(document).off("mousedown", ".tab-close-icon-overflow");
dropdown.$button.remove();
});

// a button was getting displayed on the screen wherever a click was made. not sure why
// but this fixes it
dropdown.$button.css({
$dropdown.$button.css({
display: "none"
});
}
Expand Down Expand Up @@ -335,29 +327,52 @@ define(function (require, exports, module) {
}
}

/**
* to close the overflow button's dropdown
*/
function _closeDropdown() {
if ($dropdown) {
if ($dropdown.$button) {
$dropdown.$button.remove();
}
$dropdown = null;
}
}

/**
* this function gets called when the overflow button gets clicked
* it shows/closes the dropdown as required
* @param {Event} e - the event instance
* @param {String} paneId - the pane id "first-pane" or "second-pane"
*/
function _handleOverflowButtonClick(e, paneId) {
e.stopPropagation();
$dropdown ? _closeDropdown() : showOverflowMenu(paneId, e.pageX, e.pageY);
}

/**
* To setup the handlers for the overflow menu
* initialize the handling of the overflow buttons
* this also registers the event handlers
*/
function setupOverflowHandlers() {
function init() {
// when clicked anywhere on the page we want to close the dropdown
// except the overflow-buttons
$("html").on("click", function (e) {
if ($(e.target).closest("#overflow-button, #overflow-button-2").length) { return; }
_closeDropdown();
});

// handle when the overflow button is clicked for the first pane
$(document).on("click", "#overflow-button", function (e) {
e.stopPropagation();
showOverflowMenu("first-pane", e.pageX, e.pageY);
_handleOverflowButtonClick(e, "first-pane");
});

// for second pane
$(document).on("click", "#overflow-button-2", function (e) {
e.stopPropagation();
showOverflowMenu("second-pane", e.pageX, e.pageY);
_handleOverflowButtonClick(e, "second-pane");
});
}

// initialize the handling of the overflow buttons
function init() {
setupOverflowHandlers();
}

module.exports = {
init,
toggleOverflowVisibility,
Expand Down
1 change: 1 addition & 0 deletions src/nls/root/strings.js
Original file line number Diff line number Diff line change
Expand Up @@ -1309,6 +1309,7 @@ define({
"DESCRIPTION_TABBAR": "Set the tab bar settings.",
"DESCRIPTION_SHOW_TABBAR": "true to show the tab bar, else false.",
"DESCRIPTION_NUMBER_OF_TABS": "The number of tabs to show in the tab bar. Set to -1 to show all tabs",
"TABBAR_SHOW_HIDDEN_TABS": "Show hidden tabs",

// Git extension
"ENABLE_GIT": "Enable Git",
Expand Down
2 changes: 1 addition & 1 deletion test/spec/Extn-Tabbar-integ-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1193,7 +1193,7 @@ define(function (require, exports, module) {
async function clickTabAndVerify(filePath, description) {
const $tab = getTab(filePath);
expect($tab.length).toBe(1);
$tab.trigger("mousedown");
$tab.trigger("click");

// Wait for the file to become active
await awaitsFor(
Expand Down
Loading