Skip to main content
Known Participant
July 26, 2025
Answered

Is it possible to get a preview button on an panel?

  • July 26, 2025
  • 2 replies
  • 344 views

Hello, I have a script for making guides, and would like to have a preview button similar to InDesign where you can see a preview. 

I not sure if someone has all araboards that having a preview for all would run fast enough... so would it better to show only one artboard previewed... not sure 

 

Anyhow the larger problem is what is the starting point for adding previews features. 

 

Below is a sreenshot if the interface which is pretty self expanator 

 

 

 

/**
 * Illustrator Margins, Grid & Baseline Script [Mac-Ready]
 * No ES6 code—fully ExtendScript compatible. Tested on Mac.
 */

var settingsXMLPath = Folder.myDocuments + "/IllustratorGridSettings.xml";

// --- XML functions (Modified to handle raw string values) ---
function loadSettingsFromXML(xmlFilePath, abIdx, defaults) {
    // Helper to convert default numbers to strings with units
    function stringifyDefaults(defaultsObj) {
        var stringDefaults = {};
        for (var key in defaultsObj) {
            if (defaultsObj.hasOwnProperty(key)) {
                if (key === "BaselineInc") {
                    // Baseline increment defaults to points
                    stringDefaults[key] = defaultsObj[key].toString() + "pt";
                } else if (key === "Columns" || key === "Rows") {
                    // Numbers only, no units
                    stringDefaults[key] = defaultsObj[key].toString();
                } else {
                    // Everything else defaults to mm
                    stringDefaults[key] = defaultsObj[key].toString() + "mm";
                }
            }
        }
        return stringDefaults;
    }

    var file = new File(xmlFilePath);
    if (!file.exists) return stringifyDefaults(defaults);
    
    file.open('r');
    var content = file.read();
    file.close();
    
    var abTag = new RegExp('<Artboard index="' + abIdx + '">([\\s\\S]*?)<\\/Artboard>');
    var found = content.match(abTag);
    
    if (found) {
        var vals = {};
        var tags = ["Top","Bottom","Left","Right","Columns","Rows","VertGutter","HorGutter","BaselineStart","BaselineInc"];
        for (var i = 0; i < tags.length; i++) {
            var tagName = tags[i];
            var tagRegex = new RegExp('<' + tagName + '>([\\s\\S]*?)<\\/' + tagName + '>');
            var tagMatch = found[1].match(tagRegex);
            
            if (tagMatch) {
                vals[tagName] = tagMatch[1];
            } else {
                // Apply default with appropriate unit
                if (tagName === "BaselineInc") {
                    vals[tagName] = defaults[tagName].toString() + "pt";
                } else if (tagName === "Columns" || tagName === "Rows") {
                    vals[tagName] = defaults[tagName].toString();
                } else {
                    vals[tagName] = defaults[tagName].toString() + "mm";
                }
            }
        }
        return vals;
    }
    
    return stringifyDefaults(defaults);
}

function saveSettingsToXML(xmlFilePath, abIdx, newVals) {
    var file = new File(xmlFilePath);
    var xmlContent = '';
    if (file.exists) {
        file.open('r');
        xmlContent = file.read();
        file.close();
    }
    var abTag = new RegExp('<Artboard index="' + abIdx + '">([\\s\\S]*?)<\\/Artboard>','g');
    xmlContent = xmlContent.replace(abTag, '');
    var abXML = '  <Artboard index="' + abIdx + '">\n';
    for (var key in newVals) {
        var value = newVals[key].toString().replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
        abXML += '    <' + key + '>' + value + '</' + key + '>\n';
    }
    abXML += '  </Artboard>\n';
    if (xmlContent.indexOf('<GridSettings>') === -1) {
        xmlContent = '<GridSettings>\n' + abXML + '</GridSettings>';
    } else {
        xmlContent = xmlContent.replace('</GridSettings>', abXML + '</GridSettings>');
    }
    file.open('w');
    file.write(xmlContent);
    file.close();
}

// --- Helpers ---
function mmToPt(mm) { return mm * 2.83465; }
function ptToMm(pt) { return pt / 2.83465; }
function makeRGB(r, g, b) {
    var color = new RGBColor();
    color.red = r; color.green = g; color.blue = b;
    return color;
}
function findLayer(doc, name) {
    for (var i = 0; i < doc.layers.length; i++) {
        if (doc.layers[i].name === name) return doc.layers[i];
    }
    return null;
}
function deleteLayerByExactName(doc, name) {
    for (var i = doc.layers.length - 1; i >= 0; i--) {
        if (doc.layers[i].name === name) {
            doc.layers[i].locked = false;
            doc.layers[i].visible = true;
            doc.layers[i].remove();
        }
    }
}
function removePathsForArtboard(layer, abIdx) {
    var abTag = " ab" + abIdx + " ";
    for (var i = layer.pathItems.length - 1; i >= 0; i--) {
        var p = layer.pathItems[i];
        if (p.note && p.note.indexOf(abTag) === 0) p.remove();
    }
}

// --- Enhanced Unit Parsing Functions with Default Unit Addition ---
function parseValueWithUnit(inputStr) {
    if (typeof inputStr !== 'string') {
        inputStr = String(inputStr);
    }
    
    inputStr = inputStr.replace(/\s/g, '');
    var match = inputStr.match(/^(-?\d*\.?\d+)([a-zA-Z%]*)$/);
    
    if (!match) {
        var num = parseFloat(inputStr);
        return isNaN(num) ? NaN : mmToPt(num);
    }
    
    var value = parseFloat(match[1]);
    var unit = match[2].toLowerCase();
    
    if (isNaN(value)) return NaN;
    
    switch (unit) {
        case '':
        case 'mm':
            return mmToPt(value);
        case 'cm':
            return mmToPt(value * 10);
        case 'in':
        case 'inch':
            return value * 72;
        case 'pt':
        case 'point':
            return value;
        case 'px':
        case 'pixel':
            var doc = app.activeDocument;
            if (doc.rulerUnits == RulerUnits.Pixels) {
                return value;
            } else {
                return value * 0.75;
            }
        case 'pc':
        case 'pica':
            return value * 12;
        default:
            return mmToPt(value);
    }
}

function parseValueWithUnitPt(inputStr) {
    return parseValueWithUnit(inputStr);
}

// --- Helper function to add default units to user input ---
function addDefaultUnit(inputStr, fieldType) {
    if (typeof inputStr !== 'string') {
        inputStr = String(inputStr);
    }
    
    inputStr = inputStr.replace(/\s/g, '');
    var match = inputStr.match(/^(-?\d*\.?\d+)([a-zA-Z%]*)$/);
    
    if (match && match[2] === '') {
        // No unit specified, add appropriate default
        if (fieldType === "baseline") {
            return inputStr + "pt";
        } else if (fieldType === "number") {
            return inputStr; // Columns/Rows don't need units
        } else {
            return inputStr + "mm"; // Default for margins and gutters
        }
    }
    
    // Unit already specified or invalid input, return as-is
    return inputStr;
}

// --- Guide Creation (works directly with points) ---
function addMarginsAndColumnsToLayer(layer, ab, abIdx, top_pt, bottom_pt, left_pt, right_pt, columns, vertGutter_pt, rows, horGutter_pt) {
    var rect = ab.artboardRect;
    var left = rect[0], top = rect[1], right = rect[2], bottom = rect[3];
    var width = right - left, height = top - bottom;
    var abTag = " ab" + abIdx + " ";
    
    var path = layer.pathItems.rectangle(top - top_pt, left + left_pt, width - left_pt - right_pt, height - top_pt - bottom_pt);
    path.stroked = true; path.strokeColor = makeRGB(224, 0, 255); path.strokeWidth = 0.1; path.filled = false; path.guides = true; path.note = abTag + "margin";
    
    var gridColor = makeRGB(0, 176, 255);
    if (columns > 1) {
        var usableWidth = width - left_pt - right_pt;
        var colWidth = (usableWidth - (columns - 1) * vertGutter_pt) / columns;
        var x = left + left_pt;
        for (var c = 0; c < columns - 1; c++) {
            x += colWidth;
            var vGuide1 = layer.pathItems.add();
            vGuide1.setEntirePath([[x, top - top_pt], [x, bottom + bottom_pt]]);
            vGuide1.stroked = true; vGuide1.strokeColor = gridColor; vGuide1.strokeWidth = 0.1; vGuide1.filled = false; vGuide1.guides = true; vGuide1.note = abTag + "colg";
            x += vertGutter_pt;
            var vGuide2 = layer.pathItems.add();
            vGuide2.setEntirePath([[x, top - top_pt], [x, bottom + bottom_pt]]);
            vGuide2.stroked = true; vGuide2.strokeColor = gridColor; vGuide2.strokeWidth = 0.1; vGuide2.filled = false; vGuide2.guides = true; vGuide2.note = abTag + "colg";
        }
    }
    
    if (rows > 1) {
        var usableHeight = height - top_pt - bottom_pt;
        var rowHeight = (usableHeight - (rows - 1) * horGutter_pt) / rows;
        var y = top - top_pt;
        for (var r = 0; r < rows - 1; r++) {
            y -= rowHeight;
            var hGuide1 = layer.pathItems.add();
            hGuide1.setEntirePath([[left + left_pt, y], [right - right_pt, y]]);
            hGuide1.stroked = true; hGuide1.strokeColor = gridColor; hGuide1.strokeWidth = 0.1; hGuide1.filled = false; hGuide1.guides = true; hGuide1.note = abTag + "rowg";
            y -= horGutter_pt;
            var hGuide2 = layer.pathItems.add();
            hGuide2.setEntirePath([[left + left_pt, y], [right - right_pt, y]]);
            hGuide2.stroked = true; hGuide2.strokeColor = gridColor; hGuide2.strokeWidth = 0.1; hGuide2.filled = false; hGuide2.guides = true; hGuide2.note = abTag + "rowg";
        }
    }
}

// --- ENHANCED: Baseline Grid Creation (now handles 0 increment gracefully) ---
function addBaselineGridToLayer(layer, ab, abIdx, top_pt, bottom_pt, left_pt, right_pt, baselineStart_pt, baselineInc_pt) {
    // If baseline increment is 0, skip creating baseline guides entirely
    if (baselineInc_pt <= 0) {
        return; // Exit function without creating any baseline guides
    }
    
    var rect = ab.artboardRect;
    var left = rect[0], top = rect[1], right = rect[2], bottom = rect[3];
    var abTag = " ab" + abIdx + " ";
    var y0 = top - top_pt - baselineStart_pt;
    var yEnd = bottom + bottom_pt;
    while (y0 > yEnd) {
        var line = layer.pathItems.add();
        line.setEntirePath([[left + left_pt, y0], [right - right_pt, y0]]);
        line.stroked = true; line.strokeColor = makeRGB(80, 80, 80); line.strokeWidth = 0.05; line.filled = false; line.guides = true; line.note = abTag + "baseline";
        y0 -= baselineInc_pt;
    }
}

// --- UI Dialog (IMPROVED LAYOUT) ---
function showMarginsDialog() {
    if (app.documents.length === 0) { alert("Please open a document first."); return; }
    var doc = app.activeDocument;
    var abIdx = doc.artboards.getActiveArtboardIndex();
    var defaults = {
        Top:12.7, Bottom:12.7, Left:12.7, Right:12.7, Columns:2, Rows:2,
        VertGutter:4.233, HorGutter:4.233, BaselineStart:0, BaselineInc:12
    };
    var settings = loadSettingsFromXML(settingsXMLPath, abIdx, defaults);

    // Create a wider dialog with better spacing
    var w = new Window("dialog", "Margins, Grid & Baseline (for Artboard " + (abIdx + 1) + ")");
    w.orientation = "column";
    w.alignChildren = "fill";
    w.spacing = 15;
    w.margins = 20;

    // MARGINS PANEL - wider layout with more space
    var marginPanel = w.add("panel", undefined, "Margins");
    marginPanel.orientation = "column";
    marginPanel.alignChildren = "fill";
    marginPanel.margins = 15;
    marginPanel.spacing = 10;
    
    var mRow1 = marginPanel.add("group");
    mRow1.orientation = "row";
    mRow1.alignChildren = "center";
    mRow1.spacing = 10;
    mRow1.add("statictext", undefined, "Top:").preferredSize.width = 60;
    var topInput = mRow1.add("edittext", undefined, settings.Top);
    topInput.preferredSize.width = 80;
    mRow1.add("statictext", undefined, "Left:").preferredSize.width = 60;
    var leftInput = mRow1.add("edittext", undefined, settings.Left);
    leftInput.preferredSize.width = 80;
    
    var mRow2 = marginPanel.add("group");
    mRow2.orientation = "row";
    mRow2.alignChildren = "center";
    mRow2.spacing = 10;
    mRow2.add("statictext", undefined, "Bottom:").preferredSize.width = 60;
    var bottomInput = mRow2.add("edittext", undefined, settings.Bottom);
    bottomInput.preferredSize.width = 80;
    mRow2.add("statictext", undefined, "Right:").preferredSize.width = 60;
    var rightInput = mRow2.add("edittext", undefined, settings.Right);
    rightInput.preferredSize.width = 80;

    // GRID PANEL - better organized layout
    var gridPanel = w.add("panel", undefined, "Grid");
    gridPanel.orientation = "column";
    gridPanel.alignChildren = "fill";
    gridPanel.margins = 15;
    gridPanel.spacing = 10;
    
    var gRow1 = gridPanel.add("group");
    gRow1.orientation = "row";
    gRow1.alignChildren = "center";
    gRow1.spacing = 10;
    gRow1.add("statictext", undefined, "Columns:").preferredSize.width = 80;
    var colInput = gRow1.add("edittext", undefined, settings.Columns);
    colInput.preferredSize.width = 60;
    gRow1.add("statictext", undefined, "Vertical Gutter:").preferredSize.width = 100;
    var vertGutterInput = gRow1.add("edittext", undefined, settings.VertGutter);
    vertGutterInput.preferredSize.width = 80;
    
    var gRow2 = gridPanel.add("group");
    gRow2.orientation = "row";
    gRow2.alignChildren = "center";
    gRow2.spacing = 10;
    gRow2.add("statictext", undefined, "Rows:").preferredSize.width = 80;
    var rowInput = gRow2.add("edittext", undefined, settings.Rows);
    rowInput.preferredSize.width = 60;
    gRow2.add("statictext", undefined, "Horizontal Gutter:").preferredSize.width = 100;
    var horGutterInput = gRow2.add("edittext", undefined, settings.HorGutter);
    horGutterInput.preferredSize.width = 80;

    // BASELINE PANEL - cleaner layout
    var basePanel = w.add("panel", undefined, "Baseline Grid");
    basePanel.orientation = "row";
    basePanel.alignChildren = "center";
    basePanel.margins = 15;
    basePanel.spacing = 10;
    basePanel.add("statictext", undefined, "Start:").preferredSize.width = 80;
    var baselineStartInput = basePanel.add("edittext", undefined, settings.BaselineStart);
    baselineStartInput.preferredSize.width = 80;
    basePanel.add("statictext", undefined, "Increment:").preferredSize.width = 80;
    var baselineIncInput = basePanel.add("edittext", undefined, settings.BaselineInc);
    baselineIncInput.preferredSize.width = 80;

    // APPLY TO ALL CHECKBOX
    var applyAllGroup = w.add("group");
    applyAllGroup.margins = [0, 10, 0, 0];
    var applyAllChk = applyAllGroup.add("checkbox", undefined, "Apply to all artboards");
    applyAllChk.value = (doc.artboards.length === 1);

    // BUTTONS - better spacing
    var btnGroup = w.add("group");
    btnGroup.orientation = "row";
    btnGroup.alignment = "right";
    btnGroup.spacing = 10;
    btnGroup.margins = [0, 15, 0, 0];
    var cancelBtn = btnGroup.add("button", undefined, "Cancel", { name: "cancel" });
    var okBtn = btnGroup.add("button", undefined, "OK", { name: "ok" });
    cancelBtn.preferredSize.width = 80;
    okBtn.preferredSize.width = 80;

    okBtn.onClick = function() {
        var top_pt = parseValueWithUnit(topInput.text), bottom_pt = parseValueWithUnit(bottomInput.text),
            left_pt = parseValueWithUnit(leftInput.text), right_pt = parseValueWithUnit(rightInput.text),
            cols = parseInt(colInput.text), rows = parseInt(rowInput.text),
            vertGutter_pt = parseValueWithUnit(vertGutterInput.text), horGutter_pt = parseValueWithUnit(horGutterInput.text),
            baselineStart_pt = parseValueWithUnit(baselineStartInput.text), baselineInc_pt = parseValueWithUnitPt(baselineIncInput.text);

        // --- ENHANCED VALIDATION: Allow 0 for baseline increment ---
        if (isNaN(top_pt) || isNaN(bottom_pt) || isNaN(left_pt) || isNaN(right_pt) || 
            isNaN(cols) || isNaN(rows) || 
            isNaN(vertGutter_pt) || isNaN(horGutter_pt) || 
            isNaN(baselineStart_pt) || isNaN(baselineInc_pt) ||
            top_pt < 0 || bottom_pt < 0 || left_pt < 0 || right_pt < 0 ||
            cols < 0 || rows < 0 ||
            vertGutter_pt < 0 || horGutter_pt < 0 ||
            baselineInc_pt < 0) { // Changed from baselineInc_pt <= 0 to baselineInc_pt < 0
            alert("Please enter valid (non-negative) numbers. Baseline increment can be 0 to skip baseline grid.");
            return;
        }
        
        function checkGridFit(abIdx, t_pt, b_pt, l_pt, r_pt, c, r, vg_pt, hg_pt) {
            var rect = doc.artboards[abIdx].artboardRect;
            var artW = rect[2] - rect[0] - l_pt - r_pt; var artH = rect[1] - rect[3] - t_pt - b_pt;
            var minW = mmToPt(1), minH = mmToPt(1);
            var failCol = false, failRow = false;
            if (c > 1) {
                var gutW = (c - 1) * vg_pt;
                if (artW <= gutW || (artW - gutW)/c < minW) { failCol = true; }
            }
            if (r > 1) {
                var gutH = (r - 1) * hg_pt;
                if (artH <= gutH || (artH - gutH)/r < minH) { failRow = true; }
            }
            return {failCol: failCol, failRow: failRow};
        }
        
        var abIndices = [];
        if (applyAllChk.value) { for (var i = 0; i < doc.artboards.length; i++) abIndices.push(i); } else { abIndices.push(abIdx); }
        
        var vertGutterOverride = {}, horGutterOverride = {};
        var warnedCol = false, warnedRow = false;
        for (var i = 0; i < abIndices.length; i++) {
            var check = checkGridFit(abIndices[i], top_pt, bottom_pt, left_pt, right_pt, cols, rows, vertGutter_pt, horGutter_pt);
            if (check.failCol) {
                if (!warnedCol) { alert("Column/gutter combination doesn't fit on at least one artboard. Vertical gutter is reset to default."); warnedCol = true; }
                vertGutterOverride[abIndices[i]] = mmToPt(defaults.VertGutter);
            }
            if (check.failRow) {
                if (!warnedRow) { alert("Row/gutter combination doesn't fit on at least one artboard. Horizontal gutter is reset to default."); warnedRow = true; }
                horGutterOverride[abIndices[i]] = mmToPt(defaults.HorGutter);
            }
        }

        // --- ENHANCED LAYER MANAGEMENT: Handle baseline layer conditionally ---
        if (applyAllChk.value) {
            deleteLayerByExactName(doc, "Margins and Columns");
            // Only delete baseline layer if we're going to recreate it
            if (baselineInc_pt > 0) {
                deleteLayerByExactName(doc, "Baseline");
            }
        }
        
        var marginsLayer = findLayer(doc, "Margins and Columns");
        if (!marginsLayer) { marginsLayer = doc.layers.add(); marginsLayer.name = "Margins and Columns"; }
        marginsLayer.locked = false; marginsLayer.visible = true;
        
        // Only create baseline layer if we need it (baselineInc_pt > 0)
        var baselineLayer = null;
        if (baselineInc_pt > 0) {
            baselineLayer = findLayer(doc, "Baseline");
            if (!baselineLayer) { baselineLayer = doc.layers.add(); baselineLayer.name = "Baseline"; }
            baselineLayer.locked = false; baselineLayer.visible = true;
        }

        for (var k = 0; k < abIndices.length; k++) {
            var idx = abIndices[k];
            var thisVertGutter_pt = vertGutterOverride[idx] !== undefined ? vertGutterOverride[idx] : vertGutter_pt;
            var thisHorGutter_pt = horGutterOverride[idx] !== undefined ? horGutterOverride[idx] : horGutter_pt;
            var ab = doc.artboards[idx];
            
            if (!applyAllChk.value) {
                removePathsForArtboard(marginsLayer, idx);
                // Only clean baseline layer if it exists
                if (baselineLayer) {
                    removePathsForArtboard(baselineLayer, idx);
                }
            }
            
            // Always create margins and columns
            addMarginsAndColumnsToLayer(marginsLayer, ab, idx, top_pt, bottom_pt, left_pt, right_pt, cols, thisVertGutter_pt, rows, thisHorGutter_pt);
            
            // Only create baseline grid if increment > 0 and layer exists
            if (baselineInc_pt > 0 && baselineLayer) {
                addBaselineGridToLayer(baselineLayer, ab, idx, top_pt, bottom_pt, left_pt, right_pt, baselineStart_pt, baselineInc_pt);
            }
            
            // --- SAVE LOGIC REMAINS THE SAME ---
            var valuesToSave = {
                Top: addDefaultUnit(topInput.text, "margin"),
                Bottom: addDefaultUnit(bottomInput.text, "margin"),
                Left: addDefaultUnit(leftInput.text, "margin"),
                Right: addDefaultUnit(rightInput.text, "margin"),
                Columns: addDefaultUnit(colInput.text, "number"),
                Rows: addDefaultUnit(rowInput.text, "number"),
                VertGutter: addDefaultUnit(vertGutterInput.text, "gutter"),
                HorGutter: addDefaultUnit(horGutterInput.text, "gutter"),
                BaselineStart: addDefaultUnit(baselineStartInput.text, "margin"),
                BaselineInc: addDefaultUnit(baselineIncInput.text, "baseline")
            };
            
            if (vertGutterOverride[idx] !== undefined) { 
                valuesToSave.VertGutter = defaults.VertGutter.toString() + "mm"; 
            }
            if (horGutterOverride[idx] !== undefined) { 
                valuesToSave.HorGutter = defaults.HorGutter.toString() + "mm"; 
            }
            
            saveSettingsToXML(settingsXMLPath, idx, valuesToSave);
        }
        
        // Lock layers that were created
        marginsLayer.locked = true;
        if (baselineLayer) {
            baselineLayer.locked = true;
        }
        
        w.close();
    };
    
    w.center(); 
    w.show();
}

showMarginsDialog();
Correct answer sttk3

If there are no steps that can be undone, but the script attempts to undo, it is likely to crash.

2 replies

CarlosCanto
Adobe Expert
July 27, 2025

"

Anyhow the larger problem is what is the starting point for adding previews features. "

 

The basics of making a preview functions is

1. Draw your guides as usual but do not dismiss the Dialog box

2. if Preview is invoked, delete previously made guides if any before redrawing new ones

 

Here's a basic sample

https://community.adobe.com/t5/illustrator-discussions/scriptui-how-do-i-create-a-preview-of-the-results-while-a-palette-is-open/m-p/11007015#M170887

 

for a better example check Triangle Maker by Sergei Osokin, he has many more scripts with Preview.

https://github.com/creold/illustrator-scripts/blob/master/md/Draw.md#trianglemaker

Known Participant
July 27, 2025

I got this, but have no idea why it is crashing if i change a value once the preview is ticked 😞 

 

 

/**
 * Illustrator Margins, Grid & Baseline Script [Mac-Ready]
 * No ES6 code—fully ExtendScript compatible. Tested on Mac.
 * Fixed Preview Feature: Now shows guides in real time on active artboard with crash prevention.
 */

var settingsXMLPath = Folder.myDocuments + "/IllustratorGridSettings.xml";

// --- XML functions (unchanged) ---
function loadSettingsFromXML(xmlFilePath, abIdx, defaults) {
    function stringifyDefaults(defaultsObj) {
        var stringDefaults = {};
        for (var key in defaultsObj) {
            if (defaultsObj.hasOwnProperty(key)) {
                if (key === "BaselineInc") {
                    stringDefaults[key] = defaultsObj[key].toString() + "pt";
                } else if (key === "Columns" || key === "Rows") {
                    stringDefaults[key] = defaultsObj[key].toString();
                } else {
                    stringDefaults[key] = defaultsObj[key].toString() + "mm";
                }
            }
        }
        return stringDefaults;
    }

    var file = new File(xmlFilePath);
    if (!file.exists) return stringifyDefaults(defaults);
    
    file.open('r');
    var content = file.read();
    file.close();
    
    var abTag = new RegExp('<Artboard index="' + abIdx + '">([\\s\\S]*?)<\\/Artboard>');
    var found = content.match(abTag);
    
    if (found) {
        var vals = {};
        var tags = ["Top","Bottom","Left","Right","Columns","Rows","VertGutter","HorGutter","BaselineStart","BaselineInc"];
        for (var i = 0; i < tags.length; i++) {
            var tagName = tags[i];
            var tagRegex = new RegExp('<' + tagName + '>([\\s\\S]*?)<\\/' + tagName + '>');
            var tagMatch = found[1].match(tagRegex);
            
            if (tagMatch) {
                vals[tagName] = tagMatch[1];
            } else {
                if (tagName === "BaselineInc") {
                    vals[tagName] = defaults[tagName].toString() + "pt";
                } else if (tagName === "Columns" || tagName === "Rows") {
                    vals[tagName] = defaults[tagName].toString();
                } else {
                    vals[tagName] = defaults[tagName].toString() + "mm";
                }
            }
        }
        return vals;
    }
    
    return stringifyDefaults(defaults);
}

function saveSettingsToXML(xmlFilePath, abIdx, newVals) {
    var file = new File(xmlFilePath);
    var xmlContent = '';
    if (file.exists) {
        file.open('r');
        xmlContent = file.read();
        file.close();
    }
    var abTag = new RegExp('<Artboard index="' + abIdx + '">([\\s\\S]*?)<\\/Artboard>','g');
    xmlContent = xmlContent.replace(abTag, '');
    var abXML = '  <Artboard index="' + abIdx + '">\n';
    for (var key in newVals) {
        var value = newVals[key].toString().replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
        abXML += '    <' + key + '>' + value + '</' + key + '>\n';
    }
    abXML += '  </Artboard>\n';
    if (xmlContent.indexOf('<GridSettings>') === -1) {
        xmlContent = '<GridSettings>\n' + abXML + '</GridSettings>';
    } else {
        xmlContent = xmlContent.replace('</GridSettings>', abXML + '</GridSettings>');
    }
    file.open('w');
    file.write(xmlContent);
    file.close();
}

// --- Helpers (unchanged) ---
function mmToPt(mm) { return mm * 2.83465; }
function ptToMm(pt) { return pt / 2.83465; }
function makeRGB(r, g, b) {
    var color = new RGBColor();
    color.red = r; color.green = g; color.blue = b;
    return color;
}
function findLayer(doc, name) {
    for (var i = 0; i < doc.layers.length; i++) {
        if (doc.layers[i].name === name) return doc.layers[i];
    }
    return null;
}
function deleteLayerByExactName(doc, name) {
    for (var i = doc.layers.length - 1; i >= 0; i--) {
        if (doc.layers[i].name === name) {
            doc.layers[i].locked = false;
            doc.layers[i].visible = true;
            doc.layers[i].remove();
        }
    }
}
function removePathsForArtboard(layer, abIdx) {
    var abTag = " ab" + abIdx + " ";
    for (var i = layer.pathItems.length - 1; i >= 0; i--) {
        var p = layer.pathItems[i];
        if (p.note && p.note.indexOf(abTag) === 0) p.remove();
    }
}

// --- Unit Parsing (unchanged) ---
function parseValueWithUnit(inputStr) {
    if (typeof inputStr !== 'string') {
        inputStr = String(inputStr);
    }
    
    inputStr = inputStr.replace(/\s/g, '');
    var match = inputStr.match(/^(-?\d*\.?\d+)([a-zA-Z%]*)$/);
    
    if (!match) {
        var num = parseFloat(inputStr);
        return isNaN(num) ? NaN : mmToPt(num);
    }
    
    var value = parseFloat(match[1]);
    var unit = match[2].toLowerCase();
    
    if (isNaN(value)) return NaN;
    
    switch (unit) {
        case '':
        case 'mm':
            return mmToPt(value);
        case 'cm':
            return mmToPt(value * 10);
        case 'in':
        case 'inch':
            return value * 72;
        case 'pt':
        case 'point':
            return value;
        case 'px':
        case 'pixel':
            var doc = app.activeDocument;
            if (doc.rulerUnits == RulerUnits.Pixels) {
                return value;
            } else {
                return value * 0.75;
            }
        case 'pc':
        case 'pica':
            return value * 12;
        default:
            return mmToPt(value);
    }
}

function parseValueWithUnitPt(inputStr) {
    return parseValueWithUnit(inputStr);
}

function addDefaultUnit(inputStr, fieldType) {
    if (typeof inputStr !== 'string') {
        inputStr = String(inputStr);
    }
    
    inputStr = inputStr.replace(/\s/g, '');
    var match = inputStr.match(/^(-?\d*\.?\d+)([a-zA-Z%]*)$/);
    
    if (match && match[2] === '') {
        if (fieldType === "baseline") {
            return inputStr + "pt";
        } else if (fieldType === "number") {
            return inputStr;
        } else {
            return inputStr + "mm";
        }
    }
    
    return inputStr;
}

// --- Guide Creation (unchanged) ---
function addMarginsAndColumnsToLayer(layer, ab, abIdx, top_pt, bottom_pt, left_pt, right_pt, columns, vertGutter_pt, rows, horGutter_pt) {
    var rect = ab.artboardRect;
    var left = rect[0], top = rect[1], right = rect[2], bottom = rect[3];
    var width = right - left, height = top - bottom;
    var abTag = " ab" + abIdx + " ";
    
    var path = layer.pathItems.rectangle(top - top_pt, left + left_pt, width - left_pt - right_pt, height - top_pt - bottom_pt);
    path.stroked = true; path.strokeColor = makeRGB(224, 0, 255); path.strokeWidth = 0.1; path.filled = false; path.guides = true; path.note = abTag + "margin";
    
    var gridColor = makeRGB(0, 176, 255);
    if (columns > 1) {
        var usableWidth = width - left_pt - right_pt;
        var colWidth = (usableWidth - (columns - 1) * vertGutter_pt) / columns;
        var x = left + left_pt;
        // Limit the number of columns to prevent overload
        var maxColumns = Math.min(columns, 50); // Cap to avoid crashes with large numbers
        for (var c = 0; c < maxColumns - 1; c++) {
            x += colWidth;
            var vGuide1 = layer.pathItems.add();
            vGuide1.setEntirePath([[x, top - top_pt], [x, bottom + bottom_pt]]);
            vGuide1.stroked = true; vGuide1.strokeColor = gridColor; vGuide1.strokeWidth = 0.1; vGuide1.filled = false; vGuide1.guides = true; vGuide1.note = abTag + "colg";
            x += vertGutter_pt;
            var vGuide2 = layer.pathItems.add();
            vGuide2.setEntirePath([[x, top - top_pt], [x, bottom + bottom_pt]]);
            vGuide2.stroked = true; vGuide2.strokeColor = gridColor; vGuide2.strokeWidth = 0.1; vGuide2.filled = false; vGuide2.guides = true; vGuide2.note = abTag + "colg";
        }
    }
    
    if (rows > 1) {
        var usableHeight = height - top_pt - bottom_pt;
        var rowHeight = (usableHeight - (rows - 1) * horGutter_pt) / rows;
        var y = top - top_pt;
        // Limit the number of rows to prevent overload
        var maxRows = Math.min(rows, 50); // Cap to avoid crashes with large numbers
        for (var r = 0; r < maxRows - 1; r++) {
            y -= rowHeight;
            var hGuide1 = layer.pathItems.add();
            hGuide1.setEntirePath([[left + left_pt, y], [right - right_pt, y]]);
            hGuide1.stroked = true; hGuide1.strokeColor = gridColor; hGuide1.strokeWidth = 0.1; hGuide1.filled = false; hGuide1.guides = true; hGuide1.note = abTag + "rowg";
            y -= horGutter_pt;
            var hGuide2 = layer.pathItems.add();
            hGuide2.setEntirePath([[left + left_pt, y], [right - right_pt, y]]);
            hGuide2.stroked = true; hGuide2.strokeColor = gridColor; hGuide2.strokeWidth = 0.1; hGuide2.filled = false; hGuide2.guides = true; hGuide2.note = abTag + "rowg";
        }
    }
}

function addBaselineGridToLayer(layer, ab, abIdx, top_pt, bottom_pt, left_pt, right_pt, baselineStart_pt, baselineInc_pt) {
    if (baselineInc_pt <= 0) {
        return;
    }
    
    var rect = ab.artboardRect;
    var left = rect[0], top = rect[1], right = rect[2], bottom = rect[3];
    var abTag = " ab" + abIdx + " ";
    var y0 = top - top_pt - baselineStart_pt;
    var yEnd = bottom + bottom_pt;
    var count = 0;
    // Limit the number of baseline guides to prevent overload
    var maxLines = 100; // Cap to avoid crashes with small increments
    while (y0 > yEnd && count < maxLines) {
        var line = layer.pathItems.add();
        line.setEntirePath([[left + left_pt, y0], [right - right_pt, y0]]);
        line.stroked = true; line.strokeColor = makeRGB(80, 80, 80); line.strokeWidth = 0.05; line.filled = false; line.guides = true; line.note = abTag + "baseline";
        y0 -= baselineInc_pt;
        count++;
    }
}

// --- Preview Globals and Config ---
var isUndo = false;
var CFG = { is2020: parseInt(app.version) === 24 };
var lastPreviewTime = 0; // Throttle preview updates to prevent rapid calls

// --- UI Dialog with Fixed Preview ---
function showMarginsDialog() {
    if (app.documents.length === 0) { alert("Please open a document first."); return; }
    var doc = app.activeDocument;
    var abIdx = doc.artboards.getActiveArtboardIndex();
    var defaults = {
        Top:12.7, Bottom:12.7, Left:12.7, Right:12.7, Columns:2, Rows:2,
        VertGutter:4.233, HorGutter:4.233, BaselineStart:0, BaselineInc:12
    };
    var settings = loadSettingsFromXML(settingsXMLPath, abIdx, defaults);

    var w = new Window("dialog", "Margins, Grid & Baseline (for Artboard " + (abIdx + 1) + ")");
    w.orientation = "column";
    w.alignChildren = "fill";
    w.spacing = 15;
    w.margins = 20;

    var marginPanel = w.add("panel", undefined, "Margins");
    marginPanel.orientation = "column";
    marginPanel.alignChildren = "fill";
    marginPanel.margins = 15;
    marginPanel.spacing = 10;
    
    var mRow1 = marginPanel.add("group");
    mRow1.orientation = "row";
    mRow1.alignChildren = "center";
    mRow1.spacing = 10;
    mRow1.add("statictext", undefined, "Top:").preferredSize.width = 60;
    var topInput = mRow1.add("edittext", undefined, settings.Top);
    topInput.preferredSize.width = 80;
    mRow1.add("statictext", undefined, "Left:").preferredSize.width = 60;
    var leftInput = mRow1.add("edittext", undefined, settings.Left);
    leftInput.preferredSize.width = 80;
    
    var mRow2 = marginPanel.add("group");
    mRow2.orientation = "row";
    mRow2.alignChildren = "center";
    mRow2.spacing = 10;
    mRow2.add("statictext", undefined, "Bottom:").preferredSize.width = 60;
    var bottomInput = mRow2.add("edittext", undefined, settings.Bottom);
    bottomInput.preferredSize.width = 80;
    mRow2.add("statictext", undefined, "Right:").preferredSize.width = 60;
    var rightInput = mRow2.add("edittext", undefined, settings.Right);
    rightInput.preferredSize.width = 80;

    var gridPanel = w.add("panel", undefined, "Grid");
    gridPanel.orientation = "column";
    gridPanel.alignChildren = "fill";
    gridPanel.margins = 15;
    gridPanel.spacing = 10;
    
    var gRow1 = gridPanel.add("group");
    gRow1.orientation = "row";
    gRow1.alignChildren = "center";
    gRow1.spacing = 10;
    gRow1.add("statictext", undefined, "Columns:").preferredSize.width = 80;
    var colInput = gRow1.add("edittext", undefined, settings.Columns);
    colInput.preferredSize.width = 60;
    gRow1.add("statictext", undefined, "Vertical Gutter:").preferredSize.width = 100;
    var vertGutterInput = gRow1.add("edittext", undefined, settings.VertGutter);
    vertGutterInput.preferredSize.width = 80;
    
    var gRow2 = gridPanel.add("group");
    gRow2.orientation = "row";
    gRow2.alignChildren = "center";
    gRow2.spacing = 10;
    gRow2.add("statictext", undefined, "Rows:").preferredSize.width = 80;
    var rowInput = gRow2.add("edittext", undefined, settings.Rows);
    rowInput.preferredSize.width = 60;
    gRow2.add("statictext", undefined, "Horizontal Gutter:").preferredSize.width = 100;
    var horGutterInput = gRow2.add("edittext", undefined, settings.HorGutter);
    horGutterInput.preferredSize.width = 80;

    var basePanel = w.add("panel", undefined, "Baseline Grid");
    basePanel.orientation = "row";
    basePanel.alignChildren = "center";
    basePanel.margins = 15;
    basePanel.spacing = 10;
    basePanel.add("statictext", undefined, "Start:").preferredSize.width = 80;
    var baselineStartInput = basePanel.add("edittext", undefined, settings.BaselineStart);
    baselineStartInput.preferredSize.width = 80;
    basePanel.add("statictext", undefined, "Increment:").preferredSize.width = 80;
    var baselineIncInput = basePanel.add("edittext", undefined, settings.BaselineInc);
    baselineIncInput.preferredSize.width = 80;

    var applyAllGroup = w.add("group");
    applyAllGroup.margins = [0, 10, 0, 0];
    var applyAllChk = applyAllGroup.add("checkbox", undefined, "Apply to all artboards");
    applyAllChk.value = (doc.artboards.length === 1);

    var previewGroup = w.add("group");
    previewGroup.margins = [0, 10, 0, 0];
    var isPreview = previewGroup.add("checkbox", undefined, "Preview (Active Artboard Only)");
    isPreview.helpTip = "Toggle to see changes live (undoable)";
    if (CFG.is2020) {
        isPreview.enabled = false;
        isPreview.helpTip = "Preview disabled due to Illustrator bug";
    }

    var btnGroup = w.add("group");
    btnGroup.orientation = "row";
    btnGroup.alignment = "right";
    btnGroup.spacing = 10;
    btnGroup.margins = [0, 15, 0, 0];
    var cancelBtn = btnGroup.add("button", undefined, "Cancel", { name: "cancel" });
    var okBtn = btnGroup.add("button", undefined, "OK", { name: "ok" });
    cancelBtn.preferredSize.width = 80;
    okBtn.preferredSize.width = 80;

    // FIXED: Define previewChanges with throttling and limits to prevent crashes
    function previewChanges() {
        if (CFG.is2020) return;
        // Throttle: Only update preview if enough time has passed (e.g., 500ms)
        var currentTime = new Date().getTime();
        if (currentTime - lastPreviewTime < 500) return;
        lastPreviewTime = currentTime;

        try {
            var doc = app.activeDocument;
            var abIdx = doc.artboards.getActiveArtboardIndex();
            var ab = doc.artboards[abIdx];

            // Parse current inputs
            var top_pt = parseValueWithUnit(topInput.text), bottom_pt = parseValueWithUnit(bottomInput.text),
                left_pt = parseValueWithUnit(leftInput.text), right_pt = parseValueWithUnit(rightInput.text),
                cols = parseInt(colInput.text), rows = parseInt(rowInput.text),
                vertGutter_pt = parseValueWithUnit(vertGutterInput.text), horGutter_pt = parseValueWithUnit(horGutterInput.text),
                baselineStart_pt = parseValueWithUnit(baselineStartInput.text), baselineInc_pt = parseValueWithUnitPt(baselineIncInput.text);

            // Validation (skip if invalid)
            if (isNaN(top_pt) || isNaN(bottom_pt) || isNaN(left_pt) || isNaN(right_pt) || 
                isNaN(cols) || isNaN(rows) || 
                isNaN(vertGutter_pt) || isNaN(horGutter_pt) || 
                isNaN(baselineStart_pt) || isNaN(baselineInc_pt) ||
                top_pt < 0 || bottom_pt < 0 || left_pt < 0 || right_pt < 0 ||
                cols < 0 || rows < 0 ||
                vertGutter_pt < 0 || horGutter_pt < 0 ||
                baselineInc_pt < 0) {
                return;
            }

            // Grid fit check and overrides for active artboard
            function checkGridFit(abIdx, t_pt, b_pt, l_pt, r_pt, c, r, vg_pt, hg_pt) {
                var rect = doc.artboards[abIdx].artboardRect;
                var artW = rect[2] - rect[0] - l_pt - r_pt; var artH = rect[1] - rect[3] - t_pt - b_pt;
                var minW = mmToPt(1), minH = mmToPt(1);
                var failCol = false, failRow = false;
                if (c > 1) {
                    var gutW = (c - 1) * vg_pt;
                    if (artW <= gutW || (artW - gutW)/c < minW) { failCol = true; }
                }
                if (r > 1) {
                    var gutH = (r - 1) * hg_pt;
                    if (artH <= gutH || (artH - gutH)/r < minH) { failRow = true; }
                }
                return {failCol: failCol, failRow: failRow};
            }
            var check = checkGridFit(abIdx, top_pt, bottom_pt, left_pt, right_pt, cols, rows, vertGutter_pt, horGutter_pt);
            if (check.failCol) vertGutter_pt = mmToPt(defaults.VertGutter);
            if (check.failRow) horGutter_pt = mmToPt(defaults.HorGutter);

            // Set up layers
            var marginsLayer = findLayer(doc, "Margins and Columns") || doc.layers.add();
            marginsLayer.name = "Margins and Columns";
            marginsLayer.locked = false; marginsLayer.visible = true;

            var baselineLayer = null;
            if (baselineInc_pt > 0) {
                baselineLayer = findLayer(doc, "Baseline") || doc.layers.add();
                baselineLayer.name = "Baseline";
                baselineLayer.locked = false; baselineLayer.visible = true;
            }

            if (isPreview.value) {  // Preview ON
                if (isUndo) {
                    try {
                        doc.swatches.add().remove();  // Force undo point
                        app.undo();
                        app.redraw();
                    } catch (e) {}
                }

                removePathsForArtboard(marginsLayer, abIdx);
                if (baselineLayer) removePathsForArtboard(baselineLayer, abIdx);

                addMarginsAndColumnsToLayer(marginsLayer, ab, abIdx, top_pt, bottom_pt, left_pt, right_pt, cols, vertGutter_pt, rows, horGutter_pt);
                if (baselineInc_pt > 0 && baselineLayer) {
                    addBaselineGridToLayer(baselineLayer, ab, abIdx, top_pt, bottom_pt, left_pt, right_pt, baselineStart_pt, baselineInc_pt);
                }

                try {
                    doc.swatches.add().remove();  // Force undo point
                    app.redraw();
                } catch (e) {}
                isUndo = true;
            } else if (isUndo) {  // Preview OFF
                try {
                    app.undo();
                    app.redraw();
                } catch (e) {}
                isUndo = false;
            }
        } catch (err) {
            // Silent error handling to avoid crashes
        }
    }

    // Wire up events
    topInput.onChange = previewChanges;
    bottomInput.onChange = previewChanges;
    leftInput.onChange = previewChanges;
    rightInput.onChange = previewChanges;
    colInput.onChange = previewChanges;
    rowInput.onChange = previewChanges;
    vertGutterInput.onChange = previewChanges;
    horGutterInput.onChange = previewChanges;
    baselineStartInput.onChange = previewChanges;
    baselineIncInput.onChange = previewChanges;
    isPreview.onClick = previewChanges;

    // Cleanup on close
    w.onClose = function () {
        try {
            if (isUndo) {
                app.activeDocument.swatches.add().remove();
                app.undo();
                app.redraw();
            }
        } catch (err) {}
        isUndo = false;
    };

    okBtn.onClick = function() {
        if (isPreview.value && isUndo) {
            try {
                app.undo();
                app.redraw();
            } catch (e) {}
            isUndo = false;
        }

        var top_pt = parseValueWithUnit(topInput.text), bottom_pt = parseValueWithUnit(bottomInput.text),
            left_pt = parseValueWithUnit(leftInput.text), right_pt = parseValueWithUnit(rightInput.text),
            cols = parseInt(colInput.text), rows = parseInt(rowInput.text),
            vertGutter_pt = parseValueWithUnit(vertGutterInput.text), horGutter_pt = parseValueWithUnit(horGutterInput.text),
            baselineStart_pt = parseValueWithUnit(baselineStartInput.text), baselineInc_pt = parseValueWithUnitPt(baselineIncInput.text);

        if (isNaN(top_pt) || isNaN(bottom_pt) || isNaN(left_pt) || isNaN(right_pt) || 
            isNaN(cols) || isNaN(rows) || 
            isNaN(vertGutter_pt) || isNaN(horGutter_pt) || 
            isNaN(baselineStart_pt) || isNaN(baselineInc_pt) ||
            top_pt < 0 || bottom_pt < 0 || left_pt < 0 || right_pt < 0 ||
            cols < 0 || rows < 0 ||
            vertGutter_pt < 0 || horGutter_pt < 0 ||
            baselineInc_pt < 0) {
            alert("Please enter valid (non-negative) numbers. Baseline increment can be 0 to skip baseline grid.");
            return;
        }
        
        var abIndices = [];
        if (applyAllChk.value) { for (var i = 0; i < doc.artboards.length; i++) abIndices.push(i); } else { abIndices.push(abIdx); }
        
        var vertGutterOverride = {}, horGutterOverride = {};
        var warnedCol = false, warnedRow = false;
        for (var i = 0; i < abIndices.length; i++) {
            var check = checkGridFit(abIndices[i], top_pt, bottom_pt, left_pt, right_pt, cols, rows, vertGutter_pt, horGutter_pt);
            if (check.failCol) {
                if (!warnedCol) { alert("Column/gutter combination doesn't fit on at least one artboard. Vertical gutter is reset to default."); warnedCol = true; }
                vertGutterOverride[abIndices[i]] = mmToPt(defaults.VertGutter);
            }
            if (check.failRow) {
                if (!warnedRow) { alert("Row/gutter combination doesn't fit on at least one artboard. Horizontal gutter is reset to default."); warnedRow = true; }
                horGutterOverride[abIndices[i]] = mmToPt(defaults.HorGutter);
            }
        }

        if (applyAllChk.value) {
            deleteLayerByExactName(doc, "Margins and Columns");
            if (baselineInc_pt > 0) {
                deleteLayerByExactName(doc, "Baseline");
            }
        }
        
        var marginsLayer = findLayer(doc, "Margins and Columns");
        if (!marginsLayer) { marginsLayer = doc.layers.add(); marginsLayer.name = "Margins and Columns"; }
        marginsLayer.locked = false; marginsLayer.visible = true;
        
        var baselineLayer = null;
        if (baselineInc_pt > 0) {
            baselineLayer = findLayer(doc, "Baseline");
            if (!baselineLayer) { baselineLayer = doc.layers.add(); baselineLayer.name = "Baseline"; }
            baselineLayer.locked = false; baselineLayer.visible = true;
        }

        for (var k = 0; k < abIndices.length; k++) {
            var idx = abIndices[k];
            var thisVertGutter_pt = vertGutterOverride[idx] !== undefined ? vertGutterOverride[idx] : vertGutter_pt;
            var thisHorGutter_pt = horGutterOverride[idx] !== undefined ? horGutterOverride[idx] : horGutter_pt;
            var ab = doc.artboards[idx];
            
            if (!applyAllChk.value) {
                removePathsForArtboard(marginsLayer, idx);
                if (baselineLayer) {
                    removePathsForArtboard(baselineLayer, idx);
                }
            }
            
            addMarginsAndColumnsToLayer(marginsLayer, ab, idx, top_pt, bottom_pt, left_pt, right_pt, cols, thisVertGutter_pt, rows, thisHorGutter_pt);
            
            if (baselineInc_pt > 0 && baselineLayer) {
                addBaselineGridToLayer(baselineLayer, ab, idx, top_pt, bottom_pt, left_pt, right_pt, baselineStart_pt, baselineInc_pt);
            }
            
            var valuesToSave = {
                Top: addDefaultUnit(topInput.text, "margin"),
                Bottom: addDefaultUnit(bottomInput.text, "margin"),
                Left: addDefaultUnit(leftInput.text, "margin"),
                Right: addDefaultUnit(rightInput.text, "margin"),
                Columns: addDefaultUnit(colInput.text, "number"),
                Rows: addDefaultUnit(rowInput.text, "number"),
                VertGutter: addDefaultUnit(vertGutterInput.text, "gutter"),
                HorGutter: addDefaultUnit(horGutterInput.text, "gutter"),
                BaselineStart: addDefaultUnit(baselineStartInput.text, "margin"),
                BaselineInc: addDefaultUnit(baselineIncInput.text, "baseline")
            };
            
            if (vertGutterOverride[idx] !== undefined) { 
                valuesToSave.VertGutter = defaults.VertGutter.toString() + "mm"; 
            }
            if (horGutterOverride[idx] !== undefined) { 
                valuesToSave.HorGutter = defaults.HorGutter.toString() + "mm"; 
            }
            
            saveSettingsToXML(settingsXMLPath, idx, valuesToSave);
        }
        
        marginsLayer.locked = true;
        if (baselineLayer) {
            baselineLayer.locked = true;
        }
        
        w.close();
    };
    
    w.center(); 
    w.show();
}

showMarginsDialog();
sttk3Correct answer
Brainiac
July 27, 2025

If there are no steps that can be undone, but the script attempts to undo, it is likely to crash.

Adobe Expert
July 26, 2025

@SmythWharf have you look at the other view modes in Illustrator?

Trim View is probably the most similar to InDesign's Preview. It hides all content outside your Artboard (including bleed, crop marks, and any off-artboard elements) and shows you only what will be visible within the final trimmed document. It's excellent for seeing the final layout without distractions. There's no default keyboard shortcut, but you can create your own via Edit > Keyboard Shortcuts.