ORIGIN 'astlevel'; INCLUDE 'observer'; LIB_ITEM 'mpsastlevel'; BODY 'private/notificationsbody'; (* This fragment implements a signalling system to be used by different * software components, each manipulating fragments through the same * mps instance. * * The system consists of the concept of a 'handle', which the software * component can use to both signal, that it has made some changes to * a fragment, and to subscribe to information on what other software * components are doing to the fragments. * * A handle therefore has a dual set of operations: * 'signal's and 'event's * A 'signal' operation is named 'signalXXX', and the corresponding * event is called 'onXXX', where 'XXX' is the name of the change * being reported. * * It is the responsability of the software component making the change * to signal this change. This is done by invoking the corresponding * 'signalXXX' operation. If a software component want to monitor * particular changes, it must obtain a handle with proper further * binding of the corresonding 'eventXXX' (more on this later). * * A few of these signals are automatically invoked by 'mps'. * In these cases, this is explicitly specified in the operation below. * * A software component obtains a handle by: * * mps.getHandle * (# handleType:: * (# onGroupOpen:: * (# do fg.fullname->puttext; ' opened'->putline #); * onGroupClose * (# do fg.fullname->puttext; ' closed'->putline #); * ...etc... * #) * #); * * This handle monitors opening and closing of all fragment groups. * * If you want a handle, that only monitors a particular fragment * group, you can do this by: * * mps.getHandle * (# handleType:: * (# ignore:: (# (fg[]<>myFG[])->value #); * ... som ovenfor ... * #) * #); * * You can get hold of this newly created handle by: * * mps.getHandle(# ...som ovenfor... #)->h[]; * * in which case it becomes possible later to decide to cancel this * handle by: * * h[]->mps.ignoreHandle; * * If you later want to reactivate this handle, you can always do: * * h[]->mps.activateHandle; * * If you have made changes to a fragment group, e.g. replaced an ast, * you can signal this to the other components by: * * (fg[], ff[], oldAst[], newAst[])->mps.signalAstReplaced * * If you wish to control which handlers, signals are send to, you can * use the 'where' clause of 'signal'. E.g. if you with to send a * signal to all handlers, except 'h[]', you can do this by: * * (fg[], ff[], oldAst[], newAst[])->mps.signalAstReplaced * (# where:: (# do (current[]<>h[])->value #) #) *) (* This fragment implements a signalling system to be used by different * software components, each manipulating fragments through the same * mps instance. * * The system consists of the concept of a 'handle', which the software * component can use to both signal, that it has made some changes to * a fragment, and to subscribe to information on what other software * components are doing to the fragments. * * A handle therefore has a dual set of operations: * 'signal's and 'event's * A 'signal' operation is named 'signalXXX', and the corresponding * event is called 'onXXX', where 'XXX' is the name of the change * being reported. * * It is the responsability of the software component making the change * to signal this change. This is done by invoking the corresponding * 'signalXXX' operation. If a software component want to monitor * particular changes, it must obtain a handle with proper further * binding of the corresonding 'eventXXX' (more on this later). * * A few of these signals are automatically invoked by 'mps'. * In these cases, this is explicitly specified in the operation below. * * A software component obtains a handle by: * * mps.getHandle * (# handleType:: * (# onGroupOpen:: * (# do fg.fullname->puttext; ' opened'->putline #); * onGroupClose * (# do fg.fullname->puttext; ' closed'->putline #); * ...etc... * #) * #); * * This handle monitors opening and closing of all fragment groups. * * If you want a handle, that only monitors a particular fragment * group, you can do this by: * * mps.getHandle * (# handleType:: * (# ignore:: (# (fg[]<>myFG[])->value #); * ... som ovenfor ... * #) * #); * * You can get hold of this newly created handle by: * * mps.getHandle(# ...som ovenfor... #)->h[]; * * in which case it becomes possible later to decide to cancel this * handle by: * * h[]->mps.ignoreHandle; * * If you later want to reactivate this handle, you can always do: * * h[]->mps.activateHandle; * * If you have made changes to a fragment group, e.g. replaced an ast, * you can signal this to the other components by: * * (fg[], ff[], oldAst[], newAst[])->mps.signalAstReplaced * * If you wish to control which handlers, signals are send to, you can * use the 'where' clause of 'signal'. E.g. if you with to send a * signal to all handlers, except 'h[]', you can do this by: * * (fg[], ff[], oldAst[], newAst[])->mps.signalAstReplaced * (# where:: (# do (current[]<>h[])->value #) #) *) -- astinterfacelib: Attributes -- getHandle: (* called to get a new handle on this MPS *) (# handleType:< handle; h: ^handleType ... exit h[] #); ignoreHandle: (* called to return a handle (i.e. now wanting to be monitoring * this MPS through this handle 'h' any longer *) (# h: ^handle enter h[] ... #); activateHandle: (* called to activate a handle (i.e. now wanting to be monitoring * this MPS through this handle 'h' again *) (# h: ^handle enter h[] ... #); handle: (* this defines the events of a handle *) (# ignore:< booleanValue (* if this returns TRUE, this(handle) will be ignored *) (# fg: ^astInterface.fragmentGroup; ff: ^astInterface.fragmentForm; node: ^astInterface.ast enter (fg[],ff[],node[]) do INNER #); event: (* abstract superpattern *) (# do INNER #); fragmentGroupEvent: event (* abstract superpattern *) (# fg: ^astInterface.fragmentGroup; enter fg[] do INNER ; #); fragmentFormEvent: fragmentGroupEvent (* abstract superpattern *) (# ff: ^astInterface.fragmentForm; enter ff[] do INNER ; #); astEvent: fragmentFormEvent (* abstract superpattern *) (# node: ^astInterface.ast enter node[] do INNER #); onGroupOpen:< fragmentGroupEvent (* invoked by MPS when fg[] have been opened by someone *) (# do INNER #); onGroupLock:< fragmentGroupEvent (* invoked by MPS when fg[] is locked *) (# do INNER #); onGroupUnlock:< fragmentGroupEvent (* invoked by MPS when fg[] is unlocked *) (# do INNER #); onGroupPack:< fragmentGroupEvent (* invoked by MPS when fg[] is saved to disk *) (# do INNER #); onGroupUnpack:< fragmentGroupEvent (* invoked by MPS when fg[] is unpacked from disk *) (# do INNER #); onBeforeGroupClose:< fragmentGroupEvent (* invoked by MPS before fg[] is closed * okToClose=false => fg will not be closed. *) (# okToClose: @boolean do true->okToClose; INNER exit okToClose #); onGroupClose:< fragmentGroupEvent (* invoked by MPS when fg[] have been closed *) (# do INNER #); onTrace:< event (* invoked by MPS if tracing is activated *) (# msg: ^text enter msg[] do INNER #) #); signal: (# where:< booleanValue (# do true->value; INNER #); start:< object (* executed before the signal is posted to all handlers *) ; current: ^handle; fg: ^astInterface.fragmentGroup; ff: ^astInterface.fragmentForm; node: ^astInterface.ast; ... #); fragmentGroupSignal: signal (* abstract superpattern *) (# enter fg[] do INNER #); fragmentFormSignal: signal (* abstract superpattern *) (# enter ff[] do INNER #); astSignal: signal (* abstract superpattern *) (# enter node[] do INNER #); signalGroupOpen: fragmentGroupSignal (# do fg[]->current.onGroupOpen #); signalGroupLock: fragmentGroupSignal (# do fg[]->current.onGroupLock #); signalGroupUnlock: fragmentGroupSignal (# do fg[]->current.onGroupUnlock #); signalGroupPack: fragmentGroupSignal (# do fg[]->current.onGroupPack #); signalGroupUnpack: fragmentGroupSignal (# do fg[]->current.onGroupUnpack #); signalBeforeGroupClose: fragmentGroupSignal (# okToClose: @boolean; start::< (# do true->okToClose; INNER #); do (okToClose and (fg[]->current.onBeforeGroupClose))->okToClose exit okToClose #); signalGroupClose: fragmentGroupSignal (# do fg[]->current.onGroupClose #); signalTrace: signal (# traceNo: @integer; msg: ^text; start::< (# do 'Trace: '->msg[]; traceNo->msg.putInt; ' '->msg.put; INNER #) enter traceNo do msg[]->current.onTrace #); astFocus: (# node: ^astInterface.ast; length,subCommentInx1,subCommentInx2: @integer enter (node[],length,subCommentInx1,subCommentInx2) exit (node[],length,subCommentInx1,subCommentInx2) #); astList: (# elm: [50] ^astInterface.ast #); astReplacedElement: (# oldAst,newAst: ^astInterface.ast #); astReplacedList: containerList (# element:: astReplacedElement; appendElement: (# oldAst,newAst: ^astInterface.ast; e: ^astReplacedElement; enter (oldAst[],newAst[]) do &astReplacedElement[]->e[]; oldAst[]->e.oldAst[]; newAst[]->e.newAst[]; e[]->append #) #); -- fragmentGroupLib: Attributes -- attachObserver: (* called to attach a new observer on this fragmentgroup *) (# theObserver: ^fragmentGroupObserver; enter theObserver[] ... #); detachObserver: (* called to detach an observer (i.e. now wanting to be monitoring * this fragmentGroup through this observer 'o' any longer *) (# theObserver: ^fragmentGroupObserver; enter theObserver[] ... #); notify: (# where:< booleanValue (# do true->value; INNER #); before:< object (* executed before the notification is posted to all observers *) ; after:< object (* executed after the notification is posted to all observers *) ; current: ^fragmentGroupObserver; ff: ^astInterface.fragmentForm; ... #); notifyAs: (# where:< booleanValue (# do true->value; INNER #); before:< object (* executed before the notification is posted to all observers *) ; after:< object (* executed after the notification is posted to all observers *) ; current: ^type; type:< fragmentGroupObserver; ff: ^astInterface.fragmentForm; ... #); fragmentFormNotify: notify (# enter ff[] do INNER #); notifyNameChanged: fragmentFormNotify (# oldName,newName: ^text; enter (oldName[],newName[]) do (ff[],oldName[],newName[])->current.onNameChanged #); notifyFragmentInserted: fragmentFormNotify (# do ff[]->current.onFragmentInserted #); notifyFragmentDeleted: fragmentFormNotify (# do ff[]->current.onFragmentDeleted #); notifyPropertiesChanged: notify (# oldProp,newProp: ^propertyList; enter (oldProp[],newProp[]) do (oldProp[],newProp[])->current.onPropertiesChanged #); notifyGroupSaved: notify (# do current.onGroupSaved #); notifyGroupNotSaved: notify (# do current.onGroupNotSaved #); notifyGroupAutosaved: notify (# do current.onGroupAutosaved #); notifyGroupChecked: notify (# semanticErrors: @boolean enter semanticErrors do semanticErrors->current.onGroupChecked #); notifyGroupLocked: notify (# do current.onGroupLocked #); notifyGroupUnlocked: notify (# do current.onGroupUnlocked #); notifyBeforeGroupClose: notify (# okToClose: @boolean; before::< (# do true->okToClose; INNER #); do (okToClose and current.onBeforeGroupClose)->okToClose exit okToClose #); notifyGroupClosed: notify (# do current.onGroupClosed #); -- fragmentFormLib: Attributes -- attachObserver: (* called to attach a new observer on this fragmentform *) (# theObserver: ^fragmentFormObserver; enter theObserver[] ... #); detachObserver: (* called to detach an observer (i.e. now wanting to be monitoring * this fragmentForm through this observer 'o' any longer *) (# theObserver: ^fragmentFormObserver enter theObserver[] ... #); notify: (# where:< booleanValue (# do true->value; INNER #); before:< object (* executed before the notification is posted to all observers *) ; after:< object (* executed after the notification is posted to all observers *) ; current: ^fragmentFormObserver; node: ^astInterface.ast; ... #); notifyAs: (# where:< booleanValue (# do true->value; INNER #); before:< object (* executed before the notification is posted to all observers *) ; after:< object (* executed after the notification is posted to all observers *) ; current: ^type; type:< fragmentFormObserver; node: ^astInterface.ast; ... #); listNotify: notify (* abstract superpattern *) (# enter node[] do INNER #); notifyAstReplaced: notify (# oldAst,newAst: ^astInterface.ast; enter (oldAst[],newAst[]) do (oldAst[],newAst[])->current.onAstReplaced #); notifyAstReplacedSequence: notify (# theSequence: ^astReplacedList enter (node[],theSequence[]) do (node[],theSequence[])->current.onAstReplacedSequence #); notifyListElementInserted: listNotify (# position: @integer enter position do (node[],position)->current.onListElementInserted #); notifyListElementsDeleted: listNotify (# oldElements: ^astList; position,length: @integer enter (position,length,oldElements[]) do (node[],position,length,oldElements[])->current.onListElementsDeleted #); notifyListElementsReplaced: listNotify (# oldElements: ^astList; position,length,newLength: @integer enter (position,length,oldElements[],newLength) do (node[],position,length,oldElements[],newLength) ->current.onListElementsReplaced #); locked: booleanValue (# ... #); lock: (# ... #); unLock: (# ... #); readOnly: booleanValue (# ... #); setReadOnly: (# ... #); unsetReadOnly: (# ... #); touched: booleanValue (# ... #); touch: (# ... #); detouch: (# ... #); -- lib: Attributes -- fragmentGroupObserver: observer (# group: ^astInterface.fragmentGroup; no: @integer; ignore:< booleanValue (* if this returns TRUE, this(fragmentGroupObserver) will be ignored *) (# do INNER #); fragmentFormEvent: (# ff: ^astInterface.fragmentForm enter ff[] do INNER #); fragmentGroupEvent: (# do INNER #); onNameChanged:< fragmentFormEvent (* invoked if ff[] have been given a new name *) (# oldName,newName: ^text; enter (oldName[],newName[]) do INNER ; #); onFragmentInserted:< fragmentFormEvent (* invoked when ff[] is inserted in fg[] *) (# do INNER #); onFragmentDeleted:< fragmentFormEvent (* invoked when ff[] is deleted from fg[] *) (# do INNER #); onPropertiesChanged:< fragmentGroupEvent (* invoked when the properties of fg[] have changed *) (# oldProp,newProp: ^propertyList; enter (oldProp[],newProp[]) do INNER #); onGroupSaved:< fragmentGroupEvent (* invoked when fg[] have been saved *) (# do INNER #); onGroupNotSaved:< fragmentGroupEvent (* invoked when quitting without saving the fg[], * either because no changes have been made to the fg * or becauset he user has decided not to save the changes *) (# do INNER #); onGroupAutoSaved:< fragmentGroupEvent (* invoked when fg[] have been auto-saved *) (# do INNER #); onGroupChecked:< fragmentGroupEvent (* invoked when fg[] have been checked by the checker *) (# semanticErrors: @boolean enter semanticErrors do INNER #); onGroupLocked:< fragmentGroupEvent (* invoked by MPS when fg[] is locked *) (# do INNER #); onGroupUnlocked:< fragmentGroupEvent (* invoked by MPS when fg[] is unlocked *) (# do INNER #); onBeforeGroupClose:< fragmentGroupEvent (* invoked by MPS before fg[] is closed * okToClose=false => fg will not be closed. *) (# okToClose: @boolean do true->okToClose; INNER exit okToClose #); onGroupClosed:< fragmentGroupEvent (* invoked by MPS when fg[] have been closed *) (# do INNER #) #); fragmentFormObserver: observer (# frag: ^astinterface.fragmentForm; no: @integer; astEvent: (* abstract superpattern *) (# do before; INNER ; after #); listEvent: astEvent (# node: ^astInterface.list enter node[] do INNER #); before:< object (* executed before INNER in all astEvents *) ; after:< object (* executed after INNER in all astEvents *) ; onAstReplaced:< astEvent (* invoked when an ast has been replaced *) (# oldAst,newAst: ^astInterface.ast; enter (oldAst[],newAst[]) do INNER #); onAstReplacedSequence:< astEvent (* invoked when a sequence of astReplaced events have occured in node[] *) (# node: ^astInterface.ast; theSequence: ^astInterface.astReplacedList enter (node[],theSequence[]) do INNER #); onListElementInserted:< listEvent (* invoked when a new list element have been inserted in node[] *) (# position: @integer; enter position do INNER #); onListElementsDeleted:< listEvent (* invoked when a list of elements have been deleted from node[] *) (# oldElements: ^astInterface.astList; position,length: @integer enter (position,length,oldElements[]) do INNER #); onListElementsReplaced:< listEvent (* invoked when a list of elements have been replaced in node[] *) (# oldElements: ^astInterface.astList; position,length,newLength: @integer enter (position,length,oldElements[],newLength) do INNER #) #)
13.7 Notifications Interface | © 1991-2002 Mjølner Informatics |
[Modified: Wednesday January 3rd 2001 at 12:15]
|