Reputation: 190
Though I managed to put a functional script to change the dictionary language of selected layers together, it's not quite what I need yet.
I'm currently retrieving the index of my selected layers, using them to get the layer names—it's the problematic part—then working the magic to change their language based on an option chosen in a custom dialog box I display.
The use of layers names is a very half-assed solution, I need precision, I need to be able to change the language based on a layer ID or index. Not only my script is prone to names conflicts but I have no idea of where those selected layers will be, if on the root of the document or inside 5 groups stack.
Here is my current code:
The main function
function main() {
// Create window with language selection and retrieve selected value
var lang = createWindow();
// Retrieve selected layers
var selectedLayers = getSelectedLayersIdx();
// Look at each entry and change language when possible
for(var a in selectedLayers){
try {
setLangByIndex(Number( selectedLayers[a]), lang );
} catch(err) { }
}
}
(createWindow returns a lang value, skipping that)
Mike's get Idx
function getSelectedLayersIdx(){
var selectedLayers = new Array;
var ref = new ActionReference();
ref.putEnumerated( charIDToTypeID('Dcmn'), charIDToTypeID('Ordn'), charIDToTypeID('Trgt') );
var desc = executeActionGet(ref);
if( desc.hasKey( stringIDToTypeID( 'targetLayers' ) ) ) {
desc = desc.getList( stringIDToTypeID( 'targetLayers' ));
var c = desc.count
var selectedLayers = new Array();
for(var i=0;i<c;i++) {
try{
activeDocument.backgroundLayer;
selectedLayers.push( desc.getReference( i ).getIndex() );
} catch(e) {
selectedLayers.push( desc.getReference( i ).getIndex()+1 );
}
}
} else {
var ref = new ActionReference();
ref.putProperty( charIDToTypeID('Prpr') , charIDToTypeID( 'ItmI' ));
ref.putEnumerated( charIDToTypeID('Lyr '), charIDToTypeID('Ordn'), charIDToTypeID('Trgt') );
try {
activeDocument.backgroundLayer;
selectedLayers.push( executeActionGet(ref).getInteger(charIDToTypeID( 'ItmI' ))-1);
} catch(e) {
selectedLayers.push( executeActionGet(ref).getInteger(charIDToTypeID( 'ItmI' )));
}
}
return selectedLayers;
}
The function which sets the language
function setLangByIndex(idx, lang){
ref = new ActionReference();
ref.putProperty( charIDToTypeID("Prpr") , charIDToTypeID( "Nm " ));
ref.putIndex( charIDToTypeID( "Lyr " ), idx );
var name = executeActionGet(ref).getString(charIDToTypeID( "Nm " ));
var el = activeDocument.layers.getByName( name );
// Temp quick block; MUST UPDATE IN CASE OF NEW LANGUAGES
if (lang == 'pt_br' )
el.textItem.language = Language.BRAZILLIANPORTUGUESE;
else if (lang == 'en_us' )
el.textItem.language = Language.ENGLISHUSA;
else
el.textItem.language = Language.ENGLISHUK;
}
Workarounds I inefficiently tried:
Upvotes: 4
Views: 1385
Reputation: 190
After I noticed some annoying glitches related to Paragraph Styles (the ones you can define as the default for your text on PS, not the JS object) I gave up on being stubborn and stopped avoiding doing a new loop through the indexes array to reselect the layers when done.
/*
* Based in Mike Hale's "getSelectedLayersIdx" script and Adobe's Scripting Listener dump.
Based the panel on Davide Barranca's code: http://www.davidebarranca.com/2012/10/scriptui-window-in-photoshop-palette-vs-dialog/
Useful Resources:
Photoshop char list: http://www.pcpix.com/Photoshop/char.htm
ActionDescriptor methods: http://jongware.mit.edu/pscs5js_html/psjscs5/pc_ActionDescriptor.html
TextItem methods: http://jongware.mit.edu/pscs5js_html/psjscs5/pc_TextItem.html
You can fish for language codes here: http://wingp.googlecode.com/svn/photogp/photoshopapi/photoshop/PIStringTerminology.h
*/
/* ______________________________ SCRIPT ______________________________ */
var scriptAlert = "Language Change says";
// MUST UPDATE IF YOU WANT TO CHANGE THE AVAILABLE LANGUAGES
// The available languages, as { text displayed on dialog window : codename }. See notes above for more language codes
var langs = {};
langs['Português (Brasil)'] = 'brazilianPortugueseLanguage';
langs['English (UK)'] = 'ukenglishLanguage';
langs['English (USA)'] = 'englishLanguage';
if(app.documents.length>0){ // the script will be executed only if an active document exists.
var imgName = activeDocument.name;
var extreme= imgName.substr(imgName.length - 5, 5);
var dot = extreme.lastIndexOf(".");
if(dot == -1) { // Checks if the active document was saved or not.
alert("Please, save your document!", scriptAlert, false);
} else {
main(); // if the active document was saved, go ahead!
}
}
function createWindow() { // Creates a panel asking for input
var isDone, win, windowResource, radio_group, cancel, rb, i;
//sentinel variable
isDone = false;
cancel = false;
// Build dialog radio buttons
i = 0;
for( var k in langs ) {
if( i==0 )
rb = "rb"+i+": RadioButton { text: '"+k+"', value: 1 }, \ ";
else
rb += "rb"+i+": RadioButton { text: '"+k+"' }, \ ";
i++;
}
windowResource = "palette { \
orientation: 'column', \
alignChildren: ['fill', 'top'], \
preferredSize:[300, 130], \
text: 'Change Spell Check Language', \
margins:15, \
\
optPanel: Panel { \
orientation: 'row', \
alignChildren: 'left', \
margins:15, \
text: ' Select the desired dictionary language for the select text ', \ "+ rb + " \
} \
\
bottomGroup: Group{ \
cancelButton: Button { text: 'Cancel', properties:{name:'cancel'}, size: [120,24], alignment:['right', 'center'] }, \
applyButton: Button { text: 'Ok', properties:{name:'ok'}, size: [120,24], alignment:['right', 'center'], active: true }, \
}\
}";
win = new Window(windowResource);
radio_group = win.optPanel; // set group
// Match options with language
function selected_rbutton (rbuttons)
{
for (var i = 0; i < rbuttons.children.length; i++)
if (rbuttons.children[i].value == true)
return langs[rbuttons.children[i].text];
}
win.bottomGroup.cancelButton.onClick = function() {
win.close();
return cancel = true;
};
// Button listeners
win.bottomGroup.applyButton.onClick = function() {
return isDone = true;
};
// don't forget this one!
win.onClose = function() {
return cancel = true;
};
win.addEventListener("keydown", function (k)
{
if (k.keyName == 'Enter')
return isDone = true;
});
win.show();
while (isDone === false) {
try {
app.refresh();
} catch(err) { // Esc cancels without errors
return false;
}
}
return cancel ? false : selected_rbutton (radio_group); // return value, or false if cancelled
}
function getSelectedLayersIdx(){ // Gets array of indexes of selected layers
var selectedLayers = new Array;
var ref = new ActionReference();
ref.putEnumerated( charIDToTypeID('Dcmn'), charIDToTypeID('Ordn'), charIDToTypeID('Trgt') );
var desc = executeActionGet(ref);
if( desc.hasKey( stringIDToTypeID( 'targetLayers' ) ) ) {
desc = desc.getList( stringIDToTypeID( 'targetLayers' ));
var c = desc.count
var selectedLayers = new Array();
for(var i=0;i<c;i++) {
try{
activeDocument.backgroundLayer;
selectedLayers.push( desc.getReference( i ).getIndex() );
} catch(e) {
selectedLayers.push( desc.getReference( i ).getIndex()+1 );
}
}
} else {
var ref = new ActionReference();
ref.putProperty( charIDToTypeID('Prpr') , charIDToTypeID( 'ItmI' ));
ref.putEnumerated( charIDToTypeID('Lyr '), charIDToTypeID('Ordn'), charIDToTypeID('Trgt') );
try {
activeDocument.backgroundLayer;
selectedLayers.push( executeActionGet(ref).getInteger(charIDToTypeID( 'ItmI' ))-1);
} catch(e) {
selectedLayers.push( executeActionGet(ref).getInteger(charIDToTypeID( 'ItmI' )));
}
}
return selectedLayers;
}
function selectLayerByIndex( selectedLayers, add ){ // Selects layers by index. If fed an array + true add, selects them, otherwise provide a single value so it selects a single layer
if (typeof(add)==='undefined') add = false;
if ( add ) // If Add it's an array
for(var a in selectedLayers){
var desc = new ActionDescriptor();
var ref = new ActionReference();
ref.putIndex( charIDToTypeID( "Lyr " ), Number(selectedLayers[a]) );
desc.putReference( charIDToTypeID( "null" ), ref );
desc.putEnumerated( stringIDToTypeID( "selectionModifier" ), stringIDToTypeID( "selectionModifierType" ), stringIDToTypeID( "addToSelection" ) );
var idMkVs = charIDToTypeID( "MkVs" );
desc.putBoolean( charIDToTypeID( "MkVs" ), false );
executeAction( charIDToTypeID( "slct" ), desc, DialogModes.NO );
}
else // Else I just need to make this layer active, it's a number
{
var desc = new ActionDescriptor();
var ref = new ActionReference();
var idLyr = charIDToTypeID( "Lyr " );
ref.putIndex( charIDToTypeID( "Lyr " ), selectedLayers );
desc.putReference( charIDToTypeID( "null" ), ref );
desc.putBoolean( charIDToTypeID( "MkVs" ), false );
executeAction( charIDToTypeID( "slct" ), desc, DialogModes.NO );
}
}
function setLangByIndex( idx, lang ){ // Sets the dictionary language for a text layer based on its index
// Make layer active
selectLayerByIndex( idx );
// And do tiny override
var textObj = new ActionDescriptor();
var target = new ActionReference();
target.putProperty( charIDToTypeID( "Prpr" ), charIDToTypeID( "TxtS" ) ); // desired property: text style
target.putEnumerated( charIDToTypeID( "TxLr" ), charIDToTypeID( "Ordn" ), charIDToTypeID( "Trgt" ) ); // the active layer
textObj.putReference( charIDToTypeID( "null" ), target );
var textStyle = new ActionDescriptor();
textStyle.putInteger( stringIDToTypeID( "textOverrideFeatureName" ), 808466225 );
textStyle.putInteger( stringIDToTypeID( "typeStyleOperationType" ), 3 );
textStyle.putEnumerated( stringIDToTypeID( "textLanguage" ), stringIDToTypeID( "textLanguage" ), stringIDToTypeID( lang ) );
textObj.putObject( charIDToTypeID( "T " ), charIDToTypeID( "TxtS" ), textStyle ); // to (end); text style, desc.
executeAction( charIDToTypeID( "setd" ), textObj, DialogModes.NO ); // execute
}
////////////////////////////////////
// Main function
function main() {
// Create window with language selection and retrieve selected value
var lang = createWindow();
if ( !lang ) // If cancelled please stop
return;
// Retrieve selected layers
var selectedLayers = getSelectedLayersIdx();
// Look at each entry and change language when possible; otherwise skip to next item
for(var k in selectedLayers){
try {
setLangByIndex(Number(selectedLayers[k]), lang);
} catch(err) {
continue;
}
}
selectLayerByIndex( selectedLayers, true );
}
Upvotes: 0