﻿// (c) Copyright 2005.  Adobe Systems, Incorporated.  All rights reserved.
// This script will apply each comp and then export to a file
// Written by Naoki Hada
// ZStrings and auto layout by Tom Ruark

// enable double clicking from the Macintosh Finder or the Windows Explorer
#target photoshop

// in case we double clicked the file
app.bringToFront();

// debug level: 0-2 (0:disable, 1:break on error, 2:break at beginning)
// $.level = 0;
// debugger; // launch debugger on next line

// on localized builds we pull the $$$/Strings from a .dat file, see documentation for more details
$.localize = true;

//=================================================================
// Globals
//=================================================================

// UI strings to be localized
var strTitle = localize("$$$/JavaScripts/LayerCompsToWPG/Title=Layer Comps To WPG");
var strButtonRun = localize("$$$/JavaScripts/LayerCompsToWPG/Run=Run");
var strButtonCancel = localize("$$$/JavaScripts/LayerCompsToWPG/Cancel=Cancel");
var strHelpText = localize("$$$/JavaScripts/LayerCompsToWPG/HelpText=Please specify the location where flat image files should be saved. Once Photoshop has saved these files, it will launch Web Photo Gallery in order to convert each file into a Web page.");
var strLabelDestination = localize("$$$/JavaScripts/LayerCompsToWPG/Destination=Destination:");
var strButtonBrowse = localize("$$$/JavaScripts/LayerCompsToWPG/Browse=Browse...");
var strLabelStyle = localize("$$$/JavaScripts/LayerCompsToWPG/Style=Style:");
var strCheckboxSelectionOnly = localize("$$$/JavaScripts/LayerCompsToWPG/Selected=Selected Layer Comps Only");
var strAlertSpecifyDestination = localize("$$$/JavaScripts/LayerCompsToWPG/SpecifyDestination=Please specify destination.");
var strAlertDestinationNotExist = localize("$$$/JavaScripts/LayerCompsToWPG/DestinationDoesNotExist=Destination does not exist.");
var strTitleSelectDestination = localize("$$$/JavaScripts/LayerCompsToWPG/SelectDestination=Select Destination");
var strAlertDocumentMustBeOpened = localize("$$$/JavaScripts/LayerCompsToWPG/OneDocument=You must have a document open to export!");
var strAlertNoLayerCompsFound = localize("$$$/JavaScripts/LayerCompsToWPG/NoComps=No layer comps found in document!");
var strStyle = localize("$$$/JavaScripts/LayerCompsToWPG/Simple=Simple");

// Settings
var numClipSize = 5000; // resize before call WPG (pixel)


main();


///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////



///////////////////////////////////////////////////////////////////////////////
// Function: settingDialog
// Usage: create the main dialog
// Input: settings to initialize the dialog with , ExportInfo object
// Return: true if ok, false if cancel
///////////////////////////////////////////////////////////////////////////////
function settingDialog(exportInfo) {

    dlgMain = new Window("dialog", strTitle);

	dlgMain.orientation = 'column';
	dlgMain.alignChildren = 'left';
	
	// -- top of the dialog, first line
    dlgMain.add("statictext", undefined, strLabelDestination);

	// -- two groups, one for left and one for right ok, cancel
	dlgMain.grpTop = dlgMain.add("group");
	dlgMain.grpTop.orientation = 'row';
	dlgMain.grpTop.alignChildren = 'top';
	dlgMain.grpTop.alignment = 'fill';

	// -- group contains four lines
	dlgMain.grpTopLeft = dlgMain.grpTop.add("group");
	dlgMain.grpTopLeft.orientation = 'column';
	dlgMain.grpTopLeft.alignChildren = 'left';
	dlgMain.grpTopLeft.alignment = 'fill';
	
	// -- the second line in the dialog
	dlgMain.grpSecondLine = dlgMain.grpTopLeft.add("group");
	dlgMain.grpSecondLine.orientation = 'row';
	dlgMain.grpSecondLine.alignChildren = 'center';

    dlgMain.etDestination   = dlgMain.grpSecondLine.add("edittext", undefined, exportInfo.destination.toString());
    dlgMain.etDestination.preferredSize.width = 160;

    dlgMain.btnBrowse= dlgMain.grpSecondLine.add("button", undefined, strButtonBrowse);
    dlgMain.btnBrowse.onClick = btnBrowseOnClick;

	// -- the third line in the dialog
	dlgMain.grpThirdLine = dlgMain.grpTopLeft.add("statictext", undefined, strLabelStyle);

	// -- the fourth line in the dialog
    dlgMain.etStyle   = dlgMain.grpTopLeft.add("edittext", undefined, exportInfo.style.toString());
    dlgMain.etStyle.alignment = 'fill';

	// -- the fifth line in the dialog
    dlgMain.cbSelection = dlgMain.grpTopLeft.add("checkbox", undefined, strCheckboxSelectionOnly);
    dlgMain.cbSelection.value = exportInfo.selectionOnly;

	// the right side of the dialog, the ok and cancel buttons
	dlgMain.grpTopRight = dlgMain.grpTop.add("group");
	dlgMain.grpTopRight.orientation = 'column';
	dlgMain.grpTopRight.alignChildren = 'fill';
	
	dlgMain.btnRun = dlgMain.grpTopRight.add("button", undefined, strButtonRun );
    dlgMain.btnRun.onClick = btnRunOnClick;

	dlgMain.btnCancel = dlgMain.grpTopRight.add("button", undefined, strButtonCancel );
    dlgMain.btnCancel.onClick = function() { 
		var d = this;
		while (d.type != 'dialog') {
			d = d.parent;
		}
		d.close(false); 
	}

	dlgMain.defaultElement = dlgMain.btnRun;
	dlgMain.cancelElement = dlgMain.btnCancel;

	dlgMain.grpBottom = dlgMain.add("group");
	dlgMain.grpBottom.orientation = 'column';
	dlgMain.grpBottom.alignChildren = 'left';
	dlgMain.grpBottom.alignment = 'fill';
    
    dlgMain.pnlHelp = dlgMain.grpBottom.add("panel");
    dlgMain.pnlHelp.alignment = 'fill';

    dlgMain.etHelp = dlgMain.pnlHelp.add("statictext", undefined, strHelpText, {multiline:true});
    dlgMain.etHelp.alignment = 'fill';

    dlgMain.center();
    
    var result = dlgMain.show();
    
    if (false == result) {
       return result;
    }
    
    // get setting from dialog
    exportInfo.destination = dlgMain.etDestination.text;
    exportInfo.style = dlgMain.etStyle.text;
    exportInfo.selectionOnly = dlgMain.cbSelection.value;

    return result;
}


///////////////////////////////////////////////////////////////////////////////
// Function: btnRunOnClick
// Usage: routine is assigned to the onClick method of the run button
// Input: checks the dialog params and closes with the dialog with true
// Return: <none>, dialog is closed with true on success
///////////////////////////////////////////////////////////////////////////////
function btnRunOnClick() {
    // check if the setting is properly
    var destination = dlgMain.etDestination.text;
    if (destination.length == 0) {
        alert(strAlertSpecifyDestination);
        return;
    }
    var testFolder = new Folder(destination);
    if (!testFolder.exists) {
        alert(strAlertDestinationNotExist);
        return;
    }
   
	// find the dialog in this auto layout mess
	var d = this;
	while (d.type != 'dialog') {
		d = d.parent;
	}
	d.close(true); 
}


///////////////////////////////////////////////////////////////////////////////
// Function: btnBrowseOnClick
// Usage: routine is assigned to the onClick method of the browse button
// Input: pop the selectDialog, and get a folder
// Return: <none>, sets the destination edit text
///////////////////////////////////////////////////////////////////////////////
function btnBrowseOnClick()
{
    var defaultFolder = dlgMain.etDestination.text;
    var testFolder = new Folder(dlgMain.etDestination.text);
    if (!testFolder.exists) defaultFolder = "~";
    var selFolder = Folder.selectDialog(strTitleSelectDestination, defaultFolder);
    if (selFolder != null) {
		dlgMain.etDestination.text = selFolder.fsName;
    }
	dlgMain.defaultElement.active = true;
    return;
}


///////////////////////////////////////////////////////////////////////////////
// Function: ExportInfo
// Usage: object for holding the dialog parameters
// Input: <none>
// Return: object holding the export info
///////////////////////////////////////////////////////////////////////////////
function ExportInfo() {
    this.destination = new String("");
    this.tempLocation = new String("");
    this.style = new String(strStyle);
    this.selectionOnly = false;

    try {
        this.destination = Folder(app.activeDocument.fullName.parent).fsName;
        var tmp = app.activeDocument.fullName.name;
        this.fileNamePrefix = decodeURI(tmp.substring(0, tmp.indexOf(".")));
    } 
    catch(someError) {
        this.destination = new String("");
        this.fileNamePrefix = app.activeDocument.name;
    }
}


///////////////////////////////////////////////////////////////////////////////
// Function: setTempFolder
// Usage: create a temp folder using random numbers
// Input: export info object
// Return: tempLocation of the object is set 
///////////////////////////////////////////////////////////////////////////////
function setTempFolder(exportInfo)
{
    var folder = Folder.temp; // File(exportInfo.destination).parent;
    while(true) {   // set temporary folder with random name
        exportInfo.tempLocation = folder.toString() + "/temp" + Math.floor(Math.random()*10000);
        var testFolder = new Folder(exportInfo.tempLocation);
        if (!testFolder.exists) {
            testFolder.create();
            break;
        }
    }
}


///////////////////////////////////////////////////////////////////////////////
// Function: zeroSuppress
// Usage: create a string padded with 0's
// Input: num and number of digits to pad
// Return: zero padded num
///////////////////////////////////////////////////////////////////////////////
function zeroSuppress (num, digit) {
    var tmp = num.toString();
    while(tmp.length < digit)   tmp = "0" + tmp;
    return tmp
}


///////////////////////////////////////////////////////////////////////////////
// Function: main
// Usage: the main routine for this JavaScript
// Input: <none>
// Return: <none>
///////////////////////////////////////////////////////////////////////////////
function main() {
    if (app.documents.length <= 0) {
        alert(strAlertDocumentMustBeOpened);
        return;
    }

    var exportInfo = new ExportInfo();
    if (false == settingDialog(exportInfo)) {
		return;
	}

    try {
        var docName = app.activeDocument.name;
        exportInfo.fileNamePrefix.replace(/\s/g, "_"); // replace space to '_';
    
        setTempFolder(exportInfo);
    
        var compsName = new String("none");
        var compsCount = app.activeDocument.layerComps.length;
        if (compsCount <= 1) {
            alert (strAlertNoLayerCompsFound);
        } else {
            app.activeDocument = app.documents[docName];
            docRef = app.activeDocument;
    
            var tempFileList = new Array();
    
            var orgRulerUnits = app.preferences.rulerUnits;  // save unit
            app.preferences.rulerUnits = Units.PIXELS;

            var exportFileCount = 0;
            for (compsIndex = 0; compsIndex < compsCount; compsIndex++) {
                var compRef = docRef.layerComps[compsIndex];
                if (exportInfo.selectionOnly && !compRef.selected) continue; // selected only
                compRef.apply();
                var duppedDocument = app.activeDocument.duplicate();
                if ((numClipSize < duppedDocument.width.value)||(numClipSize < duppedDocument.height.value)) {
                    var wRatio = duppedDocument.width.value / numClipSize;
                    var hRatio = duppedDocument.height.value / numClipSize;
                    var ratio = Math.max(wRatio, hRatio);               
                    duppedDocument.resizeImage(duppedDocument.width/ratio, duppedDocument.height/ratio);
                }
                var fileNameBody = zeroSuppress(compsIndex+1, 2); // starting 01
                fileNameBody += "_" + compRef.name;
                fileNameBody = fileNameBody.replace(/[:\/\\*\?\"\<\>\|]/g, "_");  // '/\:*?"<>|' -> '_'
                if (fileNameBody.length > 120) fileNameBody = fileNameBody.substring(0,120);
                var tempFile = exportInfo.tempLocation + "/" + fileNameBody + ".psd";
                tempFileList[exportFileCount] = tempFile;
                exportFileCount++;
                tempFile = new File(tempFile);
                if (null != compRef.name)   duppedDocument.info.title = compRef.name;
                if (null != compRef.comment)    duppedDocument.info.caption = compRef.comment;
                duppedDocument.saveAs(tempFile);
                duppedDocument.close();
            }
            app.preferences.rulerUnits = orgRulerUnits; // restore unit
    
            // run Web Photo Gallery
            galleryOptions = new GalleryOptions();
            galleryOptions.layoutStyle = exportInfo.style;
            galleryOptions.addSizeAttributes = true;
            galleryOptions.preserveAllMetadata = true;
            galleryOptions.bannerOptions.siteName = docName;
            galleryOptions.imagesOptions.resizeImages = true;
            galleryOptions.imagesOptions.dimension = 450;
            galleryOptions.imagesOptions.includeFilename = true;
            galleryOptions.imagesOptions.caption = true;
            galleryOptions.imagesOptions.includeTitle = true;
            galleryOptions.thumbnailOptions.includeFilename = true;
            galleryOptions.thumbnailOptions.caption = true;
            galleryOptions.thumbnailOptions.includeTitle = true;
    
            app.makePhotoGallery(Folder(exportInfo.tempLocation), Folder(exportInfo.destination), galleryOptions);
    
            // delete temporary files
            for (compsIndex = 0; compsIndex < exportFileCount; compsIndex++) {
                tempFile = new File(tempFileList[compsIndex]);
                tempFile.remove();
            }
            // delete temprary folder
            var tempFolder = new Folder(exportInfo.tempLocation);
            tempFolder.remove();
        }
    } 
    catch (e) {
        alert(e);
    }
}


