show a palette for current editor in color picker (#1068)
also keep the dialog visible for 30 seconds instead of 5
This commit is contained in:
parent
e6d73be049
commit
3cb9cbb862
|
@ -20,13 +20,11 @@
|
||||||
defaults.extraKeys[keyName] = 'colorpicker';
|
defaults.extraKeys[keyName] = 'colorpicker';
|
||||||
}
|
}
|
||||||
defaults.colorpicker = {
|
defaults.colorpicker = {
|
||||||
// FIXME: who uses this?
|
|
||||||
// forceUpdate: editor.getEditors().length > 0,
|
|
||||||
tooltip: t('colorpickerTooltip'),
|
tooltip: t('colorpickerTooltip'),
|
||||||
popup: {
|
popup: {
|
||||||
tooltipForSwitcher: t('colorpickerSwitchFormatTooltip'),
|
tooltipForSwitcher: t('colorpickerSwitchFormatTooltip'),
|
||||||
hexUppercase: prefs.get('editor.colorpicker.hexUppercase'),
|
hexUppercase: prefs.get('editor.colorpicker.hexUppercase'),
|
||||||
hideDelay: 5000,
|
hideDelay: 30e3,
|
||||||
embedderCallback: state => {
|
embedderCallback: state => {
|
||||||
['hexUppercase', 'color']
|
['hexUppercase', 'color']
|
||||||
.filter(name => state[name] !== prefs.get('editor.colorpicker.' + name))
|
.filter(name => state[name] !== prefs.get('editor.colorpicker.' + name))
|
||||||
|
|
|
@ -357,3 +357,15 @@
|
||||||
.colorpicker-format-change-button:hover {
|
.colorpicker-format-change-button:hover {
|
||||||
color: var(--label-color-hover);
|
color: var(--label-color-hover);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.colorpicker-palette:not(:empty) {
|
||||||
|
padding: 0 8px 8px;
|
||||||
|
min-height: 14px; /* same as padding-left in .colorview-swatch */
|
||||||
|
max-height: 10vw;
|
||||||
|
overflow: auto;
|
||||||
|
box-sizing: content-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.colorpicker-palette .colorview-swatch {
|
||||||
|
padding-bottom: 14px; /* same as padding-left in .colorview-swatch */
|
||||||
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
let $swatch;
|
let $swatch;
|
||||||
let $formatChangeButton;
|
let $formatChangeButton;
|
||||||
let $hexCode;
|
let $hexCode;
|
||||||
|
let $palette;
|
||||||
const $inputGroups = {};
|
const $inputGroups = {};
|
||||||
const $inputs = {};
|
const $inputs = {};
|
||||||
const $rgb = {};
|
const $rgb = {};
|
||||||
|
@ -164,6 +165,7 @@
|
||||||
$formatChangeButton = $('format-change-button', {textContent: '↔'}),
|
$formatChangeButton = $('format-change-button', {textContent: '↔'}),
|
||||||
]}),
|
]}),
|
||||||
]}),
|
]}),
|
||||||
|
$palette = $('palette'),
|
||||||
]});
|
]});
|
||||||
|
|
||||||
$inputs.hex = [$hexCode];
|
$inputs.hex = [$hexCode];
|
||||||
|
@ -221,6 +223,11 @@
|
||||||
if (!isNaN(options.left) && !isNaN(options.top)) {
|
if (!isNaN(options.left) && !isNaN(options.top)) {
|
||||||
reposition();
|
reposition();
|
||||||
}
|
}
|
||||||
|
if (Array.isArray(options.palette)) {
|
||||||
|
// Might need to clear a lot of elements so this is known to be faster than textContent = ''
|
||||||
|
while ($palette.firstChild) $palette.firstChild.remove();
|
||||||
|
$palette.append(...(options.palette));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function hide() {
|
function hide() {
|
||||||
|
@ -454,7 +461,7 @@
|
||||||
const newHSV = color.type === 'hsl' ?
|
const newHSV = color.type === 'hsl' ?
|
||||||
colorConverter.HSLtoHSV(color) :
|
colorConverter.HSLtoHSV(color) :
|
||||||
colorConverter.RGBtoHSV(color);
|
colorConverter.RGBtoHSV(color);
|
||||||
if (Object.keys(newHSV).every(k => Math.abs(newHSV[k] - HSV[k]) < 1e-3)) {
|
if (Object.entries(newHSV).every(([k, v]) => v === HSV[k] || Math.abs(v - HSV[k]) < 1e-3)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
HSV = newHSV;
|
HSV = newHSV;
|
||||||
|
@ -574,6 +581,19 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @param {MouseEvent} e */
|
||||||
|
function onPaletteClicked(e) {
|
||||||
|
if (e.target !== e.currentTarget) {
|
||||||
|
e.preventDefault();
|
||||||
|
if (!e.button && setColor(e.target.__color)) {
|
||||||
|
userActivity = performance.now();
|
||||||
|
colorpickerCallback();
|
||||||
|
} else if (e.button === 2 && options.paletteCallback) {
|
||||||
|
options.paletteCallback(e.target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function onMouseUp(event) {
|
function onMouseUp(event) {
|
||||||
releaseMouse(event, ['saturation', 'hue', 'opacity']);
|
releaseMouse(event, ['saturation', 'hue', 'opacity']);
|
||||||
if (onMouseDown.outsideClick) {
|
if (onMouseDown.outsideClick) {
|
||||||
|
@ -710,6 +730,8 @@
|
||||||
$opacity.addEventListener('mousedown', onOpacityMouseDown);
|
$opacity.addEventListener('mousedown', onOpacityMouseDown);
|
||||||
$hexLettercase.true.addEventListener('click', onHexLettercaseClicked);
|
$hexLettercase.true.addEventListener('click', onHexLettercaseClicked);
|
||||||
$hexLettercase.false.addEventListener('click', onHexLettercaseClicked);
|
$hexLettercase.false.addEventListener('click', onHexLettercaseClicked);
|
||||||
|
$palette.addEventListener('click', onPaletteClicked);
|
||||||
|
$palette.addEventListener('contextmenu', onPaletteClicked);
|
||||||
|
|
||||||
stopSnoozing();
|
stopSnoozing();
|
||||||
if (!options.isShortCut) {
|
if (!options.isShortCut) {
|
||||||
|
@ -735,6 +757,8 @@
|
||||||
$opacity.removeEventListener('mousedown', onOpacityMouseDown);
|
$opacity.removeEventListener('mousedown', onOpacityMouseDown);
|
||||||
$hexLettercase.true.removeEventListener('click', onHexLettercaseClicked);
|
$hexLettercase.true.removeEventListener('click', onHexLettercaseClicked);
|
||||||
$hexLettercase.false.removeEventListener('click', onHexLettercaseClicked);
|
$hexLettercase.false.removeEventListener('click', onHexLettercaseClicked);
|
||||||
|
$palette.removeEventListener('click', onPaletteClicked);
|
||||||
|
$palette.removeEventListener('contextmenu', onPaletteClicked);
|
||||||
releaseMouse();
|
releaseMouse();
|
||||||
stopSnoozing();
|
stopSnoozing();
|
||||||
}
|
}
|
||||||
|
|
|
@ -532,6 +532,8 @@
|
||||||
color: data.color,
|
color: data.color,
|
||||||
prevColor: data.color || '',
|
prevColor: data.color || '',
|
||||||
callback: popupOnChange,
|
callback: popupOnChange,
|
||||||
|
palette: makePalette(state),
|
||||||
|
paletteCallback: el => paletteCallback(state, el),
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -551,6 +553,49 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function makePalette({cm, options}) {
|
||||||
|
const palette = new Map();
|
||||||
|
let i = 0;
|
||||||
|
let nums;
|
||||||
|
cm.eachLine(({markedSpans}) => {
|
||||||
|
++i;
|
||||||
|
if (!markedSpans) return;
|
||||||
|
for (const {from, marker: m} of markedSpans) {
|
||||||
|
if (from == null || m.className !== COLORVIEW_CLASS) continue;
|
||||||
|
nums = palette.get(m.color);
|
||||||
|
if (!nums) palette.set(m.color, (nums = []));
|
||||||
|
nums.push(i);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const res = [];
|
||||||
|
if (palette.size > 1 || nums && nums.length > 1) {
|
||||||
|
const old = new Map((options.popup.palette || []).map(el => [el.__color, el]));
|
||||||
|
for (const [color, data] of palette) {
|
||||||
|
res.push(old.get(color) || makePaletteSwatch(color, data));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
function makePaletteSwatch(color, nums) {
|
||||||
|
const s = nums.join(', ');
|
||||||
|
const el = document.createElement('div');
|
||||||
|
el.className = COLORVIEW_SWATCH_CLASS;
|
||||||
|
el.style.cssText = COLORVIEW_SWATCH_CSS + color;
|
||||||
|
el.title = color + (!s ? '' : `\nLine: ${s.length > 50 ? s.replace(/([^,]+,\s){10}/g, '$&\n') : s}`);
|
||||||
|
el.__color = color;
|
||||||
|
return el;
|
||||||
|
}
|
||||||
|
|
||||||
|
function paletteCallback({cm}, el) {
|
||||||
|
const lines = el.title.split('\n')[1].match(/\d+/g).map(Number);
|
||||||
|
const curLine = cm.getCursor().line + 1;
|
||||||
|
const i = lines.indexOf(curLine) + 1;
|
||||||
|
const pos = {line: (lines[i] || curLine) - 1, ch: 0};
|
||||||
|
cm.scrollIntoView(pos, cm.defaultTextHeight());
|
||||||
|
cm.setCursor(pos);
|
||||||
|
}
|
||||||
|
|
||||||
//endregion
|
//endregion
|
||||||
//region Utility
|
//region Utility
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user