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:
tophf 2020-10-18 16:40:11 +03:00 committed by GitHub
parent e6d73be049
commit 3cb9cbb862
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 83 additions and 4 deletions

View File

@ -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))

View File

@ -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 */
}

View File

@ -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();
} }

View File

@ -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