Skip to content
This repository has been archived by the owner on Sep 6, 2021. It is now read-only.

command to swap visible files between panes per issue #13061 #13150

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions src/base-config/keyboard.json
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,15 @@
"platform": "mac"
}
],
"mainView.swapPaneContent": [
{
"key" : "Ctrl-Alt-F"
},
{
"key": "Cmd-Shift-F",
"platform": "mac"
}
],
"navigate.quickOpen": [
"Ctrl-Shift-O"
],
Expand Down
1 change: 1 addition & 0 deletions src/command/Commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ define(function (require, exports, module) {
exports.CMD_SPLITVIEW_VERTICAL = "cmd.splitViewVertical"; // SidebarView.js _handleSplitVertical()
exports.CMD_SPLITVIEW_HORIZONTAL = "cmd.splitViewHorizontal"; // SidebarView.js _handleSplitHorizontal()
exports.CMD_SWITCH_PANE_FOCUS = "cmd.switchPaneFocus"; // MainViewManager.js _switchPaneFocus()
exports.CMD_SWAP_PANE_CONTENT = "mainView.swapPaneContent"; // MainViewManager.js _swapPaneContent()

// File shell callbacks - string must MATCH string in native code (appshell/command_callbacks.h)
exports.HELP_ABOUT = "help.about"; // HelpCommandHandlers.js _handleAboutDialog()
Expand Down
5 changes: 3 additions & 2 deletions src/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,13 @@
},
"scripts": {
"postinstall": "grunt install",
"test": "grunt cla-check-pull test"
"test": "grunt test cla-check-pull",
"eslint": "grunt eslint"
},
"licenses": [
{
"type": "MIT",
"url": "https://github.com/adobe/brackets/blob/master/LICENSE"
}
]
}
}
1 change: 1 addition & 0 deletions src/nls/root/strings.js
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,7 @@ define({
"CMD_SHOW_IN_FINDER" : "Show in Finder",
"CMD_SHOW_IN_OS" : "Show in OS",
"CMD_SWITCH_PANE_FOCUS" : "Switch Pane Focus",
"CMD_SWAP_PANE_CONTENT" : "Swap Visible Content Between Split Panes",

// Help menu commands
"HELP_MENU" : "Help",
Expand Down
60 changes: 59 additions & 1 deletion src/view/MainViewManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
* MainViewManager manages the arrangement of all open panes as well as provides the controller
* logic behind all views in the MainView (e.g. ensuring that a file doesn't appear in 2 lists)
*
* Each pane contains one or more views wich are created by a view factory and inserted into a pane list.
* Each pane contains one or more views which are created by a view factory and inserted into a pane list.
* There may be several panes managed by the MainViewManager with each pane containing a list of views.
* The panes are always visible and the layout is determined by the MainViewManager and the user.
*
Expand Down Expand Up @@ -140,6 +140,7 @@ define(function (require, exports, module) {
*/
var SECOND_PANE = "second-pane";


/*
* NOTE: The following commands and constants will change
* when implementing the UX UI Treatment @larz0
Expand Down Expand Up @@ -845,6 +846,62 @@ define(function (require, exports, module) {
return result.promise();
}

/**
* swaps current views to opposite panes
*/
function swapPaneContent() {

var activeFileInactiveView,
inactiveFileActiveView,
activePaneId = getActivePaneId(),
inactivePaneId = activePaneId === FIRST_PANE ? SECOND_PANE : FIRST_PANE,
activePane = _getPane(activePaneId),
inactivePane = _getPane(inactivePaneId),
activeFile = activePane.getCurrentlyViewedFile(),
inactiveFile = inactivePane.getCurrentlyViewedFile();

// Check if one of the panes is empty move and open currently viewed file in opposite pane.
// if both are empty do nothing.
if (!activeFile || !inactiveFile) {
if (!activeFile && inactiveFile) {
_moveView(inactivePaneId, activePaneId, inactiveFile, 0);
} else if (!inactiveFile && activeFile) {
_moveView(activePaneId, inactivePaneId, activeFile, 0);
}

} else {

// check if currently viewed file is present in opposing pane. If it is open the file.
// if it is not add it to the opposite pane and open.
activeFileInactiveView = inactivePane.getViewForPath(activeFile.fullPath);
inactiveFileActiveView = activePane.getViewForPath(inactiveFile.fullPath);

if (inactiveFileActiveView) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These could probably be a method like _moveView is

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@petetnt I looked into moving most of what is now in MainViewManager onto the pane prototype (see below), and I can push up the commit including it, however, with this setup I can't seem to get the active pane to consistently stay in place. It flips from one pane to the other every third swap. I've tried promises and a few other ideas, but Maybe I'm missing something obvious. Any insights are welcome.

    Pane.prototype.swapPaneContent = function(oppositeFile) {
        var self = this,
            oppositePane = self.id === FIRST_PANE ? SECOND_PANE : FIRST_PANE;

        if(!oppositeFile){
            var file = self.getCurrentlyViewedFile();
            MainViewManager._moveView( self.id, oppositePane.id, file , 0);
        } else {
            if (self.getViewForPath(oppositeFile.fullPath)) {
                CommandManager.execute(Commands.FILE_OPEN, {
                    fullPath: oppositeFile.fullPath,
                    paneId: self.id
                });
            } else {
                CommandManager.execute(Commands.CMD_ADD_TO_WORKINGSET_AND_OPEN, {
                    fullPath: oppositeFile.fullPath,
                    paneId: self.id
                });
            };
        };
    };
    function swapPaneContent() {

        var activePaneId = getActivePaneId(),
            inactivePaneId = activePaneId === FIRST_PANE ? SECOND_PANE : FIRST_PANE,
            activePane = _getPane(activePaneId),
            inactivePane = _getPane(inactivePaneId),
            activeFile = activePane.getCurrentlyViewedFile(),
            inactiveFile = inactivePane.getCurrentlyViewedFile();

            inactivePane.swapPaneContent(activeFile);   // addition 
            activePane.swapPaneContent(inactiveFile);  // addition
    };

Copy link
Contributor

@zaggino zaggino Mar 6, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like this rewrite ... Pane.prototype calling MainViewManager methods doesn't seem right. Maybe @petetnt can specify little more what he meant, but looking at the code I prefer the original version.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, my idea was something in line with the rewrite but just calling the method with pane, file arguments instead of adding it to the prototype.

The original code is fine by me too if you think so too, you call @SteveMieskoski 👍

CommandManager.execute(Commands.FILE_OPEN, {
fullPath: inactiveFile.fullPath,
paneId: activePaneId
});
} else {
CommandManager.execute(Commands.CMD_ADD_TO_WORKINGSET_AND_OPEN, {
fullPath: inactiveFile.fullPath,
paneId: activePaneId
});
}

if (activeFileInactiveView) {
CommandManager.execute(Commands.FILE_OPEN, {
fullPath: activeFile.fullPath,
paneId: inactivePaneId
});
} else {
CommandManager.execute(Commands.CMD_ADD_TO_WORKINGSET_AND_OPEN, {
fullPath: activeFile.fullPath,
paneId: inactivePaneId
});
}
}
};

/**
* Switch between panes
*/
Expand Down Expand Up @@ -1752,6 +1809,7 @@ define(function (require, exports, module) {
exports.getAllOpenFiles = getAllOpenFiles;
exports.focusActivePane = focusActivePane;
exports.switchPaneFocus = switchPaneFocus;
exports.swapPaneContent = swapPaneContent;

// Layout
exports.setLayoutScheme = setLayoutScheme;
Expand Down
14 changes: 14 additions & 0 deletions src/view/ViewCommandHandlers.js
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,13 @@ define(function (require, exports, module) {
ThemeSettings.showDialog();
}

/** Handle enabling swapPaneContent in MainViewManager */
function _handleSwapPaneContent(){
if (PreferencesManager.get("mainView.swapPaneContent", PreferencesManager.CURRENT_PROJECT)) {
MainViewManager.swapPaneContent();
}
}

// Register command handlers
CommandManager.register(Strings.CMD_INCREASE_FONT_SIZE, Commands.VIEW_INCREASE_FONT_SIZE, _handleIncreaseFontSize);
CommandManager.register(Strings.CMD_DECREASE_FONT_SIZE, Commands.VIEW_DECREASE_FONT_SIZE, _handleDecreaseFontSize);
Expand All @@ -509,6 +516,13 @@ define(function (require, exports, module) {
CommandManager.register(Strings.CMD_SCROLL_LINE_DOWN, Commands.VIEW_SCROLL_LINE_DOWN, _handleScrollLineDown);
CommandManager.register(Strings.CMD_THEMES, Commands.CMD_THEMES_OPEN_SETTINGS, _handleThemeSettings);

CommandManager.register(Strings.CMD_SWAP_PANE_CONTENT, Commands.CMD_SWAP_PANE_CONTENT, _handleSwapPaneContent);

// Define swapPaneVisibleContent, which controls whether to enable command to swap visible content between panes.
PreferencesManager.definePreference("mainView.swapPaneContent", "boolean", false, {
description: Strings.CMD_SWAP_PANE_CONTENT
});

prefs.definePreference("fontSize", "string", DEFAULT_FONT_SIZE + "px", {
description: Strings.DESCRIPTION_FONT_SIZE
}).on("change", function () {
Expand Down
95 changes: 95 additions & 0 deletions test/spec/MainViewManager-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,101 @@ define(function (require, exports, module) {
expect(EditorManager.getCurrentFullEditor().document.file.name).toEqual("test.js");
});
});
it("should swap views between panes", function () {
runs(function () {
MainViewManager.setLayoutScheme(1, 2);
});
runs(function () {
promise = CommandManager.execute(Commands.FILE_OPEN, { fullPath: testPath + "/test.js",
paneId: "first-pane" });
waitsForDone(promise, Commands.FILE_OPEN);
});
runs(function () {
promise = CommandManager.execute(Commands.FILE_OPEN, { fullPath: testPath + "/test.css",
paneId: "second-pane" });
waitsForDone(promise, Commands.FILE_OPEN);
});
runs(function () {
expect(MainViewManager._getPaneIdForPath(testPath + "/test.js")).toEqual("first-pane");
expect(MainViewManager._getPaneIdForPath(testPath + "/test.css")).toEqual("second-pane");
});
runs(function () {
expect(MainViewManager.getCurrentlyViewedFile("first-pane").name).toEqual("test.js");
expect(MainViewManager.getCurrentlyViewedFile("second-pane").name).toEqual("test.css");
});
runs(function () {
MainViewManager.swapPaneContent();
});
runs(function () {
MainViewManager.setActivePaneId("first-pane");
expect(MainViewManager.getCurrentlyViewedFile(MainViewManager.ACTIVE_PANE).name).toEqual("test.css");
MainViewManager.setActivePaneId("second-pane");
expect(MainViewManager.getCurrentlyViewedFile(MainViewManager.ACTIVE_PANE).name).toEqual("test.js");
});
runs(function () {
MainViewManager.swapPaneContent();
});
runs(function () {
MainViewManager.setActivePaneId("first-pane");
expect(MainViewManager.getCurrentlyViewedFile(MainViewManager.ACTIVE_PANE).name).toEqual("test.js");
MainViewManager.setActivePaneId("second-pane");
expect(MainViewManager.getCurrentlyViewedFile(MainViewManager.ACTIVE_PANE).name).toEqual("test.css");
});
});
it("should show a file instead of swapping if file is already open", function () {
runs(function () {
MainViewManager.setLayoutScheme(1, 2);
});
runs(function () {
promise = CommandManager.execute(Commands.CMD_ADD_TO_WORKINGSET_AND_OPEN, { fullPath: testPath + "/test.js",
paneId: "first-pane" });
waitsForDone(promise, Commands.CMD_ADD_TO_WORKINGSET_AND_OPEN);
});
runs(function () {
promise = CommandManager.execute(Commands.CMD_ADD_TO_WORKINGSET_AND_OPEN, { fullPath: testPath + "/test.css",
paneId: "second-pane" });
waitsForDone(promise, Commands.CMD_ADD_TO_WORKINGSET_AND_OPEN);
});
runs(function () {
promise = CommandManager.execute(Commands.CMD_ADD_TO_WORKINGSET_AND_OPEN, { fullPath: testPath + "/test.js",
paneId: "second-pane" });
waitsForDone(promise, Commands.CMD_ADD_TO_WORKINGSET_AND_OPEN);
});
runs(function(){
MainViewManager.setActivePaneId("second-pane");
expect(MainViewManager.getCurrentlyViewedFile(MainViewManager.ACTIVE_PANE).name).toEqual("test.js");
});
runs(function () {
MainViewManager.swapPaneContent();
});
runs(function () {
MainViewManager.setActivePaneId("first-pane");
expect(MainViewManager.getCurrentlyViewedFile(MainViewManager.ACTIVE_PANE).name).toEqual("test.js");
expect(EditorManager.getCurrentFullEditor().document.file.name).toEqual("test.js");
MainViewManager.setActivePaneId("second-pane");
expect(MainViewManager.getCurrentlyViewedFile(MainViewManager.ACTIVE_PANE).name).toEqual("test.js");
expect(EditorManager.getCurrentFullEditor().document.file.name).toEqual("test.js");
});
});
it("should move file if one pane is empty", function () {
runs(function () {
MainViewManager.setLayoutScheme(1, 2);
});
runs(function () {
promise = CommandManager.execute(Commands.CMD_ADD_TO_WORKINGSET_AND_OPEN, { fullPath: testPath + "/test.js",
paneId: "first-pane" });
waitsForDone(promise, Commands.CMD_ADD_TO_WORKINGSET_AND_OPEN);
});
runs(function () {
MainViewManager.swapPaneContent();
});
runs(function () {
MainViewManager.setActivePaneId("first-pane");
expect(MainViewManager.getCurrentlyViewedFile(MainViewManager.ACTIVE_PANE)).toEqual(null);
MainViewManager.setActivePaneId("second-pane");
expect(MainViewManager.getCurrentlyViewedFile(MainViewManager.ACTIVE_PANE).name).toEqual("test.js");
});
});
it("should merge two panes to the right", function () {
runs(function () {
MainViewManager.setLayoutScheme(1, 2);
Expand Down