On 18 Jan 2014, at 12:09, b...@openinworld.com wrote:
Benjamin wrote: I think i would be more elegant that the model register to the isClosedHolder changes :) Hi Ben, I've gave that a go and had some success, but it raised an architectural question I ask near the end. I've documented my investigation here in case it is of use to others new to Spec or the Spec documentation being developed. So references to i-var 'isClosedHolder' indicate this operates through #whenClosedDo: which has three senders: * InspectorNavigator>>initialize * SpecDebugger>>initialize * SpecPreDebugWindow>>initialize All of which use the pattern... self whenWindowChanged: [ :w | w whenClosedDo: [ "do stuff" ] ]. I understand this I inserted the following breakpoints... InspectorNavigator>>initialize ... self haltOnce. self whenWindowChanged: [ :w | "outerBlock" self halt. w whenClosedDo: [ "innerBlock" self halt. self inspector close ] ]. After enabling haltOnce and doing "1 inspect"... Trace Part 1. The first breakpoint (haltOnce) occurs in InspectorNavigator(ComposableModel)>>whenWindowChanged: At this point before the window is created, the i-var 'window' holds "NewValueHolder [ nil ]". A few steps later it registers "outerBlock" on i-var 'window' for announcement ValueChanged . It is interesting that the action is registered before the window is opened/exists. Trace Part 2. After a <proceed>, the "outerBlock" breakpoint occurs. Down(or up?) the stack InspectorNavigator(ComposableModel)>>openWithSpecLayout: does "window value: (WindowModel new model: self)" so that a few steps up NewValueHolder>>valueChanged: effectively announces ValueChanged on i-var 'window' . such that WindowModel>>whenClosedDo: executes to register the "innerBlock" on WindowModel's i-var 'isClosedHolder' for announcement ValueChanged. The inspector then appears. Trace Part 3. When the close button on the inspector is clicked, the "innerBlock" breakpoint occurs. Down the stack WindowModel>>windowIsClosing does "isClosedHolder value: true" so that a few steps up NewValueHolder>>valueChanged: announces ValueChanged on i-var 'isClosedHolder' such that "self inspector close" is executed. Armed with that understanding I found the following worked fine... PharoLauncher>>initialize super initialize. self whenWindowChanged: [ :w | w whenClosedDo: [ self releaseSubscriptions ] ]. with support from PharoLauncher>>releaseSubscriptions imagesModel releaseSubscriptions PhLTitledTreeModel>>releaseSubscriptions self repository unsubscribe: self. Where PharoLauncher and PhLTitledTreeModel are both subclassed from ComposableModel, and PhLTitledTreeModel is composed into PharoLauncher by the i-var 'imagesModel'. However I could not help make the comparison of the simplicity of: PharoLauncher>>windowIsClosing self releaseSubscriptons which is 1 stack level in the debugger away from WindowModel>>windowIsClosing and took about an hour to track down and understand... versus isClosedHolder: which has 22 stack levels for both Trace Part 1 and Trace Part 2 from the two levels of redirection with Announcements and taken many hours of play to get to my current point of understanding. So what is gained in elegance from doing it the isClosedHolder way? I thought that maybe... since all these components are meant to be composable, PhLTitledTreeModel should be self-contained about about releasing its subscriptions, by registering on isClosedHolder itself at the point where the subscription-of-concern is created. Otherwise relying on its owner PharoLauncher to call PhLTitledTreeModel >>releaseSubscriptions means if PhLTitledTreeModel is composed elsewhere in ClassX, then the onus is on ClassX to do the same thing. I had hoped that adding the last line here would work... PhLTitledTreeModel>>repository: aRepository repositoryHolder value: aRepository. self repository whenChangedSend: #refresh to: self. "<--subscription-of-concern" self refresh. self whenWindowChanged: [ :w | w whenClosedDo: [ self repository unsubscribe: self ] ]. "<--added line" since that would be quite elegant! However it doesn't work since tracing through I find that the PhLTitledTreeModel i-var 'window' never changes from nil. To work it seems like PhLTitledTreeModel i-var 'window' should be the same WindowModel as its owner PharoLauncher's i-var 'window'. So the question this leads up to is... Should child ComposableModels all reference the same WindowModel as their owner? To my naive view (and direct need here) it makes intuitive sense that they should. I envisage the case in a dockable UI where ComposableModels might be dragged out from being a subpane to having a window of their own, where you would want the call to #releaseSubscriptions to be independent of the owner. Thanks for your patience on that long writeup. I hope its clear - otherwise maybe we could communicate on IM or screenshare. cheers -ben |
- [Pharo-dev] #windowIsClosing not sent to model of WindowModel btc
- Re: [Pharo-dev] #windowIsClosing not sent to model of Window... Benjamin
- Re: [Pharo-dev] #windowIsClosing not sent to model of Wi... btc
- Re: [Pharo-dev] #windowIsClosing not sent to model of Wi... btc