mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
671 lines
19 KiB
JavaScript
671 lines
19 KiB
JavaScript
/* ***** BEGIN LICENSE BLOCK *****
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
*
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
* the License. You may obtain a copy of the License at
|
|
* http://www.mozilla.org/MPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
* for the specific language governing rights and limitations under the
|
|
* License.
|
|
*
|
|
* The Original Code is mozilla.org code.
|
|
*
|
|
* The Initial Developer of the Original Code is
|
|
* Netscape Communications Corporation.
|
|
* Portions created by the Initial Developer are Copyright (C) 2001
|
|
* the Initial Developer. All Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
* Joe Hewitt <hewitt@netscape.com> (original author)
|
|
* Jason Barnabe <jason_barnabe@fastmail.fm>
|
|
*
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
* use your version of this file under the terms of the MPL, indicate your
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
* the provisions above, a recipient may use your version of this file under
|
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
*
|
|
* ***** END LICENSE BLOCK ***** */
|
|
|
|
/***************************************************************
|
|
* StyleRulesViewer --------------------------------------------
|
|
* The viewer for CSS style rules that apply to a DOM element.
|
|
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
* REQUIRED IMPORTS:
|
|
* chrome://inspector/content/util.js
|
|
* chrome://inspector/content/jsutil/xpcom/XPCU.js
|
|
* chrome://inspector/content/jsutil/rdf/RDFU.js
|
|
****************************************************************/
|
|
|
|
//////////// global variables /////////////////////
|
|
|
|
var viewer;
|
|
var gPromptService;
|
|
|
|
//////////// global constants ////////////////////
|
|
|
|
var kCSSRuleDataSourceIID = "@mozilla.org/rdf/datasource;1?name=Inspector_CSSRules";
|
|
var kCSSDecDataSourceIID = "@mozilla.org/rdf/datasource;1?name=Inspector_CSSDec";
|
|
var kPromptServiceCID = "@mozilla.org/embedcomp/prompt-service;1";
|
|
|
|
var nsEventStateUnspecificed = 0;
|
|
var nsEventStateActive = 1;
|
|
var nsEventStateFocus = 2;
|
|
var nsEventStateHover = 4;
|
|
var nsEventStateDragOver = 8;
|
|
|
|
/////////////////////////////////////////////////
|
|
|
|
window.addEventListener("load", StyleRulesViewer_initialize, false);
|
|
|
|
function StyleRulesViewer_initialize()
|
|
{
|
|
viewer = new StyleRulesViewer();
|
|
viewer.initialize(parent.FrameExchange.receiveData(window));
|
|
|
|
gPromptService = XPCU.getService(kPromptServiceCID, "nsIPromptService");
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//// class StyleRulesViewer
|
|
|
|
function StyleRulesViewer() // implements inIViewer
|
|
{
|
|
this.mObsMan = new ObserverManager();
|
|
|
|
this.mURL = window.location;
|
|
this.mRuleTree = document.getElementById("olStyleRules");
|
|
this.mRuleBoxObject = this.mRuleTree.treeBoxObject;
|
|
this.mPropsTree = document.getElementById("olStyleProps");
|
|
this.mPropsBoxObject = this.mPropsTree.treeBoxObject;
|
|
}
|
|
|
|
//XXX Don't use anonymous functions
|
|
StyleRulesViewer.prototype =
|
|
{
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//// Initialization
|
|
|
|
mRuleDS: null,
|
|
mDecDS: null,
|
|
mSubject: null,
|
|
mPanel: null,
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//// interface inIViewer
|
|
|
|
get uid() { return "styleRules" },
|
|
get pane() { return this.mPanel },
|
|
|
|
get selection() { return null },
|
|
|
|
get subject() { return this.mSubject },
|
|
set subject(aObject)
|
|
{
|
|
this.mSubject = aObject;
|
|
// update the rule tree
|
|
this.mRuleView = new StyleRuleView(aObject);
|
|
this.mRuleBoxObject.view = this.mRuleView;
|
|
// clear the props tree
|
|
this.mPropsView = null;
|
|
this.mPropsBoxObject.view = null;
|
|
|
|
this.mObsMan.dispatchEvent("subjectChange", { subject: aObject });
|
|
},
|
|
|
|
initialize: function(aPane)
|
|
{
|
|
this.mPanel = aPane;
|
|
aPane.notifyViewerReady(this);
|
|
},
|
|
|
|
destroy: function()
|
|
{
|
|
// We need to remove the views at this time or else they will attempt to
|
|
// re-paint while the document is being deconstructed, resulting in
|
|
// some nasty XPConnect assertions
|
|
this.mRuleBoxObject.view = null;
|
|
this.mPropsBoxObject.view = null;
|
|
},
|
|
|
|
isCommandEnabled: function isCommandEnabled(aCommand)
|
|
{
|
|
var declaration = this.getSelectedDec();
|
|
// if no declaration is selected, nothing is enabled
|
|
if (!declaration)
|
|
return false;
|
|
|
|
//XXX can't edit resource: stylesheets because of bug 343508
|
|
var rule = declaration.parentRule;
|
|
var isEditable = !(rule && rule.parentStyleSheet &&
|
|
/^resource:/.test(rule.parentStyleSheet.href));
|
|
|
|
switch (aCommand) {
|
|
case "cmdEditCopy":
|
|
return this.mPropsTree.view.selection.count > 0;
|
|
case "cmdEditDelete":
|
|
case "cmdTogglePriority":
|
|
return isEditable && this.mPropsTree.view.selection.count > 0;
|
|
case "cmdEditInsert":
|
|
return isEditable && this.mRuleTree.view.selection.count == 1;
|
|
case "cmdEditEdit":
|
|
return isEditable && this.mPropsTree.view.selection.count == 1;
|
|
}
|
|
return false;
|
|
},
|
|
|
|
getCommand: function getCommand(aCommand)
|
|
{
|
|
switch (aCommand) {
|
|
case "cmdEditCopy":
|
|
return new cmdEditCopy(this.mPropsView.getSelectedRowObjects());
|
|
case "cmdEditDelete":
|
|
return new cmdEditDelete(this.getSelectedDec(),
|
|
this.mPropsView.getSelectedRowObjects());
|
|
case "cmdEditInsert":
|
|
var bundle = this.mPanel.panelset.stringBundle;
|
|
var msg = bundle.getString("styleRulePropertyName.message");
|
|
var title = bundle.getString("styleRuleNewProperty.title");
|
|
|
|
var property = { value: "" };
|
|
var value = { value: "" };
|
|
var dummy = { value: false };
|
|
|
|
if (!gPromptService.prompt(window, title, msg, property, null, dummy)) {
|
|
return null;
|
|
}
|
|
|
|
msg = bundle.getString("styleRulePropertyValue.message");
|
|
if (!gPromptService.prompt(window, title, msg, value, null, dummy)) {
|
|
return null;
|
|
}
|
|
|
|
return new cmdEditInsert(this.getSelectedDec(), property.value,
|
|
value.value, "");
|
|
case "cmdEditEdit":
|
|
var rule = this.getSelectedDec();
|
|
var property = this.getSelectedProp();
|
|
var priority = rule.getPropertyPriority(property);
|
|
|
|
var bundle = this.mPanel.panelset.stringBundle;
|
|
var msg = bundle.getString("styleRulePropertyValue.message");
|
|
var title = bundle.getString("styleRuleEditProperty.title");
|
|
|
|
var value = { value: rule.getPropertyValue(property) };
|
|
var dummy = { value: false };
|
|
|
|
if (!gPromptService.prompt(window, title, msg, value, null, dummy)) {
|
|
return null;
|
|
}
|
|
|
|
return new cmdEditEdit(rule, property, value.value, priority);
|
|
case "cmdTogglePriority":
|
|
return new cmdTogglePriority(this.getSelectedDec(),
|
|
this.mPropsView.getSelectedRowObjects());
|
|
}
|
|
return null;
|
|
},
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//// event dispatching
|
|
|
|
addObserver: function(aEvent, aObserver) { this.mObsMan.addObserver(aEvent, aObserver); },
|
|
removeObserver: function(aEvent, aObserver) { this.mObsMan.removeObserver(aEvent, aObserver); },
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//// UI Commands
|
|
|
|
//////// rule contextual commands
|
|
|
|
cmdNewRule: function()
|
|
{
|
|
},
|
|
|
|
cmdToggleSelectedRule: function()
|
|
{
|
|
},
|
|
|
|
cmdDeleteSelectedRule: function()
|
|
{
|
|
},
|
|
|
|
cmdOpenSelectedFileInEditor: function()
|
|
{
|
|
var item = this.mRuleTree.selectedItems[0];
|
|
if (item)
|
|
{
|
|
var path = null;
|
|
|
|
var url = InsUtil.getDSProperty(this.mRuleDS, item.id, "FileURL");
|
|
if (url.substr(0, 6) == "chrome") {
|
|
// This is a tricky situation. Finding the source of a chrome file means knowing where
|
|
// your build tree is located, and where in the tree the file came from. Since files
|
|
// from the build tree get copied into chrome:// from unpredictable places, the best way
|
|
// to find them is manually.
|
|
//
|
|
// Solution to implement: Have the user pick the file location the first time it is opened.
|
|
// After that, keep the result in some sort of registry to look up next time it is opened.
|
|
// Allow this registry to be edited via preferences.
|
|
} else if (url.substr(0, 4) == "file") {
|
|
path = url;
|
|
}
|
|
|
|
if (path) {
|
|
try {
|
|
var exe = XPCU.createInstance("@mozilla.org/file/local;1", "nsILocalFile");
|
|
exe.initWithPath("c:\\windows\\notepad.exe");
|
|
exe = exe.nsIFile;
|
|
var C = Components;
|
|
var proc = C.classes['@mozilla.org/process/util;1'].createInstance
|
|
(C.interfaces.nsIProcess);
|
|
proc.init(exe);
|
|
proc.run(false, [url], 1);
|
|
} catch (ex) {
|
|
alert("Unable to open editor.");
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//// Uncategorized
|
|
|
|
getSelectedDec: function()
|
|
{
|
|
var idx = this.mRuleTree.currentIndex;
|
|
return this.mRuleView.getDecAt(idx);
|
|
},
|
|
|
|
getSelectedProp: function()
|
|
{
|
|
var dec = this.getSelectedDec();
|
|
var idx = this.mPropsTree.currentIndex;
|
|
return dec.item(idx);
|
|
},
|
|
|
|
onRuleSelect: function()
|
|
{
|
|
var dec = this.getSelectedDec();
|
|
this.mPropsView = new StylePropsView(dec);
|
|
this.mPropsBoxObject.view = this.mPropsView;
|
|
viewer.pane.panelset.updateAllCommands();
|
|
},
|
|
|
|
onPropSelect: function()
|
|
{
|
|
viewer.pane.panelset.updateAllCommands();
|
|
},
|
|
|
|
onCreateRulePopup: function()
|
|
{
|
|
},
|
|
|
|
propOnPopupShowing: function propOnPopupShowing()
|
|
{
|
|
var commandset = document.getElementById("cmdsProps");
|
|
for (var i = 0; i < commandset.childNodes.length; i++) {
|
|
var command = commandset.childNodes[i];
|
|
command.setAttribute("disabled", !viewer.isCommandEnabled(command.id));
|
|
}
|
|
}
|
|
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//// StyleRuleView
|
|
|
|
function StyleRuleView(aObject)
|
|
{
|
|
this.mDOMUtils = XPCU.getService("@mozilla.org/inspector/dom-utils;1", "inIDOMUtils");
|
|
if (aObject instanceof Components.interfaces.nsIDOMCSSStyleSheet) {
|
|
this.mSheetRules = aObject.cssRules;
|
|
} else {
|
|
this.mRules = this.mDOMUtils.getCSSStyleRules(aObject);
|
|
if (aObject.hasAttribute("style")) {
|
|
try {
|
|
this.mStyleAttribute =
|
|
new XPCNativeWrapper(aObject, "style").style;
|
|
} catch (ex) {}
|
|
}
|
|
}
|
|
}
|
|
|
|
StyleRuleView.prototype = new inBaseTreeView();
|
|
|
|
StyleRuleView.prototype.mSheetRules = null;
|
|
StyleRuleView.prototype.mRules = null;
|
|
StyleRuleView.prototype.mStyleAttribute = null;
|
|
|
|
StyleRuleView.prototype.__defineGetter__("rowCount",
|
|
function()
|
|
{
|
|
return this.mRules ? this.mRules.Count() + (this.mStyleAttribute ? 1 : 0)
|
|
: this.mSheetRules ? this.mSheetRules.length : 0;
|
|
});
|
|
|
|
StyleRuleView.prototype.getRuleAt =
|
|
function(aRow)
|
|
{
|
|
if (this.mRules) {
|
|
var rule = this.mRules.GetElementAt(aRow);
|
|
try {
|
|
return XPCU.QI(rule, "nsIDOMCSSStyleRule");
|
|
} catch (ex) {
|
|
return null;
|
|
}
|
|
}
|
|
return this.mSheetRules[aRow];
|
|
}
|
|
|
|
StyleRuleView.prototype.getDecAt =
|
|
function(aRow)
|
|
{
|
|
if (this.mRules) {
|
|
if (this.mStyleAttribute && aRow + 1 == this.rowCount) {
|
|
return this.mStyleAttribute;
|
|
}
|
|
var rule = this.mRules.GetElementAt(aRow);
|
|
try {
|
|
return XPCU.QI(rule, "nsIDOMCSSStyleRule").style;
|
|
} catch (ex) {
|
|
return null;
|
|
}
|
|
}
|
|
return this.mSheetRules[aRow].style;
|
|
}
|
|
|
|
StyleRuleView.prototype.getCellText =
|
|
function(aRow, aCol)
|
|
{
|
|
if (aRow > this.rowCount) return "";
|
|
|
|
// special case for the style attribute
|
|
if (this.mStyleAttribute && aRow + 1 == this.rowCount) {
|
|
if (aCol.id == "olcRule") {
|
|
return 'style=""';
|
|
}
|
|
|
|
if (aCol.id == "olcFileURL") {
|
|
// we ought to be able to get to the URL...
|
|
return "";
|
|
}
|
|
|
|
if (aCol.id == "olcLine") {
|
|
return "";
|
|
}
|
|
return "";
|
|
}
|
|
|
|
var rule = this.getRuleAt(aRow);
|
|
if (!rule) return "";
|
|
|
|
if (aCol.id == "olcRule") {
|
|
switch (rule.type) {
|
|
case CSSRule.STYLE_RULE:
|
|
return rule.selectorText;
|
|
case CSSRule.IMPORT_RULE:
|
|
// XXX should use .cssText here, but that asserts about some media crap
|
|
return "@import url(" + rule.href + ");";
|
|
default:
|
|
return rule.cssText;
|
|
}
|
|
}
|
|
|
|
if (aCol.id == "olcFileURL") {
|
|
return rule.parentStyleSheet ? rule.parentStyleSheet.href : "";
|
|
}
|
|
|
|
if (aCol.id == "olcLine") {
|
|
return rule.type == CSSRule.STYLE_RULE ? this.mDOMUtils.getRuleLine(rule) : "";
|
|
}
|
|
|
|
return "";
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//// StylePropsView
|
|
|
|
function StylePropsView(aDec)
|
|
{
|
|
this.mDec = aDec;
|
|
}
|
|
|
|
StylePropsView.prototype = new inBaseTreeView();
|
|
|
|
StylePropsView.prototype.__defineGetter__("rowCount",
|
|
function()
|
|
{
|
|
return this.mDec ? this.mDec.length : 0;
|
|
});
|
|
|
|
StylePropsView.prototype.getCellProperties =
|
|
function(aRow, aCol, aProperties)
|
|
{
|
|
if (aCol.id == "olcPropPriority") {
|
|
var prop = this.mDec.item(aRow);
|
|
if (this.mDec.getPropertyPriority(prop) == "important") {
|
|
aProperties.AppendElement(this.createAtom("important"));
|
|
}
|
|
}
|
|
}
|
|
|
|
StylePropsView.prototype.getCellText =
|
|
function (aRow, aCol)
|
|
{
|
|
var prop = this.mDec.item(aRow);
|
|
|
|
if (aCol.id == "olcPropName") {
|
|
return prop;
|
|
} else if (aCol.id == "olcPropValue") {
|
|
return this.mDec.getPropertyValue(prop)
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Returns a CSSDeclaration for the row in the tree corresponding to the
|
|
* passed index.
|
|
* @param aIndex index of the row in the tree
|
|
* @return a CSSDeclaration
|
|
*/
|
|
StylePropsView.prototype.getRowObjectFromIndex =
|
|
function getRowObjectFromIndex(aIndex)
|
|
{
|
|
var prop = this.mDec.item(aIndex);
|
|
return new CSSDeclaration(prop, this.mDec.getPropertyValue(prop),
|
|
this.mDec.getPropertyPriority(prop));
|
|
}
|
|
|
|
/**
|
|
* Handles inserting a CSS declaration
|
|
* @param aRule the rule that will contain the new declaration
|
|
* @param aProperty the property of the new declaration
|
|
* @param aValue the value of the new declaration
|
|
* @param aPriority the priority of the new declaration ("important" or "")
|
|
*/
|
|
function cmdEditInsert(aRule, aProperty, aValue, aPriority)
|
|
{
|
|
this.rule = aRule;
|
|
this.property = aProperty;
|
|
this.value = aValue;
|
|
this.priority = aPriority;
|
|
}
|
|
cmdEditInsert.prototype =
|
|
{
|
|
// remove this line for bug 179621, Phase Three
|
|
txnType: "standard",
|
|
|
|
// required for nsITransaction
|
|
QueryInterface: txnQueryInterface,
|
|
merge: txnMerge,
|
|
isTransient: false,
|
|
|
|
doTransaction: function doTransaction()
|
|
{
|
|
viewer.mPropsBoxObject.beginUpdateBatch();
|
|
try {
|
|
this.rule.setProperty(this.property, this.value, this.priority);
|
|
} finally {
|
|
viewer.mPropsBoxObject.endUpdateBatch();
|
|
}
|
|
},
|
|
|
|
undoTransaction: function undoTransaction()
|
|
{
|
|
this.rule.removeProperty(this.property);
|
|
viewer.mPropsBoxObject.invalidate();
|
|
},
|
|
|
|
redoTransaction: function redoTransaction()
|
|
{
|
|
this.doTransaction();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handles deleting CSS declarations
|
|
* @param aRule the rule containing the declarations
|
|
* @param aDeclarations an array of CSSDeclarations to delete
|
|
*/
|
|
function cmdEditDelete(aRule, aDeclarations)
|
|
{
|
|
this.rule = aRule;
|
|
this.declarations = aDeclarations;
|
|
}
|
|
cmdEditDelete.prototype =
|
|
{
|
|
// remove this line for bug 179621, Phase Three
|
|
txnType: "standard",
|
|
|
|
// required for nsITransaction
|
|
QueryInterface: txnQueryInterface,
|
|
merge: txnMerge,
|
|
isTransient: false,
|
|
|
|
doTransaction: function doTransaction()
|
|
{
|
|
viewer.mPropsBoxObject.beginUpdateBatch();
|
|
for (var i = 0; i < this.declarations.length; i++)
|
|
this.rule.removeProperty(this.declarations[i].property);
|
|
viewer.mPropsBoxObject.endUpdateBatch();
|
|
},
|
|
|
|
undoTransaction: function undoTransaction()
|
|
{
|
|
viewer.mPropsBoxObject.beginUpdateBatch();
|
|
for (var i = 0; i < this.declarations.length; i++)
|
|
this.rule.setProperty(this.declarations[i].property,
|
|
this.declarations[i].value,
|
|
this.declarations[i].important ? "important" : "");
|
|
},
|
|
|
|
redoTransaction: function redoTransaction()
|
|
{
|
|
this.doTransaction();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handles editing CSS declarations
|
|
* @param aRule the rule containing the declaration
|
|
* @param aProperty the property to change
|
|
* @param aNewValue the new value for the property
|
|
* @param aNewValue the new priority for the property ("important" or "")
|
|
*/
|
|
function cmdEditEdit(aRule, aProperty, aNewValue, aNewPriority)
|
|
{
|
|
this.rule = aRule;
|
|
this.property = aProperty;
|
|
this.oldValue = aRule.getPropertyValue(aProperty);
|
|
this.newValue = aNewValue;
|
|
this.oldPriority = aRule.getPropertyPriority(aProperty);
|
|
this.newPriority = aNewPriority;
|
|
}
|
|
cmdEditEdit.prototype =
|
|
{
|
|
// remove this line for bug 179621, Phase Three
|
|
txnType: "standard",
|
|
|
|
// required for nsITransaction
|
|
QueryInterface: txnQueryInterface,
|
|
merge: txnMerge,
|
|
isTransient: false,
|
|
|
|
doTransaction: function doTransaction()
|
|
{
|
|
this.rule.setProperty(this.property, this.newValue,
|
|
this.newPriority);
|
|
viewer.mPropsBoxObject.invalidate();
|
|
},
|
|
|
|
undoTransaction: function undoTransaction()
|
|
{
|
|
this.rule.setProperty(this.property, this.oldValue,
|
|
this.oldPriority);
|
|
viewer.mPropsBoxObject.invalidate();
|
|
},
|
|
|
|
redoTransaction: function redoTransaction()
|
|
{
|
|
this.doTransaction();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handles toggling CSS !important.
|
|
* @param aRule the rule containing the declarations
|
|
* @param aDeclarations an array of CSSDeclarations to toggle
|
|
*/
|
|
function cmdTogglePriority(aRule, aDeclarations)
|
|
{
|
|
this.rule = aRule;
|
|
this.declarations = aDeclarations;
|
|
}
|
|
cmdTogglePriority.prototype =
|
|
{
|
|
// remove this line for bug 179621, Phase Three
|
|
txnType: "standard",
|
|
|
|
// required for nsITransaction
|
|
QueryInterface: txnQueryInterface,
|
|
merge: txnMerge,
|
|
isTransient: false,
|
|
|
|
doTransaction: function doTransaction()
|
|
{
|
|
for (var i = 0; i < this.declarations.length; i++) {
|
|
//XXX bug 305761 means we can't make something not important, so instead
|
|
// we'll delete this property and make a new one at the proper priority.
|
|
// this method also sucks because the property gets moved to the bottom.
|
|
var property = this.declarations[i].property;
|
|
var value = this.declarations[i].value;
|
|
var newPriority = this.rule.getPropertyPriority(property) == "" ?
|
|
"important" : "";
|
|
this.rule.removeProperty(property);
|
|
this.rule.setProperty(property, value, newPriority);
|
|
}
|
|
viewer.mPropsBoxObject.invalidate();
|
|
},
|
|
|
|
undoTransaction: function undoTransaction()
|
|
{
|
|
this.doTransaction();
|
|
},
|
|
|
|
redoTransaction: function redoTransaction()
|
|
{
|
|
this.doTransaction();
|
|
}
|
|
}
|