diff --git a/PhotoshopEvents/CSXS/manifest.xml b/PhotoshopEvents/CSXS/manifest.xml new file mode 100644 index 00000000..8bd9992b --- /dev/null +++ b/PhotoshopEvents/CSXS/manifest.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + ./index.html + ./host/ps.jsx + + + Panel + PhotoshopEvents + + + 460 + 320 + + + 800 + 1200 + + + 100 + 100 + + + + ./PhotoshopEventsNormal.png + ./PhotoshopEventsRollover.png + + + + + + + + ./index.html + ./host/ps.jsx + + + Panel + PhotoshopEvents 2 + + + 460 + 320 + + + 800 + 1200 + + + 100 + 100 + + + + ./PhotoshopEventsNormal.png + ./PhotoshopEventsRollover.png + + + + + + diff --git a/PhotoshopEvents/PhotoshopEventsNormal.png b/PhotoshopEvents/PhotoshopEventsNormal.png new file mode 100644 index 00000000..65d338ab Binary files /dev/null and b/PhotoshopEvents/PhotoshopEventsNormal.png differ diff --git a/PhotoshopEvents/PhotoshopEventsRollover.png b/PhotoshopEvents/PhotoshopEventsRollover.png new file mode 100644 index 00000000..3378d5f1 Binary files /dev/null and b/PhotoshopEvents/PhotoshopEventsRollover.png differ diff --git a/PhotoshopEvents/host/ps.jsx b/PhotoshopEvents/host/ps.jsx new file mode 100644 index 00000000..c021dd34 --- /dev/null +++ b/PhotoshopEvents/host/ps.jsx @@ -0,0 +1,89 @@ +// Fri May 22 2015 11:56:37 GMT-0700 (Pacific Daylight Time) +var gScriptVersion = "0.1"; + +// some events we are interested in +var eventMake = 1298866208; // "Mk " +var eventDelete = 1147958304; // "Dlt " +var eventClose = 1131180832; // "Cls " +var eventSelect = 1936483188; // "slct" +var eventSet = 1936028772; // "setd" + +function LogIt( inMessage ) { + try { + var a = new Logger(); + var b = decodeURIComponent( inMessage ); + a.log( b + "\n"); + } + catch(e) { + alert("LogIt catch : " + e + ":" + e.line); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// Object: Logger +// Usage: Log information to a text file +// Input: String to full path of file to create or append, if no file is given +// then output file Logger.log is created on the users desktop +// Return: Logger object +// Example: +// +// var a = new Logger(); +// a.print( 'hello' ); +// a.print( 'hello2\n\n\nHi\n' ) ; +// a.remove(); +// a.log( Date() ); +// a.print( Date() ); +// a.display(); +// +/////////////////////////////////////////////////////////////////////////////// +function Logger( inFile ) { + + // member properties + + // the file we are currently logging to + if ( undefined == inFile ) { + this.file = new File( Folder.desktop + "/PhotoshopEvents.log" ); + } else { + this.file = new File( inFile ); + } + + // member methods + + // output to the ESTK console + // note that it behaves a bit differently + // when using the BridgeTalk section + this.print = function( inMessage ) { + if ( app.name == "ExtendScript Toolkit" ) { + print (inMessage); + } else { + var btMessage = new BridgeTalk(); + btMessage.target = "estoolkit"; + btMessage.body = "print(" + inMessage.toSource() + ")"; + btMessage.send (); + } + } + + // write out a message to the log file + this.log = function( inMessage ) { + if ( this.file.exists ) { + this.file.open( 'e' ); + this.file.seek( 0, 2 ); // end of file + } else { + this.file.open( 'w' ); + } + this.file.write( inMessage ); + this.file.close(); + } + + // show the contents with the execute method + this.display = function() { + this.file.execute(); + } + + // remove the file + this.remove = function() { + this.file.remove(); + } +} + +// end ps.jsx diff --git a/PhotoshopEvents/index.html b/PhotoshopEvents/index.html new file mode 100644 index 00000000..60069e32 --- /dev/null +++ b/PhotoshopEvents/index.html @@ -0,0 +1,31 @@ + + + + + +

Photoshop JSON Events v0.1

+ +
+ +
+ +
+ +
+ +
+ +
+
+
+
+ + + + diff --git a/PhotoshopEvents/js/CSInterface.js b/PhotoshopEvents/js/CSInterface.js new file mode 100644 index 00000000..e1e4d7b4 --- /dev/null +++ b/PhotoshopEvents/js/CSInterface.js @@ -0,0 +1,1102 @@ +/************************************************************************************************** +* +* ADOBE SYSTEMS INCORPORATED +* Copyright 2013 Adobe Systems Incorporated +* All Rights Reserved. +* +* NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the +* terms of the Adobe license agreement accompanying it. If you have received this file from a +* source other than Adobe, then your use, modification, or distribution of it requires the prior +* written permission of Adobe. +* +**************************************************************************************************/ + +/** CSInterface - v6.0.0 */ + +/** + * Stores constants for the window types supported by the CSXS infrastructure. + */ +function CSXSWindowType() +{ +}; + +/** Constant for the CSXS window type Panel. */ +CSXSWindowType._PANEL = "Panel"; + +/** Constant for the CSXS window type Modeless. */ +CSXSWindowType._MODELESS = "Modeless"; + +/** Constant for the CSXS window type ModalDialog. */ +CSXSWindowType._MODAL_DIALOG = "ModalDialog"; + +/** EvalScript error message */ +EvalScript_ErrMessage = "EvalScript error."; + +/** + * @class Version + * Defines a version number with major, minor, micro, and special + * components. The major, minor and micro values are numeric; the special + * value can be any string. + * + * @param major The major version component, a positive integer up to nine digits long. + * @param minor The minor version component, a positive integer up to nine digits long. + * @param micro The micro version component, a positive integer up to nine digits long. + * @param special The special version component, an arbitrary string. + * + * @return A new \c Version object. + */ +function Version(major, minor, micro, special) +{ + this.major = major; + this.minor = minor; + this.micro = micro; + this.special = special; +}; + +/** + * The maximum value allowed for a numeric version component. + * This reflects the maximum value allowed in PlugPlug and the manifest schema. + */ +Version.MAX_NUM = 999999999; + +/** + * @class VersionBound + * Defines a boundary for a version range, which associates a \c Version object + * with a flag for whether it is an inclusive or exclusive boundary. + * + * @param version The \c #Version object. + * @param inclusive True if this boundary is inclusive, false if it is exclusive. + * + * @return A new \c VersionBound object. + */ +function VersionBound(version, inclusive) +{ + this.version = version; + this.inclusive = inclusive; +}; + +/** + * @class VersionRange + * Defines a range of versions using a lower boundary and optional upper boundary. + * + * @param lowerBound The \c #VersionBound object. + * @param upperBound The \c #VersionBound object, or null for a range with no upper boundary. + * + * @return A new \c VersionRange object. + */ +function VersionRange(lowerBound, upperBound) +{ + this.lowerBound = lowerBound; + this.upperBound = upperBound; +}; + +/** + * @class Runtime + * Represents a runtime related to the CEP infrastructure. + * Extensions can declare dependencies on particular + * CEP runtime versions in the extension manifest. + * + * @param name The runtime name. + * @param version A \c #VersionRange object that defines a range of valid versions. + * + * @return A new \c Runtime object. + */ +function Runtime(name, versionRange) +{ + this.name = name; + this.versionRange = versionRange; +}; + +/** +* @class Extension +* Encapsulates a CEP-based extension to an Adobe application. +* +* @param id The unique identifier of this extension. +* @param name The localizable display name of this extension. +* @param mainPath The path of the "index.html" file. +* @param basePath The base path of this extension. +* @param windowType The window type of the main window of this extension. + Valid values are defined by \c #CSXSWindowType. +* @param width The default width in pixels of the main window of this extension. +* @param height The default height in pixels of the main window of this extension. +* @param minWidth The minimum width in pixels of the main window of this extension. +* @param minHeight The minimum height in pixels of the main window of this extension. +* @param maxWidth The maximum width in pixels of the main window of this extension. +* @param maxHeight The maximum height in pixels of the main window of this extension. +* @param defaultExtensionDataXml The extension data contained in the default \c ExtensionDispatchInfo section of the extension manifest. +* @param specialExtensionDataXml The extension data contained in the application-specific \c ExtensionDispatchInfo section of the extension manifest. +* @param requiredRuntimeList An array of \c Runtime objects for runtimes required by this extension. +* @param isAutoVisible True if this extension is visible on loading. +* @param isPluginExtension True if this extension has been deployed in the Plugins folder of the host application. +* +* @return A new \c Extension object. +*/ +function Extension(id, name, mainPath, basePath, windowType, width, height, minWidth, minHeight, maxWidth, maxHeight, + defaultExtensionDataXml, specialExtensionDataXml, requiredRuntimeList, isAutoVisible, isPluginExtension) +{ + this.id = id; + this.name = name; + this.mainPath = mainPath; + this.basePath = basePath; + this.windowType = windowType; + this.width = width; + this.height = height; + this.minWidth = minWidth; + this.minHeight = minHeight; + this.maxWidth = maxWidth; + this.maxHeight = maxHeight; + this.defaultExtensionDataXml = defaultExtensionDataXml; + this.specialExtensionDataXml = specialExtensionDataXml; + this.requiredRuntimeList = requiredRuntimeList; + this.isAutoVisible = isAutoVisible; + this.isPluginExtension = isPluginExtension; +}; + +/** + * @class CSEvent + * A standard JavaScript event, the base class for CEP events. + * + * @param type The name of the event type. + * @param scope The scope of event, can be "GLOBAL" or "APPLICATION". + * @param appId The unique identifier of the application that generated the event. + * @param extensionId The unique identifier of the extension that generated the event. + * + * @return A new \c CSEvent object + */ +function CSEvent(type, scope, appId, extensionId) +{ + this.type = type; + this.scope = scope; + this.appId = appId; + this.extensionId = extensionId; +}; + +/** Event-specific data. */ +CSEvent.prototype.data = ""; + +/** + * @class SystemPath + * Stores operating-system-specific location constants for use in the + * \c #CSInterface.getSystemPath() method. + * @return A new \c SystemPath object. + */ +function SystemPath() +{ +}; + +/** The path to user data. */ +SystemPath.USER_DATA = "userData"; + +/** The path to common files for Adobe applications. */ +SystemPath.COMMON_FILES = "commonFiles"; + +/** The path to the user's default document folder. */ +SystemPath.MY_DOCUMENTS = "myDocuments"; + +/** @deprecated. Use \c #SystemPath.Extension. */ +SystemPath.APPLICATION = "application"; + +/** The path to current extension. */ +SystemPath.EXTENSION = "extension"; + +/** The path to hosting application's executable. */ +SystemPath.HOST_APPLICATION = "hostApplication"; + +/** + * @class ColorType + * Stores color-type constants. + */ +function ColorType() +{ +}; + +/** RGB color type. */ +ColorType.RGB = "rgb"; + +/** Gradient color type. */ +ColorType.GRADIENT = "gradient"; + +/** Null color type. */ +ColorType.NONE = "none"; + +/** + * @class RGBColor + * Stores an RGB color with red, green, blue, and alpha values. + * All values are in the range [0.0 to 255.0]. Invalid numeric values are + * converted to numbers within this range. + * + * @param red The red value, in the range [0.0 to 255.0]. + * @param green The green value, in the range [0.0 to 255.0]. + * @param blue The blue value, in the range [0.0 to 255.0]. + * @param alpha The alpha (transparency) value, in the range [0.0 to 255.0]. + * The default, 255.0, means that the color is fully opaque. + * + * @return A new RGBColor object. + */ +function RGBColor(red, green, blue, alpha) +{ + this.red = red; + this.green = green; + this.blue = blue; + this.alpha = alpha; +}; + +/** + * @class Direction + * A point value in which the y component is 0 and the x component + * is positive or negative for a right or left direction, + * or the x component is 0 and the y component is positive or negative for + * an up or down direction. + * + * @param x The horizontal component of the point. + * @param y The vertical component of the point. + * + * @return A new \c Direction object. + */ +function Direction(x, y) +{ + this.x = x; + this.y = y; +}; + +/** + * @class GradientStop + * Stores gradient stop information. + * + * @param offset The offset of the gradient stop, in the range [0.0 to 1.0]. + * @param rgbColor The color of the gradient at this point, an \c #RGBColor object. + * + * @return GradientStop object. + */ +function GradientStop(offset, rgbColor) +{ + this.offset = offset; + this.rgbColor = rgbColor; +}; + +/** + * @class GradientColor + * Stores gradient color information. + * + * @param type The gradient type, must be "linear". + * @param direction A \c #Direction object for the direction of the gradient + (up, down, right, or left). + * @param numStops The number of stops in the gradient. + * @param gradientStopList An array of \c #GradientStop objects. + * + * @return A new \c GradientColor object. + */ +function GradientColor(type, direction, numStops, arrGradientStop) +{ + this.type = type; + this.direction = direction; + this.numStops = numStops; + this.arrGradientStop = arrGradientStop; +}; + +/** + * @class UIColor + * Stores color information, including the type, anti-alias level, and specific color + * values in a color object of an appropriate type. + * + * @param type The color type, 1 for "rgb" and 2 for "gradient". + The supplied color object must correspond to this type. + * @param antialiasLevel The anti-alias level constant. + * @param color A \c #RGBColor or \c #GradientColor object containing specific color information. + * + * @return A new \c UIColor object. + */ +function UIColor(type, antialiasLevel, color) +{ + this.type = type; + this.antialiasLevel = antialiasLevel; + this.color = color; +}; + +/** + * @class AppSkinInfo + * Stores window-skin properties, such as color and font. All color parameter values are \c #UIColor objects except that systemHighlightColor is \c #RGBColor object. + * + * @param baseFontFamily The base font family of the application. + * @param baseFontSize The base font size of the application. + * @param appBarBackgroundColor The application bar background color. + * @param panelBackgroundColor The background color of the extension panel. + * @param appBarBackgroundColorSRGB The application bar background color, as sRGB. + * @param panelBackgroundColorSRGB The background color of the extension panel, as sRGB. + * @param systemHighlightColor The operating-system highlight color, as sRGB. + * + * @return AppSkinInfo object. + */ +function AppSkinInfo(baseFontFamily, baseFontSize, appBarBackgroundColor, panelBackgroundColor, appBarBackgroundColorSRGB, panelBackgroundColorSRGB, systemHighlightColor) +{ + this.baseFontFamily = baseFontFamily; + this.baseFontSize = baseFontSize; + this.appBarBackgroundColor = appBarBackgroundColor; + this.panelBackgroundColor = panelBackgroundColor; + this.appBarBackgroundColorSRGB = appBarBackgroundColorSRGB; + this.panelBackgroundColorSRGB = panelBackgroundColorSRGB; + this.systemHighlightColor = systemHighlightColor; +}; + +/** + * @class HostEnvironment + * Stores information about the environment in which the extension is loaded. + * + * @param appName The application's name. + * @param appVersion The application's version. + * @param appLocale The application's current license locale. + * @param appUILocale The application's current UI locale. + * @param appId The application's unique identifier. + * @param isAppOnline True if the application is currently online. + * @param appSkinInfo An \c #AppSkinInfo object containing the application's default color and font styles. + * + * @return A new \c HostEnvironment object. + */ +function HostEnvironment(appName, appVersion, appLocale, appUILocale, appId, isAppOnline, appSkinInfo) +{ + this.appName = appName; + this.appVersion = appVersion; + this.appLocale = appLocale; + this.appUILocale = appUILocale; + this.appId = appId; + this.isAppOnline = isAppOnline; + this.appSkinInfo = appSkinInfo; +}; + +/** + * @class HostCapabilities + * Stores information about the host capabilities. + * + * @param EXTENDED_PANEL_MENU True if the application supports panel menu. + * @param EXTENDED_PANEL_ICONS True if the application supports panel icon. + * @param DELEGATE_APE_ENGINE True if the application supports delegated APE engine. + * @param SUPPORT_HTML_EXTENSIONS True if the application supports HTML extensions. + * @param DISABLE_FLASH_EXTENSIONS True if the application disables FLASH extensions. + * + * @return A new \c HostCapabilities object. + */ +function HostCapabilities(EXTENDED_PANEL_MENU, EXTENDED_PANEL_ICONS, DELEGATE_APE_ENGINE, SUPPORT_HTML_EXTENSIONS, DISABLE_FLASH_EXTENSIONS) +{ + this.EXTENDED_PANEL_MENU = EXTENDED_PANEL_MENU; + this.EXTENDED_PANEL_ICONS = EXTENDED_PANEL_ICONS; + this.DELEGATE_APE_ENGINE = DELEGATE_APE_ENGINE; + this.SUPPORT_HTML_EXTENSIONS = SUPPORT_HTML_EXTENSIONS; + this.DISABLE_FLASH_EXTENSIONS = DISABLE_FLASH_EXTENSIONS; // Since 5.0.0 +}; + +/** + * @class ApiVersion + * Stores current api version. + * + * Since 4.2.0 + * + * @param major The major version + * @param minor The minor version. + * @param micro The micro version. + * + * @return ApiVersion object. + */ +function ApiVersion(major, minor, micro) +{ + this.major = major; + this.minor = minor; + this.micro = micro; +}; + +/** + * @class MenuItemStatus + * Stores flyout menu item status + * + * Since 5.2.0 + * + * @param menuItemLabel The menu item label. + * @param enabled True if user wants to enable the menu item. + * @param checked True if user wants to check the menu item. + * + * @return MenuItemStatus object. + */ +function MenuItemStatus(menuItemLabel, enabled, checked) +{ + this.menuItemLabel = menuItemLabel; + this.enabled = enabled; + this.checked = checked; +}; + +/** + * @class ContextMenuItemStatus + * Stores the status of the context menu item. + * + * Since 5.2.0 + * + * @param menuItemID The menu item id. + * @param enabled True if user wants to enable the menu item. + * @param checked True if user wants to check the menu item. + * + * @return MenuItemStatus object. + */ +function ContextMenuItemStatus(menuItemID, enabled, checked) +{ + this.menuItemID = menuItemID; + this.enabled = enabled; + this.checked = checked; +}; +//------------------------------ CSInterface ---------------------------------- + +/** + * @class CSInterface + * This is the entry point to the CEP extensibility infrastructure. + * Instantiate this object and use it to: + * + * + * @return A new \c CSInterface object + */ +function CSInterface() +{ +}; + +/** + * User can add this event listener to handle native application theme color changes. + * Callback function gives extensions ability to fine-tune their theme color after the + * global theme color has been changed. + * The callback function should be like below: + * + * @example + * // event is a CSEvent object, but user can ignore it. + * function OnAppThemeColorChanged(event) + * { + * // Should get a latest HostEnvironment object from application. + * var skinInfo = JSON.parse(window.__adobe_cep__.getHostEnvironment()).appSkinInfo; + * // Gets the style information such as color info from the skinInfo, + * // and redraw all UI controls of your extension according to the style info. + * } + */ +CSInterface.THEME_COLOR_CHANGED_EVENT = "com.adobe.csxs.events.ThemeColorChanged"; + +/** The host environment data object. */ +CSInterface.prototype.hostEnvironment = JSON.parse(window.__adobe_cep__.getHostEnvironment()); + +/** Retrieves information about the host environment in which the + * extension is currently running. + * + * @return A \c #HostEnvironment object. + */ +CSInterface.prototype.getHostEnvironment = function() +{ + this.hostEnvironment = JSON.parse(window.__adobe_cep__.getHostEnvironment()); + return this.hostEnvironment; +}; + +/** Closes this extension. */ +CSInterface.prototype.closeExtension = function() +{ + window.__adobe_cep__.closeExtension(); +}; + +/** + * Retrieves a path for which a constant is defined in the system. + * + * @param pathType The path-type constant defined in \c #SystemPath , + * + * @return The platform-specific system path string. + */ +CSInterface.prototype.getSystemPath = function(pathType) +{ + var path = decodeURI(window.__adobe_cep__.getSystemPath(pathType)); + var OSVersion = this.getOSInformation(); + if (OSVersion.indexOf("Windows") >= 0) + { + path = path.replace("file:///", ""); + } + else if (OSVersion.indexOf("Mac") >= 0) + { + path = path.replace("file://", ""); + } + return path; +}; + +/** + * Evaluates a JavaScript script, which can use the JavaScript DOM + * of the host application. + * + * @param script The JavaScript script. + * @param callback Optional. A callback function that receives the result of execution. + * If execution fails, the callback function receives the error message \c EvalScript_ErrMessage. + */ +CSInterface.prototype.evalScript = function(script, callback) +{ + if(callback == null || callback == undefined) + { + callback = function(result){}; + } + window.__adobe_cep__.evalScript(script, callback); +}; + +/** + * Retrieves the unique identifier of the application. + * in which the extension is currently running. + * + * @return The unique ID string. + */ +CSInterface.prototype.getApplicationID = function() +{ + var appId = this.hostEnvironment.appId; + return appId; +}; + +/** + * Retrieves host capability information for the application + * in which the extension is currently running. + * + * @return A \c #HostCapabilities object. + */ +CSInterface.prototype.getHostCapabilities = function() +{ + var hostCapabilities = JSON.parse(window.__adobe_cep__.getHostCapabilities() ); + return hostCapabilities; +}; + +/** + * Triggers a CEP event programmatically. Yoy can use it to dispatch + * an event of a predefined type, or of a type you have defined. + * + * @param event A \c CSEvent object. + */ +CSInterface.prototype.dispatchEvent = function(event) +{ + if (typeof event.data == "object") + { + event.data = JSON.stringify(event.data); + } + + window.__adobe_cep__.dispatchEvent(event); +}; + +/** + * Registers an interest in a CEP event of a particular type, and + * assigns an event handler. + * The event infrastructure notifies your extension when events of this type occur, + * passing the event object to the registered handler function. + * + * @param type The name of the event type of interest. + * @param listener The JavaScript handler function or method. + * @param obj Optional, the object containing the handler method, if any. + * Default is null. + */ +CSInterface.prototype.addEventListener = function(type, listener, obj) +{ + window.__adobe_cep__.addEventListener(type, listener, obj); +}; + +/** + * Removes a registered event listener. + * + * @param type The name of the event type of interest. + * @param listener The JavaScript handler function or method that was registered. + * @param obj Optional, the object containing the handler method, if any. + * Default is null. + */ +CSInterface.prototype.removeEventListener = function(type, listener, obj) +{ + window.__adobe_cep__.removeEventListener(type, listener, obj); +}; + +/** + * Loads and launches another extension, or activates the extension if it is already loaded. + * + * @param extensionId The extension's unique identifier. + * @param startupParams Not currently used, pass "". + * + * @example + * To launch the extension "help" with ID "HLP" from this extension, call: + * requestOpenExtension("HLP", ""); + * + */ +CSInterface.prototype.requestOpenExtension = function(extensionId, params) +{ + window.__adobe_cep__.requestOpenExtension(extensionId, params); +}; + +/** + * Retrieves the list of extensions currently loaded in the current host application. + * The extension list is initialized once, and remains the same during the lifetime + * of the CEP session. + * + * @param extensionIds Optional, an array of unique identifiers for extensions of interest. + * If omitted, retrieves data for all extensions. + * + * @return Zero or more \c #Extension objects. + */ +CSInterface.prototype.getExtensions = function(extensionIds) +{ + var extensionIdsStr = JSON.stringify(extensionIds); + var extensionsStr = window.__adobe_cep__.getExtensions(extensionIdsStr); + + var extensions = JSON.parse(extensionsStr); + return extensions; +}; + +/** + * Retrieves network-related preferences. + * + * @return A JavaScript object containing network preferences. + */ +CSInterface.prototype.getNetworkPreferences = function() +{ + var result = window.__adobe_cep__.getNetworkPreferences(); + var networkPre = JSON.parse(result); + + return networkPre; +}; + +/** + * Initializes the resource bundle for this extension with property values + * for the current application and locale. + * To support multiple locales, you must define a property file for each locale, + * containing keyed display-string values for that locale. + * See localization documentation for Extension Builder and related products. + * + * Keys can be in the + * form key.value="localized string", for use in HTML text elements. + * For example, in this input element, the localized \c key.value string is displayed + * instead of the empty \c value string: + * + * + * + * @return An object containing the resource bundle information. + */ +CSInterface.prototype.initResourceBundle = function() +{ + var resourceBundle = JSON.parse(window.__adobe_cep__.initResourceBundle()); + var resElms = document.querySelectorAll('[data-locale]'); + for (var n = 0; n < resElms.length; n++) + { + var resEl = resElms[n]; + // Get the resource key from the element. + var resKey = resEl.getAttribute('data-locale'); + if (resKey) + { + // Get all the resources that start with the key. + for (var key in resourceBundle) + { + if (key.indexOf(resKey) == 0) + { + var resValue = resourceBundle[key]; + if (key.length == resKey.length) + { + resEl.innerHTML = resValue; + } + else if ('.' == key.charAt(resKey.length)) + { + var attrKey = key.substring(resKey.length + 1); + resEl[attrKey] = resValue; + } + } + } + } + } + return resourceBundle; +}; + +/** + * Writes installation information to a file. + * + * @return The file path. + */ +CSInterface.prototype.dumpInstallationInfo = function() +{ + return window.__adobe_cep__.dumpInstallationInfo(); +}; + +/** + * Retrieves version information for the current Operating System, + * See http://www.useragentstring.com/pages/Chrome/ for Chrome \c navigator.userAgent values. + * + * @return A string containing the OS version, or "unknown Operation System". + * If user customizes the User Agent by setting CEF command parameter "--user-agent", only + * "Mac OS X" or "Windows" will be returned. + */ +CSInterface.prototype.getOSInformation = function() +{ + var userAgent = navigator.userAgent; + + if ((navigator.platform == "Win32") || (navigator.platform == "Windows")) + { + var winVersion = "Windows"; + var winBit = ""; + if (userAgent.indexOf("Windows") > -1) + { + if (userAgent.indexOf("Windows NT 5.0") > -1) + { + winVersion = "Windows 2000 "; + } + else if (userAgent.indexOf("Windows NT 5.1") > -1) + { + winVersion = "Windows XP "; + } + else if (userAgent.indexOf("Windows NT 5.2") > -1) + { + winVersion = "Windows Server 2003 "; + } + else if (userAgent.indexOf("Windows NT 6.0") > -1) + { + winVersion = "Windows Vista "; + } + else if (userAgent.indexOf("Windows NT 6.1") > -1) + { + winVersion = "Windows 7 "; + } + else if (userAgent.indexOf("Windows NT 6.2") > -1) + { + winVersion = "Windows 8 "; + } + + if (userAgent.indexOf("WOW64") > -1) + { + winBit = "64-bit"; + } + else + { + winBit = "32-bit"; + } + } + + return winVersion + winBit; + } + else if ((navigator.platform == "MacIntel") || (navigator.platform == "Macintosh")) + { + var result = "Mac OS X"; + var agentStr = new String(); + agentStr = userAgent; + if (agentStr.indexOf("Mac OS X") > -1) + { + var verLength = agentStr.indexOf(")") - agentStr.indexOf("Mac OS X"); + var verStr = agentStr.substr(agentStr.indexOf("Mac OS X"), verLength); + result = verStr.replace("_", "."); + result = result.replace("_", "."); + } + + return result; + } + + return "Unknown Operation System"; +}; + +/** + * Opens a page in the default system browser. + * + * Since 4.2.0 + * + * @param url The URL of the page/file to open, or the email address. + * Must use HTTP/HTTPS/file/mailto protocol. For example: + * "http://www.adobe.com" + * "https://github.com" + * "file:///C:/log.txt" + * "mailto:test@adobe.com" + * + * @return One of these error codes:\n + * \n + */ +CSInterface.prototype.openURLInDefaultBrowser = function(url) +{ + return cep.util.openURLInDefaultBrowser(url); +}; + +/** + * Retrieves extension ID. + * + * Since 4.2.0 + * + * @return extension ID. + */ +CSInterface.prototype.getExtensionID = function() +{ + return window.__adobe_cep__.getExtensionId(); +}; + +/** + * Retrieves the scale factor of screen. + * On Windows platform, the value of scale factor might be different from operating system's scale factor, + * since host application may use its self-defined scale factor. + * + * Since 4.2.0 + * + * @return One of the following integer. + * \n + */ +CSInterface.prototype.getScaleFactor = function() +{ + return window.__adobe_cep__.getScaleFactor(); +}; + +/** + * Set a handler to detect any changes of scale factor. This only works on Mac. + * + * Since 4.2.0 + * + * @param handler The function to be called when scale factor is changed. + * + */ +CSInterface.prototype.setScaleFactorChangedHandler = function(handler) +{ + window.__adobe_cep__.setScaleFactorChangedHandler(handler); +}; + +/** + * Retrieves current API version. + * + * Since 4.2.0 + * + * @return ApiVersion object. + * + */ +CSInterface.prototype.getCurrentApiVersion = function() +{ + var apiVersion = JSON.parse(window.__adobe_cep__.getCurrentApiVersion()); + return apiVersion; +}; + +/** + * Set panel flyout menu by an XML. + * + * Since 5.2.0 + * + * Register a callback function for "com.adobe.csxs.events.flyoutMenuClicked" to get notified when a + * menu item is clicked. + * The "data" attribute of event is an object which contains "menuId" and "menuName" attributes. + * + * Register callback functions for "com.adobe.csxs.events.flyoutMenuOpened" and "com.adobe.csxs.events.flyoutMenuClosed" + * respectively to get notified when flyout menu is opened or closed. + * + * @param menu A XML string which describes menu structure. + * An example menu XML: + * + * + * + * + * + * + * + * + * + * + * + * + */ +CSInterface.prototype.setPanelFlyoutMenu = function(menu) +{ + if ("string" != typeof menu) + { + return; + } + + window.__adobe_cep__.invokeSync("setPanelFlyoutMenu", menu); +}; + +/** + * Updates a menu item in the extension window's flyout menu, by setting the enabled + * and selection status. + * + * Since 5.2.0 + * + * @param menuItemLabel The menu item label. + * @param enabled True to enable the item, false to disable it (gray it out). + * @param checked True to select the item, false to deselect it. + * + * @return false when the host application does not support this functionality (HostCapabilities.EXTENDED_PANEL_MENU is false). + * Fails silently if menu label is invalid. + * + * @see HostCapabilities.EXTENDED_PANEL_MENU + */ +CSInterface.prototype.updatePanelMenuItem = function(menuItemLabel, enabled, checked) +{ + var ret = false; + if (this.getHostCapabilities().EXTENDED_PANEL_MENU) + { + var itemStatus = new MenuItemStatus(menuItemLabel, enabled, checked); + ret = window.__adobe_cep__.invokeSync("updatePanelMenuItem", JSON.stringify(itemStatus)); + } + return ret; +}; + + +/** + * Set context menu by XML string. + * + * Since 5.2.0 + * + * There are a number of conventions used to communicate what type of menu item to create and how it should be handled. + * - an item without menu ID or menu name is disabled and is not shown. + * - if the item name is "---" (three hyphens) then it is treated as a separator. The menu ID in this case will always be NULL. + * - Checkable attribute takes precedence over Checked attribute. + * - a PNG icon. For optimal display results please supply a 16 x 16px icon as larger dimensions will increase the size of the menu item. + The Chrome extension contextMenus API was taken as a reference. + https://developer.chrome.com/extensions/contextMenus + * - the items with icons and checkable items cannot coexist on the same menu level. The former take precedences over the latter. + * + * @param menu A XML string which describes menu structure. + * @param callback The callback function which is called when a menu item is clicked. The only parameter is the returned ID of clicked menu item. + * + * An example menu XML: + * + * + * + * + * + * + * + * + * + * + * + */ +CSInterface.prototype.setContextMenu = function(menu, callback) +{ + if ("string" != typeof menu) + { + return; + } + + window.__adobe_cep__.invokeAsync("setContextMenu", menu, callback); +}; + +/** + * Set context menu by JSON string. + * + * Since 6.0.0 + * + * There are a number of conventions used to communicate what type of menu item to create and how it should be handled. + * - an item without menu ID or menu name is disabled and is not shown. + * - if the item label is "---" (three hyphens) then it is treated as a separator. The menu ID in this case will always be NULL. + * - Checkable attribute takes precedence over Checked attribute. + * - a PNG icon. For optimal display results please supply a 16 x 16px icon as larger dimensions will increase the size of the menu item. + The Chrome extension contextMenus API was taken as a reference. + * - the items with icons and checkable items cannot coexist on the same menu level. The former take precedences over the latter. + https://developer.chrome.com/extensions/contextMenus + * + * @param menu A JSON string which describes menu structure. + * @param callback The callback function which is called when a menu item is clicked. The only parameter is the returned ID of clicked menu item. + * + * An example menu JSON: + * + * { + * "menu": [ + * { + * "id": "menuItemId1", + * "label": "testExample1", + * "enabled": true, + * "checkable": true, + * "checked": false, + * "icon": "./image/small_16X16.png" + * }, + * { + * "id": "menuItemId2", + * "label": "testExample2", + * "menu": [ + * { + * "id": "menuItemId2-1", + * "label": "testExample2-1", + * "menu": [ + * { + * "id": "menuItemId2-1-1", + * "label": "testExample2-1-1", + * "enabled": false, + * "checkable": true, + * "checked": true + * } + * ] + * }, + * { + * "id": "menuItemId2-2", + * "label": "testExample2-2", + * "enabled": true, + * "checkable": true, + * "checked": true + } + * ] + * }, + * { + * "label": "---" + * }, + * { + * "id": "menuItemId3", + * "label": "testExample3", + * "enabled": false, + * "checkable": true, + * "checked": false + * } + * ] + * } + * + */ +CSInterface.prototype.setContextMenuByJSON = function(menu, callback) +{ + if ("string" != typeof menu) + { + return; + } + + window.__adobe_cep__.invokeAsync("setContextMenuByJSON", menu, callback); +}; + +/** + * Updates a context menu item by setting the enabled and selection status. + * + * Since 5.2.0 + * + * @param menuItemID The menu item ID. + * @param enabled True to enable the item, false to disable it (gray it out). + * @param checked True to select the item, false to deselect it. + */ +CSInterface.prototype.updateContextMenuItem = function(menuItemID, enabled, checked) +{ + var itemStatus = new ContextMenuItemStatus(menuItemID, enabled, checked); + ret = window.__adobe_cep__.invokeSync("updateContextMenuItem", JSON.stringify(itemStatus)); +}; + +/** + * Get the visibility status of an extension window. + * + * Since 6.0.0 + * + * @return true if the extension window is visible; false if the extension window is hidden. + */ +CSInterface.prototype.isWindowVisible = function() +{ + return window.__adobe_cep__.invokeSync("isWindowVisible", ""); +}; + +/** + * Resize extension's content to the specified dimensions. + * 1. Works with modal and modeless extensions in all Adobe products. + * 2. Extension's manifest min/max size constraints apply and take precedence. + * 3. For panel extensions + * 3.1 This works in all Adobe products except: + * * Premiere Pro + * * Prelude + * * After Effects + * 3.2 When the panel is in certain states (especially when being docked), + * it will not change to the desired dimensions even when the + * specified size satisfies min/max constraints. + * + * Since 6.0.0 + * + * @param width The new width + * @param height The new height + */ +CSInterface.prototype.resizeContent = function(width, height) +{ + window.__adobe_cep__.resizeContent(width, height); +}; \ No newline at end of file diff --git a/PhotoshopEvents/js/main.js b/PhotoshopEvents/js/main.js new file mode 100644 index 00000000..371ec51b --- /dev/null +++ b/PhotoshopEvents/js/main.js @@ -0,0 +1,240 @@ +// Fri May 22 2015 11:56:37 GMT-0700 (Pacific Daylight Time) +try { + +// globals +var gScriptJSVersion = "0.1"; +var gAlertsOn = true; + +var gStartDate = new Date(); +var gEndDate = new Date(); + +// Get a reference to a CSInterface object +var csInterface = new CSInterface(); + +var gExtensionID = csInterface.getExtensionID(); + +// some events we are interested in +var eventMake = 1298866208; // "Mk " +var eventDelete = 1147958304; // "Dlt " +var eventClose = 1131180832; // "Cls " +var eventSelect = 1936483188; // "slct" +var eventSet = 1936028772; // "setd" + +var gRegisteredEvents = [eventMake, eventDelete, eventClose, eventSelect, eventSet]; + +// all callbacks need to be unique so only your panel gets them +// for Photoshop specific add on the id of your extension +csInterface.addEventListener("com.adobe.PhotoshopJSONCallback" + gExtensionID, PhotoshopCallbackUnique); + +// get all my UI items +var cbMake = window.document.getElementById("cbMake"); +var lblMake = window.document.getElementById("lblMake"); +var cbDelete = window.document.getElementById("cbDelete"); +var lblDelete = window.document.getElementById("lblDelete"); +var cbClose = window.document.getElementById("cbClose"); +var lblClose = window.document.getElementById("lblClose"); +var cbSelect = window.document.getElementById("cbSelect"); +var lblSelect = window.document.getElementById("lblSelect"); +var cbSet = window.document.getElementById("cbSet"); +var lblSet = window.document.getElementById("lblSet"); +var lblResult = window.document.getElementById("lblResult"); +var lblTiming = window.document.getElementById("lblTiming"); + +// set up handlers, some are defined in HTML as well +btnClose.onclick = function() { + Register(false, gRegisteredEvents.toString()); + Persistent(false); + if (window.__adobe_cep__) { + window.__adobe_cep__.closeExtension(); + } +}; + +// event to handle when a checkbox is clicked +function EventClick(inCheckbox) { + try { + var uiItem = null; + var eventID = 0; + if (inCheckbox === cbMake) { + uiItem = cbMake; + eventID = eventMake; + } else if (inCheckbox === cbDelete) { + uiItem = cbDelete; + eventID = eventDelete; + } else if (inCheckbox === cbClose) { + uiItem = cbClose; + eventID = eventClose; + } else if (inCheckbox === cbSelect) { + uiItem = cbSelect; + eventID = eventSelect; + } else if (inCheckbox === cbSet) { + uiItem = cbSet; + eventID = eventSet; + } + if (uiItem !== null) { + Register(uiItem.checked, eventID.toString()); + } + // TODO remove or add the event into the gRegisteredEvents array + } + catch(e) { + JSLogIt("EventClick catch:" + e); + } +} + +// Tell Photoshop to not unload us when closed +function Persistent(inOn) { + gStartDate = new Date(); + var event; + if (inOn) { + event = new CSEvent("com.adobe.PhotoshopPersistent", "APPLICATION"); + } else { + event = new CSEvent("com.adobe.PhotoshopUnPersistent", "APPLICATION"); + } + event.extensionId = gExtensionID; + csInterface.dispatchEvent(event); + SetResultTime(); +} + +// Tell Photoshop the events we want to listen for +function Register(inOn, inEvents) { + gStartDate = new Date(); + var event; + if (inOn) { + event = new CSEvent("com.adobe.PhotoshopRegisterEvent", "APPLICATION"); + } else { + event = new CSEvent("com.adobe.PhotoshopUnRegisterEvent", "APPLICATION"); + } + event.extensionId = gExtensionID; + event.data = inEvents; + csInterface.dispatchEvent(event); + SetResultLabel("Register: " + inOn); +} + +function SetResultLabel(inStr) { + lblResult.innerHTML = inStr; +} + +function SetResultTime() { + gEndDate = new Date(); + lblTiming.innerHTML = ((gEndDate - gStartDate)/1000).toString(); +} + +// When an event occurs we get called here +// It is a JSON string hidden in a string (bug in Photoshop) +// Remove the header and make an object out of it +// Here is an example event for when a new doucment was created: +/* + { "eventID":1298866208, + "eventData": + { "documentID":1566, + "new": + { "_obj":"document", + "depth":8, + "fill": + { "_enum":"fill", + "_value":"white" + }, + "height": + { "_unit":"distanceUnit", + "_value":360 + }, + "mode": + { "_class":"RGBColorMode" + }, + "pixelScaleFactor":1, + "profile":"sRGB IEC61966-2.1", + "resolution": + { "_unit":"densityUnit", + "_value":300 + }, + "width": + { "_unit":"distanceUnit", + "_value":504 + } + } + } + } +*/ +function PhotoshopCallbackUnique(csEvent) { + try { + if (typeof csEvent.data === "string") { + var eventData = csEvent.data.replace("ver1,{", "{"); + var eventDataParse = JSON.parse(eventData); + var jsonStringBack = JSON.stringify(eventDataParse); + SetResultLabel("PhotoshopCallbackUnique: " + jsonStringBack); + JSLogIt("PhotoshopCallbackUnique: " + jsonStringBack); + + var uiItemToUpdate = null; + if (eventDataParse.eventID === eventMake) + uiItemToUpdate = lblMake; + else if (eventDataParse.eventID === eventDelete) + uiItemToUpdate = lblDelete; + else if (eventDataParse.eventID === eventClose) + uiItemToUpdate = lblClose; + else if (eventDataParse.eventID === eventSelect) + uiItemToUpdate = lblSelect; + else if (eventDataParse.eventID === eventSet) + uiItemToUpdate = lblSet; + + if (uiItemToUpdate !== null) { + var count = Number(uiItemToUpdate.innerHTML) + 1; + uiItemToUpdate.innerHTML = " " + count; + } + + // if you just made a text layer, let me check my object for something + // interesting to dump to log + if (eventDataParse && + eventDataParse.eventData.null && + eventDataParse.eventData.null._ref && + eventDataParse.eventData.null._ref === "textLayer") { + JSLogIt("Got a text layer, trying to find paragraphStyleRange"); + if (eventDataParse.eventData.using && + eventDataParse.eventData.using.paragraphStyleRange) { + JSLogIt("paragraphStyleRange:" + eventDataParse.eventData.using.paragraphStyleRange); + JSLogIt("paragraphStyleRange typeof :" + typeof eventDataParse.eventData.using.paragraphStyleRange); + JSLogIt("paragraphStyleRange[0].from: " + eventDataParse.eventData.using.paragraphStyleRange[0].from); + } + } + } else { + JSLogIt("PhotoshopCallbackUnique expecting string for csEvent.data!"); + } + } catch(e) { + JSLogIt("PhotoshopCallbackUnique catch:" + e); + } +} + +// Initialize my panel for first view +function Initialize() { + try { + document.body.style.backgroundColor = "#" + UIColorToHexString(csInterface.hostEnvironment.appSkinInfo.panelBackgroundColor); + Persistent(true); + Register(true, gRegisteredEvents.toString()); + SetResultLabel("Initialize done"); + SetResultTime(); + } catch(e) { + JSLogIt("InitializeCallback catch: " + e); + } +} + +function UIColorToHexString(inUIColor) { + var s = ""; + try { + if (typeof inUIColor == "undefined") return "undefined"; + if (inUIColor.type != 1) return "type:" + inUIColor.type; + s += inUIColor.color.red.toString(16); + s += inUIColor.color.green.toString(16); + s += inUIColor.color.blue.toString(16); + } catch(e) { + s = e.toString(); + } + return s; +} + +function JSLogIt(inMessage) { + csInterface.evalScript("LogIt('" + inMessage + "')"); +} + +} // global try +catch(e) { + JSLogIt("Global catch : " + e); +} +// end main.js