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

Commit ca8fe32

Browse files
committed
Merge remote-tracking branch 'upstream/master'
2 parents c30f4af + 3306e8a commit ca8fe32

45 files changed

Lines changed: 1122 additions & 317 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/base-config/keyboard.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,5 +317,8 @@
317317
],
318318
"file.rename": [
319319
"F2"
320+
],
321+
"help.support": [
322+
"F1"
320323
]
321324
}

src/brackets.config.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@
66
"about_icon" : "styles/images/brackets_icon.svg",
77
"update_info_url" : "http://dev.brackets.io/updates/stable/",
88
"how_to_use_url" : "https://github.com/adobe/brackets/wiki/How-to-Use-Brackets",
9+
"support_url" : "http://help.brackets.io",
10+
"get_involved_url" : "https://github.com/adobe/brackets",
911
"glob_help_url" : "https://github.com/adobe/brackets/wiki/Using-File-Filters",
10-
"forum_url" : "https://groups.google.com/forum/?fromgroups#!forum/brackets-dev",
1112
"release_notes_url" : "https://github.com/adobe/brackets/wiki/Release-Notes",
12-
"report_issue_url" : "https://github.com/adobe/brackets/wiki/How-to-Report-an-Issue",
1313
"twitter_url" : "https://twitter.com/brackets",
1414
"troubleshoot_url" : "https://github.com/adobe/brackets/wiki/Troubleshooting#wiki-livedev",
1515
"twitter_name" : "@brackets",

src/command/Commands.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,9 +129,9 @@ define(function (require, exports, module) {
129129
// HELP
130130
exports.HELP_CHECK_FOR_UPDATE = "help.checkForUpdate"; // HelpCommandHandlers.js _handleCheckForUpdates()
131131
exports.HELP_HOW_TO_USE_BRACKETS = "help.howToUseBrackets"; // HelpCommandHandlers.js _handleLinkMenuItem()
132-
exports.HELP_FORUM = "help.forum"; // HelpCommandHandlers.js _handleLinkMenuItem()
132+
exports.HELP_SUPPORT = "help.support"; // HelpCommandHandlers.js _handleLinkMenuItem()
133133
exports.HELP_RELEASE_NOTES = "help.releaseNotes"; // HelpCommandHandlers.js _handleLinkMenuItem()
134-
exports.HELP_REPORT_AN_ISSUE = "help.reportAnIssue"; // HelpCommandHandlers.js _handleLinkMenuItem()
134+
exports.HELP_GET_INVOLVED = "help.getInvolved"; // HelpCommandHandlers.js _handleLinkMenuItem()
135135
exports.HELP_SHOW_EXT_FOLDER = "help.showExtensionsFolder"; // HelpCommandHandlers.js _handleShowExtensionsFolder()
136136
exports.HELP_TWITTER = "help.twitter"; // HelpCommandHandlers.js _handleLinkMenuItem()
137137

src/command/DefaultMenus.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -157,14 +157,14 @@ define(function (require, exports, module) {
157157
if (brackets.config.how_to_use_url) {
158158
menu.addMenuItem(Commands.HELP_HOW_TO_USE_BRACKETS);
159159
}
160-
if (brackets.config.forum_url) {
161-
menu.addMenuItem(Commands.HELP_FORUM);
160+
if (brackets.config.support_url) {
161+
menu.addMenuItem(Commands.HELP_SUPPORT);
162162
}
163163
if (brackets.config.release_notes_url) {
164164
menu.addMenuItem(Commands.HELP_RELEASE_NOTES);
165165
}
166-
if (brackets.config.report_issue_url) {
167-
menu.addMenuItem(Commands.HELP_REPORT_AN_ISSUE);
166+
if (brackets.config.get_involved_url) {
167+
menu.addMenuItem(Commands.HELP_GET_INVOLVED);
168168
}
169169

170170
menu.addMenuDivider();

src/config.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@
55
"about_icon": "styles/images/brackets_icon.svg",
66
"update_info_url": "http://dev.brackets.io/updates/stable/",
77
"how_to_use_url": "https://github.com/adobe/brackets/wiki/How-to-Use-Brackets",
8+
"support_url": "http://help.brackets.io",
9+
"get_involved_url": "https://github.com/adobe/brackets",
810
"glob_help_url": "https://github.com/adobe/brackets/wiki/Using-File-Filters",
9-
"forum_url": "https://groups.google.com/forum/?fromgroups#!forum/brackets-dev",
1011
"release_notes_url": "https://github.com/adobe/brackets/wiki/Release-Notes",
11-
"report_issue_url": "https://github.com/adobe/brackets/wiki/How-to-Report-an-Issue",
1212
"twitter_url": "https://twitter.com/brackets",
1313
"troubleshoot_url": "https://github.com/adobe/brackets/wiki/Troubleshooting#wiki-livedev",
1414
"twitter_name": "@brackets",

src/document/DocumentCommandHandlers.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ define(function (require, exports, module) {
261261
var file = FileSystem.getFileForPath(fullPath);
262262
file.exists(function (fileError, fileExists) {
263263
if (fileExists) {
264-
EditorManager.showCustomViewer(viewProvider, fullPath);
264+
EditorManager._showCustomViewer(viewProvider, fullPath);
265265
result.resolve();
266266
} else {
267267
fileError = fileError || FileSystemError.NOT_FOUND;
@@ -983,7 +983,7 @@ define(function (require, exports, module) {
983983
result.resolve();
984984
});
985985
} else {
986-
EditorManager.closeCustomViewer();
986+
EditorManager._closeCustomViewer();
987987
result.resolve();
988988
}
989989
}
@@ -1194,15 +1194,15 @@ define(function (require, exports, module) {
11941194
return _closeList(DocumentManager.getWorkingSet(),
11951195
(commandData && commandData.promptOnly), true).done(function () {
11961196
if (!DocumentManager.getCurrentDocument()) {
1197-
EditorManager.closeCustomViewer();
1197+
EditorManager._closeCustomViewer();
11981198
}
11991199
});
12001200
}
12011201

12021202
function handleFileCloseList(commandData) {
12031203
return _closeList(commandData.fileList, false, false).done(function () {
12041204
if (!DocumentManager.getCurrentDocument()) {
1205-
EditorManager.closeCustomViewer();
1205+
EditorManager._closeCustomViewer();
12061206
}
12071207
});
12081208
}

src/editor/CSSInlineEditor.js

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,14 @@ define(function (require, exports, module) {
5454
* Given a position in an HTML editor, returns the relevant selector for the attribute/tag
5555
* surrounding that position, or "" if none is found.
5656
* @param {!Editor} editor
57+
* @param {!{line:Number, ch:Number}} pos
58+
* @return {selectorName: {string}, reason: {string}}
5759
* @private
5860
*/
5961
function _getSelectorName(editor, pos) {
6062
var tagInfo = HTMLUtils.getTagInfo(editor, pos),
61-
selectorName = "";
63+
selectorName = "",
64+
reason;
6265

6366
if (tagInfo.position.tokenType === HTMLUtils.TAG_NAME || tagInfo.position.tokenType === HTMLUtils.CLOSING_TAG) {
6467
// Type selector
@@ -85,16 +88,27 @@ define(function (require, exports, module) {
8588
if (selectorName === ".") {
8689
selectorName = "";
8790
}
91+
92+
if (selectorName === "") {
93+
reason = Strings.ERROR_CSSQUICKEDIT_CLASSNOTFOUND;
94+
}
8895
} else if (tagInfo.attr.name === "id") {
8996
// ID selector
9097
var trimmedVal = tagInfo.attr.value.trim();
9198
if (trimmedVal) {
9299
selectorName = "#" + trimmedVal;
100+
} else {
101+
reason = Strings.ERROR_CSSQUICKEDIT_IDNOTFOUND;
93102
}
103+
} else {
104+
reason = Strings.ERROR_CSSQUICKEDIT_UNSUPPORTEDATTR;
94105
}
95106
}
96107

97-
return selectorName;
108+
return {
109+
selectorName: selectorName,
110+
reason: reason
111+
};
98112
}
99113

100114
/**
@@ -146,8 +160,9 @@ define(function (require, exports, module) {
146160
*
147161
* @param {!Editor} editor
148162
* @param {!{line:Number, ch:Number}} pos
149-
* @return {$.Promise} a promise that will be resolved with an InlineWidget
150-
* or null if we're not going to provide anything.
163+
* @return {?$.Promise} synchronously resolved with an InlineWidget, or
164+
* {string} if pos is in tag but not in tag name, class attr, or id attr, or
165+
* null if we're not going to provide anything.
151166
*/
152167
function htmlToCSSProvider(hostEditor, pos) {
153168

@@ -164,10 +179,12 @@ define(function (require, exports, module) {
164179

165180
// Always use the selection start for determining selector name. The pos
166181
// parameter is usually the selection end.
167-
var selectorName = _getSelectorName(hostEditor, sel.start);
168-
if (selectorName === "") {
169-
return null;
182+
var selectorResult = _getSelectorName(hostEditor, sel.start);
183+
if (selectorResult.selectorName === "") {
184+
return selectorResult.reason || null;
170185
}
186+
187+
var selectorName = selectorResult.selectorName;
171188

172189
var result = new $.Deferred(),
173190
cssInlineEditor,

src/editor/Editor.js

Lines changed: 123 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ define(function (require, exports, module) {
6969
CodeMirror = require("thirdparty/CodeMirror2/lib/codemirror"),
7070
Menus = require("command/Menus"),
7171
PerfUtils = require("utils/PerfUtils"),
72+
PopUpManager = require("widgets/PopUpManager"),
7273
PreferencesManager = require("preferences/PreferencesManager"),
7374
Strings = require("strings"),
7475
TextRange = require("document/TextRange").TextRange,
@@ -198,6 +199,7 @@ define(function (require, exports, module) {
198199
// (if makeMasterEditor, we attach the Doc back to ourselves below once we're fully initialized)
199200

200201
this._inlineWidgets = [];
202+
this._$messagePopover = null;
201203

202204
// Editor supplies some standard keyboard behavior extensions of its own
203205
var codeMirrorKeyMap = {
@@ -811,7 +813,7 @@ define(function (require, exports, module) {
811813

812814
this._codeMirror.on("blur", function () {
813815
self._focused = false;
814-
// EditorManager only cares about other Editors gaining focus, so we don't notify it of anything here
816+
$(self).triggerHandler("blur", [self]);
815817
});
816818

817819
this._codeMirror.on("update", function (instance) {
@@ -1518,6 +1520,126 @@ define(function (require, exports, module) {
15181520
return this._inlineWidgets;
15191521
};
15201522

1523+
/**
1524+
* Display temporary popover message at current cursor position. Display message above
1525+
* cursor if space allows, otherwise below.
1526+
*
1527+
* @param {string} errorMsg Error message to display
1528+
*/
1529+
Editor.prototype.displayErrorMessageAtCursor = function (errorMsg) {
1530+
var arrowBelow, cursorPos, cursorCoord, popoverRect,
1531+
top, left, clip, arrowLeft,
1532+
self = this,
1533+
$editorHolder = $("#editor-holder"),
1534+
POPOVER_MARGIN = 10,
1535+
POPOVER_ARROW_HALF_WIDTH = 10;
1536+
1537+
function _removeListeners() {
1538+
$(self).off(".msgbox");
1539+
}
1540+
1541+
// PopUpManager.removePopUp() callback
1542+
function _clearMessagePopover() {
1543+
if (self._$messagePopover && self._$messagePopover.length > 0) {
1544+
// self._$messagePopover.remove() is done by PopUpManager
1545+
self._$messagePopover = null;
1546+
}
1547+
_removeListeners();
1548+
}
1549+
1550+
// PopUpManager.removePopUp() is called either directly by this closure, or by
1551+
// PopUpManager as a result of another popup being invoked.
1552+
function _removeMessagePopover() {
1553+
PopUpManager.removePopUp(self._$messagePopover);
1554+
}
1555+
1556+
function _addListeners() {
1557+
$(self)
1558+
.on("blur.msgbox", _removeMessagePopover)
1559+
.on("change.msgbox", _removeMessagePopover)
1560+
.on("cursorActivity.msgbox", _removeMessagePopover)
1561+
.on("update.msgbox", _removeMessagePopover);
1562+
}
1563+
1564+
// Only 1 message at a time
1565+
if (this._$messagePopover) {
1566+
_removeMessagePopover();
1567+
}
1568+
1569+
// Make sure cursor is in view
1570+
cursorPos = this.getCursorPos();
1571+
this._codeMirror.scrollIntoView(cursorPos);
1572+
1573+
// Determine if arrow is above or below
1574+
cursorCoord = this._codeMirror.charCoords(cursorPos);
1575+
1576+
// Assume popover height is max of 2 lines
1577+
arrowBelow = (cursorCoord.top > 100);
1578+
1579+
// Text is dynamic, so build popover first so we can measure final width
1580+
this._$messagePopover = $("<div/>").addClass("popover-message").appendTo($("body"));
1581+
if (!arrowBelow) {
1582+
$("<div/>").addClass("arrowAbove").appendTo(this._$messagePopover);
1583+
}
1584+
$("<div/>").addClass("text").appendTo(this._$messagePopover).html(errorMsg);
1585+
if (arrowBelow) {
1586+
$("<div/>").addClass("arrowBelow").appendTo(this._$messagePopover);
1587+
}
1588+
1589+
// Estimate where to position popover.
1590+
top = (arrowBelow) ? cursorCoord.top - this._$messagePopover.height() - POPOVER_MARGIN
1591+
: cursorCoord.bottom + POPOVER_MARGIN;
1592+
left = cursorCoord.left - (this._$messagePopover.width() / 2);
1593+
1594+
popoverRect = {
1595+
top: top,
1596+
left: left,
1597+
height: this._$messagePopover.height(),
1598+
width: this._$messagePopover.width()
1599+
};
1600+
1601+
// See if popover is clipped on any side
1602+
clip = ViewUtils.getElementClipSize($editorHolder, popoverRect);
1603+
1604+
// Prevent horizontal clipping
1605+
if (clip.left > 0) {
1606+
left += clip.left;
1607+
} else if (clip.right > 0) {
1608+
left -= clip.right;
1609+
}
1610+
1611+
// Popover text and arrow are positioned individually
1612+
this._$messagePopover.css({"top": top, "left": left});
1613+
1614+
// Position popover arrow exactly centered over/under cursor
1615+
arrowLeft = cursorCoord.left - left - POPOVER_ARROW_HALF_WIDTH;
1616+
if (arrowBelow) {
1617+
this._$messagePopover.find(".arrowBelow").css({"margin-left": arrowLeft});
1618+
} else {
1619+
this._$messagePopover.find(".arrowAbove").css({"margin-left": arrowLeft});
1620+
}
1621+
1622+
// Add listeners
1623+
PopUpManager.addPopUp(this._$messagePopover, _clearMessagePopover, true);
1624+
_addListeners();
1625+
1626+
// Animate open
1627+
AnimationUtils.animateUsingClass(this._$messagePopover[0], "animateOpen").done(function () {
1628+
// Make sure we still have a popover
1629+
if (self._$messagePopover && self._$messagePopover.length > 0) {
1630+
self._$messagePopover.addClass("open");
1631+
1632+
// Don't add scroll listeners until open so we don't get event
1633+
// from scrolling cursor into view
1634+
$(self).on("scroll.msgbox", _removeMessagePopover);
1635+
1636+
// Animate closed -- which includes delay to show message
1637+
AnimationUtils.animateUsingClass(self._$messagePopover[0], "animateClose")
1638+
.done(_removeMessagePopover);
1639+
}
1640+
});
1641+
};
1642+
15211643
/**
15221644
* Returns the offset of the top of the virtual scroll area relative to the browser window (not the editor
15231645
* itself). Mainly useful for calculations related to scrollIntoView(), where you're starting with the

0 commit comments

Comments
 (0)