2011-08-30 12:12:02 +00:00
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* vim: set ts=2 et sw=2 tw=80: */
|
2012-05-21 11:12:37 +00:00
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
2011-08-30 12:12:02 +00:00
|
|
|
|
2012-06-02 22:18:33 +00:00
|
|
|
const Cc = Components.classes;
|
2011-08-30 12:12:02 +00:00
|
|
|
const Cu = Components.utils;
|
|
|
|
const Ci = Components.interfaces;
|
|
|
|
|
|
|
|
Cu.import("resource://gre/modules/Services.jsm");
|
|
|
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
2012-04-19 18:04:46 +00:00
|
|
|
Cu.import("resource:///modules/devtools/CssRuleView.jsm");
|
2012-11-30 08:07:59 +00:00
|
|
|
Cu.import("resource:///modules/devtools/ToolDefinitions.jsm");
|
|
|
|
|
|
|
|
XPCOMUtils.defineLazyModuleGetter(this, "gDevTools",
|
|
|
|
"resource:///modules/devtools/gDevTools.jsm");
|
2011-08-30 12:12:02 +00:00
|
|
|
|
2012-04-19 18:04:46 +00:00
|
|
|
// This module doesn't currently export any symbols directly, it only
|
|
|
|
// registers inspector tools.
|
2012-11-30 08:07:59 +00:00
|
|
|
this.EXPORTED_SYMBOLS = ["RuleViewTool", "ComputedViewTool"];
|
2011-10-21 17:40:22 +00:00
|
|
|
|
2012-11-30 08:07:59 +00:00
|
|
|
this.RuleViewTool = function RVT_RuleViewTool(aInspector, aWindow, aIFrame)
|
2012-04-19 18:04:46 +00:00
|
|
|
{
|
|
|
|
this.inspector = aInspector;
|
2012-11-30 08:07:59 +00:00
|
|
|
this.doc = aWindow.document;
|
|
|
|
this.outerIFrame = aIFrame;
|
2012-04-19 18:13:42 +00:00
|
|
|
|
2012-11-30 08:07:59 +00:00
|
|
|
this.view = new CssRuleView(this.doc);
|
2012-04-19 18:04:46 +00:00
|
|
|
this.doc.documentElement.appendChild(this.view.element);
|
|
|
|
|
|
|
|
this._changeHandler = function() {
|
|
|
|
this.inspector.markDirty();
|
|
|
|
}.bind(this);
|
|
|
|
|
|
|
|
this.view.element.addEventListener("CssRuleViewChanged", this._changeHandler)
|
|
|
|
|
|
|
|
this._cssLinkHandler = function(aEvent) {
|
2012-11-30 08:07:59 +00:00
|
|
|
let contentDoc = this.inspector.selection.document;
|
2012-04-19 18:04:46 +00:00
|
|
|
let rule = aEvent.detail.rule;
|
2012-11-30 08:07:59 +00:00
|
|
|
let line = rule.ruleLine || 0;
|
2012-04-19 18:04:46 +00:00
|
|
|
let styleSheet = rule.sheet;
|
2012-11-30 08:07:59 +00:00
|
|
|
let styleSheets = contentDoc.styleSheets;
|
2012-04-19 18:04:46 +00:00
|
|
|
let contentSheet = false;
|
|
|
|
|
2012-11-30 08:07:59 +00:00
|
|
|
// The style editor can only display stylesheets coming from content because
|
|
|
|
// chrome stylesheets are not listed in the editor's stylesheet selector.
|
|
|
|
//
|
|
|
|
// If the stylesheet is a content stylesheet we send it to the style
|
|
|
|
// editor else we display it in the view source window.
|
|
|
|
//
|
2012-04-19 18:04:46 +00:00
|
|
|
// Array.prototype.indexOf always returns -1 here so we loop through
|
|
|
|
// the styleSheets object instead.
|
|
|
|
for each (let sheet in styleSheets) {
|
|
|
|
if (sheet == styleSheet) {
|
|
|
|
contentSheet = true;
|
|
|
|
break;
|
|
|
|
}
|
2011-10-21 17:40:22 +00:00
|
|
|
}
|
2011-08-30 12:12:02 +00:00
|
|
|
|
2012-04-19 18:04:46 +00:00
|
|
|
if (contentSheet) {
|
2012-11-30 08:07:59 +00:00
|
|
|
let target = this.inspector.target;
|
|
|
|
|
|
|
|
if (styleEditorDefinition.isTargetSupported(target)) {
|
2012-12-13 13:03:55 +00:00
|
|
|
gDevTools.showToolbox(target, "styleeditor").then(function(toolbox) {
|
|
|
|
toolbox.getCurrentPanel().selectStyleSheet(styleSheet, line);
|
2012-11-30 08:07:59 +00:00
|
|
|
});
|
|
|
|
}
|
2012-04-19 18:04:46 +00:00
|
|
|
} else {
|
|
|
|
let href = styleSheet ? styleSheet.href : "";
|
|
|
|
if (rule.elementStyle.element) {
|
|
|
|
href = rule.elementStyle.element.ownerDocument.location.href;
|
2011-11-03 13:37:14 +00:00
|
|
|
}
|
2012-11-30 08:07:59 +00:00
|
|
|
let viewSourceUtils = this.inspector.viewSourceUtils;
|
|
|
|
viewSourceUtils.viewSource(href, null, contentDoc, line);
|
2012-04-19 18:04:46 +00:00
|
|
|
}
|
|
|
|
}.bind(this);
|
2011-11-03 13:37:14 +00:00
|
|
|
|
2012-04-19 18:04:46 +00:00
|
|
|
this.view.element.addEventListener("CssRuleViewCSSLinkClicked",
|
|
|
|
this._cssLinkHandler);
|
2011-11-03 13:37:14 +00:00
|
|
|
|
2012-04-19 18:04:46 +00:00
|
|
|
this._onSelect = this.onSelect.bind(this);
|
2012-11-30 08:07:59 +00:00
|
|
|
this.inspector.selection.on("new-node", this._onSelect);
|
|
|
|
this.refresh = this.refresh.bind(this);
|
|
|
|
this.inspector.on("layout-change", this.refresh);
|
|
|
|
this.inspector.sidebar.on("ruleview-selected", this.refresh);
|
|
|
|
this.inspector.selection.on("pseudoclass", this.refresh);
|
|
|
|
if (this.inspector.highlighter) {
|
|
|
|
this.inspector.highlighter.on("locked", this._onSelect);
|
|
|
|
}
|
2011-10-21 17:40:22 +00:00
|
|
|
|
2012-04-19 18:04:46 +00:00
|
|
|
this.onSelect();
|
|
|
|
}
|
2011-09-01 12:17:05 +00:00
|
|
|
|
2012-04-19 18:04:46 +00:00
|
|
|
RuleViewTool.prototype = {
|
2012-11-30 08:07:59 +00:00
|
|
|
onSelect: function RVT_onSelect(aEvent) {
|
|
|
|
if (!this.inspector.selection.isConnected() ||
|
|
|
|
!this.inspector.selection.isElementNode()) {
|
2012-04-19 18:04:46 +00:00
|
|
|
this.view.highlight(null);
|
|
|
|
return;
|
2011-09-01 12:17:05 +00:00
|
|
|
}
|
2011-08-30 12:12:02 +00:00
|
|
|
|
2012-11-30 08:07:59 +00:00
|
|
|
if (!aEvent || aEvent == "new-node") {
|
|
|
|
if (this.inspector.selection.reason == "highlighter") {
|
|
|
|
this.view.highlight(null);
|
|
|
|
} else {
|
|
|
|
this.view.highlight(this.inspector.selection.node);
|
|
|
|
}
|
2011-10-21 17:40:22 +00:00
|
|
|
}
|
2011-08-30 12:12:02 +00:00
|
|
|
|
2012-11-30 08:07:59 +00:00
|
|
|
if (aEvent == "locked") {
|
|
|
|
this.view.highlight(this.inspector.selection.node);
|
2011-10-21 17:40:22 +00:00
|
|
|
}
|
2012-11-30 08:07:59 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
isActive: function RVT_isActive() {
|
|
|
|
return this.inspector.sidebar.getCurrentTabID() == "ruleview";
|
|
|
|
},
|
2011-10-07 15:38:35 +00:00
|
|
|
|
2012-11-30 08:07:59 +00:00
|
|
|
refresh: function RVT_refresh() {
|
|
|
|
if (this.isActive()) {
|
2012-04-19 18:04:46 +00:00
|
|
|
this.view.nodeChanged();
|
2011-11-07 03:02:08 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2012-04-19 18:04:46 +00:00
|
|
|
destroy: function RVT_destroy() {
|
2012-11-30 08:07:59 +00:00
|
|
|
this.inspector.off("layout-change", this.refresh);
|
|
|
|
this.inspector.sidebar.off("ruleview-selected", this.refresh);
|
|
|
|
this.inspector.selection.off("pseudoclass", this.refresh);
|
|
|
|
this.inspector.selection.off("new-node", this._onSelect);
|
|
|
|
if (this.inspector.highlighter) {
|
|
|
|
this.inspector.highlighter.off("locked", this._onSelect);
|
|
|
|
}
|
|
|
|
|
2012-04-19 18:04:46 +00:00
|
|
|
this.view.element.removeEventListener("CssRuleViewCSSLinkClicked",
|
2012-11-30 08:07:59 +00:00
|
|
|
this._cssLinkHandler);
|
|
|
|
|
|
|
|
this.view.element.removeEventListener("CssRuleViewChanged",
|
|
|
|
this._changeHandler);
|
|
|
|
|
2012-04-19 18:04:46 +00:00
|
|
|
this.doc.documentElement.removeChild(this.view.element);
|
2011-08-30 12:12:02 +00:00
|
|
|
|
2012-04-19 18:04:46 +00:00
|
|
|
this.view.destroy();
|
|
|
|
|
2012-11-30 08:07:59 +00:00
|
|
|
delete this.outerIFrame;
|
2012-04-19 18:04:46 +00:00
|
|
|
delete this.view;
|
|
|
|
delete this.doc;
|
|
|
|
delete this.inspector;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-11-30 08:07:59 +00:00
|
|
|
this.ComputedViewTool = function CVT_ComputedViewTool(aInspector, aWindow, aIFrame)
|
2012-04-19 18:04:46 +00:00
|
|
|
{
|
|
|
|
this.inspector = aInspector;
|
2012-11-30 08:07:59 +00:00
|
|
|
this.window = aWindow;
|
|
|
|
this.document = aWindow.document;
|
|
|
|
this.outerIFrame = aIFrame;
|
2012-04-19 18:04:46 +00:00
|
|
|
this.cssLogic = new CssLogic();
|
|
|
|
this.view = new CssHtmlTree(this);
|
2011-10-21 17:40:22 +00:00
|
|
|
|
2012-04-19 18:04:46 +00:00
|
|
|
this._onSelect = this.onSelect.bind(this);
|
2012-11-30 08:07:59 +00:00
|
|
|
this.inspector.selection.on("new-node", this._onSelect);
|
|
|
|
if (this.inspector.highlighter) {
|
|
|
|
this.inspector.highlighter.on("locked", this._onSelect);
|
|
|
|
}
|
|
|
|
this.refresh = this.refresh.bind(this);
|
|
|
|
this.inspector.on("layout-change", this.refresh);
|
|
|
|
this.inspector.sidebar.on("computedview-selected", this.refresh);
|
|
|
|
this.inspector.selection.on("pseudoclass", this.refresh);
|
2012-04-19 18:04:46 +00:00
|
|
|
|
|
|
|
this.cssLogic.highlight(null);
|
|
|
|
this.view.highlight(null);
|
|
|
|
|
|
|
|
this.onSelect();
|
|
|
|
}
|
|
|
|
|
|
|
|
ComputedViewTool.prototype = {
|
|
|
|
onSelect: function CVT_onSelect(aEvent)
|
2011-10-21 17:40:22 +00:00
|
|
|
{
|
2012-11-30 08:07:59 +00:00
|
|
|
if (!this.inspector.selection.isConnected() ||
|
|
|
|
!this.inspector.selection.isElementNode()) {
|
|
|
|
// FIXME: We should hide view's content
|
|
|
|
return;
|
2011-11-03 13:37:14 +00:00
|
|
|
}
|
2011-08-30 12:12:02 +00:00
|
|
|
|
2012-11-30 08:07:59 +00:00
|
|
|
if (!aEvent || aEvent == "new-node") {
|
|
|
|
if (this.inspector.selection.reason == "highlighter") {
|
|
|
|
// FIXME: We should hide view's content
|
|
|
|
} else {
|
|
|
|
this.cssLogic.highlight(this.inspector.selection.node);
|
|
|
|
this.view.highlight(this.inspector.selection.node);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (aEvent == "locked") {
|
|
|
|
this.cssLogic.highlight(this.inspector.selection.node);
|
|
|
|
this.view.highlight(this.inspector.selection.node);
|
2011-08-30 12:12:02 +00:00
|
|
|
}
|
2012-11-30 08:07:59 +00:00
|
|
|
},
|
2012-04-19 18:04:46 +00:00
|
|
|
|
2012-11-30 08:07:59 +00:00
|
|
|
isActive: function CVT_isActive() {
|
|
|
|
return this.inspector.sidebar.getCurrentTabID() == "computedview";
|
|
|
|
},
|
|
|
|
|
|
|
|
refresh: function CVT_refresh() {
|
|
|
|
if (this.isActive()) {
|
|
|
|
this.cssLogic.highlight(this.inspector.selection.node);
|
2012-06-02 22:18:33 +00:00
|
|
|
this.view.refreshPanel();
|
|
|
|
}
|
2011-08-30 12:12:02 +00:00
|
|
|
},
|
2011-11-03 13:37:14 +00:00
|
|
|
|
2012-04-19 18:04:46 +00:00
|
|
|
destroy: function CVT_destroy(aContext)
|
2011-11-03 13:37:14 +00:00
|
|
|
{
|
2012-11-30 08:07:59 +00:00
|
|
|
this.inspector.off("layout-change", this.refresh);
|
|
|
|
this.inspector.sidebar.off("computedview-selected", this.refresh);
|
|
|
|
this.inspector.selection.off("pseudoclass", this.refresh);
|
|
|
|
this.inspector.selection.off("new-node", this._onSelect);
|
|
|
|
if (this.inspector.highlighter) {
|
|
|
|
this.inspector.highlighter.off("locked", this._onSelect);
|
|
|
|
}
|
|
|
|
|
2012-04-19 18:04:46 +00:00
|
|
|
this.view.destroy();
|
|
|
|
delete this.view;
|
2011-11-03 13:37:14 +00:00
|
|
|
|
2012-11-30 08:07:59 +00:00
|
|
|
delete this.outerIFrame;
|
2011-11-03 13:37:14 +00:00
|
|
|
delete this.cssLogic;
|
|
|
|
delete this.cssHtmlTree;
|
2012-04-19 18:04:46 +00:00
|
|
|
delete this.window;
|
|
|
|
delete this.document;
|
2012-11-30 08:07:59 +00:00
|
|
|
delete this.inspector;
|
2012-04-19 18:04:46 +00:00
|
|
|
}
|
|
|
|
}
|
2011-08-30 12:12:02 +00:00
|
|
|
|
|
|
|
XPCOMUtils.defineLazyGetter(this, "_strings", function() Services.strings
|
2011-11-03 13:37:14 +00:00
|
|
|
.createBundle("chrome://browser/locale/devtools/styleinspector.properties"));
|
2011-08-30 12:12:02 +00:00
|
|
|
|
|
|
|
XPCOMUtils.defineLazyGetter(this, "CssLogic", function() {
|
|
|
|
let tmp = {};
|
|
|
|
Cu.import("resource:///modules/devtools/CssLogic.jsm", tmp);
|
|
|
|
return tmp.CssLogic;
|
|
|
|
});
|
|
|
|
|
|
|
|
XPCOMUtils.defineLazyGetter(this, "CssHtmlTree", function() {
|
|
|
|
let tmp = {};
|
|
|
|
Cu.import("resource:///modules/devtools/CssHtmlTree.jsm", tmp);
|
|
|
|
return tmp.CssHtmlTree;
|
|
|
|
});
|