XUL / Thunderbird: начало редактирования - PullRequest
0 голосов
/ 27 октября 2011

Я играю с базой кодов Thunderbird, целью которой является реализация редактирования контактов. Текущий код перехватывает событие 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 помочь? Спасибо!

Ответы [ 2 ]

2 голосов
/ 23 марта 2012

Я пытался сделать что-то подобное, и у меня та же проблема.

Упаковщик с исходным 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
};

Он реализован как компонент, заменяющий исходное представление, но его можно изменить, чтобы просто создать оболочку.

1 голос
/ 27 октября 2011

Виджет <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() должен хранить новое значение для ячейки.

...