Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
95a7b03
feat: Integrate new Collage Designer and replace old Generator
dasGOLE Dec 23, 2025
5f4696e
feat: Introduce dedicated Back button component and admin input renderer
dasGOLE Dec 24, 2025
cf9bab1
fixed formatting and removed "from" tag from collage-desginer Button
dasGOLE Dec 24, 2025
e459854
feat: Implement grouped collage layout selection
dasGOLE Dec 27, 2025
695f851
collage-desinger: small fixes
dasGOLE Dec 28, 2025
b3de08f
feat(collage): Adapt layout selection and limit calculation for new d…
dasGOLE Dec 28, 2025
9fd884b
fix rebase missin brace, fix cs and ci
reloxx13 Dec 30, 2025
3bea105
fix ci
reloxx13 Dec 30, 2025
c922ae3
feat: collage-designer:
dasGOLE Dec 30, 2025
70e278b
feat: collage-designer:
dasGOLE Dec 30, 2025
5557123
feat: collage-designer
dasGOLE Dec 30, 2025
4a4668b
feat: collage-designer: added rotation icon from `feathericons.com´
dasGOLE Dec 31, 2025
9cfac37
collage-designer: added alaignment tools
dasGOLE Dec 31, 2025
d7a4f91
collage-desginer: implementation of alaignment tools
dasGOLE Dec 31, 2025
dd7f027
collage-designer: added grouped moving, rotation and scaling.
dasGOLE Dec 31, 2025
4ad4a7b
collage-designer: added functions for distribution buttons
dasGOLE Dec 31, 2025
f93659b
collage-designer: added Undo/Redo Buttons and functionality
dasGOLE Dec 31, 2025
c662636
collage-designer: added Undo/Redo with Keyboard Shortcuts
dasGOLE Dec 31, 2025
5eb29a4
collage-designer: added `add button` for new placeholders and functio…
dasGOLE Jan 2, 2026
ca07015
collage-designer: dynamic loading of demo Img
dasGOLE Jan 4, 2026
2ecbc6a
collage-designer: added functionality for deleting objekts
dasGOLE Jan 4, 2026
4006246
collage-designer: made Handels responsive and added delete icon for m…
dasGOLE Jan 4, 2026
c2be08b
collage-designer: added z-order functions
dasGOLE Jan 4, 2026
a1843e5
collage-designer:
dasGOLE Jan 5, 2026
2b1381c
collage-designer: element-settings-panel: Limit input fields
dasGOLE Jan 5, 2026
420bf2b
collage-designer: removed backspace for removing elements
dasGOLE Jan 5, 2026
ac4d459
collage-designer: changed rotation via mouse to 1° increment
dasGOLE Jan 5, 2026
3a2c0f8
collage-designer: added `lock aspect ratio` funktionality and keep as…
dasGOLE Jan 11, 2026
b86a6d2
collage-designer: refactored img and text specific setting panel.
dasGOLE Jan 12, 2026
14aa8f5
fix dont save admin if no changes
reloxx13 Jan 14, 2026
3b69c12
order en translation
reloxx13 Jan 14, 2026
305d581
add gtRelativePath and deprecate bad function name
reloxx13 Jan 14, 2026
863bf81
fix cs ci
reloxx13 Jan 14, 2026
86f8928
add german translation
reloxx13 Jan 14, 2026
f0f9893
fix button translation
reloxx13 Jan 14, 2026
619018a
translation, fix open designer button
reloxx13 Jan 14, 2026
9ac3d9f
colllage-designer:
dasGOLE Jan 18, 2026
6e233c1
collage-designer: changed the icon for the rotating hover effect
dasGOLE Jan 18, 2026
bb2bbb7
collage-designer: Changes to apply aspect ratio
dasGOLE Jan 18, 2026
6038780
collage-designer: some refactoring
dasGOLE Jan 18, 2026
c480155
collage-designer: added frame functions for single image in collage
dasGOLE Jan 19, 2026
0df31d8
collage-designer:: added placeholder functionallity
dasGOLE Jan 21, 2026
0aab5c5
collage-designer: fix undo / redo for placeholder
dasGOLE Jan 21, 2026
0c65ee8
collage-designer: added text fields
dasGOLE Jan 26, 2026
81ec062
collage-designer: added dynamic found loading
dasGOLE Feb 2, 2026
460c104
collage-designer: fix `selected element` text in element settings panel
dasGOLE Feb 2, 2026
f6b9986
collage-designer: added functions to edit text, textcolor and font
dasGOLE Feb 2, 2026
66e9a92
collage-designer:: added button to toggle the outline of all elements
dasGOLE Feb 2, 2026
40b5764
collage-designer: small changes
dasGOLE Feb 2, 2026
8a38ae2
collage-designer: The DrawCanvas and MouseHandles functions have been…
dasGOLE Feb 2, 2026
ce2ea8f
collage-designer: preview_titel shows selected Layout name.
dasGOLE Feb 2, 2026
4da5002
collage-designer: changed outline behavior of selected elements
dasGOLE Feb 2, 2026
f64be17
collage-designer: cleanup of index.php
dasGOLE Feb 2, 2026
c639420
collage-designer: added effects to the toolbar
dasGOLE Feb 2, 2026
b16f46b
collage-designer: moved `lock_aspect_ratio` to the tools section
dasGOLE Feb 2, 2026
a991f30
collage-designer: rewritten and implemented `general-settings`
dasGOLE Feb 3, 2026
ac33469
collage-designer: fix font loading error
dasGOLE Feb 3, 2026
a33bd10
collage-designer: Added functions to adjust the dimensions of the col…
dasGOLE Feb 4, 2026
c663a1b
collage-designer: Renamed files so that they match the js files
dasGOLE Feb 4, 2026
2eb9eb0
collage-designer: improved robustness of `drawCanvas` -> `draw global…
dasGOLE Feb 4, 2026
b3931c7
collage-designer: massiv refactoring
dasGOLE Feb 4, 2026
d6639f8
collage-designer: removed old collage:generator refrences in new desi…
dasGOLE Feb 4, 2026
adbc593
collage-designer: fix cs ci
dasGOLE Feb 5, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions admin/collage-designer/assets/icons/rotate-ccw.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions admin/collage-designer/assets/icons/trash.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
269 changes: 269 additions & 0 deletions admin/collage-designer/assets/js/collage-designer-elemntSetPnl.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,269 @@
// admin/collage-designer/assets/js/collage-designer-elemntSetPnl.js

document.addEventListener('DOMContentLoaded', () => {
// Basic check to ensure main designer variables/functions are available
// These are expected to be globally exposed by collage-designer.js
if (typeof window.collageCanvas === 'undefined' || typeof window.drawCanvas === 'undefined' ||
typeof window.collageElements === 'undefined' ||
typeof window.saveState === 'undefined' || typeof window.deleteSelectedElements === 'undefined'
) {
console.error('collage-designer-elemntSetPnl.js: Dependent main designer variables/functions not found. Ensure collage-designer.js is loaded first and exposes necessary variables globally.');
return;
}


// --- DOM Elements (Defined once at load) ---
const elementSettingsPanel = document.getElementById('element_settings_panel');
const noElementSelectedMessage = document.getElementById('no_element_selected_message');
const imageSpecificSettingsPanel = document.getElementById('image_specific_settings_panel');
const textSpecificSettingsPanel = document.getElementById('text_specific_settings_panel');

// All other panel input elements should be defined here as well,
// or accessed dynamically inside updateElementSettingsPanel to avoid many global const.
// For now, let's keep them here as they are accessed in setupPanelEventListeners

const elementXPosition = document.getElementById('element_x_position');
const elementXPositionSlider = document.getElementById('element_x_position_slider');
const elementYPosition = document.getElementById('element_y_position');
const elementYPositionSlider = document.getElementById('element_y_position_slider');
const elementWidth = document.getElementById('element_width');
const elementWidthSlider = document.getElementById('element_width_slider');
const elementHeight = document.getElementById('element_height');
const elementHeightSlider = document.getElementById('element_height_slider');
const elementRotation = document.getElementById('element_rotation');
const elementRotationSlider = document.getElementById('element_rotation_slider');

//=================================================================================
// --- Element Settings Panel Management ---
//=================================================================================

/**
* Clamps a percentage value between 0 and 100.
* @param {number} value The value to clamp.
* @returns {number} The clamped value.
*/
function clampPercentage(value) {
return Math.max(0, Math.min(100, value));
}

/**
* Clamps a rotation value between -180 and 180 degrees.
* @param {number} value The value to clamp.
* @returns {number} The clamped value.
*/
function clampRotation(value) {
return Math.max(-180, Math.min(180, value));
}

/**
* Applies a new value to an element property, respecting aspect ratio lock if active.
* This function encapsulates the common logic for updating x, y, width, height, rotation.
* @param {string} prop The property name (e.g., 'width', 'height', 'x', 'y', 'rotation').
* @param {number} rawValue The raw numerical value from the input/slider.
* @param {string} [dimension=''] The canvas dimension relevant for percentage conversion ('width' or 'height').
*/
function applyPanelValueToElement(prop, rawValue, dimension = '') {
if (!window.activeElement) return;

let value = parseFloat(rawValue);
if (isNaN(value)) value = 0;

if (prop === 'rotation') {
value = clampRotation(value);
window.activeElement[prop] = value;
} else {
const canvasDimension = (dimension === 'width') ? window.collageCanvas.width : window.collageCanvas.height;
value = clampPercentage(value); // Clamp percentage value (0-100)
let newDimensionValuePx = (value / 100) * canvasDimension; // Convert to pixel value

if ((prop === 'width' || prop === 'height') && window.globalLockAspectRatio) {
// Use the current aspect ratio of the element for locking
const originalAspectRatio = window.activeElement.width / window.activeElement.height;

if (prop === 'width') {
window.activeElement.width = newDimensionValuePx;
window.activeElement.height = window.activeElement.width / originalAspectRatio;
} else { // prop === 'height'
window.activeElement.height = newDimensionValuePx;
window.activeElement.width = window.activeElement.height * originalAspectRatio;
}

// Clamp both dimensions to canvas limits (pixel values)
window.activeElement.width = Math.max(0.1 * window.collageCanvas.width / 100, Math.min(window.collageCanvas.width, window.activeElement.width));
window.activeElement.height = Math.max(0.1 * window.collageCanvas.height / 100, Math.min(window.collageCanvas.height, window.activeElement.height));

} else {
// Normal behavior without aspect ratio lock
// Ensure minimum size for width/height when not locked (value is already clamped percentage 0-100)
if ((prop === 'width' || prop === 'height') && value <= 0) {
newDimensionValuePx = (0.1 / 100) * canvasDimension; // Convert 0.1% to pixel
}
window.activeElement[prop] = newDimensionValuePx;
}
}
window.drawCanvas(); // Draw after applying value
}

/**
* Updates the element settings panel based on the current selection.
* Deactivates the panel if no or multiple elements are selected.
* Activates and populates the panel if exactly one element is selected.
*/
window.updateElementSettingsPanel = function() {
const selectedElements = window.collageElements.filter(el => el.isSelected);

// Find all interactive elements within the panel (inputs, sliders, buttons)
const interactiveElements = elementSettingsPanel.querySelectorAll(
'input:not([type="checkbox"]), textarea, select, button' // Exclude checkboxes if they should always be active for "lock aspect ratio" etc.
);

if (selectedElements.length === 1 && window.activeElement) {
// Activate panel
elementSettingsPanel.classList.remove('opacity-50', 'pointer-events-none');
interactiveElements.forEach(el => el.disabled = false);
if (noElementSelectedMessage) noElementSelectedMessage.classList.add('hidden'); // Check for existence

const activeEl = window.activeElement;

// Update basic info
document.getElementById('selected_element_type_display').textContent = photoboothTools.getTranslation(selectedElements[0].type);
document.getElementById('selected_element_id_display').textContent = `ID: ${activeEl.id}`;

const canvasWidth = window.collageCanvas.width;
const canvasHeight = window.collageCanvas.height;

// Convert pixel values to percentage for display
const xPercent = (activeEl.x / canvasWidth) * 100;
const yPercent = (activeEl.y / canvasHeight) * 100;
const widthPercent = (activeEl.width / canvasWidth) * 100;
const heightPercent = (activeEl.height / canvasHeight) * 100;

// Update X position
if (elementXPosition) elementXPosition.value = xPercent.toFixed(1);
if (elementXPositionSlider) elementXPositionSlider.value = xPercent.toFixed(1);

// Update Y position
if (elementYPosition) elementYPosition.value = yPercent.toFixed(1);
if (elementYPositionSlider) elementYPositionSlider.value = yPercent.toFixed(1);

// Update Width
if (elementWidth) elementWidth.value = widthPercent.toFixed(1);
if (elementWidthSlider) elementWidthSlider.value = widthPercent.toFixed(1);

// Update Height
if (elementHeight) elementHeight.value = heightPercent.toFixed(1);
if (elementHeightSlider) elementHeightSlider.value = heightPercent.toFixed(1);

// Update Rotation
if (elementRotation) elementRotation.value = activeEl.rotation.toFixed(0);
if (elementRotationSlider) elementRotationSlider.value = activeEl.rotation.toFixed(0);

// --- update specific panels and show / hide them ---
if (activeEl.type === 'image') {
if (window.updateImageSettingsPanel) window.updateImageSettingsPanel();
if (imageSpecificSettingsPanel) imageSpecificSettingsPanel.classList.remove('hidden'); // Jetzt sollte es gehen!
if (textSpecificSettingsPanel) textSpecificSettingsPanel.classList.add('hidden');
} else if (activeEl.type === 'text') {
if (window.updateTextSettingsPanel) window.updateTextSettingsPanel();
if (textSpecificSettingsPanel) textSpecificSettingsPanel.classList.remove('hidden');
if (imageSpecificSettingsPanel) imageSpecificSettingsPanel.classList.add('hidden');
} else {
// Typ unbekannt oder kein spezifisches Panel
if (imageSpecificSettingsPanel) imageSpecificSettingsPanel.classList.add('hidden');
if (textSpecificSettingsPanel) textSpecificSettingsPanel.classList.add('hidden');
}

} else {
// none or multiple elements selected
elementSettingsPanel.classList.add('opacity-50', 'pointer-events-none');
interactiveElements.forEach(el => el.disabled = true);

// Clear basic info
document.getElementById('selected_element_type_display').textContent = '';
document.getElementById('selected_element_id_display').textContent = 'ID: ';

// hide all specific panels
if (noElementSelectedMessage) noElementSelectedMessage.classList.remove('hidden'); // Check for existence
if (imageSpecificSettingsPanel) imageSpecificSettingsPanel.classList.add('hidden');
if (textSpecificSettingsPanel) textSpecificSettingsPanel.classList.add('hidden');
}
};

/**
* Sets up event listeners for the element settings panel inputs.
*/
function setupPanelEventListeners() {
const inputs = [
{ id: 'element_x_position', sliderId: 'element_x_position_slider', prop: 'x', dimension: 'width' },
{ id: 'element_y_position', sliderId: 'element_y_position_slider', prop: 'y', dimension: 'height' },
{ id: 'element_width', sliderId: 'element_width_slider', prop: 'width', dimension: 'width' },
{ id: 'element_height', sliderId: 'element_height_slider', prop: 'height', dimension: 'height' },
{ id: 'element_rotation', sliderId: 'element_rotation_slider', prop: 'rotation' }
];

inputs.forEach(({ id, sliderId, prop, dimension }) => {
const numberInput = document.getElementById(id);
const sliderInput = document.getElementById(sliderId);

let isChanging = false; // Flag to prevent redundant saveState calls during continuous slider drag

if (numberInput) {
numberInput.addEventListener('change', (event) => {
if (!window.activeElement) return;
window.saveState(); // Save state on change for number input

applyPanelValueToElement(prop, event.target.value, dimension);

/// Update corresponding slider
if (sliderInput) {
sliderInput.value = (prop === 'rotation') ? window.activeElement[prop].toFixed(0) :
((window.activeElement[prop] / ((dimension === 'width') ? window.collageCanvas.width : window.collageCanvas.height)) * 100).toFixed(1);
}

window.updateElementSettingsPanel(); // Re-populate to ensure consistency and handle potential rounding
});
}

if (sliderInput) {
sliderInput.addEventListener('mousedown', () => {
if (!window.activeElement) return;
window.saveState(); // Save state at the start of slider drag
isChanging = true;
});

sliderInput.addEventListener('input', (event) => {
if (!window.activeElement || !isChanging) return; // Only update if actively dragging

applyPanelValueToElement(prop, event.target.value, dimension);

// Update corresponding number input
if (numberInput) {
numberInput.value = (prop === 'rotation') ? window.activeElement[prop].toFixed(0) :
((window.activeElement[prop] / ((dimension === 'width') ? window.collageCanvas.width : window.collageCanvas.height)) * 100).toFixed(1);
}
});

sliderInput.addEventListener('mouseup', () => {
if (!window.activeElement) return;
isChanging = false;
// A final draw and panel update ensures consistency after drag ends
window.drawCanvas();
window.updateElementSettingsPanel(); // Re-populate to fix minor floating point inaccuracies
});
}
});

// Event listener for the delete button inside the panel
const deleteElementBtn = document.getElementById('panelDeleteElementBtn');
if (deleteElementBtn) {
deleteElementBtn.addEventListener('click', () => {
if (window.activeElement) {
window.deleteSelectedElements();
}
});
}
}

// Initialize panel event listeners once the DOM is ready
setupPanelEventListeners();
});
Loading
Loading