• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
2

Populating SwatchGroup Colors over Panel

Community Beginner ,
Mar 08, 2024 Mar 08, 2024

Copy link to clipboard

Copied

I'm trying to create a script with a dropdown for swatchgroup selection.

layout.png

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

 

TOPICS
How-to , Scripting

Views

155

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

Community Expert , Mar 08, 2024 Mar 08, 2024

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

Votes

Translate

Translate
Adobe
Participant ,
Mar 08, 2024 Mar 08, 2024

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

Screenshot 2024-03-08 at 3.17.03 PM.png

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Mar 08, 2024 Mar 08, 2024

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]);

            }

        }

    };

})();

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Mar 08, 2024 Mar 08, 2024

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. 

screenshot.png

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]);
            }
        }
    };

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Mar 08, 2024 Mar 08, 2024

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

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Mar 08, 2024 Mar 08, 2024

Copy link to clipboard

Copied

Thanks @m1b for the prompt response. Exactly what I wanted.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Mar 08, 2024 Mar 08, 2024

Copy link to clipboard

Copied

LATEST

Great! Hope your project goes well.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines