This is page 3 of 6. Use http://codebase.md/mikechambers/adb-mcp?lines=true&page={x} to view the full context. # Directory Structure ``` ├── .gitattributes ├── .gitignore ├── adb-proxy-socket │ ├── .gitignore │ ├── package-lock.json │ ├── package.json │ ├── proxy.js │ └── README.md ├── cep │ ├── com.mikechambers.ae │ │ ├── .debug │ │ ├── commands.js │ │ ├── CSXS │ │ │ └── manifest.xml │ │ ├── index.html │ │ ├── jsx │ │ │ └── json-polyfill.jsx │ │ ├── lib │ │ │ └── CSInterface.js │ │ ├── main.js │ │ └── style.css │ └── com.mikechambers.ai │ ├── .debug │ ├── commands.js │ ├── CSXS │ │ └── manifest.xml │ ├── index.html │ ├── jsx │ │ ├── json-polyfill.jsx │ │ └── utils.jsx │ ├── lib │ │ └── CSInterface.js │ ├── main.js │ └── style.css ├── dxt │ ├── build │ ├── pr │ │ └── manifest.json │ └── ps │ └── manifest.json ├── images │ └── claud-attach-mcp.png ├── LICENSE.md ├── mcp │ ├── .gitignore │ ├── ae-mcp.py │ ├── ai-mcp.py │ ├── core.py │ ├── fonts.py │ ├── id-mcp.py │ ├── logger.py │ ├── pr-mcp.py │ ├── ps-batch-play.py │ ├── ps-mcp.py │ ├── pyproject.toml │ ├── requirements.txt │ ├── socket_client.py │ └── uv.lock ├── package-lock.json ├── README.md └── uxp ├── id │ ├── commands │ │ └── index.js │ ├── icons │ │ ├── [email protected] │ │ ├── [email protected] │ │ ├── [email protected] │ │ └── [email protected] │ ├── index.html │ ├── LICENSE │ ├── main.js │ ├── manifest.json │ ├── package.json │ ├── socket.io.js │ └── style.css ├── pr │ ├── commands │ │ ├── consts.js │ │ ├── core.js │ │ ├── index.js │ │ └── utils.js │ ├── icons │ │ ├── [email protected] │ │ ├── [email protected] │ │ ├── [email protected] │ │ └── [email protected] │ ├── index.html │ ├── LICENSE │ ├── main.js │ ├── manifest.json │ ├── package.json │ ├── socket.io.js │ └── style.css └── ps ├── commands │ ├── adjustment_layers.js │ ├── core.js │ ├── filters.js │ ├── index.js │ ├── layer_styles.js │ ├── layers.js │ ├── selection.js │ └── utils.js ├── icons │ ├── [email protected] │ ├── [email protected] │ ├── [email protected] │ └── [email protected] ├── index.html ├── LICENSE ├── main.js ├── manifest.json ├── package.json ├── socket.io.js └── style.css ``` # Files -------------------------------------------------------------------------------- /cep/com.mikechambers.ae/lib/CSInterface.js: -------------------------------------------------------------------------------- ```javascript 1 | /************************************************************************************************** 2 | * 3 | * ADOBE SYSTEMS INCORPORATED 4 | * Copyright 2020 Adobe Systems Incorporated 5 | * All Rights Reserved. 6 | * 7 | * NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the 8 | * terms of the Adobe license agreement accompanying it. If you have received this file from a 9 | * source other than Adobe, then your use, modification, or distribution of it requires the prior 10 | * written permission of Adobe. 11 | * 12 | **************************************************************************************************/ 13 | 14 | /** CSInterface - v12.0.0 */ 15 | 16 | /** 17 | * Stores constants for the window types supported by the CSXS infrastructure. 18 | */ 19 | function CSXSWindowType() 20 | { 21 | } 22 | 23 | /** Constant for the CSXS window type Panel. */ 24 | CSXSWindowType._PANEL = "Panel"; 25 | 26 | /** Constant for the CSXS window type Modeless. */ 27 | CSXSWindowType._MODELESS = "Modeless"; 28 | 29 | /** Constant for the CSXS window type ModalDialog. */ 30 | CSXSWindowType._MODAL_DIALOG = "ModalDialog"; 31 | 32 | /** EvalScript error message */ 33 | EvalScript_ErrMessage = "EvalScript error."; 34 | 35 | /** 36 | * @class Version 37 | * Defines a version number with major, minor, micro, and special 38 | * components. The major, minor and micro values are numeric; the special 39 | * value can be any string. 40 | * 41 | * @param major The major version component, a positive integer up to nine digits long. 42 | * @param minor The minor version component, a positive integer up to nine digits long. 43 | * @param micro The micro version component, a positive integer up to nine digits long. 44 | * @param special The special version component, an arbitrary string. 45 | * 46 | * @return A new \c Version object. 47 | */ 48 | function Version(major, minor, micro, special) 49 | { 50 | this.major = major; 51 | this.minor = minor; 52 | this.micro = micro; 53 | this.special = special; 54 | } 55 | 56 | /** 57 | * The maximum value allowed for a numeric version component. 58 | * This reflects the maximum value allowed in PlugPlug and the manifest schema. 59 | */ 60 | Version.MAX_NUM = 999999999; 61 | 62 | /** 63 | * @class VersionBound 64 | * Defines a boundary for a version range, which associates a \c Version object 65 | * with a flag for whether it is an inclusive or exclusive boundary. 66 | * 67 | * @param version The \c #Version object. 68 | * @param inclusive True if this boundary is inclusive, false if it is exclusive. 69 | * 70 | * @return A new \c VersionBound object. 71 | */ 72 | function VersionBound(version, inclusive) 73 | { 74 | this.version = version; 75 | this.inclusive = inclusive; 76 | } 77 | 78 | /** 79 | * @class VersionRange 80 | * Defines a range of versions using a lower boundary and optional upper boundary. 81 | * 82 | * @param lowerBound The \c #VersionBound object. 83 | * @param upperBound The \c #VersionBound object, or null for a range with no upper boundary. 84 | * 85 | * @return A new \c VersionRange object. 86 | */ 87 | function VersionRange(lowerBound, upperBound) 88 | { 89 | this.lowerBound = lowerBound; 90 | this.upperBound = upperBound; 91 | } 92 | 93 | /** 94 | * @class Runtime 95 | * Represents a runtime related to the CEP infrastructure. 96 | * Extensions can declare dependencies on particular 97 | * CEP runtime versions in the extension manifest. 98 | * 99 | * @param name The runtime name. 100 | * @param version A \c #VersionRange object that defines a range of valid versions. 101 | * 102 | * @return A new \c Runtime object. 103 | */ 104 | function Runtime(name, versionRange) 105 | { 106 | this.name = name; 107 | this.versionRange = versionRange; 108 | } 109 | 110 | /** 111 | * @class Extension 112 | * Encapsulates a CEP-based extension to an Adobe application. 113 | * 114 | * @param id The unique identifier of this extension. 115 | * @param name The localizable display name of this extension. 116 | * @param mainPath The path of the "index.html" file. 117 | * @param basePath The base path of this extension. 118 | * @param windowType The window type of the main window of this extension. 119 | Valid values are defined by \c #CSXSWindowType. 120 | * @param width The default width in pixels of the main window of this extension. 121 | * @param height The default height in pixels of the main window of this extension. 122 | * @param minWidth The minimum width in pixels of the main window of this extension. 123 | * @param minHeight The minimum height in pixels of the main window of this extension. 124 | * @param maxWidth The maximum width in pixels of the main window of this extension. 125 | * @param maxHeight The maximum height in pixels of the main window of this extension. 126 | * @param defaultExtensionDataXml The extension data contained in the default \c ExtensionDispatchInfo section of the extension manifest. 127 | * @param specialExtensionDataXml The extension data contained in the application-specific \c ExtensionDispatchInfo section of the extension manifest. 128 | * @param requiredRuntimeList An array of \c Runtime objects for runtimes required by this extension. 129 | * @param isAutoVisible True if this extension is visible on loading. 130 | * @param isPluginExtension True if this extension has been deployed in the Plugins folder of the host application. 131 | * 132 | * @return A new \c Extension object. 133 | */ 134 | function Extension(id, name, mainPath, basePath, windowType, width, height, minWidth, minHeight, maxWidth, maxHeight, 135 | defaultExtensionDataXml, specialExtensionDataXml, requiredRuntimeList, isAutoVisible, isPluginExtension) 136 | { 137 | this.id = id; 138 | this.name = name; 139 | this.mainPath = mainPath; 140 | this.basePath = basePath; 141 | this.windowType = windowType; 142 | this.width = width; 143 | this.height = height; 144 | this.minWidth = minWidth; 145 | this.minHeight = minHeight; 146 | this.maxWidth = maxWidth; 147 | this.maxHeight = maxHeight; 148 | this.defaultExtensionDataXml = defaultExtensionDataXml; 149 | this.specialExtensionDataXml = specialExtensionDataXml; 150 | this.requiredRuntimeList = requiredRuntimeList; 151 | this.isAutoVisible = isAutoVisible; 152 | this.isPluginExtension = isPluginExtension; 153 | } 154 | 155 | /** 156 | * @class CSEvent 157 | * A standard JavaScript event, the base class for CEP events. 158 | * 159 | * @param type The name of the event type. 160 | * @param scope The scope of event, can be "GLOBAL" or "APPLICATION". 161 | * @param appId The unique identifier of the application that generated the event. 162 | * @param extensionId The unique identifier of the extension that generated the event. 163 | * 164 | * @return A new \c CSEvent object 165 | */ 166 | function CSEvent(type, scope, appId, extensionId) 167 | { 168 | this.type = type; 169 | this.scope = scope; 170 | this.appId = appId; 171 | this.extensionId = extensionId; 172 | } 173 | 174 | /** Event-specific data. */ 175 | CSEvent.prototype.data = ""; 176 | 177 | /** 178 | * @class SystemPath 179 | * Stores operating-system-specific location constants for use in the 180 | * \c #CSInterface.getSystemPath() method. 181 | * @return A new \c SystemPath object. 182 | */ 183 | function SystemPath() 184 | { 185 | } 186 | 187 | /** The path to user data. */ 188 | SystemPath.USER_DATA = "userData"; 189 | 190 | /** The path to common files for Adobe applications. */ 191 | SystemPath.COMMON_FILES = "commonFiles"; 192 | 193 | /** The path to the user's default document folder. */ 194 | SystemPath.MY_DOCUMENTS = "myDocuments"; 195 | 196 | /** @deprecated. Use \c #SystemPath.Extension. */ 197 | SystemPath.APPLICATION = "application"; 198 | 199 | /** The path to current extension. */ 200 | SystemPath.EXTENSION = "extension"; 201 | 202 | /** The path to hosting application's executable. */ 203 | SystemPath.HOST_APPLICATION = "hostApplication"; 204 | 205 | /** 206 | * @class ColorType 207 | * Stores color-type constants. 208 | */ 209 | function ColorType() 210 | { 211 | } 212 | 213 | /** RGB color type. */ 214 | ColorType.RGB = "rgb"; 215 | 216 | /** Gradient color type. */ 217 | ColorType.GRADIENT = "gradient"; 218 | 219 | /** Null color type. */ 220 | ColorType.NONE = "none"; 221 | 222 | /** 223 | * @class RGBColor 224 | * Stores an RGB color with red, green, blue, and alpha values. 225 | * All values are in the range [0.0 to 255.0]. Invalid numeric values are 226 | * converted to numbers within this range. 227 | * 228 | * @param red The red value, in the range [0.0 to 255.0]. 229 | * @param green The green value, in the range [0.0 to 255.0]. 230 | * @param blue The blue value, in the range [0.0 to 255.0]. 231 | * @param alpha The alpha (transparency) value, in the range [0.0 to 255.0]. 232 | * The default, 255.0, means that the color is fully opaque. 233 | * 234 | * @return A new RGBColor object. 235 | */ 236 | function RGBColor(red, green, blue, alpha) 237 | { 238 | this.red = red; 239 | this.green = green; 240 | this.blue = blue; 241 | this.alpha = alpha; 242 | } 243 | 244 | /** 245 | * @class Direction 246 | * A point value in which the y component is 0 and the x component 247 | * is positive or negative for a right or left direction, 248 | * or the x component is 0 and the y component is positive or negative for 249 | * an up or down direction. 250 | * 251 | * @param x The horizontal component of the point. 252 | * @param y The vertical component of the point. 253 | * 254 | * @return A new \c Direction object. 255 | */ 256 | function Direction(x, y) 257 | { 258 | this.x = x; 259 | this.y = y; 260 | } 261 | 262 | /** 263 | * @class GradientStop 264 | * Stores gradient stop information. 265 | * 266 | * @param offset The offset of the gradient stop, in the range [0.0 to 1.0]. 267 | * @param rgbColor The color of the gradient at this point, an \c #RGBColor object. 268 | * 269 | * @return GradientStop object. 270 | */ 271 | function GradientStop(offset, rgbColor) 272 | { 273 | this.offset = offset; 274 | this.rgbColor = rgbColor; 275 | } 276 | 277 | /** 278 | * @class GradientColor 279 | * Stores gradient color information. 280 | * 281 | * @param type The gradient type, must be "linear". 282 | * @param direction A \c #Direction object for the direction of the gradient 283 | (up, down, right, or left). 284 | * @param numStops The number of stops in the gradient. 285 | * @param gradientStopList An array of \c #GradientStop objects. 286 | * 287 | * @return A new \c GradientColor object. 288 | */ 289 | function GradientColor(type, direction, numStops, arrGradientStop) 290 | { 291 | this.type = type; 292 | this.direction = direction; 293 | this.numStops = numStops; 294 | this.arrGradientStop = arrGradientStop; 295 | } 296 | 297 | /** 298 | * @class UIColor 299 | * Stores color information, including the type, anti-alias level, and specific color 300 | * values in a color object of an appropriate type. 301 | * 302 | * @param type The color type, 1 for "rgb" and 2 for "gradient". 303 | The supplied color object must correspond to this type. 304 | * @param antialiasLevel The anti-alias level constant. 305 | * @param color A \c #RGBColor or \c #GradientColor object containing specific color information. 306 | * 307 | * @return A new \c UIColor object. 308 | */ 309 | function UIColor(type, antialiasLevel, color) 310 | { 311 | this.type = type; 312 | this.antialiasLevel = antialiasLevel; 313 | this.color = color; 314 | } 315 | 316 | /** 317 | * @class AppSkinInfo 318 | * Stores window-skin properties, such as color and font. All color parameter values are \c #UIColor objects except that systemHighlightColor is \c #RGBColor object. 319 | * 320 | * @param baseFontFamily The base font family of the application. 321 | * @param baseFontSize The base font size of the application. 322 | * @param appBarBackgroundColor The application bar background color. 323 | * @param panelBackgroundColor The background color of the extension panel. 324 | * @param appBarBackgroundColorSRGB The application bar background color, as sRGB. 325 | * @param panelBackgroundColorSRGB The background color of the extension panel, as sRGB. 326 | * @param systemHighlightColor The highlight color of the extension panel, if provided by the host application. Otherwise, the operating-system highlight color. 327 | * 328 | * @return AppSkinInfo object. 329 | */ 330 | function AppSkinInfo(baseFontFamily, baseFontSize, appBarBackgroundColor, panelBackgroundColor, appBarBackgroundColorSRGB, panelBackgroundColorSRGB, systemHighlightColor) 331 | { 332 | this.baseFontFamily = baseFontFamily; 333 | this.baseFontSize = baseFontSize; 334 | this.appBarBackgroundColor = appBarBackgroundColor; 335 | this.panelBackgroundColor = panelBackgroundColor; 336 | this.appBarBackgroundColorSRGB = appBarBackgroundColorSRGB; 337 | this.panelBackgroundColorSRGB = panelBackgroundColorSRGB; 338 | this.systemHighlightColor = systemHighlightColor; 339 | } 340 | 341 | /** 342 | * @class HostEnvironment 343 | * Stores information about the environment in which the extension is loaded. 344 | * 345 | * @param appName The application's name. 346 | * @param appVersion The application's version. 347 | * @param appLocale The application's current license locale. 348 | * @param appUILocale The application's current UI locale. 349 | * @param appId The application's unique identifier. 350 | * @param isAppOnline True if the application is currently online. 351 | * @param appSkinInfo An \c #AppSkinInfo object containing the application's default color and font styles. 352 | * 353 | * @return A new \c HostEnvironment object. 354 | */ 355 | function HostEnvironment(appName, appVersion, appLocale, appUILocale, appId, isAppOnline, appSkinInfo) 356 | { 357 | this.appName = appName; 358 | this.appVersion = appVersion; 359 | this.appLocale = appLocale; 360 | this.appUILocale = appUILocale; 361 | this.appId = appId; 362 | this.isAppOnline = isAppOnline; 363 | this.appSkinInfo = appSkinInfo; 364 | } 365 | 366 | /** 367 | * @class HostCapabilities 368 | * Stores information about the host capabilities. 369 | * 370 | * @param EXTENDED_PANEL_MENU True if the application supports panel menu. 371 | * @param EXTENDED_PANEL_ICONS True if the application supports panel icon. 372 | * @param DELEGATE_APE_ENGINE True if the application supports delegated APE engine. 373 | * @param SUPPORT_HTML_EXTENSIONS True if the application supports HTML extensions. 374 | * @param DISABLE_FLASH_EXTENSIONS True if the application disables FLASH extensions. 375 | * 376 | * @return A new \c HostCapabilities object. 377 | */ 378 | function HostCapabilities(EXTENDED_PANEL_MENU, EXTENDED_PANEL_ICONS, DELEGATE_APE_ENGINE, SUPPORT_HTML_EXTENSIONS, DISABLE_FLASH_EXTENSIONS) 379 | { 380 | this.EXTENDED_PANEL_MENU = EXTENDED_PANEL_MENU; 381 | this.EXTENDED_PANEL_ICONS = EXTENDED_PANEL_ICONS; 382 | this.DELEGATE_APE_ENGINE = DELEGATE_APE_ENGINE; 383 | this.SUPPORT_HTML_EXTENSIONS = SUPPORT_HTML_EXTENSIONS; 384 | this.DISABLE_FLASH_EXTENSIONS = DISABLE_FLASH_EXTENSIONS; // Since 5.0.0 385 | } 386 | 387 | /** 388 | * @class ApiVersion 389 | * Stores current api version. 390 | * 391 | * Since 4.2.0 392 | * 393 | * @param major The major version 394 | * @param minor The minor version. 395 | * @param micro The micro version. 396 | * 397 | * @return ApiVersion object. 398 | */ 399 | function ApiVersion(major, minor, micro) 400 | { 401 | this.major = major; 402 | this.minor = minor; 403 | this.micro = micro; 404 | } 405 | 406 | /** 407 | * @class MenuItemStatus 408 | * Stores flyout menu item status 409 | * 410 | * Since 5.2.0 411 | * 412 | * @param menuItemLabel The menu item label. 413 | * @param enabled True if user wants to enable the menu item. 414 | * @param checked True if user wants to check the menu item. 415 | * 416 | * @return MenuItemStatus object. 417 | */ 418 | function MenuItemStatus(menuItemLabel, enabled, checked) 419 | { 420 | this.menuItemLabel = menuItemLabel; 421 | this.enabled = enabled; 422 | this.checked = checked; 423 | } 424 | 425 | /** 426 | * @class ContextMenuItemStatus 427 | * Stores the status of the context menu item. 428 | * 429 | * Since 5.2.0 430 | * 431 | * @param menuItemID The menu item id. 432 | * @param enabled True if user wants to enable the menu item. 433 | * @param checked True if user wants to check the menu item. 434 | * 435 | * @return MenuItemStatus object. 436 | */ 437 | function ContextMenuItemStatus(menuItemID, enabled, checked) 438 | { 439 | this.menuItemID = menuItemID; 440 | this.enabled = enabled; 441 | this.checked = checked; 442 | } 443 | //------------------------------ CSInterface ---------------------------------- 444 | 445 | /** 446 | * @class CSInterface 447 | * This is the entry point to the CEP extensibility infrastructure. 448 | * Instantiate this object and use it to: 449 | * <ul> 450 | * <li>Access information about the host application in which an extension is running</li> 451 | * <li>Launch an extension</li> 452 | * <li>Register interest in event notifications, and dispatch events</li> 453 | * </ul> 454 | * 455 | * @return A new \c CSInterface object 456 | */ 457 | function CSInterface() 458 | { 459 | } 460 | 461 | /** 462 | * User can add this event listener to handle native application theme color changes. 463 | * Callback function gives extensions ability to fine-tune their theme color after the 464 | * global theme color has been changed. 465 | * The callback function should be like below: 466 | * 467 | * @example 468 | * // event is a CSEvent object, but user can ignore it. 469 | * function OnAppThemeColorChanged(event) 470 | * { 471 | * // Should get a latest HostEnvironment object from application. 472 | * var skinInfo = JSON.parse(window.__adobe_cep__.getHostEnvironment()).appSkinInfo; 473 | * // Gets the style information such as color info from the skinInfo, 474 | * // and redraw all UI controls of your extension according to the style info. 475 | * } 476 | */ 477 | CSInterface.THEME_COLOR_CHANGED_EVENT = "com.adobe.csxs.events.ThemeColorChanged"; 478 | 479 | /** The host environment data object. */ 480 | CSInterface.prototype.hostEnvironment = window.__adobe_cep__ ? JSON.parse(window.__adobe_cep__.getHostEnvironment()) : null; 481 | 482 | /** Retrieves information about the host environment in which the 483 | * extension is currently running. 484 | * 485 | * @return A \c #HostEnvironment object. 486 | */ 487 | CSInterface.prototype.getHostEnvironment = function() 488 | { 489 | this.hostEnvironment = JSON.parse(window.__adobe_cep__.getHostEnvironment()); 490 | return this.hostEnvironment; 491 | }; 492 | 493 | /** Loads binary file created which is located at url asynchronously 494 | * 495 | *@param urlName url at which binary file is located. Local files should start with 'file://' 496 | *@param callback Optional. A callback function that returns after binary is loaded 497 | 498 | *@example 499 | * To create JS binary use command ./cep_compiler test.js test.bin 500 | * To load JS binary asyncronously 501 | * var CSLib = new CSInterface(); 502 | * CSLib.loadBinAsync(url, function () { }); 503 | */ 504 | CSInterface.prototype.loadBinAsync = function(urlName,callback) 505 | { 506 | try 507 | { 508 | var xhr = new XMLHttpRequest(); 509 | xhr.responseType = 'arraybuffer'; // make response as ArrayBuffer 510 | xhr.open('GET', urlName, true); 511 | xhr.onerror = function () 512 | { 513 | console.log("Unable to load snapshot from given URL"); 514 | return false; 515 | }; 516 | xhr.send(); 517 | xhr.onload = () => { 518 | window.__adobe_cep__.loadSnapshot(xhr.response); 519 | if (typeof callback === "function") 520 | { 521 | callback(); 522 | } 523 | else if(typeof callback !== "undefined") 524 | { 525 | console.log("Provided callback is not a function"); 526 | } 527 | } 528 | } 529 | catch(err) 530 | { 531 | console.log(err); 532 | return false; 533 | } 534 | 535 | return true; 536 | }; 537 | 538 | /** Loads binary file created synchronously 539 | * 540 | *@param pathName the local path at which binary file is located 541 | 542 | *@example 543 | * To create JS binary use command ./cep_compiler test.js test.bin 544 | * To load JS binary syncronously 545 | * var CSLib = new CSInterface(); 546 | * CSLib.loadBinSync(path); 547 | */ 548 | CSInterface.prototype.loadBinSync = function(pathName) 549 | { 550 | try 551 | { 552 | var OSVersion = this.getOSInformation(); 553 | if(pathName.startsWith("file://")) 554 | { 555 | if (OSVersion.indexOf("Windows") >= 0) 556 | { 557 | pathName = pathName.replace("file:///", ""); 558 | } 559 | else if (OSVersion.indexOf("Mac") >= 0) 560 | { 561 | pathName = pathName.replace("file://", ""); 562 | } 563 | window.__adobe_cep__.loadSnapshot(pathName); 564 | return true; 565 | } 566 | } 567 | catch(err) 568 | { 569 | console.log(err); 570 | return false; 571 | } 572 | //control should not come here 573 | return false; 574 | }; 575 | 576 | /** Closes this extension. */ 577 | CSInterface.prototype.closeExtension = function() 578 | { 579 | window.__adobe_cep__.closeExtension(); 580 | }; 581 | 582 | /** 583 | * Retrieves a path for which a constant is defined in the system. 584 | * 585 | * @param pathType The path-type constant defined in \c #SystemPath , 586 | * 587 | * @return The platform-specific system path string. 588 | */ 589 | CSInterface.prototype.getSystemPath = function(pathType) 590 | { 591 | var path = decodeURI(window.__adobe_cep__.getSystemPath(pathType)); 592 | var OSVersion = this.getOSInformation(); 593 | if (OSVersion.indexOf("Windows") >= 0) 594 | { 595 | path = path.replace("file:///", ""); 596 | } 597 | else if (OSVersion.indexOf("Mac") >= 0) 598 | { 599 | path = path.replace("file://", ""); 600 | } 601 | return path; 602 | }; 603 | 604 | /** 605 | * Evaluates a JavaScript script, which can use the JavaScript DOM 606 | * of the host application. 607 | * 608 | * @param script The JavaScript script. 609 | * @param callback Optional. A callback function that receives the result of execution. 610 | * If execution fails, the callback function receives the error message \c EvalScript_ErrMessage. 611 | */ 612 | CSInterface.prototype.evalScript = function(script, callback) 613 | { 614 | if(callback === null || callback === undefined) 615 | { 616 | callback = function(result){}; 617 | } 618 | window.__adobe_cep__.evalScript(script, callback); 619 | }; 620 | 621 | /** 622 | * Retrieves the unique identifier of the application. 623 | * in which the extension is currently running. 624 | * 625 | * @return The unique ID string. 626 | */ 627 | CSInterface.prototype.getApplicationID = function() 628 | { 629 | var appId = this.hostEnvironment.appId; 630 | return appId; 631 | }; 632 | 633 | /** 634 | * Retrieves host capability information for the application 635 | * in which the extension is currently running. 636 | * 637 | * @return A \c #HostCapabilities object. 638 | */ 639 | CSInterface.prototype.getHostCapabilities = function() 640 | { 641 | var hostCapabilities = JSON.parse(window.__adobe_cep__.getHostCapabilities() ); 642 | return hostCapabilities; 643 | }; 644 | 645 | /** 646 | * Triggers a CEP event programmatically. Yoy can use it to dispatch 647 | * an event of a predefined type, or of a type you have defined. 648 | * 649 | * @param event A \c CSEvent object. 650 | */ 651 | CSInterface.prototype.dispatchEvent = function(event) 652 | { 653 | if (typeof event.data == "object") 654 | { 655 | event.data = JSON.stringify(event.data); 656 | } 657 | 658 | window.__adobe_cep__.dispatchEvent(event); 659 | }; 660 | 661 | /** 662 | * Registers an interest in a CEP event of a particular type, and 663 | * assigns an event handler. 664 | * The event infrastructure notifies your extension when events of this type occur, 665 | * passing the event object to the registered handler function. 666 | * 667 | * @param type The name of the event type of interest. 668 | * @param listener The JavaScript handler function or method. 669 | * @param obj Optional, the object containing the handler method, if any. 670 | * Default is null. 671 | */ 672 | CSInterface.prototype.addEventListener = function(type, listener, obj) 673 | { 674 | window.__adobe_cep__.addEventListener(type, listener, obj); 675 | }; 676 | 677 | /** 678 | * Removes a registered event listener. 679 | * 680 | * @param type The name of the event type of interest. 681 | * @param listener The JavaScript handler function or method that was registered. 682 | * @param obj Optional, the object containing the handler method, if any. 683 | * Default is null. 684 | */ 685 | CSInterface.prototype.removeEventListener = function(type, listener, obj) 686 | { 687 | window.__adobe_cep__.removeEventListener(type, listener, obj); 688 | }; 689 | 690 | /** 691 | * Loads and launches another extension, or activates the extension if it is already loaded. 692 | * 693 | * @param extensionId The extension's unique identifier. 694 | * @param startupParams Not currently used, pass "". 695 | * 696 | * @example 697 | * To launch the extension "help" with ID "HLP" from this extension, call: 698 | * <code>requestOpenExtension("HLP", ""); </code> 699 | * 700 | */ 701 | CSInterface.prototype.requestOpenExtension = function(extensionId, params) 702 | { 703 | window.__adobe_cep__.requestOpenExtension(extensionId, params); 704 | }; 705 | 706 | /** 707 | * Retrieves the list of extensions currently loaded in the current host application. 708 | * The extension list is initialized once, and remains the same during the lifetime 709 | * of the CEP session. 710 | * 711 | * @param extensionIds Optional, an array of unique identifiers for extensions of interest. 712 | * If omitted, retrieves data for all extensions. 713 | * 714 | * @return Zero or more \c #Extension objects. 715 | */ 716 | CSInterface.prototype.getExtensions = function(extensionIds) 717 | { 718 | var extensionIdsStr = JSON.stringify(extensionIds); 719 | var extensionsStr = window.__adobe_cep__.getExtensions(extensionIdsStr); 720 | 721 | var extensions = JSON.parse(extensionsStr); 722 | return extensions; 723 | }; 724 | 725 | /** 726 | * Retrieves network-related preferences. 727 | * 728 | * @return A JavaScript object containing network preferences. 729 | */ 730 | CSInterface.prototype.getNetworkPreferences = function() 731 | { 732 | var result = window.__adobe_cep__.getNetworkPreferences(); 733 | var networkPre = JSON.parse(result); 734 | 735 | return networkPre; 736 | }; 737 | 738 | /** 739 | * Initializes the resource bundle for this extension with property values 740 | * for the current application and locale. 741 | * To support multiple locales, you must define a property file for each locale, 742 | * containing keyed display-string values for that locale. 743 | * See localization documentation for Extension Builder and related products. 744 | * 745 | * Keys can be in the 746 | * form <code>key.value="localized string"</code>, for use in HTML text elements. 747 | * For example, in this input element, the localized \c key.value string is displayed 748 | * instead of the empty \c value string: 749 | * 750 | * <code><input type="submit" value="" data-locale="key"/></code> 751 | * 752 | * @return An object containing the resource bundle information. 753 | */ 754 | CSInterface.prototype.initResourceBundle = function() 755 | { 756 | var resourceBundle = JSON.parse(window.__adobe_cep__.initResourceBundle()); 757 | var resElms = document.querySelectorAll('[data-locale]'); 758 | for (var n = 0; n < resElms.length; n++) 759 | { 760 | var resEl = resElms[n]; 761 | // Get the resource key from the element. 762 | var resKey = resEl.getAttribute('data-locale'); 763 | if (resKey) 764 | { 765 | // Get all the resources that start with the key. 766 | for (var key in resourceBundle) 767 | { 768 | if (key.indexOf(resKey) === 0) 769 | { 770 | var resValue = resourceBundle[key]; 771 | if (key.length == resKey.length) 772 | { 773 | resEl.innerHTML = resValue; 774 | } 775 | else if ('.' == key.charAt(resKey.length)) 776 | { 777 | var attrKey = key.substring(resKey.length + 1); 778 | resEl[attrKey] = resValue; 779 | } 780 | } 781 | } 782 | } 783 | } 784 | return resourceBundle; 785 | }; 786 | 787 | /** 788 | * Writes installation information to a file. 789 | * 790 | * @return The file path. 791 | */ 792 | CSInterface.prototype.dumpInstallationInfo = function() 793 | { 794 | return window.__adobe_cep__.dumpInstallationInfo(); 795 | }; 796 | 797 | /** 798 | * Retrieves version information for the current Operating System, 799 | * See http://www.useragentstring.com/pages/Chrome/ for Chrome \c navigator.userAgent values. 800 | * 801 | * @return A string containing the OS version, or "unknown Operation System". 802 | * If user customizes the User Agent by setting CEF command parameter "--user-agent", only 803 | * "Mac OS X" or "Windows" will be returned. 804 | */ 805 | CSInterface.prototype.getOSInformation = function() 806 | { 807 | var userAgent = navigator.userAgent; 808 | 809 | if ((navigator.platform == "Win32") || (navigator.platform == "Windows")) 810 | { 811 | var winVersion = "Windows"; 812 | var winBit = ""; 813 | if (userAgent.indexOf("Windows") > -1) 814 | { 815 | if (userAgent.indexOf("Windows NT 5.0") > -1) 816 | { 817 | winVersion = "Windows 2000"; 818 | } 819 | else if (userAgent.indexOf("Windows NT 5.1") > -1) 820 | { 821 | winVersion = "Windows XP"; 822 | } 823 | else if (userAgent.indexOf("Windows NT 5.2") > -1) 824 | { 825 | winVersion = "Windows Server 2003"; 826 | } 827 | else if (userAgent.indexOf("Windows NT 6.0") > -1) 828 | { 829 | winVersion = "Windows Vista"; 830 | } 831 | else if (userAgent.indexOf("Windows NT 6.1") > -1) 832 | { 833 | winVersion = "Windows 7"; 834 | } 835 | else if (userAgent.indexOf("Windows NT 6.2") > -1) 836 | { 837 | winVersion = "Windows 8"; 838 | } 839 | else if (userAgent.indexOf("Windows NT 6.3") > -1) 840 | { 841 | winVersion = "Windows 8.1"; 842 | } 843 | else if (userAgent.indexOf("Windows NT 10") > -1) 844 | { 845 | winVersion = "Windows 10"; 846 | } 847 | 848 | if (userAgent.indexOf("WOW64") > -1 || userAgent.indexOf("Win64") > -1) 849 | { 850 | winBit = " 64-bit"; 851 | } 852 | else 853 | { 854 | winBit = " 32-bit"; 855 | } 856 | } 857 | 858 | return winVersion + winBit; 859 | } 860 | else if ((navigator.platform == "MacIntel") || (navigator.platform == "Macintosh")) 861 | { 862 | var result = "Mac OS X"; 863 | 864 | if (userAgent.indexOf("Mac OS X") > -1) 865 | { 866 | result = userAgent.substring(userAgent.indexOf("Mac OS X"), userAgent.indexOf(")")); 867 | result = result.replace(/_/g, "."); 868 | } 869 | 870 | return result; 871 | } 872 | 873 | return "Unknown Operation System"; 874 | }; 875 | 876 | /** 877 | * Opens a page in the default system browser. 878 | * 879 | * Since 4.2.0 880 | * 881 | * @param url The URL of the page/file to open, or the email address. 882 | * Must use HTTP/HTTPS/file/mailto protocol. For example: 883 | * "http://www.adobe.com" 884 | * "https://github.com" 885 | * "file:///C:/log.txt" 886 | * "mailto:[email protected]" 887 | * 888 | * @return One of these error codes:\n 889 | * <ul>\n 890 | * <li>NO_ERROR - 0</li>\n 891 | * <li>ERR_UNKNOWN - 1</li>\n 892 | * <li>ERR_INVALID_PARAMS - 2</li>\n 893 | * <li>ERR_INVALID_URL - 201</li>\n 894 | * </ul>\n 895 | */ 896 | CSInterface.prototype.openURLInDefaultBrowser = function(url) 897 | { 898 | return cep.util.openURLInDefaultBrowser(url); 899 | }; 900 | 901 | /** 902 | * Retrieves extension ID. 903 | * 904 | * Since 4.2.0 905 | * 906 | * @return extension ID. 907 | */ 908 | CSInterface.prototype.getExtensionID = function() 909 | { 910 | return window.__adobe_cep__.getExtensionId(); 911 | }; 912 | 913 | /** 914 | * Retrieves the scale factor of screen. 915 | * On Windows platform, the value of scale factor might be different from operating system's scale factor, 916 | * since host application may use its self-defined scale factor. 917 | * 918 | * Since 4.2.0 919 | * 920 | * @return One of the following float number. 921 | * <ul>\n 922 | * <li> -1.0 when error occurs </li>\n 923 | * <li> 1.0 means normal screen </li>\n 924 | * <li> >1.0 means HiDPI screen </li>\n 925 | * </ul>\n 926 | */ 927 | CSInterface.prototype.getScaleFactor = function() 928 | { 929 | return window.__adobe_cep__.getScaleFactor(); 930 | }; 931 | 932 | /** 933 | * Retrieves the scale factor of Monitor. 934 | * 935 | * Since 8.5.0 936 | * 937 | * @return value >= 1.0f 938 | * only available for windows machine 939 | */ 940 | if(navigator.appVersion.toLowerCase().indexOf("windows") >= 0) { 941 | CSInterface.prototype.getMonitorScaleFactor = function() 942 | { 943 | return window.__adobe_cep__.getMonitorScaleFactor(); 944 | }; 945 | } 946 | 947 | /** 948 | * Set a handler to detect any changes of scale factor. This only works on Mac. 949 | * 950 | * Since 4.2.0 951 | * 952 | * @param handler The function to be called when scale factor is changed. 953 | * 954 | */ 955 | CSInterface.prototype.setScaleFactorChangedHandler = function(handler) 956 | { 957 | window.__adobe_cep__.setScaleFactorChangedHandler(handler); 958 | }; 959 | 960 | /** 961 | * Retrieves current API version. 962 | * 963 | * Since 4.2.0 964 | * 965 | * @return ApiVersion object. 966 | * 967 | */ 968 | CSInterface.prototype.getCurrentApiVersion = function() 969 | { 970 | var apiVersion = JSON.parse(window.__adobe_cep__.getCurrentApiVersion()); 971 | return apiVersion; 972 | }; 973 | 974 | /** 975 | * Set panel flyout menu by an XML. 976 | * 977 | * Since 5.2.0 978 | * 979 | * Register a callback function for "com.adobe.csxs.events.flyoutMenuClicked" to get notified when a 980 | * menu item is clicked. 981 | * The "data" attribute of event is an object which contains "menuId" and "menuName" attributes. 982 | * 983 | * Register callback functions for "com.adobe.csxs.events.flyoutMenuOpened" and "com.adobe.csxs.events.flyoutMenuClosed" 984 | * respectively to get notified when flyout menu is opened or closed. 985 | * 986 | * @param menu A XML string which describes menu structure. 987 | * An example menu XML: 988 | * <Menu> 989 | * <MenuItem Id="menuItemId1" Label="TestExample1" Enabled="true" Checked="false"/> 990 | * <MenuItem Label="TestExample2"> 991 | * <MenuItem Label="TestExample2-1" > 992 | * <MenuItem Label="TestExample2-1-1" Enabled="false" Checked="true"/> 993 | * </MenuItem> 994 | * <MenuItem Label="TestExample2-2" Enabled="true" Checked="true"/> 995 | * </MenuItem> 996 | * <MenuItem Label="---" /> 997 | * <MenuItem Label="TestExample3" Enabled="false" Checked="false"/> 998 | * </Menu> 999 | * 1000 | */ 1001 | CSInterface.prototype.setPanelFlyoutMenu = function(menu) 1002 | { 1003 | if ("string" != typeof menu) 1004 | { 1005 | return; 1006 | } 1007 | 1008 | window.__adobe_cep__.invokeSync("setPanelFlyoutMenu", menu); 1009 | }; 1010 | 1011 | /** 1012 | * Updates a menu item in the extension window's flyout menu, by setting the enabled 1013 | * and selection status. 1014 | * 1015 | * Since 5.2.0 1016 | * 1017 | * @param menuItemLabel The menu item label. 1018 | * @param enabled True to enable the item, false to disable it (gray it out). 1019 | * @param checked True to select the item, false to deselect it. 1020 | * 1021 | * @return false when the host application does not support this functionality (HostCapabilities.EXTENDED_PANEL_MENU is false). 1022 | * Fails silently if menu label is invalid. 1023 | * 1024 | * @see HostCapabilities.EXTENDED_PANEL_MENU 1025 | */ 1026 | CSInterface.prototype.updatePanelMenuItem = function(menuItemLabel, enabled, checked) 1027 | { 1028 | var ret = false; 1029 | if (this.getHostCapabilities().EXTENDED_PANEL_MENU) 1030 | { 1031 | var itemStatus = new MenuItemStatus(menuItemLabel, enabled, checked); 1032 | ret = window.__adobe_cep__.invokeSync("updatePanelMenuItem", JSON.stringify(itemStatus)); 1033 | } 1034 | return ret; 1035 | }; 1036 | 1037 | 1038 | /** 1039 | * Set context menu by XML string. 1040 | * 1041 | * Since 5.2.0 1042 | * 1043 | * There are a number of conventions used to communicate what type of menu item to create and how it should be handled. 1044 | * - an item without menu ID or menu name is disabled and is not shown. 1045 | * - if the item name is "---" (three hyphens) then it is treated as a separator. The menu ID in this case will always be NULL. 1046 | * - Checkable attribute takes precedence over Checked attribute. 1047 | * - 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. 1048 | The Chrome extension contextMenus API was taken as a reference. 1049 | https://developer.chrome.com/extensions/contextMenus 1050 | * - the items with icons and checkable items cannot coexist on the same menu level. The former take precedences over the latter. 1051 | * 1052 | * @param menu A XML string which describes menu structure. 1053 | * @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. 1054 | * 1055 | * @description An example menu XML: 1056 | * <Menu> 1057 | * <MenuItem Id="menuItemId1" Label="TestExample1" Enabled="true" Checkable="true" Checked="false" Icon="./image/small_16X16.png"/> 1058 | * <MenuItem Id="menuItemId2" Label="TestExample2"> 1059 | * <MenuItem Id="menuItemId2-1" Label="TestExample2-1" > 1060 | * <MenuItem Id="menuItemId2-1-1" Label="TestExample2-1-1" Enabled="false" Checkable="true" Checked="true"/> 1061 | * </MenuItem> 1062 | * <MenuItem Id="menuItemId2-2" Label="TestExample2-2" Enabled="true" Checkable="true" Checked="true"/> 1063 | * </MenuItem> 1064 | * <MenuItem Label="---" /> 1065 | * <MenuItem Id="menuItemId3" Label="TestExample3" Enabled="false" Checkable="true" Checked="false"/> 1066 | * </Menu> 1067 | */ 1068 | CSInterface.prototype.setContextMenu = function(menu, callback) 1069 | { 1070 | if ("string" != typeof menu) 1071 | { 1072 | return; 1073 | } 1074 | 1075 | window.__adobe_cep__.invokeAsync("setContextMenu", menu, callback); 1076 | }; 1077 | 1078 | /** 1079 | * Set context menu by JSON string. 1080 | * 1081 | * Since 6.0.0 1082 | * 1083 | * There are a number of conventions used to communicate what type of menu item to create and how it should be handled. 1084 | * - an item without menu ID or menu name is disabled and is not shown. 1085 | * - if the item label is "---" (three hyphens) then it is treated as a separator. The menu ID in this case will always be NULL. 1086 | * - Checkable attribute takes precedence over Checked attribute. 1087 | * - 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. 1088 | The Chrome extension contextMenus API was taken as a reference. 1089 | * - the items with icons and checkable items cannot coexist on the same menu level. The former take precedences over the latter. 1090 | https://developer.chrome.com/extensions/contextMenus 1091 | * 1092 | * @param menu A JSON string which describes menu structure. 1093 | * @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. 1094 | * 1095 | * @description An example menu JSON: 1096 | * 1097 | * { 1098 | * "menu": [ 1099 | * { 1100 | * "id": "menuItemId1", 1101 | * "label": "testExample1", 1102 | * "enabled": true, 1103 | * "checkable": true, 1104 | * "checked": false, 1105 | * "icon": "./image/small_16X16.png" 1106 | * }, 1107 | * { 1108 | * "id": "menuItemId2", 1109 | * "label": "testExample2", 1110 | * "menu": [ 1111 | * { 1112 | * "id": "menuItemId2-1", 1113 | * "label": "testExample2-1", 1114 | * "menu": [ 1115 | * { 1116 | * "id": "menuItemId2-1-1", 1117 | * "label": "testExample2-1-1", 1118 | * "enabled": false, 1119 | * "checkable": true, 1120 | * "checked": true 1121 | * } 1122 | * ] 1123 | * }, 1124 | * { 1125 | * "id": "menuItemId2-2", 1126 | * "label": "testExample2-2", 1127 | * "enabled": true, 1128 | * "checkable": true, 1129 | * "checked": true 1130 | * } 1131 | * ] 1132 | * }, 1133 | * { 1134 | * "label": "---" 1135 | * }, 1136 | * { 1137 | * "id": "menuItemId3", 1138 | * "label": "testExample3", 1139 | * "enabled": false, 1140 | * "checkable": true, 1141 | * "checked": false 1142 | * } 1143 | * ] 1144 | * } 1145 | * 1146 | */ 1147 | CSInterface.prototype.setContextMenuByJSON = function(menu, callback) 1148 | { 1149 | if ("string" != typeof menu) 1150 | { 1151 | return; 1152 | } 1153 | 1154 | window.__adobe_cep__.invokeAsync("setContextMenuByJSON", menu, callback); 1155 | }; 1156 | 1157 | /** 1158 | * Updates a context menu item by setting the enabled and selection status. 1159 | * 1160 | * Since 5.2.0 1161 | * 1162 | * @param menuItemID The menu item ID. 1163 | * @param enabled True to enable the item, false to disable it (gray it out). 1164 | * @param checked True to select the item, false to deselect it. 1165 | */ 1166 | CSInterface.prototype.updateContextMenuItem = function(menuItemID, enabled, checked) 1167 | { 1168 | var itemStatus = new ContextMenuItemStatus(menuItemID, enabled, checked); 1169 | ret = window.__adobe_cep__.invokeSync("updateContextMenuItem", JSON.stringify(itemStatus)); 1170 | }; 1171 | 1172 | /** 1173 | * Get the visibility status of an extension window. 1174 | * 1175 | * Since 6.0.0 1176 | * 1177 | * @return true if the extension window is visible; false if the extension window is hidden. 1178 | */ 1179 | CSInterface.prototype.isWindowVisible = function() 1180 | { 1181 | return window.__adobe_cep__.invokeSync("isWindowVisible", ""); 1182 | }; 1183 | 1184 | /** 1185 | * Resize extension's content to the specified dimensions. 1186 | * 1. Works with modal and modeless extensions in all Adobe products. 1187 | * 2. Extension's manifest min/max size constraints apply and take precedence. 1188 | * 3. For panel extensions 1189 | * 3.1 This works in all Adobe products except: 1190 | * * Premiere Pro 1191 | * * Prelude 1192 | * * After Effects 1193 | * 3.2 When the panel is in certain states (especially when being docked), 1194 | * it will not change to the desired dimensions even when the 1195 | * specified size satisfies min/max constraints. 1196 | * 1197 | * Since 6.0.0 1198 | * 1199 | * @param width The new width 1200 | * @param height The new height 1201 | */ 1202 | CSInterface.prototype.resizeContent = function(width, height) 1203 | { 1204 | window.__adobe_cep__.resizeContent(width, height); 1205 | }; 1206 | 1207 | /** 1208 | * Register the invalid certificate callback for an extension. 1209 | * This callback will be triggered when the extension tries to access the web site that contains the invalid certificate on the main frame. 1210 | * But if the extension does not call this function and tries to access the web site containing the invalid certificate, a default error page will be shown. 1211 | * 1212 | * Since 6.1.0 1213 | * 1214 | * @param callback the callback function 1215 | */ 1216 | CSInterface.prototype.registerInvalidCertificateCallback = function(callback) 1217 | { 1218 | return window.__adobe_cep__.registerInvalidCertificateCallback(callback); 1219 | }; 1220 | 1221 | /** 1222 | * Register an interest in some key events to prevent them from being sent to the host application. 1223 | * 1224 | * This function works with modeless extensions and panel extensions. 1225 | * Generally all the key events will be sent to the host application for these two extensions if the current focused element 1226 | * is not text input or dropdown, 1227 | * If you want to intercept some key events and want them to be handled in the extension, please call this function 1228 | * in advance to prevent them being sent to the host application. 1229 | * 1230 | * Since 6.1.0 1231 | * 1232 | * @param keyEventsInterest A JSON string describing those key events you are interested in. A null object or 1233 | an empty string will lead to removing the interest 1234 | * 1235 | * This JSON string should be an array, each object has following keys: 1236 | * 1237 | * keyCode: [Required] represents an OS system dependent virtual key code identifying 1238 | * the unmodified value of the pressed key. 1239 | * ctrlKey: [optional] a Boolean that indicates if the control key was pressed (true) or not (false) when the event occurred. 1240 | * altKey: [optional] a Boolean that indicates if the alt key was pressed (true) or not (false) when the event occurred. 1241 | * shiftKey: [optional] a Boolean that indicates if the shift key was pressed (true) or not (false) when the event occurred. 1242 | * metaKey: [optional] (Mac Only) a Boolean that indicates if the Meta key was pressed (true) or not (false) when the event occurred. 1243 | * On Macintosh keyboards, this is the command key. To detect Windows key on Windows, please use keyCode instead. 1244 | * An example JSON string: 1245 | * 1246 | * [ 1247 | * { 1248 | * "keyCode": 48 1249 | * }, 1250 | * { 1251 | * "keyCode": 123, 1252 | * "ctrlKey": true 1253 | * }, 1254 | * { 1255 | * "keyCode": 123, 1256 | * "ctrlKey": true, 1257 | * "metaKey": true 1258 | * } 1259 | * ] 1260 | * 1261 | */ 1262 | CSInterface.prototype.registerKeyEventsInterest = function(keyEventsInterest) 1263 | { 1264 | return window.__adobe_cep__.registerKeyEventsInterest(keyEventsInterest); 1265 | }; 1266 | 1267 | /** 1268 | * Set the title of the extension window. 1269 | * This function works with modal and modeless extensions in all Adobe products, and panel extensions in Photoshop, InDesign, InCopy, Illustrator, Flash Pro and Dreamweaver. 1270 | * 1271 | * Since 6.1.0 1272 | * 1273 | * @param title The window title. 1274 | */ 1275 | CSInterface.prototype.setWindowTitle = function(title) 1276 | { 1277 | window.__adobe_cep__.invokeSync("setWindowTitle", title); 1278 | }; 1279 | 1280 | /** 1281 | * Get the title of the extension window. 1282 | * This function works with modal and modeless extensions in all Adobe products, and panel extensions in Photoshop, InDesign, InCopy, Illustrator, Flash Pro and Dreamweaver. 1283 | * 1284 | * Since 6.1.0 1285 | * 1286 | * @return The window title. 1287 | */ 1288 | CSInterface.prototype.getWindowTitle = function() 1289 | { 1290 | return window.__adobe_cep__.invokeSync("getWindowTitle", ""); 1291 | }; 1292 | ``` -------------------------------------------------------------------------------- /cep/com.mikechambers.ai/lib/CSInterface.js: -------------------------------------------------------------------------------- ```javascript 1 | /************************************************************************************************** 2 | * 3 | * ADOBE SYSTEMS INCORPORATED 4 | * Copyright 2020 Adobe Systems Incorporated 5 | * All Rights Reserved. 6 | * 7 | * NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the 8 | * terms of the Adobe license agreement accompanying it. If you have received this file from a 9 | * source other than Adobe, then your use, modification, or distribution of it requires the prior 10 | * written permission of Adobe. 11 | * 12 | **************************************************************************************************/ 13 | 14 | /** CSInterface - v12.0.0 */ 15 | 16 | /** 17 | * Stores constants for the window types supported by the CSXS infrastructure. 18 | */ 19 | function CSXSWindowType() 20 | { 21 | } 22 | 23 | /** Constant for the CSXS window type Panel. */ 24 | CSXSWindowType._PANEL = "Panel"; 25 | 26 | /** Constant for the CSXS window type Modeless. */ 27 | CSXSWindowType._MODELESS = "Modeless"; 28 | 29 | /** Constant for the CSXS window type ModalDialog. */ 30 | CSXSWindowType._MODAL_DIALOG = "ModalDialog"; 31 | 32 | /** EvalScript error message */ 33 | EvalScript_ErrMessage = "EvalScript error."; 34 | 35 | /** 36 | * @class Version 37 | * Defines a version number with major, minor, micro, and special 38 | * components. The major, minor and micro values are numeric; the special 39 | * value can be any string. 40 | * 41 | * @param major The major version component, a positive integer up to nine digits long. 42 | * @param minor The minor version component, a positive integer up to nine digits long. 43 | * @param micro The micro version component, a positive integer up to nine digits long. 44 | * @param special The special version component, an arbitrary string. 45 | * 46 | * @return A new \c Version object. 47 | */ 48 | function Version(major, minor, micro, special) 49 | { 50 | this.major = major; 51 | this.minor = minor; 52 | this.micro = micro; 53 | this.special = special; 54 | } 55 | 56 | /** 57 | * The maximum value allowed for a numeric version component. 58 | * This reflects the maximum value allowed in PlugPlug and the manifest schema. 59 | */ 60 | Version.MAX_NUM = 999999999; 61 | 62 | /** 63 | * @class VersionBound 64 | * Defines a boundary for a version range, which associates a \c Version object 65 | * with a flag for whether it is an inclusive or exclusive boundary. 66 | * 67 | * @param version The \c #Version object. 68 | * @param inclusive True if this boundary is inclusive, false if it is exclusive. 69 | * 70 | * @return A new \c VersionBound object. 71 | */ 72 | function VersionBound(version, inclusive) 73 | { 74 | this.version = version; 75 | this.inclusive = inclusive; 76 | } 77 | 78 | /** 79 | * @class VersionRange 80 | * Defines a range of versions using a lower boundary and optional upper boundary. 81 | * 82 | * @param lowerBound The \c #VersionBound object. 83 | * @param upperBound The \c #VersionBound object, or null for a range with no upper boundary. 84 | * 85 | * @return A new \c VersionRange object. 86 | */ 87 | function VersionRange(lowerBound, upperBound) 88 | { 89 | this.lowerBound = lowerBound; 90 | this.upperBound = upperBound; 91 | } 92 | 93 | /** 94 | * @class Runtime 95 | * Represents a runtime related to the CEP infrastructure. 96 | * Extensions can declare dependencies on particular 97 | * CEP runtime versions in the extension manifest. 98 | * 99 | * @param name The runtime name. 100 | * @param version A \c #VersionRange object that defines a range of valid versions. 101 | * 102 | * @return A new \c Runtime object. 103 | */ 104 | function Runtime(name, versionRange) 105 | { 106 | this.name = name; 107 | this.versionRange = versionRange; 108 | } 109 | 110 | /** 111 | * @class Extension 112 | * Encapsulates a CEP-based extension to an Adobe application. 113 | * 114 | * @param id The unique identifier of this extension. 115 | * @param name The localizable display name of this extension. 116 | * @param mainPath The path of the "index.html" file. 117 | * @param basePath The base path of this extension. 118 | * @param windowType The window type of the main window of this extension. 119 | Valid values are defined by \c #CSXSWindowType. 120 | * @param width The default width in pixels of the main window of this extension. 121 | * @param height The default height in pixels of the main window of this extension. 122 | * @param minWidth The minimum width in pixels of the main window of this extension. 123 | * @param minHeight The minimum height in pixels of the main window of this extension. 124 | * @param maxWidth The maximum width in pixels of the main window of this extension. 125 | * @param maxHeight The maximum height in pixels of the main window of this extension. 126 | * @param defaultExtensionDataXml The extension data contained in the default \c ExtensionDispatchInfo section of the extension manifest. 127 | * @param specialExtensionDataXml The extension data contained in the application-specific \c ExtensionDispatchInfo section of the extension manifest. 128 | * @param requiredRuntimeList An array of \c Runtime objects for runtimes required by this extension. 129 | * @param isAutoVisible True if this extension is visible on loading. 130 | * @param isPluginExtension True if this extension has been deployed in the Plugins folder of the host application. 131 | * 132 | * @return A new \c Extension object. 133 | */ 134 | function Extension(id, name, mainPath, basePath, windowType, width, height, minWidth, minHeight, maxWidth, maxHeight, 135 | defaultExtensionDataXml, specialExtensionDataXml, requiredRuntimeList, isAutoVisible, isPluginExtension) 136 | { 137 | this.id = id; 138 | this.name = name; 139 | this.mainPath = mainPath; 140 | this.basePath = basePath; 141 | this.windowType = windowType; 142 | this.width = width; 143 | this.height = height; 144 | this.minWidth = minWidth; 145 | this.minHeight = minHeight; 146 | this.maxWidth = maxWidth; 147 | this.maxHeight = maxHeight; 148 | this.defaultExtensionDataXml = defaultExtensionDataXml; 149 | this.specialExtensionDataXml = specialExtensionDataXml; 150 | this.requiredRuntimeList = requiredRuntimeList; 151 | this.isAutoVisible = isAutoVisible; 152 | this.isPluginExtension = isPluginExtension; 153 | } 154 | 155 | /** 156 | * @class CSEvent 157 | * A standard JavaScript event, the base class for CEP events. 158 | * 159 | * @param type The name of the event type. 160 | * @param scope The scope of event, can be "GLOBAL" or "APPLICATION". 161 | * @param appId The unique identifier of the application that generated the event. 162 | * @param extensionId The unique identifier of the extension that generated the event. 163 | * 164 | * @return A new \c CSEvent object 165 | */ 166 | function CSEvent(type, scope, appId, extensionId) 167 | { 168 | this.type = type; 169 | this.scope = scope; 170 | this.appId = appId; 171 | this.extensionId = extensionId; 172 | } 173 | 174 | /** Event-specific data. */ 175 | CSEvent.prototype.data = ""; 176 | 177 | /** 178 | * @class SystemPath 179 | * Stores operating-system-specific location constants for use in the 180 | * \c #CSInterface.getSystemPath() method. 181 | * @return A new \c SystemPath object. 182 | */ 183 | function SystemPath() 184 | { 185 | } 186 | 187 | /** The path to user data. */ 188 | SystemPath.USER_DATA = "userData"; 189 | 190 | /** The path to common files for Adobe applications. */ 191 | SystemPath.COMMON_FILES = "commonFiles"; 192 | 193 | /** The path to the user's default document folder. */ 194 | SystemPath.MY_DOCUMENTS = "myDocuments"; 195 | 196 | /** @deprecated. Use \c #SystemPath.Extension. */ 197 | SystemPath.APPLICATION = "application"; 198 | 199 | /** The path to current extension. */ 200 | SystemPath.EXTENSION = "extension"; 201 | 202 | /** The path to hosting application's executable. */ 203 | SystemPath.HOST_APPLICATION = "hostApplication"; 204 | 205 | /** 206 | * @class ColorType 207 | * Stores color-type constants. 208 | */ 209 | function ColorType() 210 | { 211 | } 212 | 213 | /** RGB color type. */ 214 | ColorType.RGB = "rgb"; 215 | 216 | /** Gradient color type. */ 217 | ColorType.GRADIENT = "gradient"; 218 | 219 | /** Null color type. */ 220 | ColorType.NONE = "none"; 221 | 222 | /** 223 | * @class RGBColor 224 | * Stores an RGB color with red, green, blue, and alpha values. 225 | * All values are in the range [0.0 to 255.0]. Invalid numeric values are 226 | * converted to numbers within this range. 227 | * 228 | * @param red The red value, in the range [0.0 to 255.0]. 229 | * @param green The green value, in the range [0.0 to 255.0]. 230 | * @param blue The blue value, in the range [0.0 to 255.0]. 231 | * @param alpha The alpha (transparency) value, in the range [0.0 to 255.0]. 232 | * The default, 255.0, means that the color is fully opaque. 233 | * 234 | * @return A new RGBColor object. 235 | */ 236 | function RGBColor(red, green, blue, alpha) 237 | { 238 | this.red = red; 239 | this.green = green; 240 | this.blue = blue; 241 | this.alpha = alpha; 242 | } 243 | 244 | /** 245 | * @class Direction 246 | * A point value in which the y component is 0 and the x component 247 | * is positive or negative for a right or left direction, 248 | * or the x component is 0 and the y component is positive or negative for 249 | * an up or down direction. 250 | * 251 | * @param x The horizontal component of the point. 252 | * @param y The vertical component of the point. 253 | * 254 | * @return A new \c Direction object. 255 | */ 256 | function Direction(x, y) 257 | { 258 | this.x = x; 259 | this.y = y; 260 | } 261 | 262 | /** 263 | * @class GradientStop 264 | * Stores gradient stop information. 265 | * 266 | * @param offset The offset of the gradient stop, in the range [0.0 to 1.0]. 267 | * @param rgbColor The color of the gradient at this point, an \c #RGBColor object. 268 | * 269 | * @return GradientStop object. 270 | */ 271 | function GradientStop(offset, rgbColor) 272 | { 273 | this.offset = offset; 274 | this.rgbColor = rgbColor; 275 | } 276 | 277 | /** 278 | * @class GradientColor 279 | * Stores gradient color information. 280 | * 281 | * @param type The gradient type, must be "linear". 282 | * @param direction A \c #Direction object for the direction of the gradient 283 | (up, down, right, or left). 284 | * @param numStops The number of stops in the gradient. 285 | * @param gradientStopList An array of \c #GradientStop objects. 286 | * 287 | * @return A new \c GradientColor object. 288 | */ 289 | function GradientColor(type, direction, numStops, arrGradientStop) 290 | { 291 | this.type = type; 292 | this.direction = direction; 293 | this.numStops = numStops; 294 | this.arrGradientStop = arrGradientStop; 295 | } 296 | 297 | /** 298 | * @class UIColor 299 | * Stores color information, including the type, anti-alias level, and specific color 300 | * values in a color object of an appropriate type. 301 | * 302 | * @param type The color type, 1 for "rgb" and 2 for "gradient". 303 | The supplied color object must correspond to this type. 304 | * @param antialiasLevel The anti-alias level constant. 305 | * @param color A \c #RGBColor or \c #GradientColor object containing specific color information. 306 | * 307 | * @return A new \c UIColor object. 308 | */ 309 | function UIColor(type, antialiasLevel, color) 310 | { 311 | this.type = type; 312 | this.antialiasLevel = antialiasLevel; 313 | this.color = color; 314 | } 315 | 316 | /** 317 | * @class AppSkinInfo 318 | * Stores window-skin properties, such as color and font. All color parameter values are \c #UIColor objects except that systemHighlightColor is \c #RGBColor object. 319 | * 320 | * @param baseFontFamily The base font family of the application. 321 | * @param baseFontSize The base font size of the application. 322 | * @param appBarBackgroundColor The application bar background color. 323 | * @param panelBackgroundColor The background color of the extension panel. 324 | * @param appBarBackgroundColorSRGB The application bar background color, as sRGB. 325 | * @param panelBackgroundColorSRGB The background color of the extension panel, as sRGB. 326 | * @param systemHighlightColor The highlight color of the extension panel, if provided by the host application. Otherwise, the operating-system highlight color. 327 | * 328 | * @return AppSkinInfo object. 329 | */ 330 | function AppSkinInfo(baseFontFamily, baseFontSize, appBarBackgroundColor, panelBackgroundColor, appBarBackgroundColorSRGB, panelBackgroundColorSRGB, systemHighlightColor) 331 | { 332 | this.baseFontFamily = baseFontFamily; 333 | this.baseFontSize = baseFontSize; 334 | this.appBarBackgroundColor = appBarBackgroundColor; 335 | this.panelBackgroundColor = panelBackgroundColor; 336 | this.appBarBackgroundColorSRGB = appBarBackgroundColorSRGB; 337 | this.panelBackgroundColorSRGB = panelBackgroundColorSRGB; 338 | this.systemHighlightColor = systemHighlightColor; 339 | } 340 | 341 | /** 342 | * @class HostEnvironment 343 | * Stores information about the environment in which the extension is loaded. 344 | * 345 | * @param appName The application's name. 346 | * @param appVersion The application's version. 347 | * @param appLocale The application's current license locale. 348 | * @param appUILocale The application's current UI locale. 349 | * @param appId The application's unique identifier. 350 | * @param isAppOnline True if the application is currently online. 351 | * @param appSkinInfo An \c #AppSkinInfo object containing the application's default color and font styles. 352 | * 353 | * @return A new \c HostEnvironment object. 354 | */ 355 | function HostEnvironment(appName, appVersion, appLocale, appUILocale, appId, isAppOnline, appSkinInfo) 356 | { 357 | this.appName = appName; 358 | this.appVersion = appVersion; 359 | this.appLocale = appLocale; 360 | this.appUILocale = appUILocale; 361 | this.appId = appId; 362 | this.isAppOnline = isAppOnline; 363 | this.appSkinInfo = appSkinInfo; 364 | } 365 | 366 | /** 367 | * @class HostCapabilities 368 | * Stores information about the host capabilities. 369 | * 370 | * @param EXTENDED_PANEL_MENU True if the application supports panel menu. 371 | * @param EXTENDED_PANEL_ICONS True if the application supports panel icon. 372 | * @param DELEGATE_APE_ENGINE True if the application supports delegated APE engine. 373 | * @param SUPPORT_HTML_EXTENSIONS True if the application supports HTML extensions. 374 | * @param DISABLE_FLASH_EXTENSIONS True if the application disables FLASH extensions. 375 | * 376 | * @return A new \c HostCapabilities object. 377 | */ 378 | function HostCapabilities(EXTENDED_PANEL_MENU, EXTENDED_PANEL_ICONS, DELEGATE_APE_ENGINE, SUPPORT_HTML_EXTENSIONS, DISABLE_FLASH_EXTENSIONS) 379 | { 380 | this.EXTENDED_PANEL_MENU = EXTENDED_PANEL_MENU; 381 | this.EXTENDED_PANEL_ICONS = EXTENDED_PANEL_ICONS; 382 | this.DELEGATE_APE_ENGINE = DELEGATE_APE_ENGINE; 383 | this.SUPPORT_HTML_EXTENSIONS = SUPPORT_HTML_EXTENSIONS; 384 | this.DISABLE_FLASH_EXTENSIONS = DISABLE_FLASH_EXTENSIONS; // Since 5.0.0 385 | } 386 | 387 | /** 388 | * @class ApiVersion 389 | * Stores current api version. 390 | * 391 | * Since 4.2.0 392 | * 393 | * @param major The major version 394 | * @param minor The minor version. 395 | * @param micro The micro version. 396 | * 397 | * @return ApiVersion object. 398 | */ 399 | function ApiVersion(major, minor, micro) 400 | { 401 | this.major = major; 402 | this.minor = minor; 403 | this.micro = micro; 404 | } 405 | 406 | /** 407 | * @class MenuItemStatus 408 | * Stores flyout menu item status 409 | * 410 | * Since 5.2.0 411 | * 412 | * @param menuItemLabel The menu item label. 413 | * @param enabled True if user wants to enable the menu item. 414 | * @param checked True if user wants to check the menu item. 415 | * 416 | * @return MenuItemStatus object. 417 | */ 418 | function MenuItemStatus(menuItemLabel, enabled, checked) 419 | { 420 | this.menuItemLabel = menuItemLabel; 421 | this.enabled = enabled; 422 | this.checked = checked; 423 | } 424 | 425 | /** 426 | * @class ContextMenuItemStatus 427 | * Stores the status of the context menu item. 428 | * 429 | * Since 5.2.0 430 | * 431 | * @param menuItemID The menu item id. 432 | * @param enabled True if user wants to enable the menu item. 433 | * @param checked True if user wants to check the menu item. 434 | * 435 | * @return MenuItemStatus object. 436 | */ 437 | function ContextMenuItemStatus(menuItemID, enabled, checked) 438 | { 439 | this.menuItemID = menuItemID; 440 | this.enabled = enabled; 441 | this.checked = checked; 442 | } 443 | //------------------------------ CSInterface ---------------------------------- 444 | 445 | /** 446 | * @class CSInterface 447 | * This is the entry point to the CEP extensibility infrastructure. 448 | * Instantiate this object and use it to: 449 | * <ul> 450 | * <li>Access information about the host application in which an extension is running</li> 451 | * <li>Launch an extension</li> 452 | * <li>Register interest in event notifications, and dispatch events</li> 453 | * </ul> 454 | * 455 | * @return A new \c CSInterface object 456 | */ 457 | function CSInterface() 458 | { 459 | } 460 | 461 | /** 462 | * User can add this event listener to handle native application theme color changes. 463 | * Callback function gives extensions ability to fine-tune their theme color after the 464 | * global theme color has been changed. 465 | * The callback function should be like below: 466 | * 467 | * @example 468 | * // event is a CSEvent object, but user can ignore it. 469 | * function OnAppThemeColorChanged(event) 470 | * { 471 | * // Should get a latest HostEnvironment object from application. 472 | * var skinInfo = JSON.parse(window.__adobe_cep__.getHostEnvironment()).appSkinInfo; 473 | * // Gets the style information such as color info from the skinInfo, 474 | * // and redraw all UI controls of your extension according to the style info. 475 | * } 476 | */ 477 | CSInterface.THEME_COLOR_CHANGED_EVENT = "com.adobe.csxs.events.ThemeColorChanged"; 478 | 479 | /** The host environment data object. */ 480 | CSInterface.prototype.hostEnvironment = window.__adobe_cep__ ? JSON.parse(window.__adobe_cep__.getHostEnvironment()) : null; 481 | 482 | /** Retrieves information about the host environment in which the 483 | * extension is currently running. 484 | * 485 | * @return A \c #HostEnvironment object. 486 | */ 487 | CSInterface.prototype.getHostEnvironment = function() 488 | { 489 | this.hostEnvironment = JSON.parse(window.__adobe_cep__.getHostEnvironment()); 490 | return this.hostEnvironment; 491 | }; 492 | 493 | /** Loads binary file created which is located at url asynchronously 494 | * 495 | *@param urlName url at which binary file is located. Local files should start with 'file://' 496 | *@param callback Optional. A callback function that returns after binary is loaded 497 | 498 | *@example 499 | * To create JS binary use command ./cep_compiler test.js test.bin 500 | * To load JS binary asyncronously 501 | * var CSLib = new CSInterface(); 502 | * CSLib.loadBinAsync(url, function () { }); 503 | */ 504 | CSInterface.prototype.loadBinAsync = function(urlName,callback) 505 | { 506 | try 507 | { 508 | var xhr = new XMLHttpRequest(); 509 | xhr.responseType = 'arraybuffer'; // make response as ArrayBuffer 510 | xhr.open('GET', urlName, true); 511 | xhr.onerror = function () 512 | { 513 | console.log("Unable to load snapshot from given URL"); 514 | return false; 515 | }; 516 | xhr.send(); 517 | xhr.onload = () => { 518 | window.__adobe_cep__.loadSnapshot(xhr.response); 519 | if (typeof callback === "function") 520 | { 521 | callback(); 522 | } 523 | else if(typeof callback !== "undefined") 524 | { 525 | console.log("Provided callback is not a function"); 526 | } 527 | } 528 | } 529 | catch(err) 530 | { 531 | console.log(err); 532 | return false; 533 | } 534 | 535 | return true; 536 | }; 537 | 538 | /** Loads binary file created synchronously 539 | * 540 | *@param pathName the local path at which binary file is located 541 | 542 | *@example 543 | * To create JS binary use command ./cep_compiler test.js test.bin 544 | * To load JS binary syncronously 545 | * var CSLib = new CSInterface(); 546 | * CSLib.loadBinSync(path); 547 | */ 548 | CSInterface.prototype.loadBinSync = function(pathName) 549 | { 550 | try 551 | { 552 | var OSVersion = this.getOSInformation(); 553 | if(pathName.startsWith("file://")) 554 | { 555 | if (OSVersion.indexOf("Windows") >= 0) 556 | { 557 | pathName = pathName.replace("file:///", ""); 558 | } 559 | else if (OSVersion.indexOf("Mac") >= 0) 560 | { 561 | pathName = pathName.replace("file://", ""); 562 | } 563 | window.__adobe_cep__.loadSnapshot(pathName); 564 | return true; 565 | } 566 | } 567 | catch(err) 568 | { 569 | console.log(err); 570 | return false; 571 | } 572 | //control should not come here 573 | return false; 574 | }; 575 | 576 | /** Closes this extension. */ 577 | CSInterface.prototype.closeExtension = function() 578 | { 579 | window.__adobe_cep__.closeExtension(); 580 | }; 581 | 582 | /** 583 | * Retrieves a path for which a constant is defined in the system. 584 | * 585 | * @param pathType The path-type constant defined in \c #SystemPath , 586 | * 587 | * @return The platform-specific system path string. 588 | */ 589 | CSInterface.prototype.getSystemPath = function(pathType) 590 | { 591 | var path = decodeURI(window.__adobe_cep__.getSystemPath(pathType)); 592 | var OSVersion = this.getOSInformation(); 593 | if (OSVersion.indexOf("Windows") >= 0) 594 | { 595 | path = path.replace("file:///", ""); 596 | } 597 | else if (OSVersion.indexOf("Mac") >= 0) 598 | { 599 | path = path.replace("file://", ""); 600 | } 601 | return path; 602 | }; 603 | 604 | /** 605 | * Evaluates a JavaScript script, which can use the JavaScript DOM 606 | * of the host application. 607 | * 608 | * @param script The JavaScript script. 609 | * @param callback Optional. A callback function that receives the result of execution. 610 | * If execution fails, the callback function receives the error message \c EvalScript_ErrMessage. 611 | */ 612 | CSInterface.prototype.evalScript = function(script, callback) 613 | { 614 | if(callback === null || callback === undefined) 615 | { 616 | callback = function(result){}; 617 | } 618 | window.__adobe_cep__.evalScript(script, callback); 619 | }; 620 | 621 | /** 622 | * Retrieves the unique identifier of the application. 623 | * in which the extension is currently running. 624 | * 625 | * @return The unique ID string. 626 | */ 627 | CSInterface.prototype.getApplicationID = function() 628 | { 629 | var appId = this.hostEnvironment.appId; 630 | return appId; 631 | }; 632 | 633 | /** 634 | * Retrieves host capability information for the application 635 | * in which the extension is currently running. 636 | * 637 | * @return A \c #HostCapabilities object. 638 | */ 639 | CSInterface.prototype.getHostCapabilities = function() 640 | { 641 | var hostCapabilities = JSON.parse(window.__adobe_cep__.getHostCapabilities() ); 642 | return hostCapabilities; 643 | }; 644 | 645 | /** 646 | * Triggers a CEP event programmatically. Yoy can use it to dispatch 647 | * an event of a predefined type, or of a type you have defined. 648 | * 649 | * @param event A \c CSEvent object. 650 | */ 651 | CSInterface.prototype.dispatchEvent = function(event) 652 | { 653 | if (typeof event.data == "object") 654 | { 655 | event.data = JSON.stringify(event.data); 656 | } 657 | 658 | window.__adobe_cep__.dispatchEvent(event); 659 | }; 660 | 661 | /** 662 | * Registers an interest in a CEP event of a particular type, and 663 | * assigns an event handler. 664 | * The event infrastructure notifies your extension when events of this type occur, 665 | * passing the event object to the registered handler function. 666 | * 667 | * @param type The name of the event type of interest. 668 | * @param listener The JavaScript handler function or method. 669 | * @param obj Optional, the object containing the handler method, if any. 670 | * Default is null. 671 | */ 672 | CSInterface.prototype.addEventListener = function(type, listener, obj) 673 | { 674 | window.__adobe_cep__.addEventListener(type, listener, obj); 675 | }; 676 | 677 | /** 678 | * Removes a registered event listener. 679 | * 680 | * @param type The name of the event type of interest. 681 | * @param listener The JavaScript handler function or method that was registered. 682 | * @param obj Optional, the object containing the handler method, if any. 683 | * Default is null. 684 | */ 685 | CSInterface.prototype.removeEventListener = function(type, listener, obj) 686 | { 687 | window.__adobe_cep__.removeEventListener(type, listener, obj); 688 | }; 689 | 690 | /** 691 | * Loads and launches another extension, or activates the extension if it is already loaded. 692 | * 693 | * @param extensionId The extension's unique identifier. 694 | * @param startupParams Not currently used, pass "". 695 | * 696 | * @example 697 | * To launch the extension "help" with ID "HLP" from this extension, call: 698 | * <code>requestOpenExtension("HLP", ""); </code> 699 | * 700 | */ 701 | CSInterface.prototype.requestOpenExtension = function(extensionId, params) 702 | { 703 | window.__adobe_cep__.requestOpenExtension(extensionId, params); 704 | }; 705 | 706 | /** 707 | * Retrieves the list of extensions currently loaded in the current host application. 708 | * The extension list is initialized once, and remains the same during the lifetime 709 | * of the CEP session. 710 | * 711 | * @param extensionIds Optional, an array of unique identifiers for extensions of interest. 712 | * If omitted, retrieves data for all extensions. 713 | * 714 | * @return Zero or more \c #Extension objects. 715 | */ 716 | CSInterface.prototype.getExtensions = function(extensionIds) 717 | { 718 | var extensionIdsStr = JSON.stringify(extensionIds); 719 | var extensionsStr = window.__adobe_cep__.getExtensions(extensionIdsStr); 720 | 721 | var extensions = JSON.parse(extensionsStr); 722 | return extensions; 723 | }; 724 | 725 | /** 726 | * Retrieves network-related preferences. 727 | * 728 | * @return A JavaScript object containing network preferences. 729 | */ 730 | CSInterface.prototype.getNetworkPreferences = function() 731 | { 732 | var result = window.__adobe_cep__.getNetworkPreferences(); 733 | var networkPre = JSON.parse(result); 734 | 735 | return networkPre; 736 | }; 737 | 738 | /** 739 | * Initializes the resource bundle for this extension with property values 740 | * for the current application and locale. 741 | * To support multiple locales, you must define a property file for each locale, 742 | * containing keyed display-string values for that locale. 743 | * See localization documentation for Extension Builder and related products. 744 | * 745 | * Keys can be in the 746 | * form <code>key.value="localized string"</code>, for use in HTML text elements. 747 | * For example, in this input element, the localized \c key.value string is displayed 748 | * instead of the empty \c value string: 749 | * 750 | * <code><input type="submit" value="" data-locale="key"/></code> 751 | * 752 | * @return An object containing the resource bundle information. 753 | */ 754 | CSInterface.prototype.initResourceBundle = function() 755 | { 756 | var resourceBundle = JSON.parse(window.__adobe_cep__.initResourceBundle()); 757 | var resElms = document.querySelectorAll('[data-locale]'); 758 | for (var n = 0; n < resElms.length; n++) 759 | { 760 | var resEl = resElms[n]; 761 | // Get the resource key from the element. 762 | var resKey = resEl.getAttribute('data-locale'); 763 | if (resKey) 764 | { 765 | // Get all the resources that start with the key. 766 | for (var key in resourceBundle) 767 | { 768 | if (key.indexOf(resKey) === 0) 769 | { 770 | var resValue = resourceBundle[key]; 771 | if (key.length == resKey.length) 772 | { 773 | resEl.innerHTML = resValue; 774 | } 775 | else if ('.' == key.charAt(resKey.length)) 776 | { 777 | var attrKey = key.substring(resKey.length + 1); 778 | resEl[attrKey] = resValue; 779 | } 780 | } 781 | } 782 | } 783 | } 784 | return resourceBundle; 785 | }; 786 | 787 | /** 788 | * Writes installation information to a file. 789 | * 790 | * @return The file path. 791 | */ 792 | CSInterface.prototype.dumpInstallationInfo = function() 793 | { 794 | return window.__adobe_cep__.dumpInstallationInfo(); 795 | }; 796 | 797 | /** 798 | * Retrieves version information for the current Operating System, 799 | * See http://www.useragentstring.com/pages/Chrome/ for Chrome \c navigator.userAgent values. 800 | * 801 | * @return A string containing the OS version, or "unknown Operation System". 802 | * If user customizes the User Agent by setting CEF command parameter "--user-agent", only 803 | * "Mac OS X" or "Windows" will be returned. 804 | */ 805 | CSInterface.prototype.getOSInformation = function() 806 | { 807 | var userAgent = navigator.userAgent; 808 | 809 | if ((navigator.platform == "Win32") || (navigator.platform == "Windows")) 810 | { 811 | var winVersion = "Windows"; 812 | var winBit = ""; 813 | if (userAgent.indexOf("Windows") > -1) 814 | { 815 | if (userAgent.indexOf("Windows NT 5.0") > -1) 816 | { 817 | winVersion = "Windows 2000"; 818 | } 819 | else if (userAgent.indexOf("Windows NT 5.1") > -1) 820 | { 821 | winVersion = "Windows XP"; 822 | } 823 | else if (userAgent.indexOf("Windows NT 5.2") > -1) 824 | { 825 | winVersion = "Windows Server 2003"; 826 | } 827 | else if (userAgent.indexOf("Windows NT 6.0") > -1) 828 | { 829 | winVersion = "Windows Vista"; 830 | } 831 | else if (userAgent.indexOf("Windows NT 6.1") > -1) 832 | { 833 | winVersion = "Windows 7"; 834 | } 835 | else if (userAgent.indexOf("Windows NT 6.2") > -1) 836 | { 837 | winVersion = "Windows 8"; 838 | } 839 | else if (userAgent.indexOf("Windows NT 6.3") > -1) 840 | { 841 | winVersion = "Windows 8.1"; 842 | } 843 | else if (userAgent.indexOf("Windows NT 10") > -1) 844 | { 845 | winVersion = "Windows 10"; 846 | } 847 | 848 | if (userAgent.indexOf("WOW64") > -1 || userAgent.indexOf("Win64") > -1) 849 | { 850 | winBit = " 64-bit"; 851 | } 852 | else 853 | { 854 | winBit = " 32-bit"; 855 | } 856 | } 857 | 858 | return winVersion + winBit; 859 | } 860 | else if ((navigator.platform == "MacIntel") || (navigator.platform == "Macintosh")) 861 | { 862 | var result = "Mac OS X"; 863 | 864 | if (userAgent.indexOf("Mac OS X") > -1) 865 | { 866 | result = userAgent.substring(userAgent.indexOf("Mac OS X"), userAgent.indexOf(")")); 867 | result = result.replace(/_/g, "."); 868 | } 869 | 870 | return result; 871 | } 872 | 873 | return "Unknown Operation System"; 874 | }; 875 | 876 | /** 877 | * Opens a page in the default system browser. 878 | * 879 | * Since 4.2.0 880 | * 881 | * @param url The URL of the page/file to open, or the email address. 882 | * Must use HTTP/HTTPS/file/mailto protocol. For example: 883 | * "http://www.adobe.com" 884 | * "https://github.com" 885 | * "file:///C:/log.txt" 886 | * "mailto:[email protected]" 887 | * 888 | * @return One of these error codes:\n 889 | * <ul>\n 890 | * <li>NO_ERROR - 0</li>\n 891 | * <li>ERR_UNKNOWN - 1</li>\n 892 | * <li>ERR_INVALID_PARAMS - 2</li>\n 893 | * <li>ERR_INVALID_URL - 201</li>\n 894 | * </ul>\n 895 | */ 896 | CSInterface.prototype.openURLInDefaultBrowser = function(url) 897 | { 898 | return cep.util.openURLInDefaultBrowser(url); 899 | }; 900 | 901 | /** 902 | * Retrieves extension ID. 903 | * 904 | * Since 4.2.0 905 | * 906 | * @return extension ID. 907 | */ 908 | CSInterface.prototype.getExtensionID = function() 909 | { 910 | return window.__adobe_cep__.getExtensionId(); 911 | }; 912 | 913 | /** 914 | * Retrieves the scale factor of screen. 915 | * On Windows platform, the value of scale factor might be different from operating system's scale factor, 916 | * since host application may use its self-defined scale factor. 917 | * 918 | * Since 4.2.0 919 | * 920 | * @return One of the following float number. 921 | * <ul>\n 922 | * <li> -1.0 when error occurs </li>\n 923 | * <li> 1.0 means normal screen </li>\n 924 | * <li> >1.0 means HiDPI screen </li>\n 925 | * </ul>\n 926 | */ 927 | CSInterface.prototype.getScaleFactor = function() 928 | { 929 | return window.__adobe_cep__.getScaleFactor(); 930 | }; 931 | 932 | /** 933 | * Retrieves the scale factor of Monitor. 934 | * 935 | * Since 8.5.0 936 | * 937 | * @return value >= 1.0f 938 | * only available for windows machine 939 | */ 940 | if(navigator.appVersion.toLowerCase().indexOf("windows") >= 0) { 941 | CSInterface.prototype.getMonitorScaleFactor = function() 942 | { 943 | return window.__adobe_cep__.getMonitorScaleFactor(); 944 | }; 945 | } 946 | 947 | /** 948 | * Set a handler to detect any changes of scale factor. This only works on Mac. 949 | * 950 | * Since 4.2.0 951 | * 952 | * @param handler The function to be called when scale factor is changed. 953 | * 954 | */ 955 | CSInterface.prototype.setScaleFactorChangedHandler = function(handler) 956 | { 957 | window.__adobe_cep__.setScaleFactorChangedHandler(handler); 958 | }; 959 | 960 | /** 961 | * Retrieves current API version. 962 | * 963 | * Since 4.2.0 964 | * 965 | * @return ApiVersion object. 966 | * 967 | */ 968 | CSInterface.prototype.getCurrentApiVersion = function() 969 | { 970 | var apiVersion = JSON.parse(window.__adobe_cep__.getCurrentApiVersion()); 971 | return apiVersion; 972 | }; 973 | 974 | /** 975 | * Set panel flyout menu by an XML. 976 | * 977 | * Since 5.2.0 978 | * 979 | * Register a callback function for "com.adobe.csxs.events.flyoutMenuClicked" to get notified when a 980 | * menu item is clicked. 981 | * The "data" attribute of event is an object which contains "menuId" and "menuName" attributes. 982 | * 983 | * Register callback functions for "com.adobe.csxs.events.flyoutMenuOpened" and "com.adobe.csxs.events.flyoutMenuClosed" 984 | * respectively to get notified when flyout menu is opened or closed. 985 | * 986 | * @param menu A XML string which describes menu structure. 987 | * An example menu XML: 988 | * <Menu> 989 | * <MenuItem Id="menuItemId1" Label="TestExample1" Enabled="true" Checked="false"/> 990 | * <MenuItem Label="TestExample2"> 991 | * <MenuItem Label="TestExample2-1" > 992 | * <MenuItem Label="TestExample2-1-1" Enabled="false" Checked="true"/> 993 | * </MenuItem> 994 | * <MenuItem Label="TestExample2-2" Enabled="true" Checked="true"/> 995 | * </MenuItem> 996 | * <MenuItem Label="---" /> 997 | * <MenuItem Label="TestExample3" Enabled="false" Checked="false"/> 998 | * </Menu> 999 | * 1000 | */ 1001 | CSInterface.prototype.setPanelFlyoutMenu = function(menu) 1002 | { 1003 | if ("string" != typeof menu) 1004 | { 1005 | return; 1006 | } 1007 | 1008 | window.__adobe_cep__.invokeSync("setPanelFlyoutMenu", menu); 1009 | }; 1010 | 1011 | /** 1012 | * Updates a menu item in the extension window's flyout menu, by setting the enabled 1013 | * and selection status. 1014 | * 1015 | * Since 5.2.0 1016 | * 1017 | * @param menuItemLabel The menu item label. 1018 | * @param enabled True to enable the item, false to disable it (gray it out). 1019 | * @param checked True to select the item, false to deselect it. 1020 | * 1021 | * @return false when the host application does not support this functionality (HostCapabilities.EXTENDED_PANEL_MENU is false). 1022 | * Fails silently if menu label is invalid. 1023 | * 1024 | * @see HostCapabilities.EXTENDED_PANEL_MENU 1025 | */ 1026 | CSInterface.prototype.updatePanelMenuItem = function(menuItemLabel, enabled, checked) 1027 | { 1028 | var ret = false; 1029 | if (this.getHostCapabilities().EXTENDED_PANEL_MENU) 1030 | { 1031 | var itemStatus = new MenuItemStatus(menuItemLabel, enabled, checked); 1032 | ret = window.__adobe_cep__.invokeSync("updatePanelMenuItem", JSON.stringify(itemStatus)); 1033 | } 1034 | return ret; 1035 | }; 1036 | 1037 | 1038 | /** 1039 | * Set context menu by XML string. 1040 | * 1041 | * Since 5.2.0 1042 | * 1043 | * There are a number of conventions used to communicate what type of menu item to create and how it should be handled. 1044 | * - an item without menu ID or menu name is disabled and is not shown. 1045 | * - if the item name is "---" (three hyphens) then it is treated as a separator. The menu ID in this case will always be NULL. 1046 | * - Checkable attribute takes precedence over Checked attribute. 1047 | * - 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. 1048 | The Chrome extension contextMenus API was taken as a reference. 1049 | https://developer.chrome.com/extensions/contextMenus 1050 | * - the items with icons and checkable items cannot coexist on the same menu level. The former take precedences over the latter. 1051 | * 1052 | * @param menu A XML string which describes menu structure. 1053 | * @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. 1054 | * 1055 | * @description An example menu XML: 1056 | * <Menu> 1057 | * <MenuItem Id="menuItemId1" Label="TestExample1" Enabled="true" Checkable="true" Checked="false" Icon="./image/small_16X16.png"/> 1058 | * <MenuItem Id="menuItemId2" Label="TestExample2"> 1059 | * <MenuItem Id="menuItemId2-1" Label="TestExample2-1" > 1060 | * <MenuItem Id="menuItemId2-1-1" Label="TestExample2-1-1" Enabled="false" Checkable="true" Checked="true"/> 1061 | * </MenuItem> 1062 | * <MenuItem Id="menuItemId2-2" Label="TestExample2-2" Enabled="true" Checkable="true" Checked="true"/> 1063 | * </MenuItem> 1064 | * <MenuItem Label="---" /> 1065 | * <MenuItem Id="menuItemId3" Label="TestExample3" Enabled="false" Checkable="true" Checked="false"/> 1066 | * </Menu> 1067 | */ 1068 | CSInterface.prototype.setContextMenu = function(menu, callback) 1069 | { 1070 | if ("string" != typeof menu) 1071 | { 1072 | return; 1073 | } 1074 | 1075 | window.__adobe_cep__.invokeAsync("setContextMenu", menu, callback); 1076 | }; 1077 | 1078 | /** 1079 | * Set context menu by JSON string. 1080 | * 1081 | * Since 6.0.0 1082 | * 1083 | * There are a number of conventions used to communicate what type of menu item to create and how it should be handled. 1084 | * - an item without menu ID or menu name is disabled and is not shown. 1085 | * - if the item label is "---" (three hyphens) then it is treated as a separator. The menu ID in this case will always be NULL. 1086 | * - Checkable attribute takes precedence over Checked attribute. 1087 | * - 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. 1088 | The Chrome extension contextMenus API was taken as a reference. 1089 | * - the items with icons and checkable items cannot coexist on the same menu level. The former take precedences over the latter. 1090 | https://developer.chrome.com/extensions/contextMenus 1091 | * 1092 | * @param menu A JSON string which describes menu structure. 1093 | * @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. 1094 | * 1095 | * @description An example menu JSON: 1096 | * 1097 | * { 1098 | * "menu": [ 1099 | * { 1100 | * "id": "menuItemId1", 1101 | * "label": "testExample1", 1102 | * "enabled": true, 1103 | * "checkable": true, 1104 | * "checked": false, 1105 | * "icon": "./image/small_16X16.png" 1106 | * }, 1107 | * { 1108 | * "id": "menuItemId2", 1109 | * "label": "testExample2", 1110 | * "menu": [ 1111 | * { 1112 | * "id": "menuItemId2-1", 1113 | * "label": "testExample2-1", 1114 | * "menu": [ 1115 | * { 1116 | * "id": "menuItemId2-1-1", 1117 | * "label": "testExample2-1-1", 1118 | * "enabled": false, 1119 | * "checkable": true, 1120 | * "checked": true 1121 | * } 1122 | * ] 1123 | * }, 1124 | * { 1125 | * "id": "menuItemId2-2", 1126 | * "label": "testExample2-2", 1127 | * "enabled": true, 1128 | * "checkable": true, 1129 | * "checked": true 1130 | * } 1131 | * ] 1132 | * }, 1133 | * { 1134 | * "label": "---" 1135 | * }, 1136 | * { 1137 | * "id": "menuItemId3", 1138 | * "label": "testExample3", 1139 | * "enabled": false, 1140 | * "checkable": true, 1141 | * "checked": false 1142 | * } 1143 | * ] 1144 | * } 1145 | * 1146 | */ 1147 | CSInterface.prototype.setContextMenuByJSON = function(menu, callback) 1148 | { 1149 | if ("string" != typeof menu) 1150 | { 1151 | return; 1152 | } 1153 | 1154 | window.__adobe_cep__.invokeAsync("setContextMenuByJSON", menu, callback); 1155 | }; 1156 | 1157 | /** 1158 | * Updates a context menu item by setting the enabled and selection status. 1159 | * 1160 | * Since 5.2.0 1161 | * 1162 | * @param menuItemID The menu item ID. 1163 | * @param enabled True to enable the item, false to disable it (gray it out). 1164 | * @param checked True to select the item, false to deselect it. 1165 | */ 1166 | CSInterface.prototype.updateContextMenuItem = function(menuItemID, enabled, checked) 1167 | { 1168 | var itemStatus = new ContextMenuItemStatus(menuItemID, enabled, checked); 1169 | ret = window.__adobe_cep__.invokeSync("updateContextMenuItem", JSON.stringify(itemStatus)); 1170 | }; 1171 | 1172 | /** 1173 | * Get the visibility status of an extension window. 1174 | * 1175 | * Since 6.0.0 1176 | * 1177 | * @return true if the extension window is visible; false if the extension window is hidden. 1178 | */ 1179 | CSInterface.prototype.isWindowVisible = function() 1180 | { 1181 | return window.__adobe_cep__.invokeSync("isWindowVisible", ""); 1182 | }; 1183 | 1184 | /** 1185 | * Resize extension's content to the specified dimensions. 1186 | * 1. Works with modal and modeless extensions in all Adobe products. 1187 | * 2. Extension's manifest min/max size constraints apply and take precedence. 1188 | * 3. For panel extensions 1189 | * 3.1 This works in all Adobe products except: 1190 | * * Premiere Pro 1191 | * * Prelude 1192 | * * After Effects 1193 | * 3.2 When the panel is in certain states (especially when being docked), 1194 | * it will not change to the desired dimensions even when the 1195 | * specified size satisfies min/max constraints. 1196 | * 1197 | * Since 6.0.0 1198 | * 1199 | * @param width The new width 1200 | * @param height The new height 1201 | */ 1202 | CSInterface.prototype.resizeContent = function(width, height) 1203 | { 1204 | window.__adobe_cep__.resizeContent(width, height); 1205 | }; 1206 | 1207 | /** 1208 | * Register the invalid certificate callback for an extension. 1209 | * This callback will be triggered when the extension tries to access the web site that contains the invalid certificate on the main frame. 1210 | * But if the extension does not call this function and tries to access the web site containing the invalid certificate, a default error page will be shown. 1211 | * 1212 | * Since 6.1.0 1213 | * 1214 | * @param callback the callback function 1215 | */ 1216 | CSInterface.prototype.registerInvalidCertificateCallback = function(callback) 1217 | { 1218 | return window.__adobe_cep__.registerInvalidCertificateCallback(callback); 1219 | }; 1220 | 1221 | /** 1222 | * Register an interest in some key events to prevent them from being sent to the host application. 1223 | * 1224 | * This function works with modeless extensions and panel extensions. 1225 | * Generally all the key events will be sent to the host application for these two extensions if the current focused element 1226 | * is not text input or dropdown, 1227 | * If you want to intercept some key events and want them to be handled in the extension, please call this function 1228 | * in advance to prevent them being sent to the host application. 1229 | * 1230 | * Since 6.1.0 1231 | * 1232 | * @param keyEventsInterest A JSON string describing those key events you are interested in. A null object or 1233 | an empty string will lead to removing the interest 1234 | * 1235 | * This JSON string should be an array, each object has following keys: 1236 | * 1237 | * keyCode: [Required] represents an OS system dependent virtual key code identifying 1238 | * the unmodified value of the pressed key. 1239 | * ctrlKey: [optional] a Boolean that indicates if the control key was pressed (true) or not (false) when the event occurred. 1240 | * altKey: [optional] a Boolean that indicates if the alt key was pressed (true) or not (false) when the event occurred. 1241 | * shiftKey: [optional] a Boolean that indicates if the shift key was pressed (true) or not (false) when the event occurred. 1242 | * metaKey: [optional] (Mac Only) a Boolean that indicates if the Meta key was pressed (true) or not (false) when the event occurred. 1243 | * On Macintosh keyboards, this is the command key. To detect Windows key on Windows, please use keyCode instead. 1244 | * An example JSON string: 1245 | * 1246 | * [ 1247 | * { 1248 | * "keyCode": 48 1249 | * }, 1250 | * { 1251 | * "keyCode": 123, 1252 | * "ctrlKey": true 1253 | * }, 1254 | * { 1255 | * "keyCode": 123, 1256 | * "ctrlKey": true, 1257 | * "metaKey": true 1258 | * } 1259 | * ] 1260 | * 1261 | */ 1262 | CSInterface.prototype.registerKeyEventsInterest = function(keyEventsInterest) 1263 | { 1264 | return window.__adobe_cep__.registerKeyEventsInterest(keyEventsInterest); 1265 | }; 1266 | 1267 | /** 1268 | * Set the title of the extension window. 1269 | * This function works with modal and modeless extensions in all Adobe products, and panel extensions in Photoshop, InDesign, InCopy, Illustrator, Flash Pro and Dreamweaver. 1270 | * 1271 | * Since 6.1.0 1272 | * 1273 | * @param title The window title. 1274 | */ 1275 | CSInterface.prototype.setWindowTitle = function(title) 1276 | { 1277 | window.__adobe_cep__.invokeSync("setWindowTitle", title); 1278 | }; 1279 | 1280 | /** 1281 | * Get the title of the extension window. 1282 | * This function works with modal and modeless extensions in all Adobe products, and panel extensions in Photoshop, InDesign, InCopy, Illustrator, Flash Pro and Dreamweaver. 1283 | * 1284 | * Since 6.1.0 1285 | * 1286 | * @return The window title. 1287 | */ 1288 | CSInterface.prototype.getWindowTitle = function() 1289 | { 1290 | return window.__adobe_cep__.invokeSync("getWindowTitle", ""); 1291 | }; 1292 | ``` -------------------------------------------------------------------------------- /mcp/ps-mcp.py: -------------------------------------------------------------------------------- ```python 1 | # MIT License 2 | # 3 | # Copyright (c) 2025 Mike Chambers 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining a copy 6 | # of this software and associated documentation files (the "Software"), to deal 7 | # in the Software without restriction, including without limitation the rights 8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | # copies of the Software, and to permit persons to whom the Software is 10 | # furnished to do so, subject to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included in all 13 | # copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | # SOFTWARE. 22 | 23 | from mcp.server.fastmcp import FastMCP, Image 24 | from core import init, sendCommand, createCommand 25 | from fonts import list_all_fonts_postscript 26 | import numpy as np 27 | import base64 28 | import socket_client 29 | import sys 30 | import os 31 | 32 | FONT_LIMIT = 1000 #max number of font names to return to AI 33 | 34 | #logger.log(f"Python path: {sys.executable}") 35 | #logger.log(f"PYTHONPATH: {os.environ.get('PYTHONPATH')}") 36 | #logger.log(f"Current working directory: {os.getcwd()}") 37 | #logger.log(f"Sys.path: {sys.path}") 38 | 39 | 40 | mcp_name = "Adobe Photoshop MCP Server" 41 | mcp = FastMCP(mcp_name, log_level="ERROR") 42 | print(f"{mcp_name} running on stdio", file=sys.stderr) 43 | 44 | APPLICATION = "photoshop" 45 | PROXY_URL = 'http://localhost:3001' 46 | PROXY_TIMEOUT = 20 47 | 48 | socket_client.configure( 49 | app=APPLICATION, 50 | url=PROXY_URL, 51 | timeout=PROXY_TIMEOUT 52 | ) 53 | 54 | init(APPLICATION, socket_client) 55 | 56 | @mcp.tool() 57 | def set_active_document(document_id:int): 58 | """ 59 | Sets the document with the specified ID to the active document in Photoshop 60 | 61 | Args: 62 | document_id (int): ID for the document to set as active. 63 | """ 64 | 65 | command = createCommand("setActiveDocument", { 66 | "documentId":document_id 67 | }) 68 | 69 | return sendCommand(command) 70 | 71 | @mcp.tool() 72 | def get_documents(): 73 | """ 74 | Returns information on the documents currently open in Photoshop 75 | """ 76 | 77 | command = createCommand("getDocuments", { 78 | }) 79 | 80 | return sendCommand(command) 81 | 82 | 83 | @mcp.tool() 84 | def create_gradient_layer_style( 85 | layer_id: int, 86 | angle: int, 87 | type:str, 88 | color_stops: list, 89 | opacity_stops: list): 90 | """ 91 | Applies gradient to active selection or entire layer if no selection exists. 92 | 93 | Color stops define transition points along the gradient (0-100), with color blending between stops. Opacity stops similarly control transparency transitions. 94 | 95 | Args: 96 | layer_id (int): ID for layer to apply gradient to. 97 | angle (int): Gradient angle (-180 to 180). 98 | type (str): LINEAR or RADIAL gradient. 99 | color_stops (list): Dictionaries defining color stops: 100 | - location (int): Position (0-100) along gradient. 101 | - color (dict): RGB values (0-255 for red/green/blue). 102 | - midpoint (int): Transition bias (0-100, default 50). 103 | opacity_stops (list): Dictionaries defining opacity stops: 104 | - location (int): Position (0-100) along gradient. 105 | - opacity (int): Level (0=transparent, 100=opaque). 106 | - midpoint (int): Transition bias (0-100, default 50). 107 | """ 108 | 109 | command = createCommand("createGradientLayerStyle", { 110 | "layerId":layer_id, 111 | "angle":angle, 112 | "colorStops":color_stops, 113 | "type":type, 114 | "opacityStops":opacity_stops 115 | }) 116 | 117 | return sendCommand(command) 118 | 119 | 120 | @mcp.tool() 121 | def duplicate_document(document_name: str): 122 | """Duplicates the current Photoshop Document into a new file 123 | 124 | 125 | Args: 126 | document_name (str): Name for the new document being created 127 | """ 128 | 129 | command = createCommand("duplicateDocument", { 130 | "name":document_name 131 | }) 132 | 133 | return sendCommand(command) 134 | 135 | 136 | @mcp.tool() 137 | def create_document(document_name: str, width: int, height:int, resolution:int, fill_color:dict = {"red":0, "green":0, "blue":0}, color_mode:str = "RGB"): 138 | """Creates a new Photoshop Document 139 | 140 | Layer are created from bottom up based on the order they are created in, so create background elements first and then build on top. 141 | 142 | New document will contain a layer named "Background" that is filled with the specified fill color 143 | 144 | Args: 145 | document_name (str): Name for the new document being created 146 | width (int): Width in pixels of the new document 147 | height (int): Height in pixels of the new document 148 | resolution (int): Resolution (Pixels per Inch) of the new document 149 | fill_color (dict): dict defining the background color fill of the new document 150 | color_mode (str): Color mode for the new document 151 | """ 152 | 153 | command = createCommand("createDocument", { 154 | "name":document_name, 155 | "width":width, 156 | "height":height, 157 | "resolution":resolution, 158 | "fillColor":fill_color, 159 | "colorMode":color_mode 160 | }) 161 | 162 | return sendCommand(command) 163 | 164 | @mcp.tool() 165 | def export_layers_as_png(layers_info: list[dict[str, str|int]]): 166 | """Exports multiple layers from the Photoshop document as PNG files. 167 | 168 | This function exports each specified layer as a separate PNG image file to its 169 | corresponding file path. The entire layer, including transparent space will be saved. 170 | 171 | Args: 172 | layers_info (list[dict[str, str|int]]): A list of dictionaries containing the export information. 173 | Each dictionary must have the following keys: 174 | - "layerId" (int): The ID of the layer to export as PNG. 175 | This layer must exist in the current document. 176 | - "filePath" (str): The absolute file path including filename where the PNG 177 | will be saved (e.g., "/path/to/directory/layername.png"). 178 | The parent directory must already exist or the export will fail. 179 | """ 180 | 181 | command = createCommand("exportLayersAsPng", { 182 | "layersInfo":layers_info 183 | }) 184 | 185 | return sendCommand(command) 186 | 187 | 188 | 189 | @mcp.tool() 190 | def save_document_as(file_path: str, file_type: str = "PSD"): 191 | """Saves the current Photoshop document to the specified location and format. 192 | 193 | Args: 194 | file_path (str): The absolute path (including filename) where the file will be saved. 195 | Example: "/Users/username/Documents/my_image.psd" 196 | file_type (str, optional): The file format to use when saving the document. 197 | Defaults to "PSD". 198 | Supported formats: 199 | - "PSD": Adobe Photoshop Document (preserves layers and editability) 200 | - "PNG": Portable Network Graphics (lossless compression with transparency) 201 | - "JPG": Joint Photographic Experts Group (lossy compression) 202 | 203 | Returns: 204 | dict: Response from the Photoshop operation indicating success status, and the path that the file was saved at 205 | """ 206 | 207 | command = createCommand("saveDocumentAs", { 208 | "filePath":file_path, 209 | "fileType":file_type 210 | }) 211 | 212 | return sendCommand(command) 213 | 214 | @mcp.tool() 215 | def save_document(): 216 | """Saves the current Photoshop Document 217 | """ 218 | 219 | command = createCommand("saveDocument", { 220 | }) 221 | 222 | return sendCommand(command) 223 | 224 | @mcp.tool() 225 | def group_layers(group_name: str, layer_ids: list[int]) -> list: 226 | """ 227 | Creates a new layer group from the specified layers in Photoshop. 228 | 229 | Note: The layers will be added to the group in the order they are specified in the document, and not the order of their layerIds passed in. The group will be made at the same level as the top most layer in the layer tree. 230 | 231 | Args: 232 | groupName (str): The name to assign to the newly created layer group. 233 | layerIds (list[int]): A list of layer ids to include in the new group. 234 | 235 | Raises: 236 | RuntimeError: If the operation fails or times out. 237 | 238 | """ 239 | 240 | 241 | command = createCommand("groupLayers", { 242 | "groupName":group_name, 243 | "layerIds":layer_ids 244 | }) 245 | 246 | return sendCommand(command) 247 | 248 | 249 | @mcp.tool() 250 | def get_layer_image(layer_id: int): 251 | """Returns a jpeg of the specified layer's content as an MCP Image object that can be displayed.""" 252 | 253 | command = createCommand("getLayerImage", 254 | { 255 | "layerId":layer_id 256 | } 257 | ) 258 | 259 | response = sendCommand(command) 260 | 261 | if response.get('status') == 'SUCCESS' and 'response' in response: 262 | image_data = response['response'] 263 | data_url = image_data.get('dataUrl') 264 | 265 | if data_url and data_url.startswith("data:image/jpeg;base64,"): 266 | # Strip the data URL prefix and decode the base64 JPEG bytes 267 | base64_data = data_url.split(",", 1)[1] 268 | jpeg_bytes = base64.b64decode(base64_data) 269 | 270 | return Image(data=jpeg_bytes, format="jpeg") 271 | 272 | return response 273 | 274 | 275 | @mcp.tool() 276 | def get_document_image(): 277 | """Returns a jpeg of the current visible Photoshop document as an MCP Image object that can be displayed.""" 278 | command = createCommand("getDocumentImage", {}) 279 | response = sendCommand(command) 280 | 281 | if response.get('status') == 'SUCCESS' and 'response' in response: 282 | image_data = response['response'] 283 | data_url = image_data.get('dataUrl') 284 | 285 | if data_url and data_url.startswith("data:image/jpeg;base64,"): 286 | # Strip the data URL prefix and decode the base64 JPEG bytes 287 | base64_data = data_url.split(",", 1)[1] 288 | jpeg_bytes = base64.b64decode(base64_data) 289 | 290 | return Image(data=jpeg_bytes, format="jpeg") 291 | 292 | return response 293 | 294 | @mcp.tool() 295 | def save_document_image_as_png(file_path: str): 296 | """ 297 | Capture the Photoshop document and save as PNG file 298 | 299 | Args: 300 | file_path: Where to save the PNG file 301 | 302 | Returns: 303 | dict: Status and file info 304 | """ 305 | command = createCommand("getDocumentImage", {}) 306 | response = sendCommand(command) 307 | 308 | if response.get('format') == 'raw' and 'rawDataBase64' in response: 309 | try: 310 | # Decode raw data 311 | raw_bytes = base64.b64decode(response['rawDataBase64']) 312 | 313 | # Extract metadata 314 | width = response['width'] 315 | height = response['height'] 316 | components = response['components'] 317 | 318 | # Convert to numpy array and reshape 319 | pixel_array = np.frombuffer(raw_bytes, dtype=np.uint8) 320 | image_array = pixel_array.reshape((height, width, components)) 321 | 322 | # Create and save PNG 323 | mode = 'RGBA' if components == 4 else 'RGB' 324 | image = Image.fromarray(image_array, mode) 325 | image.save(file_path, 'PNG') 326 | 327 | return { 328 | 'status': 'success', 329 | 'file_path': file_path, 330 | 'width': width, 331 | 'height': height, 332 | 'size_bytes': os.path.getsize(file_path) 333 | } 334 | 335 | except Exception as e: 336 | return { 337 | 'status': 'error', 338 | 'error': str(e) 339 | } 340 | else: 341 | return { 342 | 'status': 'error', 343 | 'error': 'No raw image data received' 344 | } 345 | 346 | @mcp.tool() 347 | def get_layers() -> list: 348 | """Returns a nested list of dicts that contain layer info and the order they are arranged in. 349 | 350 | Args: 351 | None 352 | 353 | Returns: 354 | list: A nested list of dictionaries containing layer information and hierarchy. 355 | Each dict has at minimum a 'name' key with the layer name. 356 | If a layer has sublayers, they will be contained in a 'layers' key which contains another list of layer dicts. 357 | Example: [{'name': 'Group 1', 'layers': [{'name': 'Layer 1'}, {'name': 'Layer 2'}]}, {'name': 'Background'}] 358 | """ 359 | 360 | command = createCommand("getLayers", {}) 361 | 362 | return sendCommand(command) 363 | 364 | 365 | @mcp.tool() 366 | def place_image( 367 | layer_id: int, 368 | image_path: str 369 | ): 370 | """Places the image at the specified path on the existing pixel layer with the specified id. 371 | 372 | The image will be placed on the center of the layer, and will fill the layer without changing its aspect ration (thus there may be bars at the top or bottom) 373 | 374 | Args: 375 | layer_id (int): The id of the layer where the image will be placed. 376 | image_path (str): The file path to the image that will be placed on the layer. 377 | """ 378 | 379 | command = createCommand("placeImage", { 380 | "layerId":layer_id, 381 | "imagePath":image_path 382 | }) 383 | 384 | return sendCommand(command) 385 | 386 | @mcp.tool() 387 | def harmonize_layer(layer_id:int, new_layer_name:str, rasterize_layer:bool = True): 388 | """Harmonizes (matches lighting and other settings) the selected layer with the background layers. 389 | 390 | The layer being harmonized should be rasterized and have some transparency. 391 | 392 | Args: 393 | layer_id (int): ID of the layer to be harmonizes. 394 | new_layer_name (str): Name for the new layer that will be created with the harmonized content 395 | rasterize_layer (bool): Whether the new layer should be rasterized. 396 | If not rasterized, the layer will remain a generative layer which 397 | allows the user to interact with it. True by default. 398 | """ 399 | 400 | command = createCommand("harmonizeLayer", { 401 | "layerId":layer_id, 402 | "newLayerName":new_layer_name, 403 | "rasterizeLayer":rasterize_layer 404 | }) 405 | 406 | return sendCommand(command) 407 | 408 | 409 | @mcp.tool() 410 | def rename_layers( 411 | layer_data: list[dict] 412 | ): 413 | """Renames one or more layers 414 | 415 | Args: 416 | layer_data (list[dict]): A list of dictionaries containing layer rename information. 417 | Each dictionary must have the following keys: 418 | - "layer_id" (int): ID of the layer to be renamed. 419 | - "new_layer_name" (str): New name for the layer. 420 | """ 421 | 422 | command = createCommand("renameLayers", { 423 | "layerData":layer_data 424 | }) 425 | 426 | return sendCommand(command) 427 | 428 | 429 | @mcp.tool() 430 | def scale_layer( 431 | layer_id:int, 432 | width:int, 433 | height:int, 434 | anchor_position:str, 435 | interpolation_method:str = "AUTOMATIC" 436 | ): 437 | """Scales the layer with the specified ID. 438 | 439 | Args: 440 | layer_id (int): ID of layer to be scaled. 441 | width (int): Percentage to scale horizontally. 442 | height (int): Percentage to scale vertically. 443 | anchor_position (str): The anchor position to rotate around, 444 | interpolation_method (str): Interpolation method to use when resampling the image 445 | """ 446 | 447 | command = createCommand("scaleLayer", { 448 | "layerId":layer_id, 449 | "width":width, 450 | "height":height, 451 | "anchorPosition":anchor_position, 452 | "interpolationMethod":interpolation_method 453 | }) 454 | 455 | return sendCommand(command) 456 | 457 | 458 | @mcp.tool() 459 | def rotate_layer( 460 | layer_id:int, 461 | angle:int, 462 | anchor_position:str, 463 | interpolation_method:str = "AUTOMATIC" 464 | ): 465 | """Rotates the layer with the specified ID. 466 | 467 | Args: 468 | layer_id (int): ID of layer to be scaled. 469 | angle (int): Angle (-359 to 359) to rotate the layer by in degrees 470 | anchor_position (str): The anchor position to rotate around, 471 | interpolation_method (str): Interpolation method to use when resampling the image 472 | """ 473 | 474 | command = createCommand("rotateLayer", { 475 | "layerId":layer_id, 476 | "angle":angle, 477 | "anchorPosition":anchor_position, 478 | "interpolationMethod":interpolation_method 479 | }) 480 | 481 | return sendCommand(command) 482 | 483 | 484 | @mcp.tool() 485 | def flip_layer( 486 | layer_id:int, 487 | axis:str 488 | ): 489 | """Flips the layer with the specified ID on the specified axis. 490 | 491 | Args: 492 | layer_id (int): ID of layer to be scaled. 493 | axis (str): The axis on which to flip the layer. Valid values are "horizontal", "vertical" or "both" 494 | """ 495 | 496 | command = createCommand("flipLayer", { 497 | "layerId":layer_id, 498 | "axis":axis 499 | }) 500 | 501 | return sendCommand(command) 502 | 503 | 504 | @mcp.tool() 505 | def delete_layer( 506 | layer_id:int 507 | ): 508 | """Deletes the layer with the specified ID 509 | 510 | Args: 511 | layer_id (int): ID of the layer to be deleted 512 | """ 513 | 514 | command = createCommand("deleteLayer", { 515 | "layerId":layer_id 516 | }) 517 | 518 | return sendCommand(command) 519 | 520 | 521 | 522 | @mcp.tool() 523 | def set_layer_visibility( 524 | layer_id:int, 525 | visible:bool 526 | ): 527 | """Sets the visibility of the layer with the specified ID 528 | 529 | Args: 530 | layer_id (int): ID of the layer to set visibility 531 | visible (bool): Whether the layer is visible 532 | """ 533 | 534 | command = createCommand("setLayerVisibility", { 535 | "layerId":layer_id, 536 | "visible":visible 537 | }) 538 | 539 | return sendCommand(command) 540 | 541 | 542 | @mcp.tool() 543 | def generate_image( 544 | layer_name:str, 545 | prompt:str, 546 | content_type:str = "none" 547 | ): 548 | """Uses Adobe Firefly Generative AI to generate an image on a new layer with the specified layer name. 549 | 550 | If there is an active selection, it will use that region for the generation. Otherwise it will generate 551 | on the entire layer. 552 | 553 | Args: 554 | layer_name (str): Name for the layer that will be created and contain the generated image 555 | prompt (str): Prompt describing the image to be generated 556 | content_type (str): The type of image to be generated. Options include "photo", "art" or "none" (default) 557 | """ 558 | 559 | command = createCommand("generateImage", { 560 | "layerName":layer_name, 561 | "prompt":prompt, 562 | "contentType":content_type 563 | }) 564 | 565 | return sendCommand(command) 566 | 567 | @mcp.tool() 568 | def generative_fill( 569 | layer_name: str, 570 | prompt: str, 571 | layer_id: int, 572 | content_type: str = "none" 573 | ): 574 | """Uses Adobe Firefly Generative AI to perform generative fill within the current selection. 575 | 576 | This function uses generative fill to seamlessly integrate new content into the existing image. 577 | It requires an active selection, and will fill that region taking into account the surrounding 578 | context and layers below. The AI considers the existing content to create a natural, 579 | contextually-aware fill. 580 | 581 | Args: 582 | layer_name (str): Name for the layer that will be created and contain the generated fill 583 | prompt (str): Prompt describing the content to be generated within the selection 584 | layer_id (int): ID of the layer to work with (though a new layer is created for the result) 585 | content_type (str): The type of image to be generated. Options include "photo", "art" or "none" (default) 586 | 587 | Returns: 588 | dict: Response from Photoshop containing the operation status and layer information 589 | """ 590 | 591 | command = createCommand("generativeFill", { 592 | "layerName":layer_name, 593 | "prompt":prompt, 594 | "layerId":layer_id, 595 | "contentType":content_type, 596 | }) 597 | 598 | return sendCommand(command) 599 | 600 | 601 | @mcp.tool() 602 | def move_layer( 603 | layer_id:int, 604 | position:str 605 | ): 606 | """Moves the layer within the layer stack based on the specified position 607 | 608 | Args: 609 | layer_id (int): Name for the layer that will be moved 610 | position (str): How the layer position within the layer stack will be updated. Value values are: TOP (Place above all layers), BOTTOM (Place below all layers), UP (Move up one layer), DOWN (Move down one layer) 611 | """ 612 | 613 | command = createCommand("moveLayer", { 614 | "layerId":layer_id, 615 | "position":position 616 | }) 617 | 618 | return sendCommand(command) 619 | 620 | @mcp.tool() 621 | def get_document_info(): 622 | """Retrieves information about the currently active document. 623 | 624 | Returns: 625 | response : An object containing the following document properties: 626 | - height (int): The height of the document in pixels. 627 | - width (int): The width of the document in pixels. 628 | - colorMode (str): The document's color mode as a string. 629 | - pixelAspectRatio (float): The pixel aspect ratio of the document. 630 | - resolution (float): The document's resolution (DPI). 631 | - path (str): The file path of the document, if saved. 632 | - saved (bool): Whether the document has been saved (True if it has a valid file path). 633 | - hasUnsavedChanges (bool): Whether the document contains unsaved changes. 634 | 635 | """ 636 | 637 | command = createCommand("getDocumentInfo", {}) 638 | 639 | return sendCommand(command) 640 | 641 | @mcp.tool() 642 | def crop_document(): 643 | """Crops the document to the active selection. 644 | 645 | This function removes all content outside the selection area and resizes the document 646 | so that the selection becomes the new canvas size. 647 | 648 | An active selection is required. 649 | """ 650 | 651 | command = createCommand("cropDocument", {}) 652 | 653 | return sendCommand(command) 654 | 655 | @mcp.tool() 656 | def paste_from_clipboard(layer_id: int, paste_in_place: bool = True): 657 | """Pastes the current clipboard contents onto the specified layer. 658 | 659 | If `paste_in_place` is True, the content will be positioned exactly where it was cut or copied from. 660 | If False and an active selection exists, the content will be centered within the selection. 661 | If no selection is active, the content will be placed at the center of the layer. 662 | 663 | Args: 664 | layer_id (int): The ID of the layer where the clipboard contents will be pasted. 665 | paste_in_place (bool): Whether to paste at the original location (True) or adjust based on selection/layer center (False). 666 | """ 667 | 668 | 669 | command = createCommand("pasteFromClipboard", { 670 | "layerId":layer_id, 671 | "pasteInPlace":paste_in_place 672 | }) 673 | 674 | return sendCommand(command) 675 | 676 | @mcp.tool() 677 | def rasterize_layer(layer_id: int): 678 | """Converts the specified layer into a rasterized (flat) image. 679 | 680 | This process removes any vector, text, or smart object properties, turning the layer 681 | into pixel-based content. 682 | 683 | Args: 684 | layer_id (int): The name of the layer to rasterize. 685 | """ 686 | 687 | command = createCommand("rasterizeLayer", { 688 | "layerId":layer_id 689 | }) 690 | 691 | return sendCommand(command) 692 | 693 | @mcp.tool() 694 | def open_photoshop_file(file_path: str): 695 | """Opens the specified Photoshop-compatible file within Photoshop. 696 | 697 | This function attempts to open a file in Adobe Photoshop. The file must be in a 698 | format compatible with Photoshop, such as PSD, TIFF, JPEG, PNG, etc. 699 | 700 | Args: 701 | file_path (str): Complete absolute path to the file to be opened, including filename and extension. 702 | 703 | Returns: 704 | dict: Response from the Photoshop operation indicating success status. 705 | 706 | Raises: 707 | RuntimeError: If the file doesn't exist, is not accessible, or is in an unsupported format. 708 | """ 709 | 710 | command = createCommand("openFile", { 711 | "filePath":file_path 712 | }) 713 | 714 | return sendCommand(command) 715 | 716 | @mcp.tool() 717 | def cut_selection_to_clipboard(layer_id: int): 718 | """Copies and removes (cuts) the selected pixels from the specified layer to the system clipboard. 719 | 720 | This function requires an active selection. 721 | 722 | Args: 723 | layer_id (int): The name of the layer that contains the pixels to copy and remove. 724 | """ 725 | 726 | command = createCommand("cutSelectionToClipboard", { 727 | "layerId":layer_id 728 | }) 729 | 730 | return sendCommand(command) 731 | 732 | 733 | @mcp.tool() 734 | def copy_merged_selection_to_clipboard(): 735 | """Copies the selected pixels from all visible layers to the system clipboard. 736 | 737 | This function requires an active selection. If no selection is active, the operation will fail. 738 | The copied content will include pixel data from all visible layers within the selection area, 739 | effectively capturing what you see on screen. 740 | 741 | Returns: 742 | dict: Response from the Photoshop operation indicating success status. 743 | 744 | Raises: 745 | RuntimeError: If no active selection exists. 746 | """ 747 | 748 | command = createCommand("copyMergedSelectionToClipboard", {}) 749 | 750 | return sendCommand(command) 751 | 752 | @mcp.tool() 753 | def copy_selection_to_clipboard(layer_id: int): 754 | """Copies the selected pixels from the specified layer to the system clipboard. 755 | 756 | This function requires an active selection. If no selection is active, the operation will fail. 757 | 758 | Args: 759 | layer_id (int): The name of the layer that contains the pixels to copy. 760 | 761 | Returns: 762 | dict: Response from the Photoshop operation indicating success status. 763 | """ 764 | 765 | command = createCommand("copySelectionToClipboard", { 766 | "layerId":layer_id 767 | }) 768 | 769 | return sendCommand(command) 770 | 771 | @mcp.tool() 772 | def select_subject(layer_id: int): 773 | """Automatically selects the subject in the specified layer. 774 | 775 | This function identifies and selects the subject in the given image layer. 776 | It returns an object containing a property named `hasActiveSelection`, 777 | which indicates whether any pixels were selected (e.g., if no subject was detected). 778 | 779 | Args: 780 | layer_int (int): The name of that contains the image to select the subject from. 781 | """ 782 | 783 | 784 | command = createCommand("selectSubject", { 785 | "layerId":layer_id 786 | }) 787 | 788 | return sendCommand(command) 789 | 790 | @mcp.tool() 791 | def select_sky(layer_id: int): 792 | """Automatically selects the sky in the specified layer. 793 | 794 | This function identifies and selects the sky in the given image layer. 795 | It returns an object containing a property named `hasActiveSelection`, 796 | which indicates whether any pixels were selected (e.g., if no sky was detected). 797 | 798 | Args: 799 | layer_id (int): The name of that contains the image to select the sky from. 800 | """ 801 | 802 | 803 | command = createCommand("selectSky", { 804 | "layerId":layer_id 805 | }) 806 | 807 | return sendCommand(command) 808 | 809 | 810 | @mcp.tool() 811 | def get_layer_bounds( 812 | layer_id: int 813 | ): 814 | """Returns the pixel bounds for the layer with the specified ID 815 | 816 | Args: 817 | layer_id (int): ID of the layer to get the bounds information from 818 | 819 | Returns: 820 | dict: A dictionary containing the layer bounds with the following properties: 821 | - left (int): The x-coordinate of the left edge of the layer 822 | - top (int): The y-coordinate of the top edge of the layer 823 | - right (int): The x-coordinate of the right edge of the layer 824 | - bottom (int): The y-coordinate of the bottom edge of the layer 825 | 826 | Raises: 827 | RuntimeError: If the layer doesn't exist or if the operation fails 828 | """ 829 | 830 | command = createCommand("getLayerBounds", { 831 | "layerId":layer_id 832 | }) 833 | 834 | return sendCommand(command) 835 | 836 | @mcp.tool() 837 | def remove_background( 838 | layer_id:int 839 | ): 840 | """Automatically removes the background of the image in the layer with the specified ID and keeps the main subject 841 | 842 | Args: 843 | layer_id (int): ID of the layer to remove the background from 844 | """ 845 | 846 | command = createCommand("removeBackground", { 847 | "layerId":layer_id 848 | }) 849 | 850 | return sendCommand(command) 851 | 852 | @mcp.tool() 853 | def create_pixel_layer( 854 | layer_name:str, 855 | fill_neutral:bool, 856 | opacity:int = 100, 857 | blend_mode:str = "NORMAL", 858 | ): 859 | """Creates a new pixel layer with the specified ID 860 | 861 | Args: 862 | layer_name (str): Name of the new layer being created 863 | fill_neutral (bool): Whether to fill the layer with a neutral color when applying Blend Mode. 864 | opacity (int): Opacity of the newly created layer 865 | blend_mode (str): Blend mode of the newly created layer 866 | """ 867 | 868 | command = createCommand("createPixelLayer", { 869 | "layerName":layer_name, 870 | "opacity":opacity, 871 | "fillNeutral":fill_neutral, 872 | "blendMode":blend_mode 873 | }) 874 | 875 | return sendCommand(command) 876 | 877 | @mcp.tool() 878 | def create_multi_line_text_layer( 879 | layer_name:str, 880 | text:str, 881 | font_size:int, 882 | postscript_font_name:str, 883 | opacity:int = 100, 884 | blend_mode:str = "NORMAL", 885 | text_color:dict = {"red":255, "green":255, "blue":255}, 886 | position:dict = {"x": 100, "y":100}, 887 | bounds:dict = {"top": 0, "left": 0, "bottom": 250, "right": 300}, 888 | justification:str = "LEFT" 889 | ): 890 | 891 | """ 892 | Creates a new multi-line text layer with the specified ID within the current Photoshop document. 893 | 894 | Args: 895 | layer_name (str): The name of the layer to be created. Can be used to select in other api calls. 896 | text (str): The text to include on the layer. 897 | font_size (int): Font size. 898 | postscript_font_name (string): Postscript Font Name to display the text in. Valid list available via get_option_info. 899 | opacity (int): Opacity for the layer specified in percent. 900 | blend_mode (str): Blend Mode for the layer. Valid list available via get_option_info 901 | text_color (dict): Color of the text expressed in Red, Green, Blue values between 0 and 255 902 | position (dict): Position (dict with x, y values) where the text will be placed in the layer. Based on bottom left point of the text. 903 | bounds (dict): text bounding box 904 | justification (str): text justification. Valid list available via get_option_info. 905 | """ 906 | 907 | command = createCommand("createMultiLineTextLayer", { 908 | "layerName":layer_name, 909 | "contents":text, 910 | "fontSize": font_size, 911 | "opacity":opacity, 912 | "position":position, 913 | "fontName":postscript_font_name, 914 | "textColor":text_color, 915 | "blendMode":blend_mode, 916 | "bounds":bounds, 917 | "justification":justification 918 | }) 919 | 920 | return sendCommand(command) 921 | 922 | 923 | @mcp.tool() 924 | def create_single_line_text_layer( 925 | layer_name:str, 926 | text:str, 927 | font_size:int, 928 | postscript_font_name:str, 929 | opacity:int = 100, 930 | blend_mode:str = "NORMAL", 931 | text_color:dict = {"red":255, "green":255, "blue":255}, 932 | position:dict = {"x": 100, "y":100} 933 | ): 934 | 935 | """ 936 | Create a new single line text layer with the specified ID within the current Photoshop document. 937 | 938 | Args: 939 | layer_name (str): The name of the layer to be created. Can be used to select in other api calls. 940 | text (str): The text to include on the layer. 941 | font_size (int): Font size. 942 | postscript_font_name (string): Postscript Font Name to display the text in. Valid list available via get_option_info. 943 | opacity (int): Opacity for the layer specified in percent. 944 | blend_mode (str): Blend Mode for the layer. Valid list available via get_option_info 945 | text_color (dict): Color of the text expressed in Red, Green, Blue values between 0 and 255 946 | position (dict): Position (dict with x, y values) where the text will be placed in the layer. Based on bottom left point of the text. 947 | """ 948 | 949 | command = createCommand("createSingleLineTextLayer", { 950 | "layerName":layer_name, 951 | "contents":text, 952 | "fontSize": font_size, 953 | "opacity":opacity, 954 | "position":position, 955 | "fontName":postscript_font_name, 956 | "textColor":text_color, 957 | "blendMode":blend_mode 958 | }) 959 | 960 | return sendCommand(command) 961 | 962 | @mcp.tool() 963 | def edit_text_layer( 964 | layer_id:int, 965 | text:str = None, 966 | font_size:int = None, 967 | postscript_font_name:str = None, 968 | text_color:dict = None, 969 | ): 970 | 971 | """ 972 | Edits the text content of an existing text layer in the current Photoshop document. 973 | 974 | Args: 975 | layer_id (int): The ID of the existing text layer to edit. 976 | text (str): The new text content to replace the current text in the layer. If None, text will not be changed. 977 | font_size (int): Font size. If None, size will not be changed. 978 | postscript_font_name (string): Postscript Font Name to display the text in. Valid list available via get_option_info. If None, font will not will not be changed. 979 | text_color (dict): Color of the text expressed in Red, Green, Blue values between 0 and 255 in format of {"red":255, "green":255, "blue":255}. If None, color will not be changed 980 | """ 981 | 982 | command = createCommand("editTextLayer", { 983 | "layerId":layer_id, 984 | "contents":text, 985 | "fontSize": font_size, 986 | "fontName":postscript_font_name, 987 | "textColor":text_color 988 | }) 989 | 990 | return sendCommand(command) 991 | 992 | 993 | 994 | @mcp.tool() 995 | def translate_layer( 996 | layer_id: int, 997 | x_offset:int = 0, 998 | y_offset:int = 0 999 | ): 1000 | 1001 | """ 1002 | Moves the layer with the specified ID on the X and Y axis by the specified number of pixels. 1003 | 1004 | Args: 1005 | layer_name (str): The name of the layer that should be moved. 1006 | x_offset (int): Amount to move on the horizontal axis. Negative values move the layer left, positive values right 1007 | y_offset (int): Amount to move on the vertical axis. Negative values move the layer down, positive values up 1008 | """ 1009 | 1010 | command = createCommand("translateLayer", { 1011 | "layerId":layer_id, 1012 | "xOffset":x_offset, 1013 | "yOffset":y_offset 1014 | }) 1015 | 1016 | return sendCommand(command) 1017 | 1018 | @mcp.tool() 1019 | def remove_layer_mask( 1020 | layer_id: int 1021 | ): 1022 | 1023 | """Removes the layer mask from the specified layer. 1024 | 1025 | Args: 1026 | None 1027 | """ 1028 | 1029 | command = createCommand("removeLayerMask", { 1030 | "layerId":layer_id 1031 | }) 1032 | 1033 | return sendCommand(command) 1034 | 1035 | @mcp.tool() 1036 | def add_layer_mask_from_selection( 1037 | layer_id: int 1038 | ): 1039 | 1040 | """Creates a layer mask on the specified layer defined by the active selection. 1041 | 1042 | This function takes the current active selection in the document and converts it into a layer mask 1043 | for the specified layer. Selected areas will be visible, while non-selected areas will be hidden. 1044 | An active selection must exist before calling this function. 1045 | 1046 | Args: 1047 | layer_name (str): The name of the layer to which the mask will be applied 1048 | """ 1049 | 1050 | command = createCommand("addLayerMask", { 1051 | "layerId":layer_id 1052 | }) 1053 | 1054 | return sendCommand(command) 1055 | 1056 | @mcp.tool() 1057 | def set_layer_properties( 1058 | layer_id: int, 1059 | blend_mode: str = "NORMAL", 1060 | layer_opacity: int = 100, 1061 | fill_opacity: int = 100, 1062 | is_clipping_mask: bool = False 1063 | ): 1064 | 1065 | """Sets the blend mode and opacity properties on the layer with the specified ID 1066 | 1067 | Args: 1068 | layer_id (int): The ID of the layer whose properties should be updated 1069 | blend_mode (str): The blend mode for the layer 1070 | layer_opacity (int): The opacity for the layer (0 - 100) 1071 | fill_opacity (int): The fill opacity for the layer (0 - 100). Will ignore anny effects that have been applied to the layer. 1072 | is_clipping_mask (bool): A boolean indicating whether this layer will be clipped to (masked by) the layer below it 1073 | """ 1074 | 1075 | command = createCommand("setLayerProperties", { 1076 | "layerId":layer_id, 1077 | "blendMode":blend_mode, 1078 | "layerOpacity":layer_opacity, 1079 | "fillOpacity":fill_opacity, 1080 | "isClippingMask":is_clipping_mask 1081 | }) 1082 | 1083 | return sendCommand(command) 1084 | 1085 | @mcp.tool() 1086 | def fill_selection( 1087 | layer_id: int, 1088 | color:dict = {"red":255, "green":0, "blue":0}, 1089 | blend_mode:str = "NORMAL", 1090 | opacity:int = 100, 1091 | ): 1092 | 1093 | """Fills the selection on the pixel layer with the specified ID 1094 | 1095 | Args: 1096 | layer_id (int): The ID of existing pixel layer to add the fill 1097 | color (dict): The color of the fill 1098 | blend_mode (dict): The blend mode for the fill 1099 | opacity (int) : The opacity of the color for the fill 1100 | """ 1101 | 1102 | command = createCommand("fillSelection", { 1103 | "layerId":layer_id, 1104 | "color":color, 1105 | "blendMode":blend_mode, 1106 | "opacity":opacity 1107 | }) 1108 | 1109 | return sendCommand(command) 1110 | 1111 | 1112 | 1113 | @mcp.tool() 1114 | def delete_selection( 1115 | layer_id: int 1116 | ): 1117 | 1118 | """Removes the pixels within the selection on the pixel layer with the specified ID 1119 | 1120 | Args: 1121 | layer_id (int): The ID of the layer from which the content of the selection should be deleted 1122 | """ 1123 | 1124 | command = createCommand("deleteSelection", { 1125 | "layerId":layer_id 1126 | }) 1127 | 1128 | return sendCommand(command) 1129 | 1130 | 1131 | @mcp.tool() 1132 | def invert_selection(): 1133 | 1134 | """Inverts the current selection in the Photoshop document""" 1135 | 1136 | command = createCommand("invertSelection", {}) 1137 | return sendCommand(command) 1138 | 1139 | 1140 | @mcp.tool() 1141 | def clear_selection(): 1142 | 1143 | """Clears / deselects the current selection""" 1144 | 1145 | command = createCommand("selectRectangle", { 1146 | "feather":0, 1147 | "antiAlias":True, 1148 | "bounds":{"top": 0, "left": 0, "bottom": 0, "right": 0} 1149 | }) 1150 | 1151 | return sendCommand(command) 1152 | 1153 | @mcp.tool() 1154 | def select_rectangle( 1155 | layer_id:int, 1156 | feather:int = 0, 1157 | anti_alias:bool = True, 1158 | bounds:dict = {"top": 0, "left": 0, "bottom": 100, "right": 100} 1159 | ): 1160 | 1161 | """Creates a rectangular selection and selects the specified layer 1162 | 1163 | Args: 1164 | layer_id (int): The layer to do the select rectangle action on. 1165 | feather (int): The amount of feathering in pixels to apply to the selection (0 - 1000) 1166 | anti_alias (bool): Whether anti-aliases is applied to the selection 1167 | bounds (dict): The bounds for the rectangle selection 1168 | """ 1169 | 1170 | command = createCommand("selectRectangle", { 1171 | "layerId":layer_id, 1172 | "feather":feather, 1173 | "antiAlias":anti_alias, 1174 | "bounds":bounds 1175 | }) 1176 | 1177 | return sendCommand(command) 1178 | 1179 | @mcp.tool() 1180 | def select_polygon( 1181 | layer_id:int, 1182 | feather:int = 0, 1183 | anti_alias:bool = True, 1184 | points:list[dict[str, int]] = [{"x": 50, "y": 10}, {"x": 100, "y": 90}, {"x": 10, "y": 40}] 1185 | ): 1186 | 1187 | """Creates an n-sided polygon selection and selects the specified layer 1188 | 1189 | Args: 1190 | layer_id (int): The layer to do the selection action on. 1191 | feather (int): The amount of feathering in pixels to apply to the selection (0 - 1000) 1192 | anti_alias (bool): Whether anti-aliases is applied to the selection 1193 | points (list): The points that define the sides of the selection, defined via a list of dicts with x, y values. 1194 | """ 1195 | 1196 | command = createCommand("selectPolygon", { 1197 | "layerId":layer_id, 1198 | "feather":feather, 1199 | "antiAlias":anti_alias, 1200 | "points":points 1201 | }) 1202 | 1203 | return sendCommand(command) 1204 | 1205 | @mcp.tool() 1206 | def select_ellipse( 1207 | layer_id:int, 1208 | feather:int = 0, 1209 | anti_alias:bool = True, 1210 | bounds:dict = {"top": 0, "left": 0, "bottom": 100, "right": 100} 1211 | ): 1212 | 1213 | """Creates an elliptical selection and selects the specified layer 1214 | 1215 | Args: 1216 | layer_id (int): The layer to do the selection action on. 1217 | feather (int): The amount of feathering in pixels to apply to the selection (0 - 1000) 1218 | anti_alias (bool): Whether anti-aliases is applied to the selection 1219 | bounds (dict): The bounds that will define the elliptical selection. 1220 | """ 1221 | 1222 | command = createCommand("selectEllipse", { 1223 | "layerId":layer_id, 1224 | "feather":feather, 1225 | "antiAlias":anti_alias, 1226 | "bounds":bounds 1227 | }) 1228 | 1229 | return sendCommand(command) 1230 | 1231 | @mcp.tool() 1232 | def align_content( 1233 | layer_id: int, 1234 | alignment_mode:str 1235 | ): 1236 | 1237 | """ 1238 | Aligns content on layer with the specified ID to the current selection. 1239 | 1240 | Args: 1241 | layer_id (int): The ID of the layer in which to align the content 1242 | alignment_mode (str): How the content should be aligned. Available options via alignment_modes 1243 | """ 1244 | 1245 | command = createCommand("alignContent", { 1246 | "layerId":layer_id, 1247 | "alignmentMode":alignment_mode 1248 | }) 1249 | 1250 | return sendCommand(command) 1251 | 1252 | @mcp.tool() 1253 | def add_drop_shadow_layer_style( 1254 | layer_id: int, 1255 | blend_mode:str = "MULTIPLY", 1256 | color:dict = {"red":0, "green":0, "blue":0}, 1257 | opacity:int = 35, 1258 | angle:int = 160, 1259 | distance:int = 3, 1260 | spread:int = 0, 1261 | size:int = 7 1262 | ): 1263 | """Adds a drop shadow layer style to the layer with the specified ID 1264 | 1265 | Args: 1266 | layer_id (int): The ID for the layer with the content to add the drop shadow to 1267 | blend_mode (str): The blend mode for the drop shadow 1268 | color (dict): The color for the drop shadow 1269 | opacity (int): The opacity of the drop shadow 1270 | angle (int): The angle (-180 to 180) of the drop shadow relative to the content 1271 | distance (int): The distance in pixels of the drop shadow (0 to 30000) 1272 | spread (int): Defines how gradually the shadow fades out at its edges, with higher values creating a harsher, more defined edge, and lower values a softer, more feathered edge (0 to 100) 1273 | size (int): Control the blur and spread of the shadow effect (0 to 250) 1274 | """ 1275 | 1276 | command = createCommand("addDropShadowLayerStyle", { 1277 | "layerId":layer_id, 1278 | "blendMode":blend_mode, 1279 | "color":color, 1280 | "opacity":opacity, 1281 | "angle":angle, 1282 | "distance":distance, 1283 | "spread":spread, 1284 | "size":size 1285 | }) 1286 | 1287 | return sendCommand(command) 1288 | 1289 | @mcp.tool() 1290 | def duplicate_layer(layer_to_duplicate_id:int, duplicate_layer_name:str): 1291 | """ 1292 | Duplicates the layer specified by layer_to_duplicate_id ID, creating a new layer above it with the name specified by duplicate_layer_name 1293 | 1294 | Args: 1295 | layer_to_duplicate_id (id): The id of the layer to be duplicated 1296 | duplicate_layer_name (str): Name for the newly created layer 1297 | """ 1298 | 1299 | command = createCommand("duplicateLayer", { 1300 | "sourceLayerId":layer_to_duplicate_id, 1301 | "duplicateLayerName":duplicate_layer_name, 1302 | }) 1303 | 1304 | return sendCommand(command) 1305 | 1306 | @mcp.tool() 1307 | def flatten_all_layers(layer_name:str): 1308 | """ 1309 | Flatten all layers in the document into a single layer with specified name 1310 | 1311 | Args: 1312 | layer_name (str): The name of the merged layer 1313 | """ 1314 | 1315 | command = createCommand("flattenAllLayers", { 1316 | "layerName":layer_name, 1317 | }) 1318 | 1319 | return sendCommand(command) 1320 | 1321 | @mcp.tool() 1322 | def add_color_balance_adjustment_layer( 1323 | layer_id: int, 1324 | highlights:list = [0,0,0], 1325 | midtones:list = [0,0,0], 1326 | shadows:list = [0,0,0]): 1327 | """Adds an adjustment layer to the layer with the specified ID to adjust color balance 1328 | 1329 | Each property highlights, midtones and shadows contains an array of 3 values between 1330 | -100 and 100 that represent the relative position between two colors. 1331 | 1332 | First value is between cyan and red 1333 | The second value is between magenta and green 1334 | The third value is between yellow and blue 1335 | 1336 | Args: 1337 | layer_id (int): The ID of the layer to apply the color balance adjustment layer 1338 | highlights (list): Relative color values for highlights 1339 | midtones (list): Relative color values for midtones 1340 | shadows (list): Relative color values for shadows 1341 | """ 1342 | 1343 | command = createCommand("addColorBalanceAdjustmentLayer", { 1344 | "layerId":layer_id, 1345 | "highlights":highlights, 1346 | "midtones":midtones, 1347 | "shadows":shadows 1348 | }) 1349 | 1350 | return sendCommand(command) 1351 | 1352 | @mcp.tool() 1353 | def add_brightness_contrast_adjustment_layer( 1354 | layer_id: int, 1355 | brightness:int = 0, 1356 | contrast:int = 0): 1357 | """Adds an adjustment layer to the layer with the specified ID to adjust brightness and contrast 1358 | 1359 | Args: 1360 | layer_id (int): The ID of the layer to apply the brightness and contrast adjustment layer 1361 | brightness (int): The brightness value (-150 to 150) 1362 | contrasts (int): The contrast value (-50 to 100) 1363 | """ 1364 | 1365 | command = createCommand("addBrightnessContrastAdjustmentLayer", { 1366 | "layerId":layer_id, 1367 | "brightness":brightness, 1368 | "contrast":contrast 1369 | }) 1370 | 1371 | return sendCommand(command) 1372 | 1373 | 1374 | @mcp.tool() 1375 | def add_stroke_layer_style( 1376 | layer_id: int, 1377 | size: int = 2, 1378 | color: dict = {"red": 0, "green": 0, "blue": 0}, 1379 | opacity: int = 100, 1380 | position: str = "CENTER", 1381 | blend_mode: str = "NORMAL" 1382 | ): 1383 | """Adds a stroke layer style to the layer with the specified ID. 1384 | 1385 | Args: 1386 | layer_id (int): The ID of the layer to apply the stroke effect to. 1387 | size (int, optional): The width of the stroke in pixels. Defaults to 2. 1388 | color (dict, optional): The color of the stroke as RGB values. Defaults to black {"red": 0, "green": 0, "blue": 0}. 1389 | opacity (int, optional): The opacity of the stroke as a percentage (0-100). Defaults to 100. 1390 | position (str, optional): The position of the stroke relative to the layer content. 1391 | Options include "CENTER", "INSIDE", or "OUTSIDE". Defaults to "CENTER". 1392 | blend_mode (str, optional): The blend mode for the stroke effect. Defaults to "NORMAL". 1393 | """ 1394 | 1395 | command = createCommand("addStrokeLayerStyle", { 1396 | "layerId":layer_id, 1397 | "size":size, 1398 | "color":color, 1399 | "opacity":opacity, 1400 | "position":position, 1401 | "blendMode":blend_mode 1402 | }) 1403 | 1404 | return sendCommand(command) 1405 | 1406 | 1407 | @mcp.tool() 1408 | def add_vibrance_adjustment_layer( 1409 | layer_id: int, 1410 | vibrance:int = 0, 1411 | saturation:int = 0): 1412 | """Adds an adjustment layer to layer with the specified ID to adjust vibrance and saturation 1413 | 1414 | Args: 1415 | layer_id (int): The ID of the layer to apply the vibrance and saturation adjustment layer 1416 | vibrance (int): Controls the intensity of less-saturated colors while preventing oversaturation of already-saturated colors. Range -100 to 100. 1417 | saturation (int): Controls the intensity of all colors equally. Range -100 to 100. 1418 | """ 1419 | #0.1 to 255 1420 | 1421 | command = createCommand("addAdjustmentLayerVibrance", { 1422 | "layerId":layer_id, 1423 | "saturation":saturation, 1424 | "vibrance":vibrance 1425 | }) 1426 | 1427 | return sendCommand(command) 1428 | 1429 | @mcp.tool() 1430 | def add_black_and_white_adjustment_layer( 1431 | layer_id: int, 1432 | colors: dict = {"blue": 20, "cyan": 60, "green": 40, "magenta": 80, "red": 40, "yellow": 60}, 1433 | tint: bool = False, 1434 | tint_color: dict = {"red": 225, "green": 211, "blue": 179} 1435 | ): 1436 | """Adds a Black & White adjustment layer to the specified layer. 1437 | 1438 | Creates an adjustment layer that converts the target layer to black and white. Optionally applies a color tint to the result. 1439 | 1440 | Args: 1441 | layer_id (int): The ID of the layer to apply the black and white adjustment to. 1442 | colors (dict): Controls how each color channel converts to grayscale. Values range from 1443 | -200 to 300, with higher values making that color appear lighter in the 1444 | conversion. Must include all keys: red, yellow, green, cyan, blue, magenta. 1445 | tint (bool, optional): Whether to apply a color tint to the black and white result. 1446 | Defaults to False. 1447 | tint_color (dict, optional): The RGB color dict to use for tinting 1448 | with "red", "green", and "blue" keys (values 0-255). 1449 | """ 1450 | 1451 | command = createCommand("addAdjustmentLayerBlackAndWhite", { 1452 | "layerId":layer_id, 1453 | "colors":colors, 1454 | "tint":tint, 1455 | "tintColor":tint_color 1456 | }) 1457 | 1458 | return sendCommand(command) 1459 | 1460 | @mcp.tool() 1461 | def apply_gaussian_blur(layer_id: int, radius: float = 2.5): 1462 | """Applies a Gaussian Blur to the layer with the specified ID 1463 | 1464 | Args: 1465 | layer_id (int): ID of layer to be blurred 1466 | radius (float): The blur radius in pixels determining the intensity of the blur effect. Default is 2.5. 1467 | Valid values range from 0.1 (subtle blur) to 10000 (extreme blur). 1468 | 1469 | Returns: 1470 | dict: Response from the Photoshop operation 1471 | 1472 | Raises: 1473 | RuntimeError: If the operation fails or times out 1474 | """ 1475 | 1476 | 1477 | 1478 | command = createCommand("applyGaussianBlur", { 1479 | "layerId":layer_id, 1480 | "radius":radius, 1481 | }) 1482 | 1483 | return sendCommand(command) 1484 | 1485 | 1486 | 1487 | 1488 | @mcp.tool() 1489 | def apply_motion_blur(layer_id: int, angle: int = 0, distance: float = 30): 1490 | """Applies a Motion Blur to the layer with the specified ID 1491 | 1492 | Args: 1493 | layer_id (int): ID of layer to be blurred 1494 | angle (int): The angle in degrees (0 to 360) that determines the direction of the motion blur effect. Default is 0. 1495 | distance (float): The distance in pixels that controls the length/strength of the motion blur. Default is 30. 1496 | Higher values create a more pronounced motion effect. 1497 | 1498 | Returns: 1499 | dict: Response from the Photoshop operation 1500 | 1501 | Raises: 1502 | RuntimeError: If the operation fails or times out 1503 | """ 1504 | 1505 | 1506 | command = createCommand("applyMotionBlur", { 1507 | "layerId":layer_id, 1508 | "angle":angle, 1509 | "distance":distance 1510 | }) 1511 | 1512 | return sendCommand(command) 1513 | 1514 | 1515 | @mcp.resource("config://get_instructions") 1516 | def get_instructions() -> str: 1517 | """Read this first! Returns information and instructions on how to use Photoshop and this API""" 1518 | 1519 | return f""" 1520 | You are a photoshop expert who is creative and loves to help other people learn to use Photoshop and create. You are well versed in composition, design and color theory, and try to follow that theory when making decisions. 1521 | 1522 | Unless otherwise specified, all commands act on the currently active document in Photoshop 1523 | 1524 | Rules to follow: 1525 | 1526 | 1. Think deeply about how to solve the task 1527 | 2. Always check your work 1528 | 3. You can view the current visible photoshop file by calling get_document_image 1529 | 4. Pay attention to font size (dont make it too big) 1530 | 5. Always use alignment (align_content()) to position your text. 1531 | 6. Read the info for the API calls to make sure you understand the requirements and arguments 1532 | 7. When you make a selection, clear it once you no longer need it 1533 | 1534 | Here are some general tips for when working with Photoshop. 1535 | 1536 | In general, layers are created from bottom up, so keep that in mind as you figure out the order or operations. If you want you have lower layers show through higher ones you must either change the opacity of the higher layers and / or blend modes. 1537 | 1538 | When using fonts there are a couple of things to keep in mind. First, the font origin is the bottom left of the font, not the top right. 1539 | 1540 | Suggestions for sizes: 1541 | Paragraph text : 8 to 12 pts 1542 | Headings : 14 - 20 pts 1543 | Single Word Large : 20 to 25pt 1544 | 1545 | Pay attention to what layer names are needed for. Sometimes the specify the name of a newly created layer and sometimes they specify the name of the layer that the action should be performed on. 1546 | 1547 | As a general rule, you should not flatten files unless asked to do so, or its necessary to apply an effect or look. 1548 | 1549 | When generating an image, you do not need to first create a pixel layer. A layer will automatically be created when you generate the image. 1550 | 1551 | Colors are defined via a dict with red, green and blue properties with values between 0 and 255 1552 | {{"red":255, "green":0, "blue":0}} 1553 | 1554 | Bounds is defined as a dict with top, left, bottom and right properties 1555 | {{"top": 0, "left": 0, "bottom": 250, "right": 300}} 1556 | 1557 | Valid options for API calls: 1558 | 1559 | alignment_modes: {", ".join(alignment_modes)} 1560 | 1561 | justification_modes: {", ".join(justification_modes)} 1562 | 1563 | blend_modes: {", ".join(blend_modes)} 1564 | 1565 | anchor_positions: {", ".join(anchor_positions)} 1566 | 1567 | interpolation_methods: {", ".join(interpolation_methods)} 1568 | 1569 | fonts: {", ".join(font_names[:FONT_LIMIT])} 1570 | """ 1571 | 1572 | font_names = list_all_fonts_postscript() 1573 | 1574 | interpolation_methods = [ 1575 | "AUTOMATIC", 1576 | "BICUBIC", 1577 | "BICUBICSHARPER", 1578 | "BICUBICSMOOTHER", 1579 | "BILINEAR", 1580 | "NEARESTNEIGHBOR" 1581 | ] 1582 | 1583 | anchor_positions = [ 1584 | "BOTTOMCENTER", 1585 | "BOTTOMLEFT", 1586 | "BOTTOMRIGHT", 1587 | "MIDDLECENTER", 1588 | "MIDDLELEFT", 1589 | "MIDDLERIGHT", 1590 | "TOPCENTER", 1591 | "TOPLEFT", 1592 | "TOPRIGHT" 1593 | ] 1594 | 1595 | justification_modes = [ 1596 | "CENTER", 1597 | "CENTERJUSTIFIED", 1598 | "FULLYJUSTIFIED", 1599 | "LEFT", 1600 | "LEFTJUSTIFIED", 1601 | "RIGHT", 1602 | "RIGHTJUSTIFIED" 1603 | ] 1604 | 1605 | alignment_modes = [ 1606 | "LEFT", 1607 | "CENTER_HORIZONTAL", 1608 | "RIGHT", 1609 | "TOP", 1610 | "CENTER_VERTICAL", 1611 | "BOTTOM" 1612 | ] 1613 | 1614 | blend_modes = [ 1615 | "COLOR", 1616 | "COLORBURN", 1617 | "COLORDODGE", 1618 | "DARKEN", 1619 | "DARKERCOLOR", 1620 | "DIFFERENCE", 1621 | "DISSOLVE", 1622 | "DIVIDE", 1623 | "EXCLUSION", 1624 | "HARDLIGHT", 1625 | "HARDMIX", 1626 | "HUE", 1627 | "LIGHTEN", 1628 | "LIGHTERCOLOR", 1629 | "LINEARBURN", 1630 | "LINEARDODGE", 1631 | "LINEARLIGHT", 1632 | "LUMINOSITY", 1633 | "MULTIPLY", 1634 | "NORMAL", 1635 | "OVERLAY", 1636 | "PASSTHROUGH", 1637 | "PINLIGHT", 1638 | "SATURATION", 1639 | "SCREEN", 1640 | "SOFTLIGHT", 1641 | "SUBTRACT", 1642 | "VIVIDLIGHT" 1643 | ] 1644 | ```