browser/devtools/styleinspector/style-inspector.js

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:1d87028d71ee
1 /* -*- Mode: Javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 const {Cc, Cu, Ci} = require("chrome");
8 const {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm", {});
9
10 let ToolDefinitions = require("main").Tools;
11
12 Cu.import("resource://gre/modules/Services.jsm");
13
14 loader.lazyGetter(this, "gDevTools", () => Cu.import("resource:///modules/devtools/gDevTools.jsm", {}).gDevTools);
15 loader.lazyGetter(this, "RuleView", () => require("devtools/styleinspector/rule-view"));
16 loader.lazyGetter(this, "ComputedView", () => require("devtools/styleinspector/computed-view"));
17 loader.lazyGetter(this, "_strings", () => Services.strings
18 .createBundle("chrome://global/locale/devtools/styleinspector.properties"));
19
20 const { PREF_ORIG_SOURCES } = require("devtools/styleeditor/utils");
21
22 // This module doesn't currently export any symbols directly, it only
23 // registers inspector tools.
24
25 function RuleViewTool(aInspector, aWindow, aIFrame)
26 {
27 this.inspector = aInspector;
28 this.doc = aWindow.document;
29 this.outerIFrame = aIFrame;
30
31 this.view = new RuleView.CssRuleView(aInspector, this.doc);
32 this.doc.documentElement.appendChild(this.view.element);
33
34 this._changeHandler = () => {
35 this.inspector.markDirty();
36 };
37
38 this.view.element.addEventListener("CssRuleViewChanged", this._changeHandler);
39
40 this._refreshHandler = () => {
41 this.inspector.emit("rule-view-refreshed");
42 };
43
44 this.view.element.addEventListener("CssRuleViewRefreshed", this._refreshHandler);
45
46 this._cssLinkHandler = (aEvent) => {
47 let rule = aEvent.detail.rule;
48 let sheet = rule.parentStyleSheet;
49
50 // Chrome stylesheets are not listed in the style editor, so show
51 // these sheets in the view source window instead.
52 if (!sheet || sheet.isSystem) {
53 let contentDoc = this.inspector.selection.document;
54 let viewSourceUtils = this.inspector.viewSourceUtils;
55 let href = rule.nodeHref || rule.href;
56 viewSourceUtils.viewSource(href, null, contentDoc, rule.line || 0);
57 return;
58 }
59
60 let location = promise.resolve(rule.location);
61 if (Services.prefs.getBoolPref(PREF_ORIG_SOURCES)) {
62 location = rule.getOriginalLocation();
63 }
64 location.then(({ href, line, column }) => {
65 let target = this.inspector.target;
66 if (ToolDefinitions.styleEditor.isTargetSupported(target)) {
67 gDevTools.showToolbox(target, "styleeditor").then(function(toolbox) {
68 toolbox.getCurrentPanel().selectStyleSheet(href, line, column);
69 });
70 }
71 return;
72 })
73 }
74
75 this.view.element.addEventListener("CssRuleViewCSSLinkClicked",
76 this._cssLinkHandler);
77
78 this._onSelect = this.onSelect.bind(this);
79 this.inspector.selection.on("detached", this._onSelect);
80 this.inspector.selection.on("new-node-front", this._onSelect);
81 this.refresh = this.refresh.bind(this);
82 this.inspector.on("layout-change", this.refresh);
83
84 this.inspector.selection.on("pseudoclass", this.refresh);
85
86 this.onSelect();
87 }
88
89 exports.RuleViewTool = RuleViewTool;
90
91 RuleViewTool.prototype = {
92 onSelect: function RVT_onSelect(aEvent) {
93 if (!this.view) {
94 // Skip the event if RuleViewTool has been destroyed.
95 return;
96 }
97 this.view.setPageStyle(this.inspector.pageStyle);
98
99 if (!this.inspector.selection.isConnected() ||
100 !this.inspector.selection.isElementNode()) {
101 this.view.highlight(null);
102 return;
103 }
104
105 if (!aEvent || aEvent == "new-node-front") {
106 let done = this.inspector.updating("rule-view");
107 this.view.highlight(this.inspector.selection.nodeFront).then(done, done);
108 }
109 },
110
111 refresh: function RVT_refresh() {
112 this.view.nodeChanged();
113 },
114
115 destroy: function RVT_destroy() {
116 this.inspector.off("layout-change", this.refresh);
117 this.inspector.selection.off("pseudoclass", this.refresh);
118 this.inspector.selection.off("new-node-front", this._onSelect);
119
120 this.view.element.removeEventListener("CssRuleViewCSSLinkClicked",
121 this._cssLinkHandler);
122
123 this.view.element.removeEventListener("CssRuleViewChanged",
124 this._changeHandler);
125
126 this.view.element.removeEventListener("CssRuleViewRefreshed",
127 this._refreshHandler);
128
129 this.doc.documentElement.removeChild(this.view.element);
130
131 this.view.destroy();
132
133 delete this.outerIFrame;
134 delete this.view;
135 delete this.doc;
136 delete this.inspector;
137 }
138 };
139
140 function ComputedViewTool(aInspector, aWindow, aIFrame)
141 {
142 this.inspector = aInspector;
143 this.window = aWindow;
144 this.document = aWindow.document;
145 this.outerIFrame = aIFrame;
146 this.view = new ComputedView.CssHtmlTree(this, aInspector.pageStyle);
147
148 this._onSelect = this.onSelect.bind(this);
149 this.inspector.selection.on("detached", this._onSelect);
150 this.inspector.selection.on("new-node-front", this._onSelect);
151 this.refresh = this.refresh.bind(this);
152 this.inspector.on("layout-change", this.refresh);
153 this.inspector.selection.on("pseudoclass", this.refresh);
154
155 this.view.highlight(null);
156
157 this.onSelect();
158 }
159
160 exports.ComputedViewTool = ComputedViewTool;
161
162 ComputedViewTool.prototype = {
163 onSelect: function CVT_onSelect(aEvent)
164 {
165 if (!this.view) {
166 // Skip the event if ComputedViewTool has been destroyed.
167 return;
168 }
169 this.view.setPageStyle(this.inspector.pageStyle);
170
171 if (!this.inspector.selection.isConnected() ||
172 !this.inspector.selection.isElementNode()) {
173 this.view.highlight(null);
174 return;
175 }
176
177 if (!aEvent || aEvent == "new-node-front") {
178 let done = this.inspector.updating("computed-view");
179 this.view.highlight(this.inspector.selection.nodeFront).then(() => {
180 done();
181 });
182 }
183 },
184
185 refresh: function CVT_refresh() {
186 this.view.refreshPanel();
187 },
188
189 destroy: function CVT_destroy(aContext)
190 {
191 this.inspector.off("layout-change", this.refresh);
192 this.inspector.sidebar.off("computedview-selected", this.refresh);
193 this.inspector.selection.off("pseudoclass", this.refresh);
194 this.inspector.selection.off("new-node-front", this._onSelect);
195
196 this.view.destroy();
197 delete this.view;
198
199 delete this.outerIFrame;
200 delete this.cssLogic;
201 delete this.cssHtmlTree;
202 delete this.window;
203 delete this.document;
204 delete this.inspector;
205 }
206 };

mercurial