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

Sidebar resize refactorization #1811

Closed
wants to merge 11 commits into from
6 changes: 3 additions & 3 deletions src/htmlContent/main-view.html
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,12 @@

<!-- Main UI -->
<div class="main-view">
<div id="sidebar-resizer"></div>
<div id="sidebar" class="sidebar quiet-scrollbars">
<!--<div id="sidebar-resizer"></div>-->
<div id="sidebar" class="sidebar quiet-scrollbars horz-resizable right-resizer collapsable">
<!-- Left-hand 'Project panel' -->
<div id="projects" class="panel">
<div id="project-header"></div>
<div id="file-section">
<div id="file-section" class="content-resizable">
<div id="open-files-container">
<!-- This will contain a dynamically generated <ul> at runtime -->
<ul>
Expand Down
203 changes: 42 additions & 161 deletions src/project/SidebarView.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,8 @@ define(function (require, exports, module) {
Commands = require("command/Commands"),
Strings = require("strings"),
PreferencesManager = require("preferences/PreferencesManager"),
EditorManager = require("editor/EditorManager"),
Global = require("utils/Global");

var isSidebarClosed = false;
Global = require("utils/Global"),
Resizer = require("utils/Resizer");

var PREFERENCES_CLIENT_ID = "com.adobe.brackets.SidebarView",
defaultPrefs = { sidebarWidth: 200, sidebarClosed: false };
Expand All @@ -67,182 +65,64 @@ define(function (require, exports, module) {
$projectTitle.attr("title", ProjectManager.getProjectRoot().fullPath);
}

/**
* @private
* Sets sidebar width and resizes editor. Does not change internal sidebar open/closed state.
* @param {number} width Optional width in pixels. If null or undefined, the default width is used.
* @param {!boolean} updateMenu Updates "View" menu label to indicate current sidebar state.
* @param {!boolean} displayTriangle Display selection marker triangle in the active view.
*/
function _setWidth(width, updateMenu, displayTriangle) {
// if we specify a width with the handler call, use that. Otherwise use
// the greater of the current width or 200 (200 is the minimum width we'd snap back to)

var prefs = PreferencesManager.getPreferenceStorage(PREFERENCES_CLIENT_ID, defaultPrefs),
sidebarWidth = Math.max(prefs.getValue("sidebarWidth"), 10);

width = width || Math.max($sidebar.width(), sidebarWidth);

if (typeof displayTriangle === "boolean") {
var display = (displayTriangle) ? "block" : "none";
$sidebar.find(".sidebar-selection-triangle").css("display", display);
}

if (isSidebarClosed) {
$sidebarResizer.css("left", 0);
} else {
$sidebar.width(width);
$sidebarResizer.css("left", width - 1);

// the following three lines help resize things when the sidebar shows
// but ultimately these should go into ProjectManager.js with a "notify"
// event that we can just call from anywhere instead of hard-coding it.
// waiting on a ProjectManager refactor to add that.
$sidebar.find(".sidebar-selection").width(width);

if (width > 10) {
prefs.setValue("sidebarWidth", width);
}
}

if (updateMenu) {
var text = (isSidebarClosed) ? Strings.CMD_SHOW_SIDEBAR : Strings.CMD_HIDE_SIDEBAR;
CommandManager.get(Commands.VIEW_HIDE_SIDEBAR).setName(text);
}
EditorManager.resizeEditor();
}

/**
* Toggle sidebar visibility.
*/
function toggleSidebar(width) {
if (isSidebarClosed) {
$sidebar.show();
$(exports).triggerHandler("show");
} else {
$sidebar.hide();
$(exports).triggerHandler("hide");
}

isSidebarClosed = !isSidebarClosed;

var prefs = PreferencesManager.getPreferenceStorage(PREFERENCES_CLIENT_ID, defaultPrefs);
prefs.setValue("sidebarClosed", isSidebarClosed);
_setWidth(width, true, !isSidebarClosed);
Resizer.toggleVisibility($sidebar);
}

/**
* @private
* Install sidebar resize handling.
*/
function _initSidebarResizer() {
var $mainView = $(".main-view"),
$body = $(document.body),
prefs = PreferencesManager.getPreferenceStorage(PREFERENCES_CLIENT_ID, defaultPrefs),
sidebarWidth = prefs.getValue("sidebarWidth"),
startingSidebarPosition = sidebarWidth,
animationRequest = null,
isMouseDown = false;

$sidebarResizer.css("left", sidebarWidth - 1);
var prefs = PreferencesManager.getPreferenceStorage(PREFERENCES_CLIENT_ID, defaultPrefs),
sidebarWidth = prefs.getValue("sidebarWidth");

if (prefs.getValue("sidebarClosed")) {
toggleSidebar(sidebarWidth);
} else {
_setWidth(sidebarWidth, true, true);
}
$sidebar.on("panelResizeStart", function (evt, width) {
$sidebar.find(".sidebar-selection-triangle").css("display", "none");
$sidebar.find(".scroller-shadow").css("display", "none");
});

$sidebarResizer.on("dblclick", function () {
if ($sidebar.width() < 10) {
//mousedown is fired first. Sidebar is already toggeled open to at least 10px.
_setWidth(null, true, true);
$projectFilesContainer.triggerHandler("scroll");
$openFilesContainer.triggerHandler("scroll");
} else {
toggleSidebar(sidebarWidth);
}
$sidebar.on("panelResizeUpdate", function (evt, width) {
$sidebar.find(".sidebar-selection").width(width);
});
$sidebarResizer.on("mousedown.sidebar", function (e) {
var startX = e.clientX,
newWidth = Math.max(e.clientX, 0),
doResize = true;

isMouseDown = true;

// take away the shadows (for performance reasons during sidebarmovement)
$sidebar.find(".scroller-shadow").css("display", "none");

$body.toggleClass("resizing");

// check to see if we're currently in hidden mode
if (isSidebarClosed) {
toggleSidebar(1);
}


animationRequest = window.webkitRequestAnimationFrame(function doRedraw() {
// only run this if the mouse is down so we don't constantly loop even
// after we're done resizing.
if (!isMouseDown) {
return;
}

// if we've gone below 10 pixels on a mouse move, and the
// sidebar is shrinking, hide the sidebar automatically an
// unbind the mouse event.
if ((startX > 10) && (newWidth < 10)) {
toggleSidebar(startingSidebarPosition);
$mainView.off("mousemove.sidebar");

// turn off the mouseup event so that it doesn't fire twice and retoggle the
// resizing class
$mainView.off("mouseup.sidebar");
$body.toggleClass("resizing");
doResize = false;
startX = 0;

// force isMouseDown so that we don't keep calling requestAnimationFrame
// this keeps the sidebar from stuttering
isMouseDown = false;

}

if (doResize) {
// for right now, displayTriangle is always going to be false for _setWidth
// because we want to hide it when we move, and _setWidth only gets called
// on mousemove now.
_setWidth(newWidth, false, false);
}

animationRequest = window.webkitRequestAnimationFrame(doRedraw);
});

$mainView.on("mousemove.sidebar", function (e) {
newWidth = Math.max(e.clientX, 0);

e.preventDefault();
});

$mainView.one("mouseup.sidebar", function (e) {
isMouseDown = false;

// replace shadows and triangle
$sidebar.find(".sidebar-selection-triangle").css("display", "block");
$sidebar.find(".scroller-shadow").css("display", "block");

$projectFilesContainer.triggerHandler("scroll");
$openFilesContainer.triggerHandler("scroll");
$mainView.off("mousemove.sidebar");
$body.toggleClass("resizing");
startingSidebarPosition = $sidebar.width();
});

$sidebar.on("panelResizeEnd", function (evt, width) {
$sidebar.find(".sidebar-selection").width(width);
$sidebar.find(".sidebar-selection-triangle").css("display", "block").css("left", width);
$sidebar.find(".scroller-shadow").css("display", "block");
$projectFilesContainer.triggerHandler("scroll");
$openFilesContainer.triggerHandler("scroll");

e.preventDefault();
prefs.setValue("sidebarWidth", width);
});

$sidebar.on("panelCollapsed", function () {
prefs.setValue("sidebarClosed", true);
CommandManager.get(Commands.VIEW_HIDE_SIDEBAR).setName(Strings.CMD_SHOW_SIDEBAR);
});

$sidebar.on("panelExpanded", function () {
prefs.setValue("sidebarClosed", false);
CommandManager.get(Commands.VIEW_HIDE_SIDEBAR).setName(Strings.CMD_HIDE_SIDEBAR);
});

// Set initial state
$sidebar.width(sidebarWidth);
if (prefs.getValue("sidebarClosed")) {
Resizer.toggleVisibility($sidebar);
} else {
$sidebar.trigger("resize");
}
}

// Initialize items dependent on HTML DOM
AppInit.htmlReady(function () {
var prefs = PreferencesManager.getPreferenceStorage(PREFERENCES_CLIENT_ID, defaultPrefs),
sidebarWidth = prefs.getValue("sidebarWidth");

$sidebar = $("#sidebar");
$sidebarMenuText = $("#menu-view-hide-sidebar span");
$sidebarResizer = $("#sidebar-resizer");
Expand All @@ -253,10 +133,11 @@ define(function (require, exports, module) {
// init
WorkingSetView.create($openFilesContainer);
_initSidebarResizer();

});

$(ProjectManager).on("projectOpen", _updateProjectTitle);
CommandManager.register(Strings.CMD_HIDE_SIDEBAR, Commands.VIEW_HIDE_SIDEBAR, toggleSidebar);
CommandManager.register(Strings.CMD_HIDE_SIDEBAR, Commands.VIEW_HIDE_SIDEBAR, toggleSidebar);

// Define public API
exports.toggleSidebar = toggleSidebar;
Expand Down
4 changes: 2 additions & 2 deletions src/styles/brackets.less
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,11 @@ html, body {
body {
.vbox;

&.resizing a, &.resizing #projects a, &.resizing .main-view, &.resizing .CodeMirror-lines {
&.horz-resizing a, &.horz-resizing #projects a, &.horz-resizing .main-view, &.horz-resizing .CodeMirror-lines, &.horz-resizing .CodeMirror-gutter-text {
Copy link
Contributor

Choose a reason for hiding this comment

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

It would be much better if we didn't need to update this rule every time someone adds a new panel. This should only be the "resizing" and "horz-resizing" classes. Maybe we need to adjust where those classes are applied, but I think it's worth the change.

Same comment for next rule with "vert-resizing".

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'll look into it before creating the pull request again.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@redmunds It's okay if we do $("*").toggleClass("vert-resizing") on the Resizer module? Or could that create some hit on performance?

Copy link
Contributor

Choose a reason for hiding this comment

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

That will remove the "vert-resizing" class from the few elements that have it, and add it to every other element in the DOM! I don't think that's what you want to do.

You can use $(".vert-resizing").toggleClass("vert-resizing") to remove the "vert-resizing" class from all elements that have it applied. Note: after that you won't be able to identify the elements that used to have it.

Copy link
Contributor

Choose a reason for hiding this comment

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

Assuming that's what you want, this is a little better: $(".vert-resizing").removeClass("vert-resizing")

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes... I was actually thinking of doing $("*").addClass("vert-resizing") on resize start and then the removeClass on the resize end. This way, the handle cursor isn't overridden by other rules, and we can take the resizing classes outside and shouldn't be affected by any element changing the cursor style...

I assume that's what you meant in the beginning.. or maybe I'm missing the point?

If this is not entirely satisfactory, maybe we can leave it for now and think it through.

Copy link
Contributor

Choose a reason for hiding this comment

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

What you're saying makes sense, but won't $("*") return every element in the entire Brackets DOM tree? I think you want to limit it to the panel that's being resized. We can talk about it more when you push up a pull request.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, that's why I wanted to avoid it. I expect $("*") to be really slow.

I think I've found a nice solution that could work creating a transparent div just for the resizing operation. I'll put together a pull request and then we can discuss it there.

Thanks for the support!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

cursor: col-resize;
}

&.vert-resizing a, &.vert-resizing #projects a, &.vert-resizing .main-view, &.vert-resizing .CodeMirror-lines {
&.vert-resizing a, &.vert-resizing #projects a, &.vert-resizing .main-view, &.vert-resizing .CodeMirror-lines, &.vert-resizing .CodeMirror-gutter-text {
cursor: row-resize;
}
}
Expand Down
Loading