Copy link to clipboard
Copied
I'm trying to create a script with a dropdown for swatchgroup selection.
All included colors should be displayed over the panel as small icons below the dropdown once a swatch group is selected. This should get changed on each dropdown change.
Not sure if this is even possible. I'm quite new to javascript and not sure how to get color box (small color icons over the panel) to render on dropdown change.
With the help of AI, I have managed the layout but cannot make it work for rendering colors over the panel.
var colorGroups = [];
var parentFolderPath = null;
var fileName = null;
var doc = app.activeDocument;
var swatchGroups = doc.swatchGroups;
// Get color groups
for (var j = 0; j < swatchGroups.length; j++) {
var currentGroup = swatchGroups[j];
colorGroups.push(currentGroup.name);
}
// Create dialog window
var dialog = new Window("dialog", "Color Group Selection");
dialog.preferredSize.width = 380; // Set width to 380 pixels
// Add panel for export options
var exportPanel = dialog.add("panel", undefined, "Export Options");
exportPanel.alignment = "left";
exportPanel.preferredSize.width = 380; // Set width to 380 pixels
// Add dropdown for color group selection
var colorGroupDropdown = exportPanel.add("dropdownlist", undefined, colorGroups);
colorGroupDropdown.selection = 0;
colorGroupDropdown.size = [300, 20]; // Set size of the dropdown
// Add panel for color boxes
var colorBoxGroup = exportPanel.add("panel", undefined, "");
colorBoxGroup.orientation = "row";
colorBoxGroup.size = [300, 20]; // Set initial size of the color box group
// Add button to close the panel
var closeButton = exportPanel.add("button", undefined, "Close");
closeButton.size = [80, 25]; // Set size of the button
// Function to update color boxes based on the selected swatch group
function updateColorBoxes() {
var selectedGroupIndex = colorGroupDropdown.selection.index;
var selectedGroup = swatchGroups[selectedGroupIndex];
var swatches = selectedGroup.getAllSwatches();
var totalColors = swatches.length;
// Clear existing color boxes
while (colorBoxGroup.children.length > 0) {
colorBoxGroup.remove(colorBoxGroup.children[0]);
}
// Calculate the width of each color box
var totalWidth = 300; // Total width available for color boxes
var numColors = swatches.length; // Total number of colors
var colorBoxWidth = totalWidth / numColors; // Calculate the width of each color box
// Create color boxes for each swatch
for (var i = 0; i < swatches.length; i++) {
var swatch = swatches[i];
var colorBox = colorBoxGroup.add("panel", undefined, "");
colorBox.size = [colorBoxWidth, 20]; // Set the width and height of the color box
// Get the swatch color components and normalize them
var red = swatch.color.red / 255; // Normalize red component
var green = swatch.color.green / 255; // Normalize green component
var blue = swatch.color.blue / 255; // Normalize blue component
// Ensure the color values are within the range [0, 1]
red = Math.max(0, Math.min(1, red));
green = Math.max(0, Math.min(1, green));
blue = Math.max(0, Math.min(1, blue));
// Create a new ScriptUI RGBColor object
var rgbColor = new RGBColor();
rgbColor.red = red * 255; // Scale to [0, 255]
rgbColor.green = green * 255; // Scale to [0, 255]
rgbColor.blue = blue * 255; // Scale to [0, 255]
// Set the background color of the color box
colorBox.graphics.backgroundColor = rgbColor;
}
}
// Add event listener to colorGroupDropdown
colorGroupDropdown.onChange = updateColorBoxes;
// Close button click event handler
closeButton.onClick = function () {
dialog.close();
};
// Call the function initially to populate the color boxes
updateColorBoxes();
// Display dialog window
dialog.show();
That's a really good attempt! It turns out that there's a method for converting colors, which is perfect for this:
function createColorBoxes(container, swatchGroups) {
for (var g = 0; g < swatchGroups.length; g++) {
var swatches = swatchGroups[g].getAllSwatches();
// Calculate the width of each color box
var numColors = swatches.length; // Total number of colors
var colorBoxWidth = COLOR_GROUP_WIDTH / numColors; // Calculate the width of each color box
...
Copy link to clipboard
Copied
I am not sure if what you are trying to do is possible, but to add my two cents. in order to add color you will need to change your code where you set the background color to this.
colorBox.graphics.backgroundColor = dialog.graphics.newBrush (dialog.graphics.BrushType.SOLID_COLOR,[red, blue, green, 1]);
ScriptUI (as far as I know) does not read normal values. it reads a 0-1 value for color. some of what you are doing is not necessary for this as youre converting 255 down to 0-1 then back to 255 range.
Other notes of the code.
it looks like youre looping through your swatches and not just the swatches in a group and you have no method of handling errors. so when you encounter the first swatch in your list, which is a NoColor swatch. it will most likely error out and not go any further. the same will happen for a CMYK and non-RGB swatches as the script tries to gather data that it doesnt have. So you will probably need a method of converting non-RGB Swatches to RGB for reading or to skip them entirely.
The dialog has the default spacing on it, so i would change the spacing on the group and have it be something small like 0 or 1.
I was not able to get the swatches to update after changing the dropdown. maybe do-able by using visibility and hiding stuff, but didn't spend a lot of time looking into it.
due to the length of swatches and the size of the dialog. if you have more than a handful of swatches the swatch boxes become impossibly small since you are dividing the total area to generate the width of the boxes. might want to figure a method that will do X number then create a new row of them
Copy link to clipboard
Copied
Hi @Tess Robinson, another approach is to draw all the colorBoxes first, and place them in a "stack". Then the update function just sets the visible of each group of boxes. See below for very rough idea.
- Mark
(function () {
const DIALOG_WIDTH = 380;
const COLOR_GROUP_WIDTH = DIALOG_WIDTH - 80; // Total width available for color boxes
var colorGroups = [];
var parentFolderPath = null;
var fileName = null;
var doc = app.activeDocument;
var swatchGroups = doc.swatchGroups;
// Get color groups
for (var j = 0; j < swatchGroups.length; j++) {
colorGroups.push(swatchGroups[j].name);
}
// Create dialog window
var dialog = new Window("dialog", "Color Group Selection");
dialog.preferredSize.width = DIALOG_WIDTH; // Set width to 380 pixels
// Add panel for export options
var exportPanel = dialog.add("panel", undefined, "Export Options");
exportPanel.alignment = "left";
exportPanel.preferredSize.width = DIALOG_WIDTH
// Add dropdown for color group selection
var colorGroupDropdown = exportPanel.add("dropdownlist", undefined, colorGroups);
colorGroupDropdown.selection = 0;
colorGroupDropdown.size = [300, 20]; // Set size of the dropdown
var colorStack = exportPanel.add("Group {orientation:'stack', alignment:['fill','fill']}");
colorStack.size = [300, 20]; // Set initial size of the color box group
// Add button to close the panel
var closeButton = dialog.add("button", undefined, "Close");
closeButton.size = [80, 24]; // Set size of the button
// Add event listener to colorGroupDropdown
colorGroupDropdown.onChange = updateColorBoxes;
// Close button click event handler
closeButton.onClick = function () {
dialog.close();
};
// create the color boxes
createColorBoxes(colorStack, doc.swatchGroups);
// Call the function initially to populate the color boxes
updateColorBoxes();
// Display dialog window
dialog.show();
// Function to update color boxes based on the selected swatch group
function updateColorBoxes() {
var activeStack = colorGroupDropdown.selection.index;
for (var i = 0; i < colorStack.children.length; i++) {
colorStack.children[i].visible = activeStack === i ? true : false;
}
colorStack.layout.layout(true);
};
function createColorBoxes(container, swatchGroups) {
for (var g = 0; g < swatchGroups.length; g++) {
var swatches = swatchGroups[g].getAllSwatches();
// Calculate the width of each color box
var numColors = swatches.length; // Total number of colors
var colorBoxWidth = COLOR_GROUP_WIDTH / numColors; // Calculate the width of each color box
var stackedItem = container.add("Group {orientation:'row', alignment:['fill','top'], alignChildren: ['left','top'], properties: { margins:[0,0,0,0] }}");
// Create color boxes for each swatch
for (var i = 0; i < swatches.length; i++) {
var col = swatches[i].color;
if ('NoColor' === col.constructor.name)
continue;
else if ('SpotColor' === col.constructor.name)
col = col.spot.color;
if ('RGBColor' !== col.constructor.name)
continue;
var colorBox = stackedItem.add("Group { properties: { margins:[0,0,0,0] } }");
colorBox.preferredSize = [Math.max(colorBoxWidth, 10), 20]; // Set the width and height of the color box
// colorBox.preferredSize = [colorBoxWidth, 20];
// Get the swatch color components and normalize them
var red = col.red / 255; // Normalize red component
var green = col.green / 255; // Normalize green component
var blue = col.blue / 255; // Normalize blue component
// Set the background color of the color box
colorBox.graphics.backgroundColor = dialog.graphics.newBrush(dialog.graphics.BrushType.SOLID_COLOR, [red, green, blue, 1]);
}
}
};
})();
Copy link to clipboard
Copied
Perfect @m1b. Working perfectly in RGB. Thank you so much.
I have made a small adjustment to make it work for CMYK as well but the conversion is a bit off.
Is there any way to make it better?
function createColorBoxes(container, swatchGroups) {
for (var g = 0; g < swatchGroups.length; g++) {
var swatches = swatchGroups[g].getAllSwatches();
// Calculate the width of each color box
var numColors = swatches.length; // Total number of colors
var colorBoxWidth = COLOR_GROUP_WIDTH / numColors; // Calculate the width of each color box
var stackedItem = container.add("Group {orientation:'row', alignment:['fill','top'], alignChildren: ['left','top'], properties: { margins:[0,0,0,0] }}");
// Create color boxes for each swatch
for (var i = 0; i < swatches.length; i++) {
var col = swatches[i].color;
// Check for NoColor swatch and skip
if (col.typename === 'NoColor') continue;
// Handle SpotColor swatches
if (col.typename === 'SpotColor') {
col = col.spot.color;
}
// Handle CMYKColor swatches
if (col.typename === 'CMYKColor') {
// Convert CMYK color to RGB color with gamma correction
var red = 1 - (Math.min(1, col.cyan / 100 * (1 - col.black / 100) + col.black / 100));
var green = 1 - (Math.min(1, col.magenta / 100 * (1 - col.black / 100) + col.black / 100));
var blue = 1 - (Math.min(1, col.yellow / 100 * (1 - col.black / 100) + col.black / 100));
} else if (col.typename === 'RGBColor') {
var red = col.red / 255;
var green = col.green / 255;
var blue = col.blue / 255;
} else {
continue; // Skip other color types
}
var colorBox = stackedItem.add("Group { properties: { margins:[0,0,0,0] } }");
colorBox.preferredSize = [Math.max(colorBoxWidth, 10), 20]; // Set the width and height of the color box
// Set the background color of the color box
colorBox.graphics.backgroundColor = dialog.graphics.newBrush(dialog.graphics.BrushType.SOLID_COLOR, [red, green, blue, 1]);
}
}
};
Copy link to clipboard
Copied
That's a really good attempt! It turns out that there's a method for converting colors, which is perfect for this:
function createColorBoxes(container, swatchGroups) {
for (var g = 0; g < swatchGroups.length; g++) {
var swatches = swatchGroups[g].getAllSwatches();
// Calculate the width of each color box
var numColors = swatches.length; // Total number of colors
var colorBoxWidth = COLOR_GROUP_WIDTH / numColors; // Calculate the width of each color box
var stackedItem = container.add("Group {orientation:'row', alignment:['fill','top'], alignChildren: ['left','top'], properties: { margins:[0,0,0,0] }}");
// Create color boxes for each swatch
for (var i = 0; i < swatches.length; i++) {
var col = swatches[i].color;
if ('NoColor' === col.constructor.name)
continue;
else if ('SpotColor' === col.constructor.name)
col = col.spot.color;
if (
'RGBColor' !== col.constructor.name
&& 'CMYKColor' !== col.constructor.name
)
// skip other color types
continue;
var colorBox = stackedItem.add("Group { properties: { margins:[0,0,0,0] } }");
colorBox.preferredSize = [Math.max(colorBoxWidth, 10), 20]; // Set the width and height of the color box
var red, green, blue;
if ('CMYKColor' === col.constructor.name) {
var rgb = app.convertSampleColor(ImageColorSpace.CMYK, [col.cyan, col.magenta, col.yellow, col.black], ImageColorSpace.RGB, ColorConvertPurpose.defaultpurpose);
red = rgb[0] / 255;
green = rgb[1] / 255;
blue = rgb[2] / 255;
}
else if ('RGBColor' === col.constructor.name) {
// Get the swatch color components and normalize them
red = col.red / 255; // Normalize red component
green = col.green / 255; // Normalize green component
blue = col.blue / 255; // Normalize blue component
}
// Set the background color of the color box
colorBox.graphics.backgroundColor = dialog.graphics.newBrush(dialog.graphics.BrushType.SOLID_COLOR, [red, green, blue, 1]);
}
}
};
I just mocked up the `CreateColorBoxes` function so you could get an idea of how to implement, but you can do it how ever you prefer.
- Mark
Copy link to clipboard
Copied
Thanks @m1b for the prompt response. Exactly what I wanted.
Copy link to clipboard
Copied
Great! Hope your project goes well.