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

Commit 5727863

Browse files
thehogfatherpetetnt
authored andcommitted
Ensures fold-gutter is always inserted after the line-number gutter (if it exists) (#12673)
* Addresses issue where line numbers appears after fold gutter if the line number visibility is toggled in the View Menu. Uses MutationObserver (https://developer.mozilla.org/en/docs/Web/API/MutationObserver) to watch changes to the brackets code mirror gutters. Was PR #11593 Addresses #11577, #10864 * Addresses issue where line numbers appears after fold gutter if the line number visibility is toggled in the View Menu. Uses MutationObserver (https://developer.mozilla.org/en/docs/Web/API/MutationObserver) to watch changes to the brackets code mirror gutters. Was PR #11593 Addresses #11577, #10864 * Added mutation observer to .brackets.json and .eslintrc.json * Refactored to address code review comments
1 parent 57b5131 commit 5727863

4 files changed

Lines changed: 87 additions & 18 deletions

File tree

.brackets.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
"clearTimeout",
2121

2222
"ArrayBuffer",
23+
"MutationObserver",
2324
"XMLHttpRequest",
2425
"Uint32Array",
2526
"WebSocket"

.eslintrc.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
"clearTimeout": false,
6262

6363
"ArrayBuffer": false,
64+
"MutationObserver": false,
6465
"XMLHttpRequest": false,
6566
"Uint32Array": false,
6667
"WebSocket": false

src/extensions/default/CodeFolding/main.js

Lines changed: 67 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
* @author Patrick Oladimeji
2626
* @date 10/24/13 9:35:26 AM
2727
*/
28-
2928
define(function (require, exports, module) {
3029
"use strict";
3130

@@ -53,7 +52,12 @@ define(function (require, exports, module) {
5352
collapseAllKey = "Alt-1",
5453
expandAllKey = "Shift-Alt-1",
5554
collapseAllKeyMac = "Cmd-1",
56-
expandAllKeyMac = "Cmd-Shift-1";
55+
expandAllKeyMac = "Cmd-Shift-1",
56+
SAVE_FOLD_STATES = "saveFoldStates",
57+
HIDE_UNTIL_MOUSE_OVER = "hideUntilMouseover",
58+
MAKE_SELECTION_FOLDABLE = "makeSelectionFoldable",
59+
ALWAYS_USE_INDENT_FOLD = "alwaysUseIndentFold",
60+
LINE_NUMBER_GUTTER = "CodeMirror-linenumbers";
5761

5862
ExtensionUtils.loadStyleSheet(module, "main.less");
5963

@@ -70,10 +74,10 @@ define(function (require, exports, module) {
7074
indentFold = require("foldhelpers/indentFold"),
7175
selectionFold = require("foldhelpers/foldSelected");
7276

73-
7477
/** Set to true when init() has run; set back to false after deinit() has run */
75-
var _isInitialized = false;
76-
78+
var _isInitialized = false,
79+
gutterObservers = {};
80+
7781
/**
7882
* Restores the linefolds in the editor using values fetched from the preference store
7983
* Checks the document to ensure that changes have not been made (e.g., in a different editor)
@@ -112,7 +116,7 @@ define(function (require, exports, module) {
112116
});
113117
}
114118

115-
var saveFolds = prefs.getSetting("saveFoldStates");
119+
var saveFolds = prefs.getSetting(SAVE_FOLD_STATES);
116120
if (!editor || !saveFolds) {
117121
return;
118122
}
@@ -147,7 +151,7 @@ define(function (require, exports, module) {
147151
* @param {Editor} editor the editor whose line folds should be saved
148152
*/
149153
function saveLineFolds(editor) {
150-
var saveFolds = prefs.getSetting("saveFoldStates");
154+
var saveFolds = prefs.getSetting(SAVE_FOLD_STATES);
151155
if (!editor || !saveFolds) {
152156
return;
153157
}
@@ -263,34 +267,38 @@ define(function (require, exports, module) {
263267
*/
264268
function createGutter(editor) {
265269
var cm = editor._codeMirror;
270+
var rootElement = editor.getRootElement();
266271
var path = editor.document.file.fullPath, _lineFolds = prefs.getFolds(path);
267272
_lineFolds = _lineFolds || {};
268273
cm._lineFolds = _lineFolds;
269274
var gutters = cm.getOption("gutters").slice(0);
270275

271276
// Reuse any existing fold gutter
272277
if (gutters.indexOf(GUTTER_NAME) < 0) {
273-
var lnIndex = gutters.indexOf("CodeMirror-linenumbers");
274-
$(editor.getRootElement()).addClass("folding-enabled");
275-
gutters.splice(lnIndex + 1, 0, GUTTER_NAME);
278+
var lineNumberIndex = gutters.indexOf(LINE_NUMBER_GUTTER);
279+
if (lineNumberIndex < 0) {
280+
$(rootElement).addClass("linenumber-disabled");
281+
}
282+
$(rootElement).addClass("folding-enabled");
283+
gutters.splice(lineNumberIndex + 1, 0, GUTTER_NAME);
276284
cm.setOption("gutters", gutters);
277285
cm.refresh(); // force recomputing gutter width - .folding-enabled class affects linenumbers gutter which has existing cached width
278286
}
279287
cm.setOption("foldGutter", {onGutterClick: onGutterClick});
280288

281289
$(cm.getGutterElement()).on({
282290
mouseenter: function () {
283-
if (prefs.getSetting("hideUntilMouseover")) {
291+
if (prefs.getSetting(HIDE_UNTIL_MOUSE_OVER)) {
284292
foldGutter.updateInViewport(cm);
285293
} else {
286-
$(editor.getRootElement()).addClass("over-gutter");
294+
$(rootElement).addClass("over-gutter");
287295
}
288296
},
289297
mouseleave: function () {
290-
if (prefs.getSetting("hideUntilMouseover")) {
298+
if (prefs.getSetting(HIDE_UNTIL_MOUSE_OVER)) {
291299
foldGutter.clearGutter(cm);
292300
} else {
293-
$(editor.getRootElement()).removeClass("over-gutter");
301+
$(rootElement).removeClass("over-gutter");
294302
}
295303
}
296304
});
@@ -304,10 +312,12 @@ define(function (require, exports, module) {
304312
var cm = editor._codeMirror;
305313
var gutters = cm.getOption("gutters").slice(0);
306314
var index = gutters.indexOf(GUTTER_NAME);
307-
$(editor.getRootElement()).removeClass("folding-enabled");
315+
var rootElement = editor.getRootElement();
316+
$(rootElement).removeClass("folding-enabled");
308317
gutters.splice(index, 1);
309318
cm.setOption("gutters", gutters);
310-
cm.refresh(); // force recomputing gutter width - .folding-enabled class affected linenumbers gutter
319+
// Force recomputing gutter width - .folding-enabled class affected linenumbers gutter
320+
cm.refresh();
311321
CodeMirror.defineOption("foldGutter", false, null);
312322
}
313323

@@ -316,6 +326,39 @@ define(function (require, exports, module) {
316326
if (editor._codeMirror.getOption("gutters").indexOf(GUTTER_NAME) === -1) {
317327
createGutter(editor);
318328
restoreLineFolds(editor);
329+
// Watch mutations on code mirror gutters and ensure line numbers are added before fold gutter.
330+
var config = {childList: true};
331+
var gutters,
332+
lineNumberIndex,
333+
foldGutterIndex,
334+
cm = editor._codeMirror,
335+
rootElement = editor.getRootElement(),
336+
guttersContainer = $(".CodeMirror-gutters", rootElement),
337+
observer = new MutationObserver(function (mutations) {
338+
observer.disconnect();
339+
// Ensure fold-gutter appears after line numbers.
340+
gutters = cm.getOption("gutters").slice(0);
341+
lineNumberIndex = gutters.indexOf(LINE_NUMBER_GUTTER);
342+
foldGutterIndex = gutters.indexOf(GUTTER_NAME);
343+
if (lineNumberIndex > -1 && foldGutterIndex < lineNumberIndex) {
344+
gutters.splice(foldGutterIndex, 1);
345+
lineNumberIndex = gutters.indexOf(LINE_NUMBER_GUTTER);
346+
gutters.splice(lineNumberIndex + 1, 0, GUTTER_NAME);
347+
}
348+
if (lineNumberIndex < 0) {
349+
$(rootElement).addClass("linenumber-disabled");
350+
} else {
351+
$(rootElement).removeClass("linenumber-disabled");
352+
}
353+
$(rootElement).addClass("folding-enabled");
354+
cm.setOption("gutters", gutters);
355+
cm.refresh();
356+
createGutter(editor);
357+
// Reconnect the observer.
358+
observer.observe(guttersContainer[0], config);
359+
});
360+
observer.observe(guttersContainer[0], config);
361+
gutterObservers[editor.document.file.fullPath] = observer;
319362
}
320363
}
321364

@@ -371,6 +414,12 @@ define(function (require, exports, module) {
371414
Editor.forEveryEditor(function (editor) {
372415
CodeMirror.commands.unfoldAll(editor._codeMirror);
373416
removeGutter(editor);
417+
//disconnect any mutation observers on the gutter
418+
var gutterObserver = gutterObservers[editor.document.file.fullPath];
419+
if (gutterObserver) {
420+
gutterObserver.disconnect();
421+
delete gutterObservers[editor.document.file.fullPath];
422+
}
374423
});
375424
}
376425

@@ -387,10 +436,10 @@ define(function (require, exports, module) {
387436
// don't, we register helpers explicitly here. We also register a global helper for generic indent-based
388437
// folding, which cuts across all languages if enabled via preference.
389438
CodeMirror.registerGlobalHelper("fold", "selectionFold", function (mode, cm) {
390-
return prefs.getSetting("makeSelectionsFoldable");
439+
return prefs.getSetting(MAKE_SELECTION_FOLDABLE);
391440
}, selectionFold);
392441
CodeMirror.registerGlobalHelper("fold", "indent", function (mode, cm) {
393-
return prefs.getSetting("alwaysUseIndentFold");
442+
return prefs.getSetting(ALWAYS_USE_INDENT_FOLD);
394443
}, indentFold);
395444

396445
CodeMirror.registerHelper("fold", "django", CodeMirror.helpers.fold.brace);

src/extensions/default/CodeFolding/main.less

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,24 @@
4949
padding-right: 5px;
5050
}
5151

52+
// If line numbers are not shown and codefolding is enabled we remove the left padding.
53+
// We add the same padding below to the fold gutter
54+
.show-line-padding {
55+
.folding-enabled.linenumber-disabled pre {
56+
padding-left: 0;
57+
}
58+
}
59+
60+
.CodeMirror.linenumber-disabled {
61+
// When there are no line numbers, .show-line-padding class adds 15px left padding to line numbers.
62+
// Here we compensate for that gap by adding the same padding to the folding gutter.
63+
.CodeMirror-foldgutter,
64+
.CodeMirror-foldgutter-open,
65+
.CodeMirror-foldgutter-folded,
66+
.CodeMirror-foldgutter-blank {
67+
padding-left: 15px;
68+
}
69+
}
5270

5371
.CodeMirror-foldmarker {
5472
// Re-enabling the pointer events for the fold marker. As pointer events are disabled for "CodeMirror-lines"

0 commit comments

Comments
 (0)