/************************************************************************** * * @@@BUILDINFO@@@ 31dataBrowser-2.jsx 2.0.0.54 08-Feb-2007 * Copyright 2006-2007 Adobe Systems Incorporated * All Rights Reserved. * * NOTICE: All information contained herein is, and remains the property of * Adobe Systems Incorporated and its suppliers, if any. The intellectual * and technical concepts contained herein are proprietary to Adobe Systems * Incorporated and its suppliers and may be covered by U.S. and Foreign * Patents,patents in process,and are protected by trade secret or copyright * law. Dissemination of this information or reproduction of this material * is strictly forbidden unless prior written permission is obtained from * Adobe Systems Incorporated. **************************************************************************/ databrowser = null; app.createDataBrowser = function (where) { databrowser = new Window( "dockpalette { \ id : 'databrowser', \ text : '$$$/ESToolkit/Panes/Variables/Title=Data Browser',\ properties : { \ defaultVisibility : true, \ name : 'databrowser', \ flyoutmenu : true, \ icon : '#PDataBrowser_N', \ rollover : '#PDataBrowser_R'," + where + "}, \ preferredSize : [100, 100], \ margins : 2, \ spacing : 2, \ orientation : 'column', \ alignment : ['fill','fill'], \ edit : EditText { \ properties : { enterKeySignalsOnChange: true }, \ preferredSize : [40, 20], \ alignment : 'fill', \ enabled : false, \ helpTip : '$$$/ESToolkit/Panes/Variables/htEdit=Assign a new value to the selected variable here.' \ }, \ list : TreeView { \ preferredSize : [10, 20], \ alignment : ['fill', 'fill' ] \ }, \ infogrp : Group \ { \ orientation : 'row', \ margins : 0, \ spacing : 0, \ alignment : ['fill','bottom'], \ targetField: StaticText \ { \ alignment : ['fill','bottom'], \ characters : 40 \ }, \ sizeBoxSpacer : Group \ { \ alignment : ['right','bottom'], \ preferredSize : [14,1] \ } \ } \ }"); databrowser.menuText = localize ("$$$/ESToolkit/Menu/Window/DataBrowser/Title=&Data Browser"); databrowser.icons = {}; databrowser.icons.UNDEFINED = ScriptUI.newImage ("#Undefined"); databrowser.icons.NULL = ScriptUI.newImage ("#Null"); databrowser.icons.BOOLEAN = ScriptUI.newImage ("#Boolean"); databrowser.icons.NUMBER = ScriptUI.newImage ("#Number"); databrowser.icons.STRING = ScriptUI.newImage ("#String"); databrowser.icons.OBJECT = ScriptUI.newImage ("#Object"); databrowser.icons.FUNCTION = ScriptUI.newImage ("#Function"); databrowser.icons.INVALID = ScriptUI.newImage ("#Invalid"); // This variable tells onExpand that it has been called programmatically. // This is necessary because item.expanded = true causes onExpand() to be called, // but we have collected the data already. databrowser.calledByProgram = false; databrowser.onNotify = function( reason ) { switch (reason) { case 'shutdown': globalBroadcaster.unregisterClient( this ); this.blockListChange = true; this.list.removeAll(); break; case 'newDebugPrefs': this.showUndefined = PrefUtils.getValue( 'prefs.databrowser.showUndefined', 'Boolean' ); this.showCore = PrefUtils.getValue( 'prefs.databrowser.showCore', 'Boolean' ); this.showFunctions = PrefUtils.getValue( 'prefs.databrowser.showFunctions', 'Boolean' ); this.showPrototype = PrefUtils.getValue( 'prefs.databrowser.showPrototype', 'Boolean' ); this.maxArrayElements = PrefUtils.getValue( 'prefs.databrowser.maxArrayElements', 'Number' ); // during startup, this is null if (currentDebugger) this.update(); break; case 'changeActiveTarget': case 'changeActiveEngine': { this.enabled = targetMgr.getActiveTarget().getConnected(); if( this.enabled ) { var targetName = BridgeTalk.getDisplayName( targetMgr.getActiveTarget().targetName ) ; this.infogrp.targetField.text = ( targetName ? targetName : targetMgr.getActiveTarget().targetName ); } else this.infogrp.targetField.text = ''; } break; } } globalBroadcaster.registerClient( databrowser ); targetMgr.registerClient( databrowser ); databrowser.onNotify ('newDebugPrefs'); databrowser.onResize = databrowser.onResizing = function () { this.layout.resize(); } // used properties: // target - the current target // engine - the current engine // global - true if the scope is global databrowser.target = ""; databrowser.engine = ""; databrowser.global = true; // // clear list // databrowser.erase = function() { this.list.removeAll(); } // Get the data for the given target and engine. // If globalScope is true, force a get for the global scope. // Otherwise, get the current scope. databrowser.getVariables = function (target, engine, globalScope, all) { this.target = target; this.engine = engine; this.global = globalScope; this.update (); } // Update the pane. databrowser.update = function (item) { // Visual clues if (item) { // not really expanded yet item.expanded = false; item.oldIcon = item.icon; item.oldText = item.text; item.text = localize ("$$$/ESToolkit/DataBrowser/Pending=pending..."); item.icon = databrowser.icons.UNDEFINED; item.removeAll(); } var bt = BridgeTalk.create (this.target, "Variables"); bt.headers.Engine = this.engine; // create the setting for things to exclude var excludes = []; if (!this.showUndefined) excludes.push ("undefined"); if (!this.showCore) excludes.push ("builtin"); if (!this.showFunctions) excludes.push ("Function"); if (!this.showPrototype) excludes.push ("prototype"); bt.headers.Exclude = excludes.join (','); bt.headers.MaxArrayElements = this.maxArrayElements; bt.onOwnResult = function (bt) { if (this.item) { this.item.text = this.item.oldText; this.item.icon = this.item.oldIcon; } databrowser._readReply (bt, this.item); } // Create the scope chain bt.item = item; bt.body = this.makePath (item); bt.headers.All = "1"; bt.safeSend(); } // Helper method: Interpret the incoming BridgeTalk message body and update the variables. // The item is the scope node (null if global) databrowser._readReply = function (bt, item) { if (!item) item = this.list; this.edit.enabled = false; // Update the display. The BridgeTalk instance contains the data. Each body line has 4 elements, // the data type, the variable name, the variable value, and a read-only indicator. var items = []; var lines = bt.body.split ('\n'); for (var i = 0; i < lines.length; i++) { // now split the line manually to digest escaped characters. var line = []; var s = lines [i]; var cur = ""; for (var j = 0; j < s.length; j++) { switch (s[j]) { case '\\': cur += (s [++j] == 'n') ? '\n' : s[j]; break; case ',': line.push (cur); cur = ""; break; default: cur += s[j]; } } if (cur.length) line.push (cur); if (line.length < 3) continue; // The line has four elements. var data = { dataType: line[0], // the JS data type name: line[1], // the variable name sortName: line[1].toUpperCase(), // the variable name for sorting index: Number (line[1]), // An eventual array index for sorting value: line[2], // the variable value readonly: line[3] == "true", // true if readonly isObject: false, // true for objects showName: true, // true if to display the variable name valid: line[0].indexOf ("invalid ") < 0, icon: databrowser.icons.UNDEFINED }; // If the line is an invalid object, the data type is "invalid classname" if (!data.valid) data.dataType = data.dataType.substr (8); data.isIndex = !isNaN (data.index); switch (data.dataType) { case "undefined": data.value = undefined; break; case "null": data.value = null; data.icon = databrowser.icons.NULL; break; case "boolean": data.value = (data.value == "true"); data.icon = databrowser.icons.BOOLEAN; break; case "number": data.value = parseFloat (eval (data.value)); data.icon = databrowser.icons.NUMBER; break; case "string": if (typeof data.value == "undefined") data.value = ""; data.icon = databrowser.icons.STRING; break; case "Function": // a function may be defined in several ways: // Function,foo,foo() defined as function foo(){} // Function,foo,() defined as foo = function() // Function,bar,foo() defined as bar = foo if (data.value[0] == '(') data.value = data.name + data.value; data.icon = databrowser.icons.FUNCTION; data.isObject = true; data.showName = false; break; case "EnumError": // On an enumeration error, the value is the error message data.icon = databrowser.icons.INVALID; data.readonly = true; data.valid = false; break; default: data.isObject = data.valid; data.icon = data.valid ? databrowser.icons.OBJECT : databrowser.icons.INVALID; // show the class if the value does not start with '[' if (typeof data.value == "undefined") data.value = '[' + data.dataType + ']'; else if (data.value.length && data.value[0] != '[') data.value = '[' + data.dataType + '] ' + data.value; } // All data has been set, now save the data into my array items.push (data); } // sort the table alphabetically by name function sortfn (a, b) { if (a.isIndex && b.isIndex) // numeric compare for array indexes return a.index - b.index; a = a.sortName; b = b.sortName; if (a < b) return -1; else if (a > b) return 1; else return 0; } items.sort (sortfn); // Now create the list this.blockListChange = true; item.removeAll(); this.blockListChange = false; for (i = 0; i < items.length; i++) { data = items [i]; var child; var itemType = (data.isObject && data.valid) ? "node" : "item"; var itemText = data.showName ? (data.name + " = " + data.value) : data.value; var index = itemText.indexOf ('\n'); if (index >= 0) itemText = itemText.substr (0, index); index = itemText.indexOf ('\r'); if (index >= 0) itemText = itemText.substr (0, index); if (itemText.length > 64) itemText = itemText.substr (0, 64) + "..."; child = item.add (itemType, itemText); child.data = data; child.scope = this.global // global scope: makePath() inserts "$.global" in front of [name][name] elements ? "['" + app.escape (data.name) + "']" // local scope: use the variable as-is (it is a local var) - but check for top-level : (item == this.list ? data.name : "['" + app.escape (data.name) + "']"); child.image = data.icon; } // inhibit onExpand() processing // onExpand() did set expanded to false, because it was not filled with data yet databrowser.calledByProgram = true; item.expanded = true; databrowser.calledByProgram = false; } // The callback for a new value selection. databrowser.list.onChange = function() { if( !this.window.blockListChange ) { var text = ""; var enabled = false; var item = this.selection; if (item && item.data.valid) { enabled = !item.data.readonly; text = item.data.value; } databrowser.edit.text = text; databrowser.edit.enabled = enabled; } } // The callback if the user clicked on a node to expand it, // or the expanded property has been set. databrowser.list.onExpand = function (item) { // could be called because of item.expanded = true if (item.data.isObject && !databrowser.calledByProgram) { // causes an update databrowser.update (item); } } // The callback if the user clicked on a node to collapse it. databrowser.list.onCollapse = function (item) { // if (item.isObject) // item.removeAll(); } // The callback if the user typed in a new value. databrowser.edit.onChange = function() { var text = this.text; var result = app.checkSyntax( text, document.includePath ); if (result.error) { app.beep(); Document.setStatusLine (result.message); } else { // eval the expression, but do not print the reply var item = databrowser.list.selection; if (item) { var name = databrowser.makePath (item); currentDebugger.eval (name + '=' + text, true); } } } databrowser.makePath = function (item) { var scopes = []; while (item && item != this.list) { scopes.unshift (item.scope); item = item.parent; } if (this.global) scopes.unshift ("$.global"); return scopes.join (''); } var item = new MenuElement( 'command', '$$$/ESToolkit/Panes/DataBrowser/Flyout/ShowUndefined=&Undefined Variables', "at the end of databrowser/flyout", "databrowser/flyout/undefined" ); item.onDisplay = function() { this.checked = databrowser.showUndefined; this.enabled = databrowser.enabled; } item.onSelect = function() { databrowser.showUndefined = !databrowser.showUndefined; prefs.databrowser.showUndefined = databrowser.showUndefined; databrowser.update(); } item = new MenuElement( 'command', '$$$/ESToolkit/Panes/DataBrowser/Flyout/ShowFunctions=&Functions', "at the end of databrowser/flyout", "databrowser/flyout/functions" ); item.onDisplay = function() { this.checked = databrowser.showFunctions; this.enabled = databrowser.enabled; } item.onSelect = function() { databrowser.showFunctions = !databrowser.showFunctions; prefs.databrowser.showFunctions = databrowser.showFunctions; databrowser.update(); } item = new MenuElement( 'command', '$$$/ESToolkit/Panes/DataBrowser/Flyout/ShowCore=\&Core JavaScript Elements', "at the end of databrowser/flyout", "databrowser/flyout/core" ); item.onDisplay = function() { this.checked = databrowser.showCore; this.enabled = databrowser.enabled; } item.onSelect = function() { databrowser.showCore = !databrowser.showCore; prefs.databrowser.showCore = databrowser.showCore; databrowser.update(); } item = new MenuElement( 'command', '$$$/ESToolkit/Panes/DataBrowser/Flyout/ShowPrototype=&Prototype Elements', "at the end of databrowser/flyout", "databrowser/flyout/proto" ); item.onDisplay = function() { this.checked = databrowser.showPrototype; this.enabled = databrowser.enabled; } item.onSelect = function() { databrowser.showPrototype = !databrowser.showPrototype; prefs.databrowser.showPrototype = databrowser.showPrototype; databrowser.update(); } databrowser.show(); panes.push (databrowser); }