home *** CD-ROM | disk | FTP | other *** search
/ Computer Active 2010 July / CA07.iso / Multimedija / QuickTimeInstaller.exe / AppleApplicationSupport.msi / WebKit.resources_inspector_ProfilesPanel.js < prev    next >
Encoding:
Text File  |  2010-03-15  |  16.3 KB  |  505 lines

  1. /*
  2.  * Copyright (C) 2008 Apple Inc. All Rights Reserved.
  3.  *
  4.  * Redistribution and use in source and binary forms, with or without
  5.  * modification, are permitted provided that the following conditions
  6.  * are met:
  7.  * 1. Redistributions of source code must retain the above copyright
  8.  *    notice, this list of conditions and the following disclaimer.
  9.  * 2. Redistributions in binary form must reproduce the above copyright
  10.  *    notice, this list of conditions and the following disclaimer in the
  11.  *    documentation and/or other materials provided with the distribution.
  12.  *
  13.  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
  14.  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  15.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  16.  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
  17.  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  18.  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  19.  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  20.  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  21.  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  22.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  23.  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  24.  */
  25.  
  26. const UserInitiatedProfileName = "org.webkit.profiles.user-initiated";
  27.  
  28. WebInspector.ProfilesPanel = function()
  29. {
  30.     WebInspector.Panel.call(this);
  31.  
  32.     this.element.addStyleClass("profiles");
  33.  
  34.     var panelEnablerHeading = WebInspector.UIString("You need to enable profiling before you can use the Profiles panel.");
  35.     var panelEnablerDisclaimer = WebInspector.UIString("Enabling profiling will make scripts run slower.");
  36.     var panelEnablerButton = WebInspector.UIString("Enable Profiling");
  37.     this.panelEnablerView = new WebInspector.PanelEnablerView("profiles", panelEnablerHeading, panelEnablerDisclaimer, panelEnablerButton);
  38.     this.panelEnablerView.addEventListener("enable clicked", this._enableProfiling, this);
  39.  
  40.     this.element.appendChild(this.panelEnablerView.element);
  41.  
  42.     this.sidebarElement = document.createElement("div");
  43.     this.sidebarElement.id = "profiles-sidebar";
  44.     this.sidebarElement.className = "sidebar";
  45.     this.element.appendChild(this.sidebarElement);
  46.  
  47.     this.sidebarResizeElement = document.createElement("div");
  48.     this.sidebarResizeElement.className = "sidebar-resizer-vertical";
  49.     this.sidebarResizeElement.addEventListener("mousedown", this._startSidebarDragging.bind(this), false);
  50.     this.element.appendChild(this.sidebarResizeElement);
  51.  
  52.     this.sidebarTreeElement = document.createElement("ol");
  53.     this.sidebarTreeElement.className = "sidebar-tree";
  54.     this.sidebarElement.appendChild(this.sidebarTreeElement);
  55.  
  56.     this.sidebarTree = new TreeOutline(this.sidebarTreeElement);
  57.  
  58.     this.profileViews = document.createElement("div");
  59.     this.profileViews.id = "profile-views";
  60.     this.element.appendChild(this.profileViews);
  61.  
  62.     this.enableToggleButton = document.createElement("button");
  63.     this.enableToggleButton.className = "enable-toggle-status-bar-item status-bar-item";
  64.     this.enableToggleButton.addEventListener("click", this._toggleProfiling.bind(this), false);
  65.  
  66.     this.recordButton = document.createElement("button");
  67.     this.recordButton.title = WebInspector.UIString("Start profiling.");
  68.     this.recordButton.id = "record-profile-status-bar-item";
  69.     this.recordButton.className = "status-bar-item";
  70.     this.recordButton.addEventListener("click", this._recordClicked.bind(this), false);
  71.  
  72.     this.recording = false;
  73.  
  74.     this.profileViewStatusBarItemsContainer = document.createElement("div");
  75.     this.profileViewStatusBarItemsContainer.id = "profile-view-status-bar-items";
  76.  
  77.     this.reset();
  78. }
  79.  
  80. WebInspector.ProfilesPanel.prototype = {
  81.     toolbarItemClass: "profiles",
  82.  
  83.     get toolbarItemLabel()
  84.     {
  85.         return WebInspector.UIString("Profiles");
  86.     },
  87.  
  88.     get statusBarItems()
  89.     {
  90.         return [this.enableToggleButton, this.recordButton, this.profileViewStatusBarItemsContainer];
  91.     },
  92.  
  93.     show: function()
  94.     {
  95.         WebInspector.Panel.prototype.show.call(this);
  96.         this._updateSidebarWidth();
  97.         if (this._shouldPopulateProfiles)
  98.             this._populateProfiles();
  99.     },
  100.  
  101.     populateInterface: function()
  102.     {
  103.         if (this.visible)
  104.             this._populateProfiles();
  105.         else
  106.             this._shouldPopulateProfiles = true;
  107.     },
  108.  
  109.     profilerWasEnabled: function()
  110.     {
  111.         this.reset();
  112.         this.populateInterface();
  113.     },
  114.  
  115.     profilerWasDisabled: function()
  116.     {
  117.         this.reset();
  118.     },
  119.  
  120.     reset: function()
  121.     {
  122.         if (this._profiles) {
  123.             var profiledLength = this._profiles.length;
  124.             for (var i = 0; i < profiledLength; ++i) {
  125.                 var profile = this._profiles[i];
  126.                 delete profile._profileView;
  127.             }
  128.         }
  129.  
  130.         delete this.currentQuery;
  131.         this.searchCanceled();
  132.  
  133.         this._profiles = [];
  134.         this._profilesIdMap = {};
  135.         this._profileGroups = {};
  136.         this._profileGroupsForLinks = {}
  137.  
  138.         this.sidebarTreeElement.removeStyleClass("some-expandable");
  139.  
  140.         this.sidebarTree.removeChildren();
  141.         this.profileViews.removeChildren();
  142.  
  143.         this.profileViewStatusBarItemsContainer.removeChildren();
  144.  
  145.         this._updateInterface();
  146.     },
  147.  
  148.     handleKeyEvent: function(event)
  149.     {
  150.         this.sidebarTree.handleKeyEvent(event);
  151.     },
  152.  
  153.     addProfile: function(profile)
  154.     {
  155.         this._profiles.push(profile);
  156.         this._profilesIdMap[profile.uid] = profile;
  157.  
  158.         var sidebarParent = this.sidebarTree;
  159.         var small = false;
  160.         var alternateTitle;
  161.  
  162.         if (profile.title.indexOf(UserInitiatedProfileName) !== 0) {
  163.             if (!(profile.title in this._profileGroups))
  164.                 this._profileGroups[profile.title] = [];
  165.  
  166.             var group = this._profileGroups[profile.title];
  167.             group.push(profile);
  168.  
  169.             if (group.length === 2) {
  170.                 // Make a group TreeElement now that there are 2 profiles.
  171.                 group._profilesTreeElement = new WebInspector.ProfileGroupSidebarTreeElement(profile.title);
  172.  
  173.                 // Insert at the same index for the first profile of the group.
  174.                 var index = this.sidebarTree.children.indexOf(group[0]._profilesTreeElement);
  175.                 this.sidebarTree.insertChild(group._profilesTreeElement, index);
  176.  
  177.                 // Move the first profile to the group.
  178.                 var selected = group[0]._profilesTreeElement.selected;
  179.                 this.sidebarTree.removeChild(group[0]._profilesTreeElement);
  180.                 group._profilesTreeElement.appendChild(group[0]._profilesTreeElement);
  181.                 if (selected) {
  182.                     group[0]._profilesTreeElement.select();
  183.                     group[0]._profilesTreeElement.reveal();
  184.                 }
  185.  
  186.                 group[0]._profilesTreeElement.small = true;
  187.                 group[0]._profilesTreeElement.mainTitle = WebInspector.UIString("Run %d", 1);
  188.  
  189.                 this.sidebarTreeElement.addStyleClass("some-expandable");
  190.             }
  191.  
  192.             if (group.length >= 2) {
  193.                 sidebarParent = group._profilesTreeElement;
  194.                 alternateTitle = WebInspector.UIString("Run %d", group.length);
  195.                 small = true;
  196.             }
  197.         }
  198.  
  199.         var profileTreeElement = new WebInspector.ProfileSidebarTreeElement(profile);
  200.         profileTreeElement.small = small;
  201.         if (alternateTitle)
  202.             profileTreeElement.mainTitle = alternateTitle;
  203.         profile._profilesTreeElement = profileTreeElement;
  204.  
  205.         sidebarParent.appendChild(profileTreeElement);
  206.     },
  207.  
  208.     showProfile: function(profile)
  209.     {
  210.         if (!profile)
  211.             return;
  212.  
  213.         if (this.visibleView)
  214.             this.visibleView.hide();
  215.  
  216.         var view = this.profileViewForProfile(profile);
  217.  
  218.         view.show(this.profileViews);
  219.  
  220.         profile._profilesTreeElement.select(true);
  221.         profile._profilesTreeElement.reveal();
  222.  
  223.         this.visibleView = view;
  224.  
  225.         this.profileViewStatusBarItemsContainer.removeChildren();
  226.  
  227.         var statusBarItems = view.statusBarItems;
  228.         for (var i = 0; i < statusBarItems.length; ++i)
  229.             this.profileViewStatusBarItemsContainer.appendChild(statusBarItems[i]);
  230.     },
  231.  
  232.     showView: function(view)
  233.     {
  234.         this.showProfile(view.profile);
  235.     },
  236.  
  237.     profileViewForProfile: function(profile)
  238.     {
  239.         if (!profile)
  240.             return null;
  241.         if (!profile._profileView)
  242.             profile._profileView = new WebInspector.ProfileView(profile);
  243.         return profile._profileView;
  244.     },
  245.  
  246.     showProfileById: function(uid)
  247.     {
  248.         this.showProfile(this._profilesIdMap[uid]);
  249.     },
  250.  
  251.     closeVisibleView: function()
  252.     {
  253.         if (this.visibleView)
  254.             this.visibleView.hide();
  255.         delete this.visibleView;
  256.     },
  257.  
  258.     displayTitleForProfileLink: function(title)
  259.     {
  260.         title = unescape(title);
  261.         if (title.indexOf(UserInitiatedProfileName) === 0) {
  262.             title = WebInspector.UIString("Profile %d", title.substring(UserInitiatedProfileName.length + 1));
  263.         } else {
  264.             if (!(title in this._profileGroupsForLinks))
  265.                 this._profileGroupsForLinks[title] = 0;
  266.  
  267.             groupNumber = ++this._profileGroupsForLinks[title];
  268.  
  269.             if (groupNumber > 2)
  270.                 // The title is used in the console message announcing that a profile has started so it gets
  271.                 // incremented twice as often as it's displayed
  272.                 title += " " + WebInspector.UIString("Run %d", groupNumber / 2);
  273.         }
  274.         
  275.         return title;
  276.     },
  277.  
  278.     get searchableViews()
  279.     {
  280.         var views = [];
  281.  
  282.         const visibleView = this.visibleView;
  283.         if (visibleView && visibleView.performSearch)
  284.             views.push(visibleView);
  285.  
  286.         var profilesLength = this._profiles.length;
  287.         for (var i = 0; i < profilesLength; ++i) {
  288.             var view = this.profileViewForProfile(this._profiles[i]);
  289.             if (!view.performSearch || view === visibleView)
  290.                 continue;
  291.             views.push(view);
  292.         }
  293.  
  294.         return views;
  295.     },
  296.  
  297.     searchMatchFound: function(view, matches)
  298.     {
  299.         view.profile._profilesTreeElement.searchMatches = matches;
  300.     },
  301.  
  302.     searchCanceled: function(startingNewSearch)
  303.     {
  304.         WebInspector.Panel.prototype.searchCanceled.call(this, startingNewSearch);
  305.  
  306.         if (!this._profiles)
  307.             return;
  308.  
  309.         for (var i = 0; i < this._profiles.length; ++i) {
  310.             var profile = this._profiles[i];
  311.             profile._profilesTreeElement.searchMatches = 0;
  312.         }
  313.     },
  314.  
  315.     setRecordingProfile: function(isProfiling)
  316.     {
  317.         this.recording = isProfiling;
  318.  
  319.         if (isProfiling) {
  320.             this.recordButton.addStyleClass("toggled-on");
  321.             this.recordButton.title = WebInspector.UIString("Stop profiling.");
  322.         } else {
  323.             this.recordButton.removeStyleClass("toggled-on");
  324.             this.recordButton.title = WebInspector.UIString("Start profiling.");
  325.         }
  326.     },
  327.  
  328.     _updateInterface: function()
  329.     {
  330.         if (InspectorController.profilerEnabled()) {
  331.             this.enableToggleButton.title = WebInspector.UIString("Profiling enabled. Click to disable.");
  332.             this.enableToggleButton.addStyleClass("toggled-on");
  333.             this.recordButton.removeStyleClass("hidden");
  334.             this.profileViewStatusBarItemsContainer.removeStyleClass("hidden");
  335.             this.panelEnablerView.visible = false;
  336.         } else {
  337.             this.enableToggleButton.title = WebInspector.UIString("Profiling disabled. Click to enable.");
  338.             this.enableToggleButton.removeStyleClass("toggled-on");
  339.             this.recordButton.addStyleClass("hidden");
  340.             this.profileViewStatusBarItemsContainer.addStyleClass("hidden");
  341.             this.panelEnablerView.visible = true;
  342.         }
  343.     },
  344.  
  345.     _recordClicked: function()
  346.     {
  347.         this.recording = !this.recording;
  348.  
  349.         if (this.recording)
  350.             InspectorController.startProfiling();
  351.         else
  352.             InspectorController.stopProfiling();
  353.     },
  354.  
  355.     _enableProfiling: function()
  356.     {
  357.         if (InspectorController.profilerEnabled())
  358.             return;
  359.         this._toggleProfiling(this.panelEnablerView.alwaysEnabled);
  360.     },
  361.  
  362.     _toggleProfiling: function(optionalAlways)
  363.     {
  364.         if (InspectorController.profilerEnabled())
  365.             InspectorController.disableProfiler(true);
  366.         else
  367.             InspectorController.enableProfiler(!!optionalAlways);
  368.     },
  369.  
  370.     _populateProfiles: function()
  371.     {
  372.         if (this.sidebarTree.children.length)
  373.             return;
  374.  
  375.         var profiles = InspectorController.profiles();
  376.         var profilesLength = profiles.length;
  377.         for (var i = 0; i < profilesLength; ++i) {
  378.             var profile = profiles[i];
  379.             this.addProfile(profile);
  380.         }
  381.  
  382.         if (this.sidebarTree.children[0])
  383.             this.sidebarTree.children[0].select();
  384.  
  385.         delete this._shouldPopulateProfiles;
  386.     },
  387.  
  388.     _startSidebarDragging: function(event)
  389.     {
  390.         WebInspector.elementDragStart(this.sidebarResizeElement, this._sidebarDragging.bind(this), this._endSidebarDragging.bind(this), event, "col-resize");
  391.     },
  392.  
  393.     _sidebarDragging: function(event)
  394.     {
  395.         this._updateSidebarWidth(event.pageX);
  396.  
  397.         event.preventDefault();
  398.     },
  399.  
  400.     _endSidebarDragging: function(event)
  401.     {
  402.         WebInspector.elementDragEnd(event);
  403.     },
  404.  
  405.     _updateSidebarWidth: function(width)
  406.     {
  407.         if (this.sidebarElement.offsetWidth <= 0) {
  408.             // The stylesheet hasn't loaded yet or the window is closed,
  409.             // so we can't calculate what is need. Return early.
  410.             return;
  411.         }
  412.  
  413.         if (!("_currentSidebarWidth" in this))
  414.             this._currentSidebarWidth = this.sidebarElement.offsetWidth;
  415.  
  416.         if (typeof width === "undefined")
  417.             width = this._currentSidebarWidth;
  418.  
  419.         width = Number.constrain(width, Preferences.minSidebarWidth, window.innerWidth / 2);
  420.  
  421.         this._currentSidebarWidth = width;
  422.  
  423.         this.sidebarElement.style.width = width + "px";
  424.         this.profileViews.style.left = width + "px";
  425.         this.profileViewStatusBarItemsContainer.style.left = width + "px";
  426.         this.sidebarResizeElement.style.left = (width - 3) + "px";
  427.     }
  428. }
  429.  
  430. WebInspector.ProfilesPanel.prototype.__proto__ = WebInspector.Panel.prototype;
  431.  
  432. WebInspector.ProfileSidebarTreeElement = function(profile)
  433. {
  434.     this.profile = profile;
  435.  
  436.     if (this.profile.title.indexOf(UserInitiatedProfileName) === 0)
  437.         this._profileNumber = this.profile.title.substring(UserInitiatedProfileName.length + 1);
  438.  
  439.     WebInspector.SidebarTreeElement.call(this, "profile-sidebar-tree-item", "", "", profile, false);
  440.  
  441.     this.refreshTitles();
  442. }
  443.  
  444. WebInspector.ProfileSidebarTreeElement.prototype = {
  445.     onselect: function()
  446.     {
  447.         WebInspector.panels.profiles.showProfile(this.profile);
  448.     },
  449.  
  450.     get mainTitle()
  451.     {
  452.         if (this._mainTitle)
  453.             return this._mainTitle;
  454.         if (this.profile.title.indexOf(UserInitiatedProfileName) === 0)
  455.             return WebInspector.UIString("Profile %d", this._profileNumber);
  456.         return this.profile.title;
  457.     },
  458.  
  459.     set mainTitle(x)
  460.     {
  461.         this._mainTitle = x;
  462.         this.refreshTitles();
  463.     },
  464.  
  465.     get subtitle()
  466.     {
  467.         // There is no subtitle.
  468.     },
  469.  
  470.     set subtitle(x)
  471.     {
  472.         // Can't change subtitle.
  473.     },
  474.  
  475.     set searchMatches(matches)
  476.     {
  477.         if (!matches) {
  478.             if (!this.bubbleElement)
  479.                 return;
  480.             this.bubbleElement.removeStyleClass("search-matches");
  481.             this.bubbleText = "";
  482.             return;
  483.         }
  484.  
  485.         this.bubbleText = matches;
  486.         this.bubbleElement.addStyleClass("search-matches");
  487.     }
  488. }
  489.  
  490. WebInspector.ProfileSidebarTreeElement.prototype.__proto__ = WebInspector.SidebarTreeElement.prototype;
  491.  
  492. WebInspector.ProfileGroupSidebarTreeElement = function(title, subtitle)
  493. {
  494.     WebInspector.SidebarTreeElement.call(this, "profile-group-sidebar-tree-item", title, subtitle, null, true);
  495. }
  496.  
  497. WebInspector.ProfileGroupSidebarTreeElement.prototype = {
  498.     onselect: function()
  499.     {
  500.         WebInspector.panels.profiles.showProfile(this.children[this.children.length - 1].profile);
  501.     }
  502. }
  503.  
  504. WebInspector.ProfileGroupSidebarTreeElement.prototype.__proto__ = WebInspector.SidebarTreeElement.prototype;
  505.