Mini Kabibi Habibi
// copyright 2010 Adobe Systems, Inc. All rights reserved.
// Written by Tai Luxon
// Adapted to be an import helper for PresetImportExport.jsx by Barkin Aygun
/*
@@@BUILDINFO@@@ WorkspaceImportExport.jsx 1.0.7
*/
/*
A few notes about this script:
General:
- Prevents importing workspaces with the same names as preset workspaces (filename or display name)
- Allows you to overwrite custom workspaces after asking you
- Handles importing over the current workspace
- Reloads the workspace list after importing
- Does not verify that files are valid or compatible workspace files when importing
Localization
- Should work in localized builds
- In localized builds, we can't prevent importing a workspace that conflicts with the localized
name of a "deleted" preset workspace
Version Compatibility
- Updated to only work for 14.0 since it is only intended to be run from the required folder via the
built in command.
*/
// Imports the provided files as workspaces, after checking for name collisions
function ImportWorkspaces(files)
{
// may get an empty list
if (files == null)
return;
var userConflicts = new Array();
var presetConflicts = new Array();
for (var i = files.length - 1; i >= 0 ; --i)
{
/* var file = files[i];
var msg = "absoluteURI: " + file.absoluteURI +
"\ndisplayName: " + file.displayName +
"\nfsName: " + file.fsName +
"\nfullName: " + file.fullName +
"\nlocalizedName: " + file.localizedName +
"\nname: " + file.name +
"\npath: " + file.path +
"\nrelativeURI: " + file.relativeURI;
alert (msg);*/
// If the workspace conflicts with a preset or user workspace, push it onto the beginning
// of the relevant array, and remove it from 'files'.
// Pass non-URI formatted names
if (PresetWorkspaceWithNameExists (decodeURI(files[i].name)))
{
presetConflicts.unshift(files[i]);
files.splice(i, 1);
}
else if (UserWorkspaceWithNameExists(decodeURI(files[i].name)))
{
userConflicts.unshift(files[i]);
files.splice(i, 1);
}
}
// If any of the files conflict with preset workspaces, we skip them.
// If any of the files conflict with user workspaces, we ask user if they want to replace them.
if (presetConflicts.length > 0)
{
// Right now we silently skip any workspaces that conflict with preset workspaces.
// We could copy them as the "modified" state of preset workspaces instead.
// To do that we would want to:
//
// 1. Potentially warn, like down below.
//
// 2. Call a modified ImportScreenedWorkspaceFiles with presetConflicts which
// copies them to a different target and handles a successful copy differently
// (want to re-load the workspace, but not reset it, which I don't think our
// DOM supports right now).
//
// - tluxon 11.8.13
}
if (userConflicts.length > 0)
{
// Mimic our parent script code, which may have already shown this message
if (!askedToReplace)
{
replaceExisting = confirm(msgReplaceFiles);
askedToReplace = true;
}
// If the user wants to import the user conflicts, add them back to the 'files' array
if (replaceExisting)
files = files.concat(userConflicts);
}
// All files canceled or conflicting
if (files.length == 0)
return false;
// Ok, let's import!
var didCopy = ImportScreenedWorkspaceFiles(files);
// Make PS reload the workspaces so they show up
if (didCopy)
ReloadWorkspaces();
return didCopy;
}
// Import the provided files as workspaces. All files in 'files' should already have been
// verified as not conflicting with preset workspaces and either not conflicting with user
// workspaces or ok'd to overwrite user workspaces.
function ImportScreenedWorkspaceFiles(files)
{
var resultObj = new Object();
resultObj.copiedAtLeastOne = false;
// Grab folders outside the loop
var userFolder = GetUserWorkspacesFolder();
var modifiedFolder = GetModifiedWorkspacesFolder();
for (var i = files.length - 1; i >= 0 ; --i)
{
app.doProgressSubTask(i, files.length, "ImportScreenedWorkspaceFile(files[i], userFolder, modifiedFolder, resultObj)");
}
return resultObj.copiedAtLeastOne;
}
function ImportScreenedWorkspaceFile(file, userFolder, modifiedFolder, outResult)
{
var decodedFilename = decodeURI(file.name);
// Extensions were added to workspace files in 15.0, so add extension during copy / remove
// to ensure we are overwriting the existing one if there is one.
var decodedFilenameWithExt = EnsureWorkspaceExtension (decodedFilename);
var targetFile = new File(userFolder.fsName + "/" + decodedFilenameWithExt);
var copySucceeded = file.copy(targetFile);
if (copySucceeded)
{
outResult.copiedAtLeastOne = true;
// The copy succeeded. If we are copying over an existing workspace, reset it.
// This does two things:
// 1. Make sure we delete any "modified" file that may be around so we load the newly
// imported version of a workspace next time it is selected.
// 2. If we imported over the current workspace, reload it now.
// If it is not an existing workspace, just make sure we delete any modified version
// that may be lying around.
// The filename without extension should be the displayname for user workspaces, which
// is what we are creating, so it works for resetting the workspace.
if (IsLoadedWorkspace(decodedFilename))
ResetWorkspace (decodedFilename);
else
{
var modifiedFile = new File (modifiedFolder.fsName + "/" + decodedFilenameWithExt);
if (modifiedFile.exists)
modifiedFile.remove();
}
}
}
// Concatenates all the filenames in an array so that they can be output for the user.
function ConcatFileNamesFromFileArray(files)
{
var rv = '';
for (var i = 0; i < files.length; ++i)
{
if (i > 0)
rv += "\n";
// decode URI to make spaces, etc user friendly
rv += "\t" + decodeURI(files[i].name);
}
return rv;
}
// Ensures .psw extension on filename
function EnsureWorkspaceExtension (filename)
{
var extension = ".psw";
if (filename.indexOf(extension, filename.length - extension.length) !== -1)
{
return filename;
}
else
{
return filename + extension;
}
}
// Determines if there is a preset workspace with the given filename
function PresetWorkspaceWithNameExists(filename)
{
// Extensions were added to workspace files in 15.0, so ensure that we are looking for files
// with extensions when looking for conflicts in the folders.
var filenameWithExt = EnsureWorkspaceExtension (filename);
// special-case Essentials
if (filenameWithExt == "Essentials.psw")
return true;
// Test against preset workspace files
if (FolderContainsFile(GetPresetWorkspacesFolder(), filenameWithExt))
return true;
// Test against localized preset workspace files
if (FolderContainsFile(GetLocalizedPresetWorkspacesFolder(), filenameWithExt))
return true;
// If we are in a localized build, check against the display names of loaded presets
// which will be different than the filenames, but which we'd also like to avoid
// conflicts with. We can't check for conflicts with display names of "deleted" presets.
if (app.locale != 'en_US')
{
// Get loaded preset workspaces
var wsList = GetWorkspaceList(false, true);
for (var i = 0; i < wsList.length; ++i)
{
if (wsList[i].displayName.toLowerCase() == filename.toLowerCase())
return true;
}
}
// We couldn't find one!
return false;
}
// Determines if there is a user workspace with the given filename
function UserWorkspaceWithNameExists(filename)
{
// Extensions were added to workspace files in 15.0, so ensure that we are looking for files
// with extensions when looking for conflicts in the folders.
var filenameWithExt = EnsureWorkspaceExtension (filename);
var userFolder = GetUserWorkspacesFolder();
return FolderContainsFile(userFolder, filenameWithExt);
}
// Returns true if Photoshop has a workspace in its list of loaded workspaces with the given filename
function IsLoadedWorkspace(filename)
{
var wsList = GetWorkspaceList(true, true);
for (var i = 0; i < wsList.length; ++i)
{
if (decodeURI(wsList[i].filename).toLowerCase() == filename.toLowerCase())
return true;
}
return false;
}
// filename should NOT be in URI format
function FolderContainsFile(folder, filename)
{
var matchingFiles = folder.getFiles(filename);
// Base Case.
// We got back a match in this folder, confirm we have a matching File, not just a Folder or
// a file that contains the filename but isn't the same
if (matchingFiles.length > 0)
{
for (var i = 0; i < matchingFiles.length; ++i)
{
if ((matchingFiles[i] instanceof File) &&
(decodeURI(matchingFiles[i].name).toLowerCase() == filename.toLowerCase()))
return true;
}
}
// Recursive Case
// Search subfolders.
var subfolders = folder.getFiles(IsFolder);
for (var i = 0; i < subfolders.length; ++i)
{
if (FolderContainsFile(subfolders[i], filename))
return true;
}
return false;
}
// Returns true if the provided object is a Folder object
function IsFolder(object)
{
return object instanceof Folder;
}
// Gets the folder where preset workspaces live
function GetLocalizedPresetWorkspacesFolder()
{
var platform = $.os.charAt(0) == 'M' ? 'Mac' : 'Win';
var folder = new Folder (app.path + "/Locales/" + app.locale + "/Additional Presets/" +
platform + "/Workspaces");
return folder;
}
// Gets the folder where preset workspaces live
function GetPresetWorkspacesFolder()
{
var appFolder = { Windows: app.path, Macintosh: BridgeTalk.getAppPath() + "/Contents" };
var folder = new Folder (appFolder[File.fs] + "/Required/Workspaces");
return folder;
}
// Gets the folder where the 'original' versions of user workspace files live.
function GetUserWorkspacesFolder()
{
var settingsFolder = new Folder (app.preferencesFolder);
if (!settingsFolder.exists)
settingsFolder.create ();
var folder = new Folder (settingsFolder.fsName + "/WorkSpaces");
if (!folder.exists)
folder.create();
return folder;
}
// Gets the folder where the 'modified' versions of workspace files live.
function GetModifiedWorkspacesFolder()
{
var settingsFolder = new Folder (app.preferencesFolder);
if (!settingsFolder.exists)
settingsFolder.create ();
var folder = new Folder (settingsFolder.fsName + "/WorkSpaces (Modified)");
if (!folder.exists)
folder.create();
return folder;
}
// Gets the list of Photoshop workspaces
function GetWorkspaceList(includeUser, includePreset)
{
var wsList = new Array();
// Request the workspace list from Photoshop
var workspaceList = stringIDToTypeID( "workspaceList" );
var typeOrdinal = charIDToTypeID( "Ordn" );
var enumTarget = charIDToTypeID( "Trgt" );
var classProperty = charIDToTypeID( "Prpr" );
var classApplication = charIDToTypeID( "capp" );
var ref = new ActionReference();
ref.putProperty( classProperty, workspaceList );
ref.putEnumerated( classApplication, typeOrdinal, enumTarget );
var desc = executeActionGet( ref );
var descList = desc.getList( workspaceList );
// Convert to a friendly list
var displayName = stringIDToTypeID( "displayName" );
var filename = stringIDToTypeID( "name" );
var userWorkspace = stringIDToTypeID( "user" );
for (var i = 0; i < descList.count; ++i)
{
var wsDesc = descList.getObjectValue( i );
var workspace = new Object;
workspace.displayName = wsDesc.getString( displayName );
workspace.filename = wsDesc.getString( filename );
workspace.user = wsDesc.getBoolean( userWorkspace );
if ((includeUser && workspace.user) || (includePreset && !workspace.user))
wsList.push (workspace);
}
return wsList;
}
// Resets the named workspace.
function ResetWorkspace(displayName)
{
var idRset = charIDToTypeID( "Rset" );
var desc4 = new ActionDescriptor();
var idnull = charIDToTypeID( "null" );
var ref3 = new ActionReference();
var idworkspace = stringIDToTypeID( "workspace" );
ref3.putName( idworkspace, displayName );
desc4.putReference( idnull, ref3 );
executeAction( idRset, desc4, DialogModes.NO );
}
// Makes PS reload the workspaces so they show up in the switcher and menus.
function ReloadWorkspaces()
{
var idDlt = stringIDToTypeID( "load" );
var desc3 = new ActionDescriptor();
var idnull = charIDToTypeID( "null" );
var ref2 = new ActionReference();
var idworkspace = stringIDToTypeID( "workspace" );
ref2.putClass( idworkspace );
desc3.putReference( idnull, ref2 );
executeAction( idDlt, desc3, DialogModes.NO );
}