mirror of
https://github.com/zen-browser/components.git
synced 2025-07-08 00:10:01 +02:00
Merge pull request #76 from neurokitti/feature/color-picker-click-spawn
Add the ability to spawn color dots where you click
This commit is contained in:
commit
037547460d
1 changed files with 147 additions and 17 deletions
|
@ -15,6 +15,7 @@
|
||||||
if (!Services.prefs.getBoolPref('zen.theme.gradient', true) || !ZenWorkspaces.shouldHaveWorkspaces) {
|
if (!Services.prefs.getBoolPref('zen.theme.gradient', true) || !ZenWorkspaces.shouldHaveWorkspaces) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
this.dragStartPosition = null;
|
||||||
|
|
||||||
ChromeUtils.defineLazyGetter(this, 'panel', () => document.getElementById('PanelUI-zen-gradient-generator'));
|
ChromeUtils.defineLazyGetter(this, 'panel', () => document.getElementById('PanelUI-zen-gradient-generator'));
|
||||||
ChromeUtils.defineLazyGetter(this, 'toolbox', () => document.getElementById('TabsToolbar'));
|
ChromeUtils.defineLazyGetter(this, 'toolbox', () => document.getElementById('TabsToolbar'));
|
||||||
|
@ -73,6 +74,7 @@
|
||||||
this.image.onload = this.onImageLoad.bind(this);
|
this.image.onload = this.onImageLoad.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
onImageLoad() {
|
onImageLoad() {
|
||||||
// resize the image to fit the panel
|
// resize the image to fit the panel
|
||||||
const imageSize = 300 - 20; // 20 is the padding (10px)
|
const imageSize = 300 - 20; // 20 is the padding (10px)
|
||||||
|
@ -90,6 +92,7 @@
|
||||||
this.initContextMenu();
|
this.initContextMenu();
|
||||||
this.initThemePicker();
|
this.initThemePicker();
|
||||||
|
|
||||||
|
|
||||||
this._hasInitialized = true;
|
this._hasInitialized = true;
|
||||||
this.onDarkModeChange(null);
|
this.onDarkModeChange(null);
|
||||||
}
|
}
|
||||||
|
@ -167,6 +170,7 @@
|
||||||
themePicker.style.setProperty('--zen-theme-picker-gradient-image', `url(${ZenThemePicker.GRADIENT_DISPLAY_URL})`);
|
themePicker.style.setProperty('--zen-theme-picker-gradient-image', `url(${ZenThemePicker.GRADIENT_DISPLAY_URL})`);
|
||||||
themePicker.addEventListener('mousemove', this.onDotMouseMove.bind(this));
|
themePicker.addEventListener('mousemove', this.onDotMouseMove.bind(this));
|
||||||
themePicker.addEventListener('mouseup', this.onDotMouseUp.bind(this));
|
themePicker.addEventListener('mouseup', this.onDotMouseUp.bind(this));
|
||||||
|
themePicker.addEventListener('click', this.onThemePickerClick.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
calculateInitialPosition(color) {
|
calculateInitialPosition(color) {
|
||||||
|
@ -231,16 +235,76 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onDotMouseDown(event) {
|
onThemePickerClick(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
if (event.button === 2) {
|
|
||||||
return;
|
|
||||||
|
if (event.button !== 0 || this.dragging ) return;
|
||||||
|
|
||||||
|
const gradient = this.panel.querySelector('.zen-theme-picker-gradient');
|
||||||
|
const rect = gradient.getBoundingClientRect();
|
||||||
|
const padding = 90; // each side
|
||||||
|
|
||||||
|
const centerX = rect.left + rect.width / 2;
|
||||||
|
const centerY = rect.top + rect.height / 2;
|
||||||
|
const radius = (rect.width - padding) / 2;
|
||||||
|
let pixelX = event.clientX;
|
||||||
|
let pixelY = event.clientY;
|
||||||
|
|
||||||
|
// Check if the click is within the circle
|
||||||
|
const distance = Math.sqrt((pixelX - centerX) ** 2 + (pixelY - centerY) ** 2);
|
||||||
|
if (distance > radius) {
|
||||||
|
return; // Don't create a dot if clicking outside the circle
|
||||||
}
|
}
|
||||||
this.dragging = true;
|
|
||||||
this.draggedDot = event.target;
|
// Check if we clicked on an existing dot
|
||||||
this.draggedDot.style.zIndex = 1;
|
const clickedElement = event.target;
|
||||||
this.draggedDot.classList.add('dragging');
|
const isExistingDot = clickedElement.classList.contains('zen-theme-picker-dot');
|
||||||
|
|
||||||
|
// Only proceed if not clicking on an existing dot
|
||||||
|
if (!isExistingDot) {
|
||||||
|
|
||||||
|
const relativeX = event.clientX - rect.left;
|
||||||
|
const relativeY = event.clientY - rect.top;
|
||||||
|
|
||||||
|
|
||||||
|
const color = this.getColorFromPosition(relativeX, relativeY);
|
||||||
|
|
||||||
|
// Create new dot
|
||||||
|
const dot = document.createElement('div');
|
||||||
|
dot.classList.add('zen-theme-picker-dot');
|
||||||
|
dot.addEventListener('mousedown', this.onDotMouseDown.bind(this));
|
||||||
|
|
||||||
|
dot.style.left = `${relativeX}px`;
|
||||||
|
dot.style.top = `${relativeY}px`;
|
||||||
|
dot.style.setProperty('--zen-theme-picker-dot-color', `rgb(${color[0]}, ${color[1]}, ${color[2]})`);
|
||||||
|
|
||||||
|
gradient.appendChild(dot);
|
||||||
|
|
||||||
|
this.updateCurrentWorkspace(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
onDotMouseDown(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
if (event.button === 2) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
this.dragging = true;
|
||||||
|
this.draggedDot = event.target;
|
||||||
|
this.draggedDot.style.zIndex = 1;
|
||||||
|
this.draggedDot.classList.add('dragging');
|
||||||
|
|
||||||
|
// Store the starting position of the drag
|
||||||
|
this.dragStartPosition = {
|
||||||
|
x: event.clientX,
|
||||||
|
y: event.clientY
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
onDotMouseMove(event) {
|
onDotMouseMove(event) {
|
||||||
if (this.dragging) {
|
if (this.dragging) {
|
||||||
|
@ -250,17 +314,19 @@
|
||||||
// do NOT let the ball be draged outside of an imaginary circle. You can drag it anywhere inside the circle
|
// do NOT let the ball be draged outside of an imaginary circle. You can drag it anywhere inside the circle
|
||||||
// if the distance between the center of the circle and the dragged ball is bigger than the radius, then the ball
|
// if the distance between the center of the circle and the dragged ball is bigger than the radius, then the ball
|
||||||
// should be placed on the edge of the circle. If it's inside the circle, then the ball just follows the mouse
|
// should be placed on the edge of the circle. If it's inside the circle, then the ball just follows the mouse
|
||||||
|
|
||||||
const centerX = rect.left + rect.width / 2;
|
const centerX = rect.left + rect.width / 2;
|
||||||
const centerY = rect.top + rect.height / 2;
|
const centerY = rect.top + rect.height / 2;
|
||||||
const radius = (rect.width - padding) / 2;
|
const radius = (rect.width - padding) / 2;
|
||||||
let pixelX = event.clientX;
|
let pixelX = event.clientX;
|
||||||
let pixelY = event.clientY;
|
let pixelY = event.clientY;
|
||||||
const distance = Math.sqrt((pixelX - centerX) ** 2 + (pixelY - centerY) ** 2);
|
const distance = Math.sqrt((pixelX - centerX) **2 + (pixelY - centerY) **2);
|
||||||
if (distance > radius) {
|
if (distance > radius) {
|
||||||
const angle = Math.atan2(pixelY - centerY, pixelX - centerX);
|
const angle = Math.atan2(pixelY - centerY, pixelX - centerX);
|
||||||
pixelX = centerX + Math.cos(angle) * radius;
|
pixelX = centerX + Math.cos(angle) * radius;
|
||||||
pixelY = centerY + Math.sin(angle) * radius;
|
pixelY = centerY + Math.sin(angle) * radius;
|
||||||
}
|
}
|
||||||
|
|
||||||
// set the location of the dot in pixels
|
// set the location of the dot in pixels
|
||||||
const relativeX = pixelX - rect.left;
|
const relativeX = pixelX - rect.left;
|
||||||
const relativeY = pixelY - rect.top;
|
const relativeY = pixelY - rect.top;
|
||||||
|
@ -288,7 +354,7 @@
|
||||||
|
|
||||||
async addCustomColor() {
|
async addCustomColor() {
|
||||||
const color = this.customColorInput.value;
|
const color = this.customColorInput.value;
|
||||||
if (!color || !color.match(/^#[0-9a-f]{3,8}$/i)) {
|
if (!color) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// can be any color format, we just add it to the list as a dot, but hidden
|
// can be any color format, we just add it to the list as a dot, but hidden
|
||||||
|
@ -301,6 +367,71 @@
|
||||||
await this.updateCurrentWorkspace();
|
await this.updateCurrentWorkspace();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
onThemePickerClick(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
if (event.button !== 0 || this.dragging) return;
|
||||||
|
|
||||||
|
const gradient = this.panel.querySelector('.zen-theme-picker-gradient');
|
||||||
|
const rect = gradient.getBoundingClientRect();
|
||||||
|
const padding = 90; // each side
|
||||||
|
|
||||||
|
const centerX = rect.left + rect.width / 2;
|
||||||
|
const centerY = rect.top + rect.height / 2;
|
||||||
|
const radius = (rect.width - padding) / 2;
|
||||||
|
let pixelX = event.clientX;
|
||||||
|
let pixelY = event.clientY;
|
||||||
|
|
||||||
|
// Check if the click is within the circle
|
||||||
|
const distance = Math.sqrt((pixelX - centerX) ** 2 + (pixelY - centerY) ** 2);
|
||||||
|
if (distance > radius) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const clickedElement = event.target;
|
||||||
|
const isExistingDot = clickedElement.classList.contains('zen-theme-picker-dot');
|
||||||
|
|
||||||
|
|
||||||
|
if (!isExistingDot && this.numberOfDots < ZenThemePicker.MAX_DOTS) {
|
||||||
|
const relativeX = event.clientX - rect.left;
|
||||||
|
const relativeY = event.clientY - rect.top;
|
||||||
|
|
||||||
|
const color = this.getColorFromPosition(relativeX, relativeY);
|
||||||
|
|
||||||
|
const dot = document.createElement('div');
|
||||||
|
dot.classList.add('zen-theme-picker-dot');
|
||||||
|
dot.addEventListener('mousedown', this.onDotMouseDown.bind(this));
|
||||||
|
|
||||||
|
dot.style.left = `${relativeX}px`;
|
||||||
|
dot.style.top = `${relativeY}px`;
|
||||||
|
dot.style.setProperty('--zen-theme-picker-dot-color', `rgb(${color[0]}, ${color[1]}, ${color[2]})`);
|
||||||
|
|
||||||
|
gradient.appendChild(dot);
|
||||||
|
|
||||||
|
this.updateCurrentWorkspace(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onDotMouseDown(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
if (event.button === 2) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.dragging = true;
|
||||||
|
this.draggedDot = event.target;
|
||||||
|
this.draggedDot.style.zIndex = 1;
|
||||||
|
this.draggedDot.classList.add('dragging');
|
||||||
|
|
||||||
|
// Store the starting position of the drag
|
||||||
|
this.dragStartPosition = {
|
||||||
|
x: event.clientX,
|
||||||
|
y: event.clientY
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
onDotMouseUp(event) {
|
onDotMouseUp(event) {
|
||||||
if (event.button === 2) {
|
if (event.button === 2) {
|
||||||
if (!event.target.classList.contains('zen-theme-picker-dot')) {
|
if (!event.target.classList.contains('zen-theme-picker-dot')) {
|
||||||
|
@ -311,20 +442,22 @@
|
||||||
this.numberOfDots--;
|
this.numberOfDots--;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.dragging) {
|
if (this.dragging) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
this.dragging = false;
|
this.dragging = false;
|
||||||
this.draggedDot.style.zIndex = 1;
|
this.draggedDot.style.zIndex = 1;
|
||||||
this.draggedDot.classList.remove('dragging');
|
this.draggedDot.classList.remove('dragging');
|
||||||
this.draggedDot = null;
|
this.draggedDot = null;
|
||||||
|
this.dragStartPosition = null; // Reset the drag start position
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.numberOfDots = this.panel.querySelectorAll('.zen-theme-picker-dot').length;
|
this.numberOfDots = this.panel.querySelectorAll('.zen-theme-picker-dot').length;
|
||||||
if (this.numberOfDots < ZenThemePicker.MAX_DOTS) {
|
|
||||||
this.createDot({c:[255, 255, 255]}); // right in the center!
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
themedColors(colors) {
|
themedColors(colors) {
|
||||||
const isDarkMode = this.isDarkMode;
|
const isDarkMode = this.isDarkMode;
|
||||||
const factor = isDarkMode ? 0.5 : 1.1;
|
const factor = isDarkMode ? 0.5 : 1.1;
|
||||||
|
@ -377,7 +510,7 @@
|
||||||
texture,
|
texture,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
//TODO: add a better noise system that adds noise not just changes transparency
|
||||||
updateNoise(texture) {
|
updateNoise(texture) {
|
||||||
const wrapper = document.getElementById('zen-main-app-wrapper');
|
const wrapper = document.getElementById('zen-main-app-wrapper');
|
||||||
wrapper.style.setProperty('--zen-grainy-background-opacity', texture);
|
wrapper.style.setProperty('--zen-grainy-background-opacity', texture);
|
||||||
|
@ -439,7 +572,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const result = this.pSBC(
|
const result = this.pSBC(
|
||||||
this.isDarkMode ? 0.1 : -0.1,
|
this.isDarkMode ? 0.5 : -0.5,
|
||||||
`rgb(${dominantColor[0]}, ${dominantColor[1]}, ${dominantColor[2]})`);
|
`rgb(${dominantColor[0]}, ${dominantColor[1]}, ${dominantColor[2]})`);
|
||||||
return result?.match(/\d+/g).map(Number);
|
return result?.match(/\d+/g).map(Number);
|
||||||
}
|
}
|
||||||
|
@ -461,9 +594,6 @@
|
||||||
|
|
||||||
// get the theme from the window
|
// get the theme from the window
|
||||||
workspaceTheme = theme || windowWorkspace.theme;
|
workspaceTheme = theme || windowWorkspace.theme;
|
||||||
workspaceTheme.gradientColors = workspaceTheme.gradientColors.filter(color =>
|
|
||||||
color.isCustom ? color.c.match(/^#[0-9a-f]{3,8}$/i) : true
|
|
||||||
);
|
|
||||||
|
|
||||||
const appWrapper = browser.document.getElementById('zen-main-app-wrapper');
|
const appWrapper = browser.document.getElementById('zen-main-app-wrapper');
|
||||||
if (!skipUpdate) {
|
if (!skipUpdate) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue