Skip to main content
Mohamed Hameed21513110
Inspiring
July 23, 2024
Question

how can modify this code to distribute the text within the columns in reverse

  • July 23, 2024
  • 0 replies
  • 250 views

Dear forum people
And people with great programming experience
I am working on creating a magazine in Photoshop, which consists of distributing the texts on the page evenly and with good layout
I know that InDesign is excellent at such things, but I am not good at working on it
I found this code to divide the text into columns very well, but it is excellent at distributing the text from left to right

But the project I am working on requires me to do the opposite, which is to create and distribute texts from right to left. I have tried a lot to modify this code to help me, but I have failed.
Now I have come to you so that you can help me, please, please

this code :

 

//------------------------------------------------------------------------------
// File: "[M] Text columns 1.1.jsx"
// Version: 1.1
// Release Date: 21. 4. 2018
// Copyright: © 2018 Jaroslav Bereza <http://bereza.cz>
// Licence: GPL <http://www.gnu.org/licenses/gpl.html>
//------------------------------------------------------------------------------
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//------------------------------------------------------------------------------

/*
    <javascriptresource>
    <name>[M] Text columns 1.1</name>
    <enableinfo>true</enableinfo>
    <category>Magic</category>
    </javascriptresource>
    
    VERSION HISTORY:
    ================
    1.1:
    - Fixes CS6 workaround
    1.0:
    - Initial release.
    
    ALGORITHM
    =========
    - read text descriptor
    - modify text descriptor - column function is already built-in but has no UI so I just set value
    - apply text descriptor
    - that's all
    
    
    TODO:
    - 
    
    KNOWN ISSUES:
    - in PS CS6 and CC(without year) - if none layer is selected then it takes top layer in layers panel
*/

#target Photoshop
app.bringToFront();

cTID = function(s) { return cTID[s] || (cTID[s] = app.charIDToTypeID(s)); };
sTID = function(s) { return app.stringIDToTypeID(s); }; 
idTS = function(id) { return app.typeIDToStringID (id);};


const psVersion=app.version.split('.')[0];
var startDisplayDialogs = app.displayDialogs;
app.displayDialogs = DialogModes.NO;


initialize();
function initialize(){
    
    if(app.documents.length==0){
        alert("Please open some document and select paragraph text layers (not point text layers)");
        return;
    }
    
    var selected = getSelectedLayers ();
    selected = filterEditableTextLayers (selected);
    
    if(selected.length===0){
        alert("Please select non-empty paragraph text layer(s) (not point text layers)");
        return;
    }
    
    app.activeDocument.suspendHistory("[M] Text columns","main(selected);");
    app.displayDialogs = startDisplayDialogs;
}


function main(selected){
    var originalTypeUnits = app.preferences.typeUnits; // remember current setting
    app.preferences.typeUnits = TypeUnits.PIXELS;
    
    var win, 
        windowResource;
        
    windowResource = """dialog {  
        orientation: 'column', 
        alignChildren: ['fill', 'top'],  
        text: '[M] Text columns 1.0',  
        margins:15, 
        alignChildren: ['fill', 'fill'], 
            
        grpColumns: Panel { 
            margins:10,
            orientation:'row',
            lblColumns: StaticText{
                text: 'Columns:',
                characters: 6
            },
            txtColumns: EditText{
                
            },
            lblDummy: StaticText{
                text: '   '
                
            },
            lblGutter: StaticText{
                text: 'Gutter:'
                
            },
            txtGutter: EditText{
                characters: 6
            },
            lblGutterPx: StaticText{
                margins: 0,
                text: 'px'
            },
        },
        bottomGroup: Group{
            statsLabel: StaticText{alignment:['right', 'bottom']},
                     
            cancelButton: Button { text: 'Cancel', properties:{name:'cancel'}}, 
            applyButton: Button { text: 'Change columns', properties:{name:'ok'}}, 
        }
    }"""
    win = new Window(windowResource);
    win.bottomGroup.applyButton.onClick = function() {
        var columns = win.grpColumns.txtColumns.text;
        var gutter = win.grpColumns.txtGutter.text.replace(",",".");
        
        // zero columns can cause Photoshop crash
        if(isNormalInteger(columns) && isNumeric (gutter)){
            for(var i=0, len = selected.length; i < len;  i++){
                var textDescriptor = getTextKey (selected[i]);  
                var properties = {
                    columnCount:columns,
                    columnGutter:gutter
                }
                    
                // changing text descriptor properties
                textDescriptor = setColumnsToDescriptor(textDescriptor,properties);
                    
                // apply modified descriptor
                applyTextKey (textDescriptor, selected[i]);        
            }
            win.close();
        }else{
            alert("Columns must be positive whole number.\nGutter must be decimal number");
        }
        
    }
    win.onShow = function(){
        var inputData = getValuesForDialog(selected);
        win.grpColumns.txtColumns.text = inputData.columns;
        win.grpColumns.txtGutter.text = inputData.gutter;
    }
    win.onClose = function(){
        app.preferences.typeUnits = originalTypeUnits;
    }
    win.show();
}

///////////////////
// Helpers
///////////////////

function isNormalInteger(str) {
    var n = Math.floor(Number(str));
    var result = String(n) === str && n > 0;
    return result;
}

function isNumeric(n) {
    var result = !isNaN(parseFloat(n)) && isFinite(n);
    return result;
}

/*
function pointsToPixels(points){
    var pixels = points * 72 / app.activeDocument.resolution;
    return pixels;
}*/

function pixelsToPoints(pixels){
    var points = (pixels / app.activeDocument.resolution) * 72;
    return points;
}


function setColumnsToDescriptor(textKey, properties){
    var textShapeList = textKey.getList(sTID ('textShape'));
    var textShapeItem = textShapeList.getObjectValue(0);
    textShapeItem.putInteger(sTID ('columnCount'),properties.columnCount);
    // if you read value it's based on text preferences units
    // but if you write this values it's always points WTF Adobe?
    textShapeItem.putDouble(sTID ('columnGutter'),pixelsToPoints(properties.columnGutter));
    //Some other properties. It can change text but I don't see usefulness
    //textShapeItem.putInteger(sTID ('rowCount'),1);
    //textShapeItem.putDouble(sTID ('rowGutter'),20);
    //textShapeItem.putDouble(sTID ('spacing'),0);
    //textShapeItem.putBoolean(sTID ('rowMajorOrder'),false);
    //textShapeItem.putDouble(sTID ('firstBaselineMinimum'),5);
    /*
    alignByMinimumValueRoman
    alignByAscent
    alignByCapHeight
    alignByLeading
    alignByXHeight
    alignByMinimumValueAsian
    */
    //var transform = textShapeItem.getObjectValue(sTID('transform'));
    //transform.putDouble(sTID ('xy'),0);
    //transform.putDouble(sTID ('tx'),0);
    //textShapeItem.putObject(sTID ('transform'),sTID ('transform'),transform);
    
    textShapeList.clear();
    textShapeList.putObject(sTID ('textShape'),textShapeItem);
    textKey.putList(sTID ('textShape'),textShapeList);
    
    return textKey;
}

function applyTextKey(textKey, index){
    var layerRef = new ActionReference();
    layerRef.putIndex( cTID('Lyr '), index );
    var idsetd = charIDToTypeID( "setd" );
    var desc151 = new ActionDescriptor();
        desc151.putReference( charIDToTypeID( "null" ), layerRef );
        var idT = charIDToTypeID( "T   " );
        var idTxLr = charIDToTypeID( "TxLr" );
        desc151.putObject( idT, idTxLr, textKey );
        
    executeAction( idsetd, desc151, DialogModes.NO ); 
}

// check if it is box text or point text
function isTextBoxType(textKey){
    var textShapeList = textKey.getList(sTID ('textShape'));
    var textShapeItem = textShapeList.getObjectValue(0);
    
    var textType = textShapeItem.getEnumerationValue(sTID ('textType'));
    var textType = idTS (textType);
    
    if(textType == "box"){
        return true;
    }
    else{
        return false;
    }
}

function getBgCounter(){
    var backGroundCounter = 1;
    try {
        var dummy = app.activeDocument.backgroundLayer;
        backGroundCounter = 0;
    }
    catch(e){;} //do nothing
    return backGroundCounter;
}


function getSelectedLayers() {
    var selectedLayers = [];
        var backGroundCounter = getBgCounter();
        var ref = new ActionReference();
        var keyTargetLayers = app.stringIDToTypeID( 'targetLayers' );
        ref.putProperty( app.charIDToTypeID( 'Prpr' ), keyTargetLayers );
        ref.putEnumerated( app.charIDToTypeID( 'Dcmn' ), app.charIDToTypeID( 'Ordn' ), app.charIDToTypeID( 'Trgt' ) );
        var desc = executeActionGet( ref );
        if ( desc.hasKey( keyTargetLayers ) ) {
            var layersList = desc.getList( keyTargetLayers );
            for ( var j = 0; j < layersList.count; j++) {
                var listRef = layersList.getReference( j );
                selectedLayers.push( listRef.getIndex() + backGroundCounter );
            }
        }
    // CS6 and CC
    if(psVersion < 15 && selectedLayers.length === 0){
        selectedLayers.push(cs6SelectedLayerBugFix());
    }
    return selectedLayers;
}

function getTextKey(layerIndex){
    var ref = new ActionReference();
    var idPrpr = charIDToTypeID( "Prpr" );
    var idTxtS = stringIDToTypeID( "textKey" );
    ref.putProperty( idPrpr, idTxtS );
    var lyr = charIDToTypeID( "Lyr " );
    ref.putIndex( lyr, layerIndex );

    // step inside
    var desc = executeActionGet(ref);
    var descTextKey = desc.getObjectValue(stringIDToTypeID('textKey'));

    return descTextKey;
}

// if all layers has same property show this value. If not, show empty input.
function getValuesForDialog(selectedLayers){
    var result = {columns: undefined, gutter: undefined};
    
    for (var i = 0, len = selectedLayers.length; i < len; i++){
        var textKey = getTextKey(selectedLayers[i]);
        if(result.columns === undefined){
            result.columns = getColumns(textKey);
        }
        else if(getColumns(textKey) != result.columns){
            result.columns = "";
            break
        }
    }

    for (var i = 0, len = selectedLayers.length; i < len; i++){
        var textKey = getTextKey(selectedLayers[i]);
        if(result.gutter === undefined){
            result.gutter = getGutter(textKey);
            
        }
        else if(getGutter(textKey) != result.gutter){
            result.gutter = "";
            break
        }
    }
    if(result.gutter){
        result.gutter = Math.round (result.gutter*100)/100;
    }
    return result;
}

function getColumns(textKey){
    var textShapeList = textKey.getList(sTID ('textShape'));
    var textShapeItem = textShapeList.getObjectValue(0);
    var columns = textShapeItem.getInteger(sTID ('columnCount'));
    
    return columns;
}

function getGutter(textKey){
    var textShapeList = textKey.getList(sTID ('textShape'));
    var textShapeItem = textShapeList.getObjectValue(0);
    var gutter = textShapeItem.getDouble(sTID ('columnGutter'));
    
    return gutter;
}


function filterEditableTextLayers(list){
    for (var i = 0, len = list.length; i < len; i++){
        var ref166 = new ActionReference();
        var idLyr = charIDToTypeID( "Lyr " );
        ref166.putIndex( idLyr, list[i] );
        var desc = executeActionGet(ref166);
        
        var isNotTextLayer = !desc.hasKey(stringIDToTypeID('textKey'));
        var descLocking = desc.getObjectValue(stringIDToTypeID('layerLocking'));
        var locked = descLocking.getBoolean(stringIDToTypeID('protectAll'));
        
        
        if(isNotTextLayer || locked){
            list.splice(i,1);
            i--;
            len--;
            continue;
        }
    
        var textKey = desc.getObjectValue(stringIDToTypeID('textKey'));
        var contentString = textKey.getString(stringIDToTypeID('textKey'));
        var isParagraphText = isTextBoxType(textKey);
        if(contentString == "" || !isParagraphText){
            list.splice(i,1);
            i--;
            len--;
            continue;
        }
    }
    
    return list;
}

function cs6SelectedLayerBugFix(){
    var ref = new ActionReference();
    var idPrpr = charIDToTypeID( "Prpr" );
    var idTxtS = stringIDToTypeID( "itemIndex" );
    ref.putProperty( idPrpr, idTxtS );

    var idLyr = charIDToTypeID( "Lyr " );
    var idOrdn = charIDToTypeID( "Ordn" );
    var idTrgt = charIDToTypeID( "Trgt" );
    ref.putEnumerated( idLyr, idOrdn, idTrgt );

    var desc = executeActionGet(ref);
    var itemIndex = desc.getInteger(stringIDToTypeID('itemIndex')) + (hasBackground() ? -1 : 0);
    return itemIndex;
}

function hasBackground(){
	try {
		var dummy = app.activeDocument.backgroundLayer;
		return true;
	} catch (e) {;
		return false;
	} 
}

 

These are also illustrative pictures of the problem I am facing 


This topic has been closed for replies.