A whole bunch of ViXEn stuff, part 1. Basic aggregate transactions and

undo/redo fit and finish. NOT PART OF BUILD


git-svn-id: svn://10.0.0.236/trunk@81450 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
ben%netscape.com 2000-10-19 11:25:53 +00:00
parent c08a906df3
commit f44f9dd029
11 changed files with 296 additions and 46 deletions

View File

@ -27,26 +27,99 @@
var vxPalette =
{
// we want to use controllers, but this will do to test our txns.
nButtons: 0, // XXX hack
mElementCount: { },
insertButtonElement: function (aType)
{
_dd("insertButtonElement");
var nElements = this.incrementElementCount("button");
var attributes = ["value", "id"];
var values = ["Button " + nElements, "button_" + nElements];
this.insertSingleElement("button", attributes, values);
},
insertTextFieldElement: function (aType)
{
var nElements = this.incrementElementCount("textfield");
var attributes = ["value", "id"];
var values = ["Textfield " + nElements, "textfield_" + nElements];
this.insertSingleElement("textfield", attributes, values);
},
insertRadioGroup: function ()
{
var nRadios = this.incrementElementCount("radio");
var nRadiogroups = this.incrementElementCount("radiogroup");
var vixenMain = vxUtils.getWindow("vixen:main");
var focusedWindow = vixenMain.vxShell.mFocusedWindow;
// need to check to see if the focused window is a vfd
var insertionPoint = focusedWindow.vxVFD.getInsertionPoint();
var vfdDocument = focusedWindow.vxVFD.getContent(true).document;
_dd(vfdDocument);
// create a button
this.nButtons++;
var buttontxn = new vxCreateElementTxn(vfdDocument, "button", insertionPoint.parent, insertionPoint.index);
var attributes = ["value", "id"];
var values = ["Button " + this.nButtons, "button_" + this.nButtons];
var buttonattrtxn = new vxChangeAttributeTxn(buttontxn.mElement, attributes, values, false);
var radiogroupTxn = new vxCreateElementTxn(vfdDocument, "radiogroup", insertionPoint.parent, insertionPoint.index);
radiogroupTxn.init();
var radiogroupAttributes = ["id"];
var radiogroupValues = ["radiogroup_" + nRadiogroups];
var radiogroupAttrTxn = new vxChangeAttributeTxn(radiogroupTxn.mID,
radiogroupAttributes,
radiogroupValues, false);
radiogroupAttrTxn.init();
var aggregateTxn = new vxAggregateTxn([buttontxn, buttonattrtxn]);
focusedWindow.vxVFD.mTxMgrShell.doTransaction(aggregateTxn);
var radioTxn = new vxCreateElementTxn(vfdDocument, "radio", radiogroupTxn.mID, insertionPoint.index);
radioTxn.init();
var radioAttributes = ["value", "group", "id"];
var radioValues = ["Radio " + nRadios, "radiogroup_" + nRadiogroups, "radio_" + nRadios];
var radioAttrTxn = new vxChangeAttributeTxn(radioTxn.mID,
radioAttributes,
radioValues, false);
radioAttrTxn.init();
// batch the transactions
var txns = [radiogroupTxn, radiogroupAttrTxn, radioTxn, radioAttrTxn];
var aggregateTxn = new vxAggregateTxn(txns);
aggregateTxn.init();
var txmgr = focusedWindow.vxVFD.mTxMgrShell;
txmgr.addListener([radioAttrTxn, radioTxn, radioAttrTxn]);
txmgr.doTransaction(aggregateTxn);
txmgr.removeListener([radioAttrTxn, radioTxn, radioAttrTxn]);
},
incrementElementCount: function (aNodeName)
{
// create an node count entry for the specified node name
if (!(aNodeName in this.mElementCount))
this.mElementCount[aNodeName] = 0;
return ++this.mElementCount[aNodeName];
},
insertSingleElement: function (aNodeName, aAttributes, aValues)
{
var vixenMain = vxUtils.getWindow("vixen:main");
var focusedWindow = vixenMain.vxShell.mFocusedWindow;
// need to check to see if the focused window is a vfd
var insertionPoint = focusedWindow.vxVFD.getInsertionPoint();
var vfdDocument = focusedWindow.vxVFD.getContent(true).document;
var elementTxn = new vxCreateElementTxn(vfdDocument, aNodeName, insertionPoint.parent, insertionPoint.index);
elementTxn.init();
var elementAttrTxn = new vxChangeAttributeTxn(elementTxn.mID, aAttributes, aValues, false);
elementAttrTxn.init();
// batch the transactions
var aggregateTxn = new vxAggregateTxn([elementTxn, elementAttrTxn]);
aggregateTxn.init();
var txmgr = focusedWindow.vxVFD.mTxMgrShell;
txmgr.addListener(elementAttrTxn);
txmgr.doTransaction(aggregateTxn);
txmgr.removeListener(elementAttrTxn);
}
};

View File

@ -19,7 +19,13 @@
<script src="chrome://vixen/content/vfd/vxCreateElementTxn.js"></script>
<button value="Button" oncommand="vxPalette.insertButtonElement('button');"/>
<button value="Button"
oncommand="vxPalette.insertButtonElement();"/>
<button value="TextField"
oncommand="vxPalette.insertTextFieldElement();"/>
<button value="RadioGroup"
oncommand="vxPalette.insertRadioGroup();"/>
</window>

View File

@ -21,14 +21,14 @@
<script src="chrome://vixen/content/vfd/vxVFDSelectionManager.js"></script>
<tabcontrol class="tabbed-edit" flex="1" orient="vertical">
<tabpanel flex="1">
<iframe id="vfdDocument" name="vfdDocument" flex="1"/>
<box id="vfdDOMTree" flex="1"/> <!-- from overlay -->
</tabpanel>
<tabbox>
<tab value="Design"/>
<tab value="DOM Tree"/>
</tabbox>
<tabpanel flex="1">
<iframe id="vfdDocument" name="vfdDocument" flex="1"/>
<box id="vfdDOMTree" flex="1"/> <!-- from overlay -->
</tabpanel>
</tabcontrol>
</window>

View File

@ -31,28 +31,37 @@
function vxAggregateTxn (aTransactionList)
{
this.mTransactionList = aTransactionList;
this.mTransactionList = { };
for (var i = 0; i < aTransactionList.length; i++)
this.mTransactionList[aTransactionList[i].mID] = aTransactionList[i];
this.mID = "aggregate-txn::";
}
vxAggregateTxn.prototype = {
init: function ()
{
this.mID += generateID();
},
doTransaction: function ()
{
_dd("vxAggregateTxn::doTransaction");
for (var i = 0; i < this.mTransactionList.length; i++)
for (var i in this.mTransactionList)
this.mTransactionList[i].doTransaction();
},
undoTransaction: function ()
{
_dd("vxAggregateTxn::undoTransaction");
for (var i = 0; i < this.mTransactionList.length; i++)
for (var i in this.mTransactionList)
this.mTransactionList[i].undoTransaction();
},
redoTransaction: function ()
{
_dd("vxAggregateTxn::redoTransaction");
for (var i = 0; i < this.mTransactionList.length; i++)
for (var i in this.mTransactionList)
this.mTransactionList[i].redoTransaction();
},

View File

@ -39,18 +39,35 @@
function vxChangeAttributeTxn(aElement, aAttribute, aValue, aRemoveFlag)
{
if (!aElement) throw Components.results.NS_ERROR_NULL_POINTER;
this.mElementCreated = false;
if (typeof(aElement) === "string" && aElement.indexOf("create-element") >= 0)
this.mElementTxnID = aElement;
else
this.mElementCreated = true;
this.mElement = aElement;
this.mAttributes = aAttribute.splice ? aAttribute : [aAttribute];
this.mValues = aValue.splice ? aValue : [aValue];
this.mRemoveFlags = aRemoveFlag.splice ? aRemoveFlag : [aRemoveFlag];
this.mAttributes = [].concat(aAttribute);
this.mValues = [].concat(aValue);
this.mRemoveFlags = [].concat(aRemoveFlag);
this.mUndoValues = [];
this.mID = "create-element::";
}
vxChangeAttributeTxn.prototype = {
init: function ()
{
this.mID += generateID();
},
doTransaction: function ()
{
if (!this.mElementCreated)
return;
for (var i = 0; i < this.mAttributes.length; i++) {
_ddf("this attribute", this.mAttributes[i]);
this.mUndoValues[i] = this.mElement.getAttribute(this.mAttributes[i]);
if (!this.mRemoveFlags[i])
this.mElement.setAttribute(this.mAttributes[i], this.mValues[i]);
@ -83,11 +100,26 @@ vxChangeAttributeTxn.prototype = {
get commandString()
{
var commandString = "change-attribute,";
commandString += this.mRemoveFlag ? "remove," : "set,";
/* commandString += this.mRemoveFlag ? "remove," : "set,";
commandString += this.mElement.id + ",";
commandString += this.mAttribute + ",";
commandString += this.mValue;
commandString += this.mValue;*/
return commandString;
},
/**
* Implementation of nsITransactionListener
*/
didDo: function (aTransactionManager, aTransaction, aInterrupt)
{
var createElementTxn = aTransaction.mTransactionList[this.mElementTxnID];
_ddf("the transaction ahead of us is", createElementTxn.commandString);
_ddf("and its element is", createElementTxn.mLocalName);
if (createElementTxn.commandString.indexOf("create-element") >= 0) {
this.mElement = createElementTxn.mElement;
this.mElementCreated = true;
this.doTransaction();
}
}
};

View File

@ -31,24 +31,40 @@ function vxCreateElementTxn(aDocument, aLocalName, aParentNode, aChildOffset)
{
this.mDocument = aDocument;
this.mLocalName = aLocalName;
this.mElementCreated = false;
if (typeof(aParentNode) === "string" && aParentNode.indexOf("create-element") >= 0)
this.mElementTxnID = aParentNode;
else
this.mElementCreated = true;
this.mParentNode = aParentNode;
this.mChildOffset = aChildOffset;
this.mElement = this.mDocument.createElement(this.mLocalName);
this.mID = "create-element::";
}
vxCreateElementTxn.prototype = {
init: function ()
{
this.mID += generateID();
},
doTransaction: function ()
{
_ddf("creating element", this.mLocalName);
if (!this.mElementCreated) {
_dd("aParentNode is an id, bailing early");
_ddf("localname is", this.mLocalName);
return;
}
this.mElement = this.mDocument.createElement(this.mLocalName);
this.insertNode();
},
undoTransaction: function ()
{
_ddf("element", this.mElement.localName);
_ddf("parent", this.mParentNode.localName);
for (var i = 0; i < this.mParentNode.childNodes.length; i++) {
_ddf("childnode at " + i, this.mParentNode.childNodes[i]);
}
this.mParentNode.removeChild(this.mElement);
},
@ -72,12 +88,22 @@ vxCreateElementTxn.prototype = {
get commandString()
{
var commandString = "create-element";
commandString = this.mRemoveFlag ? "remove," : "set,";
commandString += this.mElement.id + ",";
commandString += this.mAttribute + ",";
commandString += this.mValue;
return commandString;
},
/**
* Implementation of nsITransactionListener
*/
didDo: function (aTransactionManager, aTransaction, aInterrupt)
{
var createElementTxn = aTransaction.mTransactionList[this.mElementTxnID];
if (createElementTxn.commandString.indexOf("create-element") >= 0) {
this.mElement = createElementTxn.mElement;
this.mElementCreated = true;
this.doTransaction();
}
}
};
/**

View File

@ -24,6 +24,10 @@
function vxVFDTransactionManager()
{
this.mTxnStack = new vxVFDTransactionStack();
// a record of transaction execution listeners that have attached
// themselves to us.
this.mTransactionListeners = [];
}
vxVFDTransactionManager.prototype =
@ -35,6 +39,14 @@ vxVFDTransactionManager.prototype =
doTransaction: function (aTransaction)
{
for (var i = 0; i < this.mTransactionListeners.length; i++) {
var interruptRequest = {};
if ("willDo" in this.mTransactionListeners[i]) {
this.mTransactionListeners[i].willDo(this, aTransaction, interruptRequest);
// do something with irq here once we figure out what it does.
}
}
// perform the transaction
aTransaction.doTransaction();
@ -49,7 +61,7 @@ vxVFDTransactionManager.prototype =
// likewise with the RDF Seq.
var seqCount = this.mTxnSeq.GetCount();
for (var i = this.mTxnStack.index; i < seqCount; i++)
for (i = this.mTxnStack.index; i < seqCount; i++)
this.mTxnSeq.RemoveElementAt(i);
}
@ -59,10 +71,26 @@ vxVFDTransactionManager.prototype =
// add the transaction to the stack
this.mTxnSeq.AppendElement(new RDFLiteral(this.mTxnStack.index-1));
for (i = 0; i < this.mTransactionListeners.length; i++) {
interruptRequest = {};
if ("didDo" in this.mTransactionListeners[i]) {
_ddf("transaction listener " + i, this.mTransactionListeners[i].commandString);
this.mTransactionListeners[i].didDo(this, aTransaction, interruptRequest);
// do something with irq here once we figure out what it does.
}
}
},
undoTransaction: function ()
{
for (var i = 0; i < this.mTransactionListeners.length; i++) {
var interruptRequest = {};
if ("willUndo" in this.mTransactionListeners[i]) {
this.mTransactionListeners[i].willUndo(this, aTransaction, interruptRequest);
// do something with irq here once we figure out what it does.
}
}
// retrieve the previous transaction
var txn = this.mTxnStack.mStack[this.mTxnStack.index-1];
@ -72,18 +100,42 @@ vxVFDTransactionManager.prototype =
txn.undoTransaction();
this.mTxnStack.index--;
}
for (i = 0; i < this.mTransactionListeners.length; i++) {
interruptRequest = {};
if ("didUndo" in this.mTransactionListeners[i]) {
this.mTransactionListeners[i].didUndo(this, aTransaction, interruptRequest);
// do something with irq here once we figure out what it does.
}
}
},
redoTransaction: function (aTransaction)
{
for (var i = 0; i < this.mTransactionListeners.length; i++) {
var interruptRequest = {};
if ("willRedo" in this.mTransactionListeners[i]) {
this.mTransactionListeners[i].willRedo(this, aTransaction, interruptRequest);
// do something with irq here once we figure out what it does.
}
}
// retrieve the previous transaction
var txn = this.mTxnStack.mStack[this.mTxnStack.index+1];
var txn = this.mTxnStack.mStack[this.mTxnStack.index];
// redo the transaction
if (txn) {
txn.redoTransaction();
this.mTxnStack.index++;
}
for (i = 0; i < this.mTransactionListeners.length; i++) {
interruptRequest = {};
if ("didRedo" in this.mTransactionListeners[i]) {
this.mTransactionListeners[i].didRedo(this, aTransaction, interruptRequest);
// do something with irq here once we figure out what it does.
}
}
},
makeSeq: function (aResource)
@ -92,8 +144,34 @@ vxVFDTransactionManager.prototype =
const kContainerUtilsIID = "nsIRDFContainerUtils";
var utils = nsJSComponentManager.getServiceByID(kContainerUtilsCID, kContainerUtilsIID);
return utils.MakeSeq(vxVFDTransactionDS, aResource);
}
},
/**
* add and remove nsITransactionListeners
*/
addListener: function (aTransactionListener)
{
if ("splice" in aTransactionListener) {
for (var i = 0; i < aTransactionListener.length; i++)
this.mTransactionListeners.push(aTransactionListener[i]);
}
else
this.mTransactionListeners.join(aTransactionListener);
_ddf("transaction listeners :: ", this.mTransactionListeners.length);
},
removeListener: function (aTransactionListeners)
{
var listeners = [].join(aTransactionListeners)
for (var i = 0; i < this.mTransactionListeners.length; i++) {
for (var k = 0; k < listeners.length; k++) {
if (this.mTransactionListeners[i] == listeners[k]) {
this.mTransactionListeners.splice(i, 1);
break;
}
}
}
}
};
/**
@ -161,7 +239,7 @@ var vxVFDTransactionDS =
mObservers: [],
AddObserver: function (aObserver)
{
this.mObservers.push(aObserver);
this.mObservers[this.mObservers.length] = aObserver;
},
RemoveObserver: function (aObserver)

View File

@ -137,7 +137,7 @@ var vxShell =
this.mFocusedWindow.vxVFD.mTxMgrShell.redoTransaction();
},
appAbout: function ()
{
// XXX TEMP
@ -145,3 +145,9 @@ var vxShell =
}
};
function XXX_dumpDOM()
{
var focusedWindow = vxShell.mFocusedWindow;
var insertionPoint = focusedWindow.vxVFD.getInsertionPoint();
dumpDOM(insertionPoint.parent);
}

View File

@ -71,7 +71,7 @@
</menu>
</menubar>
<toolbar id="xuledit-toolbar" flex="1">
<button class="button-toolbar" value="Button" oncommand="goDoCommand('cmd_insert_button');"/>
<button class="button-toolbar" value="Dump DOM" oncommand="XXX_dumpDOM();"/>
</toolbar>
</toolbox>

View File

@ -44,3 +44,23 @@ var vxUtils = {
};
/**
* Generate a unique identifier for a transaction
*/
function generateID()
{
var val = ((new Date()).getUTCMilliseconds())*Math.random()*100000;
_ddf("value", val);
return val;
}
/**
* dumps the DOM tree under a given node.
*/
function dumpDOM(aNode)
{
_dd("<" + aNode.localName + " id=" + aNode.id + ">");
for (var i = 0; i < aNode.childNodes.length; i++)
dumpDOM(aNode.childNodes[i]);
}

View File

@ -13,7 +13,7 @@ vixen.jar:
content/vixen/vfd/scratch.xul (content/vfd/scratch.xul)
content/vixen/vfd/vfd.js (content/vfd/vfd.js)
content/vixen/vfd/vfd.xul (content/vfd/vfd.xul)
content/vixen/vfd/vxChangeAttributeTxn.js (content/vfd/vxChangeAttributeTxn.js)
+ content/vixen/vfd/vxChangeAttributeTxn.js (content/vfd/vxChangeAttributeTxn.js)
content/vixen/vfd/vxCreateElementTxn.js (content/vfd/vxCreateElementTxn.js)
content/vixen/vfd/vxVFDSelectionManager.js (content/vfd/vxVFDSelectionManager.js)
content/vixen/vfd/vxVFDTransactionManager.js (content/vfd/vxVFDTransactionManager.js)