1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/browser/devtools/styleinspector/style-inspector.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,206 @@ 1.4 +/* -*- Mode: Javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim: set ts=2 et sw=2 tw=80: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +const {Cc, Cu, Ci} = require("chrome"); 1.11 +const {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm", {}); 1.12 + 1.13 +let ToolDefinitions = require("main").Tools; 1.14 + 1.15 +Cu.import("resource://gre/modules/Services.jsm"); 1.16 + 1.17 +loader.lazyGetter(this, "gDevTools", () => Cu.import("resource:///modules/devtools/gDevTools.jsm", {}).gDevTools); 1.18 +loader.lazyGetter(this, "RuleView", () => require("devtools/styleinspector/rule-view")); 1.19 +loader.lazyGetter(this, "ComputedView", () => require("devtools/styleinspector/computed-view")); 1.20 +loader.lazyGetter(this, "_strings", () => Services.strings 1.21 + .createBundle("chrome://global/locale/devtools/styleinspector.properties")); 1.22 + 1.23 +const { PREF_ORIG_SOURCES } = require("devtools/styleeditor/utils"); 1.24 + 1.25 +// This module doesn't currently export any symbols directly, it only 1.26 +// registers inspector tools. 1.27 + 1.28 +function RuleViewTool(aInspector, aWindow, aIFrame) 1.29 +{ 1.30 + this.inspector = aInspector; 1.31 + this.doc = aWindow.document; 1.32 + this.outerIFrame = aIFrame; 1.33 + 1.34 + this.view = new RuleView.CssRuleView(aInspector, this.doc); 1.35 + this.doc.documentElement.appendChild(this.view.element); 1.36 + 1.37 + this._changeHandler = () => { 1.38 + this.inspector.markDirty(); 1.39 + }; 1.40 + 1.41 + this.view.element.addEventListener("CssRuleViewChanged", this._changeHandler); 1.42 + 1.43 + this._refreshHandler = () => { 1.44 + this.inspector.emit("rule-view-refreshed"); 1.45 + }; 1.46 + 1.47 + this.view.element.addEventListener("CssRuleViewRefreshed", this._refreshHandler); 1.48 + 1.49 + this._cssLinkHandler = (aEvent) => { 1.50 + let rule = aEvent.detail.rule; 1.51 + let sheet = rule.parentStyleSheet; 1.52 + 1.53 + // Chrome stylesheets are not listed in the style editor, so show 1.54 + // these sheets in the view source window instead. 1.55 + if (!sheet || sheet.isSystem) { 1.56 + let contentDoc = this.inspector.selection.document; 1.57 + let viewSourceUtils = this.inspector.viewSourceUtils; 1.58 + let href = rule.nodeHref || rule.href; 1.59 + viewSourceUtils.viewSource(href, null, contentDoc, rule.line || 0); 1.60 + return; 1.61 + } 1.62 + 1.63 + let location = promise.resolve(rule.location); 1.64 + if (Services.prefs.getBoolPref(PREF_ORIG_SOURCES)) { 1.65 + location = rule.getOriginalLocation(); 1.66 + } 1.67 + location.then(({ href, line, column }) => { 1.68 + let target = this.inspector.target; 1.69 + if (ToolDefinitions.styleEditor.isTargetSupported(target)) { 1.70 + gDevTools.showToolbox(target, "styleeditor").then(function(toolbox) { 1.71 + toolbox.getCurrentPanel().selectStyleSheet(href, line, column); 1.72 + }); 1.73 + } 1.74 + return; 1.75 + }) 1.76 + } 1.77 + 1.78 + this.view.element.addEventListener("CssRuleViewCSSLinkClicked", 1.79 + this._cssLinkHandler); 1.80 + 1.81 + this._onSelect = this.onSelect.bind(this); 1.82 + this.inspector.selection.on("detached", this._onSelect); 1.83 + this.inspector.selection.on("new-node-front", this._onSelect); 1.84 + this.refresh = this.refresh.bind(this); 1.85 + this.inspector.on("layout-change", this.refresh); 1.86 + 1.87 + this.inspector.selection.on("pseudoclass", this.refresh); 1.88 + 1.89 + this.onSelect(); 1.90 +} 1.91 + 1.92 +exports.RuleViewTool = RuleViewTool; 1.93 + 1.94 +RuleViewTool.prototype = { 1.95 + onSelect: function RVT_onSelect(aEvent) { 1.96 + if (!this.view) { 1.97 + // Skip the event if RuleViewTool has been destroyed. 1.98 + return; 1.99 + } 1.100 + this.view.setPageStyle(this.inspector.pageStyle); 1.101 + 1.102 + if (!this.inspector.selection.isConnected() || 1.103 + !this.inspector.selection.isElementNode()) { 1.104 + this.view.highlight(null); 1.105 + return; 1.106 + } 1.107 + 1.108 + if (!aEvent || aEvent == "new-node-front") { 1.109 + let done = this.inspector.updating("rule-view"); 1.110 + this.view.highlight(this.inspector.selection.nodeFront).then(done, done); 1.111 + } 1.112 + }, 1.113 + 1.114 + refresh: function RVT_refresh() { 1.115 + this.view.nodeChanged(); 1.116 + }, 1.117 + 1.118 + destroy: function RVT_destroy() { 1.119 + this.inspector.off("layout-change", this.refresh); 1.120 + this.inspector.selection.off("pseudoclass", this.refresh); 1.121 + this.inspector.selection.off("new-node-front", this._onSelect); 1.122 + 1.123 + this.view.element.removeEventListener("CssRuleViewCSSLinkClicked", 1.124 + this._cssLinkHandler); 1.125 + 1.126 + this.view.element.removeEventListener("CssRuleViewChanged", 1.127 + this._changeHandler); 1.128 + 1.129 + this.view.element.removeEventListener("CssRuleViewRefreshed", 1.130 + this._refreshHandler); 1.131 + 1.132 + this.doc.documentElement.removeChild(this.view.element); 1.133 + 1.134 + this.view.destroy(); 1.135 + 1.136 + delete this.outerIFrame; 1.137 + delete this.view; 1.138 + delete this.doc; 1.139 + delete this.inspector; 1.140 + } 1.141 +}; 1.142 + 1.143 +function ComputedViewTool(aInspector, aWindow, aIFrame) 1.144 +{ 1.145 + this.inspector = aInspector; 1.146 + this.window = aWindow; 1.147 + this.document = aWindow.document; 1.148 + this.outerIFrame = aIFrame; 1.149 + this.view = new ComputedView.CssHtmlTree(this, aInspector.pageStyle); 1.150 + 1.151 + this._onSelect = this.onSelect.bind(this); 1.152 + this.inspector.selection.on("detached", this._onSelect); 1.153 + this.inspector.selection.on("new-node-front", this._onSelect); 1.154 + this.refresh = this.refresh.bind(this); 1.155 + this.inspector.on("layout-change", this.refresh); 1.156 + this.inspector.selection.on("pseudoclass", this.refresh); 1.157 + 1.158 + this.view.highlight(null); 1.159 + 1.160 + this.onSelect(); 1.161 +} 1.162 + 1.163 +exports.ComputedViewTool = ComputedViewTool; 1.164 + 1.165 +ComputedViewTool.prototype = { 1.166 + onSelect: function CVT_onSelect(aEvent) 1.167 + { 1.168 + if (!this.view) { 1.169 + // Skip the event if ComputedViewTool has been destroyed. 1.170 + return; 1.171 + } 1.172 + this.view.setPageStyle(this.inspector.pageStyle); 1.173 + 1.174 + if (!this.inspector.selection.isConnected() || 1.175 + !this.inspector.selection.isElementNode()) { 1.176 + this.view.highlight(null); 1.177 + return; 1.178 + } 1.179 + 1.180 + if (!aEvent || aEvent == "new-node-front") { 1.181 + let done = this.inspector.updating("computed-view"); 1.182 + this.view.highlight(this.inspector.selection.nodeFront).then(() => { 1.183 + done(); 1.184 + }); 1.185 + } 1.186 + }, 1.187 + 1.188 + refresh: function CVT_refresh() { 1.189 + this.view.refreshPanel(); 1.190 + }, 1.191 + 1.192 + destroy: function CVT_destroy(aContext) 1.193 + { 1.194 + this.inspector.off("layout-change", this.refresh); 1.195 + this.inspector.sidebar.off("computedview-selected", this.refresh); 1.196 + this.inspector.selection.off("pseudoclass", this.refresh); 1.197 + this.inspector.selection.off("new-node-front", this._onSelect); 1.198 + 1.199 + this.view.destroy(); 1.200 + delete this.view; 1.201 + 1.202 + delete this.outerIFrame; 1.203 + delete this.cssLogic; 1.204 + delete this.cssHtmlTree; 1.205 + delete this.window; 1.206 + delete this.document; 1.207 + delete this.inspector; 1.208 + } 1.209 +};