This is a follow-up to a recent thread where there was someone needed to get access to an underlying property on a layer.
The code below makes it possible to access properties of Application, Document, and Layer classes without having to working about the types of the objects or properties involved. The low-level function Stdlib._getObjProperty makes it possible to access properties from other types of objects.
Internally, the code only works on the current/active object. For Application, this is not an issue. For Document and Layers, it's a big issue. If you do not have Stdlib.wrapLC or Stdlib.wrapLCLayer available, you must make sure that the document and/or layer is the current/active one.
Note that if you are wanting to access layer properties by using the internal layer index you would need to have a slightly different implementation. I'll leave that as an exercise for the reader .
Please refer to the previous thread (towards the end) for more discussion on this technique.
Code: Select allcTID = function(s) { return app.charIDToTypeID(s); };
sTID = function(s) { return app.stringIDToTypeID(s); };
xTID = function(s) {
if (s.constructor == Number) {
return s;
}
if (s.constructor == String) {
if (s.length != 4) return sTID(s);
try { return cTID(s); } catch (e) { return sTID(s); }
}
Error.runtimeError(19, "s"); // Bad Argument
};
Stdlib = function(){};
//
// Stdlib.getObjectProperty
// Return the value of a PS object's properties from the underlying
// ActionDescriptor-based definition.
// Returns 'undefined' if the property's value cannot be determined
// This api currently only works on Application, Document, and
// Layer-family objects.
// Lower level apis make it possible to access other kinds of objects.
//
// Examples:
// Stdlib.getObjectProperty(doc, 'Ttl ');
// Stdlib.getObjectProperty(doc.activLayer, 'Nm ');
// Stdlib.getObjectProperty(app, 'Path');
//
Stdlib.getObjectProperty = function(obj, prop) {
var val = Stdlib._getObjProperty(obj, prop);
return (val ? val.value : undefined);
};
// Stdlib.getObjectPropertyType
// For UnitDouble, return the type
// For Object, return the classId
// For Enumerated, return the enumerationTypeId
// All else, return undefined
//
Stdlib.getObjectPropertyType = function(obj, prop) {
var val = Stdlib._getObjProperty(obj, prop);
return (val ? val.type : undefined);
};
//
// Stdlib._getObjProperty
// Returns an object with value and (optional) type of the property.
// The 'typ' can be used when accessing an object type that this
// function does not already understand
//
Stdlib._getObjProperty = function(obj, prop, typ) {
var propId;
var otyp;
function _ftn() {
var ref = new ActionReference();
ref.putProperty(cTID("Prpr"), propId);
ref.putEnumerated(cTID(otyp), cTID("Ordn"), cTID("Trgt") );
var desc;
try {
desc = executeActionGet(ref);
} catch (e) {
return undefined;
}
var val = {};
if (desc.hasKey(propId)) {
var typ = desc.getType(propId);
switch (typ) {
case DescValueType.ALIASTYPE:
val.value = desc.getPath(propId); break;
case DescValueType.BOOLEANTYPE:
val.value = desc.getBoolean(propId); break;
case DescValueType.CLASSTYPE:
val.value = desc.getClass(propId); break;
case DescValueType.DOUBLETYPE:
val.value = desc.getDouble(propId); break;
case DescValueType.ENUMERATEDTYPE:
val.value = desc.getEnumeratedValue(propId);
val.type = desc.getEnumeratedType(propId);
break;
case DescValueType.INTEGERTYPE:
val.value = desc.getInteger(propId); break;
case DescValueType.LISTTYPE:
val.value = desc.getList(propId); break;
case DescValueType.OBJECTTYPE:
val.value = desc.getObjectValue(propId);
val.type = desc.getObjectType(propId);
break;
case DescValueType.RAWTYPE:
val.value = desc.getData(propId); break;
case DescValueType.REFERENCETYPE:
val.value = desc.getReference(propId); break;
case DescValueType.STRINGTYPE:
val.value = desc.getString(propId); break;
case DescValueType.UNITDOUBLE:
val.value = desc.getUnitDoubleValue(propId);
val.type = desc.getUnitDoubleType(propId);
break;
}
}
return val;
}
if (obj == undefined) {
Error.runtimeError(2, "object");
}
if (prop == undefined) {
Error.runtimeError(2, "property");
}
if (prop.constructor == String) {
propId = xTID(prop);
} else if (prop.constructor == Number) {
propId = prop;
} else {
Error.runtimeError(19, "property");
}
var val;
if (typ == undefined) {
if (obj.typename == "Document") {
otyp = "Dcmn";
} else if (obj.typename == "ArtLayer" || obj.typename == "LayerSet") {
otyp = "Lyr ";
} else if (obj.typename == "Application") {
otyp = "capp";
} else {
throw ("Unable to get property from " +
(obj.typename ? obj.typename : "unknown") +
" type of object.");
}
} else {
otyp = typ;
}
if (otyp == "Dcmn" && Stdlib.wrapLC) {
val = Stdlib.wrapLC(obj, _ftn);
} else if (otyp == "Lyr " && Stdlib.wrapLCLayer) {
var p = layer.parent;
while (p.typename != "Document") {
p = p.parent;
}
val = Stdlib.wrapLCLayer(p, obj, _ftn);
} else {
val = _ftn();
}
return val;
};
-X
How to retrieve internal PS object properties
How to retrieve internal PS object properties
Here's the expanded bug-reduced version:
Code: Select all//
// Stdlib.getObjectProperty
// Return the value of a PS object's properties from the underlying
// ActionDescriptor-based definition.
// Returns 'undefined' if the property's value cannot be determined
// This api currently only works on Application, Document, and
// Layer-family objects.
// Lower level apis make it possible to access other kinds of objects.
//
// Examples:
// var str = Stdlib.getObjectProperty(0, "Nm ", "Lyr ")
// var bool = Stdlib.getObjectProperty(doc.activeLayer, "Vsbl", "Lyr ")
// var str = Stdlib.getObjectProperty(doc, 'Ttl ');
// var file = Stdlib.getObjectProperty(app, 'Path');
// var clrDesc = Stdlib.getObjectProperty(app, 'FrgC');
//
Stdlib.getObjectProperty = function(obj, prop, typ) {
var val = Stdlib._getObjProperty(obj, prop, typ);
return (val ? val.value : undefined);
};
// Stdlib.getObjectPropertyType
// For UnitDouble, return the type
// For Object, return the classId
// For Enumerated, return the enumerationTypeId
// All else, return undefined
//
Stdlib.getObjectPropertyType = function(obj, prop, typ) {
var val = Stdlib._getObjProperty(obj, prop, typ);
return (val ? val.type : undefined);
};
//
// Stdlib._getObjProperty
// Returns an object with value and (optional) type of the property.
// The 'typ' can be used when accessing an object type that this
// function does not already understand
//
Stdlib._getObjProperty = function(obj, prop, typ) {
var propId;
var otyp;
function _ftn(obj, propId, otyp) {
var ref = new ActionReference();
ref.putProperty(cTID("Prpr"), propId);
if (typeof(obj) == "number") {
ref.putIndex(cTID(otyp), obj);
} else {
ref.putEnumerated(cTID(otyp), cTID("Ordn"), cTID("Trgt") );
}
var desc;
try {
desc = executeActionGet(ref);
} catch (e) {
return undefined;
}
var val = {};
if (desc.hasKey(propId)) {
var typ = desc.getType(propId);
switch (typ) {
case DescValueType.ALIASTYPE:
val.value = desc.getPath(propId); break;
case DescValueType.BOOLEANTYPE:
val.value = desc.getBoolean(propId); break;
case DescValueType.CLASSTYPE:
val.value = desc.getClass(propId); break;
case DescValueType.DOUBLETYPE:
val.value = desc.getDouble(propId); break;
case DescValueType.ENUMERATEDTYPE:
val.value = desc.getEnumeratedValue(propId);
val.type = desc.getEnumeratedType(propId);
break;o
case DescValueType.INTEGERTYPE:
val.value = desc.getInteger(propId); break;
case DescValueType.LISTTYPE:
val.value = desc.getList(propId); break;
case DescValueType.OBJECTTYPE:
val.value = desc.getObjectValue(propId);
val.type = desc.getObjectType(propId);
break;
case DescValueType.RAWTYPE:
val.value = desc.getData(propId); break;
case DescValueType.REFERENCETYPE:
val.value = desc.getReference(propId); break;
case DescValueType.STRINGTYPE:
val.value = desc.getString(propId); break;
case DescValueType.UNITDOUBLE:
val.value = desc.getUnitDoubleValue(propId);
val.type = desc.getUnitDoubleType(propId);
break;
}
}
return val;
}
if (obj == undefined) {
Error.runtimeError(2, "object");
}
if (prop == undefined) {
Error.runtimeError(2, "property");
}
if (prop.constructor == String) {
propId = xTID(prop);
} else if (prop.constructor == Number) {
propId = prop;
} else {
Error.runtimeError(19, "property");
}
var val; // {value: undefind, type: undefined}
//$.level = 1; debugger;
if (app.documents.length > 0) {
var o_doc = app.activeDocument; // active doc before this function
var o_layer = o_doc.activeLayer; // active layer before this function
}
if (typeof(obj) == "object") {
if (typ == "Dcmn" || obj.typename == "Document") {
otyp = "Dcmn";
if (app.activeDocument != obj) {
o_doc = app.activeDocument;
app.activeDocument = obj;
}
} else if (typ == "Lyr " || obj.typename == "ArtLayer"
|| obj.typename == "LayerSet") {
otyp = "Lyr ";
var layer = obj;
while(layer.parent != undefined &&
layer.parent.typename != "Document") {
layer = layer.parent;
}
if (app.activeDocument != layer.parent) {
app.activeDocument = layer.parent;
}
if (layer.parent.activeLayer != layer) {
layer.parent.activeLayer = layer;
}
} else if (typ == "capp" || obj.typename == "Application") {
otyp = "capp";
} else {
throw ("Unable to get property from " +
(obj.typename ? obj.typename : "unknown") +
" type of object.");
}
} else if (typeof(obj) == "number") {
if (!typ) {
throw ("Unable to get property from unknown type of object");
}
if (typ != "Lyr " && typ != "Dcmn") {
throw "Indexed app operations are not yet supported.";
}
otyp = typ;
}
var val = _ftn(obj, propId, otyp);
if (app.documents.length > 0) {
if (o_doc.activeLayer != o_layer) {
o_doc.activeLayer = o_layer;
}
if (app.activeDocument != o_doc) {
app.activeDocument = o_doc;
}
}
return val;
};
Stdlib.getLayerProperty = function(index, propSym) {
return Stdlib.getObjectProperty(index, propSym, 'Lyr ');
};
Stdlib.getDocumentProperty = function(index, propSym) {
return Stdlib.getObjectProperty(index, propSym, 'Dcmn');
};
Stdlib.getApplicationProperty = function(propSym) {
return Stdlib.getObjectProperty(app, propSym);
};
The previous versions had problems if the document or layer was not the active one when this was called.
-X
-X
Code: Select all//
// Stdlib.getObjectProperty
// Return the value of a PS object's properties from the underlying
// ActionDescriptor-based definition.
// Returns 'undefined' if the property's value cannot be determined
// This api currently only works on Application, Document, and
// Layer-family objects.
// Lower level apis make it possible to access other kinds of objects.
//
// Examples:
// var str = Stdlib.getObjectProperty(0, "Nm ", "Lyr ")
// var bool = Stdlib.getObjectProperty(doc.activeLayer, "Vsbl", "Lyr ")
// var str = Stdlib.getObjectProperty(doc, 'Ttl ');
// var file = Stdlib.getObjectProperty(app, 'Path');
// var clrDesc = Stdlib.getObjectProperty(app, 'FrgC');
//
Stdlib.getObjectProperty = function(obj, prop, typ) {
var val = Stdlib._getObjProperty(obj, prop, typ);
return (val ? val.value : undefined);
};
// Stdlib.getObjectPropertyType
// For UnitDouble, return the type
// For Object, return the classId
// For Enumerated, return the enumerationTypeId
// All else, return undefined
//
Stdlib.getObjectPropertyType = function(obj, prop, typ) {
var val = Stdlib._getObjProperty(obj, prop, typ);
return (val ? val.type : undefined);
};
//
// Stdlib._getObjProperty
// Returns an object with value and (optional) type of the property.
// The 'typ' can be used when accessing an object type that this
// function does not already understand
//
Stdlib._getObjProperty = function(obj, prop, typ) {
var propId;
var otyp;
function _ftn(obj, propId, otyp) {
var ref = new ActionReference();
ref.putProperty(cTID("Prpr"), propId);
if (typeof(obj) == "number") {
ref.putIndex(cTID(otyp), obj);
} else {
ref.putEnumerated(cTID(otyp), cTID("Ordn"), cTID("Trgt") );
}
var desc;
try {
desc = executeActionGet(ref);
} catch (e) {
return undefined;
}
var val = {};
if (desc.hasKey(propId)) {
var typ = desc.getType(propId);
switch (typ) {
case DescValueType.ALIASTYPE:
val.value = desc.getPath(propId); break;
case DescValueType.BOOLEANTYPE:
val.value = desc.getBoolean(propId); break;
case DescValueType.CLASSTYPE:
val.value = desc.getClass(propId); break;
case DescValueType.DOUBLETYPE:
val.value = desc.getDouble(propId); break;
case DescValueType.ENUMERATEDTYPE:
val.value = desc.getEnumeratedValue(propId);
val.type = desc.getEnumeratedType(propId);
break;o
case DescValueType.INTEGERTYPE:
val.value = desc.getInteger(propId); break;
case DescValueType.LISTTYPE:
val.value = desc.getList(propId); break;
case DescValueType.OBJECTTYPE:
val.value = desc.getObjectValue(propId);
val.type = desc.getObjectType(propId);
break;
case DescValueType.RAWTYPE:
val.value = desc.getData(propId); break;
case DescValueType.REFERENCETYPE:
val.value = desc.getReference(propId); break;
case DescValueType.STRINGTYPE:
val.value = desc.getString(propId); break;
case DescValueType.UNITDOUBLE:
val.value = desc.getUnitDoubleValue(propId);
val.type = desc.getUnitDoubleType(propId);
break;
}
}
return val;
}
if (obj == undefined) {
Error.runtimeError(2, "object");
}
if (prop == undefined) {
Error.runtimeError(2, "property");
}
if (prop.constructor == String) {
propId = xTID(prop);
} else if (prop.constructor == Number) {
propId = prop;
} else {
Error.runtimeError(19, "property");
}
var val; // {value: undefind, type: undefined}
//$.level = 1; debugger;
if (app.documents.length > 0) {
var o_doc = app.activeDocument; // active doc before this function
var o_layer = o_doc.activeLayer; // active layer before this function
}
if (typeof(obj) == "object") {
if (typ == "Dcmn" || obj.typename == "Document") {
otyp = "Dcmn";
if (app.activeDocument != obj) {
o_doc = app.activeDocument;
app.activeDocument = obj;
}
} else if (typ == "Lyr " || obj.typename == "ArtLayer"
|| obj.typename == "LayerSet") {
otyp = "Lyr ";
var layer = obj;
while(layer.parent != undefined &&
layer.parent.typename != "Document") {
layer = layer.parent;
}
if (app.activeDocument != layer.parent) {
app.activeDocument = layer.parent;
}
if (layer.parent.activeLayer != layer) {
layer.parent.activeLayer = layer;
}
} else if (typ == "capp" || obj.typename == "Application") {
otyp = "capp";
} else {
throw ("Unable to get property from " +
(obj.typename ? obj.typename : "unknown") +
" type of object.");
}
} else if (typeof(obj) == "number") {
if (!typ) {
throw ("Unable to get property from unknown type of object");
}
if (typ != "Lyr " && typ != "Dcmn") {
throw "Indexed app operations are not yet supported.";
}
otyp = typ;
}
var val = _ftn(obj, propId, otyp);
if (app.documents.length > 0) {
if (o_doc.activeLayer != o_layer) {
o_doc.activeLayer = o_layer;
}
if (app.activeDocument != o_doc) {
app.activeDocument = o_doc;
}
}
return val;
};
Stdlib.getLayerProperty = function(index, propSym) {
return Stdlib.getObjectProperty(index, propSym, 'Lyr ');
};
Stdlib.getDocumentProperty = function(index, propSym) {
return Stdlib.getObjectProperty(index, propSym, 'Dcmn');
};
Stdlib.getApplicationProperty = function(propSym) {
return Stdlib.getObjectProperty(app, propSym);
};
The previous versions had problems if the document or layer was not the active one when this was called.
-X
-X
How to retrieve internal PS object properties
The updated version will work with layer and document objects or their indexes.
Code: Select allStdlib.getLayerProperty(1, "Nm ");
Stdlib.getLayerProperty(doc.activeLayer, "Nm ");
Stdlib.getDocumentProperty(1, "Ttl ");
Stdlib.getDocumentProperty(doc, "Ttl ");
I already did the exercise for you
-X
Code: Select allStdlib.getLayerProperty(1, "Nm ");
Stdlib.getLayerProperty(doc.activeLayer, "Nm ");
Stdlib.getDocumentProperty(1, "Ttl ");
Stdlib.getDocumentProperty(doc, "Ttl ");
I already did the exercise for you
-X
How to retrieve internal PS object properties
Thanks! I had my 60th birthday on March 15. I'm beyond exercise now!