0

我正在使用雷鸟代码库,目的是实现内联联系人编辑。当前代码Click在树上捕获事件XUL,如果是双击 ( events.detail == 2),它会打开配置文件编辑器。我对其进行了修改以开始编辑当前的treeCell,并且确实添加editable=true到了相应的XUL文档中。更新的代码读取

var orow = {}, ocolumn = {}, opart = {};
gAbResultsTree.treeBoxObject.getCellAt(event.clientX, event.clientY,
                                       orow, ocolumn, opart);

var row = orow.value, column = ocolumn.value.index;         
if (row == -1) 
  return;

if (event.detail == 2)
  gAbResultsTree.startEditing(row, column);

不幸的是,当代码到达startEditing部件时,它返回

Error: uncaught exception: [Exception... "Component returned failure code: 0x80004001 (NS_ERROR_NOT_IMPLEMENTED) [nsITreeView.isEditable]" nsresult: "0x80004001 (NS_ERROR_NOT_IMPLEMENTED)" location: "JS frame :: chrome://global/content/bindings/tree.xml :: startEditing :: line 337" data: no]

我在这里几乎迷路了。有更多 XUL 经验的人可以提供帮助吗?谢谢!

4

2 回答 2

2

我试图做类似的事情,我有同样的问题。

将原始 abview 设置为__proto__覆盖函数的包装器可以正常工作,直到将其设置为 abResultsTree 的视图。

我终于找到了(我希望)一个优雅的解决方案。

function MyAbView() {
    this.originalAbViewInstance = this.originalAbViewFactory.createInstance(null, Ci.nsIAbView);

    if (!this.proxiesGenerated) {
        // find out which interfaces are implemented by original instance, their property proxies will be generated later
        for (var ifName in Ci) {
            if (Ci[ifName] instanceof Ci.nsIJSID && this.originalAbViewInstance instanceof Ci[ifName]) {
                MyAbView.prototype.supportedInterfaces.push(Ci[ifName]);
            }
        }

        function generatePropertyProxy(name) {
            Object.defineProperty(MyAbView.prototype, name, {
                get: function() {
                    return this.originalAbViewInstance[name];
                },
                set: function(val) {
                    this.originalAbViewInstance[name] = val;
                },
                enumerable: true
            });
        }

        for (var prop in this.originalAbViewInstance) {
            if (this[prop] == undefined) {
                generatePropertyProxy(prop);
            }
        }

        MyAbView.prototype.proxiesGenerated = true;
    } else {
        for each (var interface in this.supportedInterfaces) {
            this.originalAbViewInstance.QueryInterface(interface);
        }
    }
}

MyAbView.prototype = {
    classID: null,

    _xpcom_factory: {
        createInstance: function(outer, iid) {
            return new MyAbView().QueryInterface(iid);
        }
    },

    QueryInterface: function(aIID) {
        for each (var interface in this.supportedInterfaces) {
            if (interface.equals(aIID)) {
                return this;
            }
        }

        throw Components.results.NS_ERROR_NO_INTERFACE;
    },

    originalAbViewFactory: null,
    originalAbViewInstance: null,

    proxiesGenerated: false,
    supportedInterfaces: [],

    // any overriden functions come here
};

它被实现为一个替换原始abview的组件,但它可能被修改为只创建一个包装器。

于 2012-03-22T20:11:04.133 回答
1

<tree>部件使用nsITreeView对象来检索或操作需要显示的数据。有nsITreeView从 DOM 或 RDF 数据源读取数据的预定义实现,但可以选择使用自己的树视图。Thunderbird 的通讯录选择了后者:

gAbView = Components.classes["@mozilla.org/addressbook/abview;1"]
                    .createInstance(Components.interfaces.nsIAbView);

...

gAbResultsTree.treeBoxObject.view =
  gAbView.QueryInterface(Components.interfaces.nsITreeView);

不幸的是,有问题的组件是用 C++ 实现的,在文件nsAbView.cpp中。这意味着在不重新编译 Thunderbird 的情况下更改它是不可能的。并且现有组件没有实现编辑树单元所需的方法isEditable()setCellText()

如果您还不想弄乱 C++,您可以将该组件包装在您自己的对象中。像这样的东西:

gAbView = Components.classes["@mozilla.org/addressbook/abview;1"]
                    .createInstance(Components.interfaces.nsIAbView);
gAbViewWrapper = {
  __proto__: gAbView,
  QueryInterface: function(iid)
  {
    gAbView.QueryInterface(iid);
    return this;
  },
  isEditable: function(row, col)
  {
    // Do something here
  },
  setCellText: function(row, col, value)
  {
    // Do something here
  }
};

...

gAbResultsTree.treeBoxObject.view =
  gAbViewWrapper.QueryInterface(Components.interfaces.nsITreeView);

方法isEditable()应该再次检查此特定单元格是否可编辑 - 即使列是可编辑的,单个单元格也不必是。并且setCellText()应该存储单元格的新值。

于 2011-10-27T15:32:50.980 回答