Pawel Chmielowski - Object.Slot-0.01

Documentation | Source

NAME

Object.Slot

DESCRIPTION

This module adds functions for managing slots and signals.

Object.Slot.connect(SLOTOBJECT, SLOTNAME, SIGNALOBJECT, SIGNALNAME)

Connects SIGNALNAME method from SIGNALOBJECT to SLOTNAME method on SLOTOBJECT object.

Any further invocation of SLOTNAME will automaticaly also execute SIGNALOBJECT method with arguments passed to primary method.

Object.Slot.disconnect(SLOTOBJECT, SLOTNAME, SIGNALOBJECT, SIGNALNAME)

Disonnects SIGNALNAME method from SIGNALOBJECT object from SLOTNAME method on SLOTOBJECT object.

This break links between SLOTNAME method and SIGNALNAME created by Object.Slot.connect. Next invocations of SLOTNAME will not be dispatched to SIGNALOBJECT.

AUTHOR

Pawel Chmielowski <prefiks@aviary.pl>

/*

=head1 NAME

Object.Slot

=head1 DESCRIPTION

This module adds functions for managing slots and signals.

=cut

*/

try {
    JSAN.use( 'List.Utils' );
} catch (e) {
    throw "Object.Slot requires JSAN to be loaded";
}

if (!Object.Slot) {
    Object.Slot = {
      VERSION: "0.01",

/*

=head2 Object.Slot.connect(SLOTOBJECT, SLOTNAME, SIGNALOBJECT, SIGNALNAME)

Connects SIGNALNAME method from SIGNALOBJECT to SLOTNAME method on SLOTOBJECT
object.

Any further invocation of SLOTNAME will automaticaly also execute
SIGNALOBJECT method with arguments passed to primary method.

=cut

 */
        connect: function(obj, slotName, signalObj, signalMethodName)
        {
            var base;

            if (slotName in obj) {
                if (obj[slotName] != null && typeof(obj[slotName]) != "function")
                    throw "Object.Slot.connect() can be used only on function slots.";

                if (obj[slotName].__SLOT_SIGNALS__) {
                    insertIntoList(obj[slotName].__SLOT_SIGNALS__,
                                   [signalObj, signalMethodName],
                                   function(a){return a[0] == signalObj &&
                                               a[1] == signalMethodName});

                    return;
                }

                base = obj[slotName];
            }

            obj[slotName] = function() {
                var res, i, signals, exc;

                if (arguments.callee.__SLOT_BASE__)
                    res = arguments.callee.__SLOT_BASE__.apply(this, arguments);

                try {
                    var i, signals = arguments.callee.__SLOT_SIGNALS__;

                    for (i = 0; i < signals.length; i++) {
                        signal=signals[i];
                        signal[0][signal[1]].apply(signal[0], arguments);
                    }
                } catch (ex) { }

                return res;
            }
            if (base)
                obj[slotName].__SLOT_BASE__ = base;

            obj[slotName].__SLOT_SIGNALS__ = [[signalObj, signalMethodName]];
        },

/*

=head2 Object.Slot.disconnect(SLOTOBJECT, SLOTNAME, SIGNALOBJECT, SIGNALNAME)

Disonnects SIGNALNAME method from SIGNALOBJECT object from SLOTNAME method on
SLOTOBJECT object.

This break links between SLOTNAME method and SIGNALNAME created by
C<Object.Slot.connect>. Next invocations of SLOTNAME will not be dispatched
to SIGNALOBJECT.

=cut

 */
        disconnect: function(obj, slotName, signalObj, signalMethodName)
        {
            if (obj[slotName] == null || typeof(obj[slotName]) != "function" ||
                    !obj[slotName].__SLOT_SIGNALS__)
                return;

            removeFromList(obj[slotName].__SLOT_SIGNALS__,
                           [signalObj, signalMethodName],
                           function(a){return a[0] == signalObj &&
                                       a[1] == signalMethodName});

            if (obj[slotName].__SLOT_SIGNALS__.length > 0)
                return;

            obj[slotName] = obj[slotName].__SLOT_BASE__;
        }
    }
}

/*

=head1 AUTHOR

Pawel Chmielowski <prefiks@aviary.pl>

=cut

*/