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

Commit e83807d

Browse files
committed
Merge pull request #9596 from le717/issue-9519-take2
Use upper/lowercase colors in Inline Color Editor
2 parents a3068fa + c9c7a2e commit e83807d

5 files changed

Lines changed: 179 additions & 114 deletions

File tree

src/editor/Editor.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,9 @@ define(function (require, exports, module) {
9494
SPACE_UNITS = "spaceUnits",
9595
STYLE_ACTIVE_LINE = "styleActiveLine",
9696
TAB_SIZE = "tabSize",
97-
WORD_WRAP = "wordWrap",
98-
USE_TAB_CHAR = "useTabChar";
97+
UPPERCASE_COLORS = "uppercaseColors",
98+
USE_TAB_CHAR = "useTabChar",
99+
WORD_WRAP = "wordWrap";
99100

100101
var cmOptions = {};
101102

@@ -141,6 +142,7 @@ define(function (require, exports, module) {
141142
PreferencesManager.definePreference(TAB_SIZE, "number", DEFAULT_TAB_SIZE, {
142143
validator: _.partialRight(ValidationUtils.isIntegerInRange, MIN_TAB_SIZE, MAX_TAB_SIZE)
143144
});
145+
PreferencesManager.definePreference(UPPERCASE_COLORS, "boolean", false);
144146
PreferencesManager.definePreference(USE_TAB_CHAR, "boolean", false);
145147
PreferencesManager.definePreference(WORD_WRAP, "boolean", true);
146148

src/extensions/default/InlineColorEditor/ColorEditor.js

Lines changed: 80 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -22,20 +22,23 @@
2222
*/
2323

2424
/*jslint vars: true, plusplus: true, nomen: true, regexp: true, maxerr: 50 */
25-
/*global define, brackets, $, window, tinycolor, Mustache */
25+
/*global define, brackets, $, window, Mustache */
2626

2727
define(function (require, exports, module) {
2828
"use strict";
29-
require("thirdparty/tinycolor-min");
3029

31-
var KeyEvent = brackets.getModule("utils/KeyEvent"),
32-
StringUtils = brackets.getModule("utils/StringUtils"),
33-
Strings = brackets.getModule("strings");
30+
var KeyEvent = brackets.getModule("utils/KeyEvent"),
31+
PreferencesManager = brackets.getModule("preferences/PreferencesManager"),
32+
StringUtils = brackets.getModule("utils/StringUtils"),
33+
Strings = brackets.getModule("strings"),
34+
tinycolor = require("thirdparty/tinycolor-min");
3435

3536
/** Mustache template that forms the bare DOM structure of the UI */
3637
var ColorEditorTemplate = require("text!ColorEditorTemplate.html");
3738

38-
/** @const @type {number} */
39+
/**
40+
* @const @type {number}
41+
*/
3942
var STEP_MULTIPLIER = 5;
4043

4144
/**
@@ -64,6 +67,10 @@ define(function (require, exports, module) {
6467
this._color = tinycolor(color);
6568
this._originalColor = color;
6669
this._redoColor = null;
70+
this._isUpperCase = PreferencesManager.get("uppercaseColors");
71+
PreferencesManager.on("change", "uppercaseColors", function () {
72+
this._isUpperCase = PreferencesManager.get("uppercaseColors");
73+
}.bind(this));
6774

6875
this.$colorValue = this.$element.find(".color-value");
6976
this.$buttonList = this.$element.find("ul.button-bar");
@@ -152,11 +159,11 @@ define(function (require, exports, module) {
152159
* incorrect to call this directly; use _commitColor() or setColorAsHsv() instead.
153160
*/
154161
ColorEditor.prototype._synchronize = function () {
155-
var colorValue = this.getColor().toString(),
162+
var colorValue = this.getColor().getOriginalInput(),
156163
colorObject = tinycolor(colorValue),
157-
hueColor = "hsl(" + this._hsv.h + ", 100%, 50%)";
164+
hueColor = "hsl(" + this._hsv.h + ", 100%, 50%)";
158165

159-
this._updateColorTypeRadioButtons(colorObject.format);
166+
this._updateColorTypeRadioButtons(colorObject.getFormat());
160167
this.$colorValue.val(colorValue);
161168
this.$currentColor.css("background-color", colorValue);
162169
this.$selection.css("background-color", hueColor);
@@ -181,16 +188,28 @@ define(function (require, exports, module) {
181188
});
182189
};
183190

184-
/** Focus the main color square's thumb */
191+
/**
192+
* Focus the main color square's thumb.
193+
* @return {boolean} True if we focused the square, false otherwise.
194+
*/
185195
ColorEditor.prototype.focus = function () {
186196
if (!this.$selectionBase.is(":focus")) {
187197
this.$selectionBase.focus();
188198
return true;
189199
}
190200
return false;
191201
};
202+
203+
/**
204+
* Remove any preference listeners before destroying the editor.
205+
*/
206+
ColorEditor.prototype.destroy = function () {
207+
PreferencesManager.off("change", "uppercaseColors");
208+
};
192209

193-
/** @return {tinycolor|string} The currently selected color (TODO (#2201): type is unpredictable) */
210+
/**
211+
* @return {tinycolor|string} The currently selected color (TODO (#2201): type is unpredictable).
212+
*/
194213
ColorEditor.prototype.getColor = function () {
195214
return this._color;
196215
};
@@ -215,12 +234,12 @@ define(function (require, exports, module) {
215234
/** Add event listeners to the format button bar */
216235
ColorEditor.prototype._bindColorFormatToRadioButton = function (buttonClass, propertyName, value) {
217236
var handler,
218-
_this = this;
237+
self = this;
219238
handler = function (event) {
220-
var colorObject, newColor, newFormat;
221-
newFormat = $(event.currentTarget).html().toLowerCase().replace("%", "p");
222-
newColor = _this.getColor();
223-
colorObject = tinycolor(newColor);
239+
var newFormat = $(event.currentTarget).html().toLowerCase().replace("%", "p"),
240+
newColor = self.getColor().toString(),
241+
colorObject = tinycolor(newColor);
242+
224243
switch (newFormat) {
225244
case "hsla":
226245
newColor = colorObject.toHslString();
@@ -233,19 +252,23 @@ define(function (require, exports, module) {
233252
break;
234253
case "hex":
235254
newColor = colorObject.toHexString();
236-
_this._hsv.a = 1;
255+
self._hsv.a = 1;
237256
break;
238257
}
239-
_this._commitColor(newColor, false);
258+
259+
// We need to run this again whenever RGB/HSL/Hex conversions
260+
// are performed to preserve the case
261+
newColor = self._isUpperCase ? newColor.toUpperCase() : newColor;
262+
self._commitColor(newColor, false);
240263
};
241264
this.$element.find("." + buttonClass).click(handler);
242265
};
243266

244267
/** Add event listener to the "original color value" swatch */
245268
ColorEditor.prototype._bindOriginalColorButton = function () {
246-
var _this = this;
269+
var self = this;
247270
this.$originalColor.click(function (event) {
248-
_this._commitColor(_this._originalColor, true);
271+
self._commitColor(self._originalColor, true);
249272
});
250273
};
251274

@@ -256,7 +279,7 @@ define(function (require, exports, module) {
256279
* @return {string} an RGB color string in the normal format using non-percentage values
257280
*/
258281
ColorEditor.prototype._convertToNormalRGB = function (color) {
259-
var matches = color.match(/^rgb.*?([0-9]+)\%.*?([0-9]+)\%.*?([0-9]+)\%/);
282+
var matches = color.match(/^rgb.*?([0-9]+)\%.*?([0-9]+)\%.*?([0-9]+)\%/i);
260283
if (matches) {
261284
var i, percentStr, value;
262285
for (i = 0; i < 3; i++) {
@@ -279,30 +302,30 @@ define(function (require, exports, module) {
279302
ColorEditor.prototype._normalizeColorString = function (color) {
280303
var normalizedColor = color;
281304

282-
// Convert 6-digit hex to 3-digit hex as tinycolor (#ffaacc -> #fac)
305+
// Convert 6-digit hex to 3-digit hex as TinyColor (#ffaacc -> #fac)
283306
if (color.match(/^#[0-9a-fA-F]{6}/)) {
284307
return tinycolor(color).toString();
285308
}
286-
if (color.match(/^(rgb|hsl)/)) {
309+
if (color.match(/^(rgb|hsl)/i)) {
287310
normalizedColor = normalizedColor.replace(/,\s*/g, ", ");
288311
normalizedColor = normalizedColor.replace(/\(\s+/, "(");
289312
normalizedColor = normalizedColor.replace(/\s+\)/, ")");
290313
}
291-
return normalizedColor.toLowerCase();
314+
return normalizedColor;
292315
};
293316

294317
/** Handle changes in text field */
295318
ColorEditor.prototype._handleTextFieldInput = function (losingFocus) {
296-
var newColor = $.trim(this.$colorValue.val()),
319+
var newColor = $.trim(this.$colorValue.val()),
297320
newColorObj = tinycolor(newColor),
298-
newColorOk = newColorObj.ok;
321+
newColorOk = newColorObj.isValid();
299322

300-
// tinycolor will auto correct an incomplete rgb or hsl value into a valid color value.
323+
// TinyColor will auto correct an incomplete rgb or hsl value into a valid color value.
301324
// eg. rgb(0,0,0 -> rgb(0, 0, 0)
302-
// We want to avoid having tinycolor do this, because we don't want to sync the color
325+
// We want to avoid having TinyColor do this, because we don't want to sync the color
303326
// to the UI if it's incomplete. To accomplish this, we first normalize the original
304-
// color string into the format tinycolor would generate, and then compare it to what
305-
// tinycolor actually generates to see if it's different. If so, then we assume the color
327+
// color string into the format TinyColor would generate, and then compare it to what
328+
// TinyColor actually generates to see if it's different. If so, then we assume the color
306329
// was incomplete to begin with.
307330
if (newColorOk) {
308331
newColorOk = (newColorObj.toString() === this._normalizeColorString(newColor));
@@ -320,14 +343,14 @@ define(function (require, exports, module) {
320343
};
321344

322345
ColorEditor.prototype._bindInputHandlers = function () {
323-
var _this = this;
346+
var self = this;
324347

325348
this.$colorValue.bind("input", function (event) {
326-
_this._handleTextFieldInput(false);
349+
self._handleTextFieldInput(false);
327350
});
328351

329352
this.$colorValue.bind("change", function (event) {
330-
_this._handleTextFieldInput(true);
353+
self._handleTextFieldInput(true);
331354
});
332355
};
333356

@@ -336,13 +359,13 @@ define(function (require, exports, module) {
336359
* @param {!Array.<{value:string, count:number}>} swatches
337360
*/
338361
ColorEditor.prototype._addSwatches = function (swatches) {
339-
var _this = this;
362+
var self = this;
340363

341364
// Create swatches
342365
swatches.forEach(function (swatch) {
343366
var stringFormat = (swatch.count > 1) ? Strings.COLOR_EDITOR_USED_COLOR_TIP_PLURAL : Strings.COLOR_EDITOR_USED_COLOR_TIP_SINGULAR,
344367
usedColorTip = StringUtils.format(stringFormat, swatch.value, swatch.count);
345-
_this.$swatches.append("<li tabindex='0'><div class='swatch-bg'><div class='swatch' style='background-color: " +
368+
self.$swatches.append("<li tabindex='0'><div class='swatch-bg'><div class='swatch' style='background-color: " +
346369
swatch.value + ";' title='" + usedColorTip + "'></div></div> <span class='value'" + " title='" +
347370
usedColorTip + "'>" + swatch.value + "</span></li>");
348371
});
@@ -353,18 +376,18 @@ define(function (require, exports, module) {
353376
event.keyCode === KeyEvent.DOM_VK_ENTER ||
354377
event.keyCode === KeyEvent.DOM_VK_SPACE) {
355378
// Enter/Space is same as clicking on swatch
356-
_this._commitColor($(event.currentTarget).find(".value").html());
379+
self._commitColor($(event.currentTarget).find(".value").html());
357380
} else if (event.keyCode === KeyEvent.DOM_VK_TAB) {
358381
// Tab on last swatch loops back to color square
359382
if (!event.shiftKey && $(this).next("li").length === 0) {
360-
_this.$selectionBase.focus();
383+
self.$selectionBase.focus();
361384
return false;
362385
}
363386
}
364387
});
365388

366389
this.$swatches.find("li").click(function (event) {
367-
_this._commitColor($(event.currentTarget).find(".value").html());
390+
self._commitColor($(event.currentTarget).find(".value").html());
368391
});
369392
};
370393

@@ -374,8 +397,8 @@ define(function (require, exports, module) {
374397
* @param {!{h:number=, s:number=, v:number=}} hsv Any missing values use the previous color's values.
375398
*/
376399
ColorEditor.prototype.setColorAsHsv = function (hsv) {
377-
var colorVal, newColor, oldFormat;
378-
oldFormat = tinycolor(this.getColor()).format;
400+
var colorVal, newColor,
401+
oldFormat = tinycolor(this.getColor()).getFormat();
379402

380403
// Set our state to the new color
381404
$.extend(this._hsv, hsv);
@@ -396,6 +419,7 @@ define(function (require, exports, module) {
396419
colorVal = this._hsv.a < 1 ? newColor.toRgbString() : newColor.toHexString();
397420
break;
398421
}
422+
colorVal = this._isUpperCase ? colorVal.toUpperCase() : colorVal;
399423
this._commitColor(colorVal, false);
400424
};
401425

@@ -406,17 +430,16 @@ define(function (require, exports, module) {
406430
* @param {boolean=} resetHsv Pass false ONLY if hsv set already been modified to match colorVal. Default: true.
407431
*/
408432
ColorEditor.prototype._commitColor = function (colorVal, resetHsv) {
409-
var colorObj;
410433
if (resetHsv === undefined) {
411434
resetHsv = true;
412435
}
413436
this._callback(colorVal);
414-
this._color = colorVal;
437+
this._color = tinycolor(colorVal);
438+
415439
if (resetHsv) {
416-
colorObj = tinycolor(colorVal);
417-
this._hsv = colorObj.toHsv();
418-
this._color = colorObj;
440+
this._hsv = this._color.toHsv();
419441
}
442+
420443
this._redoColor = null; // if we had undone, this new value blows away the redo history
421444
this._synchronize();
422445
};
@@ -439,12 +462,11 @@ define(function (require, exports, module) {
439462

440463
/** Dragging color square's thumb */
441464
ColorEditor.prototype._handleSelectionFieldDrag = function (event) {
442-
var height, hsv, width, xOffset, yOffset;
443-
height = this.$selection.height();
444-
width = this.$selection.width();
445-
xOffset = _getNewOffset(event.clientX, this.$selection.offset().left, width);
446-
yOffset = _getNewOffset(event.clientY, this.$selection.offset().top, height);
447-
hsv = {};
465+
var height = this.$selection.height(),
466+
width = this.$selection.width(),
467+
xOffset = _getNewOffset(event.clientX, this.$selection.offset().left, width),
468+
yOffset = _getNewOffset(event.clientY, this.$selection.offset().top, height),
469+
hsv = {};
448470
hsv.s = xOffset / width;
449471
hsv.v = 1 - yOffset / height;
450472
this.setColorAsHsv(hsv, false);
@@ -455,10 +477,9 @@ define(function (require, exports, module) {
455477

456478
/** Dragging hue slider thumb */
457479
ColorEditor.prototype._handleHueDrag = function (event) {
458-
var height, hsv, offset;
459-
height = this.$hueSlider.height();
460-
offset = _getNewOffset(event.clientY, this.$hueSlider.offset().top, height);
461-
hsv = {};
480+
var height = this.$hueSlider.height(),
481+
offset = _getNewOffset(event.clientY, this.$hueSlider.offset().top, height),
482+
hsv = {};
462483
hsv.h = (1 - offset / height) * 360;
463484
this.setColorAsHsv(hsv, false);
464485
if (!this.$hueSlider.find(".selector-base").is(":focus")) {
@@ -468,11 +489,10 @@ define(function (require, exports, module) {
468489

469490
/** Dragging opacity slider thumb */
470491
ColorEditor.prototype._handleOpacityDrag = function (event) {
471-
var height, hsv, offset;
472-
height = this.$opacitySlider.height();
473-
offset = _getNewOffset(event.clientY, this.$opacitySlider.offset().top, height);
474-
hsv = {};
475-
hsv.a = 1 - offset / height;
492+
var height = this.$opacitySlider.height(),
493+
offset = _getNewOffset(event.clientY, this.$opacitySlider.offset().top, height),
494+
hsv = {};
495+
hsv.a = 1 - (offset / height);
476496
this.setColorAsHsv(hsv, false);
477497
if (!this.$opacitySlider.find(".selector-base").is(":focus")) {
478498
this.$opacitySlider.find(".selector-base").focus();

src/extensions/default/InlineColorEditor/InlineColorEditor.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@ define(function (require, exports, module) {
212212
var doc = this.hostEditor.document;
213213
doc.off("change", this._handleHostDocumentChange);
214214
doc.releaseRef();
215+
this.colorEditor.destroy();
215216
};
216217

217218
/** Comparator to sort by which colors are used the most */

0 commit comments

Comments
 (0)