Copy link to clipboard
Copied
In another thread a poster asked about multiple guide sets:
http://forums.adobe.com/message/4062904#4062904
It would seem that this should be fairly simple to achieve with writing guides’ properties into the metadata (possibly a dedidcated layer’s xmpMetaData) in sets and subsequently loading them from there.
One could even do just one dialog with an entry field for entering a name when saving a guide set and a dropDownList to load or remove such sets.
So I wonder if anybody either has already done something like this or has a (better) idea on the issue?
Thanks for any feedback.
Just a couple of amendments to it...
...#target photoshop
app.bringToFront();
///////////////////////////////////
// Photoshop CS5 or better
///////////////////////////////////
function main(){
if(!documents.length) return;
var startRulerUnits = app.preferences.rulerUnits;
app.preferences.rulerUnits = Units.PIXELS;
// Set up metadata namespace
if (ExternalObject.AdobeXMPScript == undefined) ExternalObject.AdobeXMPScript = new ExternalObject("lib:AdobeXMPScript");
var psNamespace = "http://ns.ps-scripts.com/1.0/
Copy link to clipboard
Copied
I was working on a guide panel that had just about every guide related feature Jeff Tranberry and I could think of. I was saving the sets( we called them presets ) in the user's presets folder as XML. The javascript end works just fine but I gave up on making the panel because of all the panel issues with Windows 7 and the newer Mac OSs
Maybe I should create something that uses ScriptUI for the interface.
Copy link to clipboard
Copied
Thanks for your answer.
I suspect a Panel would probably be preferable for most users, a modal dialog might scare some of them off.
If the presets were saved separately then they would not for example transfer with the documents?
Copy link to clipboard
Copied
I guess I didn't think of every feature after all. I had the guide preset set up like all the other presets in Photoshop. i.e. stored on the system and not with the document. I can see where having a guide preset travel with the document could have it's advantages. But if they are stored in the document how would one apply that set to a different document? Along those lines, do you think that being able to store other presets with a document would be useful?
I agree that a panel would be ideal. But after all the issues that came up with my smart object linking panel I decided I would not make another until Adobe sorts out the issues with them.
Copy link to clipboard
Copied
But if they are stored in the document how would one apply that set to a different document?
I suppose one would need an export-function for that after all.
Or, and this is a pretty dirty option I guess, if one uses a layer to hold the xmpMetaData one could transfer that – of course that would clash with a possible existing one in th ereceiving document. (I just wanted to use layer metadata to avoid meddling in the file’s metadata.)
But I have to admit that I was thinking only of document-specific guides and not of guide presets for documents in general.
Did you intend to offer options for units or percentages?
I once installed the Flash Builder trial and let it expire before getting anywhere, so I’m respectful for proper Panel-building …
Copy link to clipboard
Copied
As Mike has said a panel would be the best, Extension Builder, Flash Builder and Configurator all have the same problem with Windows 7 and render panels out of bounds until Adobe fix the problem.
I don't know if this will be of any use but I have a script here that creates new documents along with user selected guides, maybe it could be expanded to cope with preset guides?
Copy link to clipboard
Copied
c.pfaffenbichler wrote:
Did you intend to offer options for units or percentages
As I remember I set it up so it could work with any distance unit, pixels or percent. I also had a flag in the preset so the guide set could either be fixed or relative so ( within limits ) it could work with any size document at any resolution.
I think that if the preset is saved with the document it would be better to save it in a custom namespace in the document's metadata instead of a layer's metadata. To me the problem with using layer metadata to store a document wide setting is that it limts what can be done with the document, i.e. the layer can not be deleted, merged, etc.
As I understand it both Windows 7 and Mac OSX have problems with custom panels. They range from simple panel refresh issues to more serious fucus issues. With Windows 7 sometimes a application restart is needed.
Copy link to clipboard
Copied
I think that if the preset is saved with the document it would be better to save it in a custom namespace in the document's metadata
You are right; but (please pardon my ignorance) I have no idea how to add a custom namespace to the xmpMetaData or how to retrieve that namespace’s information …
Would I have to use BridgeTalk for that?
Copy link to clipboard
Copied
With newer versions of Photoshop you can use AdobeXMPScript to work with metadata. It is simple really, You just need to make up a namespace URL string, use new Namespace to convert that string into a namespace, then use registerNamespace() to add the namespace to the XMP. From there you can use it like any other namespace.
But now that you have me thinking about this in more detail I am not sure any longer that the document's metadata has a clear advantage. I will have to do some test when I have time.
Copy link to clipboard
Copied
Here is an example I've put together...
#target photoshop
app.bringToFront();
function main(){
var startRulerUnits = app.preferences.rulerUnits;
app.preferences.rulerUnits = Units.PIXELS;
// Set up metadata namespace
if (ExternalObject.AdobeXMPScript == undefined) ExternalObject.AdobeXMPScript = new ExternalObject("lib:AdobeXMPScript");
var psNamespace = "http://ns.ps-scripts.com/1.0/";
var psPrefix = "psscripts:";
XMPMeta.registerNamespace(psNamespace, psPrefix);
existingGuidePresets = [];
existingGuidePresets = getGuideArray();
var guides = app.activeDocument.guides;
var gH = '';
var gV = '';
for( var g = 0; g < guides.length; g++ ){
if(guides.direction.toString() == 'Direction.HORIZONTAL'){
gH+=(parseInt(guides.coordinate.value));
gH+=',';
}else{
gV+=(parseInt(guides.coordinate.value));
gV+=','
}
}
gH=gH.replace(/,$/,'');
gV=gV.replace(/,$/,'');
app.preferences.rulerUnits = startRulerUnits;
var win = new Window( 'dialog', 'Custom Guides' );
g = win.graphics;
var myBrush = g.newBrush(g.BrushType.SOLID_COLOR, [0.99, 0.99, 0.99, 1]);
g.backgroundColor = myBrush;
win.p1= win.add("panel", undefined, undefined, {borderStyle:"black"});
win.g1 = win.p1.add('group');
win.g1.orientation = "row";
win.title = win.g1.add('statictext',undefined,'Custom Guides');
win.title.alignment="fill";
var g = win.title.graphics;
g.font = ScriptUI.newFont("Georgia","BOLDITALIC",22);
win.g5 =win.p1.add('group');
win.g5.orientation = "row";
win.g5.alignment='fill';
win.g5.spacing=10;
win.g5.st1 = win.g5.add('statictext',undefined,'Existing Presets');
win.g5.dd1 = win.g5.add('dropdownlist');
win.g5.dd1.preferredSize=[300,20];
for(var w in existingGuidePresets){
win.g5.dd1.add('item',existingGuidePresets.toString().match(/^[A-Za-z0-9 ]+/));
}
win.g5.dd1.selection=0;
win.g10 =win.p1.add('group');
win.g10.orientation = "row";
win.g10.alignment='fill';
win.g10.spacing=10;
win.g10.bu1 = win.g10.add('button',undefined,'Remove Preset');
win.g10.bu2 = win.g10.add('button',undefined,'Use and Append Guides');
win.g10.bu3 = win.g10.add('button',undefined,'Use and Remove Guides');
win.g15 =win.p1.add('group');
win.g15.orientation = "row";
win.g15.alignment='fill';
win.g15.st1 = win.g15.add('statictext',undefined,'New Preset Name');
win.g20 =win.p1.add('group');
win.g20.orientation = "row";
win.g20.alignment='fill';
win.g20.spacing=10;
win.g20.et1 = win.g20.add('edittext');
win.g20.et1.preferredSize=[300,20];
win.g20.bu1 = win.g20.add('button',undefined,'Add New Preset');
win.g200 =win.p1.add('group');
win.g200.orientation = "row";
win.g200.bu1 = win.g200.add('button',undefined,'Cancel');
win.g200.bu1.preferredSize=[350,30];
win.g10.bu1.onClick=function(){//Remove preset
if(existingGuidePresets.length == 0) return;
existingGuidePresets.splice(win.g5.dd1.selection.index,1);
win.g5.dd1.removeAll();
for(var w in existingGuidePresets){
win.g5.dd1.add('item',existingGuidePresets.toString().match(/^[A-Za-z0-9 ]+/));
}
win.g5.dd1.selection=0;
putGuideArray(existingGuidePresets);
}win.g10.bu2.onClick=function(){//Use and append guides
if(existingGuidePresets.length == 0) return;
win.close(0);
var ar1 = existingGuidePresets[win.g5.dd1.selection.index].toString().split('#');
var Hor = ar1[1].toString().split(',');
var Ver = ar1[2].toString().split(',');
for(var H in Hor){
activeDocument.guides.add(Direction.HORIZONTAL,new UnitValue(Number(Hor),'px'));
}
for(var V in Ver){
activeDocument.guides.add(Direction.VERTICAL,new UnitValue(Number(Ver),'px'));
}
}
win.g10.bu3.onClick=function(){//Use and remove existing guides
if(existingGuidePresets.length == 0) return;
win.close(0);
clearGuides();
var ar1 = existingGuidePresets[win.g5.dd1.selection.index].toString().split('#');
var Hor = ar1[1].toString().split(',');
var Ver = ar1[2].toString().split(',');
for(var H in Hor){
activeDocument.guides.add(Direction.HORIZONTAL,new UnitValue(Number(Hor),'px'));
}
for(var V in Ver){
activeDocument.guides.add(Direction.VERTICAL,new UnitValue(Number(Ver),'px'));
}
}
win.g20.bu1.onClick=function(){//New preset
if(win.g20.et1.text == ''){
alert("You need to enter a name for the new preset");
return;
}
win.close(0);
currentGuides = win.g20.et1.text + "#" + gH + "#" + gV;
existingGuidePresets.push(currentGuides);
putGuideArray(existingGuidePresets);
}
win.center();
win.show();
function getGuideArray(){
var xmp;
var newGuideArray=[];
xmp = new XMPMeta( app.activeDocument.xmpMetadata.rawData );
var Count = xmp.countArrayItems(psNamespace, "GuideArray");
for(var i = 1;i <= Count;i++){
newGuideArray.push(xmp.getArrayItem(psNamespace, "GuideArray", i).toString());
}
return newGuideArray;
}
function putGuideArray(gArray){
var xmp;
xmp = new XMPMeta( app.activeDocument.xmpMetadata.rawData );
xmp.deleteProperty(psNamespace, "GuideArray");
for(var g in gArray){
xmp.appendArrayItem(psNamespace, "GuideArray", gArray.toString(), 0, XMPConst.ARRAY_IS_UNORDERED);
}
app.activeDocument.xmpMetadata.rawData = xmp.serialize();
}
function clearGuides() {
var id556 = charIDToTypeID( "Dlt " );
var desc102 = new ActionDescriptor();
var id557 = charIDToTypeID( "null" );
var ref70 = new ActionReference();
var id558 = charIDToTypeID( "Gd " );
var id559 = charIDToTypeID( "Ordn" );
var id560 = charIDToTypeID( "Al " );
ref70.putEnumerated( id558, id559, id560 );
desc102.putReference( id557, ref70 );
executeAction( id556, desc102, DialogModes.NO );
};
}
main();
Copy link to clipboard
Copied
Thanks a lot!
I’ll try to check it out tomorrow morning.
Copy link to clipboard
Copied
Just a couple of amendments to it...
#target photoshop
app.bringToFront();
///////////////////////////////////
// Photoshop CS5 or better
///////////////////////////////////
function main(){
if(!documents.length) return;
var startRulerUnits = app.preferences.rulerUnits;
app.preferences.rulerUnits = Units.PIXELS;
// Set up metadata namespace
if (ExternalObject.AdobeXMPScript == undefined) ExternalObject.AdobeXMPScript = new ExternalObject("lib:AdobeXMPScript");
var psNamespace = "http://ns.ps-scripts.com/1.0/";
var psPrefix = "psscripts:";
XMPMeta.registerNamespace(psNamespace, psPrefix);
existingGuidePresets = [];
existingGuidePresets = getGuideArray();
var guides = app.activeDocument.guides;
var gH = '';
var gV = '';
for( var g = 0; g < guides.length; g++ ){
if(guides
.direction.toString() == 'Direction.HORIZONTAL'){ gH+=(parseInt(guides
.coordinate.value)); gH+=',';
}else{
gV+=(parseInt(guides
.coordinate.value)); gV+=','
}
}
gH=gH.replace(/,$/,'');
gV=gV.replace(/,$/,'');
app.preferences.rulerUnits = startRulerUnits;
var win = new Window( 'dialog', 'Custom Guides' );
g = win.graphics;
var myBrush = g.newBrush(g.BrushType.SOLID_COLOR, [0.99, 0.99, 0.99, 1]);
g.backgroundColor = myBrush;
win.p1= win.add("panel", undefined, undefined, {borderStyle:"black"});
win.g1 = win.p1.add('group');
win.g1.orientation = "row";
win.title = win.g1.add('statictext',undefined,'Custom Guides');
win.title.alignment="fill";
var g = win.title.graphics;
g.font = ScriptUI.newFont("Georgia","BOLDITALIC",22);
win.g5 =win.p1.add('group');
win.g5.orientation = "row";
win.g5.alignment='fill';
win.g5.spacing=10;
win.g5.st1 = win.g5.add('statictext',undefined,'Existing Presets');
win.g5.dd1 = win.g5.add('dropdownlist');
win.g5.dd1.preferredSize=[300,20];
for(var w in existingGuidePresets){
win.g5.dd1.add('item',existingGuidePresets
.toString().match(/[^#]*/)); }
win.g5.dd1.selection=0;
win.g10 =win.p1.add('group');
win.g10.orientation = "row";
win.g10.alignment='fill';
win.g10.spacing=10;
win.g10.bu1 = win.g10.add('button',undefined,'Remove Preset');
win.g10.bu2 = win.g10.add('button',undefined,'Use and Append Guides');
win.g10.bu3 = win.g10.add('button',undefined,'Use and Remove Guides');
win.g15 =win.p1.add('group');
win.g15.orientation = "row";
win.g15.alignment='fill';
win.g15.st1 = win.g15.add('statictext',undefined,'New Preset Name');
win.g20 =win.p1.add('group');
win.g20.orientation = "row";
win.g20.alignment='fill';
win.g20.spacing=10;
win.g20.et1 = win.g20.add('edittext');
win.g20.et1.preferredSize=[300,20];
win.g20.bu1 = win.g20.add('button',undefined,'Add New Preset');
win.g200 =win.p1.add('group');
win.g200.orientation = "row";
win.g200.bu1 = win.g200.add('button',undefined,'Cancel');
win.g200.bu1.preferredSize=[350,30];
win.g10.bu1.onClick=function(){//Remove preset
if(existingGuidePresets.length == 0) return;
existingGuidePresets.splice(win.g5.dd1.selection.index,1);
win.g5.dd1.removeAll();
for(var w in existingGuidePresets){
win.g5.dd1.add('item',existingGuidePresets
.toString().match(/[^#]*/)); }
win.g5.dd1.selection=0;
putGuideArray(existingGuidePresets);
}
win.g10.bu2.onClick=function(){//Use and append guides
if(existingGuidePresets.length == 0) return;
win.close(0);
var ar1 = existingGuidePresets[win.g5.dd1.selection.index].toString().split('#');
var Hor = ar1[1].toString().split(',');
var Ver = ar1[2].toString().split(',');
for(var H in Hor){
activeDocument.guides.add(Direction.HORIZONTAL,new UnitValue(Number(Hor
),'px')); }
for(var V in Ver){
activeDocument.guides.add(Direction.VERTICAL,new UnitValue(Number(Ver
),'px')); }
}
win.g10.bu3.onClick=function(){//Use and remove existing guides
if(existingGuidePresets.length == 0) return;
win.close(0);
clearGuides();
var ar1 = existingGuidePresets[win.g5.dd1.selection.index].toString().split('#');
var Hor = ar1[1].toString().split(',');
var Ver = ar1[2].toString().split(',');
for(var H in Hor){
activeDocument.guides.add(Direction.HORIZONTAL,new UnitValue(Number(Hor
),'px')); }
for(var V in Ver){
activeDocument.guides.add(Direction.VERTICAL,new UnitValue(Number(Ver
),'px')); }
}
win.g20.bu1.onClick=function(){//New preset
if(app.activeDocument.guides.length == 0){
alert("No guides exist");
return;
}
if(win.g20.et1.text == ''){
alert("You need to enter a name for the new preset");
return;
}
win.close(0);
currentGuides = win.g20.et1.text + "#" + gH + "#" + gV;
existingGuidePresets.push(currentGuides);
putGuideArray(existingGuidePresets);
}
win.center();
win.show();
function getGuideArray(){
var xmp;
var newGuideArray=[];
xmp = new XMPMeta( app.activeDocument.xmpMetadata.rawData );
var Count = xmp.countArrayItems(psNamespace, "GuideArray");
for(var i = 1;i <= Count;i++){
newGuideArray.push(xmp.getArrayItem(psNamespace, "GuideArray", i).toString());
}
return newGuideArray;
}
function putGuideArray(gArray){
var xmp;
xmp = new XMPMeta( app.activeDocument.xmpMetadata.rawData );
xmp.deleteProperty(psNamespace, "GuideArray");
for(var g in gArray){
xmp.appendArrayItem(psNamespace, "GuideArray", gArray
.toString(), 0, XMPConst.ARRAY_IS_UNORDERED); }
app.activeDocument.xmpMetadata.rawData = xmp.serialize();
}
function clearGuides() {
var id556 = charIDToTypeID( "Dlt " );
var desc102 = new ActionDescriptor();
var id557 = charIDToTypeID( "null" );
var ref70 = new ActionReference();
var id558 = charIDToTypeID( "Gd " );
var id559 = charIDToTypeID( "Ordn" );
var id560 = charIDToTypeID( "Al " );
ref70.putEnumerated( id558, id559, id560 );
desc102.putReference( id557, ref70 );
executeAction( id556, desc102, DialogModes.NO );
};
}
main();
Copy link to clipboard
Copied
Thank you both, as usual your input has been remarkable.
Paul, maybe you want to point the original poster in the thread I linked to in my original post to your Script.
That thread had some unfortunate impoliteness, but your effort might be appreciated there, too.
Edit: I still don’t quite get the namespace-thing, but I hope I’ll have time to take a closer look at the Script soon.
Thanks again.